[cig-commits] commit: Rename .c -> .cxx and make configure automatically use c++

Mercurial hg at geodynamics.org
Thu May 12 11:21:48 PDT 2011


changeset:   784:46408d74ad35
tag:         tip
user:        Walter Landry <wlandry at caltech.edu>
date:        Thu May 12 11:19:05 2011 -0700
files:       Apps/EnergySolver/tests/AdvDiffSteadyState1D/AdvDiffSteadyState1D.c Apps/EnergySolver/tests/AdvDiffSteadyState1D/AdvDiffSteadyState1D.cxx Apps/EnergySolver/tests/CosineHillRotate/CosineHillRotate.c Apps/EnergySolver/tests/CosineHillRotate/CosineHillRotate.cxx Apps/EnergySolver/tests/HomogeneousEssentialBCs/HomogeneousEssentialBCs.c Apps/EnergySolver/tests/HomogeneousEssentialBCs/HomogeneousEssentialBCs.cxx Apps/EnergySolver/tests/HomogeneousNaturalBCs/HomogeneousNaturalBCs.c Apps/EnergySolver/tests/HomogeneousNaturalBCs/HomogeneousNaturalBCs.cxx Apps/StokesMomentumUzawa/tests/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.c Apps/StokesMomentumUzawa/tests/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.cxx Apps/StokesMomentumUzawa/tests/LidDrivenStokesAnalytic/LidDrivenStokesAnalytic.c Apps/StokesMomentumUzawa/tests/LidDrivenStokesAnalytic/LidDrivenStokesAnalytic.cxx Apps/StokesMomentumUzawa/tests/LinearVelocityAnalytic/LinearVelocityAnalytic.c Apps/StokesMomentumUzawa/tests/LinearVelocityAnalytic/LinearVelocityAnalytic.cxx Apps/StokesMomentumUzawa/tests/SimpleShearAnalytic/SimpleShearAnalytic.c Apps/StokesMomentumUzawa/tests/SimpleShearAnalytic/SimpleShearAnalytic.cxx Apps/TempDiffusion/tests/LinearTemperatureField/LinearTemperatureField.c Apps/TempDiffusion/tests/LinearTemperatureField/LinearTemperatureField.cxx Apps/ThermalConvection/tests/ColumnViscosityAnalytic/ColumnViscosityAnalytic.c Apps/ThermalConvection/tests/ColumnViscosityAnalytic/ColumnViscosityAnalytic.cxx Assembly/src/DivergenceMatrixTerm.c Assembly/src/DivergenceMatrixTerm.cxx Assembly/src/Finalise.c Assembly/src/Finalise.cxx Assembly/src/GradientStiffnessMatrixTerm.c Assembly/src/GradientStiffnessMatrixTerm.cxx Assembly/src/Init.c Assembly/src/Init.cxx Assembly/src/IsoviscousStressTensorTerm.c Assembly/src/IsoviscousStressTensorTerm.cxx Assembly/src/LaplacianStiffnessMatrixTerm.c Assembly/src/LaplacianStiffnessMatrixTerm.cxx Assembly/src/MassMatrixTerm.c Assembly/src/MassMatrixTerm.cxx Assembly/src/PressureGradForceTerm.c Assembly/src/PressureGradForceTerm.cxx Assembly/src/PressureGradMatrixTerm.c Assembly/src/PressureGradMatrixTerm.cxx Assembly/src/ThermalBuoyancyForceTerm.c Assembly/src/ThermalBuoyancyForceTerm.cxx Assembly/tests/IsoviscousStiffnessSuite.c Assembly/tests/IsoviscousStiffnessSuite.cxx Discretisation/src/AnalyticSolution.c Discretisation/src/AnalyticSolution.cxx Discretisation/src/BilinearElementType.c Discretisation/src/BilinearElementType.cxx Discretisation/src/BilinearInnerElType.c Discretisation/src/BilinearInnerElType.cxx Discretisation/src/Biquadratic.c Discretisation/src/Biquadratic.cxx Discretisation/src/C0Generator.c Discretisation/src/C0Generator.cxx Discretisation/src/C2Generator.c Discretisation/src/C2Generator.cxx Discretisation/src/ConstantElementType.c Discretisation/src/ConstantElementType.cxx Discretisation/src/Element.c Discretisation/src/Element.cxx Discretisation/src/ElementType.c Discretisation/src/ElementType.cxx Discretisation/src/ElementType_Register.c Discretisation/src/ElementType_Register.cxx Discretisation/src/FeEquationNumber.c Discretisation/src/FeEquationNumber.cxx Discretisation/src/FeMesh.c Discretisation/src/FeMesh.cxx Discretisation/src/FeMesh_Algorithms.c Discretisation/src/FeMesh_Algorithms.cxx Discretisation/src/FeMesh_ElementType.c Discretisation/src/FeMesh_ElementType.cxx Discretisation/src/FeSwarmVariable.c Discretisation/src/FeSwarmVariable.cxx Discretisation/src/FeVariable.c Discretisation/src/FeVariable.cxx Discretisation/src/FieldTest.c Discretisation/src/FieldTest.cxx Discretisation/src/Finalise.c Discretisation/src/Finalise.cxx Discretisation/src/FunctionSuite.c Discretisation/src/FunctionSuite.cxx Discretisation/src/Init.c Discretisation/src/Init.cxx Discretisation/src/Inner2DGenerator.c Discretisation/src/Inner2DGenerator.cxx Discretisation/src/LinearTriangleElementType.c Discretisation/src/LinearTriangleElementType.cxx Discretisation/src/LinkedDofInfo.c Discretisation/src/LinkedDofInfo.cxx Discretisation/src/OperatorFeVariable.c Discretisation/src/OperatorFeVariable.cxx Discretisation/src/P1.c Discretisation/src/P1.cxx Discretisation/src/RegularBilinear.c Discretisation/src/RegularBilinear.cxx Discretisation/src/RegularTrilinear.c Discretisation/src/RegularTrilinear.cxx Discretisation/src/ShapeFeVariable.c Discretisation/src/ShapeFeVariable.cxx Discretisation/src/TrilinearElementType.c Discretisation/src/TrilinearElementType.cxx Discretisation/src/TrilinearInnerElType.c Discretisation/src/TrilinearInnerElType.cxx Discretisation/src/Triquadratic.c Discretisation/src/Triquadratic.cxx Discretisation/tests/C2GeneratorSuite.c Discretisation/tests/C2GeneratorSuite.cxx Discretisation/tests/ElementTypeRegisterSuite.c Discretisation/tests/ElementTypeRegisterSuite.cxx Discretisation/tests/ElementTypeSuite.c Discretisation/tests/ElementTypeSuite.cxx Discretisation/tests/FeEquationNumberSuite.c Discretisation/tests/FeEquationNumberSuite.cxx Discretisation/tests/FeVariableSuite.c Discretisation/tests/FeVariableSuite.cxx Discretisation/tests/TrilinearElementTypeSuite.c Discretisation/tests/TrilinearElementTypeSuite.cxx SConscript SLE/ProvidedSystems/AdvectionDiffusion/src/AdvectionDiffusionSLE.c SLE/ProvidedSystems/AdvectionDiffusion/src/AdvectionDiffusionSLE.cxx SLE/ProvidedSystems/AdvectionDiffusion/src/Finalise.c SLE/ProvidedSystems/AdvectionDiffusion/src/Finalise.cxx SLE/ProvidedSystems/AdvectionDiffusion/src/Init.c SLE/ProvidedSystems/AdvectionDiffusion/src/Init.cxx SLE/ProvidedSystems/AdvectionDiffusion/src/LumpedMassMatrixForceTerm.c SLE/ProvidedSystems/AdvectionDiffusion/src/LumpedMassMatrixForceTerm.cxx SLE/ProvidedSystems/AdvectionDiffusion/src/MassMatrix_Assembly.c SLE/ProvidedSystems/AdvectionDiffusion/src/MassMatrix_Assembly.cxx SLE/ProvidedSystems/AdvectionDiffusion/src/Multicorrector.c SLE/ProvidedSystems/AdvectionDiffusion/src/Multicorrector.cxx SLE/ProvidedSystems/AdvectionDiffusion/src/Residual.c SLE/ProvidedSystems/AdvectionDiffusion/src/Residual.cxx SLE/ProvidedSystems/AdvectionDiffusion/src/Timestep.c SLE/ProvidedSystems/AdvectionDiffusion/src/Timestep.cxx SLE/ProvidedSystems/AdvectionDiffusion/src/UpwindParameter.c SLE/ProvidedSystems/AdvectionDiffusion/src/UpwindParameter.cxx SLE/ProvidedSystems/AdvectionDiffusion/tests/LumpedMassMatrixSuite.c SLE/ProvidedSystems/AdvectionDiffusion/tests/LumpedMassMatrixSuite.cxx SLE/ProvidedSystems/AdvectionDiffusion/tests/UpwindXiSuite.c SLE/ProvidedSystems/AdvectionDiffusion/tests/UpwindXiSuite.cxx SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testLumpedMassMatrix.c SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testLumpedMassMatrix.cxx SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testUpwindXi.c SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testUpwindXi.cxx SLE/ProvidedSystems/Energy/src/Energy_SLE.c SLE/ProvidedSystems/Energy/src/Energy_SLE.cxx SLE/ProvidedSystems/Energy/src/Energy_SLE_Solver.c SLE/ProvidedSystems/Energy/src/Energy_SLE_Solver.cxx SLE/ProvidedSystems/Energy/src/Finalise.c SLE/ProvidedSystems/Energy/src/Finalise.cxx SLE/ProvidedSystems/Energy/src/Init.c SLE/ProvidedSystems/Energy/src/Init.cxx SLE/ProvidedSystems/StokesFlow/src/Finalise.c SLE/ProvidedSystems/StokesFlow/src/Finalise.cxx SLE/ProvidedSystems/StokesFlow/src/Init.c SLE/ProvidedSystems/StokesFlow/src/Init.cxx SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE.c SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE.cxx SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_PenaltySolver.c SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_PenaltySolver.cxx SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_UzawaSolver.c SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_UzawaSolver.cxx SLE/ProvidedSystems/StokesFlow/src/UpdateDt.c SLE/ProvidedSystems/StokesFlow/src/UpdateDt.cxx SLE/ProvidedSystems/StokesFlow/src/UzawaPreconditionerTerm.c SLE/ProvidedSystems/StokesFlow/src/UzawaPreconditionerTerm.cxx SLE/ProvidedSystems/src/Finalise.c SLE/ProvidedSystems/src/Finalise.cxx SLE/ProvidedSystems/src/Init.c SLE/ProvidedSystems/src/Init.cxx SLE/SystemSetup/src/Assembler.c SLE/SystemSetup/src/Assembler.cxx SLE/SystemSetup/src/EntryPoint.c SLE/SystemSetup/src/EntryPoint.cxx SLE/SystemSetup/src/Finalise.c SLE/SystemSetup/src/Finalise.cxx SLE/SystemSetup/src/FiniteElementContext.c SLE/SystemSetup/src/FiniteElementContext.cxx SLE/SystemSetup/src/ForceTerm.c SLE/SystemSetup/src/ForceTerm.cxx SLE/SystemSetup/src/ForceVector.c SLE/SystemSetup/src/ForceVector.cxx SLE/SystemSetup/src/Init.c SLE/SystemSetup/src/Init.cxx SLE/SystemSetup/src/MGOpGenerator.c SLE/SystemSetup/src/MGOpGenerator.cxx SLE/SystemSetup/src/MultigridSolver.c SLE/SystemSetup/src/MultigridSolver.cxx SLE/SystemSetup/src/PETScMGSolver.c SLE/SystemSetup/src/PETScMGSolver.cxx SLE/SystemSetup/src/SLE_Solver.c SLE/SystemSetup/src/SLE_Solver.cxx SLE/SystemSetup/src/SROpGenerator.c SLE/SystemSetup/src/SROpGenerator.cxx SLE/SystemSetup/src/SolutionVector.c SLE/SystemSetup/src/SolutionVector.cxx SLE/SystemSetup/src/StiffnessMatrix.c SLE/SystemSetup/src/StiffnessMatrix.cxx SLE/SystemSetup/src/StiffnessMatrixTerm.c SLE/SystemSetup/src/StiffnessMatrixTerm.cxx SLE/SystemSetup/src/SystemLinearEquations.c SLE/SystemSetup/src/SystemLinearEquations.cxx SLE/SystemSetup/tests/ContextSuite.c SLE/SystemSetup/tests/ContextSuite.cxx SLE/SystemSetup/tests/SolutionVectorSuite.c SLE/SystemSetup/tests/SolutionVectorSuite.cxx SLE/SystemSetup/tests/StiffnessMatrixSuite.c SLE/SystemSetup/tests/StiffnessMatrixSuite.cxx SLE/src/Finalise.c SLE/src/Finalise.cxx SLE/src/Init.c SLE/src/Init.cxx SysTest/AnalyticPlugins/AdvDiffSteadyState1D/AdvDiffSteadyState1D.c SysTest/AnalyticPlugins/AdvDiffSteadyState1D/AdvDiffSteadyState1D.cxx SysTest/AnalyticPlugins/CosineHillRotate/CosineHillRotate.c SysTest/AnalyticPlugins/CosineHillRotate/CosineHillRotate.cxx SysTest/AnalyticPlugins/HomogeneousNaturalBCs/HomogeneousNaturalBCs.c SysTest/AnalyticPlugins/HomogeneousNaturalBCs/HomogeneousNaturalBCs.cxx SysTest/AnalyticPlugins/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.c SysTest/AnalyticPlugins/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.cxx SysTest/AnalyticPlugins/LinearTemperatureField/LinearTemperatureField.c SysTest/AnalyticPlugins/LinearTemperatureField/LinearTemperatureField.cxx SysTest/AnalyticPlugins/LinearVelocityAnalytic/LinearVelocityAnalytic.c SysTest/AnalyticPlugins/LinearVelocityAnalytic/LinearVelocityAnalytic.cxx libStgFEM/Toolbox/Toolbox.c libStgFEM/Toolbox/Toolbox.cxx libStgFEM/src/Finalise.c libStgFEM/src/Finalise.cxx libStgFEM/src/Init.c libStgFEM/src/Init.cxx libStgFEM/tests/LibStgFEMSuite.c libStgFEM/tests/LibStgFEMSuite.cxx libStgFEM/tests/testLibStgFEM.c libStgFEM/tests/testLibStgFEM.cxx plugins/CompareFeVariableAgainstReferenceSolution/CompareFeVariableAgainstReferenceSolution.c plugins/CompareFeVariableAgainstReferenceSolution/CompareFeVariableAgainstReferenceSolution.cxx plugins/FeVariableImportExporters/FeVariable_ImportExport_ABAQUS/FeVariable_ImportExport_ABAQUS.c plugins/FeVariableImportExporters/FeVariable_ImportExport_ABAQUS/FeVariable_ImportExport_ABAQUS.cxx plugins/FeVariableImportExporters/FeVariable_ImportExport_SpecRidge2D/FeVariable_ImportExport_SpecRidge2D.c plugins/FeVariableImportExporters/FeVariable_ImportExport_SpecRidge2D/FeVariable_ImportExport_SpecRidge2D.cxx plugins/FileAnalyticSolution/FileAnalyticSolution.c plugins/FileAnalyticSolution/FileAnalyticSolution.cxx plugins/Multigrid/Multigrid.c plugins/Multigrid/Multigrid.cxx plugins/Output/CPUTime/CPUTime.c plugins/Output/CPUTime/CPUTime.cxx plugins/Output/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.c plugins/Output/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.cxx plugins/Output/FeVariableList/FeVariableList.c plugins/Output/FeVariableList/FeVariableList.cxx plugins/Output/FrequentOutput/FrequentOutput.c plugins/Output/FrequentOutput/FrequentOutput.cxx plugins/Output/PeakMemory/PeakMemory.c plugins/Output/PeakMemory/PeakMemory.cxx plugins/Output/PrintFeVariableDiscreteValues/Plugin.c plugins/Output/PrintFeVariableDiscreteValues/Plugin.cxx plugins/Output/PrintFeVariableDiscreteValues_2dBox/Plugin.c plugins/Output/PrintFeVariableDiscreteValues_2dBox/Plugin.cxx plugins/Output/SwarmVariableList/SwarmVariableList.c plugins/Output/SwarmVariableList/SwarmVariableList.cxx plugins/StandardConditionFunctions/StandardConditionFunctions.c plugins/StandardConditionFunctions/StandardConditionFunctions.cxx
description:
Rename .c -> .cxx and make configure automatically use c++


diff -r bd633e2a3a35 -r 46408d74ad35 Apps/EnergySolver/tests/AdvDiffSteadyState1D/AdvDiffSteadyState1D.c
--- a/Apps/EnergySolver/tests/AdvDiffSteadyState1D/AdvDiffSteadyState1D.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: AdvDiffSteadyState1D.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-/* This analytic solutions is just the advection of a diffusing temperature for one time step.
- *  The advection is in the direction of one of the i,j,k axis 
- *  */
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include <string.h>
-
-const Type AdvDiffSteadyState1D_Type = "AdvDiffSteadyState1D";
-
-typedef struct { 
-	__AnalyticSolution
-	AdvDiffResidualForceTerm* residual;
-	/* Velocity in this analyticSolution is constant */
-	double                    velocity;
-	Axis                      velocityDirection;
-	double                    A;
-	double                    B;
-	double                    c;
-	FeVariable*		  temperatureField;
-} AdvDiffSteadyState1D;
-
-void AdvDiffSteadyState1D_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* temperature ) {
-	AdvDiffSteadyState1D* self = (AdvDiffSteadyState1D*)analyticSolution;
-	double                exponent;
-	double                kappa = self->residual->defaultDiffusivity;
-
-	exponent = self->velocity / kappa * ( coord[ self->velocityDirection ] - self->c );
-	*temperature = self->A * exp( exponent ) + self->B;
-}
-
-void AdvDiffSteadyState1D_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* temperature ){
-	DomainContext*	context    = (DomainContext*)_context;
-	AdvDiffSteadyState1D*   self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)AdvDiffSteadyState1D_Type, AdvDiffSteadyState1D, True, 0 /* dummy */ );
-	FeVariable*             feVariable = NULL;
-	FeMesh*     mesh       = NULL;
-	double*                 coord;
-	
-	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	mesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( mesh, node_lI );
-
-	AdvDiffSteadyState1D_TemperatureFunction( self, NULL, coord, temperature );
-}
-
-
-void _AdvDiffSteadyState1D_Build( void* analyticSolution, void* data ) {
-	AdvDiffSteadyState1D* self = (AdvDiffSteadyState1D*)analyticSolution;
-	FeVariable*           velocityField = Stg_CheckType( self->residual->velocityField, FeVariable );
-	CompositeVC*          velocityICs   = Stg_CheckType( velocityField->ics, CompositeVC );
-	Stream*               errorStream   = Journal_MyStream( Error_Type, self );
-	AllNodesVC*           allNodesVC;
-	AllNodesVC_Entry*     vcEntry;
-
-	_AnalyticSolution_Build( self, data );
-
-	/* Get AllNodes Variable Condition */
-	Stg_Component_Build( velocityICs, data, False );
-	Journal_Firewall( velocityICs->itemCount == 1, errorStream, 
-			"Velocity Field needs to have one and only one Boundary Condition.\n"
-			"Currently it has %d types of VariableConditions.\n", velocityICs->itemCount );
-	allNodesVC    = Stg_CheckType( velocityICs->itemTbl[ 0 ], AllNodesVC );
-
-	/* Get Variable Condition entry */
-	Journal_Firewall( allNodesVC->_entryCount == 1, errorStream, 
-			"Velocity Field has more than one Boundary Condition.\n"
-			"Currently it has %d VariableCondition entries.\n", allNodesVC->_entryCount );
-	vcEntry       = &allNodesVC->_entryTbl[0];
-
-	/* Get Velocity Direction from Variable Condition */
-	if ( strcmp( vcEntry->varName, "vx" ) == 0 ) {
-		self->velocityDirection = I_AXIS;
-	}
-	else if ( strcmp( vcEntry->varName, "vy" ) == 0 ) {
-		self->velocityDirection = J_AXIS;
-	}
-	else if ( strcmp( vcEntry->varName, "vz" ) == 0 ) {
-		self->velocityDirection = K_AXIS;
-	}
-	else {
-		Journal_Firewall( False, errorStream, "Cannot recognise Boundary Condition: %s.\n", vcEntry->varName );
-	}
-}
-
-void _AdvDiffSteadyState1D_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	AdvDiffSteadyState1D*  self = (AdvDiffSteadyState1D*)analyticSolution;
-	AbstractContext*       context;
-	ConditionFunction*     condFunc;
-
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-
-	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  );
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, AdvDiffSteadyState1D_TemperatureFunction );
-
-	self->residual = Stg_ComponentFactory_ConstructByName( cf, (Name)"defaultResidualForceTerm", AdvDiffResidualForceTerm, True, data  );
-
-	self->velocity = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"velocity", 1.0  );
-	self->A        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"A", 1.0  );
-	self->B        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"B", 0.0  );
-	self->c        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"c", 0.0  );
-	
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  );
-	condFunc = ConditionFunction_New( AdvDiffSteadyState1D_TemperatureBC, (Name)"AnalyticSolutionFunction"  );
-	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
-
-}
-
-void* _AdvDiffSteadyState1D_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(AdvDiffSteadyState1D);
-	Type                                                      type = AdvDiffSteadyState1D_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _AdvDiffSteadyState1D_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _AdvDiffSteadyState1D_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _AdvDiffSteadyState1D_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_AdvDiffSteadyState1D_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, AdvDiffSteadyState1D_Type, (Name)"0", _AdvDiffSteadyState1D_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/EnergySolver/tests/AdvDiffSteadyState1D/AdvDiffSteadyState1D.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/EnergySolver/tests/AdvDiffSteadyState1D/AdvDiffSteadyState1D.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,177 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: AdvDiffSteadyState1D.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* This analytic solutions is just the advection of a diffusing temperature for one time step.
+ *  The advection is in the direction of one of the i,j,k axis 
+ *  */
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include <string.h>
+
+const Type AdvDiffSteadyState1D_Type = "AdvDiffSteadyState1D";
+
+typedef struct { 
+	__AnalyticSolution
+	AdvDiffResidualForceTerm* residual;
+	/* Velocity in this analyticSolution is constant */
+	double                    velocity;
+	Axis                      velocityDirection;
+	double                    A;
+	double                    B;
+	double                    c;
+	FeVariable*		  temperatureField;
+} AdvDiffSteadyState1D;
+
+void AdvDiffSteadyState1D_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* temperature ) {
+	AdvDiffSteadyState1D* self = (AdvDiffSteadyState1D*)analyticSolution;
+	double                exponent;
+	double                kappa = self->residual->defaultDiffusivity;
+
+	exponent = self->velocity / kappa * ( coord[ self->velocityDirection ] - self->c );
+	*temperature = self->A * exp( exponent ) + self->B;
+}
+
+void AdvDiffSteadyState1D_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* temperature ){
+	DomainContext*	context    = (DomainContext*)_context;
+	AdvDiffSteadyState1D*   self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)AdvDiffSteadyState1D_Type, AdvDiffSteadyState1D, True, 0 /* dummy */ );
+	FeVariable*             feVariable = NULL;
+	FeMesh*     mesh       = NULL;
+	double*                 coord;
+	
+	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	mesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( mesh, node_lI );
+
+	AdvDiffSteadyState1D_TemperatureFunction( self, NULL, coord, temperature );
+}
+
+
+void _AdvDiffSteadyState1D_Build( void* analyticSolution, void* data ) {
+	AdvDiffSteadyState1D* self = (AdvDiffSteadyState1D*)analyticSolution;
+	FeVariable*           velocityField = Stg_CheckType( self->residual->velocityField, FeVariable );
+	CompositeVC*          velocityICs   = Stg_CheckType( velocityField->ics, CompositeVC );
+	Stream*               errorStream   = Journal_MyStream( Error_Type, self );
+	AllNodesVC*           allNodesVC;
+	AllNodesVC_Entry*     vcEntry;
+
+	_AnalyticSolution_Build( self, data );
+
+	/* Get AllNodes Variable Condition */
+	Stg_Component_Build( velocityICs, data, False );
+	Journal_Firewall( velocityICs->itemCount == 1, errorStream, 
+			"Velocity Field needs to have one and only one Boundary Condition.\n"
+			"Currently it has %d types of VariableConditions.\n", velocityICs->itemCount );
+	allNodesVC    = Stg_CheckType( velocityICs->itemTbl[ 0 ], AllNodesVC );
+
+	/* Get Variable Condition entry */
+	Journal_Firewall( allNodesVC->_entryCount == 1, errorStream, 
+			"Velocity Field has more than one Boundary Condition.\n"
+			"Currently it has %d VariableCondition entries.\n", allNodesVC->_entryCount );
+	vcEntry       = &allNodesVC->_entryTbl[0];
+
+	/* Get Velocity Direction from Variable Condition */
+	if ( strcmp( vcEntry->varName, "vx" ) == 0 ) {
+		self->velocityDirection = I_AXIS;
+	}
+	else if ( strcmp( vcEntry->varName, "vy" ) == 0 ) {
+		self->velocityDirection = J_AXIS;
+	}
+	else if ( strcmp( vcEntry->varName, "vz" ) == 0 ) {
+		self->velocityDirection = K_AXIS;
+	}
+	else {
+		Journal_Firewall( False, errorStream, "Cannot recognise Boundary Condition: %s.\n", vcEntry->varName );
+	}
+}
+
+void _AdvDiffSteadyState1D_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	AdvDiffSteadyState1D*  self = (AdvDiffSteadyState1D*)analyticSolution;
+	AbstractContext*       context;
+	ConditionFunction*     condFunc;
+
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+
+	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  );
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, AdvDiffSteadyState1D_TemperatureFunction );
+
+	self->residual = Stg_ComponentFactory_ConstructByName( cf, (Name)"defaultResidualForceTerm", AdvDiffResidualForceTerm, True, data  );
+
+	self->velocity = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"velocity", 1.0  );
+	self->A        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"A", 1.0  );
+	self->B        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"B", 0.0  );
+	self->c        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"c", 0.0  );
+	
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  );
+	condFunc = ConditionFunction_New( AdvDiffSteadyState1D_TemperatureBC, (Name)"AnalyticSolutionFunction"  );
+	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
+
+}
+
+void* _AdvDiffSteadyState1D_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(AdvDiffSteadyState1D);
+	Type                                                      type = AdvDiffSteadyState1D_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _AdvDiffSteadyState1D_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _AdvDiffSteadyState1D_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _AdvDiffSteadyState1D_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_AdvDiffSteadyState1D_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, AdvDiffSteadyState1D_Type, (Name)"0", _AdvDiffSteadyState1D_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/EnergySolver/tests/CosineHillRotate/CosineHillRotate.c
--- a/Apps/EnergySolver/tests/CosineHillRotate/CosineHillRotate.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: CosineHillRotate.c 968 2007-10-23 07:53:39Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-const Type CosineHillRotate_Type = "CosineHillRotate";
-
-typedef struct { 
-	__AnalyticSolution
-	FeVariable* temperatureField;
-	double      hillHeight;
-	double      hillDiameter;
-	Coord       rotationCentre;
-} CosineHillRotate;
-
-void CosineHillRotate_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* temperature ) {
-	CosineHillRotate *self = (CosineHillRotate*)analyticSolution;
-	double distanceFromCentre = StGermain_DistanceBetweenPoints( self->rotationCentre, coord, 2 );
-	
-	if (distanceFromCentre < self->hillDiameter ) 
-		*temperature = self->hillHeight * (0.5 + 0.5 * cos( 2.0 * M_PI/self->hillDiameter * distanceFromCentre + M_PI ) );
-	else
-		*temperature = 0.0;
-}
-
-void CosineHillRotate_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context    = (DomainContext*)_context;
-	CosineHillRotate*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)CosineHillRotate_Type, CosineHillRotate, True, 0 );
-	FeVariable*             feVariable = NULL;
-	FeMesh*			mesh       = NULL;
-	double*                 result     = (double*) _result;
-	double*                 coord;
-	
-	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	mesh       = feVariable->feMesh;
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	CosineHillRotate_TemperatureFunction( self, feVariable, coord, result );
-}
-
-void _CosineHillRotate_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	CosineHillRotate* self = (CosineHillRotate*)analyticSolution;
-	AbstractContext*       context;
-	ConditionFunction*     condFunc;
-
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-
-	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, CosineHillRotate_TemperatureFunction );
-
-	/* Read values from dictionary */
-	self->hillHeight       = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"CosineHillHeight"  , 1.0  );
-	self->hillDiameter     = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"CosineHillDiameter", 1.0  );
-	self->rotationCentre[ I_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreX" , 0.0  );
-	self->rotationCentre[ J_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreY" , 0.0  );
-	self->rotationCentre[ K_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ" , 0.0  );
-
-	/* Create Condition Functions */
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
-	condFunc = ConditionFunction_New( CosineHillRotate_TemperatureBC, (Name)"Temperature_CosineHill"  );
-	ConditionFunction_Register_Add( condFunc_Register, condFunc );
-}
-
-void _CosineHillRotate_Build( void* analyticSolution, void* data ) {
-	CosineHillRotate* self = (CosineHillRotate*)analyticSolution;	
-
-	_AnalyticSolution_Build( self, data );
-}
-
-void* _CosineHillRotate_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(CosineHillRotate);
-	Type                                                      type = CosineHillRotate_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _CosineHillRotate_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _CosineHillRotate_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _CosineHillRotate_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_CosineHillRotate_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, CosineHillRotate_Type, (Name)"0", _CosineHillRotate_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/EnergySolver/tests/CosineHillRotate/CosineHillRotate.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/EnergySolver/tests/CosineHillRotate/CosineHillRotate.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,137 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: CosineHillRotate.c 968 2007-10-23 07:53:39Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+const Type CosineHillRotate_Type = "CosineHillRotate";
+
+typedef struct { 
+	__AnalyticSolution
+	FeVariable* temperatureField;
+	double      hillHeight;
+	double      hillDiameter;
+	Coord       rotationCentre;
+} CosineHillRotate;
+
+void CosineHillRotate_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* temperature ) {
+	CosineHillRotate *self = (CosineHillRotate*)analyticSolution;
+	double distanceFromCentre = StGermain_DistanceBetweenPoints( self->rotationCentre, coord, 2 );
+	
+	if (distanceFromCentre < self->hillDiameter ) 
+		*temperature = self->hillHeight * (0.5 + 0.5 * cos( 2.0 * M_PI/self->hillDiameter * distanceFromCentre + M_PI ) );
+	else
+		*temperature = 0.0;
+}
+
+void CosineHillRotate_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context    = (DomainContext*)_context;
+	CosineHillRotate*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)CosineHillRotate_Type, CosineHillRotate, True, 0 );
+	FeVariable*             feVariable = NULL;
+	FeMesh*			mesh       = NULL;
+	double*                 result     = (double*) _result;
+	double*                 coord;
+	
+	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	mesh       = feVariable->feMesh;
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	CosineHillRotate_TemperatureFunction( self, feVariable, coord, result );
+}
+
+void _CosineHillRotate_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	CosineHillRotate* self = (CosineHillRotate*)analyticSolution;
+	AbstractContext*       context;
+	ConditionFunction*     condFunc;
+
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+
+	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, CosineHillRotate_TemperatureFunction );
+
+	/* Read values from dictionary */
+	self->hillHeight       = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"CosineHillHeight"  , 1.0  );
+	self->hillDiameter     = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"CosineHillDiameter", 1.0  );
+	self->rotationCentre[ I_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreX" , 0.0  );
+	self->rotationCentre[ J_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreY" , 0.0  );
+	self->rotationCentre[ K_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ" , 0.0  );
+
+	/* Create Condition Functions */
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
+	condFunc = ConditionFunction_New( CosineHillRotate_TemperatureBC, (Name)"Temperature_CosineHill"  );
+	ConditionFunction_Register_Add( condFunc_Register, condFunc );
+}
+
+void _CosineHillRotate_Build( void* analyticSolution, void* data ) {
+	CosineHillRotate* self = (CosineHillRotate*)analyticSolution;	
+
+	_AnalyticSolution_Build( self, data );
+}
+
+void* _CosineHillRotate_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(CosineHillRotate);
+	Type                                                      type = CosineHillRotate_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _CosineHillRotate_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _CosineHillRotate_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _CosineHillRotate_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_CosineHillRotate_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, CosineHillRotate_Type, (Name)"0", _CosineHillRotate_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/EnergySolver/tests/HomogeneousEssentialBCs/HomogeneousEssentialBCs.c
--- a/Apps/EnergySolver/tests/HomogeneousEssentialBCs/HomogeneousEssentialBCs.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,147 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: HomogeneousEssentialBCs.c 968 2007-10-23 07:53:39Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-const Type HomogeneousEssentialBCs_Type = "HomogeneousEssentialBCs";
-
-typedef struct { 
-	__AnalyticSolution
-	double angle;
-	FeVariable* temperatureField;
-} HomogeneousEssentialBCs;
-
-
-void HomogeneousEssentialBCs_Velocity_SkewToMesh( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	HomogeneousEssentialBCs*  self    = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousEssentialBCs_Type, HomogeneousEssentialBCs, True, 0 );
-	double*                 result  = (double*) _result;
-	
-	result[ I_AXIS ] =  cos( self->angle );
-	result[ J_AXIS ] =  sin( self->angle  );
-}
-
-
-void HomogeneousEssentialBCs_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* temperature ) {
-	HomogeneousEssentialBCs *self = (HomogeneousEssentialBCs*)analyticSolution;
-
-	if ( coord[ J_AXIS ] < tan( self->angle ) * coord[ I_AXIS ] + 0.25 )
-		*temperature = 1.0;
-	else 
-		*temperature = 0.0;
-
-	/* Perform Essential Boundary Conditions */
-	if ( (coord[ I_AXIS ] > 0.99 && coord[ J_AXIS ] > 0.01) || coord[ J_AXIS ] > 0.99 ) {
-		*temperature = 0.0;
-	}
-}
-	
-void HomogeneousEssentialBCs_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context    = (DomainContext*)_context;
-	HomogeneousEssentialBCs*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousEssentialBCs_Type, HomogeneousEssentialBCs, True, 0 );
-	FeVariable*             feVariable = NULL;
-	FeMesh*			mesh       = NULL;
-	double*                 result     = (double*) _result;
-	double*                 coord;
-	
-	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	mesh       = feVariable->feMesh;
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	HomogeneousEssentialBCs_TemperatureFunction( self, feVariable, coord, result );
-}
-
-void _HomogeneousEssentialBCs_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	HomogeneousEssentialBCs* self = (HomogeneousEssentialBCs*)analyticSolution;
-	AbstractContext*       context;
-	ConditionFunction*     condFunc;
-
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-
-	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, HomogeneousEssentialBCs_TemperatureFunction );
-
-	self->angle = StGermain_DegreeToRadian (Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"VelocitySkewAngle", 45.0 )  );
-
-	/* Create Condition Functions */
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
-	condFunc = ConditionFunction_New( HomogeneousEssentialBCs_Velocity_SkewToMesh, (Name)"Velocity_SkewToMesh"  );
-	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
-	condFunc = ConditionFunction_New( HomogeneousEssentialBCs_TemperatureBC, (Name)"Temperature_StepFunction"  );
-	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
-}
-
-void _HomogeneousEssentialBCs_Build( void* analyticSolution, void* data ) {
-	HomogeneousEssentialBCs* self = (HomogeneousEssentialBCs*)analyticSolution;	
-
-	_AnalyticSolution_Build( self, data );
-}
-
-void* _HomogeneousEssentialBCs_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(HomogeneousEssentialBCs);
-	Type                                                      type = HomogeneousEssentialBCs_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _HomogeneousEssentialBCs_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _HomogeneousEssentialBCs_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _HomogeneousEssentialBCs_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_HomogeneousEssentialBCs_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, HomogeneousEssentialBCs_Type, (Name)"0", _HomogeneousEssentialBCs_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/EnergySolver/tests/HomogeneousEssentialBCs/HomogeneousEssentialBCs.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/EnergySolver/tests/HomogeneousEssentialBCs/HomogeneousEssentialBCs.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,147 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: HomogeneousEssentialBCs.c 968 2007-10-23 07:53:39Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+const Type HomogeneousEssentialBCs_Type = "HomogeneousEssentialBCs";
+
+typedef struct { 
+	__AnalyticSolution
+	double angle;
+	FeVariable* temperatureField;
+} HomogeneousEssentialBCs;
+
+
+void HomogeneousEssentialBCs_Velocity_SkewToMesh( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	HomogeneousEssentialBCs*  self    = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousEssentialBCs_Type, HomogeneousEssentialBCs, True, 0 );
+	double*                 result  = (double*) _result;
+	
+	result[ I_AXIS ] =  cos( self->angle );
+	result[ J_AXIS ] =  sin( self->angle  );
+}
+
+
+void HomogeneousEssentialBCs_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* temperature ) {
+	HomogeneousEssentialBCs *self = (HomogeneousEssentialBCs*)analyticSolution;
+
+	if ( coord[ J_AXIS ] < tan( self->angle ) * coord[ I_AXIS ] + 0.25 )
+		*temperature = 1.0;
+	else 
+		*temperature = 0.0;
+
+	/* Perform Essential Boundary Conditions */
+	if ( (coord[ I_AXIS ] > 0.99 && coord[ J_AXIS ] > 0.01) || coord[ J_AXIS ] > 0.99 ) {
+		*temperature = 0.0;
+	}
+}
+	
+void HomogeneousEssentialBCs_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context    = (DomainContext*)_context;
+	HomogeneousEssentialBCs*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousEssentialBCs_Type, HomogeneousEssentialBCs, True, 0 );
+	FeVariable*             feVariable = NULL;
+	FeMesh*			mesh       = NULL;
+	double*                 result     = (double*) _result;
+	double*                 coord;
+	
+	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	mesh       = feVariable->feMesh;
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	HomogeneousEssentialBCs_TemperatureFunction( self, feVariable, coord, result );
+}
+
+void _HomogeneousEssentialBCs_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	HomogeneousEssentialBCs* self = (HomogeneousEssentialBCs*)analyticSolution;
+	AbstractContext*       context;
+	ConditionFunction*     condFunc;
+
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+
+	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, HomogeneousEssentialBCs_TemperatureFunction );
+
+	self->angle = StGermain_DegreeToRadian (Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"VelocitySkewAngle", 45.0 )  );
+
+	/* Create Condition Functions */
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
+	condFunc = ConditionFunction_New( HomogeneousEssentialBCs_Velocity_SkewToMesh, (Name)"Velocity_SkewToMesh"  );
+	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
+	condFunc = ConditionFunction_New( HomogeneousEssentialBCs_TemperatureBC, (Name)"Temperature_StepFunction"  );
+	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
+}
+
+void _HomogeneousEssentialBCs_Build( void* analyticSolution, void* data ) {
+	HomogeneousEssentialBCs* self = (HomogeneousEssentialBCs*)analyticSolution;	
+
+	_AnalyticSolution_Build( self, data );
+}
+
+void* _HomogeneousEssentialBCs_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(HomogeneousEssentialBCs);
+	Type                                                      type = HomogeneousEssentialBCs_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _HomogeneousEssentialBCs_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _HomogeneousEssentialBCs_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _HomogeneousEssentialBCs_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_HomogeneousEssentialBCs_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, HomogeneousEssentialBCs_Type, (Name)"0", _HomogeneousEssentialBCs_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/EnergySolver/tests/HomogeneousNaturalBCs/HomogeneousNaturalBCs.c
--- a/Apps/EnergySolver/tests/HomogeneousNaturalBCs/HomogeneousNaturalBCs.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: HomogeneousNaturalBCs.c 967 2007-10-23 05:27:09Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-const Type HomogeneousNaturalBCs_Type = "HomogeneousNaturalBCs";
-
-typedef struct { 
-	__AnalyticSolution
-	double angle;
-	FeVariable* temperatureField;
-} HomogeneousNaturalBCs;
-
-
-void HomogeneousNaturalBCs_Velocity_SkewToMesh( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	HomogeneousNaturalBCs*  self    = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousNaturalBCs_Type, HomogeneousNaturalBCs, True, 0 );
-	double*                 result  = (double*) _result;
-	
-	result[ I_AXIS ] =  cos( self->angle );
-	result[ J_AXIS ] =  sin( self->angle  );
-}
-
-
-void HomogeneousNaturalBCs_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* temperature ) {
-	HomogeneousNaturalBCs *self = (HomogeneousNaturalBCs*)analyticSolution;
-
-	if ( coord[ J_AXIS ] < tan( self->angle ) * coord[ I_AXIS ] + 0.25 )
-		*temperature = 1.0;
-	else 
-		*temperature = 0.0;
-}
-	
-void HomogeneousNaturalBCs_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context    = (DomainContext*)_context;
-	HomogeneousNaturalBCs*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousNaturalBCs_Type, HomogeneousNaturalBCs, True, 0 );
-	FeVariable*             feVariable = NULL;
-	FeMesh*			mesh       = NULL;
-	double*                 result     = (double*) _result;
-	double*                 coord;
-	
-	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	mesh       = feVariable->feMesh;
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	HomogeneousNaturalBCs_TemperatureFunction( self, feVariable, coord, result );
-}
-
-void _HomogeneousNaturalBCs_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	HomogeneousNaturalBCs* self = (HomogeneousNaturalBCs*)analyticSolution;
-	AbstractContext*       context;
-	ConditionFunction*     condFunc;
-
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-
-	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, HomogeneousNaturalBCs_TemperatureFunction );
-
-	self->angle = StGermain_DegreeToRadian (Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"VelocitySkewAngle", 45.0 )  );
-
-	/* Create Condition Functions */
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
-	condFunc = ConditionFunction_New( HomogeneousNaturalBCs_Velocity_SkewToMesh, (Name)"Velocity_SkewToMesh"  );
-	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
-	condFunc = ConditionFunction_New( HomogeneousNaturalBCs_TemperatureBC, (Name)"Temperature_StepFunction"  );
-	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
-}
-
-void _HomogeneousNaturalBCs_Build( void* analyticSolution, void* data ) {
-	HomogeneousNaturalBCs* self = (HomogeneousNaturalBCs*)analyticSolution;	
-
-	_AnalyticSolution_Build( self, data );
-}
-
-void* _HomogeneousNaturalBCs_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(HomogeneousNaturalBCs);
-	Type                                                      type = HomogeneousNaturalBCs_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _HomogeneousNaturalBCs_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _HomogeneousNaturalBCs_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _HomogeneousNaturalBCs_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_HomogeneousNaturalBCs_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, HomogeneousNaturalBCs_Type, (Name)"0", _HomogeneousNaturalBCs_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/EnergySolver/tests/HomogeneousNaturalBCs/HomogeneousNaturalBCs.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/EnergySolver/tests/HomogeneousNaturalBCs/HomogeneousNaturalBCs.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,142 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: HomogeneousNaturalBCs.c 967 2007-10-23 05:27:09Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+const Type HomogeneousNaturalBCs_Type = "HomogeneousNaturalBCs";
+
+typedef struct { 
+	__AnalyticSolution
+	double angle;
+	FeVariable* temperatureField;
+} HomogeneousNaturalBCs;
+
+
+void HomogeneousNaturalBCs_Velocity_SkewToMesh( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	HomogeneousNaturalBCs*  self    = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousNaturalBCs_Type, HomogeneousNaturalBCs, True, 0 );
+	double*                 result  = (double*) _result;
+	
+	result[ I_AXIS ] =  cos( self->angle );
+	result[ J_AXIS ] =  sin( self->angle  );
+}
+
+
+void HomogeneousNaturalBCs_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* temperature ) {
+	HomogeneousNaturalBCs *self = (HomogeneousNaturalBCs*)analyticSolution;
+
+	if ( coord[ J_AXIS ] < tan( self->angle ) * coord[ I_AXIS ] + 0.25 )
+		*temperature = 1.0;
+	else 
+		*temperature = 0.0;
+}
+	
+void HomogeneousNaturalBCs_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context    = (DomainContext*)_context;
+	HomogeneousNaturalBCs*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousNaturalBCs_Type, HomogeneousNaturalBCs, True, 0 );
+	FeVariable*             feVariable = NULL;
+	FeMesh*			mesh       = NULL;
+	double*                 result     = (double*) _result;
+	double*                 coord;
+	
+	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	mesh       = feVariable->feMesh;
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	HomogeneousNaturalBCs_TemperatureFunction( self, feVariable, coord, result );
+}
+
+void _HomogeneousNaturalBCs_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	HomogeneousNaturalBCs* self = (HomogeneousNaturalBCs*)analyticSolution;
+	AbstractContext*       context;
+	ConditionFunction*     condFunc;
+
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+
+	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, HomogeneousNaturalBCs_TemperatureFunction );
+
+	self->angle = StGermain_DegreeToRadian (Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"VelocitySkewAngle", 45.0 )  );
+
+	/* Create Condition Functions */
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
+	condFunc = ConditionFunction_New( HomogeneousNaturalBCs_Velocity_SkewToMesh, (Name)"Velocity_SkewToMesh"  );
+	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
+	condFunc = ConditionFunction_New( HomogeneousNaturalBCs_TemperatureBC, (Name)"Temperature_StepFunction"  );
+	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
+}
+
+void _HomogeneousNaturalBCs_Build( void* analyticSolution, void* data ) {
+	HomogeneousNaturalBCs* self = (HomogeneousNaturalBCs*)analyticSolution;	
+
+	_AnalyticSolution_Build( self, data );
+}
+
+void* _HomogeneousNaturalBCs_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(HomogeneousNaturalBCs);
+	Type                                                      type = HomogeneousNaturalBCs_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _HomogeneousNaturalBCs_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _HomogeneousNaturalBCs_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _HomogeneousNaturalBCs_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_HomogeneousNaturalBCs_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, HomogeneousNaturalBCs_Type, (Name)"0", _HomogeneousNaturalBCs_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/StokesMomentumUzawa/tests/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.c
--- a/Apps/StokesMomentumUzawa/tests/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LidDrivenIsoviscousAnalytic.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-/* This is taken from Mirko Velic's Analytic Stokes Flow solution */
-
-const Type LidDrivenIsoviscousAnalytic_Type = "LidDrivenIsoviscousAnalytic";
-
-typedef struct { 
-	__FieldTest 
-	unsigned int wavenumber;
-	double A, B, C, D;
-} LidDrivenIsoviscousAnalytic;
-
-
-void LidDrivenIsoviscousAnalytic_CalculateConstants( LidDrivenIsoviscousAnalytic *self ) {
-	double E;
-	double e_nPI;
-	double e_2nPI;
-	double e_4nPI;
-	double n;
-
-	n = (double) self->wavenumber;
-
-	e_nPI = exp( n * M_PI );
-	e_2nPI = e_nPI * e_nPI;
-	e_4nPI = e_2nPI * e_2nPI;
-
-	E = (4.0 * n * n * M_PI * M_PI + 2.0 ) * e_2nPI - e_4nPI - 1.0;
-
-	self->A = ( e_2nPI - 1.0 )* e_nPI / E;
-	self->B = - self->A;
-
-	self->C =   ( 2.0 * n * M_PI - e_2nPI + 1.0 ) * e_nPI / E;
-	self->D = - ( 2.0 * n * M_PI * e_2nPI - e_2nPI + 1.0 ) * e_nPI / E;
-}
-
-void LidDrivenIsoviscousAnalytic_VelocityFunction( void* codelet, double* coord, double* velocity ) {
-	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)codelet;
-	double x,y;
-	double n;
-	double A, B, C, D;
-
-	/* Get local copy of constants */
-	n = (double) self->wavenumber;
-	A = self->A;
-	B = self->B;
-	C = self->C;
-	D = self->D;
-
-	/* get copy of coords */
-	x = coord[I_AXIS];
-	y = coord[J_AXIS];
-	
-	velocity[ I_AXIS ] = sin( n * M_PI * x ) * 
-		( ( A * n * M_PI + C + C * n * M_PI * y) *exp( n * M_PI * y ) 
-		- ( B * n * M_PI - D + D * n * M_PI * y ) * exp( - n * M_PI * y ) );
-	velocity[ J_AXIS ] = - n * M_PI * cos( n * M_PI * x ) * 
-		( ( A + C * y ) * exp( n * M_PI * y ) 
-		+ ( B + D * y ) * exp( - n * M_PI * y ) );
-}
-
-void LidDrivenIsoviscousAnalytic_PressureFunction( void* codelet, double* coord, double* pressure ) {
-	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)codelet;
-	double x,y;
-	double n;
-	double A, B, C, D;
-
-	/* Get local copy of constants */
-	n = (double) self->wavenumber;
-	A = self->A;
-	B = self->B;
-	C = self->C;
-	D = self->D;
-
-	/* get copy of coords */
-	x = coord[I_AXIS];
-	y = coord[J_AXIS];
-	
-	*pressure = - 2.0 * n * M_PI * cos( n * M_PI * x ) * ( C * exp( n * M_PI * y ) + D * exp( - n * M_PI * y ) );
-}
-
-void _LidDrivenIsoviscousAnalytic_AssignFromXML( void* codelet, Stg_ComponentFactory* cf, void* data ) {
-	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)codelet;
-
-	_FieldTest_AssignFromXML( self, cf, data );
-	
-	/* Set constants */
-	self->wavenumber = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"sinusoidalLidWavenumber", 1 );
-	LidDrivenIsoviscousAnalytic_CalculateConstants( self  );
-}
-
-void _LidDrivenIsoviscousAnalytic_Build( void* codelet, void* data ) {
-	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)codelet;
-
-	_FieldTest_Build( self, data );
-
-	 /* here we assign the memory and the func ptr for analytic sols */
-   self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 2 );
-	self->_analyticSolutionList[0] = LidDrivenIsoviscousAnalytic_VelocityFunction;
-   self->_analyticSolutionList[1] = LidDrivenIsoviscousAnalytic_PressureFunction;
-}
-
-void _LidDrivenIsoviscousAnalytic_Initialise( void* codelet, void* data ) {
-   _FieldTest_Initialise( codelet, data );
-}
-
-void* _LidDrivenIsoviscousAnalytic_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(LidDrivenIsoviscousAnalytic);
-	Type                                                      type = LidDrivenIsoviscousAnalytic_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LidDrivenIsoviscousAnalytic_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _LidDrivenIsoviscousAnalytic_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _LidDrivenIsoviscousAnalytic_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_LidDrivenIsoviscousAnalytic_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, LidDrivenIsoviscousAnalytic_Type, (Name)"0", _LidDrivenIsoviscousAnalytic_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/StokesMomentumUzawa/tests/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/StokesMomentumUzawa/tests/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,175 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LidDrivenIsoviscousAnalytic.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+/* This is taken from Mirko Velic's Analytic Stokes Flow solution */
+
+const Type LidDrivenIsoviscousAnalytic_Type = "LidDrivenIsoviscousAnalytic";
+
+typedef struct { 
+	__FieldTest 
+	unsigned int wavenumber;
+	double A, B, C, D;
+} LidDrivenIsoviscousAnalytic;
+
+
+void LidDrivenIsoviscousAnalytic_CalculateConstants( LidDrivenIsoviscousAnalytic *self ) {
+	double E;
+	double e_nPI;
+	double e_2nPI;
+	double e_4nPI;
+	double n;
+
+	n = (double) self->wavenumber;
+
+	e_nPI = exp( n * M_PI );
+	e_2nPI = e_nPI * e_nPI;
+	e_4nPI = e_2nPI * e_2nPI;
+
+	E = (4.0 * n * n * M_PI * M_PI + 2.0 ) * e_2nPI - e_4nPI - 1.0;
+
+	self->A = ( e_2nPI - 1.0 )* e_nPI / E;
+	self->B = - self->A;
+
+	self->C =   ( 2.0 * n * M_PI - e_2nPI + 1.0 ) * e_nPI / E;
+	self->D = - ( 2.0 * n * M_PI * e_2nPI - e_2nPI + 1.0 ) * e_nPI / E;
+}
+
+void LidDrivenIsoviscousAnalytic_VelocityFunction( void* codelet, double* coord, double* velocity ) {
+	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)codelet;
+	double x,y;
+	double n;
+	double A, B, C, D;
+
+	/* Get local copy of constants */
+	n = (double) self->wavenumber;
+	A = self->A;
+	B = self->B;
+	C = self->C;
+	D = self->D;
+
+	/* get copy of coords */
+	x = coord[I_AXIS];
+	y = coord[J_AXIS];
+	
+	velocity[ I_AXIS ] = sin( n * M_PI * x ) * 
+		( ( A * n * M_PI + C + C * n * M_PI * y) *exp( n * M_PI * y ) 
+		- ( B * n * M_PI - D + D * n * M_PI * y ) * exp( - n * M_PI * y ) );
+	velocity[ J_AXIS ] = - n * M_PI * cos( n * M_PI * x ) * 
+		( ( A + C * y ) * exp( n * M_PI * y ) 
+		+ ( B + D * y ) * exp( - n * M_PI * y ) );
+}
+
+void LidDrivenIsoviscousAnalytic_PressureFunction( void* codelet, double* coord, double* pressure ) {
+	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)codelet;
+	double x,y;
+	double n;
+	double A, B, C, D;
+
+	/* Get local copy of constants */
+	n = (double) self->wavenumber;
+	A = self->A;
+	B = self->B;
+	C = self->C;
+	D = self->D;
+
+	/* get copy of coords */
+	x = coord[I_AXIS];
+	y = coord[J_AXIS];
+	
+	*pressure = - 2.0 * n * M_PI * cos( n * M_PI * x ) * ( C * exp( n * M_PI * y ) + D * exp( - n * M_PI * y ) );
+}
+
+void _LidDrivenIsoviscousAnalytic_AssignFromXML( void* codelet, Stg_ComponentFactory* cf, void* data ) {
+	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)codelet;
+
+	_FieldTest_AssignFromXML( self, cf, data );
+	
+	/* Set constants */
+	self->wavenumber = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"sinusoidalLidWavenumber", 1 );
+	LidDrivenIsoviscousAnalytic_CalculateConstants( self  );
+}
+
+void _LidDrivenIsoviscousAnalytic_Build( void* codelet, void* data ) {
+	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)codelet;
+
+	_FieldTest_Build( self, data );
+
+	 /* here we assign the memory and the func ptr for analytic sols */
+   self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 2 );
+	self->_analyticSolutionList[0] = LidDrivenIsoviscousAnalytic_VelocityFunction;
+   self->_analyticSolutionList[1] = LidDrivenIsoviscousAnalytic_PressureFunction;
+}
+
+void _LidDrivenIsoviscousAnalytic_Initialise( void* codelet, void* data ) {
+   _FieldTest_Initialise( codelet, data );
+}
+
+void* _LidDrivenIsoviscousAnalytic_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(LidDrivenIsoviscousAnalytic);
+	Type                                                      type = LidDrivenIsoviscousAnalytic_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LidDrivenIsoviscousAnalytic_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _LidDrivenIsoviscousAnalytic_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _LidDrivenIsoviscousAnalytic_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_LidDrivenIsoviscousAnalytic_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, LidDrivenIsoviscousAnalytic_Type, (Name)"0", _LidDrivenIsoviscousAnalytic_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/StokesMomentumUzawa/tests/LidDrivenStokesAnalytic/LidDrivenStokesAnalytic.c
--- a/Apps/StokesMomentumUzawa/tests/LidDrivenStokesAnalytic/LidDrivenStokesAnalytic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LidDrivenStokesAnalytic.c 922 2007-07-25 03:01:19Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-#include <assert.h>
-#include <math.h>
-
-const Type StgFEM_LidDrivenStokesAnalytic_Type = "StgFEM_LidDrivenStokesAnalytic";
-
-typedef struct {
-	__FieldTest;
-	unsigned int n;
-	double A, B, C, D;
-} StgFEM_LidDrivenStokesAnalytic;
-
-void StgFEM_LidDrivenStokesAnalytic_CalculateConstants( FieldTest *fieldTest ) {
-	StgFEM_LidDrivenStokesAnalytic* self = (StgFEM_LidDrivenStokesAnalytic*)fieldTest;
-	double                  E;
-	double                  e_nPI;
-	double                  e_2nPI;
-	double                  e_4nPI;
-	double                  n;
-	
-	n = (double)self->n;
-
-	e_nPI = exp( n * M_PI );
-	e_2nPI = e_nPI * e_nPI;
-	e_4nPI = e_2nPI * e_2nPI;
-
-	E = (4.0 * n * n * M_PI * M_PI + 2.0 ) * e_2nPI - e_4nPI - 1.0;
-
-	self->A     = ( e_2nPI - 1.0 )* e_nPI / E;
-	self->B     = self->A;
-
-	self->C     =   ( 2.0 * n * M_PI - e_2nPI + 1.0 ) * e_nPI / E;
-	self->D     = - ( 2.0 * n * M_PI * e_2nPI - e_2nPI + 1.0 ) * e_nPI / E;
-}
-
-void StgFEM_LidDrivenStokesAnalytic_VelocityFunction( void* data, double* coord, double* velocity ) {
-	StgFEM_LidDrivenStokesAnalytic* self = (StgFEM_LidDrivenStokesAnalytic*)data;
-	double x,y;
-	double n;
-	double A, B, C, D;
-	
-	n = (double)self->n;
-	A = self->A;
-	B = self->B;
-	C = self->C;
-	D = self->D;
-
-	/* get copy of coords */
-	x = coord[I_AXIS];
-	y = coord[J_AXIS];
-	
-	velocity[ I_AXIS ] = sin( n * M_PI * x ) * 
-		( ( A * n * M_PI + C + C * n * M_PI * y) *exp( n * M_PI * y ) 
-		- ( B * n * M_PI - D + D * n * M_PI * y ) * exp( - n * M_PI * y ) );
-	velocity[ J_AXIS ] = - n * M_PI * cos( n * M_PI * x ) * 
-		( ( A + C * y ) * exp( n * M_PI * y ) 
-		+ ( B + D * y ) * exp( - n * M_PI * y ) );
-}
-
-
-void StgFEM_LidDrivenStokesAnalytic_PressureFunction( void* data, double* coord, double* pressure ) {
-	StgFEM_LidDrivenStokesAnalytic* self = (StgFEM_LidDrivenStokesAnalytic*)data;
-	double x,y;
-	double n;
-	double A, B, C, D;
-	
-	n = (double)self->n;
-	A = self->A;
-	B = self->B;
-	C = self->C;
-	D = self->D;
-
-	/* get copy of coords */
-	x = coord[I_AXIS];
-	y = coord[J_AXIS];
-	
-	*pressure = - 2.0 * n * M_PI * cos( n * M_PI * x ) * ( C * exp( n * M_PI * y ) + D * exp( - n * M_PI * y ) );
-}
-
-void _StgFEM_LidDrivenStokesAnalytic_AssignFromXML( void* codelet, Stg_ComponentFactory* cf, void* data ) {
-	StgFEM_LidDrivenStokesAnalytic *self = (StgFEM_LidDrivenStokesAnalytic*)codelet;
-	
-	unsigned int* waveSpeed;
-
-	_FieldTest_AssignFromXML( self, cf, data );
-
-	/* Set constants */
-	*waveSpeed = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"sinusoidalLidWavenumber", 1 );
-	self->n = *waveSpeed;
-	
-	StgFEM_LidDrivenStokesAnalytic_CalculateConstants( (FieldTest*)self  );
-}
-
-void _StgFEM_LidDrivenStokesAnalytic_Build( void* codelet, void* data ) {
-	StgFEM_LidDrivenStokesAnalytic *self = (StgFEM_LidDrivenStokesAnalytic*)codelet;
-
-	_FieldTest_Build( self, data );
-
-	/* set the analytic solution functions for the feVariables - must be in the same order as the XML */
-	FieldTest_AddAnalyticSolutionFuncToListAtIndex( self, 0, StgFEM_LidDrivenStokesAnalytic_VelocityFunction, 0 );
-	FieldTest_AddAnalyticSolutionFuncToListAtIndex( self, 1, StgFEM_LidDrivenStokesAnalytic_PressureFunction, 1 );
-}
-
-void _StgFEM_LidDrivenStokesAnalytic_Initialise( void* codelet, void* data ) {
-	_FieldTest_Initialise( codelet, data );
-}
-
-
-void* _StgFEM_LidDrivenStokesAnalytic_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(StgFEM_LidDrivenStokesAnalytic);
-	Type                                                      type = StgFEM_LidDrivenStokesAnalytic_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_LidDrivenStokesAnalytic_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _StgFEM_LidDrivenStokesAnalytic_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _StgFEM_LidDrivenStokesAnalytic_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-Index StgFEM_LidDrivenStokesAnalytic_Register( PluginsManager* pluginsManager ) {
-	Journal_DPrintf( StgFEM_Debug, "In: %s( void* )\n", __func__ ); 
-
-	return PluginsManager_Submit( pluginsManager, StgFEM_LidDrivenStokesAnalytic_Type, (Name)"0", _StgFEM_LidDrivenStokesAnalytic_DefaultNew  );
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/StokesMomentumUzawa/tests/LidDrivenStokesAnalytic/LidDrivenStokesAnalytic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/StokesMomentumUzawa/tests/LidDrivenStokesAnalytic/LidDrivenStokesAnalytic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,182 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LidDrivenStokesAnalytic.c 922 2007-07-25 03:01:19Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+#include <assert.h>
+#include <math.h>
+
+const Type StgFEM_LidDrivenStokesAnalytic_Type = "StgFEM_LidDrivenStokesAnalytic";
+
+typedef struct {
+	__FieldTest;
+	unsigned int n;
+	double A, B, C, D;
+} StgFEM_LidDrivenStokesAnalytic;
+
+void StgFEM_LidDrivenStokesAnalytic_CalculateConstants( FieldTest *fieldTest ) {
+	StgFEM_LidDrivenStokesAnalytic* self = (StgFEM_LidDrivenStokesAnalytic*)fieldTest;
+	double                  E;
+	double                  e_nPI;
+	double                  e_2nPI;
+	double                  e_4nPI;
+	double                  n;
+	
+	n = (double)self->n;
+
+	e_nPI = exp( n * M_PI );
+	e_2nPI = e_nPI * e_nPI;
+	e_4nPI = e_2nPI * e_2nPI;
+
+	E = (4.0 * n * n * M_PI * M_PI + 2.0 ) * e_2nPI - e_4nPI - 1.0;
+
+	self->A     = ( e_2nPI - 1.0 )* e_nPI / E;
+	self->B     = self->A;
+
+	self->C     =   ( 2.0 * n * M_PI - e_2nPI + 1.0 ) * e_nPI / E;
+	self->D     = - ( 2.0 * n * M_PI * e_2nPI - e_2nPI + 1.0 ) * e_nPI / E;
+}
+
+void StgFEM_LidDrivenStokesAnalytic_VelocityFunction( void* data, double* coord, double* velocity ) {
+	StgFEM_LidDrivenStokesAnalytic* self = (StgFEM_LidDrivenStokesAnalytic*)data;
+	double x,y;
+	double n;
+	double A, B, C, D;
+	
+	n = (double)self->n;
+	A = self->A;
+	B = self->B;
+	C = self->C;
+	D = self->D;
+
+	/* get copy of coords */
+	x = coord[I_AXIS];
+	y = coord[J_AXIS];
+	
+	velocity[ I_AXIS ] = sin( n * M_PI * x ) * 
+		( ( A * n * M_PI + C + C * n * M_PI * y) *exp( n * M_PI * y ) 
+		- ( B * n * M_PI - D + D * n * M_PI * y ) * exp( - n * M_PI * y ) );
+	velocity[ J_AXIS ] = - n * M_PI * cos( n * M_PI * x ) * 
+		( ( A + C * y ) * exp( n * M_PI * y ) 
+		+ ( B + D * y ) * exp( - n * M_PI * y ) );
+}
+
+
+void StgFEM_LidDrivenStokesAnalytic_PressureFunction( void* data, double* coord, double* pressure ) {
+	StgFEM_LidDrivenStokesAnalytic* self = (StgFEM_LidDrivenStokesAnalytic*)data;
+	double x,y;
+	double n;
+	double A, B, C, D;
+	
+	n = (double)self->n;
+	A = self->A;
+	B = self->B;
+	C = self->C;
+	D = self->D;
+
+	/* get copy of coords */
+	x = coord[I_AXIS];
+	y = coord[J_AXIS];
+	
+	*pressure = - 2.0 * n * M_PI * cos( n * M_PI * x ) * ( C * exp( n * M_PI * y ) + D * exp( - n * M_PI * y ) );
+}
+
+void _StgFEM_LidDrivenStokesAnalytic_AssignFromXML( void* codelet, Stg_ComponentFactory* cf, void* data ) {
+	StgFEM_LidDrivenStokesAnalytic *self = (StgFEM_LidDrivenStokesAnalytic*)codelet;
+	
+	unsigned int* waveSpeed;
+
+	_FieldTest_AssignFromXML( self, cf, data );
+
+	/* Set constants */
+	*waveSpeed = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"sinusoidalLidWavenumber", 1 );
+	self->n = *waveSpeed;
+	
+	StgFEM_LidDrivenStokesAnalytic_CalculateConstants( (FieldTest*)self  );
+}
+
+void _StgFEM_LidDrivenStokesAnalytic_Build( void* codelet, void* data ) {
+	StgFEM_LidDrivenStokesAnalytic *self = (StgFEM_LidDrivenStokesAnalytic*)codelet;
+
+	_FieldTest_Build( self, data );
+
+	/* set the analytic solution functions for the feVariables - must be in the same order as the XML */
+	FieldTest_AddAnalyticSolutionFuncToListAtIndex( self, 0, StgFEM_LidDrivenStokesAnalytic_VelocityFunction, 0 );
+	FieldTest_AddAnalyticSolutionFuncToListAtIndex( self, 1, StgFEM_LidDrivenStokesAnalytic_PressureFunction, 1 );
+}
+
+void _StgFEM_LidDrivenStokesAnalytic_Initialise( void* codelet, void* data ) {
+	_FieldTest_Initialise( codelet, data );
+}
+
+
+void* _StgFEM_LidDrivenStokesAnalytic_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(StgFEM_LidDrivenStokesAnalytic);
+	Type                                                      type = StgFEM_LidDrivenStokesAnalytic_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_LidDrivenStokesAnalytic_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _StgFEM_LidDrivenStokesAnalytic_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _StgFEM_LidDrivenStokesAnalytic_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+Index StgFEM_LidDrivenStokesAnalytic_Register( PluginsManager* pluginsManager ) {
+	Journal_DPrintf( StgFEM_Debug, "In: %s( void* )\n", __func__ ); 
+
+	return PluginsManager_Submit( pluginsManager, StgFEM_LidDrivenStokesAnalytic_Type, (Name)"0", _StgFEM_LidDrivenStokesAnalytic_DefaultNew  );
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/StokesMomentumUzawa/tests/LinearVelocityAnalytic/LinearVelocityAnalytic.c
--- a/Apps/StokesMomentumUzawa/tests/LinearVelocityAnalytic/LinearVelocityAnalytic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,380 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LinearVelocityAnalytic.c 1111 2008-04-23 04:12:36Z RobertTurnbull $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include <string.h>
-
-const Type LinearVelocityAnalytic_Type = "LinearVelocityAnalytic";
-
-typedef struct { 
-	__AnalyticSolution
-	FeVariable* velocityField;
-	double  nodeVelocity[8][3];
-	double  nodeCoords[8][3];
-	int    cornerNodeCount;
-} LinearVelocityAnalytic;
-
-Index Grid_ProjectIJK( Grid* grid, Index i, Index j, Index k ) {
-	IJK ijk = {0,0,0};
-	
-	ijk[0] = i;
-	ijk[1] = j;
-	ijk[2] = k;
-
-	return Grid_Project( grid, ijk );
-}
-Index Grid_ProjectIJK_MinMax( Grid* grid, Bool iIsMax, Bool jIsMax, Bool kIsMax ) {
-	IJK ijk = {0,0,0};
-	
-	if ( iIsMax )
-		ijk[0] = grid->sizes[0] - 1;
-	if ( jIsMax )
-		ijk[1] = grid->sizes[1] - 1;
-	if ( kIsMax )
-		ijk[2] = grid->sizes[2] - 1;
-
-	return Grid_Project( grid, ijk );
-}
-
-void LinearVelocityAnalytic_GetCornerNodeVelocities(void* analyticSolution) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	Grid*                   vertGrid;
-	Node_GlobalIndex        nodeMapper[8];
-	FeVariable*             velocityField = self->velocityField;
-	FeMesh*                 mesh = velocityField->feMesh;
-	Dimension_Index         dim = velocityField->dim;
-	Node_Index              globalNode_I;
-	Node_Index              ii;
-	
-	vertGrid = *(Grid**)ExtensionManager_Get( mesh->info, mesh, ExtensionManager_GetHandle( mesh->info, (Name)"vertexGrid" )  );
-
-	/* Find global indicies of nodes */
-	self->cornerNodeCount = 4;
-	nodeMapper[0] = Grid_ProjectIJK_MinMax( vertGrid, 0, 0, 0 );
-	nodeMapper[1] = Grid_ProjectIJK_MinMax( vertGrid, 1, 0, 0 );
-	nodeMapper[2] = Grid_ProjectIJK_MinMax( vertGrid, 0, 1, 0 );
-	nodeMapper[3] = Grid_ProjectIJK_MinMax( vertGrid, 1, 1, 0 );
-	if ( dim == 3 ) {
-		self->cornerNodeCount = 8;
-		nodeMapper[4] = Grid_ProjectIJK_MinMax( vertGrid, 0, 0, 1 );
-		nodeMapper[5] = Grid_ProjectIJK_MinMax( vertGrid, 1, 0, 1 );
-		nodeMapper[6] = Grid_ProjectIJK_MinMax( vertGrid, 0, 1, 1 );
-		nodeMapper[7] = Grid_ProjectIJK_MinMax( vertGrid, 1, 1, 1 );
-	}
-
-	/* Loop over corner nodes */
-	for ( ii = 0 ; ii < self->cornerNodeCount ; ii++ ) {
-		globalNode_I = nodeMapper[ ii ];
-		FeVariable_GetValueAtNodeGlobal( velocityField, globalNode_I, self->nodeVelocity[ii] );
-		FeVariable_GetCoordAtNodeGlobal( velocityField, globalNode_I, self->nodeCoords[ii] );
-	}
-}
-
-void GetLocalCoords( LinearVelocityAnalytic* self, double* coord, double* xi ) {
-	FeVariable*             velocityField = self->velocityField;
-	XYZ                     min;
-	XYZ                     max;
-	Dimension_Index         dim = velocityField->dim;
-	Dimension_Index         dim_I;
-
-	_FeVariable_GetMinAndMaxGlobalCoords( velocityField, min, max );
-	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
-		xi[ dim_I ] = 2.0 * (coord[ dim_I ] - min[ dim_I ])/(max[dim_I] - min[dim_I]) - 1;
-	}	
-}	
-
-/* Do a normal linear interpolation as if the box were a FEM element */
-void LinearVelocityAnalytic_VelocityFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* velocity ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	FeVariable*             velocityField = self->velocityField;
-	FeMesh*                 mesh = velocityField->feMesh;
-	Dimension_Index         dim = velocityField->dim;
-	Dimension_Index         dim_I;
-	XYZ                     xi;
-	double                  Ni[8];
-	Node_Index              ii;
-	ElementType*            elementType;
-
-	/* Transform the coordinate into a master coordinate system */
-	GetLocalCoords( self, coord, xi );
-
-	/* Get Shape Functions */
-	elementType = FeMesh_GetElementType( mesh, 0 );
-	ElementType_EvaluateShapeFunctionsAt( elementType, xi, Ni );
-
-	/* Do interpolation */
-	/* Loop over corner nodes */
-	memset( velocity, 0, dim*sizeof(double) );
-	for ( ii = 0 ; ii < self->cornerNodeCount ; ii++ ) {
-		for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
-			velocity[ dim_I ] += Ni[ ii ] * self->nodeVelocity[ii][ dim_I ];
-		}
-	}
-}
-void LinearVelocityAnalytic_PressureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* pressure ) {
-	*pressure = 0.0;
-}
-
-void LinearVelocityAnalytic_VelocityGradientsFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* velocityGradients ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	FeVariable*             velocityField = self->velocityField;
-	FeMesh*                 mesh = velocityField->feMesh;
-	ElementType*            elementType;
-	XYZ                     xi;
-	double                  jac[3][3];
-	double                  cof[3][3];	/* cofactors */
-	double                  detJac;
-	Node_Index              node_I;
-	double**                GNi; 
-	double**                GNx; 
-	double*                 nodeCoord;
-	double                  nodeValue;
-	Dimension_Index         dim = velocityField->dim;
-	Dimension_Index         i, j, dx, dxi;
-	Dimension_Index         dim_I;
-	
-	/* Transform the coordinate into a master coordinate system */
-	GetLocalCoords( self, coord, xi );
-
-	GNi = Memory_Alloc_2DArray( double, dim, self->cornerNodeCount, (Name)"GNi"  );
-	GNx = Memory_Alloc_2DArray( double, dim, self->cornerNodeCount, (Name)"GNx"  );
-
-	/* Get Shape Functions */
-	elementType = FeMesh_GetElementType( mesh, 0 );
-	elementType->_evaluateShapeFunctionLocalDerivsAt( elementType, xi, GNi );
-
-	/* build the jacobian matrix */
-	/*
-	jac = 	\sum_i d/d\xi( N_i ) x_i 		\sum_i d/d\xi( N_i ) y_i
-			\sum_i d/d\eta( N_i ) x_i 		\sum_i d/d\eta( N_i ) y_i
-	*/
-	if( dim == 2 ) {
-		jac[0][0] = jac[0][1] = jac[1][0] = jac[1][1] = 0.0;
-		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
-			nodeCoord = self->nodeCoords[ node_I ];
-			jac[0][0] = jac[0][0] + GNi[0][node_I] * nodeCoord[0];
-			jac[0][1] = jac[0][1] + GNi[0][node_I] * nodeCoord[1];
-			
-			jac[1][0] = jac[1][0] + GNi[1][node_I] * nodeCoord[0];
-			jac[1][1] = jac[1][1] + GNi[1][node_I] * nodeCoord[1];
-		}
-	}
-	
-	if( dim == 3 ) {
-		jac[0][0] = jac[0][1] = jac[0][2] = 0.0;
-		jac[1][0] = jac[1][1] = jac[1][2] = 0.0;
-		jac[2][0] = jac[2][1] = jac[2][2] = 0.0;
-		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
-			nodeCoord = self->nodeCoords[ node_I ];
-			jac[0][0] = jac[0][0] + GNi[0][node_I] * nodeCoord[0];
-			jac[0][1] = jac[0][1] + GNi[0][node_I] * nodeCoord[1];
-			jac[0][2] = jac[0][2] + GNi[0][node_I] * nodeCoord[2];
-			
-			jac[1][0] = jac[1][0] + GNi[1][node_I] * nodeCoord[0];
-			jac[1][1] = jac[1][1] + GNi[1][node_I] * nodeCoord[1];
-			jac[1][2] = jac[1][2] + GNi[1][node_I] * nodeCoord[2];
-			
-			jac[2][0] = jac[2][0] + GNi[2][node_I] * nodeCoord[0];
-			jac[2][1] = jac[2][1] + GNi[2][node_I] * nodeCoord[1];
-			jac[2][2] = jac[2][2] + GNi[2][node_I] * nodeCoord[2];
-		}
-	}
-	
-	/* get determinant of the jacobian matrix */
-	if( dim == 2 ) {
-		detJac = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0]; 
-	}		
-	if( dim == 3 ) {
-		detJac = jac[0][0]*( jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1] ) 
-				  - jac[0][1]*( jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0] ) 
-				  + jac[0][2]*( jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0] );
-	}
-	
-	/* invert the jacobian matrix A^-1 = adj(A)/det(A) */
-	if( dim == 2 ) {
-		double tmp = jac[0][0];
-		jac[0][0] = jac[1][1]/detJac;
-		jac[1][1] = tmp/detJac;
-		jac[0][1] = -jac[0][1]/detJac;
-		jac[1][0] = -jac[1][0]/detJac;		
-	}
-	if( dim == 3 ) {
-		/*
-		00 01 02
-		10 11 12
-		20 21 22		
-		*/		
-		cof[0][0] = jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1];
-		cof[1][0] = -(jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0]);
-		cof[2][0] = jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0];
-		
-		cof[0][1] = -(jac[0][1]*jac[2][2] - jac[0][2]*jac[2][1]);
-		cof[1][1] = jac[0][0]*jac[2][2] - jac[0][2]*jac[2][0];
-		cof[2][1] = -(jac[0][0]*jac[2][1] - jac[0][1]*jac[2][0]);
-		
-		cof[0][2] = jac[0][1]*jac[1][2] - jac[0][2]*jac[1][1];
-		cof[1][2] = -(jac[0][0]*jac[1][2] - jac[0][2]*jac[1][0]);
-		cof[2][2] = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0];
-		
-		for( i=0; i<dim; i++ ) {
-			for( j=0; j<dim; j++ ) {
-				jac[i][j] = cof[i][j]/detJac;
-			}
-		}
-		
-		
-	}
-	
-	/* get global derivs Ni_x, Ni_y and Ni_z if dim == 3 */
-	for( dx=0; dx<dim; dx++ ) {
-		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
-			double globalSF_DerivVal = 0.0;
-			for(dxi=0; dxi<dim; dxi++) {
-				globalSF_DerivVal = globalSF_DerivVal + GNi[dxi][node_I] * jac[dx][dxi];
-			}
-			
-			GNx[dx][node_I] = globalSF_DerivVal;
-		}
-	}
-	
-	/* Initialise velocity gradients */
-	memset( velocityGradients, 0, sizeof( double ) * dim * dim );
-	
-	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
-		/* Interpolate derivative from nodes */
-		for( node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
-			nodeValue    = self->nodeVelocity[ node_I ][ dim_I ];
-			
-			velocityGradients[dim_I*dim + 0] += GNx[0][node_I] * nodeValue;
-			velocityGradients[dim_I*dim + 1] += GNx[1][node_I] * nodeValue;
-			if( dim == 3 ) 
-				velocityGradients[dim_I*dim + 2] += GNx[2][node_I] * nodeValue;	
-		}
-	}
-	Memory_Free( GNi );
-	Memory_Free( GNx );
-}
-
-void LinearVelocityAnalytic_StrainRateFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* strainRate ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	Dimension_Index         dim = self->velocityField->dim;
-	TensorArray             velocityGradients;
-
-	/* Get Velocity Gradients */
-	LinearVelocityAnalytic_VelocityGradientsFunction( self, analyticFeVariable, coord, velocityGradients );
-	
-	/* Get Strain Rate */
-	TensorArray_GetSymmetricPart( velocityGradients, dim, strainRate );
-}
-
-void LinearVelocityAnalytic_StrainRateInvFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* strainRateInv ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	Dimension_Index         dim = self->velocityField->dim;
-	SymmetricTensor         strainRate;
-
-	/* Get Strain Rate */
-	LinearVelocityAnalytic_StrainRateFunction( self, analyticFeVariable, coord, strainRate );
-	
-	/* Get Invariant */
-	*strainRateInv = SymmetricTensor_2ndInvariant( strainRate, dim );
-}
-
-void _LinearVelocityAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	FeVariable*       pressureField;
-	FeVariable*       strainRateField;
-	FeVariable*       strainRateInvField;
-
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-
-	self->velocityField = Stg_ComponentFactory_ConstructByName( cf, (Name)"VelocityField", FeVariable, True, data  ); 
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->velocityField, LinearVelocityAnalytic_VelocityFunction );
-	
-	pressureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"PressureField", FeVariable, True, data  ); 
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, pressureField, LinearVelocityAnalytic_PressureFunction );
-	
-	strainRateField = Stg_ComponentFactory_ConstructByName( cf, (Name)"StrainRateField", FeVariable, False, data ); 
-	if ( strainRateField  )
-		AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, strainRateField, LinearVelocityAnalytic_StrainRateFunction );
-	
-	strainRateInvField = Stg_ComponentFactory_ConstructByName( cf, (Name)"StrainRateInvariantField", FeVariable, False, data ); 
-	if ( strainRateInvField  )
-		AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, strainRateInvField, LinearVelocityAnalytic_StrainRateInvFunction );
-}
-
-void _LinearVelocityAnalytic_Initialise( void* analyticSolution, void* data ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	
-	Stg_Component_Initialise( self->velocityField, data,  False );
-	LinearVelocityAnalytic_GetCornerNodeVelocities( self );
-
-	_AnalyticSolution_Initialise( self, data );
-}
-
-void* _LinearVelocityAnalytic_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(LinearVelocityAnalytic);
-	Type                                                      type = LinearVelocityAnalytic_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinearVelocityAnalytic_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _LinearVelocityAnalytic_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _AnalyticSolution_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _LinearVelocityAnalytic_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_LinearVelocityAnalytic_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, LinearVelocityAnalytic_Type, (Name)"0", _LinearVelocityAnalytic_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/StokesMomentumUzawa/tests/LinearVelocityAnalytic/LinearVelocityAnalytic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/StokesMomentumUzawa/tests/LinearVelocityAnalytic/LinearVelocityAnalytic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,380 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LinearVelocityAnalytic.c 1111 2008-04-23 04:12:36Z RobertTurnbull $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include <string.h>
+
+const Type LinearVelocityAnalytic_Type = "LinearVelocityAnalytic";
+
+typedef struct { 
+	__AnalyticSolution
+	FeVariable* velocityField;
+	double  nodeVelocity[8][3];
+	double  nodeCoords[8][3];
+	int    cornerNodeCount;
+} LinearVelocityAnalytic;
+
+Index Grid_ProjectIJK( Grid* grid, Index i, Index j, Index k ) {
+	IJK ijk = {0,0,0};
+	
+	ijk[0] = i;
+	ijk[1] = j;
+	ijk[2] = k;
+
+	return Grid_Project( grid, ijk );
+}
+Index Grid_ProjectIJK_MinMax( Grid* grid, Bool iIsMax, Bool jIsMax, Bool kIsMax ) {
+	IJK ijk = {0,0,0};
+	
+	if ( iIsMax )
+		ijk[0] = grid->sizes[0] - 1;
+	if ( jIsMax )
+		ijk[1] = grid->sizes[1] - 1;
+	if ( kIsMax )
+		ijk[2] = grid->sizes[2] - 1;
+
+	return Grid_Project( grid, ijk );
+}
+
+void LinearVelocityAnalytic_GetCornerNodeVelocities(void* analyticSolution) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	Grid*                   vertGrid;
+	Node_GlobalIndex        nodeMapper[8];
+	FeVariable*             velocityField = self->velocityField;
+	FeMesh*                 mesh = velocityField->feMesh;
+	Dimension_Index         dim = velocityField->dim;
+	Node_Index              globalNode_I;
+	Node_Index              ii;
+	
+	vertGrid = *(Grid**)ExtensionManager_Get( mesh->info, mesh, ExtensionManager_GetHandle( mesh->info, (Name)"vertexGrid" )  );
+
+	/* Find global indicies of nodes */
+	self->cornerNodeCount = 4;
+	nodeMapper[0] = Grid_ProjectIJK_MinMax( vertGrid, 0, 0, 0 );
+	nodeMapper[1] = Grid_ProjectIJK_MinMax( vertGrid, 1, 0, 0 );
+	nodeMapper[2] = Grid_ProjectIJK_MinMax( vertGrid, 0, 1, 0 );
+	nodeMapper[3] = Grid_ProjectIJK_MinMax( vertGrid, 1, 1, 0 );
+	if ( dim == 3 ) {
+		self->cornerNodeCount = 8;
+		nodeMapper[4] = Grid_ProjectIJK_MinMax( vertGrid, 0, 0, 1 );
+		nodeMapper[5] = Grid_ProjectIJK_MinMax( vertGrid, 1, 0, 1 );
+		nodeMapper[6] = Grid_ProjectIJK_MinMax( vertGrid, 0, 1, 1 );
+		nodeMapper[7] = Grid_ProjectIJK_MinMax( vertGrid, 1, 1, 1 );
+	}
+
+	/* Loop over corner nodes */
+	for ( ii = 0 ; ii < self->cornerNodeCount ; ii++ ) {
+		globalNode_I = nodeMapper[ ii ];
+		FeVariable_GetValueAtNodeGlobal( velocityField, globalNode_I, self->nodeVelocity[ii] );
+		FeVariable_GetCoordAtNodeGlobal( velocityField, globalNode_I, self->nodeCoords[ii] );
+	}
+}
+
+void GetLocalCoords( LinearVelocityAnalytic* self, double* coord, double* xi ) {
+	FeVariable*             velocityField = self->velocityField;
+	XYZ                     min;
+	XYZ                     max;
+	Dimension_Index         dim = velocityField->dim;
+	Dimension_Index         dim_I;
+
+	_FeVariable_GetMinAndMaxGlobalCoords( velocityField, min, max );
+	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
+		xi[ dim_I ] = 2.0 * (coord[ dim_I ] - min[ dim_I ])/(max[dim_I] - min[dim_I]) - 1;
+	}	
+}	
+
+/* Do a normal linear interpolation as if the box were a FEM element */
+void LinearVelocityAnalytic_VelocityFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* velocity ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	FeVariable*             velocityField = self->velocityField;
+	FeMesh*                 mesh = velocityField->feMesh;
+	Dimension_Index         dim = velocityField->dim;
+	Dimension_Index         dim_I;
+	XYZ                     xi;
+	double                  Ni[8];
+	Node_Index              ii;
+	ElementType*            elementType;
+
+	/* Transform the coordinate into a master coordinate system */
+	GetLocalCoords( self, coord, xi );
+
+	/* Get Shape Functions */
+	elementType = FeMesh_GetElementType( mesh, 0 );
+	ElementType_EvaluateShapeFunctionsAt( elementType, xi, Ni );
+
+	/* Do interpolation */
+	/* Loop over corner nodes */
+	memset( velocity, 0, dim*sizeof(double) );
+	for ( ii = 0 ; ii < self->cornerNodeCount ; ii++ ) {
+		for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
+			velocity[ dim_I ] += Ni[ ii ] * self->nodeVelocity[ii][ dim_I ];
+		}
+	}
+}
+void LinearVelocityAnalytic_PressureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* pressure ) {
+	*pressure = 0.0;
+}
+
+void LinearVelocityAnalytic_VelocityGradientsFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* velocityGradients ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	FeVariable*             velocityField = self->velocityField;
+	FeMesh*                 mesh = velocityField->feMesh;
+	ElementType*            elementType;
+	XYZ                     xi;
+	double                  jac[3][3];
+	double                  cof[3][3];	/* cofactors */
+	double                  detJac;
+	Node_Index              node_I;
+	double**                GNi; 
+	double**                GNx; 
+	double*                 nodeCoord;
+	double                  nodeValue;
+	Dimension_Index         dim = velocityField->dim;
+	Dimension_Index         i, j, dx, dxi;
+	Dimension_Index         dim_I;
+	
+	/* Transform the coordinate into a master coordinate system */
+	GetLocalCoords( self, coord, xi );
+
+	GNi = Memory_Alloc_2DArray( double, dim, self->cornerNodeCount, (Name)"GNi"  );
+	GNx = Memory_Alloc_2DArray( double, dim, self->cornerNodeCount, (Name)"GNx"  );
+
+	/* Get Shape Functions */
+	elementType = FeMesh_GetElementType( mesh, 0 );
+	elementType->_evaluateShapeFunctionLocalDerivsAt( elementType, xi, GNi );
+
+	/* build the jacobian matrix */
+	/*
+	jac = 	\sum_i d/d\xi( N_i ) x_i 		\sum_i d/d\xi( N_i ) y_i
+			\sum_i d/d\eta( N_i ) x_i 		\sum_i d/d\eta( N_i ) y_i
+	*/
+	if( dim == 2 ) {
+		jac[0][0] = jac[0][1] = jac[1][0] = jac[1][1] = 0.0;
+		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
+			nodeCoord = self->nodeCoords[ node_I ];
+			jac[0][0] = jac[0][0] + GNi[0][node_I] * nodeCoord[0];
+			jac[0][1] = jac[0][1] + GNi[0][node_I] * nodeCoord[1];
+			
+			jac[1][0] = jac[1][0] + GNi[1][node_I] * nodeCoord[0];
+			jac[1][1] = jac[1][1] + GNi[1][node_I] * nodeCoord[1];
+		}
+	}
+	
+	if( dim == 3 ) {
+		jac[0][0] = jac[0][1] = jac[0][2] = 0.0;
+		jac[1][0] = jac[1][1] = jac[1][2] = 0.0;
+		jac[2][0] = jac[2][1] = jac[2][2] = 0.0;
+		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
+			nodeCoord = self->nodeCoords[ node_I ];
+			jac[0][0] = jac[0][0] + GNi[0][node_I] * nodeCoord[0];
+			jac[0][1] = jac[0][1] + GNi[0][node_I] * nodeCoord[1];
+			jac[0][2] = jac[0][2] + GNi[0][node_I] * nodeCoord[2];
+			
+			jac[1][0] = jac[1][0] + GNi[1][node_I] * nodeCoord[0];
+			jac[1][1] = jac[1][1] + GNi[1][node_I] * nodeCoord[1];
+			jac[1][2] = jac[1][2] + GNi[1][node_I] * nodeCoord[2];
+			
+			jac[2][0] = jac[2][0] + GNi[2][node_I] * nodeCoord[0];
+			jac[2][1] = jac[2][1] + GNi[2][node_I] * nodeCoord[1];
+			jac[2][2] = jac[2][2] + GNi[2][node_I] * nodeCoord[2];
+		}
+	}
+	
+	/* get determinant of the jacobian matrix */
+	if( dim == 2 ) {
+		detJac = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0]; 
+	}		
+	if( dim == 3 ) {
+		detJac = jac[0][0]*( jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1] ) 
+				  - jac[0][1]*( jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0] ) 
+				  + jac[0][2]*( jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0] );
+	}
+	
+	/* invert the jacobian matrix A^-1 = adj(A)/det(A) */
+	if( dim == 2 ) {
+		double tmp = jac[0][0];
+		jac[0][0] = jac[1][1]/detJac;
+		jac[1][1] = tmp/detJac;
+		jac[0][1] = -jac[0][1]/detJac;
+		jac[1][0] = -jac[1][0]/detJac;		
+	}
+	if( dim == 3 ) {
+		/*
+		00 01 02
+		10 11 12
+		20 21 22		
+		*/		
+		cof[0][0] = jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1];
+		cof[1][0] = -(jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0]);
+		cof[2][0] = jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0];
+		
+		cof[0][1] = -(jac[0][1]*jac[2][2] - jac[0][2]*jac[2][1]);
+		cof[1][1] = jac[0][0]*jac[2][2] - jac[0][2]*jac[2][0];
+		cof[2][1] = -(jac[0][0]*jac[2][1] - jac[0][1]*jac[2][0]);
+		
+		cof[0][2] = jac[0][1]*jac[1][2] - jac[0][2]*jac[1][1];
+		cof[1][2] = -(jac[0][0]*jac[1][2] - jac[0][2]*jac[1][0]);
+		cof[2][2] = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0];
+		
+		for( i=0; i<dim; i++ ) {
+			for( j=0; j<dim; j++ ) {
+				jac[i][j] = cof[i][j]/detJac;
+			}
+		}
+		
+		
+	}
+	
+	/* get global derivs Ni_x, Ni_y and Ni_z if dim == 3 */
+	for( dx=0; dx<dim; dx++ ) {
+		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
+			double globalSF_DerivVal = 0.0;
+			for(dxi=0; dxi<dim; dxi++) {
+				globalSF_DerivVal = globalSF_DerivVal + GNi[dxi][node_I] * jac[dx][dxi];
+			}
+			
+			GNx[dx][node_I] = globalSF_DerivVal;
+		}
+	}
+	
+	/* Initialise velocity gradients */
+	memset( velocityGradients, 0, sizeof( double ) * dim * dim );
+	
+	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
+		/* Interpolate derivative from nodes */
+		for( node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
+			nodeValue    = self->nodeVelocity[ node_I ][ dim_I ];
+			
+			velocityGradients[dim_I*dim + 0] += GNx[0][node_I] * nodeValue;
+			velocityGradients[dim_I*dim + 1] += GNx[1][node_I] * nodeValue;
+			if( dim == 3 ) 
+				velocityGradients[dim_I*dim + 2] += GNx[2][node_I] * nodeValue;	
+		}
+	}
+	Memory_Free( GNi );
+	Memory_Free( GNx );
+}
+
+void LinearVelocityAnalytic_StrainRateFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* strainRate ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	Dimension_Index         dim = self->velocityField->dim;
+	TensorArray             velocityGradients;
+
+	/* Get Velocity Gradients */
+	LinearVelocityAnalytic_VelocityGradientsFunction( self, analyticFeVariable, coord, velocityGradients );
+	
+	/* Get Strain Rate */
+	TensorArray_GetSymmetricPart( velocityGradients, dim, strainRate );
+}
+
+void LinearVelocityAnalytic_StrainRateInvFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* strainRateInv ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	Dimension_Index         dim = self->velocityField->dim;
+	SymmetricTensor         strainRate;
+
+	/* Get Strain Rate */
+	LinearVelocityAnalytic_StrainRateFunction( self, analyticFeVariable, coord, strainRate );
+	
+	/* Get Invariant */
+	*strainRateInv = SymmetricTensor_2ndInvariant( strainRate, dim );
+}
+
+void _LinearVelocityAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	FeVariable*       pressureField;
+	FeVariable*       strainRateField;
+	FeVariable*       strainRateInvField;
+
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+
+	self->velocityField = Stg_ComponentFactory_ConstructByName( cf, (Name)"VelocityField", FeVariable, True, data  ); 
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->velocityField, LinearVelocityAnalytic_VelocityFunction );
+	
+	pressureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"PressureField", FeVariable, True, data  ); 
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, pressureField, LinearVelocityAnalytic_PressureFunction );
+	
+	strainRateField = Stg_ComponentFactory_ConstructByName( cf, (Name)"StrainRateField", FeVariable, False, data ); 
+	if ( strainRateField  )
+		AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, strainRateField, LinearVelocityAnalytic_StrainRateFunction );
+	
+	strainRateInvField = Stg_ComponentFactory_ConstructByName( cf, (Name)"StrainRateInvariantField", FeVariable, False, data ); 
+	if ( strainRateInvField  )
+		AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, strainRateInvField, LinearVelocityAnalytic_StrainRateInvFunction );
+}
+
+void _LinearVelocityAnalytic_Initialise( void* analyticSolution, void* data ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	
+	Stg_Component_Initialise( self->velocityField, data,  False );
+	LinearVelocityAnalytic_GetCornerNodeVelocities( self );
+
+	_AnalyticSolution_Initialise( self, data );
+}
+
+void* _LinearVelocityAnalytic_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(LinearVelocityAnalytic);
+	Type                                                      type = LinearVelocityAnalytic_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinearVelocityAnalytic_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _LinearVelocityAnalytic_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _AnalyticSolution_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _LinearVelocityAnalytic_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_LinearVelocityAnalytic_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, LinearVelocityAnalytic_Type, (Name)"0", _LinearVelocityAnalytic_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/StokesMomentumUzawa/tests/SimpleShearAnalytic/SimpleShearAnalytic.c
--- a/Apps/StokesMomentumUzawa/tests/SimpleShearAnalytic/SimpleShearAnalytic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: SimpleShearAnalytic.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-const Type SimpleShearAnalytic_Type = "SimpleShearAnalytic";
-
-typedef struct { 
-	__AnalyticSolution 
-	double centreY;
-	double factor;
-} SimpleShearAnalytic;
-
-
-void SimpleShearAnalytic_VelocityFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* velocity ) {
-	SimpleShearAnalytic *self = (SimpleShearAnalytic*)analyticSolution;
-	
-	velocity[ I_AXIS ] = self->factor * (coord[ J_AXIS ] - self->centreY);
-	velocity[ J_AXIS ] = 0.0;
-}
-
-
-void SimpleShearAnalytic_PressureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* pressure ) {
-	*pressure = 0.0;
-}
-
-void _SimpleShearAnalytic_Build( void* analyticSolution, void* data ) {
-	SimpleShearAnalytic *self = (SimpleShearAnalytic*)analyticSolution;
-
-	_AnalyticSolution_Build( self, data );
-}
-
-void _SimpleShearAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	SimpleShearAnalytic *self = (SimpleShearAnalytic*)analyticSolution;
-	FeVariable*       velocityField;
-	FeVariable*       pressureField;
-
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-
-	velocityField = Stg_ComponentFactory_ConstructByName( cf, (Name)"VelocityField", FeVariable, True, data  ); 
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, velocityField, SimpleShearAnalytic_VelocityFunction );
-	
-	pressureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"PressureField", FeVariable, True, data  ); 
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, pressureField, SimpleShearAnalytic_PressureFunction );
-	
-	/* Set constants */
-	self->centreY = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"simpleShearCentreY", 0.0  );
-	self->factor  = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SimpleShearFactor", 1.0 );
-}
-
-void* _SimpleShearAnalytic_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(SimpleShearAnalytic);
-	Type                                                      type = SimpleShearAnalytic_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _SimpleShearAnalytic_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _SimpleShearAnalytic_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _SimpleShearAnalytic_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_SimpleShearAnalytic_Register( PluginsManager* pluginsManager  ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, SimpleShearAnalytic_Type, (Name)"0", _SimpleShearAnalytic_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/StokesMomentumUzawa/tests/SimpleShearAnalytic/SimpleShearAnalytic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/StokesMomentumUzawa/tests/SimpleShearAnalytic/SimpleShearAnalytic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,117 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: SimpleShearAnalytic.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+const Type SimpleShearAnalytic_Type = "SimpleShearAnalytic";
+
+typedef struct { 
+	__AnalyticSolution 
+	double centreY;
+	double factor;
+} SimpleShearAnalytic;
+
+
+void SimpleShearAnalytic_VelocityFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* velocity ) {
+	SimpleShearAnalytic *self = (SimpleShearAnalytic*)analyticSolution;
+	
+	velocity[ I_AXIS ] = self->factor * (coord[ J_AXIS ] - self->centreY);
+	velocity[ J_AXIS ] = 0.0;
+}
+
+
+void SimpleShearAnalytic_PressureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* pressure ) {
+	*pressure = 0.0;
+}
+
+void _SimpleShearAnalytic_Build( void* analyticSolution, void* data ) {
+	SimpleShearAnalytic *self = (SimpleShearAnalytic*)analyticSolution;
+
+	_AnalyticSolution_Build( self, data );
+}
+
+void _SimpleShearAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	SimpleShearAnalytic *self = (SimpleShearAnalytic*)analyticSolution;
+	FeVariable*       velocityField;
+	FeVariable*       pressureField;
+
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+
+	velocityField = Stg_ComponentFactory_ConstructByName( cf, (Name)"VelocityField", FeVariable, True, data  ); 
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, velocityField, SimpleShearAnalytic_VelocityFunction );
+	
+	pressureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"PressureField", FeVariable, True, data  ); 
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, pressureField, SimpleShearAnalytic_PressureFunction );
+	
+	/* Set constants */
+	self->centreY = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"simpleShearCentreY", 0.0  );
+	self->factor  = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SimpleShearFactor", 1.0 );
+}
+
+void* _SimpleShearAnalytic_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(SimpleShearAnalytic);
+	Type                                                      type = SimpleShearAnalytic_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _SimpleShearAnalytic_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _SimpleShearAnalytic_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _SimpleShearAnalytic_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_SimpleShearAnalytic_Register( PluginsManager* pluginsManager  ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, SimpleShearAnalytic_Type, (Name)"0", _SimpleShearAnalytic_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/TempDiffusion/tests/LinearTemperatureField/LinearTemperatureField.c
--- a/Apps/TempDiffusion/tests/LinearTemperatureField/LinearTemperatureField.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LinearTemperatureField.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-/** Pretty simple.
- * One time step with the diffusion coefficiants K = 1
- * TempBCs Bottom BC = 1, top BC = 0, sides = 0
- */
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-const Type LinearTemperatureField_Type = "LinearTemperatureField";
-
-typedef struct { __AnalyticSolution FeVariable* temperatureField; } LinearTemperatureField;
-
-void LinearTemperatureField_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* value ) {
-	*value = 1.0 - coord[ J_AXIS ];
-}
-
-
-void _LinearTemperatureField_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	LinearTemperatureField *self = (LinearTemperatureField*)analyticSolution;
-
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-
-	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
-
-	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, LinearTemperatureField_TemperatureFunction );
-}
-
-void _LinearTemperatureField_Build( void* analyticSolution, void* data ) {
-	LinearTemperatureField *self = (LinearTemperatureField*)analyticSolution;
-
-	_AnalyticSolution_Build( self, data );
-}
-
-void* _LinearTemperatureField_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(LinearTemperatureField);
-	Type                                                      type = LinearTemperatureField_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinearTemperatureField_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _LinearTemperatureField_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _LinearTemperatureField_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_LinearTemperatureField_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, LinearTemperatureField_Type, (Name)"0", _LinearTemperatureField_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/TempDiffusion/tests/LinearTemperatureField/LinearTemperatureField.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/TempDiffusion/tests/LinearTemperatureField/LinearTemperatureField.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,101 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LinearTemperatureField.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/** Pretty simple.
+ * One time step with the diffusion coefficiants K = 1
+ * TempBCs Bottom BC = 1, top BC = 0, sides = 0
+ */
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+const Type LinearTemperatureField_Type = "LinearTemperatureField";
+
+typedef struct { __AnalyticSolution FeVariable* temperatureField; } LinearTemperatureField;
+
+void LinearTemperatureField_TemperatureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* value ) {
+	*value = 1.0 - coord[ J_AXIS ];
+}
+
+
+void _LinearTemperatureField_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	LinearTemperatureField *self = (LinearTemperatureField*)analyticSolution;
+
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+
+	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
+
+	AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, self->temperatureField, LinearTemperatureField_TemperatureFunction );
+}
+
+void _LinearTemperatureField_Build( void* analyticSolution, void* data ) {
+	LinearTemperatureField *self = (LinearTemperatureField*)analyticSolution;
+
+	_AnalyticSolution_Build( self, data );
+}
+
+void* _LinearTemperatureField_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(LinearTemperatureField);
+	Type                                                      type = LinearTemperatureField_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinearTemperatureField_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _LinearTemperatureField_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _LinearTemperatureField_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_LinearTemperatureField_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, LinearTemperatureField_Type, (Name)"0", _LinearTemperatureField_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/ThermalConvection/tests/ColumnViscosityAnalytic/ColumnViscosityAnalytic.c
--- a/Apps/ThermalConvection/tests/ColumnViscosityAnalytic/ColumnViscosityAnalytic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2637 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: ColumnViscosityAnalytic.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-#include <assert.h>
-
-const Type ColumnViscosityAnalytic_Type = "ColumnViscosityAnalytic";
-
-typedef struct {
-	__AnalyticSolution
-	double ZA;
-	double ZB;
-	double xc;
-	double C1A,C2A,C3A,C4A,C1B,C2B,C3B,C4B;
-	FeVariable* velocityField;
-	FeVariable* pressureField;
-	FeVariable* stressField;
-} ColumnViscosityAnalytic;
-
-#define SMALL 1.0e-5
-#define IS_ODD(A)   ( (A) % 2 == 1 )
-
-
-/** Analytic Solution taken from 
- *  Shijie Zhong. Analytic solutions for Stokes' flow with lateral variations in viscosity. Geophys. J. Int., 124:18-28, 1996.
- *  All equations refer to this paper */
-
-void ColumnViscosityAnalytic_TemperatureIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*  context            = (DomainContext*)_context;
-	FeVariable*             temperatureField   = (FeVariable*) FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	FeMesh*     mesh               = temperatureField->feMesh;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	double                  x; 
-	double                  y;
-	double                  kx;
-	double                  ky;
-	int                     wavenumberX;
-	int                     wavenumberY;
-	double                  L;
-	double			min[3], max[3];
-	
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	/* Make sure that the box has right dimensions */
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	assert( ( max[ J_AXIS ] - min[ J_AXIS ] - 1.0 ) < SMALL );
-	L = max[ I_AXIS ] - min[ I_AXIS ];
-
-	x = coord[ I_AXIS ] - min[ I_AXIS ];
-	y = coord[ J_AXIS ] - min[ J_AXIS ];
-
-	wavenumberX = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberX", 1  );
-	wavenumberY = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberY", 1 );
-
-	kx = wavenumberX * M_PI/ L;
-	ky = wavenumberY * M_PI;
-
-	*result = sin( ky * y ) * cos( kx * x );
-}
-
-void ColumnViscosityAnalytic_Constants( void* analyticSolution ) {
-	ColumnViscosityAnalytic* self = (ColumnViscosityAnalytic* ) analyticSolution;
-	double                  n, nx;
-	double t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40;
-	double t41,t42,t43,t44,t45,t46,t47,t48,t49,t50,t51,t52,t53,t54,t55,t56,t57,t58,t59,t60,t61,t62,t63,t64,t65,t66,t67,t68,t69,t70,t71,t72,t73,t74,t75,t76,t77,t78,t79,t80;
-	double t81,t82,t83,t84,t85,t86,t87,t88,t89,t90,t91,t92,t93,t94,t95,t96,t97,t98,t99,t100,t101,t102,t103,t104,t105,t106,t107,t108,t109,t110,t111,t112,t113,t115,t116,t117,t118,t119,t120;
-	double t121,t122,t123,t124,t125,t126,t127,t128,t129,t130,t131,t132,t133,t134,t135,t136,t137,t138,t139,t140,t141,t142,t143,t144,t145,t146,t147,t148,t149,t150,t151,t152,t153,t154,t155,t156,t157,t158,t159,t160;
-	double t161,t162,t163,t164,t165,t166,t167,t168,t169,t170,t171,t172,t173,t174,t175,t176,t177,t178,t179,t180,t181,t182,t183,t184,t186,t187,t188,t189,t190,t191,t192,t193,t194,t195,t196,t197,t198,t199;
-	double t201,t202,t203,t204,t206,t207,t208,t209,t210,t211,t212,t213,t215,t216,t217,t218,t219,t220,t221,t222,t223,t224,t225,t226,t227,t228,t229,t230,t231,t232,t233,t234,t235,t236,t237,t238,t239,t240;
-	double t241,t242,t243,t244,t245,t246,t247,t248,t249,t250,t251,t252,t253,t254,t255,t256,t257,t258,t259,t260,t261,t262,t263,t264,t265,t267,t268,t269,t270,t272,t273,t274,t275,t276,t277,t278,t279,t280;
-	double t281,t282,t283,t284,t285,t286,t288,t289,t290,t291,t292,t295,t296,t297,t298,t299,t300,t301,t303,t304,t305,t307,t308,t310,t311,t312,t313,t314,t315,t316,t317,t318,t319,t320;
-	double t321,t322,t323,t324,t325,t326,t327,t328,t329,t330,t331,t332,t334,t335,t336,t337,t338,t339,t340,t341,t342,t344,t345,t346,t347,t348,t349,t350,t351,t352,t353,t354,t355,t356,t358,t359,t360;
-	double t361,t362,t363,t364,t365,t366,t367,t368,t369,t370,t371,t372,t373,t374,t375,t376,t377,t378,t379,t380,t381,t382,t383,t384,t385,t386,t387,t389,t390,t391,t393,t394,t395,t396,t397,t398;
-	double t401,t402,t403,t404,t405,t406,t407,t408,t409,t410,t411,t412,t413,t414,t415,t416,t417,t418,t419,t421,t422,t423,t424,t425,t426,t427,t428,t429,t430,t431,t432,t433,t434,t436,t437,t438,t439,t440;
-	double t441,t442,t443,t444,t445,t446,t447,t448,t450,t451,t453,t454,t455,t456,t457,t458,t459,t461,t462,t463,t464,t465,t466,t468,t469,t470,t471,t474,t475,t478,t480;
-	double t482,t483,t484,t485,t488,t489,t490,t492,t493,t495,t497,t498,t499,t501,t502,t503,t504,t505,t507,t508,t509,t510,t511,t512,t513,t515,t518,t520;
-	double t522,t525,t527,t528,t529,t530,t532,t533,t534,t535,t536,t538,t539,t541,t542,t544,t545,t546,t547,t548,t549,t550,t551,t552,t553,t554,t555,t556,t557,t560;
-	double t561,t562,t563,t564,t567,t568,t571,t573,t575,t576,t578,t579,t583,t590,t591,t594,t595,t596,t597,t598,t600;
-	double t601,t602,t604,t606,t607,t608,t611,t613,t615,t616,t617,t619,t621,t623,t624,t625,t626,t627,t629,t630,t632,t633,t634,t638,t639,t640;
-	double t641,t642,t643,t644,t645,t647,t648,t649,t650,t651,t652,t653,t654,t655,t656,t657,t658,t659,t660,t662,t663,t665,t666,t667,t668,t670,t671,t672,t673,t674,t675,t676,t679,t680;
-	double t682,t683,t684,t685,t686,t688,t689,t690,t691,t693,t694,t695,t696,t697,t698,t699,t700,t701,t702,t704,t705,t708,t709,t711,t712,t713,t714,t717,t718,t719;
-	double t721,t722,t723,t726,t727,t728,t730,t733,t734,t735,t736,t737,t738,t739,t740,t741,t744,t745,t746,t749,t750,t752,t753,t754,t755,t757,t758,t759,t760;
-	double t761,t762,t763,t764,t766,t767,t768,t770,t771,t772,t773,t774,t775,t776,t777,t778,t780,t781,t782,t785,t786,t789,t790,t791,t792,t793,t794,t795,t796,t797,t798,t800;
-	double t801,t806,t807,t808,t809,t811,t812,t817,t818,t819,t821,t822,t824,t827,t828,t830,t834,t835,t837,t840;
-	double t842,t843,t844,t845,t846,t849,t850,t853,t854,t855,t857,t858,t859,t860,t863,t864,t867,t868,t869,t873,t874,t877,t878,t879,t880;
-	double t884,t888,t891,t894,t900,t901,t903,t904,t907,t908,t909,t911,t914,t915,t916,t919,t920;
-	double t923,t924,t925,t926,t927,t929,t932,t935,t937,t939,t942,t943,t944,t945,t947,t948,t949,t950,t952,t953,t954,t955,t956,t957;
-	double t961,t964,t965,t966,t967,t968,t969,t971,t972,t974,t977,t978,t981,t983,t987,t988,t992,t993,t994,t997,t998;
-	double t1001,t1003,t1005,t1006,t1009,t1010,t1012,t1013,t1015,t1016,t1017,t1018,t1020,t1021,t1029,t1031,t1032,t1033,t1040;
-	double t1041,t1042,t1044,t1047,t1050,t1054,t1055,t1057,t1058,t1063,t1068,t1069,t1070,t1079,t1080;
-	double t1088,t1089,t1091,t1092,t1094,t1096,t1101,t1102,t1103,t1104,t1105,t1108,t1112,t1113,t1118,t1119,t1120;
-	double t1121,t1122,t1123,t1124,t1125,t1126,t1127,t1128,t1129,t1130,t1132,t1133,t1134,t1135,t1138,t1139,t1140,t1141,t1142,t1145,t1146,t1148,t1149,t1150,t1153,t1154,t1156,t1157,t1158,t1159;
-	double t1161,t1162,t1165,t1166,t1170,t1171,t1172,t1173,t1175,t1176,t1178,t1180,t1181,t1182,t1185,t1189,t1192,t1193,t1195,t1196,t1199;
-	double t1201,t1203,t1209,t1210,t1211,t1213,t1214,t1218,t1221,t1224,t1225,t1226,t1228,t1233,t1234,t1235,t1236,t1237,t1240;
-	double t1241,t1242,t1243,t1244,t1245,t1248,t1251,t1252,t1257,t1258,t1259,t1260,t1263,t1268,t1269,t1272,t1280;
-	double t1282,t1283,t1284,t1285,t1287,t1288,t1289,t1292,t1293,t1296,t1297,t1300,t1304,t1307,t1310,t1311,t1312,t1316,t1317,t1320;
-	double t1321,t1323,t1328,t1330,t1331,t1332,t1333,t1336,t1338,t1343,t1344,t1346,t1349,t1350,t1354;
-	double t1366,t1369,t1370,t1371,t1376,t1378,t1380,t1383,t1386,t1387,t1388,t1391,t1393,t1399;
-	double t1411,t1412,t1420,t1427;
-	double t1450,t1456,t1468,t1472,t1474,t1478;
-	double t1504,t1511;
-	double t1545;
-	double t1564,t1583;
-
-
-	/* del_rho = sin(ny*Pi*y)*cos(nx*Pi*x)  n=nx gives only non-zero terms*/ 
-	n = 1; 
-	/* only one n in Fourier series because  del_rho has cos term */ 
-	nx = n; 
-
-	self->C1A = 0;
-	/****************************************************************************************/
-	t1 = nx * 0.3141592654e1;
-	t2 = sin(t1);
-	t3 = nx * t2;
-	t4 = n * n;
-	t5 = t4 * t4;
-	t6 = 0.3141592654e1 * 0.3141592654e1;
-	t8 = t3 * t5 * t6;
-	t9 = self->ZA * self->xc;
-	t12 = exp( self->xc * n * 0.3141592654e1);
-	t13 = t12 * t12;
-	t15 = n * 0.3141592654e1;
-	t16 = exp(t15);
-	t17 = t16 * t16;
-	t18 = t17 * t16;
-	t19 = self->ZB * t13 * t18;
-	t20 = t9 * t19;
-	t23 = self->ZA * self->ZA;
-	t24 = nx * nx;
-	t25 = t24 * nx;
-	t26 = t23 * t25;
-	t28 = t13 * t13;
-	t29 = t28 * t13;
-	t33 = nx * self->ZB;
-	t34 = t1 * self->xc;
-	t35 = sin(t34);
-	t36 = t4 * n;
-	t37 = t35 * t36;
-	t38 = t33 * t37;
-	t39 = 0.3141592654e1 * self->ZA;
-	t40 = t13 * t12;
-	t41 = t17 * t40;
-	t45 = self->ZB * self->ZB;
-	t46 = t45 * t24;
-	t47 = t46 * t4;
-	t48 = 0.3141592654e1 * self->xc;
-	t49 = t13 * t17;
-	t53 = self->xc * self->xc;
-	t54 = t36 * t53;
-	t56 = t54 * t6 * t45;
-	t57 = cos(t34);
-	t58 = t57 * t24;
-	t59 = t28 * t12;
-	t60 = t17 * t59;
-	t61 = t58 * t60;
-	t64 = t25 * t2;
-	t65 = t64 * t15;
-	t72 = nx * t23;
-	t74 = t72 * t2 * t5;
-	t75 = t6 * t53;
-	t76 = t16 * t29;
-	t80 = t23 * n;
-	t81 = t80 * 0.3141592654e1;
-	t82 = t18 * t28;
-	t86 = nx * t5;
-	t87 = t23 * t6;
-	t89 = self->xc * t2;
-	t90 = t13 * t18;
-	t91 = t89 * t90;
-	t94 = t28 * t28;
-	t96 = t24 * n;
-	t98 = t4 * t45;
-	t99 = t98 * 0.3141592654e1;
-	t100 = t58 * t41;
-	t104 = 0.3141592654e1 * t25;
-	t105 = self->ZA * n * t104;
-	t106 = t2 * self->ZB;
-	t110 = t17 * t17;
-	t111 = self->ZA * t110;
-	t116 = n * t28;
-	t122 = t64 * t4 * t6;
-	t126 = t23 * t29 * t4;
-	t128 = t24 * self->xc;
-	t132 = t36 * t23;
-	t133 = t6 * t57;
-	t135 = t128 * t41;
-	t138 = t6 * self->xc;
-	t142 = t72 * t2;
-	t147 = 0.4e1 * t8 * t20 - 0.2e1 * t26 * t2 * t16 * t29 - 0.8e1 * t38 * t39 * t41 + 0.4e1 * t47 * t48 * t49 - 0.8e1 * t56 * t61 - 0.4e1 * t65 * t20 + 0.2e1 * t26 * t2 * t18 * t28 - 0.4e1 * t74 * t75 * t76 - 0.2e1 * t81 * t64 * t82 - 0.4e1 * t86 * t87 * t91 - t23 * t94 * t96 + 0.8e1 * t99 * t100 - 0.2e1 * t105 * t106 * t82 - 0.4e1 * t38 * t48 * t111 * t12 + 0.2e1 * t116 * self->ZB * t111 * t24 + 0.4e1 * t122 * t20 + 0.4e1 * t126 * 0.3141592654e1 * t17 * t128 + 0.8e1 * t132 * t133 * t135 + 0.4e1 * t74 * t138 * t76 - 0.2e1 * t142 * t4 * t18 * t28;
-	t149 = self->ZA * t25 * t2;
-	t150 = self->ZB * t28;
-	t154 = t35 * t5;
-	t155 = t72 * t154;
-	t156 = t75 * t41;
-	t159 = nx * self->ZA;
-	t160 = t2 * t36;
-	t161 = t159 * t160;
-	t162 = 0.3141592654e1 * self->ZB;
-	t163 = t28 * t16;
-	t167 = t23 * t57;
-	t168 = t167 * t24;
-	t169 = n * t110;
-	t170 = t169 * t40;
-	t173 = self->ZA * self->ZB;
-	t174 = t173 * t90;
-	t177 = t36 * 0.3141592654e1;
-	t181 = t80 * t104;
-	t184 = n * t17;
-	t188 = t17 * t29;
-	t190 = t4 * 0.3141592654e1;
-	t191 = t190 * t24;
-	t206 = t138 * t60;
-	t209 = t23 * t4;
-	t211 = t209 * t6 * t25;
-	t212 = t89 * t76;
-	t216 = self->ZB * t16 * t29;
-	t217 = t9 * t216;
-	t220 = self->ZB * t110;
-	t221 = self->ZA * t24;
-	t222 = t221 * n;
-	t225 = t132 * t75;
-	t232 = t45 * t28;
-	t233 = t110 * t24;
-	t234 = t233 * n;
-	t236 = t209 * 0.3141592654e1;
-	t237 = t17 * self->xc;
-	t239 = t237 * t13 * t24;
-	t242 = -0.2e1 * t149 * t150 * t16 - 0.8e1 * t155 * t156 - 0.2e1 * t161 * t162 * t163 + 0.2e1 * t168 * t170 + 0.2e1 * t65 * t174 - 0.2e1 * t142 * t177 * t76 + 0.4e1 * t181 * t91 - 0.4e1 * t168 * t184 * t59 - 0.4e1 * t188 * t23 * t191 + 0.4e1 * t38 * t48 * self->ZA * t17 * t40 + 0.4e1 * t49 * t23 * t191 + 0.2e1 * t26 * t2 * t13 * t18 - 0.8e1 * t155 * t206 + 0.4e1 * t211 * t212 - 0.4e1 * t8 * t217 + 0.2e1 * t220 * t222 - 0.8e1 * t225 * t100 + 0.2e1 * t142 * t4 * t16 * t29 + t232 * t234 - 0.4e1 * t236 * t239;
-	t244 = nx * t45;
-	t245 = t244 * t37;
-	t246 = t110 * t40;
-	t251 = t237 * t59;
-	t256 = t64 * t90;
-	t260 = t36 * t45 * t133;
-	t263 = t45 * t57;
-	t264 = t263 * t24;
-	t265 = t169 * t12;
-	t269 = t6 * t36;
-	t270 = t17 * t24;
-	t274 = t110 * t13;
-	t276 = t190 * t128;
-	t279 = nx * t36;
-	t281 = t28 * t40;
-	t282 = t281 * t35;
-	t286 = t138 * t41;
-	t289 = t75 * t60;
-	t296 = t190 * t173;
-	t305 = t86 * t45 * t35;
-	t312 = t33 * t154;
-	t313 = t6 * self->ZA;
-	t324 = t232 * t270;
-	t327 = -0.2e1 * t245 * t48 * t246 + 0.4e1 * t159 * t37 * t162 * t251 + 0.4e1 * t209 * t75 * t256 + 0.8e1 * t260 * t135 + 0.2e1 * t264 * t265 + 0.32e2 * t9 * t150 * t269 * t270 + 0.4e1 * t274 * t23 * t276 + 0.2e1 * t279 * t45 * t282 * t48 + 0.8e1 * t155 * t286 + 0.8e1 * t155 * t289 - 0.8e1 * t150 * self->ZA * t96 * t17 + 0.8e1 * t296 * t61 - 0.2e1 * t105 * t106 * t163 - 0.2e1 * t81 * t256 - 0.8e1 * t305 * t156 - 0.4e1 * t33 * t282 * t177 * t9 - 0.16e2 * t312 * t313 * t237 * t40 - 0.4e1 * t168 * t184 * t40 + 0.2e1 * t168 * t265 + 0.16e2 * t269 * t53 * t324;
-	t328 = t3 * t4;
-	t331 = t72 * t37;
-	t332 = t48 * t60;
-	t335 = n * t94;
-	t345 = t72 * t35;
-	t349 = t173 * t57;
-	t355 = t53 * t17;
-	t364 = t54 * t6 * self->ZB;
-	t365 = t28 * t17;
-	t369 = self->xc * self->ZB;
-	t370 = t269 * t369;
-	t371 = self->ZA * t57;
-	t373 = t371 * t270 * t40;
-	t385 = nx * t35;
-	t396 = t4 * self->xc;
-	t397 = t396 * t162;
-	t415 = t37 * t48;
-	t418 = -0.32e2 * t364 * t365 * t221 - 0.16e2 * t370 * t373 - 0.4e1 * t331 * t48 * t41 + 0.4e1 * t86 * t23 * t53 * t6 * t2 * t90 + 0.2e1 * t385 * t177 * t23 * self->xc * t246 + 0.16e2 * t132 * t53 * t6 * t28 * t270 - 0.4e1 * t397 * t371 * t233 * t12 - 0.12e2 * t173 * t58 * t190 * t251 + 0.2e1 * t385 * t36 * 0.3141592654e1 * t23 * self->xc * t59 - 0.8e1 * t99 * t61 - 0.2e1 * t244 * t59 * t415;
-	t427 = t371 * t270 * t59;
-	t439 = t209 * t48;
-	t440 = t110 * t12;
-	t441 = t58 * t440;
-	t447 = t36 * self->xc;
-	t455 = t48 * t440;
-	t471 = self->ZB * t17;
-	t492 = 0.12e2 * t397 * t373 - 0.4e1 * t122 * t217 + 0.16e2 * t364 * t427 + 0.16e2 * t312 * t313 * t355 * t40 - 0.8e1 * t279 * t39 * t35 * self->ZB * t60 + 0.2e1 * t439 * t441 - 0.2e1 * t81 * t64 * t163 + 0.8e1 * t447 * t87 * t61 + 0.2e1 * t23 * t59 * t57 * t276 + 0.2e1 * t245 * t455 - 0.4e1 * t349 * t96 * t440 - 0.16e2 * t370 * t427 + 0.4e1 * t181 * t212 - 0.16e2 * t365 * t23 * t269 * t128 + 0.16e2 * t86 * t138 * self->ZA * t35 * t471 * t59 + 0.8e1 * t305 * t289 - 0.4e1 * t439 * t100 + 0.2e1 * self->ZB * t25 * t2 * self->ZA * t18 * t28 + 0.2e1 * t142 * t4 * t28 * t16 - 0.8e1 * t56 * t100;
-	t499 = self->ZA * t53 * t19;
-	t505 = t396 * 0.3141592654e1;
-	t518 = t173 * t53 * t16 * t29;
-	t533 = t23 * t28;
-	t535 = t188 * t45;
-	t538 = t24 * t4;
-	t545 = t3 * t177;
-	t546 = t173 * t76;
-	t555 = t45 * t110;
-	t557 = t72 * t160;
-	t561 = -0.8e1 * t225 * t61 - 0.2e1 * t161 * t162 * t82 + t533 * t234 + 0.4e1 * t535 * t191 + 0.4e1 * t167 * t538 * t332 + 0.4e1 * t349 * t96 * t60 + 0.2e1 * t545 * t546 - 0.2e1 * t264 * t170 + 0.4e1 * t397 * t281 * self->ZA * t58 - t555 * t96 - 0.4e1 * t557 * t48 * t76;
-	t567 = t396 * 0.3141592654e1 * t45;
-	t568 = t58 * t246;
-	t597 = t58 * n;
-	t615 = t13 * t45;
-	t616 = t615 * t233;
-	t619 = t94 * t45;
-	t621 = t45 * t59;
-	t625 = 0.2e1 * t149 * t216 + 0.2e1 * t567 * t568 - 0.16e2 * t269 * self->xc * t324 - 0.2e1 * t236 * self->xc * t281 * t58 - 0.2e1 * t142 * t177 * t90 - 0.8e1 * t567 * t100 + 0.2e1 * t65 * t546 - 0.8e1 * t305 * t206 + 0.2e1 * n * t45 * t281 * t57 * t24 - t23 * t110 * t96 - 0.8e1 * t296 * t100 + 0.2e1 * t23 * t281 * t597 + 0.4e1 * t545 * t20 + 0.2e1 * t159 * t2 * t4 * self->ZB * t163 - 0.4e1 * t557 * t48 * t90 + 0.4e1 * t122 * t518 + 0.8e1 * t263 * t538 * t332 - 0.4e1 * t505 * t616 - t619 * t96 - 0.2e1 * t621 * t57 * t276;
-	t626 = t49 * t45;
-	t660 = t29 * t45;
-	t685 = 0.2e1 * t545 * t174 - 0.4e1 * t126 * 0.3141592654e1 * t24 * self->xc - 0.4e1 * t47 * t48 * t188 + 0.4e1 * t505 * t660 * t24 - 0.2e1 * t142 * t177 * t163 - 0.2e1 * t142 * t4 * t13 * t18 + 0.8e1 * t260 * t128 * t60 - 0.2e1 * t328 * t546 - 0.2e1 * t26 * t2 * t28 * t16 + 0.4e1 * t545 * t217 - 0.4e1 * t209 * t138 * t256;
-	t690 = t6 * 0.3141592654e1;
-	t691 = self->ZA * t690;
-	t693 = t24 * t24;
-	t694 = t693 * self->xc;
-	t695 = t188 * t694;
-	t698 = t23 * self->ZA;
-	t699 = t698 * t690;
-	t700 = t699 * t5;
-	t704 = t5 * t4;
-	t705 = t691 * t704;
-	t709 = t691 * t5;
-	t713 = t5 * n;
-	t714 = t713 * self->ZB;
-	t718 = t698 * t6;
-	t719 = t713 * t28;
-	t722 = t699 * t704;
-	t726 = t713 * t94;
-	t733 = t713 * t45;
-	t736 = t87 * t36;
-	t740 = -0.4e1 * t691 * t98 * t695 + 0.8e1 * t700 * t270 * t13 + 0.4e1 * t705 * t660 * self->xc + 0.8e1 * t709 * t660 * t128 + 0.2e1 * t87 * t714 * t110 + t718 * t719 * t110 - 0.4e1 * t722 * t237 * t13 - t313 * t726 * t45 - 0.4e1 * t699 * t704 * self->xc * t29 + t313 * t733 * t28 + 0.4e1 * t736 * t150 * t233;
-	t746 = t313 * t36;
-	t752 = t6 * t6;
-	t753 = t23 * t752;
-	t759 = t698 * t752;
-	t760 = t759 * t36;
-	t761 = t17 * t693;
-	t762 = self->xc * t28;
-	t763 = t761 * t762;
-	t766 = t87 * t713;
-	t773 = t699 * t4;
-	t774 = t110 * t693;
-	t775 = self->xc * t13;
-	t785 = t704 * t17;
-	t789 = -0.16e2 * t736 * t150 * t270 + t718 * t116 * t693 - 0.2e1 * t746 * t555 * t24 + 0.4e1 * t705 * t535 + 0.64e2 * t753 * t713 * t17 * t150 * t128 - 0.16e2 * t760 * t763 + 0.2e1 * t766 * t150 * t110 + 0.4e1 * t722 * t274 * self->xc + 0.4e1 * t773 * t774 * t775 - 0.8e1 * t766 * t150 * t17 + 0.8e1 * t700 * t233 * t775 + 0.4e1 * t699 * t785 * t13;
-	t791 = t691 * t4;
-	t792 = t45 * t693;
-	t793 = t49 * t792;
-	t796 = t759 * t713;
-	t797 = t53 * t28;
-	t798 = t270 * t797;
-	t801 = t87 * n;
-	t818 = t5 * t36;
-	t819 = t753 * t818;
-	t827 = t753 * t36 * self->ZB;
-	t830 = self->xc * t45;
-	t834 = -0.4e1 * t791 * t793 + 0.32e2 * t796 * t798 + 0.2e1 * t801 * self->ZB * t693 * t110 + 0.2e1 * t718 * t36 * t28 * t24 - 0.8e1 * t700 * t128 * t29 - 0.8e1 * t700 * t239 - 0.8e1 * t801 * t150 * t761 + 0.32e2 * t819 * t365 * t369 - 0.64e2 * t753 * t714 * t798 + 0.32e2 * t827 * t763 + 0.4e1 * t705 * t830 * t49;
-	t842 = self->xc * t29;
-	t843 = t270 * t842;
-	t849 = t759 * t818;
-	t853 = t691 * t396;
-	t857 = t691 * t5 * t45;
-	t869 = t313 * n;
-	t874 = -0.2e1 * t718 * t36 * t94 * t24 - 0.4e1 * t773 * t761 * t29 + 0.8e1 * t700 * t843 + 0.2e1 * t87 * t726 * self->ZB + 0.16e2 * t849 * t797 * t17 + 0.4e1 * t853 * t793 + 0.8e1 * t857 * t239 + 0.2e1 * t801 * t150 * t693 - 0.8e1 * t700 * t270 * t29 - 0.8e1 * t709 * t49 * t46 - t869 * t619 * t693 + t869 * t232 * t693;
-	t877 = self->ZA * t752;
-	t878 = t877 * t818;
-	t911 = 0.16e2 * t878 * t53 * t45 * t365 - 0.4e1 * t699 * t785 * t29 - 0.4e1 * t705 * t188 * t830 + 0.2e1 * t801 * t94 * t693 * self->ZB - 0.8e1 * t857 * t843 - t718 * t726 + 0.4e1 * t773 * t761 * t13 - 0.4e1 * t705 * t775 * t555 + 0.2e1 * t746 * t232 * t233 - 0.16e2 * t878 * t830 * t365 - 0.2e1 * t746 * t619 * t24;
-	t916 = t110 * t28;
-	t945 = t28 * t693 * t45 * t17;
-	t948 = 0.32e2 * t877 * t733 * t798 + 0.2e1 * t718 * t36 * t916 * t24 - 0.4e1 * t705 * t626 + t718 * n * t916 * t693 - t869 * t792 * t110 - 0.4e1 * t773 * t761 * t775 + t718 * t719 + 0.2e1 * t746 * t232 * t24 - 0.16e2 * t849 * t365 * self->xc - t718 * t713 * t110 - 0.4e1 * t773 * t694 * t29 + 0.16e2 * t877 * t54 * t945;
-	t974 = t761 * t797;
-	t987 = 0.4e1 * t773 * t695 + 0.4e1 * t736 * t150 * t24 + 0.4e1 * t722 * t842 * t17 - 0.16e2 * t877 * t447 * t945 + 0.2e1 * t87 * t714 * t28 + t313 * t713 * t916 * t45 - 0.4e1 * t853 * t615 * t774 - 0.32e2 * t877 * t713 * self->xc * t324 + 0.16e2 * t760 * t974 + 0.4e1 * t736 * t94 * t24 * self->ZB + t869 * t792 * t916 - 0.8e1 * t691 * t5 * self->xc * t616;
-	t1021 = -t718 * t169 * t693 - 0.32e2 * t827 * t974 + 0.2e1 * t801 * t150 * t774 + 0.4e1 * t791 * t188 * t792 + 0.4e1 * t736 * t220 * t24 + 0.4e1 * t791 * t842 * t792 + 0.8e1 * t709 * t660 * t270 - t718 * t335 * t693 - 0.2e1 * t718 * t36 * t110 * t24 - 0.32e2 * t819 * t797 * t471 - t313 * t733 * t110 - 0.32e2 * t796 * t270 * t762;
-
-	self->C2A = (t147 - 0.4e1 * t65 * t217 + t418 + 0.2e1 * t150 * t222 + t327 - 0.2e1 * t149 * t19 + 0.2e1 * t335 * self->ZB * t24 * self->ZA - 0.16e2 * t312 * t313 * t355 * t59 - 0.4e1 * t281 * self->ZB * self->ZA * t597 - 0.2e1 * t505 * t45 * t281 * t58 - 0.4e1 * t211 * t2 * t53 * t76 + 0.8e1 * t305 * t286 - 0.4e1 * t122 * t499 - 0.4e1 * t331 * t332 + 0.8e1 * t345 * t177 * t60 - 0.2e1 * t142 * t177 * t82 + 0.2e1 * t72 * t281 * t415 + 0.4e1 * t349 * t96 * t41 - 0.2e1 * t81 * t64 * t76 + 0.2e1 * t58 * t80 * t59 + 0.8e1 * t345 * t177 * t41 - 0.4e1 * t8 * t499 + t242 + 0.4e1 * t8 * t518 + t625 + t685 + 0.2e1 * t328 * t174 + 0.2e1 * t331 * t455 - 0.2e1 * t33 * t2 * t4 * self->ZA * t82 - 0.4e1 * t626 * t191 + 0.16e2 * t364 * t373 - 0.2e1 * t621 * t597 - 0.2e1 * t439 * t568 + t492 + t533 * t96 + t232 * t96 + 0.2e1 * t567 * t441 + t561) / (t740 + t789 + t834 + t874 + t911 + t948 + t987 + t1021);
-	/****************************************************************************************/
-	t1 = n * n;
-	t2 = t1 * n;
-	t3 = t2 * 0.3141592654e1;
-	t4 = t3 * self->xc;
-	t5 = self->ZB * self->ZB;
-	t7 = exp(n * 0.3141592654e1);
-	t8 = t7 * t7;
-	t9 = t5 * t8;
-	t12 = exp( self->xc * n * 0.3141592654e1);
-	t13 = t12 * t12;
-	t14 = t13 * t13;
-	t15 = t14 * t13;
-	t19 = nx * nx;
-	t21 = nx * 0.3141592654e1;
-	t22 = sin(t21);
-	t23 = t19 * nx * t22;
-	t24 = t23 * 0.3141592654e1;
-	t25 = self->ZA * self->ZB;
-	t26 = t7 * t15;
-	t27 = t25 * t26;
-	t30 = t21 * self->xc;
-	t31 = sin(t30);
-	t32 = t31 * nx;
-	t33 = t32 * n;
-	t34 = self->ZA * self->ZA;
-	t35 = t8 * t8;
-	t36 = t34 * t35;
-	t40 = t2 * t34;
-	t41 = 0.3141592654e1 * t8;
-	t42 = t41 * t15;
-	t45 = t1 * t5;
-	t46 = t14 * t14;
-	t49 = t19 * t5;
-	t51 = t19 * t46;
-	t53 = t19 * t34;
-	t55 = t8 * t7;
-	t56 = t13 * t55;
-	t57 = t25 * t56;
-	t60 = t2 * nx;
-	t61 = 0.3141592654e1 * 0.3141592654e1;
-	t63 = t60 * t31 * t61;
-	t64 = self->xc * self->xc;
-	t65 = self->ZA * t64;
-	t66 = self->ZB * t8;
-	t67 = t14 * t12;
-	t68 = t66 * t67;
-	t69 = t65 * t68;
-	t72 = -0.4e1 * t4 * t9 * t15 + 0.4e1 * t24 * t27 + 0.4e1 * t33 * t36 * t12 - 0.4e1 * t40 * t42 - t45 * t46 + t45 * t14 - t49 * t14 + t51 * t5 - t53 * t14 + 0.4e1 * t24 * t57 + 0.32e2 * t63 * t69;
-	t73 = t1 * nx;
-	t75 = t73 * t31 * 0.3141592654e1;
-	t76 = t8 * t67;
-	t77 = t25 * t76;
-	t80 = t1 * t1;
-	t81 = t80 * t34;
-	t83 = t61 * t14;
-	t87 = t1 * t19;
-	t88 = cos(t30);
-	t90 = t87 * t88 * t61;
-	t91 = t5 * t64;
-	t92 = t13 * t12;
-	t93 = t8 * t92;
-	t94 = t91 * t93;
-	t100 = self->ZB * t64 * self->ZA * t8 * t92;
-	t103 = n * t19;
-	t105 = t103 * t88 * 0.3141592654e1;
-	t106 = self->ZA * self->xc;
-	t107 = self->ZB * t35;
-	t109 = t106 * t107 * t12;
-	t112 = t34 * self->xc;
-	t113 = t112 * t93;
-	t116 = t35 * t14;
-	t118 = t1 * self->ZA;
-	t119 = self->ZB * t14;
-	t122 = t1 * t46;
-	t125 = t19 * self->ZB;
-	t126 = t35 * self->ZA;
-	t127 = t125 * t126;
-	t129 = t1 * self->ZB;
-	t132 = -0.16e2 * t75 * t77 + 0.16e2 * t81 * t64 * t83 * t8 + 0.16e2 * t90 * t94 - 0.32e2 * t90 * t100 + 0.8e1 * t105 * t109 - 0.8e1 * t75 * t113 + t45 * t116 + 0.2e1 * t118 * t119 + 0.2e1 * t122 * t25 - 0.2e1 * t127 + 0.2e1 * t129 * t126;
-	t134 = t1 * t34;
-	t136 = t34 * t64;
-	t137 = t136 * t76;
-	t141 = t91 * t76;
-	t145 = t103 * t34;
-	t146 = 0.3141592654e1 * self->xc;
-	t147 = t8 * t13;
-	t153 = t14 * self->ZA;
-	t156 = self->xc * t5;
-	t157 = t156 * t93;
-	t160 = t103 * t5;
-	t162 = t146 * t8 * t15;
-	t166 = t34 * t7 * t15;
-	t169 = t134 * t116 - 0.16e2 * t63 * t137 - t49 * t116 - 0.16e2 * t63 * t141 - t53 * t116 + 0.4e1 * t145 * t146 * t147 - 0.2e1 * t51 * t25 - 0.2e1 * t125 * t153 - 0.16e2 * t75 * t157 + 0.4e1 * t160 * t162 - 0.4e1 * t24 * t166;
-	t170 = t106 * t68;
-	t177 = t35 * t92;
-	t178 = t112 * t177;
-	t181 = t156 * t76;
-	t186 = t35 * t12;
-	t187 = t112 * t186;
-	t193 = t5 * 0.3141592654e1;
-	t206 = t34 * t14;
-	t207 = t206 * t7;
-	t210 = -0.32e2 * t63 * t170 + 0.32e2 * t90 * t170 + 0.8e1 * t75 * t109 + 0.4e1 * t105 * t178 - 0.16e2 * t75 * t181 - 0.16e2 * t90 * t113 - 0.4e1 * t75 * t187 + 0.16e2 * t90 * t141 - 0.4e1 * t103 * t15 * t193 * self->xc + 0.16e2 * t73 * t22 * t34 * t146 * t26 + 0.4e1 * t32 * n * t34 * t67 + 0.4e1 * t24 * t207;
-	t217 = t106 * t66 * t92;
-	t226 = t88 * t19 * n;
-	t227 = 0.3141592654e1 * t34;
-	t229 = t227 * self->xc * t67;
-	t232 = t73 * t31;
-	t234 = t146 * t5 * t67;
-	t238 = t61 * self->ZB;
-	t239 = t14 * t8;
-	t240 = t238 * t239;
-	t243 = t136 * t93;
-	t246 = -0.8e1 * t33 * t25 * t186 + 0.32e2 * t90 * t217 - t45 * t35 + t53 * t35 - t134 * t35 - t134 * t46 + t134 * t14 - 0.4e1 * t226 * t229 + 0.4e1 * t232 * t234 + 0.32e2 * t87 * t65 * t240 + 0.16e2 * t63 * t243;
-	t247 = t14 * t92;
-	t249 = t227 * t247 * self->xc;
-	t254 = t73 * t22;
-	t259 = t60 * t22 * t61;
-	t260 = t112 * t26;
-	t264 = t146 * t247 * t5;
-	t268 = self->xc * t14;
-	t274 = t5 * t14;
-	t275 = t274 * t8;
-	t280 = n * nx;
-	t281 = t280 * t22;
-	t282 = t55 * t14;
-	t283 = t25 * t282;
-	t290 = self->ZA * t247 * self->xc * self->ZB;
-	t295 = t22 * nx * t1 * 0.3141592654e1;
-	t298 = -0.4e1 * t232 * t249 + 0.8e1 * t105 * t217 - 0.4e1 * t254 * t227 * t26 - 0.8e1 * t259 * t260 - 0.4e1 * t232 * t264 - 0.16e2 * t81 * t61 * t268 * t8 + 0.16e2 * t80 * t64 * t61 * t275 - 0.4e1 * t232 * t229 + 0.8e1 * t281 * t283 - 0.4e1 * t105 * t187 + 0.8e1 * t75 * t290 + 0.4e1 * t295 * t27;
-	t301 = t61 * t5;
-	t307 = t87 * t34;
-	t312 = t61 * self->xc;
-	t313 = t312 * t239;
-	t317 = t34 * t55 * t14;
-	t329 = self->ZB * t13 * t55;
-	t330 = t65 * t329;
-	t337 = -0.16e2 * t87 * t64 * t301 * t239 - 0.32e2 * t90 * t69 - 0.16e2 * t307 * t64 * t61 * t239 + 0.16e2 * t307 * t313 + 0.4e1 * t24 * t317 + t53 * t46 + t49 * t35 - 0.32e2 * t63 * t100 - 0.4e1 * t280 * t31 * t34 * t247 + 0.8e1 * t259 * t330 - 0.4e1 * t280 * t31 * t247 * t5;
-	t340 = t5 * t35;
-	t344 = t25 * t93;
-	t356 = t41 * t13;
-	t360 = t23 * n * t61;
-	t363 = t25 * t64 * t7 * t15;
-	t366 = t156 * t177;
-	t369 = t14 * t7;
-	t370 = t25 * t369;
-	t373 = t156 * t186;
-	t378 = 0.4e1 * t24 * t283 + 0.4e1 * t33 * t340 * t12 - 0.16e2 * t75 * t344 - 0.4e1 * t280 * t31 * t5 * t67 + 0.8e1 * t33 * t25 * t247 + 0.32e2 * t63 * t217 + 0.4e1 * t40 * t356 - 0.8e1 * t360 * t363 + 0.4e1 * t75 * t366 + 0.4e1 * t295 * t370 - 0.4e1 * t75 * t373 - 0.4e1 * t105 * t366;
-	t382 = t112 * t76;
-	t387 = t80 * t61;
-	t391 = t136 * t26;
-	t409 = 0.16e2 * t63 * t382 + 0.4e1 * t226 * t234 - 0.16e2 * t387 * self->xc * t275 + 0.8e1 * t259 * t391 - 0.16e2 * t105 * t344 + 0.4e1 * t226 * t264 - 0.8e1 * t105 * t170 + 0.16e2 * t232 * t193 * t76 + 0.8e1 * t360 * t330 - 0.8e1 * t105 * t290 + 0.16e2 * t90 * t243;
-	t423 = t153 * t8;
-	t426 = t34 * t13;
-	t427 = t426 * t55;
-	t430 = t34 * t8;
-	t437 = t80 * self->ZA;
-	t441 = 0.4e1 * t145 * t42 - 0.16e2 * t90 * t157 + 0.24e2 * t75 * t217 + 0.4e1 * t226 * t249 + 0.4e1 * t254 * t227 * t282 + 0.4e1 * t160 * t356 - 0.8e1 * t129 * t423 - 0.8e1 * t281 * t427 - 0.8e1 * t33 * t430 * t67 + 0.8e1 * t33 * t430 * t92 + 0.32e2 * t437 * self->ZB * t313;
-	t453 = t106 * self->ZB * t7 * t15;
-	t456 = t2 * t5;
-	t459 = t112 * t56;
-	t462 = t126 * t14;
-	t474 = t40 * 0.3141592654e1;
-	t475 = self->xc * t8;
-	t480 = t146 * t13 * t35;
-	t483 = -0.4e1 * t103 * self->xc * t193 * t147 + 0.16e2 * t87 * t61 * t156 * t239 + 0.8e1 * t259 * t453 - 0.4e1 * t456 * t356 + 0.8e1 * t259 * t459 - 0.2e1 * t125 * t462 - 0.8e1 * t281 * t207 + 0.16e2 * t295 * t459 - 0.8e1 * t60 * t22 * self->ZA * t312 * t329 + 0.4e1 * t474 * t475 * t15 + 0.4e1 * t160 * t480;
-	t497 = t136 * t56;
-	t504 = t9 * t13;
-	t509 = t475 * t13;
-	t512 = -0.8e1 * t105 * t113 - 0.4e1 * t254 * t227 * t56 + 0.8e1 * t281 * t57 + 0.4e1 * t295 * t283 + 0.2e1 * t129 * t462 + 0.4e1 * t24 * t370 - 0.8e1 * t360 * t497 - 0.4e1 * t24 * t427 - 0.4e1 * t145 * t162 + 0.4e1 * t4 * t504 - 0.8e1 * t281 * t370 - 0.4e1 * t474 * t509;
-	t528 = t5 * t13;
-	t529 = t528 * t35;
-	t532 = t106 * t329;
-	t542 = -0.16e2 * t295 * t453 - 0.32e2 * t437 * t64 * t240 + 0.8e1 * t281 * t317 + 0.24e2 * t75 * t170 - 0.4e1 * t75 * t178 + 0.8e1 * t360 * t453 - 0.4e1 * t4 * t529 - 0.16e2 * t295 * t532 - 0.8e1 * t33 * t344 - 0.16e2 * t90 * t181 + 0.4e1 * t33 * t340 * t92;
-	t557 = t146 * t15;
-	t562 = self->xc * t15;
-	t563 = t562 * t5;
-	t573 = 0.16e2 * t232 * t193 * t93 - 0.8e1 * t259 * t363 - 0.8e1 * t259 * t497 + 0.8e1 * t33 * t77 + 0.8e1 * t360 * t391 + 0.4e1 * t254 * t227 * t369 + 0.4e1 * t145 * t557 + 0.8e1 * t281 * t166 + 0.4e1 * t3 * t563 + 0.8e1 * t105 * t382 - 0.4e1 * t145 * t480 - 0.4e1 * t33 * t36 * t92;
-	t600 = 0.4e1 * t456 * t42 - 0.8e1 * t360 * t260 - 0.4e1 * t40 * t557 - 0.4e1 * t105 * t373 + 0.16e2 * t226 * t227 * t93 - 0.16e2 * t90 * t382 - 0.4e1 * t145 * t356 - 0.16e2 * t63 * t157 - 0.32e2 * t87 * t25 * t313 - 0.16e2 * t226 * t227 * t76 - 0.16e2 * t63 * t113;
-	t623 = self->xc * t13;
-	t627 = 0.8e1 * t125 * t423 - 0.8e1 * t360 * t532 + 0.16e2 * t90 * t137 - 0.4e1 * t160 * t42 + 0.16e2 * t63 * t94 + 0.16e2 * t63 * t181 - 0.8e1 * t281 * t27 - 0.8e1 * t75 * t382 + 0.8e1 * t360 * t459 + 0.4e1 * t295 * t57 + 0.16e2 * t105 * t77 + 0.4e1 * t474 * t623 * t35;
-	t632 = t61 * 0.3141592654e1;
-	t633 = t632 * t8;
-	t634 = t80 * n;
-	t638 = t632 * t634;
-	t639 = t638 * self->xc;
-	t642 = t61 * t34;
-	t643 = t122 * t19;
-	t649 = t61 * t61;
-	t650 = t649 * t1;
-	t652 = t19 * t19;
-	t653 = t14 * t652;
-	t654 = t653 * t9;
-	t657 = t14 * t1;
-	t658 = t657 * t19;
-	t665 = t632 * t34;
-	t666 = t665 * t2;
-	t667 = t8 * t19;
-	t668 = t667 * t623;
-	t674 = t665 * n;
-	t675 = t652 * self->xc;
-	t682 = 0.8e1 * t633 * t426 * t634 - 0.8e1 * t639 * t529 - 0.4e1 * t642 * t643 + 0.2e1 * t642 * t116 * t80 + 0.32e2 * t650 * t64 * t654 + 0.4e1 * t301 * t658 + 0.4e1 * t387 * t46 * self->ZA * self->ZB - 0.16e2 * t666 * t668 - 0.16e2 * t666 * t667 * t15 - 0.8e1 * t674 * t675 * t15 + 0.4e1 * t238 * t153 * t80;
-	t683 = t46 * t652;
-	t686 = t633 * t15;
-	t691 = t35 * t80;
-	t698 = t35 * t652;
-	t705 = t14 * t80;
-	t708 = t61 * t35;
-	t717 = -0.2e1 * t642 * t683 - 0.8e1 * t686 * t5 * t634 * self->xc - 0.2e1 * t301 * t691 + 0.8e1 * t638 * t563 - 0.2e1 * t642 * t691 - 0.2e1 * t642 * t698 - 0.2e1 * t301 * t698 - 0.2e1 * t301 * t683 + 0.2e1 * t642 * t705 + 0.2e1 * t708 * t274 * t80 + 0.2e1 * t301 * t653 - 0.2e1 * t642 * t80 * t46;
-	t727 = t61 * t46;
-	t737 = t649 * t34;
-	t738 = t737 * t1;
-	t739 = t8 * t652;
-	t740 = t739 * t268;
-	t746 = t61 * self->ZA;
-	t754 = t632 * n * self->xc;
-	t758 = 0.2e1 * t301 * t705 + 0.2e1 * t642 * t653 - 0.8e1 * t665 * self->xc * t634 * t15 - 0.2e1 * t727 * t5 * t80 - 0.32e2 * t650 * self->xc * t654 + 0.2e1 * t301 * t698 * t14 - 0.32e2 * t738 * t740 + 0.8e1 * t674 * t739 * t562 + 0.4e1 * t746 * t119 * t652 + 0.8e1 * t674 * t698 * t623 - 0.8e1 * t754 * t528 * t698;
-	t762 = t633 * t13;
-	t764 = t5 * n * t652;
-	t767 = t80 * t1;
-	t768 = t649 * t767;
-	t772 = t649 * self->ZA;
-	t773 = t772 * t129;
-	t777 = t35 * t1 * t19;
-	t780 = t632 * t5;
-	t781 = t780 * t15;
-	t786 = t698 * self->ZA;
-	t790 = t64 * t14;
-	t800 = t649 * t8;
-	t809 = 0.4e1 * t238 * t126 * t80 - 0.8e1 * t762 * t764 - 0.32e2 * t768 * self->xc * t275 + 0.64e2 * t773 * t740 - 0.4e1 * t301 * t777 - 0.8e1 * t781 * n * t8 * t675 + 0.4e1 * t238 * t786 + 0.32e2 * t768 * t34 * t790 * t8 - 0.8e1 * t633 * t528 * t634 + 0.8e1 * t754 * t528 * t739 + 0.128e3 * t800 * t119 * t80 * t19 * t106 + 0.8e1 * t674 * t739 * t13;
-	t812 = t649 * t80;
-	t817 = t83 * self->ZB;
-	t824 = t746 * self->ZB;
-	t828 = t800 * t14;
-	t855 = -0.64e2 * t812 * self->xc * t274 * t667 + 0.4e1 * t817 * t786 + 0.4e1 * t727 * self->ZA * t652 * self->ZB - 0.32e2 * t824 * t657 * t667 - 0.32e2 * t828 * t34 * t767 * self->xc - 0.8e1 * t633 * t15 * t34 * t634 - 0.8e1 * t674 * t739 * t15 + 0.32e2 * t768 * t64 * t275 + 0.4e1 * t708 * t14 * t307 + 0.2e1 * t708 * t206 * t652 + 0.8e1 * t632 * t35 * t13 * t34 * t634 * self->xc;
-	t858 = t35 * t19;
-	t873 = t2 * t8;
-	t878 = t61 * t1;
-	t901 = -0.16e2 * t632 * t2 * self->xc * t528 * t858 + 0.8e1 * t824 * t658 + 0.4e1 * t301 * t14 * t777 - 0.8e1 * t665 * t634 * t509 - 0.8e1 * t674 * t739 * t623 - 0.16e2 * t781 * t873 * t19 * self->xc + 0.8e1 * t878 * t14 * t127 + 0.8e1 * t878 * self->ZA * t51 * self->ZB + 0.8e1 * t686 * t764 + 0.8e1 * t665 * self->xc * t634 * t15 * t8 + 0.8e1 * t633 * t15 * t5 * t634 + 0.4e1 * t387 * t14 * t107 * self->ZA;
-	t903 = t739 * t790;
-	t923 = t737 * t80;
-	t924 = t667 * t790;
-	t927 = t780 * t2;
-	t937 = t15 * t19 * self->xc;
-	t943 = 0.32e2 * t738 * t903 + 0.16e2 * t781 * t873 * t19 + 0.8e1 * t754 * t15 * t652 * t5 + 0.16e2 * t666 * t858 * t623 + 0.64e2 * t828 * t25 * t767 * self->xc - 0.16e2 * t762 * t456 * t19 + 0.64e2 * t923 * t924 + 0.16e2 * t927 * t668 - 0.64e2 * t768 * self->ZA * t790 * t66 - 0.64e2 * t773 * t903 + 0.16e2 * t927 * t937 + 0.16e2 * t666 * t667 * t562;
-	t977 = 0.64e2 * t812 * t5 * t924 + 0.8e1 * t639 * t504 + 0.8e1 * t238 * t35 * t118 * t19 + 0.4e1 * t642 * t658 - 0.16e2 * t817 * t437 * t8 - 0.128e3 * t772 * self->ZB * t80 * t924 + 0.16e2 * t666 * t667 * t13 - 0.4e1 * t301 * t643 - 0.16e2 * t824 * t653 * t8 - 0.4e1 * t642 * t777 - 0.64e2 * t923 * t667 * t268 - 0.16e2 * t666 * t937;
-
-	self->C3A = (t72 + t132 + t169 + t210 + t246 + t298 + t337 + t378 + t409 + t441 + t483 + t512 + t542 + t573 + t600 + t627) / (t682 + t717 + t758 + t809 + t855 + t901 + t943 + t977);
-	/****************************************************************************************/
-	self->C4A = 0;
-	/****************************************************************************************/
-	t1 = nx * 0.3141592654e1;
-	t2 = t1 * self->xc;
-	t3 = cos(t2);
-	t4 = nx * nx;
-	t6 = n * 0.3141592654e1;
-	t7 = t3 * t4 * t6;
-	t8 = self->ZA * self->ZB;
-	t9 = exp(t6);
-	t10 = t9 * t9;
-	t11 = self->xc * n;
-	t13 = exp(t11 * 0.3141592654e1);
-	t14 = t13 * t13;
-	t15 = t14 * t13;
-	t16 = t14 * t14;
-	t17 = t16 * t15;
-	t18 = t10 * t17;
-	t19 = t8 * t18;
-	t22 = sin(t2);
-	t23 = nx * t22;
-	t24 = t23 * n;
-	t25 = self->ZB * self->ZB;
-	t30 = n * n;
-	t31 = t30 * n;
-	t32 = t31 * nx;
-	t33 = 0.3141592654e1 * 0.3141592654e1;
-	t35 = t32 * t22 * t33;
-	t36 = self->ZA * self->ZA;
-	t37 = t36 * self->xc;
-	t38 = t16 * t13;
-	t39 = t10 * t38;
-	t40 = t37 * t39;
-	t43 = sin(t1);
-	t44 = nx * t43;
-	t45 = t30 * 0.3141592654e1;
-	t46 = t44 * t45;
-	t47 = self->ZA * self->xc;
-	t49 = self->ZB * t16 * t9;
-	t54 = t4 * nx * t43;
-	t55 = self->xc * self->xc;
-	t57 = t54 * t30 * t55;
-	t58 = t33 * 0.3141592654e1;
-	t59 = t58 * t25;
-	t60 = t16 * t9;
-	t61 = t59 * t60;
-	t64 = self->xc * t25;
-	t65 = t14 * t9;
-	t66 = t64 * t65;
-	t70 = t44 * t31 * t33;
-	t71 = t37 * t65;
-	t74 = t10 * t15;
-	t75 = t64 * t74;
-	t78 = t25 * t10;
-	t83 = t54 * n * t33;
-	t84 = t55 * t25;
-	t85 = t10 * t9;
-	t86 = t14 * t85;
-	t87 = t84 * t86;
-	t90 = t30 * t30;
-	t92 = t44 * t90 * t58;
-	t93 = t55 * self->xc;
-	t94 = t93 * t25;
-	t95 = t85 * t16;
-	t96 = t94 * t95;
-	t102 = t23 * t45;
-	t103 = t10 * t10;
-	t104 = self->ZB * t103;
-	t106 = t47 * t104 * t15;
-	t111 = t54 * 0.3141592654e1;
-	t112 = t25 * t85;
-	t113 = t112 * t16;
-	t115 = t8 * t39;
-	t118 = t16 * t14;
-	t119 = t85 * t118;
-	t120 = t37 * t119;
-	t123 = t16 * t16;
-	t124 = t36 * t123;
-	t125 = t124 * t9;
-	t127 = -0.8e1 * t7 * t19 + 0.2e1 * t24 * t25 * t13 * t10 - 0.16e2 * t35 * t40 - 0.16e2 * t46 * t47 * t49 - 0.8e1 * t57 * t61 + 0.4e1 * t46 * t66 + 0.2e1 * t70 * t71 - 0.16e2 * t35 * t75 + 0.6e1 * t24 * t78 * t38 - 0.2e1 * t83 * t87 - 0.8e1 * t92 * t96 - 0.8e1 * t46 * t37 * t95 - 0.12e2 * t102 * t106 + 0.2e1 * t83 * t71 + t111 * t113 + 0.8e1 * t7 * t115 + 0.2e1 * t83 * t120 + t111 * t125;
-	t128 = t37 * t74;
-	t131 = t44 * n;
-	t133 = t25 * t9 * t118;
-	t136 = t36 * t14;
-	t137 = t136 * t9;
-	t140 = t30 * t4;
-	t142 = t140 * t3 * t33;
-	t143 = t64 * t39;
-	t147 = t30 * nx * t43;
-	t148 = 0.3141592654e1 * t36;
-	t149 = t9 * t118;
-	t153 = t44 * t31 * self->ZA;
-	t154 = t33 * self->xc;
-	t155 = t154 * t49;
-	t160 = self->ZA * t17 * self->xc * self->ZB;
-	t163 = t103 * t13;
-	t164 = t64 * t163;
-	t170 = t44 * t90 * t55;
-	t171 = t58 * self->ZB;
-	t172 = self->ZA * t16;
-	t174 = t171 * t172 * t9;
-	t177 = t36 * t55;
-	t178 = t177 * t149;
-	t181 = t54 * t11;
-	t182 = t33 * t25;
-	t186 = t25 * t14;
-	t187 = t186 * t9;
-	t193 = t186 * t85;
-	t198 = self->ZB * t55;
-	t199 = self->ZA * t103;
-	t201 = t198 * t199 * t15;
-	t204 = 0.2e1 * t7 * t128 - 0.2e1 * t131 * t133 - 0.2e1 * t131 * t137 + 0.16e2 * t142 * t143 - t147 * t148 * t149 + 0.8e1 * t153 * t155 - 0.4e1 * t7 * t160 + 0.2e1 * t7 * t164 + 0.10e2 * t102 * t40 + 0.16e2 * t170 * t174 + 0.2e1 * t83 * t178 - 0.2e1 * t181 * t182 * t65 - t111 * t187 - 0.2e1 * t70 * t87 + 0.4e1 * t102 * t160 - 0.2e1 * t131 * t193 - 0.16e2 * t142 * t75 + 0.16e2 * t35 * t201;
-	t210 = t32 * t22;
-	t211 = t33 * t55;
-	t212 = t25 * t38;
-	t213 = t211 * t212;
-	t216 = n * nx;
-	t217 = t22 * t25;
-	t222 = self->ZB * t85 * t16;
-	t226 = t23 * t30;
-	t227 = t13 * t10;
-	t228 = t148 * t227;
-	t233 = t37 * t163;
-	t237 = n * t4 * t3;
-	t238 = t148 * t74;
-	t241 = t64 * t86;
-	t245 = t148 * self->xc * t15;
-	t248 = t112 * t118;
-	t250 = t22 * t36;
-	t256 = 0.3141592654e1 * t25;
-	t257 = t256 * t39;
-	t262 = t38 * t103;
-	t263 = t37 * t262;
-	t267 = t148 * t17 * self->xc;
-	t270 = -0.6e1 * t7 * t143 - 0.4e1 * t24 * t19 - 0.8e1 * t210 * t213 - 0.2e1 * t216 * t217 * t15 - 0.32e2 * t153 * t211 * t222 + 0.4e1 * t226 * t228 + 0.16e2 * t142 * t201 + 0.2e1 * t7 * t233 - 0.4e1 * t237 * t238 - 0.2e1 * t83 * t241 - 0.2e1 * t237 * t245 + t111 * t248 + 0.2e1 * t216 * t250 * t15 - 0.2e1 * t131 * t125 - 0.4e1 * t226 * t257 + t147 * t148 * t95 - 0.2e1 * t102 * t263 + 0.2e1 * t237 * t267;
-	t273 = t37 * t149;
-	t277 = t47 * t104 * t13;
-	t285 = t31 * t36;
-	t286 = t44 * t285;
-	t291 = t25 * t123 * t9;
-	t304 = 0.3141592654e1 * self->xc;
-	t305 = t304 * t212;
-	t312 = t256 * t18;
-	t315 = t8 * t60;
-	t319 = t54 * t30 * t58;
-	t323 = t90 * t36;
-	t324 = t44 * t323;
-	t325 = t55 * t58;
-	t326 = t325 * t60;
-	t329 = 0.2e1 * t102 * t164 + 0.2e1 * t83 * t273 - 0.4e1 * t102 * t277 - 0.2e1 * t7 * t263 + 0.4e1 * t24 * t8 * t17 - 0.4e1 * t286 * t154 * t60 - 0.2e1 * t131 * t291 - t147 * t148 * t119 + 0.2e1 * t24 * t78 * t17 + 0.2e1 * t54 * t85 * 0.3141592654e1 * self->ZA * self->ZB - 0.4e1 * t226 * t305 - 0.2e1 * t70 * t66 + t147 * t256 * t95 + 0.4e1 * t237 * t312 + 0.2e1 * t111 * t315 - 0.8e1 * t319 * t96 - t111 * t193 - 0.8e1 * t324 * t326;
-	t332 = t8 * t95;
-	t335 = t136 * t85;
-	t337 = t256 * t227;
-	t340 = t177 * t119;
-	t346 = t37 * t86;
-	t351 = t103 * t15;
-	t352 = t177 * t351;
-	t355 = t64 * t119;
-	t358 = t8 * t227;
-	t361 = t85 * 0.3141592654e1;
-	t365 = t84 * t39;
-	t372 = self->ZB * t10;
-	t373 = t372 * t38;
-	t374 = t47 * t373;
-	t379 = t177 * t39;
-	t384 = -0.2e1 * t46 * t332 + t111 * t335 + 0.4e1 * t237 * t337 - 0.2e1 * t83 * t340 + 0.16e2 * t286 * t211 * t95 + 0.2e1 * t70 * t346 - 0.8e1 * t170 * t61 - 0.8e1 * t142 * t352 - 0.2e1 * t83 * t355 - 0.4e1 * t24 * t358 + 0.2e1 * t147 * t361 * t8 + 0.8e1 * t35 * t365 - 0.2e1 * t226 * t267 + 0.8e1 * t102 * t115 - 0.12e2 * t102 * t374 + 0.16e2 * t142 * t40 - 0.8e1 * t142 * t379 + 0.4e1 * t237 * t228;
-	t386 = t54 * t30 * t93;
-	t387 = self->ZA * t85;
-	t389 = t171 * t387 * t16;
-	t394 = t64 * t60;
-	t398 = t304 * t25 * t15;
-	t401 = t361 * t25;
-	t405 = t84 * t65;
-	t410 = t148 * t18;
-	t414 = t25 * t16 * t9;
-	t417 = t84 * t74;
-	t422 = t177 * t86;
-	t428 = self->ZB * t38;
-	t429 = t47 * t428;
-	t432 = t148 * t39;
-	t439 = 0.16e2 * t386 * t389 - 0.16e2 * t386 * t174 + 0.8e1 * t46 * t394 + 0.2e1 * t237 * t398 - t147 * t401 + 0.4e1 * t7 * t374 + 0.2e1 * t83 * t405 - 0.4e1 * t46 * t241 - 0.4e1 * t226 * t410 + 0.2e1 * t131 * t414 + 0.8e1 * t35 * t417 - 0.8e1 * t142 * t365 + 0.2e1 * t70 * t422 - 0.4e1 * t181 * t182 * t60 + 0.12e2 * t102 * t429 - 0.4e1 * t226 * t432 + 0.32e2 * t35 * t374 - 0.4e1 * t7 * t106;
-	t442 = t36 * t9 * t118;
-	t444 = t123 * t9;
-	t445 = t8 * t444;
-	t448 = t361 * t36;
-	t451 = t47 * t372 * t17;
-	t454 = t94 * t60;
-	t457 = t25 * t103;
-	t465 = t47 * t372 * t15;
-	t468 = t36 * t85;
-	t469 = t468 * t16;
-	t474 = t43 * t85;
-	t478 = t8 * t74;
-	t484 = t256 * t74;
-	t489 = t198 * self->ZA * t10 * t15;
-	t501 = -t111 * t442 + 0.4e1 * t131 * t445 - t147 * t448 + 0.4e1 * t7 * t451 + 0.8e1 * t92 * t454 - 0.2e1 * t24 * t457 * t13 - 0.2e1 * t286 * t211 * t65 + 0.4e1 * t7 * t465 + t111 * t469 - 0.2e1 * t216 * t250 * t17 - 0.2e1 * t216 * t474 * t25 - 0.4e1 * t24 * t478 + 0.4e1 * t24 * t8 * t38 + 0.4e1 * t226 * t484 - 0.16e2 * t142 * t489 - 0.2e1 * t24 * t212 * t103 - 0.2e1 * t216 * t22 * t17 * t25 + 0.2e1 * t70 * t120;
-	t504 = t33 * t36 * t55 * t38;
-	t507 = t37 * t18;
-	t512 = t47 * self->ZB * t13 * t10;
-	t518 = t59 * t95;
-	t530 = t84 * t351;
-	t534 = t37 * t227;
-	t549 = -0.8e1 * t210 * t504 + 0.2e1 * t102 * t507 + 0.4e1 * t7 * t512 + t111 * t133 - 0.16e2 * t35 * t489 + 0.8e1 * t170 * t518 + 0.2e1 * t24 * t36 * t13 * t10 + 0.4e1 * t131 * t387 * self->ZB + 0.12e2 * t102 * t465 - 0.8e1 * t142 * t530 + t111 * t291 - 0.2e1 * t102 * t534 - 0.4e1 * t70 * t394 - 0.10e2 * t102 * t128 + 0.4e1 * t237 * t305 + 0.8e1 * t102 * t19 + 0.2e1 * t83 * t346 - 0.16e2 * t35 * t128;
-	t557 = t468 * t118;
-	t562 = t93 * t58;
-	t563 = t562 * t60;
-	t567 = t44 * t90 * t93;
-	t575 = self->ZA * t55;
-	t576 = t575 * t428;
-	t583 = t37 * t60;
-	t590 = t140 * t3;
-	t601 = -0.2e1 * t226 * t398 - 0.2e1 * t70 * t340 - 0.2e1 * t131 * t557 - 0.4e1 * t24 * t115 + 0.8e1 * t324 * t563 + 0.16e2 * t567 * t389 + 0.16e2 * t70 * t84 * t95 + 0.2e1 * t70 * t178 - 0.16e2 * t142 * t576 - 0.4e1 * t237 * t257 - 0.4e1 * t226 * t312 + 0.8e1 * t46 * t583 + 0.2e1 * t24 * t36 * t38 * t103 + 0.8e1 * t590 * t213 + 0.2e1 * t102 * t143 - 0.16e2 * t35 * t143 + 0.2e1 * t131 * t248 + 0.4e1 * t46 * t346;
-	t604 = n * t36;
-	t606 = t154 * t95;
-	t625 = t36 * t103;
-	t640 = t30 * t36;
-	t641 = t54 * t640;
-	t642 = t325 * t95;
-	t647 = -0.4e1 * t131 * t315 - 0.4e1 * t54 * t604 * t606 - t147 * t148 * t60 + 0.16e2 * t35 * t576 - 0.8e1 * t102 * t478 + 0.32e2 * t142 * t465 - 0.4e1 * t237 * t484 - 0.2e1 * t70 * t355 + 0.2e1 * t70 * t273 + 0.2e1 * t102 * t233 - 0.2e1 * t24 * t625 * t13 - 0.8e1 * t7 * t358 - 0.2e1 * t111 * t445 - 0.4e1 * t7 * t429 + 0.16e2 * t46 * t47 * t222 + 0.2e1 * t131 * t113 + 0.8e1 * t641 * t642 - 0.2e1 * t7 * t534;
-	t652 = t36 * t16;
-	t653 = t652 * t9;
-	t655 = t64 * t227;
-	t658 = t182 * t95;
-	t663 = t562 * t95;
-	t684 = t64 * t351;
-	t689 = t36 * t10;
-	t695 = t154 * t222;
-	t698 = -0.4e1 * t216 * t217 * t38 - t111 * t653 - 0.2e1 * t7 * t655 - 0.4e1 * t181 * t658 + 0.2e1 * t131 * t469 - 0.8e1 * t641 * t663 - 0.4e1 * t83 * t583 - 0.2e1 * t83 * t177 * t65 - 0.4e1 * t24 * t457 * t15 + 0.16e2 * t70 * t84 * t60 + 0.8e1 * t57 * t518 - 0.32e2 * t142 * t374 + 0.4e1 * t24 * t8 * t351 + 0.4e1 * t102 * t684 - t147 * t256 * t86 - 0.2e1 * t24 * t689 * t15 - 0.2e1 * t70 * t241 + 0.8e1 * t153 * t695;
-	t711 = t575 * t373;
-	t717 = t304 * t17 * t25;
-	t736 = t177 * t74;
-	t739 = 0.2e1 * t226 * t245 - 0.8e1 * t102 * t358 - 0.16e2 * t57 * t389 - 0.2e1 * t102 * t655 + 0.8e1 * t590 * t504 - 0.8e1 * t641 * t326 - 0.16e2 * t35 * t711 - t111 * t557 + t111 * t137 - 0.2e1 * t226 * t717 + 0.8e1 * t102 * t37 * t351 + 0.2e1 * t131 * t335 - 0.4e1 * t131 * t332 - 0.2e1 * t216 * t474 * t36 - 0.2e1 * t111 * t332 + 0.16e2 * t142 * t711 - t147 * t256 * t60 + 0.8e1 * t142 * t736;
-	t750 = t64 * t262;
-	t763 = t44 * t640;
-	t770 = t84 * t119;
-	t782 = 0.4e1 * t102 * t512 + 0.8e1 * t142 * t417 + 0.8e1 * t641 * t563 - 0.2e1 * t7 * t507 + 0.2e1 * t7 * t750 - 0.8e1 * t35 * t352 + 0.4e1 * t237 * t410 + 0.4e1 * t7 * t684 - 0.2e1 * t46 * t445 + t147 * t148 * t65 + 0.4e1 * t763 * t304 * t119 + 0.16e2 * t70 * t177 * t60 + 0.2e1 * t70 * t770 - t111 * t414 - 0.16e2 * t567 * t174 - 0.4e1 * t46 * t71 - 0.4e1 * t46 * t355 - 0.4e1 * t7 * t277;
-	t797 = t64 * t149;
-	t821 = -t54 * t448 + 0.2e1 * t131 * t442 + 0.8e1 * t7 * t478 + 0.8e1 * t35 * t379 - 0.2e1 * t181 * t182 * t149 + 0.2e1 * t70 * t405 + 0.2e1 * t83 * t770 - 0.2e1 * t70 * t797 - 0.6e1 * t7 * t75 - 0.4e1 * t286 * t606 - 0.4e1 * t237 * t432 + t147 * t256 * t149 - 0.4e1 * t763 * t304 * t149 - 0.2e1 * t102 * t75 + 0.2e1 * t237 * t717 + 0.8e1 * t324 * t642 - 0.16e2 * t170 * t389 + 0.2e1 * t83 * t422;
-	t827 = t84 * t149;
-	t846 = t54 * n * self->ZA;
-	t854 = t64 * t18;
-	t867 = -0.16e2 * t142 * t128 + 0.32e2 * t35 * t465 - 0.2e1 * t83 * t827 + 0.2e1 * t46 * t315 + t147 * t148 * t86 - 0.4e1 * t102 * t451 - 0.8e1 * t226 * t148 * self->xc * t38 - 0.2e1 * t24 * t689 * t38 + 0.2e1 * t131 * t187 + 0.8e1 * t846 * t155 + 0.8e1 * t35 * t736 + 0.2e1 * t24 * t689 * t17 - 0.2e1 * t7 * t854 + t147 * t256 * t119 + 0.2e1 * t102 * t854 - 0.8e1 * t35 * t530 + 0.4e1 * t46 * t797 + 0.2e1 * t102 * t750;
-	t909 = -0.8e1 * t324 * t663 + t147 * t256 * t444 - t147 * t256 * t65 + 0.4e1 * t226 * t238 + 0.2e1 * t7 * t40 - t54 * t401 + 0.16e2 * t57 * t174 + 0.4e1 * t226 * t337 + 0.4e1 * t24 * t8 * t163 + 0.8e1 * t846 * t695 + 0.8e1 * t319 * t454 + 0.2e1 * t131 * t653 - 0.8e1 * t46 * t64 * t95 + 0.6e1 * t24 * t78 * t15 - 0.4e1 * t44 * t31 * self->xc * t658 - 0.32e2 * t153 * t211 * t49 - 0.2e1 * t70 * t827 + t147 * t148 * t444;
-	t914 = t25 * self->ZB;
-	t915 = t33 * t914;
-	t919 = t4 * t4;
-	t920 = t16 * t919;
-	t929 = t123 * t90;
-	t932 = t919 * t103;
-	t935 = t33 * self->ZB;
-	t939 = t652 * t919;
-	t942 = t16 * t30;
-	t943 = t942 * t4;
-	t949 = t103 * t16;
-	t950 = t949 * t90;
-	t953 = -0.2e1 * t915 * t103 * t90 + 0.2e1 * t915 * t920 - 0.2e1 * t915 * t123 * t919 + 0.2e1 * t915 * t16 * t90 - 0.2e1 * t915 * t929 - 0.2e1 * t915 * t932 - 0.2e1 * t935 * t323 * t123 + 0.2e1 * t935 * t939 + 0.4e1 * t915 * t943 + 0.4e1 * t182 * t172 * t90 + 0.2e1 * t915 * t950;
-	t954 = t171 * t36;
-	t955 = t90 * n;
-	t956 = self->xc * t955;
-	t957 = t118 * t10;
-	t964 = t33 * t33;
-	t965 = t964 * self->ZB;
-	t966 = t965 * t640;
-	t967 = t10 * t919;
-	t968 = t55 * t16;
-	t969 = t967 * t968;
-	t972 = t935 * t36;
-	t974 = t103 * t30 * t4;
-	t977 = self->xc * t16;
-	t978 = t967 * t977;
-	t981 = t90 * t30;
-	t983 = t16 * t10;
-	t987 = t182 * self->ZA;
-	t988 = t4 * t10;
-	t992 = t171 * t604;
-	t993 = self->xc * t14;
-	t994 = t932 * t993;
-	t997 = t182 * t30;
-	t1005 = t171 * t285;
-	t1006 = t988 * t993;
-	t1009 = t58 * t914;
-	t1010 = t1009 * t31;
-	t1013 = 0.8e1 * t954 * t956 * t957 + 0.2e1 * t915 * t932 * t16 + 0.32e2 * t966 * t969 - 0.4e1 * t972 * t974 - 0.32e2 * t966 * t978 + 0.32e2 * t965 * t981 * t177 * t983 - 0.32e2 * t987 * t942 * t988 + 0.8e1 * t992 * t994 + 0.8e1 * t997 * t949 * self->ZA * t4 - 0.2e1 * t935 * t124 * t919 - 0.16e2 * t1005 * t1006 + 0.16e2 * t1010 * t1006;
-	t1015 = t964 * t25;
-	t1016 = self->ZA * t30;
-	t1017 = t1015 * t1016;
-	t1020 = t967 * t993;
-	t1031 = t1009 * t118;
-	t1032 = t31 * t10;
-	t1040 = t964 * t914;
-	t1041 = t1040 * t90;
-	t1044 = t55 * t10 * t4 * t16;
-	t1047 = t1040 * t30;
-	t1050 = t123 * self->ZA;
-	t1054 = t977 * t988;
-	t1057 = 0.64e2 * t1017 * t978 - 0.8e1 * t992 * t1020 + 0.2e1 * t972 * t950 + 0.4e1 * t182 * t929 * self->ZA + 0.4e1 * t182 * t199 * t90 - 0.16e2 * t1031 * t1032 * t4 * self->xc + 0.4e1 * t182 * t172 * t919 + 0.64e2 * t1041 * t1044 + 0.32e2 * t1047 * t969 + 0.4e1 * t182 * t1050 * t919 - 0.64e2 * t1041 * t1054;
-	t1058 = t1009 * n;
-	t1063 = t932 * self->ZA;
-	t1069 = t123 * t30 * t4;
-	t1080 = t993 * t103 * t4;
-	t1088 = t935 * t103;
-	t1094 = -0.8e1 * t1058 * t994 - 0.32e2 * t1047 * t978 + 0.4e1 * t182 * t1063 - 0.4e1 * t915 * t974 - 0.4e1 * t915 * t1069 - 0.2e1 * t935 * t625 * t90 - 0.8e1 * t1009 * t10 * t14 * t955 - 0.16e2 * t1010 * t1080 - 0.2e1 * t935 * t625 * t919 - 0.64e2 * t1017 * t969 + 0.2e1 * t1088 * t939 + 0.8e1 * t1009 * t957 * t955;
-	t1113 = t955 * t118 * self->xc;
-	t1120 = t4 * t118;
-	t1125 = t981 * self->xc;
-	t1133 = n * t10;
-	t1140 = -0.8e1 * t954 * t955 * t10 * t993 + 0.2e1 * t935 * t652 * t90 - 0.64e2 * t1015 * t981 * t575 * t983 + 0.8e1 * t182 * t103 * t1016 * t4 + 0.8e1 * t1009 * t1113 + 0.16e2 * t954 * t1032 * t4 * t14 - 0.16e2 * t954 * t1032 * t1120 + 0.64e2 * t1015 * t10 * t172 * t1125 + 0.8e1 * t171 * t103 * t136 * t956 - 0.8e1 * t1031 * t1133 * t919 * self->xc + 0.8e1 * t1058 * t1020;
-	t1153 = self->xc * t118;
-	t1165 = t182 * t16;
-	t1170 = t171 * t10;
-	t1178 = self->ZA * t90;
-	t1182 = 0.4e1 * t1088 * t652 * t140 + 0.8e1 * t954 * t1133 * t919 * t14 + 0.4e1 * t972 * t943 - 0.4e1 * t972 * t1069 - 0.16e2 * t954 * t31 * t4 * t1153 - 0.8e1 * t954 * n * t919 * t1153 - 0.8e1 * t954 * t1133 * t919 * t118 + 0.4e1 * t1165 * t1063 + 0.16e2 * t1005 * t1080 - 0.8e1 * t1170 * t118 * t36 * t955 - 0.16e2 * t987 * t920 * t10 - 0.16e2 * t1165 * t1178 * t10;
-	t1195 = t1040 * t981;
-	t1199 = t1009 * t955;
-	t1203 = t1009 * t10;
-	t1211 = t965 * t323;
-	t1225 = -0.32e2 * t965 * t10 * t652 * t1125 + 0.4e1 * t915 * t16 * t974 + 0.4e1 * t182 * t90 * t949 * self->ZA + 0.32e2 * t1195 * t968 * t10 - 0.8e1 * t1199 * t993 * t103 + 0.8e1 * t1203 * t118 * n * t919 + 0.8e1 * t1170 * t136 * t955 + 0.64e2 * t1211 * t1044 + 0.16e2 * t1031 * t1032 * t4 + 0.8e1 * t987 * t943 + 0.8e1 * t1199 * t993 * t10 + 0.8e1 * t997 * t1050 * t4;
-	t1263 = -0.128e3 * t1015 * t1178 * t1044 + 0.16e2 * t1005 * t988 * t1153 + 0.8e1 * t1058 * t1153 * t919 + 0.16e2 * t1010 * t1120 * self->xc - 0.8e1 * t954 * t1113 - 0.8e1 * t1203 * t14 * n * t919 - 0.16e2 * t1203 * t14 * t31 * t4 - 0.8e1 * t1203 * t1113 - 0.32e2 * t1195 * t977 * t10 - 0.64e2 * t1211 * t1054 + 0.8e1 * t992 * t967 * t1153 + 0.128e3 * t1015 * t983 * t90 * t4 * t47;
-
-	self->C1B = (t127 + t204 + t270 + t329 + t384 + t439 + t501 + t549 + t601 + t647 + t698 + t739 + t782 + t821 + t867 + t909) / (t953 + t1013 + t1057 + t1094 + t1140 + t1182 + t1225 + t1263);
-	/****************************************************************************************/
-	t1 = n * n;
-	t2 = t1 * n;
-	t3 = nx * t2;
-	t4 = 0.3141592654e1 * self->ZA;
-	t5 = t3 * t4;
-	t6 = nx * 0.3141592654e1;
-	t7 = t6 * self->xc;
-	t8 = sin(t7);
-	t9 = t8 * self->ZB;
-	t10 = n * 0.3141592654e1;
-	t11 = exp(t10);
-	t12 = t11 * t11;
-	t15 = exp( self->xc * n * 0.3141592654e1);
-	t16 = t15 * t15;
-	t17 = t16 * t16;
-	t18 = t17 * t15;
-	t19 = t12 * t18;
-	t23 = t1 * t1;
-	t24 = nx * t23;
-	t25 = self->ZB * self->ZB;
-	t27 = t18 * t8;
-	t28 = 0.3141592654e1 * 0.3141592654e1;
-	t29 = self->xc * self->xc;
-	t30 = t28 * t29;
-	t34 = t1 * self->xc;
-	t35 = 0.3141592654e1 * self->ZB;
-	t36 = t34 * t35;
-	t37 = cos(t7);
-	t38 = self->ZA * t37;
-	t39 = nx * nx;
-	t40 = t39 * t12;
-	t41 = t16 * t15;
-	t43 = t38 * t40 * t41;
-	t46 = t25 * n;
-	t47 = t46 * 0.3141592654e1;
-	t48 = t39 * nx;
-	t49 = sin(t6);
-	t50 = t48 * t49;
-	t51 = t12 * t11;
-	t52 = t51 * t17;
-	t53 = t50 * t52;
-	t56 = t34 * 0.3141592654e1 * t25;
-	t57 = t37 * t39;
-	t58 = t17 * t41;
-	t59 = t12 * t58;
-	t60 = t57 * t59;
-	t63 = t25 * t18;
-	t64 = t57 * n;
-	t67 = self->ZA * self->ZA;
-	t68 = t67 * n;
-	t69 = 0.3141592654e1 * t48;
-	t70 = t68 * t69;
-	t71 = t49 * self->xc;
-	t72 = t17 * t16;
-	t73 = t11 * t72;
-	t74 = t71 * t73;
-	t77 = t1 * t67;
-	t78 = t77 * 0.3141592654e1;
-	t81 = nx * t25;
-	t82 = t81 * t49;
-	t83 = t17 * t17;
-	t85 = t1 * t83 * t11;
-	t87 = nx * self->ZB;
-	t88 = t8 * t2;
-	t89 = t87 * t88;
-	t90 = 0.3141592654e1 * self->xc;
-	t91 = t12 * t12;
-	t92 = self->ZA * t91;
-	t97 = self->ZB * self->ZA;
-	t98 = t97 * t37;
-	t99 = t39 * n;
-	t100 = t12 * t41;
-	t104 = 0.8e1 * t5 * t9 * t19 + 0.8e1 * t24 * t25 * t27 * t30 + 0.12e2 * t36 * t43 - t47 * t53 - 0.2e1 * t56 * t60 - 0.4e1 * t63 * t64 + 0.6e1 * t70 * t74 + 0.4e1 * t78 * t60 - t82 * t85 + 0.4e1 * t89 * t90 * t92 * t41 + 0.4e1 * t98 * t99 * t100;
-	t105 = t67 * t48;
-	t106 = t49 * t51;
-	t107 = t106 * t72;
-	t109 = t1 * 0.3141592654e1;
-	t110 = t109 * self->xc;
-	t115 = nx * t67;
-	t116 = t115 * t49;
-	t117 = t1 * t16;
-	t118 = t117 * t11;
-	t120 = t2 * t25;
-	t121 = t28 * 0.3141592654e1;
-	t122 = t121 * t29;
-	t123 = t120 * t122;
-	t129 = t1 * self->ZB;
-	t130 = t129 * t4;
-	t131 = t57 * t100;
-	t134 = t12 * t16;
-	t136 = t109 * t39;
-	t139 = self->ZB * t18;
-	t141 = t39 * t1;
-	t142 = t141 * t90;
-	t145 = t77 * t90;
-	t146 = t91 * t41;
-	t147 = t57 * t146;
-	t151 = t25 * t39 * t1;
-	t152 = t72 * t12;
-	t156 = t49 * t2;
-	t158 = t83 * t11;
-	t162 = -t105 * t107 + 0.8e1 * t110 * t72 * t25 * t39 - t116 * t118 + 0.8e1 * t123 * t53 + 0.8e1 * t5 * t9 * t59 - 0.8e1 * t130 * t131 - 0.8e1 * t134 * t25 * t136 - 0.12e2 * t139 * t38 * t142 - 0.8e1 * t145 * t147 - 0.8e1 * t151 * t90 * t152 - 0.2e1 * t87 * t156 * t4 * t158;
-	t164 = t115 * t88;
-	t165 = t90 * t19;
-	t168 = t25 * t48;
-	t169 = t49 * t16;
-	t170 = t169 * t11;
-	t174 = self->ZA * n * t69;
-	t175 = self->ZB * t51;
-	t176 = t175 * t17;
-	t177 = t71 * t176;
-	t180 = t1 * t29;
-	t181 = t28 * t25;
-	t182 = t180 * t181;
-	t183 = t50 * t73;
-	t186 = self->ZA * t1;
-	t187 = t28 * t48;
-	t188 = t186 * t187;
-	t189 = self->ZB * t17;
-	t190 = t189 * t11;
-	t191 = t71 * t190;
-	t194 = t50 * t158;
-	t196 = t115 * t156;
-	t197 = t90 * t73;
-	t201 = t49 * t17 * t11;
-	t204 = t88 * t90;
-	t207 = t68 * 0.3141592654e1;
-	t208 = t17 * t11;
-	t209 = t50 * t208;
-	t211 = -0.2e1 * t164 * t165 - t168 * t170 + t168 * t107 + 0.8e1 * t174 * t177 + 0.2e1 * t182 * t183 + 0.8e1 * t188 * t191 + t47 * t194 - 0.6e1 * t196 * t197 - t168 * t201 - 0.4e1 * t81 * t18 * t204 - t207 * t209;
-	t212 = t2 * 0.3141592654e1;
-	t213 = t212 * t52;
-	t215 = t81 * t8;
-	t216 = t212 * t59;
-	t219 = t3 * t90;
-	t220 = t25 * t8;
-	t221 = t18 * t91;
-	t225 = t71 * t52;
-	t231 = t16 * t51;
-	t232 = t50 * t231;
-	t237 = self->ZA * t12;
-	t243 = t67 * t28;
-	t244 = t24 * t243;
-	t245 = t71 * t231;
-	t249 = -t116 * t213 - 0.4e1 * t215 * t216 + 0.2e1 * t219 * t220 * t221 - 0.4e1 * t70 * t225 + 0.4e1 * t98 * t99 * t146 + t47 * t232 - 0.2e1 * t145 * t57 * t221 + 0.4e1 * t89 * t90 * t237 * t41 - t105 * t201 - 0.6e1 * t244 * t245 + t105 * t170;
-	t252 = t25 * t37;
-	t253 = t252 * t39;
-	t255 = n * t15 * t12;
-	t258 = t2 * t29;
-	t259 = self->ZB * t28;
-	t260 = t258 * t259;
-	t263 = t106 * t17;
-	t265 = self->xc * t25;
-	t269 = t25 * t49;
-	t270 = t269 * t52;
-	t273 = t1 * t25;
-	t274 = t273 * 0.3141592654e1;
-	t275 = t57 * t19;
-	t278 = t24 * t30;
-	t288 = t1 * t11 * t72;
-	t290 = t212 * t208;
-	t292 = t2 * self->xc;
-	t296 = 0.2e1 * t253 * t255 + 0.16e2 * t260 * t43 + t105 * t263 - 0.4e1 * t10 * t265 * t53 + 0.4e1 * t219 * t270 - 0.12e2 * t274 * t275 + 0.8e1 * t278 * t270 - 0.2e1 * self->ZB * n * t69 * t49 * self->ZA * t158 - t82 * t288 - t116 * t290 + 0.16e2 * t292 * t243 * t275;
-	t301 = t50 * t176;
-	t304 = t51 * t72;
-	t305 = t71 * t304;
-	t308 = t25 * t41;
-	t311 = self->ZA * t48;
-	t312 = t311 * t49;
-	t317 = t91 * t15;
-	t318 = t57 * t317;
-	t321 = t81 * t88;
-	t322 = t90 * t59;
-	t325 = t212 * t231;
-	t327 = t15 * t12;
-	t328 = t57 * t327;
-	t331 = t77 * t187;
-	t334 = t2 * self->ZA;
-	t335 = t334 * t122;
-	t336 = t50 * t190;
-	t339 = 0.8e1 * t151 * t90 * t134 + 0.16e2 * t186 * t30 * t301 - 0.2e1 * t70 * t305 + 0.2e1 * t308 * t64 - 0.2e1 * t312 * self->ZB * t83 * t11 + 0.2e1 * t56 * t318 + 0.2e1 * t321 * t322 - t116 * t325 - 0.4e1 * t274 * t328 + 0.2e1 * t331 * t305 - 0.16e2 * t335 * t336;
-	t341 = t169 * t51;
-	t344 = t49 * t11 * t72;
-	t346 = t77 * t30;
-	t347 = t50 * t304;
-	t350 = t25 * t51;
-	t352 = nx * self->ZA;
-	t353 = t49 * t23;
-	t354 = t352 * t353;
-	t355 = t28 * self->xc;
-	t362 = t25 * t91;
-	t365 = t23 * n;
-	t366 = nx * t365;
-	t367 = t366 * t122;
-	t368 = self->ZB * t49;
-	t369 = self->ZA * t51;
-	t370 = t369 * t17;
-	t371 = t368 * t370;
-	t374 = t115 * t353;
-	t375 = t355 * t73;
-	t381 = t105 * t341 - t105 * t344 - 0.2e1 * t346 * t347 - t350 * t50 - 0.8e1 * t354 * t355 * t176 - 0.4e1 * t98 * t99 * t317 - 0.2e1 * t362 * t99 - 0.16e2 * t367 * t371 + 0.6e1 * t374 * t375 - 0.8e1 * t182 * t53 - t82 * t290;
-	t382 = t71 * t208;
-	t394 = t2 * t67;
-	t395 = t394 * t122;
-	t398 = t352 * t156;
-	t402 = t17 * t12;
-	t403 = t39 * self->ZA;
-	t404 = t402 * t403;
-	t407 = t269 * t208;
-	t411 = t49 * t83 * t11;
-	t413 = t46 * t69;
-	t419 = -0.4e1 * t331 * t382 + 0.2e1 * t115 * t58 * t204 - 0.2e1 * t145 * t60 + 0.12e2 * t274 * t131 + 0.2e1 * t346 * t232 + 0.8e1 * t395 * t53 - 0.8e1 * t398 * t90 * t176 - 0.64e2 * t260 * t404 + 0.4e1 * t219 * t407 + t168 * t411 - 0.6e1 * t413 * t74 - 0.2e1 * t110 * t308 * t57;
-	t424 = t16 * t11;
-	t425 = t212 * t424;
-	t427 = t258 * t181;
-	t430 = t67 * t29;
-	t431 = t366 * t430;
-	t432 = t121 * t49;
-	t433 = t432 * t52;
-	t436 = n * t12;
-	t437 = t436 * t18;
-	t440 = t29 * self->xc;
-	t441 = t440 * t121;
-	t442 = t394 * t441;
-	t445 = t67 * t37;
-	t446 = t445 * t39;
-	t448 = n * t18 * t91;
-	t453 = t352 * t49;
-	t458 = t8 * t23;
-	t462 = t81 * t458;
-	t463 = t30 * t19;
-	t466 = -t47 * t209 + t116 * t425 - 0.8e1 * t427 * t275 + 0.8e1 * t431 * t433 - 0.2e1 * t253 * t437 - 0.8e1 * t442 * t53 - 0.2e1 * t446 * t448 + 0.2e1 * t175 * t312 + 0.6e1 * t453 * t129 * t208 + 0.8e1 * t115 * t18 * t458 * t30 + 0.8e1 * t462 * t463;
-	t470 = t436 * t58;
-	t475 = t2 * t121 * t440 * t25;
-	t485 = t212 * t73;
-	t488 = t67 * t72 * t1;
-	t490 = t39 * self->xc;
-	t501 = 0.4e1 * t374 * t355 * t52 + 0.2e1 * t446 * t470 - 0.8e1 * t475 * t53 - 0.2e1 * t446 * t437 - 0.4e1 * t36 * t38 * t39 * t15 * t12 - t116 * t485 + 0.8e1 * t488 * 0.3141592654e1 * t12 * t490 - t207 * t183 - 0.2e1 * t182 * t232 - 0.6e1 * t413 * t245 - 0.4e1 * t413 * t382;
-	t503 = t115 * t8;
-	t510 = t355 * t19;
-	t513 = t432 * t208;
-	t525 = t38 * t40 * t18;
-	t533 = -0.4e1 * t503 * t216 - 0.4e1 * t89 * t90 * t92 * t15 - 0.16e2 * t462 * t510 + 0.8e1 * t431 * t513 - 0.4e1 * t78 * t131 + t47 * t183 - 0.2e1 * t67 * t83 * t99 + 0.4e1 * t331 * t225 + 0.16e2 * t260 * t525 - 0.4e1 * t89 * t90 * t237 * t58 - t207 * t53;
-	t536 = t28 * t37;
-	t538 = t490 * t100;
-	t541 = t334 * t441;
-	t547 = t394 * t30;
-	t550 = t212 * t19;
-	t553 = t366 * t441;
-	t556 = n * t17;
-	t571 = -0.8e1 * t427 * t131 + 0.16e2 * t394 * t536 * t538 + 0.16e2 * t541 * t336 + 0.2e1 * t453 * t129 * t158 - 0.8e1 * t547 * t147 + 0.4e1 * t503 * t550 - 0.8e1 * t553 * t270 + 0.4e1 * t556 * self->ZB * t92 * t39 - 0.2e1 * t67 * t91 * t99 - t82 * t425 + 0.4e1 * t78 * t275 + 0.2e1 * t78 * self->xc * t41 * t57;
-	t583 = t90 * t317;
-	t594 = t212 * t158;
-	t596 = t152 * t67;
-	t602 = t67 * t17;
-	t607 = 0.8e1 * t367 * t407 - 0.4e1 * t98 * t99 * t59 + 0.16e2 * t260 * t18 * self->ZA * t57 + 0.2e1 * t321 * t583 - 0.6e1 * t174 * t368 * t52 - 0.4e1 * t89 * t90 * self->ZA * t15 * t12 + t116 * t594 - 0.8e1 * t596 * t136 - 0.4e1 * t98 * t99 * t327 + 0.2e1 * t602 * t99 + 0.2e1 * t164 * t583;
-	t613 = t83 * t25;
-	t616 = t81 * t156;
-	t627 = t90 * t231;
-	t630 = t91 * t16;
-	t638 = 0.4e1 * t196 * t90 * t208 - 0.8e1 * t130 * t60 - 0.2e1 * t613 * t99 + 0.6e1 * t616 * t197 - 0.8e1 * t547 * t131 + 0.8e1 * t67 * t18 * t37 * t142 + 0.2e1 * t145 * t328 - 0.6e1 * t196 * t627 + 0.8e1 * t630 * t67 * t142 - 0.8e1 * t547 * t275 + 0.8e1 * t395 * t209;
-	t643 = t77 * t355;
-	t648 = t115 * t458;
-	t651 = t134 * t67;
-	t657 = t30 * t304;
-	t660 = t30 * t146;
-	t665 = t25 * t17;
-	t668 = t50 * t424;
-	t671 = -0.4e1 * t321 * t90 * t146 - 0.6e1 * t643 * t232 + 0.8e1 * t182 * t209 - 0.16e2 * t648 * t510 + 0.8e1 * t651 * t136 + 0.8e1 * t89 * t4 * t100 - 0.2e1 * t374 * t657 - 0.8e1 * t648 * t660 + 0.8e1 * t130 * t328 + 0.2e1 * t665 * t99 + 0.2e1 * t346 * t668;
-	t672 = t90 * t424;
-	t676 = t120 * t536;
-	t680 = t436 * t41;
-	t688 = t366 * t67 * t440;
-	t696 = self->xc * t12;
-	t697 = t696 * t18;
-	t701 = t252 * t141;
-	t702 = t90 * t221;
-	t705 = 0.2e1 * t196 * t672 - t47 * t347 + 0.16e2 * t676 * t538 - t116 * t85 - 0.2e1 * t253 * t680 + t207 * t194 + 0.4e1 * t98 * t99 * t19 - 0.8e1 * t688 * t433 + 0.16e2 * t541 * t301 - 0.6e1 * t312 * t190 + 0.4e1 * t352 * t88 * t35 * t697 + 0.2e1 * t701 * t702;
-	t712 = t24 * t430;
-	t713 = t28 * t49;
-	t721 = t1 * t17 * t11;
-	t726 = self->ZB * self->xc;
-	t737 = n * t91;
-	t741 = 0.8e1 * t346 * t209 + 0.2e1 * t712 * t713 * t424 + 0.8e1 * t130 * t275 - t47 * t668 + t116 * t721 - 0.8e1 * t688 * t513 + 0.4e1 * t352 * t27 * t212 * t726 + 0.8e1 * t648 * t463 + 0.4e1 * t274 * t60 - 0.4e1 * t374 * t355 * t208 - 0.4e1 * t253 * t737 * t41;
-	t745 = t269 * t231;
-	t749 = t1 * t28 * t265;
-	t757 = t16 * t39;
-	t758 = t696 * t757;
-	t762 = t69 * t49;
-	t772 = t355 * t100;
-	t775 = t81 * t353;
-	t778 = -0.8e1 * t398 * t90 * t190 - 0.2e1 * t278 * t745 + 0.4e1 * t749 * t53 + 0.32e2 * t394 * t29 * t28 * t17 * t40 - 0.8e1 * t78 * t758 + t350 * n * t762 - 0.6e1 * t87 * t49 * t186 * t52 - 0.8e1 * t553 * t407 - 0.4e1 * t749 * t209 + 0.16e2 * t648 * t772 - 0.6e1 * t775 * t375;
-	t790 = t212 * t304;
-	t793 = t156 * 0.3141592654e1;
-	t795 = t355 * t304;
-	t800 = t91 * t39;
-	t801 = t800 * n;
-	t807 = t2 * t28;
-	t808 = t807 * t726;
-	t811 = -0.2e1 * t616 * t672 - 0.2e1 * t446 * t680 - 0.2e1 * t78 * self->xc * t58 * t57 + 0.8e1 * t367 * t270 - t82 * t790 + t115 * t51 * t793 - 0.2e1 * t775 * t795 + 0.8e1 * t123 * t209 + 0.2e1 * t665 * t801 - 0.2e1 * t67 * t41 * t64 - 0.32e2 * t808 * t43;
-	t812 = t117 * t51;
-	t821 = t24 * t355;
-	t827 = t90 * t304;
-	t840 = t800 * t41;
-	t844 = -t116 * t812 - 0.2e1 * t110 * t25 * t58 * t57 - 0.4e1 * t78 * t328 + t82 * t485 - 0.4e1 * t821 * t407 + 0.4e1 * t196 * t90 * t52 + 0.2e1 * t196 * t827 + t82 * t325 + 0.2e1 * t253 * t448 - 0.32e2 * t402 * t67 * t807 * t490 - t207 * t232 + 0.12e2 * t186 * t90 * self->ZB * t37 * t840;
-	t849 = t1 * t51;
-	t850 = t849 * t17;
-	t860 = t269 * t424;
-	t863 = t273 * t187;
-	t874 = 0.16e2 * t462 * t772 - t116 * t850 + 0.16e2 * t553 * t371 + t116 * t288 - 0.12e2 * t97 * t57 * t109 * t697 + t82 * t594 - 0.2e1 * t278 * t860 - 0.2e1 * t863 * t305 - 0.16e2 * t180 * t259 * t311 * t201 - 0.6e1 * t863 * t74 + 0.8e1 * t174 * t191;
-	t879 = self->xc * self->ZA;
-	t888 = t67 * t51;
-	t901 = self->ZA * t17;
-	t903 = t368 * t901 * t11;
-	t908 = -0.2e1 * t352 * t51 * t156 * t35 + 0.64e2 * t879 * t189 * t807 * t40 + 0.2e1 * t46 * t58 * t37 * t39 - t888 * t50 + t105 * t411 - 0.16e2 * t335 * t301 + 0.8e1 * t152 * t25 * t136 - 0.8e1 * t278 * t407 + 0.2e1 * t712 * t713 * t231 - 0.16e2 * t367 * t903 + 0.2e1 * t145 * t318;
-	t923 = t71 * t424;
-	t926 = t87 * t458;
-	t927 = t28 * self->ZA;
-	t944 = 0.8e1 * t354 * t355 * t190 - 0.8e1 * t110 * t16 * t25 * t800 - 0.2e1 * t374 * t30 * t73 - 0.16e2 * t354 * t30 * t176 - 0.2e1 * t244 * t923 - 0.32e2 * t926 * t927 * t696 * t41 - 0.32e2 * t808 * t525 + 0.6e1 * t749 * t232 - 0.8e1 * t188 * t177 + 0.4e1 * t36 * t58 * self->ZA * t57 + 0.4e1 * t821 * t270;
-	t948 = t90 * t327;
-	t961 = t30 * t100;
-	t964 = t29 * t49;
-	t981 = t106 * t1;
-	t983 = -0.2e1 * t219 * t220 * t100 + 0.2e1 * t321 * t948 - 0.16e2 * t189 * self->ZA * t99 * t12 - 0.2e1 * t369 * n * t69 * t368 + 0.2e1 * t374 * t795 - 0.8e1 * t462 * t961 - 0.8e1 * t244 * t964 * t208 + 0.2e1 * t413 * t923 + 0.4e1 * t36 * t38 * t40 * t58 - 0.2e1 * t87 * t51 * t49 * t1 * self->ZA + t888 * n * t762 + t115 * t981;
-	t1012 = 0.6e1 * t616 * t627 - t82 * t213 + 0.2e1 * t775 * t657 - 0.12e2 * t215 * t550 - 0.6e1 * t145 * t131 + 0.2e1 * t81 * t41 * t204 + 0.6e1 * self->ZB * t48 * t49 * t370 - 0.4e1 * t70 * t382 + 0.2e1 * t446 * t255 + 0.8e1 * t89 * t4 * t327 - 0.4e1 * t56 * t147;
-	t1018 = t212 * t100;
-	t1029 = t212 * t327;
-	t1040 = 0.6e1 * t70 * t245 + 0.2e1 * t56 * t328 + t207 * t668 + 0.4e1 * t503 * t1018 + 0.2e1 * t253 * t470 - 0.6e1 * t398 * t35 * t208 - 0.8e1 * t331 * t964 * t52 - 0.4e1 * t503 * t1029 + 0.6e1 * t821 * t745 + 0.4e1 * t63 * t37 * t142 + 0.16e2 * t260 * t38 * t840;
-	t1068 = t207 * t347 - 0.2e1 * t164 * t702 - 0.2e1 * t331 * t964 * t73 + 0.8e1 * t374 * t30 * t52 + 0.16e2 * t278 * t903 + 0.2e1 * t863 * t923 + 0.6e1 * t445 * t141 * t165 - 0.2e1 * t164 * t90 * t100 + 0.6e1 * t331 * t74 - 0.2e1 * t182 * t668 - 0.2e1 * t115 * t41 * t204;
-	t1079 = t58 * t8;
-	t1091 = t807 * t29;
-	t1092 = t665 * t40;
-	t1101 = self->ZB * t91;
-	t1102 = t403 * n;
-	t1105 = -0.4e1 * t58 * self->ZB * self->ZA * t64 - t82 * t850 + 0.2e1 * t821 * t860 + t81 * t51 * t793 + 0.2e1 * t3 * t25 * t1079 * t90 + t82 * t721 - 0.2e1 * t643 * t668 + 0.16e2 * t926 * t927 * t29 * t91 * t41 + 0.32e2 * t1091 * t1092 - 0.2e1 * t219 * t220 * t19 + 0.4e1 * t139 * self->ZA * t64 + 0.4e1 * t1101 * t1102;
-	t1108 = t849 * t72;
-	t1121 = t737 * t15;
-	t1124 = t29 * t12;
-	t1133 = t116 * t1108 - 0.8e1 * t475 * t209 - 0.32e2 * t807 * self->xc * t1092 + 0.2e1 * t278 * t269 * t73 + t82 * t812 - 0.6e1 * t56 * t131 + 0.2e1 * t253 * t1121 + 0.16e2 * t926 * t927 * t1124 * t41 + t168 * t263 - 0.2e1 * t616 * t827 + t81 * t981;
-	t1134 = t394 * t28;
-	t1159 = -0.8e1 * t1134 * t29 * t18 * t57 + t82 * t118 - 0.12e2 * t215 * t1018 + 0.2e1 * t602 * t801 - t168 * t341 + 0.2e1 * t67 * t58 * t64 + t168 * t344 - 0.6e1 * t174 * t368 * t208 + 0.16e2 * t553 * t903 + t116 * t790 - 0.4e1 * t36 * t38 * t800 * t15;
-	t1161 = n * t83;
-	t1173 = self->ZB * t12;
-	t1196 = 0.4e1 * t1161 * self->ZB * t39 * self->ZA - 0.4e1 * t215 * t1029 - 0.8e1 * t488 * 0.3141592654e1 * t39 * self->xc + 0.32e2 * t821 * self->ZA * t8 * t1173 * t18 - 0.8e1 * t427 * t147 + 0.6e1 * t701 * t165 - 0.16e2 * t926 * t927 * t1124 * t18 - 0.8e1 * t1091 * t63 * t57 - 0.8e1 * t442 * t209 - 0.8e1 * t462 * t660 - 0.6e1 * t398 * t35 * t52;
-	t1228 = 0.2e1 * t413 * t305 - 0.8e1 * t648 * t961 - 0.16e2 * t87 * t27 * t23 * t28 * self->ZA * t29 + 0.4e1 * t189 * t1102 - 0.4e1 * t87 * t1079 * t212 * t879 + 0.2e1 * t164 * t948 - 0.2e1 * t70 * t923 + 0.2e1 * t164 * t322 + 0.2e1 * t446 * t1121 + 0.2e1 * t863 * t964 * t304 - t82 * t1108 + 0.16e2 * t676 * t490 * t19;
-	t1234 = t25 * self->ZB;
-	t1235 = t1234 * t28;
-	t1236 = t365 * t91;
-	t1240 = self->ZB * t121;
-	t1241 = t1240 * t77;
-	t1242 = t39 * t39;
-	t1243 = t12 * t1242;
-	t1244 = self->xc * t72;
-	t1245 = t1243 * t1244;
-	t1248 = t365 * t25;
-	t1252 = t243 * n;
-	t1257 = t23 * t1;
-	t1258 = t1240 * t1257;
-	t1259 = t67 * t12;
-	t1260 = self->xc * t16;
-	t1268 = t1234 * t121;
-	t1269 = t1268 * t23;
-	t1272 = t1242 * t91;
-	t1280 = t67 * self->xc;
-	t1284 = t28 * t28;
-	t1285 = t67 * t1284;
-	t1287 = t1285 * t2 * self->ZB;
-	t1288 = t17 * self->xc;
-	t1289 = t1243 * t1288;
-	t1292 = 0.2e1 * t1235 * t1236 * t17 + 0.8e1 * t1241 * t1245 + 0.4e1 * t927 * t1248 * t91 - 0.2e1 * t1252 * self->ZB * t1242 * t91 - 0.8e1 * t1258 * t1259 * t1260 - 0.4e1 * t1235 * t2 * t83 * t39 + 0.16e2 * t1269 * t758 + 0.2e1 * t1252 * t189 * t1272 - 0.2e1 * t1252 * t83 * t1242 * self->ZB + 0.8e1 * t1258 * t630 * t1280 - 0.32e2 * t1287 * t1289;
-	t1293 = t365 * t83;
-	t1300 = self->ZA * t1284;
-	t1304 = t17 * t1242 * t25 * t12;
-	t1307 = t927 * t2;
-	t1311 = t23 * t2;
-	t1312 = t1300 * t1311;
-	t1316 = t1234 * t1284;
-	t1317 = t1316 * t1311;
-	t1321 = t1240 * t23;
-	t1331 = t1240 * t23 * t67;
-	t1332 = t40 * t1244;
-	t1338 = t1243 * t1260;
-	t1344 = -0.2e1 * t1235 * t1293 - 0.16e2 * t181 * t365 * t901 * t12 - 0.64e2 * t1300 * t258 * t1304 + 0.8e1 * t1307 * t613 * t39 + 0.64e2 * t1312 * t265 * t402 - 0.32e2 * t1317 * t1288 * t12 - 0.16e2 * t1321 * t67 * t39 * t1244 + 0.2e1 * t1235 * n * t1272 * t17 + 0.16e2 * t1331 * t1332 + 0.64e2 * t1300 * t292 * t1304 - 0.8e1 * t1241 * t1338 - 0.2e1 * t243 * t1293 * self->ZB;
-	t1346 = t1316 * t2;
-	t1349 = t927 * n;
-	t1350 = t25 * t1242;
-	t1354 = t1268 * t1257;
-	t1366 = t1268 * t1;
-	t1370 = t29 * t17;
-	t1371 = t1243 * t1370;
-	t1386 = -0.32e2 * t1346 * t1289 + 0.4e1 * t1349 * t1350 * t91 + 0.8e1 * t1354 * t1260 * t12 - 0.16e2 * t181 * n * t901 * t1243 - 0.4e1 * t1235 * t2 * t91 * t39 + 0.8e1 * t1366 * t152 * t1242 + 0.32e2 * t1287 * t1371 + 0.8e1 * t1258 * t1280 * t152 - 0.8e1 * t1354 * t1260 * t91 + 0.128e3 * t1300 * t365 * self->xc * t1092 + 0.8e1 * t1366 * t1338;
-	t1387 = t1257 * t12;
-	t1391 = t1240 * t1;
-	t1399 = t1272 * t1260;
-	t1412 = t1285 * t1311;
-	t1427 = -0.8e1 * t1268 * t1387 * t16 - 0.8e1 * t1391 * t67 * t1242 * t1244 - 0.4e1 * t1134 * t1101 * t39 + 0.8e1 * t1241 * t1399 - 0.8e1 * t1258 * t596 + 0.4e1 * t927 * t1293 * t25 - 0.16e2 * t1331 * t758 + 0.8e1 * t1307 * t665 * t39 + 0.32e2 * t1412 * t1370 * t1173 + 0.8e1 * t1307 * t665 * t800 + 0.8e1 * t1391 * t1259 * t1242 * t16 - 0.8e1 * t1391 * t1259 * t1242 * t72;
-	t1456 = t365 * self->ZB;
-	t1468 = 0.4e1 * t927 * t1248 * t17 - 0.2e1 * t1235 * n * t1242 * t91 + 0.8e1 * t1366 * t1244 * t1242 - 0.16e2 * t1269 * t134 * t39 + 0.8e1 * t1268 * t1257 * t72 * self->xc + 0.16e2 * t1321 * t1259 * t757 + 0.32e2 * t1317 * t1370 * t12 + 0.4e1 * t1349 * t613 * t1242 + 0.2e1 * t243 * t1456 * t17 - 0.64e2 * t1285 * t365 * t12 * t189 * t490 - 0.8e1 * t1354 * t152 * self->xc;
-	t1472 = t1316 * t365;
-	t1474 = t1124 * t39 * t17;
-	t1478 = t17 * t91;
-	t1504 = t72 * t39;
-	t1511 = 0.4e1 * t1134 * t189 * t800 + 0.64e2 * t1472 * t1474 + 0.4e1 * t1235 * t2 * t1478 * t39 + 0.4e1 * t1349 * t665 * t1242 - 0.8e1 * t1258 * t1280 * t72 + 0.2e1 * t1252 * t189 * t1242 + 0.2e1 * t243 * t365 * t189 * t91 + 0.4e1 * t927 * t365 * t1478 * t25 - 0.128e3 * t1300 * t1248 * t1474 - 0.2e1 * t1235 * t1236 + 0.16e2 * t1269 * t1504 * self->xc + 0.2e1 * t1235 * t365 * t17;
-	t1545 = -0.2e1 * t1235 * t1161 * t1242 + 0.4e1 * t1349 * t1350 * t1478 - 0.8e1 * t1366 * t1245 + 0.2e1 * t1235 * t556 * t1242 - 0.32e2 * t1412 * t402 * t726 - 0.8e1 * t1366 * t1399 + 0.8e1 * t1258 * t651 - 0.2e1 * t243 * t1456 * t91 + 0.8e1 * t1268 * t1387 * t72 - 0.16e2 * t1269 * t1332 + 0.4e1 * t1134 * t189 * t39 + 0.16e2 * t1269 * t152 * t39;
-	t1564 = t1260 * t800;
-	t1583 = 0.64e2 * t1285 * t1456 * t1474 - 0.64e2 * t1472 * t1288 * t40 - 0.8e1 * t1366 * t134 * t1242 + 0.8e1 * t1307 * t362 * t39 + 0.4e1 * t1235 * t2 * t17 * t39 + 0.32e2 * t1346 * t1371 - 0.16e2 * t1269 * t1564 - 0.16e2 * t1321 * t1259 * t1504 + 0.16e2 * t1331 * t1564 - 0.64e2 * t1312 * t29 * t25 * t402 - 0.4e1 * t1134 * t83 * t39 * self->ZB - 0.32e2 * t181 * t2 * t404;
-
-	self->C2B = (t1133 + t1196 + t1068 + t811 + t466 + t1012 + t381 + t162 + t249 + t533 + t844 + t104 + t1159 + t571 + t211 + t874 + t607 + t339 + t296 + t638 + t908 + t671 + t419 + t983 + t705 + t1105 + t501 + t778 + t1040 + t1228 + t741 + t944) / (t1292 + t1344 + t1386 + t1427 + t1468 + t1511 + t1545 + t1583);
-	/****************************************************************************************/
-	t1 = n * n;
-	t2 = t1 * n;
-	t3 = t2 * nx;
-	t4 = nx * 0.3141592654e1;
-	t5 = t4 * self->xc;
-	t6 = sin(t5);
-	t7 = 0.3141592654e1 * 0.3141592654e1;
-	t9 = t3 * t6 * t7;
-	t10 = self->xc * self->xc;
-	t11 = self->ZA * self->ZA;
-	t12 = t10 * t11;
-	t13 = n * 0.3141592654e1;
-	t14 = exp(t13);
-	t15 = t14 * t14;
-	t16 = self->xc * n;
-	t18 = exp(t16 * 0.3141592654e1);
-	t19 = t18 * t18;
-	t20 = t19 * t18;
-	t21 = t15 * t20;
-	t22 = t12 * t21;
-	t25 = nx * t6;
-	t26 = t1 * 0.3141592654e1;
-	t27 = t25 * t26;
-	t28 = self->ZA * self->ZB;
-	t29 = t18 * t15;
-	t30 = t28 * t29;
-	t33 = t25 * n;
-	t34 = t11 * t15;
-	t35 = t19 * t19;
-	t36 = t35 * t18;
-	t40 = t25 * t1;
-	t41 = 0.3141592654e1 * t11;
-	t42 = t15 * t36;
-	t43 = t41 * t42;
-	t46 = nx * nx;
-	t47 = t1 * t46;
-	t48 = t47 * t11;
-	t49 = t7 * self->xc;
-	t50 = t35 * t15;
-	t51 = t49 * t50;
-	t55 = sin(t4);
-	t56 = t46 * nx * t55;
-	t58 = t56 * n * t7;
-	t59 = self->ZB * self->ZB;
-	t60 = t10 * t59;
-	t61 = t15 * t14;
-	t62 = t19 * t61;
-	t63 = t60 * t62;
-	t66 = t19 * t14;
-	t67 = t60 * t66;
-	t70 = t28 * t42;
-	t73 = cos(t5);
-	t74 = t47 * t73;
-	t75 = t7 * t11;
-	t77 = t75 * t10 * t36;
-	t80 = t73 * t46;
-	t81 = t80 * n;
-	t82 = 0.3141592654e1 * t59;
-	t83 = t82 * t42;
-	t87 = self->xc * t11;
-	t88 = t87 * t62;
-	t91 = n * nx;
-	t92 = t55 * t61;
-	t96 = nx * t55;
-	t98 = t96 * t2 * t7;
-	t101 = self->xc * t59;
-	t102 = t101 * t62;
-	t108 = t1 * t1;
-	t109 = t108 * t7;
-	t111 = t59 * t35;
-	t112 = t111 * t15;
-	t115 = t35 * t20;
-	t123 = t1 * nx * t55;
-	t124 = t61 * t35;
-	t127 = t35 * t19;
-	t128 = t61 * t127;
-	t129 = t60 * t128;
-	t132 = t56 * t16;
-	t133 = t7 * t59;
-	t134 = t133 * t124;
-	t137 = 0.6e1 * t58 * t88 - 0.2e1 * t91 * t92 * t11 + 0.2e1 * t98 * t63 - 0.6e1 * t58 * t102 - 0.2e1 * t91 * t92 * t59 - 0.16e2 * t109 * self->xc * t112 - 0.2e1 * t91 * t6 * t115 * t59 + 0.12e2 * t40 * t83 + t123 * t41 * t124 - 0.2e1 * t58 * t129 + 0.4e1 * t132 * t134;
-	t139 = t56 * 0.3141592654e1;
-	t140 = t111 * t14;
-	t144 = t49 * t124;
-	t147 = t91 * t55;
-	t148 = t61 * self->ZA;
-	t154 = self->ZA * t115 * self->xc * self->ZB;
-	t157 = t7 * 0.3141592654e1;
-	t159 = t96 * t108 * t157;
-	t160 = t10 * self->xc;
-	t161 = t160 * t59;
-	t162 = t35 * t14;
-	t163 = t161 * t162;
-	t166 = t28 * t162;
-	t169 = t80 * t13;
-	t170 = t101 * t42;
-	t173 = t2 * t11;
-	t174 = t96 * t173;
-	t175 = t7 * t10;
-	t179 = t59 * t15;
-	t184 = t15 * t15;
-	t193 = t139 * t140 + 0.4e1 * t56 * n * t11 * t144 + 0.4e1 * t147 * t148 * self->ZB + 0.4e1 * t27 * t154 + 0.8e1 * t159 * t163 - 0.12e2 * t147 * t166 + 0.2e1 * t169 * t170 - 0.16e2 * t174 * t175 * t124 + 0.2e1 * t33 * t179 * t20 - 0.2e1 * t33 * t11 * t36 * t184 + 0.2e1 * t56 * t61 * 0.3141592654e1 * self->ZA * self->ZB;
-	t194 = t173 * 0.3141592654e1;
-	t195 = self->xc * t15;
-	t196 = t195 * t19;
-	t202 = t15 * t115;
-	t203 = t28 * t202;
-	t206 = t96 * t26;
-	t207 = t14 * t127;
-	t208 = t101 * t207;
-	t211 = t12 * t128;
-	t218 = t11 * t61;
-	t219 = t218 * t35;
-	t221 = t108 * self->ZA;
-	t223 = t7 * self->ZB;
-	t224 = t223 * t50;
-	t227 = self->ZA * self->xc;
-	t228 = self->ZB * t15;
-	t229 = t228 * t36;
-	t230 = t227 * t229;
-	t233 = t87 * t207;
-	t236 = t6 * t11;
-	t240 = -0.4e1 * t194 * t196 + 0.4e1 * t194 * t195 * t127 + 0.4e1 * t33 * t203 - 0.12e2 * t206 * t208 + 0.2e1 * t58 * t211 - 0.16e2 * t47 * t10 * t133 * t50 + t139 * t219 - 0.32e2 * t221 * t10 * t224 - 0.4e1 * t169 * t230 - 0.6e1 * t98 * t233 + 0.2e1 * t91 * t236 * t20;
-	t244 = t227 * t228 * t20;
-	t252 = t184 * t18;
-	t253 = t101 * t252;
-	t256 = t35 * t35;
-	t257 = t256 * t14;
-	t258 = t28 * t257;
-	t261 = t108 * t11;
-	t263 = t7 * t35;
-	t268 = self->ZB * t61 * t35;
-	t273 = t96 * t108 * t160;
-	t274 = t157 * self->ZB;
-	t276 = t274 * t148 * t35;
-	t279 = t101 * t21;
-	t282 = 0.3141592654e1 * self->xc;
-	t283 = t59 * t36;
-	t284 = t282 * t283;
-	t289 = 0.4e1 * t169 * t244 - 0.4e1 * t132 * t133 * t162 - 0.2e1 * t147 * t140 - 0.2e1 * t27 * t253 + 0.2e1 * t139 * t258 + 0.16e2 * t261 * t10 * t263 * t15 - 0.16e2 * t206 * t227 * t268 - 0.16e2 * t273 * t276 - 0.6e1 * t27 * t279 - 0.4e1 * t40 * t284 - 0.32e2 * t9 * t230;
-	t290 = t1 * t11;
-	t291 = t96 * t290;
-	t297 = t59 * t61;
-	t298 = t297 * t127;
-	t300 = self->ZB * t36;
-	t301 = t227 * t300;
-	t304 = t1 * t59;
-	t305 = t184 * t35;
-	t310 = t46 * self->ZB;
-	t311 = t184 * self->ZA;
-	t312 = t310 * t311;
-	t314 = t60 * t21;
-	t317 = t1 * self->ZA;
-	t318 = self->ZB * t35;
-	t321 = t1 * t256;
-	t324 = t96 * t261;
-	t325 = t10 * t157;
-	t326 = t325 * t124;
-	t329 = -0.4e1 * t291 * t282 * t128 + t123 * t82 * t62 - t139 * t298 + 0.12e2 * t27 * t301 + t304 * t305 - 0.2e1 * t58 * t12 * t66 - 0.2e1 * t312 + 0.8e1 * t9 * t314 + 0.2e1 * t317 * t318 + 0.2e1 * t321 * t28 - 0.8e1 * t324 * t326;
-	t331 = t28 * t124;
-	t334 = 0.3141592654e1 * t15;
-	t335 = t334 * t127;
-	t338 = t35 * self->ZA;
-	t341 = t46 * t256;
-	t344 = t46 * t11;
-	t346 = t46 * t59;
-	t348 = t297 * t35;
-	t351 = self->ZA * t10;
-	t352 = t351 * t300;
-	t355 = t1 * self->ZB;
-	t362 = 0.12e2 * t147 * t331 - 0.4e1 * t173 * t335 - 0.2e1 * t310 * t338 - 0.2e1 * t341 * t28 - t344 * t305 - t346 * t305 + 0.2e1 * t147 * t348 + 0.16e2 * t9 * t352 + 0.2e1 * t355 * t311 + t290 * t305 + 0.2e1 * t33 * t34 * t20;
-	t363 = t36 * t184;
-	t364 = t87 * t363;
-	t368 = t47 * t73 * t7;
-	t373 = t160 * t157;
-	t374 = t373 * t124;
-	t377 = t311 * t35;
-	t380 = t12 * t62;
-	t386 = self->ZB * t10 * self->ZA * t15 * t20;
-	t389 = t87 * t66;
-	t393 = t56 * t1 * t10;
-	t401 = 0.2e1 * t27 * t364 - 0.16e2 * t368 * t279 - t123 * t41 * t257 + 0.8e1 * t324 * t374 + 0.2e1 * t355 * t377 - 0.2e1 * t98 * t380 - 0.16e2 * t9 * t386 + 0.2e1 * t58 * t389 + 0.16e2 * t393 * t276 + t123 * t82 * t162 - 0.2e1 * t33 * t179 * t36;
-	t412 = t11 * t14 * t127;
-	t416 = t11 * t19;
-	t417 = t416 * t61;
-	t421 = t96 * t2 * self->ZA;
-	t426 = t56 * n * self->ZA;
-	t427 = t318 * t14;
-	t428 = t49 * t427;
-	t431 = t82 * t29;
-	t434 = t87 * t21;
-	t442 = 0.2e1 * t33 * t11 * t184 * t18 + 0.4e1 * t81 * t284 - t139 * t412 + 0.2e1 * t147 * t219 - 0.2e1 * t147 * t417 + 0.32e2 * t421 * t175 * t268 + 0.8e1 * t426 * t428 + 0.4e1 * t81 * t431 - 0.2e1 * t169 * t434 - 0.2e1 * t98 * t129 - 0.32e2 * t47 * t28 * t51;
-	t443 = t184 * t20;
-	t447 = t61 * 0.3141592654e1;
-	t448 = t447 * t11;
-	t450 = t49 * t268;
-	t453 = t60 * t42;
-	t456 = t41 * t202;
-	t463 = t101 * t443;
-	t469 = t41 * self->xc * t20;
-	t474 = -0.8e1 * t27 * t87 * t443 - t56 * t448 - 0.8e1 * t426 * t450 + 0.8e1 * t368 * t453 + 0.4e1 * t40 * t456 + 0.4e1 * t40 * t431 - 0.4e1 * t81 * t456 - 0.4e1 * t27 * t463 + 0.6e1 * t139 * t331 + 0.2e1 * t40 * t469 - 0.16e2 * t9 * t434;
-	t482 = t108 * t10;
-	t492 = n * t46;
-	t493 = t492 * t11;
-	t495 = t282 * t19 * t184;
-	t498 = t56 * t290;
-	t499 = t325 * t162;
-	t502 = t416 * t14;
-	t504 = t60 * t207;
-	t507 = -t123 * t82 * t257 - 0.4e1 * t169 * t301 + t123 * t41 * t162 + 0.16e2 * t482 * t7 * t112 - 0.12e2 * t206 * t102 - t123 * t82 * t66 - 0.4e1 * t147 * t258 - 0.4e1 * t493 * t495 - 0.8e1 * t498 * t499 + t139 * t502 - 0.2e1 * t98 * t504;
-	t508 = t101 * t162;
-	t512 = t41 * t115 * self->xc;
-	t515 = t87 * t42;
-	t520 = self->ZB * t184;
-	t522 = t227 * t520 * t18;
-	t525 = t492 * t59;
-	t528 = t6 * t59;
-	t532 = t520 * t20;
-	t533 = t351 * t532;
-	t539 = t447 * t59;
-	t544 = 0.8e1 * t206 * t508 - 0.2e1 * t40 * t512 - 0.16e2 * t368 * t515 + 0.12e2 * t206 * t88 + 0.4e1 * t27 * t522 + 0.4e1 * t525 * t495 - 0.4e1 * t91 * t528 * t36 - 0.16e2 * t368 * t533 - 0.16e2 * t206 * t227 * t427 - t56 * t539 - 0.2e1 * t132 * t133 * t66;
-	t551 = t87 * t162;
-	t554 = t351 * t229;
-	t560 = t59 * t19;
-	t561 = t560 * t14;
-	t564 = t101 * t202;
-	t567 = t87 * t252;
-	t573 = t227 * t228 * t115;
-	t578 = 0.4e1 * t33 * t70 + 0.4e1 * t493 * t335 - 0.4e1 * t58 * t551 + 0.16e2 * t9 * t554 - 0.4e1 * t33 * t28 * t252 + 0.2e1 * t147 * t561 + 0.2e1 * t169 * t564 - 0.2e1 * t27 * t567 - 0.8e1 * t324 * t499 - 0.4e1 * t169 * t573 + 0.12e2 * t27 * t244;
-	t579 = t82 * t202;
-	t591 = t282 * t115 * t59;
-	t598 = t101 * t66;
-	t606 = -0.4e1 * t81 * t579 - 0.2e1 * t169 * t567 - 0.6e1 * t27 * t170 + 0.8e1 * t169 * t203 + 0.2e1 * t98 * t67 + 0.2e1 * t81 * t591 + 0.32e2 * t368 * t244 - 0.2e1 * t27 * t564 + 0.4e1 * t206 * t598 + 0.16e2 * t9 * t170 + 0.2e1 * t33 * t283 * t184;
-	t608 = t373 * t162;
-	t611 = t59 * t184;
-	t617 = t101 * t29;
-	t624 = t227 * self->ZB * t18 * t15;
-	t629 = t157 * t59;
-	t630 = t629 * t124;
-	t633 = t3 * t6;
-	t634 = t175 * t283;
-	t644 = 0.8e1 * t498 * t608 + 0.2e1 * t33 * t611 * t18 - 0.4e1 * t206 * t389 - 0.2e1 * t27 * t617 - 0.4e1 * t169 * t154 + 0.4e1 * t27 * t624 + 0.12e2 * t27 * t230 - 0.8e1 * t393 * t630 - 0.8e1 * t633 * t634 + 0.16e2 * t47 * t7 * t101 * t50 + 0.2e1 * t123 * t447 * t28;
-	t645 = t41 * t29;
-	t648 = t2 * 0.3141592654e1;
-	t649 = t648 * self->xc;
-	t650 = t560 * t184;
-	t656 = t56 * t1 * t157;
-	t659 = t87 * t128;
-	t662 = t96 * t482;
-	t663 = t629 * t162;
-	t671 = t161 * t124;
-	t674 = t218 * t127;
-	t679 = 0.4e1 * t81 * t645 - 0.4e1 * t649 * t650 - 0.8e1 * t169 * t70 + 0.8e1 * t656 * t163 - 0.2e1 * t98 * t659 - 0.8e1 * t662 * t663 - 0.32e2 * t421 * t175 * t427 - 0.2e1 * t147 * t502 + 0.8e1 * t656 * t671 + 0.2e1 * t147 * t674 - 0.16e2 * t368 * t386;
-	t714 = t334 * t19;
-	t719 = t12 * t42;
-	t722 = t304 * t35 - t346 * t35 + t341 * t59 - t344 * t35 + t344 * t256 + t346 * t184 - 0.16e2 * t368 * t554 - 0.16e2 * t48 * t175 * t50 + 0.4e1 * t525 * t714 - 0.2e1 * t58 * t659 + 0.8e1 * t368 * t719;
-	t730 = self->xc * t19;
-	t735 = t59 * t256 * t14;
-	t752 = 0.4e1 * t173 * t714 - 0.6e1 * t27 * t515 - 0.16e2 * t9 * t279 + 0.4e1 * t194 * t730 * t184 - t139 * t735 - 0.4e1 * t492 * t127 * t82 * self->xc - 0.4e1 * t98 * t508 - t123 * t41 * t207 - 0.2e1 * t147 * t298 + 0.8e1 * t368 * t314 + 0.6e1 * t132 * t133 * t207;
-	t755 = t28 * t21;
-	t759 = t274 * t338 * t14;
-	t767 = t11 * t35;
-	t768 = t767 * t14;
-	t778 = t560 * t61;
-	t781 = -0.2e1 * t58 * t504 - 0.8e1 * t27 * t755 + 0.16e2 * t662 * t759 + 0.12e2 * t291 * t282 * t207 - 0.6e1 * t27 * t434 + t139 * t768 - 0.8e1 * t498 * t326 + 0.4e1 * t33 * t611 * t20 + 0.2e1 * t81 * t512 - t139 * t561 + 0.2e1 * t147 * t778;
-	t786 = t12 * t443;
-	t790 = t282 * t59 * t20;
-	t796 = t59 * t14 * t127;
-	t806 = t41 * t21;
-	t811 = -0.8e1 * t393 * t663 + 0.8e1 * t368 * t786 + 0.2e1 * t81 * t790 + 0.4e1 * t169 * t624 + t139 * t796 + 0.2e1 * t206 * t258 - 0.2e1 * t40 * t591 - 0.8e1 * t662 * t630 - 0.4e1 * t33 * t30 - 0.4e1 * t40 * t806 + 0.8e1 * t9 * t786;
-	t819 = t282 * t15 * t127;
-	t822 = t101 * t363;
-	t830 = t11 * t256 * t14;
-	t835 = t227 * t532;
-	t842 = 0.2e1 * t33 * t11 * t18 * t15 + t123 * t41 * t66 - 0.4e1 * t493 * t819 - 0.2e1 * t27 * t822 - 0.16e2 * t368 * t170 - 0.4e1 * t169 * t463 - t139 * t830 - 0.4e1 * t649 * t179 * t127 + 0.12e2 * t27 * t835 - 0.16e2 * t368 * t434 - 0.2e1 * t40 * t790;
-	t845 = t87 * t202;
-	t854 = t338 * t15;
-	t859 = t12 * t207;
-	t868 = t139 * t348 - 0.2e1 * t27 * t845 + 0.8e1 * t169 * t755 - 0.2e1 * t58 * t380 + 0.6e1 * t206 * t331 + 0.8e1 * t310 * t854 - 0.2e1 * t169 * t822 + 0.2e1 * t98 * t859 + 0.8e1 * t159 * t671 + 0.8e1 * t74 * t634 - 0.2e1 * t169 * t253;
-	t880 = t60 * t443;
-	t891 = t101 * t128;
-	t894 = -t123 * t539 - 0.2e1 * t147 * t796 + 0.32e2 * t368 * t230 + t139 * t674 - 0.16e2 * t98 * t60 * t124 + 0.32e2 * t9 * t244 + 0.8e1 * t368 * t880 - 0.8e1 * t40 * t41 * self->xc * t36 - t123 * t82 * t128 - 0.6e1 * t58 * t233 + 0.2e1 * t58 * t891;
-	t903 = t179 * t19;
-	t920 = t56 * t1 * t160;
-	t925 = -0.2e1 * t174 * t175 * t66 - 0.4e1 * t493 * t714 + 0.4e1 * t649 * t903 - 0.4e1 * t81 * t43 + t123 * t82 * t207 + 0.4e1 * t206 * t891 - 0.16e2 * t273 * t759 - 0.8e1 * t27 * t203 + 0.32e2 * t221 * self->ZB * t51 - 0.16e2 * t920 * t759 - 0.8e1 * t9 * t453;
-	t932 = t87 * t29;
-	t945 = t82 * t21;
-	t953 = -0.16e2 * t920 * t276 - 0.8e1 * t169 * t30 - 0.8e1 * t633 * t77 - 0.2e1 * t27 * t932 - 0.4e1 * t174 * t49 * t162 + 0.8e1 * t206 * t87 * t124 - 0.2e1 * t147 * t768 + 0.4e1 * t169 * t522 - 0.12e2 * t81 * t945 + 0.4e1 * t33 * t28 * t115 + 0.4e1 * t525 * t819;
-	t971 = t282 * t127;
-	t978 = -0.6e1 * t98 * t102 + 0.2e1 * t169 * t515 - 0.2e1 * t310 * t377 + 0.2e1 * t147 * t830 + 0.8e1 * t368 * t22 - 0.2e1 * t169 * t617 + 0.16e2 * t662 * t276 - 0.8e1 * t355 * t854 + 0.4e1 * t493 * t971 - 0.16e2 * t9 * t533 - 0.2e1 * t169 * t279;
-	t997 = self->xc * t127;
-	t998 = t997 * t59;
-	t1003 = 0.4e1 * t40 * t579 + 0.2e1 * t169 * t845 + 0.16e2 * t9 * t515 + 0.8e1 * t206 * t551 + t123 * t41 * t128 + 0.16e2 * t98 * t60 * t162 + 0.2e1 * t169 * t364 - 0.2e1 * t169 * t932 + t139 * t778 + 0.4e1 * t648 * t998 + 0.2e1 * t147 * t412;
-	t1006 = t2 * t59;
-	t1017 = self->xc * t35;
-	t1033 = 0.4e1 * t1006 * t335 + 0.4e1 * t81 * t806 - 0.2e1 * t33 * t34 * t115 + 0.8e1 * t498 * t374 - 0.16e2 * t261 * t7 * t1017 * t15 + 0.8e1 * t206 * t101 * t124 - t123 * t448 + 0.2e1 * t147 * t735 + 0.6e1 * t98 * t208 + 0.6e1 * t98 * t88 - 0.4e1 * t33 * t755;
-	t1055 = -0.4e1 * t173 * t971 + 0.2e1 * t98 * t891 + 0.8e1 * t9 * t880 + 0.4e1 * t169 * t835 - t304 * t184 + t344 * t184 - t123 * t41 * t62 - 0.2e1 * t98 * t598 + 0.2e1 * t58 * t859 + 0.32e2 * t47 * t351 * t224 + 0.2e1 * t98 * t389;
-	t1070 = t15 * t19;
-	t1089 = -0.16e2 * t368 * t352 - 0.8e1 * t9 * t719 + 0.4e1 * t96 * t2 * self->xc * t134 - 0.2e1 * t91 * t236 * t115 + 0.4e1 * t27 * t573 + 0.4e1 * t493 * t282 * t1070 + 0.2e1 * t33 * t59 * t18 * t15 + 0.12e2 * t40 * t945 - 0.4e1 * t492 * self->xc * t82 * t1070 - 0.2e1 * t91 * t528 * t20 + 0.8e1 * t324 * t608;
-	t1113 = t123 * t82 * t124 + 0.8e1 * t421 * t428 - t139 * t417 + 0.4e1 * t40 * t645 + 0.16e2 * t393 * t759 - 0.2e1 * t33 * t179 * t115 - 0.4e1 * t525 * t335 + 0.4e1 * t33 * t28 * t36 - 0.4e1 * t1006 * t714 + 0.6e1 * t206 * t166 - 0.8e1 * t421 * t450;
-	t1119 = t321 * t46;
-	t1122 = t157 * t11;
-	t1123 = t1122 * t2;
-	t1124 = t184 * t46;
-	t1128 = t108 * n;
-	t1132 = t7 * t7;
-	t1133 = t1132 * t11;
-	t1134 = t1133 * t108;
-	t1135 = t15 * t46;
-	t1139 = t7 * self->ZA;
-	t1140 = t1139 * self->ZB;
-	t1141 = t1 * t35;
-	t1145 = t629 * t2;
-	t1146 = t1135 * t730;
-	t1149 = t157 * t1128;
-	t1150 = t1149 * self->xc;
-	t1153 = t46 * self->xc;
-	t1154 = t1153 * t127;
-	t1158 = t184 * t1 * t46;
-	t1161 = t46 * t46;
-	t1162 = t35 * t1161;
-	t1166 = t7 * t1;
-	t1170 = -0.4e1 * t133 * t1119 + 0.16e2 * t1123 * t1124 * t730 - 0.8e1 * t1122 * t1128 * t196 - 0.64e2 * t1134 * t1135 * t1017 - 0.32e2 * t1140 * t1141 * t1135 + 0.16e2 * t1145 * t1146 - 0.8e1 * t1150 * t650 - 0.16e2 * t1123 * t1154 - 0.4e1 * t133 * t1158 - 0.16e2 * t1140 * t1162 * t15 + 0.8e1 * t1166 * t35 * t312;
-	t1171 = t1161 * t184;
-	t1175 = t1122 * n;
-	t1176 = t15 * t1161;
-	t1180 = t1132 * self->ZA;
-	t1181 = t1180 * t355;
-	t1182 = t1176 * t1017;
-	t1185 = t1161 * self->xc;
-	t1189 = t1133 * t1;
-	t1192 = t108 * t1;
-	t1193 = t1132 * t1192;
-	t1195 = t10 * t35;
-	t1199 = t157 * t15;
-	t1203 = t1141 * t46;
-	t1211 = t184 * t108;
-	t1218 = 0.2e1 * t133 * t1171 * t35 + 0.8e1 * t1175 * t1176 * t997 + 0.64e2 * t1181 * t1182 - 0.8e1 * t1175 * t1185 * t127 - 0.32e2 * t1189 * t1182 - 0.64e2 * t1193 * self->ZA * t1195 * t228 + 0.8e1 * t1199 * t416 * t1128 + 0.8e1 * t1140 * t1203 - 0.4e1 * t75 * t1158 - 0.8e1 * t1199 * t560 * t1128 - 0.2e1 * t133 * t1211 - 0.8e1 * t1199 * t127 * t11 * t1128;
-	t1221 = t256 * t1161;
-	t1224 = t35 * t108;
-	t1233 = t7 * t256;
-	t1236 = -t75 * t1211 - t75 * t1221 - t133 * t1221 + t75 * t1224 - t75 * t1171 - t133 * t1171 + t133 * t1224 + t75 * t1162 - t75 * t108 * t256 + t133 * t1162 - t1233 * t59 * t108;
-	t1240 = t1135 * t1195;
-	t1252 = t629 * t127;
-	t1263 = t1171 * self->ZA;
-	t1280 = -0.128e3 * t1180 * self->ZB * t108 * t1240 + 0.32e2 * t1193 * t10 * t112 + 0.4e1 * t133 * t1203 + 0.4e1 * t109 * t256 * self->ZA * self->ZB - 0.8e1 * t1252 * n * t15 * t1185 + 0.8e1 * t1175 * t1171 * t730 - 0.8e1 * t1175 * t1176 * t127 + 0.4e1 * t223 * t1263 - 0.8e1 * t1175 * t1176 * t730 + 0.8e1 * t1166 * self->ZA * t341 * self->ZB + 0.64e2 * t1134 * t1240 + 0.8e1 * t1122 * self->xc * t1128 * t127 * t15;
-	t1283 = t1199 * t19;
-	t1287 = t1199 * t127;
-	t1289 = t59 * n * t1161;
-	t1293 = t157 * n * self->xc;
-	t1304 = t1132 * t108;
-	t1310 = t263 * self->ZB;
-	t1316 = t2 * t15;
-	t1323 = -0.16e2 * t1283 * t1006 * t46 + 0.8e1 * t1287 * t1289 + 0.8e1 * t1293 * t127 * t1161 * t59 + 0.16e2 * t1123 * t1135 * t19 + 0.8e1 * t1293 * t560 * t1176 + 0.64e2 * t1304 * t59 * t1240 + 0.4e1 * t75 * t1203 + 0.4e1 * t1310 * t1263 + 0.4e1 * t223 * t338 * t108 - 0.16e2 * t1252 * t1316 * t1153 - 0.16e2 * t1310 * t221 * t15;
-	t1330 = t1132 * t15;
-	t1336 = t1132 * t1;
-	t1338 = t1162 * t179;
-	t1370 = 0.8e1 * t1175 * t1176 * t19 + 0.4e1 * t1139 * t318 * t1161 + 0.128e3 * t1330 * t318 * t108 * t46 * t227 - 0.32e2 * t1336 * self->xc * t1338 + 0.4e1 * t1233 * self->ZA * t1161 * self->ZB - 0.8e1 * t1287 * t59 * t1128 * self->xc + 0.2e1 * t75 * t305 * t108 + 0.8e1 * t1199 * t127 * t59 * t1128 - 0.8e1 * t1283 * t1289 - 0.8e1 * t1293 * t560 * t1171 + 0.4e1 * t133 * t35 * t1158 + 0.8e1 * t157 * t184 * t19 * t11 * t1128 * self->xc;
-	t1376 = t7 * t184;
-	t1380 = t1176 * t1195;
-	t1393 = t1330 * t35;
-	t1411 = 0.16e2 * t1145 * t1154 + 0.8e1 * t1149 * t998 + 0.4e1 * t1376 * t35 * t48 + 0.32e2 * t1189 * t1380 + 0.32e2 * t1193 * t11 * t1195 * t15 - 0.64e2 * t1304 * self->xc * t111 * t1135 - 0.16e2 * t1123 * t1146 + 0.64e2 * t1393 * t28 * t1192 * self->xc - 0.16e2 * t1123 * t1135 * t127 - 0.8e1 * t1122 * self->xc * t1128 * t127 - 0.32e2 * t1193 * self->xc * t112 + 0.16e2 * t1252 * t1316 * t46;
-	t1450 = 0.2e1 * t1376 * t767 * t1161 + 0.2e1 * t1376 * t111 * t108 + 0.4e1 * t223 * t311 * t108 + 0.4e1 * t109 * t35 * t520 * self->ZA + 0.16e2 * t1123 * t1135 * t997 - 0.64e2 * t1181 * t1380 + 0.8e1 * t1150 * t903 - 0.32e2 * t1393 * t11 * t1192 * self->xc - 0.16e2 * t157 * t2 * self->xc * t560 * t1124 + 0.8e1 * t223 * t184 * t317 * t46 + 0.32e2 * t1336 * t10 * t1338 - 0.4e1 * t75 * t1119;
-	self->C3B = (t606 + t722 + t1089 + t781 + 0.16e2 * t48 * t51 + t978 + t868 + t507 - t304 * t256 + 0.8e1 * t9 * t22 + t752 + 0.4e1 * t174 * t144 - 0.2e1 * t81 * t469 + 0.6e1 * t139 * t166 + t362 + 0.2e1 * t98 * t211 + t925 + t137 - t290 * t184 + 0.12e2 * t81 * t83 + t842 + 0.8e1 * t74 * t77 + 0.16e2 * t98 * t12 * t162 - 0.4e1 * t33 * t28 * t443 - 0.8e1 * t27 * t70 - 0.2e1 * t33 * t34 * t36 - 0.8e1 * t27 * t30 + 0.2e1 * t58 * t67 - 0.4e1 * t40 * t43 + 0.2e1 * t58 * t63 + t1033 - t290 * t256 + t290 * t35 + t193 + t1113 + t578 + t442 + t474 + t544 + t329 + t679 + t401 + t953 + t811 + t644 + t894 + t289 + t240 + t1055 + t1003) / (t1170 + t1218 + 0.2e1 * t1236 + t1280 + t1323 + t1370 + t1411 + t1450);
-	/****************************************************************************************/
-	t1 = n * n;
-	t2 = t1 * self->xc;
-	t3 = self->ZB * self->ZB;
-	t5 = t2 * 0.3141592654e1 * t3;
-	t6 = nx * 0.3141592654e1;
-	t7 = t6 * self->xc;
-	t8 = cos(t7);
-	t9 = nx * nx;
-	t10 = t8 * t9;
-	t11 = n * 0.3141592654e1;
-	t12 = exp(t11);
-	t13 = t12 * t12;
-	t16 = exp( self->xc * n * 0.3141592654e1);
-	t17 = t16 * t16;
-	t18 = t17 * t16;
-	t19 = t17 * t17;
-	t20 = t19 * t18;
-	t21 = t13 * t20;
-	t22 = t10 * t21;
-	t25 = self->ZA * self->ZA;
-	t26 = t1 * t25;
-	t27 = self->xc * 0.3141592654e1;
-	t28 = t26 * t27;
-	t29 = t19 * t16;
-	t30 = t13 * t13;
-	t31 = t29 * t30;
-	t35 = t9 * nx;
-	t36 = t3 * t35;
-	t37 = sin(t6);
-	t38 = t13 * t12;
-	t39 = t37 * t38;
-	t40 = t39 * t19;
-	t42 = t1 * t1;
-	t43 = nx * t42;
-	t44 = self->xc * self->xc;
-	t45 = t25 * t44;
-	t46 = t43 * t45;
-	t47 = 0.3141592654e1 * 0.3141592654e1;
-	t48 = t47 * t37;
-	t49 = t17 * t38;
-	t54 = 0.3141592654e1 * t35;
-	t55 = self->ZA * n * t54;
-	t56 = t37 * self->ZB;
-	t57 = t19 * t12;
-	t61 = t25 * t8;
-	t62 = t61 * t9;
-	t63 = n * t30;
-	t64 = t63 * t16;
-	t67 = t1 * n;
-	t69 = t47 * self->ZB;
-	t70 = t67 * t44 * t69;
-	t75 = nx * t3;
-	t76 = t75 * t37;
-	t77 = t67 * 0.3141592654e1;
-	t78 = t19 * t19;
-	t79 = t78 * t12;
-	t80 = t77 * t79;
-	t82 = t3 * t38;
-	t84 = t54 * t37;
-	t87 = sin(t7);
-	t88 = t29 * t87;
-	t89 = t47 * t44;
-	t93 = nx * t25;
-	t94 = t87 * t42;
-	t95 = t93 * t94;
-	t96 = t47 * self->xc;
-	t97 = t13 * t29;
-	t98 = t96 * t97;
-	t101 = t87 * t67;
-	t102 = t93 * t101;
-	t103 = t13 * t18;
-	t107 = t47 * t35;
-	t108 = t26 * t107;
-	t109 = t37 * t44;
-	t110 = t19 * t17;
-	t111 = t12 * t110;
-	t116 = t37 * t19 * t12;
-	t118 = t37 * self->xc;
-	t119 = self->ZB * t19;
-	t120 = t119 * t12;
-	t121 = t118 * t120;
-	t125 = self->xc * t3;
-	t126 = t1 * t47 * t125;
-	t127 = t35 * t37;
-	t128 = t38 * t19;
-	t129 = t127 * t128;
-	t132 = t26 * 0.3141592654e1;
-	t133 = t16 * t13;
-	t134 = t10 * t133;
-	t137 = 0.3141592654e1 * self->ZB;
-	t138 = t2 * t137;
-	t139 = self->ZA * t8;
-	t140 = t9 * t13;
-	t145 = t30 * t18;
-	t146 = t10 * t145;
-	t149 = t3 * t8;
-	t150 = t149 * t9;
-	t153 = 0.2e1 * t5 * t22 + 0.2e1 * t28 * t10 * t31 + t36 * t40 - 0.2e1 * t46 * t48 * t49 - 0.2e1 * t55 * t56 * t57 - 0.2e1 * t62 * t64 + 0.16e2 * t70 * t29 * self->ZA * t10 - t76 * t80 + t82 * n * t84 + 0.8e1 * t43 * t3 * t88 * t89 + 0.16e2 * t95 * t98 + 0.2e1 * t102 * t27 * t103 - 0.2e1 * t108 * t109 * t111 + t36 * t116 + 0.8e1 * t55 * t121 - 0.4e1 * t126 * t129 - 0.4e1 * t132 * t134 - 0.4e1 * t138 * t139 * t140 * t20 + 0.8e1 * t28 * t146 - 0.2e1 * t150 * t64;
-	t154 = t42 * n;
-	t155 = nx * t154;
-	t156 = t44 * self->xc;
-	t157 = t47 * 0.3141592654e1;
-	t158 = t156 * t157;
-	t159 = t155 * t158;
-	t162 = t56 * self->ZA * t19 * t12;
-	t165 = t77 * t49;
-	t167 = t1 * t3;
-	t168 = t167 * t89;
-	t169 = t127 * t49;
-	t172 = t37 * t67;
-	t173 = t75 * t172;
-	t174 = t38 * t110;
-	t175 = t27 * t174;
-	t179 = t47 * t25;
-	t181 = t10 * t97;
-	t184 = t27 * t31;
-	t187 = t67 * t47;
-	t188 = t44 * t3;
-	t189 = t187 * t188;
-	t192 = t25 * t35;
-	t193 = t37 * t17;
-	t194 = t193 * t12;
-	t196 = nx * self->ZA;
-	t197 = t196 * t172;
-	t198 = self->ZB * t38;
-	t199 = t198 * t19;
-	t204 = t1 * t12 * t110;
-	t207 = nx * self->ZB;
-	t209 = t1 * self->ZA;
-	t215 = t67 * t3;
-	t216 = t47 * t8;
-	t217 = t215 * t216;
-	t218 = t9 * self->xc;
-	t222 = nx * t67;
-	t223 = t222 * t27;
-	t224 = t3 * t87;
-	t228 = t167 * t107;
-	t232 = t26 * t96;
-	t235 = t207 * t94;
-	t236 = t47 * self->ZA;
-	t243 = self->xc * t13;
-	t244 = t243 * t29;
-	t248 = t25 * n;
-	t249 = t248 * 0.3141592654e1;
-	t253 = self->ZB * self->ZA;
-	t254 = t253 * t8;
-	t255 = t9 * n;
-	t256 = t30 * t16;
-	t260 = 0.2e1 * t207 * t37 * t209 * t128 + 0.2e1 * t5 * t134 - 0.16e2 * t217 * t218 * t97 - 0.2e1 * t223 * t224 * t31 - 0.2e1 * t228 * t109 * t174 - 0.2e1 * t232 * t169 - 0.16e2 * t235 * t236 * t44 * t30 * t18 - 0.4e1 * t196 * t101 * t137 * t244 + t249 * t169 + 0.8e1 * t168 * t129 + 0.4e1 * t254 * t255 * t256;
-	t263 = t43 * t179;
-	t267 = t3 * n;
-	t268 = t267 * t54;
-	t269 = t118 * t57;
-	t272 = t39 * t1;
-	t274 = t67 * t25;
-	t275 = t274 * t158;
-	t278 = t75 * t87;
-	t279 = t77 * t103;
-	t282 = t25 * t38;
-	t285 = self->ZA * t38;
-	t290 = t267 * 0.3141592654e1;
-	t296 = t77 * t111;
-	t298 = t196 * t37;
-	t299 = t1 * self->ZB;
-	t303 = t37 * t42;
-	t304 = t196 * t303;
-	t308 = t77 * t57;
-	t310 = t26 * t89;
-	t313 = t77 * t128;
-	t316 = t101 * t27;
-	t319 = t93 * t87;
-	t320 = t77 * t97;
-	t323 = t127 * t57;
-	t326 = t10 * n;
-	t329 = t118 * t174;
-	t332 = -0.8e1 * t263 * t109 * t57 - 0.4e1 * t268 * t269 + t93 * t272 + 0.8e1 * t275 * t129 - 0.4e1 * t278 * t279 + t282 * n * t84 - 0.2e1 * t285 * n * t54 * t56 - t290 * t169 - 0.2e1 * t196 * t38 * t172 * t137 + t76 * t296 - 0.2e1 * t298 * t299 * t79 + 0.8e1 * t304 * t96 * t120 + t76 * t308 - 0.2e1 * t310 * t169 - t76 * t313 + 0.2e1 * t75 * t18 * t316 + 0.4e1 * t319 * t320 + t249 * t323 - 0.2e1 * t25 * t18 * t326 + 0.2e1 * t228 * t329;
-	t335 = t75 * t101;
-	t336 = t27 * t21;
-	t342 = t77 * t133;
-	t347 = t209 * t137;
-	t350 = t9 * t1;
-	t351 = t149 * t350;
-	t355 = t37 * t78 * t12;
-	t359 = t93 * t303;
-	t367 = t172 * 0.3141592654e1;
-	t369 = t96 * t103;
-	t376 = t209 * t107;
-	t379 = t10 * t103;
-	t383 = t207 * t101;
-	t389 = 0.3141592654e1 * self->ZA;
-	t390 = t222 * t389;
-	t391 = t87 * self->ZB;
-	t398 = -0.2e1 * t102 * t336 + t93 * t38 * t367 + 0.16e2 * t95 * t369 - t82 * t127 - 0.8e1 * t197 * t27 * t120 + 0.8e1 * t376 * t121 - 0.8e1 * t189 * t379 - t249 * t129 - 0.4e1 * t383 * t27 * self->ZA * t16 * t13 - 0.8e1 * t390 * t391 * t21 - 0.2e1 * t197 * t137 * t57;
-	t402 = t39 * t110;
-	t404 = t193 * t38;
-	t406 = t127 * t174;
-	t408 = t167 * 0.3141592654e1;
-	t411 = t44 * t157;
-	t412 = t155 * t411;
-	t413 = t285 * t19;
-	t414 = t56 * t413;
-	t417 = self->ZA * t30;
-	t424 = t93 * t37;
-	t426 = t248 * t54;
-	t427 = t17 * t12;
-	t428 = t118 * t427;
-	t431 = t77 * t21;
-	t438 = self->ZA * t13;
-	t443 = t93 * t172;
-	t444 = t27 * t427;
-	t448 = t1 * t78 * t12;
-	t455 = t274 * t89;
-	t461 = t118 * t111;
-	t464 = -t36 * t402 + t36 * t404 - t249 * t406 - 0.4e1 * t408 * t134 + 0.16e2 * t412 * t414 - 0.4e1 * t383 * t27 * t417 * t18 + 0.2e1 * t28 * t22 - t424 * t80 - 0.2e1 * t426 * t428 + 0.4e1 * t278 * t431 + 0.4e1 * t254 * t255 * t103 + t290 * t323 + 0.4e1 * t383 * t27 * t438 * t20 + 0.2e1 * t443 * t444 + t424 * t448 - t36 * t194 - 0.32e2 * t235 * t236 * t243 * t18 + 0.8e1 * t455 * t181 - 0.4e1 * t359 * t96 * t128 - 0.2e1 * t426 * t461;
-	t469 = n * t16 * t13;
-	t474 = t1 * t38;
-	t475 = t474 * t19;
-	t480 = t89 * t103;
-	t483 = t67 * self->ZA;
-	t484 = t483 * t411;
-	t485 = t127 * t120;
-	t488 = t127 * t111;
-	t497 = t77 * t427;
-	t502 = t27 * t97;
-	t508 = t1 * t19 * t12;
-	t511 = t155 * t25 * t156;
-	t512 = t157 * t37;
-	t513 = t512 * t128;
-	t527 = t1 * t17;
-	t528 = t527 * t38;
-	t530 = -t76 * t497 - 0.4e1 * t254 * t255 * t97 - 0.2e1 * t102 * t502 - 0.4e1 * t108 * t269 - t76 * t508 + 0.8e1 * t511 * t513 + 0.4e1 * t150 * t63 * t18 + 0.4e1 * t383 * t27 * t438 * t18 + 0.4e1 * t132 * t379 + 0.2e1 * t168 * t488 - t76 * t528;
-	t535 = t44 * t13;
-	t542 = t527 * t12;
-	t544 = n * t13;
-	t545 = t544 * t20;
-	t548 = t75 * t303;
-	t549 = t96 * t111;
-	t552 = self->ZA * t35;
-	t553 = t552 * t37;
-	t562 = t43 * t96;
-	t563 = t3 * t37;
-	t564 = t563 * t128;
-	t579 = t474 * t110;
-	t590 = t9 * t30;
-	t591 = t590 * t18;
-	t595 = t127 * t427;
-	t598 = t77 * t174;
-	t600 = 0.4e1 * t5 * t146 + 0.16e2 * t235 * t236 * t535 * t18 + 0.8e1 * t455 * t146 + t76 * t542 - 0.2e1 * t150 * t545 + 0.2e1 * t548 * t549 - 0.2e1 * t553 * t120 + t290 * t488 - 0.8e1 * t274 * t47 * t44 * t29 * t10 - 0.4e1 * t562 * t564 - 0.2e1 * t132 * self->xc * t20 * t10 - 0.32e2 * t562 * self->ZA * t87 * self->ZB * t13 * t29 - 0.8e1 * t347 * t379 + t76 * t579 - 0.4e1 * t359 * t96 * t57 + 0.4e1 * t408 * t181 - 0.4e1 * t223 * t564 - 0.12e2 * t209 * t27 * self->ZB * t8 * t591 + 0.2e1 * t310 * t595 + t76 * t598;
-	t601 = t27 * t49;
-	t604 = t127 * t79;
-	t606 = self->ZB * t29;
-	t616 = t139 * t140 * t18;
-	t638 = t10 * t256;
-	t643 = t118 * t199;
-	t653 = t544 * t29;
-	t658 = t3 * t29;
-	t660 = t350 * t27;
-	t663 = -0.4e1 * t254 * t255 * t145 + 0.2e1 * t267 * t20 * t8 * t9 - 0.4e1 * t138 * t139 * t9 * t16 * t13 - 0.2e1 * t5 * t638 + 0.2e1 * t126 * t169 + 0.8e1 * t376 * t643 + 0.4e1 * t335 * t27 * t145 + 0.16e2 * t235 * t236 * t535 * t29 + 0.6e1 * t150 * t653 - 0.4e1 * t426 * t269 + 0.4e1 * t658 * t8 * t660;
-	t670 = t274 * t411;
-	t673 = t118 * t49;
-	t694 = t155 * t45;
-	t713 = n * t29 * t30;
-	t717 = t20 * t87;
-	t723 = t512 * t57;
-	t728 = -0.2e1 * t443 * t175 - 0.8e1 * t670 * t129 + 0.2e1 * t426 * t673 - 0.16e2 * t207 * t88 * t42 * t47 * self->ZA * t44 + 0.4e1 * t254 * t255 * t21 + t249 * t595 + 0.8e1 * t25 * t29 * t8 * t660 + 0.2e1 * t268 * t461 + 0.8e1 * t189 * t181 - 0.8e1 * t694 * t513 + 0.2e1 * t198 * t553 - 0.12e2 * t606 * t139 * t660 - 0.2e1 * t359 * t549 + 0.4e1 * t138 * t139 * t590 * t16 + 0.8e1 * t93 * t29 * t94 * t89 - 0.2e1 * t150 * t713 + 0.2e1 * t222 * t3 * t717 * t27 + 0.8e1 * t670 * t323 + 0.8e1 * t694 * t723 - 0.2e1 * t62 * t653;
-	t734 = t43 * t89;
-	t735 = t563 * t427;
-	t740 = t75 * t94;
-	t744 = self->ZB * self->xc;
-	t750 = t563 * t57;
-	t754 = t218 * t103;
-	t771 = t127 * t199;
-	t776 = t89 * t174;
-	t791 = -0.4e1 * t207 * t717 * t77 * self->xc * self->ZA + 0.4e1 * t443 * t27 * t57 + t192 * t40 - 0.8e1 * t55 * t643 - 0.16e2 * t209 * t89 * t771 - 0.8e1 * t275 * t323 + 0.2e1 * t359 * t776 + 0.16e2 * t304 * t89 * t199 + 0.4e1 * t278 * t320 + 0.2e1 * t207 * t172 * t389 * t79 - 0.8e1 * t390 * t391 * t97;
-	t794 = t483 * t158;
-	t801 = t2 * 0.3141592654e1;
-	t818 = t215 * t411;
-	t827 = t96 * t174;
-	t837 = t37 * t12 * t110;
-	t845 = 0.16e2 * t794 * t485 + 0.8e1 * t159 * t564 - 0.8e1 * t455 * t379 - 0.2e1 * t801 * t3 * t20 * t10 - 0.4e1 * t132 * t22 - 0.8e1 * t734 * t564 - 0.8e1 * t187 * t44 * t658 * t10 - 0.8e1 * t412 * t564 + 0.4e1 * t132 * t181 - 0.8e1 * t818 * t129 + 0.2e1 * t46 * t48 * t427 - 0.4e1 * t75 * t29 * t316 - 0.2e1 * t359 * t827 - t290 * t595 + 0.16e2 * t217 * t754 - t424 * t542 - 0.8e1 * t734 * t750 - t192 * t837 - 0.4e1 * t254 * t255 * t133 + 0.8e1 * t304 * t96 * t199;
-	t864 = t544 * t18;
-	t867 = t3 * t18;
-	t884 = t27 * t256;
-	t891 = t187 * t744;
-	t894 = t563 * t49;
-	t900 = -0.2e1 * t263 * t428 + 0.2e1 * t228 * t428 - 0.6e1 * t223 * t224 * t103 - t192 * t404 + 0.2e1 * t268 * t428 - 0.2e1 * t335 * t884 - t424 * t296 + 0.2e1 * t93 * t20 * t316 - 0.32e2 * t891 * t616 + 0.2e1 * t562 * t894 - 0.2e1 * t801 * t867 * t10;
-	t904 = t27 * t111;
-	t907 = t118 * t128;
-	t915 = t89 * t145;
-	t947 = t139 * t140 * t29;
-	t952 = -0.2e1 * t173 * t904 + 0.4e1 * t426 * t907 + 0.12e2 * t253 * t10 * t1 * 0.3141592654e1 * t244 + 0.8e1 * t95 * t915 - t36 * t355 - 0.16e2 * t794 * t771 - 0.8e1 * t511 * t723 + 0.16e2 * t734 * t162 + t36 * t837 + 0.2e1 * t298 * t299 * t57 - 0.2e1 * t28 * t638 - 0.2e1 * t62 * t545 + 0.2e1 * t310 * t406 + 0.12e2 * t138 * t616 + 0.4e1 * t223 * t750 + t424 * t497 + 0.2e1 * t734 * t894 + 0.2e1 * t132 * self->xc * t18 * t10 - 0.16e2 * t70 * t947 + 0.32e2 * t891 * t947;
-	t969 = t67 * t157 * t156 * t3;
-	t974 = t27 * t133;
-	t1001 = -0.8e1 * t159 * t750 - 0.16e2 * t412 * t162 - t290 * t129 + 0.8e1 * t310 * t323 - 0.4e1 * t319 * t342 + t75 * t272 + t192 * t402 - 0.8e1 * t359 * t89 * t128 - 0.10e2 * t61 * t350 * t502 + 0.8e1 * t818 * t323 - 0.4e1 * t108 * t907;
-	t1042 = t89 * t97;
-	t1055 = -0.2e1 * t168 * t595 + 0.16e2 * t484 * t771 + 0.4e1 * t11 * t125 * t129 - 0.2e1 * t173 * t444 + 0.2e1 * self->ZB * n * t54 * t37 * self->ZA * t79 - t424 * t475 + 0.2e1 * t562 * t735 - 0.2e1 * t548 * t776 + t424 * t204 + 0.2e1 * t25 * t20 * t326 + 0.8e1 * t383 * t389 * t133 + t75 * t38 * t367 + 0.2e1 * t62 * t469 + 0.2e1 * t197 * t137 * t128 - 0.2e1 * t102 * t884 - 0.2e1 * t5 * t379 - 0.8e1 * t740 * t1042 - 0.16e2 * t159 * t414 - 0.2e1 * self->ZB * t35 * t37 * t413 + 0.2e1 * t553 * self->ZB * t78 * t12;
-	t1096 = 0.2e1 * t443 * t904 - 0.2e1 * t268 * t329 - 0.2e1 * t443 * t601 + 0.2e1 * t102 * t974 - 0.2e1 * t263 * t673 + t424 * t165 + 0.2e1 * t62 * t713 + t424 * t308 - t424 * t313 + 0.8e1 * t347 * t22 - t424 * t598;
-	t1103 = t42 * t1 * t157;
-	t1104 = t1103 * t25;
-	t1108 = t3 * t19;
-	t1112 = n * t47;
-	t1113 = t9 * t9;
-	t1118 = t42 * t157;
-	t1119 = t1118 * t9;
-	t1120 = t25 * self->xc;
-	t1121 = t13 * t110;
-	t1122 = t1120 * t1121;
-	t1125 = t47 * t47;
-	t1126 = t67 * t1125;
-	t1127 = t1113 * self->ZA;
-	t1128 = t1126 * t1127;
-	t1129 = t19 * t13;
-	t1130 = t744 * t1129;
-	t1133 = t154 * t1125;
-	t1134 = t1133 * t9;
-	t1135 = t45 * t1129;
-	t1138 = t154 * t47;
-	t1139 = t25 * t30;
-	t1142 = t1126 * t1113;
-	t1145 = t125 * t1129;
-	t1148 = t1103 * self->xc;
-	t1149 = t3 * t13;
-	t1150 = t1149 * t17;
-	t1153 = t25 * t78;
-	t1156 = -0.8e1 * t1104 * t243 * t17 + 0.4e1 * t187 * t1108 * t9 - 0.2e1 * t1112 * t3 * t1113 * t30 + 0.16e2 * t1119 * t1122 + 0.64e2 * t1128 * t1130 + 0.64e2 * t1134 * t1135 - 0.2e1 * t1138 * t1139 + 0.32e2 * t1142 * t1135 - 0.32e2 * t1142 * t1145 + 0.8e1 * t1148 * t1150 - 0.2e1 * t1138 * t1153;
-	t1157 = t25 * t13;
-	t1158 = t1157 * t17;
-	t1161 = t13 * t17;
-	t1162 = t1120 * t1161;
-	t1165 = t3 * t78;
-	t1170 = t42 * t67 * t1125;
-	t1172 = t1108 * t13;
-	t1175 = t1 * t157;
-	t1176 = t1175 * t1113;
-	t1182 = t1120 * t1129;
-	t1189 = t110 * t9 * self->xc;
-	t1192 = t1149 * t110;
-	t1201 = 0.8e1 * t1103 * t1158 - 0.16e2 * t1119 * t1162 - 0.2e1 * t1112 * t1165 * t1113 + 0.32e2 * t1170 * t44 * t1172 - 0.8e1 * t1176 * t1162 + 0.8e1 * t1104 * t243 * t110 - 0.64e2 * t1134 * t1182 - 0.64e2 * t1134 * t1145 + 0.16e2 * t1118 * t3 * t1189 + 0.16e2 * t1119 * t1192 - 0.4e1 * t187 * t1165 * t9 - 0.4e1 * t187 * t1139 * t9;
-	t1209 = t17 * t30;
-	t1210 = t125 * t1209;
-	t1213 = t1138 * self->ZA;
-	t1214 = self->ZB * t30;
-	t1218 = t1157 * t110;
-	t1226 = t3 * t30;
-	t1237 = t1170 * t25;
-	t1242 = 0.4e1 * t1112 * self->ZA * t119 * t1113 - 0.16e2 * t1119 * t1150 - 0.8e1 * t1176 * t1210 + 0.4e1 * t1213 * t1214 * t19 - 0.16e2 * t1119 * t1218 - 0.32e2 * t1142 * t1182 - 0.8e1 * t1103 * t1120 * t110 - 0.4e1 * t187 * t1226 * t9 + 0.8e1 * t1103 * t1192 + 0.4e1 * t1112 * self->ZB * t1113 * t30 * self->ZA - 0.32e2 * t1237 * self->xc * t19 * t13;
-	t1251 = t125 * t1121;
-	t1260 = t1120 * t1209;
-	t1263 = t1139 * t19;
-	t1282 = 0.8e1 * t1103 * t110 * t3 * self->xc + 0.8e1 * t1104 * self->xc * t17 * t30 - 0.8e1 * t1176 * t1251 + 0.16e2 * t1119 * t1158 + 0.4e1 * t1112 * t78 * t1127 * self->ZB + 0.16e2 * t1119 * t1260 + 0.2e1 * t1138 * t1263 - 0.32e2 * t1170 * self->xc * t1172 - 0.16e2 * t1213 * t119 * t13 + 0.4e1 * t1138 * t1214 * self->ZA + 0.32e2 * t1237 * t44 * t19 * t13 - 0.16e2 * t1118 * t25 * t1189;
-	t1287 = t188 * t1129;
-	t1292 = t25 * t19;
-	t1296 = t187 * t9;
-	t1297 = t1226 * t19;
-	t1311 = t1112 * t1113;
-	t1317 = -0.8e1 * t1176 * t1150 + 0.32e2 * t1142 * t1287 - 0.8e1 * t1103 * t1150 + 0.2e1 * t1112 * t1292 * t1113 + 0.4e1 * t1296 * t1297 + 0.8e1 * t1176 * t1192 + 0.4e1 * t1296 * t1263 + 0.8e1 * t1176 * t1158 - 0.8e1 * t1175 * t25 * t1113 * self->xc * t110 + 0.2e1 * t1311 * t1297 + 0.2e1 * t1112 * t1108 * t1113;
-	t1320 = t253 * t1129;
-	t1328 = t253 * t30 * t19;
-	t1333 = t125 * t1161;
-	t1343 = self->ZB * t44 * t1129;
-	t1350 = -0.8e1 * t1176 * t1218 - 0.16e2 * t1311 * t1320 + 0.8e1 * t1176 * t1260 - 0.16e2 * t1119 * t1210 + 0.4e1 * t1311 * t1328 + 0.2e1 * t1311 * t1263 + 0.8e1 * t1176 * t1333 + 0.8e1 * t187 * self->ZB * t417 * t9 - 0.2e1 * t1138 * t1165 - 0.64e2 * t1128 * t1343 + 0.64e2 * t1134 * t1287 + 0.2e1 * t1138 * t1108;
-	t1369 = t1133 * t9 * self->ZA;
-	t1378 = t187 * self->ZA;
-	t1383 = t1170 * self->ZA;
-	t1388 = 0.2e1 * t1138 * t1297 - 0.8e1 * t1148 * t1192 + 0.2e1 * t1138 * t1292 - 0.16e2 * t1119 * t1251 + 0.8e1 * t1175 * self->xc * t110 * t1113 * t3 - 0.2e1 * t1112 * t1153 * t1113 + 0.128e3 * t1369 * t1130 + 0.16e2 * t1119 * t1333 + 0.4e1 * t1138 * t78 * self->ZA * self->ZB + 0.8e1 * t1378 * t78 * t9 * self->ZB - 0.64e2 * t1383 * t1343 + 0.64e2 * t1383 * t1130;
-	t1420 = 0.4e1 * t1138 * t119 * self->ZA - 0.128e3 * t1369 * t1343 - 0.4e1 * t187 * t1153 * t9 - 0.2e1 * t1138 * t1226 + 0.8e1 * t1296 * t1328 - 0.2e1 * t1112 * t1139 * t1113 - 0.8e1 * t1148 * t3 * t17 * t30 - 0.32e2 * t1296 * t1320 + 0.8e1 * t1176 * t1122 + 0.4e1 * t187 * t1292 * t9 + 0.8e1 * t1378 * t119 * t9 - 0.8e1 * t1103 * t1218;
-
-	self->C4B = (-t424 * t508 + 0.8e1 * t412 * t750 - 0.2e1 * t232 * t595 - 0.4e1 * t126 * t323 + t1096 - t76 * t204 + t728 + 0.2e1 * t548 * t827 + 0.2e1 * t150 * t469 + t398 + 0.8e1 * t189 * t146 + t260 - 0.2e1 * t351 * t184 - 0.2e1 * t268 * t673 - 0.4e1 * t319 * t279 + t464 - 0.2e1 * t108 * t461 + 0.16e2 * t740 * t369 + 0.16e2 * t274 * t216 * t754 - 0.16e2 * t70 * t139 * t591 + 0.2e1 * t55 * t56 * t128 - 0.2e1 * t359 * t89 * t111 + 0.2e1 * t734 * t563 * t111 + 0.6e1 * t223 * t224 * t97 + 0.8e1 * t383 * t389 * t103 + 0.4e1 * t606 * self->ZA * t326 - 0.2e1 * t93 * t18 * t316 - 0.4e1 * t443 * t27 * t128 + 0.8e1 * t197 * t27 * t199 + 0.8e1 * t108 * t109 * t128 - t249 * t604 + 0.16e2 * t70 * t616 - 0.8e1 * t969 * t323 + t845 - t424 * t579 + 0.16e2 * t159 * t162 + t290 * t406 - 0.6e1 * t150 * t864 + t192 * t116 + 0.2e1 * t867 * t326 - 0.4e1 * t658 * t326 - 0.2e1 * t351 * t502 - t76 * t165 + t900 + 0.8e1 * t168 * t323 + t791 + 0.8e1 * t740 * t915 - 0.4e1 * t562 * t750 - 0.4e1 * t278 * t342 + 0.4e1 * t319 * t431 + 0.2e1 * t173 * t175 + t424 * t528 + 0.8e1 * t969 * t129 - 0.8e1 * t347 * t181 + t332 + t530 - 0.2e1 * t108 * t329 - 0.2e1 * t207 * t38 * t37 * t1 * self->ZA + t1001 + 0.4e1 * t408 * t379 + t76 * t448 + 0.2e1 * t102 * t184 + 0.2e1 * t426 * t329 + 0.16e2 * t740 * t98 - t282 * t127 - 0.16e2 * t1 * t44 * t69 * t552 * t116 + 0.2e1 * t168 * t169 + 0.2e1 * t28 * t134 - t290 * t604 - 0.16e2 * t484 * t485 - 0.8e1 * t740 * t480 + 0.2e1 * t173 * t601 - 0.2e1 * t335 * t336 + t600 + 0.2e1 * t62 * t864 + t952 + 0.8e1 * t347 * t134 - t192 * t355 + t192 * t194 + 0.2e1 * t228 * t461 + t663 + 0.4e1 * t383 * t27 * t417 * t16 + 0.4e1 * t138 * t20 * self->ZA * t10 - 0.4e1 * t20 * self->ZB * self->ZA * t326 + 0.4e1 * t196 * t88 * t77 * t744 - 0.16e2 * t67 * self->xc * t179 * t181 - 0.8e1 * t95 * t480 - t249 * t488 - t76 * t475 + t1055 - 0.4e1 * t408 * t22 - 0.10e2 * t28 * t379 + 0.2e1 * t335 * t974 + t153 - 0.8e1 * t95 * t1042 - 0.2e1 * t734 * t735) / (t1156 + t1201 + t1242 + t1282 + t1317 + t1350 + t1388 + t1420);
-	/****************************************************************************************/
-	/****************************************************************************************/
-}
-	
-	
-
-void ColumnViscosityAnalytic_VelocityFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* velocity ) {
-	ColumnViscosityAnalytic *self = (ColumnViscosityAnalytic*)analyticSolution;
-	double                  Z;
-	double                  x,y;
-	double                  C1,C2,C3,C4;
-	double                  n, nx;
-	double t1,t2,t3,t4,t5,t6,t7,t8,t11,t12,t13,t14,t15,t16,t18,t19,t20,t21,t23,t24,t25,t28,t29,t30,t31,t32,t33,t34,t36,t37;
-	double t41,t45,t49,t51,t53,t55,t58,t59,t60,t63,t67,t68,t73;
-	double t86,t87,t90,t91,t94,t106,t120;
-	double t121,t129,t146,t155,t156,t158,t159;
-	
-	/* Find coordinate of node */
-	x = coord[ I_AXIS ];
-	y = coord[ J_AXIS ];
-    
-	/* del_rho = sin(ny*Pi*y)*cos(nx*Pi*x)  n=nx gives only non-zero terms*/ 
-	n = 1; 
-	/* only one n in Fourier series because  del_rho has cos term */ 
-	nx = n; 
-
-	if ( x > self->xc ) { 
-		C1 = self->C1B; 
-		C2 = self->C2B;
-		C3 = self->C3B; 
-		C4 = self->C4B; 
-		Z  = self->ZB; 
-	}
-	else {
-		C1 = self->C1A; 
-		C2 = self->C2A; 
-		C3 = self->C3A; 
-		C4 = self->C4A; 
-		Z  = self->ZA;
-	}
-
-	/****************************************************************************************/
-	/****************************************************************************************/
-	t1 = n * n;
-	t2 = t1 * t1;
-	t3 = t2 * n;
-	t4 = x * t3;
-	t5 = 0.3141592654e1 * 0.3141592654e1;
-	t6 = t5 * 0.3141592654e1;
-	t11 = C3 * t6;
-	t12 = x * n;
-	t13 = nx * nx;
-	t14 = t13 * t13;
-	t15 = t12 * t14;
-	t19 = exp(t12 * 0.3141592654e1);
-	t20 = t19 * t19;
-	t21 = t4 * t20;
-	t24 = C1 * t5;
-	t25 = Z * t20;
-	t29 = C1 * t6;
-	t30 = t29 * Z;
-	t31 = t1 * n;
-	t32 = x * t31;
-	t33 = t32 * t13;
-	t36 = t11 * x;
-	t41 = n * t20;
-	t45 = t6 * C4;
-	t49 = t20 * t1;
-	t51 = C2 * Z;
-	t55 = -0.2e1 * t4 * t6 * C2 * Z - 0.2e1 * t11 * t15 - 0.2e1 * t11 * t21 + 0.2e1 * t24 * t25 * t14 - t13 + 0.4e1 * t30 * t33 - 0.4e1 * t36 * t31 * t20 * t13 - 0.2e1 * t36 * t41 * t14 - 0.2e1 * t4 * t45 * t20 - t49 - 0.2e1 * t4 * t6 * t51 * t20;
-	t58 = t32 * t6;
-	t59 = C4 * t20;
-	t63 = t20 * t13;
-	t67 = t12 * t6;
-	t68 = t20 * t14;
-	t87 = t49 * t13;
-	t90 = -0.4e1 * t11 * t33 - 0.4e1 * t58 * t59 * t13 - 0.4e1 * t58 * t51 * t63 - 0.2e1 * t67 * t51 * t68 + 0.4e1 * t32 * t45 * t13 - 0.2e1 * t67 * t59 * t14 - 0.2e1 * t30 * t21 + t1 + 0.2e1 * t24 * t25 * t2 + 0.2e1 * t12 * t45 * t14 + 0.4e1 * t24 * Z * t87;
-	t106 = C3 * t5;
-	t120 = -0.4e1 * t30 * t32 * t63 + t63 + 0.4e1 * t24 * Z * t1 * t13 + 0.2e1 * t29 * Z * x * t3 - 0.4e1 * t58 * t51 * t13 - 0.2e1 * t106 * t2 + t32 * 0.3141592654e1 - 0.2e1 * t106 * t14 - 0.2e1 * t30 * t12 * t68 - 0.2e1 * t67 * t51 * t14 + 0.4e1 * t106 * t87;
-	t129 = sin(nx * 0.3141592654e1 * x);
-	t155 = 0.2e1 * t30 * t15 + x * 0.3141592654e1 * t41 * t13 - 0.4e1 * t19 * nx * t129 * n + t32 * 0.3141592654e1 * t20 + 0.2e1 * t106 * t68 + 0.2e1 * t106 * t20 * t2 - 0.4e1 * t106 * t1 * t13 - 0.2e1 * t11 * t4 + 0.2e1 * t4 * t45 + 0.2e1 * t24 * Z * t2 + 0.2e1 * t24 * Z * t14 + t12 * 0.3141592654e1 * t13;
-	t158 = t5 * Z;
-
-	velocity[ I_AXIS ] = (t55 + t90 + t120 + t155) / (0.4e1 * t158 * t19 * t2 + 0.8e1 * t158 * t19 * t1 * t13 + 0.4e1 * t158 * t19 * t14);
-	velocity[ I_AXIS ] *= cos(n*M_PI*y); 
-
-	/****************************************************************************************/
-	/****************************************************************************************/
-	t1 = n * n;
-	t2 = t1 * n;
-	t3 = x * t2;
-	t4 = 0.3141592654e1 * 0.3141592654e1;
-	t5 = t4 * 0.3141592654e1;
-	t6 = t3 * t5;
-	t7 = C2 * Z;
-	t8 = nx * nx;
-	t12 = t1 * t1;
-	t13 = t12 * n;
-	t14 = x * t13;
-	t15 = t5 * C4;
-	t16 = x * n;
-	t18 = exp(t16 * 0.3141592654e1);
-	t19 = t18 * t18;
-	t23 = t16 * t5;
-	t24 = t8 * t8;
-	t28 = C3 * t5;
-	t29 = t14 * t19;
-	t32 = C1 * t5;
-	t33 = t32 * Z;
-	t34 = t16 * t24;
-	t37 = C4 * t19;
-	t45 = C2 * t4;
-	t53 = t19 * t8;
-	t58 = C4 * t4;
-	t60 = t1 * t19 * t8;
-	t63 = t19 * t24;
-	t67 = t3 * t8;
-	t73 = n * t19;
-	t86 = t28 * x;
-	t91 = 0.4e1 * t58 * t60 + 0.2e1 * t33 * t16 * t63 + 0.4e1 * t33 * t67 + 0.2e1 * t33 * t29 - x * 0.3141592654e1 * t73 * t8 - 0.2e1 * t53 + 0.2e1 * t32 * Z * x * t13 - 0.2e1 * t58 * t12 - 0.2e1 * t58 * t24 + t3 * 0.3141592654e1 + 0.4e1 * t86 * t2 * t19 * t8;
-	t94 = Z * t12;
-	t121 = -0.2e1 * t8 + 0.2e1 * t45 * t94 * t19 + 0.2e1 * t14 * t5 * t7 * t19 + 0.4e1 * t6 * t7 * t53 + 0.2e1 * t23 * t7 * t63 - 0.4e1 * t28 * t67 + 0.2e1 * t45 * t94 + 0.2e1 * t58 * t12 * t19 + t16 * 0.3141592654e1 * t8 + 0.2e1 * t14 * t15 - 0.2e1 * t28 * t14;
-	t146 = cos(nx * 0.3141592654e1 * x);
-	t156 = -t3 * 0.3141592654e1 * t19 + 0.2e1 * t58 * t63 - 0.4e1 * t58 * t1 * t8 + 0.4e1 * t45 * Z * t1 * t8 - 0.2e1 * t28 * t34 + 0.2e1 * t86 * t73 * t24 + 0.4e1 * t3 * t15 * t8 + 0.4e1 * t45 * Z * t60 + 0.4e1 * t18 * t146 * t8 + 0.2e1 * t45 * Z * t24 + 0.2e1 * t16 * t15 * t24;
-	t159 = t4 * Z;
-
-	velocity[ J_AXIS ] = (-0.4e1 * t6 * t7 * t8 + 0.2e1 * t14 * t15 * t19 - 0.2e1 * t23 * t7 * t24 + 0.2e1 * t28 * t29 + 0.2e1 * t33 * t34 + 0.4e1 * t6 * t37 * t8 - 0.2e1 * t14 * t5 * C2 * Z + 0.2e1 * t45 * Z * t19 * t24 + 0.2e1 * t23 * t37 * t24 + 0.4e1 * t33 * t3 * t53 + t91 + t121 + t156) / (0.4e1 * t159 * t18 * t12 + 0.8e1 * t159 * t18 * t1 * t8 + 0.4e1 * t159 * t18 * t24);
-	velocity[ J_AXIS ] *= sin(n*M_PI*y); /* y velocity */
-
-}
-
-
-void ColumnViscosityAnalytic_PressureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* pressure ) {
-	ColumnViscosityAnalytic *self = (ColumnViscosityAnalytic*)analyticSolution;
-	double                  Z;
-	double                  x,y;
-	double                  C1,C2,C3,C4;
-	double                  n, nx;
-	XYZ                     velocity;
-	double                  u3;
-	double t9, t17, t40, t44, t48, t52, t57, t61, t62, t78, t101, t102, t109, t110, t128;
-	double t1,t2,t3,t4,t5,t6,t7,t8,t11,t12,t13,t14,t15,t16,t18,t19,t20,t23,t24,t28,t29,t30,t31,t32,t33,t34,t37;
-	double t45,t53,t58,t60,t63,t67,t73;
-	double t86,t90,t91,t94;
-	double t121,t146,t156,t159;
-	
-	/* Find coordinate of node */
-	x = coord[ I_AXIS ];
-	y = coord[ J_AXIS ];
-    
-	/* del_rho = sin(ny*Pi*y)*cos(nx*Pi*x)  n=nx gives only non-zero terms*/ 
-	n = 1; 
-	/* only one n in Fourier series because  del_rho has cos term */ 
-	nx = n; 
-
-	if ( x > self->xc ) { 
-		C1 = self->C1B; 
-		C2 = self->C2B;
-		C3 = self->C3B; 
-		C4 = self->C4B; 
-		Z  = self->ZB; 
-	}
-	else {
-		C1 = self->C1A; 
-		C2 = self->C2A; 
-		C3 = self->C3A; 
-		C4 = self->C4A; 
-		Z  = self->ZA;
-	}
-
-	/****************************************************************************************/
-	/****************************************************************************************/
-	t1 = n * n;
-	t2 = t1 * n;
-	t3 = x * t2;
-	t4 = 0.3141592654e1 * 0.3141592654e1;
-	t5 = t4 * 0.3141592654e1;
-	t6 = t3 * t5;
-	t7 = C2 * Z;
-	t8 = nx * nx;
-	t12 = t1 * t1;
-	t13 = t12 * n;
-	t14 = x * t13;
-	t15 = t5 * C4;
-	t16 = x * n;
-	t18 = exp(t16 * 0.3141592654e1);
-	t19 = t18 * t18;
-	t23 = t16 * t5;
-	t24 = t8 * t8;
-	t28 = C3 * t5;
-	t29 = t14 * t19;
-	t32 = C1 * t5;
-	t33 = t32 * Z;
-	t34 = t16 * t24;
-	t37 = C4 * t19;
-	t45 = C2 * t4;
-	t53 = t19 * t8;
-	t58 = C4 * t4;
-	t60 = t1 * t19 * t8;
-	t63 = t19 * t24;
-	t67 = t3 * t8;
-	t73 = n * t19;
-	t86 = t28 * x;
-	t91 = 0.4e1 * t58 * t60 + 0.2e1 * t33 * t16 * t63 + 0.4e1 * t33 * t67 + 0.2e1 * t33 * t29 - x * 0.3141592654e1 * t73 * t8 - 0.2e1 * t53 + 0.2e1 * t32 * Z * x * t13 - 0.2e1 * t58 * t12 - 0.2e1 * t58 * t24 + t3 * 0.3141592654e1 + 0.4e1 * t86 * t2 * t19 * t8;
-	t94 = Z * t12;
-	t121 = -0.2e1 * t8 + 0.2e1 * t45 * t94 * t19 + 0.2e1 * t14 * t5 * t7 * t19 + 0.4e1 * t6 * t7 * t53 + 0.2e1 * t23 * t7 * t63 - 0.4e1 * t28 * t67 + 0.2e1 * t45 * t94 + 0.2e1 * t58 * t12 * t19 + t16 * 0.3141592654e1 * t8 + 0.2e1 * t14 * t15 - 0.2e1 * t28 * t14;
-	t146 = cos(nx * 0.3141592654e1 * x);
-	t156 = -t3 * 0.3141592654e1 * t19 + 0.2e1 * t58 * t63 - 0.4e1 * t58 * t1 * t8 + 0.4e1 * t45 * Z * t1 * t8 - 0.2e1 * t28 * t34 + 0.2e1 * t86 * t73 * t24 + 0.4e1 * t3 * t15 * t8 + 0.4e1 * t45 * Z * t60 + 0.4e1 * t18 * t146 * t8 + 0.2e1 * t45 * Z * t24 + 0.2e1 * t16 * t15 * t24;
-	t159 = t4 * Z;
-
-	velocity[ J_AXIS ] = (-0.4e1 * t6 * t7 * t8 + 0.2e1 * t14 * t15 * t19 - 0.2e1 * t23 * t7 * t24 + 0.2e1 * t28 * t29 + 0.2e1 * t33 * t34 + 0.4e1 * t6 * t37 * t8 - 0.2e1 * t14 * t5 * C2 * Z + 0.2e1 * t45 * Z * t19 * t24 + 0.2e1 * t23 * t37 * t24 + 0.4e1 * t33 * t3 * t53 + t91 + t121 + t156) / (0.4e1 * t159 * t18 * t12 + 0.8e1 * t159 * t18 * t1 * t8 + 0.4e1 * t159 * t18 * t24);
-	velocity[ J_AXIS ] *= sin(n*M_PI*y); /* y velocity */
-
-	/****************************************************************************************/
-	/****************************************************************************************/
-	t1 = 0.3141592654e1 * 0.3141592654e1;
-	t2 = t1 * 0.3141592654e1;
-	t3 = C1 * t2;
-	t4 = t3 * Z;
-	t5 = n * n;
-	t6 = t5 * t5;
-	t7 = t6 * n;
-	t8 = x * t7;
-	t9 = x * n;
-	t11 = exp(t9 * 0.3141592654e1);
-	t12 = t11 * t11;
-	t13 = t8 * t12;
-	t16 = t5 * n;
-	t17 = x * t16;
-	t18 = t17 * t2;
-	t19 = C4 * t12;
-	t20 = nx * nx;
-	t24 = t2 * C4;
-	t28 = C3 * t2;
-	t29 = t28 * x;
-	t30 = t12 * n;
-	t31 = t20 * t20;
-	t40 = C2 * Z;
-	t44 = t9 * t2;
-	t48 = t12 * t20;
-	t52 = t17 * t20;
-	t57 = -0.2e1 * t4 * t13 - 0.4e1 * t18 * t19 * t20 - 0.2e1 * t8 * t24 * t12 - 0.2e1 * t29 * t30 * t31 + 0.2e1 * t8 * t2 * C2 * Z - 0.2e1 * t8 * t2 * t40 * t12 - 0.2e1 * t44 * t19 * t31 - 0.4e1 * t18 * t40 * t48 + t20 + 0.4e1 * t28 * t52 + t17 * 0.3141592654e1 * t12;
-	t58 = t9 * t31;
-	t61 = C3 * t1;
-	t62 = t12 * t31;
-	t73 = t5 * t20;
-	t78 = C1 * t1;
-	t90 = Z * t12;
-	t94 = 0.2e1 * t28 * t58 + 0.2e1 * t61 * t62 + 0.2e1 * t61 * t12 * t6 - 0.4e1 * t4 * t17 * t48 + 0.2e1 * t28 * t8 + 0.4e1 * t61 * t73 - 0.2e1 * t8 * t24 - 0.2e1 * t78 * Z * t6 - 0.2e1 * t44 * t40 * t62 - 0.2e1 * t78 * Z * t31 - t9 * 0.3141592654e1 * t20 + 0.2e1 * t78 * t90 * t6;
-	t101 = cos(nx * 0.3141592654e1 * x);
-	t102 = t11 * t101;
-	t109 = t12 * t5;
-	t110 = t109 * t20;
-	t128 = 0.2e1 * t61 * t6 - t17 * 0.3141592654e1 + 0.2e1 * t102 * t5 - 0.4e1 * t17 * t24 * t20 + 0.4e1 * t78 * Z * t110 - 0.2e1 * t9 * t24 * t31 - 0.4e1 * t4 * t52 - 0.2e1 * t4 * t9 * t62 + x * 0.3141592654e1 * t30 * t20 - t5 - 0.4e1 * t78 * Z * t5 * t20;
-	t156 = 0.2e1 * t78 * t90 * t31 - 0.2e1 * t3 * Z * x * t7 + t48 + 0.4e1 * t61 * t110 + 0.4e1 * t18 * t40 * t20 - 0.2e1 * t102 * t20 + 0.2e1 * t61 * t31 + 0.2e1 * t44 * t40 * t31 - t109 - 0.2e1 * t4 * t58 - 0.2e1 * t28 * t13 - 0.4e1 * t29 * t16 * t12 * t20;
-	t159 = t1 * t11;
-
-	u3 = (t57 + t94 + t128 + t156) / (0.4e1 * t159 * t6 + 0.8e1 * t159 * t73 + 0.4e1 * t159 * t31);
-	/****************************************************************************************/
-	/****************************************************************************************/
-
-	*pressure = (double)(-2*Z*n*M_PI*velocity[ J_AXIS ]-u3*2*n*M_PI)*cos(n*M_PI*y); 
-	 
-}
-
-void ColumnViscosityAnalytic_StressFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* stress ) {
-	ColumnViscosityAnalytic *self = (ColumnViscosityAnalytic*)analyticSolution;
-	double                  Z;
-	double                  x,y;
-	double                  C1,C2,C3,C4;
-	double                  n, nx;
-	double                  u2, u3, u4;
-	double t1,t2,t3,t4,t5,t6,t7,t8,t9,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t23,t24,t28,t29,t30,t31,t32,t33,t34,t35,t37,t40;
-	double t41,t44,t45,t47,t48,t52,t53,t54,t57,t58,t60,t61,t62,t63,t67,t69,t73,t75,t78,t79;
-	double t83,t84,t86,t90,t91,t94,t95,t97,t101,t102,t106,t109,t110;
-	double t121,t127,t128,t131,t135,t146,t156,t159;
-	double t164;
-	
-	/* Find coordinate of node */
-	x = coord[ I_AXIS ];
-	y = coord[ J_AXIS ];
-    
-	/* del_rho = sin(ny*Pi*y)*cos(nx*Pi*x)  n=nx gives only non-zero terms*/ 
-	n = 1; 
-	/* only one n in Fourier series because  del_rho has cos term */ 
-	nx = n; 
-
-	if ( x > self->xc ) { 
-		C1 = self->C1B; 
-		C2 = self->C2B;
-		C3 = self->C3B; 
-		C4 = self->C4B; 
-		Z  = self->ZB; 
-	}
-	else {
-		C1 = self->C1A; 
-		C2 = self->C2A; 
-		C3 = self->C3A; 
-		C4 = self->C4A; 
-		Z  = self->ZA;
-	}
-
-	t1 = n * n;
-	t2 = t1 * n;
-	t3 = x * t2;
-	t4 = 0.3141592654e1 * 0.3141592654e1;
-	t5 = t4 * 0.3141592654e1;
-	t6 = t3 * t5;
-	t7 = C2 * Z;
-	t8 = nx * nx;
-	t12 = t1 * t1;
-	t13 = t12 * n;
-	t14 = x * t13;
-	t15 = t5 * C4;
-	t16 = x * n;
-	t18 = exp(t16 * 0.3141592654e1);
-	t19 = t18 * t18;
-	t23 = t16 * t5;
-	t24 = t8 * t8;
-	t28 = C3 * t5;
-	t29 = t14 * t19;
-	t32 = C1 * t5;
-	t33 = t32 * Z;
-	t34 = t16 * t24;
-	t37 = C4 * t19;
-	t45 = C2 * t4;
-	t53 = t19 * t8;
-	t58 = C4 * t4;
-	t60 = t1 * t19 * t8;
-	t63 = t19 * t24;
-	t67 = t3 * t8;
-	t73 = n * t19;
-	t86 = t28 * x;
-	t91 = 0.4e1 * t58 * t60 + 0.2e1 * t33 * t16 * t63 + 0.4e1 * t33 * t67 + 0.2e1 * t33 * t29 - x * 0.3141592654e1 * t73 * t8 - 0.2e1 * t53 + 0.2e1 * t32 * Z * x * t13 - 0.2e1 * t58 * t12 - 0.2e1 * t58 * t24 + t3 * 0.3141592654e1 + 0.4e1 * t86 * t2 * t19 * t8;
-	t94 = Z * t12;
-	t121 = -0.2e1 * t8 + 0.2e1 * t45 * t94 * t19 + 0.2e1 * t14 * t5 * t7 * t19 + 0.4e1 * t6 * t7 * t53 + 0.2e1 * t23 * t7 * t63 - 0.4e1 * t28 * t67 + 0.2e1 * t45 * t94 + 0.2e1 * t58 * t12 * t19 + t16 * 0.3141592654e1 * t8 + 0.2e1 * t14 * t15 - 0.2e1 * t28 * t14;
-	t146 = cos(nx * 0.3141592654e1 * x);
-	t156 = -t3 * 0.3141592654e1 * t19 + 0.2e1 * t58 * t63 - 0.4e1 * t58 * t1 * t8 + 0.4e1 * t45 * Z * t1 * t8 - 0.2e1 * t28 * t34 + 0.2e1 * t86 * t73 * t24 + 0.4e1 * t3 * t15 * t8 + 0.4e1 * t45 * Z * t60 + 0.4e1 * t18 * t146 * t8 + 0.2e1 * t45 * Z * t24 + 0.2e1 * t16 * t15 * t24;
-	t159 = t4 * Z;
-
-	u2 = (-0.4e1 * t6 * t7 * t8 + 0.2e1 * t14 * t15 * t19 - 0.2e1 * t23 * t7 * t24 + 0.2e1 * t28 * t29 + 0.2e1 * t33 * t34 + 0.4e1 * t6 * t37 * t8 - 0.2e1 * t14 * t5 * C2 * Z + 0.2e1 * t45 * Z * t19 * t24 + 0.2e1 * t23 * t37 * t24 + 0.4e1 * t33 * t3 * t53 + t91 + t121 + t156) / (0.4e1 * t159 * t18 * t12 + 0.8e1 * t159 * t18 * t1 * t8 + 0.4e1 * t159 * t18 * t24);
-
-	/****************************************************************************************/
-	/****************************************************************************************/
-
-	t1 = 0.3141592654e1 * 0.3141592654e1;
-	t2 = t1 * 0.3141592654e1;
-	t3 = C1 * t2;
-	t4 = t3 * Z;
-	t5 = n * n;
-	t6 = t5 * t5;
-	t7 = t6 * n;
-	t8 = x * t7;
-	t9 = x * n;
-	t11 = exp(t9 * 0.3141592654e1);
-	t12 = t11 * t11;
-	t13 = t8 * t12;
-	t16 = t5 * n;
-	t17 = x * t16;
-	t18 = t17 * t2;
-	t19 = C4 * t12;
-	t20 = nx * nx;
-	t24 = t2 * C4;
-	t28 = C3 * t2;
-	t29 = t28 * x;
-	t30 = t12 * n;
-	t31 = t20 * t20;
-	t40 = C2 * Z;
-	t44 = t9 * t2;
-	t48 = t12 * t20;
-	t52 = t17 * t20;
-	t57 = -0.2e1 * t4 * t13 - 0.4e1 * t18 * t19 * t20 - 0.2e1 * t8 * t24 * t12 - 0.2e1 * t29 * t30 * t31 + 0.2e1 * t8 * t2 * C2 * Z - 0.2e1 * t8 * t2 * t40 * t12 - 0.2e1 * t44 * t19 * t31 - 0.4e1 * t18 * t40 * t48 + t20 + 0.4e1 * t28 * t52 + t17 * 0.3141592654e1 * t12;
-	t58 = t9 * t31;
-	t61 = C3 * t1;
-	t62 = t12 * t31;
-	t73 = t5 * t20;
-	t78 = C1 * t1;
-	t90 = Z * t12;
-	t94 = 0.2e1 * t28 * t58 + 0.2e1 * t61 * t62 + 0.2e1 * t61 * t12 * t6 - 0.4e1 * t4 * t17 * t48 + 0.2e1 * t28 * t8 + 0.4e1 * t61 * t73 - 0.2e1 * t8 * t24 - 0.2e1 * t78 * Z * t6 - 0.2e1 * t44 * t40 * t62 - 0.2e1 * t78 * Z * t31 - t9 * 0.3141592654e1 * t20 + 0.2e1 * t78 * t90 * t6;
-	t101 = cos(nx * 0.3141592654e1 * x);
-	t102 = t11 * t101;
-	t109 = t12 * t5;
-	t110 = t109 * t20;
-	t128 = 0.2e1 * t61 * t6 - t17 * 0.3141592654e1 + 0.2e1 * t102 * t5 - 0.4e1 * t17 * t24 * t20 + 0.4e1 * t78 * Z * t110 - 0.2e1 * t9 * t24 * t31 - 0.4e1 * t4 * t52 - 0.2e1 * t4 * t9 * t62 + x * 0.3141592654e1 * t30 * t20 - t5 - 0.4e1 * t78 * Z * t5 * t20;
-	t156 = 0.2e1 * t78 * t90 * t31 - 0.2e1 * t3 * Z * x * t7 + t48 + 0.4e1 * t61 * t110 + 0.4e1 * t18 * t40 * t20 - 0.2e1 * t102 * t20 + 0.2e1 * t61 * t31 + 0.2e1 * t44 * t40 * t31 - t109 - 0.2e1 * t4 * t58 - 0.2e1 * t28 * t13 - 0.4e1 * t29 * t16 * t12 * t20;
-	t159 = t1 * t11;
-
-	u3 = (t57 + t94 + t128 + t156) / (0.4e1 * t159 * t6 + 0.8e1 * t159 * t73 + 0.4e1 * t159 * t31);	
-	/****************************************************************************************/
-	/****************************************************************************************/
-	
-	t1 = C2 * Z;
-	t2 = 0.3141592654e1 * 0.3141592654e1;
-	t3 = t2 * 0.3141592654e1;
-	t4 = n * n;
-	t5 = t4 * t4;
-	t6 = t5 * t4;
-	t8 = t3 * t6 * x;
-	t11 = x * t4;
-	t12 = t11 * t3;
-	t15 = exp(x * n * 0.3141592654e1);
-	t16 = t15 * t15;
-	t17 = C3 * t16;
-	t18 = nx * nx;
-	t19 = t18 * t18;
-	t23 = t5 * n;
-	t24 = t2 * t23;
-	t28 = t1 * t3;
-	t29 = t6 * x;
-	t30 = t29 * t16;
-	t33 = C4 * t3;
-	t34 = t5 * x;
-	t35 = t34 * t18;
-	t41 = sin(nx * 0.3141592654e1 * x);
-	t47 = t11 * t19;
-	t54 = t3 * C3;
-	t57 = 0.2e1 * t1 * t8 + 0.2e1 * t12 * t17 * t19 + 0.2e1 * t1 * t24 * t16 + 0.2e1 * t28 * t30 - 0.4e1 * t33 * t35 + 0.2e1 * t15 * nx * t41 * t4 + 0.4e1 * t28 * t35 - 0.2e1 * t33 * t47 - 0.2e1 * t1 * t24 - 0.2e1 * t33 * t29 + 0.2e1 * t29 * t54;
-	t58 = 0.3141592654e1 * t16;
-	t60 = t2 * C4;
-	t69 = t4 * n;
-	t73 = t1 * t2;
-	t75 = t69 * t16 * t18;
-	t79 = x * t16;
-	t83 = n * t16;
-	t84 = t83 * t19;
-	t95 = -t34 * t58 + 0.2e1 * t60 * t23 * t16 + 0.2e1 * t60 * n * t19 - t11 * 0.3141592654e1 * t18 + 0.4e1 * t60 * t69 * t18 + 0.4e1 * t73 * t75 + 0.4e1 * t33 * t5 * t79 * t18 + 0.2e1 * t73 * t84 + 0.2e1 * t60 * t84 + 0.2e1 * t33 * t4 * t79 * t19 + 0.4e1 * t60 * t75;
-	t97 = t34 * t3;
-	t101 = Z * C1;
-	t102 = t16 * t19;
-	t106 = t16 * t18;
-	t127 = t2 * t69;
-	t131 = t2 * n;
-	t135 = 0.4e1 * t97 * t17 * t18 + 0.2e1 * t12 * t101 * t102 + 0.4e1 * t28 * t34 * t106 + 0.2e1 * t28 * t11 * t102 - 0.2e1 * t29 * t3 * Z * C1 - 0.4e1 * t97 * t101 * t18 - 0.2e1 * t12 * t101 * t19 + 0.2e1 * t60 * t23 - 0.2e1 * t83 * t18 - 0.4e1 * t1 * t127 * t18 - 0.2e1 * t1 * t131 * t19;
-	t164 = 0.2e1 * t28 * t47 + 0.2e1 * t11 * t54 * t19 + 0.2e1 * t8 * t101 * t16 + 0.2e1 * t33 * t30 - t11 * t58 * t18 + 0.2e1 * t29 * t54 * t16 + 0.4e1 * t34 * t54 * t18 + 0.4e1 * t97 * t101 * t106 - 0.2e1 * t15 * t18 * nx * t41 - t34 * 0.3141592654e1 + 0.2e1 * n * t18;
-
-	u4 = (t57 + t95 + t135 + t164) / (0.4e1 * t24 * t15 + 0.8e1 * t127 * t15 * t18 + 0.4e1 * t131 * t15 * t19);	
-	/****************************************************************************************/
-	/****************************************************************************************/
-
-	stress[0] = (double)(u4*2*n*M_PI + 4*Z*n*M_PI*u2)*cos(n*M_PI*y); /* xx stress */
-	stress[1] = 2*n*M_PI*cos(n*M_PI*y) * u3; /* yy stress */
-	stress[2] = 2*n*M_PI*sin(n*M_PI*y) * u4; /* xy stress */
-}
-
-void _ColumnViscosityAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	ColumnViscosityAnalytic* self = (ColumnViscosityAnalytic*)analyticSolution;
-	AbstractContext*         context;
-	ConditionFunction*       condFunc;
-
-	/* Construct Parent */
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
-	
-	/* Create Analytic Fields */
-	self->velocityField = Stg_ComponentFactory_ConstructByName( cf, (Name)"VelocityField", FeVariable, True, data  ); 
-	self->pressureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"PressureField", FeVariable, True, data  ); 
-	self->stressField = Stg_ComponentFactory_ConstructByName( cf, (Name)"StressField", FeVariable, False, data  ); 
-
-	/* Add condition function for temperature */
-	condFunc = ConditionFunction_New( ColumnViscosityAnalytic_TemperatureIC, (Name)"ColumnViscosityAnalytic_TemperatureIC"  );
-	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
-
-	/* Set up constants */
-	self->ZA = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"leftViscosity", 1.0  );
-	self->ZB = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"rightViscosity", 1.0  );
-
-	/* top layer viscosity */
-	self->xc = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"columnEnd", 0.5 );
-	ColumnViscosityAnalytic_Constants( self  );
-}
-
-void _ColumnViscosityAnalytic_Build( void* analyticSolution, void* data ) {
-	ColumnViscosityAnalytic* self = (ColumnViscosityAnalytic*)analyticSolution;
-
-	Build( self->velocityField, data, False );
-	Build( self->pressureField, data, False );
-	if( self->stressField )
-		Build( self->stressField, data, False );
-
-	AnalyticSolution_CreateAnalyticField( self, self->velocityField, ColumnViscosityAnalytic_VelocityFunction );
-	AnalyticSolution_CreateAnalyticField( self, self->pressureField, ColumnViscosityAnalytic_PressureFunction );
-	if( self->stressField ) 
-		AnalyticSolution_CreateAnalyticField( self, self->stressField, ColumnViscosityAnalytic_StressFunction );
-
-	_AnalyticSolution_Build( self, data );
-}
-
-void* _ColumnViscosityAnalytic_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(ColumnViscosityAnalytic);
-	Type                                                      type = ColumnViscosityAnalytic_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _ColumnViscosityAnalytic_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _ColumnViscosityAnalytic_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _ColumnViscosityAnalytic_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-Index StgFEM_ColumnViscosityAnalytic_Register( PluginsManager* pluginsManager ) {
-	return PluginsManager_Submit( pluginsManager, ColumnViscosityAnalytic_Type, (Name)"0", _ColumnViscosityAnalytic_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Apps/ThermalConvection/tests/ColumnViscosityAnalytic/ColumnViscosityAnalytic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Apps/ThermalConvection/tests/ColumnViscosityAnalytic/ColumnViscosityAnalytic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,2637 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: ColumnViscosityAnalytic.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+#include <assert.h>
+
+const Type ColumnViscosityAnalytic_Type = "ColumnViscosityAnalytic";
+
+typedef struct {
+	__AnalyticSolution
+	double ZA;
+	double ZB;
+	double xc;
+	double C1A,C2A,C3A,C4A,C1B,C2B,C3B,C4B;
+	FeVariable* velocityField;
+	FeVariable* pressureField;
+	FeVariable* stressField;
+} ColumnViscosityAnalytic;
+
+#define SMALL 1.0e-5
+#define IS_ODD(A)   ( (A) % 2 == 1 )
+
+
+/** Analytic Solution taken from 
+ *  Shijie Zhong. Analytic solutions for Stokes' flow with lateral variations in viscosity. Geophys. J. Int., 124:18-28, 1996.
+ *  All equations refer to this paper */
+
+void ColumnViscosityAnalytic_TemperatureIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*  context            = (DomainContext*)_context;
+	FeVariable*             temperatureField   = (FeVariable*) FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	FeMesh*     mesh               = temperatureField->feMesh;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	double                  x; 
+	double                  y;
+	double                  kx;
+	double                  ky;
+	int                     wavenumberX;
+	int                     wavenumberY;
+	double                  L;
+	double			min[3], max[3];
+	
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	/* Make sure that the box has right dimensions */
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	assert( ( max[ J_AXIS ] - min[ J_AXIS ] - 1.0 ) < SMALL );
+	L = max[ I_AXIS ] - min[ I_AXIS ];
+
+	x = coord[ I_AXIS ] - min[ I_AXIS ];
+	y = coord[ J_AXIS ] - min[ J_AXIS ];
+
+	wavenumberX = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberX", 1  );
+	wavenumberY = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberY", 1 );
+
+	kx = wavenumberX * M_PI/ L;
+	ky = wavenumberY * M_PI;
+
+	*result = sin( ky * y ) * cos( kx * x );
+}
+
+void ColumnViscosityAnalytic_Constants( void* analyticSolution ) {
+	ColumnViscosityAnalytic* self = (ColumnViscosityAnalytic* ) analyticSolution;
+	double                  n, nx;
+	double t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t21,t22,t23,t24,t25,t26,t27,t28,t29,t30,t31,t32,t33,t34,t35,t36,t37,t38,t39,t40;
+	double t41,t42,t43,t44,t45,t46,t47,t48,t49,t50,t51,t52,t53,t54,t55,t56,t57,t58,t59,t60,t61,t62,t63,t64,t65,t66,t67,t68,t69,t70,t71,t72,t73,t74,t75,t76,t77,t78,t79,t80;
+	double t81,t82,t83,t84,t85,t86,t87,t88,t89,t90,t91,t92,t93,t94,t95,t96,t97,t98,t99,t100,t101,t102,t103,t104,t105,t106,t107,t108,t109,t110,t111,t112,t113,t115,t116,t117,t118,t119,t120;
+	double t121,t122,t123,t124,t125,t126,t127,t128,t129,t130,t131,t132,t133,t134,t135,t136,t137,t138,t139,t140,t141,t142,t143,t144,t145,t146,t147,t148,t149,t150,t151,t152,t153,t154,t155,t156,t157,t158,t159,t160;
+	double t161,t162,t163,t164,t165,t166,t167,t168,t169,t170,t171,t172,t173,t174,t175,t176,t177,t178,t179,t180,t181,t182,t183,t184,t186,t187,t188,t189,t190,t191,t192,t193,t194,t195,t196,t197,t198,t199;
+	double t201,t202,t203,t204,t206,t207,t208,t209,t210,t211,t212,t213,t215,t216,t217,t218,t219,t220,t221,t222,t223,t224,t225,t226,t227,t228,t229,t230,t231,t232,t233,t234,t235,t236,t237,t238,t239,t240;
+	double t241,t242,t243,t244,t245,t246,t247,t248,t249,t250,t251,t252,t253,t254,t255,t256,t257,t258,t259,t260,t261,t262,t263,t264,t265,t267,t268,t269,t270,t272,t273,t274,t275,t276,t277,t278,t279,t280;
+	double t281,t282,t283,t284,t285,t286,t288,t289,t290,t291,t292,t295,t296,t297,t298,t299,t300,t301,t303,t304,t305,t307,t308,t310,t311,t312,t313,t314,t315,t316,t317,t318,t319,t320;
+	double t321,t322,t323,t324,t325,t326,t327,t328,t329,t330,t331,t332,t334,t335,t336,t337,t338,t339,t340,t341,t342,t344,t345,t346,t347,t348,t349,t350,t351,t352,t353,t354,t355,t356,t358,t359,t360;
+	double t361,t362,t363,t364,t365,t366,t367,t368,t369,t370,t371,t372,t373,t374,t375,t376,t377,t378,t379,t380,t381,t382,t383,t384,t385,t386,t387,t389,t390,t391,t393,t394,t395,t396,t397,t398;
+	double t401,t402,t403,t404,t405,t406,t407,t408,t409,t410,t411,t412,t413,t414,t415,t416,t417,t418,t419,t421,t422,t423,t424,t425,t426,t427,t428,t429,t430,t431,t432,t433,t434,t436,t437,t438,t439,t440;
+	double t441,t442,t443,t444,t445,t446,t447,t448,t450,t451,t453,t454,t455,t456,t457,t458,t459,t461,t462,t463,t464,t465,t466,t468,t469,t470,t471,t474,t475,t478,t480;
+	double t482,t483,t484,t485,t488,t489,t490,t492,t493,t495,t497,t498,t499,t501,t502,t503,t504,t505,t507,t508,t509,t510,t511,t512,t513,t515,t518,t520;
+	double t522,t525,t527,t528,t529,t530,t532,t533,t534,t535,t536,t538,t539,t541,t542,t544,t545,t546,t547,t548,t549,t550,t551,t552,t553,t554,t555,t556,t557,t560;
+	double t561,t562,t563,t564,t567,t568,t571,t573,t575,t576,t578,t579,t583,t590,t591,t594,t595,t596,t597,t598,t600;
+	double t601,t602,t604,t606,t607,t608,t611,t613,t615,t616,t617,t619,t621,t623,t624,t625,t626,t627,t629,t630,t632,t633,t634,t638,t639,t640;
+	double t641,t642,t643,t644,t645,t647,t648,t649,t650,t651,t652,t653,t654,t655,t656,t657,t658,t659,t660,t662,t663,t665,t666,t667,t668,t670,t671,t672,t673,t674,t675,t676,t679,t680;
+	double t682,t683,t684,t685,t686,t688,t689,t690,t691,t693,t694,t695,t696,t697,t698,t699,t700,t701,t702,t704,t705,t708,t709,t711,t712,t713,t714,t717,t718,t719;
+	double t721,t722,t723,t726,t727,t728,t730,t733,t734,t735,t736,t737,t738,t739,t740,t741,t744,t745,t746,t749,t750,t752,t753,t754,t755,t757,t758,t759,t760;
+	double t761,t762,t763,t764,t766,t767,t768,t770,t771,t772,t773,t774,t775,t776,t777,t778,t780,t781,t782,t785,t786,t789,t790,t791,t792,t793,t794,t795,t796,t797,t798,t800;
+	double t801,t806,t807,t808,t809,t811,t812,t817,t818,t819,t821,t822,t824,t827,t828,t830,t834,t835,t837,t840;
+	double t842,t843,t844,t845,t846,t849,t850,t853,t854,t855,t857,t858,t859,t860,t863,t864,t867,t868,t869,t873,t874,t877,t878,t879,t880;
+	double t884,t888,t891,t894,t900,t901,t903,t904,t907,t908,t909,t911,t914,t915,t916,t919,t920;
+	double t923,t924,t925,t926,t927,t929,t932,t935,t937,t939,t942,t943,t944,t945,t947,t948,t949,t950,t952,t953,t954,t955,t956,t957;
+	double t961,t964,t965,t966,t967,t968,t969,t971,t972,t974,t977,t978,t981,t983,t987,t988,t992,t993,t994,t997,t998;
+	double t1001,t1003,t1005,t1006,t1009,t1010,t1012,t1013,t1015,t1016,t1017,t1018,t1020,t1021,t1029,t1031,t1032,t1033,t1040;
+	double t1041,t1042,t1044,t1047,t1050,t1054,t1055,t1057,t1058,t1063,t1068,t1069,t1070,t1079,t1080;
+	double t1088,t1089,t1091,t1092,t1094,t1096,t1101,t1102,t1103,t1104,t1105,t1108,t1112,t1113,t1118,t1119,t1120;
+	double t1121,t1122,t1123,t1124,t1125,t1126,t1127,t1128,t1129,t1130,t1132,t1133,t1134,t1135,t1138,t1139,t1140,t1141,t1142,t1145,t1146,t1148,t1149,t1150,t1153,t1154,t1156,t1157,t1158,t1159;
+	double t1161,t1162,t1165,t1166,t1170,t1171,t1172,t1173,t1175,t1176,t1178,t1180,t1181,t1182,t1185,t1189,t1192,t1193,t1195,t1196,t1199;
+	double t1201,t1203,t1209,t1210,t1211,t1213,t1214,t1218,t1221,t1224,t1225,t1226,t1228,t1233,t1234,t1235,t1236,t1237,t1240;
+	double t1241,t1242,t1243,t1244,t1245,t1248,t1251,t1252,t1257,t1258,t1259,t1260,t1263,t1268,t1269,t1272,t1280;
+	double t1282,t1283,t1284,t1285,t1287,t1288,t1289,t1292,t1293,t1296,t1297,t1300,t1304,t1307,t1310,t1311,t1312,t1316,t1317,t1320;
+	double t1321,t1323,t1328,t1330,t1331,t1332,t1333,t1336,t1338,t1343,t1344,t1346,t1349,t1350,t1354;
+	double t1366,t1369,t1370,t1371,t1376,t1378,t1380,t1383,t1386,t1387,t1388,t1391,t1393,t1399;
+	double t1411,t1412,t1420,t1427;
+	double t1450,t1456,t1468,t1472,t1474,t1478;
+	double t1504,t1511;
+	double t1545;
+	double t1564,t1583;
+
+
+	/* del_rho = sin(ny*Pi*y)*cos(nx*Pi*x)  n=nx gives only non-zero terms*/ 
+	n = 1; 
+	/* only one n in Fourier series because  del_rho has cos term */ 
+	nx = n; 
+
+	self->C1A = 0;
+	/****************************************************************************************/
+	t1 = nx * 0.3141592654e1;
+	t2 = sin(t1);
+	t3 = nx * t2;
+	t4 = n * n;
+	t5 = t4 * t4;
+	t6 = 0.3141592654e1 * 0.3141592654e1;
+	t8 = t3 * t5 * t6;
+	t9 = self->ZA * self->xc;
+	t12 = exp( self->xc * n * 0.3141592654e1);
+	t13 = t12 * t12;
+	t15 = n * 0.3141592654e1;
+	t16 = exp(t15);
+	t17 = t16 * t16;
+	t18 = t17 * t16;
+	t19 = self->ZB * t13 * t18;
+	t20 = t9 * t19;
+	t23 = self->ZA * self->ZA;
+	t24 = nx * nx;
+	t25 = t24 * nx;
+	t26 = t23 * t25;
+	t28 = t13 * t13;
+	t29 = t28 * t13;
+	t33 = nx * self->ZB;
+	t34 = t1 * self->xc;
+	t35 = sin(t34);
+	t36 = t4 * n;
+	t37 = t35 * t36;
+	t38 = t33 * t37;
+	t39 = 0.3141592654e1 * self->ZA;
+	t40 = t13 * t12;
+	t41 = t17 * t40;
+	t45 = self->ZB * self->ZB;
+	t46 = t45 * t24;
+	t47 = t46 * t4;
+	t48 = 0.3141592654e1 * self->xc;
+	t49 = t13 * t17;
+	t53 = self->xc * self->xc;
+	t54 = t36 * t53;
+	t56 = t54 * t6 * t45;
+	t57 = cos(t34);
+	t58 = t57 * t24;
+	t59 = t28 * t12;
+	t60 = t17 * t59;
+	t61 = t58 * t60;
+	t64 = t25 * t2;
+	t65 = t64 * t15;
+	t72 = nx * t23;
+	t74 = t72 * t2 * t5;
+	t75 = t6 * t53;
+	t76 = t16 * t29;
+	t80 = t23 * n;
+	t81 = t80 * 0.3141592654e1;
+	t82 = t18 * t28;
+	t86 = nx * t5;
+	t87 = t23 * t6;
+	t89 = self->xc * t2;
+	t90 = t13 * t18;
+	t91 = t89 * t90;
+	t94 = t28 * t28;
+	t96 = t24 * n;
+	t98 = t4 * t45;
+	t99 = t98 * 0.3141592654e1;
+	t100 = t58 * t41;
+	t104 = 0.3141592654e1 * t25;
+	t105 = self->ZA * n * t104;
+	t106 = t2 * self->ZB;
+	t110 = t17 * t17;
+	t111 = self->ZA * t110;
+	t116 = n * t28;
+	t122 = t64 * t4 * t6;
+	t126 = t23 * t29 * t4;
+	t128 = t24 * self->xc;
+	t132 = t36 * t23;
+	t133 = t6 * t57;
+	t135 = t128 * t41;
+	t138 = t6 * self->xc;
+	t142 = t72 * t2;
+	t147 = 0.4e1 * t8 * t20 - 0.2e1 * t26 * t2 * t16 * t29 - 0.8e1 * t38 * t39 * t41 + 0.4e1 * t47 * t48 * t49 - 0.8e1 * t56 * t61 - 0.4e1 * t65 * t20 + 0.2e1 * t26 * t2 * t18 * t28 - 0.4e1 * t74 * t75 * t76 - 0.2e1 * t81 * t64 * t82 - 0.4e1 * t86 * t87 * t91 - t23 * t94 * t96 + 0.8e1 * t99 * t100 - 0.2e1 * t105 * t106 * t82 - 0.4e1 * t38 * t48 * t111 * t12 + 0.2e1 * t116 * self->ZB * t111 * t24 + 0.4e1 * t122 * t20 + 0.4e1 * t126 * 0.3141592654e1 * t17 * t128 + 0.8e1 * t132 * t133 * t135 + 0.4e1 * t74 * t138 * t76 - 0.2e1 * t142 * t4 * t18 * t28;
+	t149 = self->ZA * t25 * t2;
+	t150 = self->ZB * t28;
+	t154 = t35 * t5;
+	t155 = t72 * t154;
+	t156 = t75 * t41;
+	t159 = nx * self->ZA;
+	t160 = t2 * t36;
+	t161 = t159 * t160;
+	t162 = 0.3141592654e1 * self->ZB;
+	t163 = t28 * t16;
+	t167 = t23 * t57;
+	t168 = t167 * t24;
+	t169 = n * t110;
+	t170 = t169 * t40;
+	t173 = self->ZA * self->ZB;
+	t174 = t173 * t90;
+	t177 = t36 * 0.3141592654e1;
+	t181 = t80 * t104;
+	t184 = n * t17;
+	t188 = t17 * t29;
+	t190 = t4 * 0.3141592654e1;
+	t191 = t190 * t24;
+	t206 = t138 * t60;
+	t209 = t23 * t4;
+	t211 = t209 * t6 * t25;
+	t212 = t89 * t76;
+	t216 = self->ZB * t16 * t29;
+	t217 = t9 * t216;
+	t220 = self->ZB * t110;
+	t221 = self->ZA * t24;
+	t222 = t221 * n;
+	t225 = t132 * t75;
+	t232 = t45 * t28;
+	t233 = t110 * t24;
+	t234 = t233 * n;
+	t236 = t209 * 0.3141592654e1;
+	t237 = t17 * self->xc;
+	t239 = t237 * t13 * t24;
+	t242 = -0.2e1 * t149 * t150 * t16 - 0.8e1 * t155 * t156 - 0.2e1 * t161 * t162 * t163 + 0.2e1 * t168 * t170 + 0.2e1 * t65 * t174 - 0.2e1 * t142 * t177 * t76 + 0.4e1 * t181 * t91 - 0.4e1 * t168 * t184 * t59 - 0.4e1 * t188 * t23 * t191 + 0.4e1 * t38 * t48 * self->ZA * t17 * t40 + 0.4e1 * t49 * t23 * t191 + 0.2e1 * t26 * t2 * t13 * t18 - 0.8e1 * t155 * t206 + 0.4e1 * t211 * t212 - 0.4e1 * t8 * t217 + 0.2e1 * t220 * t222 - 0.8e1 * t225 * t100 + 0.2e1 * t142 * t4 * t16 * t29 + t232 * t234 - 0.4e1 * t236 * t239;
+	t244 = nx * t45;
+	t245 = t244 * t37;
+	t246 = t110 * t40;
+	t251 = t237 * t59;
+	t256 = t64 * t90;
+	t260 = t36 * t45 * t133;
+	t263 = t45 * t57;
+	t264 = t263 * t24;
+	t265 = t169 * t12;
+	t269 = t6 * t36;
+	t270 = t17 * t24;
+	t274 = t110 * t13;
+	t276 = t190 * t128;
+	t279 = nx * t36;
+	t281 = t28 * t40;
+	t282 = t281 * t35;
+	t286 = t138 * t41;
+	t289 = t75 * t60;
+	t296 = t190 * t173;
+	t305 = t86 * t45 * t35;
+	t312 = t33 * t154;
+	t313 = t6 * self->ZA;
+	t324 = t232 * t270;
+	t327 = -0.2e1 * t245 * t48 * t246 + 0.4e1 * t159 * t37 * t162 * t251 + 0.4e1 * t209 * t75 * t256 + 0.8e1 * t260 * t135 + 0.2e1 * t264 * t265 + 0.32e2 * t9 * t150 * t269 * t270 + 0.4e1 * t274 * t23 * t276 + 0.2e1 * t279 * t45 * t282 * t48 + 0.8e1 * t155 * t286 + 0.8e1 * t155 * t289 - 0.8e1 * t150 * self->ZA * t96 * t17 + 0.8e1 * t296 * t61 - 0.2e1 * t105 * t106 * t163 - 0.2e1 * t81 * t256 - 0.8e1 * t305 * t156 - 0.4e1 * t33 * t282 * t177 * t9 - 0.16e2 * t312 * t313 * t237 * t40 - 0.4e1 * t168 * t184 * t40 + 0.2e1 * t168 * t265 + 0.16e2 * t269 * t53 * t324;
+	t328 = t3 * t4;
+	t331 = t72 * t37;
+	t332 = t48 * t60;
+	t335 = n * t94;
+	t345 = t72 * t35;
+	t349 = t173 * t57;
+	t355 = t53 * t17;
+	t364 = t54 * t6 * self->ZB;
+	t365 = t28 * t17;
+	t369 = self->xc * self->ZB;
+	t370 = t269 * t369;
+	t371 = self->ZA * t57;
+	t373 = t371 * t270 * t40;
+	t385 = nx * t35;
+	t396 = t4 * self->xc;
+	t397 = t396 * t162;
+	t415 = t37 * t48;
+	t418 = -0.32e2 * t364 * t365 * t221 - 0.16e2 * t370 * t373 - 0.4e1 * t331 * t48 * t41 + 0.4e1 * t86 * t23 * t53 * t6 * t2 * t90 + 0.2e1 * t385 * t177 * t23 * self->xc * t246 + 0.16e2 * t132 * t53 * t6 * t28 * t270 - 0.4e1 * t397 * t371 * t233 * t12 - 0.12e2 * t173 * t58 * t190 * t251 + 0.2e1 * t385 * t36 * 0.3141592654e1 * t23 * self->xc * t59 - 0.8e1 * t99 * t61 - 0.2e1 * t244 * t59 * t415;
+	t427 = t371 * t270 * t59;
+	t439 = t209 * t48;
+	t440 = t110 * t12;
+	t441 = t58 * t440;
+	t447 = t36 * self->xc;
+	t455 = t48 * t440;
+	t471 = self->ZB * t17;
+	t492 = 0.12e2 * t397 * t373 - 0.4e1 * t122 * t217 + 0.16e2 * t364 * t427 + 0.16e2 * t312 * t313 * t355 * t40 - 0.8e1 * t279 * t39 * t35 * self->ZB * t60 + 0.2e1 * t439 * t441 - 0.2e1 * t81 * t64 * t163 + 0.8e1 * t447 * t87 * t61 + 0.2e1 * t23 * t59 * t57 * t276 + 0.2e1 * t245 * t455 - 0.4e1 * t349 * t96 * t440 - 0.16e2 * t370 * t427 + 0.4e1 * t181 * t212 - 0.16e2 * t365 * t23 * t269 * t128 + 0.16e2 * t86 * t138 * self->ZA * t35 * t471 * t59 + 0.8e1 * t305 * t289 - 0.4e1 * t439 * t100 + 0.2e1 * self->ZB * t25 * t2 * self->ZA * t18 * t28 + 0.2e1 * t142 * t4 * t28 * t16 - 0.8e1 * t56 * t100;
+	t499 = self->ZA * t53 * t19;
+	t505 = t396 * 0.3141592654e1;
+	t518 = t173 * t53 * t16 * t29;
+	t533 = t23 * t28;
+	t535 = t188 * t45;
+	t538 = t24 * t4;
+	t545 = t3 * t177;
+	t546 = t173 * t76;
+	t555 = t45 * t110;
+	t557 = t72 * t160;
+	t561 = -0.8e1 * t225 * t61 - 0.2e1 * t161 * t162 * t82 + t533 * t234 + 0.4e1 * t535 * t191 + 0.4e1 * t167 * t538 * t332 + 0.4e1 * t349 * t96 * t60 + 0.2e1 * t545 * t546 - 0.2e1 * t264 * t170 + 0.4e1 * t397 * t281 * self->ZA * t58 - t555 * t96 - 0.4e1 * t557 * t48 * t76;
+	t567 = t396 * 0.3141592654e1 * t45;
+	t568 = t58 * t246;
+	t597 = t58 * n;
+	t615 = t13 * t45;
+	t616 = t615 * t233;
+	t619 = t94 * t45;
+	t621 = t45 * t59;
+	t625 = 0.2e1 * t149 * t216 + 0.2e1 * t567 * t568 - 0.16e2 * t269 * self->xc * t324 - 0.2e1 * t236 * self->xc * t281 * t58 - 0.2e1 * t142 * t177 * t90 - 0.8e1 * t567 * t100 + 0.2e1 * t65 * t546 - 0.8e1 * t305 * t206 + 0.2e1 * n * t45 * t281 * t57 * t24 - t23 * t110 * t96 - 0.8e1 * t296 * t100 + 0.2e1 * t23 * t281 * t597 + 0.4e1 * t545 * t20 + 0.2e1 * t159 * t2 * t4 * self->ZB * t163 - 0.4e1 * t557 * t48 * t90 + 0.4e1 * t122 * t518 + 0.8e1 * t263 * t538 * t332 - 0.4e1 * t505 * t616 - t619 * t96 - 0.2e1 * t621 * t57 * t276;
+	t626 = t49 * t45;
+	t660 = t29 * t45;
+	t685 = 0.2e1 * t545 * t174 - 0.4e1 * t126 * 0.3141592654e1 * t24 * self->xc - 0.4e1 * t47 * t48 * t188 + 0.4e1 * t505 * t660 * t24 - 0.2e1 * t142 * t177 * t163 - 0.2e1 * t142 * t4 * t13 * t18 + 0.8e1 * t260 * t128 * t60 - 0.2e1 * t328 * t546 - 0.2e1 * t26 * t2 * t28 * t16 + 0.4e1 * t545 * t217 - 0.4e1 * t209 * t138 * t256;
+	t690 = t6 * 0.3141592654e1;
+	t691 = self->ZA * t690;
+	t693 = t24 * t24;
+	t694 = t693 * self->xc;
+	t695 = t188 * t694;
+	t698 = t23 * self->ZA;
+	t699 = t698 * t690;
+	t700 = t699 * t5;
+	t704 = t5 * t4;
+	t705 = t691 * t704;
+	t709 = t691 * t5;
+	t713 = t5 * n;
+	t714 = t713 * self->ZB;
+	t718 = t698 * t6;
+	t719 = t713 * t28;
+	t722 = t699 * t704;
+	t726 = t713 * t94;
+	t733 = t713 * t45;
+	t736 = t87 * t36;
+	t740 = -0.4e1 * t691 * t98 * t695 + 0.8e1 * t700 * t270 * t13 + 0.4e1 * t705 * t660 * self->xc + 0.8e1 * t709 * t660 * t128 + 0.2e1 * t87 * t714 * t110 + t718 * t719 * t110 - 0.4e1 * t722 * t237 * t13 - t313 * t726 * t45 - 0.4e1 * t699 * t704 * self->xc * t29 + t313 * t733 * t28 + 0.4e1 * t736 * t150 * t233;
+	t746 = t313 * t36;
+	t752 = t6 * t6;
+	t753 = t23 * t752;
+	t759 = t698 * t752;
+	t760 = t759 * t36;
+	t761 = t17 * t693;
+	t762 = self->xc * t28;
+	t763 = t761 * t762;
+	t766 = t87 * t713;
+	t773 = t699 * t4;
+	t774 = t110 * t693;
+	t775 = self->xc * t13;
+	t785 = t704 * t17;
+	t789 = -0.16e2 * t736 * t150 * t270 + t718 * t116 * t693 - 0.2e1 * t746 * t555 * t24 + 0.4e1 * t705 * t535 + 0.64e2 * t753 * t713 * t17 * t150 * t128 - 0.16e2 * t760 * t763 + 0.2e1 * t766 * t150 * t110 + 0.4e1 * t722 * t274 * self->xc + 0.4e1 * t773 * t774 * t775 - 0.8e1 * t766 * t150 * t17 + 0.8e1 * t700 * t233 * t775 + 0.4e1 * t699 * t785 * t13;
+	t791 = t691 * t4;
+	t792 = t45 * t693;
+	t793 = t49 * t792;
+	t796 = t759 * t713;
+	t797 = t53 * t28;
+	t798 = t270 * t797;
+	t801 = t87 * n;
+	t818 = t5 * t36;
+	t819 = t753 * t818;
+	t827 = t753 * t36 * self->ZB;
+	t830 = self->xc * t45;
+	t834 = -0.4e1 * t791 * t793 + 0.32e2 * t796 * t798 + 0.2e1 * t801 * self->ZB * t693 * t110 + 0.2e1 * t718 * t36 * t28 * t24 - 0.8e1 * t700 * t128 * t29 - 0.8e1 * t700 * t239 - 0.8e1 * t801 * t150 * t761 + 0.32e2 * t819 * t365 * t369 - 0.64e2 * t753 * t714 * t798 + 0.32e2 * t827 * t763 + 0.4e1 * t705 * t830 * t49;
+	t842 = self->xc * t29;
+	t843 = t270 * t842;
+	t849 = t759 * t818;
+	t853 = t691 * t396;
+	t857 = t691 * t5 * t45;
+	t869 = t313 * n;
+	t874 = -0.2e1 * t718 * t36 * t94 * t24 - 0.4e1 * t773 * t761 * t29 + 0.8e1 * t700 * t843 + 0.2e1 * t87 * t726 * self->ZB + 0.16e2 * t849 * t797 * t17 + 0.4e1 * t853 * t793 + 0.8e1 * t857 * t239 + 0.2e1 * t801 * t150 * t693 - 0.8e1 * t700 * t270 * t29 - 0.8e1 * t709 * t49 * t46 - t869 * t619 * t693 + t869 * t232 * t693;
+	t877 = self->ZA * t752;
+	t878 = t877 * t818;
+	t911 = 0.16e2 * t878 * t53 * t45 * t365 - 0.4e1 * t699 * t785 * t29 - 0.4e1 * t705 * t188 * t830 + 0.2e1 * t801 * t94 * t693 * self->ZB - 0.8e1 * t857 * t843 - t718 * t726 + 0.4e1 * t773 * t761 * t13 - 0.4e1 * t705 * t775 * t555 + 0.2e1 * t746 * t232 * t233 - 0.16e2 * t878 * t830 * t365 - 0.2e1 * t746 * t619 * t24;
+	t916 = t110 * t28;
+	t945 = t28 * t693 * t45 * t17;
+	t948 = 0.32e2 * t877 * t733 * t798 + 0.2e1 * t718 * t36 * t916 * t24 - 0.4e1 * t705 * t626 + t718 * n * t916 * t693 - t869 * t792 * t110 - 0.4e1 * t773 * t761 * t775 + t718 * t719 + 0.2e1 * t746 * t232 * t24 - 0.16e2 * t849 * t365 * self->xc - t718 * t713 * t110 - 0.4e1 * t773 * t694 * t29 + 0.16e2 * t877 * t54 * t945;
+	t974 = t761 * t797;
+	t987 = 0.4e1 * t773 * t695 + 0.4e1 * t736 * t150 * t24 + 0.4e1 * t722 * t842 * t17 - 0.16e2 * t877 * t447 * t945 + 0.2e1 * t87 * t714 * t28 + t313 * t713 * t916 * t45 - 0.4e1 * t853 * t615 * t774 - 0.32e2 * t877 * t713 * self->xc * t324 + 0.16e2 * t760 * t974 + 0.4e1 * t736 * t94 * t24 * self->ZB + t869 * t792 * t916 - 0.8e1 * t691 * t5 * self->xc * t616;
+	t1021 = -t718 * t169 * t693 - 0.32e2 * t827 * t974 + 0.2e1 * t801 * t150 * t774 + 0.4e1 * t791 * t188 * t792 + 0.4e1 * t736 * t220 * t24 + 0.4e1 * t791 * t842 * t792 + 0.8e1 * t709 * t660 * t270 - t718 * t335 * t693 - 0.2e1 * t718 * t36 * t110 * t24 - 0.32e2 * t819 * t797 * t471 - t313 * t733 * t110 - 0.32e2 * t796 * t270 * t762;
+
+	self->C2A = (t147 - 0.4e1 * t65 * t217 + t418 + 0.2e1 * t150 * t222 + t327 - 0.2e1 * t149 * t19 + 0.2e1 * t335 * self->ZB * t24 * self->ZA - 0.16e2 * t312 * t313 * t355 * t59 - 0.4e1 * t281 * self->ZB * self->ZA * t597 - 0.2e1 * t505 * t45 * t281 * t58 - 0.4e1 * t211 * t2 * t53 * t76 + 0.8e1 * t305 * t286 - 0.4e1 * t122 * t499 - 0.4e1 * t331 * t332 + 0.8e1 * t345 * t177 * t60 - 0.2e1 * t142 * t177 * t82 + 0.2e1 * t72 * t281 * t415 + 0.4e1 * t349 * t96 * t41 - 0.2e1 * t81 * t64 * t76 + 0.2e1 * t58 * t80 * t59 + 0.8e1 * t345 * t177 * t41 - 0.4e1 * t8 * t499 + t242 + 0.4e1 * t8 * t518 + t625 + t685 + 0.2e1 * t328 * t174 + 0.2e1 * t331 * t455 - 0.2e1 * t33 * t2 * t4 * self->ZA * t82 - 0.4e1 * t626 * t191 + 0.16e2 * t364 * t373 - 0.2e1 * t621 * t597 - 0.2e1 * t439 * t568 + t492 + t533 * t96 + t232 * t96 + 0.2e1 * t567 * t441 + t561) / (t740 + t789 + t834 + t874 + t911 + t948 + t987 + t1021);
+	/****************************************************************************************/
+	t1 = n * n;
+	t2 = t1 * n;
+	t3 = t2 * 0.3141592654e1;
+	t4 = t3 * self->xc;
+	t5 = self->ZB * self->ZB;
+	t7 = exp(n * 0.3141592654e1);
+	t8 = t7 * t7;
+	t9 = t5 * t8;
+	t12 = exp( self->xc * n * 0.3141592654e1);
+	t13 = t12 * t12;
+	t14 = t13 * t13;
+	t15 = t14 * t13;
+	t19 = nx * nx;
+	t21 = nx * 0.3141592654e1;
+	t22 = sin(t21);
+	t23 = t19 * nx * t22;
+	t24 = t23 * 0.3141592654e1;
+	t25 = self->ZA * self->ZB;
+	t26 = t7 * t15;
+	t27 = t25 * t26;
+	t30 = t21 * self->xc;
+	t31 = sin(t30);
+	t32 = t31 * nx;
+	t33 = t32 * n;
+	t34 = self->ZA * self->ZA;
+	t35 = t8 * t8;
+	t36 = t34 * t35;
+	t40 = t2 * t34;
+	t41 = 0.3141592654e1 * t8;
+	t42 = t41 * t15;
+	t45 = t1 * t5;
+	t46 = t14 * t14;
+	t49 = t19 * t5;
+	t51 = t19 * t46;
+	t53 = t19 * t34;
+	t55 = t8 * t7;
+	t56 = t13 * t55;
+	t57 = t25 * t56;
+	t60 = t2 * nx;
+	t61 = 0.3141592654e1 * 0.3141592654e1;
+	t63 = t60 * t31 * t61;
+	t64 = self->xc * self->xc;
+	t65 = self->ZA * t64;
+	t66 = self->ZB * t8;
+	t67 = t14 * t12;
+	t68 = t66 * t67;
+	t69 = t65 * t68;
+	t72 = -0.4e1 * t4 * t9 * t15 + 0.4e1 * t24 * t27 + 0.4e1 * t33 * t36 * t12 - 0.4e1 * t40 * t42 - t45 * t46 + t45 * t14 - t49 * t14 + t51 * t5 - t53 * t14 + 0.4e1 * t24 * t57 + 0.32e2 * t63 * t69;
+	t73 = t1 * nx;
+	t75 = t73 * t31 * 0.3141592654e1;
+	t76 = t8 * t67;
+	t77 = t25 * t76;
+	t80 = t1 * t1;
+	t81 = t80 * t34;
+	t83 = t61 * t14;
+	t87 = t1 * t19;
+	t88 = cos(t30);
+	t90 = t87 * t88 * t61;
+	t91 = t5 * t64;
+	t92 = t13 * t12;
+	t93 = t8 * t92;
+	t94 = t91 * t93;
+	t100 = self->ZB * t64 * self->ZA * t8 * t92;
+	t103 = n * t19;
+	t105 = t103 * t88 * 0.3141592654e1;
+	t106 = self->ZA * self->xc;
+	t107 = self->ZB * t35;
+	t109 = t106 * t107 * t12;
+	t112 = t34 * self->xc;
+	t113 = t112 * t93;
+	t116 = t35 * t14;
+	t118 = t1 * self->ZA;
+	t119 = self->ZB * t14;
+	t122 = t1 * t46;
+	t125 = t19 * self->ZB;
+	t126 = t35 * self->ZA;
+	t127 = t125 * t126;
+	t129 = t1 * self->ZB;
+	t132 = -0.16e2 * t75 * t77 + 0.16e2 * t81 * t64 * t83 * t8 + 0.16e2 * t90 * t94 - 0.32e2 * t90 * t100 + 0.8e1 * t105 * t109 - 0.8e1 * t75 * t113 + t45 * t116 + 0.2e1 * t118 * t119 + 0.2e1 * t122 * t25 - 0.2e1 * t127 + 0.2e1 * t129 * t126;
+	t134 = t1 * t34;
+	t136 = t34 * t64;
+	t137 = t136 * t76;
+	t141 = t91 * t76;
+	t145 = t103 * t34;
+	t146 = 0.3141592654e1 * self->xc;
+	t147 = t8 * t13;
+	t153 = t14 * self->ZA;
+	t156 = self->xc * t5;
+	t157 = t156 * t93;
+	t160 = t103 * t5;
+	t162 = t146 * t8 * t15;
+	t166 = t34 * t7 * t15;
+	t169 = t134 * t116 - 0.16e2 * t63 * t137 - t49 * t116 - 0.16e2 * t63 * t141 - t53 * t116 + 0.4e1 * t145 * t146 * t147 - 0.2e1 * t51 * t25 - 0.2e1 * t125 * t153 - 0.16e2 * t75 * t157 + 0.4e1 * t160 * t162 - 0.4e1 * t24 * t166;
+	t170 = t106 * t68;
+	t177 = t35 * t92;
+	t178 = t112 * t177;
+	t181 = t156 * t76;
+	t186 = t35 * t12;
+	t187 = t112 * t186;
+	t193 = t5 * 0.3141592654e1;
+	t206 = t34 * t14;
+	t207 = t206 * t7;
+	t210 = -0.32e2 * t63 * t170 + 0.32e2 * t90 * t170 + 0.8e1 * t75 * t109 + 0.4e1 * t105 * t178 - 0.16e2 * t75 * t181 - 0.16e2 * t90 * t113 - 0.4e1 * t75 * t187 + 0.16e2 * t90 * t141 - 0.4e1 * t103 * t15 * t193 * self->xc + 0.16e2 * t73 * t22 * t34 * t146 * t26 + 0.4e1 * t32 * n * t34 * t67 + 0.4e1 * t24 * t207;
+	t217 = t106 * t66 * t92;
+	t226 = t88 * t19 * n;
+	t227 = 0.3141592654e1 * t34;
+	t229 = t227 * self->xc * t67;
+	t232 = t73 * t31;
+	t234 = t146 * t5 * t67;
+	t238 = t61 * self->ZB;
+	t239 = t14 * t8;
+	t240 = t238 * t239;
+	t243 = t136 * t93;
+	t246 = -0.8e1 * t33 * t25 * t186 + 0.32e2 * t90 * t217 - t45 * t35 + t53 * t35 - t134 * t35 - t134 * t46 + t134 * t14 - 0.4e1 * t226 * t229 + 0.4e1 * t232 * t234 + 0.32e2 * t87 * t65 * t240 + 0.16e2 * t63 * t243;
+	t247 = t14 * t92;
+	t249 = t227 * t247 * self->xc;
+	t254 = t73 * t22;
+	t259 = t60 * t22 * t61;
+	t260 = t112 * t26;
+	t264 = t146 * t247 * t5;
+	t268 = self->xc * t14;
+	t274 = t5 * t14;
+	t275 = t274 * t8;
+	t280 = n * nx;
+	t281 = t280 * t22;
+	t282 = t55 * t14;
+	t283 = t25 * t282;
+	t290 = self->ZA * t247 * self->xc * self->ZB;
+	t295 = t22 * nx * t1 * 0.3141592654e1;
+	t298 = -0.4e1 * t232 * t249 + 0.8e1 * t105 * t217 - 0.4e1 * t254 * t227 * t26 - 0.8e1 * t259 * t260 - 0.4e1 * t232 * t264 - 0.16e2 * t81 * t61 * t268 * t8 + 0.16e2 * t80 * t64 * t61 * t275 - 0.4e1 * t232 * t229 + 0.8e1 * t281 * t283 - 0.4e1 * t105 * t187 + 0.8e1 * t75 * t290 + 0.4e1 * t295 * t27;
+	t301 = t61 * t5;
+	t307 = t87 * t34;
+	t312 = t61 * self->xc;
+	t313 = t312 * t239;
+	t317 = t34 * t55 * t14;
+	t329 = self->ZB * t13 * t55;
+	t330 = t65 * t329;
+	t337 = -0.16e2 * t87 * t64 * t301 * t239 - 0.32e2 * t90 * t69 - 0.16e2 * t307 * t64 * t61 * t239 + 0.16e2 * t307 * t313 + 0.4e1 * t24 * t317 + t53 * t46 + t49 * t35 - 0.32e2 * t63 * t100 - 0.4e1 * t280 * t31 * t34 * t247 + 0.8e1 * t259 * t330 - 0.4e1 * t280 * t31 * t247 * t5;
+	t340 = t5 * t35;
+	t344 = t25 * t93;
+	t356 = t41 * t13;
+	t360 = t23 * n * t61;
+	t363 = t25 * t64 * t7 * t15;
+	t366 = t156 * t177;
+	t369 = t14 * t7;
+	t370 = t25 * t369;
+	t373 = t156 * t186;
+	t378 = 0.4e1 * t24 * t283 + 0.4e1 * t33 * t340 * t12 - 0.16e2 * t75 * t344 - 0.4e1 * t280 * t31 * t5 * t67 + 0.8e1 * t33 * t25 * t247 + 0.32e2 * t63 * t217 + 0.4e1 * t40 * t356 - 0.8e1 * t360 * t363 + 0.4e1 * t75 * t366 + 0.4e1 * t295 * t370 - 0.4e1 * t75 * t373 - 0.4e1 * t105 * t366;
+	t382 = t112 * t76;
+	t387 = t80 * t61;
+	t391 = t136 * t26;
+	t409 = 0.16e2 * t63 * t382 + 0.4e1 * t226 * t234 - 0.16e2 * t387 * self->xc * t275 + 0.8e1 * t259 * t391 - 0.16e2 * t105 * t344 + 0.4e1 * t226 * t264 - 0.8e1 * t105 * t170 + 0.16e2 * t232 * t193 * t76 + 0.8e1 * t360 * t330 - 0.8e1 * t105 * t290 + 0.16e2 * t90 * t243;
+	t423 = t153 * t8;
+	t426 = t34 * t13;
+	t427 = t426 * t55;
+	t430 = t34 * t8;
+	t437 = t80 * self->ZA;
+	t441 = 0.4e1 * t145 * t42 - 0.16e2 * t90 * t157 + 0.24e2 * t75 * t217 + 0.4e1 * t226 * t249 + 0.4e1 * t254 * t227 * t282 + 0.4e1 * t160 * t356 - 0.8e1 * t129 * t423 - 0.8e1 * t281 * t427 - 0.8e1 * t33 * t430 * t67 + 0.8e1 * t33 * t430 * t92 + 0.32e2 * t437 * self->ZB * t313;
+	t453 = t106 * self->ZB * t7 * t15;
+	t456 = t2 * t5;
+	t459 = t112 * t56;
+	t462 = t126 * t14;
+	t474 = t40 * 0.3141592654e1;
+	t475 = self->xc * t8;
+	t480 = t146 * t13 * t35;
+	t483 = -0.4e1 * t103 * self->xc * t193 * t147 + 0.16e2 * t87 * t61 * t156 * t239 + 0.8e1 * t259 * t453 - 0.4e1 * t456 * t356 + 0.8e1 * t259 * t459 - 0.2e1 * t125 * t462 - 0.8e1 * t281 * t207 + 0.16e2 * t295 * t459 - 0.8e1 * t60 * t22 * self->ZA * t312 * t329 + 0.4e1 * t474 * t475 * t15 + 0.4e1 * t160 * t480;
+	t497 = t136 * t56;
+	t504 = t9 * t13;
+	t509 = t475 * t13;
+	t512 = -0.8e1 * t105 * t113 - 0.4e1 * t254 * t227 * t56 + 0.8e1 * t281 * t57 + 0.4e1 * t295 * t283 + 0.2e1 * t129 * t462 + 0.4e1 * t24 * t370 - 0.8e1 * t360 * t497 - 0.4e1 * t24 * t427 - 0.4e1 * t145 * t162 + 0.4e1 * t4 * t504 - 0.8e1 * t281 * t370 - 0.4e1 * t474 * t509;
+	t528 = t5 * t13;
+	t529 = t528 * t35;
+	t532 = t106 * t329;
+	t542 = -0.16e2 * t295 * t453 - 0.32e2 * t437 * t64 * t240 + 0.8e1 * t281 * t317 + 0.24e2 * t75 * t170 - 0.4e1 * t75 * t178 + 0.8e1 * t360 * t453 - 0.4e1 * t4 * t529 - 0.16e2 * t295 * t532 - 0.8e1 * t33 * t344 - 0.16e2 * t90 * t181 + 0.4e1 * t33 * t340 * t92;
+	t557 = t146 * t15;
+	t562 = self->xc * t15;
+	t563 = t562 * t5;
+	t573 = 0.16e2 * t232 * t193 * t93 - 0.8e1 * t259 * t363 - 0.8e1 * t259 * t497 + 0.8e1 * t33 * t77 + 0.8e1 * t360 * t391 + 0.4e1 * t254 * t227 * t369 + 0.4e1 * t145 * t557 + 0.8e1 * t281 * t166 + 0.4e1 * t3 * t563 + 0.8e1 * t105 * t382 - 0.4e1 * t145 * t480 - 0.4e1 * t33 * t36 * t92;
+	t600 = 0.4e1 * t456 * t42 - 0.8e1 * t360 * t260 - 0.4e1 * t40 * t557 - 0.4e1 * t105 * t373 + 0.16e2 * t226 * t227 * t93 - 0.16e2 * t90 * t382 - 0.4e1 * t145 * t356 - 0.16e2 * t63 * t157 - 0.32e2 * t87 * t25 * t313 - 0.16e2 * t226 * t227 * t76 - 0.16e2 * t63 * t113;
+	t623 = self->xc * t13;
+	t627 = 0.8e1 * t125 * t423 - 0.8e1 * t360 * t532 + 0.16e2 * t90 * t137 - 0.4e1 * t160 * t42 + 0.16e2 * t63 * t94 + 0.16e2 * t63 * t181 - 0.8e1 * t281 * t27 - 0.8e1 * t75 * t382 + 0.8e1 * t360 * t459 + 0.4e1 * t295 * t57 + 0.16e2 * t105 * t77 + 0.4e1 * t474 * t623 * t35;
+	t632 = t61 * 0.3141592654e1;
+	t633 = t632 * t8;
+	t634 = t80 * n;
+	t638 = t632 * t634;
+	t639 = t638 * self->xc;
+	t642 = t61 * t34;
+	t643 = t122 * t19;
+	t649 = t61 * t61;
+	t650 = t649 * t1;
+	t652 = t19 * t19;
+	t653 = t14 * t652;
+	t654 = t653 * t9;
+	t657 = t14 * t1;
+	t658 = t657 * t19;
+	t665 = t632 * t34;
+	t666 = t665 * t2;
+	t667 = t8 * t19;
+	t668 = t667 * t623;
+	t674 = t665 * n;
+	t675 = t652 * self->xc;
+	t682 = 0.8e1 * t633 * t426 * t634 - 0.8e1 * t639 * t529 - 0.4e1 * t642 * t643 + 0.2e1 * t642 * t116 * t80 + 0.32e2 * t650 * t64 * t654 + 0.4e1 * t301 * t658 + 0.4e1 * t387 * t46 * self->ZA * self->ZB - 0.16e2 * t666 * t668 - 0.16e2 * t666 * t667 * t15 - 0.8e1 * t674 * t675 * t15 + 0.4e1 * t238 * t153 * t80;
+	t683 = t46 * t652;
+	t686 = t633 * t15;
+	t691 = t35 * t80;
+	t698 = t35 * t652;
+	t705 = t14 * t80;
+	t708 = t61 * t35;
+	t717 = -0.2e1 * t642 * t683 - 0.8e1 * t686 * t5 * t634 * self->xc - 0.2e1 * t301 * t691 + 0.8e1 * t638 * t563 - 0.2e1 * t642 * t691 - 0.2e1 * t642 * t698 - 0.2e1 * t301 * t698 - 0.2e1 * t301 * t683 + 0.2e1 * t642 * t705 + 0.2e1 * t708 * t274 * t80 + 0.2e1 * t301 * t653 - 0.2e1 * t642 * t80 * t46;
+	t727 = t61 * t46;
+	t737 = t649 * t34;
+	t738 = t737 * t1;
+	t739 = t8 * t652;
+	t740 = t739 * t268;
+	t746 = t61 * self->ZA;
+	t754 = t632 * n * self->xc;
+	t758 = 0.2e1 * t301 * t705 + 0.2e1 * t642 * t653 - 0.8e1 * t665 * self->xc * t634 * t15 - 0.2e1 * t727 * t5 * t80 - 0.32e2 * t650 * self->xc * t654 + 0.2e1 * t301 * t698 * t14 - 0.32e2 * t738 * t740 + 0.8e1 * t674 * t739 * t562 + 0.4e1 * t746 * t119 * t652 + 0.8e1 * t674 * t698 * t623 - 0.8e1 * t754 * t528 * t698;
+	t762 = t633 * t13;
+	t764 = t5 * n * t652;
+	t767 = t80 * t1;
+	t768 = t649 * t767;
+	t772 = t649 * self->ZA;
+	t773 = t772 * t129;
+	t777 = t35 * t1 * t19;
+	t780 = t632 * t5;
+	t781 = t780 * t15;
+	t786 = t698 * self->ZA;
+	t790 = t64 * t14;
+	t800 = t649 * t8;
+	t809 = 0.4e1 * t238 * t126 * t80 - 0.8e1 * t762 * t764 - 0.32e2 * t768 * self->xc * t275 + 0.64e2 * t773 * t740 - 0.4e1 * t301 * t777 - 0.8e1 * t781 * n * t8 * t675 + 0.4e1 * t238 * t786 + 0.32e2 * t768 * t34 * t790 * t8 - 0.8e1 * t633 * t528 * t634 + 0.8e1 * t754 * t528 * t739 + 0.128e3 * t800 * t119 * t80 * t19 * t106 + 0.8e1 * t674 * t739 * t13;
+	t812 = t649 * t80;
+	t817 = t83 * self->ZB;
+	t824 = t746 * self->ZB;
+	t828 = t800 * t14;
+	t855 = -0.64e2 * t812 * self->xc * t274 * t667 + 0.4e1 * t817 * t786 + 0.4e1 * t727 * self->ZA * t652 * self->ZB - 0.32e2 * t824 * t657 * t667 - 0.32e2 * t828 * t34 * t767 * self->xc - 0.8e1 * t633 * t15 * t34 * t634 - 0.8e1 * t674 * t739 * t15 + 0.32e2 * t768 * t64 * t275 + 0.4e1 * t708 * t14 * t307 + 0.2e1 * t708 * t206 * t652 + 0.8e1 * t632 * t35 * t13 * t34 * t634 * self->xc;
+	t858 = t35 * t19;
+	t873 = t2 * t8;
+	t878 = t61 * t1;
+	t901 = -0.16e2 * t632 * t2 * self->xc * t528 * t858 + 0.8e1 * t824 * t658 + 0.4e1 * t301 * t14 * t777 - 0.8e1 * t665 * t634 * t509 - 0.8e1 * t674 * t739 * t623 - 0.16e2 * t781 * t873 * t19 * self->xc + 0.8e1 * t878 * t14 * t127 + 0.8e1 * t878 * self->ZA * t51 * self->ZB + 0.8e1 * t686 * t764 + 0.8e1 * t665 * self->xc * t634 * t15 * t8 + 0.8e1 * t633 * t15 * t5 * t634 + 0.4e1 * t387 * t14 * t107 * self->ZA;
+	t903 = t739 * t790;
+	t923 = t737 * t80;
+	t924 = t667 * t790;
+	t927 = t780 * t2;
+	t937 = t15 * t19 * self->xc;
+	t943 = 0.32e2 * t738 * t903 + 0.16e2 * t781 * t873 * t19 + 0.8e1 * t754 * t15 * t652 * t5 + 0.16e2 * t666 * t858 * t623 + 0.64e2 * t828 * t25 * t767 * self->xc - 0.16e2 * t762 * t456 * t19 + 0.64e2 * t923 * t924 + 0.16e2 * t927 * t668 - 0.64e2 * t768 * self->ZA * t790 * t66 - 0.64e2 * t773 * t903 + 0.16e2 * t927 * t937 + 0.16e2 * t666 * t667 * t562;
+	t977 = 0.64e2 * t812 * t5 * t924 + 0.8e1 * t639 * t504 + 0.8e1 * t238 * t35 * t118 * t19 + 0.4e1 * t642 * t658 - 0.16e2 * t817 * t437 * t8 - 0.128e3 * t772 * self->ZB * t80 * t924 + 0.16e2 * t666 * t667 * t13 - 0.4e1 * t301 * t643 - 0.16e2 * t824 * t653 * t8 - 0.4e1 * t642 * t777 - 0.64e2 * t923 * t667 * t268 - 0.16e2 * t666 * t937;
+
+	self->C3A = (t72 + t132 + t169 + t210 + t246 + t298 + t337 + t378 + t409 + t441 + t483 + t512 + t542 + t573 + t600 + t627) / (t682 + t717 + t758 + t809 + t855 + t901 + t943 + t977);
+	/****************************************************************************************/
+	self->C4A = 0;
+	/****************************************************************************************/
+	t1 = nx * 0.3141592654e1;
+	t2 = t1 * self->xc;
+	t3 = cos(t2);
+	t4 = nx * nx;
+	t6 = n * 0.3141592654e1;
+	t7 = t3 * t4 * t6;
+	t8 = self->ZA * self->ZB;
+	t9 = exp(t6);
+	t10 = t9 * t9;
+	t11 = self->xc * n;
+	t13 = exp(t11 * 0.3141592654e1);
+	t14 = t13 * t13;
+	t15 = t14 * t13;
+	t16 = t14 * t14;
+	t17 = t16 * t15;
+	t18 = t10 * t17;
+	t19 = t8 * t18;
+	t22 = sin(t2);
+	t23 = nx * t22;
+	t24 = t23 * n;
+	t25 = self->ZB * self->ZB;
+	t30 = n * n;
+	t31 = t30 * n;
+	t32 = t31 * nx;
+	t33 = 0.3141592654e1 * 0.3141592654e1;
+	t35 = t32 * t22 * t33;
+	t36 = self->ZA * self->ZA;
+	t37 = t36 * self->xc;
+	t38 = t16 * t13;
+	t39 = t10 * t38;
+	t40 = t37 * t39;
+	t43 = sin(t1);
+	t44 = nx * t43;
+	t45 = t30 * 0.3141592654e1;
+	t46 = t44 * t45;
+	t47 = self->ZA * self->xc;
+	t49 = self->ZB * t16 * t9;
+	t54 = t4 * nx * t43;
+	t55 = self->xc * self->xc;
+	t57 = t54 * t30 * t55;
+	t58 = t33 * 0.3141592654e1;
+	t59 = t58 * t25;
+	t60 = t16 * t9;
+	t61 = t59 * t60;
+	t64 = self->xc * t25;
+	t65 = t14 * t9;
+	t66 = t64 * t65;
+	t70 = t44 * t31 * t33;
+	t71 = t37 * t65;
+	t74 = t10 * t15;
+	t75 = t64 * t74;
+	t78 = t25 * t10;
+	t83 = t54 * n * t33;
+	t84 = t55 * t25;
+	t85 = t10 * t9;
+	t86 = t14 * t85;
+	t87 = t84 * t86;
+	t90 = t30 * t30;
+	t92 = t44 * t90 * t58;
+	t93 = t55 * self->xc;
+	t94 = t93 * t25;
+	t95 = t85 * t16;
+	t96 = t94 * t95;
+	t102 = t23 * t45;
+	t103 = t10 * t10;
+	t104 = self->ZB * t103;
+	t106 = t47 * t104 * t15;
+	t111 = t54 * 0.3141592654e1;
+	t112 = t25 * t85;
+	t113 = t112 * t16;
+	t115 = t8 * t39;
+	t118 = t16 * t14;
+	t119 = t85 * t118;
+	t120 = t37 * t119;
+	t123 = t16 * t16;
+	t124 = t36 * t123;
+	t125 = t124 * t9;
+	t127 = -0.8e1 * t7 * t19 + 0.2e1 * t24 * t25 * t13 * t10 - 0.16e2 * t35 * t40 - 0.16e2 * t46 * t47 * t49 - 0.8e1 * t57 * t61 + 0.4e1 * t46 * t66 + 0.2e1 * t70 * t71 - 0.16e2 * t35 * t75 + 0.6e1 * t24 * t78 * t38 - 0.2e1 * t83 * t87 - 0.8e1 * t92 * t96 - 0.8e1 * t46 * t37 * t95 - 0.12e2 * t102 * t106 + 0.2e1 * t83 * t71 + t111 * t113 + 0.8e1 * t7 * t115 + 0.2e1 * t83 * t120 + t111 * t125;
+	t128 = t37 * t74;
+	t131 = t44 * n;
+	t133 = t25 * t9 * t118;
+	t136 = t36 * t14;
+	t137 = t136 * t9;
+	t140 = t30 * t4;
+	t142 = t140 * t3 * t33;
+	t143 = t64 * t39;
+	t147 = t30 * nx * t43;
+	t148 = 0.3141592654e1 * t36;
+	t149 = t9 * t118;
+	t153 = t44 * t31 * self->ZA;
+	t154 = t33 * self->xc;
+	t155 = t154 * t49;
+	t160 = self->ZA * t17 * self->xc * self->ZB;
+	t163 = t103 * t13;
+	t164 = t64 * t163;
+	t170 = t44 * t90 * t55;
+	t171 = t58 * self->ZB;
+	t172 = self->ZA * t16;
+	t174 = t171 * t172 * t9;
+	t177 = t36 * t55;
+	t178 = t177 * t149;
+	t181 = t54 * t11;
+	t182 = t33 * t25;
+	t186 = t25 * t14;
+	t187 = t186 * t9;
+	t193 = t186 * t85;
+	t198 = self->ZB * t55;
+	t199 = self->ZA * t103;
+	t201 = t198 * t199 * t15;
+	t204 = 0.2e1 * t7 * t128 - 0.2e1 * t131 * t133 - 0.2e1 * t131 * t137 + 0.16e2 * t142 * t143 - t147 * t148 * t149 + 0.8e1 * t153 * t155 - 0.4e1 * t7 * t160 + 0.2e1 * t7 * t164 + 0.10e2 * t102 * t40 + 0.16e2 * t170 * t174 + 0.2e1 * t83 * t178 - 0.2e1 * t181 * t182 * t65 - t111 * t187 - 0.2e1 * t70 * t87 + 0.4e1 * t102 * t160 - 0.2e1 * t131 * t193 - 0.16e2 * t142 * t75 + 0.16e2 * t35 * t201;
+	t210 = t32 * t22;
+	t211 = t33 * t55;
+	t212 = t25 * t38;
+	t213 = t211 * t212;
+	t216 = n * nx;
+	t217 = t22 * t25;
+	t222 = self->ZB * t85 * t16;
+	t226 = t23 * t30;
+	t227 = t13 * t10;
+	t228 = t148 * t227;
+	t233 = t37 * t163;
+	t237 = n * t4 * t3;
+	t238 = t148 * t74;
+	t241 = t64 * t86;
+	t245 = t148 * self->xc * t15;
+	t248 = t112 * t118;
+	t250 = t22 * t36;
+	t256 = 0.3141592654e1 * t25;
+	t257 = t256 * t39;
+	t262 = t38 * t103;
+	t263 = t37 * t262;
+	t267 = t148 * t17 * self->xc;
+	t270 = -0.6e1 * t7 * t143 - 0.4e1 * t24 * t19 - 0.8e1 * t210 * t213 - 0.2e1 * t216 * t217 * t15 - 0.32e2 * t153 * t211 * t222 + 0.4e1 * t226 * t228 + 0.16e2 * t142 * t201 + 0.2e1 * t7 * t233 - 0.4e1 * t237 * t238 - 0.2e1 * t83 * t241 - 0.2e1 * t237 * t245 + t111 * t248 + 0.2e1 * t216 * t250 * t15 - 0.2e1 * t131 * t125 - 0.4e1 * t226 * t257 + t147 * t148 * t95 - 0.2e1 * t102 * t263 + 0.2e1 * t237 * t267;
+	t273 = t37 * t149;
+	t277 = t47 * t104 * t13;
+	t285 = t31 * t36;
+	t286 = t44 * t285;
+	t291 = t25 * t123 * t9;
+	t304 = 0.3141592654e1 * self->xc;
+	t305 = t304 * t212;
+	t312 = t256 * t18;
+	t315 = t8 * t60;
+	t319 = t54 * t30 * t58;
+	t323 = t90 * t36;
+	t324 = t44 * t323;
+	t325 = t55 * t58;
+	t326 = t325 * t60;
+	t329 = 0.2e1 * t102 * t164 + 0.2e1 * t83 * t273 - 0.4e1 * t102 * t277 - 0.2e1 * t7 * t263 + 0.4e1 * t24 * t8 * t17 - 0.4e1 * t286 * t154 * t60 - 0.2e1 * t131 * t291 - t147 * t148 * t119 + 0.2e1 * t24 * t78 * t17 + 0.2e1 * t54 * t85 * 0.3141592654e1 * self->ZA * self->ZB - 0.4e1 * t226 * t305 - 0.2e1 * t70 * t66 + t147 * t256 * t95 + 0.4e1 * t237 * t312 + 0.2e1 * t111 * t315 - 0.8e1 * t319 * t96 - t111 * t193 - 0.8e1 * t324 * t326;
+	t332 = t8 * t95;
+	t335 = t136 * t85;
+	t337 = t256 * t227;
+	t340 = t177 * t119;
+	t346 = t37 * t86;
+	t351 = t103 * t15;
+	t352 = t177 * t351;
+	t355 = t64 * t119;
+	t358 = t8 * t227;
+	t361 = t85 * 0.3141592654e1;
+	t365 = t84 * t39;
+	t372 = self->ZB * t10;
+	t373 = t372 * t38;
+	t374 = t47 * t373;
+	t379 = t177 * t39;
+	t384 = -0.2e1 * t46 * t332 + t111 * t335 + 0.4e1 * t237 * t337 - 0.2e1 * t83 * t340 + 0.16e2 * t286 * t211 * t95 + 0.2e1 * t70 * t346 - 0.8e1 * t170 * t61 - 0.8e1 * t142 * t352 - 0.2e1 * t83 * t355 - 0.4e1 * t24 * t358 + 0.2e1 * t147 * t361 * t8 + 0.8e1 * t35 * t365 - 0.2e1 * t226 * t267 + 0.8e1 * t102 * t115 - 0.12e2 * t102 * t374 + 0.16e2 * t142 * t40 - 0.8e1 * t142 * t379 + 0.4e1 * t237 * t228;
+	t386 = t54 * t30 * t93;
+	t387 = self->ZA * t85;
+	t389 = t171 * t387 * t16;
+	t394 = t64 * t60;
+	t398 = t304 * t25 * t15;
+	t401 = t361 * t25;
+	t405 = t84 * t65;
+	t410 = t148 * t18;
+	t414 = t25 * t16 * t9;
+	t417 = t84 * t74;
+	t422 = t177 * t86;
+	t428 = self->ZB * t38;
+	t429 = t47 * t428;
+	t432 = t148 * t39;
+	t439 = 0.16e2 * t386 * t389 - 0.16e2 * t386 * t174 + 0.8e1 * t46 * t394 + 0.2e1 * t237 * t398 - t147 * t401 + 0.4e1 * t7 * t374 + 0.2e1 * t83 * t405 - 0.4e1 * t46 * t241 - 0.4e1 * t226 * t410 + 0.2e1 * t131 * t414 + 0.8e1 * t35 * t417 - 0.8e1 * t142 * t365 + 0.2e1 * t70 * t422 - 0.4e1 * t181 * t182 * t60 + 0.12e2 * t102 * t429 - 0.4e1 * t226 * t432 + 0.32e2 * t35 * t374 - 0.4e1 * t7 * t106;
+	t442 = t36 * t9 * t118;
+	t444 = t123 * t9;
+	t445 = t8 * t444;
+	t448 = t361 * t36;
+	t451 = t47 * t372 * t17;
+	t454 = t94 * t60;
+	t457 = t25 * t103;
+	t465 = t47 * t372 * t15;
+	t468 = t36 * t85;
+	t469 = t468 * t16;
+	t474 = t43 * t85;
+	t478 = t8 * t74;
+	t484 = t256 * t74;
+	t489 = t198 * self->ZA * t10 * t15;
+	t501 = -t111 * t442 + 0.4e1 * t131 * t445 - t147 * t448 + 0.4e1 * t7 * t451 + 0.8e1 * t92 * t454 - 0.2e1 * t24 * t457 * t13 - 0.2e1 * t286 * t211 * t65 + 0.4e1 * t7 * t465 + t111 * t469 - 0.2e1 * t216 * t250 * t17 - 0.2e1 * t216 * t474 * t25 - 0.4e1 * t24 * t478 + 0.4e1 * t24 * t8 * t38 + 0.4e1 * t226 * t484 - 0.16e2 * t142 * t489 - 0.2e1 * t24 * t212 * t103 - 0.2e1 * t216 * t22 * t17 * t25 + 0.2e1 * t70 * t120;
+	t504 = t33 * t36 * t55 * t38;
+	t507 = t37 * t18;
+	t512 = t47 * self->ZB * t13 * t10;
+	t518 = t59 * t95;
+	t530 = t84 * t351;
+	t534 = t37 * t227;
+	t549 = -0.8e1 * t210 * t504 + 0.2e1 * t102 * t507 + 0.4e1 * t7 * t512 + t111 * t133 - 0.16e2 * t35 * t489 + 0.8e1 * t170 * t518 + 0.2e1 * t24 * t36 * t13 * t10 + 0.4e1 * t131 * t387 * self->ZB + 0.12e2 * t102 * t465 - 0.8e1 * t142 * t530 + t111 * t291 - 0.2e1 * t102 * t534 - 0.4e1 * t70 * t394 - 0.10e2 * t102 * t128 + 0.4e1 * t237 * t305 + 0.8e1 * t102 * t19 + 0.2e1 * t83 * t346 - 0.16e2 * t35 * t128;
+	t557 = t468 * t118;
+	t562 = t93 * t58;
+	t563 = t562 * t60;
+	t567 = t44 * t90 * t93;
+	t575 = self->ZA * t55;
+	t576 = t575 * t428;
+	t583 = t37 * t60;
+	t590 = t140 * t3;
+	t601 = -0.2e1 * t226 * t398 - 0.2e1 * t70 * t340 - 0.2e1 * t131 * t557 - 0.4e1 * t24 * t115 + 0.8e1 * t324 * t563 + 0.16e2 * t567 * t389 + 0.16e2 * t70 * t84 * t95 + 0.2e1 * t70 * t178 - 0.16e2 * t142 * t576 - 0.4e1 * t237 * t257 - 0.4e1 * t226 * t312 + 0.8e1 * t46 * t583 + 0.2e1 * t24 * t36 * t38 * t103 + 0.8e1 * t590 * t213 + 0.2e1 * t102 * t143 - 0.16e2 * t35 * t143 + 0.2e1 * t131 * t248 + 0.4e1 * t46 * t346;
+	t604 = n * t36;
+	t606 = t154 * t95;
+	t625 = t36 * t103;
+	t640 = t30 * t36;
+	t641 = t54 * t640;
+	t642 = t325 * t95;
+	t647 = -0.4e1 * t131 * t315 - 0.4e1 * t54 * t604 * t606 - t147 * t148 * t60 + 0.16e2 * t35 * t576 - 0.8e1 * t102 * t478 + 0.32e2 * t142 * t465 - 0.4e1 * t237 * t484 - 0.2e1 * t70 * t355 + 0.2e1 * t70 * t273 + 0.2e1 * t102 * t233 - 0.2e1 * t24 * t625 * t13 - 0.8e1 * t7 * t358 - 0.2e1 * t111 * t445 - 0.4e1 * t7 * t429 + 0.16e2 * t46 * t47 * t222 + 0.2e1 * t131 * t113 + 0.8e1 * t641 * t642 - 0.2e1 * t7 * t534;
+	t652 = t36 * t16;
+	t653 = t652 * t9;
+	t655 = t64 * t227;
+	t658 = t182 * t95;
+	t663 = t562 * t95;
+	t684 = t64 * t351;
+	t689 = t36 * t10;
+	t695 = t154 * t222;
+	t698 = -0.4e1 * t216 * t217 * t38 - t111 * t653 - 0.2e1 * t7 * t655 - 0.4e1 * t181 * t658 + 0.2e1 * t131 * t469 - 0.8e1 * t641 * t663 - 0.4e1 * t83 * t583 - 0.2e1 * t83 * t177 * t65 - 0.4e1 * t24 * t457 * t15 + 0.16e2 * t70 * t84 * t60 + 0.8e1 * t57 * t518 - 0.32e2 * t142 * t374 + 0.4e1 * t24 * t8 * t351 + 0.4e1 * t102 * t684 - t147 * t256 * t86 - 0.2e1 * t24 * t689 * t15 - 0.2e1 * t70 * t241 + 0.8e1 * t153 * t695;
+	t711 = t575 * t373;
+	t717 = t304 * t17 * t25;
+	t736 = t177 * t74;
+	t739 = 0.2e1 * t226 * t245 - 0.8e1 * t102 * t358 - 0.16e2 * t57 * t389 - 0.2e1 * t102 * t655 + 0.8e1 * t590 * t504 - 0.8e1 * t641 * t326 - 0.16e2 * t35 * t711 - t111 * t557 + t111 * t137 - 0.2e1 * t226 * t717 + 0.8e1 * t102 * t37 * t351 + 0.2e1 * t131 * t335 - 0.4e1 * t131 * t332 - 0.2e1 * t216 * t474 * t36 - 0.2e1 * t111 * t332 + 0.16e2 * t142 * t711 - t147 * t256 * t60 + 0.8e1 * t142 * t736;
+	t750 = t64 * t262;
+	t763 = t44 * t640;
+	t770 = t84 * t119;
+	t782 = 0.4e1 * t102 * t512 + 0.8e1 * t142 * t417 + 0.8e1 * t641 * t563 - 0.2e1 * t7 * t507 + 0.2e1 * t7 * t750 - 0.8e1 * t35 * t352 + 0.4e1 * t237 * t410 + 0.4e1 * t7 * t684 - 0.2e1 * t46 * t445 + t147 * t148 * t65 + 0.4e1 * t763 * t304 * t119 + 0.16e2 * t70 * t177 * t60 + 0.2e1 * t70 * t770 - t111 * t414 - 0.16e2 * t567 * t174 - 0.4e1 * t46 * t71 - 0.4e1 * t46 * t355 - 0.4e1 * t7 * t277;
+	t797 = t64 * t149;
+	t821 = -t54 * t448 + 0.2e1 * t131 * t442 + 0.8e1 * t7 * t478 + 0.8e1 * t35 * t379 - 0.2e1 * t181 * t182 * t149 + 0.2e1 * t70 * t405 + 0.2e1 * t83 * t770 - 0.2e1 * t70 * t797 - 0.6e1 * t7 * t75 - 0.4e1 * t286 * t606 - 0.4e1 * t237 * t432 + t147 * t256 * t149 - 0.4e1 * t763 * t304 * t149 - 0.2e1 * t102 * t75 + 0.2e1 * t237 * t717 + 0.8e1 * t324 * t642 - 0.16e2 * t170 * t389 + 0.2e1 * t83 * t422;
+	t827 = t84 * t149;
+	t846 = t54 * n * self->ZA;
+	t854 = t64 * t18;
+	t867 = -0.16e2 * t142 * t128 + 0.32e2 * t35 * t465 - 0.2e1 * t83 * t827 + 0.2e1 * t46 * t315 + t147 * t148 * t86 - 0.4e1 * t102 * t451 - 0.8e1 * t226 * t148 * self->xc * t38 - 0.2e1 * t24 * t689 * t38 + 0.2e1 * t131 * t187 + 0.8e1 * t846 * t155 + 0.8e1 * t35 * t736 + 0.2e1 * t24 * t689 * t17 - 0.2e1 * t7 * t854 + t147 * t256 * t119 + 0.2e1 * t102 * t854 - 0.8e1 * t35 * t530 + 0.4e1 * t46 * t797 + 0.2e1 * t102 * t750;
+	t909 = -0.8e1 * t324 * t663 + t147 * t256 * t444 - t147 * t256 * t65 + 0.4e1 * t226 * t238 + 0.2e1 * t7 * t40 - t54 * t401 + 0.16e2 * t57 * t174 + 0.4e1 * t226 * t337 + 0.4e1 * t24 * t8 * t163 + 0.8e1 * t846 * t695 + 0.8e1 * t319 * t454 + 0.2e1 * t131 * t653 - 0.8e1 * t46 * t64 * t95 + 0.6e1 * t24 * t78 * t15 - 0.4e1 * t44 * t31 * self->xc * t658 - 0.32e2 * t153 * t211 * t49 - 0.2e1 * t70 * t827 + t147 * t148 * t444;
+	t914 = t25 * self->ZB;
+	t915 = t33 * t914;
+	t919 = t4 * t4;
+	t920 = t16 * t919;
+	t929 = t123 * t90;
+	t932 = t919 * t103;
+	t935 = t33 * self->ZB;
+	t939 = t652 * t919;
+	t942 = t16 * t30;
+	t943 = t942 * t4;
+	t949 = t103 * t16;
+	t950 = t949 * t90;
+	t953 = -0.2e1 * t915 * t103 * t90 + 0.2e1 * t915 * t920 - 0.2e1 * t915 * t123 * t919 + 0.2e1 * t915 * t16 * t90 - 0.2e1 * t915 * t929 - 0.2e1 * t915 * t932 - 0.2e1 * t935 * t323 * t123 + 0.2e1 * t935 * t939 + 0.4e1 * t915 * t943 + 0.4e1 * t182 * t172 * t90 + 0.2e1 * t915 * t950;
+	t954 = t171 * t36;
+	t955 = t90 * n;
+	t956 = self->xc * t955;
+	t957 = t118 * t10;
+	t964 = t33 * t33;
+	t965 = t964 * self->ZB;
+	t966 = t965 * t640;
+	t967 = t10 * t919;
+	t968 = t55 * t16;
+	t969 = t967 * t968;
+	t972 = t935 * t36;
+	t974 = t103 * t30 * t4;
+	t977 = self->xc * t16;
+	t978 = t967 * t977;
+	t981 = t90 * t30;
+	t983 = t16 * t10;
+	t987 = t182 * self->ZA;
+	t988 = t4 * t10;
+	t992 = t171 * t604;
+	t993 = self->xc * t14;
+	t994 = t932 * t993;
+	t997 = t182 * t30;
+	t1005 = t171 * t285;
+	t1006 = t988 * t993;
+	t1009 = t58 * t914;
+	t1010 = t1009 * t31;
+	t1013 = 0.8e1 * t954 * t956 * t957 + 0.2e1 * t915 * t932 * t16 + 0.32e2 * t966 * t969 - 0.4e1 * t972 * t974 - 0.32e2 * t966 * t978 + 0.32e2 * t965 * t981 * t177 * t983 - 0.32e2 * t987 * t942 * t988 + 0.8e1 * t992 * t994 + 0.8e1 * t997 * t949 * self->ZA * t4 - 0.2e1 * t935 * t124 * t919 - 0.16e2 * t1005 * t1006 + 0.16e2 * t1010 * t1006;
+	t1015 = t964 * t25;
+	t1016 = self->ZA * t30;
+	t1017 = t1015 * t1016;
+	t1020 = t967 * t993;
+	t1031 = t1009 * t118;
+	t1032 = t31 * t10;
+	t1040 = t964 * t914;
+	t1041 = t1040 * t90;
+	t1044 = t55 * t10 * t4 * t16;
+	t1047 = t1040 * t30;
+	t1050 = t123 * self->ZA;
+	t1054 = t977 * t988;
+	t1057 = 0.64e2 * t1017 * t978 - 0.8e1 * t992 * t1020 + 0.2e1 * t972 * t950 + 0.4e1 * t182 * t929 * self->ZA + 0.4e1 * t182 * t199 * t90 - 0.16e2 * t1031 * t1032 * t4 * self->xc + 0.4e1 * t182 * t172 * t919 + 0.64e2 * t1041 * t1044 + 0.32e2 * t1047 * t969 + 0.4e1 * t182 * t1050 * t919 - 0.64e2 * t1041 * t1054;
+	t1058 = t1009 * n;
+	t1063 = t932 * self->ZA;
+	t1069 = t123 * t30 * t4;
+	t1080 = t993 * t103 * t4;
+	t1088 = t935 * t103;
+	t1094 = -0.8e1 * t1058 * t994 - 0.32e2 * t1047 * t978 + 0.4e1 * t182 * t1063 - 0.4e1 * t915 * t974 - 0.4e1 * t915 * t1069 - 0.2e1 * t935 * t625 * t90 - 0.8e1 * t1009 * t10 * t14 * t955 - 0.16e2 * t1010 * t1080 - 0.2e1 * t935 * t625 * t919 - 0.64e2 * t1017 * t969 + 0.2e1 * t1088 * t939 + 0.8e1 * t1009 * t957 * t955;
+	t1113 = t955 * t118 * self->xc;
+	t1120 = t4 * t118;
+	t1125 = t981 * self->xc;
+	t1133 = n * t10;
+	t1140 = -0.8e1 * t954 * t955 * t10 * t993 + 0.2e1 * t935 * t652 * t90 - 0.64e2 * t1015 * t981 * t575 * t983 + 0.8e1 * t182 * t103 * t1016 * t4 + 0.8e1 * t1009 * t1113 + 0.16e2 * t954 * t1032 * t4 * t14 - 0.16e2 * t954 * t1032 * t1120 + 0.64e2 * t1015 * t10 * t172 * t1125 + 0.8e1 * t171 * t103 * t136 * t956 - 0.8e1 * t1031 * t1133 * t919 * self->xc + 0.8e1 * t1058 * t1020;
+	t1153 = self->xc * t118;
+	t1165 = t182 * t16;
+	t1170 = t171 * t10;
+	t1178 = self->ZA * t90;
+	t1182 = 0.4e1 * t1088 * t652 * t140 + 0.8e1 * t954 * t1133 * t919 * t14 + 0.4e1 * t972 * t943 - 0.4e1 * t972 * t1069 - 0.16e2 * t954 * t31 * t4 * t1153 - 0.8e1 * t954 * n * t919 * t1153 - 0.8e1 * t954 * t1133 * t919 * t118 + 0.4e1 * t1165 * t1063 + 0.16e2 * t1005 * t1080 - 0.8e1 * t1170 * t118 * t36 * t955 - 0.16e2 * t987 * t920 * t10 - 0.16e2 * t1165 * t1178 * t10;
+	t1195 = t1040 * t981;
+	t1199 = t1009 * t955;
+	t1203 = t1009 * t10;
+	t1211 = t965 * t323;
+	t1225 = -0.32e2 * t965 * t10 * t652 * t1125 + 0.4e1 * t915 * t16 * t974 + 0.4e1 * t182 * t90 * t949 * self->ZA + 0.32e2 * t1195 * t968 * t10 - 0.8e1 * t1199 * t993 * t103 + 0.8e1 * t1203 * t118 * n * t919 + 0.8e1 * t1170 * t136 * t955 + 0.64e2 * t1211 * t1044 + 0.16e2 * t1031 * t1032 * t4 + 0.8e1 * t987 * t943 + 0.8e1 * t1199 * t993 * t10 + 0.8e1 * t997 * t1050 * t4;
+	t1263 = -0.128e3 * t1015 * t1178 * t1044 + 0.16e2 * t1005 * t988 * t1153 + 0.8e1 * t1058 * t1153 * t919 + 0.16e2 * t1010 * t1120 * self->xc - 0.8e1 * t954 * t1113 - 0.8e1 * t1203 * t14 * n * t919 - 0.16e2 * t1203 * t14 * t31 * t4 - 0.8e1 * t1203 * t1113 - 0.32e2 * t1195 * t977 * t10 - 0.64e2 * t1211 * t1054 + 0.8e1 * t992 * t967 * t1153 + 0.128e3 * t1015 * t983 * t90 * t4 * t47;
+
+	self->C1B = (t127 + t204 + t270 + t329 + t384 + t439 + t501 + t549 + t601 + t647 + t698 + t739 + t782 + t821 + t867 + t909) / (t953 + t1013 + t1057 + t1094 + t1140 + t1182 + t1225 + t1263);
+	/****************************************************************************************/
+	t1 = n * n;
+	t2 = t1 * n;
+	t3 = nx * t2;
+	t4 = 0.3141592654e1 * self->ZA;
+	t5 = t3 * t4;
+	t6 = nx * 0.3141592654e1;
+	t7 = t6 * self->xc;
+	t8 = sin(t7);
+	t9 = t8 * self->ZB;
+	t10 = n * 0.3141592654e1;
+	t11 = exp(t10);
+	t12 = t11 * t11;
+	t15 = exp( self->xc * n * 0.3141592654e1);
+	t16 = t15 * t15;
+	t17 = t16 * t16;
+	t18 = t17 * t15;
+	t19 = t12 * t18;
+	t23 = t1 * t1;
+	t24 = nx * t23;
+	t25 = self->ZB * self->ZB;
+	t27 = t18 * t8;
+	t28 = 0.3141592654e1 * 0.3141592654e1;
+	t29 = self->xc * self->xc;
+	t30 = t28 * t29;
+	t34 = t1 * self->xc;
+	t35 = 0.3141592654e1 * self->ZB;
+	t36 = t34 * t35;
+	t37 = cos(t7);
+	t38 = self->ZA * t37;
+	t39 = nx * nx;
+	t40 = t39 * t12;
+	t41 = t16 * t15;
+	t43 = t38 * t40 * t41;
+	t46 = t25 * n;
+	t47 = t46 * 0.3141592654e1;
+	t48 = t39 * nx;
+	t49 = sin(t6);
+	t50 = t48 * t49;
+	t51 = t12 * t11;
+	t52 = t51 * t17;
+	t53 = t50 * t52;
+	t56 = t34 * 0.3141592654e1 * t25;
+	t57 = t37 * t39;
+	t58 = t17 * t41;
+	t59 = t12 * t58;
+	t60 = t57 * t59;
+	t63 = t25 * t18;
+	t64 = t57 * n;
+	t67 = self->ZA * self->ZA;
+	t68 = t67 * n;
+	t69 = 0.3141592654e1 * t48;
+	t70 = t68 * t69;
+	t71 = t49 * self->xc;
+	t72 = t17 * t16;
+	t73 = t11 * t72;
+	t74 = t71 * t73;
+	t77 = t1 * t67;
+	t78 = t77 * 0.3141592654e1;
+	t81 = nx * t25;
+	t82 = t81 * t49;
+	t83 = t17 * t17;
+	t85 = t1 * t83 * t11;
+	t87 = nx * self->ZB;
+	t88 = t8 * t2;
+	t89 = t87 * t88;
+	t90 = 0.3141592654e1 * self->xc;
+	t91 = t12 * t12;
+	t92 = self->ZA * t91;
+	t97 = self->ZB * self->ZA;
+	t98 = t97 * t37;
+	t99 = t39 * n;
+	t100 = t12 * t41;
+	t104 = 0.8e1 * t5 * t9 * t19 + 0.8e1 * t24 * t25 * t27 * t30 + 0.12e2 * t36 * t43 - t47 * t53 - 0.2e1 * t56 * t60 - 0.4e1 * t63 * t64 + 0.6e1 * t70 * t74 + 0.4e1 * t78 * t60 - t82 * t85 + 0.4e1 * t89 * t90 * t92 * t41 + 0.4e1 * t98 * t99 * t100;
+	t105 = t67 * t48;
+	t106 = t49 * t51;
+	t107 = t106 * t72;
+	t109 = t1 * 0.3141592654e1;
+	t110 = t109 * self->xc;
+	t115 = nx * t67;
+	t116 = t115 * t49;
+	t117 = t1 * t16;
+	t118 = t117 * t11;
+	t120 = t2 * t25;
+	t121 = t28 * 0.3141592654e1;
+	t122 = t121 * t29;
+	t123 = t120 * t122;
+	t129 = t1 * self->ZB;
+	t130 = t129 * t4;
+	t131 = t57 * t100;
+	t134 = t12 * t16;
+	t136 = t109 * t39;
+	t139 = self->ZB * t18;
+	t141 = t39 * t1;
+	t142 = t141 * t90;
+	t145 = t77 * t90;
+	t146 = t91 * t41;
+	t147 = t57 * t146;
+	t151 = t25 * t39 * t1;
+	t152 = t72 * t12;
+	t156 = t49 * t2;
+	t158 = t83 * t11;
+	t162 = -t105 * t107 + 0.8e1 * t110 * t72 * t25 * t39 - t116 * t118 + 0.8e1 * t123 * t53 + 0.8e1 * t5 * t9 * t59 - 0.8e1 * t130 * t131 - 0.8e1 * t134 * t25 * t136 - 0.12e2 * t139 * t38 * t142 - 0.8e1 * t145 * t147 - 0.8e1 * t151 * t90 * t152 - 0.2e1 * t87 * t156 * t4 * t158;
+	t164 = t115 * t88;
+	t165 = t90 * t19;
+	t168 = t25 * t48;
+	t169 = t49 * t16;
+	t170 = t169 * t11;
+	t174 = self->ZA * n * t69;
+	t175 = self->ZB * t51;
+	t176 = t175 * t17;
+	t177 = t71 * t176;
+	t180 = t1 * t29;
+	t181 = t28 * t25;
+	t182 = t180 * t181;
+	t183 = t50 * t73;
+	t186 = self->ZA * t1;
+	t187 = t28 * t48;
+	t188 = t186 * t187;
+	t189 = self->ZB * t17;
+	t190 = t189 * t11;
+	t191 = t71 * t190;
+	t194 = t50 * t158;
+	t196 = t115 * t156;
+	t197 = t90 * t73;
+	t201 = t49 * t17 * t11;
+	t204 = t88 * t90;
+	t207 = t68 * 0.3141592654e1;
+	t208 = t17 * t11;
+	t209 = t50 * t208;
+	t211 = -0.2e1 * t164 * t165 - t168 * t170 + t168 * t107 + 0.8e1 * t174 * t177 + 0.2e1 * t182 * t183 + 0.8e1 * t188 * t191 + t47 * t194 - 0.6e1 * t196 * t197 - t168 * t201 - 0.4e1 * t81 * t18 * t204 - t207 * t209;
+	t212 = t2 * 0.3141592654e1;
+	t213 = t212 * t52;
+	t215 = t81 * t8;
+	t216 = t212 * t59;
+	t219 = t3 * t90;
+	t220 = t25 * t8;
+	t221 = t18 * t91;
+	t225 = t71 * t52;
+	t231 = t16 * t51;
+	t232 = t50 * t231;
+	t237 = self->ZA * t12;
+	t243 = t67 * t28;
+	t244 = t24 * t243;
+	t245 = t71 * t231;
+	t249 = -t116 * t213 - 0.4e1 * t215 * t216 + 0.2e1 * t219 * t220 * t221 - 0.4e1 * t70 * t225 + 0.4e1 * t98 * t99 * t146 + t47 * t232 - 0.2e1 * t145 * t57 * t221 + 0.4e1 * t89 * t90 * t237 * t41 - t105 * t201 - 0.6e1 * t244 * t245 + t105 * t170;
+	t252 = t25 * t37;
+	t253 = t252 * t39;
+	t255 = n * t15 * t12;
+	t258 = t2 * t29;
+	t259 = self->ZB * t28;
+	t260 = t258 * t259;
+	t263 = t106 * t17;
+	t265 = self->xc * t25;
+	t269 = t25 * t49;
+	t270 = t269 * t52;
+	t273 = t1 * t25;
+	t274 = t273 * 0.3141592654e1;
+	t275 = t57 * t19;
+	t278 = t24 * t30;
+	t288 = t1 * t11 * t72;
+	t290 = t212 * t208;
+	t292 = t2 * self->xc;
+	t296 = 0.2e1 * t253 * t255 + 0.16e2 * t260 * t43 + t105 * t263 - 0.4e1 * t10 * t265 * t53 + 0.4e1 * t219 * t270 - 0.12e2 * t274 * t275 + 0.8e1 * t278 * t270 - 0.2e1 * self->ZB * n * t69 * t49 * self->ZA * t158 - t82 * t288 - t116 * t290 + 0.16e2 * t292 * t243 * t275;
+	t301 = t50 * t176;
+	t304 = t51 * t72;
+	t305 = t71 * t304;
+	t308 = t25 * t41;
+	t311 = self->ZA * t48;
+	t312 = t311 * t49;
+	t317 = t91 * t15;
+	t318 = t57 * t317;
+	t321 = t81 * t88;
+	t322 = t90 * t59;
+	t325 = t212 * t231;
+	t327 = t15 * t12;
+	t328 = t57 * t327;
+	t331 = t77 * t187;
+	t334 = t2 * self->ZA;
+	t335 = t334 * t122;
+	t336 = t50 * t190;
+	t339 = 0.8e1 * t151 * t90 * t134 + 0.16e2 * t186 * t30 * t301 - 0.2e1 * t70 * t305 + 0.2e1 * t308 * t64 - 0.2e1 * t312 * self->ZB * t83 * t11 + 0.2e1 * t56 * t318 + 0.2e1 * t321 * t322 - t116 * t325 - 0.4e1 * t274 * t328 + 0.2e1 * t331 * t305 - 0.16e2 * t335 * t336;
+	t341 = t169 * t51;
+	t344 = t49 * t11 * t72;
+	t346 = t77 * t30;
+	t347 = t50 * t304;
+	t350 = t25 * t51;
+	t352 = nx * self->ZA;
+	t353 = t49 * t23;
+	t354 = t352 * t353;
+	t355 = t28 * self->xc;
+	t362 = t25 * t91;
+	t365 = t23 * n;
+	t366 = nx * t365;
+	t367 = t366 * t122;
+	t368 = self->ZB * t49;
+	t369 = self->ZA * t51;
+	t370 = t369 * t17;
+	t371 = t368 * t370;
+	t374 = t115 * t353;
+	t375 = t355 * t73;
+	t381 = t105 * t341 - t105 * t344 - 0.2e1 * t346 * t347 - t350 * t50 - 0.8e1 * t354 * t355 * t176 - 0.4e1 * t98 * t99 * t317 - 0.2e1 * t362 * t99 - 0.16e2 * t367 * t371 + 0.6e1 * t374 * t375 - 0.8e1 * t182 * t53 - t82 * t290;
+	t382 = t71 * t208;
+	t394 = t2 * t67;
+	t395 = t394 * t122;
+	t398 = t352 * t156;
+	t402 = t17 * t12;
+	t403 = t39 * self->ZA;
+	t404 = t402 * t403;
+	t407 = t269 * t208;
+	t411 = t49 * t83 * t11;
+	t413 = t46 * t69;
+	t419 = -0.4e1 * t331 * t382 + 0.2e1 * t115 * t58 * t204 - 0.2e1 * t145 * t60 + 0.12e2 * t274 * t131 + 0.2e1 * t346 * t232 + 0.8e1 * t395 * t53 - 0.8e1 * t398 * t90 * t176 - 0.64e2 * t260 * t404 + 0.4e1 * t219 * t407 + t168 * t411 - 0.6e1 * t413 * t74 - 0.2e1 * t110 * t308 * t57;
+	t424 = t16 * t11;
+	t425 = t212 * t424;
+	t427 = t258 * t181;
+	t430 = t67 * t29;
+	t431 = t366 * t430;
+	t432 = t121 * t49;
+	t433 = t432 * t52;
+	t436 = n * t12;
+	t437 = t436 * t18;
+	t440 = t29 * self->xc;
+	t441 = t440 * t121;
+	t442 = t394 * t441;
+	t445 = t67 * t37;
+	t446 = t445 * t39;
+	t448 = n * t18 * t91;
+	t453 = t352 * t49;
+	t458 = t8 * t23;
+	t462 = t81 * t458;
+	t463 = t30 * t19;
+	t466 = -t47 * t209 + t116 * t425 - 0.8e1 * t427 * t275 + 0.8e1 * t431 * t433 - 0.2e1 * t253 * t437 - 0.8e1 * t442 * t53 - 0.2e1 * t446 * t448 + 0.2e1 * t175 * t312 + 0.6e1 * t453 * t129 * t208 + 0.8e1 * t115 * t18 * t458 * t30 + 0.8e1 * t462 * t463;
+	t470 = t436 * t58;
+	t475 = t2 * t121 * t440 * t25;
+	t485 = t212 * t73;
+	t488 = t67 * t72 * t1;
+	t490 = t39 * self->xc;
+	t501 = 0.4e1 * t374 * t355 * t52 + 0.2e1 * t446 * t470 - 0.8e1 * t475 * t53 - 0.2e1 * t446 * t437 - 0.4e1 * t36 * t38 * t39 * t15 * t12 - t116 * t485 + 0.8e1 * t488 * 0.3141592654e1 * t12 * t490 - t207 * t183 - 0.2e1 * t182 * t232 - 0.6e1 * t413 * t245 - 0.4e1 * t413 * t382;
+	t503 = t115 * t8;
+	t510 = t355 * t19;
+	t513 = t432 * t208;
+	t525 = t38 * t40 * t18;
+	t533 = -0.4e1 * t503 * t216 - 0.4e1 * t89 * t90 * t92 * t15 - 0.16e2 * t462 * t510 + 0.8e1 * t431 * t513 - 0.4e1 * t78 * t131 + t47 * t183 - 0.2e1 * t67 * t83 * t99 + 0.4e1 * t331 * t225 + 0.16e2 * t260 * t525 - 0.4e1 * t89 * t90 * t237 * t58 - t207 * t53;
+	t536 = t28 * t37;
+	t538 = t490 * t100;
+	t541 = t334 * t441;
+	t547 = t394 * t30;
+	t550 = t212 * t19;
+	t553 = t366 * t441;
+	t556 = n * t17;
+	t571 = -0.8e1 * t427 * t131 + 0.16e2 * t394 * t536 * t538 + 0.16e2 * t541 * t336 + 0.2e1 * t453 * t129 * t158 - 0.8e1 * t547 * t147 + 0.4e1 * t503 * t550 - 0.8e1 * t553 * t270 + 0.4e1 * t556 * self->ZB * t92 * t39 - 0.2e1 * t67 * t91 * t99 - t82 * t425 + 0.4e1 * t78 * t275 + 0.2e1 * t78 * self->xc * t41 * t57;
+	t583 = t90 * t317;
+	t594 = t212 * t158;
+	t596 = t152 * t67;
+	t602 = t67 * t17;
+	t607 = 0.8e1 * t367 * t407 - 0.4e1 * t98 * t99 * t59 + 0.16e2 * t260 * t18 * self->ZA * t57 + 0.2e1 * t321 * t583 - 0.6e1 * t174 * t368 * t52 - 0.4e1 * t89 * t90 * self->ZA * t15 * t12 + t116 * t594 - 0.8e1 * t596 * t136 - 0.4e1 * t98 * t99 * t327 + 0.2e1 * t602 * t99 + 0.2e1 * t164 * t583;
+	t613 = t83 * t25;
+	t616 = t81 * t156;
+	t627 = t90 * t231;
+	t630 = t91 * t16;
+	t638 = 0.4e1 * t196 * t90 * t208 - 0.8e1 * t130 * t60 - 0.2e1 * t613 * t99 + 0.6e1 * t616 * t197 - 0.8e1 * t547 * t131 + 0.8e1 * t67 * t18 * t37 * t142 + 0.2e1 * t145 * t328 - 0.6e1 * t196 * t627 + 0.8e1 * t630 * t67 * t142 - 0.8e1 * t547 * t275 + 0.8e1 * t395 * t209;
+	t643 = t77 * t355;
+	t648 = t115 * t458;
+	t651 = t134 * t67;
+	t657 = t30 * t304;
+	t660 = t30 * t146;
+	t665 = t25 * t17;
+	t668 = t50 * t424;
+	t671 = -0.4e1 * t321 * t90 * t146 - 0.6e1 * t643 * t232 + 0.8e1 * t182 * t209 - 0.16e2 * t648 * t510 + 0.8e1 * t651 * t136 + 0.8e1 * t89 * t4 * t100 - 0.2e1 * t374 * t657 - 0.8e1 * t648 * t660 + 0.8e1 * t130 * t328 + 0.2e1 * t665 * t99 + 0.2e1 * t346 * t668;
+	t672 = t90 * t424;
+	t676 = t120 * t536;
+	t680 = t436 * t41;
+	t688 = t366 * t67 * t440;
+	t696 = self->xc * t12;
+	t697 = t696 * t18;
+	t701 = t252 * t141;
+	t702 = t90 * t221;
+	t705 = 0.2e1 * t196 * t672 - t47 * t347 + 0.16e2 * t676 * t538 - t116 * t85 - 0.2e1 * t253 * t680 + t207 * t194 + 0.4e1 * t98 * t99 * t19 - 0.8e1 * t688 * t433 + 0.16e2 * t541 * t301 - 0.6e1 * t312 * t190 + 0.4e1 * t352 * t88 * t35 * t697 + 0.2e1 * t701 * t702;
+	t712 = t24 * t430;
+	t713 = t28 * t49;
+	t721 = t1 * t17 * t11;
+	t726 = self->ZB * self->xc;
+	t737 = n * t91;
+	t741 = 0.8e1 * t346 * t209 + 0.2e1 * t712 * t713 * t424 + 0.8e1 * t130 * t275 - t47 * t668 + t116 * t721 - 0.8e1 * t688 * t513 + 0.4e1 * t352 * t27 * t212 * t726 + 0.8e1 * t648 * t463 + 0.4e1 * t274 * t60 - 0.4e1 * t374 * t355 * t208 - 0.4e1 * t253 * t737 * t41;
+	t745 = t269 * t231;
+	t749 = t1 * t28 * t265;
+	t757 = t16 * t39;
+	t758 = t696 * t757;
+	t762 = t69 * t49;
+	t772 = t355 * t100;
+	t775 = t81 * t353;
+	t778 = -0.8e1 * t398 * t90 * t190 - 0.2e1 * t278 * t745 + 0.4e1 * t749 * t53 + 0.32e2 * t394 * t29 * t28 * t17 * t40 - 0.8e1 * t78 * t758 + t350 * n * t762 - 0.6e1 * t87 * t49 * t186 * t52 - 0.8e1 * t553 * t407 - 0.4e1 * t749 * t209 + 0.16e2 * t648 * t772 - 0.6e1 * t775 * t375;
+	t790 = t212 * t304;
+	t793 = t156 * 0.3141592654e1;
+	t795 = t355 * t304;
+	t800 = t91 * t39;
+	t801 = t800 * n;
+	t807 = t2 * t28;
+	t808 = t807 * t726;
+	t811 = -0.2e1 * t616 * t672 - 0.2e1 * t446 * t680 - 0.2e1 * t78 * self->xc * t58 * t57 + 0.8e1 * t367 * t270 - t82 * t790 + t115 * t51 * t793 - 0.2e1 * t775 * t795 + 0.8e1 * t123 * t209 + 0.2e1 * t665 * t801 - 0.2e1 * t67 * t41 * t64 - 0.32e2 * t808 * t43;
+	t812 = t117 * t51;
+	t821 = t24 * t355;
+	t827 = t90 * t304;
+	t840 = t800 * t41;
+	t844 = -t116 * t812 - 0.2e1 * t110 * t25 * t58 * t57 - 0.4e1 * t78 * t328 + t82 * t485 - 0.4e1 * t821 * t407 + 0.4e1 * t196 * t90 * t52 + 0.2e1 * t196 * t827 + t82 * t325 + 0.2e1 * t253 * t448 - 0.32e2 * t402 * t67 * t807 * t490 - t207 * t232 + 0.12e2 * t186 * t90 * self->ZB * t37 * t840;
+	t849 = t1 * t51;
+	t850 = t849 * t17;
+	t860 = t269 * t424;
+	t863 = t273 * t187;
+	t874 = 0.16e2 * t462 * t772 - t116 * t850 + 0.16e2 * t553 * t371 + t116 * t288 - 0.12e2 * t97 * t57 * t109 * t697 + t82 * t594 - 0.2e1 * t278 * t860 - 0.2e1 * t863 * t305 - 0.16e2 * t180 * t259 * t311 * t201 - 0.6e1 * t863 * t74 + 0.8e1 * t174 * t191;
+	t879 = self->xc * self->ZA;
+	t888 = t67 * t51;
+	t901 = self->ZA * t17;
+	t903 = t368 * t901 * t11;
+	t908 = -0.2e1 * t352 * t51 * t156 * t35 + 0.64e2 * t879 * t189 * t807 * t40 + 0.2e1 * t46 * t58 * t37 * t39 - t888 * t50 + t105 * t411 - 0.16e2 * t335 * t301 + 0.8e1 * t152 * t25 * t136 - 0.8e1 * t278 * t407 + 0.2e1 * t712 * t713 * t231 - 0.16e2 * t367 * t903 + 0.2e1 * t145 * t318;
+	t923 = t71 * t424;
+	t926 = t87 * t458;
+	t927 = t28 * self->ZA;
+	t944 = 0.8e1 * t354 * t355 * t190 - 0.8e1 * t110 * t16 * t25 * t800 - 0.2e1 * t374 * t30 * t73 - 0.16e2 * t354 * t30 * t176 - 0.2e1 * t244 * t923 - 0.32e2 * t926 * t927 * t696 * t41 - 0.32e2 * t808 * t525 + 0.6e1 * t749 * t232 - 0.8e1 * t188 * t177 + 0.4e1 * t36 * t58 * self->ZA * t57 + 0.4e1 * t821 * t270;
+	t948 = t90 * t327;
+	t961 = t30 * t100;
+	t964 = t29 * t49;
+	t981 = t106 * t1;
+	t983 = -0.2e1 * t219 * t220 * t100 + 0.2e1 * t321 * t948 - 0.16e2 * t189 * self->ZA * t99 * t12 - 0.2e1 * t369 * n * t69 * t368 + 0.2e1 * t374 * t795 - 0.8e1 * t462 * t961 - 0.8e1 * t244 * t964 * t208 + 0.2e1 * t413 * t923 + 0.4e1 * t36 * t38 * t40 * t58 - 0.2e1 * t87 * t51 * t49 * t1 * self->ZA + t888 * n * t762 + t115 * t981;
+	t1012 = 0.6e1 * t616 * t627 - t82 * t213 + 0.2e1 * t775 * t657 - 0.12e2 * t215 * t550 - 0.6e1 * t145 * t131 + 0.2e1 * t81 * t41 * t204 + 0.6e1 * self->ZB * t48 * t49 * t370 - 0.4e1 * t70 * t382 + 0.2e1 * t446 * t255 + 0.8e1 * t89 * t4 * t327 - 0.4e1 * t56 * t147;
+	t1018 = t212 * t100;
+	t1029 = t212 * t327;
+	t1040 = 0.6e1 * t70 * t245 + 0.2e1 * t56 * t328 + t207 * t668 + 0.4e1 * t503 * t1018 + 0.2e1 * t253 * t470 - 0.6e1 * t398 * t35 * t208 - 0.8e1 * t331 * t964 * t52 - 0.4e1 * t503 * t1029 + 0.6e1 * t821 * t745 + 0.4e1 * t63 * t37 * t142 + 0.16e2 * t260 * t38 * t840;
+	t1068 = t207 * t347 - 0.2e1 * t164 * t702 - 0.2e1 * t331 * t964 * t73 + 0.8e1 * t374 * t30 * t52 + 0.16e2 * t278 * t903 + 0.2e1 * t863 * t923 + 0.6e1 * t445 * t141 * t165 - 0.2e1 * t164 * t90 * t100 + 0.6e1 * t331 * t74 - 0.2e1 * t182 * t668 - 0.2e1 * t115 * t41 * t204;
+	t1079 = t58 * t8;
+	t1091 = t807 * t29;
+	t1092 = t665 * t40;
+	t1101 = self->ZB * t91;
+	t1102 = t403 * n;
+	t1105 = -0.4e1 * t58 * self->ZB * self->ZA * t64 - t82 * t850 + 0.2e1 * t821 * t860 + t81 * t51 * t793 + 0.2e1 * t3 * t25 * t1079 * t90 + t82 * t721 - 0.2e1 * t643 * t668 + 0.16e2 * t926 * t927 * t29 * t91 * t41 + 0.32e2 * t1091 * t1092 - 0.2e1 * t219 * t220 * t19 + 0.4e1 * t139 * self->ZA * t64 + 0.4e1 * t1101 * t1102;
+	t1108 = t849 * t72;
+	t1121 = t737 * t15;
+	t1124 = t29 * t12;
+	t1133 = t116 * t1108 - 0.8e1 * t475 * t209 - 0.32e2 * t807 * self->xc * t1092 + 0.2e1 * t278 * t269 * t73 + t82 * t812 - 0.6e1 * t56 * t131 + 0.2e1 * t253 * t1121 + 0.16e2 * t926 * t927 * t1124 * t41 + t168 * t263 - 0.2e1 * t616 * t827 + t81 * t981;
+	t1134 = t394 * t28;
+	t1159 = -0.8e1 * t1134 * t29 * t18 * t57 + t82 * t118 - 0.12e2 * t215 * t1018 + 0.2e1 * t602 * t801 - t168 * t341 + 0.2e1 * t67 * t58 * t64 + t168 * t344 - 0.6e1 * t174 * t368 * t208 + 0.16e2 * t553 * t903 + t116 * t790 - 0.4e1 * t36 * t38 * t800 * t15;
+	t1161 = n * t83;
+	t1173 = self->ZB * t12;
+	t1196 = 0.4e1 * t1161 * self->ZB * t39 * self->ZA - 0.4e1 * t215 * t1029 - 0.8e1 * t488 * 0.3141592654e1 * t39 * self->xc + 0.32e2 * t821 * self->ZA * t8 * t1173 * t18 - 0.8e1 * t427 * t147 + 0.6e1 * t701 * t165 - 0.16e2 * t926 * t927 * t1124 * t18 - 0.8e1 * t1091 * t63 * t57 - 0.8e1 * t442 * t209 - 0.8e1 * t462 * t660 - 0.6e1 * t398 * t35 * t52;
+	t1228 = 0.2e1 * t413 * t305 - 0.8e1 * t648 * t961 - 0.16e2 * t87 * t27 * t23 * t28 * self->ZA * t29 + 0.4e1 * t189 * t1102 - 0.4e1 * t87 * t1079 * t212 * t879 + 0.2e1 * t164 * t948 - 0.2e1 * t70 * t923 + 0.2e1 * t164 * t322 + 0.2e1 * t446 * t1121 + 0.2e1 * t863 * t964 * t304 - t82 * t1108 + 0.16e2 * t676 * t490 * t19;
+	t1234 = t25 * self->ZB;
+	t1235 = t1234 * t28;
+	t1236 = t365 * t91;
+	t1240 = self->ZB * t121;
+	t1241 = t1240 * t77;
+	t1242 = t39 * t39;
+	t1243 = t12 * t1242;
+	t1244 = self->xc * t72;
+	t1245 = t1243 * t1244;
+	t1248 = t365 * t25;
+	t1252 = t243 * n;
+	t1257 = t23 * t1;
+	t1258 = t1240 * t1257;
+	t1259 = t67 * t12;
+	t1260 = self->xc * t16;
+	t1268 = t1234 * t121;
+	t1269 = t1268 * t23;
+	t1272 = t1242 * t91;
+	t1280 = t67 * self->xc;
+	t1284 = t28 * t28;
+	t1285 = t67 * t1284;
+	t1287 = t1285 * t2 * self->ZB;
+	t1288 = t17 * self->xc;
+	t1289 = t1243 * t1288;
+	t1292 = 0.2e1 * t1235 * t1236 * t17 + 0.8e1 * t1241 * t1245 + 0.4e1 * t927 * t1248 * t91 - 0.2e1 * t1252 * self->ZB * t1242 * t91 - 0.8e1 * t1258 * t1259 * t1260 - 0.4e1 * t1235 * t2 * t83 * t39 + 0.16e2 * t1269 * t758 + 0.2e1 * t1252 * t189 * t1272 - 0.2e1 * t1252 * t83 * t1242 * self->ZB + 0.8e1 * t1258 * t630 * t1280 - 0.32e2 * t1287 * t1289;
+	t1293 = t365 * t83;
+	t1300 = self->ZA * t1284;
+	t1304 = t17 * t1242 * t25 * t12;
+	t1307 = t927 * t2;
+	t1311 = t23 * t2;
+	t1312 = t1300 * t1311;
+	t1316 = t1234 * t1284;
+	t1317 = t1316 * t1311;
+	t1321 = t1240 * t23;
+	t1331 = t1240 * t23 * t67;
+	t1332 = t40 * t1244;
+	t1338 = t1243 * t1260;
+	t1344 = -0.2e1 * t1235 * t1293 - 0.16e2 * t181 * t365 * t901 * t12 - 0.64e2 * t1300 * t258 * t1304 + 0.8e1 * t1307 * t613 * t39 + 0.64e2 * t1312 * t265 * t402 - 0.32e2 * t1317 * t1288 * t12 - 0.16e2 * t1321 * t67 * t39 * t1244 + 0.2e1 * t1235 * n * t1272 * t17 + 0.16e2 * t1331 * t1332 + 0.64e2 * t1300 * t292 * t1304 - 0.8e1 * t1241 * t1338 - 0.2e1 * t243 * t1293 * self->ZB;
+	t1346 = t1316 * t2;
+	t1349 = t927 * n;
+	t1350 = t25 * t1242;
+	t1354 = t1268 * t1257;
+	t1366 = t1268 * t1;
+	t1370 = t29 * t17;
+	t1371 = t1243 * t1370;
+	t1386 = -0.32e2 * t1346 * t1289 + 0.4e1 * t1349 * t1350 * t91 + 0.8e1 * t1354 * t1260 * t12 - 0.16e2 * t181 * n * t901 * t1243 - 0.4e1 * t1235 * t2 * t91 * t39 + 0.8e1 * t1366 * t152 * t1242 + 0.32e2 * t1287 * t1371 + 0.8e1 * t1258 * t1280 * t152 - 0.8e1 * t1354 * t1260 * t91 + 0.128e3 * t1300 * t365 * self->xc * t1092 + 0.8e1 * t1366 * t1338;
+	t1387 = t1257 * t12;
+	t1391 = t1240 * t1;
+	t1399 = t1272 * t1260;
+	t1412 = t1285 * t1311;
+	t1427 = -0.8e1 * t1268 * t1387 * t16 - 0.8e1 * t1391 * t67 * t1242 * t1244 - 0.4e1 * t1134 * t1101 * t39 + 0.8e1 * t1241 * t1399 - 0.8e1 * t1258 * t596 + 0.4e1 * t927 * t1293 * t25 - 0.16e2 * t1331 * t758 + 0.8e1 * t1307 * t665 * t39 + 0.32e2 * t1412 * t1370 * t1173 + 0.8e1 * t1307 * t665 * t800 + 0.8e1 * t1391 * t1259 * t1242 * t16 - 0.8e1 * t1391 * t1259 * t1242 * t72;
+	t1456 = t365 * self->ZB;
+	t1468 = 0.4e1 * t927 * t1248 * t17 - 0.2e1 * t1235 * n * t1242 * t91 + 0.8e1 * t1366 * t1244 * t1242 - 0.16e2 * t1269 * t134 * t39 + 0.8e1 * t1268 * t1257 * t72 * self->xc + 0.16e2 * t1321 * t1259 * t757 + 0.32e2 * t1317 * t1370 * t12 + 0.4e1 * t1349 * t613 * t1242 + 0.2e1 * t243 * t1456 * t17 - 0.64e2 * t1285 * t365 * t12 * t189 * t490 - 0.8e1 * t1354 * t152 * self->xc;
+	t1472 = t1316 * t365;
+	t1474 = t1124 * t39 * t17;
+	t1478 = t17 * t91;
+	t1504 = t72 * t39;
+	t1511 = 0.4e1 * t1134 * t189 * t800 + 0.64e2 * t1472 * t1474 + 0.4e1 * t1235 * t2 * t1478 * t39 + 0.4e1 * t1349 * t665 * t1242 - 0.8e1 * t1258 * t1280 * t72 + 0.2e1 * t1252 * t189 * t1242 + 0.2e1 * t243 * t365 * t189 * t91 + 0.4e1 * t927 * t365 * t1478 * t25 - 0.128e3 * t1300 * t1248 * t1474 - 0.2e1 * t1235 * t1236 + 0.16e2 * t1269 * t1504 * self->xc + 0.2e1 * t1235 * t365 * t17;
+	t1545 = -0.2e1 * t1235 * t1161 * t1242 + 0.4e1 * t1349 * t1350 * t1478 - 0.8e1 * t1366 * t1245 + 0.2e1 * t1235 * t556 * t1242 - 0.32e2 * t1412 * t402 * t726 - 0.8e1 * t1366 * t1399 + 0.8e1 * t1258 * t651 - 0.2e1 * t243 * t1456 * t91 + 0.8e1 * t1268 * t1387 * t72 - 0.16e2 * t1269 * t1332 + 0.4e1 * t1134 * t189 * t39 + 0.16e2 * t1269 * t152 * t39;
+	t1564 = t1260 * t800;
+	t1583 = 0.64e2 * t1285 * t1456 * t1474 - 0.64e2 * t1472 * t1288 * t40 - 0.8e1 * t1366 * t134 * t1242 + 0.8e1 * t1307 * t362 * t39 + 0.4e1 * t1235 * t2 * t17 * t39 + 0.32e2 * t1346 * t1371 - 0.16e2 * t1269 * t1564 - 0.16e2 * t1321 * t1259 * t1504 + 0.16e2 * t1331 * t1564 - 0.64e2 * t1312 * t29 * t25 * t402 - 0.4e1 * t1134 * t83 * t39 * self->ZB - 0.32e2 * t181 * t2 * t404;
+
+	self->C2B = (t1133 + t1196 + t1068 + t811 + t466 + t1012 + t381 + t162 + t249 + t533 + t844 + t104 + t1159 + t571 + t211 + t874 + t607 + t339 + t296 + t638 + t908 + t671 + t419 + t983 + t705 + t1105 + t501 + t778 + t1040 + t1228 + t741 + t944) / (t1292 + t1344 + t1386 + t1427 + t1468 + t1511 + t1545 + t1583);
+	/****************************************************************************************/
+	t1 = n * n;
+	t2 = t1 * n;
+	t3 = t2 * nx;
+	t4 = nx * 0.3141592654e1;
+	t5 = t4 * self->xc;
+	t6 = sin(t5);
+	t7 = 0.3141592654e1 * 0.3141592654e1;
+	t9 = t3 * t6 * t7;
+	t10 = self->xc * self->xc;
+	t11 = self->ZA * self->ZA;
+	t12 = t10 * t11;
+	t13 = n * 0.3141592654e1;
+	t14 = exp(t13);
+	t15 = t14 * t14;
+	t16 = self->xc * n;
+	t18 = exp(t16 * 0.3141592654e1);
+	t19 = t18 * t18;
+	t20 = t19 * t18;
+	t21 = t15 * t20;
+	t22 = t12 * t21;
+	t25 = nx * t6;
+	t26 = t1 * 0.3141592654e1;
+	t27 = t25 * t26;
+	t28 = self->ZA * self->ZB;
+	t29 = t18 * t15;
+	t30 = t28 * t29;
+	t33 = t25 * n;
+	t34 = t11 * t15;
+	t35 = t19 * t19;
+	t36 = t35 * t18;
+	t40 = t25 * t1;
+	t41 = 0.3141592654e1 * t11;
+	t42 = t15 * t36;
+	t43 = t41 * t42;
+	t46 = nx * nx;
+	t47 = t1 * t46;
+	t48 = t47 * t11;
+	t49 = t7 * self->xc;
+	t50 = t35 * t15;
+	t51 = t49 * t50;
+	t55 = sin(t4);
+	t56 = t46 * nx * t55;
+	t58 = t56 * n * t7;
+	t59 = self->ZB * self->ZB;
+	t60 = t10 * t59;
+	t61 = t15 * t14;
+	t62 = t19 * t61;
+	t63 = t60 * t62;
+	t66 = t19 * t14;
+	t67 = t60 * t66;
+	t70 = t28 * t42;
+	t73 = cos(t5);
+	t74 = t47 * t73;
+	t75 = t7 * t11;
+	t77 = t75 * t10 * t36;
+	t80 = t73 * t46;
+	t81 = t80 * n;
+	t82 = 0.3141592654e1 * t59;
+	t83 = t82 * t42;
+	t87 = self->xc * t11;
+	t88 = t87 * t62;
+	t91 = n * nx;
+	t92 = t55 * t61;
+	t96 = nx * t55;
+	t98 = t96 * t2 * t7;
+	t101 = self->xc * t59;
+	t102 = t101 * t62;
+	t108 = t1 * t1;
+	t109 = t108 * t7;
+	t111 = t59 * t35;
+	t112 = t111 * t15;
+	t115 = t35 * t20;
+	t123 = t1 * nx * t55;
+	t124 = t61 * t35;
+	t127 = t35 * t19;
+	t128 = t61 * t127;
+	t129 = t60 * t128;
+	t132 = t56 * t16;
+	t133 = t7 * t59;
+	t134 = t133 * t124;
+	t137 = 0.6e1 * t58 * t88 - 0.2e1 * t91 * t92 * t11 + 0.2e1 * t98 * t63 - 0.6e1 * t58 * t102 - 0.2e1 * t91 * t92 * t59 - 0.16e2 * t109 * self->xc * t112 - 0.2e1 * t91 * t6 * t115 * t59 + 0.12e2 * t40 * t83 + t123 * t41 * t124 - 0.2e1 * t58 * t129 + 0.4e1 * t132 * t134;
+	t139 = t56 * 0.3141592654e1;
+	t140 = t111 * t14;
+	t144 = t49 * t124;
+	t147 = t91 * t55;
+	t148 = t61 * self->ZA;
+	t154 = self->ZA * t115 * self->xc * self->ZB;
+	t157 = t7 * 0.3141592654e1;
+	t159 = t96 * t108 * t157;
+	t160 = t10 * self->xc;
+	t161 = t160 * t59;
+	t162 = t35 * t14;
+	t163 = t161 * t162;
+	t166 = t28 * t162;
+	t169 = t80 * t13;
+	t170 = t101 * t42;
+	t173 = t2 * t11;
+	t174 = t96 * t173;
+	t175 = t7 * t10;
+	t179 = t59 * t15;
+	t184 = t15 * t15;
+	t193 = t139 * t140 + 0.4e1 * t56 * n * t11 * t144 + 0.4e1 * t147 * t148 * self->ZB + 0.4e1 * t27 * t154 + 0.8e1 * t159 * t163 - 0.12e2 * t147 * t166 + 0.2e1 * t169 * t170 - 0.16e2 * t174 * t175 * t124 + 0.2e1 * t33 * t179 * t20 - 0.2e1 * t33 * t11 * t36 * t184 + 0.2e1 * t56 * t61 * 0.3141592654e1 * self->ZA * self->ZB;
+	t194 = t173 * 0.3141592654e1;
+	t195 = self->xc * t15;
+	t196 = t195 * t19;
+	t202 = t15 * t115;
+	t203 = t28 * t202;
+	t206 = t96 * t26;
+	t207 = t14 * t127;
+	t208 = t101 * t207;
+	t211 = t12 * t128;
+	t218 = t11 * t61;
+	t219 = t218 * t35;
+	t221 = t108 * self->ZA;
+	t223 = t7 * self->ZB;
+	t224 = t223 * t50;
+	t227 = self->ZA * self->xc;
+	t228 = self->ZB * t15;
+	t229 = t228 * t36;
+	t230 = t227 * t229;
+	t233 = t87 * t207;
+	t236 = t6 * t11;
+	t240 = -0.4e1 * t194 * t196 + 0.4e1 * t194 * t195 * t127 + 0.4e1 * t33 * t203 - 0.12e2 * t206 * t208 + 0.2e1 * t58 * t211 - 0.16e2 * t47 * t10 * t133 * t50 + t139 * t219 - 0.32e2 * t221 * t10 * t224 - 0.4e1 * t169 * t230 - 0.6e1 * t98 * t233 + 0.2e1 * t91 * t236 * t20;
+	t244 = t227 * t228 * t20;
+	t252 = t184 * t18;
+	t253 = t101 * t252;
+	t256 = t35 * t35;
+	t257 = t256 * t14;
+	t258 = t28 * t257;
+	t261 = t108 * t11;
+	t263 = t7 * t35;
+	t268 = self->ZB * t61 * t35;
+	t273 = t96 * t108 * t160;
+	t274 = t157 * self->ZB;
+	t276 = t274 * t148 * t35;
+	t279 = t101 * t21;
+	t282 = 0.3141592654e1 * self->xc;
+	t283 = t59 * t36;
+	t284 = t282 * t283;
+	t289 = 0.4e1 * t169 * t244 - 0.4e1 * t132 * t133 * t162 - 0.2e1 * t147 * t140 - 0.2e1 * t27 * t253 + 0.2e1 * t139 * t258 + 0.16e2 * t261 * t10 * t263 * t15 - 0.16e2 * t206 * t227 * t268 - 0.16e2 * t273 * t276 - 0.6e1 * t27 * t279 - 0.4e1 * t40 * t284 - 0.32e2 * t9 * t230;
+	t290 = t1 * t11;
+	t291 = t96 * t290;
+	t297 = t59 * t61;
+	t298 = t297 * t127;
+	t300 = self->ZB * t36;
+	t301 = t227 * t300;
+	t304 = t1 * t59;
+	t305 = t184 * t35;
+	t310 = t46 * self->ZB;
+	t311 = t184 * self->ZA;
+	t312 = t310 * t311;
+	t314 = t60 * t21;
+	t317 = t1 * self->ZA;
+	t318 = self->ZB * t35;
+	t321 = t1 * t256;
+	t324 = t96 * t261;
+	t325 = t10 * t157;
+	t326 = t325 * t124;
+	t329 = -0.4e1 * t291 * t282 * t128 + t123 * t82 * t62 - t139 * t298 + 0.12e2 * t27 * t301 + t304 * t305 - 0.2e1 * t58 * t12 * t66 - 0.2e1 * t312 + 0.8e1 * t9 * t314 + 0.2e1 * t317 * t318 + 0.2e1 * t321 * t28 - 0.8e1 * t324 * t326;
+	t331 = t28 * t124;
+	t334 = 0.3141592654e1 * t15;
+	t335 = t334 * t127;
+	t338 = t35 * self->ZA;
+	t341 = t46 * t256;
+	t344 = t46 * t11;
+	t346 = t46 * t59;
+	t348 = t297 * t35;
+	t351 = self->ZA * t10;
+	t352 = t351 * t300;
+	t355 = t1 * self->ZB;
+	t362 = 0.12e2 * t147 * t331 - 0.4e1 * t173 * t335 - 0.2e1 * t310 * t338 - 0.2e1 * t341 * t28 - t344 * t305 - t346 * t305 + 0.2e1 * t147 * t348 + 0.16e2 * t9 * t352 + 0.2e1 * t355 * t311 + t290 * t305 + 0.2e1 * t33 * t34 * t20;
+	t363 = t36 * t184;
+	t364 = t87 * t363;
+	t368 = t47 * t73 * t7;
+	t373 = t160 * t157;
+	t374 = t373 * t124;
+	t377 = t311 * t35;
+	t380 = t12 * t62;
+	t386 = self->ZB * t10 * self->ZA * t15 * t20;
+	t389 = t87 * t66;
+	t393 = t56 * t1 * t10;
+	t401 = 0.2e1 * t27 * t364 - 0.16e2 * t368 * t279 - t123 * t41 * t257 + 0.8e1 * t324 * t374 + 0.2e1 * t355 * t377 - 0.2e1 * t98 * t380 - 0.16e2 * t9 * t386 + 0.2e1 * t58 * t389 + 0.16e2 * t393 * t276 + t123 * t82 * t162 - 0.2e1 * t33 * t179 * t36;
+	t412 = t11 * t14 * t127;
+	t416 = t11 * t19;
+	t417 = t416 * t61;
+	t421 = t96 * t2 * self->ZA;
+	t426 = t56 * n * self->ZA;
+	t427 = t318 * t14;
+	t428 = t49 * t427;
+	t431 = t82 * t29;
+	t434 = t87 * t21;
+	t442 = 0.2e1 * t33 * t11 * t184 * t18 + 0.4e1 * t81 * t284 - t139 * t412 + 0.2e1 * t147 * t219 - 0.2e1 * t147 * t417 + 0.32e2 * t421 * t175 * t268 + 0.8e1 * t426 * t428 + 0.4e1 * t81 * t431 - 0.2e1 * t169 * t434 - 0.2e1 * t98 * t129 - 0.32e2 * t47 * t28 * t51;
+	t443 = t184 * t20;
+	t447 = t61 * 0.3141592654e1;
+	t448 = t447 * t11;
+	t450 = t49 * t268;
+	t453 = t60 * t42;
+	t456 = t41 * t202;
+	t463 = t101 * t443;
+	t469 = t41 * self->xc * t20;
+	t474 = -0.8e1 * t27 * t87 * t443 - t56 * t448 - 0.8e1 * t426 * t450 + 0.8e1 * t368 * t453 + 0.4e1 * t40 * t456 + 0.4e1 * t40 * t431 - 0.4e1 * t81 * t456 - 0.4e1 * t27 * t463 + 0.6e1 * t139 * t331 + 0.2e1 * t40 * t469 - 0.16e2 * t9 * t434;
+	t482 = t108 * t10;
+	t492 = n * t46;
+	t493 = t492 * t11;
+	t495 = t282 * t19 * t184;
+	t498 = t56 * t290;
+	t499 = t325 * t162;
+	t502 = t416 * t14;
+	t504 = t60 * t207;
+	t507 = -t123 * t82 * t257 - 0.4e1 * t169 * t301 + t123 * t41 * t162 + 0.16e2 * t482 * t7 * t112 - 0.12e2 * t206 * t102 - t123 * t82 * t66 - 0.4e1 * t147 * t258 - 0.4e1 * t493 * t495 - 0.8e1 * t498 * t499 + t139 * t502 - 0.2e1 * t98 * t504;
+	t508 = t101 * t162;
+	t512 = t41 * t115 * self->xc;
+	t515 = t87 * t42;
+	t520 = self->ZB * t184;
+	t522 = t227 * t520 * t18;
+	t525 = t492 * t59;
+	t528 = t6 * t59;
+	t532 = t520 * t20;
+	t533 = t351 * t532;
+	t539 = t447 * t59;
+	t544 = 0.8e1 * t206 * t508 - 0.2e1 * t40 * t512 - 0.16e2 * t368 * t515 + 0.12e2 * t206 * t88 + 0.4e1 * t27 * t522 + 0.4e1 * t525 * t495 - 0.4e1 * t91 * t528 * t36 - 0.16e2 * t368 * t533 - 0.16e2 * t206 * t227 * t427 - t56 * t539 - 0.2e1 * t132 * t133 * t66;
+	t551 = t87 * t162;
+	t554 = t351 * t229;
+	t560 = t59 * t19;
+	t561 = t560 * t14;
+	t564 = t101 * t202;
+	t567 = t87 * t252;
+	t573 = t227 * t228 * t115;
+	t578 = 0.4e1 * t33 * t70 + 0.4e1 * t493 * t335 - 0.4e1 * t58 * t551 + 0.16e2 * t9 * t554 - 0.4e1 * t33 * t28 * t252 + 0.2e1 * t147 * t561 + 0.2e1 * t169 * t564 - 0.2e1 * t27 * t567 - 0.8e1 * t324 * t499 - 0.4e1 * t169 * t573 + 0.12e2 * t27 * t244;
+	t579 = t82 * t202;
+	t591 = t282 * t115 * t59;
+	t598 = t101 * t66;
+	t606 = -0.4e1 * t81 * t579 - 0.2e1 * t169 * t567 - 0.6e1 * t27 * t170 + 0.8e1 * t169 * t203 + 0.2e1 * t98 * t67 + 0.2e1 * t81 * t591 + 0.32e2 * t368 * t244 - 0.2e1 * t27 * t564 + 0.4e1 * t206 * t598 + 0.16e2 * t9 * t170 + 0.2e1 * t33 * t283 * t184;
+	t608 = t373 * t162;
+	t611 = t59 * t184;
+	t617 = t101 * t29;
+	t624 = t227 * self->ZB * t18 * t15;
+	t629 = t157 * t59;
+	t630 = t629 * t124;
+	t633 = t3 * t6;
+	t634 = t175 * t283;
+	t644 = 0.8e1 * t498 * t608 + 0.2e1 * t33 * t611 * t18 - 0.4e1 * t206 * t389 - 0.2e1 * t27 * t617 - 0.4e1 * t169 * t154 + 0.4e1 * t27 * t624 + 0.12e2 * t27 * t230 - 0.8e1 * t393 * t630 - 0.8e1 * t633 * t634 + 0.16e2 * t47 * t7 * t101 * t50 + 0.2e1 * t123 * t447 * t28;
+	t645 = t41 * t29;
+	t648 = t2 * 0.3141592654e1;
+	t649 = t648 * self->xc;
+	t650 = t560 * t184;
+	t656 = t56 * t1 * t157;
+	t659 = t87 * t128;
+	t662 = t96 * t482;
+	t663 = t629 * t162;
+	t671 = t161 * t124;
+	t674 = t218 * t127;
+	t679 = 0.4e1 * t81 * t645 - 0.4e1 * t649 * t650 - 0.8e1 * t169 * t70 + 0.8e1 * t656 * t163 - 0.2e1 * t98 * t659 - 0.8e1 * t662 * t663 - 0.32e2 * t421 * t175 * t427 - 0.2e1 * t147 * t502 + 0.8e1 * t656 * t671 + 0.2e1 * t147 * t674 - 0.16e2 * t368 * t386;
+	t714 = t334 * t19;
+	t719 = t12 * t42;
+	t722 = t304 * t35 - t346 * t35 + t341 * t59 - t344 * t35 + t344 * t256 + t346 * t184 - 0.16e2 * t368 * t554 - 0.16e2 * t48 * t175 * t50 + 0.4e1 * t525 * t714 - 0.2e1 * t58 * t659 + 0.8e1 * t368 * t719;
+	t730 = self->xc * t19;
+	t735 = t59 * t256 * t14;
+	t752 = 0.4e1 * t173 * t714 - 0.6e1 * t27 * t515 - 0.16e2 * t9 * t279 + 0.4e1 * t194 * t730 * t184 - t139 * t735 - 0.4e1 * t492 * t127 * t82 * self->xc - 0.4e1 * t98 * t508 - t123 * t41 * t207 - 0.2e1 * t147 * t298 + 0.8e1 * t368 * t314 + 0.6e1 * t132 * t133 * t207;
+	t755 = t28 * t21;
+	t759 = t274 * t338 * t14;
+	t767 = t11 * t35;
+	t768 = t767 * t14;
+	t778 = t560 * t61;
+	t781 = -0.2e1 * t58 * t504 - 0.8e1 * t27 * t755 + 0.16e2 * t662 * t759 + 0.12e2 * t291 * t282 * t207 - 0.6e1 * t27 * t434 + t139 * t768 - 0.8e1 * t498 * t326 + 0.4e1 * t33 * t611 * t20 + 0.2e1 * t81 * t512 - t139 * t561 + 0.2e1 * t147 * t778;
+	t786 = t12 * t443;
+	t790 = t282 * t59 * t20;
+	t796 = t59 * t14 * t127;
+	t806 = t41 * t21;
+	t811 = -0.8e1 * t393 * t663 + 0.8e1 * t368 * t786 + 0.2e1 * t81 * t790 + 0.4e1 * t169 * t624 + t139 * t796 + 0.2e1 * t206 * t258 - 0.2e1 * t40 * t591 - 0.8e1 * t662 * t630 - 0.4e1 * t33 * t30 - 0.4e1 * t40 * t806 + 0.8e1 * t9 * t786;
+	t819 = t282 * t15 * t127;
+	t822 = t101 * t363;
+	t830 = t11 * t256 * t14;
+	t835 = t227 * t532;
+	t842 = 0.2e1 * t33 * t11 * t18 * t15 + t123 * t41 * t66 - 0.4e1 * t493 * t819 - 0.2e1 * t27 * t822 - 0.16e2 * t368 * t170 - 0.4e1 * t169 * t463 - t139 * t830 - 0.4e1 * t649 * t179 * t127 + 0.12e2 * t27 * t835 - 0.16e2 * t368 * t434 - 0.2e1 * t40 * t790;
+	t845 = t87 * t202;
+	t854 = t338 * t15;
+	t859 = t12 * t207;
+	t868 = t139 * t348 - 0.2e1 * t27 * t845 + 0.8e1 * t169 * t755 - 0.2e1 * t58 * t380 + 0.6e1 * t206 * t331 + 0.8e1 * t310 * t854 - 0.2e1 * t169 * t822 + 0.2e1 * t98 * t859 + 0.8e1 * t159 * t671 + 0.8e1 * t74 * t634 - 0.2e1 * t169 * t253;
+	t880 = t60 * t443;
+	t891 = t101 * t128;
+	t894 = -t123 * t539 - 0.2e1 * t147 * t796 + 0.32e2 * t368 * t230 + t139 * t674 - 0.16e2 * t98 * t60 * t124 + 0.32e2 * t9 * t244 + 0.8e1 * t368 * t880 - 0.8e1 * t40 * t41 * self->xc * t36 - t123 * t82 * t128 - 0.6e1 * t58 * t233 + 0.2e1 * t58 * t891;
+	t903 = t179 * t19;
+	t920 = t56 * t1 * t160;
+	t925 = -0.2e1 * t174 * t175 * t66 - 0.4e1 * t493 * t714 + 0.4e1 * t649 * t903 - 0.4e1 * t81 * t43 + t123 * t82 * t207 + 0.4e1 * t206 * t891 - 0.16e2 * t273 * t759 - 0.8e1 * t27 * t203 + 0.32e2 * t221 * self->ZB * t51 - 0.16e2 * t920 * t759 - 0.8e1 * t9 * t453;
+	t932 = t87 * t29;
+	t945 = t82 * t21;
+	t953 = -0.16e2 * t920 * t276 - 0.8e1 * t169 * t30 - 0.8e1 * t633 * t77 - 0.2e1 * t27 * t932 - 0.4e1 * t174 * t49 * t162 + 0.8e1 * t206 * t87 * t124 - 0.2e1 * t147 * t768 + 0.4e1 * t169 * t522 - 0.12e2 * t81 * t945 + 0.4e1 * t33 * t28 * t115 + 0.4e1 * t525 * t819;
+	t971 = t282 * t127;
+	t978 = -0.6e1 * t98 * t102 + 0.2e1 * t169 * t515 - 0.2e1 * t310 * t377 + 0.2e1 * t147 * t830 + 0.8e1 * t368 * t22 - 0.2e1 * t169 * t617 + 0.16e2 * t662 * t276 - 0.8e1 * t355 * t854 + 0.4e1 * t493 * t971 - 0.16e2 * t9 * t533 - 0.2e1 * t169 * t279;
+	t997 = self->xc * t127;
+	t998 = t997 * t59;
+	t1003 = 0.4e1 * t40 * t579 + 0.2e1 * t169 * t845 + 0.16e2 * t9 * t515 + 0.8e1 * t206 * t551 + t123 * t41 * t128 + 0.16e2 * t98 * t60 * t162 + 0.2e1 * t169 * t364 - 0.2e1 * t169 * t932 + t139 * t778 + 0.4e1 * t648 * t998 + 0.2e1 * t147 * t412;
+	t1006 = t2 * t59;
+	t1017 = self->xc * t35;
+	t1033 = 0.4e1 * t1006 * t335 + 0.4e1 * t81 * t806 - 0.2e1 * t33 * t34 * t115 + 0.8e1 * t498 * t374 - 0.16e2 * t261 * t7 * t1017 * t15 + 0.8e1 * t206 * t101 * t124 - t123 * t448 + 0.2e1 * t147 * t735 + 0.6e1 * t98 * t208 + 0.6e1 * t98 * t88 - 0.4e1 * t33 * t755;
+	t1055 = -0.4e1 * t173 * t971 + 0.2e1 * t98 * t891 + 0.8e1 * t9 * t880 + 0.4e1 * t169 * t835 - t304 * t184 + t344 * t184 - t123 * t41 * t62 - 0.2e1 * t98 * t598 + 0.2e1 * t58 * t859 + 0.32e2 * t47 * t351 * t224 + 0.2e1 * t98 * t389;
+	t1070 = t15 * t19;
+	t1089 = -0.16e2 * t368 * t352 - 0.8e1 * t9 * t719 + 0.4e1 * t96 * t2 * self->xc * t134 - 0.2e1 * t91 * t236 * t115 + 0.4e1 * t27 * t573 + 0.4e1 * t493 * t282 * t1070 + 0.2e1 * t33 * t59 * t18 * t15 + 0.12e2 * t40 * t945 - 0.4e1 * t492 * self->xc * t82 * t1070 - 0.2e1 * t91 * t528 * t20 + 0.8e1 * t324 * t608;
+	t1113 = t123 * t82 * t124 + 0.8e1 * t421 * t428 - t139 * t417 + 0.4e1 * t40 * t645 + 0.16e2 * t393 * t759 - 0.2e1 * t33 * t179 * t115 - 0.4e1 * t525 * t335 + 0.4e1 * t33 * t28 * t36 - 0.4e1 * t1006 * t714 + 0.6e1 * t206 * t166 - 0.8e1 * t421 * t450;
+	t1119 = t321 * t46;
+	t1122 = t157 * t11;
+	t1123 = t1122 * t2;
+	t1124 = t184 * t46;
+	t1128 = t108 * n;
+	t1132 = t7 * t7;
+	t1133 = t1132 * t11;
+	t1134 = t1133 * t108;
+	t1135 = t15 * t46;
+	t1139 = t7 * self->ZA;
+	t1140 = t1139 * self->ZB;
+	t1141 = t1 * t35;
+	t1145 = t629 * t2;
+	t1146 = t1135 * t730;
+	t1149 = t157 * t1128;
+	t1150 = t1149 * self->xc;
+	t1153 = t46 * self->xc;
+	t1154 = t1153 * t127;
+	t1158 = t184 * t1 * t46;
+	t1161 = t46 * t46;
+	t1162 = t35 * t1161;
+	t1166 = t7 * t1;
+	t1170 = -0.4e1 * t133 * t1119 + 0.16e2 * t1123 * t1124 * t730 - 0.8e1 * t1122 * t1128 * t196 - 0.64e2 * t1134 * t1135 * t1017 - 0.32e2 * t1140 * t1141 * t1135 + 0.16e2 * t1145 * t1146 - 0.8e1 * t1150 * t650 - 0.16e2 * t1123 * t1154 - 0.4e1 * t133 * t1158 - 0.16e2 * t1140 * t1162 * t15 + 0.8e1 * t1166 * t35 * t312;
+	t1171 = t1161 * t184;
+	t1175 = t1122 * n;
+	t1176 = t15 * t1161;
+	t1180 = t1132 * self->ZA;
+	t1181 = t1180 * t355;
+	t1182 = t1176 * t1017;
+	t1185 = t1161 * self->xc;
+	t1189 = t1133 * t1;
+	t1192 = t108 * t1;
+	t1193 = t1132 * t1192;
+	t1195 = t10 * t35;
+	t1199 = t157 * t15;
+	t1203 = t1141 * t46;
+	t1211 = t184 * t108;
+	t1218 = 0.2e1 * t133 * t1171 * t35 + 0.8e1 * t1175 * t1176 * t997 + 0.64e2 * t1181 * t1182 - 0.8e1 * t1175 * t1185 * t127 - 0.32e2 * t1189 * t1182 - 0.64e2 * t1193 * self->ZA * t1195 * t228 + 0.8e1 * t1199 * t416 * t1128 + 0.8e1 * t1140 * t1203 - 0.4e1 * t75 * t1158 - 0.8e1 * t1199 * t560 * t1128 - 0.2e1 * t133 * t1211 - 0.8e1 * t1199 * t127 * t11 * t1128;
+	t1221 = t256 * t1161;
+	t1224 = t35 * t108;
+	t1233 = t7 * t256;
+	t1236 = -t75 * t1211 - t75 * t1221 - t133 * t1221 + t75 * t1224 - t75 * t1171 - t133 * t1171 + t133 * t1224 + t75 * t1162 - t75 * t108 * t256 + t133 * t1162 - t1233 * t59 * t108;
+	t1240 = t1135 * t1195;
+	t1252 = t629 * t127;
+	t1263 = t1171 * self->ZA;
+	t1280 = -0.128e3 * t1180 * self->ZB * t108 * t1240 + 0.32e2 * t1193 * t10 * t112 + 0.4e1 * t133 * t1203 + 0.4e1 * t109 * t256 * self->ZA * self->ZB - 0.8e1 * t1252 * n * t15 * t1185 + 0.8e1 * t1175 * t1171 * t730 - 0.8e1 * t1175 * t1176 * t127 + 0.4e1 * t223 * t1263 - 0.8e1 * t1175 * t1176 * t730 + 0.8e1 * t1166 * self->ZA * t341 * self->ZB + 0.64e2 * t1134 * t1240 + 0.8e1 * t1122 * self->xc * t1128 * t127 * t15;
+	t1283 = t1199 * t19;
+	t1287 = t1199 * t127;
+	t1289 = t59 * n * t1161;
+	t1293 = t157 * n * self->xc;
+	t1304 = t1132 * t108;
+	t1310 = t263 * self->ZB;
+	t1316 = t2 * t15;
+	t1323 = -0.16e2 * t1283 * t1006 * t46 + 0.8e1 * t1287 * t1289 + 0.8e1 * t1293 * t127 * t1161 * t59 + 0.16e2 * t1123 * t1135 * t19 + 0.8e1 * t1293 * t560 * t1176 + 0.64e2 * t1304 * t59 * t1240 + 0.4e1 * t75 * t1203 + 0.4e1 * t1310 * t1263 + 0.4e1 * t223 * t338 * t108 - 0.16e2 * t1252 * t1316 * t1153 - 0.16e2 * t1310 * t221 * t15;
+	t1330 = t1132 * t15;
+	t1336 = t1132 * t1;
+	t1338 = t1162 * t179;
+	t1370 = 0.8e1 * t1175 * t1176 * t19 + 0.4e1 * t1139 * t318 * t1161 + 0.128e3 * t1330 * t318 * t108 * t46 * t227 - 0.32e2 * t1336 * self->xc * t1338 + 0.4e1 * t1233 * self->ZA * t1161 * self->ZB - 0.8e1 * t1287 * t59 * t1128 * self->xc + 0.2e1 * t75 * t305 * t108 + 0.8e1 * t1199 * t127 * t59 * t1128 - 0.8e1 * t1283 * t1289 - 0.8e1 * t1293 * t560 * t1171 + 0.4e1 * t133 * t35 * t1158 + 0.8e1 * t157 * t184 * t19 * t11 * t1128 * self->xc;
+	t1376 = t7 * t184;
+	t1380 = t1176 * t1195;
+	t1393 = t1330 * t35;
+	t1411 = 0.16e2 * t1145 * t1154 + 0.8e1 * t1149 * t998 + 0.4e1 * t1376 * t35 * t48 + 0.32e2 * t1189 * t1380 + 0.32e2 * t1193 * t11 * t1195 * t15 - 0.64e2 * t1304 * self->xc * t111 * t1135 - 0.16e2 * t1123 * t1146 + 0.64e2 * t1393 * t28 * t1192 * self->xc - 0.16e2 * t1123 * t1135 * t127 - 0.8e1 * t1122 * self->xc * t1128 * t127 - 0.32e2 * t1193 * self->xc * t112 + 0.16e2 * t1252 * t1316 * t46;
+	t1450 = 0.2e1 * t1376 * t767 * t1161 + 0.2e1 * t1376 * t111 * t108 + 0.4e1 * t223 * t311 * t108 + 0.4e1 * t109 * t35 * t520 * self->ZA + 0.16e2 * t1123 * t1135 * t997 - 0.64e2 * t1181 * t1380 + 0.8e1 * t1150 * t903 - 0.32e2 * t1393 * t11 * t1192 * self->xc - 0.16e2 * t157 * t2 * self->xc * t560 * t1124 + 0.8e1 * t223 * t184 * t317 * t46 + 0.32e2 * t1336 * t10 * t1338 - 0.4e1 * t75 * t1119;
+	self->C3B = (t606 + t722 + t1089 + t781 + 0.16e2 * t48 * t51 + t978 + t868 + t507 - t304 * t256 + 0.8e1 * t9 * t22 + t752 + 0.4e1 * t174 * t144 - 0.2e1 * t81 * t469 + 0.6e1 * t139 * t166 + t362 + 0.2e1 * t98 * t211 + t925 + t137 - t290 * t184 + 0.12e2 * t81 * t83 + t842 + 0.8e1 * t74 * t77 + 0.16e2 * t98 * t12 * t162 - 0.4e1 * t33 * t28 * t443 - 0.8e1 * t27 * t70 - 0.2e1 * t33 * t34 * t36 - 0.8e1 * t27 * t30 + 0.2e1 * t58 * t67 - 0.4e1 * t40 * t43 + 0.2e1 * t58 * t63 + t1033 - t290 * t256 + t290 * t35 + t193 + t1113 + t578 + t442 + t474 + t544 + t329 + t679 + t401 + t953 + t811 + t644 + t894 + t289 + t240 + t1055 + t1003) / (t1170 + t1218 + 0.2e1 * t1236 + t1280 + t1323 + t1370 + t1411 + t1450);
+	/****************************************************************************************/
+	t1 = n * n;
+	t2 = t1 * self->xc;
+	t3 = self->ZB * self->ZB;
+	t5 = t2 * 0.3141592654e1 * t3;
+	t6 = nx * 0.3141592654e1;
+	t7 = t6 * self->xc;
+	t8 = cos(t7);
+	t9 = nx * nx;
+	t10 = t8 * t9;
+	t11 = n * 0.3141592654e1;
+	t12 = exp(t11);
+	t13 = t12 * t12;
+	t16 = exp( self->xc * n * 0.3141592654e1);
+	t17 = t16 * t16;
+	t18 = t17 * t16;
+	t19 = t17 * t17;
+	t20 = t19 * t18;
+	t21 = t13 * t20;
+	t22 = t10 * t21;
+	t25 = self->ZA * self->ZA;
+	t26 = t1 * t25;
+	t27 = self->xc * 0.3141592654e1;
+	t28 = t26 * t27;
+	t29 = t19 * t16;
+	t30 = t13 * t13;
+	t31 = t29 * t30;
+	t35 = t9 * nx;
+	t36 = t3 * t35;
+	t37 = sin(t6);
+	t38 = t13 * t12;
+	t39 = t37 * t38;
+	t40 = t39 * t19;
+	t42 = t1 * t1;
+	t43 = nx * t42;
+	t44 = self->xc * self->xc;
+	t45 = t25 * t44;
+	t46 = t43 * t45;
+	t47 = 0.3141592654e1 * 0.3141592654e1;
+	t48 = t47 * t37;
+	t49 = t17 * t38;
+	t54 = 0.3141592654e1 * t35;
+	t55 = self->ZA * n * t54;
+	t56 = t37 * self->ZB;
+	t57 = t19 * t12;
+	t61 = t25 * t8;
+	t62 = t61 * t9;
+	t63 = n * t30;
+	t64 = t63 * t16;
+	t67 = t1 * n;
+	t69 = t47 * self->ZB;
+	t70 = t67 * t44 * t69;
+	t75 = nx * t3;
+	t76 = t75 * t37;
+	t77 = t67 * 0.3141592654e1;
+	t78 = t19 * t19;
+	t79 = t78 * t12;
+	t80 = t77 * t79;
+	t82 = t3 * t38;
+	t84 = t54 * t37;
+	t87 = sin(t7);
+	t88 = t29 * t87;
+	t89 = t47 * t44;
+	t93 = nx * t25;
+	t94 = t87 * t42;
+	t95 = t93 * t94;
+	t96 = t47 * self->xc;
+	t97 = t13 * t29;
+	t98 = t96 * t97;
+	t101 = t87 * t67;
+	t102 = t93 * t101;
+	t103 = t13 * t18;
+	t107 = t47 * t35;
+	t108 = t26 * t107;
+	t109 = t37 * t44;
+	t110 = t19 * t17;
+	t111 = t12 * t110;
+	t116 = t37 * t19 * t12;
+	t118 = t37 * self->xc;
+	t119 = self->ZB * t19;
+	t120 = t119 * t12;
+	t121 = t118 * t120;
+	t125 = self->xc * t3;
+	t126 = t1 * t47 * t125;
+	t127 = t35 * t37;
+	t128 = t38 * t19;
+	t129 = t127 * t128;
+	t132 = t26 * 0.3141592654e1;
+	t133 = t16 * t13;
+	t134 = t10 * t133;
+	t137 = 0.3141592654e1 * self->ZB;
+	t138 = t2 * t137;
+	t139 = self->ZA * t8;
+	t140 = t9 * t13;
+	t145 = t30 * t18;
+	t146 = t10 * t145;
+	t149 = t3 * t8;
+	t150 = t149 * t9;
+	t153 = 0.2e1 * t5 * t22 + 0.2e1 * t28 * t10 * t31 + t36 * t40 - 0.2e1 * t46 * t48 * t49 - 0.2e1 * t55 * t56 * t57 - 0.2e1 * t62 * t64 + 0.16e2 * t70 * t29 * self->ZA * t10 - t76 * t80 + t82 * n * t84 + 0.8e1 * t43 * t3 * t88 * t89 + 0.16e2 * t95 * t98 + 0.2e1 * t102 * t27 * t103 - 0.2e1 * t108 * t109 * t111 + t36 * t116 + 0.8e1 * t55 * t121 - 0.4e1 * t126 * t129 - 0.4e1 * t132 * t134 - 0.4e1 * t138 * t139 * t140 * t20 + 0.8e1 * t28 * t146 - 0.2e1 * t150 * t64;
+	t154 = t42 * n;
+	t155 = nx * t154;
+	t156 = t44 * self->xc;
+	t157 = t47 * 0.3141592654e1;
+	t158 = t156 * t157;
+	t159 = t155 * t158;
+	t162 = t56 * self->ZA * t19 * t12;
+	t165 = t77 * t49;
+	t167 = t1 * t3;
+	t168 = t167 * t89;
+	t169 = t127 * t49;
+	t172 = t37 * t67;
+	t173 = t75 * t172;
+	t174 = t38 * t110;
+	t175 = t27 * t174;
+	t179 = t47 * t25;
+	t181 = t10 * t97;
+	t184 = t27 * t31;
+	t187 = t67 * t47;
+	t188 = t44 * t3;
+	t189 = t187 * t188;
+	t192 = t25 * t35;
+	t193 = t37 * t17;
+	t194 = t193 * t12;
+	t196 = nx * self->ZA;
+	t197 = t196 * t172;
+	t198 = self->ZB * t38;
+	t199 = t198 * t19;
+	t204 = t1 * t12 * t110;
+	t207 = nx * self->ZB;
+	t209 = t1 * self->ZA;
+	t215 = t67 * t3;
+	t216 = t47 * t8;
+	t217 = t215 * t216;
+	t218 = t9 * self->xc;
+	t222 = nx * t67;
+	t223 = t222 * t27;
+	t224 = t3 * t87;
+	t228 = t167 * t107;
+	t232 = t26 * t96;
+	t235 = t207 * t94;
+	t236 = t47 * self->ZA;
+	t243 = self->xc * t13;
+	t244 = t243 * t29;
+	t248 = t25 * n;
+	t249 = t248 * 0.3141592654e1;
+	t253 = self->ZB * self->ZA;
+	t254 = t253 * t8;
+	t255 = t9 * n;
+	t256 = t30 * t16;
+	t260 = 0.2e1 * t207 * t37 * t209 * t128 + 0.2e1 * t5 * t134 - 0.16e2 * t217 * t218 * t97 - 0.2e1 * t223 * t224 * t31 - 0.2e1 * t228 * t109 * t174 - 0.2e1 * t232 * t169 - 0.16e2 * t235 * t236 * t44 * t30 * t18 - 0.4e1 * t196 * t101 * t137 * t244 + t249 * t169 + 0.8e1 * t168 * t129 + 0.4e1 * t254 * t255 * t256;
+	t263 = t43 * t179;
+	t267 = t3 * n;
+	t268 = t267 * t54;
+	t269 = t118 * t57;
+	t272 = t39 * t1;
+	t274 = t67 * t25;
+	t275 = t274 * t158;
+	t278 = t75 * t87;
+	t279 = t77 * t103;
+	t282 = t25 * t38;
+	t285 = self->ZA * t38;
+	t290 = t267 * 0.3141592654e1;
+	t296 = t77 * t111;
+	t298 = t196 * t37;
+	t299 = t1 * self->ZB;
+	t303 = t37 * t42;
+	t304 = t196 * t303;
+	t308 = t77 * t57;
+	t310 = t26 * t89;
+	t313 = t77 * t128;
+	t316 = t101 * t27;
+	t319 = t93 * t87;
+	t320 = t77 * t97;
+	t323 = t127 * t57;
+	t326 = t10 * n;
+	t329 = t118 * t174;
+	t332 = -0.8e1 * t263 * t109 * t57 - 0.4e1 * t268 * t269 + t93 * t272 + 0.8e1 * t275 * t129 - 0.4e1 * t278 * t279 + t282 * n * t84 - 0.2e1 * t285 * n * t54 * t56 - t290 * t169 - 0.2e1 * t196 * t38 * t172 * t137 + t76 * t296 - 0.2e1 * t298 * t299 * t79 + 0.8e1 * t304 * t96 * t120 + t76 * t308 - 0.2e1 * t310 * t169 - t76 * t313 + 0.2e1 * t75 * t18 * t316 + 0.4e1 * t319 * t320 + t249 * t323 - 0.2e1 * t25 * t18 * t326 + 0.2e1 * t228 * t329;
+	t335 = t75 * t101;
+	t336 = t27 * t21;
+	t342 = t77 * t133;
+	t347 = t209 * t137;
+	t350 = t9 * t1;
+	t351 = t149 * t350;
+	t355 = t37 * t78 * t12;
+	t359 = t93 * t303;
+	t367 = t172 * 0.3141592654e1;
+	t369 = t96 * t103;
+	t376 = t209 * t107;
+	t379 = t10 * t103;
+	t383 = t207 * t101;
+	t389 = 0.3141592654e1 * self->ZA;
+	t390 = t222 * t389;
+	t391 = t87 * self->ZB;
+	t398 = -0.2e1 * t102 * t336 + t93 * t38 * t367 + 0.16e2 * t95 * t369 - t82 * t127 - 0.8e1 * t197 * t27 * t120 + 0.8e1 * t376 * t121 - 0.8e1 * t189 * t379 - t249 * t129 - 0.4e1 * t383 * t27 * self->ZA * t16 * t13 - 0.8e1 * t390 * t391 * t21 - 0.2e1 * t197 * t137 * t57;
+	t402 = t39 * t110;
+	t404 = t193 * t38;
+	t406 = t127 * t174;
+	t408 = t167 * 0.3141592654e1;
+	t411 = t44 * t157;
+	t412 = t155 * t411;
+	t413 = t285 * t19;
+	t414 = t56 * t413;
+	t417 = self->ZA * t30;
+	t424 = t93 * t37;
+	t426 = t248 * t54;
+	t427 = t17 * t12;
+	t428 = t118 * t427;
+	t431 = t77 * t21;
+	t438 = self->ZA * t13;
+	t443 = t93 * t172;
+	t444 = t27 * t427;
+	t448 = t1 * t78 * t12;
+	t455 = t274 * t89;
+	t461 = t118 * t111;
+	t464 = -t36 * t402 + t36 * t404 - t249 * t406 - 0.4e1 * t408 * t134 + 0.16e2 * t412 * t414 - 0.4e1 * t383 * t27 * t417 * t18 + 0.2e1 * t28 * t22 - t424 * t80 - 0.2e1 * t426 * t428 + 0.4e1 * t278 * t431 + 0.4e1 * t254 * t255 * t103 + t290 * t323 + 0.4e1 * t383 * t27 * t438 * t20 + 0.2e1 * t443 * t444 + t424 * t448 - t36 * t194 - 0.32e2 * t235 * t236 * t243 * t18 + 0.8e1 * t455 * t181 - 0.4e1 * t359 * t96 * t128 - 0.2e1 * t426 * t461;
+	t469 = n * t16 * t13;
+	t474 = t1 * t38;
+	t475 = t474 * t19;
+	t480 = t89 * t103;
+	t483 = t67 * self->ZA;
+	t484 = t483 * t411;
+	t485 = t127 * t120;
+	t488 = t127 * t111;
+	t497 = t77 * t427;
+	t502 = t27 * t97;
+	t508 = t1 * t19 * t12;
+	t511 = t155 * t25 * t156;
+	t512 = t157 * t37;
+	t513 = t512 * t128;
+	t527 = t1 * t17;
+	t528 = t527 * t38;
+	t530 = -t76 * t497 - 0.4e1 * t254 * t255 * t97 - 0.2e1 * t102 * t502 - 0.4e1 * t108 * t269 - t76 * t508 + 0.8e1 * t511 * t513 + 0.4e1 * t150 * t63 * t18 + 0.4e1 * t383 * t27 * t438 * t18 + 0.4e1 * t132 * t379 + 0.2e1 * t168 * t488 - t76 * t528;
+	t535 = t44 * t13;
+	t542 = t527 * t12;
+	t544 = n * t13;
+	t545 = t544 * t20;
+	t548 = t75 * t303;
+	t549 = t96 * t111;
+	t552 = self->ZA * t35;
+	t553 = t552 * t37;
+	t562 = t43 * t96;
+	t563 = t3 * t37;
+	t564 = t563 * t128;
+	t579 = t474 * t110;
+	t590 = t9 * t30;
+	t591 = t590 * t18;
+	t595 = t127 * t427;
+	t598 = t77 * t174;
+	t600 = 0.4e1 * t5 * t146 + 0.16e2 * t235 * t236 * t535 * t18 + 0.8e1 * t455 * t146 + t76 * t542 - 0.2e1 * t150 * t545 + 0.2e1 * t548 * t549 - 0.2e1 * t553 * t120 + t290 * t488 - 0.8e1 * t274 * t47 * t44 * t29 * t10 - 0.4e1 * t562 * t564 - 0.2e1 * t132 * self->xc * t20 * t10 - 0.32e2 * t562 * self->ZA * t87 * self->ZB * t13 * t29 - 0.8e1 * t347 * t379 + t76 * t579 - 0.4e1 * t359 * t96 * t57 + 0.4e1 * t408 * t181 - 0.4e1 * t223 * t564 - 0.12e2 * t209 * t27 * self->ZB * t8 * t591 + 0.2e1 * t310 * t595 + t76 * t598;
+	t601 = t27 * t49;
+	t604 = t127 * t79;
+	t606 = self->ZB * t29;
+	t616 = t139 * t140 * t18;
+	t638 = t10 * t256;
+	t643 = t118 * t199;
+	t653 = t544 * t29;
+	t658 = t3 * t29;
+	t660 = t350 * t27;
+	t663 = -0.4e1 * t254 * t255 * t145 + 0.2e1 * t267 * t20 * t8 * t9 - 0.4e1 * t138 * t139 * t9 * t16 * t13 - 0.2e1 * t5 * t638 + 0.2e1 * t126 * t169 + 0.8e1 * t376 * t643 + 0.4e1 * t335 * t27 * t145 + 0.16e2 * t235 * t236 * t535 * t29 + 0.6e1 * t150 * t653 - 0.4e1 * t426 * t269 + 0.4e1 * t658 * t8 * t660;
+	t670 = t274 * t411;
+	t673 = t118 * t49;
+	t694 = t155 * t45;
+	t713 = n * t29 * t30;
+	t717 = t20 * t87;
+	t723 = t512 * t57;
+	t728 = -0.2e1 * t443 * t175 - 0.8e1 * t670 * t129 + 0.2e1 * t426 * t673 - 0.16e2 * t207 * t88 * t42 * t47 * self->ZA * t44 + 0.4e1 * t254 * t255 * t21 + t249 * t595 + 0.8e1 * t25 * t29 * t8 * t660 + 0.2e1 * t268 * t461 + 0.8e1 * t189 * t181 - 0.8e1 * t694 * t513 + 0.2e1 * t198 * t553 - 0.12e2 * t606 * t139 * t660 - 0.2e1 * t359 * t549 + 0.4e1 * t138 * t139 * t590 * t16 + 0.8e1 * t93 * t29 * t94 * t89 - 0.2e1 * t150 * t713 + 0.2e1 * t222 * t3 * t717 * t27 + 0.8e1 * t670 * t323 + 0.8e1 * t694 * t723 - 0.2e1 * t62 * t653;
+	t734 = t43 * t89;
+	t735 = t563 * t427;
+	t740 = t75 * t94;
+	t744 = self->ZB * self->xc;
+	t750 = t563 * t57;
+	t754 = t218 * t103;
+	t771 = t127 * t199;
+	t776 = t89 * t174;
+	t791 = -0.4e1 * t207 * t717 * t77 * self->xc * self->ZA + 0.4e1 * t443 * t27 * t57 + t192 * t40 - 0.8e1 * t55 * t643 - 0.16e2 * t209 * t89 * t771 - 0.8e1 * t275 * t323 + 0.2e1 * t359 * t776 + 0.16e2 * t304 * t89 * t199 + 0.4e1 * t278 * t320 + 0.2e1 * t207 * t172 * t389 * t79 - 0.8e1 * t390 * t391 * t97;
+	t794 = t483 * t158;
+	t801 = t2 * 0.3141592654e1;
+	t818 = t215 * t411;
+	t827 = t96 * t174;
+	t837 = t37 * t12 * t110;
+	t845 = 0.16e2 * t794 * t485 + 0.8e1 * t159 * t564 - 0.8e1 * t455 * t379 - 0.2e1 * t801 * t3 * t20 * t10 - 0.4e1 * t132 * t22 - 0.8e1 * t734 * t564 - 0.8e1 * t187 * t44 * t658 * t10 - 0.8e1 * t412 * t564 + 0.4e1 * t132 * t181 - 0.8e1 * t818 * t129 + 0.2e1 * t46 * t48 * t427 - 0.4e1 * t75 * t29 * t316 - 0.2e1 * t359 * t827 - t290 * t595 + 0.16e2 * t217 * t754 - t424 * t542 - 0.8e1 * t734 * t750 - t192 * t837 - 0.4e1 * t254 * t255 * t133 + 0.8e1 * t304 * t96 * t199;
+	t864 = t544 * t18;
+	t867 = t3 * t18;
+	t884 = t27 * t256;
+	t891 = t187 * t744;
+	t894 = t563 * t49;
+	t900 = -0.2e1 * t263 * t428 + 0.2e1 * t228 * t428 - 0.6e1 * t223 * t224 * t103 - t192 * t404 + 0.2e1 * t268 * t428 - 0.2e1 * t335 * t884 - t424 * t296 + 0.2e1 * t93 * t20 * t316 - 0.32e2 * t891 * t616 + 0.2e1 * t562 * t894 - 0.2e1 * t801 * t867 * t10;
+	t904 = t27 * t111;
+	t907 = t118 * t128;
+	t915 = t89 * t145;
+	t947 = t139 * t140 * t29;
+	t952 = -0.2e1 * t173 * t904 + 0.4e1 * t426 * t907 + 0.12e2 * t253 * t10 * t1 * 0.3141592654e1 * t244 + 0.8e1 * t95 * t915 - t36 * t355 - 0.16e2 * t794 * t771 - 0.8e1 * t511 * t723 + 0.16e2 * t734 * t162 + t36 * t837 + 0.2e1 * t298 * t299 * t57 - 0.2e1 * t28 * t638 - 0.2e1 * t62 * t545 + 0.2e1 * t310 * t406 + 0.12e2 * t138 * t616 + 0.4e1 * t223 * t750 + t424 * t497 + 0.2e1 * t734 * t894 + 0.2e1 * t132 * self->xc * t18 * t10 - 0.16e2 * t70 * t947 + 0.32e2 * t891 * t947;
+	t969 = t67 * t157 * t156 * t3;
+	t974 = t27 * t133;
+	t1001 = -0.8e1 * t159 * t750 - 0.16e2 * t412 * t162 - t290 * t129 + 0.8e1 * t310 * t323 - 0.4e1 * t319 * t342 + t75 * t272 + t192 * t402 - 0.8e1 * t359 * t89 * t128 - 0.10e2 * t61 * t350 * t502 + 0.8e1 * t818 * t323 - 0.4e1 * t108 * t907;
+	t1042 = t89 * t97;
+	t1055 = -0.2e1 * t168 * t595 + 0.16e2 * t484 * t771 + 0.4e1 * t11 * t125 * t129 - 0.2e1 * t173 * t444 + 0.2e1 * self->ZB * n * t54 * t37 * self->ZA * t79 - t424 * t475 + 0.2e1 * t562 * t735 - 0.2e1 * t548 * t776 + t424 * t204 + 0.2e1 * t25 * t20 * t326 + 0.8e1 * t383 * t389 * t133 + t75 * t38 * t367 + 0.2e1 * t62 * t469 + 0.2e1 * t197 * t137 * t128 - 0.2e1 * t102 * t884 - 0.2e1 * t5 * t379 - 0.8e1 * t740 * t1042 - 0.16e2 * t159 * t414 - 0.2e1 * self->ZB * t35 * t37 * t413 + 0.2e1 * t553 * self->ZB * t78 * t12;
+	t1096 = 0.2e1 * t443 * t904 - 0.2e1 * t268 * t329 - 0.2e1 * t443 * t601 + 0.2e1 * t102 * t974 - 0.2e1 * t263 * t673 + t424 * t165 + 0.2e1 * t62 * t713 + t424 * t308 - t424 * t313 + 0.8e1 * t347 * t22 - t424 * t598;
+	t1103 = t42 * t1 * t157;
+	t1104 = t1103 * t25;
+	t1108 = t3 * t19;
+	t1112 = n * t47;
+	t1113 = t9 * t9;
+	t1118 = t42 * t157;
+	t1119 = t1118 * t9;
+	t1120 = t25 * self->xc;
+	t1121 = t13 * t110;
+	t1122 = t1120 * t1121;
+	t1125 = t47 * t47;
+	t1126 = t67 * t1125;
+	t1127 = t1113 * self->ZA;
+	t1128 = t1126 * t1127;
+	t1129 = t19 * t13;
+	t1130 = t744 * t1129;
+	t1133 = t154 * t1125;
+	t1134 = t1133 * t9;
+	t1135 = t45 * t1129;
+	t1138 = t154 * t47;
+	t1139 = t25 * t30;
+	t1142 = t1126 * t1113;
+	t1145 = t125 * t1129;
+	t1148 = t1103 * self->xc;
+	t1149 = t3 * t13;
+	t1150 = t1149 * t17;
+	t1153 = t25 * t78;
+	t1156 = -0.8e1 * t1104 * t243 * t17 + 0.4e1 * t187 * t1108 * t9 - 0.2e1 * t1112 * t3 * t1113 * t30 + 0.16e2 * t1119 * t1122 + 0.64e2 * t1128 * t1130 + 0.64e2 * t1134 * t1135 - 0.2e1 * t1138 * t1139 + 0.32e2 * t1142 * t1135 - 0.32e2 * t1142 * t1145 + 0.8e1 * t1148 * t1150 - 0.2e1 * t1138 * t1153;
+	t1157 = t25 * t13;
+	t1158 = t1157 * t17;
+	t1161 = t13 * t17;
+	t1162 = t1120 * t1161;
+	t1165 = t3 * t78;
+	t1170 = t42 * t67 * t1125;
+	t1172 = t1108 * t13;
+	t1175 = t1 * t157;
+	t1176 = t1175 * t1113;
+	t1182 = t1120 * t1129;
+	t1189 = t110 * t9 * self->xc;
+	t1192 = t1149 * t110;
+	t1201 = 0.8e1 * t1103 * t1158 - 0.16e2 * t1119 * t1162 - 0.2e1 * t1112 * t1165 * t1113 + 0.32e2 * t1170 * t44 * t1172 - 0.8e1 * t1176 * t1162 + 0.8e1 * t1104 * t243 * t110 - 0.64e2 * t1134 * t1182 - 0.64e2 * t1134 * t1145 + 0.16e2 * t1118 * t3 * t1189 + 0.16e2 * t1119 * t1192 - 0.4e1 * t187 * t1165 * t9 - 0.4e1 * t187 * t1139 * t9;
+	t1209 = t17 * t30;
+	t1210 = t125 * t1209;
+	t1213 = t1138 * self->ZA;
+	t1214 = self->ZB * t30;
+	t1218 = t1157 * t110;
+	t1226 = t3 * t30;
+	t1237 = t1170 * t25;
+	t1242 = 0.4e1 * t1112 * self->ZA * t119 * t1113 - 0.16e2 * t1119 * t1150 - 0.8e1 * t1176 * t1210 + 0.4e1 * t1213 * t1214 * t19 - 0.16e2 * t1119 * t1218 - 0.32e2 * t1142 * t1182 - 0.8e1 * t1103 * t1120 * t110 - 0.4e1 * t187 * t1226 * t9 + 0.8e1 * t1103 * t1192 + 0.4e1 * t1112 * self->ZB * t1113 * t30 * self->ZA - 0.32e2 * t1237 * self->xc * t19 * t13;
+	t1251 = t125 * t1121;
+	t1260 = t1120 * t1209;
+	t1263 = t1139 * t19;
+	t1282 = 0.8e1 * t1103 * t110 * t3 * self->xc + 0.8e1 * t1104 * self->xc * t17 * t30 - 0.8e1 * t1176 * t1251 + 0.16e2 * t1119 * t1158 + 0.4e1 * t1112 * t78 * t1127 * self->ZB + 0.16e2 * t1119 * t1260 + 0.2e1 * t1138 * t1263 - 0.32e2 * t1170 * self->xc * t1172 - 0.16e2 * t1213 * t119 * t13 + 0.4e1 * t1138 * t1214 * self->ZA + 0.32e2 * t1237 * t44 * t19 * t13 - 0.16e2 * t1118 * t25 * t1189;
+	t1287 = t188 * t1129;
+	t1292 = t25 * t19;
+	t1296 = t187 * t9;
+	t1297 = t1226 * t19;
+	t1311 = t1112 * t1113;
+	t1317 = -0.8e1 * t1176 * t1150 + 0.32e2 * t1142 * t1287 - 0.8e1 * t1103 * t1150 + 0.2e1 * t1112 * t1292 * t1113 + 0.4e1 * t1296 * t1297 + 0.8e1 * t1176 * t1192 + 0.4e1 * t1296 * t1263 + 0.8e1 * t1176 * t1158 - 0.8e1 * t1175 * t25 * t1113 * self->xc * t110 + 0.2e1 * t1311 * t1297 + 0.2e1 * t1112 * t1108 * t1113;
+	t1320 = t253 * t1129;
+	t1328 = t253 * t30 * t19;
+	t1333 = t125 * t1161;
+	t1343 = self->ZB * t44 * t1129;
+	t1350 = -0.8e1 * t1176 * t1218 - 0.16e2 * t1311 * t1320 + 0.8e1 * t1176 * t1260 - 0.16e2 * t1119 * t1210 + 0.4e1 * t1311 * t1328 + 0.2e1 * t1311 * t1263 + 0.8e1 * t1176 * t1333 + 0.8e1 * t187 * self->ZB * t417 * t9 - 0.2e1 * t1138 * t1165 - 0.64e2 * t1128 * t1343 + 0.64e2 * t1134 * t1287 + 0.2e1 * t1138 * t1108;
+	t1369 = t1133 * t9 * self->ZA;
+	t1378 = t187 * self->ZA;
+	t1383 = t1170 * self->ZA;
+	t1388 = 0.2e1 * t1138 * t1297 - 0.8e1 * t1148 * t1192 + 0.2e1 * t1138 * t1292 - 0.16e2 * t1119 * t1251 + 0.8e1 * t1175 * self->xc * t110 * t1113 * t3 - 0.2e1 * t1112 * t1153 * t1113 + 0.128e3 * t1369 * t1130 + 0.16e2 * t1119 * t1333 + 0.4e1 * t1138 * t78 * self->ZA * self->ZB + 0.8e1 * t1378 * t78 * t9 * self->ZB - 0.64e2 * t1383 * t1343 + 0.64e2 * t1383 * t1130;
+	t1420 = 0.4e1 * t1138 * t119 * self->ZA - 0.128e3 * t1369 * t1343 - 0.4e1 * t187 * t1153 * t9 - 0.2e1 * t1138 * t1226 + 0.8e1 * t1296 * t1328 - 0.2e1 * t1112 * t1139 * t1113 - 0.8e1 * t1148 * t3 * t17 * t30 - 0.32e2 * t1296 * t1320 + 0.8e1 * t1176 * t1122 + 0.4e1 * t187 * t1292 * t9 + 0.8e1 * t1378 * t119 * t9 - 0.8e1 * t1103 * t1218;
+
+	self->C4B = (-t424 * t508 + 0.8e1 * t412 * t750 - 0.2e1 * t232 * t595 - 0.4e1 * t126 * t323 + t1096 - t76 * t204 + t728 + 0.2e1 * t548 * t827 + 0.2e1 * t150 * t469 + t398 + 0.8e1 * t189 * t146 + t260 - 0.2e1 * t351 * t184 - 0.2e1 * t268 * t673 - 0.4e1 * t319 * t279 + t464 - 0.2e1 * t108 * t461 + 0.16e2 * t740 * t369 + 0.16e2 * t274 * t216 * t754 - 0.16e2 * t70 * t139 * t591 + 0.2e1 * t55 * t56 * t128 - 0.2e1 * t359 * t89 * t111 + 0.2e1 * t734 * t563 * t111 + 0.6e1 * t223 * t224 * t97 + 0.8e1 * t383 * t389 * t103 + 0.4e1 * t606 * self->ZA * t326 - 0.2e1 * t93 * t18 * t316 - 0.4e1 * t443 * t27 * t128 + 0.8e1 * t197 * t27 * t199 + 0.8e1 * t108 * t109 * t128 - t249 * t604 + 0.16e2 * t70 * t616 - 0.8e1 * t969 * t323 + t845 - t424 * t579 + 0.16e2 * t159 * t162 + t290 * t406 - 0.6e1 * t150 * t864 + t192 * t116 + 0.2e1 * t867 * t326 - 0.4e1 * t658 * t326 - 0.2e1 * t351 * t502 - t76 * t165 + t900 + 0.8e1 * t168 * t323 + t791 + 0.8e1 * t740 * t915 - 0.4e1 * t562 * t750 - 0.4e1 * t278 * t342 + 0.4e1 * t319 * t431 + 0.2e1 * t173 * t175 + t424 * t528 + 0.8e1 * t969 * t129 - 0.8e1 * t347 * t181 + t332 + t530 - 0.2e1 * t108 * t329 - 0.2e1 * t207 * t38 * t37 * t1 * self->ZA + t1001 + 0.4e1 * t408 * t379 + t76 * t448 + 0.2e1 * t102 * t184 + 0.2e1 * t426 * t329 + 0.16e2 * t740 * t98 - t282 * t127 - 0.16e2 * t1 * t44 * t69 * t552 * t116 + 0.2e1 * t168 * t169 + 0.2e1 * t28 * t134 - t290 * t604 - 0.16e2 * t484 * t485 - 0.8e1 * t740 * t480 + 0.2e1 * t173 * t601 - 0.2e1 * t335 * t336 + t600 + 0.2e1 * t62 * t864 + t952 + 0.8e1 * t347 * t134 - t192 * t355 + t192 * t194 + 0.2e1 * t228 * t461 + t663 + 0.4e1 * t383 * t27 * t417 * t16 + 0.4e1 * t138 * t20 * self->ZA * t10 - 0.4e1 * t20 * self->ZB * self->ZA * t326 + 0.4e1 * t196 * t88 * t77 * t744 - 0.16e2 * t67 * self->xc * t179 * t181 - 0.8e1 * t95 * t480 - t249 * t488 - t76 * t475 + t1055 - 0.4e1 * t408 * t22 - 0.10e2 * t28 * t379 + 0.2e1 * t335 * t974 + t153 - 0.8e1 * t95 * t1042 - 0.2e1 * t734 * t735) / (t1156 + t1201 + t1242 + t1282 + t1317 + t1350 + t1388 + t1420);
+	/****************************************************************************************/
+	/****************************************************************************************/
+}
+	
+	
+
+void ColumnViscosityAnalytic_VelocityFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* velocity ) {
+	ColumnViscosityAnalytic *self = (ColumnViscosityAnalytic*)analyticSolution;
+	double                  Z;
+	double                  x,y;
+	double                  C1,C2,C3,C4;
+	double                  n, nx;
+	double t1,t2,t3,t4,t5,t6,t7,t8,t11,t12,t13,t14,t15,t16,t18,t19,t20,t21,t23,t24,t25,t28,t29,t30,t31,t32,t33,t34,t36,t37;
+	double t41,t45,t49,t51,t53,t55,t58,t59,t60,t63,t67,t68,t73;
+	double t86,t87,t90,t91,t94,t106,t120;
+	double t121,t129,t146,t155,t156,t158,t159;
+	
+	/* Find coordinate of node */
+	x = coord[ I_AXIS ];
+	y = coord[ J_AXIS ];
+    
+	/* del_rho = sin(ny*Pi*y)*cos(nx*Pi*x)  n=nx gives only non-zero terms*/ 
+	n = 1; 
+	/* only one n in Fourier series because  del_rho has cos term */ 
+	nx = n; 
+
+	if ( x > self->xc ) { 
+		C1 = self->C1B; 
+		C2 = self->C2B;
+		C3 = self->C3B; 
+		C4 = self->C4B; 
+		Z  = self->ZB; 
+	}
+	else {
+		C1 = self->C1A; 
+		C2 = self->C2A; 
+		C3 = self->C3A; 
+		C4 = self->C4A; 
+		Z  = self->ZA;
+	}
+
+	/****************************************************************************************/
+	/****************************************************************************************/
+	t1 = n * n;
+	t2 = t1 * t1;
+	t3 = t2 * n;
+	t4 = x * t3;
+	t5 = 0.3141592654e1 * 0.3141592654e1;
+	t6 = t5 * 0.3141592654e1;
+	t11 = C3 * t6;
+	t12 = x * n;
+	t13 = nx * nx;
+	t14 = t13 * t13;
+	t15 = t12 * t14;
+	t19 = exp(t12 * 0.3141592654e1);
+	t20 = t19 * t19;
+	t21 = t4 * t20;
+	t24 = C1 * t5;
+	t25 = Z * t20;
+	t29 = C1 * t6;
+	t30 = t29 * Z;
+	t31 = t1 * n;
+	t32 = x * t31;
+	t33 = t32 * t13;
+	t36 = t11 * x;
+	t41 = n * t20;
+	t45 = t6 * C4;
+	t49 = t20 * t1;
+	t51 = C2 * Z;
+	t55 = -0.2e1 * t4 * t6 * C2 * Z - 0.2e1 * t11 * t15 - 0.2e1 * t11 * t21 + 0.2e1 * t24 * t25 * t14 - t13 + 0.4e1 * t30 * t33 - 0.4e1 * t36 * t31 * t20 * t13 - 0.2e1 * t36 * t41 * t14 - 0.2e1 * t4 * t45 * t20 - t49 - 0.2e1 * t4 * t6 * t51 * t20;
+	t58 = t32 * t6;
+	t59 = C4 * t20;
+	t63 = t20 * t13;
+	t67 = t12 * t6;
+	t68 = t20 * t14;
+	t87 = t49 * t13;
+	t90 = -0.4e1 * t11 * t33 - 0.4e1 * t58 * t59 * t13 - 0.4e1 * t58 * t51 * t63 - 0.2e1 * t67 * t51 * t68 + 0.4e1 * t32 * t45 * t13 - 0.2e1 * t67 * t59 * t14 - 0.2e1 * t30 * t21 + t1 + 0.2e1 * t24 * t25 * t2 + 0.2e1 * t12 * t45 * t14 + 0.4e1 * t24 * Z * t87;
+	t106 = C3 * t5;
+	t120 = -0.4e1 * t30 * t32 * t63 + t63 + 0.4e1 * t24 * Z * t1 * t13 + 0.2e1 * t29 * Z * x * t3 - 0.4e1 * t58 * t51 * t13 - 0.2e1 * t106 * t2 + t32 * 0.3141592654e1 - 0.2e1 * t106 * t14 - 0.2e1 * t30 * t12 * t68 - 0.2e1 * t67 * t51 * t14 + 0.4e1 * t106 * t87;
+	t129 = sin(nx * 0.3141592654e1 * x);
+	t155 = 0.2e1 * t30 * t15 + x * 0.3141592654e1 * t41 * t13 - 0.4e1 * t19 * nx * t129 * n + t32 * 0.3141592654e1 * t20 + 0.2e1 * t106 * t68 + 0.2e1 * t106 * t20 * t2 - 0.4e1 * t106 * t1 * t13 - 0.2e1 * t11 * t4 + 0.2e1 * t4 * t45 + 0.2e1 * t24 * Z * t2 + 0.2e1 * t24 * Z * t14 + t12 * 0.3141592654e1 * t13;
+	t158 = t5 * Z;
+
+	velocity[ I_AXIS ] = (t55 + t90 + t120 + t155) / (0.4e1 * t158 * t19 * t2 + 0.8e1 * t158 * t19 * t1 * t13 + 0.4e1 * t158 * t19 * t14);
+	velocity[ I_AXIS ] *= cos(n*M_PI*y); 
+
+	/****************************************************************************************/
+	/****************************************************************************************/
+	t1 = n * n;
+	t2 = t1 * n;
+	t3 = x * t2;
+	t4 = 0.3141592654e1 * 0.3141592654e1;
+	t5 = t4 * 0.3141592654e1;
+	t6 = t3 * t5;
+	t7 = C2 * Z;
+	t8 = nx * nx;
+	t12 = t1 * t1;
+	t13 = t12 * n;
+	t14 = x * t13;
+	t15 = t5 * C4;
+	t16 = x * n;
+	t18 = exp(t16 * 0.3141592654e1);
+	t19 = t18 * t18;
+	t23 = t16 * t5;
+	t24 = t8 * t8;
+	t28 = C3 * t5;
+	t29 = t14 * t19;
+	t32 = C1 * t5;
+	t33 = t32 * Z;
+	t34 = t16 * t24;
+	t37 = C4 * t19;
+	t45 = C2 * t4;
+	t53 = t19 * t8;
+	t58 = C4 * t4;
+	t60 = t1 * t19 * t8;
+	t63 = t19 * t24;
+	t67 = t3 * t8;
+	t73 = n * t19;
+	t86 = t28 * x;
+	t91 = 0.4e1 * t58 * t60 + 0.2e1 * t33 * t16 * t63 + 0.4e1 * t33 * t67 + 0.2e1 * t33 * t29 - x * 0.3141592654e1 * t73 * t8 - 0.2e1 * t53 + 0.2e1 * t32 * Z * x * t13 - 0.2e1 * t58 * t12 - 0.2e1 * t58 * t24 + t3 * 0.3141592654e1 + 0.4e1 * t86 * t2 * t19 * t8;
+	t94 = Z * t12;
+	t121 = -0.2e1 * t8 + 0.2e1 * t45 * t94 * t19 + 0.2e1 * t14 * t5 * t7 * t19 + 0.4e1 * t6 * t7 * t53 + 0.2e1 * t23 * t7 * t63 - 0.4e1 * t28 * t67 + 0.2e1 * t45 * t94 + 0.2e1 * t58 * t12 * t19 + t16 * 0.3141592654e1 * t8 + 0.2e1 * t14 * t15 - 0.2e1 * t28 * t14;
+	t146 = cos(nx * 0.3141592654e1 * x);
+	t156 = -t3 * 0.3141592654e1 * t19 + 0.2e1 * t58 * t63 - 0.4e1 * t58 * t1 * t8 + 0.4e1 * t45 * Z * t1 * t8 - 0.2e1 * t28 * t34 + 0.2e1 * t86 * t73 * t24 + 0.4e1 * t3 * t15 * t8 + 0.4e1 * t45 * Z * t60 + 0.4e1 * t18 * t146 * t8 + 0.2e1 * t45 * Z * t24 + 0.2e1 * t16 * t15 * t24;
+	t159 = t4 * Z;
+
+	velocity[ J_AXIS ] = (-0.4e1 * t6 * t7 * t8 + 0.2e1 * t14 * t15 * t19 - 0.2e1 * t23 * t7 * t24 + 0.2e1 * t28 * t29 + 0.2e1 * t33 * t34 + 0.4e1 * t6 * t37 * t8 - 0.2e1 * t14 * t5 * C2 * Z + 0.2e1 * t45 * Z * t19 * t24 + 0.2e1 * t23 * t37 * t24 + 0.4e1 * t33 * t3 * t53 + t91 + t121 + t156) / (0.4e1 * t159 * t18 * t12 + 0.8e1 * t159 * t18 * t1 * t8 + 0.4e1 * t159 * t18 * t24);
+	velocity[ J_AXIS ] *= sin(n*M_PI*y); /* y velocity */
+
+}
+
+
+void ColumnViscosityAnalytic_PressureFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* pressure ) {
+	ColumnViscosityAnalytic *self = (ColumnViscosityAnalytic*)analyticSolution;
+	double                  Z;
+	double                  x,y;
+	double                  C1,C2,C3,C4;
+	double                  n, nx;
+	XYZ                     velocity;
+	double                  u3;
+	double t9, t17, t40, t44, t48, t52, t57, t61, t62, t78, t101, t102, t109, t110, t128;
+	double t1,t2,t3,t4,t5,t6,t7,t8,t11,t12,t13,t14,t15,t16,t18,t19,t20,t23,t24,t28,t29,t30,t31,t32,t33,t34,t37;
+	double t45,t53,t58,t60,t63,t67,t73;
+	double t86,t90,t91,t94;
+	double t121,t146,t156,t159;
+	
+	/* Find coordinate of node */
+	x = coord[ I_AXIS ];
+	y = coord[ J_AXIS ];
+    
+	/* del_rho = sin(ny*Pi*y)*cos(nx*Pi*x)  n=nx gives only non-zero terms*/ 
+	n = 1; 
+	/* only one n in Fourier series because  del_rho has cos term */ 
+	nx = n; 
+
+	if ( x > self->xc ) { 
+		C1 = self->C1B; 
+		C2 = self->C2B;
+		C3 = self->C3B; 
+		C4 = self->C4B; 
+		Z  = self->ZB; 
+	}
+	else {
+		C1 = self->C1A; 
+		C2 = self->C2A; 
+		C3 = self->C3A; 
+		C4 = self->C4A; 
+		Z  = self->ZA;
+	}
+
+	/****************************************************************************************/
+	/****************************************************************************************/
+	t1 = n * n;
+	t2 = t1 * n;
+	t3 = x * t2;
+	t4 = 0.3141592654e1 * 0.3141592654e1;
+	t5 = t4 * 0.3141592654e1;
+	t6 = t3 * t5;
+	t7 = C2 * Z;
+	t8 = nx * nx;
+	t12 = t1 * t1;
+	t13 = t12 * n;
+	t14 = x * t13;
+	t15 = t5 * C4;
+	t16 = x * n;
+	t18 = exp(t16 * 0.3141592654e1);
+	t19 = t18 * t18;
+	t23 = t16 * t5;
+	t24 = t8 * t8;
+	t28 = C3 * t5;
+	t29 = t14 * t19;
+	t32 = C1 * t5;
+	t33 = t32 * Z;
+	t34 = t16 * t24;
+	t37 = C4 * t19;
+	t45 = C2 * t4;
+	t53 = t19 * t8;
+	t58 = C4 * t4;
+	t60 = t1 * t19 * t8;
+	t63 = t19 * t24;
+	t67 = t3 * t8;
+	t73 = n * t19;
+	t86 = t28 * x;
+	t91 = 0.4e1 * t58 * t60 + 0.2e1 * t33 * t16 * t63 + 0.4e1 * t33 * t67 + 0.2e1 * t33 * t29 - x * 0.3141592654e1 * t73 * t8 - 0.2e1 * t53 + 0.2e1 * t32 * Z * x * t13 - 0.2e1 * t58 * t12 - 0.2e1 * t58 * t24 + t3 * 0.3141592654e1 + 0.4e1 * t86 * t2 * t19 * t8;
+	t94 = Z * t12;
+	t121 = -0.2e1 * t8 + 0.2e1 * t45 * t94 * t19 + 0.2e1 * t14 * t5 * t7 * t19 + 0.4e1 * t6 * t7 * t53 + 0.2e1 * t23 * t7 * t63 - 0.4e1 * t28 * t67 + 0.2e1 * t45 * t94 + 0.2e1 * t58 * t12 * t19 + t16 * 0.3141592654e1 * t8 + 0.2e1 * t14 * t15 - 0.2e1 * t28 * t14;
+	t146 = cos(nx * 0.3141592654e1 * x);
+	t156 = -t3 * 0.3141592654e1 * t19 + 0.2e1 * t58 * t63 - 0.4e1 * t58 * t1 * t8 + 0.4e1 * t45 * Z * t1 * t8 - 0.2e1 * t28 * t34 + 0.2e1 * t86 * t73 * t24 + 0.4e1 * t3 * t15 * t8 + 0.4e1 * t45 * Z * t60 + 0.4e1 * t18 * t146 * t8 + 0.2e1 * t45 * Z * t24 + 0.2e1 * t16 * t15 * t24;
+	t159 = t4 * Z;
+
+	velocity[ J_AXIS ] = (-0.4e1 * t6 * t7 * t8 + 0.2e1 * t14 * t15 * t19 - 0.2e1 * t23 * t7 * t24 + 0.2e1 * t28 * t29 + 0.2e1 * t33 * t34 + 0.4e1 * t6 * t37 * t8 - 0.2e1 * t14 * t5 * C2 * Z + 0.2e1 * t45 * Z * t19 * t24 + 0.2e1 * t23 * t37 * t24 + 0.4e1 * t33 * t3 * t53 + t91 + t121 + t156) / (0.4e1 * t159 * t18 * t12 + 0.8e1 * t159 * t18 * t1 * t8 + 0.4e1 * t159 * t18 * t24);
+	velocity[ J_AXIS ] *= sin(n*M_PI*y); /* y velocity */
+
+	/****************************************************************************************/
+	/****************************************************************************************/
+	t1 = 0.3141592654e1 * 0.3141592654e1;
+	t2 = t1 * 0.3141592654e1;
+	t3 = C1 * t2;
+	t4 = t3 * Z;
+	t5 = n * n;
+	t6 = t5 * t5;
+	t7 = t6 * n;
+	t8 = x * t7;
+	t9 = x * n;
+	t11 = exp(t9 * 0.3141592654e1);
+	t12 = t11 * t11;
+	t13 = t8 * t12;
+	t16 = t5 * n;
+	t17 = x * t16;
+	t18 = t17 * t2;
+	t19 = C4 * t12;
+	t20 = nx * nx;
+	t24 = t2 * C4;
+	t28 = C3 * t2;
+	t29 = t28 * x;
+	t30 = t12 * n;
+	t31 = t20 * t20;
+	t40 = C2 * Z;
+	t44 = t9 * t2;
+	t48 = t12 * t20;
+	t52 = t17 * t20;
+	t57 = -0.2e1 * t4 * t13 - 0.4e1 * t18 * t19 * t20 - 0.2e1 * t8 * t24 * t12 - 0.2e1 * t29 * t30 * t31 + 0.2e1 * t8 * t2 * C2 * Z - 0.2e1 * t8 * t2 * t40 * t12 - 0.2e1 * t44 * t19 * t31 - 0.4e1 * t18 * t40 * t48 + t20 + 0.4e1 * t28 * t52 + t17 * 0.3141592654e1 * t12;
+	t58 = t9 * t31;
+	t61 = C3 * t1;
+	t62 = t12 * t31;
+	t73 = t5 * t20;
+	t78 = C1 * t1;
+	t90 = Z * t12;
+	t94 = 0.2e1 * t28 * t58 + 0.2e1 * t61 * t62 + 0.2e1 * t61 * t12 * t6 - 0.4e1 * t4 * t17 * t48 + 0.2e1 * t28 * t8 + 0.4e1 * t61 * t73 - 0.2e1 * t8 * t24 - 0.2e1 * t78 * Z * t6 - 0.2e1 * t44 * t40 * t62 - 0.2e1 * t78 * Z * t31 - t9 * 0.3141592654e1 * t20 + 0.2e1 * t78 * t90 * t6;
+	t101 = cos(nx * 0.3141592654e1 * x);
+	t102 = t11 * t101;
+	t109 = t12 * t5;
+	t110 = t109 * t20;
+	t128 = 0.2e1 * t61 * t6 - t17 * 0.3141592654e1 + 0.2e1 * t102 * t5 - 0.4e1 * t17 * t24 * t20 + 0.4e1 * t78 * Z * t110 - 0.2e1 * t9 * t24 * t31 - 0.4e1 * t4 * t52 - 0.2e1 * t4 * t9 * t62 + x * 0.3141592654e1 * t30 * t20 - t5 - 0.4e1 * t78 * Z * t5 * t20;
+	t156 = 0.2e1 * t78 * t90 * t31 - 0.2e1 * t3 * Z * x * t7 + t48 + 0.4e1 * t61 * t110 + 0.4e1 * t18 * t40 * t20 - 0.2e1 * t102 * t20 + 0.2e1 * t61 * t31 + 0.2e1 * t44 * t40 * t31 - t109 - 0.2e1 * t4 * t58 - 0.2e1 * t28 * t13 - 0.4e1 * t29 * t16 * t12 * t20;
+	t159 = t1 * t11;
+
+	u3 = (t57 + t94 + t128 + t156) / (0.4e1 * t159 * t6 + 0.8e1 * t159 * t73 + 0.4e1 * t159 * t31);
+	/****************************************************************************************/
+	/****************************************************************************************/
+
+	*pressure = (double)(-2*Z*n*M_PI*velocity[ J_AXIS ]-u3*2*n*M_PI)*cos(n*M_PI*y); 
+	 
+}
+
+void ColumnViscosityAnalytic_StressFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* stress ) {
+	ColumnViscosityAnalytic *self = (ColumnViscosityAnalytic*)analyticSolution;
+	double                  Z;
+	double                  x,y;
+	double                  C1,C2,C3,C4;
+	double                  n, nx;
+	double                  u2, u3, u4;
+	double t1,t2,t3,t4,t5,t6,t7,t8,t9,t11,t12,t13,t14,t15,t16,t17,t18,t19,t20,t23,t24,t28,t29,t30,t31,t32,t33,t34,t35,t37,t40;
+	double t41,t44,t45,t47,t48,t52,t53,t54,t57,t58,t60,t61,t62,t63,t67,t69,t73,t75,t78,t79;
+	double t83,t84,t86,t90,t91,t94,t95,t97,t101,t102,t106,t109,t110;
+	double t121,t127,t128,t131,t135,t146,t156,t159;
+	double t164;
+	
+	/* Find coordinate of node */
+	x = coord[ I_AXIS ];
+	y = coord[ J_AXIS ];
+    
+	/* del_rho = sin(ny*Pi*y)*cos(nx*Pi*x)  n=nx gives only non-zero terms*/ 
+	n = 1; 
+	/* only one n in Fourier series because  del_rho has cos term */ 
+	nx = n; 
+
+	if ( x > self->xc ) { 
+		C1 = self->C1B; 
+		C2 = self->C2B;
+		C3 = self->C3B; 
+		C4 = self->C4B; 
+		Z  = self->ZB; 
+	}
+	else {
+		C1 = self->C1A; 
+		C2 = self->C2A; 
+		C3 = self->C3A; 
+		C4 = self->C4A; 
+		Z  = self->ZA;
+	}
+
+	t1 = n * n;
+	t2 = t1 * n;
+	t3 = x * t2;
+	t4 = 0.3141592654e1 * 0.3141592654e1;
+	t5 = t4 * 0.3141592654e1;
+	t6 = t3 * t5;
+	t7 = C2 * Z;
+	t8 = nx * nx;
+	t12 = t1 * t1;
+	t13 = t12 * n;
+	t14 = x * t13;
+	t15 = t5 * C4;
+	t16 = x * n;
+	t18 = exp(t16 * 0.3141592654e1);
+	t19 = t18 * t18;
+	t23 = t16 * t5;
+	t24 = t8 * t8;
+	t28 = C3 * t5;
+	t29 = t14 * t19;
+	t32 = C1 * t5;
+	t33 = t32 * Z;
+	t34 = t16 * t24;
+	t37 = C4 * t19;
+	t45 = C2 * t4;
+	t53 = t19 * t8;
+	t58 = C4 * t4;
+	t60 = t1 * t19 * t8;
+	t63 = t19 * t24;
+	t67 = t3 * t8;
+	t73 = n * t19;
+	t86 = t28 * x;
+	t91 = 0.4e1 * t58 * t60 + 0.2e1 * t33 * t16 * t63 + 0.4e1 * t33 * t67 + 0.2e1 * t33 * t29 - x * 0.3141592654e1 * t73 * t8 - 0.2e1 * t53 + 0.2e1 * t32 * Z * x * t13 - 0.2e1 * t58 * t12 - 0.2e1 * t58 * t24 + t3 * 0.3141592654e1 + 0.4e1 * t86 * t2 * t19 * t8;
+	t94 = Z * t12;
+	t121 = -0.2e1 * t8 + 0.2e1 * t45 * t94 * t19 + 0.2e1 * t14 * t5 * t7 * t19 + 0.4e1 * t6 * t7 * t53 + 0.2e1 * t23 * t7 * t63 - 0.4e1 * t28 * t67 + 0.2e1 * t45 * t94 + 0.2e1 * t58 * t12 * t19 + t16 * 0.3141592654e1 * t8 + 0.2e1 * t14 * t15 - 0.2e1 * t28 * t14;
+	t146 = cos(nx * 0.3141592654e1 * x);
+	t156 = -t3 * 0.3141592654e1 * t19 + 0.2e1 * t58 * t63 - 0.4e1 * t58 * t1 * t8 + 0.4e1 * t45 * Z * t1 * t8 - 0.2e1 * t28 * t34 + 0.2e1 * t86 * t73 * t24 + 0.4e1 * t3 * t15 * t8 + 0.4e1 * t45 * Z * t60 + 0.4e1 * t18 * t146 * t8 + 0.2e1 * t45 * Z * t24 + 0.2e1 * t16 * t15 * t24;
+	t159 = t4 * Z;
+
+	u2 = (-0.4e1 * t6 * t7 * t8 + 0.2e1 * t14 * t15 * t19 - 0.2e1 * t23 * t7 * t24 + 0.2e1 * t28 * t29 + 0.2e1 * t33 * t34 + 0.4e1 * t6 * t37 * t8 - 0.2e1 * t14 * t5 * C2 * Z + 0.2e1 * t45 * Z * t19 * t24 + 0.2e1 * t23 * t37 * t24 + 0.4e1 * t33 * t3 * t53 + t91 + t121 + t156) / (0.4e1 * t159 * t18 * t12 + 0.8e1 * t159 * t18 * t1 * t8 + 0.4e1 * t159 * t18 * t24);
+
+	/****************************************************************************************/
+	/****************************************************************************************/
+
+	t1 = 0.3141592654e1 * 0.3141592654e1;
+	t2 = t1 * 0.3141592654e1;
+	t3 = C1 * t2;
+	t4 = t3 * Z;
+	t5 = n * n;
+	t6 = t5 * t5;
+	t7 = t6 * n;
+	t8 = x * t7;
+	t9 = x * n;
+	t11 = exp(t9 * 0.3141592654e1);
+	t12 = t11 * t11;
+	t13 = t8 * t12;
+	t16 = t5 * n;
+	t17 = x * t16;
+	t18 = t17 * t2;
+	t19 = C4 * t12;
+	t20 = nx * nx;
+	t24 = t2 * C4;
+	t28 = C3 * t2;
+	t29 = t28 * x;
+	t30 = t12 * n;
+	t31 = t20 * t20;
+	t40 = C2 * Z;
+	t44 = t9 * t2;
+	t48 = t12 * t20;
+	t52 = t17 * t20;
+	t57 = -0.2e1 * t4 * t13 - 0.4e1 * t18 * t19 * t20 - 0.2e1 * t8 * t24 * t12 - 0.2e1 * t29 * t30 * t31 + 0.2e1 * t8 * t2 * C2 * Z - 0.2e1 * t8 * t2 * t40 * t12 - 0.2e1 * t44 * t19 * t31 - 0.4e1 * t18 * t40 * t48 + t20 + 0.4e1 * t28 * t52 + t17 * 0.3141592654e1 * t12;
+	t58 = t9 * t31;
+	t61 = C3 * t1;
+	t62 = t12 * t31;
+	t73 = t5 * t20;
+	t78 = C1 * t1;
+	t90 = Z * t12;
+	t94 = 0.2e1 * t28 * t58 + 0.2e1 * t61 * t62 + 0.2e1 * t61 * t12 * t6 - 0.4e1 * t4 * t17 * t48 + 0.2e1 * t28 * t8 + 0.4e1 * t61 * t73 - 0.2e1 * t8 * t24 - 0.2e1 * t78 * Z * t6 - 0.2e1 * t44 * t40 * t62 - 0.2e1 * t78 * Z * t31 - t9 * 0.3141592654e1 * t20 + 0.2e1 * t78 * t90 * t6;
+	t101 = cos(nx * 0.3141592654e1 * x);
+	t102 = t11 * t101;
+	t109 = t12 * t5;
+	t110 = t109 * t20;
+	t128 = 0.2e1 * t61 * t6 - t17 * 0.3141592654e1 + 0.2e1 * t102 * t5 - 0.4e1 * t17 * t24 * t20 + 0.4e1 * t78 * Z * t110 - 0.2e1 * t9 * t24 * t31 - 0.4e1 * t4 * t52 - 0.2e1 * t4 * t9 * t62 + x * 0.3141592654e1 * t30 * t20 - t5 - 0.4e1 * t78 * Z * t5 * t20;
+	t156 = 0.2e1 * t78 * t90 * t31 - 0.2e1 * t3 * Z * x * t7 + t48 + 0.4e1 * t61 * t110 + 0.4e1 * t18 * t40 * t20 - 0.2e1 * t102 * t20 + 0.2e1 * t61 * t31 + 0.2e1 * t44 * t40 * t31 - t109 - 0.2e1 * t4 * t58 - 0.2e1 * t28 * t13 - 0.4e1 * t29 * t16 * t12 * t20;
+	t159 = t1 * t11;
+
+	u3 = (t57 + t94 + t128 + t156) / (0.4e1 * t159 * t6 + 0.8e1 * t159 * t73 + 0.4e1 * t159 * t31);	
+	/****************************************************************************************/
+	/****************************************************************************************/
+	
+	t1 = C2 * Z;
+	t2 = 0.3141592654e1 * 0.3141592654e1;
+	t3 = t2 * 0.3141592654e1;
+	t4 = n * n;
+	t5 = t4 * t4;
+	t6 = t5 * t4;
+	t8 = t3 * t6 * x;
+	t11 = x * t4;
+	t12 = t11 * t3;
+	t15 = exp(x * n * 0.3141592654e1);
+	t16 = t15 * t15;
+	t17 = C3 * t16;
+	t18 = nx * nx;
+	t19 = t18 * t18;
+	t23 = t5 * n;
+	t24 = t2 * t23;
+	t28 = t1 * t3;
+	t29 = t6 * x;
+	t30 = t29 * t16;
+	t33 = C4 * t3;
+	t34 = t5 * x;
+	t35 = t34 * t18;
+	t41 = sin(nx * 0.3141592654e1 * x);
+	t47 = t11 * t19;
+	t54 = t3 * C3;
+	t57 = 0.2e1 * t1 * t8 + 0.2e1 * t12 * t17 * t19 + 0.2e1 * t1 * t24 * t16 + 0.2e1 * t28 * t30 - 0.4e1 * t33 * t35 + 0.2e1 * t15 * nx * t41 * t4 + 0.4e1 * t28 * t35 - 0.2e1 * t33 * t47 - 0.2e1 * t1 * t24 - 0.2e1 * t33 * t29 + 0.2e1 * t29 * t54;
+	t58 = 0.3141592654e1 * t16;
+	t60 = t2 * C4;
+	t69 = t4 * n;
+	t73 = t1 * t2;
+	t75 = t69 * t16 * t18;
+	t79 = x * t16;
+	t83 = n * t16;
+	t84 = t83 * t19;
+	t95 = -t34 * t58 + 0.2e1 * t60 * t23 * t16 + 0.2e1 * t60 * n * t19 - t11 * 0.3141592654e1 * t18 + 0.4e1 * t60 * t69 * t18 + 0.4e1 * t73 * t75 + 0.4e1 * t33 * t5 * t79 * t18 + 0.2e1 * t73 * t84 + 0.2e1 * t60 * t84 + 0.2e1 * t33 * t4 * t79 * t19 + 0.4e1 * t60 * t75;
+	t97 = t34 * t3;
+	t101 = Z * C1;
+	t102 = t16 * t19;
+	t106 = t16 * t18;
+	t127 = t2 * t69;
+	t131 = t2 * n;
+	t135 = 0.4e1 * t97 * t17 * t18 + 0.2e1 * t12 * t101 * t102 + 0.4e1 * t28 * t34 * t106 + 0.2e1 * t28 * t11 * t102 - 0.2e1 * t29 * t3 * Z * C1 - 0.4e1 * t97 * t101 * t18 - 0.2e1 * t12 * t101 * t19 + 0.2e1 * t60 * t23 - 0.2e1 * t83 * t18 - 0.4e1 * t1 * t127 * t18 - 0.2e1 * t1 * t131 * t19;
+	t164 = 0.2e1 * t28 * t47 + 0.2e1 * t11 * t54 * t19 + 0.2e1 * t8 * t101 * t16 + 0.2e1 * t33 * t30 - t11 * t58 * t18 + 0.2e1 * t29 * t54 * t16 + 0.4e1 * t34 * t54 * t18 + 0.4e1 * t97 * t101 * t106 - 0.2e1 * t15 * t18 * nx * t41 - t34 * 0.3141592654e1 + 0.2e1 * n * t18;
+
+	u4 = (t57 + t95 + t135 + t164) / (0.4e1 * t24 * t15 + 0.8e1 * t127 * t15 * t18 + 0.4e1 * t131 * t15 * t19);	
+	/****************************************************************************************/
+	/****************************************************************************************/
+
+	stress[0] = (double)(u4*2*n*M_PI + 4*Z*n*M_PI*u2)*cos(n*M_PI*y); /* xx stress */
+	stress[1] = 2*n*M_PI*cos(n*M_PI*y) * u3; /* yy stress */
+	stress[2] = 2*n*M_PI*sin(n*M_PI*y) * u4; /* xy stress */
+}
+
+void _ColumnViscosityAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	ColumnViscosityAnalytic* self = (ColumnViscosityAnalytic*)analyticSolution;
+	AbstractContext*         context;
+	ConditionFunction*       condFunc;
+
+	/* Construct Parent */
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
+	
+	/* Create Analytic Fields */
+	self->velocityField = Stg_ComponentFactory_ConstructByName( cf, (Name)"VelocityField", FeVariable, True, data  ); 
+	self->pressureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"PressureField", FeVariable, True, data  ); 
+	self->stressField = Stg_ComponentFactory_ConstructByName( cf, (Name)"StressField", FeVariable, False, data  ); 
+
+	/* Add condition function for temperature */
+	condFunc = ConditionFunction_New( ColumnViscosityAnalytic_TemperatureIC, (Name)"ColumnViscosityAnalytic_TemperatureIC"  );
+	ConditionFunction_Register_Add( context->condFunc_Register, condFunc );
+
+	/* Set up constants */
+	self->ZA = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"leftViscosity", 1.0  );
+	self->ZB = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"rightViscosity", 1.0  );
+
+	/* top layer viscosity */
+	self->xc = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"columnEnd", 0.5 );
+	ColumnViscosityAnalytic_Constants( self  );
+}
+
+void _ColumnViscosityAnalytic_Build( void* analyticSolution, void* data ) {
+	ColumnViscosityAnalytic* self = (ColumnViscosityAnalytic*)analyticSolution;
+
+	Build( self->velocityField, data, False );
+	Build( self->pressureField, data, False );
+	if( self->stressField )
+		Build( self->stressField, data, False );
+
+	AnalyticSolution_CreateAnalyticField( self, self->velocityField, ColumnViscosityAnalytic_VelocityFunction );
+	AnalyticSolution_CreateAnalyticField( self, self->pressureField, ColumnViscosityAnalytic_PressureFunction );
+	if( self->stressField ) 
+		AnalyticSolution_CreateAnalyticField( self, self->stressField, ColumnViscosityAnalytic_StressFunction );
+
+	_AnalyticSolution_Build( self, data );
+}
+
+void* _ColumnViscosityAnalytic_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(ColumnViscosityAnalytic);
+	Type                                                      type = ColumnViscosityAnalytic_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _ColumnViscosityAnalytic_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _ColumnViscosityAnalytic_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _ColumnViscosityAnalytic_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+Index StgFEM_ColumnViscosityAnalytic_Register( PluginsManager* pluginsManager ) {
+	return PluginsManager_Submit( pluginsManager, ColumnViscosityAnalytic_Type, (Name)"0", _ColumnViscosityAnalytic_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/DivergenceMatrixTerm.c
--- a/Assembly/src/DivergenceMatrixTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,255 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: DivergenceMatrixTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "types.h"
-#include "DivergenceMatrixTerm.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type DivergenceMatrixTerm_Type = "DivergenceMatrixTerm";
-
-DivergenceMatrixTerm* DivergenceMatrixTerm_New( 
-	Name					     name,
-	FiniteElementContext*  context,
-	StiffnessMatrix*	     stiffnessMatrix,
-	Swarm*				     integrationSwarm )
-{
-	DivergenceMatrixTerm* self = (DivergenceMatrixTerm*) _DivergenceMatrixTerm_DefaultNew( name );
-	
-	self->isConstructed = True;
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
-   _DivergenceMatrixTerm_Init( self );
-
-   return self;
-}
-
-/* Creation implementation / Virtual constructor */
-DivergenceMatrixTerm* _DivergenceMatrixTerm_New(  DIVERGENCEMATRIXTERM_DEFARGS  )
-{
-   DivergenceMatrixTerm* self;
-	
-   /* Allocate memory */
-   assert( _sizeOfSelf >= sizeof(DivergenceMatrixTerm) );
-   self = (DivergenceMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
-	
-   /* Virtual info */
-	
-   return self;
-}
-
-void _DivergenceMatrixTerm_Init( void* matrixTerm ) {
-   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
-
-	self->max_nElNodes_col = 0;
-	self->Ni_col = NULL;
-}
-
-void _DivergenceMatrixTerm_Delete( void* matrixTerm ) {
-   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
-
-   _StiffnessMatrixTerm_Delete( self );
-	
-	Memory_Free( self->Ni_col );
-}
-
-void _DivergenceMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
-   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
-	
-   _StiffnessMatrixTerm_Print( self, stream );
-
-   /* General info */
-}
-
-void* _DivergenceMatrixTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(DivergenceMatrixTerm);
-	Type                                                         type = DivergenceMatrixTerm_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _DivergenceMatrixTerm_Delete;
-	Stg_Class_PrintFunction*                                   _print = _DivergenceMatrixTerm_Print;
-	Stg_Class_CopyFunction*                                     _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _DivergenceMatrixTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _DivergenceMatrixTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _DivergenceMatrixTerm_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _DivergenceMatrixTerm_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _DivergenceMatrixTerm_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _DivergenceMatrixTerm_Destroy;
-	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _DivergenceMatrixTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-   return (void*)_DivergenceMatrixTerm_New(  DIVERGENCEMATRIXTERM_PASSARGS  );
-}
-
-void _DivergenceMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
-   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
-
-   /* Construct Parent */
-   _StiffnessMatrixTerm_AssignFromXML( self, cf, data );
-
-   _DivergenceMatrixTerm_Init( self );
-}
-
-void _DivergenceMatrixTerm_Build( void* matrixTerm, void* data ) {
-   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
-
-   _StiffnessMatrixTerm_Build( self, data );
-}
-
-void _DivergenceMatrixTerm_Initialise( void* matrixTerm, void* data ) {
-   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
-
-   _StiffnessMatrixTerm_Initialise( self, data );
-}
-
-void _DivergenceMatrixTerm_Execute( void* matrixTerm, void* data ) {
-   _StiffnessMatrixTerm_Execute( matrixTerm, data );
-}
-
-void _DivergenceMatrixTerm_Destroy( void* matrixTerm, void* data ) {
-	DivergenceMatrixTerm* self = (DivergenceMatrixTerm*) matrixTerm;
-
-   if( self->Ni_col) Memory_Free( self->Ni_col );
-	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
-}
-
-void _DivergenceMatrixTerm_AssembleElement( 
-   void*							matrixTerm,
-   StiffnessMatrix*			stiffnessMatrix, 
-   Element_LocalIndex		lElement_I, 
-   SystemLinearEquations*	sle,
-   FiniteElementContext*	context,
-   double**						elStiffMat ) 
-{
-   DivergenceMatrixTerm*	self         = Stg_CheckType( matrixTerm, DivergenceMatrixTerm );
-   Swarm*						swarm        = self->integrationSwarm;
-   FeVariable*					variable_row = stiffnessMatrix->columnVariable;
-   FeVariable*					variable_col = stiffnessMatrix->rowVariable;
-   Dimension_Index			dim          = stiffnessMatrix->dim;
-   double*						xi;
-   double						weight;
-   Particle_InCellIndex		cParticle_I, cellParticleCount;
-   Node_ElementLocalIndex	nodesPerEl_row;
-   Node_ElementLocalIndex	nodesPerEl_col;	
-   Dof_Index					totalDofsThisElement_row, totalDofsThisElement_col;
-	
-   Dof_Index					dofPerNode_row, dofPerNode_col;
-   Index							row, col; /* Indices into the stiffness matrix */
-   Node_ElementLocalIndex	rowNode_I;
-   Node_ElementLocalIndex	colNode_I;
-   Dof_Index					rowDof_I, colDof_I;
-   double**						GNx_row;
-   double*						Ni_col;
-   double						detJac;
-   IntegrationPoint*			currIntegrationPoint;
-	
-   Cell_Index					cell_I;
-   ElementType*				elementType_row;
-   ElementType*				elementType_col;
-	
-   /* Set the element type */
-   elementType_row = FeMesh_GetElementType( variable_row->feMesh, lElement_I );
-   nodesPerEl_row = elementType_row->nodeCount;
-	
-   elementType_col = FeMesh_GetElementType( variable_col->feMesh, lElement_I );
-   nodesPerEl_col = elementType_col->nodeCount;
-		
-   dofPerNode_row = dim;	/* velocity */
-   dofPerNode_col = 1;	/* pressure */
-	
-   totalDofsThisElement_row = nodesPerEl_row * dofPerNode_row;
-   totalDofsThisElement_col = nodesPerEl_col * dofPerNode_col;
-	
-	if( nodesPerEl_row > self->max_nElNodes ) {
-		/* reallocate */
-		self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl_row );
-		self->max_nElNodes = nodesPerEl_row;
-	}
-	GNx_row = self->GNx;
-
-	if( nodesPerEl_col > self->max_nElNodes_col ) {
-   /* allocate */
-		self->Ni_col = ReallocArray( self->Ni_col, double, nodesPerEl_col );
-		self->max_nElNodes_col = nodesPerEl_col;
-	}
-	Ni_col = self->Ni_col;
-	
-   cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
-   cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-	
-   for ( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
-      currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
-      xi = currIntegrationPoint->xi;
-      weight = currIntegrationPoint->weight;
-		
-      /* get shape function derivs for the row (ie. velocity) */
-      ElementType_ShapeFunctionsGlobalDerivs( elementType_row, variable_row->feMesh, lElement_I, xi, dim, &detJac, GNx_row );
-		
-      /* get the shape functions for the col. (ie. pressure) */
-      ElementType_EvaluateShapeFunctionsAt( elementType_col, xi, Ni_col );
-		
-      /* build stiffness matrix */
-      for ( rowNode_I = 0; rowNode_I < nodesPerEl_row ; rowNode_I++) {  	
-         for( rowDof_I=0; rowDof_I<dofPerNode_row; rowDof_I++) {	
-            row = rowNode_I*dofPerNode_row + rowDof_I;
-
-            for (colNode_I = 0; colNode_I < nodesPerEl_col; colNode_I++ ) { 
-               for( colDof_I=0; colDof_I<dofPerNode_col; colDof_I++) {		
-                  col = colNode_I*dofPerNode_col + colDof_I;
-						
-                  elStiffMat[col][row] += + weight * ( -detJac ) * ( GNx_row[rowDof_I][rowNode_I] * Ni_col[colNode_I] );
-               }
-            }
-         }
-      }
-   }
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/DivergenceMatrixTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/DivergenceMatrixTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,255 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: DivergenceMatrixTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "types.h"
+#include "DivergenceMatrixTerm.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type DivergenceMatrixTerm_Type = "DivergenceMatrixTerm";
+
+DivergenceMatrixTerm* DivergenceMatrixTerm_New( 
+	Name					     name,
+	FiniteElementContext*  context,
+	StiffnessMatrix*	     stiffnessMatrix,
+	Swarm*				     integrationSwarm )
+{
+	DivergenceMatrixTerm* self = (DivergenceMatrixTerm*) _DivergenceMatrixTerm_DefaultNew( name );
+	
+	self->isConstructed = True;
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
+   _DivergenceMatrixTerm_Init( self );
+
+   return self;
+}
+
+/* Creation implementation / Virtual constructor */
+DivergenceMatrixTerm* _DivergenceMatrixTerm_New(  DIVERGENCEMATRIXTERM_DEFARGS  )
+{
+   DivergenceMatrixTerm* self;
+	
+   /* Allocate memory */
+   assert( _sizeOfSelf >= sizeof(DivergenceMatrixTerm) );
+   self = (DivergenceMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
+	
+   /* Virtual info */
+	
+   return self;
+}
+
+void _DivergenceMatrixTerm_Init( void* matrixTerm ) {
+   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
+
+	self->max_nElNodes_col = 0;
+	self->Ni_col = NULL;
+}
+
+void _DivergenceMatrixTerm_Delete( void* matrixTerm ) {
+   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
+
+   _StiffnessMatrixTerm_Delete( self );
+	
+	Memory_Free( self->Ni_col );
+}
+
+void _DivergenceMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
+   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
+	
+   _StiffnessMatrixTerm_Print( self, stream );
+
+   /* General info */
+}
+
+void* _DivergenceMatrixTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(DivergenceMatrixTerm);
+	Type                                                         type = DivergenceMatrixTerm_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _DivergenceMatrixTerm_Delete;
+	Stg_Class_PrintFunction*                                   _print = _DivergenceMatrixTerm_Print;
+	Stg_Class_CopyFunction*                                     _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _DivergenceMatrixTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _DivergenceMatrixTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _DivergenceMatrixTerm_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _DivergenceMatrixTerm_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _DivergenceMatrixTerm_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _DivergenceMatrixTerm_Destroy;
+	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _DivergenceMatrixTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+   return (void*)_DivergenceMatrixTerm_New(  DIVERGENCEMATRIXTERM_PASSARGS  );
+}
+
+void _DivergenceMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
+   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
+
+   /* Construct Parent */
+   _StiffnessMatrixTerm_AssignFromXML( self, cf, data );
+
+   _DivergenceMatrixTerm_Init( self );
+}
+
+void _DivergenceMatrixTerm_Build( void* matrixTerm, void* data ) {
+   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
+
+   _StiffnessMatrixTerm_Build( self, data );
+}
+
+void _DivergenceMatrixTerm_Initialise( void* matrixTerm, void* data ) {
+   DivergenceMatrixTerm* self = (DivergenceMatrixTerm*)matrixTerm;
+
+   _StiffnessMatrixTerm_Initialise( self, data );
+}
+
+void _DivergenceMatrixTerm_Execute( void* matrixTerm, void* data ) {
+   _StiffnessMatrixTerm_Execute( matrixTerm, data );
+}
+
+void _DivergenceMatrixTerm_Destroy( void* matrixTerm, void* data ) {
+	DivergenceMatrixTerm* self = (DivergenceMatrixTerm*) matrixTerm;
+
+   if( self->Ni_col) Memory_Free( self->Ni_col );
+	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
+}
+
+void _DivergenceMatrixTerm_AssembleElement( 
+   void*							matrixTerm,
+   StiffnessMatrix*			stiffnessMatrix, 
+   Element_LocalIndex		lElement_I, 
+   SystemLinearEquations*	sle,
+   FiniteElementContext*	context,
+   double**						elStiffMat ) 
+{
+   DivergenceMatrixTerm*	self         = Stg_CheckType( matrixTerm, DivergenceMatrixTerm );
+   Swarm*						swarm        = self->integrationSwarm;
+   FeVariable*					variable_row = stiffnessMatrix->columnVariable;
+   FeVariable*					variable_col = stiffnessMatrix->rowVariable;
+   Dimension_Index			dim          = stiffnessMatrix->dim;
+   double*						xi;
+   double						weight;
+   Particle_InCellIndex		cParticle_I, cellParticleCount;
+   Node_ElementLocalIndex	nodesPerEl_row;
+   Node_ElementLocalIndex	nodesPerEl_col;	
+   Dof_Index					totalDofsThisElement_row, totalDofsThisElement_col;
+	
+   Dof_Index					dofPerNode_row, dofPerNode_col;
+   Index							row, col; /* Indices into the stiffness matrix */
+   Node_ElementLocalIndex	rowNode_I;
+   Node_ElementLocalIndex	colNode_I;
+   Dof_Index					rowDof_I, colDof_I;
+   double**						GNx_row;
+   double*						Ni_col;
+   double						detJac;
+   IntegrationPoint*			currIntegrationPoint;
+	
+   Cell_Index					cell_I;
+   ElementType*				elementType_row;
+   ElementType*				elementType_col;
+	
+   /* Set the element type */
+   elementType_row = FeMesh_GetElementType( variable_row->feMesh, lElement_I );
+   nodesPerEl_row = elementType_row->nodeCount;
+	
+   elementType_col = FeMesh_GetElementType( variable_col->feMesh, lElement_I );
+   nodesPerEl_col = elementType_col->nodeCount;
+		
+   dofPerNode_row = dim;	/* velocity */
+   dofPerNode_col = 1;	/* pressure */
+	
+   totalDofsThisElement_row = nodesPerEl_row * dofPerNode_row;
+   totalDofsThisElement_col = nodesPerEl_col * dofPerNode_col;
+	
+	if( nodesPerEl_row > self->max_nElNodes ) {
+		/* reallocate */
+		self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl_row );
+		self->max_nElNodes = nodesPerEl_row;
+	}
+	GNx_row = self->GNx;
+
+	if( nodesPerEl_col > self->max_nElNodes_col ) {
+   /* allocate */
+		self->Ni_col = ReallocArray( self->Ni_col, double, nodesPerEl_col );
+		self->max_nElNodes_col = nodesPerEl_col;
+	}
+	Ni_col = self->Ni_col;
+	
+   cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
+   cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+	
+   for ( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
+      currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
+      xi = currIntegrationPoint->xi;
+      weight = currIntegrationPoint->weight;
+		
+      /* get shape function derivs for the row (ie. velocity) */
+      ElementType_ShapeFunctionsGlobalDerivs( elementType_row, variable_row->feMesh, lElement_I, xi, dim, &detJac, GNx_row );
+		
+      /* get the shape functions for the col. (ie. pressure) */
+      ElementType_EvaluateShapeFunctionsAt( elementType_col, xi, Ni_col );
+		
+      /* build stiffness matrix */
+      for ( rowNode_I = 0; rowNode_I < nodesPerEl_row ; rowNode_I++) {  	
+         for( rowDof_I=0; rowDof_I<dofPerNode_row; rowDof_I++) {	
+            row = rowNode_I*dofPerNode_row + rowDof_I;
+
+            for (colNode_I = 0; colNode_I < nodesPerEl_col; colNode_I++ ) { 
+               for( colDof_I=0; colDof_I<dofPerNode_col; colDof_I++) {		
+                  col = colNode_I*dofPerNode_col + colDof_I;
+						
+                  elStiffMat[col][row] += + weight * ( -detJac ) * ( GNx_row[rowDof_I][rowNode_I] * Ni_col[colNode_I] );
+               }
+            }
+         }
+      }
+   }
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/Finalise.c
--- a/Assembly/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SLE.h"
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "Finalise.h"
-
-#include <stdio.h>
-
-Bool StgFEM_Assembly_Finalise( void ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	Stream_IndentBranch( StgFEM_Debug );
-	Stream_UnIndentBranch( StgFEM_Debug );
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,62 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SLE.h"
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "Finalise.h"
+
+#include <stdio.h>
+
+Bool StgFEM_Assembly_Finalise( void ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	Stream_IndentBranch( StgFEM_Debug );
+	Stream_UnIndentBranch( StgFEM_Debug );
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/GradientStiffnessMatrixTerm.c
--- a/Assembly/src/GradientStiffnessMatrixTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,257 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: GradientStiffnessMatrixTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "types.h"
-#include "GradientStiffnessMatrixTerm.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type GradientStiffnessMatrixTerm_Type = "GradientStiffnessMatrixTerm";
-
-GradientStiffnessMatrixTerm* GradientStiffnessMatrixTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	StiffnessMatrix*			stiffnessMatrix,
-	Swarm*						integrationSwarm )
-{
-	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*) _GradientStiffnessMatrixTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
-	_GradientStiffnessMatrixTerm_Init( self );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-GradientStiffnessMatrixTerm* _GradientStiffnessMatrixTerm_New(  GRADIENTSTIFFNESSMATRIXTERM_DEFARGS  )
-{
-	GradientStiffnessMatrixTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(GradientStiffnessMatrixTerm) );
-	self = (GradientStiffnessMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _GradientStiffnessMatrixTerm_Init( void* matrixTerm ) {
-	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
-
-	self->max_nElNodes_col = 0;
-	self->Ni_col = NULL;
-}
-
-void _GradientStiffnessMatrixTerm_Delete( void* matrixTerm ) {
-	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Delete( self );
-}
-
-void _GradientStiffnessMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
-	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
-	
-	_StiffnessMatrixTerm_Print( self, stream );
-
-	/* General info */
-}
-
-void* _GradientStiffnessMatrixTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(GradientStiffnessMatrixTerm);
-	Type                                                         type = GradientStiffnessMatrixTerm_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _GradientStiffnessMatrixTerm_Delete;
-	Stg_Class_PrintFunction*                                   _print = _GradientStiffnessMatrixTerm_Print;
-	Stg_Class_CopyFunction*                                     _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _GradientStiffnessMatrixTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _GradientStiffnessMatrixTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _GradientStiffnessMatrixTerm_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _GradientStiffnessMatrixTerm_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _GradientStiffnessMatrixTerm_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _GradientStiffnessMatrixTerm_Destroy;
-	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _GradientStiffnessMatrixTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_GradientStiffnessMatrixTerm_New(  GRADIENTSTIFFNESSMATRIXTERM_PASSARGS  );
-}
-
-void _GradientStiffnessMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
-	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
-
-	/* Construct Parent */
-	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
-
-	_GradientStiffnessMatrixTerm_Init( self );
-}
-
-void _GradientStiffnessMatrixTerm_Build( void* matrixTerm, void* data ) {
-	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Build( self, data );
-}
-
-void _GradientStiffnessMatrixTerm_Initialise( void* matrixTerm, void* data ) {
-	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Initialise( self, data );
-}
-
-void _GradientStiffnessMatrixTerm_Execute( void* matrixTerm, void* data ) {
-	_StiffnessMatrixTerm_Execute( matrixTerm, data );
-}
-
-void _GradientStiffnessMatrixTerm_Destroy( void* matrixTerm, void* data ) {
-	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
-
-   if( self->Ni_col ) Memory_Free( self->Ni_col ); 
-	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
-}
-
-void _GradientStiffnessMatrixTerm_AssembleElement( 
-		void*                                              matrixTerm,
-		StiffnessMatrix*                                   stiffnessMatrix, 
-		Element_LocalIndex                                 lElement_I, 
-		SystemLinearEquations*                             sle,
-		FiniteElementContext*                              context,
-		double**                                           elStiffMat ) 
-{
-	GradientStiffnessMatrixTerm*        self         = Stg_CheckType( matrixTerm, GradientStiffnessMatrixTerm );
-	Swarm*                              swarm        = self->integrationSwarm;
-	FeVariable*                         variable_row = stiffnessMatrix->rowVariable;
-	FeVariable*                         variable_col = stiffnessMatrix->columnVariable;
-	Dimension_Index                     dim          = stiffnessMatrix->dim;
-	double*                             xi;
-	double                              weight;
-	Particle_InCellIndex                cParticle_I, cellParticleCount;
-	Node_ElementLocalIndex              nodesPerEl_row;
-	Node_ElementLocalIndex              nodesPerEl_col;	
-	Dof_Index                           totalDofsThisElement_row, totalDofsThisElement_col;
-	
-	Dof_Index                           dofPerNode_row, dofPerNode_col;
-	Index                               row, col; /* Indices into the stiffness matrix */
-	Node_ElementLocalIndex              rowNode_I;
-	Node_ElementLocalIndex              colNode_I;
-	Dof_Index                           rowDof_I, colDof_I;
-	double**                            GNx_row;
-	double*                             Ni_col;
-	double                              detJac;
-	IntegrationPoint*                   currIntegrationPoint;
-	
-	Cell_Index                          cell_I;
-	ElementType*                        elementType_row;
-	ElementType*                        elementType_col;
-	
-	/* Set the element type */
-	elementType_row = FeMesh_GetElementType( variable_row->feMesh, lElement_I );
-	nodesPerEl_row = elementType_row->nodeCount;
-	
-	elementType_col = FeMesh_GetElementType( variable_col->feMesh, lElement_I );
-	nodesPerEl_col = elementType_col->nodeCount;
-		
-	dofPerNode_row = dim;	/* velocity */
-	dofPerNode_col = 1;	/* pressure */
-	
-	totalDofsThisElement_row = nodesPerEl_row * dofPerNode_row;
-	totalDofsThisElement_col = nodesPerEl_col * dofPerNode_col;
-	
-	if( nodesPerEl_row > self->max_nElNodes ) {
-		/* reallocate */
-		self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl_row );
-		self->max_nElNodes = nodesPerEl_row;
-	}
-	GNx_row = self->GNx;
-
-	if( nodesPerEl_col > self->max_nElNodes_col ) {
-   /* allocate */
-		self->Ni_col = ReallocArray( self->Ni_col, double, nodesPerEl_col );
-		self->max_nElNodes_col = nodesPerEl_col;
-	}
-	Ni_col = self->Ni_col;
-	
-	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
-	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-	
-	for ( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
-		currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
-		xi = currIntegrationPoint->xi;
-		weight = currIntegrationPoint->weight;
-		
-		/* get shape function derivs for the row (ie. velocity) */
-		ElementType_ShapeFunctionsGlobalDerivs( 
-				elementType_row,
-				variable_row->feMesh, lElement_I,
-				xi, dim, &detJac, GNx_row );
-		
-		/* get the shape functions for the col. (ie. pressure) */
-		ElementType_EvaluateShapeFunctionsAt( elementType_col, xi, Ni_col );
-		
-		/* build stiffness matrix */
-		for ( rowNode_I = 0; rowNode_I < nodesPerEl_row ; rowNode_I++) {  	
-			for( rowDof_I=0; rowDof_I<dofPerNode_row; rowDof_I++) {	
-				row = rowNode_I*dofPerNode_row + rowDof_I;
-
-				for (colNode_I = 0; colNode_I < nodesPerEl_col; colNode_I++ ) { 
-					for( colDof_I=0; colDof_I<dofPerNode_col; colDof_I++) {		
-						col = colNode_I*dofPerNode_col + colDof_I;
-						
-						elStiffMat[row][col] +=
-							+ weight * ( - detJac ) * ( GNx_row[rowDof_I][rowNode_I] * Ni_col[colNode_I] );
-					}
-				}		
-			}
-		}
-	}
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/GradientStiffnessMatrixTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/GradientStiffnessMatrixTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,257 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: GradientStiffnessMatrixTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "types.h"
+#include "GradientStiffnessMatrixTerm.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type GradientStiffnessMatrixTerm_Type = "GradientStiffnessMatrixTerm";
+
+GradientStiffnessMatrixTerm* GradientStiffnessMatrixTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	StiffnessMatrix*			stiffnessMatrix,
+	Swarm*						integrationSwarm )
+{
+	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*) _GradientStiffnessMatrixTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
+	_GradientStiffnessMatrixTerm_Init( self );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+GradientStiffnessMatrixTerm* _GradientStiffnessMatrixTerm_New(  GRADIENTSTIFFNESSMATRIXTERM_DEFARGS  )
+{
+	GradientStiffnessMatrixTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(GradientStiffnessMatrixTerm) );
+	self = (GradientStiffnessMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _GradientStiffnessMatrixTerm_Init( void* matrixTerm ) {
+	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
+
+	self->max_nElNodes_col = 0;
+	self->Ni_col = NULL;
+}
+
+void _GradientStiffnessMatrixTerm_Delete( void* matrixTerm ) {
+	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Delete( self );
+}
+
+void _GradientStiffnessMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
+	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
+	
+	_StiffnessMatrixTerm_Print( self, stream );
+
+	/* General info */
+}
+
+void* _GradientStiffnessMatrixTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(GradientStiffnessMatrixTerm);
+	Type                                                         type = GradientStiffnessMatrixTerm_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _GradientStiffnessMatrixTerm_Delete;
+	Stg_Class_PrintFunction*                                   _print = _GradientStiffnessMatrixTerm_Print;
+	Stg_Class_CopyFunction*                                     _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _GradientStiffnessMatrixTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _GradientStiffnessMatrixTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _GradientStiffnessMatrixTerm_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _GradientStiffnessMatrixTerm_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _GradientStiffnessMatrixTerm_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _GradientStiffnessMatrixTerm_Destroy;
+	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _GradientStiffnessMatrixTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_GradientStiffnessMatrixTerm_New(  GRADIENTSTIFFNESSMATRIXTERM_PASSARGS  );
+}
+
+void _GradientStiffnessMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
+	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
+
+	/* Construct Parent */
+	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
+
+	_GradientStiffnessMatrixTerm_Init( self );
+}
+
+void _GradientStiffnessMatrixTerm_Build( void* matrixTerm, void* data ) {
+	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Build( self, data );
+}
+
+void _GradientStiffnessMatrixTerm_Initialise( void* matrixTerm, void* data ) {
+	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Initialise( self, data );
+}
+
+void _GradientStiffnessMatrixTerm_Execute( void* matrixTerm, void* data ) {
+	_StiffnessMatrixTerm_Execute( matrixTerm, data );
+}
+
+void _GradientStiffnessMatrixTerm_Destroy( void* matrixTerm, void* data ) {
+	GradientStiffnessMatrixTerm* self = (GradientStiffnessMatrixTerm*)matrixTerm;
+
+   if( self->Ni_col ) Memory_Free( self->Ni_col ); 
+	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
+}
+
+void _GradientStiffnessMatrixTerm_AssembleElement( 
+		void*                                              matrixTerm,
+		StiffnessMatrix*                                   stiffnessMatrix, 
+		Element_LocalIndex                                 lElement_I, 
+		SystemLinearEquations*                             sle,
+		FiniteElementContext*                              context,
+		double**                                           elStiffMat ) 
+{
+	GradientStiffnessMatrixTerm*        self         = Stg_CheckType( matrixTerm, GradientStiffnessMatrixTerm );
+	Swarm*                              swarm        = self->integrationSwarm;
+	FeVariable*                         variable_row = stiffnessMatrix->rowVariable;
+	FeVariable*                         variable_col = stiffnessMatrix->columnVariable;
+	Dimension_Index                     dim          = stiffnessMatrix->dim;
+	double*                             xi;
+	double                              weight;
+	Particle_InCellIndex                cParticle_I, cellParticleCount;
+	Node_ElementLocalIndex              nodesPerEl_row;
+	Node_ElementLocalIndex              nodesPerEl_col;	
+	Dof_Index                           totalDofsThisElement_row, totalDofsThisElement_col;
+	
+	Dof_Index                           dofPerNode_row, dofPerNode_col;
+	Index                               row, col; /* Indices into the stiffness matrix */
+	Node_ElementLocalIndex              rowNode_I;
+	Node_ElementLocalIndex              colNode_I;
+	Dof_Index                           rowDof_I, colDof_I;
+	double**                            GNx_row;
+	double*                             Ni_col;
+	double                              detJac;
+	IntegrationPoint*                   currIntegrationPoint;
+	
+	Cell_Index                          cell_I;
+	ElementType*                        elementType_row;
+	ElementType*                        elementType_col;
+	
+	/* Set the element type */
+	elementType_row = FeMesh_GetElementType( variable_row->feMesh, lElement_I );
+	nodesPerEl_row = elementType_row->nodeCount;
+	
+	elementType_col = FeMesh_GetElementType( variable_col->feMesh, lElement_I );
+	nodesPerEl_col = elementType_col->nodeCount;
+		
+	dofPerNode_row = dim;	/* velocity */
+	dofPerNode_col = 1;	/* pressure */
+	
+	totalDofsThisElement_row = nodesPerEl_row * dofPerNode_row;
+	totalDofsThisElement_col = nodesPerEl_col * dofPerNode_col;
+	
+	if( nodesPerEl_row > self->max_nElNodes ) {
+		/* reallocate */
+		self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl_row );
+		self->max_nElNodes = nodesPerEl_row;
+	}
+	GNx_row = self->GNx;
+
+	if( nodesPerEl_col > self->max_nElNodes_col ) {
+   /* allocate */
+		self->Ni_col = ReallocArray( self->Ni_col, double, nodesPerEl_col );
+		self->max_nElNodes_col = nodesPerEl_col;
+	}
+	Ni_col = self->Ni_col;
+	
+	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
+	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+	
+	for ( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
+		currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
+		xi = currIntegrationPoint->xi;
+		weight = currIntegrationPoint->weight;
+		
+		/* get shape function derivs for the row (ie. velocity) */
+		ElementType_ShapeFunctionsGlobalDerivs( 
+				elementType_row,
+				variable_row->feMesh, lElement_I,
+				xi, dim, &detJac, GNx_row );
+		
+		/* get the shape functions for the col. (ie. pressure) */
+		ElementType_EvaluateShapeFunctionsAt( elementType_col, xi, Ni_col );
+		
+		/* build stiffness matrix */
+		for ( rowNode_I = 0; rowNode_I < nodesPerEl_row ; rowNode_I++) {  	
+			for( rowDof_I=0; rowDof_I<dofPerNode_row; rowDof_I++) {	
+				row = rowNode_I*dofPerNode_row + rowDof_I;
+
+				for (colNode_I = 0; colNode_I < nodesPerEl_col; colNode_I++ ) { 
+					for( colDof_I=0; colDof_I<dofPerNode_col; colDof_I++) {		
+						col = colNode_I*dofPerNode_col + colDof_I;
+						
+						elStiffMat[row][col] +=
+							+ weight * ( - detJac ) * ( GNx_row[rowDof_I][rowNode_I] * Ni_col[colNode_I] );
+					}
+				}		
+			}
+		}
+	}
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/Init.c
--- a/Assembly/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 1209 2008-08-25 01:16:22Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "Assembly.h"
-
-#include <stdio.h>
-
-Stream* StgFEM_Assembly_Debug = NULL;
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_Assembly_Init( int* argc, char** argv[] ) {
-	Stg_ComponentRegister* componentRegister = Stg_ComponentRegister_Get_ComponentRegister();
-	int tmp;
-	
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	tmp = Stream_GetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context" )  );
-	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), 0 );
-	Journal_Printf( /* DO NOT CHANGE OR REMOVE */
-		Journal_Register( InfoStream_Type, (Name)"Context"  ), 
-		"StGermain FEM Assembly Library revision %s. Copyright (C) 2003-2005 VPAC.\n", VERSION );
-	Stream_Flush( Journal_Register( InfoStream_Type, (Name)"Context" )  );
-	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), tmp );
-	
-	/* initialise this level's streams */
-	StgFEM_Assembly_Debug = Stream_RegisterChild( StgFEM_Debug, "Assembly" );
-	
-	Stg_ComponentRegister_Add( componentRegister, ThermalBuoyancyForceTerm_Type, (Name)"0", _ThermalBuoyancyForceTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, GradientStiffnessMatrixTerm_Type, (Name)"0", _GradientStiffnessMatrixTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, DivergenceMatrixTerm_Type, (Name)"0", _DivergenceMatrixTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, LaplacianStiffnessMatrixTerm_Type, (Name)"0", _LaplacianStiffnessMatrixTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, IsoviscousStressTensorTerm_Type, (Name)"0", _IsoviscousStressTensorTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, PressureGradMatrixTerm_Type, (Name)"0", _PressureGradMatrixTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, PressureGradForceTerm_Type, (Name)"0", _PressureGradForceTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, MassMatrixTerm_Type, (Name)"0", _MassMatrixTerm_DefaultNew  );
-
-	RegisterParent( ThermalBuoyancyForceTerm_Type,     ForceTerm_Type );
-	RegisterParent( GradientStiffnessMatrixTerm_Type,  StiffnessMatrixTerm_Type );
-	RegisterParent( DivergenceMatrixTerm_Type,  StiffnessMatrixTerm_Type );
-	RegisterParent( LaplacianStiffnessMatrixTerm_Type, StiffnessMatrixTerm_Type );
-	RegisterParent( IsoviscousStressTensorTerm_Type,   StiffnessMatrixTerm_Type );
-	RegisterParent( PressureGradMatrixTerm_Type,   StiffnessMatrixTerm_Type );
-	RegisterParent( PressureGradForceTerm_Type,     ForceTerm_Type );
-	RegisterParent( MassMatrixTerm_Type,   StiffnessMatrixTerm_Type );
-
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,93 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 1209 2008-08-25 01:16:22Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "Assembly.h"
+
+#include <stdio.h>
+
+Stream* StgFEM_Assembly_Debug = NULL;
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_Assembly_Init( int* argc, char** argv[] ) {
+	Stg_ComponentRegister* componentRegister = Stg_ComponentRegister_Get_ComponentRegister();
+	int tmp;
+	
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	tmp = Stream_GetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context" )  );
+	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), 0 );
+	Journal_Printf( /* DO NOT CHANGE OR REMOVE */
+		Journal_Register( InfoStream_Type, (Name)"Context"  ), 
+		"StGermain FEM Assembly Library revision %s. Copyright (C) 2003-2005 VPAC.\n", VERSION );
+	Stream_Flush( Journal_Register( InfoStream_Type, (Name)"Context" )  );
+	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), tmp );
+	
+	/* initialise this level's streams */
+	StgFEM_Assembly_Debug = Stream_RegisterChild( StgFEM_Debug, "Assembly" );
+	
+	Stg_ComponentRegister_Add( componentRegister, ThermalBuoyancyForceTerm_Type, (Name)"0", _ThermalBuoyancyForceTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, GradientStiffnessMatrixTerm_Type, (Name)"0", _GradientStiffnessMatrixTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, DivergenceMatrixTerm_Type, (Name)"0", _DivergenceMatrixTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, LaplacianStiffnessMatrixTerm_Type, (Name)"0", _LaplacianStiffnessMatrixTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, IsoviscousStressTensorTerm_Type, (Name)"0", _IsoviscousStressTensorTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, PressureGradMatrixTerm_Type, (Name)"0", _PressureGradMatrixTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, PressureGradForceTerm_Type, (Name)"0", _PressureGradForceTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, MassMatrixTerm_Type, (Name)"0", _MassMatrixTerm_DefaultNew  );
+
+	RegisterParent( ThermalBuoyancyForceTerm_Type,     ForceTerm_Type );
+	RegisterParent( GradientStiffnessMatrixTerm_Type,  StiffnessMatrixTerm_Type );
+	RegisterParent( DivergenceMatrixTerm_Type,  StiffnessMatrixTerm_Type );
+	RegisterParent( LaplacianStiffnessMatrixTerm_Type, StiffnessMatrixTerm_Type );
+	RegisterParent( IsoviscousStressTensorTerm_Type,   StiffnessMatrixTerm_Type );
+	RegisterParent( PressureGradMatrixTerm_Type,   StiffnessMatrixTerm_Type );
+	RegisterParent( PressureGradForceTerm_Type,     ForceTerm_Type );
+	RegisterParent( MassMatrixTerm_Type,   StiffnessMatrixTerm_Type );
+
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/IsoviscousStressTensorTerm.c
--- a/Assembly/src/IsoviscousStressTensorTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,259 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: IsoviscousStressTensorTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "types.h"
-#include "IsoviscousStressTensorTerm.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type IsoviscousStressTensorTerm_Type = "IsoviscousStressTensorTerm";
-
-IsoviscousStressTensorTerm* IsoviscousStressTensorTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	StiffnessMatrix*			stiffnessMatrix,
-	Swarm*						integrationSwarm,
-	double						viscosity )
-{
-	IsoviscousStressTensorTerm* self = (IsoviscousStressTensorTerm*) _IsoviscousStressTensorTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
-	_IsoviscousStressTensorTerm_Init( self, viscosity );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-IsoviscousStressTensorTerm* _IsoviscousStressTensorTerm_New(  ISOVISCOUSSTRESSTENSORTERM_DEFARGS  )
-{
-	IsoviscousStressTensorTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(IsoviscousStressTensorTerm) );
-	self = (IsoviscousStressTensorTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _IsoviscousStressTensorTerm_Init( void* matrixTerm, double viscosity ) {
-	IsoviscousStressTensorTerm* self = (IsoviscousStressTensorTerm*)matrixTerm;
-	self->viscosity = viscosity;
-}
-
-void _IsoviscousStressTensorTerm_Delete( void* matrixTerm ) {
-	IsoviscousStressTensorTerm* self = (IsoviscousStressTensorTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Delete( self );
-}
-
-void _IsoviscousStressTensorTerm_Print( void* matrixTerm, Stream* stream ) {
-	IsoviscousStressTensorTerm* self = (IsoviscousStressTensorTerm*)matrixTerm;
-	
-	_StiffnessMatrixTerm_Print( self, stream );
-
-	/* General info */
-	Journal_PrintValue( stream, self->viscosity );
-}
-
-void* _IsoviscousStressTensorTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(IsoviscousStressTensorTerm);
-	Type                                                         type = IsoviscousStressTensorTerm_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _IsoviscousStressTensorTerm_Delete;
-	Stg_Class_PrintFunction*                                   _print = _IsoviscousStressTensorTerm_Print;
-	Stg_Class_CopyFunction*                                     _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _IsoviscousStressTensorTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _IsoviscousStressTensorTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _IsoviscousStressTensorTerm_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _IsoviscousStressTensorTerm_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _IsoviscousStressTensorTerm_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _IsoviscousStressTensorTerm_Destroy;
-	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _IsoviscousStressTensorTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_IsoviscousStressTensorTerm_New(  ISOVISCOUSSTRESSTENSORTERM_PASSARGS  );
-}
-
-void _IsoviscousStressTensorTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
-	IsoviscousStressTensorTerm*            self             = (IsoviscousStressTensorTerm*)matrixTerm;
-
-	/* Construct Parent */
-	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
-
-	_IsoviscousStressTensorTerm_Init( self, Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"viscosity", 1.0 )  );
-}
-
-void _IsoviscousStressTensorTerm_Build( void* matrixTerm, void* data ) {
-	IsoviscousStressTensorTerm*             self             = (IsoviscousStressTensorTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Build( self, data );
-}
-
-void _IsoviscousStressTensorTerm_Initialise( void* matrixTerm, void* data ) {
-	IsoviscousStressTensorTerm*             self             = (IsoviscousStressTensorTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Initialise( self, data );
-}
-
-void _IsoviscousStressTensorTerm_Execute( void* matrixTerm, void* data ) {
-	_StiffnessMatrixTerm_Execute( matrixTerm, data );
-}
-
-void _IsoviscousStressTensorTerm_Destroy( void* matrixTerm, void* data ) {
-	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
-}
-
-
-void _IsoviscousStressTensorTerm_AssembleElement( 
-		void*                                              matrixTerm,
-		StiffnessMatrix*                                   stiffnessMatrix, 
-		Element_LocalIndex                                 lElement_I, 
-		SystemLinearEquations*                             sle,
-		FiniteElementContext*                              context,
-		double**                                           elStiffMat ) 
-{
-	IsoviscousStressTensorTerm*         self         = Stg_CheckType( matrixTerm, IsoviscousStressTensorTerm );
-	Swarm*                              swarm        = self->integrationSwarm;
-	FeVariable*                         variable1    = stiffnessMatrix->rowVariable;
-	Dimension_Index                     dim          = stiffnessMatrix->dim;
-	
-	IntegrationPoint*                   currIntegrationPoint;
-	double*                             xi;
-	double                              weight;
-	Particle_InCellIndex                cParticle_I, cellParticleCount;
-	Index                               nodesPerEl;
-	Node_ElementLocalIndex              rowNode_I;
-	Node_ElementLocalIndex              colNode_I;
-	double**                            GNx;
-	double                              detJac;
-	double                              visc           = self->viscosity;
-	
-	Cell_Index                          cell_I;
-	ElementType*                        elementType;
-	int                                 nodalDofs;
-	Dof_Index                           diagDof_I;
-	Dof_Index                           rowDof_I;
-	Dof_Index                           colDof_I;
-	Dof_Index                           d;
-	Dof_Index                           dofsPerNode;
-	Index                               rowIndex;
-	Index                               colIndex;
-	
-	/* Set the element type */
-	elementType = FeMesh_GetElementType( variable1->feMesh, lElement_I );
-	nodesPerEl = elementType->nodeCount;
-
-	/* assumes constant number of dofs per element */
-	nodalDofs = nodesPerEl * dim;
-	dofsPerNode = dim;
-	
-	if( nodesPerEl > self->max_nElNodes ) {
-		/* reallocate */
-		self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl );
-		self->max_nElNodes = nodesPerEl;
-	}
-	GNx = self->GNx;
-
-	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
-	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-	
-	for( cParticle_I=0; cParticle_I < cellParticleCount; cParticle_I++ ) {
-		
-		currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
-		xi = currIntegrationPoint->xi;
-		weight = currIntegrationPoint->weight;
-		
-		ElementType_ShapeFunctionsGlobalDerivs( 
-			elementType,
-			variable1->feMesh, lElement_I,
-			xi, dim, &detJac, GNx );
-		
-		/* Initially just build the diagonal (from a Dof perspective) entries */
-		for( rowNode_I=0; rowNode_I < nodesPerEl; rowNode_I++ ) { 		
-			for( colNode_I=0; colNode_I < nodesPerEl; colNode_I++ ) {		
-				for( diagDof_I=0; diagDof_I < dofsPerNode; diagDof_I++ ) {	
-					rowIndex =  rowNode_I*dofsPerNode + diagDof_I;
-					colIndex = colNode_I*dofsPerNode + diagDof_I;
-					elStiffMat[rowIndex][colIndex] +=
-						detJac * visc * weight * ( GNx[diagDof_I][rowNode_I] * GNx[diagDof_I][colNode_I] );
-					for( d=0; d<dofsPerNode; d++ ) {	
-						elStiffMat[rowIndex][colIndex] +=
-							detJac * visc * weight * ( GNx[d][rowNode_I] * GNx[d][colNode_I] );
-					}
-				}
-			}
-		}
-		
-		/* then build one set of the off diagonal blocks of K, and copy to the other off diags using symmetry */
-		for( rowNode_I=0; rowNode_I < nodesPerEl; rowNode_I++ ) {
-                  for( rowDof_I=0; rowDof_I < dofsPerNode-1; rowDof_I++ ) {	/* dont need to do anything in last row */
-				for( colNode_I=0; colNode_I < nodesPerEl; colNode_I++ ) {
-					for( colDof_I=rowDof_I+1; colDof_I < dofsPerNode; colDof_I++ ) {
-						rowIndex = rowNode_I*dofsPerNode + rowDof_I;
-						colIndex = colNode_I*dofsPerNode + colDof_I;
-						elStiffMat[rowIndex][colIndex] += detJac * visc * weight * 
-								( GNx[colDof_I][rowNode_I] * GNx[rowDof_I][colNode_I] );
-						/* symmetry	*/
-						elStiffMat[colIndex][rowIndex] = elStiffMat[rowIndex][colIndex];
-					}
-				}
-			}
-		}
-	}
-	
-	return;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/IsoviscousStressTensorTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/IsoviscousStressTensorTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,259 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: IsoviscousStressTensorTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "types.h"
+#include "IsoviscousStressTensorTerm.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type IsoviscousStressTensorTerm_Type = "IsoviscousStressTensorTerm";
+
+IsoviscousStressTensorTerm* IsoviscousStressTensorTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	StiffnessMatrix*			stiffnessMatrix,
+	Swarm*						integrationSwarm,
+	double						viscosity )
+{
+	IsoviscousStressTensorTerm* self = (IsoviscousStressTensorTerm*) _IsoviscousStressTensorTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
+	_IsoviscousStressTensorTerm_Init( self, viscosity );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+IsoviscousStressTensorTerm* _IsoviscousStressTensorTerm_New(  ISOVISCOUSSTRESSTENSORTERM_DEFARGS  )
+{
+	IsoviscousStressTensorTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(IsoviscousStressTensorTerm) );
+	self = (IsoviscousStressTensorTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _IsoviscousStressTensorTerm_Init( void* matrixTerm, double viscosity ) {
+	IsoviscousStressTensorTerm* self = (IsoviscousStressTensorTerm*)matrixTerm;
+	self->viscosity = viscosity;
+}
+
+void _IsoviscousStressTensorTerm_Delete( void* matrixTerm ) {
+	IsoviscousStressTensorTerm* self = (IsoviscousStressTensorTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Delete( self );
+}
+
+void _IsoviscousStressTensorTerm_Print( void* matrixTerm, Stream* stream ) {
+	IsoviscousStressTensorTerm* self = (IsoviscousStressTensorTerm*)matrixTerm;
+	
+	_StiffnessMatrixTerm_Print( self, stream );
+
+	/* General info */
+	Journal_PrintValue( stream, self->viscosity );
+}
+
+void* _IsoviscousStressTensorTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(IsoviscousStressTensorTerm);
+	Type                                                         type = IsoviscousStressTensorTerm_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _IsoviscousStressTensorTerm_Delete;
+	Stg_Class_PrintFunction*                                   _print = _IsoviscousStressTensorTerm_Print;
+	Stg_Class_CopyFunction*                                     _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _IsoviscousStressTensorTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _IsoviscousStressTensorTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _IsoviscousStressTensorTerm_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _IsoviscousStressTensorTerm_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _IsoviscousStressTensorTerm_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _IsoviscousStressTensorTerm_Destroy;
+	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _IsoviscousStressTensorTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_IsoviscousStressTensorTerm_New(  ISOVISCOUSSTRESSTENSORTERM_PASSARGS  );
+}
+
+void _IsoviscousStressTensorTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
+	IsoviscousStressTensorTerm*            self             = (IsoviscousStressTensorTerm*)matrixTerm;
+
+	/* Construct Parent */
+	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
+
+	_IsoviscousStressTensorTerm_Init( self, Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"viscosity", 1.0 )  );
+}
+
+void _IsoviscousStressTensorTerm_Build( void* matrixTerm, void* data ) {
+	IsoviscousStressTensorTerm*             self             = (IsoviscousStressTensorTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Build( self, data );
+}
+
+void _IsoviscousStressTensorTerm_Initialise( void* matrixTerm, void* data ) {
+	IsoviscousStressTensorTerm*             self             = (IsoviscousStressTensorTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Initialise( self, data );
+}
+
+void _IsoviscousStressTensorTerm_Execute( void* matrixTerm, void* data ) {
+	_StiffnessMatrixTerm_Execute( matrixTerm, data );
+}
+
+void _IsoviscousStressTensorTerm_Destroy( void* matrixTerm, void* data ) {
+	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
+}
+
+
+void _IsoviscousStressTensorTerm_AssembleElement( 
+		void*                                              matrixTerm,
+		StiffnessMatrix*                                   stiffnessMatrix, 
+		Element_LocalIndex                                 lElement_I, 
+		SystemLinearEquations*                             sle,
+		FiniteElementContext*                              context,
+		double**                                           elStiffMat ) 
+{
+	IsoviscousStressTensorTerm*         self         = Stg_CheckType( matrixTerm, IsoviscousStressTensorTerm );
+	Swarm*                              swarm        = self->integrationSwarm;
+	FeVariable*                         variable1    = stiffnessMatrix->rowVariable;
+	Dimension_Index                     dim          = stiffnessMatrix->dim;
+	
+	IntegrationPoint*                   currIntegrationPoint;
+	double*                             xi;
+	double                              weight;
+	Particle_InCellIndex                cParticle_I, cellParticleCount;
+	Index                               nodesPerEl;
+	Node_ElementLocalIndex              rowNode_I;
+	Node_ElementLocalIndex              colNode_I;
+	double**                            GNx;
+	double                              detJac;
+	double                              visc           = self->viscosity;
+	
+	Cell_Index                          cell_I;
+	ElementType*                        elementType;
+	int                                 nodalDofs;
+	Dof_Index                           diagDof_I;
+	Dof_Index                           rowDof_I;
+	Dof_Index                           colDof_I;
+	Dof_Index                           d;
+	Dof_Index                           dofsPerNode;
+	Index                               rowIndex;
+	Index                               colIndex;
+	
+	/* Set the element type */
+	elementType = FeMesh_GetElementType( variable1->feMesh, lElement_I );
+	nodesPerEl = elementType->nodeCount;
+
+	/* assumes constant number of dofs per element */
+	nodalDofs = nodesPerEl * dim;
+	dofsPerNode = dim;
+	
+	if( nodesPerEl > self->max_nElNodes ) {
+		/* reallocate */
+		self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl );
+		self->max_nElNodes = nodesPerEl;
+	}
+	GNx = self->GNx;
+
+	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
+	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+	
+	for( cParticle_I=0; cParticle_I < cellParticleCount; cParticle_I++ ) {
+		
+		currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
+		xi = currIntegrationPoint->xi;
+		weight = currIntegrationPoint->weight;
+		
+		ElementType_ShapeFunctionsGlobalDerivs( 
+			elementType,
+			variable1->feMesh, lElement_I,
+			xi, dim, &detJac, GNx );
+		
+		/* Initially just build the diagonal (from a Dof perspective) entries */
+		for( rowNode_I=0; rowNode_I < nodesPerEl; rowNode_I++ ) { 		
+			for( colNode_I=0; colNode_I < nodesPerEl; colNode_I++ ) {		
+				for( diagDof_I=0; diagDof_I < dofsPerNode; diagDof_I++ ) {	
+					rowIndex =  rowNode_I*dofsPerNode + diagDof_I;
+					colIndex = colNode_I*dofsPerNode + diagDof_I;
+					elStiffMat[rowIndex][colIndex] +=
+						detJac * visc * weight * ( GNx[diagDof_I][rowNode_I] * GNx[diagDof_I][colNode_I] );
+					for( d=0; d<dofsPerNode; d++ ) {	
+						elStiffMat[rowIndex][colIndex] +=
+							detJac * visc * weight * ( GNx[d][rowNode_I] * GNx[d][colNode_I] );
+					}
+				}
+			}
+		}
+		
+		/* then build one set of the off diagonal blocks of K, and copy to the other off diags using symmetry */
+		for( rowNode_I=0; rowNode_I < nodesPerEl; rowNode_I++ ) {
+                  for( rowDof_I=0; rowDof_I < dofsPerNode-1; rowDof_I++ ) {	/* dont need to do anything in last row */
+				for( colNode_I=0; colNode_I < nodesPerEl; colNode_I++ ) {
+					for( colDof_I=rowDof_I+1; colDof_I < dofsPerNode; colDof_I++ ) {
+						rowIndex = rowNode_I*dofsPerNode + rowDof_I;
+						colIndex = colNode_I*dofsPerNode + colDof_I;
+						elStiffMat[rowIndex][colIndex] += detJac * visc * weight * 
+								( GNx[colDof_I][rowNode_I] * GNx[rowDof_I][colNode_I] );
+						/* symmetry	*/
+						elStiffMat[colIndex][rowIndex] = elStiffMat[rowIndex][colIndex];
+					}
+				}
+			}
+		}
+	}
+	
+	return;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/LaplacianStiffnessMatrixTerm.c
--- a/Assembly/src/LaplacianStiffnessMatrixTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LaplacianStiffnessMatrixTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "types.h"
-#include "LaplacianStiffnessMatrixTerm.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type LaplacianStiffnessMatrixTerm_Type = "LaplacianStiffnessMatrixTerm";
-
-LaplacianStiffnessMatrixTerm* LaplacianStiffnessMatrixTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	StiffnessMatrix*			stiffnessMatrix,
-	Swarm*						integrationSwarm )
-{
-	LaplacianStiffnessMatrixTerm* self = (LaplacianStiffnessMatrixTerm*) _LaplacianStiffnessMatrixTerm_DefaultNew( name );
-
-	self->isConstructed = False;	
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
-	_LaplacianStiffnessMatrixTerm_Init( self );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-LaplacianStiffnessMatrixTerm* _LaplacianStiffnessMatrixTerm_New(  LAPLACIANSTIFFNESSMATRIXTERM_DEFARGS  )
-{
-	LaplacianStiffnessMatrixTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(LaplacianStiffnessMatrixTerm) );
-	self = (LaplacianStiffnessMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _LaplacianStiffnessMatrixTerm_Init( void* matrixTerm ) {
-}
-
-void _LaplacianStiffnessMatrixTerm_Delete( void* matrixTerm ) {
-	LaplacianStiffnessMatrixTerm* self = (LaplacianStiffnessMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Delete( self );
-}
-
-void _LaplacianStiffnessMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
-	LaplacianStiffnessMatrixTerm* self = (LaplacianStiffnessMatrixTerm*)matrixTerm;
-	
-	_StiffnessMatrixTerm_Print( self, stream );
-
-	/* General info */
-}
-
-void* _LaplacianStiffnessMatrixTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(LaplacianStiffnessMatrixTerm);
-	Type                                                         type = LaplacianStiffnessMatrixTerm_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _LaplacianStiffnessMatrixTerm_Delete;
-	Stg_Class_PrintFunction*                                   _print = _LaplacianStiffnessMatrixTerm_Print;
-	Stg_Class_CopyFunction*                                     _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _LaplacianStiffnessMatrixTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _LaplacianStiffnessMatrixTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _LaplacianStiffnessMatrixTerm_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _LaplacianStiffnessMatrixTerm_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _LaplacianStiffnessMatrixTerm_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _LaplacianStiffnessMatrixTerm_Destroy;
-	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _LaplacianStiffnessMatrixTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_LaplacianStiffnessMatrixTerm_New(  LAPLACIANSTIFFNESSMATRIXTERM_PASSARGS  );
-}
-
-void _LaplacianStiffnessMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
-	LaplacianStiffnessMatrixTerm*            self             = (LaplacianStiffnessMatrixTerm*)matrixTerm;
-
-	/* Construct Parent */
-	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
-
-	_LaplacianStiffnessMatrixTerm_Init( self );
-}
-
-void _LaplacianStiffnessMatrixTerm_Build( void* matrixTerm, void* data ) {
-	LaplacianStiffnessMatrixTerm*             self             = (LaplacianStiffnessMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Build( self, data );
-}
-
-void _LaplacianStiffnessMatrixTerm_Initialise( void* matrixTerm, void* data ) {
-	LaplacianStiffnessMatrixTerm*             self             = (LaplacianStiffnessMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Initialise( self, data );
-}
-
-void _LaplacianStiffnessMatrixTerm_Execute( void* matrixTerm, void* data ) {
-	_StiffnessMatrixTerm_Execute( matrixTerm, data );
-}
-
-void _LaplacianStiffnessMatrixTerm_Destroy( void* matrixTerm, void* data ) {
-	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
-}
-
-void _LaplacianStiffnessMatrixTerm_AssembleElement( 
-		void*                                              matrixTerm,
-		StiffnessMatrix*                                   stiffnessMatrix, 
-		Element_LocalIndex                                 lElement_I, 
-		SystemLinearEquations*                             sle,
-		FiniteElementContext*                              context,
-		double**                                           elStiffMat ) 
-{
-	LaplacianStiffnessMatrixTerm*       self         = Stg_CheckType( matrixTerm, LaplacianStiffnessMatrixTerm );
-	Swarm*                              swarm        = self->integrationSwarm;
-	FeVariable*                         variable1    = stiffnessMatrix->rowVariable;
-	Dimension_Index                     dim          = stiffnessMatrix->dim;
-	IntegrationPoint*                   currIntegrationPoint;
-	double*                             xi;
-	double                              weight;
-	Particle_InCellIndex                cParticle_I, cellParticleCount;
-	Index                               nodesPerEl;
-	Index                               i,j;
-	Dimension_Index                     dim_I;
-	double**                            GNx;
-	double                              detJac;
-	
-	Cell_Index                          cell_I;
-	ElementType*                        elementType;
-	
-	/* Set the element type */
-	elementType = FeMesh_GetElementType( variable1->feMesh, lElement_I );
-	nodesPerEl = elementType->nodeCount;
-	
-	if( nodesPerEl > self->max_nElNodes ) {
-		/* reallocate */
-		self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl );
-		self->max_nElNodes = nodesPerEl;
-	}
-	GNx = self->GNx;
-	
-	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
-	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-
-	/* Slap the laplacian together */
-	for( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
-		
-		currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
-
-		xi = currIntegrationPoint->xi;
-		weight = currIntegrationPoint->weight;
-		
-		ElementType_ShapeFunctionsGlobalDerivs( 
-			elementType,
-			variable1->feMesh, lElement_I,
-			xi, dim, &detJac, GNx );
-			
-		for( i=0; i<nodesPerEl; i++ ) {
-			for( j=0; j<nodesPerEl; j++ ) {
-				for ( dim_I = 0; dim_I < dim ; dim_I++ ) { 
-					elStiffMat[i][j] += detJac * weight * GNx[dim_I][i] * GNx[dim_I][j];
-				}
-			}
-		}
-	}
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/LaplacianStiffnessMatrixTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/LaplacianStiffnessMatrixTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,216 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LaplacianStiffnessMatrixTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "types.h"
+#include "LaplacianStiffnessMatrixTerm.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type LaplacianStiffnessMatrixTerm_Type = "LaplacianStiffnessMatrixTerm";
+
+LaplacianStiffnessMatrixTerm* LaplacianStiffnessMatrixTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	StiffnessMatrix*			stiffnessMatrix,
+	Swarm*						integrationSwarm )
+{
+	LaplacianStiffnessMatrixTerm* self = (LaplacianStiffnessMatrixTerm*) _LaplacianStiffnessMatrixTerm_DefaultNew( name );
+
+	self->isConstructed = False;	
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
+	_LaplacianStiffnessMatrixTerm_Init( self );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+LaplacianStiffnessMatrixTerm* _LaplacianStiffnessMatrixTerm_New(  LAPLACIANSTIFFNESSMATRIXTERM_DEFARGS  )
+{
+	LaplacianStiffnessMatrixTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(LaplacianStiffnessMatrixTerm) );
+	self = (LaplacianStiffnessMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _LaplacianStiffnessMatrixTerm_Init( void* matrixTerm ) {
+}
+
+void _LaplacianStiffnessMatrixTerm_Delete( void* matrixTerm ) {
+	LaplacianStiffnessMatrixTerm* self = (LaplacianStiffnessMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Delete( self );
+}
+
+void _LaplacianStiffnessMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
+	LaplacianStiffnessMatrixTerm* self = (LaplacianStiffnessMatrixTerm*)matrixTerm;
+	
+	_StiffnessMatrixTerm_Print( self, stream );
+
+	/* General info */
+}
+
+void* _LaplacianStiffnessMatrixTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(LaplacianStiffnessMatrixTerm);
+	Type                                                         type = LaplacianStiffnessMatrixTerm_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _LaplacianStiffnessMatrixTerm_Delete;
+	Stg_Class_PrintFunction*                                   _print = _LaplacianStiffnessMatrixTerm_Print;
+	Stg_Class_CopyFunction*                                     _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _LaplacianStiffnessMatrixTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _LaplacianStiffnessMatrixTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _LaplacianStiffnessMatrixTerm_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _LaplacianStiffnessMatrixTerm_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _LaplacianStiffnessMatrixTerm_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _LaplacianStiffnessMatrixTerm_Destroy;
+	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _LaplacianStiffnessMatrixTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_LaplacianStiffnessMatrixTerm_New(  LAPLACIANSTIFFNESSMATRIXTERM_PASSARGS  );
+}
+
+void _LaplacianStiffnessMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
+	LaplacianStiffnessMatrixTerm*            self             = (LaplacianStiffnessMatrixTerm*)matrixTerm;
+
+	/* Construct Parent */
+	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
+
+	_LaplacianStiffnessMatrixTerm_Init( self );
+}
+
+void _LaplacianStiffnessMatrixTerm_Build( void* matrixTerm, void* data ) {
+	LaplacianStiffnessMatrixTerm*             self             = (LaplacianStiffnessMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Build( self, data );
+}
+
+void _LaplacianStiffnessMatrixTerm_Initialise( void* matrixTerm, void* data ) {
+	LaplacianStiffnessMatrixTerm*             self             = (LaplacianStiffnessMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Initialise( self, data );
+}
+
+void _LaplacianStiffnessMatrixTerm_Execute( void* matrixTerm, void* data ) {
+	_StiffnessMatrixTerm_Execute( matrixTerm, data );
+}
+
+void _LaplacianStiffnessMatrixTerm_Destroy( void* matrixTerm, void* data ) {
+	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
+}
+
+void _LaplacianStiffnessMatrixTerm_AssembleElement( 
+		void*                                              matrixTerm,
+		StiffnessMatrix*                                   stiffnessMatrix, 
+		Element_LocalIndex                                 lElement_I, 
+		SystemLinearEquations*                             sle,
+		FiniteElementContext*                              context,
+		double**                                           elStiffMat ) 
+{
+	LaplacianStiffnessMatrixTerm*       self         = Stg_CheckType( matrixTerm, LaplacianStiffnessMatrixTerm );
+	Swarm*                              swarm        = self->integrationSwarm;
+	FeVariable*                         variable1    = stiffnessMatrix->rowVariable;
+	Dimension_Index                     dim          = stiffnessMatrix->dim;
+	IntegrationPoint*                   currIntegrationPoint;
+	double*                             xi;
+	double                              weight;
+	Particle_InCellIndex                cParticle_I, cellParticleCount;
+	Index                               nodesPerEl;
+	Index                               i,j;
+	Dimension_Index                     dim_I;
+	double**                            GNx;
+	double                              detJac;
+	
+	Cell_Index                          cell_I;
+	ElementType*                        elementType;
+	
+	/* Set the element type */
+	elementType = FeMesh_GetElementType( variable1->feMesh, lElement_I );
+	nodesPerEl = elementType->nodeCount;
+	
+	if( nodesPerEl > self->max_nElNodes ) {
+		/* reallocate */
+		self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl );
+		self->max_nElNodes = nodesPerEl;
+	}
+	GNx = self->GNx;
+	
+	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
+	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+
+	/* Slap the laplacian together */
+	for( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
+		
+		currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
+
+		xi = currIntegrationPoint->xi;
+		weight = currIntegrationPoint->weight;
+		
+		ElementType_ShapeFunctionsGlobalDerivs( 
+			elementType,
+			variable1->feMesh, lElement_I,
+			xi, dim, &detJac, GNx );
+			
+		for( i=0; i<nodesPerEl; i++ ) {
+			for( j=0; j<nodesPerEl; j++ ) {
+				for ( dim_I = 0; dim_I < dim ; dim_I++ ) { 
+					elStiffMat[i][j] += detJac * weight * GNx[dim_I][i] * GNx[dim_I][j];
+				}
+			}
+		}
+	}
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/MassMatrixTerm.c
--- a/Assembly/src/MassMatrixTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,233 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: MassMatrixTerm.c 822 2007-04-27 06:20:35Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <assert.h>
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "types.h"
-#include "MassMatrixTerm.h"
-
-/* Textual name of this class */
-const Type MassMatrixTerm_Type = "MassMatrixTerm";
-
-MassMatrixTerm* MassMatrixTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	StiffnessMatrix*			stiffnessMatrix,
-	Swarm*						integrationSwarm,
-	FeVariable*					field )
-{
-    MassMatrixTerm* self = (MassMatrixTerm*) _MassMatrixTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
-	_MassMatrixTerm_Init( self, field );
-
-    return self;
-}
-
-/* Creation implementation / Virtual constructor */
-MassMatrixTerm* _MassMatrixTerm_New(  MASSMATRIXTERM_DEFARGS  )
-{
-    MassMatrixTerm* self;
-	
-    /* Allocate memory */
-    assert( _sizeOfSelf >= sizeof(MassMatrixTerm) );
-    self = (MassMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
-	
-    /* Virtual info */
-	
-    return self;
-}
-
-void _MassMatrixTerm_Init( void* matrixTerm, FeVariable* field ) {
-    MassMatrixTerm* self = (MassMatrixTerm*)matrixTerm;
-
-    self->field = field;
-}
-
-void _MassMatrixTerm_Delete( void* matrixTerm ) {
-    MassMatrixTerm* self = (MassMatrixTerm*)matrixTerm;
-
-    _StiffnessMatrixTerm_Delete( self );
-}
-
-void _MassMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
-    MassMatrixTerm* self = (MassMatrixTerm*)matrixTerm;
-	
-    _StiffnessMatrixTerm_Print( self, stream );
-
-    /* General info */
-    Journal_PrintPointer( stream, self->field );
-}
-
-void* _MassMatrixTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(MassMatrixTerm);
-	Type                                                         type = MassMatrixTerm_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _MassMatrixTerm_Delete;
-	Stg_Class_PrintFunction*                                   _print = _MassMatrixTerm_Print;
-	Stg_Class_CopyFunction*                                     _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _MassMatrixTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _MassMatrixTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _MassMatrixTerm_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _MassMatrixTerm_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _MassMatrixTerm_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _MassMatrixTerm_Destroy;
-	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _MassMatrixTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-    return (void*)_MassMatrixTerm_New(  MASSMATRIXTERM_PASSARGS  );
-}
-
-void _MassMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
-    MassMatrixTerm*            self             = (MassMatrixTerm*)matrixTerm;
-    FeVariable*                field;
-
-    /* Construct Parent */
-    _StiffnessMatrixTerm_AssignFromXML( self, cf, data );
-
-    field = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"field", FeVariable, True, data  ) ;
-
-    _MassMatrixTerm_Init( self, field );
-}
-
-void _MassMatrixTerm_Build( void* matrixTerm, void* data ) {
-    MassMatrixTerm*             self             = (MassMatrixTerm*)matrixTerm;
-
-    _StiffnessMatrixTerm_Build( self, data );
-    Stg_Component_Build( self->field, data, False );
-}
-
-void _MassMatrixTerm_Initialise( void* matrixTerm, void* data ) {
-    MassMatrixTerm*             self             = (MassMatrixTerm*)matrixTerm;
-
-    _StiffnessMatrixTerm_Initialise( self, data );
-    Stg_Component_Initialise( self->field, data, False );
-}
-
-void _MassMatrixTerm_Execute( void* matrixTerm, void* data ) {
-    _StiffnessMatrixTerm_Execute( matrixTerm, data );
-}
-
-void _MassMatrixTerm_Destroy( void* matrixTerm, void* data ) {
-   MassMatrixTerm* self = (MassMatrixTerm*)matrixTerm;
-
-   Stg_Component_Destroy( self->field, data, False );
-   _StiffnessMatrixTerm_Destroy( matrixTerm, data );
-}
-
-
-void _MassMatrixTerm_AssembleElement(
-	void*							matrixTerm,
-	StiffnessMatrix*			stiffMat, 
-	Element_LocalIndex		lElement_I, 
-	SystemLinearEquations*	sle, 
-	FiniteElementContext*	context, 
-	double**						elStiffMat )
-{
-	MassMatrixTerm*       self         = Stg_CheckType( matrixTerm, MassMatrixTerm );
-	StiffnessMatrix			*stiffnessMatrix = self->stiffnessMatrix;
-	Swarm*                              swarm        = self->integrationSwarm;
-	FeVariable*                         variable1    = stiffnessMatrix->rowVariable;
-	Dimension_Index                     dim          = stiffnessMatrix->dim;
-	int num_node_dofs = self->field->fieldComponentCount;
-	IntegrationPoint*                   currIntegrationPoint;
-	double*                             xi;
-	double                              weight;
-    Particle_InCellIndex                cParticle_I, cellParticleCount;
-    Index                               nodesPerEl;
-    Index                               i,j, k;
-    double**                            GNx, *N;
-    double                              detJac;
-	
-    Cell_Index                          cell_I;
-    ElementType*                        elementType;
-	
-    /* Set the element type */
-    elementType = FeMesh_GetElementType( variable1->feMesh, lElement_I );
-    nodesPerEl = elementType->nodeCount;
-	
-    if( nodesPerEl > self->max_nElNodes ) {
-	/* reallocate */
-	self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl );
-	self->N = ReallocArray( self->N, double, nodesPerEl );
-	self->max_nElNodes = nodesPerEl;
-    }
-    GNx = self->GNx;
-    N = self->N;
-
-    cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
-    cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-
-    /* Slap the laplacian together */
-    for( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
-
-	currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
-
-	xi = currIntegrationPoint->xi;
-	weight = currIntegrationPoint->weight;
-
-	ElementType_ShapeFunctionsGlobalDerivs( 
-	    elementType,
-	    variable1->feMesh, lElement_I,
-	    xi, dim, &detJac, GNx );
-
-	ElementType_EvaluateShapeFunctionsAt( elementType, xi, N );
-
-	for( i=0; i<nodesPerEl; i++ ) {
-	    for( j=0; j<nodesPerEl; j++ ) {
-		for( k = 0; k < num_node_dofs; k++)
-		    elStiffMat[num_node_dofs*i + k][num_node_dofs*j + k] += detJac * weight * N[i] * N[j];
-	    }
-	}
-    }
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/MassMatrixTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/MassMatrixTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,233 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: MassMatrixTerm.c 822 2007-04-27 06:20:35Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <assert.h>
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "types.h"
+#include "MassMatrixTerm.h"
+
+/* Textual name of this class */
+const Type MassMatrixTerm_Type = "MassMatrixTerm";
+
+MassMatrixTerm* MassMatrixTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	StiffnessMatrix*			stiffnessMatrix,
+	Swarm*						integrationSwarm,
+	FeVariable*					field )
+{
+    MassMatrixTerm* self = (MassMatrixTerm*) _MassMatrixTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
+	_MassMatrixTerm_Init( self, field );
+
+    return self;
+}
+
+/* Creation implementation / Virtual constructor */
+MassMatrixTerm* _MassMatrixTerm_New(  MASSMATRIXTERM_DEFARGS  )
+{
+    MassMatrixTerm* self;
+	
+    /* Allocate memory */
+    assert( _sizeOfSelf >= sizeof(MassMatrixTerm) );
+    self = (MassMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
+	
+    /* Virtual info */
+	
+    return self;
+}
+
+void _MassMatrixTerm_Init( void* matrixTerm, FeVariable* field ) {
+    MassMatrixTerm* self = (MassMatrixTerm*)matrixTerm;
+
+    self->field = field;
+}
+
+void _MassMatrixTerm_Delete( void* matrixTerm ) {
+    MassMatrixTerm* self = (MassMatrixTerm*)matrixTerm;
+
+    _StiffnessMatrixTerm_Delete( self );
+}
+
+void _MassMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
+    MassMatrixTerm* self = (MassMatrixTerm*)matrixTerm;
+	
+    _StiffnessMatrixTerm_Print( self, stream );
+
+    /* General info */
+    Journal_PrintPointer( stream, self->field );
+}
+
+void* _MassMatrixTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(MassMatrixTerm);
+	Type                                                         type = MassMatrixTerm_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _MassMatrixTerm_Delete;
+	Stg_Class_PrintFunction*                                   _print = _MassMatrixTerm_Print;
+	Stg_Class_CopyFunction*                                     _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _MassMatrixTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _MassMatrixTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _MassMatrixTerm_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _MassMatrixTerm_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _MassMatrixTerm_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _MassMatrixTerm_Destroy;
+	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _MassMatrixTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+    return (void*)_MassMatrixTerm_New(  MASSMATRIXTERM_PASSARGS  );
+}
+
+void _MassMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
+    MassMatrixTerm*            self             = (MassMatrixTerm*)matrixTerm;
+    FeVariable*                field;
+
+    /* Construct Parent */
+    _StiffnessMatrixTerm_AssignFromXML( self, cf, data );
+
+    field = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"field", FeVariable, True, data  ) ;
+
+    _MassMatrixTerm_Init( self, field );
+}
+
+void _MassMatrixTerm_Build( void* matrixTerm, void* data ) {
+    MassMatrixTerm*             self             = (MassMatrixTerm*)matrixTerm;
+
+    _StiffnessMatrixTerm_Build( self, data );
+    Stg_Component_Build( self->field, data, False );
+}
+
+void _MassMatrixTerm_Initialise( void* matrixTerm, void* data ) {
+    MassMatrixTerm*             self             = (MassMatrixTerm*)matrixTerm;
+
+    _StiffnessMatrixTerm_Initialise( self, data );
+    Stg_Component_Initialise( self->field, data, False );
+}
+
+void _MassMatrixTerm_Execute( void* matrixTerm, void* data ) {
+    _StiffnessMatrixTerm_Execute( matrixTerm, data );
+}
+
+void _MassMatrixTerm_Destroy( void* matrixTerm, void* data ) {
+   MassMatrixTerm* self = (MassMatrixTerm*)matrixTerm;
+
+   Stg_Component_Destroy( self->field, data, False );
+   _StiffnessMatrixTerm_Destroy( matrixTerm, data );
+}
+
+
+void _MassMatrixTerm_AssembleElement(
+	void*							matrixTerm,
+	StiffnessMatrix*			stiffMat, 
+	Element_LocalIndex		lElement_I, 
+	SystemLinearEquations*	sle, 
+	FiniteElementContext*	context, 
+	double**						elStiffMat )
+{
+	MassMatrixTerm*       self         = Stg_CheckType( matrixTerm, MassMatrixTerm );
+	StiffnessMatrix			*stiffnessMatrix = self->stiffnessMatrix;
+	Swarm*                              swarm        = self->integrationSwarm;
+	FeVariable*                         variable1    = stiffnessMatrix->rowVariable;
+	Dimension_Index                     dim          = stiffnessMatrix->dim;
+	int num_node_dofs = self->field->fieldComponentCount;
+	IntegrationPoint*                   currIntegrationPoint;
+	double*                             xi;
+	double                              weight;
+    Particle_InCellIndex                cParticle_I, cellParticleCount;
+    Index                               nodesPerEl;
+    Index                               i,j, k;
+    double**                            GNx, *N;
+    double                              detJac;
+	
+    Cell_Index                          cell_I;
+    ElementType*                        elementType;
+	
+    /* Set the element type */
+    elementType = FeMesh_GetElementType( variable1->feMesh, lElement_I );
+    nodesPerEl = elementType->nodeCount;
+	
+    if( nodesPerEl > self->max_nElNodes ) {
+	/* reallocate */
+	self->GNx = ReallocArray2D( self->GNx, double, dim, nodesPerEl );
+	self->N = ReallocArray( self->N, double, nodesPerEl );
+	self->max_nElNodes = nodesPerEl;
+    }
+    GNx = self->GNx;
+    N = self->N;
+
+    cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
+    cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+
+    /* Slap the laplacian together */
+    for( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
+
+	currIntegrationPoint = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
+
+	xi = currIntegrationPoint->xi;
+	weight = currIntegrationPoint->weight;
+
+	ElementType_ShapeFunctionsGlobalDerivs( 
+	    elementType,
+	    variable1->feMesh, lElement_I,
+	    xi, dim, &detJac, GNx );
+
+	ElementType_EvaluateShapeFunctionsAt( elementType, xi, N );
+
+	for( i=0; i<nodesPerEl; i++ ) {
+	    for( j=0; j<nodesPerEl; j++ ) {
+		for( k = 0; k < num_node_dofs; k++)
+		    elStiffMat[num_node_dofs*i + k][num_node_dofs*j + k] += detJac * weight * N[i] * N[j];
+	    }
+	}
+    }
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/PressureGradForceTerm.c
--- a/Assembly/src/PressureGradForceTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: PressureGradForceTerm.c 822 2007-04-27 06:20:35Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <assert.h>
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "types.h"
-#include "PressureGradForceTerm.h"
-
-/* Textual name of this class */
-const Type PressureGradForceTerm_Type = "PressureGradForceTerm";
-
-PressureGradForceTerm* PressureGradForceTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	ForceVector*				forceVector,
-	Swarm*						integrationSwarm,
-	FeVariable*					gradField, 
-	FeVariable*					pressureField )
-{
-	PressureGradForceTerm* self = (PressureGradForceTerm*) _PressureGradForceTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ForceTerm_Init( self, context, forceVector, integrationSwarm, NULL );
-	_PressureGradForceTerm_Init( self, pressureField, gradField );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-PressureGradForceTerm* _PressureGradForceTerm_New(  PRESSUREGRADFORCETERM_DEFARGS  )
-{
-	PressureGradForceTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(PressureGradForceTerm) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (PressureGradForceTerm*) _ForceTerm_New(  FORCETERM_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _PressureGradForceTerm_Init( void* forceTerm, FeVariable* pressureField, FeVariable* gradField ) {
-	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
-
-	self->asmb = Assembler_New();
-	Assembler_SetCallbacks( self->asmb, 
-		NULL, 
-		NULL, 
-		(Assembler_CallbackType*)PressureGradForceTerm_RowCB, 
-		(Assembler_CallbackType*)PressureGradForceTerm_ColCB, 
-		(Assembler_CallbackType*)PressureGradForceTerm_ColCB, 
-		self );
-	self->pressureField = pressureField;
-	self->gradField = gradField;
-	self->forceVector = NULL;
-	self->elForceVec = NULL;
-	self->factor = 0.0;
-}
-
-void _PressureGradForceTerm_Delete( void* forceTerm ) {
-	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
-
-	_ForceTerm_Delete( self );
-}
-
-void _PressureGradForceTerm_Print( void* forceTerm, Stream* stream ) {
-	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
-	
-	_ForceTerm_Print( self, stream );
-
-	/* General info */
-	Journal_PrintPointer( stream, self->pressureField );
-}
-
-void* _PressureGradForceTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(PressureGradForceTerm);
-	Type                                                      type = PressureGradForceTerm_Type;
-	Stg_Class_DeleteFunction*                              _delete = _PressureGradForceTerm_Delete;
-	Stg_Class_PrintFunction*                                _print = _PressureGradForceTerm_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _PressureGradForceTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _PressureGradForceTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _PressureGradForceTerm_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _PressureGradForceTerm_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _PressureGradForceTerm_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _PressureGradForceTerm_Destroy;
-	ForceTerm_AssembleElementFunction*            _assembleElement = _PressureGradForceTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_PressureGradForceTerm_New(  PRESSUREGRADFORCETERM_PASSARGS  );
-}
-
-void _PressureGradForceTerm_AssignFromXML( void* forceTerm, Stg_ComponentFactory* cf, void* data ) {
-	PressureGradForceTerm*	self = (PressureGradForceTerm*)forceTerm;
-
-	/* Construct Parent */
-	_ForceTerm_AssignFromXML( self, cf, data );
-
-	_PressureGradForceTerm_Init(
-		self, 
-		Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PressureField", FeVariable, True, data  ),
-		Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PressureGradField", FeVariable, True, data )  );
-}
-
-void _PressureGradForceTerm_Build( void* forceTerm, void* data ) {
-	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
-
-	_ForceTerm_Build( self, data );
-	Stg_Component_Build( self->pressureField, data, False );
-	Stg_Component_Build( self->gradField, data, False );
-	Assembler_SetVariables( self->asmb, self->gradField, self->pressureField );
-	Assembler_SetIntegrationSwarm( self->asmb, self->integrationSwarm );
-}
-
-void _PressureGradForceTerm_Initialise( void* forceTerm, void* data ) {
-	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
-
-	Stg_Component_Initialise( self->pressureField, data, False );
-	Stg_Component_Initialise( self->gradField, data, False );
-	_ForceTerm_Initialise( self, data );
-}
-
-void _PressureGradForceTerm_Execute( void* forceTerm, void* data ) {
-	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
-
-	_ForceTerm_Execute( self, data );
-}
-
-void _PressureGradForceTerm_Destroy( void* forceTerm, void* data ) {
-	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
-
-	Stg_Component_Destroy( self->pressureField, data, False );
-	Stg_Component_Destroy( self->gradField, data, False );
-	_ForceTerm_Destroy( self, data );
-}
-
-
-void _PressureGradForceTerm_AssembleElement( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elForceVec ) {
-	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
-
-	assert( self );
-
-	self->forceVector = forceVector;
-	self->elForceVec = elForceVec;
-	Assembler_IntegrateMatrixElement( self->asmb, lElement_I );
-}
-
-Bool PressureGradForceTerm_RowCB( PressureGradForceTerm* self, Assembler* assm ) {
-	self->factor = assm->particle->weight * assm->detJac;
-	return True;
-}
-
-Bool PressureGradForceTerm_ColCB( PressureGradForceTerm* self, Assembler* assm ) {
-	double val;
-
-	FeVariable_GetValueAtNode( self->pressureField, assm->colNodeInd, &val );
-	self->elForceVec[assm->rowInd] += 
-		val * 
-		assm->shapeFuncs[assm->rowElNodeInd] * 
-		assm->globalDerivs[assm->rowDofInd][assm->colElNodeInd] * 
-		self->factor;
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/PressureGradForceTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/PressureGradForceTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,219 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: PressureGradForceTerm.c 822 2007-04-27 06:20:35Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <assert.h>
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "types.h"
+#include "PressureGradForceTerm.h"
+
+/* Textual name of this class */
+const Type PressureGradForceTerm_Type = "PressureGradForceTerm";
+
+PressureGradForceTerm* PressureGradForceTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	ForceVector*				forceVector,
+	Swarm*						integrationSwarm,
+	FeVariable*					gradField, 
+	FeVariable*					pressureField )
+{
+	PressureGradForceTerm* self = (PressureGradForceTerm*) _PressureGradForceTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ForceTerm_Init( self, context, forceVector, integrationSwarm, NULL );
+	_PressureGradForceTerm_Init( self, pressureField, gradField );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+PressureGradForceTerm* _PressureGradForceTerm_New(  PRESSUREGRADFORCETERM_DEFARGS  )
+{
+	PressureGradForceTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(PressureGradForceTerm) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (PressureGradForceTerm*) _ForceTerm_New(  FORCETERM_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _PressureGradForceTerm_Init( void* forceTerm, FeVariable* pressureField, FeVariable* gradField ) {
+	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
+
+	self->asmb = Assembler_New();
+	Assembler_SetCallbacks( self->asmb, 
+		NULL, 
+		NULL, 
+		(Assembler_CallbackType*)PressureGradForceTerm_RowCB, 
+		(Assembler_CallbackType*)PressureGradForceTerm_ColCB, 
+		(Assembler_CallbackType*)PressureGradForceTerm_ColCB, 
+		self );
+	self->pressureField = pressureField;
+	self->gradField = gradField;
+	self->forceVector = NULL;
+	self->elForceVec = NULL;
+	self->factor = 0.0;
+}
+
+void _PressureGradForceTerm_Delete( void* forceTerm ) {
+	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
+
+	_ForceTerm_Delete( self );
+}
+
+void _PressureGradForceTerm_Print( void* forceTerm, Stream* stream ) {
+	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
+	
+	_ForceTerm_Print( self, stream );
+
+	/* General info */
+	Journal_PrintPointer( stream, self->pressureField );
+}
+
+void* _PressureGradForceTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(PressureGradForceTerm);
+	Type                                                      type = PressureGradForceTerm_Type;
+	Stg_Class_DeleteFunction*                              _delete = _PressureGradForceTerm_Delete;
+	Stg_Class_PrintFunction*                                _print = _PressureGradForceTerm_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _PressureGradForceTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _PressureGradForceTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _PressureGradForceTerm_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _PressureGradForceTerm_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _PressureGradForceTerm_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _PressureGradForceTerm_Destroy;
+	ForceTerm_AssembleElementFunction*            _assembleElement = _PressureGradForceTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_PressureGradForceTerm_New(  PRESSUREGRADFORCETERM_PASSARGS  );
+}
+
+void _PressureGradForceTerm_AssignFromXML( void* forceTerm, Stg_ComponentFactory* cf, void* data ) {
+	PressureGradForceTerm*	self = (PressureGradForceTerm*)forceTerm;
+
+	/* Construct Parent */
+	_ForceTerm_AssignFromXML( self, cf, data );
+
+	_PressureGradForceTerm_Init(
+		self, 
+		Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PressureField", FeVariable, True, data  ),
+		Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PressureGradField", FeVariable, True, data )  );
+}
+
+void _PressureGradForceTerm_Build( void* forceTerm, void* data ) {
+	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
+
+	_ForceTerm_Build( self, data );
+	Stg_Component_Build( self->pressureField, data, False );
+	Stg_Component_Build( self->gradField, data, False );
+	Assembler_SetVariables( self->asmb, self->gradField, self->pressureField );
+	Assembler_SetIntegrationSwarm( self->asmb, self->integrationSwarm );
+}
+
+void _PressureGradForceTerm_Initialise( void* forceTerm, void* data ) {
+	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
+
+	Stg_Component_Initialise( self->pressureField, data, False );
+	Stg_Component_Initialise( self->gradField, data, False );
+	_ForceTerm_Initialise( self, data );
+}
+
+void _PressureGradForceTerm_Execute( void* forceTerm, void* data ) {
+	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
+
+	_ForceTerm_Execute( self, data );
+}
+
+void _PressureGradForceTerm_Destroy( void* forceTerm, void* data ) {
+	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
+
+	Stg_Component_Destroy( self->pressureField, data, False );
+	Stg_Component_Destroy( self->gradField, data, False );
+	_ForceTerm_Destroy( self, data );
+}
+
+
+void _PressureGradForceTerm_AssembleElement( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elForceVec ) {
+	PressureGradForceTerm* self = (PressureGradForceTerm*)forceTerm;
+
+	assert( self );
+
+	self->forceVector = forceVector;
+	self->elForceVec = elForceVec;
+	Assembler_IntegrateMatrixElement( self->asmb, lElement_I );
+}
+
+Bool PressureGradForceTerm_RowCB( PressureGradForceTerm* self, Assembler* assm ) {
+	self->factor = assm->particle->weight * assm->detJac;
+	return True;
+}
+
+Bool PressureGradForceTerm_ColCB( PressureGradForceTerm* self, Assembler* assm ) {
+	double val;
+
+	FeVariable_GetValueAtNode( self->pressureField, assm->colNodeInd, &val );
+	self->elForceVec[assm->rowInd] += 
+		val * 
+		assm->shapeFuncs[assm->rowElNodeInd] * 
+		assm->globalDerivs[assm->rowDofInd][assm->colElNodeInd] * 
+		self->factor;
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/PressureGradMatrixTerm.c
--- a/Assembly/src/PressureGradMatrixTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: PressureGradMatrixTerm.c 822 2007-04-27 06:20:35Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <assert.h>
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "types.h"
-#include "PressureGradMatrixTerm.h"
-
-/* Textual name of this class */
-const Type PressureGradMatrixTerm_Type = "PressureGradMatrixTerm";
-
-PressureGradMatrixTerm* PressureGradMatrixTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	StiffnessMatrix*			stiffnessMatrix,
-	Swarm*						integrationSwarm,
-	FeVariable*					gradField )
-{
-	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*) _PressureGradMatrixTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
-	_PressureGradMatrixTerm_Init( self, gradField );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-PressureGradMatrixTerm* _PressureGradMatrixTerm_New(  PRESSUREGRADMATRIXTERM_DEFARGS  )
-{
-	PressureGradMatrixTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(PressureGradMatrixTerm) );
-	self = (PressureGradMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _PressureGradMatrixTerm_Init( void* matrixTerm, FeVariable* gradField ) {
-	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
-
-	self->assm = Assembler_New();
-	Assembler_SetCallbacks( self->assm, 
-		NULL, 
-		NULL, 
-		(Assembler_CallbackType*)PressureGradMatrixTerm_RowCB, 
-		(Assembler_CallbackType*)PressureGradMatrixTerm_ColCB, 
-		(Assembler_CallbackType*)PressureGradMatrixTerm_ColCB, 
-		self );
-	self->gradField = gradField;
-	self->stiffnessMatrix = NULL;
-	self->elStiffMat = NULL;
-	self->factor = 0.0;
-}
-
-void _PressureGradMatrixTerm_Delete( void* matrixTerm ) {
-	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Delete( self );
-}
-
-void _PressureGradMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
-	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
-	
-	_StiffnessMatrixTerm_Print( self, stream );
-
-	/* General info */
-	Journal_PrintPointer( stream, self->gradField );
-}
-
-void* _PressureGradMatrixTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(PressureGradMatrixTerm);
-	Type                                                         type = PressureGradMatrixTerm_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _PressureGradMatrixTerm_Delete;
-	Stg_Class_PrintFunction*                                   _print = _PressureGradMatrixTerm_Print;
-	Stg_Class_CopyFunction*                                     _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _PressureGradMatrixTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _PressureGradMatrixTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _PressureGradMatrixTerm_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _PressureGradMatrixTerm_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _PressureGradMatrixTerm_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _PressureGradMatrixTerm_Destroy;
-	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _PressureGradMatrixTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_PressureGradMatrixTerm_New(  PRESSUREGRADMATRIXTERM_PASSARGS  );
-}
-
-void _PressureGradMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
-	PressureGradMatrixTerm*	self = (PressureGradMatrixTerm*)matrixTerm;
-	FeVariable*					gradField;
-
-	/* Construct Parent */
-	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
-
-	gradField = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PressureGradField", FeVariable, True, data  ) ;
-
-	_PressureGradMatrixTerm_Init( self, gradField );
-}
-
-void _PressureGradMatrixTerm_Build( void* matrixTerm, void* data ) {
-	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Build( self, data );
-	Stg_Component_Build( self->gradField, data, False );
-	Assembler_SetVariables( self->assm, self->gradField, self->gradField );
-	Assembler_SetIntegrationSwarm( self->assm, self->integrationSwarm );
-}
-
-void _PressureGradMatrixTerm_Initialise( void* matrixTerm, void* data ) {
-	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Initialise( self, data );
-	Stg_Component_Initialise( self->gradField, data, False );
-}
-
-void _PressureGradMatrixTerm_Execute( void* matrixTerm, void* data ) {
-	_StiffnessMatrixTerm_Execute( matrixTerm, data );
-}
-
-void _PressureGradMatrixTerm_Destroy( void* matrixTerm, void* data ) {
-   PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
-   Stg_Component_Destroy( self->gradField, data, False );
-   Stg_Component_Destroy( self->stiffMat, data, False );
-
-	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
-}
-
-void _PressureGradMatrixTerm_AssembleElement(
-	 void*						matrixTerm,
-	StiffnessMatrix*			stiffnessMatrix, 
-	Element_LocalIndex		lElement_I, 
-	SystemLinearEquations*	 sle, 
-	FiniteElementContext*	context, 
-	double**						elStiffMat )
-{
-	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
-
-	assert( self );
-
-	self->stiffnessMatrix = stiffnessMatrix;
-	self->elStiffMat = elStiffMat;
-	Assembler_IntegrateMatrixElement( self->assm, lElement_I );
-}
-
-Bool PressureGradMatrixTerm_RowCB( PressureGradMatrixTerm* self, Assembler* assm ) {
-	self->factor = assm->particle->weight * assm->detJac;
-	return True;
-}
-
-Bool PressureGradMatrixTerm_ColCB( PressureGradMatrixTerm* self, Assembler* assm ) {
-	if( assm->rowDofInd != assm->colDofInd )
-          return False;
-
-	self->elStiffMat[assm->rowInd][assm->colInd] += 
-		assm->shapeFuncs[assm->rowElNodeInd] * 
-		assm->shapeFuncs[assm->colElNodeInd] * 
-		self->factor;
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/PressureGradMatrixTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/PressureGradMatrixTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,213 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: PressureGradMatrixTerm.c 822 2007-04-27 06:20:35Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <assert.h>
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "types.h"
+#include "PressureGradMatrixTerm.h"
+
+/* Textual name of this class */
+const Type PressureGradMatrixTerm_Type = "PressureGradMatrixTerm";
+
+PressureGradMatrixTerm* PressureGradMatrixTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	StiffnessMatrix*			stiffnessMatrix,
+	Swarm*						integrationSwarm,
+	FeVariable*					gradField )
+{
+	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*) _PressureGradMatrixTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
+	_PressureGradMatrixTerm_Init( self, gradField );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+PressureGradMatrixTerm* _PressureGradMatrixTerm_New(  PRESSUREGRADMATRIXTERM_DEFARGS  )
+{
+	PressureGradMatrixTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(PressureGradMatrixTerm) );
+	self = (PressureGradMatrixTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _PressureGradMatrixTerm_Init( void* matrixTerm, FeVariable* gradField ) {
+	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
+
+	self->assm = Assembler_New();
+	Assembler_SetCallbacks( self->assm, 
+		NULL, 
+		NULL, 
+		(Assembler_CallbackType*)PressureGradMatrixTerm_RowCB, 
+		(Assembler_CallbackType*)PressureGradMatrixTerm_ColCB, 
+		(Assembler_CallbackType*)PressureGradMatrixTerm_ColCB, 
+		self );
+	self->gradField = gradField;
+	self->stiffnessMatrix = NULL;
+	self->elStiffMat = NULL;
+	self->factor = 0.0;
+}
+
+void _PressureGradMatrixTerm_Delete( void* matrixTerm ) {
+	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Delete( self );
+}
+
+void _PressureGradMatrixTerm_Print( void* matrixTerm, Stream* stream ) {
+	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
+	
+	_StiffnessMatrixTerm_Print( self, stream );
+
+	/* General info */
+	Journal_PrintPointer( stream, self->gradField );
+}
+
+void* _PressureGradMatrixTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(PressureGradMatrixTerm);
+	Type                                                         type = PressureGradMatrixTerm_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _PressureGradMatrixTerm_Delete;
+	Stg_Class_PrintFunction*                                   _print = _PressureGradMatrixTerm_Print;
+	Stg_Class_CopyFunction*                                     _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _PressureGradMatrixTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _PressureGradMatrixTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _PressureGradMatrixTerm_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _PressureGradMatrixTerm_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _PressureGradMatrixTerm_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _PressureGradMatrixTerm_Destroy;
+	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _PressureGradMatrixTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_PressureGradMatrixTerm_New(  PRESSUREGRADMATRIXTERM_PASSARGS  );
+}
+
+void _PressureGradMatrixTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
+	PressureGradMatrixTerm*	self = (PressureGradMatrixTerm*)matrixTerm;
+	FeVariable*					gradField;
+
+	/* Construct Parent */
+	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
+
+	gradField = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PressureGradField", FeVariable, True, data  ) ;
+
+	_PressureGradMatrixTerm_Init( self, gradField );
+}
+
+void _PressureGradMatrixTerm_Build( void* matrixTerm, void* data ) {
+	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Build( self, data );
+	Stg_Component_Build( self->gradField, data, False );
+	Assembler_SetVariables( self->assm, self->gradField, self->gradField );
+	Assembler_SetIntegrationSwarm( self->assm, self->integrationSwarm );
+}
+
+void _PressureGradMatrixTerm_Initialise( void* matrixTerm, void* data ) {
+	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Initialise( self, data );
+	Stg_Component_Initialise( self->gradField, data, False );
+}
+
+void _PressureGradMatrixTerm_Execute( void* matrixTerm, void* data ) {
+	_StiffnessMatrixTerm_Execute( matrixTerm, data );
+}
+
+void _PressureGradMatrixTerm_Destroy( void* matrixTerm, void* data ) {
+   PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
+   Stg_Component_Destroy( self->gradField, data, False );
+   Stg_Component_Destroy( self->stiffMat, data, False );
+
+	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
+}
+
+void _PressureGradMatrixTerm_AssembleElement(
+	 void*						matrixTerm,
+	StiffnessMatrix*			stiffnessMatrix, 
+	Element_LocalIndex		lElement_I, 
+	SystemLinearEquations*	 sle, 
+	FiniteElementContext*	context, 
+	double**						elStiffMat )
+{
+	PressureGradMatrixTerm* self = (PressureGradMatrixTerm*)matrixTerm;
+
+	assert( self );
+
+	self->stiffnessMatrix = stiffnessMatrix;
+	self->elStiffMat = elStiffMat;
+	Assembler_IntegrateMatrixElement( self->assm, lElement_I );
+}
+
+Bool PressureGradMatrixTerm_RowCB( PressureGradMatrixTerm* self, Assembler* assm ) {
+	self->factor = assm->particle->weight * assm->detJac;
+	return True;
+}
+
+Bool PressureGradMatrixTerm_ColCB( PressureGradMatrixTerm* self, Assembler* assm ) {
+	if( assm->rowDofInd != assm->colDofInd )
+          return False;
+
+	self->elStiffMat[assm->rowInd][assm->colInd] += 
+		assm->shapeFuncs[assm->rowElNodeInd] * 
+		assm->shapeFuncs[assm->colElNodeInd] * 
+		self->factor;
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/ThermalBuoyancyForceTerm.c
--- a/Assembly/src/ThermalBuoyancyForceTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,243 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: ThermalBuoyancyForceTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SLE.h>
-
-#include "types.h"
-#include "ThermalBuoyancyForceTerm.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type ThermalBuoyancyForceTerm_Type = "ThermalBuoyancyForceTerm";
-
-ThermalBuoyancyForceTerm* ThermalBuoyancyForceTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	ForceVector*				forceVector,
-	Swarm*						integrationSwarm,
-	FeVariable*					temperatureField,
-	double						rayleighNumber )
-{
-	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*) _ThermalBuoyancyForceTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ForceTerm_Init( self, context, forceVector, integrationSwarm, NULL );
-	_ThermalBuoyancyForceTerm_Init( self, temperatureField, rayleighNumber );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-ThermalBuoyancyForceTerm* _ThermalBuoyancyForceTerm_New(  THERMALBUOYANCYFORCETERM_DEFARGS  )
-{
-	ThermalBuoyancyForceTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(ThermalBuoyancyForceTerm) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (ThermalBuoyancyForceTerm*) _ForceTerm_New(  FORCETERM_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _ThermalBuoyancyForceTerm_Init( void* forceTerm, FeVariable* temperatureField, double rayleighNumber ) {
-	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
-
-	self->temperatureField = temperatureField;
-	self->rayleighNumber = rayleighNumber;
-}
-
-void _ThermalBuoyancyForceTerm_Delete( void* forceTerm ) {
-	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
-
-	_ForceTerm_Delete( self );
-}
-
-void _ThermalBuoyancyForceTerm_Print( void* forceTerm, Stream* stream ) {
-	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
-	
-	_ForceTerm_Print( self, stream );
-
-	/* General info */
-	Journal_PrintPointer( stream, self->temperatureField );
-	Journal_PrintDouble( stream, self->rayleighNumber );
-}
-
-void* _ThermalBuoyancyForceTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(ThermalBuoyancyForceTerm);
-	Type                                                      type = ThermalBuoyancyForceTerm_Type;
-	Stg_Class_DeleteFunction*                              _delete = _ThermalBuoyancyForceTerm_Delete;
-	Stg_Class_PrintFunction*                                _print = _ThermalBuoyancyForceTerm_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _ThermalBuoyancyForceTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _ThermalBuoyancyForceTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _ThermalBuoyancyForceTerm_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _ThermalBuoyancyForceTerm_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _ThermalBuoyancyForceTerm_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _ThermalBuoyancyForceTerm_Destroy;
-	ForceTerm_AssembleElementFunction*            _assembleElement = _ThermalBuoyancyForceTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_ThermalBuoyancyForceTerm_New(  THERMALBUOYANCYFORCETERM_PASSARGS  );
-}
-
-void _ThermalBuoyancyForceTerm_AssignFromXML( void* forceTerm, Stg_ComponentFactory* cf, void* data ) {
-	ThermalBuoyancyForceTerm*	self = (ThermalBuoyancyForceTerm*)forceTerm;
-	FeVariable*						temperatureField;
-	double							rayleighNumber;
-
-	/* Construct Parent */
-	_ForceTerm_AssignFromXML( self, cf, data );
-
-	temperatureField = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"TemperatureField", FeVariable, True, data  ) ;
-	rayleighNumber   = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"Ra", 0.0  );
-
-	_ThermalBuoyancyForceTerm_Init( self, temperatureField, rayleighNumber );
-}
-
-void _ThermalBuoyancyForceTerm_Build( void* forceTerm, void* data ) {
-	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
-
-	Stg_Component_Build( self->temperatureField, data, False );
-	_ForceTerm_Build( self, data );
-}
-
-void _ThermalBuoyancyForceTerm_Initialise( void* forceTerm, void* data ) {
-	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
-
-	Stg_Component_Initialise( self->temperatureField, data, False );
-	_ForceTerm_Initialise( self, data );
-}
-
-void _ThermalBuoyancyForceTerm_Execute( void* forceTerm, void* data ) {
-	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
-
-	_ForceTerm_Execute( self, data );
-}
-
-void _ThermalBuoyancyForceTerm_Destroy( void* forceTerm, void* data ) {
-	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
-
-   Stg_Component_Destroy( self->temperatureField, data, False );
-	_ForceTerm_Destroy( self, data );
-}
-
-
-void _ThermalBuoyancyForceTerm_AssembleElement( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elForceVec ) {
-	ThermalBuoyancyForceTerm*	self = Stg_CheckType( forceTerm, ThermalBuoyancyForceTerm );
-	Swarm*							swarm = self->integrationSwarm;
-	Dimension_Index				dim = forceVector->dim;
-	IntegrationPoint*				particle;
-	FeVariable*						temperatureField;
-	FeMesh*							mesh;
-	FeMesh*							temperatureMesh;
-	double*							xi;
-	Particle_InCellIndex			cParticle_I;
-	Particle_InCellIndex			cellParticleCount;
-	Element_NodeIndex				elementNodeCount;
-	Node_ElementLocalIndex		node_I;
-	ElementType*					elementType;
-	Dof_Index						dofsPerNode;
-	Cell_Index						cell_I;
-	double							detJac;
-	double							factor;
-	/*double							Ni[8];*/
-	double							Ni[27];
-	double							force;
-	double							rayleighNumber;
-	double							temperature;
-
-	/* Get context extension */
-	rayleighNumber   = self->rayleighNumber;
-	temperatureField = self->temperatureField;
-	temperatureMesh  = temperatureField->feMesh;
-
-	/* Since we are integrating over the velocity mesh - we want the velocity mesh here and not the temperature mesh */
-	mesh             = forceVector->feVariable->feMesh;
-	
-	/* Set the element type */
-	elementType      = FeMesh_GetElementType( mesh, lElement_I ); 
-	elementNodeCount = elementType->nodeCount;
-
-	/* assumes constant number of dofs per element */
-	dofsPerNode = dim;
-	
-	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
-	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-	
-	for ( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
-		particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
-		xi       = particle->xi;
-		
-		/* Calculate Determinant of Jacobian and Shape Functions */
-		detJac = ElementType_JacobianDeterminant( elementType, mesh, lElement_I, xi, dim );
-		ElementType_EvaluateShapeFunctionsAt( elementType, xi, Ni );
-
-		/* Field Get Temperature from Field Variable */
-		FeVariable_InterpolateFromMeshLocalCoord( temperatureField, mesh, lElement_I, xi, &temperature );
-
-		force = rayleighNumber * temperature;
-
-		factor = detJac * particle->weight * force;
-		for( node_I = 0 ; node_I < elementNodeCount ; node_I++ ) 
-			elForceVec[node_I * dofsPerNode + J_AXIS ] += factor * Ni[ node_I ] ;
-		
-	}
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/src/ThermalBuoyancyForceTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/src/ThermalBuoyancyForceTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,243 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: ThermalBuoyancyForceTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SLE.h>
+
+#include "types.h"
+#include "ThermalBuoyancyForceTerm.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type ThermalBuoyancyForceTerm_Type = "ThermalBuoyancyForceTerm";
+
+ThermalBuoyancyForceTerm* ThermalBuoyancyForceTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	ForceVector*				forceVector,
+	Swarm*						integrationSwarm,
+	FeVariable*					temperatureField,
+	double						rayleighNumber )
+{
+	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*) _ThermalBuoyancyForceTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ForceTerm_Init( self, context, forceVector, integrationSwarm, NULL );
+	_ThermalBuoyancyForceTerm_Init( self, temperatureField, rayleighNumber );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+ThermalBuoyancyForceTerm* _ThermalBuoyancyForceTerm_New(  THERMALBUOYANCYFORCETERM_DEFARGS  )
+{
+	ThermalBuoyancyForceTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(ThermalBuoyancyForceTerm) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (ThermalBuoyancyForceTerm*) _ForceTerm_New(  FORCETERM_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _ThermalBuoyancyForceTerm_Init( void* forceTerm, FeVariable* temperatureField, double rayleighNumber ) {
+	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
+
+	self->temperatureField = temperatureField;
+	self->rayleighNumber = rayleighNumber;
+}
+
+void _ThermalBuoyancyForceTerm_Delete( void* forceTerm ) {
+	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
+
+	_ForceTerm_Delete( self );
+}
+
+void _ThermalBuoyancyForceTerm_Print( void* forceTerm, Stream* stream ) {
+	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
+	
+	_ForceTerm_Print( self, stream );
+
+	/* General info */
+	Journal_PrintPointer( stream, self->temperatureField );
+	Journal_PrintDouble( stream, self->rayleighNumber );
+}
+
+void* _ThermalBuoyancyForceTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(ThermalBuoyancyForceTerm);
+	Type                                                      type = ThermalBuoyancyForceTerm_Type;
+	Stg_Class_DeleteFunction*                              _delete = _ThermalBuoyancyForceTerm_Delete;
+	Stg_Class_PrintFunction*                                _print = _ThermalBuoyancyForceTerm_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _ThermalBuoyancyForceTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _ThermalBuoyancyForceTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _ThermalBuoyancyForceTerm_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _ThermalBuoyancyForceTerm_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _ThermalBuoyancyForceTerm_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _ThermalBuoyancyForceTerm_Destroy;
+	ForceTerm_AssembleElementFunction*            _assembleElement = _ThermalBuoyancyForceTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_ThermalBuoyancyForceTerm_New(  THERMALBUOYANCYFORCETERM_PASSARGS  );
+}
+
+void _ThermalBuoyancyForceTerm_AssignFromXML( void* forceTerm, Stg_ComponentFactory* cf, void* data ) {
+	ThermalBuoyancyForceTerm*	self = (ThermalBuoyancyForceTerm*)forceTerm;
+	FeVariable*						temperatureField;
+	double							rayleighNumber;
+
+	/* Construct Parent */
+	_ForceTerm_AssignFromXML( self, cf, data );
+
+	temperatureField = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"TemperatureField", FeVariable, True, data  ) ;
+	rayleighNumber   = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"Ra", 0.0  );
+
+	_ThermalBuoyancyForceTerm_Init( self, temperatureField, rayleighNumber );
+}
+
+void _ThermalBuoyancyForceTerm_Build( void* forceTerm, void* data ) {
+	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
+
+	Stg_Component_Build( self->temperatureField, data, False );
+	_ForceTerm_Build( self, data );
+}
+
+void _ThermalBuoyancyForceTerm_Initialise( void* forceTerm, void* data ) {
+	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
+
+	Stg_Component_Initialise( self->temperatureField, data, False );
+	_ForceTerm_Initialise( self, data );
+}
+
+void _ThermalBuoyancyForceTerm_Execute( void* forceTerm, void* data ) {
+	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
+
+	_ForceTerm_Execute( self, data );
+}
+
+void _ThermalBuoyancyForceTerm_Destroy( void* forceTerm, void* data ) {
+	ThermalBuoyancyForceTerm* self = (ThermalBuoyancyForceTerm*)forceTerm;
+
+   Stg_Component_Destroy( self->temperatureField, data, False );
+	_ForceTerm_Destroy( self, data );
+}
+
+
+void _ThermalBuoyancyForceTerm_AssembleElement( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elForceVec ) {
+	ThermalBuoyancyForceTerm*	self = Stg_CheckType( forceTerm, ThermalBuoyancyForceTerm );
+	Swarm*							swarm = self->integrationSwarm;
+	Dimension_Index				dim = forceVector->dim;
+	IntegrationPoint*				particle;
+	FeVariable*						temperatureField;
+	FeMesh*							mesh;
+	FeMesh*							temperatureMesh;
+	double*							xi;
+	Particle_InCellIndex			cParticle_I;
+	Particle_InCellIndex			cellParticleCount;
+	Element_NodeIndex				elementNodeCount;
+	Node_ElementLocalIndex		node_I;
+	ElementType*					elementType;
+	Dof_Index						dofsPerNode;
+	Cell_Index						cell_I;
+	double							detJac;
+	double							factor;
+	/*double							Ni[8];*/
+	double							Ni[27];
+	double							force;
+	double							rayleighNumber;
+	double							temperature;
+
+	/* Get context extension */
+	rayleighNumber   = self->rayleighNumber;
+	temperatureField = self->temperatureField;
+	temperatureMesh  = temperatureField->feMesh;
+
+	/* Since we are integrating over the velocity mesh - we want the velocity mesh here and not the temperature mesh */
+	mesh             = forceVector->feVariable->feMesh;
+	
+	/* Set the element type */
+	elementType      = FeMesh_GetElementType( mesh, lElement_I ); 
+	elementNodeCount = elementType->nodeCount;
+
+	/* assumes constant number of dofs per element */
+	dofsPerNode = dim;
+	
+	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
+	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+	
+	for ( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
+		particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
+		xi       = particle->xi;
+		
+		/* Calculate Determinant of Jacobian and Shape Functions */
+		detJac = ElementType_JacobianDeterminant( elementType, mesh, lElement_I, xi, dim );
+		ElementType_EvaluateShapeFunctionsAt( elementType, xi, Ni );
+
+		/* Field Get Temperature from Field Variable */
+		FeVariable_InterpolateFromMeshLocalCoord( temperatureField, mesh, lElement_I, xi, &temperature );
+
+		force = rayleighNumber * temperature;
+
+		factor = detJac * particle->weight * force;
+		for( node_I = 0 ; node_I < elementNodeCount ; node_I++ ) 
+			elForceVec[node_I * dofsPerNode + J_AXIS ] += factor * Ni[ node_I ] ;
+		
+	}
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/tests/IsoviscousStiffnessSuite.c
--- a/Assembly/tests/IsoviscousStiffnessSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include <PICellerator/PICellerator.h>
-#include "Underworld/Underworld.h"
-
-/* silly stgermain, I must define this */
-#define CURR_MODULE_NAME "StgFEM.c"
-
-typedef struct {
-	FiniteElementContext* context;
-} IsoviscousStiffnessData;
-
-void IsoviscousStiffness_Setup( IsoviscousStiffnessData* data ) { 
-	Journal_Enable_AllTypedStream( False );
-	data->context=NULL;
-}
-
-void IsoviscousStiffness_Teardown( IsoviscousStiffnessData* data ) {
-}
-
-void IsoviscousStiffness2D( IsoviscousStiffnessData* data ) {
-	StiffnessMatrix*			stiffnessMatrix;
-	Dictionary*					dictionary;
-	FiniteElementContext*	context;
-	Stg_ComponentFactory*	cf;
-	PetscViewer					expViewer;
-	PetscReal					matrixNorm, errorNorm, test;
-	Mat							expected;
-	char							expected_file[PCU_PATH_MAX];
-	char							*filename, *matrixName;
-	double						tolerance;
-	char							xml_input[PCU_PATH_MAX];
-	Stream*						infoStream = Journal_Register( Info_Type, (Name)CURR_MODULE_NAME );
-	char							rFile[PCU_PATH_MAX];
-	int							err;
-
-	pcu_docstring( "This test compares a Stiffness matrix against a previously generated stiffness matrix"
-		"The stiffness matrix is generated from a 2D FEM model for an isoviscous fluid flow." 
-		"See testIsoviscous.xml for the actual xml used"	 );
-
-	/* read in the xml input file */
-	pcu_filename_input( "IsoviscousStiffnessMatrix.xml", xml_input );
-	cf = stgMainInitFromXML( xml_input, MPI_COMM_WORLD, NULL );
-	context = (FiniteElementContext*)LiveComponentRegister_Get( cf->LCRegister, (Name)"context" );
-	data->context = context;
-	dictionary = context->dictionary;
-
-	stgMainBuildAndInitialise( cf );
-
-	/* Test is to check the relative error between an
-		 1 ) expected stiffness matrix, (made years ago)
-		 2) the current stiffness matrix.
-
-		 both matricies are built using only an Arrhenius rheology 
-	 */
-
-	/* get the tolerance */
-	tolerance = Dictionary_GetDouble( dictionary, "StiffnessMatrixCompareTolerance" );
-
-	/* Get Matrix */
-	matrixName = Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"CompareStiffnessMatrix"  );
-	Journal_Printf( infoStream, "Comparing stiffness matrix '%s'\n", matrixName );
-	stiffnessMatrix = (StiffnessMatrix*) LiveComponentRegister_Get( context->CF->LCRegister, (Name)matrixName );
-	assert( stiffnessMatrix  );
-
-	StiffnessMatrix_Assemble( stiffnessMatrix, False, NULL, context );
-
-	/* Get Stored Matrix from file */
-	filename = Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"StiffnessMatrixCompareFilename"  );
-	Journal_Printf( infoStream, "Checking with file '%s'\n", filename );
-
-	pcu_filename_expected( filename, expected_file );
-	PetscViewerBinaryOpen( context->communicator, expected_file, FILE_MODE_READ, &expViewer );
-
-	MatLoad( expViewer, MATAIJ, &expected );
-
-	MatNorm( expected, NORM_FROBENIUS, &matrixNorm );
-	assert( matrixNorm != 0 );
-
-	MatAXPY( expected, -1, (stiffnessMatrix->matrix) , DIFFERENT_NONZERO_PATTERN );
-	MatNorm( expected, NORM_FROBENIUS, &errorNorm );
-	test = errorNorm / matrixNorm;
-
-	pcu_check_lt( test, tolerance );
-
-	/* Check tolerance */
-	/*
-	stream = Journal_Register( Info_Type, (Name)"StiffnessMatrixComparison"  );
-	Stream_RedirectFile_WithPrependedPath( stream, context->outputPath, "StiffnessMatrixCompare.dat" );
-	Journal_PrintValue( infoStream, tolerance );
-	Journal_Printf( stream, "Comparison between stiffness matrix '%s' %s with tolerance %4g.\n", 
-			matrixName, 
-			( errorNorm/matrixNorm < tolerance ? "passed" : "failed" ),
-			tolerance );
-			*/
-
-	/* 
-	Stream_CloseFile( stream );
-		 To view the expected and computed matricies uncomment this
-	PetscViewerASCIIOpen(context->communicator, "numerical.dat",&currViewer);
-	PetscViewerASCIIOpen(context->communicator, "expected.dat",&parallelViewer);
-	MatView( stiffnessMatrix->matrix, currViewer ); //PETSC_VIEWER_STDOUT_WORLD );
-	MatView( expected, parallelViewer ); //PETSC_VIEWER_STDOUT_WORLD );
-	PetscViewerDestroy(currViewer);
-	PetscViewerDestroy(parallelViewer);
-	*/
-	if( data->context->rank == 0 ) {
-		/* Now clean output path */
-		sprintf(rFile, "%s/input.xml", data->context->outputPath );
-		err = remove( rFile );
-		if( err == -1 ) printf("Error in %s, can't delete the input.xml\n", __func__);
-	}
-
-	stgMainDestroy( cf );
-}
-
-void IsoviscousStiffnessSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, IsoviscousStiffnessData );
-   pcu_suite_setFixtures( suite, IsoviscousStiffness_Setup, IsoviscousStiffness_Teardown );
-   pcu_suite_addTest( suite, IsoviscousStiffness2D );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Assembly/tests/IsoviscousStiffnessSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Assembly/tests/IsoviscousStiffnessSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include <PICellerator/PICellerator.h>
+#include "Underworld/Underworld.h"
+
+/* silly stgermain, I must define this */
+#define CURR_MODULE_NAME "StgFEM.c"
+
+typedef struct {
+	FiniteElementContext* context;
+} IsoviscousStiffnessData;
+
+void IsoviscousStiffness_Setup( IsoviscousStiffnessData* data ) { 
+	Journal_Enable_AllTypedStream( False );
+	data->context=NULL;
+}
+
+void IsoviscousStiffness_Teardown( IsoviscousStiffnessData* data ) {
+}
+
+void IsoviscousStiffness2D( IsoviscousStiffnessData* data ) {
+	StiffnessMatrix*			stiffnessMatrix;
+	Dictionary*					dictionary;
+	FiniteElementContext*	context;
+	Stg_ComponentFactory*	cf;
+	PetscViewer					expViewer;
+	PetscReal					matrixNorm, errorNorm, test;
+	Mat							expected;
+	char							expected_file[PCU_PATH_MAX];
+	char							*filename, *matrixName;
+	double						tolerance;
+	char							xml_input[PCU_PATH_MAX];
+	Stream*						infoStream = Journal_Register( Info_Type, (Name)CURR_MODULE_NAME );
+	char							rFile[PCU_PATH_MAX];
+	int							err;
+
+	pcu_docstring( "This test compares a Stiffness matrix against a previously generated stiffness matrix"
+		"The stiffness matrix is generated from a 2D FEM model for an isoviscous fluid flow." 
+		"See testIsoviscous.xml for the actual xml used"	 );
+
+	/* read in the xml input file */
+	pcu_filename_input( "IsoviscousStiffnessMatrix.xml", xml_input );
+	cf = stgMainInitFromXML( xml_input, MPI_COMM_WORLD, NULL );
+	context = (FiniteElementContext*)LiveComponentRegister_Get( cf->LCRegister, (Name)"context" );
+	data->context = context;
+	dictionary = context->dictionary;
+
+	stgMainBuildAndInitialise( cf );
+
+	/* Test is to check the relative error between an
+		 1 ) expected stiffness matrix, (made years ago)
+		 2) the current stiffness matrix.
+
+		 both matricies are built using only an Arrhenius rheology 
+	 */
+
+	/* get the tolerance */
+	tolerance = Dictionary_GetDouble( dictionary, "StiffnessMatrixCompareTolerance" );
+
+	/* Get Matrix */
+	matrixName = Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"CompareStiffnessMatrix"  );
+	Journal_Printf( infoStream, "Comparing stiffness matrix '%s'\n", matrixName );
+	stiffnessMatrix = (StiffnessMatrix*) LiveComponentRegister_Get( context->CF->LCRegister, (Name)matrixName );
+	assert( stiffnessMatrix  );
+
+	StiffnessMatrix_Assemble( stiffnessMatrix, False, NULL, context );
+
+	/* Get Stored Matrix from file */
+	filename = Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"StiffnessMatrixCompareFilename"  );
+	Journal_Printf( infoStream, "Checking with file '%s'\n", filename );
+
+	pcu_filename_expected( filename, expected_file );
+	PetscViewerBinaryOpen( context->communicator, expected_file, FILE_MODE_READ, &expViewer );
+
+	MatLoad( expViewer, MATAIJ, &expected );
+
+	MatNorm( expected, NORM_FROBENIUS, &matrixNorm );
+	assert( matrixNorm != 0 );
+
+	MatAXPY( expected, -1, (stiffnessMatrix->matrix) , DIFFERENT_NONZERO_PATTERN );
+	MatNorm( expected, NORM_FROBENIUS, &errorNorm );
+	test = errorNorm / matrixNorm;
+
+	pcu_check_lt( test, tolerance );
+
+	/* Check tolerance */
+	/*
+	stream = Journal_Register( Info_Type, (Name)"StiffnessMatrixComparison"  );
+	Stream_RedirectFile_WithPrependedPath( stream, context->outputPath, "StiffnessMatrixCompare.dat" );
+	Journal_PrintValue( infoStream, tolerance );
+	Journal_Printf( stream, "Comparison between stiffness matrix '%s' %s with tolerance %4g.\n", 
+			matrixName, 
+			( errorNorm/matrixNorm < tolerance ? "passed" : "failed" ),
+			tolerance );
+			*/
+
+	/* 
+	Stream_CloseFile( stream );
+		 To view the expected and computed matricies uncomment this
+	PetscViewerASCIIOpen(context->communicator, "numerical.dat",&currViewer);
+	PetscViewerASCIIOpen(context->communicator, "expected.dat",&parallelViewer);
+	MatView( stiffnessMatrix->matrix, currViewer ); //PETSC_VIEWER_STDOUT_WORLD );
+	MatView( expected, parallelViewer ); //PETSC_VIEWER_STDOUT_WORLD );
+	PetscViewerDestroy(currViewer);
+	PetscViewerDestroy(parallelViewer);
+	*/
+	if( data->context->rank == 0 ) {
+		/* Now clean output path */
+		sprintf(rFile, "%s/input.xml", data->context->outputPath );
+		err = remove( rFile );
+		if( err == -1 ) printf("Error in %s, can't delete the input.xml\n", __func__);
+	}
+
+	stgMainDestroy( cf );
+}
+
+void IsoviscousStiffnessSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, IsoviscousStiffnessData );
+   pcu_suite_setFixtures( suite, IsoviscousStiffness_Setup, IsoviscousStiffness_Teardown );
+   pcu_suite_addTest( suite, IsoviscousStiffness2D );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/AnalyticSolution.c
--- a/Discretisation/src/AnalyticSolution.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,636 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: AnalyticSolution.c 1137 2008-05-23 05:57:48Z RobertTurnbull $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "types.h"
-#include "AnalyticSolution.h"
-#include "FeVariable.h"
-#include "OperatorFeVariable.h"
-#include "FeMesh.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-const Type AnalyticSolution_Type = "AnalyticSolution";
-/* Singleton for analytical solution */
-AnalyticSolution* mySingleton = NULL;
-
-void* _AnalyticSolution_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(AnalyticSolution);
-	Type                                                      type = AnalyticSolution_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _AnalyticSolution_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _AnalyticSolution_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _AnalyticSolution_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-AnalyticSolution* _AnalyticSolution_New(  ANALYTICSOLUTION_DEFARGS  )
-{
-	AnalyticSolution*			self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(AnalyticSolution) );
-	/* Construct using parent */
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (AnalyticSolution*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-
-	/* Assign singleton ptr */
-	mySingleton = self;
-	return self;
-}
-
-void _AnalyticSolution_Init( AnalyticSolution* self, Swarm* integrationSwarm, LiveComponentRegister* LC_Register, AbstractContext* context, Bool verboseMode ) {
-	self->LC_Register = LC_Register;
-	self->integrationSwarm = integrationSwarm;
-	self->context = (DomainContext*)context;
-
-	/* Initialise AnalyticFunctions */
-	self->_getAnalyticVelocity = NULL;
-	self->_getAnalyticPressure = NULL;
-	self->_getAnalyticTotalStress = NULL;
-	self->_getAnalyticStrainRate = NULL;
-
-	/* Create Lists */
-	self->feVariableList             = Stg_ObjectList_New();
-	self->analyticFeVariableList     = Stg_ObjectList_New();
-	self->analyticFeVariableFuncList = Stg_ObjectList_New();
-	self->errorMagnitudeFieldList    = Stg_ObjectList_New();
-	self->relativeErrorMagnitudeFieldList    = Stg_ObjectList_New();
-	self->streamList                 = Stg_ObjectList_New();
-
-	/* Add functions to entry points */
-	EntryPoint_AppendClassHook( Context_GetEntryPoint( context, AbstractContext_EP_UpdateClass ), 
-                                    self->type, (void*)AnalyticSolution_Update, self->type, self );
-	EP_AppendClassHook( Context_GetEntryPoint( context, AbstractContext_EP_DumpClass ), 
-			AnalyticSolution_TestAll, self );
-
-	if ( verboseMode ) {
-		Stream* infoStream = Journal_MyStream( Info_Type, self );
-		Stream_SetLevel( infoStream, 2 );
-	}
-}
-
-void _AnalyticSolution_Delete( void* analyticSolution ) {
-	AnalyticSolution* self = (AnalyticSolution*)analyticSolution;
-
-	Stg_Class_Delete( self->feVariableList );
-	Stg_Class_Delete( self->analyticFeVariableList );
-	Stg_Class_Delete( self->analyticFeVariableFuncList );
-	Stg_Class_Delete( self->errorMagnitudeFieldList );
-	Stg_Class_Delete( self->relativeErrorMagnitudeFieldList );
-	Stg_Class_Delete( self->streamList );
-
-	if ( self->toleranceList )
-		Memory_Free( self->toleranceList );
-	
-	/* Stg_Class_Delete parent*/
-	_Stg_Component_Delete( self );
-}
-
-void _AnalyticSolution_Print( void* analyticSolution, Stream* stream ) {
-	AnalyticSolution* self = (AnalyticSolution*)analyticSolution;
-	
-	/* Print parent */
-	_Stg_Component_Print( self, stream );
-	
-}
-
-void* _AnalyticSolution_Copy( const void* analyticSolution, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	abort();
-	return NULL;
-}
-
-void _AnalyticSolution_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) 
-{
-	AnalyticSolution* self = (AnalyticSolution*)analyticSolution;
-	AbstractContext*  context;
-	Swarm*            integrationSwarm;
-	Bool              verboseMode;
-
-	context = (AbstractContext*)(Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", DomainContext, False, data ));
-	if( !context  )
-          context = (AbstractContext*)(Stg_ComponentFactory_ConstructByName( cf, (Name)"context", DomainContext, True, data  ));
-
-	integrationSwarm = Stg_ComponentFactory_ConstructByName( cf, (Name)"gaussSwarm", Swarm, True, data  ); 
-	verboseMode = Stg_ComponentFactory_GetRootDictBool( cf, (Dictionary_Entry_Key)"analyticSolutionVerbose", False  );
-
-	_AnalyticSolution_Init( self, integrationSwarm, cf->LCRegister, context, verboseMode );
-}
-
-void _AnalyticSolution_Build( void* analyticSolution, void* data ) {
-	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
-	Index             analyticFeVariableCount;
-	Index             analyticFeVariable_I;
-
-   Stg_Component_Build( self->integrationSwarm, data, False );
-	/* Build all the analytic fields registered to this AnalyticSolution */
-	AnalyticSolution_BuildAllAnalyticFields( self, data );
-	
-	analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
-	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
-
-	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
-		Stg_Component_Build( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Build( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Build( Stg_ObjectList_At( self->relativeErrorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
-	}
-}
-
-void _AnalyticSolution_Initialise( void* analyticSolution, void* data ) {
-	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
-	Index             analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
-	Index             analyticFeVariable_I;
-
-   Stg_Component_Initialise( self->integrationSwarm, data, False );
-	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
-
-	/* Assign values to all analytic fields */
-	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
-		Stg_Component_Initialise( Stg_ObjectList_At( self->feVariableList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Initialise( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Initialise( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Initialise( Stg_ObjectList_At( self->relativeErrorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
-
-		AnalyticSolution_PutAnalyticSolutionOntoNodes( self, analyticFeVariable_I );
-	}
-}
-
-/* This function is called when the 'Update' phase happens */
-void AnalyticSolution_Update( void* analyticSolution ) {
-	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
-
-	self->_initialise( self, NULL );
-}
-
-void _AnalyticSolution_Execute( void* analyticSolution, void* data ) {
-}
-
-void _AnalyticSolution_Destroy( void* analyticSolution, void* data ) {
-	AnalyticSolution* self = (AnalyticSolution*)analyticSolution;
-	Index             analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
-	Index             analyticFeVariable_I;
-
-   Stg_Component_Destroy( self, data, False );
-   
-   Stg_Component_Destroy( self->integrationSwarm, data, False );
-	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
-
-	/* Destroy all analytic fields */
-	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
-		Stg_Component_Destroy( Stg_ObjectList_At( self->feVariableList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Destroy( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Destroy( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Destroy( Stg_ObjectList_At( self->relativeErrorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
-	}
-
-}
-
-void AnalyticSolution_PutAnalyticSolutionOntoNodes( void* analyticSolution, Index analyticFeVariable_I ) {
-	AnalyticSolution*                            self = (AnalyticSolution*) analyticSolution;
-	AnalyticSolution_SolutionFunction*           solutionFunction;
-	FeVariable*                                  analyticFeVariable;
-	double*                                      coord;
-	Dof_Index                                    dofAtEachNodeCount;
-	Node_DomainIndex                             dNode_I;
-	double*                                      value;
-	Stream*                                      infoStream = Journal_MyStream( Info_Type, self );
-	FeVariable*                                  feVariable;
-	FeMesh*						mesh;
-
-	/* Do some error checking */
-	assert( Stg_ObjectList_Count( self->analyticFeVariableList ) >= analyticFeVariable_I );
-
-	/* Grab pointers */
-	analyticFeVariable = 
-		Stg_CheckType( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), FeVariable );
-	mesh = analyticFeVariable->feMesh;
-	solutionFunction   = (AnalyticSolution_SolutionFunction*) 
-		Stg_ObjectList_ObjectAt( self->analyticFeVariableFuncList, analyticFeVariable_I );
-	feVariable = AnalyticSolution_GetFeVariableFromAnalyticFeVariable( self, analyticFeVariable );
-
-	/* Get number of degrees of freedom at each node (assuming they are the same) */
-	dofAtEachNodeCount = analyticFeVariable->fieldComponentCount;
-	value = Memory_Alloc_Array( double, dofAtEachNodeCount, "value" );
-
-	/* Loop over all the nodes - applying the analytic solution */
-	for ( dNode_I = 0 ; dNode_I < Mesh_GetDomainSize( mesh, MT_VERTEX ); dNode_I++ ) {
-		coord = Mesh_GetVertex( mesh, dNode_I );
-
-		/* Calculate value at node */
-		memset( value, 0, dofAtEachNodeCount * sizeof(double) );
-		solutionFunction( self, analyticFeVariable, coord, value );
-
-		/* Put value on node */
-		FeVariable_SetValueAtNode( analyticFeVariable, dNode_I, value );
-
-		/* Print verbose information */
-		if ( Stream_IsPrintableLevel( infoStream, 2 ) ) {
-			Dimension_Index dim = analyticFeVariable->dim;
-			Dimension_Index dim_I;
-			Dof_Index       dof_I;
-
-			/* Print Coord */
-			Journal_Printf( infoStream, "Node = %u Coord ( ", dNode_I );
-			for ( dim_I = 0 ; dim_I < dim - 1 ; dim_I++ ) {
-				Journal_Printf( infoStream, "%g, ", coord[ dim_I ] );
-			}
-			Journal_Printf( infoStream, "%g ) ", coord[ dim_I ] );
-
-			/* Print Analytic Values */
-			Journal_Printf( infoStream, "%s ( ", analyticFeVariable->name );
-			for ( dof_I = 0 ; dof_I < dofAtEachNodeCount - 1 ; dof_I++ ) {
-				Journal_Printf( infoStream, "%g, ", value[ dof_I ] );
-			}
-			Journal_Printf( infoStream, "%g ) ", value[ dof_I ] );
-
-			/* Print FeVariable Values */
-			memset( value, 0, dofAtEachNodeCount * sizeof(double) );
-			FeVariable_GetValueAtNode( feVariable, dNode_I, value );
-			Journal_Printf( infoStream, "%s ( ", feVariable->name );
-			for ( dof_I = 0 ; dof_I < dofAtEachNodeCount - 1 ; dof_I++ ) {
-				Journal_Printf( infoStream, "%g, ", value[ dof_I ] );
-			}
-			Journal_Printf( infoStream, "%g )\n", value[ dof_I ] );			
-		}
-	}
-
-	Memory_Free( value );
-}
-
-void AnalyticSolution_Test( void* analyticSolution, Index analyticFeVariable_I ) {
-	AnalyticSolution*                            self = (AnalyticSolution*) analyticSolution;
-	FeVariable*                                  errorMagnitudeField;
-	double                                       result;
-	Stream*                                      stream;
-	double                                       tolerance;
-	Stream*                                      infoStream = Journal_MyStream( Info_Type, self );
-
-	/* Do some error checking */
-	assert( Stg_ObjectList_Count( self->analyticFeVariableList ) >= analyticFeVariable_I );
-
-	/* Grab pointers */
-	errorMagnitudeField = 
-		Stg_CheckType( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), FeVariable );
-
-	stream = (Stream*) Stg_ObjectList_ObjectAt( self->streamList, analyticFeVariable_I );
-	tolerance = self->toleranceList[ analyticFeVariable_I ];
-
-	result = FeVariable_Integrate( errorMagnitudeField, self->integrationSwarm );
-
-	Journal_Printf( stream, "Timestep %u: Total integrated value of '%s' is %s a tolerance %.5g.\n", 
-				self->context->timeStep, errorMagnitudeField->name, result <= tolerance ? "within" : "outside", tolerance );
-	Stream_Flush( stream );
-
-	Journal_Printf( infoStream, "Timestep %u: Total integrated value of '%s' is %g\n", 
-			self->context->timeStep, errorMagnitudeField->name, result );
-}
-	
-
-void AnalyticSolution_TestAll( void* analyticSolution, void* data ) {
-	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
-	Index             analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
-	Index             analyticFeVariable_I;
-
-	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
-
-	/* Assign values to all analytic fields */
-	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
-		AnalyticSolution_Test( self, analyticFeVariable_I );
-	}
-}
-
-void AnalyticSolution_RegisterFeVariableWithAnalyticFunction( void* analyticSolution, FeVariable* feVariable, AnalyticSolution_SolutionFunction* solutionFunction) {
-	AnalyticSolution* self    = (AnalyticSolution*) analyticSolution;
-	char*             tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Analytic"  );
-
-	/* Add feVariable to list */
-	Stg_ObjectList_Append( self->feVariableList, feVariable );
-	/* Add function to list */
-	Stg_ObjectList_GlobalPointerAppend( self->analyticFeVariableFuncList, (void*)solutionFunction, (Name)tmpName );
-	Memory_Free( tmpName  );	
-}
-
-
-FeVariable* AnalyticSolution_RegisterFeVariableFromCF( void* analyticSolution, char* fieldName, AnalyticSolution_SolutionFunction* solutionFunction, Stg_ComponentFactory* cf, Bool isEssential, void* data ) {
-	AnalyticSolution* self    = (AnalyticSolution*) analyticSolution;
-	FeVariable*       field;
-
-	field = Stg_ComponentFactory_ConstructByName( cf, (Name)fieldName, FeVariable, isEssential, data ); 
-	if ( field  )
-		AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, field, solutionFunction );
-
-	return field;
-}
-
-
-void AnalyticSolution_BuildAllAnalyticFields( void* analyticSolution, void* data ) {
-	AnalyticSolution* self       = (AnalyticSolution*) analyticSolution;
-	FeVariable*       feVariable = NULL;
-	Stream*           errStream  = Journal_Register( Error_Type, (Name)"AnalyticSolution"  );
-	unsigned          feVar_I, feVarCount;
-
-	feVarCount = Stg_ObjectList_Count( self->feVariableList );
-
-	for( feVar_I = 0 ; feVar_I < feVarCount ; feVar_I++ ) {
-		feVariable = (FeVariable*)Stg_ObjectList_At( self->feVariableList, feVar_I );
-		
-		/* Check to see whether this field has already been added */
-		
-
-		/* Build the FeVariable here ensuring the analytic "copy" of it has valid values */
-		Stg_Component_Build( feVariable, data, False ) ;
-		
-		if( feVariable->fieldComponentCount == 1 ) {
-			if( NULL == AnalyticSolution_CreateAnalyticField( self, feVariable ) ) {
-
-				Journal_Firewall( 0 , errStream,
-				"Error in function %s: Error in building analyticSolution for the feVariable %s,\n",
-				__func__ , feVariable );
-			}
-		} else {
-			if( NULL == AnalyticSolution_CreateAnalyticSymmetricTensorField( self, feVariable ) ) {
-
-				Journal_Firewall( 0 , errStream,
-				"Error in function %s: Error in building analyticSolution for the feVariable %s,\n",
-				__func__ , feVariable );
-			}
-		}
-
-	}
-
-
-}
-
-FeVariable* AnalyticSolution_CreateAnalyticField( void* analyticSolution, FeVariable* feVariable ) {
-	AnalyticSolution*                            self = (AnalyticSolution*) analyticSolution;
-	char*                                        tmpName;
-	FeVariable*                                  analyticFeVariable;
-	Variable*                                    dataVariable;
-	DofLayout*                                   dofLayout;
-	Variable_Register*                           variable_Register = self->context->variable_Register;
-	Dof_Index                                    componentsCount   = feVariable->fieldComponentCount;
-	char*                                        variableName[9];
-	Variable_Index                               variable_I;
-	Node_DomainIndex                             node_I;
-	Bool scalar=(componentsCount==1) ? True : False;
-	OperatorFeVariable*                          analyticMagField;
-	OperatorFeVariable*                          errorField;
-	OperatorFeVariable*                          errorMagnitudeField;
-	OperatorFeVariable*                          relativeErrorMagnitudeField;
-	Stream*                                      stream;
-	Index                                        count;
-
-	Stg_Component_Build( feVariable->feMesh, NULL, False );
-
-	/* Create new data Variable */
-	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Analytic-DataVariable" );
-	if ( scalar  ) {
-		Sync*	sync;
-
-		sync = Mesh_GetSync( feVariable->feMesh, MT_VERTEX );
-		dataVariable = Variable_NewScalar( tmpName, (AbstractContext*)self->context, Variable_DataType_Double, (Index*)(unsigned*)&sync->nDomains, NULL, (void**)NULL, variable_Register  );
-	}
-	else {
-		Sync*		sync;
-		unsigned	c_i;
-
-		sync = Mesh_GetSync( feVariable->feMesh, MT_VERTEX );
-
-		/* Create names of variables */
-		assert( componentsCount <= 9 );
-		for ( variable_I = 0 ; variable_I < componentsCount ; variable_I++ ) {
-			Stg_asprintf( &variableName[ variable_I ], "%s-Analytic-ComponentVariable%d", feVariable->name, variable_I );
-		}
-		dataVariable = Variable_NewVector( 	
-				tmpName,
-				(AbstractContext*)self->context,
-				Variable_DataType_Double, 
-				componentsCount,
-				(unsigned*)&sync->nDomains, 
-				NULL, 
-				(void**)NULL, 
-				variable_Register,
-				variableName[0],
-				variableName[1],
-				variableName[2],
-				variableName[3],
-				variableName[4],
-				variableName[5],
-				variableName[6],
-				variableName[7],
-				variableName[8] );
-		for( c_i = 0; c_i < dataVariable->dataTypeCounts[0]; c_i++ )
-			dataVariable->components[c_i]->allocateSelf = True;
-	}
-	Memory_Free( tmpName );
-	dataVariable->allocateSelf = True;
-	
-	/* Create new dof layout */
-	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Analytic-DofLayout"  );
-	dofLayout = DofLayout_New( tmpName, self->context, variable_Register, Mesh_GetDomainSize( feVariable->feMesh, MT_VERTEX ), NULL );
-	if ( scalar ) {
-		DofLayout_AddAllFromVariableArray( dofLayout, 1, &dataVariable );
-	}
-	else {
-		for ( variable_I = 0 ; variable_I < componentsCount ; variable_I++ ) {
-
-			/* We have to set the array ptr ptr for these guys manually - this should be fixed */
-			Variable* variable = Variable_Register_GetByName( variable_Register, variableName[ variable_I ] );
-			variable->arrayPtrPtr = &dataVariable->arrayPtr;
-
-			/* Assign variable to each node */
-			for( node_I = 0; node_I < Mesh_GetDomainSize( feVariable->feMesh, MT_VERTEX ); node_I++ ) {
-				DofLayout_AddDof_ByVarName( dofLayout, variableName[variable_I], node_I );
-			}
-			/* Free Name */
-			Memory_Free( variableName[ variable_I ] );
-		}
-	}
-	Memory_Free( tmpName );
-
-	/* Create new FeVariable */
-	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Analytic"  );
-	analyticFeVariable = FeVariable_New( tmpName, self->context, feVariable->feMesh, feVariable->geometryMesh, dofLayout,
-		NULL, NULL, NULL, feVariable->dim, feVariable->isCheckpointedAndReloaded, 
-		False, False,
-		feVariable->fieldVariable_Register );
-
-	/* Add new analyticFeVariable to list */
-	Stg_ObjectList_Append( self->analyticFeVariableList, analyticFeVariable );
-
-	/* Create Magnitude Field */
-	tmpName = Stg_Object_AppendSuffix( analyticFeVariable, (Name)"Magnitude"  );
-	analyticMagField = OperatorFeVariable_NewUnary( tmpName, self->context, analyticFeVariable, "Magnitude" );
-	Memory_Free( tmpName );
-
-	/* Create Error field - The the calculated field minus the analytic field */
-	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"ErrorField"  );
-	errorField = OperatorFeVariable_NewBinary( tmpName, self->context, feVariable, analyticFeVariable, "Subtraction" );
-	Memory_Free( tmpName );
-	
-	/* Create Error magnitude field */
-	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"ErrorMagnitudeField"  );
-	errorMagnitudeField = OperatorFeVariable_NewUnary( tmpName, self->context, errorField, "Magnitude" );
-	Memory_Free( tmpName );
-	Stg_ObjectList_Append( self->errorMagnitudeFieldList, errorMagnitudeField ); /* Add it to list */
-
-	/* Create Relative Error magnitude field - The magnitude of relative error */
-	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"RelativeErrorMagnitudeField"  );
-	relativeErrorMagnitudeField = OperatorFeVariable_NewBinary( tmpName, self->context, errorMagnitudeField, analyticMagField, "ScalarDivision" );
-	Memory_Free( tmpName );
-	Stg_ObjectList_Append( self->relativeErrorMagnitudeFieldList, relativeErrorMagnitudeField ); /* Add it to list */
-
-	/* Create Stream for field to dump error information to */
-	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"ErrorFile"  );
-	stream = Journal_Register( Dump_Type, (Name)tmpName  );
-	Stg_ObjectList_GlobalPointerAppend( self->streamList, stream, (Name)tmpName  );
-	Stream_Enable( stream, True );
-	Stream_RedirectFile_WithPrependedPath( stream, self->context->outputPath, tmpName );
-	Memory_Free( tmpName );
-
-	/* Get tolerance from dictionary */
-	count = Stg_ObjectList_Count( self->analyticFeVariableList );
-	self->toleranceList = Memory_Realloc_Array( self->toleranceList, double, count );
-	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Tolerance"  );
-	self->toleranceList[ count - 1 ] = Dictionary_GetDouble_WithDefault( self->context->dictionary, (Dictionary_Entry_Key)tmpName, 0.0 );
-	Memory_Free( tmpName  );
-
-	/* Add components to LiveComponentRegister so they will be visible to other components 
-	 * and will be built, initialised and  deleted */
-	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) dataVariable );
-	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) dofLayout );
-	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) analyticFeVariable );
-	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) analyticMagField );
-	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) errorField );
-	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) errorMagnitudeField );
-	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) relativeErrorMagnitudeField );
-
-	return analyticFeVariable;
-}
-
-FeVariable* AnalyticSolution_CreateAnalyticVectorField( void* analyticSolution, FeVariable* vectorField, AnalyticSolution_SolutionFunction* solutionFunction ) {
-	AnalyticSolution*	self = (AnalyticSolution*) analyticSolution;
-	FeVariable*			analyticVectorField;
-
-	analyticVectorField = AnalyticSolution_CreateAnalyticField( self, vectorField );
-
-	return analyticVectorField;
-}
-
-FeVariable* AnalyticSolution_CreateAnalyticSymmetricTensorField( void* analyticSolution, FeVariable* vectorField ) {
-  AnalyticSolution*		self = (AnalyticSolution*) analyticSolution;
-  FeVariable*				analyticVectorField;
-  OperatorFeVariable*	analyticVectorInvField;
-  char					*tmpName, *tmpName2;
-  DofLayout*				dofLayout;
-
-  analyticVectorField = AnalyticSolution_CreateAnalyticField( self, vectorField );
-
-  /* Create new dof layout */
-  tmpName = Stg_Object_AppendSuffix( analyticVectorField, (Name)"Analytic-DofLayout"  );
-  dofLayout = DofLayout_New( tmpName, self->context, self->context->variable_Register, Mesh_GetDomainSize( analyticVectorField->feMesh, MT_VERTEX ), NULL );
-
-  /* Create Invariant Field */
-  tmpName2 = Stg_Object_AppendSuffix( analyticVectorField, (Name)"Invariant"  );
-  analyticVectorInvField = OperatorFeVariable_NewUnary( tmpName2, self->context, analyticVectorField, "SymmetricTensor_Invariant" );
-
-  Memory_Free( tmpName );
-  Memory_Free( tmpName2 );
-
-  LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) analyticVectorInvField );
-
-  return analyticVectorField;
-}
-
-FeVariable* AnalyticSolution_GetFeVariableFromAnalyticFeVariable( void* analyticSolution, FeVariable* analyticFeVariable ) {
-	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
-	Index             analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
-	Index             analyticFeVariable_I;
-
-	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->feVariableList ) );
-
-	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
-		/* find the index of analytic feVariable and then return the corresponding feVariable */
-		if ( analyticFeVariable == (FeVariable*) Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ) )
-			return (FeVariable*) Stg_ObjectList_At( self->feVariableList, analyticFeVariable_I );
-	}
-
-	return NULL;
-}
-	
-InterpolationResult AnalyticSolution_InterpolateValueFromNormalFeVariable( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* value ) {
-	AnalyticSolution*	self = (AnalyticSolution*) analyticSolution;
-	FeVariable*       normalFeVariable;
-
-	normalFeVariable = AnalyticSolution_GetFeVariableFromAnalyticFeVariable( self, analyticFeVariable );
-
-	return FieldVariable_InterpolateValueAt( normalFeVariable, coord, value );
-}
-
-AnalyticSolution* AnalyticSolution_GetAnalyticSolution() {
-	Journal_Firewall( mySingleton != NULL , Journal_Register( Error_Type, (Name)"AnalyticSolution"  ),
-		"Error in function %s: The Singleton Ptr is NULL, meaning the AnalyticSolution has not been created yet\n", __func__ );
-
-	return mySingleton;
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/AnalyticSolution.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/AnalyticSolution.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,636 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: AnalyticSolution.c 1137 2008-05-23 05:57:48Z RobertTurnbull $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "types.h"
+#include "AnalyticSolution.h"
+#include "FeVariable.h"
+#include "OperatorFeVariable.h"
+#include "FeMesh.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+const Type AnalyticSolution_Type = "AnalyticSolution";
+/* Singleton for analytical solution */
+AnalyticSolution* mySingleton = NULL;
+
+void* _AnalyticSolution_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(AnalyticSolution);
+	Type                                                      type = AnalyticSolution_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _AnalyticSolution_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _AnalyticSolution_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _AnalyticSolution_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+AnalyticSolution* _AnalyticSolution_New(  ANALYTICSOLUTION_DEFARGS  )
+{
+	AnalyticSolution*			self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(AnalyticSolution) );
+	/* Construct using parent */
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (AnalyticSolution*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+
+	/* Assign singleton ptr */
+	mySingleton = self;
+	return self;
+}
+
+void _AnalyticSolution_Init( AnalyticSolution* self, Swarm* integrationSwarm, LiveComponentRegister* LC_Register, AbstractContext* context, Bool verboseMode ) {
+	self->LC_Register = LC_Register;
+	self->integrationSwarm = integrationSwarm;
+	self->context = (DomainContext*)context;
+
+	/* Initialise AnalyticFunctions */
+	self->_getAnalyticVelocity = NULL;
+	self->_getAnalyticPressure = NULL;
+	self->_getAnalyticTotalStress = NULL;
+	self->_getAnalyticStrainRate = NULL;
+
+	/* Create Lists */
+	self->feVariableList             = Stg_ObjectList_New();
+	self->analyticFeVariableList     = Stg_ObjectList_New();
+	self->analyticFeVariableFuncList = Stg_ObjectList_New();
+	self->errorMagnitudeFieldList    = Stg_ObjectList_New();
+	self->relativeErrorMagnitudeFieldList    = Stg_ObjectList_New();
+	self->streamList                 = Stg_ObjectList_New();
+
+	/* Add functions to entry points */
+	EntryPoint_AppendClassHook( Context_GetEntryPoint( context, AbstractContext_EP_UpdateClass ), 
+                                    self->type, (void*)AnalyticSolution_Update, self->type, self );
+	EP_AppendClassHook( Context_GetEntryPoint( context, AbstractContext_EP_DumpClass ), 
+			AnalyticSolution_TestAll, self );
+
+	if ( verboseMode ) {
+		Stream* infoStream = Journal_MyStream( Info_Type, self );
+		Stream_SetLevel( infoStream, 2 );
+	}
+}
+
+void _AnalyticSolution_Delete( void* analyticSolution ) {
+	AnalyticSolution* self = (AnalyticSolution*)analyticSolution;
+
+	Stg_Class_Delete( self->feVariableList );
+	Stg_Class_Delete( self->analyticFeVariableList );
+	Stg_Class_Delete( self->analyticFeVariableFuncList );
+	Stg_Class_Delete( self->errorMagnitudeFieldList );
+	Stg_Class_Delete( self->relativeErrorMagnitudeFieldList );
+	Stg_Class_Delete( self->streamList );
+
+	if ( self->toleranceList )
+		Memory_Free( self->toleranceList );
+	
+	/* Stg_Class_Delete parent*/
+	_Stg_Component_Delete( self );
+}
+
+void _AnalyticSolution_Print( void* analyticSolution, Stream* stream ) {
+	AnalyticSolution* self = (AnalyticSolution*)analyticSolution;
+	
+	/* Print parent */
+	_Stg_Component_Print( self, stream );
+	
+}
+
+void* _AnalyticSolution_Copy( const void* analyticSolution, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	abort();
+	return NULL;
+}
+
+void _AnalyticSolution_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) 
+{
+	AnalyticSolution* self = (AnalyticSolution*)analyticSolution;
+	AbstractContext*  context;
+	Swarm*            integrationSwarm;
+	Bool              verboseMode;
+
+	context = (AbstractContext*)(Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", DomainContext, False, data ));
+	if( !context  )
+          context = (AbstractContext*)(Stg_ComponentFactory_ConstructByName( cf, (Name)"context", DomainContext, True, data  ));
+
+	integrationSwarm = Stg_ComponentFactory_ConstructByName( cf, (Name)"gaussSwarm", Swarm, True, data  ); 
+	verboseMode = Stg_ComponentFactory_GetRootDictBool( cf, (Dictionary_Entry_Key)"analyticSolutionVerbose", False  );
+
+	_AnalyticSolution_Init( self, integrationSwarm, cf->LCRegister, context, verboseMode );
+}
+
+void _AnalyticSolution_Build( void* analyticSolution, void* data ) {
+	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
+	Index             analyticFeVariableCount;
+	Index             analyticFeVariable_I;
+
+   Stg_Component_Build( self->integrationSwarm, data, False );
+	/* Build all the analytic fields registered to this AnalyticSolution */
+	AnalyticSolution_BuildAllAnalyticFields( self, data );
+	
+	analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
+	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
+
+	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
+		Stg_Component_Build( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Build( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Build( Stg_ObjectList_At( self->relativeErrorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
+	}
+}
+
+void _AnalyticSolution_Initialise( void* analyticSolution, void* data ) {
+	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
+	Index             analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
+	Index             analyticFeVariable_I;
+
+   Stg_Component_Initialise( self->integrationSwarm, data, False );
+	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
+
+	/* Assign values to all analytic fields */
+	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
+		Stg_Component_Initialise( Stg_ObjectList_At( self->feVariableList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Initialise( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Initialise( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Initialise( Stg_ObjectList_At( self->relativeErrorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
+
+		AnalyticSolution_PutAnalyticSolutionOntoNodes( self, analyticFeVariable_I );
+	}
+}
+
+/* This function is called when the 'Update' phase happens */
+void AnalyticSolution_Update( void* analyticSolution ) {
+	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
+
+	self->_initialise( self, NULL );
+}
+
+void _AnalyticSolution_Execute( void* analyticSolution, void* data ) {
+}
+
+void _AnalyticSolution_Destroy( void* analyticSolution, void* data ) {
+	AnalyticSolution* self = (AnalyticSolution*)analyticSolution;
+	Index             analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
+	Index             analyticFeVariable_I;
+
+   Stg_Component_Destroy( self, data, False );
+   
+   Stg_Component_Destroy( self->integrationSwarm, data, False );
+	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
+
+	/* Destroy all analytic fields */
+	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
+		Stg_Component_Destroy( Stg_ObjectList_At( self->feVariableList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Destroy( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Destroy( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Destroy( Stg_ObjectList_At( self->relativeErrorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
+	}
+
+}
+
+void AnalyticSolution_PutAnalyticSolutionOntoNodes( void* analyticSolution, Index analyticFeVariable_I ) {
+	AnalyticSolution*                            self = (AnalyticSolution*) analyticSolution;
+	AnalyticSolution_SolutionFunction*           solutionFunction;
+	FeVariable*                                  analyticFeVariable;
+	double*                                      coord;
+	Dof_Index                                    dofAtEachNodeCount;
+	Node_DomainIndex                             dNode_I;
+	double*                                      value;
+	Stream*                                      infoStream = Journal_MyStream( Info_Type, self );
+	FeVariable*                                  feVariable;
+	FeMesh*						mesh;
+
+	/* Do some error checking */
+	assert( Stg_ObjectList_Count( self->analyticFeVariableList ) >= analyticFeVariable_I );
+
+	/* Grab pointers */
+	analyticFeVariable = 
+		Stg_CheckType( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), FeVariable );
+	mesh = analyticFeVariable->feMesh;
+	solutionFunction   = (AnalyticSolution_SolutionFunction*) 
+		Stg_ObjectList_ObjectAt( self->analyticFeVariableFuncList, analyticFeVariable_I );
+	feVariable = AnalyticSolution_GetFeVariableFromAnalyticFeVariable( self, analyticFeVariable );
+
+	/* Get number of degrees of freedom at each node (assuming they are the same) */
+	dofAtEachNodeCount = analyticFeVariable->fieldComponentCount;
+	value = Memory_Alloc_Array( double, dofAtEachNodeCount, "value" );
+
+	/* Loop over all the nodes - applying the analytic solution */
+	for ( dNode_I = 0 ; dNode_I < Mesh_GetDomainSize( mesh, MT_VERTEX ); dNode_I++ ) {
+		coord = Mesh_GetVertex( mesh, dNode_I );
+
+		/* Calculate value at node */
+		memset( value, 0, dofAtEachNodeCount * sizeof(double) );
+		solutionFunction( self, analyticFeVariable, coord, value );
+
+		/* Put value on node */
+		FeVariable_SetValueAtNode( analyticFeVariable, dNode_I, value );
+
+		/* Print verbose information */
+		if ( Stream_IsPrintableLevel( infoStream, 2 ) ) {
+			Dimension_Index dim = analyticFeVariable->dim;
+			Dimension_Index dim_I;
+			Dof_Index       dof_I;
+
+			/* Print Coord */
+			Journal_Printf( infoStream, "Node = %u Coord ( ", dNode_I );
+			for ( dim_I = 0 ; dim_I < dim - 1 ; dim_I++ ) {
+				Journal_Printf( infoStream, "%g, ", coord[ dim_I ] );
+			}
+			Journal_Printf( infoStream, "%g ) ", coord[ dim_I ] );
+
+			/* Print Analytic Values */
+			Journal_Printf( infoStream, "%s ( ", analyticFeVariable->name );
+			for ( dof_I = 0 ; dof_I < dofAtEachNodeCount - 1 ; dof_I++ ) {
+				Journal_Printf( infoStream, "%g, ", value[ dof_I ] );
+			}
+			Journal_Printf( infoStream, "%g ) ", value[ dof_I ] );
+
+			/* Print FeVariable Values */
+			memset( value, 0, dofAtEachNodeCount * sizeof(double) );
+			FeVariable_GetValueAtNode( feVariable, dNode_I, value );
+			Journal_Printf( infoStream, "%s ( ", feVariable->name );
+			for ( dof_I = 0 ; dof_I < dofAtEachNodeCount - 1 ; dof_I++ ) {
+				Journal_Printf( infoStream, "%g, ", value[ dof_I ] );
+			}
+			Journal_Printf( infoStream, "%g )\n", value[ dof_I ] );			
+		}
+	}
+
+	Memory_Free( value );
+}
+
+void AnalyticSolution_Test( void* analyticSolution, Index analyticFeVariable_I ) {
+	AnalyticSolution*                            self = (AnalyticSolution*) analyticSolution;
+	FeVariable*                                  errorMagnitudeField;
+	double                                       result;
+	Stream*                                      stream;
+	double                                       tolerance;
+	Stream*                                      infoStream = Journal_MyStream( Info_Type, self );
+
+	/* Do some error checking */
+	assert( Stg_ObjectList_Count( self->analyticFeVariableList ) >= analyticFeVariable_I );
+
+	/* Grab pointers */
+	errorMagnitudeField = 
+		Stg_CheckType( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), FeVariable );
+
+	stream = (Stream*) Stg_ObjectList_ObjectAt( self->streamList, analyticFeVariable_I );
+	tolerance = self->toleranceList[ analyticFeVariable_I ];
+
+	result = FeVariable_Integrate( errorMagnitudeField, self->integrationSwarm );
+
+	Journal_Printf( stream, "Timestep %u: Total integrated value of '%s' is %s a tolerance %.5g.\n", 
+				self->context->timeStep, errorMagnitudeField->name, result <= tolerance ? "within" : "outside", tolerance );
+	Stream_Flush( stream );
+
+	Journal_Printf( infoStream, "Timestep %u: Total integrated value of '%s' is %g\n", 
+			self->context->timeStep, errorMagnitudeField->name, result );
+}
+	
+
+void AnalyticSolution_TestAll( void* analyticSolution, void* data ) {
+	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
+	Index             analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
+	Index             analyticFeVariable_I;
+
+	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
+
+	/* Assign values to all analytic fields */
+	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
+		AnalyticSolution_Test( self, analyticFeVariable_I );
+	}
+}
+
+void AnalyticSolution_RegisterFeVariableWithAnalyticFunction( void* analyticSolution, FeVariable* feVariable, AnalyticSolution_SolutionFunction* solutionFunction) {
+	AnalyticSolution* self    = (AnalyticSolution*) analyticSolution;
+	char*             tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Analytic"  );
+
+	/* Add feVariable to list */
+	Stg_ObjectList_Append( self->feVariableList, feVariable );
+	/* Add function to list */
+	Stg_ObjectList_GlobalPointerAppend( self->analyticFeVariableFuncList, (void*)solutionFunction, (Name)tmpName );
+	Memory_Free( tmpName  );	
+}
+
+
+FeVariable* AnalyticSolution_RegisterFeVariableFromCF( void* analyticSolution, char* fieldName, AnalyticSolution_SolutionFunction* solutionFunction, Stg_ComponentFactory* cf, Bool isEssential, void* data ) {
+	AnalyticSolution* self    = (AnalyticSolution*) analyticSolution;
+	FeVariable*       field;
+
+	field = Stg_ComponentFactory_ConstructByName( cf, (Name)fieldName, FeVariable, isEssential, data ); 
+	if ( field  )
+		AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, field, solutionFunction );
+
+	return field;
+}
+
+
+void AnalyticSolution_BuildAllAnalyticFields( void* analyticSolution, void* data ) {
+	AnalyticSolution* self       = (AnalyticSolution*) analyticSolution;
+	FeVariable*       feVariable = NULL;
+	Stream*           errStream  = Journal_Register( Error_Type, (Name)"AnalyticSolution"  );
+	unsigned          feVar_I, feVarCount;
+
+	feVarCount = Stg_ObjectList_Count( self->feVariableList );
+
+	for( feVar_I = 0 ; feVar_I < feVarCount ; feVar_I++ ) {
+		feVariable = (FeVariable*)Stg_ObjectList_At( self->feVariableList, feVar_I );
+		
+		/* Check to see whether this field has already been added */
+		
+
+		/* Build the FeVariable here ensuring the analytic "copy" of it has valid values */
+		Stg_Component_Build( feVariable, data, False ) ;
+		
+		if( feVariable->fieldComponentCount == 1 ) {
+			if( NULL == AnalyticSolution_CreateAnalyticField( self, feVariable ) ) {
+
+				Journal_Firewall( 0 , errStream,
+				"Error in function %s: Error in building analyticSolution for the feVariable %s,\n",
+				__func__ , feVariable );
+			}
+		} else {
+			if( NULL == AnalyticSolution_CreateAnalyticSymmetricTensorField( self, feVariable ) ) {
+
+				Journal_Firewall( 0 , errStream,
+				"Error in function %s: Error in building analyticSolution for the feVariable %s,\n",
+				__func__ , feVariable );
+			}
+		}
+
+	}
+
+
+}
+
+FeVariable* AnalyticSolution_CreateAnalyticField( void* analyticSolution, FeVariable* feVariable ) {
+	AnalyticSolution*                            self = (AnalyticSolution*) analyticSolution;
+	char*                                        tmpName;
+	FeVariable*                                  analyticFeVariable;
+	Variable*                                    dataVariable;
+	DofLayout*                                   dofLayout;
+	Variable_Register*                           variable_Register = self->context->variable_Register;
+	Dof_Index                                    componentsCount   = feVariable->fieldComponentCount;
+	char*                                        variableName[9];
+	Variable_Index                               variable_I;
+	Node_DomainIndex                             node_I;
+	Bool scalar=(componentsCount==1) ? True : False;
+	OperatorFeVariable*                          analyticMagField;
+	OperatorFeVariable*                          errorField;
+	OperatorFeVariable*                          errorMagnitudeField;
+	OperatorFeVariable*                          relativeErrorMagnitudeField;
+	Stream*                                      stream;
+	Index                                        count;
+
+	Stg_Component_Build( feVariable->feMesh, NULL, False );
+
+	/* Create new data Variable */
+	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Analytic-DataVariable" );
+	if ( scalar  ) {
+		Sync*	sync;
+
+		sync = Mesh_GetSync( feVariable->feMesh, MT_VERTEX );
+		dataVariable = Variable_NewScalar( tmpName, (AbstractContext*)self->context, Variable_DataType_Double, (Index*)(unsigned*)&sync->nDomains, NULL, (void**)NULL, variable_Register  );
+	}
+	else {
+		Sync*		sync;
+		unsigned	c_i;
+
+		sync = Mesh_GetSync( feVariable->feMesh, MT_VERTEX );
+
+		/* Create names of variables */
+		assert( componentsCount <= 9 );
+		for ( variable_I = 0 ; variable_I < componentsCount ; variable_I++ ) {
+			Stg_asprintf( &variableName[ variable_I ], "%s-Analytic-ComponentVariable%d", feVariable->name, variable_I );
+		}
+		dataVariable = Variable_NewVector( 	
+				tmpName,
+				(AbstractContext*)self->context,
+				Variable_DataType_Double, 
+				componentsCount,
+				(unsigned*)&sync->nDomains, 
+				NULL, 
+				(void**)NULL, 
+				variable_Register,
+				variableName[0],
+				variableName[1],
+				variableName[2],
+				variableName[3],
+				variableName[4],
+				variableName[5],
+				variableName[6],
+				variableName[7],
+				variableName[8] );
+		for( c_i = 0; c_i < dataVariable->dataTypeCounts[0]; c_i++ )
+			dataVariable->components[c_i]->allocateSelf = True;
+	}
+	Memory_Free( tmpName );
+	dataVariable->allocateSelf = True;
+	
+	/* Create new dof layout */
+	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Analytic-DofLayout"  );
+	dofLayout = DofLayout_New( tmpName, self->context, variable_Register, Mesh_GetDomainSize( feVariable->feMesh, MT_VERTEX ), NULL );
+	if ( scalar ) {
+		DofLayout_AddAllFromVariableArray( dofLayout, 1, &dataVariable );
+	}
+	else {
+		for ( variable_I = 0 ; variable_I < componentsCount ; variable_I++ ) {
+
+			/* We have to set the array ptr ptr for these guys manually - this should be fixed */
+			Variable* variable = Variable_Register_GetByName( variable_Register, variableName[ variable_I ] );
+			variable->arrayPtrPtr = &dataVariable->arrayPtr;
+
+			/* Assign variable to each node */
+			for( node_I = 0; node_I < Mesh_GetDomainSize( feVariable->feMesh, MT_VERTEX ); node_I++ ) {
+				DofLayout_AddDof_ByVarName( dofLayout, variableName[variable_I], node_I );
+			}
+			/* Free Name */
+			Memory_Free( variableName[ variable_I ] );
+		}
+	}
+	Memory_Free( tmpName );
+
+	/* Create new FeVariable */
+	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Analytic"  );
+	analyticFeVariable = FeVariable_New( tmpName, self->context, feVariable->feMesh, feVariable->geometryMesh, dofLayout,
+		NULL, NULL, NULL, feVariable->dim, feVariable->isCheckpointedAndReloaded, 
+		False, False,
+		feVariable->fieldVariable_Register );
+
+	/* Add new analyticFeVariable to list */
+	Stg_ObjectList_Append( self->analyticFeVariableList, analyticFeVariable );
+
+	/* Create Magnitude Field */
+	tmpName = Stg_Object_AppendSuffix( analyticFeVariable, (Name)"Magnitude"  );
+	analyticMagField = OperatorFeVariable_NewUnary( tmpName, self->context, analyticFeVariable, "Magnitude" );
+	Memory_Free( tmpName );
+
+	/* Create Error field - The the calculated field minus the analytic field */
+	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"ErrorField"  );
+	errorField = OperatorFeVariable_NewBinary( tmpName, self->context, feVariable, analyticFeVariable, "Subtraction" );
+	Memory_Free( tmpName );
+	
+	/* Create Error magnitude field */
+	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"ErrorMagnitudeField"  );
+	errorMagnitudeField = OperatorFeVariable_NewUnary( tmpName, self->context, errorField, "Magnitude" );
+	Memory_Free( tmpName );
+	Stg_ObjectList_Append( self->errorMagnitudeFieldList, errorMagnitudeField ); /* Add it to list */
+
+	/* Create Relative Error magnitude field - The magnitude of relative error */
+	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"RelativeErrorMagnitudeField"  );
+	relativeErrorMagnitudeField = OperatorFeVariable_NewBinary( tmpName, self->context, errorMagnitudeField, analyticMagField, "ScalarDivision" );
+	Memory_Free( tmpName );
+	Stg_ObjectList_Append( self->relativeErrorMagnitudeFieldList, relativeErrorMagnitudeField ); /* Add it to list */
+
+	/* Create Stream for field to dump error information to */
+	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"ErrorFile"  );
+	stream = Journal_Register( Dump_Type, (Name)tmpName  );
+	Stg_ObjectList_GlobalPointerAppend( self->streamList, stream, (Name)tmpName  );
+	Stream_Enable( stream, True );
+	Stream_RedirectFile_WithPrependedPath( stream, self->context->outputPath, tmpName );
+	Memory_Free( tmpName );
+
+	/* Get tolerance from dictionary */
+	count = Stg_ObjectList_Count( self->analyticFeVariableList );
+	self->toleranceList = Memory_Realloc_Array( self->toleranceList, double, count );
+	tmpName = Stg_Object_AppendSuffix( feVariable, (Name)"Tolerance"  );
+	self->toleranceList[ count - 1 ] = Dictionary_GetDouble_WithDefault( self->context->dictionary, (Dictionary_Entry_Key)tmpName, 0.0 );
+	Memory_Free( tmpName  );
+
+	/* Add components to LiveComponentRegister so they will be visible to other components 
+	 * and will be built, initialised and  deleted */
+	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) dataVariable );
+	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) dofLayout );
+	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) analyticFeVariable );
+	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) analyticMagField );
+	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) errorField );
+	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) errorMagnitudeField );
+	LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) relativeErrorMagnitudeField );
+
+	return analyticFeVariable;
+}
+
+FeVariable* AnalyticSolution_CreateAnalyticVectorField( void* analyticSolution, FeVariable* vectorField, AnalyticSolution_SolutionFunction* solutionFunction ) {
+	AnalyticSolution*	self = (AnalyticSolution*) analyticSolution;
+	FeVariable*			analyticVectorField;
+
+	analyticVectorField = AnalyticSolution_CreateAnalyticField( self, vectorField );
+
+	return analyticVectorField;
+}
+
+FeVariable* AnalyticSolution_CreateAnalyticSymmetricTensorField( void* analyticSolution, FeVariable* vectorField ) {
+  AnalyticSolution*		self = (AnalyticSolution*) analyticSolution;
+  FeVariable*				analyticVectorField;
+  OperatorFeVariable*	analyticVectorInvField;
+  char					*tmpName, *tmpName2;
+  DofLayout*				dofLayout;
+
+  analyticVectorField = AnalyticSolution_CreateAnalyticField( self, vectorField );
+
+  /* Create new dof layout */
+  tmpName = Stg_Object_AppendSuffix( analyticVectorField, (Name)"Analytic-DofLayout"  );
+  dofLayout = DofLayout_New( tmpName, self->context, self->context->variable_Register, Mesh_GetDomainSize( analyticVectorField->feMesh, MT_VERTEX ), NULL );
+
+  /* Create Invariant Field */
+  tmpName2 = Stg_Object_AppendSuffix( analyticVectorField, (Name)"Invariant"  );
+  analyticVectorInvField = OperatorFeVariable_NewUnary( tmpName2, self->context, analyticVectorField, "SymmetricTensor_Invariant" );
+
+  Memory_Free( tmpName );
+  Memory_Free( tmpName2 );
+
+  LiveComponentRegister_Add( self->LC_Register, (Stg_Component*) analyticVectorInvField );
+
+  return analyticVectorField;
+}
+
+FeVariable* AnalyticSolution_GetFeVariableFromAnalyticFeVariable( void* analyticSolution, FeVariable* analyticFeVariable ) {
+	AnalyticSolution* self = (AnalyticSolution*) analyticSolution;
+	Index             analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
+	Index             analyticFeVariable_I;
+
+	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->feVariableList ) );
+
+	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
+		/* find the index of analytic feVariable and then return the corresponding feVariable */
+		if ( analyticFeVariable == (FeVariable*) Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ) )
+			return (FeVariable*) Stg_ObjectList_At( self->feVariableList, analyticFeVariable_I );
+	}
+
+	return NULL;
+}
+	
+InterpolationResult AnalyticSolution_InterpolateValueFromNormalFeVariable( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* value ) {
+	AnalyticSolution*	self = (AnalyticSolution*) analyticSolution;
+	FeVariable*       normalFeVariable;
+
+	normalFeVariable = AnalyticSolution_GetFeVariableFromAnalyticFeVariable( self, analyticFeVariable );
+
+	return FieldVariable_InterpolateValueAt( normalFeVariable, coord, value );
+}
+
+AnalyticSolution* AnalyticSolution_GetAnalyticSolution() {
+	Journal_Firewall( mySingleton != NULL , Journal_Register( Error_Type, (Name)"AnalyticSolution"  ),
+		"Error in function %s: The Singleton Ptr is NULL, meaning the AnalyticSolution has not been created yet\n", __func__ );
+
+	return mySingleton;
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/BilinearElementType.c
--- a/Discretisation/src/BilinearElementType.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,311 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: BilinearElementType.c 1179 2008-07-15 05:28:11Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType.h"
-#include "BilinearElementType.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <math.h>
-
-const Type BilinearElementType_Type = "BilinearElementType";
-
-#define _BilinearElementType_NodeCount 4
-
-BilinearElementType* BilinearElementType_New( Name name ) {
-  BilinearElementType* self = (BilinearElementType*)_BilinearElementType_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, _BilinearElementType_NodeCount );
-	_BilinearElementType_Init( self );
-
-	return self;
-}
-
-void* _BilinearElementType_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(BilinearElementType);
-	Type                                                                                    type = BilinearElementType_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _BilinearElementType_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _BilinearElementType_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = _BilinearElementType_DefaultNew;
-	Stg_Component_ConstructFunction*                                                  _construct = _BilinearElementType_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _BilinearElementType_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _BilinearElementType_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _BilinearElementType_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _BilinearElementType_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _BilinearElementType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _BilinearElementType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _BilinearElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
-
-	return _BilinearElementType_New(  BILINEARELEMENTTYPE_PASSARGS  );
-}
-
-BilinearElementType* _BilinearElementType_New(  BILINEARELEMENTTYPE_DEFARGS  ) {
-	BilinearElementType* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(BilinearElementType) );
-	self = (BilinearElementType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual functions */
-	
-	return self;
-}
-
-void _BilinearElementType_Init( BilinearElementType* self ) {
-	Dimension_Index dim, dim_I=0;
-	/* General and Virtual info should already be set */
-	
-	/* set the dimensionality of the element */
-	dim = self->dim = 2;
-
-	for ( dim_I = 0; dim_I < dim; dim_I++ ) {
-		self->minElLocalCoord[dim_I] = -1;
-		self->maxElLocalCoord[dim_I] = 1;
-		self->elLocalLength[dim_I] = self->maxElLocalCoord[dim_I] - self->minElLocalCoord[dim_I];
-	}
-
-	self->triInds = Memory_Alloc_2DArray( unsigned, dim, 3, (Name)"BilinearElementType::triInds" );
-	self->triInds[0][0] = 0; self->triInds[0][1] = 1; self->triInds[0][2] = 2;
-	self->triInds[1][0] = 1; self->triInds[1][1] = 3; self->triInds[1][2] = 2;
-}
-
-void _BilinearElementType_Delete( void* elementType ) {
-	BilinearElementType* self = (BilinearElementType*)elementType;
-
-	/* Stg_Class_Delete parent */
-	_ElementType_Delete( self  );
-}
-
-void _BilinearElementType_Print( void* elementType, Stream* stream ) {
-	BilinearElementType* self = (BilinearElementType*)elementType;
-	Dimension_Index dim_I=0;
-
-	/* General info */
-	Journal_Printf( stream, "BilinearElementType (ptr): %p\n", self );
-	
-	/* Print parent */
-	_ElementType_Print( self, stream );
-	
-	/* Virtual info */
-	
-	/* BilinearElementType info */
-	Journal_Printf( stream, "self->minElLocalCoord: (", self );
-	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
-		Journal_Printf( stream, "%0.5f,", self->minElLocalCoord[dim_I] );
-	}
-	Journal_Printf( stream, ")\n", self );
-	Journal_Printf( stream, "self->maxElLocalCoord: (", self );
-	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
-		Journal_Printf( stream, "%0.5f,", self->maxElLocalCoord[dim_I] );
-	}	
-	Journal_Printf( stream, ")\n", self );
-	Journal_Printf( stream, "self->elLocalLength: (", self );
-	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
-		Journal_Printf( stream, "%0.5f,", self->elLocalLength[dim_I] );
-	}
-	Journal_Printf( stream, ")\n", self );
-}
-
-void _BilinearElementType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ) {
-}
-	
-void _BilinearElementType_Initialise( void* elementType, void *data ){
-	BilinearElementType*	self	= (BilinearElementType*) elementType;
-
-	self->faceNodes = Memory_Alloc_2DArray( unsigned, 4, 2, (Name)"node indices for element faces"  );
-
-	self->faceNodes[0][0] = 0; self->faceNodes[0][1] = 1;
-	self->faceNodes[1][0] = 2; self->faceNodes[1][1] = 3;
-	self->faceNodes[2][0] = 0; self->faceNodes[2][1] = 2;
-	self->faceNodes[3][0] = 1; self->faceNodes[3][1] = 3;
-}
-	
-void _BilinearElementType_Execute( void* elementType, void *data ){
-}
-	
-void _BilinearElementType_Destroy( void* elementType, void *data ){
-	BilinearElementType*	self	= (BilinearElementType*) elementType;
-
-	FreeArray( self->triInds );
-
-	Memory_Free( self->faceNodes );	
-	Memory_Free( self->evaluatedShapeFunc );
-	Memory_Free( self->GNi );
-	
-	_ElementType_Destroy( self, data );
-}
-
-void _BilinearElementType_Build( void* elementType, void *data ) {
-	BilinearElementType*	self	= (BilinearElementType*) elementType;
-
-	self->evaluatedShapeFunc = Memory_Alloc_Array( double, self->nodeCount, "evaluatedShapeFuncs" );
-	self->GNi = Memory_Alloc_2DArray( double, self->dim, self->nodeCount, (Name)"localShapeFuncDerivitives"  );
-}
-
-/*
- - Shape function definitions
- - Local node numbering convention for billinear element (xi, eta)
- - Local coordinate domain spans  -1 <= xi,eta <= 1
-
-  eta
-   |
-3-----2
-|  |__|___xi
-|     |
-0-----1
-
-*/
-void _BilinearElementType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
-	double xi, eta;
-	
-	xi  = localCoord[0];
-	eta = localCoord[1];
-	
-	evaluatedValues[0] = 0.25*( 1.0-xi )*( 1.0-eta );
-	evaluatedValues[1] = 0.25*( 1.0+xi )*( 1.0-eta );
-	evaluatedValues[3] = 0.25*( 1.0+xi )*( 1.0+eta );
-	evaluatedValues[2] = 0.25*( 1.0-xi )*( 1.0+eta );
-}
-
-
-void _BilinearElementType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
-		double** const evaluatedDerivatives ) 
-{		
-	double xi, eta;
-	
-	xi  = localCoord[0];
-	eta = localCoord[1];
-	
-	/* derivatives wrt xi */
-	evaluatedDerivatives[0][0] = - 0.25*( 1.0 - eta );
-	evaluatedDerivatives[0][1] =   0.25*( 1.0 - eta );
-	evaluatedDerivatives[0][3] =   0.25*( 1.0 + eta );
-	evaluatedDerivatives[0][2] = - 0.25*( 1.0 + eta );
-	
-	/* derivatives wrt eta */
-	evaluatedDerivatives[1][0] = - 0.25*( 1.0 - xi );
-	evaluatedDerivatives[1][1] = - 0.25*( 1.0 + xi );
-	evaluatedDerivatives[1][3] =   0.25*( 1.0 + xi );
-	evaluatedDerivatives[1][2] =   0.25*( 1.0 - xi );
-}
-
-
-#if 0
-/*
-** Calculates the barycenter of a triangle with respect to some point.
-*/
-
-void _BilinearElementType_ConvertGlobalCoordToElLocal(
-		void*		elementType,
-		void*		_mesh, 
-		unsigned	element, 
-		const double*	globalCoord,
-		double*		elLocalCoord )
-{
-	BilinearElementType*	self = (BilinearElementType*)elementType;
-	Mesh*			mesh = (Mesh*)_mesh;
-	unsigned		inside;
-	double			bc[3];
-	static double		lCrds[4][3] = {{-1.0, -1.0, 0.0}, {1.0, -1.0, 0.0}, 
-					       {-1.0, 1.0, 0.0}, {1.0, 1.0, 0.0}};
-	unsigned		nInc, *inc;
-	unsigned		bc_i;
-
-	Mesh_GetIncidence( mesh, MT_FACE, element, MT_VERTEX, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = IArray_GetPtr( self->inc );
-	assert( nInc == 4 );
-
-	insist( Simplex_Search2D( mesh->verts, inc, 2, self->triInds, (double*)globalCoord, bc, &inside ), == True );
-
-	elLocalCoord[0] = bc[0] * lCrds[self->triInds[inside][0]][0];
-	elLocalCoord[1] = bc[0] * lCrds[self->triInds[inside][0]][1];
-	for( bc_i = 1; bc_i < 3; bc_i++ ) {
-		elLocalCoord[0] += bc[bc_i] * lCrds[self->triInds[inside][bc_i]][0];
-		elLocalCoord[1] += bc[bc_i] * lCrds[self->triInds[inside][bc_i]][1];
-	}
-}
-#endif
-
-double _BilinearElementType_JacobianDeterminantSurface( 
-		void* elementType, 
-		void* _mesh, 
-		unsigned element_I,
-		const double localCoord[],
-		unsigned face_I, 
-		unsigned norm ) 
-{
-	BilinearElementType*	self		= (BilinearElementType*) elementType;
-	Mesh*			mesh		= (Mesh*)_mesh;
-	unsigned		surfaceDim	= ( norm + 1 ) % 2;
-	double			x[2];
-	double			detJac;
-	Index			nodes[2];
-
-	ElementType_GetFaceNodes( self, mesh, element_I, face_I, 2, nodes );
-
-	x[0] = Mesh_GetVertex( mesh, nodes[0] )[surfaceDim];
-	x[1] = Mesh_GetVertex( mesh, nodes[1] )[surfaceDim];
-
-	detJac = 0.5 * ( x[1] - x[0] );
-
-	return fabs( detJac );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/BilinearElementType.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/BilinearElementType.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,311 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: BilinearElementType.c 1179 2008-07-15 05:28:11Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType.h"
+#include "BilinearElementType.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+const Type BilinearElementType_Type = "BilinearElementType";
+
+#define _BilinearElementType_NodeCount 4
+
+BilinearElementType* BilinearElementType_New( Name name ) {
+  BilinearElementType* self = (BilinearElementType*)_BilinearElementType_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, _BilinearElementType_NodeCount );
+	_BilinearElementType_Init( self );
+
+	return self;
+}
+
+void* _BilinearElementType_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(BilinearElementType);
+	Type                                                                                    type = BilinearElementType_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _BilinearElementType_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _BilinearElementType_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = _BilinearElementType_DefaultNew;
+	Stg_Component_ConstructFunction*                                                  _construct = _BilinearElementType_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _BilinearElementType_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _BilinearElementType_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _BilinearElementType_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _BilinearElementType_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _BilinearElementType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _BilinearElementType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _BilinearElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
+
+	return _BilinearElementType_New(  BILINEARELEMENTTYPE_PASSARGS  );
+}
+
+BilinearElementType* _BilinearElementType_New(  BILINEARELEMENTTYPE_DEFARGS  ) {
+	BilinearElementType* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(BilinearElementType) );
+	self = (BilinearElementType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual functions */
+	
+	return self;
+}
+
+void _BilinearElementType_Init( BilinearElementType* self ) {
+	Dimension_Index dim, dim_I=0;
+	/* General and Virtual info should already be set */
+	
+	/* set the dimensionality of the element */
+	dim = self->dim = 2;
+
+	for ( dim_I = 0; dim_I < dim; dim_I++ ) {
+		self->minElLocalCoord[dim_I] = -1;
+		self->maxElLocalCoord[dim_I] = 1;
+		self->elLocalLength[dim_I] = self->maxElLocalCoord[dim_I] - self->minElLocalCoord[dim_I];
+	}
+
+	self->triInds = Memory_Alloc_2DArray( unsigned, dim, 3, (Name)"BilinearElementType::triInds" );
+	self->triInds[0][0] = 0; self->triInds[0][1] = 1; self->triInds[0][2] = 2;
+	self->triInds[1][0] = 1; self->triInds[1][1] = 3; self->triInds[1][2] = 2;
+}
+
+void _BilinearElementType_Delete( void* elementType ) {
+	BilinearElementType* self = (BilinearElementType*)elementType;
+
+	/* Stg_Class_Delete parent */
+	_ElementType_Delete( self  );
+}
+
+void _BilinearElementType_Print( void* elementType, Stream* stream ) {
+	BilinearElementType* self = (BilinearElementType*)elementType;
+	Dimension_Index dim_I=0;
+
+	/* General info */
+	Journal_Printf( stream, "BilinearElementType (ptr): %p\n", self );
+	
+	/* Print parent */
+	_ElementType_Print( self, stream );
+	
+	/* Virtual info */
+	
+	/* BilinearElementType info */
+	Journal_Printf( stream, "self->minElLocalCoord: (", self );
+	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
+		Journal_Printf( stream, "%0.5f,", self->minElLocalCoord[dim_I] );
+	}
+	Journal_Printf( stream, ")\n", self );
+	Journal_Printf( stream, "self->maxElLocalCoord: (", self );
+	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
+		Journal_Printf( stream, "%0.5f,", self->maxElLocalCoord[dim_I] );
+	}	
+	Journal_Printf( stream, ")\n", self );
+	Journal_Printf( stream, "self->elLocalLength: (", self );
+	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
+		Journal_Printf( stream, "%0.5f,", self->elLocalLength[dim_I] );
+	}
+	Journal_Printf( stream, ")\n", self );
+}
+
+void _BilinearElementType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ) {
+}
+	
+void _BilinearElementType_Initialise( void* elementType, void *data ){
+	BilinearElementType*	self	= (BilinearElementType*) elementType;
+
+	self->faceNodes = Memory_Alloc_2DArray( unsigned, 4, 2, (Name)"node indices for element faces"  );
+
+	self->faceNodes[0][0] = 0; self->faceNodes[0][1] = 1;
+	self->faceNodes[1][0] = 2; self->faceNodes[1][1] = 3;
+	self->faceNodes[2][0] = 0; self->faceNodes[2][1] = 2;
+	self->faceNodes[3][0] = 1; self->faceNodes[3][1] = 3;
+}
+	
+void _BilinearElementType_Execute( void* elementType, void *data ){
+}
+	
+void _BilinearElementType_Destroy( void* elementType, void *data ){
+	BilinearElementType*	self	= (BilinearElementType*) elementType;
+
+	FreeArray( self->triInds );
+
+	Memory_Free( self->faceNodes );	
+	Memory_Free( self->evaluatedShapeFunc );
+	Memory_Free( self->GNi );
+	
+	_ElementType_Destroy( self, data );
+}
+
+void _BilinearElementType_Build( void* elementType, void *data ) {
+	BilinearElementType*	self	= (BilinearElementType*) elementType;
+
+	self->evaluatedShapeFunc = Memory_Alloc_Array( double, self->nodeCount, "evaluatedShapeFuncs" );
+	self->GNi = Memory_Alloc_2DArray( double, self->dim, self->nodeCount, (Name)"localShapeFuncDerivitives"  );
+}
+
+/*
+ - Shape function definitions
+ - Local node numbering convention for billinear element (xi, eta)
+ - Local coordinate domain spans  -1 <= xi,eta <= 1
+
+  eta
+   |
+3-----2
+|  |__|___xi
+|     |
+0-----1
+
+*/
+void _BilinearElementType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
+	double xi, eta;
+	
+	xi  = localCoord[0];
+	eta = localCoord[1];
+	
+	evaluatedValues[0] = 0.25*( 1.0-xi )*( 1.0-eta );
+	evaluatedValues[1] = 0.25*( 1.0+xi )*( 1.0-eta );
+	evaluatedValues[3] = 0.25*( 1.0+xi )*( 1.0+eta );
+	evaluatedValues[2] = 0.25*( 1.0-xi )*( 1.0+eta );
+}
+
+
+void _BilinearElementType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
+		double** const evaluatedDerivatives ) 
+{		
+	double xi, eta;
+	
+	xi  = localCoord[0];
+	eta = localCoord[1];
+	
+	/* derivatives wrt xi */
+	evaluatedDerivatives[0][0] = - 0.25*( 1.0 - eta );
+	evaluatedDerivatives[0][1] =   0.25*( 1.0 - eta );
+	evaluatedDerivatives[0][3] =   0.25*( 1.0 + eta );
+	evaluatedDerivatives[0][2] = - 0.25*( 1.0 + eta );
+	
+	/* derivatives wrt eta */
+	evaluatedDerivatives[1][0] = - 0.25*( 1.0 - xi );
+	evaluatedDerivatives[1][1] = - 0.25*( 1.0 + xi );
+	evaluatedDerivatives[1][3] =   0.25*( 1.0 + xi );
+	evaluatedDerivatives[1][2] =   0.25*( 1.0 - xi );
+}
+
+
+#if 0
+/*
+** Calculates the barycenter of a triangle with respect to some point.
+*/
+
+void _BilinearElementType_ConvertGlobalCoordToElLocal(
+		void*		elementType,
+		void*		_mesh, 
+		unsigned	element, 
+		const double*	globalCoord,
+		double*		elLocalCoord )
+{
+	BilinearElementType*	self = (BilinearElementType*)elementType;
+	Mesh*			mesh = (Mesh*)_mesh;
+	unsigned		inside;
+	double			bc[3];
+	static double		lCrds[4][3] = {{-1.0, -1.0, 0.0}, {1.0, -1.0, 0.0}, 
+					       {-1.0, 1.0, 0.0}, {1.0, 1.0, 0.0}};
+	unsigned		nInc, *inc;
+	unsigned		bc_i;
+
+	Mesh_GetIncidence( mesh, MT_FACE, element, MT_VERTEX, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = IArray_GetPtr( self->inc );
+	assert( nInc == 4 );
+
+	insist( Simplex_Search2D( mesh->verts, inc, 2, self->triInds, (double*)globalCoord, bc, &inside ), == True );
+
+	elLocalCoord[0] = bc[0] * lCrds[self->triInds[inside][0]][0];
+	elLocalCoord[1] = bc[0] * lCrds[self->triInds[inside][0]][1];
+	for( bc_i = 1; bc_i < 3; bc_i++ ) {
+		elLocalCoord[0] += bc[bc_i] * lCrds[self->triInds[inside][bc_i]][0];
+		elLocalCoord[1] += bc[bc_i] * lCrds[self->triInds[inside][bc_i]][1];
+	}
+}
+#endif
+
+double _BilinearElementType_JacobianDeterminantSurface( 
+		void* elementType, 
+		void* _mesh, 
+		unsigned element_I,
+		const double localCoord[],
+		unsigned face_I, 
+		unsigned norm ) 
+{
+	BilinearElementType*	self		= (BilinearElementType*) elementType;
+	Mesh*			mesh		= (Mesh*)_mesh;
+	unsigned		surfaceDim	= ( norm + 1 ) % 2;
+	double			x[2];
+	double			detJac;
+	Index			nodes[2];
+
+	ElementType_GetFaceNodes( self, mesh, element_I, face_I, 2, nodes );
+
+	x[0] = Mesh_GetVertex( mesh, nodes[0] )[surfaceDim];
+	x[1] = Mesh_GetVertex( mesh, nodes[1] )[surfaceDim];
+
+	detJac = 0.5 * ( x[1] - x[0] );
+
+	return fabs( detJac );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/BilinearInnerElType.c
--- a/Discretisation/src/BilinearInnerElType.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: BilinearInnerElType.c 832 2007-05-16 01:11:18Z DaveLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType.h"
-#include "BilinearInnerElType.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-const Type BilinearInnerElType_Type = "BilinearInnerElType";
-
-#define _BilinearInnerElType_NodeCount 3
-
-BilinearInnerElType* BilinearInnerElType_New( Name name ) {
-  BilinearInnerElType* self = (BilinearInnerElType*)BilinearInnerElType_DefaultNew( name );
-
-	self->isConstructed = True;	
-	_ElementType_Init( (ElementType*)self, _BilinearInnerElType_NodeCount );
-	_BilinearInnerElType_Init( self );
-
-	return self;
-}
-
-void* BilinearInnerElType_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(BilinearInnerElType);
-	Type                                                                                    type = BilinearInnerElType_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _BilinearInnerElType_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _BilinearInnerElType_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = BilinearInnerElType_DefaultNew;
-	Stg_Component_ConstructFunction*                                                  _construct = _BilinearInnerElType_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _BilinearInnerElType_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _BilinearInnerElType_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _BilinearInnerElType_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _BilinearInnerElType_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _BilinearInnerElType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _BilinearInnerElType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _BilinearInnerElType_SurfaceNormal;
-
-	return _BilinearInnerElType_New(  BILINEARINNERELTYPE_PASSARGS  );
-}
-
-BilinearInnerElType* _BilinearInnerElType_New(  BILINEARINNERELTYPE_DEFARGS  ) {
-	BilinearInnerElType*		self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(BilinearInnerElType) );
-	self = (BilinearInnerElType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual functions */
-	
-	return self;
-}
-
-void _BilinearInnerElType_Init( BilinearInnerElType* self ) {
-	Dimension_Index dim_I=0;
-	/* General and Virtual info should already be set */
-	
-	/* BilinearInnerElType info */
-	self->isConstructed = True;
-	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
-		self->minElLocalCoord[dim_I] = -1;
-		self->maxElLocalCoord[dim_I] = 1;
-		self->elLocalLength[dim_I] = self->maxElLocalCoord[dim_I] - self->minElLocalCoord[dim_I];
-	}
-
-	self->triInds = Memory_Alloc_2DArray( unsigned, 2, 3, (Name)"BilinearInnerElType::triInds" );
-	self->triInds[0][0] = 0; self->triInds[0][1] = 1; self->triInds[0][2] = 2;
-	self->triInds[1][0] = 1; self->triInds[1][1] = 3; self->triInds[1][2] = 2;
-}
-
-void _BilinearInnerElType_Delete( void* elementType ) {
-	BilinearInnerElType* self = (BilinearInnerElType*)elementType;
-
-	/* Stg_Class_Delete parent */
-	_ElementType_Delete( self  );
-}
-
-void _BilinearInnerElType_Print( void* elementType, Stream* stream ) {
-	BilinearInnerElType* self = (BilinearInnerElType*)elementType;
-	Dimension_Index dim_I=0;
-
-	/* General info */
-	Journal_Printf( stream, "BilinearInnerElType (ptr): %p\n", self );
-	
-	/* Print parent */
-	_ElementType_Print( self, stream );
-	
-	/* Virtual info */
-	
-	/* BilinearInnerElType info */
-	Journal_Printf( stream, "self->minElLocalCoord: (", self );
-	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
-		Journal_Printf( stream, "%0.5f,", self->minElLocalCoord[dim_I] );
-	}
-	Journal_Printf( stream, ")\n", self );
-	Journal_Printf( stream, "self->maxElLocalCoord: (", self );
-	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
-		Journal_Printf( stream, "%0.5f,", self->maxElLocalCoord[dim_I] );
-	}	
-	Journal_Printf( stream, ")\n", self );
-	Journal_Printf( stream, "self->elLocalLength: (", self );
-	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
-		Journal_Printf( stream, "%0.5f,", self->elLocalLength[dim_I] );
-	}
-	Journal_Printf( stream, ")\n", self );
-}
-
-void _BilinearInnerElType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
-}
-	
-void _BilinearInnerElType_Initialise( void* elementType, void *data ){
-}
-	
-void _BilinearInnerElType_Execute( void* elementType, void *data ){
-}
-	
-void _BilinearInnerElType_Destroy( void* elementType, void *data ){
-	BilinearInnerElType* self = (BilinearInnerElType*)elementType;
-
-	FreeArray( self->triInds );
-
-	_ElementType_Destroy( self, data );
-}
-
-void _BilinearInnerElType_Build( void* elementType, void *data ) {
-}
-
-/*
-
- - Shape function definitions
- - Local node numbering convention for billinear element (xi, eta)
- - Local coordinate domain spans  -1 <= xi,eta <= 1
-
-  eta
-   |
-3-----2
-|  |__|___xi
-|     |
-0-----1
-
-*/
-void _BilinearInnerElType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
-	double xi, eta;
-	
-	xi  = localCoord[0];
-	eta = localCoord[1];
-
-	evaluatedValues[0] = - xi - 0.5*eta + 0.25;
-	evaluatedValues[1] = xi - 0.5*eta + 0.25;
-	evaluatedValues[2] = eta + 0.5;
-}
-
-
-void _BilinearInnerElType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
-		double** const evaluatedDerivatives ) 
-{		
-	double xi, eta;
-	
-	xi  = localCoord[0];
-	eta = localCoord[1];
-
-	evaluatedDerivatives[0][0] = - 1.0;
-	evaluatedDerivatives[0][1] = 1.0;
-	evaluatedDerivatives[0][2] = 0.0;
-
-	evaluatedDerivatives[1][0] = - 0.5;
-	evaluatedDerivatives[1][1] = - 0.5;
-	evaluatedDerivatives[1][2] = 1.0;
-}
-
-int _BilinearInnerElType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* norm ) {
-	Stream*	errStream = Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
-
-	Journal_Printf( errStream, "surface normal function not yet implemented for this element type.\n" );
-	assert( 0 );
-
-	norm = NULL;
-
-	return -1;
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/BilinearInnerElType.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/BilinearInnerElType.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,237 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: BilinearInnerElType.c 832 2007-05-16 01:11:18Z DaveLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType.h"
+#include "BilinearInnerElType.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+const Type BilinearInnerElType_Type = "BilinearInnerElType";
+
+#define _BilinearInnerElType_NodeCount 3
+
+BilinearInnerElType* BilinearInnerElType_New( Name name ) {
+  BilinearInnerElType* self = (BilinearInnerElType*)BilinearInnerElType_DefaultNew( name );
+
+	self->isConstructed = True;	
+	_ElementType_Init( (ElementType*)self, _BilinearInnerElType_NodeCount );
+	_BilinearInnerElType_Init( self );
+
+	return self;
+}
+
+void* BilinearInnerElType_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(BilinearInnerElType);
+	Type                                                                                    type = BilinearInnerElType_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _BilinearInnerElType_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _BilinearInnerElType_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = BilinearInnerElType_DefaultNew;
+	Stg_Component_ConstructFunction*                                                  _construct = _BilinearInnerElType_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _BilinearInnerElType_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _BilinearInnerElType_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _BilinearInnerElType_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _BilinearInnerElType_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _BilinearInnerElType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _BilinearInnerElType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _BilinearInnerElType_SurfaceNormal;
+
+	return _BilinearInnerElType_New(  BILINEARINNERELTYPE_PASSARGS  );
+}
+
+BilinearInnerElType* _BilinearInnerElType_New(  BILINEARINNERELTYPE_DEFARGS  ) {
+	BilinearInnerElType*		self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(BilinearInnerElType) );
+	self = (BilinearInnerElType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual functions */
+	
+	return self;
+}
+
+void _BilinearInnerElType_Init( BilinearInnerElType* self ) {
+	Dimension_Index dim_I=0;
+	/* General and Virtual info should already be set */
+	
+	/* BilinearInnerElType info */
+	self->isConstructed = True;
+	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
+		self->minElLocalCoord[dim_I] = -1;
+		self->maxElLocalCoord[dim_I] = 1;
+		self->elLocalLength[dim_I] = self->maxElLocalCoord[dim_I] - self->minElLocalCoord[dim_I];
+	}
+
+	self->triInds = Memory_Alloc_2DArray( unsigned, 2, 3, (Name)"BilinearInnerElType::triInds" );
+	self->triInds[0][0] = 0; self->triInds[0][1] = 1; self->triInds[0][2] = 2;
+	self->triInds[1][0] = 1; self->triInds[1][1] = 3; self->triInds[1][2] = 2;
+}
+
+void _BilinearInnerElType_Delete( void* elementType ) {
+	BilinearInnerElType* self = (BilinearInnerElType*)elementType;
+
+	/* Stg_Class_Delete parent */
+	_ElementType_Delete( self  );
+}
+
+void _BilinearInnerElType_Print( void* elementType, Stream* stream ) {
+	BilinearInnerElType* self = (BilinearInnerElType*)elementType;
+	Dimension_Index dim_I=0;
+
+	/* General info */
+	Journal_Printf( stream, "BilinearInnerElType (ptr): %p\n", self );
+	
+	/* Print parent */
+	_ElementType_Print( self, stream );
+	
+	/* Virtual info */
+	
+	/* BilinearInnerElType info */
+	Journal_Printf( stream, "self->minElLocalCoord: (", self );
+	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
+		Journal_Printf( stream, "%0.5f,", self->minElLocalCoord[dim_I] );
+	}
+	Journal_Printf( stream, ")\n", self );
+	Journal_Printf( stream, "self->maxElLocalCoord: (", self );
+	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
+		Journal_Printf( stream, "%0.5f,", self->maxElLocalCoord[dim_I] );
+	}	
+	Journal_Printf( stream, ")\n", self );
+	Journal_Printf( stream, "self->elLocalLength: (", self );
+	for ( dim_I = 0; dim_I < 2; dim_I++ ) {
+		Journal_Printf( stream, "%0.5f,", self->elLocalLength[dim_I] );
+	}
+	Journal_Printf( stream, ")\n", self );
+}
+
+void _BilinearInnerElType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
+}
+	
+void _BilinearInnerElType_Initialise( void* elementType, void *data ){
+}
+	
+void _BilinearInnerElType_Execute( void* elementType, void *data ){
+}
+	
+void _BilinearInnerElType_Destroy( void* elementType, void *data ){
+	BilinearInnerElType* self = (BilinearInnerElType*)elementType;
+
+	FreeArray( self->triInds );
+
+	_ElementType_Destroy( self, data );
+}
+
+void _BilinearInnerElType_Build( void* elementType, void *data ) {
+}
+
+/*
+
+ - Shape function definitions
+ - Local node numbering convention for billinear element (xi, eta)
+ - Local coordinate domain spans  -1 <= xi,eta <= 1
+
+  eta
+   |
+3-----2
+|  |__|___xi
+|     |
+0-----1
+
+*/
+void _BilinearInnerElType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
+	double xi, eta;
+	
+	xi  = localCoord[0];
+	eta = localCoord[1];
+
+	evaluatedValues[0] = - xi - 0.5*eta + 0.25;
+	evaluatedValues[1] = xi - 0.5*eta + 0.25;
+	evaluatedValues[2] = eta + 0.5;
+}
+
+
+void _BilinearInnerElType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
+		double** const evaluatedDerivatives ) 
+{		
+	double xi, eta;
+	
+	xi  = localCoord[0];
+	eta = localCoord[1];
+
+	evaluatedDerivatives[0][0] = - 1.0;
+	evaluatedDerivatives[0][1] = 1.0;
+	evaluatedDerivatives[0][2] = 0.0;
+
+	evaluatedDerivatives[1][0] = - 0.5;
+	evaluatedDerivatives[1][1] = - 0.5;
+	evaluatedDerivatives[1][2] = 1.0;
+}
+
+int _BilinearInnerElType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* norm ) {
+	Stream*	errStream = Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
+
+	Journal_Printf( errStream, "surface normal function not yet implemented for this element type.\n" );
+	assert( 0 );
+
+	norm = NULL;
+
+	return -1;
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Biquadratic.c
--- a/Discretisation/src/Biquadratic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Biquadratic.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type Biquadratic_Type = "Biquadratic";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-#define BIQUADRATICNODECOUNT 9
-
-Biquadratic* Biquadratic_New( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(Biquadratic);
-	Type                                                                                    type = Biquadratic_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _Biquadratic_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _Biquadratic_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_Biquadratic_New;
-	Stg_Component_ConstructFunction*                                                  _construct = _Biquadratic_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _Biquadratic_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _Biquadratic_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _Biquadratic_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _Biquadratic_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = Biquadratic_EvalBasis;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = Biquadratic_EvalLocalDerivs;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = Biquadratic_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
-
-	return _Biquadratic_New(  BIQUADRATIC_PASSARGS  );
-}
-
-Biquadratic* _Biquadratic_New(  BIQUADRATIC_DEFARGS  ) {
-	Biquadratic*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Biquadratic) );
-	self = (Biquadratic*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-
-	/* Virtual info */
-
-	/* Biquadratic info */
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, BIQUADRATICNODECOUNT );
-	_Biquadratic_Init( self );
-
-	return self;
-}
-
-void _Biquadratic_Init( Biquadratic* self ) {
-	assert( self && Stg_CheckType( self, Biquadratic ) );
-
-	self->dim = 2;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _Biquadratic_Delete( void* elementType ) {
-	Biquadratic* self = (Biquadratic*)elementType;
-
-	/* Delete the parent. */
-	_ElementType_Delete( self );
-}
-
-void _Biquadratic_Print( void* elementType, Stream* stream ) {
-	Biquadratic* self = (Biquadratic*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* elementTypeStream;
-	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"BiquadraticStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "Biquadratic (ptr): (%p)\n", self );
-	_ElementType_Print( self, stream );
-}
-
-void _Biquadratic_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
-}
-
-void _Biquadratic_Build( void* elementType, void* data ) {
-}
-
-void _Biquadratic_Initialise( void* elementType, void* data ) {
-	Biquadratic*	self = (Biquadratic*)elementType;
-
-	self->faceNodes = Memory_Alloc_2DArray( unsigned, 4, 3, (Name)"node indices for element faces"  );
-
-	self->faceNodes[0][0] = 0; self->faceNodes[0][1] = 1; self->faceNodes[0][2] = 2;
-	self->faceNodes[1][0] = 6; self->faceNodes[1][1] = 7; self->faceNodes[1][2] = 8;
-	self->faceNodes[2][0] = 0; self->faceNodes[2][1] = 3; self->faceNodes[2][2] = 6;
-	self->faceNodes[3][0] = 2; self->faceNodes[3][1] = 5; self->faceNodes[3][2] = 8;
-
-	self->evaluatedShapeFunc = Memory_Alloc_Array( double, self->nodeCount, "evaluatedShapeFuncs" );
-	self->GNi = Memory_Alloc_2DArray( double, self->dim, self->nodeCount, (Name)"localShapeFuncDerivatives"  );
-}
-
-void _Biquadratic_Execute( void* elementType, void* data ) {
-}
-
-void _Biquadratic_Destroy( void* elementType, void* data ) {
-	Biquadratic* self = (Biquadratic*)elementType;
-
-	Memory_Free( self->faceNodes );
-	Memory_Free( self->evaluatedShapeFunc );
-	Memory_Free( self->GNi );
-
-	_ElementType_Destroy( elementType, data );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void Biquadratic_EvalBasis( void* elementType, const double* localCoord, double* basis ) {
-	double	xi = localCoord[0], eta = localCoord[1];
-	double	a0 = xi - 1.0, b0 = eta - 1.0;
-	double	a1 = 1.0 - xi * xi, b1 = 1.0 - eta * eta;
-	double	a2 = xi + 1.0, b2 = eta + 1.0;
-	double	m0 = 0.5 * xi;
-	double	m1 = 0.5 * eta;
-	double	m2 = 0.25 * xi * eta;
-
-	basis[0] = m2 * a0 * b0;
-	basis[1] = m1 * a1 * b0;
-	basis[2] = m2 * a2 * b0;
-
-	basis[3] = m0 * a0 * b1;
-	basis[4] = a1 * b1;
-	basis[5] = m0 * a2 * b1;
-
-	basis[6] = m2 * a0 * b2;
-	basis[7] = m1 * a1 * b2;
-	basis[8] = m2 * a2 * b2;
-}
-
-void Biquadratic_EvalLocalDerivs( void* elementType, const double* localCoord, double** derivs ) {
-	double	xi = localCoord[0], eta = localCoord[1];
-	double	a0 = xi - 1.0, b0 = eta - 1.0;
-	double	a1 = xi + 1.0, b1 = eta + 1.0;
-	double	a2 = 2.0 * xi - 1.0, b2 = 2.0 * eta - 1.0;
-	double	a3 = 2.0 * xi + 1.0, b3 = 2.0 * eta + 1.0;
-	double	a4 = 1.0 - xi * xi, b4 = 1.0 - eta * eta;
-	double	m0 = 0.25 * xi;
-	double	m1 = 0.25 * eta;
-	double	m2 = -xi * eta;
-
-	/* Corner nodes. */
-	derivs[0][0] = m1 * a2 * b0;
-	derivs[0][2] = m1 * a3 * b0;
-	derivs[0][6] = m1 * a2 * b1;
-	derivs[0][8] = m1 * a3 * b1;
-	derivs[1][0] = m0 * a0 * b2;
-	derivs[1][2] = m0 * a1 * b2;
-	derivs[1][6] = m0 * a0 * b3;
-	derivs[1][8] = m0 * a1 * b3;
-
-	/* Side nodes. */
-	derivs[0][1] = m2 * b0;
-	derivs[0][7] = m2 * b1;
-	derivs[0][3] = 0.5 * a2 * b4;
-	derivs[0][5] = 0.5 * a3 * b4;
-	derivs[1][1] = 0.5 * a4 * b2;
-	derivs[1][7] = 0.5 * a4 * b3;
-	derivs[1][3] = m2 * a0;
-	derivs[1][5] = m2 * a1;
-
-	/* Center node. */
-	derivs[0][4] = -2.0 * xi * b4;
-	derivs[1][4] = -2.0 * eta * a4;
-}
-
-double Biquadratic_JacobianDeterminantSurface(
-	void*				elementType,
-	void*				_mesh,
-	unsigned			element_I,
-	const double*	localCoord, 
-	unsigned			face_I,
-	unsigned			norm )
-{
-	Biquadratic*	self = (Biquadratic*) elementType;
-	Mesh*				mesh = (Mesh*)_mesh;
-	unsigned			surfaceDim	= ( norm + 1 ) % 2;
-	double			x[3];
-	double			detJac;
-	unsigned			nodes[3];
-
-	self = (Biquadratic*) elementType;
-
-	ElementType_GetFaceNodes( elementType, mesh, element_I, face_I, 3, nodes );
-
-	x[0] = Mesh_GetVertex( mesh, nodes[0] )[surfaceDim];
-	x[1] = Mesh_GetVertex( mesh, nodes[1] )[surfaceDim];
-	x[2] = Mesh_GetVertex( mesh, nodes[2] )[surfaceDim];
-
-	detJac = ( localCoord[surfaceDim] - 0.5 ) * x[0] - 2.0 * localCoord[surfaceDim] * x[1] + 
-		 ( localCoord[surfaceDim] + 0.5 ) * x[2];
-
-	return fabs( detJac );
-}
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Biquadratic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/Biquadratic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,251 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Biquadratic.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type Biquadratic_Type = "Biquadratic";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+#define BIQUADRATICNODECOUNT 9
+
+Biquadratic* Biquadratic_New( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(Biquadratic);
+	Type                                                                                    type = Biquadratic_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _Biquadratic_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _Biquadratic_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_Biquadratic_New;
+	Stg_Component_ConstructFunction*                                                  _construct = _Biquadratic_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _Biquadratic_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _Biquadratic_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _Biquadratic_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _Biquadratic_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = Biquadratic_EvalBasis;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = Biquadratic_EvalLocalDerivs;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = Biquadratic_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
+
+	return _Biquadratic_New(  BIQUADRATIC_PASSARGS  );
+}
+
+Biquadratic* _Biquadratic_New(  BIQUADRATIC_DEFARGS  ) {
+	Biquadratic*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Biquadratic) );
+	self = (Biquadratic*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+
+	/* Virtual info */
+
+	/* Biquadratic info */
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, BIQUADRATICNODECOUNT );
+	_Biquadratic_Init( self );
+
+	return self;
+}
+
+void _Biquadratic_Init( Biquadratic* self ) {
+	assert( self && Stg_CheckType( self, Biquadratic ) );
+
+	self->dim = 2;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _Biquadratic_Delete( void* elementType ) {
+	Biquadratic* self = (Biquadratic*)elementType;
+
+	/* Delete the parent. */
+	_ElementType_Delete( self );
+}
+
+void _Biquadratic_Print( void* elementType, Stream* stream ) {
+	Biquadratic* self = (Biquadratic*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* elementTypeStream;
+	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"BiquadraticStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "Biquadratic (ptr): (%p)\n", self );
+	_ElementType_Print( self, stream );
+}
+
+void _Biquadratic_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
+}
+
+void _Biquadratic_Build( void* elementType, void* data ) {
+}
+
+void _Biquadratic_Initialise( void* elementType, void* data ) {
+	Biquadratic*	self = (Biquadratic*)elementType;
+
+	self->faceNodes = Memory_Alloc_2DArray( unsigned, 4, 3, (Name)"node indices for element faces"  );
+
+	self->faceNodes[0][0] = 0; self->faceNodes[0][1] = 1; self->faceNodes[0][2] = 2;
+	self->faceNodes[1][0] = 6; self->faceNodes[1][1] = 7; self->faceNodes[1][2] = 8;
+	self->faceNodes[2][0] = 0; self->faceNodes[2][1] = 3; self->faceNodes[2][2] = 6;
+	self->faceNodes[3][0] = 2; self->faceNodes[3][1] = 5; self->faceNodes[3][2] = 8;
+
+	self->evaluatedShapeFunc = Memory_Alloc_Array( double, self->nodeCount, "evaluatedShapeFuncs" );
+	self->GNi = Memory_Alloc_2DArray( double, self->dim, self->nodeCount, (Name)"localShapeFuncDerivatives"  );
+}
+
+void _Biquadratic_Execute( void* elementType, void* data ) {
+}
+
+void _Biquadratic_Destroy( void* elementType, void* data ) {
+	Biquadratic* self = (Biquadratic*)elementType;
+
+	Memory_Free( self->faceNodes );
+	Memory_Free( self->evaluatedShapeFunc );
+	Memory_Free( self->GNi );
+
+	_ElementType_Destroy( elementType, data );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void Biquadratic_EvalBasis( void* elementType, const double* localCoord, double* basis ) {
+	double	xi = localCoord[0], eta = localCoord[1];
+	double	a0 = xi - 1.0, b0 = eta - 1.0;
+	double	a1 = 1.0 - xi * xi, b1 = 1.0 - eta * eta;
+	double	a2 = xi + 1.0, b2 = eta + 1.0;
+	double	m0 = 0.5 * xi;
+	double	m1 = 0.5 * eta;
+	double	m2 = 0.25 * xi * eta;
+
+	basis[0] = m2 * a0 * b0;
+	basis[1] = m1 * a1 * b0;
+	basis[2] = m2 * a2 * b0;
+
+	basis[3] = m0 * a0 * b1;
+	basis[4] = a1 * b1;
+	basis[5] = m0 * a2 * b1;
+
+	basis[6] = m2 * a0 * b2;
+	basis[7] = m1 * a1 * b2;
+	basis[8] = m2 * a2 * b2;
+}
+
+void Biquadratic_EvalLocalDerivs( void* elementType, const double* localCoord, double** derivs ) {
+	double	xi = localCoord[0], eta = localCoord[1];
+	double	a0 = xi - 1.0, b0 = eta - 1.0;
+	double	a1 = xi + 1.0, b1 = eta + 1.0;
+	double	a2 = 2.0 * xi - 1.0, b2 = 2.0 * eta - 1.0;
+	double	a3 = 2.0 * xi + 1.0, b3 = 2.0 * eta + 1.0;
+	double	a4 = 1.0 - xi * xi, b4 = 1.0 - eta * eta;
+	double	m0 = 0.25 * xi;
+	double	m1 = 0.25 * eta;
+	double	m2 = -xi * eta;
+
+	/* Corner nodes. */
+	derivs[0][0] = m1 * a2 * b0;
+	derivs[0][2] = m1 * a3 * b0;
+	derivs[0][6] = m1 * a2 * b1;
+	derivs[0][8] = m1 * a3 * b1;
+	derivs[1][0] = m0 * a0 * b2;
+	derivs[1][2] = m0 * a1 * b2;
+	derivs[1][6] = m0 * a0 * b3;
+	derivs[1][8] = m0 * a1 * b3;
+
+	/* Side nodes. */
+	derivs[0][1] = m2 * b0;
+	derivs[0][7] = m2 * b1;
+	derivs[0][3] = 0.5 * a2 * b4;
+	derivs[0][5] = 0.5 * a3 * b4;
+	derivs[1][1] = 0.5 * a4 * b2;
+	derivs[1][7] = 0.5 * a4 * b3;
+	derivs[1][3] = m2 * a0;
+	derivs[1][5] = m2 * a1;
+
+	/* Center node. */
+	derivs[0][4] = -2.0 * xi * b4;
+	derivs[1][4] = -2.0 * eta * a4;
+}
+
+double Biquadratic_JacobianDeterminantSurface(
+	void*				elementType,
+	void*				_mesh,
+	unsigned			element_I,
+	const double*	localCoord, 
+	unsigned			face_I,
+	unsigned			norm )
+{
+	Biquadratic*	self = (Biquadratic*) elementType;
+	Mesh*				mesh = (Mesh*)_mesh;
+	unsigned			surfaceDim	= ( norm + 1 ) % 2;
+	double			x[3];
+	double			detJac;
+	unsigned			nodes[3];
+
+	self = (Biquadratic*) elementType;
+
+	ElementType_GetFaceNodes( elementType, mesh, element_I, face_I, 3, nodes );
+
+	x[0] = Mesh_GetVertex( mesh, nodes[0] )[surfaceDim];
+	x[1] = Mesh_GetVertex( mesh, nodes[1] )[surfaceDim];
+	x[2] = Mesh_GetVertex( mesh, nodes[2] )[surfaceDim];
+
+	detJac = ( localCoord[surfaceDim] - 0.5 ) * x[0] - 2.0 * localCoord[surfaceDim] * x[1] + 
+		 ( localCoord[surfaceDim] + 0.5 ) * x[2];
+
+	return fabs( detJac );
+}
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/C0Generator.c
--- a/Discretisation/src/C0Generator.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,272 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: C0Generator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type C0Generator_Type = "C0Generator";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-C0Generator* C0Generator_New( Name name, AbstractContext* context ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(C0Generator);
-	Type                                                      type = C0Generator_Type;
-	Stg_Class_DeleteFunction*                              _delete = _C0Generator_Delete;
-	Stg_Class_PrintFunction*                                _print = _C0Generator_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (void* (*)(Name))_C0Generator_New;
-	Stg_Component_ConstructFunction*                    _construct = _C0Generator_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _C0Generator_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _C0Generator_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _C0Generator_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = NULL;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-	MeshGenerator_SetDimSizeFunc*                   setDimSizeFunc = _MeshGenerator_SetDimSize;
-	MeshGenerator_GenerateFunc*                       generateFunc = (MeshGenerator_GenerateFunc*)C0Generator_Generate;
-
-	C0Generator* self = _C0Generator_New(  C0GENERATOR_PASSARGS  );
-   
-   _MeshGenerator_Init( (MeshGenerator*)self, context );
-	_C0Generator_Init( self );
-
-   return self;
-}
-
-C0Generator* _C0Generator_New(  C0GENERATOR_DEFARGS  ) {
-	C0Generator*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(C0Generator) );
-	self = (C0Generator*)_MeshGenerator_New(  MESHGENERATOR_PASSARGS  );
-
-	/* Virtual info */
-
-	return self;
-}
-
-void _C0Generator_Init( C0Generator* self ) {
-	assert( self && Stg_CheckType( self, C0Generator ) );
-
-	self->elMesh = NULL;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _C0Generator_Delete( void* generator ) {
-	C0Generator*	self = (C0Generator*)generator;
-
-	/* Delete the parent. */
-	_MeshGenerator_Delete( self );
-}
-
-void _C0Generator_Print( void* generator, Stream* stream ) {
-	C0Generator*	self = (C0Generator*)generator;
-	
-	/* Set the Journal for printing informations */
-	Stream* generatorStream;
-	generatorStream = Journal_Register( InfoStream_Type, (Name)"C0GeneratorStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "C0Generator (ptr): (%p)\n", self );
-	_MeshGenerator_Print( self, stream );
-}
-
-void _C0Generator_AssignFromXML( void* generator, Stg_ComponentFactory* cf, void* data ) {
-	C0Generator*	self = (C0Generator*)generator;
-	Mesh*		elMesh;
-
-	assert( self );
-	assert( cf );
-
-	_MeshGenerator_AssignFromXML( self, cf, data );
-
-	elMesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"elementMesh", Mesh, True, data  );
-	C0Generator_SetElementMesh( self, elMesh );
-}
-
-void _C0Generator_Build( void* generator, void* data ) {
-	_MeshGenerator_Build( generator, data );
-}
-
-void _C0Generator_Initialise( void* generator, void* data ) {
-	_MeshGenerator_Initialise( generator, data );
-}
-
-void _C0Generator_Execute( void* generator, void* data ) {
-}
-
-void _C0Generator_Destroy( void* generator, void* data ) {
-}
-
-void C0Generator_Generate( void* generator, void* _mesh ) {
-	C0Generator*	self = (C0Generator*)generator;
-	FeMesh*		mesh = (FeMesh*)_mesh;
-	Grid**		grid;
-	Grid*		elGrid;
-
-	assert( self && Stg_CheckType( self, C0Generator ) );
-	assert( mesh && Stg_CheckType( mesh, FeMesh ) );
-
-	C0Generator_BuildTopology( self, mesh );
-	C0Generator_BuildGeometry( self, mesh );
-	C0Generator_BuildElementTypes( self, mesh );
-
-	elGrid = *(Grid**)ExtensionManager_Get( self->elMesh->info, self->elMesh, 
-					       ExtensionManager_GetHandle( self->elMesh->info, (Name)"elementGrid" )  );
-	ExtensionManager_Add( mesh->info, (Name)"elementGrid", sizeof(Grid*) );
-	grid = (Grid** )ExtensionManager_Get( mesh->info, mesh, 
-					     ExtensionManager_GetHandle( mesh->info, (Name)"elementGrid" ) );
-	*grid = Grid_New( );
-	Grid_SetNumDims( *grid, elGrid->nDims );
-	Grid_SetSizes( *grid, elGrid->sizes );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void C0Generator_SetElementMesh( void* generator, void* mesh ) {
-	C0Generator*	self = (C0Generator*)generator;
-
-	assert( self && Stg_CheckType( self, C0Generator ) );
-
-	self->elMesh = (Mesh*)mesh;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-void C0Generator_BuildTopology( C0Generator* self, FeMesh* mesh ) {
-	Mesh*		elMesh;
-	MeshTopology	*topo, *elTopo;
-	Sync*		elSync;
-	unsigned	nDims;
-	unsigned	*nIncEls, **incEls;
-	unsigned	nDomainEls;
-	unsigned	e_i;
-
-	assert( self );
-	assert( mesh );
-
-	elMesh = self->elMesh;
-	nDims = Mesh_GetDimSize( elMesh );
-	elTopo = Mesh_GetTopology( elMesh );
-	elSync = Mesh_GetSync( elMesh, (MeshTopology_Dim)nDims );
-
-	topo = Mesh_GetTopology( mesh );
-	MeshTopology_SetComm( topo, MeshTopology_GetComm( elTopo ) );
-	MeshTopology_SetNumDims( topo, nDims );
-	IGraph_SetDomain( topo, nDims, elSync );
-	IGraph_SetDomain( topo, MT_VERTEX, elSync );
-	topo->shadDepth = elTopo->shadDepth;
-
-	nDomainEls = Mesh_GetDomainSize( elMesh, (MeshTopology_Dim)nDims );
-	nIncEls = AllocArray( unsigned, nDomainEls );
-	incEls = AllocArray2D( unsigned, nDomainEls, 1 );
-	for( e_i = 0; e_i < nDomainEls; e_i++ ) {
-		nIncEls[e_i] = 1;
-		incEls[e_i][0] = e_i;
-		IGraph_SetIncidence( topo, nDims, e_i, MT_VERTEX, nIncEls[e_i], (int*)(incEls[e_i]) );
-	}
-	FreeArray( nIncEls );
-	FreeArray( incEls );
-
-	IGraph_InvertIncidence( topo, MT_VERTEX, nDims );
-}
-
-void C0Generator_BuildGeometry( C0Generator* self, FeMesh* mesh ) {
-	Mesh*			elMesh;
-	double			*centroid, *vert;
-	unsigned		nDims;
-	unsigned		nDomainEls;
-	Mesh_ElementType*	elType;
-	unsigned		e_i;
-
-	assert( self );
-	assert( mesh );
-
-	elMesh = self->elMesh;
-	nDims = Mesh_GetDimSize( elMesh );
-	nDomainEls = Mesh_GetDomainSize( elMesh, (MeshTopology_Dim)nDims );
-	mesh->verts = AllocArray2D( double, nDomainEls, nDims );
-	centroid = AllocArray( double, nDims );
-	for( e_i = 0; e_i < nDomainEls; e_i++ ) {
-		elType = Mesh_GetElementType( elMesh, e_i );
-		Mesh_ElementType_GetCentroid( elType, e_i, centroid );
-		vert = Mesh_GetVertex( mesh, e_i );
-		memcpy( vert, centroid, nDims * sizeof(double) );
-	}
-	FreeArray( centroid );
-}
-
-void C0Generator_BuildElementTypes( C0Generator* self, FeMesh* mesh ) {
-	unsigned		nDomainEls;
-	Mesh_Algorithms*	algs;
-	unsigned		e_i;
-
-	assert( self );
-	assert( mesh );
-
-	mesh->nElTypes = 1;
-	mesh->elTypes = AllocNamedArray( Mesh_ElementType*, mesh->nElTypes, "Mesh::elTypes" );
-	mesh->elTypes[0] = (Mesh_ElementType*)Mesh_CentroidType_New();
-	Mesh_ElementType_SetMesh( mesh->elTypes[0], mesh );
-	Mesh_CentroidType_SetElementMesh( mesh->elTypes[0], self->elMesh );
-	nDomainEls = Mesh_GetDomainSize( mesh, Mesh_GetDimSize( mesh ) );
-	mesh->elTypeMap = AllocNamedArray( unsigned, nDomainEls, "Mesh::elTypeMap" );
-
-	for( e_i = 0; e_i < nDomainEls; e_i++ )
-		mesh->elTypeMap[e_i] = 0;
-
-	algs = (Mesh_Algorithms*)Mesh_CentroidAlgorithms_New( "", NULL );
-	Mesh_CentroidAlgorithms_SetElementMesh( algs, self->elMesh );
-	Mesh_SetAlgorithms( mesh, algs );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/C0Generator.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/C0Generator.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,272 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: C0Generator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type C0Generator_Type = "C0Generator";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+C0Generator* C0Generator_New( Name name, AbstractContext* context ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(C0Generator);
+	Type                                                      type = C0Generator_Type;
+	Stg_Class_DeleteFunction*                              _delete = _C0Generator_Delete;
+	Stg_Class_PrintFunction*                                _print = _C0Generator_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (void* (*)(Name))_C0Generator_New;
+	Stg_Component_ConstructFunction*                    _construct = _C0Generator_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _C0Generator_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _C0Generator_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _C0Generator_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = NULL;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+	MeshGenerator_SetDimSizeFunc*                   setDimSizeFunc = _MeshGenerator_SetDimSize;
+	MeshGenerator_GenerateFunc*                       generateFunc = (MeshGenerator_GenerateFunc*)C0Generator_Generate;
+
+	C0Generator* self = _C0Generator_New(  C0GENERATOR_PASSARGS  );
+   
+   _MeshGenerator_Init( (MeshGenerator*)self, context );
+	_C0Generator_Init( self );
+
+   return self;
+}
+
+C0Generator* _C0Generator_New(  C0GENERATOR_DEFARGS  ) {
+	C0Generator*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(C0Generator) );
+	self = (C0Generator*)_MeshGenerator_New(  MESHGENERATOR_PASSARGS  );
+
+	/* Virtual info */
+
+	return self;
+}
+
+void _C0Generator_Init( C0Generator* self ) {
+	assert( self && Stg_CheckType( self, C0Generator ) );
+
+	self->elMesh = NULL;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _C0Generator_Delete( void* generator ) {
+	C0Generator*	self = (C0Generator*)generator;
+
+	/* Delete the parent. */
+	_MeshGenerator_Delete( self );
+}
+
+void _C0Generator_Print( void* generator, Stream* stream ) {
+	C0Generator*	self = (C0Generator*)generator;
+	
+	/* Set the Journal for printing informations */
+	Stream* generatorStream;
+	generatorStream = Journal_Register( InfoStream_Type, (Name)"C0GeneratorStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "C0Generator (ptr): (%p)\n", self );
+	_MeshGenerator_Print( self, stream );
+}
+
+void _C0Generator_AssignFromXML( void* generator, Stg_ComponentFactory* cf, void* data ) {
+	C0Generator*	self = (C0Generator*)generator;
+	Mesh*		elMesh;
+
+	assert( self );
+	assert( cf );
+
+	_MeshGenerator_AssignFromXML( self, cf, data );
+
+	elMesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"elementMesh", Mesh, True, data  );
+	C0Generator_SetElementMesh( self, elMesh );
+}
+
+void _C0Generator_Build( void* generator, void* data ) {
+	_MeshGenerator_Build( generator, data );
+}
+
+void _C0Generator_Initialise( void* generator, void* data ) {
+	_MeshGenerator_Initialise( generator, data );
+}
+
+void _C0Generator_Execute( void* generator, void* data ) {
+}
+
+void _C0Generator_Destroy( void* generator, void* data ) {
+}
+
+void C0Generator_Generate( void* generator, void* _mesh ) {
+	C0Generator*	self = (C0Generator*)generator;
+	FeMesh*		mesh = (FeMesh*)_mesh;
+	Grid**		grid;
+	Grid*		elGrid;
+
+	assert( self && Stg_CheckType( self, C0Generator ) );
+	assert( mesh && Stg_CheckType( mesh, FeMesh ) );
+
+	C0Generator_BuildTopology( self, mesh );
+	C0Generator_BuildGeometry( self, mesh );
+	C0Generator_BuildElementTypes( self, mesh );
+
+	elGrid = *(Grid**)ExtensionManager_Get( self->elMesh->info, self->elMesh, 
+					       ExtensionManager_GetHandle( self->elMesh->info, (Name)"elementGrid" )  );
+	ExtensionManager_Add( mesh->info, (Name)"elementGrid", sizeof(Grid*) );
+	grid = (Grid** )ExtensionManager_Get( mesh->info, mesh, 
+					     ExtensionManager_GetHandle( mesh->info, (Name)"elementGrid" ) );
+	*grid = Grid_New( );
+	Grid_SetNumDims( *grid, elGrid->nDims );
+	Grid_SetSizes( *grid, elGrid->sizes );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void C0Generator_SetElementMesh( void* generator, void* mesh ) {
+	C0Generator*	self = (C0Generator*)generator;
+
+	assert( self && Stg_CheckType( self, C0Generator ) );
+
+	self->elMesh = (Mesh*)mesh;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+void C0Generator_BuildTopology( C0Generator* self, FeMesh* mesh ) {
+	Mesh*		elMesh;
+	MeshTopology	*topo, *elTopo;
+	Sync*		elSync;
+	unsigned	nDims;
+	unsigned	*nIncEls, **incEls;
+	unsigned	nDomainEls;
+	unsigned	e_i;
+
+	assert( self );
+	assert( mesh );
+
+	elMesh = self->elMesh;
+	nDims = Mesh_GetDimSize( elMesh );
+	elTopo = Mesh_GetTopology( elMesh );
+	elSync = Mesh_GetSync( elMesh, (MeshTopology_Dim)nDims );
+
+	topo = Mesh_GetTopology( mesh );
+	MeshTopology_SetComm( topo, MeshTopology_GetComm( elTopo ) );
+	MeshTopology_SetNumDims( topo, nDims );
+	IGraph_SetDomain( topo, nDims, elSync );
+	IGraph_SetDomain( topo, MT_VERTEX, elSync );
+	topo->shadDepth = elTopo->shadDepth;
+
+	nDomainEls = Mesh_GetDomainSize( elMesh, (MeshTopology_Dim)nDims );
+	nIncEls = AllocArray( unsigned, nDomainEls );
+	incEls = AllocArray2D( unsigned, nDomainEls, 1 );
+	for( e_i = 0; e_i < nDomainEls; e_i++ ) {
+		nIncEls[e_i] = 1;
+		incEls[e_i][0] = e_i;
+		IGraph_SetIncidence( topo, nDims, e_i, MT_VERTEX, nIncEls[e_i], (int*)(incEls[e_i]) );
+	}
+	FreeArray( nIncEls );
+	FreeArray( incEls );
+
+	IGraph_InvertIncidence( topo, MT_VERTEX, nDims );
+}
+
+void C0Generator_BuildGeometry( C0Generator* self, FeMesh* mesh ) {
+	Mesh*			elMesh;
+	double			*centroid, *vert;
+	unsigned		nDims;
+	unsigned		nDomainEls;
+	Mesh_ElementType*	elType;
+	unsigned		e_i;
+
+	assert( self );
+	assert( mesh );
+
+	elMesh = self->elMesh;
+	nDims = Mesh_GetDimSize( elMesh );
+	nDomainEls = Mesh_GetDomainSize( elMesh, (MeshTopology_Dim)nDims );
+	mesh->verts = AllocArray2D( double, nDomainEls, nDims );
+	centroid = AllocArray( double, nDims );
+	for( e_i = 0; e_i < nDomainEls; e_i++ ) {
+		elType = Mesh_GetElementType( elMesh, e_i );
+		Mesh_ElementType_GetCentroid( elType, e_i, centroid );
+		vert = Mesh_GetVertex( mesh, e_i );
+		memcpy( vert, centroid, nDims * sizeof(double) );
+	}
+	FreeArray( centroid );
+}
+
+void C0Generator_BuildElementTypes( C0Generator* self, FeMesh* mesh ) {
+	unsigned		nDomainEls;
+	Mesh_Algorithms*	algs;
+	unsigned		e_i;
+
+	assert( self );
+	assert( mesh );
+
+	mesh->nElTypes = 1;
+	mesh->elTypes = AllocNamedArray( Mesh_ElementType*, mesh->nElTypes, "Mesh::elTypes" );
+	mesh->elTypes[0] = (Mesh_ElementType*)Mesh_CentroidType_New();
+	Mesh_ElementType_SetMesh( mesh->elTypes[0], mesh );
+	Mesh_CentroidType_SetElementMesh( mesh->elTypes[0], self->elMesh );
+	nDomainEls = Mesh_GetDomainSize( mesh, Mesh_GetDimSize( mesh ) );
+	mesh->elTypeMap = AllocNamedArray( unsigned, nDomainEls, "Mesh::elTypeMap" );
+
+	for( e_i = 0; e_i < nDomainEls; e_i++ )
+		mesh->elTypeMap[e_i] = 0;
+
+	algs = (Mesh_Algorithms*)Mesh_CentroidAlgorithms_New( "", NULL );
+	Mesh_CentroidAlgorithms_SetElementMesh( algs, self->elMesh );
+	Mesh_SetAlgorithms( mesh, algs );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/C2Generator.c
--- a/Discretisation/src/C2Generator.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,508 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: C2Generator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type C2Generator_Type = "C2Generator";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-C2Generator* C2Generator_New( Name name, AbstractContext* context ) {
-	/* Variables set in this function */
-	SizeT                                                    _sizeOfSelf = sizeof(C2Generator);
-	Type                                                            type = C2Generator_Type;
-	Stg_Class_DeleteFunction*                                    _delete = _C2Generator_Delete;
-	Stg_Class_PrintFunction*                                      _print = _C2Generator_Print;
-	Stg_Class_CopyFunction*                                        _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*        _defaultConstructor = (void* (*)(Name))_C2Generator_New;
-	Stg_Component_ConstructFunction*                          _construct = _C2Generator_AssignFromXML;
-	Stg_Component_BuildFunction*                                  _build = _C2Generator_Build;
-	Stg_Component_InitialiseFunction*                        _initialise = _C2Generator_Initialise;
-	Stg_Component_ExecuteFunction*                              _execute = _C2Generator_Execute;
-	Stg_Component_DestroyFunction*                              _destroy = NULL;
-	AllocationType                                    nameAllocationType = NON_GLOBAL;
-	MeshGenerator_SetDimSizeFunc*                         setDimSizeFunc = CartesianGenerator_SetDimSize;
-	MeshGenerator_GenerateFunc*                             generateFunc = CartesianGenerator_Generate;
-	CartesianGenerator_SetTopologyParamsFunc*      setTopologyParamsFunc = C2Generator_SetTopologyParams;
-	CartesianGenerator_GenElementsFunc*                  genElementsFunc = _CartesianGenerator_GenElements;
-	CartesianGenerator_GenFacesFunc*                        genFacesFunc = _CartesianGenerator_GenFaces;
-	CartesianGenerator_GenEdgesFunc*                        genEdgesFunc = _CartesianGenerator_GenEdges;
-	CartesianGenerator_GenVerticesFunc*                  genVerticesFunc = _CartesianGenerator_GenVertices;
-	CartesianGenerator_GenElementVertexIncFunc*  genElementVertexIncFunc = C2Generator_GenElementVertexInc;
-	CartesianGenerator_GenVolumeEdgeIncFunc*        genVolumeEdgeIncFunc = _CartesianGenerator_GenVolumeEdgeInc;
-	CartesianGenerator_GenVolumeFaceIncFunc*        genVolumeFaceIncFunc = _CartesianGenerator_GenVolumeFaceInc;
-	CartesianGenerator_GenFaceVertexIncFunc*        genFaceVertexIncFunc = C2Generator_GenFaceVertexInc;
-	CartesianGenerator_GenFaceEdgeIncFunc*            genFaceEdgeIncFunc = _CartesianGenerator_GenFaceEdgeInc;
-	CartesianGenerator_GenEdgeVertexIncFunc*        genEdgeVertexIncFunc = C2Generator_GenEdgeVertexInc;
-	CartesianGenerator_GenElementTypesFunc*          genElementTypesFunc = C2Generator_GenElementTypes;
-
-	C2Generator* self = _C2Generator_New(  C2GENERATOR_PASSARGS  );
-
-   _MeshGenerator_Init( (MeshGenerator*)self, context );
-   _CartesianGenerator_Init( (CartesianGenerator*)self );
-   _C2Generator_Init( self );
-   return self;
-}
-
-C2Generator* _C2Generator_New(  C2GENERATOR_DEFARGS  ) {
-	C2Generator*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(C2Generator) );
-	self = (C2Generator*)_CartesianGenerator_New(  CARTESIANGENERATOR_PASSARGS  );
-
-
-
-	return self;
-}
-
-void _C2Generator_Init( C2Generator* self ) {
-	assert( self );
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _C2Generator_Delete( void* meshGenerator ) {
-	C2Generator*	self = (C2Generator*)meshGenerator;
-
-	/* Delete the parent. */
-	_CartesianGenerator_Delete( self );
-}
-
-void _C2Generator_Print( void* meshGenerator, Stream* stream ) {
-	C2Generator*	self = (C2Generator*)meshGenerator;
-	
-	/* Set the Journal for printing informations */
-	Stream* meshGeneratorStream;
-	meshGeneratorStream = Journal_Register( InfoStream_Type, (Name)"C2GeneratorStream" );
-
-	assert( self  );
-
-	/* Print parent */
-	Journal_Printf( stream, "C2Generator (ptr): (%p)\n", self );
-	_CartesianGenerator_Print( self, stream );
-}
-
-void _C2Generator_AssignFromXML( void* meshGenerator, Stg_ComponentFactory* cf, void* data ) {
-	_CartesianGenerator_AssignFromXML( meshGenerator, cf, data );
-}
-
-void _C2Generator_Build( void* meshGenerator, void* data ) {
-	_CartesianGenerator_Build( meshGenerator, data );
-}
-
-void _C2Generator_Initialise( void* meshGenerator, void* data ) {
-}
-
-void _C2Generator_Execute( void* meshGenerator, void* data ) {
-}
-
-void _C2Generator_Destroy( void* meshGenerator, void* data ) {
-}
-
-void C2Generator_SetTopologyParams( void* meshGenerator, unsigned* sizes, 
-				    unsigned maxDecompDims, unsigned* minDecomp, unsigned* maxDecomp )
-{
-	C2Generator*	self = (C2Generator*)meshGenerator;
-	unsigned*	vertSizes;
-	unsigned	d_i;
-
-	assert( self );
-
-	_CartesianGenerator_SetTopologyParams( self, sizes, 
-					       maxDecompDims, minDecomp, maxDecomp );
-	vertSizes = AllocArray( unsigned, self->vertGrid->nDims );
-	for( d_i = 0; d_i < self->vertGrid->nDims; d_i++ ) {
-		vertSizes[d_i] = self->vertGrid->sizes[d_i] * 2 - 1;
-		self->vertOrigin[d_i] *= 2;
-		self->vertRange[d_i] = self->vertRange[d_i] * 2 - 1;
-	}
-	Grid_SetSizes( self->vertGrid, vertSizes );
-	FreeArray( vertSizes );
-}
-
-void C2Generator_GenElementVertexInc( void* meshGenerator, IGraph* topo, Grid*** grids ) {
-	C2Generator*	self = (C2Generator*)meshGenerator;
-	Stream*		stream = Journal_Register( Info_Type, (Name)self->type  );
-	unsigned*	incEls;
-	unsigned*	dimInds;
-	unsigned	vertsPerEl;
-	unsigned	nDims;
-	unsigned	e_i, d_i;
-	int nDomainEls;
-
-	assert( self );
-	assert( topo );
-	assert( grids );
-
-	Journal_Printf( stream, "Generating element-vertex incidence...\n" );
-	Stream_Indent( stream );
-
-	vertsPerEl = (topo->nDims == 1) ? 3 : (topo->nDims == 2) ? 9 : 27;
-
-	nDims = topo->nDims;
-	nDomainEls = Sync_GetNumDomains( IGraph_GetDomain( topo, nDims ) );
-	incEls = Memory_Alloc_Array_Unnamed( unsigned, vertsPerEl );
-	dimInds = Memory_Alloc_Array_Unnamed( unsigned, topo->nDims );
-	for( e_i = 0; e_i < (unsigned)nDomainEls; e_i++ ) {
-		unsigned	gInd = Sync_DomainToGlobal( IGraph_GetDomain( topo, nDims ), e_i );
-		unsigned	curNode = 0;
-
-		Grid_Lift( grids[topo->nDims][0], gInd, dimInds );
-		for( d_i = 0; d_i < nDims; d_i++ )
-			dimInds[d_i] *= 2;
-
-		incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-		dimInds[0]++;
-		incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-		dimInds[0]++;
-		incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-		dimInds[0] -= 2;
-
-		if( topo->nDims >= 2 ) {
-			dimInds[1]++;
-			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2;
-			dimInds[1]++;
-			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2;
-			dimInds[1] -= 2;
-
-			if( topo->nDims >= 3 ) {
-				dimInds[2]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0] -= 2;
-				dimInds[1]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0] -= 2;
-				dimInds[1]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0] -= 2;
-				dimInds[1] -= 2;
-				dimInds[2]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0] -= 2;
-				dimInds[1]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0] -= 2;
-				dimInds[1]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0]++;
-				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
-				dimInds[0] -= 2;
-				dimInds[1] -= 2;
-				dimInds[2] -= 2;
-			}
-		}
-		CartesianGenerator_MapToDomain( (CartesianGenerator*)self, IGraph_GetDomain( topo, 0), vertsPerEl, incEls );
-		IGraph_SetIncidence( topo, topo->nDims, e_i, MT_VERTEX, vertsPerEl, (int*)incEls );
-	}
-
-	FreeArray( incEls );
-	FreeArray( dimInds );
-
-	MPI_Barrier( self->mpiComm );
-	Journal_Printf( stream, "... done.\n" );
-	Stream_UnIndent( stream );
-}
-
-void C2Generator_GenFaceVertexInc( void* meshGenerator, IGraph* topo, Grid*** grids ) {
-	C2Generator*	self 		= (C2Generator*)meshGenerator;
-	Stream*		stream;
-	unsigned	face_i;
-	unsigned	gFace;
-	unsigned	verts[9];
-	unsigned*	dimInds		= Memory_Alloc_Array( unsigned, topo->nDims, "edgeDimensionIndices" );
-
-	stream = Journal_Register( Info_Type, (Name)self->type  );
-	Journal_Printf( stream, "Generating face-vertex types...\n" );
-	Stream_Indent( stream );
-
-	for( face_i = 0; face_i < (unsigned)(topo->remotes[MT_FACE]->nDomains); face_i++ ) {
-		gFace = Sync_DomainToGlobal( topo->remotes[MT_FACE], face_i );
-
-		if( gFace < grids[2][0]->nPoints ) {
-			Grid_Lift( grids[2][0], gFace, dimInds );
-
-			dimInds[0] *= 2;
-			dimInds[1] *= 2;
-			if( topo->nDims == 3 )
-				dimInds[2] *= 2;
-
-			verts[0] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[1] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[2] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2; dimInds[1]++;
-			verts[3] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[4] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[5] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2; dimInds[1]++;
-			verts[6] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[7] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[8] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2; dimInds[1] -= 2;
-		}
-		else if( topo->nDims == 3 && gFace < grids[2][0]->nPoints + grids[2][1]->nPoints ) {
-			Grid_Lift( grids[2][1], gFace - grids[2][0]->nPoints, dimInds );
-
-			dimInds[0] *= 2;
-			dimInds[1] *= 2;
-			if( topo->nDims == 3 )
-				dimInds[2] *= 2;
-
-			verts[0] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[1] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[2] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2; dimInds[2]++;
-			verts[3] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[4] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[5] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2; dimInds[2]++;
-			verts[6] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[7] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[8] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2; dimInds[2] -= 2;
-		}
-		else if( topo->nDims == 3 && gFace < grids[2][0]->nPoints + grids[2][1]->nPoints + grids[2][2]->nPoints ) {
-			Grid_Lift( grids[2][2], gFace - grids[2][0]->nPoints - grids[2][1]->nPoints, dimInds );
-
-			dimInds[0] *= 2;
-			dimInds[1] *= 2;
-			if( topo->nDims == 3 )
-				dimInds[2] *= 2;
-
-			verts[0] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1]++;
-			verts[1] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1]++;
-			verts[2] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1] -= 2; dimInds[2]++;
-			verts[3] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1]++;
-			verts[4] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1]++;
-			verts[5] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1] -= 2; dimInds[2]++;
-			verts[6] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1]++;
-			verts[7] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1]++;
-			verts[8] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1] -= 2; dimInds[2] -= 2;
-		}
-
-		CartesianGenerator_MapToDomain( (CartesianGenerator*)self, (Sync*)IGraph_GetDomain( topo, MT_VERTEX ), 9, verts );
-		IGraph_SetIncidence( topo, MT_FACE, face_i, MT_VERTEX, 9, (int*)verts );
-	}
-
-	Memory_Free( dimInds );	
-
-	MPI_Barrier( self->mpiComm );
-	
-	Journal_Printf( stream, "... done.\n" );
-	Stream_UnIndent( stream );
-}
-
-void C2Generator_GenEdgeVertexInc( void* meshGenerator, IGraph* topo, Grid*** grids ) {
-	C2Generator*	self 		= (C2Generator*)meshGenerator;
-	const Sync*	sync		= IGraph_GetDomain( topo, MT_EDGE );
-	Stream*		stream;
-	unsigned	edge_i;
-	unsigned	gEdge;
-	unsigned	verts[3];
-	unsigned*	dimInds		= Memory_Alloc_Array( unsigned, topo->nDims, "edgeDimensionIndices" );
-
-	stream = Journal_Register( Info_Type, (Name)self->type  );
-	Journal_Printf( stream, "Generating edge-vertex incidence...\n" );
-	Stream_Indent( stream );
-
-	for( edge_i = 0; edge_i < (unsigned)Sync_GetNumDomains( sync ); edge_i++ ) {
-		gEdge = Sync_DomainToGlobal( sync, edge_i );
-
-		if( gEdge < grids[1][0]->nPoints ) {
-			Grid_Lift( grids[1][0], gEdge, dimInds );
-
-			dimInds[0] *= 2;
-			dimInds[1] *= 2;
-			if( topo->nDims == 3 )
-				dimInds[2] *= 2;
-
-			verts[0] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[1] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0]++;
-			verts[2] = Grid_Project( grids[0][0], dimInds );
-			dimInds[0] -= 2;
-		}
-		else if( gEdge < grids[1][0]->nPoints + grids[1][1]->nPoints ) {
-			Grid_Lift( grids[1][1], gEdge - grids[1][0]->nPoints, dimInds );
-
-			dimInds[0] *= 2;
-			dimInds[1] *= 2;
-			if( topo->nDims == 3 )
-				dimInds[2] *= 2;
-
-			verts[0] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1]++;
-			verts[1] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1]++;
-			verts[2] = Grid_Project( grids[0][0], dimInds );
-			dimInds[1] -= 2;
-		}
-		else if( topo->nDims == 3 && gEdge < grids[1][0]->nPoints + grids[1][1]->nPoints + grids[1][2]->nPoints ) {
-			Grid_Lift( grids[1][2], gEdge - grids[1][0]->nPoints - grids[1][1]->nPoints, dimInds );
-
-			dimInds[0] *= 2;
-			dimInds[1] *= 2;
-			if( topo->nDims == 3 )
-				dimInds[2] *= 2;
-
-			verts[0] = Grid_Project( grids[0][0], dimInds );
-			dimInds[2]++;
-			verts[1] = Grid_Project( grids[0][0], dimInds );
-			dimInds[2]++;
-			verts[2] = Grid_Project( grids[0][0], dimInds );
-			dimInds[2] -= 2;
-		}
-
-		CartesianGenerator_MapToDomain( (CartesianGenerator*)self, (Sync*)IGraph_GetDomain( topo, MT_VERTEX ), 3, verts );
-		IGraph_SetIncidence( topo, MT_EDGE, edge_i, MT_VERTEX, 3, (int*)verts );
-	}
-
-	Memory_Free( dimInds );
-
-	MPI_Barrier( self->mpiComm );
-
-	Journal_Printf( stream, "... done.\n" );
-	Stream_UnIndent( stream );
-}
-
-void C2Generator_GenElementTypes( void* meshGenerator, Mesh* mesh ) {
-	C2Generator*	self = (C2Generator*)meshGenerator;
-	Stream*		stream;
-	unsigned	nDomainEls;
-	unsigned	vertMap[8] = {0, 2, 6, 8, 18, 20, 24, 26};
-	unsigned	e_i;
-
-	assert( self );
-
-	stream = Journal_Register( Info_Type, (Name)self->type  );
-	Journal_Printf( stream, "Generating element types...\n" );
-	Stream_Indent( stream );
-
-	mesh->nElTypes = 1;
-	mesh->elTypes = AllocArray( Mesh_ElementType*, mesh->nElTypes );
-	mesh->elTypes[0] = (Mesh_ElementType*)Mesh_HexType_New();
-	Mesh_ElementType_SetMesh( mesh->elTypes[0], mesh );
-	Mesh_HexType_SetVertexMap( mesh->elTypes[0], vertMap );
-	nDomainEls = Mesh_GetDomainSize( mesh, Mesh_GetDimSize( mesh ) );
-	mesh->elTypeMap = AllocArray( unsigned, nDomainEls );
-	for( e_i = 0; e_i < nDomainEls; e_i++ )
-		mesh->elTypeMap[e_i] = 0;
-
-	if( self->regular )
-		Mesh_SetAlgorithms( mesh, Mesh_RegularAlgorithms_New( "", NULL ) );
-
-	MPI_Barrier( self->mpiComm );
-	Journal_Printf( stream, "... element types are '%s',\n", mesh->elTypes[0]->type );
-	Journal_Printf( stream, "... mesh algorithm type is '%s',\n", mesh->algorithms->type );
-	Journal_Printf( stream, "... done.\n" );
-	Stream_UnIndent( stream );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/C2Generator.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/C2Generator.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,508 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: C2Generator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type C2Generator_Type = "C2Generator";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+C2Generator* C2Generator_New( Name name, AbstractContext* context ) {
+	/* Variables set in this function */
+	SizeT                                                    _sizeOfSelf = sizeof(C2Generator);
+	Type                                                            type = C2Generator_Type;
+	Stg_Class_DeleteFunction*                                    _delete = _C2Generator_Delete;
+	Stg_Class_PrintFunction*                                      _print = _C2Generator_Print;
+	Stg_Class_CopyFunction*                                        _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*        _defaultConstructor = (void* (*)(Name))_C2Generator_New;
+	Stg_Component_ConstructFunction*                          _construct = _C2Generator_AssignFromXML;
+	Stg_Component_BuildFunction*                                  _build = _C2Generator_Build;
+	Stg_Component_InitialiseFunction*                        _initialise = _C2Generator_Initialise;
+	Stg_Component_ExecuteFunction*                              _execute = _C2Generator_Execute;
+	Stg_Component_DestroyFunction*                              _destroy = NULL;
+	AllocationType                                    nameAllocationType = NON_GLOBAL;
+	MeshGenerator_SetDimSizeFunc*                         setDimSizeFunc = CartesianGenerator_SetDimSize;
+	MeshGenerator_GenerateFunc*                             generateFunc = CartesianGenerator_Generate;
+	CartesianGenerator_SetTopologyParamsFunc*      setTopologyParamsFunc = C2Generator_SetTopologyParams;
+	CartesianGenerator_GenElementsFunc*                  genElementsFunc = _CartesianGenerator_GenElements;
+	CartesianGenerator_GenFacesFunc*                        genFacesFunc = _CartesianGenerator_GenFaces;
+	CartesianGenerator_GenEdgesFunc*                        genEdgesFunc = _CartesianGenerator_GenEdges;
+	CartesianGenerator_GenVerticesFunc*                  genVerticesFunc = _CartesianGenerator_GenVertices;
+	CartesianGenerator_GenElementVertexIncFunc*  genElementVertexIncFunc = C2Generator_GenElementVertexInc;
+	CartesianGenerator_GenVolumeEdgeIncFunc*        genVolumeEdgeIncFunc = _CartesianGenerator_GenVolumeEdgeInc;
+	CartesianGenerator_GenVolumeFaceIncFunc*        genVolumeFaceIncFunc = _CartesianGenerator_GenVolumeFaceInc;
+	CartesianGenerator_GenFaceVertexIncFunc*        genFaceVertexIncFunc = C2Generator_GenFaceVertexInc;
+	CartesianGenerator_GenFaceEdgeIncFunc*            genFaceEdgeIncFunc = _CartesianGenerator_GenFaceEdgeInc;
+	CartesianGenerator_GenEdgeVertexIncFunc*        genEdgeVertexIncFunc = C2Generator_GenEdgeVertexInc;
+	CartesianGenerator_GenElementTypesFunc*          genElementTypesFunc = C2Generator_GenElementTypes;
+
+	C2Generator* self = _C2Generator_New(  C2GENERATOR_PASSARGS  );
+
+   _MeshGenerator_Init( (MeshGenerator*)self, context );
+   _CartesianGenerator_Init( (CartesianGenerator*)self );
+   _C2Generator_Init( self );
+   return self;
+}
+
+C2Generator* _C2Generator_New(  C2GENERATOR_DEFARGS  ) {
+	C2Generator*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(C2Generator) );
+	self = (C2Generator*)_CartesianGenerator_New(  CARTESIANGENERATOR_PASSARGS  );
+
+
+
+	return self;
+}
+
+void _C2Generator_Init( C2Generator* self ) {
+	assert( self );
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _C2Generator_Delete( void* meshGenerator ) {
+	C2Generator*	self = (C2Generator*)meshGenerator;
+
+	/* Delete the parent. */
+	_CartesianGenerator_Delete( self );
+}
+
+void _C2Generator_Print( void* meshGenerator, Stream* stream ) {
+	C2Generator*	self = (C2Generator*)meshGenerator;
+	
+	/* Set the Journal for printing informations */
+	Stream* meshGeneratorStream;
+	meshGeneratorStream = Journal_Register( InfoStream_Type, (Name)"C2GeneratorStream" );
+
+	assert( self  );
+
+	/* Print parent */
+	Journal_Printf( stream, "C2Generator (ptr): (%p)\n", self );
+	_CartesianGenerator_Print( self, stream );
+}
+
+void _C2Generator_AssignFromXML( void* meshGenerator, Stg_ComponentFactory* cf, void* data ) {
+	_CartesianGenerator_AssignFromXML( meshGenerator, cf, data );
+}
+
+void _C2Generator_Build( void* meshGenerator, void* data ) {
+	_CartesianGenerator_Build( meshGenerator, data );
+}
+
+void _C2Generator_Initialise( void* meshGenerator, void* data ) {
+}
+
+void _C2Generator_Execute( void* meshGenerator, void* data ) {
+}
+
+void _C2Generator_Destroy( void* meshGenerator, void* data ) {
+}
+
+void C2Generator_SetTopologyParams( void* meshGenerator, unsigned* sizes, 
+				    unsigned maxDecompDims, unsigned* minDecomp, unsigned* maxDecomp )
+{
+	C2Generator*	self = (C2Generator*)meshGenerator;
+	unsigned*	vertSizes;
+	unsigned	d_i;
+
+	assert( self );
+
+	_CartesianGenerator_SetTopologyParams( self, sizes, 
+					       maxDecompDims, minDecomp, maxDecomp );
+	vertSizes = AllocArray( unsigned, self->vertGrid->nDims );
+	for( d_i = 0; d_i < self->vertGrid->nDims; d_i++ ) {
+		vertSizes[d_i] = self->vertGrid->sizes[d_i] * 2 - 1;
+		self->vertOrigin[d_i] *= 2;
+		self->vertRange[d_i] = self->vertRange[d_i] * 2 - 1;
+	}
+	Grid_SetSizes( self->vertGrid, vertSizes );
+	FreeArray( vertSizes );
+}
+
+void C2Generator_GenElementVertexInc( void* meshGenerator, IGraph* topo, Grid*** grids ) {
+	C2Generator*	self = (C2Generator*)meshGenerator;
+	Stream*		stream = Journal_Register( Info_Type, (Name)self->type  );
+	unsigned*	incEls;
+	unsigned*	dimInds;
+	unsigned	vertsPerEl;
+	unsigned	nDims;
+	unsigned	e_i, d_i;
+	int nDomainEls;
+
+	assert( self );
+	assert( topo );
+	assert( grids );
+
+	Journal_Printf( stream, "Generating element-vertex incidence...\n" );
+	Stream_Indent( stream );
+
+	vertsPerEl = (topo->nDims == 1) ? 3 : (topo->nDims == 2) ? 9 : 27;
+
+	nDims = topo->nDims;
+	nDomainEls = Sync_GetNumDomains( IGraph_GetDomain( topo, nDims ) );
+	incEls = Memory_Alloc_Array_Unnamed( unsigned, vertsPerEl );
+	dimInds = Memory_Alloc_Array_Unnamed( unsigned, topo->nDims );
+	for( e_i = 0; e_i < (unsigned)nDomainEls; e_i++ ) {
+		unsigned	gInd = Sync_DomainToGlobal( IGraph_GetDomain( topo, nDims ), e_i );
+		unsigned	curNode = 0;
+
+		Grid_Lift( grids[topo->nDims][0], gInd, dimInds );
+		for( d_i = 0; d_i < nDims; d_i++ )
+			dimInds[d_i] *= 2;
+
+		incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+		dimInds[0]++;
+		incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+		dimInds[0]++;
+		incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+		dimInds[0] -= 2;
+
+		if( topo->nDims >= 2 ) {
+			dimInds[1]++;
+			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2;
+			dimInds[1]++;
+			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2;
+			dimInds[1] -= 2;
+
+			if( topo->nDims >= 3 ) {
+				dimInds[2]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0] -= 2;
+				dimInds[1]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0] -= 2;
+				dimInds[1]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0] -= 2;
+				dimInds[1] -= 2;
+				dimInds[2]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0] -= 2;
+				dimInds[1]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0] -= 2;
+				dimInds[1]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0]++;
+				incEls[curNode++] = Grid_Project( grids[0][0], dimInds );
+				dimInds[0] -= 2;
+				dimInds[1] -= 2;
+				dimInds[2] -= 2;
+			}
+		}
+		CartesianGenerator_MapToDomain( (CartesianGenerator*)self, IGraph_GetDomain( topo, 0), vertsPerEl, incEls );
+		IGraph_SetIncidence( topo, topo->nDims, e_i, MT_VERTEX, vertsPerEl, (int*)incEls );
+	}
+
+	FreeArray( incEls );
+	FreeArray( dimInds );
+
+	MPI_Barrier( self->mpiComm );
+	Journal_Printf( stream, "... done.\n" );
+	Stream_UnIndent( stream );
+}
+
+void C2Generator_GenFaceVertexInc( void* meshGenerator, IGraph* topo, Grid*** grids ) {
+	C2Generator*	self 		= (C2Generator*)meshGenerator;
+	Stream*		stream;
+	unsigned	face_i;
+	unsigned	gFace;
+	unsigned	verts[9];
+	unsigned*	dimInds		= Memory_Alloc_Array( unsigned, topo->nDims, "edgeDimensionIndices" );
+
+	stream = Journal_Register( Info_Type, (Name)self->type  );
+	Journal_Printf( stream, "Generating face-vertex types...\n" );
+	Stream_Indent( stream );
+
+	for( face_i = 0; face_i < (unsigned)(topo->remotes[MT_FACE]->nDomains); face_i++ ) {
+		gFace = Sync_DomainToGlobal( topo->remotes[MT_FACE], face_i );
+
+		if( gFace < grids[2][0]->nPoints ) {
+			Grid_Lift( grids[2][0], gFace, dimInds );
+
+			dimInds[0] *= 2;
+			dimInds[1] *= 2;
+			if( topo->nDims == 3 )
+				dimInds[2] *= 2;
+
+			verts[0] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[1] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[2] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2; dimInds[1]++;
+			verts[3] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[4] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[5] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2; dimInds[1]++;
+			verts[6] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[7] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[8] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2; dimInds[1] -= 2;
+		}
+		else if( topo->nDims == 3 && gFace < grids[2][0]->nPoints + grids[2][1]->nPoints ) {
+			Grid_Lift( grids[2][1], gFace - grids[2][0]->nPoints, dimInds );
+
+			dimInds[0] *= 2;
+			dimInds[1] *= 2;
+			if( topo->nDims == 3 )
+				dimInds[2] *= 2;
+
+			verts[0] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[1] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[2] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2; dimInds[2]++;
+			verts[3] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[4] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[5] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2; dimInds[2]++;
+			verts[6] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[7] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[8] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2; dimInds[2] -= 2;
+		}
+		else if( topo->nDims == 3 && gFace < grids[2][0]->nPoints + grids[2][1]->nPoints + grids[2][2]->nPoints ) {
+			Grid_Lift( grids[2][2], gFace - grids[2][0]->nPoints - grids[2][1]->nPoints, dimInds );
+
+			dimInds[0] *= 2;
+			dimInds[1] *= 2;
+			if( topo->nDims == 3 )
+				dimInds[2] *= 2;
+
+			verts[0] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1]++;
+			verts[1] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1]++;
+			verts[2] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1] -= 2; dimInds[2]++;
+			verts[3] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1]++;
+			verts[4] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1]++;
+			verts[5] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1] -= 2; dimInds[2]++;
+			verts[6] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1]++;
+			verts[7] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1]++;
+			verts[8] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1] -= 2; dimInds[2] -= 2;
+		}
+
+		CartesianGenerator_MapToDomain( (CartesianGenerator*)self, (Sync*)IGraph_GetDomain( topo, MT_VERTEX ), 9, verts );
+		IGraph_SetIncidence( topo, MT_FACE, face_i, MT_VERTEX, 9, (int*)verts );
+	}
+
+	Memory_Free( dimInds );	
+
+	MPI_Barrier( self->mpiComm );
+	
+	Journal_Printf( stream, "... done.\n" );
+	Stream_UnIndent( stream );
+}
+
+void C2Generator_GenEdgeVertexInc( void* meshGenerator, IGraph* topo, Grid*** grids ) {
+	C2Generator*	self 		= (C2Generator*)meshGenerator;
+	const Sync*	sync		= IGraph_GetDomain( topo, MT_EDGE );
+	Stream*		stream;
+	unsigned	edge_i;
+	unsigned	gEdge;
+	unsigned	verts[3];
+	unsigned*	dimInds		= Memory_Alloc_Array( unsigned, topo->nDims, "edgeDimensionIndices" );
+
+	stream = Journal_Register( Info_Type, (Name)self->type  );
+	Journal_Printf( stream, "Generating edge-vertex incidence...\n" );
+	Stream_Indent( stream );
+
+	for( edge_i = 0; edge_i < (unsigned)Sync_GetNumDomains( sync ); edge_i++ ) {
+		gEdge = Sync_DomainToGlobal( sync, edge_i );
+
+		if( gEdge < grids[1][0]->nPoints ) {
+			Grid_Lift( grids[1][0], gEdge, dimInds );
+
+			dimInds[0] *= 2;
+			dimInds[1] *= 2;
+			if( topo->nDims == 3 )
+				dimInds[2] *= 2;
+
+			verts[0] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[1] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0]++;
+			verts[2] = Grid_Project( grids[0][0], dimInds );
+			dimInds[0] -= 2;
+		}
+		else if( gEdge < grids[1][0]->nPoints + grids[1][1]->nPoints ) {
+			Grid_Lift( grids[1][1], gEdge - grids[1][0]->nPoints, dimInds );
+
+			dimInds[0] *= 2;
+			dimInds[1] *= 2;
+			if( topo->nDims == 3 )
+				dimInds[2] *= 2;
+
+			verts[0] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1]++;
+			verts[1] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1]++;
+			verts[2] = Grid_Project( grids[0][0], dimInds );
+			dimInds[1] -= 2;
+		}
+		else if( topo->nDims == 3 && gEdge < grids[1][0]->nPoints + grids[1][1]->nPoints + grids[1][2]->nPoints ) {
+			Grid_Lift( grids[1][2], gEdge - grids[1][0]->nPoints - grids[1][1]->nPoints, dimInds );
+
+			dimInds[0] *= 2;
+			dimInds[1] *= 2;
+			if( topo->nDims == 3 )
+				dimInds[2] *= 2;
+
+			verts[0] = Grid_Project( grids[0][0], dimInds );
+			dimInds[2]++;
+			verts[1] = Grid_Project( grids[0][0], dimInds );
+			dimInds[2]++;
+			verts[2] = Grid_Project( grids[0][0], dimInds );
+			dimInds[2] -= 2;
+		}
+
+		CartesianGenerator_MapToDomain( (CartesianGenerator*)self, (Sync*)IGraph_GetDomain( topo, MT_VERTEX ), 3, verts );
+		IGraph_SetIncidence( topo, MT_EDGE, edge_i, MT_VERTEX, 3, (int*)verts );
+	}
+
+	Memory_Free( dimInds );
+
+	MPI_Barrier( self->mpiComm );
+
+	Journal_Printf( stream, "... done.\n" );
+	Stream_UnIndent( stream );
+}
+
+void C2Generator_GenElementTypes( void* meshGenerator, Mesh* mesh ) {
+	C2Generator*	self = (C2Generator*)meshGenerator;
+	Stream*		stream;
+	unsigned	nDomainEls;
+	unsigned	vertMap[8] = {0, 2, 6, 8, 18, 20, 24, 26};
+	unsigned	e_i;
+
+	assert( self );
+
+	stream = Journal_Register( Info_Type, (Name)self->type  );
+	Journal_Printf( stream, "Generating element types...\n" );
+	Stream_Indent( stream );
+
+	mesh->nElTypes = 1;
+	mesh->elTypes = AllocArray( Mesh_ElementType*, mesh->nElTypes );
+	mesh->elTypes[0] = (Mesh_ElementType*)Mesh_HexType_New();
+	Mesh_ElementType_SetMesh( mesh->elTypes[0], mesh );
+	Mesh_HexType_SetVertexMap( mesh->elTypes[0], vertMap );
+	nDomainEls = Mesh_GetDomainSize( mesh, Mesh_GetDimSize( mesh ) );
+	mesh->elTypeMap = AllocArray( unsigned, nDomainEls );
+	for( e_i = 0; e_i < nDomainEls; e_i++ )
+		mesh->elTypeMap[e_i] = 0;
+
+	if( self->regular )
+		Mesh_SetAlgorithms( mesh, Mesh_RegularAlgorithms_New( "", NULL ) );
+
+	MPI_Barrier( self->mpiComm );
+	Journal_Printf( stream, "... element types are '%s',\n", mesh->elTypes[0]->type );
+	Journal_Printf( stream, "... mesh algorithm type is '%s',\n", mesh->algorithms->type );
+	Journal_Printf( stream, "... done.\n" );
+	Stream_UnIndent( stream );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/ConstantElementType.c
--- a/Discretisation/src/ConstantElementType.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: ConstantElementType.c 1177 2008-07-15 01:29:58Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType.h"
-#include "ConstantElementType.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-const Type ConstantElementType_Type = "ConstantElementType";
-#define _ConstantElementType_NodeCount 1
-
-ConstantElementType* ConstantElementType_New( Name name ) {
-  ConstantElementType* self = (ConstantElementType*)ConstantElementType_DefaultNew( name );
-
-	self->isConstructed = True;	
-	_ElementType_Init( (ElementType*)self, _ConstantElementType_NodeCount );
-	_ConstantElementType_Init( self );	
-
-	return self;
-}
-
-void* ConstantElementType_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(ConstantElementType);
-	Type                                                                                    type = ConstantElementType_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _ConstantElementType_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _ConstantElementType_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = ConstantElementType_DefaultNew;
-	Stg_Component_ConstructFunction*                                                  _construct = _ConstantElementType_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _ConstantElementType_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _ConstantElementType_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _ConstantElementType_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _ConstantElementType_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _ConstantElementType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _ConstantElementType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ConstantElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ConstantElementType_SurfaceNormal;
-
-	return _ConstantElementType_New(  CONSTANTELEMENTTYPE_PASSARGS  );
-}
-
-ConstantElementType* _ConstantElementType_New(  CONSTANTELEMENTTYPE_DEFARGS  ) {
-	ConstantElementType*		self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(ConstantElementType) );
-	self = (ConstantElementType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual functions */
-	
-	/* ConstantElementType info */
-
-	return self;
-}
-
-void _ConstantElementType_Init( ConstantElementType* self ) {
-	self->dim = 0;
-}
-
-void _ConstantElementType_Delete( void* elementType ) {
-	ConstantElementType* self = (ConstantElementType*)elementType;
-
-	/* Stg_Class_Delete parent*/
-	_ElementType_Delete( self );
-}
-
-void _ConstantElementType_Print( void* elementType, Stream* stream ) {
-	ConstantElementType* self = (ConstantElementType*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* constantElementTypeStream = stream;
-	
-	/* General info */
-	Journal_Printf( constantElementTypeStream, "ConstantElementType (ptr): %p\n", self );
-	
-	/* Print parent */
-	_ElementType_Print( self, constantElementTypeStream );
-	
-	/* Virtual info */
-	
-	/* ConstantElementType info */
-}
-
-void _ConstantElementType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
-	ConstantElementType* self = (ConstantElementType*)elementType;
-
-	_ConstantElementType_Init( self );
-}
-	
-void _ConstantElementType_Initialise( void* elementType, void *data ){
-}
-	
-void _ConstantElementType_Execute( void* elementType, void *data ){
-}
-	
-void _ConstantElementType_Destroy( void* elementType, void *data ){
-	ConstantElementType* self = (ConstantElementType*)elementType;
-
-	_ElementType_Destroy( self, data );
-}
-
-void _ConstantElementType_Build( void* elementType, void *data ) {
-
-}
-
-/*
-
- - Shape function definition
- - Constant shape function in 2d/3d has only one node at centroid of element.
- - Node id is 0 in both cases.
- - Local coordinate domain spans  -1 <= xi,eta <= 1 in 2d
- - Local coordinate domain spans  -1 <= xi,eta,zeta <= 1 in 3d
-
-*/
-void _ConstantElementType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
-	evaluatedValues[0] = 1.0;
-}
-
-
-/*
-Since we use only have one constant shape func for 2d and 3d quads, then
-if we want to return the zero derivatives we need to pass in "dim" so we know
-whether to fill in GNi[0][0] = GNi[1][0] = 0.0 + GNi[2][0] = 0.0 if dim == 3
-Should just return error if we try to take deriv of constant. No one would want
-to do this!
-*/
-void _ConstantElementType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
-		double** const evaluatedDerivatives )
-{		
-	Stream* error = Journal_Register( ErrorStream_Type, (Name)ConstantElementType_Type  );
-	/* all derivatives are zero*/
-	Journal_Printf( error, "Error: Trying take derivative of a constant shape function \n" );
-	assert( 0 );
-}
-
-
-void _ConstantElementType_ConvertGlobalCoordToElLocal(
-		void*		elementType,
-		void*		mesh, 
-		unsigned	element, 
-		const double*	globalCoord,
-		double*		elLocalCoord )
-{
-	/* See header file function introduction for explanation... */
-	elLocalCoord[0] = elLocalCoord[1] = elLocalCoord[2] = 0;
-}
-
-int _ConstantElementType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
-	Stream*	errStream	= Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
-
-	Journal_Printf( errStream, "surface normal not defined for this element type.\n" );
-	assert( 0 );
-
-	normal = NULL;
-
-	return -1;
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/ConstantElementType.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/ConstantElementType.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,210 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: ConstantElementType.c 1177 2008-07-15 01:29:58Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType.h"
+#include "ConstantElementType.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+const Type ConstantElementType_Type = "ConstantElementType";
+#define _ConstantElementType_NodeCount 1
+
+ConstantElementType* ConstantElementType_New( Name name ) {
+  ConstantElementType* self = (ConstantElementType*)ConstantElementType_DefaultNew( name );
+
+	self->isConstructed = True;	
+	_ElementType_Init( (ElementType*)self, _ConstantElementType_NodeCount );
+	_ConstantElementType_Init( self );	
+
+	return self;
+}
+
+void* ConstantElementType_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(ConstantElementType);
+	Type                                                                                    type = ConstantElementType_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _ConstantElementType_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _ConstantElementType_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = ConstantElementType_DefaultNew;
+	Stg_Component_ConstructFunction*                                                  _construct = _ConstantElementType_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _ConstantElementType_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _ConstantElementType_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _ConstantElementType_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _ConstantElementType_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _ConstantElementType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _ConstantElementType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ConstantElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ConstantElementType_SurfaceNormal;
+
+	return _ConstantElementType_New(  CONSTANTELEMENTTYPE_PASSARGS  );
+}
+
+ConstantElementType* _ConstantElementType_New(  CONSTANTELEMENTTYPE_DEFARGS  ) {
+	ConstantElementType*		self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(ConstantElementType) );
+	self = (ConstantElementType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual functions */
+	
+	/* ConstantElementType info */
+
+	return self;
+}
+
+void _ConstantElementType_Init( ConstantElementType* self ) {
+	self->dim = 0;
+}
+
+void _ConstantElementType_Delete( void* elementType ) {
+	ConstantElementType* self = (ConstantElementType*)elementType;
+
+	/* Stg_Class_Delete parent*/
+	_ElementType_Delete( self );
+}
+
+void _ConstantElementType_Print( void* elementType, Stream* stream ) {
+	ConstantElementType* self = (ConstantElementType*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* constantElementTypeStream = stream;
+	
+	/* General info */
+	Journal_Printf( constantElementTypeStream, "ConstantElementType (ptr): %p\n", self );
+	
+	/* Print parent */
+	_ElementType_Print( self, constantElementTypeStream );
+	
+	/* Virtual info */
+	
+	/* ConstantElementType info */
+}
+
+void _ConstantElementType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
+	ConstantElementType* self = (ConstantElementType*)elementType;
+
+	_ConstantElementType_Init( self );
+}
+	
+void _ConstantElementType_Initialise( void* elementType, void *data ){
+}
+	
+void _ConstantElementType_Execute( void* elementType, void *data ){
+}
+	
+void _ConstantElementType_Destroy( void* elementType, void *data ){
+	ConstantElementType* self = (ConstantElementType*)elementType;
+
+	_ElementType_Destroy( self, data );
+}
+
+void _ConstantElementType_Build( void* elementType, void *data ) {
+
+}
+
+/*
+
+ - Shape function definition
+ - Constant shape function in 2d/3d has only one node at centroid of element.
+ - Node id is 0 in both cases.
+ - Local coordinate domain spans  -1 <= xi,eta <= 1 in 2d
+ - Local coordinate domain spans  -1 <= xi,eta,zeta <= 1 in 3d
+
+*/
+void _ConstantElementType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
+	evaluatedValues[0] = 1.0;
+}
+
+
+/*
+Since we use only have one constant shape func for 2d and 3d quads, then
+if we want to return the zero derivatives we need to pass in "dim" so we know
+whether to fill in GNi[0][0] = GNi[1][0] = 0.0 + GNi[2][0] = 0.0 if dim == 3
+Should just return error if we try to take deriv of constant. No one would want
+to do this!
+*/
+void _ConstantElementType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
+		double** const evaluatedDerivatives )
+{		
+	Stream* error = Journal_Register( ErrorStream_Type, (Name)ConstantElementType_Type  );
+	/* all derivatives are zero*/
+	Journal_Printf( error, "Error: Trying take derivative of a constant shape function \n" );
+	assert( 0 );
+}
+
+
+void _ConstantElementType_ConvertGlobalCoordToElLocal(
+		void*		elementType,
+		void*		mesh, 
+		unsigned	element, 
+		const double*	globalCoord,
+		double*		elLocalCoord )
+{
+	/* See header file function introduction for explanation... */
+	elLocalCoord[0] = elLocalCoord[1] = elLocalCoord[2] = 0;
+}
+
+int _ConstantElementType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
+	Stream*	errStream	= Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
+
+	Journal_Printf( errStream, "surface normal not defined for this element type.\n" );
+	assert( 0 );
+
+	normal = NULL;
+
+	return -1;
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Element.c
--- a/Discretisation/src/Element.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Element.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "Element.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-void FiniteElement_Element_Print( void* element, Stream* stream ) {
-	FiniteElement_Element*	self = (FiniteElement_Element*)element;
-	
-	Journal_Printf( stream, "FiniteElement_Element (ptr): %p\n", self );
-	Journal_Printf( stream, "\telementType_I: %u", self->elementType_I );
-	Journal_Printf( stream, "\tcell_I: %u", self->cell_I );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Element.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/Element.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,62 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Element.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "Element.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+void FiniteElement_Element_Print( void* element, Stream* stream ) {
+	FiniteElement_Element*	self = (FiniteElement_Element*)element;
+	
+	Journal_Printf( stream, "FiniteElement_Element (ptr): %p\n", self );
+	Journal_Printf( stream, "\telementType_I: %u", self->elementType_I );
+	Journal_Printf( stream, "\tcell_I: %u", self->cell_I );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/ElementType.c
--- a/Discretisation/src/ElementType.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,633 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: ElementType.c 1179 2008-07-15 05:28:11Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "FeMesh.h"
-#include "ElementType.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-
-const Type ElementType_Type = "ElementType";
-
-ElementType* _ElementType_New(  ELEMENTTYPE_DEFARGS  ) {
-	ElementType* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(ElementType) );
-	self = (ElementType*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual functions */
-	self->_build = _build;
-	self->_evaluateShapeFunctionsAt = _evaluateShapeFunctionsAt;
-	self->_evaluateShapeFunctionLocalDerivsAt = _evaluateShapeFunctionLocalDerivsAt;
-	self->_convertGlobalCoordToElLocal = _convertGlobalCoordToElLocal;
-	self->_jacobianDeterminantSurface = _jacobianDeterminantSurface;
-	self->_surfaceNormal = _surfaceNormal;
-	
-	/* ElementType info */
-	
-	return self;
-}
-
-void _ElementType_Init( ElementType* self, Index nodeCount ) {
-	/* General and Virtual info should already be set */
-	self->dim = 0;
-	/* ElementType info */
-	self->nodeCount = nodeCount;
-	self->debug = Stream_RegisterChild( StgFEM_Discretisation_Debug, ElementType_Type );
-	self->inc = IArray_New();
-}
-
-
-void _ElementType_Destroy( void* elementType, void* data ){
-	ElementType* self = (ElementType*)elementType;
-
-	NewClass_Delete( self->inc );
-
-	Stg_Component_Destroy( self, data, False );
-}
-
-void _ElementType_Delete( void* elementType ) {
-	ElementType* self = (ElementType*)elementType;
-
-	/* Stg_Class_Delete parent*/
-	_Stg_Component_Delete( self );
-}
-
-void _ElementType_Print( void* elementType, Stream* stream ) {
-	ElementType* self = (ElementType*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* elementTypeStream = stream;
-	
-	/* General info */
-	Journal_Printf( elementTypeStream, "ElementType (ptr): %p\n", self );
-	
-	/* Print parent */
-	_Stg_Class_Print( self, elementTypeStream );
-	
-	/* Virtual info */
-	Journal_Printf( elementTypeStream, "\t_build (func ptr): %p\n", self->_build );
-	Journal_Printf( elementTypeStream, "\t_evaluateShapeFunctionsAt (func ptr): %p\n", self->_evaluateShapeFunctionsAt );
-	Journal_Printf( elementTypeStream,  "\t_evaluateShapeFunctionLocalDerivsAt (func ptr): %p\n", self->_evaluateShapeFunctionLocalDerivsAt );
-	
-	/* ElementType info */
-	Journal_Printf( elementTypeStream, "\tnodeCount: %u\n", self->nodeCount );
-}
-
-/* +++ Virtual Function Interfaces +++ */
-
-void ElementType_Build( void* elementType, void *data ) {
-	ElementType* self = (ElementType*)elementType;
-	
-	/* ElementType's are implemented NOT in the standard parent child
-	 * manner as the rest of StGermain. Here the parents calls the child's
-	 * build function */
-	self->_build( self, data);
-}
-
-void ElementType_EvaluateShapeFunctionsAt( void* elementType, const double localCoord[], double* const evaluatedValues ) {
-	ElementType* self = (ElementType*)elementType;
-	
-	self->_evaluateShapeFunctionsAt( self, localCoord, evaluatedValues );
-}
-
-void ElementType_EvaluateShapeFunctionLocalDerivsAt( void* elementType, const double localCoord[], double** const evaluatedDerivatives ) {
-	ElementType* self = (ElementType*)elementType;
-	
-	self->_evaluateShapeFunctionLocalDerivsAt( self, localCoord, evaluatedDerivatives );
-}
-
-double _ElementType_JacobianDeterminantSurface( void* elementType, void* mesh, unsigned element_I, const double localCoord[], 
-						unsigned face_I, unsigned norm ) 
-{
-	ElementType*	self;
-	Stream*			error = Journal_Register( ErrorStream_Type, (Name)ElementType_Type );
-
-	self = (ElementType* ) elementType;
-
-	Journal_Printf( error, "Error: the jacobian for this element type cannot be evaluated on the element surface" );
-	Journal_Printf( error, "(perhaps because the nodes are defined internally for the element).\n" );
-	assert( 0 );
-
-	return -1;
-}
-
-double ElementType_JacobianDeterminantSurface( void* elementType, void* mesh, unsigned element_I, 
-						const double localCoord[], unsigned face_I, unsigned norm ) {
-	ElementType* self = (ElementType*)elementType;
-
-	return self->_jacobianDeterminantSurface( self, mesh, element_I, localCoord, face_I, norm );
-}
-
-#define EPS 1.0E-6
-
-int _ElementType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
-	ElementType* self;
-
-	self = (ElementType*)elementType;
-
-	memset( normal, 0, sizeof(double) * dim );
-
-	if( xi[J_AXIS] < -1.0 + EPS ) {
-		normal[J_AXIS] = -1.0;
-		return 0;
-	}
-	else if( xi[J_AXIS] > +1.0 - EPS ) {
-		normal[J_AXIS] = +1.0;
-		return 1;
-	}
-	else if( xi[I_AXIS] < -1.0 + EPS ) {
-		normal[I_AXIS] = -1.0;
-		return 2;
-	}
-	else if( xi[I_AXIS] > +1.0 - EPS ) {
-		normal[I_AXIS] = +1.0;
-		return 3;
-	}
-	else if( xi[K_AXIS] < -1.0 + EPS ) {
-		normal[K_AXIS] = -1.0;
-		return 4;
-	}
-	else if( xi[K_AXIS] > +1.0 - EPS ) {
-		normal[K_AXIS] = +1.0;
-		return 5;
-	}
-	return 0;
-}
-
-int ElementType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
-	ElementType* 	self = (ElementType*)elementType;
-
-	return self->_surfaceNormal( self, element_I, dim, xi, normal );
-}
-
-void ElementType_ConvertGlobalCoordToElLocal(
-		void*		elementType,
-		void*		mesh, 
-		unsigned	element, 
-		const double*	globalCoord,
-		double*		elLocalCoord )
-{
-	ElementType*	self = (ElementType*)elementType;
-
-	self->_convertGlobalCoordToElLocal( self, mesh, element, globalCoord, elLocalCoord );
-}
-
-
-/* +++ Virtual Function Implementations +++ */
-
-void _ElementType_ConvertGlobalCoordToElLocal(
-		void*		elementType,
-		void*		_mesh, 
-		unsigned	element, 
-		const double*	globalCoord,
-		double*		elLocalCoord )
-{		
-	ElementType*		self            = (ElementType*)elementType;
-	Mesh*			mesh = (Mesh*)_mesh;
-	TensorArray         jacobiMatrix;
-	double              tolerance       = 0.0001; /* TODO put on class */
-	double              maxResidual;
-	Iteration_Index     maxIterations   = 100;    /*  TODO put on class */
-	Iteration_Index     iteration_I;
-	Node_Index          node_I;
-	Node_Index          nodeCount       = self->nodeCount;
-	double*             evaluatedShapeFuncs = self->evaluatedShapeFunc;
-	XYZ                 rightHandSide;
-	XYZ                 xiIncrement;
-	double              shapeFunc;
-	double*       	    nodeCoord;
-	double**            GNi = self->GNi;
-	unsigned	    nInc, *inc;
-	Dimension_Index     dim             = Mesh_GetDimSize( mesh );
-
-	/* This function uses a Newton-Raphson iterative method to find the local coordinate from the global coordinate 
-	 * the equations are ( see FEM/BEM nodes p. 9 )
-	 *
-	 * x = \Sum_n( Ni( \xi, \eta, \zeta ) x_n )
-	 * y = \Sum_n( Ni( \xi, \eta, \zeta ) y_n )
-	 * z = \Sum_n( Ni( \xi, \eta, \zeta ) z_n )
-	 *
-	 * which are non-linear.
-	 *
-	 * This can be formulated into a system of linear equations of the form
-	 *
-	 * [              ][ \xi_{i + 1}   - \xi_i   ]   [ x - \Sum_n( Ni( \xi_i, \eta_i, \zeta_i ) x_n ]
-	 * [   Jacobian   ][ \eta_{i + 1}  - \eta_i  ] = [ y - \Sum_n( Ni( \xi_i, \eta_i, \zeta_i ) y_n ]
-	 * [              ][ \zeta_{i + 1} - \zeta_I ]   [ z - \Sum_n( Ni( \xi_i, \eta_i, \zeta_i ) z_n ]
-	 *
-	 * see http://en.wikipedia.org/wiki/Newton-Raphson_method
-	 *
-	 * */
-
-	Mesh_GetIncidence( mesh, Mesh_GetDimSize( mesh ), element, MT_VERTEX, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = (unsigned*)IArray_GetPtr( (self->inc) );
-
-	/* Initial guess for element local coordinate is in the centre of the element - ( 0.0, 0.0, 0.0 ) */
-	memset( elLocalCoord, 0, dim*sizeof(double) );
-
-	/* Do Newton-Raphson Iteration */
-	for ( iteration_I = 0 ; iteration_I < maxIterations ; iteration_I++ ) {
-		/* Initialise Values */
-		TensorArray_Zero( jacobiMatrix );
-		memset( rightHandSide, 0, sizeof( XYZ ) );
-
-		/* Evaluate shape functions for rhs */
-		ElementType_EvaluateShapeFunctionsAt( self, elLocalCoord, evaluatedShapeFuncs );
-		self->_evaluateShapeFunctionLocalDerivsAt( self, elLocalCoord, GNi );
-
-
-		for ( node_I = 0 ; node_I < nodeCount ; node_I++ ) {
-			shapeFunc = evaluatedShapeFuncs[node_I];
-			nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
-
-			/* Form jacobi matrix */
-			jacobiMatrix[ MAP_TENSOR( 0, 0, dim ) ] += GNi[0][node_I] * nodeCoord[ I_AXIS ];
-			jacobiMatrix[ MAP_TENSOR( 0, 1, dim ) ] += GNi[1][node_I] * nodeCoord[ I_AXIS ];
-
-			jacobiMatrix[ MAP_TENSOR( 1, 0, dim ) ] += GNi[0][node_I] * nodeCoord[ J_AXIS ];
-			jacobiMatrix[ MAP_TENSOR( 1, 1, dim ) ] += GNi[1][node_I] * nodeCoord[ J_AXIS ];
-			
-
-			/* Form right hand side */
-			rightHandSide[ I_AXIS ] -= shapeFunc * nodeCoord[ I_AXIS ];
-			rightHandSide[ J_AXIS ] -= shapeFunc * nodeCoord[ J_AXIS ];
-
-			if ( dim == 3 ) {
-				jacobiMatrix[ MAP_3D_TENSOR( 0, 2 ) ] += GNi[2][node_I] * nodeCoord[ I_AXIS ];
-				jacobiMatrix[ MAP_3D_TENSOR( 1, 2 ) ] += GNi[2][node_I] * nodeCoord[ J_AXIS ];
-
-				jacobiMatrix[ MAP_3D_TENSOR( 2, 0 ) ] += GNi[0][node_I] * nodeCoord[ K_AXIS ];
-				jacobiMatrix[ MAP_3D_TENSOR( 2, 1 ) ] += GNi[1][node_I] * nodeCoord[ K_AXIS ];
-				jacobiMatrix[ MAP_3D_TENSOR( 2, 2 ) ] += GNi[2][node_I] * nodeCoord[ K_AXIS ];
-				
-				rightHandSide[ K_AXIS ] -= shapeFunc * nodeCoord[ K_AXIS ];
-			}
-		}
-
-		/* Finish building right hand side */
-		rightHandSide[ I_AXIS ] += globalCoord[ I_AXIS ];
-		rightHandSide[ J_AXIS ] += globalCoord[ J_AXIS ];
-		if ( dim == 3 )
-			rightHandSide[ K_AXIS ] += globalCoord[ K_AXIS ];
-
-		/* Solve for xi increment */
-		TensorArray_SolveSystem( jacobiMatrix, xiIncrement, rightHandSide, dim );
-
-		/* Update xi */
-		elLocalCoord[ I_AXIS ] += xiIncrement[ I_AXIS ];
-		elLocalCoord[ J_AXIS ] += xiIncrement[ J_AXIS ];
-		if ( dim == 3 )
-			elLocalCoord[ K_AXIS ] += xiIncrement[ K_AXIS ];
-
-		/* Check for convergence */
-		maxResidual = fabs( xiIncrement[ I_AXIS ] );
-		if ( maxResidual < fabs( xiIncrement[ J_AXIS ] ) )
-			maxResidual = fabs( xiIncrement[ J_AXIS ] );
-		if ( dim == 3 && maxResidual < fabs( xiIncrement[ K_AXIS ] ) )
-			maxResidual = fabs( xiIncrement[ K_AXIS ] );
-
-		if ( maxResidual < tolerance )
-			break;
-	}
-}				
-
-
-/* +++ Public Functions +++ */
-void ElementType_ShapeFunctionsGlobalDerivs( 
-		void*			elementType,
-		void*			_mesh,
-		Element_DomainIndex	elId, 
-		double*			xi, 
-		int			dim, 
-		double*			detJac, 
-		double**		GNx )
-{
-	ElementType*			self = (ElementType*)elementType;
-	Mesh*				mesh = (Mesh*)_mesh;
-	double				*nodeCoord;
-	
-	double jac[3][3];
-	int rows;		/* max dimensions */
-	int cols;		/* max nodes per el */
-	double** GNi; 
-	int n, i, j;
-	double globalSF_DerivVal;
-	int dx, dxi;
-	double tmp, D = 0.0;
-	double cof[3][3];	/* cofactors */
-	unsigned nInc, *inc;
-	Index nodesPerEl;
-
-	rows=Mesh_GetDimSize( mesh );
-	cols=self->nodeCount;	
-	
-	GNi = self->GNi;
-
-	nodesPerEl = self->nodeCount;
-
-	Mesh_GetIncidence( mesh, Mesh_GetDimSize( mesh ), elId, MT_VERTEX, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = (unsigned*)IArray_GetPtr((self->inc) );
-	
-	/*
-	If constant shape function gets passed in here, getLocalDeriv will
-	indicate the error and exit code.
-	*/
-	
-	self->_evaluateShapeFunctionLocalDerivsAt( self, xi, GNi );
-	
-	
-	/* build the jacobian matrix */
-	/*
-	jac = 	\sum_i d/d\xi( N_i ) x_i 		\sum_i d/d\xi( N_i ) y_i
-			\sum_i d/d\eta( N_i ) x_i 		\sum_i d/d\eta( N_i ) y_i
-	*/
-	/* unroll this bugger cause we do it all the time */
-	if( dim == 2 ) {
-		jac[0][0] = jac[0][1] = jac[1][0] = jac[1][1] = 0.0;
-		for( n=0; n<(int)nodesPerEl; n++){	
-			nodeCoord = Mesh_GetVertex( mesh, inc[n] );
-			jac[0][0] = jac[0][0] + GNi[0][n] * nodeCoord[0];
-			jac[0][1] = jac[0][1] + GNi[0][n] * nodeCoord[1];
-			
-			jac[1][0] = jac[1][0] + GNi[1][n] * nodeCoord[0];
-			jac[1][1] = jac[1][1] + GNi[1][n] * nodeCoord[1];
-		}
-	}
-	
-	if( dim == 3 ) {
-		jac[0][0] = jac[0][1] = jac[0][2] = 0.0;
-		jac[1][0] = jac[1][1] = jac[1][2] = 0.0;
-		jac[2][0] = jac[2][1] = jac[2][2] = 0.0;
-		for( n=0; n<(int)nodesPerEl; n++){	
-			nodeCoord = Mesh_GetVertex( mesh, inc[n] );
-			jac[0][0] = jac[0][0] + GNi[0][n] * nodeCoord[0];
-			jac[0][1] = jac[0][1] + GNi[0][n] * nodeCoord[1];
-			jac[0][2] = jac[0][2] + GNi[0][n] * nodeCoord[2];
-			
-			jac[1][0] = jac[1][0] + GNi[1][n] * nodeCoord[0];
-			jac[1][1] = jac[1][1] + GNi[1][n] * nodeCoord[1];
-			jac[1][2] = jac[1][2] + GNi[1][n] * nodeCoord[2];
-			
-			jac[2][0] = jac[2][0] + GNi[2][n] * nodeCoord[0];
-			jac[2][1] = jac[2][1] + GNi[2][n] * nodeCoord[1];
-			jac[2][2] = jac[2][2] + GNi[2][n] * nodeCoord[2];
-		}
-	}
-	
-	/* get determinant of the jacobian matrix */
-	if( dim == 2 ) {
-		D = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0]; 
-	}		
-	if( dim == 3 ) {
-		D = jac[0][0]*( jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1] ) 
-				  - jac[0][1]*( jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0] ) 
-				  + jac[0][2]*( jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0] );
-	}
-	(*detJac) = D;
-	
-	
-	/* invert the jacobian matrix A^-1 = adj(A)/det(A) */
-	if( dim == 2 ) {
-		tmp = jac[0][0];
-		jac[0][0] = jac[1][1]/D;
-		jac[1][1] = tmp/D;
-		jac[0][1] = -jac[0][1]/D;
-		jac[1][0] = -jac[1][0]/D;		
-	}
-	if( dim == 3 ) {
-		/*
-		00 01 02
-		10 11 12
-		20 21 22		
-		*/		
-		cof[0][0] = jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1];
-		cof[1][0] = -(jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0]);
-		cof[2][0] = jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0];
-		
-		cof[0][1] = -(jac[0][1]*jac[2][2] - jac[0][2]*jac[2][1]);
-		cof[1][1] = jac[0][0]*jac[2][2] - jac[0][2]*jac[2][0];
-		cof[2][1] = -(jac[0][0]*jac[2][1] - jac[0][1]*jac[2][0]);
-		
-		cof[0][2] = jac[0][1]*jac[1][2] - jac[0][2]*jac[1][1];
-		cof[1][2] = -(jac[0][0]*jac[1][2] - jac[0][2]*jac[1][0]);
-		cof[2][2] = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0];
-		
-		for( i=0; i<dim; i++ ) {
-			for( j=0; j<dim; j++ ) {
-				jac[i][j] = cof[i][j]/D;
-			}
-		}
-		
-		
-	}
-	
-	/* get global derivs Ni_x, Ni_y and Ni_z if dim == 3 */
-	for( dx=0; dx<dim; dx++ ) {
-          for( n=0; n<(int)nodesPerEl; n++ ) {
-			
-			globalSF_DerivVal = 0.0;
-			for(dxi=0; dxi<dim; dxi++) {
-				globalSF_DerivVal = globalSF_DerivVal + GNi[dxi][n] * jac[dx][dxi];
-			}
-			
-			GNx[dx][n] = globalSF_DerivVal;
-		}
-	}
-}
-
-void ElementType_Jacobian_AxisIndependent( 
-		void*               elementType, 
-		void*               _mesh, 
-		Element_DomainIndex	elId, 
-		double*             xi, 
-		Dimension_Index     dim, 
-		double**            jacobian, 
-		double**            _GNi, 
-		Coord_Index         A_axis, 
-		Coord_Index         B_axis, 
-		Coord_Index         C_axis ) 
-{
-	ElementType* self        = (ElementType*) elementType;
-	Mesh*        mesh        = (Mesh*)_mesh;
-	double*      nodeCoord;
-	double**     GNi;
-	Node_Index   nodesPerEl  = self->nodeCount;
-	Node_Index   node_I;
-	unsigned	nInc, *inc;
-
-	Mesh_GetIncidence( mesh, Mesh_GetDimSize( mesh ), elId, MT_VERTEX, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = (unsigned*)IArray_GetPtr((self->inc) );
-	
-	/* If GNi isn't passed in - then evaluate them for you */
-	if (_GNi == NULL) {
-		/* Using 3 here instead of dim so that you can pass in dim = 2 and use axes 0 and 2 for your jacobian */
-		GNi = Memory_Alloc_2DArray( double, 3, nodesPerEl, (Name)"Temporary GNi"  );
-		self->_evaluateShapeFunctionLocalDerivsAt( self, xi, GNi );
-	}
-	else GNi = _GNi;
-
-	/* build the jacobian matrix */
-	/*
-	jacobian =  \sum_i d/d\xi( N_i ) x_i        \sum_i d/d\xi( N_i ) y_i
-	            \sum_i d/d\eta( N_i ) x_i       \sum_i d/d\eta( N_i ) y_i
-	*/
-	switch (dim) {
-		case 1: 			
-			jacobian[A_axis][A_axis] = 0.0;
-			for( node_I = 0 ; node_I < nodesPerEl; node_I++){
-				nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
-				jacobian[A_axis][A_axis] += GNi[A_axis][node_I] * nodeCoord[A_axis];
-			}
-			break;
-		case 2:
-			jacobian[A_axis][A_axis] = jacobian[A_axis][B_axis] = jacobian[B_axis][A_axis] = jacobian[B_axis][B_axis] = 0.0;
-			for( node_I = 0 ; node_I < nodesPerEl; node_I++){
-				nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
-				jacobian[A_axis][A_axis] += GNi[A_axis][node_I] * nodeCoord[A_axis];
-				jacobian[A_axis][B_axis] += GNi[A_axis][node_I] * nodeCoord[B_axis];
-
-				jacobian[B_axis][A_axis] += GNi[B_axis][node_I] * nodeCoord[A_axis];
-				jacobian[B_axis][B_axis] += GNi[B_axis][node_I] * nodeCoord[B_axis];
-			}
-			break;
-		case 3:
-			jacobian[A_axis][A_axis] = jacobian[A_axis][B_axis] = jacobian[A_axis][C_axis] = 0.0;
-			jacobian[B_axis][A_axis] = jacobian[B_axis][B_axis] = jacobian[B_axis][C_axis] = 0.0;
-			jacobian[C_axis][A_axis] = jacobian[C_axis][B_axis] = jacobian[C_axis][C_axis] = 0.0;
-			for( node_I = 0 ; node_I < nodesPerEl; node_I++){
-				nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
-
-				jacobian[A_axis][A_axis] += GNi[A_axis][node_I] * nodeCoord[A_axis];
-				jacobian[A_axis][B_axis] += GNi[A_axis][node_I] * nodeCoord[B_axis];
-				jacobian[A_axis][C_axis] += GNi[A_axis][node_I] * nodeCoord[C_axis];
-
-				jacobian[B_axis][A_axis] += GNi[B_axis][node_I] * nodeCoord[A_axis];
-				jacobian[B_axis][B_axis] += GNi[B_axis][node_I] * nodeCoord[B_axis];
-				jacobian[B_axis][C_axis] += GNi[B_axis][node_I] * nodeCoord[C_axis];
-
-				jacobian[C_axis][A_axis] += GNi[C_axis][node_I] * nodeCoord[A_axis];
-				jacobian[C_axis][B_axis] += GNi[C_axis][node_I] * nodeCoord[B_axis];
-				jacobian[C_axis][C_axis] += GNi[C_axis][node_I] * nodeCoord[C_axis];
-			}
-			break;
-		/* Mainly here to check unrolled loops above */
-		default: {
-			Coord_Index row_I, column_I;
-			
-			for ( row_I = 0 ; row_I < dim ; row_I++ ) {
-				for ( column_I = 0 ; column_I < dim ; column_I++ ) {
-					/* Initialise */
-					jacobian[row_I][column_I] = 0.0;
-
-					/* Calculate */
-					for( node_I = 0 ; node_I < nodesPerEl; node_I++){
-						nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
-				
-						jacobian[row_I][column_I] += GNi[row_I][node_I] * nodeCoord[column_I];
-					}
-				}
-			}
-		}
-	}
-
-	/* Clean up */
-	if (_GNi == NULL) 
-		Memory_Free(GNi);
-}
-
-double ElementType_JacobianDeterminant_AxisIndependent( 
-		void*               elementType, 
-		void*               _mesh, 
-		Element_DomainIndex	elId, 
-		double*             xi, 
-		Dimension_Index     dim, 
-		Coord_Index         A_axis, 
-		Coord_Index         B_axis, 
-		Coord_Index         C_axis ) 
-{
-	double** jacobian;
-	double detJac;
-
-	/* Using 3 here instead of dim so that you can pass in dim = 2 and use axes 0 and 2 for your jacobian */
-	jacobian = Memory_Alloc_2DArray( double, 3, 3, (Name)"Temporary Jacobian"  );
-
-	ElementType_Jacobian_AxisIndependent( elementType, _mesh, elId, xi, dim, jacobian, NULL, A_axis, B_axis, C_axis );
-	detJac = StGermain_MatrixDeterminant_AxisIndependent( jacobian, dim, A_axis, B_axis, C_axis );
-
-	/* Cleaning up */
-	Memory_Free( jacobian );
-
-	return detJac;
-}
-
-void ElementType_GetFaceNodes( void* elementType, Mesh* mesh, unsigned element_I, unsigned face_I, 
-				unsigned nNodes, unsigned* nodes ) {
-	ElementType* 	self        = (ElementType*) elementType;
-	Index		node_i;
-	unsigned*	inc;
-
-	assert( mesh && Stg_CheckType( mesh, FeMesh ) );
-
-	FeMesh_GetElementNodes( mesh, element_I, self->inc );
-	inc = (unsigned*)IArray_GetPtr((self->inc) );
-
-	for( node_i = 0; node_i < nNodes; node_i++ )
-		nodes[node_i] = inc[self->faceNodes[face_I][node_i]];
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/ElementType.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/ElementType.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,633 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: ElementType.c 1179 2008-07-15 05:28:11Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "FeMesh.h"
+#include "ElementType.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+
+const Type ElementType_Type = "ElementType";
+
+ElementType* _ElementType_New(  ELEMENTTYPE_DEFARGS  ) {
+	ElementType* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(ElementType) );
+	self = (ElementType*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual functions */
+	self->_build = _build;
+	self->_evaluateShapeFunctionsAt = _evaluateShapeFunctionsAt;
+	self->_evaluateShapeFunctionLocalDerivsAt = _evaluateShapeFunctionLocalDerivsAt;
+	self->_convertGlobalCoordToElLocal = _convertGlobalCoordToElLocal;
+	self->_jacobianDeterminantSurface = _jacobianDeterminantSurface;
+	self->_surfaceNormal = _surfaceNormal;
+	
+	/* ElementType info */
+	
+	return self;
+}
+
+void _ElementType_Init( ElementType* self, Index nodeCount ) {
+	/* General and Virtual info should already be set */
+	self->dim = 0;
+	/* ElementType info */
+	self->nodeCount = nodeCount;
+	self->debug = Stream_RegisterChild( StgFEM_Discretisation_Debug, ElementType_Type );
+	self->inc = IArray_New();
+}
+
+
+void _ElementType_Destroy( void* elementType, void* data ){
+	ElementType* self = (ElementType*)elementType;
+
+	NewClass_Delete( self->inc );
+
+	Stg_Component_Destroy( self, data, False );
+}
+
+void _ElementType_Delete( void* elementType ) {
+	ElementType* self = (ElementType*)elementType;
+
+	/* Stg_Class_Delete parent*/
+	_Stg_Component_Delete( self );
+}
+
+void _ElementType_Print( void* elementType, Stream* stream ) {
+	ElementType* self = (ElementType*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* elementTypeStream = stream;
+	
+	/* General info */
+	Journal_Printf( elementTypeStream, "ElementType (ptr): %p\n", self );
+	
+	/* Print parent */
+	_Stg_Class_Print( self, elementTypeStream );
+	
+	/* Virtual info */
+	Journal_Printf( elementTypeStream, "\t_build (func ptr): %p\n", self->_build );
+	Journal_Printf( elementTypeStream, "\t_evaluateShapeFunctionsAt (func ptr): %p\n", self->_evaluateShapeFunctionsAt );
+	Journal_Printf( elementTypeStream,  "\t_evaluateShapeFunctionLocalDerivsAt (func ptr): %p\n", self->_evaluateShapeFunctionLocalDerivsAt );
+	
+	/* ElementType info */
+	Journal_Printf( elementTypeStream, "\tnodeCount: %u\n", self->nodeCount );
+}
+
+/* +++ Virtual Function Interfaces +++ */
+
+void ElementType_Build( void* elementType, void *data ) {
+	ElementType* self = (ElementType*)elementType;
+	
+	/* ElementType's are implemented NOT in the standard parent child
+	 * manner as the rest of StGermain. Here the parents calls the child's
+	 * build function */
+	self->_build( self, data);
+}
+
+void ElementType_EvaluateShapeFunctionsAt( void* elementType, const double localCoord[], double* const evaluatedValues ) {
+	ElementType* self = (ElementType*)elementType;
+	
+	self->_evaluateShapeFunctionsAt( self, localCoord, evaluatedValues );
+}
+
+void ElementType_EvaluateShapeFunctionLocalDerivsAt( void* elementType, const double localCoord[], double** const evaluatedDerivatives ) {
+	ElementType* self = (ElementType*)elementType;
+	
+	self->_evaluateShapeFunctionLocalDerivsAt( self, localCoord, evaluatedDerivatives );
+}
+
+double _ElementType_JacobianDeterminantSurface( void* elementType, void* mesh, unsigned element_I, const double localCoord[], 
+						unsigned face_I, unsigned norm ) 
+{
+	ElementType*	self;
+	Stream*			error = Journal_Register( ErrorStream_Type, (Name)ElementType_Type );
+
+	self = (ElementType* ) elementType;
+
+	Journal_Printf( error, "Error: the jacobian for this element type cannot be evaluated on the element surface" );
+	Journal_Printf( error, "(perhaps because the nodes are defined internally for the element).\n" );
+	assert( 0 );
+
+	return -1;
+}
+
+double ElementType_JacobianDeterminantSurface( void* elementType, void* mesh, unsigned element_I, 
+						const double localCoord[], unsigned face_I, unsigned norm ) {
+	ElementType* self = (ElementType*)elementType;
+
+	return self->_jacobianDeterminantSurface( self, mesh, element_I, localCoord, face_I, norm );
+}
+
+#define EPS 1.0E-6
+
+int _ElementType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
+	ElementType* self;
+
+	self = (ElementType*)elementType;
+
+	memset( normal, 0, sizeof(double) * dim );
+
+	if( xi[J_AXIS] < -1.0 + EPS ) {
+		normal[J_AXIS] = -1.0;
+		return 0;
+	}
+	else if( xi[J_AXIS] > +1.0 - EPS ) {
+		normal[J_AXIS] = +1.0;
+		return 1;
+	}
+	else if( xi[I_AXIS] < -1.0 + EPS ) {
+		normal[I_AXIS] = -1.0;
+		return 2;
+	}
+	else if( xi[I_AXIS] > +1.0 - EPS ) {
+		normal[I_AXIS] = +1.0;
+		return 3;
+	}
+	else if( xi[K_AXIS] < -1.0 + EPS ) {
+		normal[K_AXIS] = -1.0;
+		return 4;
+	}
+	else if( xi[K_AXIS] > +1.0 - EPS ) {
+		normal[K_AXIS] = +1.0;
+		return 5;
+	}
+	return 0;
+}
+
+int ElementType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
+	ElementType* 	self = (ElementType*)elementType;
+
+	return self->_surfaceNormal( self, element_I, dim, xi, normal );
+}
+
+void ElementType_ConvertGlobalCoordToElLocal(
+		void*		elementType,
+		void*		mesh, 
+		unsigned	element, 
+		const double*	globalCoord,
+		double*		elLocalCoord )
+{
+	ElementType*	self = (ElementType*)elementType;
+
+	self->_convertGlobalCoordToElLocal( self, mesh, element, globalCoord, elLocalCoord );
+}
+
+
+/* +++ Virtual Function Implementations +++ */
+
+void _ElementType_ConvertGlobalCoordToElLocal(
+		void*		elementType,
+		void*		_mesh, 
+		unsigned	element, 
+		const double*	globalCoord,
+		double*		elLocalCoord )
+{		
+	ElementType*		self            = (ElementType*)elementType;
+	Mesh*			mesh = (Mesh*)_mesh;
+	TensorArray         jacobiMatrix;
+	double              tolerance       = 0.0001; /* TODO put on class */
+	double              maxResidual;
+	Iteration_Index     maxIterations   = 100;    /*  TODO put on class */
+	Iteration_Index     iteration_I;
+	Node_Index          node_I;
+	Node_Index          nodeCount       = self->nodeCount;
+	double*             evaluatedShapeFuncs = self->evaluatedShapeFunc;
+	XYZ                 rightHandSide;
+	XYZ                 xiIncrement;
+	double              shapeFunc;
+	double*       	    nodeCoord;
+	double**            GNi = self->GNi;
+	unsigned	    nInc, *inc;
+	Dimension_Index     dim             = Mesh_GetDimSize( mesh );
+
+	/* This function uses a Newton-Raphson iterative method to find the local coordinate from the global coordinate 
+	 * the equations are ( see FEM/BEM nodes p. 9 )
+	 *
+	 * x = \Sum_n( Ni( \xi, \eta, \zeta ) x_n )
+	 * y = \Sum_n( Ni( \xi, \eta, \zeta ) y_n )
+	 * z = \Sum_n( Ni( \xi, \eta, \zeta ) z_n )
+	 *
+	 * which are non-linear.
+	 *
+	 * This can be formulated into a system of linear equations of the form
+	 *
+	 * [              ][ \xi_{i + 1}   - \xi_i   ]   [ x - \Sum_n( Ni( \xi_i, \eta_i, \zeta_i ) x_n ]
+	 * [   Jacobian   ][ \eta_{i + 1}  - \eta_i  ] = [ y - \Sum_n( Ni( \xi_i, \eta_i, \zeta_i ) y_n ]
+	 * [              ][ \zeta_{i + 1} - \zeta_I ]   [ z - \Sum_n( Ni( \xi_i, \eta_i, \zeta_i ) z_n ]
+	 *
+	 * see http://en.wikipedia.org/wiki/Newton-Raphson_method
+	 *
+	 * */
+
+	Mesh_GetIncidence( mesh, Mesh_GetDimSize( mesh ), element, MT_VERTEX, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = (unsigned*)IArray_GetPtr( (self->inc) );
+
+	/* Initial guess for element local coordinate is in the centre of the element - ( 0.0, 0.0, 0.0 ) */
+	memset( elLocalCoord, 0, dim*sizeof(double) );
+
+	/* Do Newton-Raphson Iteration */
+	for ( iteration_I = 0 ; iteration_I < maxIterations ; iteration_I++ ) {
+		/* Initialise Values */
+		TensorArray_Zero( jacobiMatrix );
+		memset( rightHandSide, 0, sizeof( XYZ ) );
+
+		/* Evaluate shape functions for rhs */
+		ElementType_EvaluateShapeFunctionsAt( self, elLocalCoord, evaluatedShapeFuncs );
+		self->_evaluateShapeFunctionLocalDerivsAt( self, elLocalCoord, GNi );
+
+
+		for ( node_I = 0 ; node_I < nodeCount ; node_I++ ) {
+			shapeFunc = evaluatedShapeFuncs[node_I];
+			nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
+
+			/* Form jacobi matrix */
+			jacobiMatrix[ MAP_TENSOR( 0, 0, dim ) ] += GNi[0][node_I] * nodeCoord[ I_AXIS ];
+			jacobiMatrix[ MAP_TENSOR( 0, 1, dim ) ] += GNi[1][node_I] * nodeCoord[ I_AXIS ];
+
+			jacobiMatrix[ MAP_TENSOR( 1, 0, dim ) ] += GNi[0][node_I] * nodeCoord[ J_AXIS ];
+			jacobiMatrix[ MAP_TENSOR( 1, 1, dim ) ] += GNi[1][node_I] * nodeCoord[ J_AXIS ];
+			
+
+			/* Form right hand side */
+			rightHandSide[ I_AXIS ] -= shapeFunc * nodeCoord[ I_AXIS ];
+			rightHandSide[ J_AXIS ] -= shapeFunc * nodeCoord[ J_AXIS ];
+
+			if ( dim == 3 ) {
+				jacobiMatrix[ MAP_3D_TENSOR( 0, 2 ) ] += GNi[2][node_I] * nodeCoord[ I_AXIS ];
+				jacobiMatrix[ MAP_3D_TENSOR( 1, 2 ) ] += GNi[2][node_I] * nodeCoord[ J_AXIS ];
+
+				jacobiMatrix[ MAP_3D_TENSOR( 2, 0 ) ] += GNi[0][node_I] * nodeCoord[ K_AXIS ];
+				jacobiMatrix[ MAP_3D_TENSOR( 2, 1 ) ] += GNi[1][node_I] * nodeCoord[ K_AXIS ];
+				jacobiMatrix[ MAP_3D_TENSOR( 2, 2 ) ] += GNi[2][node_I] * nodeCoord[ K_AXIS ];
+				
+				rightHandSide[ K_AXIS ] -= shapeFunc * nodeCoord[ K_AXIS ];
+			}
+		}
+
+		/* Finish building right hand side */
+		rightHandSide[ I_AXIS ] += globalCoord[ I_AXIS ];
+		rightHandSide[ J_AXIS ] += globalCoord[ J_AXIS ];
+		if ( dim == 3 )
+			rightHandSide[ K_AXIS ] += globalCoord[ K_AXIS ];
+
+		/* Solve for xi increment */
+		TensorArray_SolveSystem( jacobiMatrix, xiIncrement, rightHandSide, dim );
+
+		/* Update xi */
+		elLocalCoord[ I_AXIS ] += xiIncrement[ I_AXIS ];
+		elLocalCoord[ J_AXIS ] += xiIncrement[ J_AXIS ];
+		if ( dim == 3 )
+			elLocalCoord[ K_AXIS ] += xiIncrement[ K_AXIS ];
+
+		/* Check for convergence */
+		maxResidual = fabs( xiIncrement[ I_AXIS ] );
+		if ( maxResidual < fabs( xiIncrement[ J_AXIS ] ) )
+			maxResidual = fabs( xiIncrement[ J_AXIS ] );
+		if ( dim == 3 && maxResidual < fabs( xiIncrement[ K_AXIS ] ) )
+			maxResidual = fabs( xiIncrement[ K_AXIS ] );
+
+		if ( maxResidual < tolerance )
+			break;
+	}
+}				
+
+
+/* +++ Public Functions +++ */
+void ElementType_ShapeFunctionsGlobalDerivs( 
+		void*			elementType,
+		void*			_mesh,
+		Element_DomainIndex	elId, 
+		double*			xi, 
+		int			dim, 
+		double*			detJac, 
+		double**		GNx )
+{
+	ElementType*			self = (ElementType*)elementType;
+	Mesh*				mesh = (Mesh*)_mesh;
+	double				*nodeCoord;
+	
+	double jac[3][3];
+	int rows;		/* max dimensions */
+	int cols;		/* max nodes per el */
+	double** GNi; 
+	int n, i, j;
+	double globalSF_DerivVal;
+	int dx, dxi;
+	double tmp, D = 0.0;
+	double cof[3][3];	/* cofactors */
+	unsigned nInc, *inc;
+	Index nodesPerEl;
+
+	rows=Mesh_GetDimSize( mesh );
+	cols=self->nodeCount;	
+	
+	GNi = self->GNi;
+
+	nodesPerEl = self->nodeCount;
+
+	Mesh_GetIncidence( mesh, Mesh_GetDimSize( mesh ), elId, MT_VERTEX, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = (unsigned*)IArray_GetPtr((self->inc) );
+	
+	/*
+	If constant shape function gets passed in here, getLocalDeriv will
+	indicate the error and exit code.
+	*/
+	
+	self->_evaluateShapeFunctionLocalDerivsAt( self, xi, GNi );
+	
+	
+	/* build the jacobian matrix */
+	/*
+	jac = 	\sum_i d/d\xi( N_i ) x_i 		\sum_i d/d\xi( N_i ) y_i
+			\sum_i d/d\eta( N_i ) x_i 		\sum_i d/d\eta( N_i ) y_i
+	*/
+	/* unroll this bugger cause we do it all the time */
+	if( dim == 2 ) {
+		jac[0][0] = jac[0][1] = jac[1][0] = jac[1][1] = 0.0;
+		for( n=0; n<(int)nodesPerEl; n++){	
+			nodeCoord = Mesh_GetVertex( mesh, inc[n] );
+			jac[0][0] = jac[0][0] + GNi[0][n] * nodeCoord[0];
+			jac[0][1] = jac[0][1] + GNi[0][n] * nodeCoord[1];
+			
+			jac[1][0] = jac[1][0] + GNi[1][n] * nodeCoord[0];
+			jac[1][1] = jac[1][1] + GNi[1][n] * nodeCoord[1];
+		}
+	}
+	
+	if( dim == 3 ) {
+		jac[0][0] = jac[0][1] = jac[0][2] = 0.0;
+		jac[1][0] = jac[1][1] = jac[1][2] = 0.0;
+		jac[2][0] = jac[2][1] = jac[2][2] = 0.0;
+		for( n=0; n<(int)nodesPerEl; n++){	
+			nodeCoord = Mesh_GetVertex( mesh, inc[n] );
+			jac[0][0] = jac[0][0] + GNi[0][n] * nodeCoord[0];
+			jac[0][1] = jac[0][1] + GNi[0][n] * nodeCoord[1];
+			jac[0][2] = jac[0][2] + GNi[0][n] * nodeCoord[2];
+			
+			jac[1][0] = jac[1][0] + GNi[1][n] * nodeCoord[0];
+			jac[1][1] = jac[1][1] + GNi[1][n] * nodeCoord[1];
+			jac[1][2] = jac[1][2] + GNi[1][n] * nodeCoord[2];
+			
+			jac[2][0] = jac[2][0] + GNi[2][n] * nodeCoord[0];
+			jac[2][1] = jac[2][1] + GNi[2][n] * nodeCoord[1];
+			jac[2][2] = jac[2][2] + GNi[2][n] * nodeCoord[2];
+		}
+	}
+	
+	/* get determinant of the jacobian matrix */
+	if( dim == 2 ) {
+		D = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0]; 
+	}		
+	if( dim == 3 ) {
+		D = jac[0][0]*( jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1] ) 
+				  - jac[0][1]*( jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0] ) 
+				  + jac[0][2]*( jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0] );
+	}
+	(*detJac) = D;
+	
+	
+	/* invert the jacobian matrix A^-1 = adj(A)/det(A) */
+	if( dim == 2 ) {
+		tmp = jac[0][0];
+		jac[0][0] = jac[1][1]/D;
+		jac[1][1] = tmp/D;
+		jac[0][1] = -jac[0][1]/D;
+		jac[1][0] = -jac[1][0]/D;		
+	}
+	if( dim == 3 ) {
+		/*
+		00 01 02
+		10 11 12
+		20 21 22		
+		*/		
+		cof[0][0] = jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1];
+		cof[1][0] = -(jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0]);
+		cof[2][0] = jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0];
+		
+		cof[0][1] = -(jac[0][1]*jac[2][2] - jac[0][2]*jac[2][1]);
+		cof[1][1] = jac[0][0]*jac[2][2] - jac[0][2]*jac[2][0];
+		cof[2][1] = -(jac[0][0]*jac[2][1] - jac[0][1]*jac[2][0]);
+		
+		cof[0][2] = jac[0][1]*jac[1][2] - jac[0][2]*jac[1][1];
+		cof[1][2] = -(jac[0][0]*jac[1][2] - jac[0][2]*jac[1][0]);
+		cof[2][2] = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0];
+		
+		for( i=0; i<dim; i++ ) {
+			for( j=0; j<dim; j++ ) {
+				jac[i][j] = cof[i][j]/D;
+			}
+		}
+		
+		
+	}
+	
+	/* get global derivs Ni_x, Ni_y and Ni_z if dim == 3 */
+	for( dx=0; dx<dim; dx++ ) {
+          for( n=0; n<(int)nodesPerEl; n++ ) {
+			
+			globalSF_DerivVal = 0.0;
+			for(dxi=0; dxi<dim; dxi++) {
+				globalSF_DerivVal = globalSF_DerivVal + GNi[dxi][n] * jac[dx][dxi];
+			}
+			
+			GNx[dx][n] = globalSF_DerivVal;
+		}
+	}
+}
+
+void ElementType_Jacobian_AxisIndependent( 
+		void*               elementType, 
+		void*               _mesh, 
+		Element_DomainIndex	elId, 
+		double*             xi, 
+		Dimension_Index     dim, 
+		double**            jacobian, 
+		double**            _GNi, 
+		Coord_Index         A_axis, 
+		Coord_Index         B_axis, 
+		Coord_Index         C_axis ) 
+{
+	ElementType* self        = (ElementType*) elementType;
+	Mesh*        mesh        = (Mesh*)_mesh;
+	double*      nodeCoord;
+	double**     GNi;
+	Node_Index   nodesPerEl  = self->nodeCount;
+	Node_Index   node_I;
+	unsigned	nInc, *inc;
+
+	Mesh_GetIncidence( mesh, Mesh_GetDimSize( mesh ), elId, MT_VERTEX, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = (unsigned*)IArray_GetPtr((self->inc) );
+	
+	/* If GNi isn't passed in - then evaluate them for you */
+	if (_GNi == NULL) {
+		/* Using 3 here instead of dim so that you can pass in dim = 2 and use axes 0 and 2 for your jacobian */
+		GNi = Memory_Alloc_2DArray( double, 3, nodesPerEl, (Name)"Temporary GNi"  );
+		self->_evaluateShapeFunctionLocalDerivsAt( self, xi, GNi );
+	}
+	else GNi = _GNi;
+
+	/* build the jacobian matrix */
+	/*
+	jacobian =  \sum_i d/d\xi( N_i ) x_i        \sum_i d/d\xi( N_i ) y_i
+	            \sum_i d/d\eta( N_i ) x_i       \sum_i d/d\eta( N_i ) y_i
+	*/
+	switch (dim) {
+		case 1: 			
+			jacobian[A_axis][A_axis] = 0.0;
+			for( node_I = 0 ; node_I < nodesPerEl; node_I++){
+				nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
+				jacobian[A_axis][A_axis] += GNi[A_axis][node_I] * nodeCoord[A_axis];
+			}
+			break;
+		case 2:
+			jacobian[A_axis][A_axis] = jacobian[A_axis][B_axis] = jacobian[B_axis][A_axis] = jacobian[B_axis][B_axis] = 0.0;
+			for( node_I = 0 ; node_I < nodesPerEl; node_I++){
+				nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
+				jacobian[A_axis][A_axis] += GNi[A_axis][node_I] * nodeCoord[A_axis];
+				jacobian[A_axis][B_axis] += GNi[A_axis][node_I] * nodeCoord[B_axis];
+
+				jacobian[B_axis][A_axis] += GNi[B_axis][node_I] * nodeCoord[A_axis];
+				jacobian[B_axis][B_axis] += GNi[B_axis][node_I] * nodeCoord[B_axis];
+			}
+			break;
+		case 3:
+			jacobian[A_axis][A_axis] = jacobian[A_axis][B_axis] = jacobian[A_axis][C_axis] = 0.0;
+			jacobian[B_axis][A_axis] = jacobian[B_axis][B_axis] = jacobian[B_axis][C_axis] = 0.0;
+			jacobian[C_axis][A_axis] = jacobian[C_axis][B_axis] = jacobian[C_axis][C_axis] = 0.0;
+			for( node_I = 0 ; node_I < nodesPerEl; node_I++){
+				nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
+
+				jacobian[A_axis][A_axis] += GNi[A_axis][node_I] * nodeCoord[A_axis];
+				jacobian[A_axis][B_axis] += GNi[A_axis][node_I] * nodeCoord[B_axis];
+				jacobian[A_axis][C_axis] += GNi[A_axis][node_I] * nodeCoord[C_axis];
+
+				jacobian[B_axis][A_axis] += GNi[B_axis][node_I] * nodeCoord[A_axis];
+				jacobian[B_axis][B_axis] += GNi[B_axis][node_I] * nodeCoord[B_axis];
+				jacobian[B_axis][C_axis] += GNi[B_axis][node_I] * nodeCoord[C_axis];
+
+				jacobian[C_axis][A_axis] += GNi[C_axis][node_I] * nodeCoord[A_axis];
+				jacobian[C_axis][B_axis] += GNi[C_axis][node_I] * nodeCoord[B_axis];
+				jacobian[C_axis][C_axis] += GNi[C_axis][node_I] * nodeCoord[C_axis];
+			}
+			break;
+		/* Mainly here to check unrolled loops above */
+		default: {
+			Coord_Index row_I, column_I;
+			
+			for ( row_I = 0 ; row_I < dim ; row_I++ ) {
+				for ( column_I = 0 ; column_I < dim ; column_I++ ) {
+					/* Initialise */
+					jacobian[row_I][column_I] = 0.0;
+
+					/* Calculate */
+					for( node_I = 0 ; node_I < nodesPerEl; node_I++){
+						nodeCoord = Mesh_GetVertex( mesh, inc[node_I] );
+				
+						jacobian[row_I][column_I] += GNi[row_I][node_I] * nodeCoord[column_I];
+					}
+				}
+			}
+		}
+	}
+
+	/* Clean up */
+	if (_GNi == NULL) 
+		Memory_Free(GNi);
+}
+
+double ElementType_JacobianDeterminant_AxisIndependent( 
+		void*               elementType, 
+		void*               _mesh, 
+		Element_DomainIndex	elId, 
+		double*             xi, 
+		Dimension_Index     dim, 
+		Coord_Index         A_axis, 
+		Coord_Index         B_axis, 
+		Coord_Index         C_axis ) 
+{
+	double** jacobian;
+	double detJac;
+
+	/* Using 3 here instead of dim so that you can pass in dim = 2 and use axes 0 and 2 for your jacobian */
+	jacobian = Memory_Alloc_2DArray( double, 3, 3, (Name)"Temporary Jacobian"  );
+
+	ElementType_Jacobian_AxisIndependent( elementType, _mesh, elId, xi, dim, jacobian, NULL, A_axis, B_axis, C_axis );
+	detJac = StGermain_MatrixDeterminant_AxisIndependent( jacobian, dim, A_axis, B_axis, C_axis );
+
+	/* Cleaning up */
+	Memory_Free( jacobian );
+
+	return detJac;
+}
+
+void ElementType_GetFaceNodes( void* elementType, Mesh* mesh, unsigned element_I, unsigned face_I, 
+				unsigned nNodes, unsigned* nodes ) {
+	ElementType* 	self        = (ElementType*) elementType;
+	Index		node_i;
+	unsigned*	inc;
+
+	assert( mesh && Stg_CheckType( mesh, FeMesh ) );
+
+	FeMesh_GetElementNodes( mesh, element_I, self->inc );
+	inc = (unsigned*)IArray_GetPtr((self->inc) );
+
+	for( node_i = 0; node_i < nNodes; node_i++ )
+		nodes[node_i] = inc[self->faceNodes[face_I][node_i]];
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/ElementType_Register.c
--- a/Discretisation/src/ElementType_Register.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,232 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: ElementType_Register.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType.h"
-#include "ElementType_Register.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type ElementType_Register_Type = "ElementType_Register";
-
-ElementType_Register* elementType_Register = 0;
-
-ElementType_Register* ElementType_Register_New( Name name ) {
-  ElementType_Register* self = (ElementType_Register*)ElementType_Register_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ElementType_Register_Init( self );
-
-	return self;
-}
-
-void* ElementType_Register_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(ElementType_Register);
-	Type                                                      type = ElementType_Register_Type;
-	Stg_Class_DeleteFunction*                              _delete = _ElementType_Register_Delete;
-	Stg_Class_PrintFunction*                                _print = _ElementType_Register_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = ElementType_Register_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _ElementType_Register_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _ElementType_Register_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _ElementType_Register_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _ElementType_Register_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _ElementType_Register_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-
-	return (void*) _ElementType_Register_New(  ELEMENTTYPE_REGISTER_PASSARGS  );
-}
-
-ElementType_Register* _ElementType_Register_New(  ELEMENTTYPE_REGISTER_DEFARGS  ) {
-	ElementType_Register* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(ElementType_Register) );
-	self = (ElementType_Register*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _ElementType_Register_Init( void* elementType_Register ) {
-	ElementType_Register* self = (ElementType_Register*)elementType_Register;
-	
-	/* General and Virtual info should already be set */
-	
-	/* ElementType_Register info */
-	self->count = 0;
-	self->_size = 8;
-	self->_delta = 8;
-	self->elementType = Memory_Alloc_Array( ElementType*, self->_size, "ElementType_Register->elementType" );
-	memset( self->elementType, 0, sizeof(ElementType*) * self->_size );
-	self->debug = Stream_RegisterChild( StgFEM_Discretisation_Debug, ElementType_Register_Type );
-}
-
-void _ElementType_Register_Delete( void* elementType_Register ) {
-	ElementType_Register* self = (ElementType_Register*)elementType_Register;
-
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	_Stg_Component_Delete( self );
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _ElementType_Register_Print( void* elementType_Register, Stream* stream ) {
-	ElementType_Register* self = (ElementType_Register*)elementType_Register;
-	ElementType_Index elementType_I;
-	
-	/* Set the Journal for printing informations */
-	Stream* elementType_RegisterStream = stream;
-	
-	/* General info */
-	Journal_Printf( stream, "ElementType_Register (ptr): %p\n", self );
-	
-	/* Print parent */
-	_Stg_Class_Print( self, elementType_RegisterStream );
-	
-	/* Virtual info */
-	
-	/* ElementType_Register info */
-	Journal_Printf( stream, "\tcount: %u\n", self->count );
-	Journal_Printf( stream, "\t_size: %lu\n", self->_size );
-	Journal_Printf( stream, "\t_delta: %lu\n", self->_delta );
-	
-	Journal_Printf( stream, "\telementType (ptr): %p\n", self->elementType );
-	Journal_Printf( stream, "\telementType[0-%u]:\n", self->count );
-
-	for( elementType_I = 0; elementType_I < self->count; elementType_I++ ) {
-		Journal_Printf( stream, "elementType[%u]: ", elementType_I );
-		Stg_Class_Print( self->elementType[elementType_I], elementType_RegisterStream );
-	}
-	Journal_Printf( stream, "\t]\n" );
-}
-
-void _ElementType_Register_AssignFromXML( void* elementType_Register, Stg_ComponentFactory *cf, void* data ){
-	ElementType_Register*	self = (ElementType_Register*)elementType_Register;
-	
-	self->context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", DomainContext, False, data );
-	if( !self->context  ) 
-		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", DomainContext, True, data  );
-}
-	
-void _ElementType_Register_Build( void* elementType_Register, void *data ){
-	
-}
-	
-void _ElementType_Register_Initialise( void* elementType_Register, void *data ){
-	
-}
-	
-void _ElementType_Register_Execute( void* elementType_Register, void *data ){
-	
-}
-
-void _ElementType_Register_Destroy( void* elementType_Register, void *data ){
-	ElementType_Register* self = (ElementType_Register*)elementType_Register;
-	
-	/* Assumes ownerships of the element types */
-	if( self->elementType ) {
-		ElementType_Index elementType_I;
-		
-		for( elementType_I = 0; elementType_I < self->count; elementType_I++ ) {
-			_Stg_Component_Delete( self->elementType[elementType_I] );
-		}
-	}
-   Memory_Free( self->elementType );
-}
-
-ElementType_Index ElementType_Register_Add( void* elementType_Register, void* elementType ) {
-	ElementType_Register*	self = (ElementType_Register*)elementType_Register;
-	ElementType_Index			handle;
-	
-	if( self->count >= self->_size ) {
-		ElementType**	newElementType;
-		
-		self->_size += self->_delta;
-		newElementType = Memory_Alloc_Array( ElementType*, self->_size, "ElementType_Register->elementType" );
-		memcpy( newElementType, self->elementType, sizeof(ElementType*) * self->count );
-		Memory_Free( self->elementType );
-		self->elementType = newElementType;
-		Memory_Free( newElementType );
-	}
-	
-	handle = self->count;
-	self->elementType[handle] = (ElementType*)elementType;
-	self->count++;
-	
-	/* Build the elementType... i.e assume it hasn't been built already */
-	ElementType_Build( self->elementType[handle], NULL );
-	
-	return handle;
-}
-
-ElementType_Index ElementType_Register_GetIndex( void* elementType_Register, Type type ) {
-	ElementType_Register*	self = (ElementType_Register*)elementType_Register;
-	ElementType_Index			elementType_I;
-	
-	for( elementType_I = 0; elementType_I < self->count; elementType_I++ ) {
-		if( self->elementType[elementType_I]->type == type ) {
-			return elementType_I;
-		}
-	}
-	return (unsigned)-1;
-}
-
-ElementType* _ElementType_Register_At( void* elementType_Register, ElementType_Index handle ) {
-	ElementType_Register*	self = (ElementType_Register*)elementType_Register;
-	
-	return ElementType_Register_At( self, handle );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/ElementType_Register.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/ElementType_Register.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,232 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: ElementType_Register.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType.h"
+#include "ElementType_Register.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type ElementType_Register_Type = "ElementType_Register";
+
+ElementType_Register* elementType_Register = 0;
+
+ElementType_Register* ElementType_Register_New( Name name ) {
+  ElementType_Register* self = (ElementType_Register*)ElementType_Register_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ElementType_Register_Init( self );
+
+	return self;
+}
+
+void* ElementType_Register_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(ElementType_Register);
+	Type                                                      type = ElementType_Register_Type;
+	Stg_Class_DeleteFunction*                              _delete = _ElementType_Register_Delete;
+	Stg_Class_PrintFunction*                                _print = _ElementType_Register_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = ElementType_Register_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _ElementType_Register_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _ElementType_Register_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _ElementType_Register_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _ElementType_Register_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _ElementType_Register_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+
+	return (void*) _ElementType_Register_New(  ELEMENTTYPE_REGISTER_PASSARGS  );
+}
+
+ElementType_Register* _ElementType_Register_New(  ELEMENTTYPE_REGISTER_DEFARGS  ) {
+	ElementType_Register* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(ElementType_Register) );
+	self = (ElementType_Register*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _ElementType_Register_Init( void* elementType_Register ) {
+	ElementType_Register* self = (ElementType_Register*)elementType_Register;
+	
+	/* General and Virtual info should already be set */
+	
+	/* ElementType_Register info */
+	self->count = 0;
+	self->_size = 8;
+	self->_delta = 8;
+	self->elementType = Memory_Alloc_Array( ElementType*, self->_size, "ElementType_Register->elementType" );
+	memset( self->elementType, 0, sizeof(ElementType*) * self->_size );
+	self->debug = Stream_RegisterChild( StgFEM_Discretisation_Debug, ElementType_Register_Type );
+}
+
+void _ElementType_Register_Delete( void* elementType_Register ) {
+	ElementType_Register* self = (ElementType_Register*)elementType_Register;
+
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	_Stg_Component_Delete( self );
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _ElementType_Register_Print( void* elementType_Register, Stream* stream ) {
+	ElementType_Register* self = (ElementType_Register*)elementType_Register;
+	ElementType_Index elementType_I;
+	
+	/* Set the Journal for printing informations */
+	Stream* elementType_RegisterStream = stream;
+	
+	/* General info */
+	Journal_Printf( stream, "ElementType_Register (ptr): %p\n", self );
+	
+	/* Print parent */
+	_Stg_Class_Print( self, elementType_RegisterStream );
+	
+	/* Virtual info */
+	
+	/* ElementType_Register info */
+	Journal_Printf( stream, "\tcount: %u\n", self->count );
+	Journal_Printf( stream, "\t_size: %lu\n", self->_size );
+	Journal_Printf( stream, "\t_delta: %lu\n", self->_delta );
+	
+	Journal_Printf( stream, "\telementType (ptr): %p\n", self->elementType );
+	Journal_Printf( stream, "\telementType[0-%u]:\n", self->count );
+
+	for( elementType_I = 0; elementType_I < self->count; elementType_I++ ) {
+		Journal_Printf( stream, "elementType[%u]: ", elementType_I );
+		Stg_Class_Print( self->elementType[elementType_I], elementType_RegisterStream );
+	}
+	Journal_Printf( stream, "\t]\n" );
+}
+
+void _ElementType_Register_AssignFromXML( void* elementType_Register, Stg_ComponentFactory *cf, void* data ){
+	ElementType_Register*	self = (ElementType_Register*)elementType_Register;
+	
+	self->context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", DomainContext, False, data );
+	if( !self->context  ) 
+		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", DomainContext, True, data  );
+}
+	
+void _ElementType_Register_Build( void* elementType_Register, void *data ){
+	
+}
+	
+void _ElementType_Register_Initialise( void* elementType_Register, void *data ){
+	
+}
+	
+void _ElementType_Register_Execute( void* elementType_Register, void *data ){
+	
+}
+
+void _ElementType_Register_Destroy( void* elementType_Register, void *data ){
+	ElementType_Register* self = (ElementType_Register*)elementType_Register;
+	
+	/* Assumes ownerships of the element types */
+	if( self->elementType ) {
+		ElementType_Index elementType_I;
+		
+		for( elementType_I = 0; elementType_I < self->count; elementType_I++ ) {
+			_Stg_Component_Delete( self->elementType[elementType_I] );
+		}
+	}
+   Memory_Free( self->elementType );
+}
+
+ElementType_Index ElementType_Register_Add( void* elementType_Register, void* elementType ) {
+	ElementType_Register*	self = (ElementType_Register*)elementType_Register;
+	ElementType_Index			handle;
+	
+	if( self->count >= self->_size ) {
+		ElementType**	newElementType;
+		
+		self->_size += self->_delta;
+		newElementType = Memory_Alloc_Array( ElementType*, self->_size, "ElementType_Register->elementType" );
+		memcpy( newElementType, self->elementType, sizeof(ElementType*) * self->count );
+		Memory_Free( self->elementType );
+		self->elementType = newElementType;
+		Memory_Free( newElementType );
+	}
+	
+	handle = self->count;
+	self->elementType[handle] = (ElementType*)elementType;
+	self->count++;
+	
+	/* Build the elementType... i.e assume it hasn't been built already */
+	ElementType_Build( self->elementType[handle], NULL );
+	
+	return handle;
+}
+
+ElementType_Index ElementType_Register_GetIndex( void* elementType_Register, Type type ) {
+	ElementType_Register*	self = (ElementType_Register*)elementType_Register;
+	ElementType_Index			elementType_I;
+	
+	for( elementType_I = 0; elementType_I < self->count; elementType_I++ ) {
+		if( self->elementType[elementType_I]->type == type ) {
+			return elementType_I;
+		}
+	}
+	return (unsigned)-1;
+}
+
+ElementType* _ElementType_Register_At( void* elementType_Register, ElementType_Index handle ) {
+	ElementType_Register*	self = (ElementType_Register*)elementType_Register;
+	
+	return ElementType_Register_At( self, handle );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeEquationNumber.c
--- a/Discretisation/src/FeEquationNumber.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3367 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FeEquationNumber.c 1191 2008-07-25 03:06:19Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType.h"
-#include "ElementType_Register.h"
-#include "Element.h"
-#include "FeMesh.h"
-#include "FeEquationNumber.h"
-#include "LinkedDofInfo.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-#include <petsc.h>
-#include <petscvec.h>
-
-int stgCmpInt( const void *l, const void *r ) {
-   return *(int*)l - *(int*)r;
-}
-
-/*###### Typedefs and Structs ######*/
-
-/** Textual name of this class */
-const Type FeEquationNumber_Type = "FeEquationNumber";
-
-/** struct to store sub-totals: what is the equation number up to at a given
-    node? These can then be exchanged between processors */
-typedef struct CritPointInfo {
-      Node_GlobalIndex	index;
-      Dof_EquationNumber	eqNum;
-} CritPointInfo;
-
-
-/** An element of linked list of critical point info. Several of the functions
-    use this to keep track of key points */
-typedef struct AddListEntry {
-      CritPointInfo*		critPointInfo;
-      struct AddListEntry*	next;
-} AddListEntry;
-
-/** Enum to say whetehr values at crit. nodes should be printed */
-typedef enum PrintValuesFlag {
-   DONT_PRINT_VALUES,
-   PRINT_VALUES
-} PrintValuesFlag;
-
-/** MPI datatype handle for efficiently exchanging CritPointInfo structures.
-	see FeEquationNumber_Create_CritPointInfo_MPI_Datatype() for where this
-	handle is defined. */
-MPI_Datatype MPI_critPointInfoType;
-
-/*###### Private Function Declarations ######*/
-
-#if 0
-static void _FeEquationNumber_BuildRemappedNodeInfoTable( void* feEquationNumber );
-
-static void _FeEquationNumber_CalculateDomainKnownCriticalPoints(
-	FeEquationNumber* self,
-	Node_DomainIndex	nodeDomainCount,
-	CritPointInfo*		mySetEnds,
-	Index* const		mySetEndsTotal,
-	Node_GlobalIndex*	myWantedCriticalPoints,
-	Index* const		myWantedCriticalPointsTotal );
-	
-static void _FeEquationNumber_HandleNode(
-	FeEquationNumber*			self,
-	const Node_DomainIndex	dNode_I,
-	Dof_EquationNumber*		const currEqNum );
-	
-static void _FeEquationNumber_PostProcessLinkedDofs( FeEquationNumber* self );
-
-static void _FeEquationNumber_CalculateCritPointsIHave(
-	FeEquationNumber*				self,
-	Node_GlobalIndex** const	myWantedCriticalPointsPtr,
-	Node_GlobalIndex				myWantedCriticalPointsTotal,
-	CritPointInfo** const		critPointsIHave,
-	Index* const					critPointsIHaveTotal,
-	CritPointInfo* const			critPointsToSend,
-	Index* const					critPointsToSendTotal );
-	
-static void _FeEquationNumber_ShareCriticalPoints(
-   FeEquationNumber*				self,
-   Node_GlobalIndex** const	myCriticalPoints,
-   Node_GlobalIndex				myCriticalPointsTotal,
-   Node_GlobalIndex**			allCriticalPoints,
-   Index**							procCritPointsTotals, 
-   Node_GlobalIndex* const		maxCritPointsPerProc );
-
-static void _FeEquationNumber_ShareCritPointInfo(
-   FeEquationNumber*	self,
-   CritPointInfo**	const myCritPointInfo,
-   Index					myCritPointInfoTotal,
-   CritPointInfo**	allCritPointInfo,
-   Index**				procCritPointInfoTotals,
-   Index*				const maxCritPointInfoPerProc,
-   PrintValuesFlag	printValuesFlag );
-
-static void _FeEquationNumber_DoPartialTotals(
-	FeEquationNumber*		self,
-	CritPointInfo* const	critPointsIHave,
-	Index						critPointsIHaveTotal,
-	CritPointInfo* const	critPointsToSend,
-	Index						critPointsToSendTotal );
-
-static void _FeEquationNumber_AddAllPartialTotals(
-	FeEquationNumber*	self,
-	CritPointInfo*		mySubTotals,
-	Index					myCritPointInfoTotal,
-	CritPointInfo*		allSubTotals,
-	Index*				procCritPointInfoTotals,
-	Index					maxSubTotalsPerProc );
-
-Node_RemappedGlobalIndex _FeEquationNumber_RemapNode( 
-   Mesh* mesh, 
-   Index newDimOrder[3],
-   Node_GlobalIndex gNode_I );
-
-int GenerateEquationNumbering(
-	int			NX, int NY, int NZ,
-	int			nlocal, int g_node_id[],
-	int			dof, int nglobal,
-	PetscTruth	periodic_x, PetscTruth periodic_y, PetscTruth periodic_z,
-	int			npx, int npy, int npz,
-	int			periodic_x_gnode_id[], int periodic_y_gnode_id[], int periodic_z_gnode_id[],
-	int			eqnums[], int *neqnums );
-
-/** Tests if the critical point from another processor is held by ours.
-    Is complicated by the possibility of remapping. */
-static Bool _FeEquationNumber_IHaveCritPoint(
-   FeEquationNumber* self,
-   Node_RemappedGlobalIndex critPoint );
-#endif
-
-/*###### Function Definitions ######*/
-
-/** Public constructor */
-
-FeEquationNumber* FeEquationNumber_New(
-	Name						name,
-	DomainContext*			context,
-	void*						mesh,
-	DofLayout*				dofLayout,
-	VariableCondition*	bcs,
-	LinkedDofInfo*			linkedDofInfo )
-{
-  FeEquationNumber* self = (FeEquationNumber*)FeEquationNumber_DefaultNew( name );
-
-	self->isConstructed = True;
-	_FeEquationNumber_Init( self, context, mesh, dofLayout, bcs, linkedDofInfo );
-
-	return self;
-}
-
-void* FeEquationNumber_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(FeEquationNumber);
-	Type                                                      type = FeEquationNumber_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FeEquationNumber_Delete;
-	Stg_Class_PrintFunction*                                _print = _FeEquationNumber_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FeEquationNumber_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (Stg_Component_DefaultConstructorFunction*)FeEquationNumber_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _FeEquationNumber_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _FeEquationNumber_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FeEquationNumber_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FeEquationNumber_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FeEquationNumber_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-
-   return _FeEquationNumber_New(  FEEQUATIONNUMBER_PASSARGS  );
-}
-/** Constructor implementation. */
-FeEquationNumber* _FeEquationNumber_New(  FEEQUATIONNUMBER_DEFARGS  ){
-   FeEquationNumber* self;
-	
-   /* Allocate memory */
-   assert( _sizeOfSelf >= sizeof(FeEquationNumber) );
-   self = (FeEquationNumber*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-	
-   /* General info */
-	
-   /* Virtual info */
-   self->_build = _build;
-   self->_initialise = _initialise;
-	
-   /* Mesh info */
-	
-   return self;
-}
-
-
-/** Constructor variables initialisation. Doesn't allocate any
-    memory, just saves arguments and sets counters to 0. */
-void _FeEquationNumber_Init(
-   FeEquationNumber*		self, 
-	DomainContext*			context,
-   void*						feMesh,
-   DofLayout*				dofLayout,
-   VariableCondition*	bcs,
-   LinkedDofInfo*			linkedDofInfo )
-{
-   /* General and Virtual info should already be set */
-	
-   /* FinteElementMesh info */
-	self->context = context;
-   self->feMesh = (FeMesh*)feMesh;
-   self->globalSumUnconstrainedDofs = 0;
-   self->isBuilt = False;
-   self->locationMatrixBuilt = False;
-   self->_lowestLocalEqNum = -1;
-   self->_lowestGlobalEqNums = NULL;
-   self->_highestLocalEqNum = -1;
-   self->dofLayout = dofLayout;
-   self->bcs = bcs;
-   self->linkedDofInfo = linkedDofInfo;
-   self->remappingActivated = False;
-   /* register streams */
-   self->debug = Stream_RegisterChild( StgFEM_Discretisation_Debug, FeEquationNumber_Type );
-   self->debugLM = Stream_RegisterChild( self->debug, "LM" );
-   self->warning = Stream_RegisterChild( StgFEM_Warning, FeEquationNumber_Type );
-   self->removeBCs = True;
-   self->bcEqNums = STree_New();
-   STree_SetIntCallbacks( self->bcEqNums );
-   STree_SetItemSize( self->bcEqNums, sizeof(int) );
-   self->ownedMap = STreeMap_New();
-   STreeMap_SetItemSize( self->ownedMap, sizeof(int), sizeof(int) );
-   STree_SetIntCallbacks( self->ownedMap );
-
-   Stream_SetPrintingRank( self->debug, 0 );
-}
-
-void _FeEquationNumber_AssignFromXML( void* feEquationNumber, Stg_ComponentFactory *cf, void* data ) {
-}
-	
-void _FeEquationNumber_Execute( void* feEquationNumber, void *data ){
-	
-}
-	
-void _FeEquationNumber_Destroy( void* feEquationNumber, void *data ){
-   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
-   Index ii;
-
-   Stg_Component_Destroy( self->feMesh   , data, False );
-   Stg_Component_Destroy( self->dofLayout, data, False );
-   if ( self->linkedDofInfo ) Stg_Component_Destroy( self->dofLayout, data, False );
-   if ( self->bcs )           Stg_Component_Destroy( self->bcs      , data, False );
-	
-   FreeArray( self->remappedNodeInfos );
-   /* free destination array memory */
-   Journal_DPrintfL( self->debug, 2, "Freeing I.D. Array\n" );
-   FreeArray( self->destinationArray );
-	
-   if (self->locationMatrix) {
-      Journal_DPrintfL( self->debug, 2, "Freeing Full L.M. Array\n" );
-      for( ii = 0; ii < self->nDomainEls; ii++ )
-         FreeArray( self->locationMatrix[ii] );
-         
-      FreeArray( self->locationMatrix );
-   }
-
-   if( self->bcEqNums ) 
-      NewClass_Delete( self->bcEqNums );
-   
-   if( self->ownedMap ) 
-      NewClass_Delete( self->ownedMap );
-}
-	
-/* Copy */
-
-/** Stg_Class_Delete implementation. */
-void _FeEquationNumber_Delete( void* feEquationNumber ) {
-   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
-
-   Journal_DPrintfL( self->debug, 1, "In %s\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-
-   /* Stg_Class_Delete parent */
-   _Stg_Class_Delete( self );
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-/** Print implementation */
-void _FeEquationNumber_Print( void* mesh, Stream* stream ) {
-   FeEquationNumber* self = (FeEquationNumber*)mesh;
-	
-   /* General info */
-   Journal_Printf( stream, "FeEquationNumber (ptr): %p\n", self );
-	
-   /* Print parent */
-   _Stg_Class_Print( self, stream );
-	
-   /* Virtual info */
-   Journal_Printf( stream,  "\t_build (func ptr): %p\n", self->_build );
-   Journal_Printf( stream,  "\t_intialise (func ptr): %p\n", self->_initialise );
-	
-   /* FeEquationNumber info */
-   /* Don't print dofs or bcs as these will be printed by FeVariable */
-	
-   if ( self->destinationArray ) {
-      FeEquationNumber_PrintDestinationArray( self, stream );
-      FeEquationNumber_PrintLocationMatrix( self, stream );
-   }
-   else {
-      Journal_Printf( stream, "\tdestinationArray: (null)... not built yet\n" );
-      Journal_Printf( stream, "\tlocationMatrix: (null)... not built yet\n" );
-   }
-}
-
-
-void* _FeEquationNumber_Copy( const void* feEquationNumber, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-#if 0
-   FeEquationNumber*	self = (FeEquationNumber*)feEquationNumber;
-   Mesh*			mesh;
-   FeEquationNumber*	newFeEquationNumber;
-   PtrMap*			map = ptrMap;
-   Bool			ownMap = False;
-
-   mesh = (Mesh*)self->feMesh;
-	
-   if( !map ) {
-      map = PtrMap_New( 10 );
-      ownMap = True;
-   }
-	
-   newFeEquationNumber = _Stg_Class_Copy( self, dest, deep, nameExt, map );
-	
-   /* Virtual methods */
-   newFeEquationNumber->_build = self->_build;
-   newFeEquationNumber->_initialise = self->_initialise;
-	
-   newFeEquationNumber->_highestLocalEqNum = self->_highestLocalEqNum;
-   newFeEquationNumber->_lowestLocalEqNum = self->_lowestLocalEqNum;
-   newFeEquationNumber->_eqNumsPerProcDivisor = self->_eqNumsPerProcDivisor;
-   newFeEquationNumber->_eqNumsRemainder = self->_eqNumsRemainder;
-   newFeEquationNumber->_remNotAddedChangeover = self->_remNotAddedChangeover;
-   newFeEquationNumber->firstOwnedEqNum = self->firstOwnedEqNum;
-   newFeEquationNumber->lastOwnedEqNum = self->lastOwnedEqNum;
-   newFeEquationNumber->localEqNumsOwnedCount = self->localEqNumsOwnedCount;
-   newFeEquationNumber->globalSumUnconstrainedDofs = self->globalSumUnconstrainedDofs;
-   newFeEquationNumber->locationMatrixBuilt = self->locationMatrixBuilt;
-   newFeEquationNumber->remappingActivated = self->remappingActivated;
-	
-   if( deep ) {
-      newFeEquationNumber->debug = (Stream*)Stg_Class_Copy( self->debug, NULL, deep, nameExt, map );
-      newFeEquationNumber->debugLM = (Stream*)Stg_Class_Copy( self->debugLM, NULL, deep, nameExt, map );
-      newFeEquationNumber->warning = (Stream*)Stg_Class_Copy( self->warning, NULL, deep, nameExt, map );
-      newFeEquationNumber->feMesh = (FeMesh*)Stg_Class_Copy( self->feMesh, NULL, deep, nameExt, map );
-      newFeEquationNumber->dofLayout = (DofLayout*)Stg_Class_Copy( self->dofLayout, NULL, deep, nameExt, map );
-      newFeEquationNumber->bcs = (VariableCondition*)Stg_Class_Copy( self->bcs, NULL, deep, nameExt, map );
-      newFeEquationNumber->linkedDofInfo = (LinkedDofInfo*)Stg_Class_Copy( self->linkedDofInfo, NULL, deep, nameExt, map );
-		
-      if( (newFeEquationNumber->remappedNodeInfos = PtrMap_Find( map, self->remappedNodeInfos )) == NULL && self->remappedNodeInfos ) {
-         Node_DomainIndex	nodeDomainCount;
-
-         nodeDomainCount = Mesh_GetDomainSize( mesh, MT_VERTEX );
-			
-         newFeEquationNumber->remappedNodeInfos = Memory_Alloc_Array( RemappedNodeInfo, nodeDomainCount, "FeEquationNumber->remappedNodeInfos" );
-         memcpy( newFeEquationNumber->remappedNodeInfos, self->remappedNodeInfos, sizeof(RemappedNodeInfo) * nodeDomainCount );
-         PtrMap_Append( map, self->remappedNodeInfos, newFeEquationNumber->remappedNodeInfos );
-      }
-		
-      if( (newFeEquationNumber->destinationArray = PtrMap_Find( map, self->destinationArray )) == NULL && self->destinationArray ) {
-         Node_DomainIndex	nodeDomainCount;
-         Node_DomainIndex	node_dI;
-
-         nodeDomainCount = Mesh_GetDomainSize( mesh, MT_VERTEX );
-			
-         newFeEquationNumber->destinationArray = Memory_Alloc_2DComplex( Dof_EquationNumber, nodeDomainCount, self->dofLayout->dofCounts, "FeEquationNumber->destinationArray" );
-         for( node_dI = 0; node_dI < nodeDomainCount; node_dI++ ) {
-            memcpy( newFeEquationNumber->destinationArray[node_dI], self->destinationArray[node_dI], sizeof(Dof_EquationNumber) * self->dofLayout->dofCounts[node_dI] );
-         }
-         PtrMap_Append( map, self->destinationArray, newFeEquationNumber->destinationArray );
-      }
-		
-      if( (newFeEquationNumber->_lowestGlobalEqNums = PtrMap_Find( map, self->_lowestGlobalEqNums )) == NULL && self->_lowestGlobalEqNums ) {
-         Partition_Index		nProc;
-
-         nProc = Mesh_GetCommTopology( mesh, MT_VERTEX )->nProcs;
-			
-         newFeEquationNumber->_lowestGlobalEqNums = Memory_Alloc_Array( Dof_EquationNumber, nProc, "FeEquationNumber->_lowestGlobalEqNums" );
-         memcpy( newFeEquationNumber->_lowestGlobalEqNums, self->_lowestGlobalEqNums, sizeof(Dof_EquationNumber) * nProc );
-         PtrMap_Append( map, self->_lowestGlobalEqNums, newFeEquationNumber->_lowestGlobalEqNums );
-      }
-		
-      if( (newFeEquationNumber->locationMatrix = PtrMap_Find( map, self->locationMatrix )) == NULL && self->locationMatrix ) {
-         FeMesh*	mesh = self->feMesh;
-         Element_LocalIndex	lElement_I;
-         Node_LocalIndex		numNodesThisElement;
-         Node_LocalIndex		elLocalNode_I;
-         Dof_Index		numDofsThisNode;
-         Element_LocalIndex	elementLocalCount = mesh->elementLocalCount;
-         Dof_Index**		dofCountsAtElementNodesArray;
-			
-         dofCountsAtElementNodesArray = Memory_Alloc_3DSetup( elementLocalCount, mesh->elementNodeCountTbl );
-         for ( lElement_I = 0; lElement_I < elementLocalCount; lElement_I++ ) {
-            numNodesThisElement = mesh->elementNodeCountTbl[lElement_I];
-				
-            for( elLocalNode_I = 0; elLocalNode_I < numNodesThisElement; elLocalNode_I++) {
-               Node_LocalIndex		dNode_I = mesh->elementNodeTbl[lElement_I][elLocalNode_I];
-					
-               numDofsThisNode = self->dofLayout->dofCounts[dNode_I];
-               dofCountsAtElementNodesArray[lElement_I][elLocalNode_I] = numDofsThisNode;
-            }
-         }
-			
-         newFeEquationNumber->locationMatrix = Memory_Alloc_3DComplex( Dof_EquationNumber, elementLocalCount, mesh->elementNodeCountTbl, dofCountsAtElementNodesArray, "FeEquationNumber->locationMatrix" );
-         for( lElement_I = 0; lElement_I < elementLocalCount; lElement_I++ ) {
-            for( elLocalNode_I = 0; elLocalNode_I < mesh->elementNodeCountTbl[lElement_I]; elLocalNode_I++ ) {
-               memcpy( newFeEquationNumber->locationMatrix[lElement_I][elLocalNode_I], self->locationMatrix[lElement_I][elLocalNode_I], sizeof(Dof_EquationNumber) * dofCountsAtElementNodesArray[lElement_I][elLocalNode_I] );
-            }
-         }
-			
-         Memory_Free( dofCountsAtElementNodesArray );
-         PtrMap_Append( map, self->locationMatrix, newFeEquationNumber->locationMatrix );
-      }
-   }
-   else {
-      newFeEquationNumber->debug = self->debug;
-      newFeEquationNumber->debugLM = self->debugLM;
-      newFeEquationNumber->warning = self->warning;
-      newFeEquationNumber->feMesh = self->feMesh;
-      newFeEquationNumber->dofLayout = self->dofLayout;
-      newFeEquationNumber->bcs = self->bcs;
-      newFeEquationNumber->linkedDofInfo = self->linkedDofInfo;
-      newFeEquationNumber->remappedNodeInfos = self->remappedNodeInfos;
-      newFeEquationNumber->destinationArray = self->destinationArray;
-      newFeEquationNumber->_lowestGlobalEqNums = self->_lowestGlobalEqNums;
-      newFeEquationNumber->locationMatrix = self->locationMatrix;
-   }
-	
-   if( ownMap ) {
-      Stg_Class_Delete( map );
-   }
-	
-   return (void*)newFeEquationNumber;
-#endif
-   abort();
-}
-
-void _FeEquationNumber_Build( void* feEquationNumber, void* data ) {
-   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
-
-   assert(self);
-	
-   Journal_DPrintf( self->debug, "In %s:\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-
-   Stg_Component_Build( self->feMesh   , data, False );
-   Stg_Component_Build( self->dofLayout, data, False );
-   if ( self->linkedDofInfo ) Stg_Component_Build( self->dofLayout, data, False );
-   if ( self->bcs )           Stg_Component_Build( self->bcs      , data, False );
-	/* If we have new mesh topology information, do this differently. */
-   /* if( self->feMesh->topo->domains && self->feMesh->topo->domains[MT_VERTEX] ) { */
-
-   if( Mesh_HasExtension( self->feMesh, "vertexGrid" ) )
-      FeEquationNumber_BuildWithDave( self );
-   else
-      FeEquationNumber_BuildWithTopology( self );
-
-   /* If not removing BCs, construct a table of which equation numbers are actually BCs. */
-   if( !self->removeBCs ) {
-      FeMesh* mesh = self->feMesh;
-      DofLayout* dofLayout = self->dofLayout;
-      VariableCondition* bcs = self->bcs;
-      int nDofs, varInd;
-      unsigned ii;
-      int jj;
-
-      for( ii = 0; ii < FeMesh_GetNodeLocalSize( mesh ); ii++ ) {
-         nDofs = dofLayout->dofCounts[ii];
-         for( jj = 0; jj < nDofs; jj++ ) {
-            varInd = dofLayout->varIndices[ii][jj];
-            if( bcs && VariableCondition_IsCondition( bcs, ii, varInd ) ) {
-               if( !STree_Has( self->bcEqNums, self->destinationArray[ii] + jj ) )
-                  STree_Insert( self->bcEqNums, self->destinationArray[ii] + jj );
-            }
-         }
-      }
-   }
-
-   /*}
-   else {
-      _FeEquationNumber_BuildRemappedNodeInfoTable( self );
-      _FeEquationNumber_BuildDestinationArray( self );
-      _FeEquationNumber_CalculateGlobalUnconstrainedDofTotal( self );
-      _FeEquationNumber_CalculateEqNumsDecomposition( self );
-   }*/
-
-   if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-      FeEquationNumber_PrintDestinationArray( self, self->debug );
-   }
-
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-/** Initialise implementation. Currently does nothing. */
-void _FeEquationNumber_Initialise( void* feEquationNumber, void* data ) {
-   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
-
-   Stg_Component_Initialise( self->feMesh   , data, False );
-   Stg_Component_Initialise( self->dofLayout, data, False );
-   if ( self->linkedDofInfo ) Stg_Component_Initialise( self->dofLayout, data, False );
-   if ( self->bcs )           Stg_Component_Initialise( self->bcs      , data, False );
-}
-
-
-#if 0
-Node_RemappedGlobalIndex _FeEquationNumber_RemapNode( 
-   HexaMD* hexaMD,
-   Index newDimOrder[3],
-   Node_GlobalIndex gNode_I )
-{
-   Node_RemappedGlobalIndex remappedGlobalIndex = 0;
-   Index dim_I = 0;
-   Index currNewDim = 0;
-   IJK defaultIJK;
-   IJK newOrderIJK;
-   IJK	newOrderNodeCounts;
-	
-   Dimension_1DTo3D( gNode_I, hexaMD->nodeGlobal3DCounts, defaultIJK );
-
-   for ( dim_I = I_AXIS; dim_I < 3; dim_I++ ) {
-      currNewDim = newDimOrder[dim_I];
-      newOrderIJK[dim_I] = defaultIJK[currNewDim]; 
-      newOrderNodeCounts[dim_I] = hexaMD->nodeGlobal3DCounts[currNewDim];
-   }
-
-   Dimension_3DTo1D( newOrderIJK, newOrderNodeCounts, &remappedGlobalIndex );
-
-   return remappedGlobalIndex;
-}
-
-
-static void _FeEquationNumber_BuildRemappedNodeInfoTable( void* feEquationNumber ) {
-   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
-   FeMesh* mesh = self->feMesh;
-   Node_DomainIndex nodeDomainCount = Mesh_GetDomainSize( mesh, MT_VERTEX );
-   CommTopology*	commTopo = Mesh_GetCommTopology( mesh, MT_VERTEX );
-   Node_GlobalIndex gNode_I = 0;
-   Node_DomainIndex dNode_I = 0;
-/*#if DEBUG*/
-   RemappedNodeInfo_Index rNodeInfo_I;
-/*#endif*/
-	
-   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-
-   self->remappedNodeInfos = Memory_Alloc_Array( RemappedNodeInfo, nodeDomainCount, 
-                                                 "FeEquationNumber->remappedNodeInfos" );
-	
-   if ( 1 == commTopo->nProcs ) {
-      Journal_DPrintfL( self->debug, 1, "Serial code: No remapping required...filling remapping table with normal values.\n" );
-      for (dNode_I = 0; dNode_I < nodeDomainCount; dNode_I++ ) {
-         gNode_I = mesh->nodeD2G[dNode_I];
-         self->remappedNodeInfos[dNode_I].remappedGlobal = gNode_I;
-         self->remappedNodeInfos[dNode_I].domain = dNode_I;
-      }		
-   }
-   else if ( meshDecomp->type != HexaMD_Type ) {
-      Node_GlobalIndex	prevGNode_I = (unsigned int)-1;
-      RemappedNodeInfo_Index	insertIndex;
-	
-      Journal_DPrintfL( self->debug, 1, "Parallel, but non-hexa decomp: building the remapping table by "
-                        "insertion-sorting based on global node number order.\n" );
-      for (dNode_I = 0; dNode_I < nodeDomainCount; dNode_I++ ) {
-         gNode_I = mesh->nodeD2G[dNode_I];
-
-         if ( gNode_I > prevGNode_I ) {
-            self->remappedNodeInfos[dNode_I].remappedGlobal = gNode_I;
-            self->remappedNodeInfos[dNode_I].domain = dNode_I;
-            prevGNode_I = gNode_I;
-            continue;
-         }
-         else {
-            insertIndex = 0;
-            while ( gNode_I > self->remappedNodeInfos[insertIndex].remappedGlobal ) insertIndex++;
-            memmove( &self->remappedNodeInfos[insertIndex+1], &self->remappedNodeInfos[insertIndex],
-                     sizeof(RemappedNodeInfo) * (dNode_I - insertIndex + 1) );
-            self->remappedNodeInfos[insertIndex].remappedGlobal = gNode_I;
-            self->remappedNodeInfos[insertIndex].domain = dNode_I;
-         }
-      }
-   }
-   else if ( ((HexaMD*)meshDecomp)->numPartitionedDims > 1 )
-   {
-      Node_GlobalIndex	nextShadowGlobalMap;
-      Node_LocalIndex		lNode_I;
-      Node_ShadowIndex	sNode_I = mesh->nodeLocalCount;
-      RemappedNodeInfo_Index	insertIndex = 0;
-	
-      Journal_DPrintfL( self->debug, 1, "Parallel, hexa decomp but multiple partition dims:\n"
-                        "filling remapping table with insertion sort\n"
-                        "of local & shadow elements.\n" );
-		
-      if ( meshDecomp->shadowDepth > 0 ) {
-         nextShadowGlobalMap = mesh->nodeD2G[sNode_I];
-      }
-      else {
-         nextShadowGlobalMap = mesh->nodeGlobalCount;
-      }
-
-      insertIndex = 0;
-      for (lNode_I = 0; lNode_I < mesh->nodeLocalCount; lNode_I++ ) {
-         gNode_I = mesh->nodeL2G[lNode_I];
-
-         while ( nextShadowGlobalMap < gNode_I ) {
-            self->remappedNodeInfos[insertIndex].remappedGlobal = nextShadowGlobalMap;
-            self->remappedNodeInfos[insertIndex++].domain = sNode_I++;
-            if ( sNode_I < mesh->nodeDomainCount ) {
-               nextShadowGlobalMap = mesh->nodeD2G[sNode_I];
-            }
-            else {
-               nextShadowGlobalMap = mesh->nodeGlobalCount;
-            }
-         }
-         self->remappedNodeInfos[insertIndex].remappedGlobal = gNode_I;
-         self->remappedNodeInfos[insertIndex++].domain = lNode_I;
-      }		
-
-      /* now know all local elements inserted, so ensure all shadow elements have also been inserted */
-      for ( ; sNode_I < mesh->nodeDomainCount; sNode_I++ ) {
-         gNode_I = mesh->nodeD2G[sNode_I];
-         self->remappedNodeInfos[insertIndex].remappedGlobal = gNode_I;
-         self->remappedNodeInfos[insertIndex++].domain = sNode_I;
-      }
-      Journal_Firewall( (insertIndex == mesh->nodeDomainCount), self->debug,
-                        "Stuffup: should have inserted exactly the right number of values by here.\n" );
-   }
-   else {
-      /* Otherwise, we remap each of the global node values, so the eqNums
-         will cause minimal communication during mesh assembly */
-      Node_RemappedGlobalIndex currRemappedGNode_I = 0;
-      Node_RemappedGlobalIndex firstRemappedGNode_I = 0;
-      Index newDimOrder[3] = {0,0,0};
-      Index newOrder_I = 0;
-      Index partitionedAxis = I_AXIS;
-      Index dim_I;
-      RemappedNodeInfo_Index insertIndex;
-      Bool lowestIsShadow = False;
-
-      self->remappingActivated = True;
-
-      Journal_DPrintfL( self->debug, 1, "Parallel, hexa decomp with 1 partition dim:\n"
-                        "remapping eqNum traversal order to be aligned with mesh decomposition:\n" );
-
-      /* Work out the new dimension order for the EqNums. The partitioned index
-         goes last */
-      for ( dim_I = I_AXIS; dim_I < 3; dim_I++ ) {
-         if (True == ((HexaMD*)meshDecomp)->partitionedAxis[dim_I]) {
-            partitionedAxis = dim_I;
-            newDimOrder[2] = partitionedAxis;
-         } else {
-            newDimOrder[newOrder_I++] = dim_I;
-         }
-      }
-      Journal_DPrintfL( self->debug, 1, "Given partition axis is %c, calc. remapping dimension order as %c,%c,%c\n",
-                        IJKTopology_DimNumToDimLetter[partitionedAxis],
-                        IJKTopology_DimNumToDimLetter[newDimOrder[0]],
-                        IJKTopology_DimNumToDimLetter[newDimOrder[1]],
-                        IJKTopology_DimNumToDimLetter[newDimOrder[2]] );
-
-      Journal_DPrintfL( self->debug, 4, "Calculating over %d domain nodes, %d local, %d shadow.\n",
-                        mesh->nodeDomainCount, mesh->nodeLocalCount, mesh->nodeShadowCount );
-
-      /* Work out the lowest remapped global index (so we know where to insert into the table) */
-      gNode_I = mesh->nodeD2G[0];
-      firstRemappedGNode_I = _FeEquationNumber_RemapNode( (HexaMD*)meshDecomp, newDimOrder, gNode_I );
-      /* if shadow elements are enabled, check if the first shadow element has lower
-         global index than first local element */
-      if ( meshDecomp->shadowDepth > 0 ) {
-         Node_RemappedGlobalIndex firstRemappedShadowGNode_I;
-		
-         gNode_I = mesh->nodeD2G[mesh->nodeLocalCount];
-         firstRemappedShadowGNode_I = _FeEquationNumber_RemapNode( (HexaMD*)meshDecomp,
-                                                                   newDimOrder, gNode_I );
-			
-         if ( firstRemappedShadowGNode_I < firstRemappedGNode_I ) {
-            firstRemappedGNode_I = firstRemappedShadowGNode_I;
-            lowestIsShadow = True;
-         }
-      }
-      Journal_DPrintfL( self->debug, 4, "Calculated lowest remapped global index is %d",
-                        firstRemappedGNode_I );
-      if ( lowestIsShadow ) {
-         Journal_DPrintfL( self->debug, 4, " (a shadow node.)\n" );
-      }
-      else {
-         Journal_DPrintfL( self->debug, 4, " (a local node.)\n" );
-      }
-
-      Stream_IndentBranch( StgFEM_Debug );
-      /* Now add the rest, relative to the first */
-      for (dNode_I = 0; dNode_I < nodeDomainCount; dNode_I++ ) {
-         gNode_I = mesh->nodeD2G[dNode_I];
-         currRemappedGNode_I = _FeEquationNumber_RemapNode( (HexaMD*)meshDecomp, newDimOrder, gNode_I );
-         insertIndex = currRemappedGNode_I - firstRemappedGNode_I;
-         self->remappedNodeInfos[insertIndex].remappedGlobal = currRemappedGNode_I;
-         self->remappedNodeInfos[insertIndex].domain = dNode_I;
-         Journal_DPrintfL( self->debug, 4, "Processing domain node %d: original global = %d, remaps to %d.\n",
-                           dNode_I, gNode_I, currRemappedGNode_I );
-      }	
-      Stream_UnIndentBranch( StgFEM_Debug );
-   }
-
-/*#if DEBUG*/
-   if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-      Journal_DPrintf( self->debug, "Calculated remapped node info table as:\n{\n" );
-      for (rNodeInfo_I = 0; rNodeInfo_I < nodeDomainCount; rNodeInfo_I++ ) {
-         Journal_DPrintf( self->debug, " %d:(remap=%d,domain=%d),\n", rNodeInfo_I,
-                          self->remappedNodeInfos[rNodeInfo_I].remappedGlobal,
-                          self->remappedNodeInfos[rNodeInfo_I].domain );
-      }
-      Journal_DPrintf( self->debug, "}\n");
-   }
-/*#endif*/
-   Stream_UnIndentBranch( StgFEM_Debug );
-}	
-
-
-/* Build the processor's ID (destination) array */
-void _FeEquationNumber_BuildDestinationArray( FeEquationNumber* self ) {
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-   Node_DomainIndex nodeDomainCount = meshDecomp->nodeDomainCount;
-   CritPointInfo* critPointsIHave = NULL;
-   Index critPointsIHaveTotal = 0;
-   CritPointInfo* critPointsToSend = NULL;
-   Index critPointsToSendTotal = 0;
-   Stream* errorStream = Journal_Register( Error_Type, (Name)self->type  );
-
-   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-
-   Journal_Firewall( ( nodeDomainCount == self->dofLayout->_numItemsInLayout ),
-                     errorStream, "Error: In %s: DofLayout's size is %d, which isn't equal to "
-                     "Node domain count of %d. Did you create the dofLayout of size node local count? "
-                     "It should be aset up to size node domain count.\n",
-                     __func__, self->dofLayout->_numItemsInLayout, nodeDomainCount );
-		
-
-   self->destinationArray = Memory_Alloc_2DComplex( Dof_EquationNumber, nodeDomainCount,
-                                                    self->dofLayout->dofCounts, "FeEquationNumber->destinationArray" );
-
-
-   if (meshDecomp->procsInUse == 1)
-   {
-      /* for serial jobs, don't worry about the critical points, just calculate
-         the totals normally */
-      critPointsIHave = Memory_Alloc( CritPointInfo, "critPointsIHave (BuildDestinationArray)" );
-      critPointsToSend = Memory_Alloc( CritPointInfo, "critPointsToSend (BuildDestinationArray)" );
-      critPointsIHave[0].index = meshDecomp->nodeGlobalCount;
-      critPointsToSend[0].index = meshDecomp->nodeGlobalCount;
-      _FeEquationNumber_DoPartialTotals( self, critPointsIHave, 0, critPointsToSend, 0 );
-      self->_lowestLocalEqNum = 0;
-   }
-   else {
-      Node_GlobalIndex* myWantedCriticalPoints = NULL;
-      Index myWantedCriticalPointsTotal = 0;
-      CritPointInfo* allSendCriticalPoints = NULL;
-      Index* procSendCritPointsTotals = NULL;
-      Index maxSendCritPointsPerProc = 0;
-
-      critPointsIHave = Memory_Alloc_Array( CritPointInfo, nodeDomainCount,
-                                            "critPointsIHave (BuildDestinationArray)" );
-      critPointsToSend = Memory_Alloc_Array( CritPointInfo, nodeDomainCount,
-                                             "critPointsToSend (BuildDestinationArray)" );
-      myWantedCriticalPoints = Memory_Alloc_Array( Node_GlobalIndex, nodeDomainCount,
-                                                   "myWantedCritialPoints (BuildDestinationArray)" );
-
-      /* Go through all domain nodes, work out end of runs, and interfaces needed */
-      _FeEquationNumber_CalculateDomainKnownCriticalPoints( self, nodeDomainCount, critPointsIHave, &critPointsIHaveTotal,
-                                                            myWantedCriticalPoints, &myWantedCriticalPointsTotal );
-	
-      /* initialise the below to the set end critical nodes I already worked out I have */
-      critPointsToSend = (CritPointInfo*) memcpy( critPointsToSend, critPointsIHave, (critPointsIHaveTotal * sizeof(CritPointInfo)) );
-      critPointsToSendTotal = critPointsIHaveTotal;
-		
-      /* work out critical points (inc. those needed by others) I hold, and those to send.
-         The list I have could be greater than my end of runs, in an irregular mesh case */
-      _FeEquationNumber_CalculateCritPointsIHave( self, 
-                                                  &myWantedCriticalPoints, myWantedCriticalPointsTotal, &critPointsIHave, &critPointsIHaveTotal,
-                                                  critPointsToSend, &critPointsToSendTotal );
-	
-      Memory_Free( myWantedCriticalPoints );
-
-      /* OK: We now know all the critical points on this processor, so go ahead and work out the partial ID number
-         at all of them. */
-
-      Journal_DPrintfL( self->debug, 2, "Looping through nodes again, calculating eq nums (re-setting to 0 at critical points)\n,"
-                        "and storing subtotal of each each critical node:\n" );
-      _FeEquationNumber_DoPartialTotals( self, critPointsIHave, critPointsIHaveTotal,
-                                         critPointsToSend, critPointsToSendTotal );
-
-      Journal_DPrintfL( self->debug, 2, "Now sub-totals have been calculated, share all of my critical point sub-totals "
-                        "and get any that I need:\n" );
-      _FeEquationNumber_ShareCritPointInfo( self, &critPointsToSend, critPointsToSendTotal,
-                                            &allSendCriticalPoints, &procSendCritPointsTotals, &maxSendCritPointsPerProc, PRINT_VALUES );
-
-      Journal_DPrintfL( self->debug, 2, "Final loop: add the sub-totals at all the critical points to the existing values:\n" );
-      _FeEquationNumber_AddAllPartialTotals( self, critPointsIHave, critPointsIHaveTotal,
-                                             allSendCriticalPoints, procSendCritPointsTotals, maxSendCritPointsPerProc );
-
-      /* Post process the linked dofs */
-      if ( self->linkedDofInfo ) {
-         _FeEquationNumber_PostProcessLinkedDofs( self );
-      }	
-
-      Memory_Free( allSendCriticalPoints );
-      Memory_Free( procSendCritPointsTotals );
-   }
-
-   /* If not removing BCs, construct a table of which equation numbers are actually BCs. */
-   if( !self->removeBCs ) {
-      FeMesh*	feMesh = self->feMesh;
-      DofLayout*		dofLayout = self->dofLayout;
-      VariableCondition*	bcs = self->bcs;
-      unsigned		lNode_i;
-
-      /* New index set. */
-      self->bcEqNums = IndexSet_New( self->_highestLocalEqNum - self->_lowestLocalEqNum );
-
-      /* Fill it up. */
-      for( lNode_i = 0; lNode_i < feMesh->nodeLocalCount; lNode_i++ ) {
-         unsigned	nDofs = dofLayout->dofCounts[lNode_i];
-         unsigned	dof_i;
-
-         for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
-            unsigned	varInd = dofLayout->varIndices[lNode_i][dof_i];
-
-            if( bcs && VariableCondition_IsCondition( bcs, lNode_i, varInd ) ) {
-               IndexSet_Add( self->bcEqNums, self->destinationArray[lNode_i][dof_i] );
-            }
-         }
-      }
-   }
-
-   Memory_Free( critPointsIHave );
-   Memory_Free( critPointsToSend );
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-
-
-/** Works out 'critical nodes' I know from domain information (those I want are the start
-    of my runs -1, those I know others want are the end of my runs. */
-static void _FeEquationNumber_CalculateDomainKnownCriticalPoints(
-   FeEquationNumber* self,
-   Node_DomainIndex nodeDomainCount,
-   CritPointInfo* mySetEnds,
-   Index* const mySetEndsTotal,
-   Node_GlobalIndex* myWantedCriticalPoints,
-   Index* const myWantedCriticalPointsTotal )
-{
-   RemappedNodeInfo_Index rNodeInfo_I = 0;
-   Node_RemappedGlobalIndex remappedGlobal_I = 0;
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-
-   Journal_DPrintf( self->debug, "In %s\n", __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-
-   if ( self->remappingActivated ) {
-      /* if remapping has been done, the only possible crit points are the first and last
-         points */
-      remappedGlobal_I = self->remappedNodeInfos[0].remappedGlobal;
-      if (remappedGlobal_I != 0) {
-         Journal_DPrintfL( self->debug, 3, "Adding interface c.p. to myWantedCriticalPoints[%d] = %d\n", 
-                           (*myWantedCriticalPointsTotal), remappedGlobal_I-1 );
-         myWantedCriticalPoints[(*myWantedCriticalPointsTotal)++] = remappedGlobal_I-1;
-      }	
-
-      remappedGlobal_I = self->remappedNodeInfos[nodeDomainCount-1].remappedGlobal;
-      if ( remappedGlobal_I != (meshDecomp->nodeGlobalCount-1) ) {
-         Journal_DPrintfL( self->debug, 3, "Adding set end c.p. mySetEnds[%d] = %d\n", 
-                           (*mySetEndsTotal), remappedGlobal_I );
-         mySetEnds[(*mySetEndsTotal)++].index = remappedGlobal_I;
-      }
-      Stream_UnIndentBranch( StgFEM_Debug );
-      return;
-   }
-	
-   while ( rNodeInfo_I < nodeDomainCount ) {
-      /* save start of set */
-      remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I].remappedGlobal;
-
-      if (remappedGlobal_I != 0) {
-         Journal_DPrintfL( self->debug, 3, "Adding interface c.p. to myWantedCriticalPoints[%d] = %d\n", 
-                           (*myWantedCriticalPointsTotal), remappedGlobal_I-1 );
-         myWantedCriticalPoints[(*myWantedCriticalPointsTotal)++] = remappedGlobal_I-1;
-      }	
-      rNodeInfo_I++;
-
-      /* skip to end of contiguous set */
-      while ( (rNodeInfo_I < nodeDomainCount)
-              && (self->remappedNodeInfos[rNodeInfo_I].remappedGlobal ==
-                  (self->remappedNodeInfos[rNodeInfo_I-1].remappedGlobal + 1) ) )
-      {
-         Journal_DPrintfL( self->debug, 4, "skipping remapped gNode[%d] domain = %d\n", 
-                           self->remappedNodeInfos[rNodeInfo_I].remappedGlobal,
-                           self->remappedNodeInfos[rNodeInfo_I].domain );
-         rNodeInfo_I++;
-      }	
-
-      /* and add the critical point, if not the last node */
-      remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I-1].remappedGlobal;
-      if ( remappedGlobal_I != (meshDecomp->nodeGlobalCount-1) ) {
-         Journal_DPrintfL( self->debug, 3, "Adding set end c.p. mySetEnds[%d] = %d\n", 
-                           (*mySetEndsTotal), remappedGlobal_I );
-         mySetEnds[(*mySetEndsTotal)++].index = remappedGlobal_I;
-      }
-   }
-
-/*#if DEBUG*/
-   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
-      Index cPoint_I;
-
-      Journal_DPrintf( self->debug, "My set end Crit Points:[0-%d][ ",  (*mySetEndsTotal) );
-      for (cPoint_I = 0 ; cPoint_I < (*mySetEndsTotal) ; cPoint_I++) {
-         Journal_DPrintf( self->debug, "%2d, ", mySetEnds[cPoint_I].index );
-      }	
-      Journal_DPrintf( self->debug, "]\n" );
-
-      Journal_DPrintf( self->debug, "interface Crit Points I want:[0-%d][ ",  (*myWantedCriticalPointsTotal) );
-      for (cPoint_I = 0 ; cPoint_I < (*myWantedCriticalPointsTotal) ; cPoint_I++) {
-         Journal_DPrintf( self->debug, "%2d, ", myWantedCriticalPoints[cPoint_I] );
-      }
-      Journal_DPrintf( self->debug, "]\n" );
-   }
-/*#endif*/
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-/* work out critical points (inc. those needed by others) I hold, and those to send.
-   The list I have could be greater than my end of runs, in an irregular mesh case */
-static void _FeEquationNumber_CalculateCritPointsIHave( FeEquationNumber* self,
-							Node_GlobalIndex** const myWantedCriticalPointsPtr, Node_GlobalIndex myWantedCriticalPointsTotal,
-							CritPointInfo** const critPointsIHavePtr, Index* const critPointsIHaveTotal,
-							CritPointInfo* const critPointsToSend, Index* const critPointsToSendTotal )
-{
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-   Partition_Index proc_I; 
-   Node_GlobalIndex* allWantedCriticalPoints = NULL;
-   CritPointInfo* allHaveCriticalPoints = NULL;
-   Node_GlobalIndex* procWantedCritPointsTotals = NULL;
-   Index* procHaveCritPointsTotals = NULL;
-   Node_GlobalIndex maxWantedCritPointsPerProc = 0;
-   Node_GlobalIndex maxHaveCritPointsPerProc = 0;
-   Index myCritPoint_I = 0;
-   PartitionIndex myRank = meshDecomp->rank;
-
-   Journal_DPrintf( self->debug, "In %s\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-
-   Journal_DPrintfL( self->debug, 2, "Globally sharing locally known wanted C.N. lists:\n",  __func__ );
-   _FeEquationNumber_ShareCriticalPoints( self, myWantedCriticalPointsPtr, myWantedCriticalPointsTotal,
-                                          &allWantedCriticalPoints, &procWantedCritPointsTotals, &maxWantedCritPointsPerProc );
-
-   Journal_DPrintfL( self->debug, 2, "Globally sharing locally known 'have' C.N. lists:\n",  __func__ );
-   _FeEquationNumber_ShareCritPointInfo( self, critPointsIHavePtr, (*critPointsIHaveTotal),
-                                         &allHaveCriticalPoints, &procHaveCritPointsTotals, &maxHaveCritPointsPerProc, DONT_PRINT_VALUES );
-
-   /* now we build our lists of crit points on my processor, and crit points on my processor to send to others */
-   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
-      Index otherCritPoint_I = proc_I * maxWantedCritPointsPerProc;
-      Index otherCritPoint_End_I = (proc_I * maxWantedCritPointsPerProc) + procWantedCritPointsTotals[proc_I];
-      myCritPoint_I = 0;
-
-      /* don't try and add my own */
-      if ( myRank == proc_I ) continue;
-
-      /* for each crit point they want, if I have it add it to my have and send lists */
-      for (; otherCritPoint_I < otherCritPoint_End_I; otherCritPoint_I++) {
-         Node_GlobalIndex otherCritPoint = allWantedCriticalPoints[otherCritPoint_I];
-			
-         if ( _FeEquationNumber_IHaveCritPoint( self, otherCritPoint ) ) {
-
-            while ( (myCritPoint_I < (*critPointsIHaveTotal) ) &&
-                    (otherCritPoint > (*critPointsIHavePtr)[myCritPoint_I].index) ) {
-               /* skip ahead to right spot */
-               myCritPoint_I++;
-            }
-            if ( myCritPoint_I == (*critPointsIHaveTotal) ) {
-               (*critPointsIHavePtr)[(*critPointsIHaveTotal)++].index = otherCritPoint; 
-               critPointsToSend[(*critPointsToSendTotal)++].index = otherCritPoint;
-            }
-            else if ( otherCritPoint != (*critPointsIHavePtr)[myCritPoint_I].index ) {
-               memmove( &((*critPointsIHavePtr)[myCritPoint_I+1]),
-                        &((*critPointsIHavePtr)[myCritPoint_I]),
-                        ((*critPointsIHaveTotal) - myCritPoint_I) * sizeof(CritPointInfo) );
-               (*critPointsIHavePtr)[myCritPoint_I].index = otherCritPoint;
-               (*critPointsIHaveTotal)++;
-               memmove( &critPointsToSend[myCritPoint_I+1], &critPointsToSend[myCritPoint_I],
-                        ((*critPointsToSendTotal) - myCritPoint_I) * sizeof(CritPointInfo) );
-               critPointsToSend[myCritPoint_I].index = otherCritPoint;
-               (*critPointsToSendTotal)++;
-            }
-            /* move to the next point in any case */
-            myCritPoint_I++;
-         }	
-      }		
-   }			
-
-   /* For each crit point the others have, if I have it add it to my have list */
-   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
-      Index otherCritPointInfo_I = proc_I * maxHaveCritPointsPerProc;
-      Index otherCritPointInfo_End_I = (proc_I * maxHaveCritPointsPerProc) + procHaveCritPointsTotals[proc_I];
-      myCritPoint_I = 0;
-
-      /* don't try and add my own */
-      if ( myRank == proc_I ) continue;
-
-      for (; otherCritPointInfo_I < otherCritPointInfo_End_I; otherCritPointInfo_I++) {
-         Node_GlobalIndex otherCritPoint = allHaveCriticalPoints[otherCritPointInfo_I].index;
-			
-         if ( _FeEquationNumber_IHaveCritPoint( self, otherCritPoint ) ) {
-			
-            while ( (myCritPoint_I < (*critPointsIHaveTotal) ) &&
-                    (otherCritPoint > (*critPointsIHavePtr)[myCritPoint_I].index) ) {
-               myCritPoint_I++;
-               /* skip ahead to right spot */
-            }
-            if ( myCritPoint_I == (*critPointsIHaveTotal) ) {
-               (*critPointsIHavePtr)[(*critPointsIHaveTotal)++].index = otherCritPoint; 
-            }
-            else if ( otherCritPoint != (*critPointsIHavePtr)[myCritPoint_I].index ) {
-               memmove( &((*critPointsIHavePtr)[myCritPoint_I+1]),
-                        &((*critPointsIHavePtr)[myCritPoint_I]),
-                        ((*critPointsIHaveTotal) - myCritPoint_I) * sizeof(CritPointInfo) );
-               (*critPointsIHavePtr)[myCritPoint_I].index = otherCritPoint;
-               (*critPointsIHaveTotal)++;
-            }
-            /* move to the next point in any case */
-            myCritPoint_I++;
-         }	
-      }		
-   }			
-/*#if DEBUG*/
-   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
-      Journal_DPrintf( self->debug, "Calculated crit points I Have:\n[" );
-      for ( myCritPoint_I = 0; myCritPoint_I < (*critPointsIHaveTotal); myCritPoint_I++ ) {
-         Journal_DPrintf( self->debug, "%3d, ", (*critPointsIHavePtr)[myCritPoint_I].index );
-      }
-      Journal_DPrintf( self->debug, "]\nCalculated crit points To Send:\n[" );
-      for ( myCritPoint_I = 0; myCritPoint_I < (*critPointsToSendTotal); myCritPoint_I++ ) {
-         Journal_DPrintf( self->debug, "%3d, ", critPointsToSend[myCritPoint_I].index );
-      }
-      Journal_DPrintf( self->debug, "]\n");
-   }	
-/*#endif*/
-	
-   Memory_Free( allWantedCriticalPoints );
-   Memory_Free( procWantedCritPointsTotals );
-   Memory_Free( allHaveCriticalPoints );
-   Memory_Free( procHaveCritPointsTotals );
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-static Bool _FeEquationNumber_IHaveCritPoint(
-   FeEquationNumber* self,
-   Node_RemappedGlobalIndex critPoint )
-{
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-   Node_DomainIndex nodeDomainCount = meshDecomp->nodeDomainCount;
-   PartitionIndex myRank = meshDecomp->rank;
-
-   /* Case 1: for remapped hexa mesh, just check if its between max and min numbers */	
-   if ( self->remappingActivated ) {
-      if ( ( self->remappedNodeInfos[0].remappedGlobal <= critPoint ) &&
-           ( critPoint <= self->remappedNodeInfos[nodeDomainCount-1].remappedGlobal ) )
-      {
-         return True;
-      }
-      else {
-         return False;
-      }	
-   }
-   /* Case 2: 2D+ hexa decomps or other decomp strategy, use local (and shadow if enabled) node IndexSet */
-   else {
-      if ( IndexSet_IsMember( meshDecomp->localNodeSets[myRank], critPoint ) ) {
-         return True;
-      }
-      else if ( (meshDecomp->shadowDepth > 0) 
-                && IndexSet_IsMember( meshDecomp->shadowNodeSets[myRank], critPoint ) ) {
-         return True;
-      }
-      else {
-         return False;
-      }
-   }
-}
-
-
-/** Performs an AllGather on a set of critical points: Each processer will afterwards have all the critical points
-    of all the processors, in one large array. The user must then index into the array by processor carefully. */
-static void _FeEquationNumber_ShareCriticalPoints(
-   FeEquationNumber* self,
-   Node_GlobalIndex** const myCriticalPoints,
-   Node_GlobalIndex myCriticalPointsTotal,
-   Node_GlobalIndex** allCriticalPoints,
-   Index** procCritPointsTotals, 
-   Node_GlobalIndex* const maxCritPointsPerProc)
-{
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-   Partition_Index proc_I; 
-/*#if DEBUG*/
-   Index point_I = 0;
-/*#endif*/
-
-   Journal_DPrintf( self->debug, "In %s\n", __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-	
-   (*maxCritPointsPerProc) = 0;
-	
-/*#if DEBUG*/
-   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
-      Journal_DPrintf( self->debug, "myCriticalPointsTotal=%u\n",  myCriticalPointsTotal);
-      Journal_DPrintf( self->debug, "myCritPoints:(" );
-      for ( point_I = 0; point_I < myCriticalPointsTotal; point_I++)
-      {
-         Journal_DPrintf( self->debug, "%u, ", (*myCriticalPoints)[point_I]);
-      }	
-      Journal_DPrintf( self->debug, ")\n");
-   }	
-/*#endif*/
-
-   /* First, we allocate and calculate how many critical points are on each node (this way, we don't have to guess
-      how much memory to allocate in the main array.) */
-   (*procCritPointsTotals) = Memory_Alloc_Array( Node_GlobalIndex, meshDecomp->nproc,
-                                                 "*procCritPointsTotals (ShareCriticalPoints)" ); 
-	
-   MPI_Allgather( &myCriticalPointsTotal, 1, MPI_UNSIGNED,
-                  (*procCritPointsTotals), 1, MPI_UNSIGNED,
-                  meshDecomp->communicator );
-	
-   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
-      if ( (*procCritPointsTotals)[proc_I] > (*maxCritPointsPerProc) )
-         (*maxCritPointsPerProc) = (*procCritPointsTotals)[proc_I];
-   }
-
-/*#if DEBUG*/
-   Journal_DPrintfL( self->debug, 2, "procCritPoints totals:(");
-   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
-      Journal_DPrintfL( self->debug, 2, "%d, ", (*procCritPointsTotals)[proc_I]);
-   }
-   Journal_DPrintfL( self->debug, 2, ")\n");
-   Journal_DPrintfL( self->debug, 2, "MaxCritPointsPerProc = %d\n", (*maxCritPointsPerProc));
-/*#endif*/
-
-   /* Now share the actual point values */
-   (*myCriticalPoints) = Memory_Realloc_Array( (*myCriticalPoints), Node_GlobalIndex, *maxCritPointsPerProc );
-   (*allCriticalPoints) = Memory_Alloc_Array( Node_GlobalIndex, meshDecomp->nproc * (*maxCritPointsPerProc),
-                                              "*allCriticalPoints (ShareCriticalPoints)" );
-
-   MPI_Allgather( (*myCriticalPoints), (*maxCritPointsPerProc), MPI_UNSIGNED,
-                  (*allCriticalPoints), (*maxCritPointsPerProc), MPI_UNSIGNED,
-                  meshDecomp->communicator );
-
-/*#if DEBUG*/
-   Journal_DPrintfL( self->debug, 2, "procCritPoints:(" );
-   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
-      for ( point_I = 0; point_I < (*procCritPointsTotals)[proc_I]; point_I++)
-      {
-         Journal_DPrintfL( self->debug, 2, "%u, ", 
-                           (*allCriticalPoints)[(*maxCritPointsPerProc)*proc_I + point_I]);
-      }	
-   }
-   Journal_DPrintfL( self->debug, 2, ")\n");
-/*#endif*/
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-
-/** Performs an AllGather on a set of CritPointInfo structs: Each processer will afterwards have all the CritPointInfo
-    structs of all the processors, in one large array. The user must then index into the array by processor
-    carefully. */
-static void _FeEquationNumber_ShareCritPointInfo(
-   FeEquationNumber* self,
-   CritPointInfo** const myCritPointInfo,
-   Index myCritPointInfoTotal,
-   CritPointInfo** allCritPointInfo,
-   Index** procCritPointInfoTotals,
-   Index* const maxCritPointInfoPerProc,
-   PrintValuesFlag printValuesFlag )
-{
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-   Partition_Index proc_I; 
-/*#if DEBUG*/
-   Index point_I = 0;
-/*#endif*/
-
-   Journal_DPrintfL( self->debug, 1, "In %s\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-   (*maxCritPointInfoPerProc) = 0;
-
-   /* allgather the totals (to save allocating unnecessary memory) */
-   (*procCritPointInfoTotals) = Memory_Alloc_Array( Node_GlobalIndex, meshDecomp->nproc, "*procCritPointInfoTotals" ); 
-
-   MPI_Allgather( &myCritPointInfoTotal, 1, MPI_INT, (*procCritPointInfoTotals), 1, MPI_INT,
-                  meshDecomp->communicator );
-
-   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
-      if ( (*procCritPointInfoTotals)[proc_I] > (*maxCritPointInfoPerProc) )
-         (*maxCritPointInfoPerProc) = (*procCritPointInfoTotals)[proc_I];
-   }
-
-/*#if DEBUG*/
-   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
-      Journal_DPrintf( self->debug, "procCritPointInfo totals:(" );
-      for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
-         Journal_DPrintf( self->debug, "%d, ", (*procCritPointInfoTotals)[proc_I]);
-      }
-      Journal_DPrintf( self->debug, ")\n");
-      Journal_DPrintf( self->debug, "MaxCritPointInfoPerProc = %d\n", (*maxCritPointInfoPerProc));
-   }	
-/*#endif*/
-
-   /* Now share the actual critPointInfo arrays */
-   (*allCritPointInfo) = Memory_Alloc_Array( CritPointInfo, meshDecomp->nproc * (*maxCritPointInfoPerProc), 
-                                             "allCritPointInfo (ShareCritPointInfo)" );
-
-   /* below changed by PatrickSunter 27/1/2004 to work on grendel */
-   MPI_Allgather( (*myCritPointInfo), (*maxCritPointInfoPerProc), MPI_critPointInfoType,
-                  (*allCritPointInfo), (*maxCritPointInfoPerProc), MPI_critPointInfoType,
-                  meshDecomp->communicator );
-	
-/*#if DEBUG*/
-   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {	
-      Journal_DPrintf( self->debug, "procCritPointInfos" );
-      if ( DONT_PRINT_VALUES == printValuesFlag ) {
-         Journal_DPrintf( self->debug, "(indices only)" );
-      }
-      Journal_DPrintf( self->debug, ": (" );
-      for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
-         for ( point_I = 0; point_I < (*procCritPointInfoTotals)[proc_I]; point_I++)
-         {
-            Index current = (*maxCritPointInfoPerProc)*proc_I + point_I;
-            Journal_DPrintf( self->debug, "%u", (*allCritPointInfo)[current].index );
-            if ( PRINT_VALUES == printValuesFlag ) {
-               Journal_DPrintf( self->debug, "= %d", (*allCritPointInfo)[current].eqNum );
-            }	
-            Journal_DPrintf( self->debug, ", " );
-         }	
-      }
-      Journal_DPrintf( self->debug, ")\n");
-   }	
-/*#endif*/
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-/** For each domain node, calculate the Equation number, restarting at 0 whenever a critical node is reached and
-    saving the value I was up to. */
-static void _FeEquationNumber_DoPartialTotals( FeEquationNumber* self,
-					       CritPointInfo* const critPointsIHave, Index critPointsIHaveTotal,
-					       CritPointInfo* const critPointsToSend, Index critPointsToSendTotal )
-{
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-   Node_DomainIndex nodeDomainCount = meshDecomp->nodeDomainCount;
-   RemappedNodeInfo_Index rNodeInfo_I = 0;
-   Node_RemappedGlobalIndex remappedGlobal_I = 0;
-   Node_DomainIndex dNode_I = 0;
-   Index haveCritPoint_I = 0;
-   Index sendCritPoint_I = 0;
-   Dof_EquationNumber currSubTotalEqNum = 0;
-
-   Journal_DPrintf( self->debug, "In %s:\n", __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-	
-   while ( (rNodeInfo_I < nodeDomainCount) ) {
-      remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I].remappedGlobal;
-      dNode_I = self->remappedNodeInfos[rNodeInfo_I].domain;
-	
-      _FeEquationNumber_HandleNode( self, dNode_I, &currSubTotalEqNum );
-
-      /* if the node is next critical point */
-      if ( ( haveCritPoint_I < critPointsIHaveTotal ) 
-           && ( remappedGlobal_I == critPointsIHave[haveCritPoint_I].index ) ) 
-      {
-         Journal_DPrintfL( self->debug, 3, "storing c.p. subtotal at remapped global index %u = %d\n", 
-                           remappedGlobal_I, currSubTotalEqNum );
-         /* store current value */
-         critPointsIHave[haveCritPoint_I++].eqNum = currSubTotalEqNum;
-
-         /* check if its also a to send point */
-         if ( ( sendCritPoint_I < critPointsToSendTotal )
-              && ( remappedGlobal_I == critPointsToSend[sendCritPoint_I].index ) )
-         {
-            /* store current value */
-            critPointsToSend[sendCritPoint_I++].eqNum = currSubTotalEqNum;
-         }
-         /* reset counter and move to next point */
-         currSubTotalEqNum = 0;
-      }	
-      rNodeInfo_I++;
-   }
-
-/*#if DEBUG*/
-   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
-      Journal_DPrintf( self->debug, "Totals I have:[ " );
-      haveCritPoint_I = 0;
-      for ( haveCritPoint_I = 0; haveCritPoint_I < critPointsIHaveTotal; haveCritPoint_I++ )
-      {	
-         Journal_DPrintf( self->debug, "%2u=%d, ", critPointsIHave[haveCritPoint_I].index, critPointsIHave[haveCritPoint_I].eqNum  );
-      }	
-      Journal_DPrintf( self->debug, "]\n" );
-      Journal_DPrintf( self->debug, "Totals to send:[ " );
-      sendCritPoint_I = 0;
-      for ( sendCritPoint_I = 0; sendCritPoint_I < critPointsToSendTotal; sendCritPoint_I++ )
-      {	
-         Journal_DPrintf( self->debug, "%2u=%d, ", critPointsToSend[sendCritPoint_I].index, critPointsToSend[sendCritPoint_I].eqNum  );
-      }	
-      Journal_Printf( self->debug, "]\n" );
-   }
-/*#endif*/
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-/** Called right at the end of calculating ID array, to add the locally calculated partial totals with the final
-    global information, and arrive at the complete figures. */
-static void _FeEquationNumber_AddAllPartialTotals( FeEquationNumber* self, CritPointInfo* mySubTotals,
-						   Index myCritPointInfoTotal, CritPointInfo* allSubTotals, Index* procCritPointInfoTotals,
-						   Index maxSubTotalsPerProc )
-{	
-   Partition_Index proc_I;
-   FeMesh* mesh = self->feMesh;
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-   Index myRank = meshDecomp->rank;
-   Node_GlobalIndex nodeDomainCount = meshDecomp->nodeDomainCount;
-   RemappedNodeInfo_Index rNodeInfo_I = 0;
-   Node_RemappedGlobalIndex remappedGlobal_I = 0;
-   Node_DomainIndex dNode_I = 0;
-   Node_GlobalIndex gNode_I = 0;
-   Index myCritPointInfo_I = 0;
-   Index* procCritPointInfo_Is = NULL;
-   Dof_EquationNumber adjustSum = 0;
-   Dof_EquationNumber currEqNum;
-   Dof_Index currNodeNumDofs;
-   Dof_Index nodeLocalDof_I;
-   AddListEntry* addListStart;
-   AddListEntry* addListPtr;
-   AddListEntry* addListPrev;
-   Bool firstOfSet;
-   Bool* haveUpdatedLinkedDofSetTbl = NULL;
-   Index linkedDof_I;
-   Index linkedDofSet;
-#define NEXT_PROCESSOR_SECTION_START ( maxSubTotalsPerProc * (proc_I) + procCritPointInfoTotals[proc_I] )
-
-   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-	
-   gNode_I += 0;
-	
-   self->_lowestLocalEqNum = -1;
-   self->_highestLocalEqNum = -1;
-   procCritPointInfo_Is = Memory_Alloc_Array( Index, meshDecomp->nproc, "procCritPointInfo_Is (AddAllPartialTotals)" );
-	
-   /* set iterators into processors */
-   for ( proc_I = 0; proc_I < meshDecomp->nproc; proc_I++ ) {
-      procCritPointInfo_Is[proc_I] = maxSubTotalsPerProc * proc_I;
-   }
-							
-   if ( self->linkedDofInfo ) {
-      haveUpdatedLinkedDofSetTbl = Memory_Alloc_Array( Bool, self->linkedDofInfo->linkedDofSetsCount,
-                                                       "haveUpdatedLinkedDofSetTbl" );
-      for ( linkedDof_I=0; linkedDof_I < self->linkedDofInfo->linkedDofSetsCount; linkedDof_I++ ) {
-         haveUpdatedLinkedDofSetTbl[linkedDof_I] = False;
-      }	
-   }
-							
-
-   Journal_DPrintfL( self->debug, 3, "beginning sequential run through nodes...\n" );
-
-   while (rNodeInfo_I < nodeDomainCount) {
-      Node_GlobalIndex newCritInfoIndex;
-      /* reset the add list information */
-      addListPtr = addListStart = NULL;
-      remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I].remappedGlobal;
-      dNode_I = self->remappedNodeInfos[rNodeInfo_I].domain;
-	
-      Journal_DPrintfL( self->debug, 3, "At remapped gNode[%d]: ",  remappedGlobal_I );
-      Journal_DPrintfL( self->debug, 3, "...adding critical node totals from the block we just skipped...\n" );
-
-      /* Ok, now add critical node totals from other processors in the block we just skipped. */
-      for ( proc_I = 0; proc_I < meshDecomp->nproc; proc_I++ ) {
-         if ( proc_I == myRank ) continue;
-
-         /* reset the add list back to start */
-         addListPtr = addListStart;
-         addListPrev = NULL;
-			
-
-         /* Only add critical node totals from other processors lower than current index */
-         while (( procCritPointInfo_Is[proc_I] < NEXT_PROCESSOR_SECTION_START ) &&
-                (newCritInfoIndex = allSubTotals[(procCritPointInfo_Is[proc_I])].index) < remappedGlobal_I )
-         {
-            /* See if we are scheduled to add this critical point yet, and if not where it should go */
-            while ( addListPtr && ( newCritInfoIndex > addListPtr->critPointInfo->index ) ) {
-               addListPrev = addListPtr; 
-               addListPtr = addListPtr->next;
-            }
-            /* Note: The 2nd condition guards against trying to add a duplicate. In that case we
-             * just progress on. */
-            if ( (addListPtr == NULL) || ( addListPtr->critPointInfo->index != newCritInfoIndex )) {
-               /*
-                 if inside this condition we are either:
-                 1. Adding the first crit node to be added
-                 2. Have found a non-duplicate crit node to be added, either at the end or
-                 partway through.
-                 So go ahead and add to the addList, reconnecting both the prev and next.
-               */
-               AddListEntry* newAddListEntry = Memory_Alloc( AddListEntry,
-                                                             "newAddListEntry (AddAllPartialTotals)" );
-               adjustSum += allSubTotals[procCritPointInfo_Is[proc_I]].eqNum;
-               Journal_DPrintfL( self->debug, 3, "at other c.p. (%d):incrementing adjustSum by %d to = %d\n", 
-                                 allSubTotals[procCritPointInfo_Is[proc_I]].index,
-                                 allSubTotals[procCritPointInfo_Is[proc_I]].eqNum,
-                                 adjustSum );
-               newAddListEntry->critPointInfo = &allSubTotals[procCritPointInfo_Is[proc_I]];
-               newAddListEntry->next = addListPtr;
-               if ( addListPrev ) {
-                  addListPrev->next = newAddListEntry;
-               }
-               else {
-                  addListStart = newAddListEntry;
-               }
-               addListPtr = newAddListEntry;
-            }	
-            /* Move to the next potential crit node from that processor, regardless of whether we
-             * added the last one or not. */
-            (procCritPointInfo_Is[proc_I])++;
-         }	
-      }
-
-      /* free the add list */
-      while ( addListStart ) {
-         addListPrev = addListStart;
-         addListStart = addListStart->next;
-         Memory_Free( addListPrev );
-      }
-		
-      /* Now go through a run of nodes this processor owns, and add subtotals locally calculated */
-      firstOfSet = True;
-
-      while ( (firstOfSet) ||
-              ( (rNodeInfo_I < nodeDomainCount)
-                && (self->remappedNodeInfos[rNodeInfo_I].remappedGlobal ==
-                    (self->remappedNodeInfos[rNodeInfo_I-1].remappedGlobal + 1) ) ) )
-      {
-         remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I].remappedGlobal;
-         dNode_I = self->remappedNodeInfos[rNodeInfo_I].domain;
-         gNode_I = mesh->nodeD2G[dNode_I];
-         firstOfSet = False;
-			
-         Journal_DPrintfL( self->debug, 3, "At remapped gNode[%d]: I own it, so adjusting EqNums\n", 
-                           remappedGlobal_I );
-
-         /* increment the value at each non-bc dof by adjustSum */
-         currNodeNumDofs = self->dofLayout->dofCounts[ dNode_I ];
-
-         for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-            if( !self->bcs || !VariableCondition_IsCondition( self->bcs, dNode_I,
-                                                              self->dofLayout->varIndices[dNode_I][nodeLocalDof_I] ) )
-            {
-               if ( (NULL == self->linkedDofInfo) ||	/* TAG: bcs */
-                    ( self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I] == -1 ) )
-               {
-                  /* A normal point, so increment */
-                  self->destinationArray[dNode_I][nodeLocalDof_I] += adjustSum;
-               }
-               else {
-                  /* Handling of linked dofs: the first time we encounter one of a set,
-                     add the adjust sum. Afterwards, just set to the updated value. */
-                  linkedDofSet = self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I];
-                  if ( False == haveUpdatedLinkedDofSetTbl[linkedDofSet] ) {
-                     self->destinationArray[dNode_I][nodeLocalDof_I] += adjustSum;
-                     self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] += adjustSum;
-                     haveUpdatedLinkedDofSetTbl[linkedDofSet] = True;
-                  }
-                  else {
-                     self->destinationArray[dNode_I][nodeLocalDof_I] =
-                        self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet];
-                  }
-               }
-						
-               currEqNum = self->destinationArray[dNode_I][nodeLocalDof_I];
-               /* If current node not a shadow, then check totals */
-               if ( dNode_I < mesh->nodeLocalCount ) {
-                  if ( currEqNum != -1 ) {	/* TAG: bcs */
-                     if ( self->_lowestLocalEqNum == -1 ) {
-                        /* We need this if statement to initialise this */
-                        self->_lowestLocalEqNum = currEqNum;
-                     }	
-                     else if ( currEqNum < self->_lowestLocalEqNum ) {
-                        self->_lowestLocalEqNum = currEqNum;
-                     }
-
-                     if ( currEqNum > self->_highestLocalEqNum ) {
-                        self->_highestLocalEqNum = currEqNum;
-                     }	
-                  }
-               }
-            }	
-         }		
-
-         /* if the node is my next critical point, add the sub-total */
-         if ( ( myCritPointInfo_I < myCritPointInfoTotal ) &&
-              ( remappedGlobal_I == mySubTotals[myCritPointInfo_I].index)  ) 
-         {
-            adjustSum += mySubTotals[myCritPointInfo_I].eqNum;
-            Journal_DPrintfL( self->debug, 3, "at   my    c.p. %d(%d):incrementing adjustSum by %d to = %d\n", 
-                              myCritPointInfo_I, remappedGlobal_I, mySubTotals[myCritPointInfo_I].eqNum, adjustSum );
-            myCritPointInfo_I++;
-         }
-
-         rNodeInfo_I++;
-      }	
-
-      /* If any of the other processors had sub-totals I've just added, jump past them */
-      if (rNodeInfo_I < nodeDomainCount) {
-         for ( proc_I = 0; proc_I < meshDecomp->nproc; proc_I++ ) {
-
-            while (( procCritPointInfo_Is[proc_I] < NEXT_PROCESSOR_SECTION_START ) &&
-                   allSubTotals[(procCritPointInfo_Is[proc_I])].index <= remappedGlobal_I )
-            {
-               (procCritPointInfo_Is[proc_I])++;
-            }
-
-         }
-      }
-   }
-
-   if ( self->linkedDofInfo ) {
-      Memory_Free( haveUpdatedLinkedDofSetTbl );
-   }	
-   Memory_Free( procCritPointInfo_Is );
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-/** Updates the currEqNum argument for the number of dofs at the current node, and increments the ID Eq. Num for each
-    dof where appropriate (setting it to -1 if its a B.C.) */
-static void _FeEquationNumber_HandleNode( FeEquationNumber* self, const Node_DomainIndex dNode_I,
-					  Dof_EquationNumber* const currEqNum )
-{
-   Dof_Index	currNodeNumDofs;
-   Dof_Index	nodeLocalDof_I;
-/*#if DEBUG*/
-   Stream*		error;
-/*#endif*/
-	
-   Journal_DPrintfL( self->debug, 3, "In %s:",  __func__ );
-/*#if DEBUG*/
-   error = Journal_Register( Error_Type, (Name)self->type );
-   Journal_Firewall( (dNode_I < self->feMesh->nodeDomainCount ), error, "Stuffup: %s() asked to operate on node %d, bigger "
-                     "than domain count %d. Exiting.\n", __func__, dNode_I, self->feMesh->nodeDomainCount );
-/*#endif*/
-	
-   /* get the number of dofs */
-   currNodeNumDofs = self->dofLayout->dofCounts[ dNode_I ];
-   Journal_DPrintfL( self->debug, 3, " domain node %d, has %d dofs.\n", dNode_I, currNodeNumDofs );
-   /* process each dof, at the same time updating the updatePtr for the next node. */
-   for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-      Journal_DPrintfL( self->debug, 3, "dof %d: ", nodeLocalDof_I );
-
-      /* if dof is a boundary condition, set eq num=-1. Otherwise increment counter. */
-      /* Also, only set to -1 if we want the BCs removed from the matrix. - Luke */
-      if( self->removeBCs && 
-          self->bcs && VariableCondition_IsCondition( self->bcs, dNode_I, self->dofLayout->varIndices[dNode_I][nodeLocalDof_I] ) ) 
-      {
-         Journal_DPrintfL( self->debug, 3, "is a BC, setting ID[%d][%d] = -1.\n", dNode_I, nodeLocalDof_I );
-         self->destinationArray[dNode_I][nodeLocalDof_I] = -1;
-      }	
-      /* Check if node,dof is a linked dof */
-      else if ( self->linkedDofInfo && ( self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I] != -1 ) ) {
-         Index linkedDofSet = self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I];
-			
-         if ( self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] != -1 ) {
-            Journal_DPrintfL( self->debug, 3, "is a linked Dof, so setting ID[%d][%d] to the "
-                              "previous value = %d.\n", dNode_I, nodeLocalDof_I, 
-                              self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] );
-            /* value is same as the first part of the linked node set */
-            self->destinationArray[dNode_I][nodeLocalDof_I] =
-               self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet];
-         }
-         else /* This is the first time we've hit this linked eq num, so treat as normal */
-         {
-            Journal_DPrintfL( self->debug, 3, "is a linked Dof hit the first time, so setting "
-                              "ID[%d][%d] = %d.\n", dNode_I, nodeLocalDof_I, *currEqNum );
-			
-            self->destinationArray[dNode_I][nodeLocalDof_I] = (*currEqNum)++;
-            if ( dNode_I < self->feMesh->nodeLocalCount ) {
-               self->_highestLocalEqNum = self->destinationArray[dNode_I][nodeLocalDof_I];
-            }	
-            /* And save the value at the linked eq num for later */
-            self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] = 
-               self->destinationArray[dNode_I][nodeLocalDof_I];
-         }
-      }
-      else {	
-         Journal_DPrintfL( self->debug, 3, "is a normal node, setting ID[%d][%d] = %d.\n", dNode_I, nodeLocalDof_I, *currEqNum );
-         self->destinationArray[dNode_I][nodeLocalDof_I] = (*currEqNum)++;
-         if ( dNode_I < self->feMesh->nodeLocalCount ) {
-            self->_highestLocalEqNum = self->destinationArray[dNode_I][nodeLocalDof_I];
-         }	
-      }
-   }
-}
-
-
-void _FeEquationNumber_PostProcessLinkedDofs( FeEquationNumber* self ) {
-   Index			linkedDof_I;
-   int			valueToReduce;
-   int			minimumValue;
-   Node_Index		rNodeInfo_I;
-   Node_DomainIndex	dNode_I;
-   MeshDecomp*		meshDecomp = self->feMesh->layout->decomp;
-   Dof_Index		nodeLocalDof_I;
-   Dof_Index		currNodeNumDofs;
-   Index			linkedDofSet;
-   Bool*			adjustDueToNonLocalLinkedDofsTbl = NULL;
-   unsigned int		subtractionAdjustmentTotal;
-   Dof_EquationNumber      currEqNum;
-	
-   Journal_DPrintfL( self->debug, 1, "In Func %s():\n", __func__ );
-   adjustDueToNonLocalLinkedDofsTbl = Memory_Alloc_Array( Bool, self->linkedDofInfo->linkedDofSetsCount,
-                                                          "adjustDueToNonLocalLinkedDofsTbl" );
-		
-   /* We need to re-calculate these, since the post processing may alter both the lowest and higest eqNum values */
-   self->_lowestLocalEqNum = -1;
-   self->_highestLocalEqNum = -1;
-		
-   Journal_DPrintfL( self->debug, 2, "Note: in reductions to follow, value of %d, the node global count, "
-                     "denotes that this processor doesn't hold any of that linked dof.\n", self->feMesh->nodeGlobalCount );
-
-   Stream_Indent( self->debug );
-   for ( linkedDof_I=0; linkedDof_I < self->linkedDofInfo->linkedDofSetsCount; linkedDof_I++ ) {
-      if ( -1 != self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDof_I] ) {
-         valueToReduce = self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDof_I];
-      }
-      else {
-         valueToReduce = self->feMesh->nodeGlobalCount;
-      }	
-		
-      Journal_DPrintfL( self->debug, 2, "Reducing linked Dof %d: this proc has value %d\n", linkedDof_I, valueToReduce );
-      MPI_Allreduce( &valueToReduce, &minimumValue, 1, MPI_INT, MPI_MIN, meshDecomp->communicator );
-		
-      Journal_DPrintfL( self->debug, 2, "\tMinimum val = %d\n", minimumValue );
-      self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDof_I] = minimumValue;
-
-      if ( valueToReduce != minimumValue ) {
-         adjustDueToNonLocalLinkedDofsTbl[linkedDof_I] = True;
-      }
-      else {
-         adjustDueToNonLocalLinkedDofsTbl[linkedDof_I] = False;
-      }
-   }	
-   Stream_UnIndent( self->debug );
-	
-   Journal_DPrintfL( self->debug, 2, "Post-processing totals to correct based on non-local linked dofs\n" );
-   subtractionAdjustmentTotal = 0;
-	
-   Stream_Indent( self->debug );
-   for ( rNodeInfo_I = 0; rNodeInfo_I < self->feMesh->nodeDomainCount; rNodeInfo_I++ ) {
-      dNode_I = self->remappedNodeInfos[rNodeInfo_I].domain;
-      Journal_DPrintfL( self->debug, 3, "At remapped node %d (dNode %d):\n", rNodeInfo_I, dNode_I );
-      currNodeNumDofs = self->dofLayout->dofCounts[ dNode_I ];
-		
-      for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-
-         Stream_Indent( self->debug );
-         Journal_DPrintfL( self->debug, 3, "At dof %d: ", nodeLocalDof_I );
-		
-         if( self->bcs && VariableCondition_IsCondition( self->bcs, dNode_I,
-                                                         self->dofLayout->varIndices[dNode_I][nodeLocalDof_I] ) )
-         {
-            Journal_DPrintfL( self->debug, 3, "is a BC: ignoring.\n" );
-         }
-         else if ( self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I] != -1 ) {
-            linkedDofSet = self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I];
-
-            Journal_DPrintfL( self->debug, 3, "is a linked Dof, so setting value to %d\n",
-                              self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] );
-
-            self->destinationArray[dNode_I][nodeLocalDof_I] -= subtractionAdjustmentTotal;
-
-            if ( True == adjustDueToNonLocalLinkedDofsTbl[linkedDofSet] ) {
-               /* We now need to test, after the subtraction adjustment has been made, if the 
-                  value of this linked dof now matches the minimum. If so, don't subtract further. */
-               if ( self->destinationArray[dNode_I][nodeLocalDof_I] != 
-                    self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] )
-               {
-                  subtractionAdjustmentTotal++;
-                  Journal_DPrintfL( self->debug, 3, "And since first was non-local, increasing "
-                                    "subtraction adj. to %d\n", subtractionAdjustmentTotal );
-               }	
-						
-               /* Make sure we only adjust once */
-               adjustDueToNonLocalLinkedDofsTbl[linkedDofSet] = False;
-            }
-
-            self->destinationArray[dNode_I][nodeLocalDof_I] =
-               self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet];
-				
-         }
-         else {
-            Journal_DPrintfL( self->debug, 3, "subtracting %d\n", subtractionAdjustmentTotal );
-            self->destinationArray[dNode_I][nodeLocalDof_I] -= subtractionAdjustmentTotal;
-         }
-
-         currEqNum = self->destinationArray[dNode_I][nodeLocalDof_I];
-         if ( dNode_I < self->feMesh->nodeLocalCount ) {
-            if ( currEqNum != -1 ) {	/* TAG: bcs */
-               if ( self->_lowestLocalEqNum == -1 ) {
-                  /* We need this if statement to initialise this */
-                  self->_lowestLocalEqNum = currEqNum;
-               }	
-               else if ( currEqNum < self->_lowestLocalEqNum ) {
-                  self->_lowestLocalEqNum = currEqNum;
-               }
-
-               if ( currEqNum > self->_highestLocalEqNum ) {
-                  self->_highestLocalEqNum = currEqNum;
-               }	
-            }
-         }	
-         Stream_UnIndent( self->debug );
-      }	
-   }		
-   Stream_UnIndent( self->debug );
-
-   Memory_Free( adjustDueToNonLocalLinkedDofsTbl );
-}
-#endif
-
-
-Index FeEquationNumber_CalculateActiveEqCountAtNode(
-   void*			feEquationNumber,
-   Node_DomainIndex	dNode_I,
-   Dof_EquationNumber*	lowestActiveEqNumAtNodePtr )
-{
-   FeEquationNumber*	self = (FeEquationNumber*) feEquationNumber;
-   Dof_Index		nodalDof_I = 0;
-   Index			activeEqsAtCurrRowNode = 0;		
-   Dof_EquationNumber	currEqNum;
-   Bool			foundLowest = False;
-
-   for ( nodalDof_I = 0; nodalDof_I < self->dofLayout->dofCounts[dNode_I]; nodalDof_I++ ) {
-      currEqNum = self->destinationArray[dNode_I][nodalDof_I];
-      if ( currEqNum != -1 ) {
-         activeEqsAtCurrRowNode++;
-         if ( False == foundLowest ) {
-            (*lowestActiveEqNumAtNodePtr) = currEqNum;
-            foundLowest = True;
-         }
-      }
-   }
-
-   return activeEqsAtCurrRowNode;
-}
-
-
-void FeEquationNumber_BuildLocationMatrix( void* feEquationNumber ) {
-   FeEquationNumber*	self = (FeEquationNumber*)feEquationNumber;
-   FeMesh*			feMesh;
-   unsigned		nDims;
-   unsigned		nDomainEls;
-   unsigned		nLocalNodes;
-   unsigned*		nNodalDofs;
-   unsigned		nElNodes;
-   unsigned*		elNodes;
-   int**			dstArray;
-   int***			locMat;
-   IArray*			inc;
-   unsigned		e_i, n_i, dof_i;
-
-   assert( self );
-
-   /* Don't build if already done. */
-   if( self->locationMatrixBuilt ) {
-      Journal_DPrintf( self->debugLM, "In %s: LM already built, so just returning.\n",  __func__ );
-      Stream_UnIndentBranch( StgFEM_Debug );
-      return;
-   }
-
-   inc = IArray_New();
-
-   /* Shortcuts. */
-   feMesh = self->feMesh;
-   nDims = Mesh_GetDimSize( feMesh );
-   nDomainEls = FeMesh_GetElementDomainSize( feMesh );
-   nLocalNodes = FeMesh_GetNodeLocalSize( feMesh );
-   nNodalDofs = self->dofLayout->dofCounts;
-   dstArray = self->destinationArray;
-
-   /* Allocate for the location matrix. */
-   locMat = AllocArray( int**, nDomainEls );
-   for( e_i = 0; e_i < nDomainEls; e_i++ ) {
-      FeMesh_GetElementNodes( feMesh, e_i, inc );
-      nElNodes = IArray_GetSize( inc );
-      elNodes = (unsigned*)IArray_GetPtr( inc );
-      locMat[e_i] = AllocArray( int*, nElNodes );
-      for( n_i = 0; n_i < nElNodes; n_i++ )
-         locMat[e_i][n_i] = AllocArray( int, nNodalDofs[elNodes[n_i]] );
-   }
-
-   /* Build location matrix. */
-   for( e_i = 0; e_i < nDomainEls; e_i++ ) {
-      FeMesh_GetElementNodes( feMesh, e_i, inc );
-      nElNodes = IArray_GetSize( inc );
-      elNodes = (unsigned*)IArray_GetPtr( inc );
-      for( n_i = 0; n_i < nElNodes; n_i++ ) {
-         for( dof_i = 0; dof_i < nNodalDofs[elNodes[n_i]]; dof_i++ )
-            locMat[e_i][n_i][dof_i] = dstArray[elNodes[n_i]][dof_i];
-      }
-   }
-
-   NewClass_Delete( inc );
-
-   /* Store result. */
-   self->locationMatrix = locMat;
-}
-
-
-#if 0
-/** build the element location matrix mapping elements, element node, dof -> eq num */
-void FeEquationNumber_BuildLocationMatrix( FeEquationNumber* self ) {
-   FeMesh* mesh = self->feMesh;
-   Element_LocalIndex lElement_I;
-   Node_LocalIndex numNodesThisElement = 0;
-   Node_LocalIndex elLocalNode_I = 0;
-   Dof_Index numDofsThisNode = 0;
-   Dof_Index** dofCountsAtElementNodesArray = NULL;
-   Element_LocalIndex elementLocalCount = Mesh_GetLocalSize( mesh, Mesh_GetDimSize( mesh ) );
-
-   Journal_DPrintf( self->debug, "In %s():\n", __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-	
-   if (self->locationMatrixBuilt) {
-      Journal_DPrintf( self->debugLM, "In %s: LM already built, so just returning.\n",  __func__ );
-      Stream_UnIndentBranch( StgFEM_Debug );
-      return;
-   }
-
-   Journal_DPrintf( self->debugLM, "In %s: building over %d elements.\n",  __func__, elementLocalCount );
-
-   /* Allocate the LM 3D array using the Memory module, in 2 stage process */
-   dofCountsAtElementNodesArray = Memory_Alloc_3DSetup( elementLocalCount, 
-                                                        mesh->topo->nIncEls[nDims][MT_VERTEX] );
-
-   for ( lElement_I = 0; lElement_I < elementLocalCount; lElement_I++ ) {
-      numNodesThisElement = mesh->elementNodeCountTbl[lElement_I];
-
-      for( elLocalNode_I = 0; elLocalNode_I < numNodesThisElement; elLocalNode_I++) {
-         Node_LocalIndex dNode_I = mesh->elementNodeTbl[lElement_I][elLocalNode_I];
-         numDofsThisNode = self->dofLayout->dofCounts[dNode_I];
-         dofCountsAtElementNodesArray[lElement_I][elLocalNode_I] = numDofsThisNode;
-      }
-   }
-
-   self->locationMatrix = Memory_Alloc_3DComplex( Dof_EquationNumber, elementLocalCount, mesh->elementNodeCountTbl,
-                                                  dofCountsAtElementNodesArray, "FeEquationNumber->locationMatrix" );
-   /* Free the dof counts array:- we have to look up domain node numbers anyway later, might as
-      well just use the dof counts array then. */
-   Memory_Free( dofCountsAtElementNodesArray );
-
-   for ( lElement_I = 0; lElement_I < elementLocalCount; lElement_I++ ) {
-      FeEquationNumber_BuildOneElementLocationMatrix( self, lElement_I );
-   }	
-
-   self->locationMatrixBuilt = True;
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-#endif
-
-
-/** Build an element's local location matrix */
-Dof_EquationNumber** FeEquationNumber_BuildOneElementLocationMatrix( void* feEquationNumber, Element_LocalIndex lElement_I ) {
-   FeEquationNumber* self = (FeEquationNumber*)feEquationNumber;
-   /* Node_DomainIndex elLocalNode_I; */
-   Node_DomainIndex numNodesThisElement, *elInc;
-   Dof_EquationNumber** localLocationMatrix = NULL;
-   FeMesh* feMesh = self->feMesh;
-   /* Dof_Index numDofsThisNode = 0; */
-   IArray* inc;
-
-   inc = IArray_New();
-   FeMesh_GetElementNodes( feMesh, lElement_I, inc );
-   numNodesThisElement = IArray_GetSize( inc );
-   elInc = (Node_DomainIndex*)IArray_GetPtr( inc );
-
-   /* HACK: Make sure global element location matrix is built. */
-   if( !self->locationMatrixBuilt )
-      abort();
-
-   /* if ( big LM allocated ) set pointer into it correctly */
-   if ( self->locationMatrix ) {
-      /* set ptr to correct set of local nodes ptrs */
-      localLocationMatrix = self->locationMatrix[lElement_I];
-      Journal_DPrintfL( self->debugLM, 3, "set localLocationMatrix to pt. to big LM[%d] = %p\n",  lElement_I, self->locationMatrix[lElement_I] ) ;
-   }
-
-#if 0
-   else {
-      Dof_Index* numDofsEachNode = NULL;
-
-      /* allocate memory for local LM to return */
-      numDofsEachNode = Memory_Alloc_Array_Unnamed( Dof_Index, numNodesThisElement );
-
-      for( elLocalNode_I = 0; elLocalNode_I < numNodesThisElement; elLocalNode_I++) {
-         Node_LocalIndex localNode = mesh->elementNodeTbl[lElement_I][elLocalNode_I];
-         numDofsEachNode[elLocalNode_I] = self->dofLayout->dofCounts[localNode];
-      }
-
-      localLocationMatrix = Memory_Alloc_2DComplex( Dof_EquationNumber, numNodesThisElement, numDofsEachNode,
-                                                    "localLocationMatrix (set of ptrs to dof lists, indexed by element-local node)" );
-      Memory_Free( numDofsEachNode );
-   }
-#endif
-
-#if 0
-   /* If we haven't yet built full LM, copy ID values across */
-   if ( False == self->locationMatrixBuilt ) {
-      /* for (each el-local node) */
-      for ( elLocalNode_I = 0; elLocalNode_I < numNodesThisElement; elLocalNode_I++ ) {
-         /* look up processor local node number. */
-         Node_LocalIndex procDomainNode = mesh->elementNodeTbl[lElement_I][elLocalNode_I];
-         numDofsThisNode = self->dofLayout->dofCounts[procDomainNode];
-
-         /* copy pointers to dof eq nums from ID array relevant to that node */
-         Journal_DPrintfL( self->debugLM, 3, "copying %d dof eq. numbers from ID[%d] to LM[%d][%d]\n", 
-                           numDofsThisNode, procDomainNode, lElement_I, elLocalNode_I );
-         memcpy( localLocationMatrix[elLocalNode_I],
-                 self->destinationArray[procDomainNode], numDofsThisNode * sizeof(Dof_EquationNumber) );
-      }
-   }
-#endif
-
-   NewClass_Delete( inc );
-
-   return localLocationMatrix;
-}
-
-
-void FeEquationNumber_PrintDestinationArray( void* feFeEquationNumber, Stream* stream ) {
-   FeEquationNumber* self = (FeEquationNumber*) feFeEquationNumber;
-   FeMesh*		feMesh = self->feMesh;
-   MPI_Comm comm = Comm_GetMPIComm( Mesh_GetCommTopology( feMesh, MT_VERTEX ) );
-   unsigned rank;
-   Node_GlobalIndex gNode_I;
-   Node_GlobalIndex nodeGlobalCount = FeMesh_GetNodeGlobalSize( feMesh );
-
-   MPI_Comm_rank( comm, (int*)&rank );
-   Journal_Printf( stream, "%d: *** Printing destination array ***\n", rank );
-
-   for (gNode_I =0; gNode_I < nodeGlobalCount; gNode_I++) {
-      Node_DomainIndex dNode_I;
-
-      if ( !Mesh_GlobalToDomain( feMesh, MT_VERTEX, gNode_I, &dNode_I ) ) {
-         Journal_Printf( stream, "\tdestinationArray[(gnode)%2d]: on another proc\n", gNode_I);
-      }
-      else {
-         Dof_Index currNodeNumDofs = self->dofLayout->dofCounts[ dNode_I ];
-         Dof_Index nodeLocalDof_I;
-
-         Journal_Printf( stream, "\tdestinationArray[(gnode)%2d][(dof)0-%d]:",gNode_I, currNodeNumDofs );
-         for( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-            Journal_Printf( stream, "%3d, ", self->destinationArray[dNode_I][nodeLocalDof_I] );
-         }
-         Journal_Printf( stream, "\n" );
-      }
-   }		
-}
-
-void FeEquationNumber_PrintDestinationArrayBox( void* feFeEquationNumber, Stream* stream ) {
-	FeEquationNumber*   self = (FeEquationNumber*) feFeEquationNumber;
-	FeMesh*             feMesh = self->feMesh;
-	MPI_Comm            comm = Comm_GetMPIComm( Mesh_GetCommTopology( feMesh, MT_VERTEX ) );
-	unsigned            rank;
-	Grid*               vGrid;
-	unsigned            ijk[3];
-	Element_LocalIndex  lNode_I;
-	Node_GlobalIndex    gNode_I;
-	Node_Index          sizeI, sizeJ, sizeK;
-	Dof_Index           nDofs;
-	Dof_Index           dof_I;
-
-	MPI_Comm_rank( comm, (int*)&rank );
-	Journal_Printf( stream, "%d: *** Printing destination array ***\n", rank );
-	
-	vGrid = *Mesh_GetExtension( feMesh, Grid**, "vertexGrid" );
-	nDofs = self->dofLayout->dofCounts[0];
-	sizeI = vGrid->sizes[ I_AXIS ];
-	sizeJ = vGrid->sizes[ J_AXIS ];
-	sizeK = vGrid->sizes[ K_AXIS ] ? vGrid->sizes[ K_AXIS ] : 1;
-
-	for ( ijk[2] = 0 ; ijk[2] < sizeK ; ijk[2]++ ) {
-		if ( sizeK != 1 )
-			Journal_Printf( stream, "\nk = %d\n", ijk[2] );
-		for ( ijk[1] = sizeJ - 1 ; ijk[1] >= 0 ; ijk[1]-- ) {
-			Journal_Printf( stream, "%2d - ", ijk[1] );
-			for ( ijk[0] = 0 ; ijk[0] < sizeI ; ijk[0]++ ) {
-				gNode_I = Grid_Project( vGrid, ijk );
-				Journal_Printf( stream, "{ " );
-				if ( Mesh_GlobalToDomain( feMesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
-					for ( dof_I = 0 ; dof_I < nDofs ; dof_I++ )
-						Journal_Printf( stream, "%3d ", self->destinationArray[lNode_I][dof_I] );
-				}
-				else {
-					for ( dof_I = 0 ; dof_I < nDofs ; dof_I++ )
-						Journal_Printf( stream, " XX " );
-				}
-				Journal_Printf( stream, "}" );
-			}
-			Journal_Printf( stream, "\n" );
-		}
-		/* Bottom row */
-		Journal_Printf( stream, "    " );
-		for ( ijk[0] = 0 ; ijk[0] < sizeI ; ijk[0]++ ) {
-			Journal_Printf( stream, "    %3d    ", ijk[0] );
-			if ( nDofs == 3 )
-				Journal_Printf( stream, "    " );
-		}
-		Journal_Printf( stream, "\n" );
-	}	
-}
-
-void FeEquationNumber_PrintLocationMatrix( void* feFeEquationNumber, Stream* stream ) {
-   FeEquationNumber* self = (FeEquationNumber*) feFeEquationNumber;
-   FeMesh*		feMesh = self->feMesh;
-   MPI_Comm comm = Comm_GetMPIComm( Mesh_GetCommTopology( feMesh, MT_VERTEX ) );
-   unsigned rank;
-   Element_GlobalIndex gEl_I;
-   unsigned nDims = Mesh_GetDimSize( feMesh );
-   Element_GlobalIndex elementGlobalCount = FeMesh_GetElementGlobalSize( feMesh );
-   unsigned nLocalEls = FeMesh_GetElementLocalSize( feMesh );
-
-   Journal_Printf( stream, "%d: *** Printing location matrix ***\n", rank  );
-
-   MPI_Comm_rank( comm, (int*)&rank );
-	
-   for (gEl_I =0; gEl_I < elementGlobalCount; gEl_I++ ) {
-      Element_LocalIndex lEl_I;
-
-      if ( !Mesh_GlobalToDomain( feMesh, (MeshTopology_Dim)nDims, gEl_I, &lEl_I ) || lEl_I >= nLocalEls ) {
-         Journal_Printf( stream, "\tLM[(g/l el)%2d/XXX]: on another proc\n", gEl_I);
-      }
-      else {
-         Node_LocalIndex numNodesAtElement;
-         Node_LocalIndex elLocalNode_I;
-         unsigned*	incNodes;
-         IArray*		inc;
-
-         inc = IArray_New();
-         FeMesh_GetElementNodes( self->feMesh, lEl_I, inc );
-         numNodesAtElement = IArray_GetSize( inc );
-         incNodes = (unsigned*)IArray_GetPtr( inc );
-
-         Journal_Printf( stream, "\tLM[(g/l el)%2d/%2d][(enodes)0-%d]", gEl_I, lEl_I, numNodesAtElement);	
-         /* print the nodes and dofs */
-         for ( elLocalNode_I = 0; elLocalNode_I < numNodesAtElement; elLocalNode_I++ ) {
-            /* look up processor local node number. */
-            Element_LocalIndex currNode = incNodes[elLocalNode_I == 2 ? 3 : 
-                                                   elLocalNode_I == 3 ? 2 : 
-                                                   elLocalNode_I == 6 ? 7 : 
-                                                   elLocalNode_I == 7 ? 6 : 
-                                                   elLocalNode_I];
-            /* get the number of dofs at current node */
-            Dof_Index currNodeNumDofs = self->dofLayout->dofCounts[ currNode ];
-            Dof_Index nodeLocalDof_I;
-
-            Journal_Printf( stream, "({%2d}", currNode );
-            for( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-               Journal_Printf( stream, "%3d,", self->destinationArray[currNode][nodeLocalDof_I] );
-            }
-            Journal_Printf( stream, "), " );
-         }	
-
-         Journal_Printf( stream, "\n" );
-
-         NewClass_Delete( inc );
-      }
-
-   }
-}
-
-
-#if 0
-void FeEquationNumber_PrintElementLocationMatrix(
-   void*			feEquationNumber,
-   Dof_EquationNumber**	elementLM,
-   Element_LocalIndex	element_lI,
-   Stream*			stream )
-{
-   FeEquationNumber*	self = (FeEquationNumber*)feEquationNumber;
-   Dof_Index		dof_elLocalI;
-   Node_ElementLocalIndex	nodeCountThisEl = self->feMesh->elementNodeCountTbl[element_lI];
-   Node_LocalIndex		node_lI = self->feMesh->elementNodeTbl[element_lI][nodeCountThisEl-1];
-   Dof_Index		dofCountLastNode = self->dofLayout->dofCounts[node_lI];
-   Dof_Index		totalDofsThisElement = 0;
-	
-   totalDofsThisElement = &elementLM[nodeCountThisEl-1][dofCountLastNode-1] - &elementLM[0][0] + 1;
-
-   Journal_DPrintf( stream, "LM[ el %d ], dofs[0-%d] = {", element_lI, totalDofsThisElement );
-
-   for( dof_elLocalI=0; dof_elLocalI < totalDofsThisElement; dof_elLocalI++ ) {
-      Journal_DPrintf( stream, "%d, ", elementLM[0][dof_elLocalI] ); 
-   }
-   Journal_DPrintf( stream, "}\n" );
-}
-
-
-/* Calculates global sum unconstrained dofs */
-void _FeEquationNumber_CalculateGlobalUnconstrainedDofTotal( FeEquationNumber* self ) {
-   int	globalSumUnconstrainedDofs;
-   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
-	
-   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-   MPI_Allreduce( &self->_highestLocalEqNum, &globalSumUnconstrainedDofs, 1, MPI_INT, MPI_MAX, meshDecomp->communicator );
-   self->globalSumUnconstrainedDofs = (unsigned)(globalSumUnconstrainedDofs+1);
-	
-   Journal_DPrintf( self->debug, "Calculated total (across all processors) unconstrained dofs as:%d\n", self->globalSumUnconstrainedDofs  );
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-/* calculate the minimum and maximum parts that my processor is responsible for holding */
-void _FeEquationNumber_CalculateEqNumsDecomposition( FeEquationNumber* self ) {
-   MeshDecomp*		meshDecomp = self->feMesh->layout->decomp;
-   Partition_Index		myRank = meshDecomp->rank;
-   Partition_Index		nProc = meshDecomp->nproc;
-
-   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
-   Stream_IndentBranch( StgFEM_Debug );
-
-   if ( (self->remappingActivated) && ( (self->linkedDofInfo == NULL) || (self->linkedDofInfo->linkedDofSetsCount == 0 ) ) ) {
-      /* If the remapping is activated, and things aren't complicated by periodic BCs,
-         then each processor should hold the Matrix/Vector
-         component corresponding to the lowest local eqNum, to the lowest eqNum of the next
-         processor. This means that _only shared boundary nodes_ will need to be communicated,
-         and the last processor will have no communication. */
-      Journal_DPrintfL( self->debug, 2, "Remapping active and no periodic bcs: using lowest local eqNums as boundaries.\n");
-
-      self->_lowestGlobalEqNums = Memory_Alloc_Array( Dof_EquationNumber, nProc,
-                                                      "FeEquationNumber->_lowestGlobalEqNums" );
-      MPI_Allgather(
-         &self->_lowestLocalEqNum, 1, MPI_INT,
-         self->_lowestGlobalEqNums, 1, MPI_INT,
-         meshDecomp->communicator );
-
-      self->firstOwnedEqNum = self->_lowestLocalEqNum;
-      if (myRank == nProc-1) {
-         self->lastOwnedEqNum = self->_highestLocalEqNum;
-      }
-      else {
-         Node_LocalIndex nextProcLowestEqNum = self->_lowestGlobalEqNums[myRank+1] - 1;
-         if ( (unsigned int)-1 == nextProcLowestEqNum ) {
-            /* Pathological case of next proc having all B.C.s */
-            self->lastOwnedEqNum = self->_highestLocalEqNum;
-         }	
-         else {
-            self->lastOwnedEqNum = nextProcLowestEqNum;
-         }
-      }
-
-      self->localEqNumsOwnedCount = self->lastOwnedEqNum - self->firstOwnedEqNum + 1;	
-   }	
-   else {
-      /* If the remapping isn't activated and the eqNum ordering isn't aligned with the mesh
-         decomposition, or there are periodic BCs, we can't get a clear idea of where the processor boundaries are:
-         therefore just split up the EqNums equally between processors: still should be 
-         fairly good alignment. */
-      Journal_DPrintfL( self->debug, 2, "Remapping inactive and/or periodic bcs used: just dividing eqNums as evenly as possible.\n");
-
-      self->_eqNumsPerProcDivisor = self->globalSumUnconstrainedDofs / nProc;
-      self->_eqNumsRemainder = self->globalSumUnconstrainedDofs % nProc;
-      Journal_DPrintfL( self->debug, 2, "Calculated %d eqNums per proc, with %d remainder\n",
-                        self->_eqNumsPerProcDivisor, self->_eqNumsRemainder );
-      self->_remNotAddedChangeover = (self->_eqNumsPerProcDivisor+1) * self->_eqNumsRemainder;
-
-      self->localEqNumsOwnedCount = self->_eqNumsPerProcDivisor;
-      if ( myRank < self->_eqNumsRemainder ) {
-         self->localEqNumsOwnedCount++;
-      }
-
-      if ( myRank < self->_eqNumsRemainder ) {
-         self->firstOwnedEqNum = myRank * (self->_eqNumsPerProcDivisor+1);
-      }
-      else {
-         self->firstOwnedEqNum = self->_remNotAddedChangeover
-            + (myRank - self->_eqNumsRemainder) * self->_eqNumsPerProcDivisor;
-      }
-      self->lastOwnedEqNum = self->firstOwnedEqNum + self->localEqNumsOwnedCount - 1;
-   }	
-
-   Journal_DPrintfL( self->debug, 1, "Calculated I own %d eqNums, between indices %d to %d\n",
-                     self->localEqNumsOwnedCount, self->firstOwnedEqNum, self->lastOwnedEqNum );
-   Journal_DPrintfL( self->debug, 1, "(Range of eqNums on local mesh segment is %d to %d)\n",
-                     self->_lowestLocalEqNum, self->_highestLocalEqNum );
-
-   Stream_UnIndentBranch( StgFEM_Debug );
-}
-#endif
-
-
-Partition_Index FeEquationNumber_CalculateOwningProcessorOfEqNum( void* feEquationNumber, Dof_EquationNumber eqNum ) {
-   FeEquationNumber* self = (FeEquationNumber*)feEquationNumber;
-   /* Partition_Index ownerProc = (unsigned int)-1; */
-   Comm*	comm = Mesh_GetCommTopology( self->feMesh, MT_VERTEX );
-   MPI_Comm	mpiComm = Comm_GetMPIComm( comm );
-   unsigned	nProcs;
-   unsigned	p_i;
-
-   MPI_Comm_size( mpiComm, (int*)&nProcs );
-   for( p_i = 1; p_i < nProcs; p_i++ ) {
-      if( eqNum < self->_lowestGlobalEqNums[p_i] )
-         break;
-   }
-
-   return p_i - 1;
-
-#if 0
-   if ( (self->remappingActivated) && ( (self->linkedDofInfo == NULL) || (self->linkedDofInfo->linkedDofSetsCount == 0 ) ) ) {
-      MeshDecomp*		meshDecomp = self->feMesh->layout->decomp;
-      Partition_Index		myRank = meshDecomp->rank;
-      Partition_Index		nProc = meshDecomp->nproc;
-
-      /* Expect it to be on the next processor, so try there first */
-      if ( eqNum > self->lastOwnedEqNum ) {
-         ownerProc = myRank + 1;
-         while ( (ownerProc+1) < nProc ) {
-            if ( eqNum >= self->_lowestGlobalEqNums[ownerProc+1] ) {
-               ownerProc++;
-            }	
-            else {
-               break;
-            }	
-         }
-      }
-      /* otherwise count back from current */
-      else {
-         ownerProc = myRank;
-         while ( ownerProc > 0 ) {
-            if ( eqNum < self->_lowestGlobalEqNums[ownerProc] ) {
-               ownerProc--;
-            }
-            else {
-               break;
-            }	
-         }
-      }
-   }
-   else {
-      if ( eqNum < self->_remNotAddedChangeover ) {
-         ownerProc = eqNum / (self->_eqNumsPerProcDivisor+1);
-      }
-      else {
-         ownerProc = self->_eqNumsRemainder + (eqNum - self->_remNotAddedChangeover) / self->_eqNumsPerProcDivisor;
-      }
-   }
-}
-
-return ownerProc;
-#endif
-}	
-
-
-#if 0
-void FeEquationNumber_Create_CritPointInfo_MPI_Datatype( void ) {
-#define CRIT_POINT_INFO_NBLOCKS 2
-   MPI_Aint indexExtent = 0;
-   MPI_Datatype critPointInfoTypes[CRIT_POINT_INFO_NBLOCKS] = {MPI_UNSIGNED, MPI_INT };
-   MPI_Aint critPointInfoBlockDisplacements[CRIT_POINT_INFO_NBLOCKS];
-   int critPointInfoBlockLengths[CRIT_POINT_INFO_NBLOCKS] = { 1, 1 };
-
-   MPI_Type_extent(MPI_UNSIGNED, &indexExtent);
-   critPointInfoBlockDisplacements[0] = 0;
-   critPointInfoBlockDisplacements[1] = indexExtent;
-
-   MPI_Type_struct( CRIT_POINT_INFO_NBLOCKS, critPointInfoBlockLengths, critPointInfoBlockDisplacements,
-                    critPointInfoTypes, &MPI_critPointInfoType );
-	
-   MPI_Type_commit( &MPI_critPointInfoType );
-}
-#endif
-
-
-void FeEquationNumber_BuildWithTopology( FeEquationNumber* self ) {
-   Stream*		stream;
-   double		startTime, endTime, time, tmin, tmax;
-   FeMesh*		feMesh;
-   Sync*		sync;
-   Comm*		comm;
-   MPI_Comm		mpiComm;
-   unsigned		rank, nProcs;
-   unsigned		nDims;
-   unsigned		nDomainNodes;
-   unsigned		nLocalNodes;
-   unsigned*		nNodalDofs;
-   unsigned		nElNodes, *elNodes;
-   int**		dstArray;
-   int			*nLocMatDofs, ***locMat;
-   unsigned		varInd;
-   unsigned		curEqNum;
-   unsigned		base;
-   unsigned		subTotal;
-   MPI_Status		status;
-   unsigned		maxDofs;
-   unsigned*		tuples;
-   LinkedDofInfo*	links;
-   unsigned		highest;
-   IArray*		inc;
-   unsigned             e_i, n_i, dof_i, s_i;
-   int			ii;
-
-   assert( self );
-
-   inc = IArray_New();
-
-   stream = Journal_Register( Info_Type, (Name)self->type  );
-   Stream_SetPrintingRank( stream, 0 );
-
-   Journal_RPrintf( stream, "FeEquationNumber: '%s'\n", self->name );
-   Stream_Indent( stream );
-   Journal_RPrintf( stream, "Generating equation numbers...\n" );
-   Stream_Indent( stream );
-   if( self->removeBCs )
-      Journal_RPrintf( stream, "BCs set to be removed.\n" );
-   else
-      Journal_RPrintf( stream, "BCs will not be removed.\n" );
-
-   startTime = MPI_Wtime();
-
-   /* Shortcuts. */
-   feMesh = self->feMesh;
-   comm = Mesh_GetCommTopology( feMesh, MT_VERTEX );
-   mpiComm = Comm_GetMPIComm( comm );
-   MPI_Comm_size( mpiComm, (int*)&nProcs );
-   MPI_Comm_rank( mpiComm, (int*)&rank );
-   nDims = Mesh_GetDimSize( feMesh );
-   nDomainNodes = FeMesh_GetNodeDomainSize( feMesh );
-   self->nDomainEls = FeMesh_GetElementDomainSize( feMesh );
-   nLocalNodes = FeMesh_GetNodeLocalSize( feMesh );
-   nNodalDofs = self->dofLayout->dofCounts;
-   links = self->linkedDofInfo;
-
-   /* Allocate for destination array. */
-   dstArray = Memory_Alloc_2DComplex( int, nDomainNodes, nNodalDofs, 
-                                      "FeEquationNumber::destinationArray" );
-
-   /* If needed, allocate for linked equation numbers. */
-   if( links ) {
-      unsigned	s_i;
-
-      links->eqNumsOfLinkedDofs = ReallocArray( links->eqNumsOfLinkedDofs, int, links->linkedDofSetsCount );
-      for( s_i = 0; s_i < links->linkedDofSetsCount; s_i++ )
-         links->eqNumsOfLinkedDofs[s_i] = -1;
-   }
-
-   /* Allocate for the location matrix. */
-   nLocMatDofs = NULL;
-   locMat = AllocArray( int**, self->nDomainEls );
-   for( e_i = 0; e_i < self->nDomainEls; e_i++ ) {
-      FeMesh_GetElementNodes( feMesh, e_i, inc );
-      nElNodes = IArray_GetSize( inc );
-      elNodes = (unsigned*)IArray_GetPtr( inc );
-      nLocMatDofs = ReallocArray( nLocMatDofs, int, nElNodes );
-      for( n_i = 0; n_i < nElNodes; n_i++ )
-         nLocMatDofs[n_i] = nNodalDofs[elNodes[n_i]];
-      locMat[e_i] = AllocComplex2D( int, nElNodes, (Index*)nLocMatDofs );
-   }
-   FreeArray( nLocMatDofs );
-
-   /* Build initial destination array and store max dofs. */
-   curEqNum = 0;
-   maxDofs = 0;
-   for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
-      if( nNodalDofs[n_i] > maxDofs )
-         maxDofs = nNodalDofs[n_i];
-
-      for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
-         varInd = self->dofLayout->varIndices[n_i][dof_i];
-         if( !self->bcs || !VariableCondition_IsCondition( self->bcs, n_i, varInd ) || 
-             !self->removeBCs )
-         {
-            if( links && links->linkedDofTbl[n_i][dof_i] != -1 ) {
-               if( rank > 0 ) {
-                  dstArray[n_i][dof_i] = -2;
-                  continue;
-               }
-               if( links->eqNumsOfLinkedDofs[links->linkedDofTbl[n_i][dof_i]] == -1 )
-                  links->eqNumsOfLinkedDofs[links->linkedDofTbl[n_i][dof_i]] = curEqNum++;
-               dstArray[n_i][dof_i] = links->eqNumsOfLinkedDofs[links->linkedDofTbl[n_i][dof_i]];
-            }
-            else
-               dstArray[n_i][dof_i] = curEqNum++;
-         }
-         else
-            dstArray[n_i][dof_i] = -1;
-      }
-   }
-
-   /* Order the equation numbers based on processor rank; cascade counts forward. */
-   base = 0;
-   if( rank > 0 )
-      MPI_Recv( &base, 1, MPI_UNSIGNED, rank - 1, 6669, mpiComm, &status );
-   subTotal = base + curEqNum;
-   if( rank < nProcs - 1 )
-      MPI_Send( &subTotal, 1, MPI_UNSIGNED, rank + 1, 6669, mpiComm );
-
-   if( links ) {
-      /* Reduce to find lowest linked DOFs. */
-      for( s_i = 0; s_i < links->linkedDofSetsCount; s_i++ ) {
-         if( links->eqNumsOfLinkedDofs[s_i] != -1 )
-            links->eqNumsOfLinkedDofs[s_i] += base;
-/*
-  MPI_Allreduce( links->eqNumsOfLinkedDofs + s_i, &lowest, 1, MPI_UNSIGNED, MPI_MAX, mpiComm );
-*/
-         MPI_Allreduce( links->eqNumsOfLinkedDofs + s_i, &highest, 1, MPI_INT, MPI_MAX, mpiComm );
-/*
-  assert( (lowest == (unsigned)-1) ? lowest == highest : 1 );
-*/
-         links->eqNumsOfLinkedDofs[s_i] = highest;
-      }
-   }
-
-   /* Modify existing destination array and dump to a tuple array. */
-   tuples = AllocArray( unsigned, nDomainNodes * maxDofs );
-   for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
-      for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
-         varInd = self->dofLayout->varIndices[n_i][dof_i];
-         if( !self->bcs || !VariableCondition_IsCondition( self->bcs, n_i, varInd ) || 
-             !self->removeBCs )
-         {
-            if( links && links->linkedDofTbl[n_i][dof_i] != -1 ) {
-               highest = links->eqNumsOfLinkedDofs[links->linkedDofTbl[n_i][dof_i]];
-               dstArray[n_i][dof_i] = highest;
-            }
-            else
-               dstArray[n_i][dof_i] += base;
-         }
-         tuples[n_i * maxDofs + dof_i] = dstArray[n_i][dof_i];
-      }
-   }
-
-   /* Update all other procs. */
-   sync = Mesh_GetSync( feMesh, MT_VERTEX );
-   Sync_SyncArray( sync, tuples, maxDofs * sizeof(unsigned), 
-                   tuples + nLocalNodes * maxDofs, maxDofs * sizeof(unsigned), 
-                   maxDofs * sizeof(unsigned) );
-
-   /* Update destination array's domain indices. */
-   for( n_i = nLocalNodes; n_i < nDomainNodes; n_i++ ) {
-      for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
-         varInd = self->dofLayout->varIndices[n_i][dof_i];
-         if( !self->bcs || !VariableCondition_IsCondition( self->bcs, n_i, varInd ) || 
-             !self->removeBCs )
-         {
-            dstArray[n_i][dof_i] = tuples[n_i * maxDofs + dof_i];
-         }
-         else
-            dstArray[n_i][dof_i] = -1;
-      }
-   }
-
-   /* Destroy tuple array. */
-   FreeArray( tuples );
-
-   /* Build location matrix. */
-   for( e_i = 0; e_i < self->nDomainEls; e_i++ ) {
-      FeMesh_GetElementNodes( feMesh, e_i, inc );
-      nElNodes = IArray_GetSize( inc );
-      elNodes = (unsigned*)IArray_GetPtr( inc );
-      for( n_i = 0; n_i < nElNodes; n_i++ ) {
-         for( dof_i = 0; dof_i < nNodalDofs[elNodes[n_i]]; dof_i++ )
-            locMat[e_i][n_i][dof_i] = dstArray[elNodes[n_i]][dof_i];
-      }
-   }
-
-   /* Store stuff on class. */
-   self->destinationArray = dstArray;
-   self->locationMatrix = locMat;
-   self->locationMatrixBuilt = True;
-   self->remappingActivated = False;
-   self->localEqNumsOwnedCount = curEqNum;
-   self->firstOwnedEqNum = base;
-   self->lastOwnedEqNum = subTotal - 1;
-   self->_lowestLocalEqNum = self->firstOwnedEqNum;
-
-   /* Setup owned mapping. */
-   STree_Clear( self->ownedMap );
-   for( ii = self->firstOwnedEqNum; ii <= self->lastOwnedEqNum; ii++ ) {
-      int val = ii - self->firstOwnedEqNum;
-      STreeMap_Insert( self->ownedMap, &ii, &val );
-   }
-
-   /* Bcast global sum from highest rank. */
-   if( rank == nProcs - 1 )
-      self->globalSumUnconstrainedDofs = self->lastOwnedEqNum + 1;
-   MPI_Bcast( &self->globalSumUnconstrainedDofs, 1, MPI_UNSIGNED, nProcs - 1, mpiComm );
-
-   /* Construct lowest global equation number list. */
-   self->_lowestGlobalEqNums = AllocArray( int, nProcs );
-   MPI_Allgather( &self->firstOwnedEqNum, 1, MPI_UNSIGNED, self->_lowestGlobalEqNums, 1, MPI_UNSIGNED, mpiComm );
-
-   endTime = MPI_Wtime();
-
-   Journal_RPrintf( stream, "Assigned %d global equation numbers.\n", self->globalSumUnconstrainedDofs );
-   Journal_Printf( stream, "[%u] Assigned %d local equation numbers, within range %d to %d.\n", 
-                   rank, self->lastOwnedEqNum - self->firstOwnedEqNum + 1, self->firstOwnedEqNum, self->lastOwnedEqNum + 1 );
-   Stream_UnIndent( stream );
-
-   time = endTime - startTime;
-   MPI_Reduce( &time, &tmin, 1, MPI_DOUBLE, MPI_MIN, 0, mpiComm );
-   MPI_Reduce( &time, &tmax, 1, MPI_DOUBLE, MPI_MAX, 0, mpiComm );
-   Journal_RPrintf( stream, "... Completed in %g [min] / %g [max] seconds.\n", tmin, tmax );
-   Stream_UnIndent( stream );
-
-   NewClass_Delete( inc );
-}
-
-#if 0
-void FeEquationNumber_BuildVariableIndices( FeEquationNumber* self, int* nInds, int** inds, int* maxDofs ) {
-   int maxDofs;
-   ISet indSetObj, *indSet = &indSetObj;
-
-   *maxDofs = 0;
-   for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
-      if( nNodalDofs[n_i] > *maxDofs )
-         *maxDofs = nNodalDofs[n_i];
-   }
-
-   ISet_Construct( indSet );
-   ISet_SetMaxSize( indSet, *maxDofs );
-   for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
-      for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
-         varInd = self->dofLayout->varIndices[n_i][dof_i];
-         ISet_TryInsert( indSet, varInd );
-      }
-   }
-
-   *nInds = ISet_GetSize( indSet );
-   *inds = MemArray( int, *nInds, FeEquationNumber_Type );
-   ISet_GetArray( indSet, NULL, inds );
-   ISet_Destruct( indSet );
-}
-#endif
-
-
-#if 0
-void FeEquationNumber_Invert( void* feEqNum, int equation, unsigned* node, unsigned* dof ) {
-   FeEquationNumber*	self = (FeEquationNumber*)feEqNum;
-
-   assert( self && Stg_CheckType( self, FeEquationNumber ) );
-   assert( equation - self->firstOwnedEqNum < self->localEqNumsOwnedCount );
-   assert( node );
-   assert( dof );
-
-   eq = equation - self->firstOwnedEqNum;
-   *node = self->eqToNode[eq];
-   *dof = self->eqToDof[eq];
-}
-
-Bool FeEquationNumber_IsKnown( void* feEqNum, int equation ) {
-   FeEquationNumber*	self = (FeEquationNumber*)feEqNum;
-   unsigned		node, dof;
-   unsigned		varInd;
-
-   assert( self && Stg_CheckType( self, FeEquationNumber ) );
-
-   if( !self->bcs ) return False;
-   FeEquationNumber_Invert( self, equation, &node, &dof );
-
-   assert( self->dofLayout );
-   assert( self->dofLayout->varIndices );
-   assert( self->dofLayout->varIndices[node] );
-   varInd = self->dofLayout->varIndices[node][dof];
-   return VariableCondition_IsCondition( self->bcs, n_i, varInd );
-}
-#endif
-
-
-int GenerateEquationNumbering(
-		int NX, int NY, int NZ,
-		int nlocal, int g_node_id[],
-		int dof, int nglobal,
-		PetscTruth periodic_x, PetscTruth periodic_y, PetscTruth periodic_z,
-		int npx, int npy, int npz,
-		int periodic_x_gnode_id[], int periodic_y_gnode_id[], int periodic_z_gnode_id[],
-		int eqnums[], int *neqnums );
-
-void FeEquationNumber_BuildWithDave( FeEquationNumber* self ) {
-   int nLocals, *locals;
-   Grid *vGrid;
-   int varInd;
-   int nEqNums, **dstArray;
-   IArray *inc;
-   int nDofs;
-   int *periodic;
-   int ***locMat;
-   int nDims;
-   int *elNodes;
-   Comm *comm;
-   MPI_Comm mpiComm;
-   int nRanks, rank;
-   Sync *sync;
-   Bool isCond;
-   int nPeriodicInds[3];
-   int *periodicInds[3];
-   int inds[3];
-   Bool usePeriodic;
-   int *tmpArray, nLocalEqNums;
-   int lastOwnedEqNum, ind;
-   STree *doneSet;
-   int ii, jj, kk;
-
-   comm = Mesh_GetCommTopology( self->feMesh, (MeshTopology_Dim)0 );
-   mpiComm = Comm_GetMPIComm( comm );
-   MPI_Comm_size( mpiComm, &nRanks );
-   MPI_Comm_rank( mpiComm, &rank );
-
-   /* Setup an array containing global indices of all locally owned nodes. */
-   nLocals = Mesh_GetLocalSize( self->feMesh, (MeshTopology_Dim)0 );
-   locals = AllocArray( int, nLocals );
-   for( ii = 0; ii < nLocals; ii++ )
-      locals[ii] = Mesh_DomainToGlobal( self->feMesh, (MeshTopology_Dim)0, ii );
-
-   /* Allocate for destination array. */
-   nDofs = self->dofLayout->dofCounts[0];
-   dstArray = AllocArray2D( int, Mesh_GetDomainSize( self->feMesh, (MeshTopology_Dim)0 ), nDofs );
-
-   /* Get the vertex grid extension and any periodicity. */
-   nDims = Mesh_GetDimSize( self->feMesh );
-   vGrid = *Mesh_GetExtension( self->feMesh, Grid**, "vertexGrid" );
-   periodic = Mesh_GetExtension( self->feMesh, int*, "periodic" );
-
-   /* Fill destination array with initial values, setting dirichlet BCs as we go. */
-   for( ii = 0; ii < nLocals; ii++ ) {
-     Grid_Lift( vGrid, locals[ii], (unsigned*)inds );
-      usePeriodic = False;
-      for( jj = 0; jj < nDims; jj++ ) {
-        if( periodic[jj] && (inds[jj] == 0 || inds[jj] == (int)(vGrid->sizes[jj] - 1)) ) {
-            usePeriodic = True;
-	    break;
-	 }
-      }
-      for( jj = 0; jj < nDofs; jj++ ) {
-         varInd = self->dofLayout->varIndices[ii][jj];
-	 if( self->bcs )
-	    isCond = VariableCondition_IsCondition( self->bcs, ii, varInd );
-	 else
-	    isCond = False;
-         if( isCond && self->removeBCs )
-            dstArray[ii][jj] = -1;
-         else
-            dstArray[ii][jj] = 0;
-      }
-   }
-
-   /* Generate opposing indices for periodicity. */
-   for( ii = 0; ii < nDims; ii++ ) {
-      nPeriodicInds[ii] = 0;
-      periodicInds[ii] = NULL;
-      if( periodic[ii] ) {
-	 periodicInds[ii] = AllocArray( int, nLocals );
-	 for( jj = 0; jj < nLocals; jj++ ) {
-           Grid_Lift( vGrid, locals[jj], (unsigned*)inds );
-           if( inds[ii] != (int)(vGrid->sizes[ii] - 1) ) continue;
-/*
-            for( kk = 0; kk < nDofs; kk++ )
-               if( dstArray[jj][kk] == -1 ) break;
-            if( kk < nDofs ) continue;
-*/
-            periodicInds[ii][nPeriodicInds[ii]++] = locals[jj];
-	 }
-      }
-   }
-
-   /* Call Dave's equation number generation routine. */
-   if( nDims == 2 ) {
-      GenerateEquationNumbering( vGrid->sizes[0], vGrid->sizes[1], 1,
-				 nLocals, locals,
-				 nDofs, Mesh_GetGlobalSize( self->feMesh, (MeshTopology_Dim)0 ),
-				 (PetscTruth)periodic[0], (PetscTruth)periodic[1], (PetscTruth)False,
-				 nPeriodicInds[0], nPeriodicInds[1], 0,
-				 periodicInds[0], periodicInds[1], NULL,
-				 dstArray[0], &nEqNums );
-   }
-   else {
-      GenerateEquationNumbering( vGrid->sizes[0], vGrid->sizes[1], vGrid->sizes[2],
-				 nLocals, locals,
-				 nDofs, Mesh_GetGlobalSize( self->feMesh, (MeshTopology_Dim)0 ),
-				 (PetscTruth)periodic[0], (PetscTruth)periodic[1], (PetscTruth)periodic[2],
-				 nPeriodicInds[0], nPeriodicInds[1], nPeriodicInds[2],
-				 periodicInds[0], periodicInds[1], periodicInds[2],
-				 dstArray[0], &nEqNums );
-   }
-
-   /* Free periodic arrays. */
-   for( ii = 0; ii < nDims; ii++ ) {
-      if( periodicInds[ii] )
-	 FreeArray( periodicInds[ii] );
-   }
-
-   /* Setup owned mapping part 1. */
-   STree_Clear( self->ownedMap );
-   for( ii = 0; ii < nLocals; ii++ ) {
-     Grid_Lift( vGrid, locals[ii], (unsigned*)inds );
-      for( jj = 0; jj < nDims; jj++ ) {
-        if( periodic[jj] && inds[jj] == (int)(vGrid->sizes[jj] - 1) ) {
-            inds[jj] = 0;
-            ind = Grid_Project( vGrid, (unsigned*)inds );
-            if( !FeMesh_NodeGlobalToDomain( self->feMesh, ind, (unsigned*)(&ind) ) )
-               break;
-         }
-      }
-      if( jj < nDims ) continue;
-      for( jj = 0; jj < nDofs; jj++ ) {
-	 if( dstArray[ii][jj] == -1 || STreeMap_HasKey( self->ownedMap, dstArray[ii] + jj ) )
-            continue;
-	 STreeMap_Insert( self->ownedMap, dstArray[ii] + jj, &ii );
-      }
-   }
-
-   /* Setup owned mapping. */
-   tmpArray = AllocArray( int, nLocals * nDofs );
-   memcpy( tmpArray, dstArray[0], nLocals * nDofs * sizeof(int) );
-   qsort( tmpArray, nLocals * nDofs, sizeof(int), stgCmpInt );
-   doneSet = STree_New();
-   STree_SetItemSize( doneSet, sizeof(int) );
-   STree_SetIntCallbacks( doneSet );
-   for( nLocalEqNums = 0, ii = 0; ii < nLocals * nDofs; ii++ ) {
-      if( tmpArray[ii] != -1 &&
-          STreeMap_HasKey( self->ownedMap, tmpArray + ii ) &&
-          !STree_Has( doneSet, tmpArray + ii ) )
-      {
-	 if( !nLocalEqNums )
-	    self->_lowestLocalEqNum = tmpArray[ii];
-	 *(int*)STreeMap_Map( self->ownedMap, tmpArray + ii ) = nLocalEqNums;
-         STree_Insert( doneSet, tmpArray + ii );
-	 nLocalEqNums++;
-      }
-   }
-   lastOwnedEqNum = -1; /* Don't need this anymore. */
-   FreeArray( tmpArray );
-   NewClass_Delete( doneSet );
-
-   /* Transfer remote equation numbers. */
-   sync = Mesh_GetSync( self->feMesh, (MeshTopology_Dim)0 );
-   Sync_SyncArray( sync, dstArray[0], nDofs * sizeof(int),
-                   dstArray[0] + nLocals * nDofs, nDofs * sizeof(int),
-                   nDofs * sizeof(int) );
-
-   /* Allocate for location matrix. */
-   /* first store nDomainEls for usage during destroy */
-   self->nDomainEls = Mesh_GetDomainSize( self->feMesh, (MeshTopology_Dim)nDims );
-   locMat = AllocArray( int**, self->nDomainEls );
-   for( ii = 0; ii < (int)(self->nDomainEls); ii++ )
-      locMat[ii] = AllocArray2D( int, FeMesh_GetElementNodeSize( self->feMesh, 0 ), nDofs );
-
-   /* Fill in location matrix. */
-   inc = IArray_New();
-   for( ii = 0; ii < (int)Mesh_GetDomainSize( self->feMesh, (MeshTopology_Dim)nDims ); ii++ ) {
-      FeMesh_GetElementNodes( self->feMesh, ii, inc );
-      elNodes = IArray_GetPtr( inc );
-      for( jj = 0; jj < (int)FeMesh_GetElementNodeSize( self->feMesh, 0 ); jj++ ) {
-         for( kk = 0; kk < nDofs; kk++ )
-            locMat[ii][jj][kk] = dstArray[elNodes[jj]][kk];
-      }
-   }
-   NewClass_Delete( inc );
-
-   /* Fill in our other weird values. */
-   self->destinationArray = dstArray;
-   self->locationMatrix = locMat;
-   self->locationMatrixBuilt = True;
-   self->remappingActivated = False;
-   self->localEqNumsOwnedCount = nLocalEqNums;
-
-   /* Bcast global sum from highest rank. */
-   self->globalSumUnconstrainedDofs = nEqNums;
-
-   /* Construct lowest global equation number list. */
-   self->_lowestGlobalEqNums = AllocArray( int, nRanks );
-   MPI_Allgather( &self->_lowestLocalEqNum, 1, MPI_UNSIGNED, 
-                  self->_lowestGlobalEqNums, 1, MPI_UNSIGNED,
-                  mpiComm );
-
-   FreeArray( locals );
-
-   /* 
-   printf( "%d: localEqNumsOwned = %d\n", rank, self->localEqNumsOwnedCount );
-   printf( "%d: globalSumUnconstrainedDofs = %d\n", rank, self->globalSumUnconstrainedDofs );
-   */
-}
-
-
-
-
-/*
-
-Input:
-  nlocal - number of locally ownded nodes
-  g_node_id - global indices of nodes owned locally. Size nlocal
-  dof - degrees of freedom per node
-  nglobal - number of global nodes
-  npx - number of consider to be periodic in x (local to this proc)
-  npy - number of consider to be periodic in y (local to this proc)
-  periodic_x_gnode_id - global indices of nodes (on this proc) which are on right hand side boundary
-  periodic_y_gnode_id - global indices of nodes (on this proc) which are on top boundary
-  eqnums - contains any dirichlet boundary conditions. Size nlocal*dof
-
-Output;
-  eqnums - contains full list of eqnums
-
-Assumptions: 
-- Ordering eqnums[] = { (node_0,[dof_0,dof_1,..,dof_x]), (node_1,[dof_0,dof_1,..,dof_x]), ... }
-- Any dirichlet set along a boundary deemed to be periodic will be clobbered.
-- Processors may have duplicate nodes in the g_node_id[] list.
-- A number in the corner is considered part of both boundaries (horiz and vert)
-- If npx is not 0, then periodicity is assumed in x
-- If npy is not 0, then periodicity is assumed in y
-- Dofs constrained to be dirichlet must be marked with a negative number.
-- Dofs are NOT split across processors.
-- We can define a logical i,j,k ordering to uniquely identify nodes.
-
-*/
-
-PetscErrorCode _VecScatterBeginEnd( VecScatter vscat, Vec FROM, Vec TO, InsertMode addv,ScatterMode mode )
-{
-#if( (PETSC_VERSION_MAJOR==2) && (PETSC_VERSION_MINOR==3) && (PETSC_VERSION_SUBMINOR==2) )
-	// 2.3.2 ordering of args
-	VecScatterBegin( FROM, TO, addv, mode, vscat );
-	VecScatterEnd( FROM, TO, addv, mode, vscat );
-#else
-	// 2.3.3 or 3.0.0
-	VecScatterBegin( vscat, FROM, TO, addv, mode );
-	VecScatterEnd( vscat, FROM, TO, addv, mode );
-#endif
-	
-	PetscFunctionReturn(0);
-}
-
-int GenerateEquationNumbering(
-		int NX, int NY, int NZ,
-		int nlocal, int g_node_id[],
-		int dof, int nglobal,
-		PetscTruth periodic_x, PetscTruth periodic_y, PetscTruth periodic_z,
-		int npx, int npy, int npz,
-		int periodic_x_gnode_id[], int periodic_y_gnode_id[], int periodic_z_gnode_id[],
-		int eqnums[], int *neqnums )
-{
-	PetscErrorCode ierr;
-	PetscInt periodic_mask;
-	Vec global_eqnum, g_ownership;
-	PetscInt i;
-	PetscMPIInt rank;        /* processor rank */
-	PetscMPIInt size;        /* size of communicator */
-	Vec local_ownership, local_eqnum;
-	PetscInt *_g_node_id;
-	IS is_gnode, is_eqnum;
-	VecScatter vscat_ownership, vscat_eqnum;
-	PetscScalar *_local_ownership, *_local_eqnum;
-	PetscInt local_eqnum_count,global_eqnum_count;
-	PetscScalar val[10];
-	PetscInt d,idx[10];
-	PetscInt *to_fetch,cnt,number_to_fetch;
-	PetscInt eq_cnt;
-	Vec offset_list;
-	VecScatter vscat_offset;
-	Vec seq_offset_list;
-	PetscInt offset, inc;
-	
-	PetscInt spanx,spany,spanz,total;
-	PetscInt loc;
-	PetscReal max;
-	PetscInt n_inserts;
-	
-	
-	ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
-	ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
-	
-	if( dof>=10 ) {
-		SETERRQ(PETSC_ERR_SUP, "Max allowable degrees of freedom per node = 10. Change static size" );
-	}
-	
-	
-	/* 
-	Claim locally owned nodes. Duplicate nodes on the interior will be resolved by the processor
-	which inserts last.
-	*/
-	VecCreate( PETSC_COMM_WORLD, &g_ownership );
-	VecSetSizes( g_ownership, PETSC_DECIDE, nglobal );
-	VecSetFromOptions( g_ownership );
-	
-	for( i=0; i<nlocal; i++ ) {
-		VecSetValue( g_ownership, g_node_id[i], rank, INSERT_VALUES );
-	}
-	VecAssemblyBegin(g_ownership);
-	VecAssemblyEnd(g_ownership);
-	
-	
-	/* Mask out the periodic boundaries. */
-	periodic_mask = -6699.0;
-	if (periodic_x_gnode_id!=NULL) {
-		for( i=0; i<npx; i++ ) {
-			VecSetValue( g_ownership, periodic_x_gnode_id[i], periodic_mask, INSERT_VALUES );
-		}
-	}
-	if (periodic_y_gnode_id!=NULL) {
-		for( i=0; i<npy; i++ ) {
-			VecSetValue( g_ownership, periodic_y_gnode_id[i], periodic_mask, INSERT_VALUES );
-		}
-	}
-	if (periodic_z_gnode_id!=NULL) {
-		for( i=0; i<npz; i++ ) {
-			VecSetValue( g_ownership, periodic_z_gnode_id[i], periodic_mask, INSERT_VALUES );
-		}
-	}
-	VecAssemblyBegin(g_ownership);
-	VecAssemblyEnd(g_ownership);
-	
-	/*
-	PetscPrintf(PETSC_COMM_WORLD, "g_ownership \n");
-	VecView( g_ownership, PETSC_VIEWER_STDOUT_WORLD );
-	*/
-	
-	/* Get all locally owned nodes */
-	VecCreate( PETSC_COMM_SELF, &local_ownership );
-	VecSetSizes( local_ownership, PETSC_DECIDE, nlocal );
-	VecSetFromOptions( local_ownership );
-	
-	PetscMalloc( sizeof(PetscInt)*nlocal, &_g_node_id);
-	for( i=0; i<nlocal; i++ ) {
-		_g_node_id[i] = g_node_id[i]; 
-	}
-	ISCreateGeneralWithArray( PETSC_COMM_WORLD, nlocal, _g_node_id, &is_gnode );
-	VecScatterCreate( g_ownership, is_gnode, local_ownership, PETSC_NULL, &vscat_ownership );
-	
-	
-	/* assign unique equation numbers */
-	VecSet( local_ownership, -6699 );
-	_VecScatterBeginEnd( vscat_ownership, g_ownership, local_ownership, INSERT_VALUES, SCATTER_FORWARD );
-	
-	
-	/* Count instances of rank in the local_ownership vector */
-	VecGetArray( local_ownership, &_local_ownership );
-	local_eqnum_count = 0;
-	for( i=0; i<nlocal; i++ ) {
-		if( ((PetscInt)_local_ownership[i]) == rank ) {
-			local_eqnum_count++;
-		}
-	}
-	
-	MPI_Allreduce( &local_eqnum_count, &global_eqnum_count, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD );
-	/* PetscPrintf( PETSC_COMM_SELF, 
-	    "[%d] number of local,global equations (without dofs) %d,%d \n", rank, local_eqnum_count, global_eqnum_count ); */
-	/* check */
-	spanx = NX;
-	spany = NY;
-	spanz = NZ;
-	if( periodic_x==PETSC_TRUE ) {
-		spanx--;
-	}
-	if( periodic_y==PETSC_TRUE ) {
-		spany--;
-	}
-	if( periodic_z==PETSC_TRUE ) {
-		spanz--;
-	}
-	total = spanx*spany*spanz;
-	if( total!=global_eqnum_count ) {
-		SETERRQ(PETSC_ERR_SUP, "Something stinks. Computed global size for nodes does not match expected" );
-	}
-	
-	
-	
-	VecCreate( PETSC_COMM_WORLD, &global_eqnum );
-	VecSetSizes( global_eqnum, PETSC_DECIDE, nglobal*dof );
-	VecSetFromOptions( global_eqnum );
-	VecSet( global_eqnum, 0.0 );
-	
-	/* Load existing eqnums in */
-	for( i=0; i<nlocal; i++ ) {
-		n_inserts = 0;
-		for( d=0; d<dof; d++ ) {
-/*
-			idx[d] = -(g_node_id[i]*dof + d);
-			val[d] = 0.0;
-*/
-			if( eqnums[ i*dof + d ] < 0.0 ) {
-				idx[n_inserts] = g_node_id[i]*dof + d;
-				val[n_inserts] = eqnums[ i*dof + d ];
-				n_inserts++;
-			}
-		}
-		/* only insert dirichlet bc's */
-		VecSetValues( global_eqnum, n_inserts, idx, val, INSERT_VALUES );
-	}
-	VecAssemblyBegin(global_eqnum);
-	VecAssemblyEnd(global_eqnum);
-	
-	
-	
-	
-	
-	/* Generate list of eqnums to get */
-	PetscMalloc( sizeof(PetscInt)*nlocal*dof, &to_fetch );
-	cnt = 0;
-	for( i=0; i<nlocal; i++ ) {
-		if( _local_ownership[i]==rank ) {
-			for( d=0; d<dof; d++ ) {
-				to_fetch[cnt] = g_node_id[i]*dof + d;
-				cnt++;
-			}
-		}
-	}
-	number_to_fetch = cnt;
-	
-	
-	VecCreate( PETSC_COMM_SELF, &local_eqnum );
-	VecSetSizes( local_eqnum, PETSC_DECIDE, number_to_fetch);
-	VecSetFromOptions( local_eqnum );
-	
-	ISCreateGeneralWithArray( PETSC_COMM_SELF, number_to_fetch, to_fetch, &is_eqnum );
-	VecScatterCreate( global_eqnum, is_eqnum, local_eqnum, PETSC_NULL, &vscat_eqnum );
-	
-	VecSet( local_eqnum, -6699 );
-	_VecScatterBeginEnd( vscat_eqnum, global_eqnum, local_eqnum, INSERT_VALUES, SCATTER_FORWARD );
-	
-	
-	/* compute offset */
-	/* count how many entries there are */
-	VecGetArray( local_eqnum, &_local_eqnum );
-	eq_cnt = 0;
-	for( i=0; i<number_to_fetch; i++ ) {
-		if( (PetscInt)_local_eqnum[i]==0 ) {
-			eq_cnt++;
-		}
-	}
-	VecRestoreArray( local_eqnum, &_local_eqnum );
-	
-	VecCreate( PETSC_COMM_WORLD, &offset_list );
-	VecSetSizes( offset_list, PETSC_DECIDE, (size+1) );
-	VecSetFromOptions( offset_list );
-	for( i=rank; i<size; i++ ) {
-		VecSetValue( offset_list, i+1, eq_cnt, ADD_VALUES );
-	}
-	VecAssemblyBegin(offset_list);
-	VecAssemblyEnd(offset_list);
-	/*
-	PetscPrintf(PETSC_COMM_WORLD, "offset_list \n");
-	VecView( offset_list, PETSC_VIEWER_STDOUT_WORLD );
-	*/
-	
-	VecScatterCreateToAll(offset_list,&vscat_offset,&seq_offset_list);
-	_VecScatterBeginEnd( vscat_offset, offset_list, seq_offset_list, INSERT_VALUES, SCATTER_FORWARD );
-	
-	{
-		PetscScalar *_seq_offset_list;
-		
-		VecGetArray( seq_offset_list, &_seq_offset_list );
-		offset = _seq_offset_list[ rank ];
-		VecRestoreArray( seq_offset_list, &_seq_offset_list );
-	}
-	VecScatterDestroy(vscat_offset);
-	VecDestroy(offset_list);
-	VecDestroy(seq_offset_list);
-	
-	/* PetscPrintf( PETSC_COMM_SELF, "[%d]: offset = %d \n", rank, offset ); */
-	
-	
-	VecGetArray( local_eqnum, &_local_eqnum );
-	inc = 0;
-	for( i=0; i<number_to_fetch; i++ ) {
-		if( (PetscInt)_local_eqnum[i]==0 ) {
-			_local_eqnum[i] = offset+inc;
-			inc++;
-		}
-	}
-	VecRestoreArray( local_eqnum, &_local_eqnum );
-	
-	_VecScatterBeginEnd( vscat_eqnum, local_eqnum, global_eqnum, INSERT_VALUES, SCATTER_REVERSE );
-	/*
-	PetscPrintf(PETSC_COMM_WORLD, "global_eqnum \n");
-	VecView( global_eqnum, PETSC_VIEWER_STDOUT_WORLD );
-	*/
-	
-	/* For each periodic boundary, get the mapped nodes */
-	
-	if( periodic_x==PETSC_TRUE ) {
-		VecScatter vscat_p;
-		IS is_from;
-		PetscInt *from, *to;
-		Vec mapped;
-		PetscScalar *_mapped;
-		PetscInt c;
-		
-		PetscMalloc( sizeof(PetscInt)*npx*dof, &from );
-		PetscMalloc( sizeof(PetscInt)*npx*dof, &to );
-		
-		c = 0;
-		for( i=0; i<npx; i++ ) {
-			PetscInt I,J,K,gid,from_gid;
-			
-			gid = periodic_x_gnode_id[i];
-			K = gid/(NX*NY);
-			J = (gid - K*(NX*NY))/NX;
-			I = gid - K*(NX*NY) - J*NX;
-			from_gid = (I-(NX-1)) + J*NX + K*(NX*NY);
-			
-			for( d=0; d<dof; d++ ) {
-				to[c] = gid * dof + d;
-				from[c] = from_gid * dof + d;
-				c++;
-			}
-		}
-		
-		
-		VecCreate( PETSC_COMM_SELF, &mapped );
-		VecSetSizes( mapped, PETSC_DECIDE, npx*dof );
-		VecSetFromOptions( mapped );
-		
-		ISCreateGeneralWithArray( PETSC_COMM_SELF, npx*dof, from, &is_from );
-		VecScatterCreate( global_eqnum, is_from, mapped, PETSC_NULL, &vscat_p );
-		
-		_VecScatterBeginEnd( vscat_p, global_eqnum, mapped, INSERT_VALUES, SCATTER_FORWARD );
-		if( npx>0 ) {
-			VecGetArray( mapped, &_mapped );
-			VecSetValues( global_eqnum, npx*dof, to, _mapped,  INSERT_VALUES );
-			VecRestoreArray( mapped, &_mapped );
-		}
-		
-		VecAssemblyBegin(global_eqnum);
-		VecAssemblyEnd(global_eqnum);
-		
-		VecScatterDestroy( vscat_p );
-		ISDestroy( is_from );
-		VecDestroy( mapped );
-		PetscFree( from );
-		PetscFree( to );
-	}
-	
-	
-	if( periodic_y==PETSC_TRUE ) {
-		VecScatter vscat_p;
-		IS is_from;
-		PetscInt *from, *to;
-		Vec mapped;
-		PetscScalar *_mapped;
-		PetscInt c;
-		
-		PetscMalloc( sizeof(PetscInt)*npy*dof, &from );
-		PetscMalloc( sizeof(PetscInt)*npy*dof, &to );
-		
-		c = 0;
-		for( i=0; i<npy; i++ ) {
-			PetscInt I,J,K,gid,from_gid;
-			
-			gid = periodic_y_gnode_id[i];
-			K = gid/(NX*NY);
-			J = (gid - K*(NX*NY))/NX;
-			I = gid - K*(NX*NY) - J*NX;
-			from_gid = I + (J - (NY - 1))*NX + K*(NX*NY);
-			
-			for( d=0; d<dof; d++ ) {
-				to[c] = gid * dof + d;
-				from[c] = from_gid * dof + d;
-				c++;
-			}
-		}
-		
-		
-		VecCreate( PETSC_COMM_SELF, &mapped );
-		VecSetSizes( mapped, PETSC_DECIDE, npy*dof );
-		VecSetFromOptions( mapped );
-		
-		ISCreateGeneralWithArray( PETSC_COMM_SELF, npy*dof, from, &is_from );
-		VecScatterCreate( global_eqnum, is_from, mapped, PETSC_NULL, &vscat_p );
-		
-		_VecScatterBeginEnd( vscat_p, global_eqnum, mapped, INSERT_VALUES, SCATTER_FORWARD );
-		if( npy>0 ) {
-			VecGetArray( mapped, &_mapped );
-			VecSetValues( global_eqnum, npy*dof, to, _mapped,  INSERT_VALUES );
-			VecRestoreArray( mapped, &_mapped );
-		}
-		
-		VecAssemblyBegin(global_eqnum);
-		VecAssemblyEnd(global_eqnum);
-		
-		VecScatterDestroy( vscat_p );
-		ISDestroy( is_from );
-		VecDestroy( mapped );
-		PetscFree( from );
-		PetscFree( to );
-	}
-
-	if( periodic_z==PETSC_TRUE ) {
-		VecScatter vscat_p;
-		IS is_from;
-		PetscInt *from, *to;
-		Vec mapped;
-		PetscScalar *_mapped;
-		PetscInt c;
-		
-		PetscMalloc( sizeof(PetscInt)*npz*dof, &from );
-		PetscMalloc( sizeof(PetscInt)*npz*dof, &to );
-		
-		c = 0;
-		for( i=0; i<npz; i++ ) {
-			PetscInt I,J,K,gid,from_gid;
-			
-			gid = periodic_z_gnode_id[i];
-			K = gid/(NX*NY);
-			J = (gid - K*(NX*NY))/NX;
-			I = gid - K*(NX*NY) - J*NX;
-			from_gid = I + J*NX + (K - (NZ-1))*(NX*NY);
-			
-			for( d=0; d<dof; d++ ) {
-				to[c] = gid * dof + d;
-				from[c] = from_gid * dof + d;
-				c++;
-			}
-		}
-		
-		
-		VecCreate( PETSC_COMM_SELF, &mapped );
-		VecSetSizes( mapped, PETSC_DECIDE, npz*dof );
-		VecSetFromOptions( mapped );
-		
-		ISCreateGeneralWithArray( PETSC_COMM_SELF, npz*dof, from, &is_from );
-		VecScatterCreate( global_eqnum, is_from, mapped, PETSC_NULL, &vscat_p );
-		
-		_VecScatterBeginEnd( vscat_p, global_eqnum, mapped, INSERT_VALUES, SCATTER_FORWARD );
-		if( npz>0 ) {
-			VecGetArray( mapped, &_mapped );
-			VecSetValues( global_eqnum, npz*dof, to, _mapped,  INSERT_VALUES );
-			VecRestoreArray( mapped, &_mapped );
-		}
-		
-		VecAssemblyBegin(global_eqnum);
-		VecAssemblyEnd(global_eqnum);
-		
-		VecScatterDestroy( vscat_p );
-		ISDestroy( is_from );
-		VecDestroy( mapped );
-		PetscFree( from );
-		PetscFree( to );
-	}
-
-	
-	/*
-	PetscPrintf(PETSC_COMM_WORLD, "global_eqnum following periodic \n");
-	VecView( global_eqnum, PETSC_VIEWER_STDOUT_WORLD );
-	*/
-	
-	
-	/* Finally, scatter stuff from global_eqnums into MY array */
-	{
-		IS is_all_my_eqnums;
-		PetscInt *all_my_eqnum_index;
-		PetscInt _I,_D,CNT;
-		Vec all_my_eqnums;
-		PetscScalar *_all_my_eqnums;
-		VecScatter vscat_p;
-		
-		PetscMalloc( sizeof(PetscInt)*dof*nlocal, &all_my_eqnum_index );
-		
-		CNT = 0;
-		for( _I=0; _I<nlocal; _I++ ) {
-			for( _D=0; _D<dof; _D++ ) {
-				all_my_eqnum_index[CNT] = g_node_id[_I]*dof + _D;
-				CNT++;
-			}
-		}
-		
-		ISCreateGeneralWithArray( PETSC_COMM_SELF, nlocal*dof, all_my_eqnum_index, &is_all_my_eqnums );
-		VecCreate( PETSC_COMM_SELF, &all_my_eqnums );
-		VecSetSizes( all_my_eqnums, PETSC_DECIDE, nlocal*dof );
-		VecSetFromOptions( all_my_eqnums );
-		VecScatterCreate( global_eqnum, is_all_my_eqnums, all_my_eqnums, PETSC_NULL, &vscat_p );
-		_VecScatterBeginEnd( vscat_p, global_eqnum, all_my_eqnums, INSERT_VALUES, SCATTER_FORWARD );
-		VecGetArray( all_my_eqnums, &_all_my_eqnums );
-
-		for( i=0; i<nlocal*dof; i++ ) {
-			eqnums[i] = (int)_all_my_eqnums[i];
-		}
-		VecRestoreArray( all_my_eqnums, &_all_my_eqnums );
-		
-		VecScatterDestroy( vscat_p );
-		VecDestroy( all_my_eqnums );
-		ISDestroy( is_all_my_eqnums );
-		PetscFree( all_my_eqnum_index );
-	}
-	
-	VecMax( global_eqnum, &loc, &max );
-	*neqnums = (int)max;
-	(*neqnums)++;
-	
-	/* tidy up */
-	VecRestoreArray( local_ownership, &_local_ownership );
-	
-	
-	VecDestroy( g_ownership );
-	VecDestroy( local_ownership );
-	PetscFree( _g_node_id );
-	ISDestroy( is_gnode );
-	VecScatterDestroy( vscat_ownership );
-	
-	VecDestroy( global_eqnum );
-	VecDestroy( local_eqnum );
-	PetscFree( to_fetch );
-	ISDestroy( is_eqnum );
-	VecScatterDestroy( vscat_eqnum );
-	
-	return 0;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeEquationNumber.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/FeEquationNumber.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,3367 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FeEquationNumber.c 1191 2008-07-25 03:06:19Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType.h"
+#include "ElementType_Register.h"
+#include "Element.h"
+#include "FeMesh.h"
+#include "FeEquationNumber.h"
+#include "LinkedDofInfo.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+#include <petsc.h>
+#include <petscvec.h>
+
+int stgCmpInt( const void *l, const void *r ) {
+   return *(int*)l - *(int*)r;
+}
+
+/*###### Typedefs and Structs ######*/
+
+/** Textual name of this class */
+const Type FeEquationNumber_Type = "FeEquationNumber";
+
+/** struct to store sub-totals: what is the equation number up to at a given
+    node? These can then be exchanged between processors */
+typedef struct CritPointInfo {
+      Node_GlobalIndex	index;
+      Dof_EquationNumber	eqNum;
+} CritPointInfo;
+
+
+/** An element of linked list of critical point info. Several of the functions
+    use this to keep track of key points */
+typedef struct AddListEntry {
+      CritPointInfo*		critPointInfo;
+      struct AddListEntry*	next;
+} AddListEntry;
+
+/** Enum to say whetehr values at crit. nodes should be printed */
+typedef enum PrintValuesFlag {
+   DONT_PRINT_VALUES,
+   PRINT_VALUES
+} PrintValuesFlag;
+
+/** MPI datatype handle for efficiently exchanging CritPointInfo structures.
+	see FeEquationNumber_Create_CritPointInfo_MPI_Datatype() for where this
+	handle is defined. */
+MPI_Datatype MPI_critPointInfoType;
+
+/*###### Private Function Declarations ######*/
+
+#if 0
+static void _FeEquationNumber_BuildRemappedNodeInfoTable( void* feEquationNumber );
+
+static void _FeEquationNumber_CalculateDomainKnownCriticalPoints(
+	FeEquationNumber* self,
+	Node_DomainIndex	nodeDomainCount,
+	CritPointInfo*		mySetEnds,
+	Index* const		mySetEndsTotal,
+	Node_GlobalIndex*	myWantedCriticalPoints,
+	Index* const		myWantedCriticalPointsTotal );
+	
+static void _FeEquationNumber_HandleNode(
+	FeEquationNumber*			self,
+	const Node_DomainIndex	dNode_I,
+	Dof_EquationNumber*		const currEqNum );
+	
+static void _FeEquationNumber_PostProcessLinkedDofs( FeEquationNumber* self );
+
+static void _FeEquationNumber_CalculateCritPointsIHave(
+	FeEquationNumber*				self,
+	Node_GlobalIndex** const	myWantedCriticalPointsPtr,
+	Node_GlobalIndex				myWantedCriticalPointsTotal,
+	CritPointInfo** const		critPointsIHave,
+	Index* const					critPointsIHaveTotal,
+	CritPointInfo* const			critPointsToSend,
+	Index* const					critPointsToSendTotal );
+	
+static void _FeEquationNumber_ShareCriticalPoints(
+   FeEquationNumber*				self,
+   Node_GlobalIndex** const	myCriticalPoints,
+   Node_GlobalIndex				myCriticalPointsTotal,
+   Node_GlobalIndex**			allCriticalPoints,
+   Index**							procCritPointsTotals, 
+   Node_GlobalIndex* const		maxCritPointsPerProc );
+
+static void _FeEquationNumber_ShareCritPointInfo(
+   FeEquationNumber*	self,
+   CritPointInfo**	const myCritPointInfo,
+   Index					myCritPointInfoTotal,
+   CritPointInfo**	allCritPointInfo,
+   Index**				procCritPointInfoTotals,
+   Index*				const maxCritPointInfoPerProc,
+   PrintValuesFlag	printValuesFlag );
+
+static void _FeEquationNumber_DoPartialTotals(
+	FeEquationNumber*		self,
+	CritPointInfo* const	critPointsIHave,
+	Index						critPointsIHaveTotal,
+	CritPointInfo* const	critPointsToSend,
+	Index						critPointsToSendTotal );
+
+static void _FeEquationNumber_AddAllPartialTotals(
+	FeEquationNumber*	self,
+	CritPointInfo*		mySubTotals,
+	Index					myCritPointInfoTotal,
+	CritPointInfo*		allSubTotals,
+	Index*				procCritPointInfoTotals,
+	Index					maxSubTotalsPerProc );
+
+Node_RemappedGlobalIndex _FeEquationNumber_RemapNode( 
+   Mesh* mesh, 
+   Index newDimOrder[3],
+   Node_GlobalIndex gNode_I );
+
+int GenerateEquationNumbering(
+	int			NX, int NY, int NZ,
+	int			nlocal, int g_node_id[],
+	int			dof, int nglobal,
+	PetscTruth	periodic_x, PetscTruth periodic_y, PetscTruth periodic_z,
+	int			npx, int npy, int npz,
+	int			periodic_x_gnode_id[], int periodic_y_gnode_id[], int periodic_z_gnode_id[],
+	int			eqnums[], int *neqnums );
+
+/** Tests if the critical point from another processor is held by ours.
+    Is complicated by the possibility of remapping. */
+static Bool _FeEquationNumber_IHaveCritPoint(
+   FeEquationNumber* self,
+   Node_RemappedGlobalIndex critPoint );
+#endif
+
+/*###### Function Definitions ######*/
+
+/** Public constructor */
+
+FeEquationNumber* FeEquationNumber_New(
+	Name						name,
+	DomainContext*			context,
+	void*						mesh,
+	DofLayout*				dofLayout,
+	VariableCondition*	bcs,
+	LinkedDofInfo*			linkedDofInfo )
+{
+  FeEquationNumber* self = (FeEquationNumber*)FeEquationNumber_DefaultNew( name );
+
+	self->isConstructed = True;
+	_FeEquationNumber_Init( self, context, mesh, dofLayout, bcs, linkedDofInfo );
+
+	return self;
+}
+
+void* FeEquationNumber_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(FeEquationNumber);
+	Type                                                      type = FeEquationNumber_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FeEquationNumber_Delete;
+	Stg_Class_PrintFunction*                                _print = _FeEquationNumber_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FeEquationNumber_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (Stg_Component_DefaultConstructorFunction*)FeEquationNumber_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _FeEquationNumber_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _FeEquationNumber_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FeEquationNumber_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FeEquationNumber_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FeEquationNumber_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+
+   return _FeEquationNumber_New(  FEEQUATIONNUMBER_PASSARGS  );
+}
+/** Constructor implementation. */
+FeEquationNumber* _FeEquationNumber_New(  FEEQUATIONNUMBER_DEFARGS  ){
+   FeEquationNumber* self;
+	
+   /* Allocate memory */
+   assert( _sizeOfSelf >= sizeof(FeEquationNumber) );
+   self = (FeEquationNumber*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+	
+   /* General info */
+	
+   /* Virtual info */
+   self->_build = _build;
+   self->_initialise = _initialise;
+	
+   /* Mesh info */
+	
+   return self;
+}
+
+
+/** Constructor variables initialisation. Doesn't allocate any
+    memory, just saves arguments and sets counters to 0. */
+void _FeEquationNumber_Init(
+   FeEquationNumber*		self, 
+	DomainContext*			context,
+   void*						feMesh,
+   DofLayout*				dofLayout,
+   VariableCondition*	bcs,
+   LinkedDofInfo*			linkedDofInfo )
+{
+   /* General and Virtual info should already be set */
+	
+   /* FinteElementMesh info */
+	self->context = context;
+   self->feMesh = (FeMesh*)feMesh;
+   self->globalSumUnconstrainedDofs = 0;
+   self->isBuilt = False;
+   self->locationMatrixBuilt = False;
+   self->_lowestLocalEqNum = -1;
+   self->_lowestGlobalEqNums = NULL;
+   self->_highestLocalEqNum = -1;
+   self->dofLayout = dofLayout;
+   self->bcs = bcs;
+   self->linkedDofInfo = linkedDofInfo;
+   self->remappingActivated = False;
+   /* register streams */
+   self->debug = Stream_RegisterChild( StgFEM_Discretisation_Debug, FeEquationNumber_Type );
+   self->debugLM = Stream_RegisterChild( self->debug, "LM" );
+   self->warning = Stream_RegisterChild( StgFEM_Warning, FeEquationNumber_Type );
+   self->removeBCs = True;
+   self->bcEqNums = STree_New();
+   STree_SetIntCallbacks( self->bcEqNums );
+   STree_SetItemSize( self->bcEqNums, sizeof(int) );
+   self->ownedMap = STreeMap_New();
+   STreeMap_SetItemSize( self->ownedMap, sizeof(int), sizeof(int) );
+   STree_SetIntCallbacks( self->ownedMap );
+
+   Stream_SetPrintingRank( self->debug, 0 );
+}
+
+void _FeEquationNumber_AssignFromXML( void* feEquationNumber, Stg_ComponentFactory *cf, void* data ) {
+}
+	
+void _FeEquationNumber_Execute( void* feEquationNumber, void *data ){
+	
+}
+	
+void _FeEquationNumber_Destroy( void* feEquationNumber, void *data ){
+   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
+   Index ii;
+
+   Stg_Component_Destroy( self->feMesh   , data, False );
+   Stg_Component_Destroy( self->dofLayout, data, False );
+   if ( self->linkedDofInfo ) Stg_Component_Destroy( self->dofLayout, data, False );
+   if ( self->bcs )           Stg_Component_Destroy( self->bcs      , data, False );
+	
+   FreeArray( self->remappedNodeInfos );
+   /* free destination array memory */
+   Journal_DPrintfL( self->debug, 2, "Freeing I.D. Array\n" );
+   FreeArray( self->destinationArray );
+	
+   if (self->locationMatrix) {
+      Journal_DPrintfL( self->debug, 2, "Freeing Full L.M. Array\n" );
+      for( ii = 0; ii < self->nDomainEls; ii++ )
+         FreeArray( self->locationMatrix[ii] );
+         
+      FreeArray( self->locationMatrix );
+   }
+
+   if( self->bcEqNums ) 
+      NewClass_Delete( self->bcEqNums );
+   
+   if( self->ownedMap ) 
+      NewClass_Delete( self->ownedMap );
+}
+	
+/* Copy */
+
+/** Stg_Class_Delete implementation. */
+void _FeEquationNumber_Delete( void* feEquationNumber ) {
+   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
+
+   Journal_DPrintfL( self->debug, 1, "In %s\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+
+   /* Stg_Class_Delete parent */
+   _Stg_Class_Delete( self );
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+/** Print implementation */
+void _FeEquationNumber_Print( void* mesh, Stream* stream ) {
+   FeEquationNumber* self = (FeEquationNumber*)mesh;
+	
+   /* General info */
+   Journal_Printf( stream, "FeEquationNumber (ptr): %p\n", self );
+	
+   /* Print parent */
+   _Stg_Class_Print( self, stream );
+	
+   /* Virtual info */
+   Journal_Printf( stream,  "\t_build (func ptr): %p\n", self->_build );
+   Journal_Printf( stream,  "\t_intialise (func ptr): %p\n", self->_initialise );
+	
+   /* FeEquationNumber info */
+   /* Don't print dofs or bcs as these will be printed by FeVariable */
+	
+   if ( self->destinationArray ) {
+      FeEquationNumber_PrintDestinationArray( self, stream );
+      FeEquationNumber_PrintLocationMatrix( self, stream );
+   }
+   else {
+      Journal_Printf( stream, "\tdestinationArray: (null)... not built yet\n" );
+      Journal_Printf( stream, "\tlocationMatrix: (null)... not built yet\n" );
+   }
+}
+
+
+void* _FeEquationNumber_Copy( const void* feEquationNumber, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+#if 0
+   FeEquationNumber*	self = (FeEquationNumber*)feEquationNumber;
+   Mesh*			mesh;
+   FeEquationNumber*	newFeEquationNumber;
+   PtrMap*			map = ptrMap;
+   Bool			ownMap = False;
+
+   mesh = (Mesh*)self->feMesh;
+	
+   if( !map ) {
+      map = PtrMap_New( 10 );
+      ownMap = True;
+   }
+	
+   newFeEquationNumber = _Stg_Class_Copy( self, dest, deep, nameExt, map );
+	
+   /* Virtual methods */
+   newFeEquationNumber->_build = self->_build;
+   newFeEquationNumber->_initialise = self->_initialise;
+	
+   newFeEquationNumber->_highestLocalEqNum = self->_highestLocalEqNum;
+   newFeEquationNumber->_lowestLocalEqNum = self->_lowestLocalEqNum;
+   newFeEquationNumber->_eqNumsPerProcDivisor = self->_eqNumsPerProcDivisor;
+   newFeEquationNumber->_eqNumsRemainder = self->_eqNumsRemainder;
+   newFeEquationNumber->_remNotAddedChangeover = self->_remNotAddedChangeover;
+   newFeEquationNumber->firstOwnedEqNum = self->firstOwnedEqNum;
+   newFeEquationNumber->lastOwnedEqNum = self->lastOwnedEqNum;
+   newFeEquationNumber->localEqNumsOwnedCount = self->localEqNumsOwnedCount;
+   newFeEquationNumber->globalSumUnconstrainedDofs = self->globalSumUnconstrainedDofs;
+   newFeEquationNumber->locationMatrixBuilt = self->locationMatrixBuilt;
+   newFeEquationNumber->remappingActivated = self->remappingActivated;
+	
+   if( deep ) {
+      newFeEquationNumber->debug = (Stream*)Stg_Class_Copy( self->debug, NULL, deep, nameExt, map );
+      newFeEquationNumber->debugLM = (Stream*)Stg_Class_Copy( self->debugLM, NULL, deep, nameExt, map );
+      newFeEquationNumber->warning = (Stream*)Stg_Class_Copy( self->warning, NULL, deep, nameExt, map );
+      newFeEquationNumber->feMesh = (FeMesh*)Stg_Class_Copy( self->feMesh, NULL, deep, nameExt, map );
+      newFeEquationNumber->dofLayout = (DofLayout*)Stg_Class_Copy( self->dofLayout, NULL, deep, nameExt, map );
+      newFeEquationNumber->bcs = (VariableCondition*)Stg_Class_Copy( self->bcs, NULL, deep, nameExt, map );
+      newFeEquationNumber->linkedDofInfo = (LinkedDofInfo*)Stg_Class_Copy( self->linkedDofInfo, NULL, deep, nameExt, map );
+		
+      if( (newFeEquationNumber->remappedNodeInfos = PtrMap_Find( map, self->remappedNodeInfos )) == NULL && self->remappedNodeInfos ) {
+         Node_DomainIndex	nodeDomainCount;
+
+         nodeDomainCount = Mesh_GetDomainSize( mesh, MT_VERTEX );
+			
+         newFeEquationNumber->remappedNodeInfos = Memory_Alloc_Array( RemappedNodeInfo, nodeDomainCount, "FeEquationNumber->remappedNodeInfos" );
+         memcpy( newFeEquationNumber->remappedNodeInfos, self->remappedNodeInfos, sizeof(RemappedNodeInfo) * nodeDomainCount );
+         PtrMap_Append( map, self->remappedNodeInfos, newFeEquationNumber->remappedNodeInfos );
+      }
+		
+      if( (newFeEquationNumber->destinationArray = PtrMap_Find( map, self->destinationArray )) == NULL && self->destinationArray ) {
+         Node_DomainIndex	nodeDomainCount;
+         Node_DomainIndex	node_dI;
+
+         nodeDomainCount = Mesh_GetDomainSize( mesh, MT_VERTEX );
+			
+         newFeEquationNumber->destinationArray = Memory_Alloc_2DComplex( Dof_EquationNumber, nodeDomainCount, self->dofLayout->dofCounts, "FeEquationNumber->destinationArray" );
+         for( node_dI = 0; node_dI < nodeDomainCount; node_dI++ ) {
+            memcpy( newFeEquationNumber->destinationArray[node_dI], self->destinationArray[node_dI], sizeof(Dof_EquationNumber) * self->dofLayout->dofCounts[node_dI] );
+         }
+         PtrMap_Append( map, self->destinationArray, newFeEquationNumber->destinationArray );
+      }
+		
+      if( (newFeEquationNumber->_lowestGlobalEqNums = PtrMap_Find( map, self->_lowestGlobalEqNums )) == NULL && self->_lowestGlobalEqNums ) {
+         Partition_Index		nProc;
+
+         nProc = Mesh_GetCommTopology( mesh, MT_VERTEX )->nProcs;
+			
+         newFeEquationNumber->_lowestGlobalEqNums = Memory_Alloc_Array( Dof_EquationNumber, nProc, "FeEquationNumber->_lowestGlobalEqNums" );
+         memcpy( newFeEquationNumber->_lowestGlobalEqNums, self->_lowestGlobalEqNums, sizeof(Dof_EquationNumber) * nProc );
+         PtrMap_Append( map, self->_lowestGlobalEqNums, newFeEquationNumber->_lowestGlobalEqNums );
+      }
+		
+      if( (newFeEquationNumber->locationMatrix = PtrMap_Find( map, self->locationMatrix )) == NULL && self->locationMatrix ) {
+         FeMesh*	mesh = self->feMesh;
+         Element_LocalIndex	lElement_I;
+         Node_LocalIndex		numNodesThisElement;
+         Node_LocalIndex		elLocalNode_I;
+         Dof_Index		numDofsThisNode;
+         Element_LocalIndex	elementLocalCount = mesh->elementLocalCount;
+         Dof_Index**		dofCountsAtElementNodesArray;
+			
+         dofCountsAtElementNodesArray = Memory_Alloc_3DSetup( elementLocalCount, mesh->elementNodeCountTbl );
+         for ( lElement_I = 0; lElement_I < elementLocalCount; lElement_I++ ) {
+            numNodesThisElement = mesh->elementNodeCountTbl[lElement_I];
+				
+            for( elLocalNode_I = 0; elLocalNode_I < numNodesThisElement; elLocalNode_I++) {
+               Node_LocalIndex		dNode_I = mesh->elementNodeTbl[lElement_I][elLocalNode_I];
+					
+               numDofsThisNode = self->dofLayout->dofCounts[dNode_I];
+               dofCountsAtElementNodesArray[lElement_I][elLocalNode_I] = numDofsThisNode;
+            }
+         }
+			
+         newFeEquationNumber->locationMatrix = Memory_Alloc_3DComplex( Dof_EquationNumber, elementLocalCount, mesh->elementNodeCountTbl, dofCountsAtElementNodesArray, "FeEquationNumber->locationMatrix" );
+         for( lElement_I = 0; lElement_I < elementLocalCount; lElement_I++ ) {
+            for( elLocalNode_I = 0; elLocalNode_I < mesh->elementNodeCountTbl[lElement_I]; elLocalNode_I++ ) {
+               memcpy( newFeEquationNumber->locationMatrix[lElement_I][elLocalNode_I], self->locationMatrix[lElement_I][elLocalNode_I], sizeof(Dof_EquationNumber) * dofCountsAtElementNodesArray[lElement_I][elLocalNode_I] );
+            }
+         }
+			
+         Memory_Free( dofCountsAtElementNodesArray );
+         PtrMap_Append( map, self->locationMatrix, newFeEquationNumber->locationMatrix );
+      }
+   }
+   else {
+      newFeEquationNumber->debug = self->debug;
+      newFeEquationNumber->debugLM = self->debugLM;
+      newFeEquationNumber->warning = self->warning;
+      newFeEquationNumber->feMesh = self->feMesh;
+      newFeEquationNumber->dofLayout = self->dofLayout;
+      newFeEquationNumber->bcs = self->bcs;
+      newFeEquationNumber->linkedDofInfo = self->linkedDofInfo;
+      newFeEquationNumber->remappedNodeInfos = self->remappedNodeInfos;
+      newFeEquationNumber->destinationArray = self->destinationArray;
+      newFeEquationNumber->_lowestGlobalEqNums = self->_lowestGlobalEqNums;
+      newFeEquationNumber->locationMatrix = self->locationMatrix;
+   }
+	
+   if( ownMap ) {
+      Stg_Class_Delete( map );
+   }
+	
+   return (void*)newFeEquationNumber;
+#endif
+   abort();
+}
+
+void _FeEquationNumber_Build( void* feEquationNumber, void* data ) {
+   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
+
+   assert(self);
+	
+   Journal_DPrintf( self->debug, "In %s:\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+
+   Stg_Component_Build( self->feMesh   , data, False );
+   Stg_Component_Build( self->dofLayout, data, False );
+   if ( self->linkedDofInfo ) Stg_Component_Build( self->dofLayout, data, False );
+   if ( self->bcs )           Stg_Component_Build( self->bcs      , data, False );
+	/* If we have new mesh topology information, do this differently. */
+   /* if( self->feMesh->topo->domains && self->feMesh->topo->domains[MT_VERTEX] ) { */
+
+   if( Mesh_HasExtension( self->feMesh, "vertexGrid" ) )
+      FeEquationNumber_BuildWithDave( self );
+   else
+      FeEquationNumber_BuildWithTopology( self );
+
+   /* If not removing BCs, construct a table of which equation numbers are actually BCs. */
+   if( !self->removeBCs ) {
+      FeMesh* mesh = self->feMesh;
+      DofLayout* dofLayout = self->dofLayout;
+      VariableCondition* bcs = self->bcs;
+      int nDofs, varInd;
+      unsigned ii;
+      int jj;
+
+      for( ii = 0; ii < FeMesh_GetNodeLocalSize( mesh ); ii++ ) {
+         nDofs = dofLayout->dofCounts[ii];
+         for( jj = 0; jj < nDofs; jj++ ) {
+            varInd = dofLayout->varIndices[ii][jj];
+            if( bcs && VariableCondition_IsCondition( bcs, ii, varInd ) ) {
+               if( !STree_Has( self->bcEqNums, self->destinationArray[ii] + jj ) )
+                  STree_Insert( self->bcEqNums, self->destinationArray[ii] + jj );
+            }
+         }
+      }
+   }
+
+   /*}
+   else {
+      _FeEquationNumber_BuildRemappedNodeInfoTable( self );
+      _FeEquationNumber_BuildDestinationArray( self );
+      _FeEquationNumber_CalculateGlobalUnconstrainedDofTotal( self );
+      _FeEquationNumber_CalculateEqNumsDecomposition( self );
+   }*/
+
+   if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+      FeEquationNumber_PrintDestinationArray( self, self->debug );
+   }
+
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+/** Initialise implementation. Currently does nothing. */
+void _FeEquationNumber_Initialise( void* feEquationNumber, void* data ) {
+   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
+
+   Stg_Component_Initialise( self->feMesh   , data, False );
+   Stg_Component_Initialise( self->dofLayout, data, False );
+   if ( self->linkedDofInfo ) Stg_Component_Initialise( self->dofLayout, data, False );
+   if ( self->bcs )           Stg_Component_Initialise( self->bcs      , data, False );
+}
+
+
+#if 0
+Node_RemappedGlobalIndex _FeEquationNumber_RemapNode( 
+   HexaMD* hexaMD,
+   Index newDimOrder[3],
+   Node_GlobalIndex gNode_I )
+{
+   Node_RemappedGlobalIndex remappedGlobalIndex = 0;
+   Index dim_I = 0;
+   Index currNewDim = 0;
+   IJK defaultIJK;
+   IJK newOrderIJK;
+   IJK	newOrderNodeCounts;
+	
+   Dimension_1DTo3D( gNode_I, hexaMD->nodeGlobal3DCounts, defaultIJK );
+
+   for ( dim_I = I_AXIS; dim_I < 3; dim_I++ ) {
+      currNewDim = newDimOrder[dim_I];
+      newOrderIJK[dim_I] = defaultIJK[currNewDim]; 
+      newOrderNodeCounts[dim_I] = hexaMD->nodeGlobal3DCounts[currNewDim];
+   }
+
+   Dimension_3DTo1D( newOrderIJK, newOrderNodeCounts, &remappedGlobalIndex );
+
+   return remappedGlobalIndex;
+}
+
+
+static void _FeEquationNumber_BuildRemappedNodeInfoTable( void* feEquationNumber ) {
+   FeEquationNumber* self = (FeEquationNumber*) feEquationNumber;
+   FeMesh* mesh = self->feMesh;
+   Node_DomainIndex nodeDomainCount = Mesh_GetDomainSize( mesh, MT_VERTEX );
+   CommTopology*	commTopo = Mesh_GetCommTopology( mesh, MT_VERTEX );
+   Node_GlobalIndex gNode_I = 0;
+   Node_DomainIndex dNode_I = 0;
+/*#if DEBUG*/
+   RemappedNodeInfo_Index rNodeInfo_I;
+/*#endif*/
+	
+   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+
+   self->remappedNodeInfos = Memory_Alloc_Array( RemappedNodeInfo, nodeDomainCount, 
+                                                 "FeEquationNumber->remappedNodeInfos" );
+	
+   if ( 1 == commTopo->nProcs ) {
+      Journal_DPrintfL( self->debug, 1, "Serial code: No remapping required...filling remapping table with normal values.\n" );
+      for (dNode_I = 0; dNode_I < nodeDomainCount; dNode_I++ ) {
+         gNode_I = mesh->nodeD2G[dNode_I];
+         self->remappedNodeInfos[dNode_I].remappedGlobal = gNode_I;
+         self->remappedNodeInfos[dNode_I].domain = dNode_I;
+      }		
+   }
+   else if ( meshDecomp->type != HexaMD_Type ) {
+      Node_GlobalIndex	prevGNode_I = (unsigned int)-1;
+      RemappedNodeInfo_Index	insertIndex;
+	
+      Journal_DPrintfL( self->debug, 1, "Parallel, but non-hexa decomp: building the remapping table by "
+                        "insertion-sorting based on global node number order.\n" );
+      for (dNode_I = 0; dNode_I < nodeDomainCount; dNode_I++ ) {
+         gNode_I = mesh->nodeD2G[dNode_I];
+
+         if ( gNode_I > prevGNode_I ) {
+            self->remappedNodeInfos[dNode_I].remappedGlobal = gNode_I;
+            self->remappedNodeInfos[dNode_I].domain = dNode_I;
+            prevGNode_I = gNode_I;
+            continue;
+         }
+         else {
+            insertIndex = 0;
+            while ( gNode_I > self->remappedNodeInfos[insertIndex].remappedGlobal ) insertIndex++;
+            memmove( &self->remappedNodeInfos[insertIndex+1], &self->remappedNodeInfos[insertIndex],
+                     sizeof(RemappedNodeInfo) * (dNode_I - insertIndex + 1) );
+            self->remappedNodeInfos[insertIndex].remappedGlobal = gNode_I;
+            self->remappedNodeInfos[insertIndex].domain = dNode_I;
+         }
+      }
+   }
+   else if ( ((HexaMD*)meshDecomp)->numPartitionedDims > 1 )
+   {
+      Node_GlobalIndex	nextShadowGlobalMap;
+      Node_LocalIndex		lNode_I;
+      Node_ShadowIndex	sNode_I = mesh->nodeLocalCount;
+      RemappedNodeInfo_Index	insertIndex = 0;
+	
+      Journal_DPrintfL( self->debug, 1, "Parallel, hexa decomp but multiple partition dims:\n"
+                        "filling remapping table with insertion sort\n"
+                        "of local & shadow elements.\n" );
+		
+      if ( meshDecomp->shadowDepth > 0 ) {
+         nextShadowGlobalMap = mesh->nodeD2G[sNode_I];
+      }
+      else {
+         nextShadowGlobalMap = mesh->nodeGlobalCount;
+      }
+
+      insertIndex = 0;
+      for (lNode_I = 0; lNode_I < mesh->nodeLocalCount; lNode_I++ ) {
+         gNode_I = mesh->nodeL2G[lNode_I];
+
+         while ( nextShadowGlobalMap < gNode_I ) {
+            self->remappedNodeInfos[insertIndex].remappedGlobal = nextShadowGlobalMap;
+            self->remappedNodeInfos[insertIndex++].domain = sNode_I++;
+            if ( sNode_I < mesh->nodeDomainCount ) {
+               nextShadowGlobalMap = mesh->nodeD2G[sNode_I];
+            }
+            else {
+               nextShadowGlobalMap = mesh->nodeGlobalCount;
+            }
+         }
+         self->remappedNodeInfos[insertIndex].remappedGlobal = gNode_I;
+         self->remappedNodeInfos[insertIndex++].domain = lNode_I;
+      }		
+
+      /* now know all local elements inserted, so ensure all shadow elements have also been inserted */
+      for ( ; sNode_I < mesh->nodeDomainCount; sNode_I++ ) {
+         gNode_I = mesh->nodeD2G[sNode_I];
+         self->remappedNodeInfos[insertIndex].remappedGlobal = gNode_I;
+         self->remappedNodeInfos[insertIndex++].domain = sNode_I;
+      }
+      Journal_Firewall( (insertIndex == mesh->nodeDomainCount), self->debug,
+                        "Stuffup: should have inserted exactly the right number of values by here.\n" );
+   }
+   else {
+      /* Otherwise, we remap each of the global node values, so the eqNums
+         will cause minimal communication during mesh assembly */
+      Node_RemappedGlobalIndex currRemappedGNode_I = 0;
+      Node_RemappedGlobalIndex firstRemappedGNode_I = 0;
+      Index newDimOrder[3] = {0,0,0};
+      Index newOrder_I = 0;
+      Index partitionedAxis = I_AXIS;
+      Index dim_I;
+      RemappedNodeInfo_Index insertIndex;
+      Bool lowestIsShadow = False;
+
+      self->remappingActivated = True;
+
+      Journal_DPrintfL( self->debug, 1, "Parallel, hexa decomp with 1 partition dim:\n"
+                        "remapping eqNum traversal order to be aligned with mesh decomposition:\n" );
+
+      /* Work out the new dimension order for the EqNums. The partitioned index
+         goes last */
+      for ( dim_I = I_AXIS; dim_I < 3; dim_I++ ) {
+         if (True == ((HexaMD*)meshDecomp)->partitionedAxis[dim_I]) {
+            partitionedAxis = dim_I;
+            newDimOrder[2] = partitionedAxis;
+         } else {
+            newDimOrder[newOrder_I++] = dim_I;
+         }
+      }
+      Journal_DPrintfL( self->debug, 1, "Given partition axis is %c, calc. remapping dimension order as %c,%c,%c\n",
+                        IJKTopology_DimNumToDimLetter[partitionedAxis],
+                        IJKTopology_DimNumToDimLetter[newDimOrder[0]],
+                        IJKTopology_DimNumToDimLetter[newDimOrder[1]],
+                        IJKTopology_DimNumToDimLetter[newDimOrder[2]] );
+
+      Journal_DPrintfL( self->debug, 4, "Calculating over %d domain nodes, %d local, %d shadow.\n",
+                        mesh->nodeDomainCount, mesh->nodeLocalCount, mesh->nodeShadowCount );
+
+      /* Work out the lowest remapped global index (so we know where to insert into the table) */
+      gNode_I = mesh->nodeD2G[0];
+      firstRemappedGNode_I = _FeEquationNumber_RemapNode( (HexaMD*)meshDecomp, newDimOrder, gNode_I );
+      /* if shadow elements are enabled, check if the first shadow element has lower
+         global index than first local element */
+      if ( meshDecomp->shadowDepth > 0 ) {
+         Node_RemappedGlobalIndex firstRemappedShadowGNode_I;
+		
+         gNode_I = mesh->nodeD2G[mesh->nodeLocalCount];
+         firstRemappedShadowGNode_I = _FeEquationNumber_RemapNode( (HexaMD*)meshDecomp,
+                                                                   newDimOrder, gNode_I );
+			
+         if ( firstRemappedShadowGNode_I < firstRemappedGNode_I ) {
+            firstRemappedGNode_I = firstRemappedShadowGNode_I;
+            lowestIsShadow = True;
+         }
+      }
+      Journal_DPrintfL( self->debug, 4, "Calculated lowest remapped global index is %d",
+                        firstRemappedGNode_I );
+      if ( lowestIsShadow ) {
+         Journal_DPrintfL( self->debug, 4, " (a shadow node.)\n" );
+      }
+      else {
+         Journal_DPrintfL( self->debug, 4, " (a local node.)\n" );
+      }
+
+      Stream_IndentBranch( StgFEM_Debug );
+      /* Now add the rest, relative to the first */
+      for (dNode_I = 0; dNode_I < nodeDomainCount; dNode_I++ ) {
+         gNode_I = mesh->nodeD2G[dNode_I];
+         currRemappedGNode_I = _FeEquationNumber_RemapNode( (HexaMD*)meshDecomp, newDimOrder, gNode_I );
+         insertIndex = currRemappedGNode_I - firstRemappedGNode_I;
+         self->remappedNodeInfos[insertIndex].remappedGlobal = currRemappedGNode_I;
+         self->remappedNodeInfos[insertIndex].domain = dNode_I;
+         Journal_DPrintfL( self->debug, 4, "Processing domain node %d: original global = %d, remaps to %d.\n",
+                           dNode_I, gNode_I, currRemappedGNode_I );
+      }	
+      Stream_UnIndentBranch( StgFEM_Debug );
+   }
+
+/*#if DEBUG*/
+   if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+      Journal_DPrintf( self->debug, "Calculated remapped node info table as:\n{\n" );
+      for (rNodeInfo_I = 0; rNodeInfo_I < nodeDomainCount; rNodeInfo_I++ ) {
+         Journal_DPrintf( self->debug, " %d:(remap=%d,domain=%d),\n", rNodeInfo_I,
+                          self->remappedNodeInfos[rNodeInfo_I].remappedGlobal,
+                          self->remappedNodeInfos[rNodeInfo_I].domain );
+      }
+      Journal_DPrintf( self->debug, "}\n");
+   }
+/*#endif*/
+   Stream_UnIndentBranch( StgFEM_Debug );
+}	
+
+
+/* Build the processor's ID (destination) array */
+void _FeEquationNumber_BuildDestinationArray( FeEquationNumber* self ) {
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+   Node_DomainIndex nodeDomainCount = meshDecomp->nodeDomainCount;
+   CritPointInfo* critPointsIHave = NULL;
+   Index critPointsIHaveTotal = 0;
+   CritPointInfo* critPointsToSend = NULL;
+   Index critPointsToSendTotal = 0;
+   Stream* errorStream = Journal_Register( Error_Type, (Name)self->type  );
+
+   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+
+   Journal_Firewall( ( nodeDomainCount == self->dofLayout->_numItemsInLayout ),
+                     errorStream, "Error: In %s: DofLayout's size is %d, which isn't equal to "
+                     "Node domain count of %d. Did you create the dofLayout of size node local count? "
+                     "It should be aset up to size node domain count.\n",
+                     __func__, self->dofLayout->_numItemsInLayout, nodeDomainCount );
+		
+
+   self->destinationArray = Memory_Alloc_2DComplex( Dof_EquationNumber, nodeDomainCount,
+                                                    self->dofLayout->dofCounts, "FeEquationNumber->destinationArray" );
+
+
+   if (meshDecomp->procsInUse == 1)
+   {
+      /* for serial jobs, don't worry about the critical points, just calculate
+         the totals normally */
+      critPointsIHave = Memory_Alloc( CritPointInfo, "critPointsIHave (BuildDestinationArray)" );
+      critPointsToSend = Memory_Alloc( CritPointInfo, "critPointsToSend (BuildDestinationArray)" );
+      critPointsIHave[0].index = meshDecomp->nodeGlobalCount;
+      critPointsToSend[0].index = meshDecomp->nodeGlobalCount;
+      _FeEquationNumber_DoPartialTotals( self, critPointsIHave, 0, critPointsToSend, 0 );
+      self->_lowestLocalEqNum = 0;
+   }
+   else {
+      Node_GlobalIndex* myWantedCriticalPoints = NULL;
+      Index myWantedCriticalPointsTotal = 0;
+      CritPointInfo* allSendCriticalPoints = NULL;
+      Index* procSendCritPointsTotals = NULL;
+      Index maxSendCritPointsPerProc = 0;
+
+      critPointsIHave = Memory_Alloc_Array( CritPointInfo, nodeDomainCount,
+                                            "critPointsIHave (BuildDestinationArray)" );
+      critPointsToSend = Memory_Alloc_Array( CritPointInfo, nodeDomainCount,
+                                             "critPointsToSend (BuildDestinationArray)" );
+      myWantedCriticalPoints = Memory_Alloc_Array( Node_GlobalIndex, nodeDomainCount,
+                                                   "myWantedCritialPoints (BuildDestinationArray)" );
+
+      /* Go through all domain nodes, work out end of runs, and interfaces needed */
+      _FeEquationNumber_CalculateDomainKnownCriticalPoints( self, nodeDomainCount, critPointsIHave, &critPointsIHaveTotal,
+                                                            myWantedCriticalPoints, &myWantedCriticalPointsTotal );
+	
+      /* initialise the below to the set end critical nodes I already worked out I have */
+      critPointsToSend = (CritPointInfo*) memcpy( critPointsToSend, critPointsIHave, (critPointsIHaveTotal * sizeof(CritPointInfo)) );
+      critPointsToSendTotal = critPointsIHaveTotal;
+		
+      /* work out critical points (inc. those needed by others) I hold, and those to send.
+         The list I have could be greater than my end of runs, in an irregular mesh case */
+      _FeEquationNumber_CalculateCritPointsIHave( self, 
+                                                  &myWantedCriticalPoints, myWantedCriticalPointsTotal, &critPointsIHave, &critPointsIHaveTotal,
+                                                  critPointsToSend, &critPointsToSendTotal );
+	
+      Memory_Free( myWantedCriticalPoints );
+
+      /* OK: We now know all the critical points on this processor, so go ahead and work out the partial ID number
+         at all of them. */
+
+      Journal_DPrintfL( self->debug, 2, "Looping through nodes again, calculating eq nums (re-setting to 0 at critical points)\n,"
+                        "and storing subtotal of each each critical node:\n" );
+      _FeEquationNumber_DoPartialTotals( self, critPointsIHave, critPointsIHaveTotal,
+                                         critPointsToSend, critPointsToSendTotal );
+
+      Journal_DPrintfL( self->debug, 2, "Now sub-totals have been calculated, share all of my critical point sub-totals "
+                        "and get any that I need:\n" );
+      _FeEquationNumber_ShareCritPointInfo( self, &critPointsToSend, critPointsToSendTotal,
+                                            &allSendCriticalPoints, &procSendCritPointsTotals, &maxSendCritPointsPerProc, PRINT_VALUES );
+
+      Journal_DPrintfL( self->debug, 2, "Final loop: add the sub-totals at all the critical points to the existing values:\n" );
+      _FeEquationNumber_AddAllPartialTotals( self, critPointsIHave, critPointsIHaveTotal,
+                                             allSendCriticalPoints, procSendCritPointsTotals, maxSendCritPointsPerProc );
+
+      /* Post process the linked dofs */
+      if ( self->linkedDofInfo ) {
+         _FeEquationNumber_PostProcessLinkedDofs( self );
+      }	
+
+      Memory_Free( allSendCriticalPoints );
+      Memory_Free( procSendCritPointsTotals );
+   }
+
+   /* If not removing BCs, construct a table of which equation numbers are actually BCs. */
+   if( !self->removeBCs ) {
+      FeMesh*	feMesh = self->feMesh;
+      DofLayout*		dofLayout = self->dofLayout;
+      VariableCondition*	bcs = self->bcs;
+      unsigned		lNode_i;
+
+      /* New index set. */
+      self->bcEqNums = IndexSet_New( self->_highestLocalEqNum - self->_lowestLocalEqNum );
+
+      /* Fill it up. */
+      for( lNode_i = 0; lNode_i < feMesh->nodeLocalCount; lNode_i++ ) {
+         unsigned	nDofs = dofLayout->dofCounts[lNode_i];
+         unsigned	dof_i;
+
+         for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
+            unsigned	varInd = dofLayout->varIndices[lNode_i][dof_i];
+
+            if( bcs && VariableCondition_IsCondition( bcs, lNode_i, varInd ) ) {
+               IndexSet_Add( self->bcEqNums, self->destinationArray[lNode_i][dof_i] );
+            }
+         }
+      }
+   }
+
+   Memory_Free( critPointsIHave );
+   Memory_Free( critPointsToSend );
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+
+
+/** Works out 'critical nodes' I know from domain information (those I want are the start
+    of my runs -1, those I know others want are the end of my runs. */
+static void _FeEquationNumber_CalculateDomainKnownCriticalPoints(
+   FeEquationNumber* self,
+   Node_DomainIndex nodeDomainCount,
+   CritPointInfo* mySetEnds,
+   Index* const mySetEndsTotal,
+   Node_GlobalIndex* myWantedCriticalPoints,
+   Index* const myWantedCriticalPointsTotal )
+{
+   RemappedNodeInfo_Index rNodeInfo_I = 0;
+   Node_RemappedGlobalIndex remappedGlobal_I = 0;
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+
+   Journal_DPrintf( self->debug, "In %s\n", __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+
+   if ( self->remappingActivated ) {
+      /* if remapping has been done, the only possible crit points are the first and last
+         points */
+      remappedGlobal_I = self->remappedNodeInfos[0].remappedGlobal;
+      if (remappedGlobal_I != 0) {
+         Journal_DPrintfL( self->debug, 3, "Adding interface c.p. to myWantedCriticalPoints[%d] = %d\n", 
+                           (*myWantedCriticalPointsTotal), remappedGlobal_I-1 );
+         myWantedCriticalPoints[(*myWantedCriticalPointsTotal)++] = remappedGlobal_I-1;
+      }	
+
+      remappedGlobal_I = self->remappedNodeInfos[nodeDomainCount-1].remappedGlobal;
+      if ( remappedGlobal_I != (meshDecomp->nodeGlobalCount-1) ) {
+         Journal_DPrintfL( self->debug, 3, "Adding set end c.p. mySetEnds[%d] = %d\n", 
+                           (*mySetEndsTotal), remappedGlobal_I );
+         mySetEnds[(*mySetEndsTotal)++].index = remappedGlobal_I;
+      }
+      Stream_UnIndentBranch( StgFEM_Debug );
+      return;
+   }
+	
+   while ( rNodeInfo_I < nodeDomainCount ) {
+      /* save start of set */
+      remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I].remappedGlobal;
+
+      if (remappedGlobal_I != 0) {
+         Journal_DPrintfL( self->debug, 3, "Adding interface c.p. to myWantedCriticalPoints[%d] = %d\n", 
+                           (*myWantedCriticalPointsTotal), remappedGlobal_I-1 );
+         myWantedCriticalPoints[(*myWantedCriticalPointsTotal)++] = remappedGlobal_I-1;
+      }	
+      rNodeInfo_I++;
+
+      /* skip to end of contiguous set */
+      while ( (rNodeInfo_I < nodeDomainCount)
+              && (self->remappedNodeInfos[rNodeInfo_I].remappedGlobal ==
+                  (self->remappedNodeInfos[rNodeInfo_I-1].remappedGlobal + 1) ) )
+      {
+         Journal_DPrintfL( self->debug, 4, "skipping remapped gNode[%d] domain = %d\n", 
+                           self->remappedNodeInfos[rNodeInfo_I].remappedGlobal,
+                           self->remappedNodeInfos[rNodeInfo_I].domain );
+         rNodeInfo_I++;
+      }	
+
+      /* and add the critical point, if not the last node */
+      remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I-1].remappedGlobal;
+      if ( remappedGlobal_I != (meshDecomp->nodeGlobalCount-1) ) {
+         Journal_DPrintfL( self->debug, 3, "Adding set end c.p. mySetEnds[%d] = %d\n", 
+                           (*mySetEndsTotal), remappedGlobal_I );
+         mySetEnds[(*mySetEndsTotal)++].index = remappedGlobal_I;
+      }
+   }
+
+/*#if DEBUG*/
+   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
+      Index cPoint_I;
+
+      Journal_DPrintf( self->debug, "My set end Crit Points:[0-%d][ ",  (*mySetEndsTotal) );
+      for (cPoint_I = 0 ; cPoint_I < (*mySetEndsTotal) ; cPoint_I++) {
+         Journal_DPrintf( self->debug, "%2d, ", mySetEnds[cPoint_I].index );
+      }	
+      Journal_DPrintf( self->debug, "]\n" );
+
+      Journal_DPrintf( self->debug, "interface Crit Points I want:[0-%d][ ",  (*myWantedCriticalPointsTotal) );
+      for (cPoint_I = 0 ; cPoint_I < (*myWantedCriticalPointsTotal) ; cPoint_I++) {
+         Journal_DPrintf( self->debug, "%2d, ", myWantedCriticalPoints[cPoint_I] );
+      }
+      Journal_DPrintf( self->debug, "]\n" );
+   }
+/*#endif*/
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+/* work out critical points (inc. those needed by others) I hold, and those to send.
+   The list I have could be greater than my end of runs, in an irregular mesh case */
+static void _FeEquationNumber_CalculateCritPointsIHave( FeEquationNumber* self,
+							Node_GlobalIndex** const myWantedCriticalPointsPtr, Node_GlobalIndex myWantedCriticalPointsTotal,
+							CritPointInfo** const critPointsIHavePtr, Index* const critPointsIHaveTotal,
+							CritPointInfo* const critPointsToSend, Index* const critPointsToSendTotal )
+{
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+   Partition_Index proc_I; 
+   Node_GlobalIndex* allWantedCriticalPoints = NULL;
+   CritPointInfo* allHaveCriticalPoints = NULL;
+   Node_GlobalIndex* procWantedCritPointsTotals = NULL;
+   Index* procHaveCritPointsTotals = NULL;
+   Node_GlobalIndex maxWantedCritPointsPerProc = 0;
+   Node_GlobalIndex maxHaveCritPointsPerProc = 0;
+   Index myCritPoint_I = 0;
+   PartitionIndex myRank = meshDecomp->rank;
+
+   Journal_DPrintf( self->debug, "In %s\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+
+   Journal_DPrintfL( self->debug, 2, "Globally sharing locally known wanted C.N. lists:\n",  __func__ );
+   _FeEquationNumber_ShareCriticalPoints( self, myWantedCriticalPointsPtr, myWantedCriticalPointsTotal,
+                                          &allWantedCriticalPoints, &procWantedCritPointsTotals, &maxWantedCritPointsPerProc );
+
+   Journal_DPrintfL( self->debug, 2, "Globally sharing locally known 'have' C.N. lists:\n",  __func__ );
+   _FeEquationNumber_ShareCritPointInfo( self, critPointsIHavePtr, (*critPointsIHaveTotal),
+                                         &allHaveCriticalPoints, &procHaveCritPointsTotals, &maxHaveCritPointsPerProc, DONT_PRINT_VALUES );
+
+   /* now we build our lists of crit points on my processor, and crit points on my processor to send to others */
+   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
+      Index otherCritPoint_I = proc_I * maxWantedCritPointsPerProc;
+      Index otherCritPoint_End_I = (proc_I * maxWantedCritPointsPerProc) + procWantedCritPointsTotals[proc_I];
+      myCritPoint_I = 0;
+
+      /* don't try and add my own */
+      if ( myRank == proc_I ) continue;
+
+      /* for each crit point they want, if I have it add it to my have and send lists */
+      for (; otherCritPoint_I < otherCritPoint_End_I; otherCritPoint_I++) {
+         Node_GlobalIndex otherCritPoint = allWantedCriticalPoints[otherCritPoint_I];
+			
+         if ( _FeEquationNumber_IHaveCritPoint( self, otherCritPoint ) ) {
+
+            while ( (myCritPoint_I < (*critPointsIHaveTotal) ) &&
+                    (otherCritPoint > (*critPointsIHavePtr)[myCritPoint_I].index) ) {
+               /* skip ahead to right spot */
+               myCritPoint_I++;
+            }
+            if ( myCritPoint_I == (*critPointsIHaveTotal) ) {
+               (*critPointsIHavePtr)[(*critPointsIHaveTotal)++].index = otherCritPoint; 
+               critPointsToSend[(*critPointsToSendTotal)++].index = otherCritPoint;
+            }
+            else if ( otherCritPoint != (*critPointsIHavePtr)[myCritPoint_I].index ) {
+               memmove( &((*critPointsIHavePtr)[myCritPoint_I+1]),
+                        &((*critPointsIHavePtr)[myCritPoint_I]),
+                        ((*critPointsIHaveTotal) - myCritPoint_I) * sizeof(CritPointInfo) );
+               (*critPointsIHavePtr)[myCritPoint_I].index = otherCritPoint;
+               (*critPointsIHaveTotal)++;
+               memmove( &critPointsToSend[myCritPoint_I+1], &critPointsToSend[myCritPoint_I],
+                        ((*critPointsToSendTotal) - myCritPoint_I) * sizeof(CritPointInfo) );
+               critPointsToSend[myCritPoint_I].index = otherCritPoint;
+               (*critPointsToSendTotal)++;
+            }
+            /* move to the next point in any case */
+            myCritPoint_I++;
+         }	
+      }		
+   }			
+
+   /* For each crit point the others have, if I have it add it to my have list */
+   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
+      Index otherCritPointInfo_I = proc_I * maxHaveCritPointsPerProc;
+      Index otherCritPointInfo_End_I = (proc_I * maxHaveCritPointsPerProc) + procHaveCritPointsTotals[proc_I];
+      myCritPoint_I = 0;
+
+      /* don't try and add my own */
+      if ( myRank == proc_I ) continue;
+
+      for (; otherCritPointInfo_I < otherCritPointInfo_End_I; otherCritPointInfo_I++) {
+         Node_GlobalIndex otherCritPoint = allHaveCriticalPoints[otherCritPointInfo_I].index;
+			
+         if ( _FeEquationNumber_IHaveCritPoint( self, otherCritPoint ) ) {
+			
+            while ( (myCritPoint_I < (*critPointsIHaveTotal) ) &&
+                    (otherCritPoint > (*critPointsIHavePtr)[myCritPoint_I].index) ) {
+               myCritPoint_I++;
+               /* skip ahead to right spot */
+            }
+            if ( myCritPoint_I == (*critPointsIHaveTotal) ) {
+               (*critPointsIHavePtr)[(*critPointsIHaveTotal)++].index = otherCritPoint; 
+            }
+            else if ( otherCritPoint != (*critPointsIHavePtr)[myCritPoint_I].index ) {
+               memmove( &((*critPointsIHavePtr)[myCritPoint_I+1]),
+                        &((*critPointsIHavePtr)[myCritPoint_I]),
+                        ((*critPointsIHaveTotal) - myCritPoint_I) * sizeof(CritPointInfo) );
+               (*critPointsIHavePtr)[myCritPoint_I].index = otherCritPoint;
+               (*critPointsIHaveTotal)++;
+            }
+            /* move to the next point in any case */
+            myCritPoint_I++;
+         }	
+      }		
+   }			
+/*#if DEBUG*/
+   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
+      Journal_DPrintf( self->debug, "Calculated crit points I Have:\n[" );
+      for ( myCritPoint_I = 0; myCritPoint_I < (*critPointsIHaveTotal); myCritPoint_I++ ) {
+         Journal_DPrintf( self->debug, "%3d, ", (*critPointsIHavePtr)[myCritPoint_I].index );
+      }
+      Journal_DPrintf( self->debug, "]\nCalculated crit points To Send:\n[" );
+      for ( myCritPoint_I = 0; myCritPoint_I < (*critPointsToSendTotal); myCritPoint_I++ ) {
+         Journal_DPrintf( self->debug, "%3d, ", critPointsToSend[myCritPoint_I].index );
+      }
+      Journal_DPrintf( self->debug, "]\n");
+   }	
+/*#endif*/
+	
+   Memory_Free( allWantedCriticalPoints );
+   Memory_Free( procWantedCritPointsTotals );
+   Memory_Free( allHaveCriticalPoints );
+   Memory_Free( procHaveCritPointsTotals );
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+static Bool _FeEquationNumber_IHaveCritPoint(
+   FeEquationNumber* self,
+   Node_RemappedGlobalIndex critPoint )
+{
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+   Node_DomainIndex nodeDomainCount = meshDecomp->nodeDomainCount;
+   PartitionIndex myRank = meshDecomp->rank;
+
+   /* Case 1: for remapped hexa mesh, just check if its between max and min numbers */	
+   if ( self->remappingActivated ) {
+      if ( ( self->remappedNodeInfos[0].remappedGlobal <= critPoint ) &&
+           ( critPoint <= self->remappedNodeInfos[nodeDomainCount-1].remappedGlobal ) )
+      {
+         return True;
+      }
+      else {
+         return False;
+      }	
+   }
+   /* Case 2: 2D+ hexa decomps or other decomp strategy, use local (and shadow if enabled) node IndexSet */
+   else {
+      if ( IndexSet_IsMember( meshDecomp->localNodeSets[myRank], critPoint ) ) {
+         return True;
+      }
+      else if ( (meshDecomp->shadowDepth > 0) 
+                && IndexSet_IsMember( meshDecomp->shadowNodeSets[myRank], critPoint ) ) {
+         return True;
+      }
+      else {
+         return False;
+      }
+   }
+}
+
+
+/** Performs an AllGather on a set of critical points: Each processer will afterwards have all the critical points
+    of all the processors, in one large array. The user must then index into the array by processor carefully. */
+static void _FeEquationNumber_ShareCriticalPoints(
+   FeEquationNumber* self,
+   Node_GlobalIndex** const myCriticalPoints,
+   Node_GlobalIndex myCriticalPointsTotal,
+   Node_GlobalIndex** allCriticalPoints,
+   Index** procCritPointsTotals, 
+   Node_GlobalIndex* const maxCritPointsPerProc)
+{
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+   Partition_Index proc_I; 
+/*#if DEBUG*/
+   Index point_I = 0;
+/*#endif*/
+
+   Journal_DPrintf( self->debug, "In %s\n", __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+	
+   (*maxCritPointsPerProc) = 0;
+	
+/*#if DEBUG*/
+   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
+      Journal_DPrintf( self->debug, "myCriticalPointsTotal=%u\n",  myCriticalPointsTotal);
+      Journal_DPrintf( self->debug, "myCritPoints:(" );
+      for ( point_I = 0; point_I < myCriticalPointsTotal; point_I++)
+      {
+         Journal_DPrintf( self->debug, "%u, ", (*myCriticalPoints)[point_I]);
+      }	
+      Journal_DPrintf( self->debug, ")\n");
+   }	
+/*#endif*/
+
+   /* First, we allocate and calculate how many critical points are on each node (this way, we don't have to guess
+      how much memory to allocate in the main array.) */
+   (*procCritPointsTotals) = Memory_Alloc_Array( Node_GlobalIndex, meshDecomp->nproc,
+                                                 "*procCritPointsTotals (ShareCriticalPoints)" ); 
+	
+   MPI_Allgather( &myCriticalPointsTotal, 1, MPI_UNSIGNED,
+                  (*procCritPointsTotals), 1, MPI_UNSIGNED,
+                  meshDecomp->communicator );
+	
+   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
+      if ( (*procCritPointsTotals)[proc_I] > (*maxCritPointsPerProc) )
+         (*maxCritPointsPerProc) = (*procCritPointsTotals)[proc_I];
+   }
+
+/*#if DEBUG*/
+   Journal_DPrintfL( self->debug, 2, "procCritPoints totals:(");
+   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
+      Journal_DPrintfL( self->debug, 2, "%d, ", (*procCritPointsTotals)[proc_I]);
+   }
+   Journal_DPrintfL( self->debug, 2, ")\n");
+   Journal_DPrintfL( self->debug, 2, "MaxCritPointsPerProc = %d\n", (*maxCritPointsPerProc));
+/*#endif*/
+
+   /* Now share the actual point values */
+   (*myCriticalPoints) = Memory_Realloc_Array( (*myCriticalPoints), Node_GlobalIndex, *maxCritPointsPerProc );
+   (*allCriticalPoints) = Memory_Alloc_Array( Node_GlobalIndex, meshDecomp->nproc * (*maxCritPointsPerProc),
+                                              "*allCriticalPoints (ShareCriticalPoints)" );
+
+   MPI_Allgather( (*myCriticalPoints), (*maxCritPointsPerProc), MPI_UNSIGNED,
+                  (*allCriticalPoints), (*maxCritPointsPerProc), MPI_UNSIGNED,
+                  meshDecomp->communicator );
+
+/*#if DEBUG*/
+   Journal_DPrintfL( self->debug, 2, "procCritPoints:(" );
+   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
+      for ( point_I = 0; point_I < (*procCritPointsTotals)[proc_I]; point_I++)
+      {
+         Journal_DPrintfL( self->debug, 2, "%u, ", 
+                           (*allCriticalPoints)[(*maxCritPointsPerProc)*proc_I + point_I]);
+      }	
+   }
+   Journal_DPrintfL( self->debug, 2, ")\n");
+/*#endif*/
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+
+/** Performs an AllGather on a set of CritPointInfo structs: Each processer will afterwards have all the CritPointInfo
+    structs of all the processors, in one large array. The user must then index into the array by processor
+    carefully. */
+static void _FeEquationNumber_ShareCritPointInfo(
+   FeEquationNumber* self,
+   CritPointInfo** const myCritPointInfo,
+   Index myCritPointInfoTotal,
+   CritPointInfo** allCritPointInfo,
+   Index** procCritPointInfoTotals,
+   Index* const maxCritPointInfoPerProc,
+   PrintValuesFlag printValuesFlag )
+{
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+   Partition_Index proc_I; 
+/*#if DEBUG*/
+   Index point_I = 0;
+/*#endif*/
+
+   Journal_DPrintfL( self->debug, 1, "In %s\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+   (*maxCritPointInfoPerProc) = 0;
+
+   /* allgather the totals (to save allocating unnecessary memory) */
+   (*procCritPointInfoTotals) = Memory_Alloc_Array( Node_GlobalIndex, meshDecomp->nproc, "*procCritPointInfoTotals" ); 
+
+   MPI_Allgather( &myCritPointInfoTotal, 1, MPI_INT, (*procCritPointInfoTotals), 1, MPI_INT,
+                  meshDecomp->communicator );
+
+   for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
+      if ( (*procCritPointInfoTotals)[proc_I] > (*maxCritPointInfoPerProc) )
+         (*maxCritPointInfoPerProc) = (*procCritPointInfoTotals)[proc_I];
+   }
+
+/*#if DEBUG*/
+   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
+      Journal_DPrintf( self->debug, "procCritPointInfo totals:(" );
+      for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
+         Journal_DPrintf( self->debug, "%d, ", (*procCritPointInfoTotals)[proc_I]);
+      }
+      Journal_DPrintf( self->debug, ")\n");
+      Journal_DPrintf( self->debug, "MaxCritPointInfoPerProc = %d\n", (*maxCritPointInfoPerProc));
+   }	
+/*#endif*/
+
+   /* Now share the actual critPointInfo arrays */
+   (*allCritPointInfo) = Memory_Alloc_Array( CritPointInfo, meshDecomp->nproc * (*maxCritPointInfoPerProc), 
+                                             "allCritPointInfo (ShareCritPointInfo)" );
+
+   /* below changed by PatrickSunter 27/1/2004 to work on grendel */
+   MPI_Allgather( (*myCritPointInfo), (*maxCritPointInfoPerProc), MPI_critPointInfoType,
+                  (*allCritPointInfo), (*maxCritPointInfoPerProc), MPI_critPointInfoType,
+                  meshDecomp->communicator );
+	
+/*#if DEBUG*/
+   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {	
+      Journal_DPrintf( self->debug, "procCritPointInfos" );
+      if ( DONT_PRINT_VALUES == printValuesFlag ) {
+         Journal_DPrintf( self->debug, "(indices only)" );
+      }
+      Journal_DPrintf( self->debug, ": (" );
+      for (proc_I = 0; proc_I < meshDecomp->nproc; proc_I++) {
+         for ( point_I = 0; point_I < (*procCritPointInfoTotals)[proc_I]; point_I++)
+         {
+            Index current = (*maxCritPointInfoPerProc)*proc_I + point_I;
+            Journal_DPrintf( self->debug, "%u", (*allCritPointInfo)[current].index );
+            if ( PRINT_VALUES == printValuesFlag ) {
+               Journal_DPrintf( self->debug, "= %d", (*allCritPointInfo)[current].eqNum );
+            }	
+            Journal_DPrintf( self->debug, ", " );
+         }	
+      }
+      Journal_DPrintf( self->debug, ")\n");
+   }	
+/*#endif*/
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+/** For each domain node, calculate the Equation number, restarting at 0 whenever a critical node is reached and
+    saving the value I was up to. */
+static void _FeEquationNumber_DoPartialTotals( FeEquationNumber* self,
+					       CritPointInfo* const critPointsIHave, Index critPointsIHaveTotal,
+					       CritPointInfo* const critPointsToSend, Index critPointsToSendTotal )
+{
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+   Node_DomainIndex nodeDomainCount = meshDecomp->nodeDomainCount;
+   RemappedNodeInfo_Index rNodeInfo_I = 0;
+   Node_RemappedGlobalIndex remappedGlobal_I = 0;
+   Node_DomainIndex dNode_I = 0;
+   Index haveCritPoint_I = 0;
+   Index sendCritPoint_I = 0;
+   Dof_EquationNumber currSubTotalEqNum = 0;
+
+   Journal_DPrintf( self->debug, "In %s:\n", __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+	
+   while ( (rNodeInfo_I < nodeDomainCount) ) {
+      remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I].remappedGlobal;
+      dNode_I = self->remappedNodeInfos[rNodeInfo_I].domain;
+	
+      _FeEquationNumber_HandleNode( self, dNode_I, &currSubTotalEqNum );
+
+      /* if the node is next critical point */
+      if ( ( haveCritPoint_I < critPointsIHaveTotal ) 
+           && ( remappedGlobal_I == critPointsIHave[haveCritPoint_I].index ) ) 
+      {
+         Journal_DPrintfL( self->debug, 3, "storing c.p. subtotal at remapped global index %u = %d\n", 
+                           remappedGlobal_I, currSubTotalEqNum );
+         /* store current value */
+         critPointsIHave[haveCritPoint_I++].eqNum = currSubTotalEqNum;
+
+         /* check if its also a to send point */
+         if ( ( sendCritPoint_I < critPointsToSendTotal )
+              && ( remappedGlobal_I == critPointsToSend[sendCritPoint_I].index ) )
+         {
+            /* store current value */
+            critPointsToSend[sendCritPoint_I++].eqNum = currSubTotalEqNum;
+         }
+         /* reset counter and move to next point */
+         currSubTotalEqNum = 0;
+      }	
+      rNodeInfo_I++;
+   }
+
+/*#if DEBUG*/
+   if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
+      Journal_DPrintf( self->debug, "Totals I have:[ " );
+      haveCritPoint_I = 0;
+      for ( haveCritPoint_I = 0; haveCritPoint_I < critPointsIHaveTotal; haveCritPoint_I++ )
+      {	
+         Journal_DPrintf( self->debug, "%2u=%d, ", critPointsIHave[haveCritPoint_I].index, critPointsIHave[haveCritPoint_I].eqNum  );
+      }	
+      Journal_DPrintf( self->debug, "]\n" );
+      Journal_DPrintf( self->debug, "Totals to send:[ " );
+      sendCritPoint_I = 0;
+      for ( sendCritPoint_I = 0; sendCritPoint_I < critPointsToSendTotal; sendCritPoint_I++ )
+      {	
+         Journal_DPrintf( self->debug, "%2u=%d, ", critPointsToSend[sendCritPoint_I].index, critPointsToSend[sendCritPoint_I].eqNum  );
+      }	
+      Journal_Printf( self->debug, "]\n" );
+   }
+/*#endif*/
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+/** Called right at the end of calculating ID array, to add the locally calculated partial totals with the final
+    global information, and arrive at the complete figures. */
+static void _FeEquationNumber_AddAllPartialTotals( FeEquationNumber* self, CritPointInfo* mySubTotals,
+						   Index myCritPointInfoTotal, CritPointInfo* allSubTotals, Index* procCritPointInfoTotals,
+						   Index maxSubTotalsPerProc )
+{	
+   Partition_Index proc_I;
+   FeMesh* mesh = self->feMesh;
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+   Index myRank = meshDecomp->rank;
+   Node_GlobalIndex nodeDomainCount = meshDecomp->nodeDomainCount;
+   RemappedNodeInfo_Index rNodeInfo_I = 0;
+   Node_RemappedGlobalIndex remappedGlobal_I = 0;
+   Node_DomainIndex dNode_I = 0;
+   Node_GlobalIndex gNode_I = 0;
+   Index myCritPointInfo_I = 0;
+   Index* procCritPointInfo_Is = NULL;
+   Dof_EquationNumber adjustSum = 0;
+   Dof_EquationNumber currEqNum;
+   Dof_Index currNodeNumDofs;
+   Dof_Index nodeLocalDof_I;
+   AddListEntry* addListStart;
+   AddListEntry* addListPtr;
+   AddListEntry* addListPrev;
+   Bool firstOfSet;
+   Bool* haveUpdatedLinkedDofSetTbl = NULL;
+   Index linkedDof_I;
+   Index linkedDofSet;
+#define NEXT_PROCESSOR_SECTION_START ( maxSubTotalsPerProc * (proc_I) + procCritPointInfoTotals[proc_I] )
+
+   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+	
+   gNode_I += 0;
+	
+   self->_lowestLocalEqNum = -1;
+   self->_highestLocalEqNum = -1;
+   procCritPointInfo_Is = Memory_Alloc_Array( Index, meshDecomp->nproc, "procCritPointInfo_Is (AddAllPartialTotals)" );
+	
+   /* set iterators into processors */
+   for ( proc_I = 0; proc_I < meshDecomp->nproc; proc_I++ ) {
+      procCritPointInfo_Is[proc_I] = maxSubTotalsPerProc * proc_I;
+   }
+							
+   if ( self->linkedDofInfo ) {
+      haveUpdatedLinkedDofSetTbl = Memory_Alloc_Array( Bool, self->linkedDofInfo->linkedDofSetsCount,
+                                                       "haveUpdatedLinkedDofSetTbl" );
+      for ( linkedDof_I=0; linkedDof_I < self->linkedDofInfo->linkedDofSetsCount; linkedDof_I++ ) {
+         haveUpdatedLinkedDofSetTbl[linkedDof_I] = False;
+      }	
+   }
+							
+
+   Journal_DPrintfL( self->debug, 3, "beginning sequential run through nodes...\n" );
+
+   while (rNodeInfo_I < nodeDomainCount) {
+      Node_GlobalIndex newCritInfoIndex;
+      /* reset the add list information */
+      addListPtr = addListStart = NULL;
+      remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I].remappedGlobal;
+      dNode_I = self->remappedNodeInfos[rNodeInfo_I].domain;
+	
+      Journal_DPrintfL( self->debug, 3, "At remapped gNode[%d]: ",  remappedGlobal_I );
+      Journal_DPrintfL( self->debug, 3, "...adding critical node totals from the block we just skipped...\n" );
+
+      /* Ok, now add critical node totals from other processors in the block we just skipped. */
+      for ( proc_I = 0; proc_I < meshDecomp->nproc; proc_I++ ) {
+         if ( proc_I == myRank ) continue;
+
+         /* reset the add list back to start */
+         addListPtr = addListStart;
+         addListPrev = NULL;
+			
+
+         /* Only add critical node totals from other processors lower than current index */
+         while (( procCritPointInfo_Is[proc_I] < NEXT_PROCESSOR_SECTION_START ) &&
+                (newCritInfoIndex = allSubTotals[(procCritPointInfo_Is[proc_I])].index) < remappedGlobal_I )
+         {
+            /* See if we are scheduled to add this critical point yet, and if not where it should go */
+            while ( addListPtr && ( newCritInfoIndex > addListPtr->critPointInfo->index ) ) {
+               addListPrev = addListPtr; 
+               addListPtr = addListPtr->next;
+            }
+            /* Note: The 2nd condition guards against trying to add a duplicate. In that case we
+             * just progress on. */
+            if ( (addListPtr == NULL) || ( addListPtr->critPointInfo->index != newCritInfoIndex )) {
+               /*
+                 if inside this condition we are either:
+                 1. Adding the first crit node to be added
+                 2. Have found a non-duplicate crit node to be added, either at the end or
+                 partway through.
+                 So go ahead and add to the addList, reconnecting both the prev and next.
+               */
+               AddListEntry* newAddListEntry = Memory_Alloc( AddListEntry,
+                                                             "newAddListEntry (AddAllPartialTotals)" );
+               adjustSum += allSubTotals[procCritPointInfo_Is[proc_I]].eqNum;
+               Journal_DPrintfL( self->debug, 3, "at other c.p. (%d):incrementing adjustSum by %d to = %d\n", 
+                                 allSubTotals[procCritPointInfo_Is[proc_I]].index,
+                                 allSubTotals[procCritPointInfo_Is[proc_I]].eqNum,
+                                 adjustSum );
+               newAddListEntry->critPointInfo = &allSubTotals[procCritPointInfo_Is[proc_I]];
+               newAddListEntry->next = addListPtr;
+               if ( addListPrev ) {
+                  addListPrev->next = newAddListEntry;
+               }
+               else {
+                  addListStart = newAddListEntry;
+               }
+               addListPtr = newAddListEntry;
+            }	
+            /* Move to the next potential crit node from that processor, regardless of whether we
+             * added the last one or not. */
+            (procCritPointInfo_Is[proc_I])++;
+         }	
+      }
+
+      /* free the add list */
+      while ( addListStart ) {
+         addListPrev = addListStart;
+         addListStart = addListStart->next;
+         Memory_Free( addListPrev );
+      }
+		
+      /* Now go through a run of nodes this processor owns, and add subtotals locally calculated */
+      firstOfSet = True;
+
+      while ( (firstOfSet) ||
+              ( (rNodeInfo_I < nodeDomainCount)
+                && (self->remappedNodeInfos[rNodeInfo_I].remappedGlobal ==
+                    (self->remappedNodeInfos[rNodeInfo_I-1].remappedGlobal + 1) ) ) )
+      {
+         remappedGlobal_I = self->remappedNodeInfos[rNodeInfo_I].remappedGlobal;
+         dNode_I = self->remappedNodeInfos[rNodeInfo_I].domain;
+         gNode_I = mesh->nodeD2G[dNode_I];
+         firstOfSet = False;
+			
+         Journal_DPrintfL( self->debug, 3, "At remapped gNode[%d]: I own it, so adjusting EqNums\n", 
+                           remappedGlobal_I );
+
+         /* increment the value at each non-bc dof by adjustSum */
+         currNodeNumDofs = self->dofLayout->dofCounts[ dNode_I ];
+
+         for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+            if( !self->bcs || !VariableCondition_IsCondition( self->bcs, dNode_I,
+                                                              self->dofLayout->varIndices[dNode_I][nodeLocalDof_I] ) )
+            {
+               if ( (NULL == self->linkedDofInfo) ||	/* TAG: bcs */
+                    ( self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I] == -1 ) )
+               {
+                  /* A normal point, so increment */
+                  self->destinationArray[dNode_I][nodeLocalDof_I] += adjustSum;
+               }
+               else {
+                  /* Handling of linked dofs: the first time we encounter one of a set,
+                     add the adjust sum. Afterwards, just set to the updated value. */
+                  linkedDofSet = self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I];
+                  if ( False == haveUpdatedLinkedDofSetTbl[linkedDofSet] ) {
+                     self->destinationArray[dNode_I][nodeLocalDof_I] += adjustSum;
+                     self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] += adjustSum;
+                     haveUpdatedLinkedDofSetTbl[linkedDofSet] = True;
+                  }
+                  else {
+                     self->destinationArray[dNode_I][nodeLocalDof_I] =
+                        self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet];
+                  }
+               }
+						
+               currEqNum = self->destinationArray[dNode_I][nodeLocalDof_I];
+               /* If current node not a shadow, then check totals */
+               if ( dNode_I < mesh->nodeLocalCount ) {
+                  if ( currEqNum != -1 ) {	/* TAG: bcs */
+                     if ( self->_lowestLocalEqNum == -1 ) {
+                        /* We need this if statement to initialise this */
+                        self->_lowestLocalEqNum = currEqNum;
+                     }	
+                     else if ( currEqNum < self->_lowestLocalEqNum ) {
+                        self->_lowestLocalEqNum = currEqNum;
+                     }
+
+                     if ( currEqNum > self->_highestLocalEqNum ) {
+                        self->_highestLocalEqNum = currEqNum;
+                     }	
+                  }
+               }
+            }	
+         }		
+
+         /* if the node is my next critical point, add the sub-total */
+         if ( ( myCritPointInfo_I < myCritPointInfoTotal ) &&
+              ( remappedGlobal_I == mySubTotals[myCritPointInfo_I].index)  ) 
+         {
+            adjustSum += mySubTotals[myCritPointInfo_I].eqNum;
+            Journal_DPrintfL( self->debug, 3, "at   my    c.p. %d(%d):incrementing adjustSum by %d to = %d\n", 
+                              myCritPointInfo_I, remappedGlobal_I, mySubTotals[myCritPointInfo_I].eqNum, adjustSum );
+            myCritPointInfo_I++;
+         }
+
+         rNodeInfo_I++;
+      }	
+
+      /* If any of the other processors had sub-totals I've just added, jump past them */
+      if (rNodeInfo_I < nodeDomainCount) {
+         for ( proc_I = 0; proc_I < meshDecomp->nproc; proc_I++ ) {
+
+            while (( procCritPointInfo_Is[proc_I] < NEXT_PROCESSOR_SECTION_START ) &&
+                   allSubTotals[(procCritPointInfo_Is[proc_I])].index <= remappedGlobal_I )
+            {
+               (procCritPointInfo_Is[proc_I])++;
+            }
+
+         }
+      }
+   }
+
+   if ( self->linkedDofInfo ) {
+      Memory_Free( haveUpdatedLinkedDofSetTbl );
+   }	
+   Memory_Free( procCritPointInfo_Is );
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+/** Updates the currEqNum argument for the number of dofs at the current node, and increments the ID Eq. Num for each
+    dof where appropriate (setting it to -1 if its a B.C.) */
+static void _FeEquationNumber_HandleNode( FeEquationNumber* self, const Node_DomainIndex dNode_I,
+					  Dof_EquationNumber* const currEqNum )
+{
+   Dof_Index	currNodeNumDofs;
+   Dof_Index	nodeLocalDof_I;
+/*#if DEBUG*/
+   Stream*		error;
+/*#endif*/
+	
+   Journal_DPrintfL( self->debug, 3, "In %s:",  __func__ );
+/*#if DEBUG*/
+   error = Journal_Register( Error_Type, (Name)self->type );
+   Journal_Firewall( (dNode_I < self->feMesh->nodeDomainCount ), error, "Stuffup: %s() asked to operate on node %d, bigger "
+                     "than domain count %d. Exiting.\n", __func__, dNode_I, self->feMesh->nodeDomainCount );
+/*#endif*/
+	
+   /* get the number of dofs */
+   currNodeNumDofs = self->dofLayout->dofCounts[ dNode_I ];
+   Journal_DPrintfL( self->debug, 3, " domain node %d, has %d dofs.\n", dNode_I, currNodeNumDofs );
+   /* process each dof, at the same time updating the updatePtr for the next node. */
+   for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+      Journal_DPrintfL( self->debug, 3, "dof %d: ", nodeLocalDof_I );
+
+      /* if dof is a boundary condition, set eq num=-1. Otherwise increment counter. */
+      /* Also, only set to -1 if we want the BCs removed from the matrix. - Luke */
+      if( self->removeBCs && 
+          self->bcs && VariableCondition_IsCondition( self->bcs, dNode_I, self->dofLayout->varIndices[dNode_I][nodeLocalDof_I] ) ) 
+      {
+         Journal_DPrintfL( self->debug, 3, "is a BC, setting ID[%d][%d] = -1.\n", dNode_I, nodeLocalDof_I );
+         self->destinationArray[dNode_I][nodeLocalDof_I] = -1;
+      }	
+      /* Check if node,dof is a linked dof */
+      else if ( self->linkedDofInfo && ( self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I] != -1 ) ) {
+         Index linkedDofSet = self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I];
+			
+         if ( self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] != -1 ) {
+            Journal_DPrintfL( self->debug, 3, "is a linked Dof, so setting ID[%d][%d] to the "
+                              "previous value = %d.\n", dNode_I, nodeLocalDof_I, 
+                              self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] );
+            /* value is same as the first part of the linked node set */
+            self->destinationArray[dNode_I][nodeLocalDof_I] =
+               self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet];
+         }
+         else /* This is the first time we've hit this linked eq num, so treat as normal */
+         {
+            Journal_DPrintfL( self->debug, 3, "is a linked Dof hit the first time, so setting "
+                              "ID[%d][%d] = %d.\n", dNode_I, nodeLocalDof_I, *currEqNum );
+			
+            self->destinationArray[dNode_I][nodeLocalDof_I] = (*currEqNum)++;
+            if ( dNode_I < self->feMesh->nodeLocalCount ) {
+               self->_highestLocalEqNum = self->destinationArray[dNode_I][nodeLocalDof_I];
+            }	
+            /* And save the value at the linked eq num for later */
+            self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] = 
+               self->destinationArray[dNode_I][nodeLocalDof_I];
+         }
+      }
+      else {	
+         Journal_DPrintfL( self->debug, 3, "is a normal node, setting ID[%d][%d] = %d.\n", dNode_I, nodeLocalDof_I, *currEqNum );
+         self->destinationArray[dNode_I][nodeLocalDof_I] = (*currEqNum)++;
+         if ( dNode_I < self->feMesh->nodeLocalCount ) {
+            self->_highestLocalEqNum = self->destinationArray[dNode_I][nodeLocalDof_I];
+         }	
+      }
+   }
+}
+
+
+void _FeEquationNumber_PostProcessLinkedDofs( FeEquationNumber* self ) {
+   Index			linkedDof_I;
+   int			valueToReduce;
+   int			minimumValue;
+   Node_Index		rNodeInfo_I;
+   Node_DomainIndex	dNode_I;
+   MeshDecomp*		meshDecomp = self->feMesh->layout->decomp;
+   Dof_Index		nodeLocalDof_I;
+   Dof_Index		currNodeNumDofs;
+   Index			linkedDofSet;
+   Bool*			adjustDueToNonLocalLinkedDofsTbl = NULL;
+   unsigned int		subtractionAdjustmentTotal;
+   Dof_EquationNumber      currEqNum;
+	
+   Journal_DPrintfL( self->debug, 1, "In Func %s():\n", __func__ );
+   adjustDueToNonLocalLinkedDofsTbl = Memory_Alloc_Array( Bool, self->linkedDofInfo->linkedDofSetsCount,
+                                                          "adjustDueToNonLocalLinkedDofsTbl" );
+		
+   /* We need to re-calculate these, since the post processing may alter both the lowest and higest eqNum values */
+   self->_lowestLocalEqNum = -1;
+   self->_highestLocalEqNum = -1;
+		
+   Journal_DPrintfL( self->debug, 2, "Note: in reductions to follow, value of %d, the node global count, "
+                     "denotes that this processor doesn't hold any of that linked dof.\n", self->feMesh->nodeGlobalCount );
+
+   Stream_Indent( self->debug );
+   for ( linkedDof_I=0; linkedDof_I < self->linkedDofInfo->linkedDofSetsCount; linkedDof_I++ ) {
+      if ( -1 != self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDof_I] ) {
+         valueToReduce = self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDof_I];
+      }
+      else {
+         valueToReduce = self->feMesh->nodeGlobalCount;
+      }	
+		
+      Journal_DPrintfL( self->debug, 2, "Reducing linked Dof %d: this proc has value %d\n", linkedDof_I, valueToReduce );
+      MPI_Allreduce( &valueToReduce, &minimumValue, 1, MPI_INT, MPI_MIN, meshDecomp->communicator );
+		
+      Journal_DPrintfL( self->debug, 2, "\tMinimum val = %d\n", minimumValue );
+      self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDof_I] = minimumValue;
+
+      if ( valueToReduce != minimumValue ) {
+         adjustDueToNonLocalLinkedDofsTbl[linkedDof_I] = True;
+      }
+      else {
+         adjustDueToNonLocalLinkedDofsTbl[linkedDof_I] = False;
+      }
+   }	
+   Stream_UnIndent( self->debug );
+	
+   Journal_DPrintfL( self->debug, 2, "Post-processing totals to correct based on non-local linked dofs\n" );
+   subtractionAdjustmentTotal = 0;
+	
+   Stream_Indent( self->debug );
+   for ( rNodeInfo_I = 0; rNodeInfo_I < self->feMesh->nodeDomainCount; rNodeInfo_I++ ) {
+      dNode_I = self->remappedNodeInfos[rNodeInfo_I].domain;
+      Journal_DPrintfL( self->debug, 3, "At remapped node %d (dNode %d):\n", rNodeInfo_I, dNode_I );
+      currNodeNumDofs = self->dofLayout->dofCounts[ dNode_I ];
+		
+      for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+
+         Stream_Indent( self->debug );
+         Journal_DPrintfL( self->debug, 3, "At dof %d: ", nodeLocalDof_I );
+		
+         if( self->bcs && VariableCondition_IsCondition( self->bcs, dNode_I,
+                                                         self->dofLayout->varIndices[dNode_I][nodeLocalDof_I] ) )
+         {
+            Journal_DPrintfL( self->debug, 3, "is a BC: ignoring.\n" );
+         }
+         else if ( self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I] != -1 ) {
+            linkedDofSet = self->linkedDofInfo->linkedDofTbl[dNode_I][nodeLocalDof_I];
+
+            Journal_DPrintfL( self->debug, 3, "is a linked Dof, so setting value to %d\n",
+                              self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] );
+
+            self->destinationArray[dNode_I][nodeLocalDof_I] -= subtractionAdjustmentTotal;
+
+            if ( True == adjustDueToNonLocalLinkedDofsTbl[linkedDofSet] ) {
+               /* We now need to test, after the subtraction adjustment has been made, if the 
+                  value of this linked dof now matches the minimum. If so, don't subtract further. */
+               if ( self->destinationArray[dNode_I][nodeLocalDof_I] != 
+                    self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet] )
+               {
+                  subtractionAdjustmentTotal++;
+                  Journal_DPrintfL( self->debug, 3, "And since first was non-local, increasing "
+                                    "subtraction adj. to %d\n", subtractionAdjustmentTotal );
+               }	
+						
+               /* Make sure we only adjust once */
+               adjustDueToNonLocalLinkedDofsTbl[linkedDofSet] = False;
+            }
+
+            self->destinationArray[dNode_I][nodeLocalDof_I] =
+               self->linkedDofInfo->eqNumsOfLinkedDofs[linkedDofSet];
+				
+         }
+         else {
+            Journal_DPrintfL( self->debug, 3, "subtracting %d\n", subtractionAdjustmentTotal );
+            self->destinationArray[dNode_I][nodeLocalDof_I] -= subtractionAdjustmentTotal;
+         }
+
+         currEqNum = self->destinationArray[dNode_I][nodeLocalDof_I];
+         if ( dNode_I < self->feMesh->nodeLocalCount ) {
+            if ( currEqNum != -1 ) {	/* TAG: bcs */
+               if ( self->_lowestLocalEqNum == -1 ) {
+                  /* We need this if statement to initialise this */
+                  self->_lowestLocalEqNum = currEqNum;
+               }	
+               else if ( currEqNum < self->_lowestLocalEqNum ) {
+                  self->_lowestLocalEqNum = currEqNum;
+               }
+
+               if ( currEqNum > self->_highestLocalEqNum ) {
+                  self->_highestLocalEqNum = currEqNum;
+               }	
+            }
+         }	
+         Stream_UnIndent( self->debug );
+      }	
+   }		
+   Stream_UnIndent( self->debug );
+
+   Memory_Free( adjustDueToNonLocalLinkedDofsTbl );
+}
+#endif
+
+
+Index FeEquationNumber_CalculateActiveEqCountAtNode(
+   void*			feEquationNumber,
+   Node_DomainIndex	dNode_I,
+   Dof_EquationNumber*	lowestActiveEqNumAtNodePtr )
+{
+   FeEquationNumber*	self = (FeEquationNumber*) feEquationNumber;
+   Dof_Index		nodalDof_I = 0;
+   Index			activeEqsAtCurrRowNode = 0;		
+   Dof_EquationNumber	currEqNum;
+   Bool			foundLowest = False;
+
+   for ( nodalDof_I = 0; nodalDof_I < self->dofLayout->dofCounts[dNode_I]; nodalDof_I++ ) {
+      currEqNum = self->destinationArray[dNode_I][nodalDof_I];
+      if ( currEqNum != -1 ) {
+         activeEqsAtCurrRowNode++;
+         if ( False == foundLowest ) {
+            (*lowestActiveEqNumAtNodePtr) = currEqNum;
+            foundLowest = True;
+         }
+      }
+   }
+
+   return activeEqsAtCurrRowNode;
+}
+
+
+void FeEquationNumber_BuildLocationMatrix( void* feEquationNumber ) {
+   FeEquationNumber*	self = (FeEquationNumber*)feEquationNumber;
+   FeMesh*			feMesh;
+   unsigned		nDims;
+   unsigned		nDomainEls;
+   unsigned		nLocalNodes;
+   unsigned*		nNodalDofs;
+   unsigned		nElNodes;
+   unsigned*		elNodes;
+   int**			dstArray;
+   int***			locMat;
+   IArray*			inc;
+   unsigned		e_i, n_i, dof_i;
+
+   assert( self );
+
+   /* Don't build if already done. */
+   if( self->locationMatrixBuilt ) {
+      Journal_DPrintf( self->debugLM, "In %s: LM already built, so just returning.\n",  __func__ );
+      Stream_UnIndentBranch( StgFEM_Debug );
+      return;
+   }
+
+   inc = IArray_New();
+
+   /* Shortcuts. */
+   feMesh = self->feMesh;
+   nDims = Mesh_GetDimSize( feMesh );
+   nDomainEls = FeMesh_GetElementDomainSize( feMesh );
+   nLocalNodes = FeMesh_GetNodeLocalSize( feMesh );
+   nNodalDofs = self->dofLayout->dofCounts;
+   dstArray = self->destinationArray;
+
+   /* Allocate for the location matrix. */
+   locMat = AllocArray( int**, nDomainEls );
+   for( e_i = 0; e_i < nDomainEls; e_i++ ) {
+      FeMesh_GetElementNodes( feMesh, e_i, inc );
+      nElNodes = IArray_GetSize( inc );
+      elNodes = (unsigned*)IArray_GetPtr( inc );
+      locMat[e_i] = AllocArray( int*, nElNodes );
+      for( n_i = 0; n_i < nElNodes; n_i++ )
+         locMat[e_i][n_i] = AllocArray( int, nNodalDofs[elNodes[n_i]] );
+   }
+
+   /* Build location matrix. */
+   for( e_i = 0; e_i < nDomainEls; e_i++ ) {
+      FeMesh_GetElementNodes( feMesh, e_i, inc );
+      nElNodes = IArray_GetSize( inc );
+      elNodes = (unsigned*)IArray_GetPtr( inc );
+      for( n_i = 0; n_i < nElNodes; n_i++ ) {
+         for( dof_i = 0; dof_i < nNodalDofs[elNodes[n_i]]; dof_i++ )
+            locMat[e_i][n_i][dof_i] = dstArray[elNodes[n_i]][dof_i];
+      }
+   }
+
+   NewClass_Delete( inc );
+
+   /* Store result. */
+   self->locationMatrix = locMat;
+}
+
+
+#if 0
+/** build the element location matrix mapping elements, element node, dof -> eq num */
+void FeEquationNumber_BuildLocationMatrix( FeEquationNumber* self ) {
+   FeMesh* mesh = self->feMesh;
+   Element_LocalIndex lElement_I;
+   Node_LocalIndex numNodesThisElement = 0;
+   Node_LocalIndex elLocalNode_I = 0;
+   Dof_Index numDofsThisNode = 0;
+   Dof_Index** dofCountsAtElementNodesArray = NULL;
+   Element_LocalIndex elementLocalCount = Mesh_GetLocalSize( mesh, Mesh_GetDimSize( mesh ) );
+
+   Journal_DPrintf( self->debug, "In %s():\n", __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+	
+   if (self->locationMatrixBuilt) {
+      Journal_DPrintf( self->debugLM, "In %s: LM already built, so just returning.\n",  __func__ );
+      Stream_UnIndentBranch( StgFEM_Debug );
+      return;
+   }
+
+   Journal_DPrintf( self->debugLM, "In %s: building over %d elements.\n",  __func__, elementLocalCount );
+
+   /* Allocate the LM 3D array using the Memory module, in 2 stage process */
+   dofCountsAtElementNodesArray = Memory_Alloc_3DSetup( elementLocalCount, 
+                                                        mesh->topo->nIncEls[nDims][MT_VERTEX] );
+
+   for ( lElement_I = 0; lElement_I < elementLocalCount; lElement_I++ ) {
+      numNodesThisElement = mesh->elementNodeCountTbl[lElement_I];
+
+      for( elLocalNode_I = 0; elLocalNode_I < numNodesThisElement; elLocalNode_I++) {
+         Node_LocalIndex dNode_I = mesh->elementNodeTbl[lElement_I][elLocalNode_I];
+         numDofsThisNode = self->dofLayout->dofCounts[dNode_I];
+         dofCountsAtElementNodesArray[lElement_I][elLocalNode_I] = numDofsThisNode;
+      }
+   }
+
+   self->locationMatrix = Memory_Alloc_3DComplex( Dof_EquationNumber, elementLocalCount, mesh->elementNodeCountTbl,
+                                                  dofCountsAtElementNodesArray, "FeEquationNumber->locationMatrix" );
+   /* Free the dof counts array:- we have to look up domain node numbers anyway later, might as
+      well just use the dof counts array then. */
+   Memory_Free( dofCountsAtElementNodesArray );
+
+   for ( lElement_I = 0; lElement_I < elementLocalCount; lElement_I++ ) {
+      FeEquationNumber_BuildOneElementLocationMatrix( self, lElement_I );
+   }	
+
+   self->locationMatrixBuilt = True;
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+#endif
+
+
+/** Build an element's local location matrix */
+Dof_EquationNumber** FeEquationNumber_BuildOneElementLocationMatrix( void* feEquationNumber, Element_LocalIndex lElement_I ) {
+   FeEquationNumber* self = (FeEquationNumber*)feEquationNumber;
+   /* Node_DomainIndex elLocalNode_I; */
+   Node_DomainIndex numNodesThisElement, *elInc;
+   Dof_EquationNumber** localLocationMatrix = NULL;
+   FeMesh* feMesh = self->feMesh;
+   /* Dof_Index numDofsThisNode = 0; */
+   IArray* inc;
+
+   inc = IArray_New();
+   FeMesh_GetElementNodes( feMesh, lElement_I, inc );
+   numNodesThisElement = IArray_GetSize( inc );
+   elInc = (Node_DomainIndex*)IArray_GetPtr( inc );
+
+   /* HACK: Make sure global element location matrix is built. */
+   if( !self->locationMatrixBuilt )
+      abort();
+
+   /* if ( big LM allocated ) set pointer into it correctly */
+   if ( self->locationMatrix ) {
+      /* set ptr to correct set of local nodes ptrs */
+      localLocationMatrix = self->locationMatrix[lElement_I];
+      Journal_DPrintfL( self->debugLM, 3, "set localLocationMatrix to pt. to big LM[%d] = %p\n",  lElement_I, self->locationMatrix[lElement_I] ) ;
+   }
+
+#if 0
+   else {
+      Dof_Index* numDofsEachNode = NULL;
+
+      /* allocate memory for local LM to return */
+      numDofsEachNode = Memory_Alloc_Array_Unnamed( Dof_Index, numNodesThisElement );
+
+      for( elLocalNode_I = 0; elLocalNode_I < numNodesThisElement; elLocalNode_I++) {
+         Node_LocalIndex localNode = mesh->elementNodeTbl[lElement_I][elLocalNode_I];
+         numDofsEachNode[elLocalNode_I] = self->dofLayout->dofCounts[localNode];
+      }
+
+      localLocationMatrix = Memory_Alloc_2DComplex( Dof_EquationNumber, numNodesThisElement, numDofsEachNode,
+                                                    "localLocationMatrix (set of ptrs to dof lists, indexed by element-local node)" );
+      Memory_Free( numDofsEachNode );
+   }
+#endif
+
+#if 0
+   /* If we haven't yet built full LM, copy ID values across */
+   if ( False == self->locationMatrixBuilt ) {
+      /* for (each el-local node) */
+      for ( elLocalNode_I = 0; elLocalNode_I < numNodesThisElement; elLocalNode_I++ ) {
+         /* look up processor local node number. */
+         Node_LocalIndex procDomainNode = mesh->elementNodeTbl[lElement_I][elLocalNode_I];
+         numDofsThisNode = self->dofLayout->dofCounts[procDomainNode];
+
+         /* copy pointers to dof eq nums from ID array relevant to that node */
+         Journal_DPrintfL( self->debugLM, 3, "copying %d dof eq. numbers from ID[%d] to LM[%d][%d]\n", 
+                           numDofsThisNode, procDomainNode, lElement_I, elLocalNode_I );
+         memcpy( localLocationMatrix[elLocalNode_I],
+                 self->destinationArray[procDomainNode], numDofsThisNode * sizeof(Dof_EquationNumber) );
+      }
+   }
+#endif
+
+   NewClass_Delete( inc );
+
+   return localLocationMatrix;
+}
+
+
+void FeEquationNumber_PrintDestinationArray( void* feFeEquationNumber, Stream* stream ) {
+   FeEquationNumber* self = (FeEquationNumber*) feFeEquationNumber;
+   FeMesh*		feMesh = self->feMesh;
+   MPI_Comm comm = Comm_GetMPIComm( Mesh_GetCommTopology( feMesh, MT_VERTEX ) );
+   unsigned rank;
+   Node_GlobalIndex gNode_I;
+   Node_GlobalIndex nodeGlobalCount = FeMesh_GetNodeGlobalSize( feMesh );
+
+   MPI_Comm_rank( comm, (int*)&rank );
+   Journal_Printf( stream, "%d: *** Printing destination array ***\n", rank );
+
+   for (gNode_I =0; gNode_I < nodeGlobalCount; gNode_I++) {
+      Node_DomainIndex dNode_I;
+
+      if ( !Mesh_GlobalToDomain( feMesh, MT_VERTEX, gNode_I, &dNode_I ) ) {
+         Journal_Printf( stream, "\tdestinationArray[(gnode)%2d]: on another proc\n", gNode_I);
+      }
+      else {
+         Dof_Index currNodeNumDofs = self->dofLayout->dofCounts[ dNode_I ];
+         Dof_Index nodeLocalDof_I;
+
+         Journal_Printf( stream, "\tdestinationArray[(gnode)%2d][(dof)0-%d]:",gNode_I, currNodeNumDofs );
+         for( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+            Journal_Printf( stream, "%3d, ", self->destinationArray[dNode_I][nodeLocalDof_I] );
+         }
+         Journal_Printf( stream, "\n" );
+      }
+   }		
+}
+
+void FeEquationNumber_PrintDestinationArrayBox( void* feFeEquationNumber, Stream* stream ) {
+	FeEquationNumber*   self = (FeEquationNumber*) feFeEquationNumber;
+	FeMesh*             feMesh = self->feMesh;
+	MPI_Comm            comm = Comm_GetMPIComm( Mesh_GetCommTopology( feMesh, MT_VERTEX ) );
+	unsigned            rank;
+	Grid*               vGrid;
+	unsigned            ijk[3];
+	Element_LocalIndex  lNode_I;
+	Node_GlobalIndex    gNode_I;
+	Node_Index          sizeI, sizeJ, sizeK;
+	Dof_Index           nDofs;
+	Dof_Index           dof_I;
+
+	MPI_Comm_rank( comm, (int*)&rank );
+	Journal_Printf( stream, "%d: *** Printing destination array ***\n", rank );
+	
+	vGrid = *Mesh_GetExtension( feMesh, Grid**, "vertexGrid" );
+	nDofs = self->dofLayout->dofCounts[0];
+	sizeI = vGrid->sizes[ I_AXIS ];
+	sizeJ = vGrid->sizes[ J_AXIS ];
+	sizeK = vGrid->sizes[ K_AXIS ] ? vGrid->sizes[ K_AXIS ] : 1;
+
+	for ( ijk[2] = 0 ; ijk[2] < sizeK ; ijk[2]++ ) {
+		if ( sizeK != 1 )
+			Journal_Printf( stream, "\nk = %d\n", ijk[2] );
+		for ( ijk[1] = sizeJ - 1 ; ijk[1] >= 0 ; ijk[1]-- ) {
+			Journal_Printf( stream, "%2d - ", ijk[1] );
+			for ( ijk[0] = 0 ; ijk[0] < sizeI ; ijk[0]++ ) {
+				gNode_I = Grid_Project( vGrid, ijk );
+				Journal_Printf( stream, "{ " );
+				if ( Mesh_GlobalToDomain( feMesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
+					for ( dof_I = 0 ; dof_I < nDofs ; dof_I++ )
+						Journal_Printf( stream, "%3d ", self->destinationArray[lNode_I][dof_I] );
+				}
+				else {
+					for ( dof_I = 0 ; dof_I < nDofs ; dof_I++ )
+						Journal_Printf( stream, " XX " );
+				}
+				Journal_Printf( stream, "}" );
+			}
+			Journal_Printf( stream, "\n" );
+		}
+		/* Bottom row */
+		Journal_Printf( stream, "    " );
+		for ( ijk[0] = 0 ; ijk[0] < sizeI ; ijk[0]++ ) {
+			Journal_Printf( stream, "    %3d    ", ijk[0] );
+			if ( nDofs == 3 )
+				Journal_Printf( stream, "    " );
+		}
+		Journal_Printf( stream, "\n" );
+	}	
+}
+
+void FeEquationNumber_PrintLocationMatrix( void* feFeEquationNumber, Stream* stream ) {
+   FeEquationNumber* self = (FeEquationNumber*) feFeEquationNumber;
+   FeMesh*		feMesh = self->feMesh;
+   MPI_Comm comm = Comm_GetMPIComm( Mesh_GetCommTopology( feMesh, MT_VERTEX ) );
+   unsigned rank;
+   Element_GlobalIndex gEl_I;
+   unsigned nDims = Mesh_GetDimSize( feMesh );
+   Element_GlobalIndex elementGlobalCount = FeMesh_GetElementGlobalSize( feMesh );
+   unsigned nLocalEls = FeMesh_GetElementLocalSize( feMesh );
+
+   Journal_Printf( stream, "%d: *** Printing location matrix ***\n", rank  );
+
+   MPI_Comm_rank( comm, (int*)&rank );
+	
+   for (gEl_I =0; gEl_I < elementGlobalCount; gEl_I++ ) {
+      Element_LocalIndex lEl_I;
+
+      if ( !Mesh_GlobalToDomain( feMesh, (MeshTopology_Dim)nDims, gEl_I, &lEl_I ) || lEl_I >= nLocalEls ) {
+         Journal_Printf( stream, "\tLM[(g/l el)%2d/XXX]: on another proc\n", gEl_I);
+      }
+      else {
+         Node_LocalIndex numNodesAtElement;
+         Node_LocalIndex elLocalNode_I;
+         unsigned*	incNodes;
+         IArray*		inc;
+
+         inc = IArray_New();
+         FeMesh_GetElementNodes( self->feMesh, lEl_I, inc );
+         numNodesAtElement = IArray_GetSize( inc );
+         incNodes = (unsigned*)IArray_GetPtr( inc );
+
+         Journal_Printf( stream, "\tLM[(g/l el)%2d/%2d][(enodes)0-%d]", gEl_I, lEl_I, numNodesAtElement);	
+         /* print the nodes and dofs */
+         for ( elLocalNode_I = 0; elLocalNode_I < numNodesAtElement; elLocalNode_I++ ) {
+            /* look up processor local node number. */
+            Element_LocalIndex currNode = incNodes[elLocalNode_I == 2 ? 3 : 
+                                                   elLocalNode_I == 3 ? 2 : 
+                                                   elLocalNode_I == 6 ? 7 : 
+                                                   elLocalNode_I == 7 ? 6 : 
+                                                   elLocalNode_I];
+            /* get the number of dofs at current node */
+            Dof_Index currNodeNumDofs = self->dofLayout->dofCounts[ currNode ];
+            Dof_Index nodeLocalDof_I;
+
+            Journal_Printf( stream, "({%2d}", currNode );
+            for( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+               Journal_Printf( stream, "%3d,", self->destinationArray[currNode][nodeLocalDof_I] );
+            }
+            Journal_Printf( stream, "), " );
+         }	
+
+         Journal_Printf( stream, "\n" );
+
+         NewClass_Delete( inc );
+      }
+
+   }
+}
+
+
+#if 0
+void FeEquationNumber_PrintElementLocationMatrix(
+   void*			feEquationNumber,
+   Dof_EquationNumber**	elementLM,
+   Element_LocalIndex	element_lI,
+   Stream*			stream )
+{
+   FeEquationNumber*	self = (FeEquationNumber*)feEquationNumber;
+   Dof_Index		dof_elLocalI;
+   Node_ElementLocalIndex	nodeCountThisEl = self->feMesh->elementNodeCountTbl[element_lI];
+   Node_LocalIndex		node_lI = self->feMesh->elementNodeTbl[element_lI][nodeCountThisEl-1];
+   Dof_Index		dofCountLastNode = self->dofLayout->dofCounts[node_lI];
+   Dof_Index		totalDofsThisElement = 0;
+	
+   totalDofsThisElement = &elementLM[nodeCountThisEl-1][dofCountLastNode-1] - &elementLM[0][0] + 1;
+
+   Journal_DPrintf( stream, "LM[ el %d ], dofs[0-%d] = {", element_lI, totalDofsThisElement );
+
+   for( dof_elLocalI=0; dof_elLocalI < totalDofsThisElement; dof_elLocalI++ ) {
+      Journal_DPrintf( stream, "%d, ", elementLM[0][dof_elLocalI] ); 
+   }
+   Journal_DPrintf( stream, "}\n" );
+}
+
+
+/* Calculates global sum unconstrained dofs */
+void _FeEquationNumber_CalculateGlobalUnconstrainedDofTotal( FeEquationNumber* self ) {
+   int	globalSumUnconstrainedDofs;
+   MeshDecomp* meshDecomp = self->feMesh->layout->decomp;
+	
+   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+   MPI_Allreduce( &self->_highestLocalEqNum, &globalSumUnconstrainedDofs, 1, MPI_INT, MPI_MAX, meshDecomp->communicator );
+   self->globalSumUnconstrainedDofs = (unsigned)(globalSumUnconstrainedDofs+1);
+	
+   Journal_DPrintf( self->debug, "Calculated total (across all processors) unconstrained dofs as:%d\n", self->globalSumUnconstrainedDofs  );
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+/* calculate the minimum and maximum parts that my processor is responsible for holding */
+void _FeEquationNumber_CalculateEqNumsDecomposition( FeEquationNumber* self ) {
+   MeshDecomp*		meshDecomp = self->feMesh->layout->decomp;
+   Partition_Index		myRank = meshDecomp->rank;
+   Partition_Index		nProc = meshDecomp->nproc;
+
+   Journal_DPrintfL( self->debug, 1, "In %s:\n",  __func__ );
+   Stream_IndentBranch( StgFEM_Debug );
+
+   if ( (self->remappingActivated) && ( (self->linkedDofInfo == NULL) || (self->linkedDofInfo->linkedDofSetsCount == 0 ) ) ) {
+      /* If the remapping is activated, and things aren't complicated by periodic BCs,
+         then each processor should hold the Matrix/Vector
+         component corresponding to the lowest local eqNum, to the lowest eqNum of the next
+         processor. This means that _only shared boundary nodes_ will need to be communicated,
+         and the last processor will have no communication. */
+      Journal_DPrintfL( self->debug, 2, "Remapping active and no periodic bcs: using lowest local eqNums as boundaries.\n");
+
+      self->_lowestGlobalEqNums = Memory_Alloc_Array( Dof_EquationNumber, nProc,
+                                                      "FeEquationNumber->_lowestGlobalEqNums" );
+      MPI_Allgather(
+         &self->_lowestLocalEqNum, 1, MPI_INT,
+         self->_lowestGlobalEqNums, 1, MPI_INT,
+         meshDecomp->communicator );
+
+      self->firstOwnedEqNum = self->_lowestLocalEqNum;
+      if (myRank == nProc-1) {
+         self->lastOwnedEqNum = self->_highestLocalEqNum;
+      }
+      else {
+         Node_LocalIndex nextProcLowestEqNum = self->_lowestGlobalEqNums[myRank+1] - 1;
+         if ( (unsigned int)-1 == nextProcLowestEqNum ) {
+            /* Pathological case of next proc having all B.C.s */
+            self->lastOwnedEqNum = self->_highestLocalEqNum;
+         }	
+         else {
+            self->lastOwnedEqNum = nextProcLowestEqNum;
+         }
+      }
+
+      self->localEqNumsOwnedCount = self->lastOwnedEqNum - self->firstOwnedEqNum + 1;	
+   }	
+   else {
+      /* If the remapping isn't activated and the eqNum ordering isn't aligned with the mesh
+         decomposition, or there are periodic BCs, we can't get a clear idea of where the processor boundaries are:
+         therefore just split up the EqNums equally between processors: still should be 
+         fairly good alignment. */
+      Journal_DPrintfL( self->debug, 2, "Remapping inactive and/or periodic bcs used: just dividing eqNums as evenly as possible.\n");
+
+      self->_eqNumsPerProcDivisor = self->globalSumUnconstrainedDofs / nProc;
+      self->_eqNumsRemainder = self->globalSumUnconstrainedDofs % nProc;
+      Journal_DPrintfL( self->debug, 2, "Calculated %d eqNums per proc, with %d remainder\n",
+                        self->_eqNumsPerProcDivisor, self->_eqNumsRemainder );
+      self->_remNotAddedChangeover = (self->_eqNumsPerProcDivisor+1) * self->_eqNumsRemainder;
+
+      self->localEqNumsOwnedCount = self->_eqNumsPerProcDivisor;
+      if ( myRank < self->_eqNumsRemainder ) {
+         self->localEqNumsOwnedCount++;
+      }
+
+      if ( myRank < self->_eqNumsRemainder ) {
+         self->firstOwnedEqNum = myRank * (self->_eqNumsPerProcDivisor+1);
+      }
+      else {
+         self->firstOwnedEqNum = self->_remNotAddedChangeover
+            + (myRank - self->_eqNumsRemainder) * self->_eqNumsPerProcDivisor;
+      }
+      self->lastOwnedEqNum = self->firstOwnedEqNum + self->localEqNumsOwnedCount - 1;
+   }	
+
+   Journal_DPrintfL( self->debug, 1, "Calculated I own %d eqNums, between indices %d to %d\n",
+                     self->localEqNumsOwnedCount, self->firstOwnedEqNum, self->lastOwnedEqNum );
+   Journal_DPrintfL( self->debug, 1, "(Range of eqNums on local mesh segment is %d to %d)\n",
+                     self->_lowestLocalEqNum, self->_highestLocalEqNum );
+
+   Stream_UnIndentBranch( StgFEM_Debug );
+}
+#endif
+
+
+Partition_Index FeEquationNumber_CalculateOwningProcessorOfEqNum( void* feEquationNumber, Dof_EquationNumber eqNum ) {
+   FeEquationNumber* self = (FeEquationNumber*)feEquationNumber;
+   /* Partition_Index ownerProc = (unsigned int)-1; */
+   Comm*	comm = Mesh_GetCommTopology( self->feMesh, MT_VERTEX );
+   MPI_Comm	mpiComm = Comm_GetMPIComm( comm );
+   unsigned	nProcs;
+   unsigned	p_i;
+
+   MPI_Comm_size( mpiComm, (int*)&nProcs );
+   for( p_i = 1; p_i < nProcs; p_i++ ) {
+      if( eqNum < self->_lowestGlobalEqNums[p_i] )
+         break;
+   }
+
+   return p_i - 1;
+
+#if 0
+   if ( (self->remappingActivated) && ( (self->linkedDofInfo == NULL) || (self->linkedDofInfo->linkedDofSetsCount == 0 ) ) ) {
+      MeshDecomp*		meshDecomp = self->feMesh->layout->decomp;
+      Partition_Index		myRank = meshDecomp->rank;
+      Partition_Index		nProc = meshDecomp->nproc;
+
+      /* Expect it to be on the next processor, so try there first */
+      if ( eqNum > self->lastOwnedEqNum ) {
+         ownerProc = myRank + 1;
+         while ( (ownerProc+1) < nProc ) {
+            if ( eqNum >= self->_lowestGlobalEqNums[ownerProc+1] ) {
+               ownerProc++;
+            }	
+            else {
+               break;
+            }	
+         }
+      }
+      /* otherwise count back from current */
+      else {
+         ownerProc = myRank;
+         while ( ownerProc > 0 ) {
+            if ( eqNum < self->_lowestGlobalEqNums[ownerProc] ) {
+               ownerProc--;
+            }
+            else {
+               break;
+            }	
+         }
+      }
+   }
+   else {
+      if ( eqNum < self->_remNotAddedChangeover ) {
+         ownerProc = eqNum / (self->_eqNumsPerProcDivisor+1);
+      }
+      else {
+         ownerProc = self->_eqNumsRemainder + (eqNum - self->_remNotAddedChangeover) / self->_eqNumsPerProcDivisor;
+      }
+   }
+}
+
+return ownerProc;
+#endif
+}	
+
+
+#if 0
+void FeEquationNumber_Create_CritPointInfo_MPI_Datatype( void ) {
+#define CRIT_POINT_INFO_NBLOCKS 2
+   MPI_Aint indexExtent = 0;
+   MPI_Datatype critPointInfoTypes[CRIT_POINT_INFO_NBLOCKS] = {MPI_UNSIGNED, MPI_INT };
+   MPI_Aint critPointInfoBlockDisplacements[CRIT_POINT_INFO_NBLOCKS];
+   int critPointInfoBlockLengths[CRIT_POINT_INFO_NBLOCKS] = { 1, 1 };
+
+   MPI_Type_extent(MPI_UNSIGNED, &indexExtent);
+   critPointInfoBlockDisplacements[0] = 0;
+   critPointInfoBlockDisplacements[1] = indexExtent;
+
+   MPI_Type_struct( CRIT_POINT_INFO_NBLOCKS, critPointInfoBlockLengths, critPointInfoBlockDisplacements,
+                    critPointInfoTypes, &MPI_critPointInfoType );
+	
+   MPI_Type_commit( &MPI_critPointInfoType );
+}
+#endif
+
+
+void FeEquationNumber_BuildWithTopology( FeEquationNumber* self ) {
+   Stream*		stream;
+   double		startTime, endTime, time, tmin, tmax;
+   FeMesh*		feMesh;
+   Sync*		sync;
+   Comm*		comm;
+   MPI_Comm		mpiComm;
+   unsigned		rank, nProcs;
+   unsigned		nDims;
+   unsigned		nDomainNodes;
+   unsigned		nLocalNodes;
+   unsigned*		nNodalDofs;
+   unsigned		nElNodes, *elNodes;
+   int**		dstArray;
+   int			*nLocMatDofs, ***locMat;
+   unsigned		varInd;
+   unsigned		curEqNum;
+   unsigned		base;
+   unsigned		subTotal;
+   MPI_Status		status;
+   unsigned		maxDofs;
+   unsigned*		tuples;
+   LinkedDofInfo*	links;
+   unsigned		highest;
+   IArray*		inc;
+   unsigned             e_i, n_i, dof_i, s_i;
+   int			ii;
+
+   assert( self );
+
+   inc = IArray_New();
+
+   stream = Journal_Register( Info_Type, (Name)self->type  );
+   Stream_SetPrintingRank( stream, 0 );
+
+   Journal_RPrintf( stream, "FeEquationNumber: '%s'\n", self->name );
+   Stream_Indent( stream );
+   Journal_RPrintf( stream, "Generating equation numbers...\n" );
+   Stream_Indent( stream );
+   if( self->removeBCs )
+      Journal_RPrintf( stream, "BCs set to be removed.\n" );
+   else
+      Journal_RPrintf( stream, "BCs will not be removed.\n" );
+
+   startTime = MPI_Wtime();
+
+   /* Shortcuts. */
+   feMesh = self->feMesh;
+   comm = Mesh_GetCommTopology( feMesh, MT_VERTEX );
+   mpiComm = Comm_GetMPIComm( comm );
+   MPI_Comm_size( mpiComm, (int*)&nProcs );
+   MPI_Comm_rank( mpiComm, (int*)&rank );
+   nDims = Mesh_GetDimSize( feMesh );
+   nDomainNodes = FeMesh_GetNodeDomainSize( feMesh );
+   self->nDomainEls = FeMesh_GetElementDomainSize( feMesh );
+   nLocalNodes = FeMesh_GetNodeLocalSize( feMesh );
+   nNodalDofs = self->dofLayout->dofCounts;
+   links = self->linkedDofInfo;
+
+   /* Allocate for destination array. */
+   dstArray = Memory_Alloc_2DComplex( int, nDomainNodes, nNodalDofs, 
+                                      "FeEquationNumber::destinationArray" );
+
+   /* If needed, allocate for linked equation numbers. */
+   if( links ) {
+      unsigned	s_i;
+
+      links->eqNumsOfLinkedDofs = ReallocArray( links->eqNumsOfLinkedDofs, int, links->linkedDofSetsCount );
+      for( s_i = 0; s_i < links->linkedDofSetsCount; s_i++ )
+         links->eqNumsOfLinkedDofs[s_i] = -1;
+   }
+
+   /* Allocate for the location matrix. */
+   nLocMatDofs = NULL;
+   locMat = AllocArray( int**, self->nDomainEls );
+   for( e_i = 0; e_i < self->nDomainEls; e_i++ ) {
+      FeMesh_GetElementNodes( feMesh, e_i, inc );
+      nElNodes = IArray_GetSize( inc );
+      elNodes = (unsigned*)IArray_GetPtr( inc );
+      nLocMatDofs = ReallocArray( nLocMatDofs, int, nElNodes );
+      for( n_i = 0; n_i < nElNodes; n_i++ )
+         nLocMatDofs[n_i] = nNodalDofs[elNodes[n_i]];
+      locMat[e_i] = AllocComplex2D( int, nElNodes, (Index*)nLocMatDofs );
+   }
+   FreeArray( nLocMatDofs );
+
+   /* Build initial destination array and store max dofs. */
+   curEqNum = 0;
+   maxDofs = 0;
+   for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
+      if( nNodalDofs[n_i] > maxDofs )
+         maxDofs = nNodalDofs[n_i];
+
+      for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
+         varInd = self->dofLayout->varIndices[n_i][dof_i];
+         if( !self->bcs || !VariableCondition_IsCondition( self->bcs, n_i, varInd ) || 
+             !self->removeBCs )
+         {
+            if( links && links->linkedDofTbl[n_i][dof_i] != -1 ) {
+               if( rank > 0 ) {
+                  dstArray[n_i][dof_i] = -2;
+                  continue;
+               }
+               if( links->eqNumsOfLinkedDofs[links->linkedDofTbl[n_i][dof_i]] == -1 )
+                  links->eqNumsOfLinkedDofs[links->linkedDofTbl[n_i][dof_i]] = curEqNum++;
+               dstArray[n_i][dof_i] = links->eqNumsOfLinkedDofs[links->linkedDofTbl[n_i][dof_i]];
+            }
+            else
+               dstArray[n_i][dof_i] = curEqNum++;
+         }
+         else
+            dstArray[n_i][dof_i] = -1;
+      }
+   }
+
+   /* Order the equation numbers based on processor rank; cascade counts forward. */
+   base = 0;
+   if( rank > 0 )
+      MPI_Recv( &base, 1, MPI_UNSIGNED, rank - 1, 6669, mpiComm, &status );
+   subTotal = base + curEqNum;
+   if( rank < nProcs - 1 )
+      MPI_Send( &subTotal, 1, MPI_UNSIGNED, rank + 1, 6669, mpiComm );
+
+   if( links ) {
+      /* Reduce to find lowest linked DOFs. */
+      for( s_i = 0; s_i < links->linkedDofSetsCount; s_i++ ) {
+         if( links->eqNumsOfLinkedDofs[s_i] != -1 )
+            links->eqNumsOfLinkedDofs[s_i] += base;
+/*
+  MPI_Allreduce( links->eqNumsOfLinkedDofs + s_i, &lowest, 1, MPI_UNSIGNED, MPI_MAX, mpiComm );
+*/
+         MPI_Allreduce( links->eqNumsOfLinkedDofs + s_i, &highest, 1, MPI_INT, MPI_MAX, mpiComm );
+/*
+  assert( (lowest == (unsigned)-1) ? lowest == highest : 1 );
+*/
+         links->eqNumsOfLinkedDofs[s_i] = highest;
+      }
+   }
+
+   /* Modify existing destination array and dump to a tuple array. */
+   tuples = AllocArray( unsigned, nDomainNodes * maxDofs );
+   for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
+      for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
+         varInd = self->dofLayout->varIndices[n_i][dof_i];
+         if( !self->bcs || !VariableCondition_IsCondition( self->bcs, n_i, varInd ) || 
+             !self->removeBCs )
+         {
+            if( links && links->linkedDofTbl[n_i][dof_i] != -1 ) {
+               highest = links->eqNumsOfLinkedDofs[links->linkedDofTbl[n_i][dof_i]];
+               dstArray[n_i][dof_i] = highest;
+            }
+            else
+               dstArray[n_i][dof_i] += base;
+         }
+         tuples[n_i * maxDofs + dof_i] = dstArray[n_i][dof_i];
+      }
+   }
+
+   /* Update all other procs. */
+   sync = Mesh_GetSync( feMesh, MT_VERTEX );
+   Sync_SyncArray( sync, tuples, maxDofs * sizeof(unsigned), 
+                   tuples + nLocalNodes * maxDofs, maxDofs * sizeof(unsigned), 
+                   maxDofs * sizeof(unsigned) );
+
+   /* Update destination array's domain indices. */
+   for( n_i = nLocalNodes; n_i < nDomainNodes; n_i++ ) {
+      for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
+         varInd = self->dofLayout->varIndices[n_i][dof_i];
+         if( !self->bcs || !VariableCondition_IsCondition( self->bcs, n_i, varInd ) || 
+             !self->removeBCs )
+         {
+            dstArray[n_i][dof_i] = tuples[n_i * maxDofs + dof_i];
+         }
+         else
+            dstArray[n_i][dof_i] = -1;
+      }
+   }
+
+   /* Destroy tuple array. */
+   FreeArray( tuples );
+
+   /* Build location matrix. */
+   for( e_i = 0; e_i < self->nDomainEls; e_i++ ) {
+      FeMesh_GetElementNodes( feMesh, e_i, inc );
+      nElNodes = IArray_GetSize( inc );
+      elNodes = (unsigned*)IArray_GetPtr( inc );
+      for( n_i = 0; n_i < nElNodes; n_i++ ) {
+         for( dof_i = 0; dof_i < nNodalDofs[elNodes[n_i]]; dof_i++ )
+            locMat[e_i][n_i][dof_i] = dstArray[elNodes[n_i]][dof_i];
+      }
+   }
+
+   /* Store stuff on class. */
+   self->destinationArray = dstArray;
+   self->locationMatrix = locMat;
+   self->locationMatrixBuilt = True;
+   self->remappingActivated = False;
+   self->localEqNumsOwnedCount = curEqNum;
+   self->firstOwnedEqNum = base;
+   self->lastOwnedEqNum = subTotal - 1;
+   self->_lowestLocalEqNum = self->firstOwnedEqNum;
+
+   /* Setup owned mapping. */
+   STree_Clear( self->ownedMap );
+   for( ii = self->firstOwnedEqNum; ii <= self->lastOwnedEqNum; ii++ ) {
+      int val = ii - self->firstOwnedEqNum;
+      STreeMap_Insert( self->ownedMap, &ii, &val );
+   }
+
+   /* Bcast global sum from highest rank. */
+   if( rank == nProcs - 1 )
+      self->globalSumUnconstrainedDofs = self->lastOwnedEqNum + 1;
+   MPI_Bcast( &self->globalSumUnconstrainedDofs, 1, MPI_UNSIGNED, nProcs - 1, mpiComm );
+
+   /* Construct lowest global equation number list. */
+   self->_lowestGlobalEqNums = AllocArray( int, nProcs );
+   MPI_Allgather( &self->firstOwnedEqNum, 1, MPI_UNSIGNED, self->_lowestGlobalEqNums, 1, MPI_UNSIGNED, mpiComm );
+
+   endTime = MPI_Wtime();
+
+   Journal_RPrintf( stream, "Assigned %d global equation numbers.\n", self->globalSumUnconstrainedDofs );
+   Journal_Printf( stream, "[%u] Assigned %d local equation numbers, within range %d to %d.\n", 
+                   rank, self->lastOwnedEqNum - self->firstOwnedEqNum + 1, self->firstOwnedEqNum, self->lastOwnedEqNum + 1 );
+   Stream_UnIndent( stream );
+
+   time = endTime - startTime;
+   MPI_Reduce( &time, &tmin, 1, MPI_DOUBLE, MPI_MIN, 0, mpiComm );
+   MPI_Reduce( &time, &tmax, 1, MPI_DOUBLE, MPI_MAX, 0, mpiComm );
+   Journal_RPrintf( stream, "... Completed in %g [min] / %g [max] seconds.\n", tmin, tmax );
+   Stream_UnIndent( stream );
+
+   NewClass_Delete( inc );
+}
+
+#if 0
+void FeEquationNumber_BuildVariableIndices( FeEquationNumber* self, int* nInds, int** inds, int* maxDofs ) {
+   int maxDofs;
+   ISet indSetObj, *indSet = &indSetObj;
+
+   *maxDofs = 0;
+   for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
+      if( nNodalDofs[n_i] > *maxDofs )
+         *maxDofs = nNodalDofs[n_i];
+   }
+
+   ISet_Construct( indSet );
+   ISet_SetMaxSize( indSet, *maxDofs );
+   for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
+      for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
+         varInd = self->dofLayout->varIndices[n_i][dof_i];
+         ISet_TryInsert( indSet, varInd );
+      }
+   }
+
+   *nInds = ISet_GetSize( indSet );
+   *inds = MemArray( int, *nInds, FeEquationNumber_Type );
+   ISet_GetArray( indSet, NULL, inds );
+   ISet_Destruct( indSet );
+}
+#endif
+
+
+#if 0
+void FeEquationNumber_Invert( void* feEqNum, int equation, unsigned* node, unsigned* dof ) {
+   FeEquationNumber*	self = (FeEquationNumber*)feEqNum;
+
+   assert( self && Stg_CheckType( self, FeEquationNumber ) );
+   assert( equation - self->firstOwnedEqNum < self->localEqNumsOwnedCount );
+   assert( node );
+   assert( dof );
+
+   eq = equation - self->firstOwnedEqNum;
+   *node = self->eqToNode[eq];
+   *dof = self->eqToDof[eq];
+}
+
+Bool FeEquationNumber_IsKnown( void* feEqNum, int equation ) {
+   FeEquationNumber*	self = (FeEquationNumber*)feEqNum;
+   unsigned		node, dof;
+   unsigned		varInd;
+
+   assert( self && Stg_CheckType( self, FeEquationNumber ) );
+
+   if( !self->bcs ) return False;
+   FeEquationNumber_Invert( self, equation, &node, &dof );
+
+   assert( self->dofLayout );
+   assert( self->dofLayout->varIndices );
+   assert( self->dofLayout->varIndices[node] );
+   varInd = self->dofLayout->varIndices[node][dof];
+   return VariableCondition_IsCondition( self->bcs, n_i, varInd );
+}
+#endif
+
+
+int GenerateEquationNumbering(
+		int NX, int NY, int NZ,
+		int nlocal, int g_node_id[],
+		int dof, int nglobal,
+		PetscTruth periodic_x, PetscTruth periodic_y, PetscTruth periodic_z,
+		int npx, int npy, int npz,
+		int periodic_x_gnode_id[], int periodic_y_gnode_id[], int periodic_z_gnode_id[],
+		int eqnums[], int *neqnums );
+
+void FeEquationNumber_BuildWithDave( FeEquationNumber* self ) {
+   int nLocals, *locals;
+   Grid *vGrid;
+   int varInd;
+   int nEqNums, **dstArray;
+   IArray *inc;
+   int nDofs;
+   int *periodic;
+   int ***locMat;
+   int nDims;
+   int *elNodes;
+   Comm *comm;
+   MPI_Comm mpiComm;
+   int nRanks, rank;
+   Sync *sync;
+   Bool isCond;
+   int nPeriodicInds[3];
+   int *periodicInds[3];
+   int inds[3];
+   Bool usePeriodic;
+   int *tmpArray, nLocalEqNums;
+   int lastOwnedEqNum, ind;
+   STree *doneSet;
+   int ii, jj, kk;
+
+   comm = Mesh_GetCommTopology( self->feMesh, (MeshTopology_Dim)0 );
+   mpiComm = Comm_GetMPIComm( comm );
+   MPI_Comm_size( mpiComm, &nRanks );
+   MPI_Comm_rank( mpiComm, &rank );
+
+   /* Setup an array containing global indices of all locally owned nodes. */
+   nLocals = Mesh_GetLocalSize( self->feMesh, (MeshTopology_Dim)0 );
+   locals = AllocArray( int, nLocals );
+   for( ii = 0; ii < nLocals; ii++ )
+      locals[ii] = Mesh_DomainToGlobal( self->feMesh, (MeshTopology_Dim)0, ii );
+
+   /* Allocate for destination array. */
+   nDofs = self->dofLayout->dofCounts[0];
+   dstArray = AllocArray2D( int, Mesh_GetDomainSize( self->feMesh, (MeshTopology_Dim)0 ), nDofs );
+
+   /* Get the vertex grid extension and any periodicity. */
+   nDims = Mesh_GetDimSize( self->feMesh );
+   vGrid = *Mesh_GetExtension( self->feMesh, Grid**, "vertexGrid" );
+   periodic = Mesh_GetExtension( self->feMesh, int*, "periodic" );
+
+   /* Fill destination array with initial values, setting dirichlet BCs as we go. */
+   for( ii = 0; ii < nLocals; ii++ ) {
+     Grid_Lift( vGrid, locals[ii], (unsigned*)inds );
+      usePeriodic = False;
+      for( jj = 0; jj < nDims; jj++ ) {
+        if( periodic[jj] && (inds[jj] == 0 || inds[jj] == (int)(vGrid->sizes[jj] - 1)) ) {
+            usePeriodic = True;
+	    break;
+	 }
+      }
+      for( jj = 0; jj < nDofs; jj++ ) {
+         varInd = self->dofLayout->varIndices[ii][jj];
+	 if( self->bcs )
+	    isCond = VariableCondition_IsCondition( self->bcs, ii, varInd );
+	 else
+	    isCond = False;
+         if( isCond && self->removeBCs )
+            dstArray[ii][jj] = -1;
+         else
+            dstArray[ii][jj] = 0;
+      }
+   }
+
+   /* Generate opposing indices for periodicity. */
+   for( ii = 0; ii < nDims; ii++ ) {
+      nPeriodicInds[ii] = 0;
+      periodicInds[ii] = NULL;
+      if( periodic[ii] ) {
+	 periodicInds[ii] = AllocArray( int, nLocals );
+	 for( jj = 0; jj < nLocals; jj++ ) {
+           Grid_Lift( vGrid, locals[jj], (unsigned*)inds );
+           if( inds[ii] != (int)(vGrid->sizes[ii] - 1) ) continue;
+/*
+            for( kk = 0; kk < nDofs; kk++ )
+               if( dstArray[jj][kk] == -1 ) break;
+            if( kk < nDofs ) continue;
+*/
+            periodicInds[ii][nPeriodicInds[ii]++] = locals[jj];
+	 }
+      }
+   }
+
+   /* Call Dave's equation number generation routine. */
+   if( nDims == 2 ) {
+      GenerateEquationNumbering( vGrid->sizes[0], vGrid->sizes[1], 1,
+				 nLocals, locals,
+				 nDofs, Mesh_GetGlobalSize( self->feMesh, (MeshTopology_Dim)0 ),
+				 (PetscTruth)periodic[0], (PetscTruth)periodic[1], (PetscTruth)False,
+				 nPeriodicInds[0], nPeriodicInds[1], 0,
+				 periodicInds[0], periodicInds[1], NULL,
+				 dstArray[0], &nEqNums );
+   }
+   else {
+      GenerateEquationNumbering( vGrid->sizes[0], vGrid->sizes[1], vGrid->sizes[2],
+				 nLocals, locals,
+				 nDofs, Mesh_GetGlobalSize( self->feMesh, (MeshTopology_Dim)0 ),
+				 (PetscTruth)periodic[0], (PetscTruth)periodic[1], (PetscTruth)periodic[2],
+				 nPeriodicInds[0], nPeriodicInds[1], nPeriodicInds[2],
+				 periodicInds[0], periodicInds[1], periodicInds[2],
+				 dstArray[0], &nEqNums );
+   }
+
+   /* Free periodic arrays. */
+   for( ii = 0; ii < nDims; ii++ ) {
+      if( periodicInds[ii] )
+	 FreeArray( periodicInds[ii] );
+   }
+
+   /* Setup owned mapping part 1. */
+   STree_Clear( self->ownedMap );
+   for( ii = 0; ii < nLocals; ii++ ) {
+     Grid_Lift( vGrid, locals[ii], (unsigned*)inds );
+      for( jj = 0; jj < nDims; jj++ ) {
+        if( periodic[jj] && inds[jj] == (int)(vGrid->sizes[jj] - 1) ) {
+            inds[jj] = 0;
+            ind = Grid_Project( vGrid, (unsigned*)inds );
+            if( !FeMesh_NodeGlobalToDomain( self->feMesh, ind, (unsigned*)(&ind) ) )
+               break;
+         }
+      }
+      if( jj < nDims ) continue;
+      for( jj = 0; jj < nDofs; jj++ ) {
+	 if( dstArray[ii][jj] == -1 || STreeMap_HasKey( self->ownedMap, dstArray[ii] + jj ) )
+            continue;
+	 STreeMap_Insert( self->ownedMap, dstArray[ii] + jj, &ii );
+      }
+   }
+
+   /* Setup owned mapping. */
+   tmpArray = AllocArray( int, nLocals * nDofs );
+   memcpy( tmpArray, dstArray[0], nLocals * nDofs * sizeof(int) );
+   qsort( tmpArray, nLocals * nDofs, sizeof(int), stgCmpInt );
+   doneSet = STree_New();
+   STree_SetItemSize( doneSet, sizeof(int) );
+   STree_SetIntCallbacks( doneSet );
+   for( nLocalEqNums = 0, ii = 0; ii < nLocals * nDofs; ii++ ) {
+      if( tmpArray[ii] != -1 &&
+          STreeMap_HasKey( self->ownedMap, tmpArray + ii ) &&
+          !STree_Has( doneSet, tmpArray + ii ) )
+      {
+	 if( !nLocalEqNums )
+	    self->_lowestLocalEqNum = tmpArray[ii];
+	 *(int*)STreeMap_Map( self->ownedMap, tmpArray + ii ) = nLocalEqNums;
+         STree_Insert( doneSet, tmpArray + ii );
+	 nLocalEqNums++;
+      }
+   }
+   lastOwnedEqNum = -1; /* Don't need this anymore. */
+   FreeArray( tmpArray );
+   NewClass_Delete( doneSet );
+
+   /* Transfer remote equation numbers. */
+   sync = Mesh_GetSync( self->feMesh, (MeshTopology_Dim)0 );
+   Sync_SyncArray( sync, dstArray[0], nDofs * sizeof(int),
+                   dstArray[0] + nLocals * nDofs, nDofs * sizeof(int),
+                   nDofs * sizeof(int) );
+
+   /* Allocate for location matrix. */
+   /* first store nDomainEls for usage during destroy */
+   self->nDomainEls = Mesh_GetDomainSize( self->feMesh, (MeshTopology_Dim)nDims );
+   locMat = AllocArray( int**, self->nDomainEls );
+   for( ii = 0; ii < (int)(self->nDomainEls); ii++ )
+      locMat[ii] = AllocArray2D( int, FeMesh_GetElementNodeSize( self->feMesh, 0 ), nDofs );
+
+   /* Fill in location matrix. */
+   inc = IArray_New();
+   for( ii = 0; ii < (int)Mesh_GetDomainSize( self->feMesh, (MeshTopology_Dim)nDims ); ii++ ) {
+      FeMesh_GetElementNodes( self->feMesh, ii, inc );
+      elNodes = IArray_GetPtr( inc );
+      for( jj = 0; jj < (int)FeMesh_GetElementNodeSize( self->feMesh, 0 ); jj++ ) {
+         for( kk = 0; kk < nDofs; kk++ )
+            locMat[ii][jj][kk] = dstArray[elNodes[jj]][kk];
+      }
+   }
+   NewClass_Delete( inc );
+
+   /* Fill in our other weird values. */
+   self->destinationArray = dstArray;
+   self->locationMatrix = locMat;
+   self->locationMatrixBuilt = True;
+   self->remappingActivated = False;
+   self->localEqNumsOwnedCount = nLocalEqNums;
+
+   /* Bcast global sum from highest rank. */
+   self->globalSumUnconstrainedDofs = nEqNums;
+
+   /* Construct lowest global equation number list. */
+   self->_lowestGlobalEqNums = AllocArray( int, nRanks );
+   MPI_Allgather( &self->_lowestLocalEqNum, 1, MPI_UNSIGNED, 
+                  self->_lowestGlobalEqNums, 1, MPI_UNSIGNED,
+                  mpiComm );
+
+   FreeArray( locals );
+
+   /* 
+   printf( "%d: localEqNumsOwned = %d\n", rank, self->localEqNumsOwnedCount );
+   printf( "%d: globalSumUnconstrainedDofs = %d\n", rank, self->globalSumUnconstrainedDofs );
+   */
+}
+
+
+
+
+/*
+
+Input:
+  nlocal - number of locally ownded nodes
+  g_node_id - global indices of nodes owned locally. Size nlocal
+  dof - degrees of freedom per node
+  nglobal - number of global nodes
+  npx - number of consider to be periodic in x (local to this proc)
+  npy - number of consider to be periodic in y (local to this proc)
+  periodic_x_gnode_id - global indices of nodes (on this proc) which are on right hand side boundary
+  periodic_y_gnode_id - global indices of nodes (on this proc) which are on top boundary
+  eqnums - contains any dirichlet boundary conditions. Size nlocal*dof
+
+Output;
+  eqnums - contains full list of eqnums
+
+Assumptions: 
+- Ordering eqnums[] = { (node_0,[dof_0,dof_1,..,dof_x]), (node_1,[dof_0,dof_1,..,dof_x]), ... }
+- Any dirichlet set along a boundary deemed to be periodic will be clobbered.
+- Processors may have duplicate nodes in the g_node_id[] list.
+- A number in the corner is considered part of both boundaries (horiz and vert)
+- If npx is not 0, then periodicity is assumed in x
+- If npy is not 0, then periodicity is assumed in y
+- Dofs constrained to be dirichlet must be marked with a negative number.
+- Dofs are NOT split across processors.
+- We can define a logical i,j,k ordering to uniquely identify nodes.
+
+*/
+
+PetscErrorCode _VecScatterBeginEnd( VecScatter vscat, Vec FROM, Vec TO, InsertMode addv,ScatterMode mode )
+{
+#if( (PETSC_VERSION_MAJOR==2) && (PETSC_VERSION_MINOR==3) && (PETSC_VERSION_SUBMINOR==2) )
+	// 2.3.2 ordering of args
+	VecScatterBegin( FROM, TO, addv, mode, vscat );
+	VecScatterEnd( FROM, TO, addv, mode, vscat );
+#else
+	// 2.3.3 or 3.0.0
+	VecScatterBegin( vscat, FROM, TO, addv, mode );
+	VecScatterEnd( vscat, FROM, TO, addv, mode );
+#endif
+	
+	PetscFunctionReturn(0);
+}
+
+int GenerateEquationNumbering(
+		int NX, int NY, int NZ,
+		int nlocal, int g_node_id[],
+		int dof, int nglobal,
+		PetscTruth periodic_x, PetscTruth periodic_y, PetscTruth periodic_z,
+		int npx, int npy, int npz,
+		int periodic_x_gnode_id[], int periodic_y_gnode_id[], int periodic_z_gnode_id[],
+		int eqnums[], int *neqnums )
+{
+	PetscErrorCode ierr;
+	PetscInt periodic_mask;
+	Vec global_eqnum, g_ownership;
+	PetscInt i;
+	PetscMPIInt rank;        /* processor rank */
+	PetscMPIInt size;        /* size of communicator */
+	Vec local_ownership, local_eqnum;
+	PetscInt *_g_node_id;
+	IS is_gnode, is_eqnum;
+	VecScatter vscat_ownership, vscat_eqnum;
+	PetscScalar *_local_ownership, *_local_eqnum;
+	PetscInt local_eqnum_count,global_eqnum_count;
+	PetscScalar val[10];
+	PetscInt d,idx[10];
+	PetscInt *to_fetch,cnt,number_to_fetch;
+	PetscInt eq_cnt;
+	Vec offset_list;
+	VecScatter vscat_offset;
+	Vec seq_offset_list;
+	PetscInt offset, inc;
+	
+	PetscInt spanx,spany,spanz,total;
+	PetscInt loc;
+	PetscReal max;
+	PetscInt n_inserts;
+	
+	
+	ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
+	ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
+	
+	if( dof>=10 ) {
+		SETERRQ(PETSC_ERR_SUP, "Max allowable degrees of freedom per node = 10. Change static size" );
+	}
+	
+	
+	/* 
+	Claim locally owned nodes. Duplicate nodes on the interior will be resolved by the processor
+	which inserts last.
+	*/
+	VecCreate( PETSC_COMM_WORLD, &g_ownership );
+	VecSetSizes( g_ownership, PETSC_DECIDE, nglobal );
+	VecSetFromOptions( g_ownership );
+	
+	for( i=0; i<nlocal; i++ ) {
+		VecSetValue( g_ownership, g_node_id[i], rank, INSERT_VALUES );
+	}
+	VecAssemblyBegin(g_ownership);
+	VecAssemblyEnd(g_ownership);
+	
+	
+	/* Mask out the periodic boundaries. */
+	periodic_mask = -6699.0;
+	if (periodic_x_gnode_id!=NULL) {
+		for( i=0; i<npx; i++ ) {
+			VecSetValue( g_ownership, periodic_x_gnode_id[i], periodic_mask, INSERT_VALUES );
+		}
+	}
+	if (periodic_y_gnode_id!=NULL) {
+		for( i=0; i<npy; i++ ) {
+			VecSetValue( g_ownership, periodic_y_gnode_id[i], periodic_mask, INSERT_VALUES );
+		}
+	}
+	if (periodic_z_gnode_id!=NULL) {
+		for( i=0; i<npz; i++ ) {
+			VecSetValue( g_ownership, periodic_z_gnode_id[i], periodic_mask, INSERT_VALUES );
+		}
+	}
+	VecAssemblyBegin(g_ownership);
+	VecAssemblyEnd(g_ownership);
+	
+	/*
+	PetscPrintf(PETSC_COMM_WORLD, "g_ownership \n");
+	VecView( g_ownership, PETSC_VIEWER_STDOUT_WORLD );
+	*/
+	
+	/* Get all locally owned nodes */
+	VecCreate( PETSC_COMM_SELF, &local_ownership );
+	VecSetSizes( local_ownership, PETSC_DECIDE, nlocal );
+	VecSetFromOptions( local_ownership );
+	
+	PetscMalloc( sizeof(PetscInt)*nlocal, &_g_node_id);
+	for( i=0; i<nlocal; i++ ) {
+		_g_node_id[i] = g_node_id[i]; 
+	}
+	ISCreateGeneralWithArray( PETSC_COMM_WORLD, nlocal, _g_node_id, &is_gnode );
+	VecScatterCreate( g_ownership, is_gnode, local_ownership, PETSC_NULL, &vscat_ownership );
+	
+	
+	/* assign unique equation numbers */
+	VecSet( local_ownership, -6699 );
+	_VecScatterBeginEnd( vscat_ownership, g_ownership, local_ownership, INSERT_VALUES, SCATTER_FORWARD );
+	
+	
+	/* Count instances of rank in the local_ownership vector */
+	VecGetArray( local_ownership, &_local_ownership );
+	local_eqnum_count = 0;
+	for( i=0; i<nlocal; i++ ) {
+		if( ((PetscInt)_local_ownership[i]) == rank ) {
+			local_eqnum_count++;
+		}
+	}
+	
+	MPI_Allreduce( &local_eqnum_count, &global_eqnum_count, 1, MPI_INT, MPI_SUM, PETSC_COMM_WORLD );
+	/* PetscPrintf( PETSC_COMM_SELF, 
+	    "[%d] number of local,global equations (without dofs) %d,%d \n", rank, local_eqnum_count, global_eqnum_count ); */
+	/* check */
+	spanx = NX;
+	spany = NY;
+	spanz = NZ;
+	if( periodic_x==PETSC_TRUE ) {
+		spanx--;
+	}
+	if( periodic_y==PETSC_TRUE ) {
+		spany--;
+	}
+	if( periodic_z==PETSC_TRUE ) {
+		spanz--;
+	}
+	total = spanx*spany*spanz;
+	if( total!=global_eqnum_count ) {
+		SETERRQ(PETSC_ERR_SUP, "Something stinks. Computed global size for nodes does not match expected" );
+	}
+	
+	
+	
+	VecCreate( PETSC_COMM_WORLD, &global_eqnum );
+	VecSetSizes( global_eqnum, PETSC_DECIDE, nglobal*dof );
+	VecSetFromOptions( global_eqnum );
+	VecSet( global_eqnum, 0.0 );
+	
+	/* Load existing eqnums in */
+	for( i=0; i<nlocal; i++ ) {
+		n_inserts = 0;
+		for( d=0; d<dof; d++ ) {
+/*
+			idx[d] = -(g_node_id[i]*dof + d);
+			val[d] = 0.0;
+*/
+			if( eqnums[ i*dof + d ] < 0.0 ) {
+				idx[n_inserts] = g_node_id[i]*dof + d;
+				val[n_inserts] = eqnums[ i*dof + d ];
+				n_inserts++;
+			}
+		}
+		/* only insert dirichlet bc's */
+		VecSetValues( global_eqnum, n_inserts, idx, val, INSERT_VALUES );
+	}
+	VecAssemblyBegin(global_eqnum);
+	VecAssemblyEnd(global_eqnum);
+	
+	
+	
+	
+	
+	/* Generate list of eqnums to get */
+	PetscMalloc( sizeof(PetscInt)*nlocal*dof, &to_fetch );
+	cnt = 0;
+	for( i=0; i<nlocal; i++ ) {
+		if( _local_ownership[i]==rank ) {
+			for( d=0; d<dof; d++ ) {
+				to_fetch[cnt] = g_node_id[i]*dof + d;
+				cnt++;
+			}
+		}
+	}
+	number_to_fetch = cnt;
+	
+	
+	VecCreate( PETSC_COMM_SELF, &local_eqnum );
+	VecSetSizes( local_eqnum, PETSC_DECIDE, number_to_fetch);
+	VecSetFromOptions( local_eqnum );
+	
+	ISCreateGeneralWithArray( PETSC_COMM_SELF, number_to_fetch, to_fetch, &is_eqnum );
+	VecScatterCreate( global_eqnum, is_eqnum, local_eqnum, PETSC_NULL, &vscat_eqnum );
+	
+	VecSet( local_eqnum, -6699 );
+	_VecScatterBeginEnd( vscat_eqnum, global_eqnum, local_eqnum, INSERT_VALUES, SCATTER_FORWARD );
+	
+	
+	/* compute offset */
+	/* count how many entries there are */
+	VecGetArray( local_eqnum, &_local_eqnum );
+	eq_cnt = 0;
+	for( i=0; i<number_to_fetch; i++ ) {
+		if( (PetscInt)_local_eqnum[i]==0 ) {
+			eq_cnt++;
+		}
+	}
+	VecRestoreArray( local_eqnum, &_local_eqnum );
+	
+	VecCreate( PETSC_COMM_WORLD, &offset_list );
+	VecSetSizes( offset_list, PETSC_DECIDE, (size+1) );
+	VecSetFromOptions( offset_list );
+	for( i=rank; i<size; i++ ) {
+		VecSetValue( offset_list, i+1, eq_cnt, ADD_VALUES );
+	}
+	VecAssemblyBegin(offset_list);
+	VecAssemblyEnd(offset_list);
+	/*
+	PetscPrintf(PETSC_COMM_WORLD, "offset_list \n");
+	VecView( offset_list, PETSC_VIEWER_STDOUT_WORLD );
+	*/
+	
+	VecScatterCreateToAll(offset_list,&vscat_offset,&seq_offset_list);
+	_VecScatterBeginEnd( vscat_offset, offset_list, seq_offset_list, INSERT_VALUES, SCATTER_FORWARD );
+	
+	{
+		PetscScalar *_seq_offset_list;
+		
+		VecGetArray( seq_offset_list, &_seq_offset_list );
+		offset = _seq_offset_list[ rank ];
+		VecRestoreArray( seq_offset_list, &_seq_offset_list );
+	}
+	VecScatterDestroy(vscat_offset);
+	VecDestroy(offset_list);
+	VecDestroy(seq_offset_list);
+	
+	/* PetscPrintf( PETSC_COMM_SELF, "[%d]: offset = %d \n", rank, offset ); */
+	
+	
+	VecGetArray( local_eqnum, &_local_eqnum );
+	inc = 0;
+	for( i=0; i<number_to_fetch; i++ ) {
+		if( (PetscInt)_local_eqnum[i]==0 ) {
+			_local_eqnum[i] = offset+inc;
+			inc++;
+		}
+	}
+	VecRestoreArray( local_eqnum, &_local_eqnum );
+	
+	_VecScatterBeginEnd( vscat_eqnum, local_eqnum, global_eqnum, INSERT_VALUES, SCATTER_REVERSE );
+	/*
+	PetscPrintf(PETSC_COMM_WORLD, "global_eqnum \n");
+	VecView( global_eqnum, PETSC_VIEWER_STDOUT_WORLD );
+	*/
+	
+	/* For each periodic boundary, get the mapped nodes */
+	
+	if( periodic_x==PETSC_TRUE ) {
+		VecScatter vscat_p;
+		IS is_from;
+		PetscInt *from, *to;
+		Vec mapped;
+		PetscScalar *_mapped;
+		PetscInt c;
+		
+		PetscMalloc( sizeof(PetscInt)*npx*dof, &from );
+		PetscMalloc( sizeof(PetscInt)*npx*dof, &to );
+		
+		c = 0;
+		for( i=0; i<npx; i++ ) {
+			PetscInt I,J,K,gid,from_gid;
+			
+			gid = periodic_x_gnode_id[i];
+			K = gid/(NX*NY);
+			J = (gid - K*(NX*NY))/NX;
+			I = gid - K*(NX*NY) - J*NX;
+			from_gid = (I-(NX-1)) + J*NX + K*(NX*NY);
+			
+			for( d=0; d<dof; d++ ) {
+				to[c] = gid * dof + d;
+				from[c] = from_gid * dof + d;
+				c++;
+			}
+		}
+		
+		
+		VecCreate( PETSC_COMM_SELF, &mapped );
+		VecSetSizes( mapped, PETSC_DECIDE, npx*dof );
+		VecSetFromOptions( mapped );
+		
+		ISCreateGeneralWithArray( PETSC_COMM_SELF, npx*dof, from, &is_from );
+		VecScatterCreate( global_eqnum, is_from, mapped, PETSC_NULL, &vscat_p );
+		
+		_VecScatterBeginEnd( vscat_p, global_eqnum, mapped, INSERT_VALUES, SCATTER_FORWARD );
+		if( npx>0 ) {
+			VecGetArray( mapped, &_mapped );
+			VecSetValues( global_eqnum, npx*dof, to, _mapped,  INSERT_VALUES );
+			VecRestoreArray( mapped, &_mapped );
+		}
+		
+		VecAssemblyBegin(global_eqnum);
+		VecAssemblyEnd(global_eqnum);
+		
+		VecScatterDestroy( vscat_p );
+		ISDestroy( is_from );
+		VecDestroy( mapped );
+		PetscFree( from );
+		PetscFree( to );
+	}
+	
+	
+	if( periodic_y==PETSC_TRUE ) {
+		VecScatter vscat_p;
+		IS is_from;
+		PetscInt *from, *to;
+		Vec mapped;
+		PetscScalar *_mapped;
+		PetscInt c;
+		
+		PetscMalloc( sizeof(PetscInt)*npy*dof, &from );
+		PetscMalloc( sizeof(PetscInt)*npy*dof, &to );
+		
+		c = 0;
+		for( i=0; i<npy; i++ ) {
+			PetscInt I,J,K,gid,from_gid;
+			
+			gid = periodic_y_gnode_id[i];
+			K = gid/(NX*NY);
+			J = (gid - K*(NX*NY))/NX;
+			I = gid - K*(NX*NY) - J*NX;
+			from_gid = I + (J - (NY - 1))*NX + K*(NX*NY);
+			
+			for( d=0; d<dof; d++ ) {
+				to[c] = gid * dof + d;
+				from[c] = from_gid * dof + d;
+				c++;
+			}
+		}
+		
+		
+		VecCreate( PETSC_COMM_SELF, &mapped );
+		VecSetSizes( mapped, PETSC_DECIDE, npy*dof );
+		VecSetFromOptions( mapped );
+		
+		ISCreateGeneralWithArray( PETSC_COMM_SELF, npy*dof, from, &is_from );
+		VecScatterCreate( global_eqnum, is_from, mapped, PETSC_NULL, &vscat_p );
+		
+		_VecScatterBeginEnd( vscat_p, global_eqnum, mapped, INSERT_VALUES, SCATTER_FORWARD );
+		if( npy>0 ) {
+			VecGetArray( mapped, &_mapped );
+			VecSetValues( global_eqnum, npy*dof, to, _mapped,  INSERT_VALUES );
+			VecRestoreArray( mapped, &_mapped );
+		}
+		
+		VecAssemblyBegin(global_eqnum);
+		VecAssemblyEnd(global_eqnum);
+		
+		VecScatterDestroy( vscat_p );
+		ISDestroy( is_from );
+		VecDestroy( mapped );
+		PetscFree( from );
+		PetscFree( to );
+	}
+
+	if( periodic_z==PETSC_TRUE ) {
+		VecScatter vscat_p;
+		IS is_from;
+		PetscInt *from, *to;
+		Vec mapped;
+		PetscScalar *_mapped;
+		PetscInt c;
+		
+		PetscMalloc( sizeof(PetscInt)*npz*dof, &from );
+		PetscMalloc( sizeof(PetscInt)*npz*dof, &to );
+		
+		c = 0;
+		for( i=0; i<npz; i++ ) {
+			PetscInt I,J,K,gid,from_gid;
+			
+			gid = periodic_z_gnode_id[i];
+			K = gid/(NX*NY);
+			J = (gid - K*(NX*NY))/NX;
+			I = gid - K*(NX*NY) - J*NX;
+			from_gid = I + J*NX + (K - (NZ-1))*(NX*NY);
+			
+			for( d=0; d<dof; d++ ) {
+				to[c] = gid * dof + d;
+				from[c] = from_gid * dof + d;
+				c++;
+			}
+		}
+		
+		
+		VecCreate( PETSC_COMM_SELF, &mapped );
+		VecSetSizes( mapped, PETSC_DECIDE, npz*dof );
+		VecSetFromOptions( mapped );
+		
+		ISCreateGeneralWithArray( PETSC_COMM_SELF, npz*dof, from, &is_from );
+		VecScatterCreate( global_eqnum, is_from, mapped, PETSC_NULL, &vscat_p );
+		
+		_VecScatterBeginEnd( vscat_p, global_eqnum, mapped, INSERT_VALUES, SCATTER_FORWARD );
+		if( npz>0 ) {
+			VecGetArray( mapped, &_mapped );
+			VecSetValues( global_eqnum, npz*dof, to, _mapped,  INSERT_VALUES );
+			VecRestoreArray( mapped, &_mapped );
+		}
+		
+		VecAssemblyBegin(global_eqnum);
+		VecAssemblyEnd(global_eqnum);
+		
+		VecScatterDestroy( vscat_p );
+		ISDestroy( is_from );
+		VecDestroy( mapped );
+		PetscFree( from );
+		PetscFree( to );
+	}
+
+	
+	/*
+	PetscPrintf(PETSC_COMM_WORLD, "global_eqnum following periodic \n");
+	VecView( global_eqnum, PETSC_VIEWER_STDOUT_WORLD );
+	*/
+	
+	
+	/* Finally, scatter stuff from global_eqnums into MY array */
+	{
+		IS is_all_my_eqnums;
+		PetscInt *all_my_eqnum_index;
+		PetscInt _I,_D,CNT;
+		Vec all_my_eqnums;
+		PetscScalar *_all_my_eqnums;
+		VecScatter vscat_p;
+		
+		PetscMalloc( sizeof(PetscInt)*dof*nlocal, &all_my_eqnum_index );
+		
+		CNT = 0;
+		for( _I=0; _I<nlocal; _I++ ) {
+			for( _D=0; _D<dof; _D++ ) {
+				all_my_eqnum_index[CNT] = g_node_id[_I]*dof + _D;
+				CNT++;
+			}
+		}
+		
+		ISCreateGeneralWithArray( PETSC_COMM_SELF, nlocal*dof, all_my_eqnum_index, &is_all_my_eqnums );
+		VecCreate( PETSC_COMM_SELF, &all_my_eqnums );
+		VecSetSizes( all_my_eqnums, PETSC_DECIDE, nlocal*dof );
+		VecSetFromOptions( all_my_eqnums );
+		VecScatterCreate( global_eqnum, is_all_my_eqnums, all_my_eqnums, PETSC_NULL, &vscat_p );
+		_VecScatterBeginEnd( vscat_p, global_eqnum, all_my_eqnums, INSERT_VALUES, SCATTER_FORWARD );
+		VecGetArray( all_my_eqnums, &_all_my_eqnums );
+
+		for( i=0; i<nlocal*dof; i++ ) {
+			eqnums[i] = (int)_all_my_eqnums[i];
+		}
+		VecRestoreArray( all_my_eqnums, &_all_my_eqnums );
+		
+		VecScatterDestroy( vscat_p );
+		VecDestroy( all_my_eqnums );
+		ISDestroy( is_all_my_eqnums );
+		PetscFree( all_my_eqnum_index );
+	}
+	
+	VecMax( global_eqnum, &loc, &max );
+	*neqnums = (int)max;
+	(*neqnums)++;
+	
+	/* tidy up */
+	VecRestoreArray( local_ownership, &_local_ownership );
+	
+	
+	VecDestroy( g_ownership );
+	VecDestroy( local_ownership );
+	PetscFree( _g_node_id );
+	ISDestroy( is_gnode );
+	VecScatterDestroy( vscat_ownership );
+	
+	VecDestroy( global_eqnum );
+	VecDestroy( local_eqnum );
+	PetscFree( to_fetch );
+	ISDestroy( is_eqnum );
+	VecScatterDestroy( vscat_eqnum );
+	
+	return 0;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeMesh.c
--- a/Discretisation/src/FeMesh.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,453 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FeMesh.c 992 2008-01-03 04:46:19Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type FeMesh_Type = "FeMesh";
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-FeMesh* FeMesh_New( Name name, AbstractContext* context ) {
-   FeMesh* self = _FeMesh_DefaultNew( name );
-   _Mesh_Init( (Mesh*)self, context );
-	/* FeMesh info */
-	_FeMesh_Init( self, NULL, NULL, False ); /* this is a useless Init() */
-
-   return self;
-}
-
-FeMesh* _FeMesh_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(FeMesh);
-	Type                                                      type = FeMesh_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FeMesh_Delete;
-	Stg_Class_PrintFunction*                                _print = _FeMesh_Print;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (void* (*)(Name))_FeMesh_New;
-	Stg_Component_ConstructFunction*                    _construct = _FeMesh_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _FeMesh_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FeMesh_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FeMesh_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FeMesh_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-
-	/* The following terms are parameters that have been passed into or defined in this function but are being set before being passed onto the parent */
-	Stg_Class_CopyFunction*        _copy = NULL;
-
-   return _FeMesh_New(  FEMESH_PASSARGS  );
-}
-
-FeMesh* _FeMesh_New(  FEMESH_DEFARGS  ) {
-	FeMesh*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(FeMesh) );
-	self = (FeMesh*)_Mesh_New(  MESH_PASSARGS  );
-
-	return self;
-}
-
-void _FeMesh_Init( FeMesh* self, ElementType* elType, Name family, Bool elementMesh ) {
-	Stream*	stream;
-
-	assert( self && Stg_CheckType( self, FeMesh ) );
-
-	stream = Journal_Register( Info_Type, (Name)self->type  );
-	Stream_SetPrintingRank( stream, 0 );
-
-	self->feElType = elType;
-	self->feElFamily = family;
-	self->elementMesh = elementMesh;
-
-   /* checkpoint non-constant meshes */
-   if ( self->feElFamily && strcmp( self->feElFamily, "constant" ) ){
-      self->isCheckpointedAndReloaded = True;
-      self->requiresCheckpointing     = True;
-   }
-	
-	self->inc = IArray_New();
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _FeMesh_Delete( void* feMesh ) {
-	FeMesh*	self = (FeMesh*)feMesh;
-	/* Delete the parent. */
-	_Mesh_Delete( self );
-}
-
-void _FeMesh_Print( void* feMesh, Stream* stream ) {
-	FeMesh*	self = (FeMesh*)feMesh;
-	
-	/* Set the Journal for printing informations */
-	Stream* feMeshStream;
-	feMeshStream = Journal_Register( InfoStream_Type, (Name)"FeMeshStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "FeMesh (ptr): (%p)\n", self );
-	_Mesh_Print( self, stream );
-}
-
-void _FeMesh_AssignFromXML( void* feMesh, Stg_ComponentFactory* cf, void* data ) {
-	FeMesh*	self = (FeMesh*)feMesh;
-
-	assert( self );
-
-	_Mesh_AssignFromXML( self, cf, data );
-
-	_FeMesh_Init( self, NULL, Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"elementType", "linear"  ), 
-		Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"isElementMesh", False )  );
-}
-
-void _FeMesh_Build( void* feMesh, void* data ) {
-	FeMesh*		self = (FeMesh*)feMesh;
-	Stream*		stream;
-	ElementType*	elType;
-
-	assert( self );
-
-	stream = Journal_Register( Info_Type, (Name)self->type  );
-
-	_Mesh_Build( self, data );
-
-	Stream_Indent( stream );
-	Journal_Printf( stream, "Assigning FeMesh element types...\n" );
-	Stream_Indent( stream );
-
-	if( !strcmp( self->feElFamily, "quadratic" ) ) {
-		unsigned	nDims;
-
-		nDims = Mesh_GetDimSize( self );
-		if( nDims == 3 )
-			elType = (ElementType*)Triquadratic_New( "" );
-		else if( nDims == 2 )
-			elType = (ElementType*)Biquadratic_New( "" );
-		else
-			abort();
-	}
-	else if( !strcmp( self->feElFamily, "linear" ) ) {
-		unsigned	nDims;
-
-		nDims = Mesh_GetDimSize( self );
-		if( nDims == 3 )
-			elType = (ElementType*)TrilinearElementType_New( "" );
-		else if( nDims == 2 )
-			elType = (ElementType*)BilinearElementType_New( "" );
-		else
-			abort();
-	}
-	else if( !strcmp( self->feElFamily, "linear-regular" ) ) {
-		unsigned	nDims;
-
-		nDims = Mesh_GetDimSize( self );
-		if( nDims == 3 )
-			elType = (ElementType*)RegularTrilinear_New( "" );
-		else if( nDims == 2 )
-			elType = (ElementType*)RegularBilinear_New( "" );
-		else
-			abort();
-	}
-	else if( !strcmp( self->feElFamily, "linear-inner" ) ) {
-		unsigned	nDims;
-
-		nDims = Mesh_GetDimSize( self );
-		if( nDims == 3 )
-			elType = (ElementType*)TrilinearInnerElType_New( "" );
-		else if( nDims == 2 )
-			elType = (ElementType*)BilinearInnerElType_New( "" );
-		else
-			abort();
-	}
-	else if( !strcmp( self->feElFamily, "constant" ) ) {
-		elType = (ElementType*)ConstantElementType_New( "" );
-	}
-	else if( !strcmp( self->feElFamily, "p1" ) ) {
-		elType = (ElementType*)P1_New( "" );
-	}
-	else
-		abort();
-	FeMesh_SetElementType( self, elType );
-	if( self->feElType )
-		Stg_Component_Build( self->feElType, data, False );
-
-	/*
-	** Reset the element type to FeMesh_ElementType.
-	**/
-
-	if( self->elementMesh ) {
-		Stg_Class_Delete( self->algorithms );
-		self->algorithms = (Mesh_Algorithms*)FeMesh_Algorithms_New( "", NULL );
-		Mesh_Algorithms_SetMesh( self->algorithms, self );
-		Mesh_Algorithms_Update( self->algorithms );
-
-		Stg_Class_Delete( self->elTypes[0] );
-		self->elTypes[0] = (Mesh_ElementType*)FeMesh_ElementType_New();
-		Mesh_ElementType_SetMesh( self->elTypes[0], self );
-		Mesh_ElementType_Update( self->elTypes[0] );
-	}
-
-	Journal_Printf( stream, "... FE element types are '%s',\n", elType->type );
-	Journal_Printf( stream, "... done.\n" );
-	Stream_UnIndent( stream );
-	Stream_UnIndent( stream );
-}
-
-void _FeMesh_Initialise( void* feMesh, void* data ) {
-	FeMesh*	self = (FeMesh*)feMesh;
-
-	assert( self );
-
-	_Mesh_Initialise( self, data );
-
-	if( self->feElType )
-		Stg_Component_Initialise( self->feElType, data, False );
-}
-
-void _FeMesh_Execute( void* feMesh, void* data ) {
-}
-
-void _FeMesh_Destroy( void* feMesh, void* data ) {
-	FeMesh*	self = (FeMesh*)feMesh;
-   
-	FeMesh_Destruct( self );
-	NewClass_Delete( self->inc );
-   _Mesh_Destroy( self, data );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void FeMesh_SetElementType( void* feMesh, ElementType* elType ) {
-	FeMesh*	self = (FeMesh*)feMesh;
-
-	assert( self );
-
-   if( self->feElType ) Stg_Class_Delete( self->feElType );
-	self->feElType = elType;
-}
-
-void FeMesh_SetElementFamily( void* feMesh, Name family ) {
-	FeMesh*	self = (FeMesh*)feMesh;
-
-	assert( self );
-
-	self->feElFamily = family;
-}
-
-ElementType* FeMesh_GetElementType( void* feMesh, unsigned element ) {
-	FeMesh*	self = (FeMesh*)feMesh;
-
-	assert( self );
-
-	return self->feElType;
-}
-
-unsigned FeMesh_GetNodeLocalSize( void* feMesh ) {
-	return Mesh_GetLocalSize( feMesh, MT_VERTEX );
-}
-
-unsigned FeMesh_GetNodeRemoteSize( void* feMesh ) {
-	return Mesh_GetRemoteSize( feMesh, MT_VERTEX );
-}
-
-unsigned FeMesh_GetNodeDomainSize( void* feMesh ) {
-	return Mesh_GetDomainSize( feMesh, MT_VERTEX );
-}
-
-unsigned FeMesh_GetNodeGlobalSize( void* feMesh ) {
-	return Mesh_GetGlobalSize( feMesh, MT_VERTEX );
-}
-
-unsigned FeMesh_GetElementLocalSize( void* feMesh ) {
-	return Mesh_GetLocalSize( feMesh, Mesh_GetDimSize( feMesh ) );
-}
-
-unsigned FeMesh_GetElementRemoteSize( void* feMesh ) {
-	return Mesh_GetRemoteSize( feMesh, Mesh_GetDimSize( feMesh ) );
-}
-
-unsigned FeMesh_GetElementDomainSize( void* feMesh ) {
-	return Mesh_GetDomainSize( feMesh, Mesh_GetDimSize( feMesh ) );
-}
-
-unsigned FeMesh_GetElementGlobalSize( void* feMesh ) {
-	return Mesh_GetGlobalSize( feMesh, Mesh_GetDimSize( feMesh ) );
-}
-
-unsigned FeMesh_GetElementNodeSize( void* feMesh, unsigned element ) {
-	return Mesh_GetIncidenceSize( feMesh, Mesh_GetDimSize( feMesh ), element, MT_VERTEX );
-}
-
-unsigned FeMesh_GetNodeElementSize( void* feMesh, unsigned node ) {
-	return Mesh_GetIncidenceSize( feMesh, MT_VERTEX, node, Mesh_GetDimSize( feMesh ) );
-}
-
-void FeMesh_GetElementNodes( void* feMesh, unsigned element, IArray* inc ) {
-	Mesh_GetIncidence( feMesh, Mesh_GetDimSize( feMesh ), element, MT_VERTEX, inc );
-}
-
-void FeMesh_GetNodeElements( void* feMesh, unsigned node, IArray* inc ) {
-	Mesh_GetIncidence( feMesh, MT_VERTEX, node, Mesh_GetDimSize( feMesh ), inc );
-}
-
-unsigned FeMesh_ElementDomainToGlobal( void* feMesh, unsigned domain ) {
-	return Mesh_DomainToGlobal( feMesh, Mesh_GetDimSize( feMesh ), domain );
-}
-
-Bool FeMesh_ElementGlobalToDomain( void* feMesh, unsigned global, unsigned* domain ) {
-	return Mesh_GlobalToDomain( feMesh, Mesh_GetDimSize( feMesh ), global, domain );
-}
-
-unsigned FeMesh_NodeDomainToGlobal( void* feMesh, unsigned domain ) {
-	return Mesh_DomainToGlobal( feMesh, MT_VERTEX, domain );
-}
-
-Bool FeMesh_NodeGlobalToDomain( void* feMesh, unsigned global, unsigned* domain ) {
-	return Mesh_GlobalToDomain( feMesh, MT_VERTEX, global, domain );
-}
-
-void FeMesh_CoordGlobalToLocal( void* feMesh, unsigned element, double* global, double* local ) {
-	FeMesh*		self = (FeMesh*)feMesh;
-	ElementType*	elType;
-
-	assert( self );
-	assert( element < FeMesh_GetElementDomainSize( self ) );
-	assert( global );
-	assert( local );
-
-	elType = FeMesh_GetElementType( self, element );
-	ElementType_ConvertGlobalCoordToElLocal( elType, self, element, global, local );
-}
-
-void FeMesh_CoordLocalToGlobal( void* feMesh, unsigned element, double* local, double* global ) {
-	FeMesh*		self = (FeMesh*)feMesh;
-	unsigned	nDims;
-	ElementType*	elType;
-	double*		basis;
-	unsigned	nElNodes, *elNodes;
-	double		dimBasis;
-	double*		vert;
-	unsigned	n_i, d_i;
-
-	assert( self );
-	assert( element < FeMesh_GetElementDomainSize( self ) );
-	assert( global );
-	assert( local );
-
-	nDims = Mesh_GetDimSize( self );
-	elType = FeMesh_GetElementType( self, element );
-	FeMesh_GetElementNodes( self, element, self->inc );
-	nElNodes = IArray_GetSize( self->inc );
-	elNodes = (unsigned*)IArray_GetPtr( self->inc );
-	basis = AllocArray( double, nElNodes );
-	ElementType_EvaluateShapeFunctionsAt( elType, local, basis );
-
-	memset( global, 0, nDims * sizeof(double) );
-	for( n_i = 0; n_i < nElNodes; n_i++ ) {
-		dimBasis = basis[n_i];
-		vert = Mesh_GetVertex( self, elNodes[n_i] );
-		for( d_i = 0; d_i < nDims; d_i++ )
-			global[d_i] += dimBasis * vert[d_i];
-	}
-
-	FreeArray( basis );
-}
-
-void FeMesh_EvalBasis( void* feMesh, unsigned element, double* localCoord, double* basis ) {
-	FeMesh*		self = (FeMesh*)feMesh;
-	ElementType*	elType;
-
-	assert( self );
-	assert( localCoord );
-
-	elType = FeMesh_GetElementType( self, element );
-	ElementType_EvaluateShapeFunctionsAt( elType, localCoord, basis );
-}
-
-void FeMesh_EvalLocalDerivs( void* feMesh, unsigned element, double* localCoord, double** derivs ) {
-	FeMesh*		self = (FeMesh*)feMesh;
-	ElementType*	elType;
-
-	assert( self );
-	assert( localCoord );
-	assert( derivs );
-
-	elType = FeMesh_GetElementType( self, element );
-	ElementType_EvaluateShapeFunctionLocalDerivsAt( elType, localCoord, derivs );
-}
-
-void FeMesh_EvalGlobalDerivs( void* feMesh, unsigned element, double* localCoord, double** derivs, double* jacDet ) {
-	FeMesh*		self = (FeMesh*)feMesh;
-	unsigned	nDims;
-	ElementType*	elType;
-	double		jd;
-
-	assert( self );
-	assert( localCoord );
-	assert( derivs );
-
-	nDims = Mesh_GetDimSize( self );
-	elType = FeMesh_GetElementType( self, element );
-	ElementType_ShapeFunctionsGlobalDerivs( elType, self, element, localCoord, nDims, 
-						&jd, derivs );
-	if( jacDet )
-		*jacDet = jd;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-void FeMesh_Destruct( FeMesh* self ) {
-   Stg_Class_Delete( self->feElType );
-	self->feElFamily = NULL;
-	/* Disabling the killing of this object from within this
-	component as this will be destroyed by the LiveComponentRegister_DestroyAll function 101109 */
-	/*KillObject( self->feElType );*/ 
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeMesh.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/FeMesh.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,453 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FeMesh.c 992 2008-01-03 04:46:19Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type FeMesh_Type = "FeMesh";
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+FeMesh* FeMesh_New( Name name, AbstractContext* context ) {
+   FeMesh* self = _FeMesh_DefaultNew( name );
+   _Mesh_Init( (Mesh*)self, context );
+	/* FeMesh info */
+	_FeMesh_Init( self, NULL, NULL, False ); /* this is a useless Init() */
+
+   return self;
+}
+
+FeMesh* _FeMesh_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(FeMesh);
+	Type                                                      type = FeMesh_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FeMesh_Delete;
+	Stg_Class_PrintFunction*                                _print = _FeMesh_Print;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (void* (*)(Name))_FeMesh_New;
+	Stg_Component_ConstructFunction*                    _construct = _FeMesh_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _FeMesh_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FeMesh_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FeMesh_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FeMesh_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+
+	/* The following terms are parameters that have been passed into or defined in this function but are being set before being passed onto the parent */
+	Stg_Class_CopyFunction*        _copy = NULL;
+
+   return _FeMesh_New(  FEMESH_PASSARGS  );
+}
+
+FeMesh* _FeMesh_New(  FEMESH_DEFARGS  ) {
+	FeMesh*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(FeMesh) );
+	self = (FeMesh*)_Mesh_New(  MESH_PASSARGS  );
+
+	return self;
+}
+
+void _FeMesh_Init( FeMesh* self, ElementType* elType, Name family, Bool elementMesh ) {
+	Stream*	stream;
+
+	assert( self && Stg_CheckType( self, FeMesh ) );
+
+	stream = Journal_Register( Info_Type, (Name)self->type  );
+	Stream_SetPrintingRank( stream, 0 );
+
+	self->feElType = elType;
+	self->feElFamily = family;
+	self->elementMesh = elementMesh;
+
+   /* checkpoint non-constant meshes */
+   if ( self->feElFamily && strcmp( self->feElFamily, "constant" ) ){
+      self->isCheckpointedAndReloaded = True;
+      self->requiresCheckpointing     = True;
+   }
+	
+	self->inc = IArray_New();
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _FeMesh_Delete( void* feMesh ) {
+	FeMesh*	self = (FeMesh*)feMesh;
+	/* Delete the parent. */
+	_Mesh_Delete( self );
+}
+
+void _FeMesh_Print( void* feMesh, Stream* stream ) {
+	FeMesh*	self = (FeMesh*)feMesh;
+	
+	/* Set the Journal for printing informations */
+	Stream* feMeshStream;
+	feMeshStream = Journal_Register( InfoStream_Type, (Name)"FeMeshStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "FeMesh (ptr): (%p)\n", self );
+	_Mesh_Print( self, stream );
+}
+
+void _FeMesh_AssignFromXML( void* feMesh, Stg_ComponentFactory* cf, void* data ) {
+	FeMesh*	self = (FeMesh*)feMesh;
+
+	assert( self );
+
+	_Mesh_AssignFromXML( self, cf, data );
+
+	_FeMesh_Init( self, NULL, Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"elementType", "linear"  ), 
+		Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"isElementMesh", False )  );
+}
+
+void _FeMesh_Build( void* feMesh, void* data ) {
+	FeMesh*		self = (FeMesh*)feMesh;
+	Stream*		stream;
+	ElementType*	elType;
+
+	assert( self );
+
+	stream = Journal_Register( Info_Type, (Name)self->type  );
+
+	_Mesh_Build( self, data );
+
+	Stream_Indent( stream );
+	Journal_Printf( stream, "Assigning FeMesh element types...\n" );
+	Stream_Indent( stream );
+
+	if( !strcmp( self->feElFamily, "quadratic" ) ) {
+		unsigned	nDims;
+
+		nDims = Mesh_GetDimSize( self );
+		if( nDims == 3 )
+			elType = (ElementType*)Triquadratic_New( "" );
+		else if( nDims == 2 )
+			elType = (ElementType*)Biquadratic_New( "" );
+		else
+			abort();
+	}
+	else if( !strcmp( self->feElFamily, "linear" ) ) {
+		unsigned	nDims;
+
+		nDims = Mesh_GetDimSize( self );
+		if( nDims == 3 )
+			elType = (ElementType*)TrilinearElementType_New( "" );
+		else if( nDims == 2 )
+			elType = (ElementType*)BilinearElementType_New( "" );
+		else
+			abort();
+	}
+	else if( !strcmp( self->feElFamily, "linear-regular" ) ) {
+		unsigned	nDims;
+
+		nDims = Mesh_GetDimSize( self );
+		if( nDims == 3 )
+			elType = (ElementType*)RegularTrilinear_New( "" );
+		else if( nDims == 2 )
+			elType = (ElementType*)RegularBilinear_New( "" );
+		else
+			abort();
+	}
+	else if( !strcmp( self->feElFamily, "linear-inner" ) ) {
+		unsigned	nDims;
+
+		nDims = Mesh_GetDimSize( self );
+		if( nDims == 3 )
+			elType = (ElementType*)TrilinearInnerElType_New( "" );
+		else if( nDims == 2 )
+			elType = (ElementType*)BilinearInnerElType_New( "" );
+		else
+			abort();
+	}
+	else if( !strcmp( self->feElFamily, "constant" ) ) {
+		elType = (ElementType*)ConstantElementType_New( "" );
+	}
+	else if( !strcmp( self->feElFamily, "p1" ) ) {
+		elType = (ElementType*)P1_New( "" );
+	}
+	else
+		abort();
+	FeMesh_SetElementType( self, elType );
+	if( self->feElType )
+		Stg_Component_Build( self->feElType, data, False );
+
+	/*
+	** Reset the element type to FeMesh_ElementType.
+	**/
+
+	if( self->elementMesh ) {
+		Stg_Class_Delete( self->algorithms );
+		self->algorithms = (Mesh_Algorithms*)FeMesh_Algorithms_New( "", NULL );
+		Mesh_Algorithms_SetMesh( self->algorithms, self );
+		Mesh_Algorithms_Update( self->algorithms );
+
+		Stg_Class_Delete( self->elTypes[0] );
+		self->elTypes[0] = (Mesh_ElementType*)FeMesh_ElementType_New();
+		Mesh_ElementType_SetMesh( self->elTypes[0], self );
+		Mesh_ElementType_Update( self->elTypes[0] );
+	}
+
+	Journal_Printf( stream, "... FE element types are '%s',\n", elType->type );
+	Journal_Printf( stream, "... done.\n" );
+	Stream_UnIndent( stream );
+	Stream_UnIndent( stream );
+}
+
+void _FeMesh_Initialise( void* feMesh, void* data ) {
+	FeMesh*	self = (FeMesh*)feMesh;
+
+	assert( self );
+
+	_Mesh_Initialise( self, data );
+
+	if( self->feElType )
+		Stg_Component_Initialise( self->feElType, data, False );
+}
+
+void _FeMesh_Execute( void* feMesh, void* data ) {
+}
+
+void _FeMesh_Destroy( void* feMesh, void* data ) {
+	FeMesh*	self = (FeMesh*)feMesh;
+   
+	FeMesh_Destruct( self );
+	NewClass_Delete( self->inc );
+   _Mesh_Destroy( self, data );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void FeMesh_SetElementType( void* feMesh, ElementType* elType ) {
+	FeMesh*	self = (FeMesh*)feMesh;
+
+	assert( self );
+
+   if( self->feElType ) Stg_Class_Delete( self->feElType );
+	self->feElType = elType;
+}
+
+void FeMesh_SetElementFamily( void* feMesh, Name family ) {
+	FeMesh*	self = (FeMesh*)feMesh;
+
+	assert( self );
+
+	self->feElFamily = family;
+}
+
+ElementType* FeMesh_GetElementType( void* feMesh, unsigned element ) {
+	FeMesh*	self = (FeMesh*)feMesh;
+
+	assert( self );
+
+	return self->feElType;
+}
+
+unsigned FeMesh_GetNodeLocalSize( void* feMesh ) {
+	return Mesh_GetLocalSize( feMesh, MT_VERTEX );
+}
+
+unsigned FeMesh_GetNodeRemoteSize( void* feMesh ) {
+	return Mesh_GetRemoteSize( feMesh, MT_VERTEX );
+}
+
+unsigned FeMesh_GetNodeDomainSize( void* feMesh ) {
+	return Mesh_GetDomainSize( feMesh, MT_VERTEX );
+}
+
+unsigned FeMesh_GetNodeGlobalSize( void* feMesh ) {
+	return Mesh_GetGlobalSize( feMesh, MT_VERTEX );
+}
+
+unsigned FeMesh_GetElementLocalSize( void* feMesh ) {
+	return Mesh_GetLocalSize( feMesh, Mesh_GetDimSize( feMesh ) );
+}
+
+unsigned FeMesh_GetElementRemoteSize( void* feMesh ) {
+	return Mesh_GetRemoteSize( feMesh, Mesh_GetDimSize( feMesh ) );
+}
+
+unsigned FeMesh_GetElementDomainSize( void* feMesh ) {
+	return Mesh_GetDomainSize( feMesh, Mesh_GetDimSize( feMesh ) );
+}
+
+unsigned FeMesh_GetElementGlobalSize( void* feMesh ) {
+	return Mesh_GetGlobalSize( feMesh, Mesh_GetDimSize( feMesh ) );
+}
+
+unsigned FeMesh_GetElementNodeSize( void* feMesh, unsigned element ) {
+	return Mesh_GetIncidenceSize( feMesh, Mesh_GetDimSize( feMesh ), element, MT_VERTEX );
+}
+
+unsigned FeMesh_GetNodeElementSize( void* feMesh, unsigned node ) {
+	return Mesh_GetIncidenceSize( feMesh, MT_VERTEX, node, Mesh_GetDimSize( feMesh ) );
+}
+
+void FeMesh_GetElementNodes( void* feMesh, unsigned element, IArray* inc ) {
+	Mesh_GetIncidence( feMesh, Mesh_GetDimSize( feMesh ), element, MT_VERTEX, inc );
+}
+
+void FeMesh_GetNodeElements( void* feMesh, unsigned node, IArray* inc ) {
+	Mesh_GetIncidence( feMesh, MT_VERTEX, node, Mesh_GetDimSize( feMesh ), inc );
+}
+
+unsigned FeMesh_ElementDomainToGlobal( void* feMesh, unsigned domain ) {
+	return Mesh_DomainToGlobal( feMesh, Mesh_GetDimSize( feMesh ), domain );
+}
+
+Bool FeMesh_ElementGlobalToDomain( void* feMesh, unsigned global, unsigned* domain ) {
+	return Mesh_GlobalToDomain( feMesh, Mesh_GetDimSize( feMesh ), global, domain );
+}
+
+unsigned FeMesh_NodeDomainToGlobal( void* feMesh, unsigned domain ) {
+	return Mesh_DomainToGlobal( feMesh, MT_VERTEX, domain );
+}
+
+Bool FeMesh_NodeGlobalToDomain( void* feMesh, unsigned global, unsigned* domain ) {
+	return Mesh_GlobalToDomain( feMesh, MT_VERTEX, global, domain );
+}
+
+void FeMesh_CoordGlobalToLocal( void* feMesh, unsigned element, double* global, double* local ) {
+	FeMesh*		self = (FeMesh*)feMesh;
+	ElementType*	elType;
+
+	assert( self );
+	assert( element < FeMesh_GetElementDomainSize( self ) );
+	assert( global );
+	assert( local );
+
+	elType = FeMesh_GetElementType( self, element );
+	ElementType_ConvertGlobalCoordToElLocal( elType, self, element, global, local );
+}
+
+void FeMesh_CoordLocalToGlobal( void* feMesh, unsigned element, double* local, double* global ) {
+	FeMesh*		self = (FeMesh*)feMesh;
+	unsigned	nDims;
+	ElementType*	elType;
+	double*		basis;
+	unsigned	nElNodes, *elNodes;
+	double		dimBasis;
+	double*		vert;
+	unsigned	n_i, d_i;
+
+	assert( self );
+	assert( element < FeMesh_GetElementDomainSize( self ) );
+	assert( global );
+	assert( local );
+
+	nDims = Mesh_GetDimSize( self );
+	elType = FeMesh_GetElementType( self, element );
+	FeMesh_GetElementNodes( self, element, self->inc );
+	nElNodes = IArray_GetSize( self->inc );
+	elNodes = (unsigned*)IArray_GetPtr( self->inc );
+	basis = AllocArray( double, nElNodes );
+	ElementType_EvaluateShapeFunctionsAt( elType, local, basis );
+
+	memset( global, 0, nDims * sizeof(double) );
+	for( n_i = 0; n_i < nElNodes; n_i++ ) {
+		dimBasis = basis[n_i];
+		vert = Mesh_GetVertex( self, elNodes[n_i] );
+		for( d_i = 0; d_i < nDims; d_i++ )
+			global[d_i] += dimBasis * vert[d_i];
+	}
+
+	FreeArray( basis );
+}
+
+void FeMesh_EvalBasis( void* feMesh, unsigned element, double* localCoord, double* basis ) {
+	FeMesh*		self = (FeMesh*)feMesh;
+	ElementType*	elType;
+
+	assert( self );
+	assert( localCoord );
+
+	elType = FeMesh_GetElementType( self, element );
+	ElementType_EvaluateShapeFunctionsAt( elType, localCoord, basis );
+}
+
+void FeMesh_EvalLocalDerivs( void* feMesh, unsigned element, double* localCoord, double** derivs ) {
+	FeMesh*		self = (FeMesh*)feMesh;
+	ElementType*	elType;
+
+	assert( self );
+	assert( localCoord );
+	assert( derivs );
+
+	elType = FeMesh_GetElementType( self, element );
+	ElementType_EvaluateShapeFunctionLocalDerivsAt( elType, localCoord, derivs );
+}
+
+void FeMesh_EvalGlobalDerivs( void* feMesh, unsigned element, double* localCoord, double** derivs, double* jacDet ) {
+	FeMesh*		self = (FeMesh*)feMesh;
+	unsigned	nDims;
+	ElementType*	elType;
+	double		jd;
+
+	assert( self );
+	assert( localCoord );
+	assert( derivs );
+
+	nDims = Mesh_GetDimSize( self );
+	elType = FeMesh_GetElementType( self, element );
+	ElementType_ShapeFunctionsGlobalDerivs( elType, self, element, localCoord, nDims, 
+						&jd, derivs );
+	if( jacDet )
+		*jacDet = jd;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+void FeMesh_Destruct( FeMesh* self ) {
+   Stg_Class_Delete( self->feElType );
+	self->feElFamily = NULL;
+	/* Disabling the killing of this object from within this
+	component as this will be destroyed by the LiveComponentRegister_DestroyAll function 101109 */
+	/*KillObject( self->feElType );*/ 
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeMesh_Algorithms.c
--- a/Discretisation/src/FeMesh_Algorithms.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FeMesh_Algorithms.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type FeMesh_Algorithms_Type = "FeMesh_Algorithms";
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-FeMesh_Algorithms* FeMesh_Algorithms_New( Name name, AbstractContext* context ) {
-	/* Variables set in this function */
-	SizeT                                                   _sizeOfSelf = sizeof(FeMesh_Algorithms);
-	Type                                                           type = FeMesh_Algorithms_Type;
-	Stg_Class_DeleteFunction*                                   _delete = _FeMesh_Algorithms_Delete;
-	Stg_Class_PrintFunction*                                     _print = _FeMesh_Algorithms_Print;
-	Stg_Class_CopyFunction*                                       _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*       _defaultConstructor = (void* (*)(Name))_FeMesh_Algorithms_New;
-	Stg_Component_ConstructFunction*                         _construct = _FeMesh_Algorithms_AssignFromXML;
-	Stg_Component_BuildFunction*                                 _build = _FeMesh_Algorithms_Build;
-	Stg_Component_InitialiseFunction*                       _initialise = _FeMesh_Algorithms_Initialise;
-	Stg_Component_ExecuteFunction*                             _execute = _FeMesh_Algorithms_Execute;
-	Stg_Component_DestroyFunction*                             _destroy = _FeMesh_Algorithms_Destroy;
-	AllocationType                                   nameAllocationType = NON_GLOBAL;
-	Mesh_Algorithms_SetMeshFunc*                            setMeshFunc = _Mesh_Algorithms_SetMesh;
-	Mesh_Algorithms_UpdateFunc*                              updateFunc = _Mesh_Algorithms_Update;
-	Mesh_Algorithms_NearestVertexFunc*                nearestVertexFunc = _Mesh_Algorithms_NearestVertex;
-	Mesh_Algorithms_SearchFunc*                              searchFunc = _FeMesh_Algorithms_Search;
-	Mesh_Algorithms_SearchElementsFunc*              searchElementsFunc = _FeMesh_Algorithms_SearchElements;
-	Mesh_Algorithms_GetMinimumSeparationFunc*  getMinimumSeparationFunc = _Mesh_Algorithms_GetMinimumSeparation;
-	Mesh_Algorithms_GetLocalCoordRangeFunc*      getLocalCoordRangeFunc = _Mesh_Algorithms_GetLocalCoordRange;
-	Mesh_Algorithms_GetDomainCoordRangeFunc*    getDomainCoordRangeFunc = _Mesh_Algorithms_GetDomainCoordRange;
-	Mesh_Algorithms_GetGlobalCoordRangeFunc*    getGlobalCoordRangeFunc = _Mesh_Algorithms_GetGlobalCoordRange;
-
-   FeMesh_Algorithms* self =  _FeMesh_Algorithms_New(  FEMESH_ALGORITHMS_PASSARGS  );
-
-   _Mesh_Algorithms_Init( (Mesh_Algorithms*)self, context );
-	_FeMesh_Algorithms_Init( self );
-   return self;
-}
-
-FeMesh_Algorithms* _FeMesh_Algorithms_New(  FEMESH_ALGORITHMS_DEFARGS  ) {
-	FeMesh_Algorithms* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(FeMesh_Algorithms) );
-	self = (FeMesh_Algorithms*)_Mesh_Algorithms_New(  MESH_ALGORITHMS_PASSARGS  );
-
-	return self;
-}
-
-void _FeMesh_Algorithms_Init( FeMesh_Algorithms* self ) {
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _FeMesh_Algorithms_Delete( void* algorithms ) {
-	FeMesh_Algorithms*	self = (FeMesh_Algorithms*)algorithms;
-
-	/* Delete the parent. */
-	_Mesh_Algorithms_Delete( self );
-}
-
-void _FeMesh_Algorithms_Print( void* algorithms, Stream* stream ) {
-	FeMesh_Algorithms*	self = (FeMesh_Algorithms*)algorithms;
-	
-	/* Set the Journal for printing informations */
-	Stream* algorithmsStream;
-	algorithmsStream = Journal_Register( InfoStream_Type, (Name)"FeMesh_AlgorithmsStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "FeMesh_Algorithms (ptr): (%p)\n", self );
-	_Stg_Component_Print( self, stream );
-}
-
-void _FeMesh_Algorithms_AssignFromXML( void* algorithms, Stg_ComponentFactory* cf, void* data ) {
-  _FeMesh_Algorithms_Init( (FeMesh_Algorithms*)algorithms );
-}
-
-void _FeMesh_Algorithms_Build( void* algorithms, void* data ) {
-   FeMesh_Algorithms* self = (FeMesh_Algorithms*)algorithms;
-   _Mesh_Algorithms_Build( self, data );
-}
-
-void _FeMesh_Algorithms_Initialise( void* algorithms, void* data ) {
-   FeMesh_Algorithms* self = (FeMesh_Algorithms*)algorithms;
-   _Mesh_Algorithms_Initialise( self, data );
-}
-
-void _FeMesh_Algorithms_Execute( void* algorithms, void* data ) {
-}
-
-void _FeMesh_Algorithms_Destroy( void* algorithms, void* data ) {
-   FeMesh_Algorithms* self = (FeMesh_Algorithms*)algorithms;
-   _Mesh_Algorithms_Destroy( self, data );
-}
-
-Bool _FeMesh_Algorithms_Search( void* algorithms, double* point, 
-			      MeshTopology_Dim* dim, unsigned* ind )
-{
-	FeMesh_Algorithms*	self = (FeMesh_Algorithms*)algorithms;
-
-	return FeMesh_Algorithms_SearchWithTree( self, point, (unsigned*)dim, ind );
-}
-
-Bool _FeMesh_Algorithms_SearchElements( void* algorithms, double* point, 
-				      unsigned* elInd )
-{
-	FeMesh_Algorithms*	self = (FeMesh_Algorithms*)algorithms;
-	unsigned		dim;
-
-	assert( self );
-
-	return FeMesh_Algorithms_SearchWithTree( self, point, &dim, elInd );
-}
-
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-Bool FeMesh_Algorithms_SearchWithTree( void* _self, double* pnt, unsigned* dim, unsigned* el ) {
-   FeMesh_Algorithms* self = (FeMesh_Algorithms*)_self;
-   int nEls, *els;
-   int curRank, ii;
-   unsigned curDim, curEl;
-   int nLocals, owner;
-   Mesh_ElementType* elType;
-
-   *dim = Mesh_GetDimSize( self->mesh );
-   MPI_Comm_size( MPI_COMM_WORLD, &curRank );
-   nLocals = Mesh_GetLocalSize( self->mesh, (MeshTopology_Dim)(*dim) );
-   if( !SpatialTree_Search( self->tree, pnt, &nEls, &els ) )
-      return False;
-
-   *el = nLocals;
-   elType = Mesh_GetElementType( self->mesh, 0 );
-   for( ii = 0; ii < nEls; ii++ ) {
-     if( FeMesh_ElementType_ElementHasPoint( elType, els[ii], pnt, (MeshTopology_Dim*)(&curDim), &curEl ) ) {
-       if( curEl >= (unsigned)nLocals ) {
-         owner = Mesh_GetOwner( self->mesh, (MeshTopology_Dim)curDim, curEl - nLocals );
-            owner = Comm_RankLocalToGlobal( self->mesh->topo->comm, owner );
-            if( owner <= curRank ) {
-               curRank = owner;
-               *el = curEl;
-            }
-         } else if( self->rank <= curRank && curEl < *el ) {
-            curRank = self->rank;
-            *el = curEl;
-         }
-      }
-   }
-
-   return True;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeMesh_Algorithms.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/FeMesh_Algorithms.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,205 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FeMesh_Algorithms.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type FeMesh_Algorithms_Type = "FeMesh_Algorithms";
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+FeMesh_Algorithms* FeMesh_Algorithms_New( Name name, AbstractContext* context ) {
+	/* Variables set in this function */
+	SizeT                                                   _sizeOfSelf = sizeof(FeMesh_Algorithms);
+	Type                                                           type = FeMesh_Algorithms_Type;
+	Stg_Class_DeleteFunction*                                   _delete = _FeMesh_Algorithms_Delete;
+	Stg_Class_PrintFunction*                                     _print = _FeMesh_Algorithms_Print;
+	Stg_Class_CopyFunction*                                       _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*       _defaultConstructor = (void* (*)(Name))_FeMesh_Algorithms_New;
+	Stg_Component_ConstructFunction*                         _construct = _FeMesh_Algorithms_AssignFromXML;
+	Stg_Component_BuildFunction*                                 _build = _FeMesh_Algorithms_Build;
+	Stg_Component_InitialiseFunction*                       _initialise = _FeMesh_Algorithms_Initialise;
+	Stg_Component_ExecuteFunction*                             _execute = _FeMesh_Algorithms_Execute;
+	Stg_Component_DestroyFunction*                             _destroy = _FeMesh_Algorithms_Destroy;
+	AllocationType                                   nameAllocationType = NON_GLOBAL;
+	Mesh_Algorithms_SetMeshFunc*                            setMeshFunc = _Mesh_Algorithms_SetMesh;
+	Mesh_Algorithms_UpdateFunc*                              updateFunc = _Mesh_Algorithms_Update;
+	Mesh_Algorithms_NearestVertexFunc*                nearestVertexFunc = _Mesh_Algorithms_NearestVertex;
+	Mesh_Algorithms_SearchFunc*                              searchFunc = _FeMesh_Algorithms_Search;
+	Mesh_Algorithms_SearchElementsFunc*              searchElementsFunc = _FeMesh_Algorithms_SearchElements;
+	Mesh_Algorithms_GetMinimumSeparationFunc*  getMinimumSeparationFunc = _Mesh_Algorithms_GetMinimumSeparation;
+	Mesh_Algorithms_GetLocalCoordRangeFunc*      getLocalCoordRangeFunc = _Mesh_Algorithms_GetLocalCoordRange;
+	Mesh_Algorithms_GetDomainCoordRangeFunc*    getDomainCoordRangeFunc = _Mesh_Algorithms_GetDomainCoordRange;
+	Mesh_Algorithms_GetGlobalCoordRangeFunc*    getGlobalCoordRangeFunc = _Mesh_Algorithms_GetGlobalCoordRange;
+
+   FeMesh_Algorithms* self =  _FeMesh_Algorithms_New(  FEMESH_ALGORITHMS_PASSARGS  );
+
+   _Mesh_Algorithms_Init( (Mesh_Algorithms*)self, context );
+	_FeMesh_Algorithms_Init( self );
+   return self;
+}
+
+FeMesh_Algorithms* _FeMesh_Algorithms_New(  FEMESH_ALGORITHMS_DEFARGS  ) {
+	FeMesh_Algorithms* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(FeMesh_Algorithms) );
+	self = (FeMesh_Algorithms*)_Mesh_Algorithms_New(  MESH_ALGORITHMS_PASSARGS  );
+
+	return self;
+}
+
+void _FeMesh_Algorithms_Init( FeMesh_Algorithms* self ) {
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _FeMesh_Algorithms_Delete( void* algorithms ) {
+	FeMesh_Algorithms*	self = (FeMesh_Algorithms*)algorithms;
+
+	/* Delete the parent. */
+	_Mesh_Algorithms_Delete( self );
+}
+
+void _FeMesh_Algorithms_Print( void* algorithms, Stream* stream ) {
+	FeMesh_Algorithms*	self = (FeMesh_Algorithms*)algorithms;
+	
+	/* Set the Journal for printing informations */
+	Stream* algorithmsStream;
+	algorithmsStream = Journal_Register( InfoStream_Type, (Name)"FeMesh_AlgorithmsStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "FeMesh_Algorithms (ptr): (%p)\n", self );
+	_Stg_Component_Print( self, stream );
+}
+
+void _FeMesh_Algorithms_AssignFromXML( void* algorithms, Stg_ComponentFactory* cf, void* data ) {
+  _FeMesh_Algorithms_Init( (FeMesh_Algorithms*)algorithms );
+}
+
+void _FeMesh_Algorithms_Build( void* algorithms, void* data ) {
+   FeMesh_Algorithms* self = (FeMesh_Algorithms*)algorithms;
+   _Mesh_Algorithms_Build( self, data );
+}
+
+void _FeMesh_Algorithms_Initialise( void* algorithms, void* data ) {
+   FeMesh_Algorithms* self = (FeMesh_Algorithms*)algorithms;
+   _Mesh_Algorithms_Initialise( self, data );
+}
+
+void _FeMesh_Algorithms_Execute( void* algorithms, void* data ) {
+}
+
+void _FeMesh_Algorithms_Destroy( void* algorithms, void* data ) {
+   FeMesh_Algorithms* self = (FeMesh_Algorithms*)algorithms;
+   _Mesh_Algorithms_Destroy( self, data );
+}
+
+Bool _FeMesh_Algorithms_Search( void* algorithms, double* point, 
+			      MeshTopology_Dim* dim, unsigned* ind )
+{
+	FeMesh_Algorithms*	self = (FeMesh_Algorithms*)algorithms;
+
+	return FeMesh_Algorithms_SearchWithTree( self, point, (unsigned*)dim, ind );
+}
+
+Bool _FeMesh_Algorithms_SearchElements( void* algorithms, double* point, 
+				      unsigned* elInd )
+{
+	FeMesh_Algorithms*	self = (FeMesh_Algorithms*)algorithms;
+	unsigned		dim;
+
+	assert( self );
+
+	return FeMesh_Algorithms_SearchWithTree( self, point, &dim, elInd );
+}
+
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+Bool FeMesh_Algorithms_SearchWithTree( void* _self, double* pnt, unsigned* dim, unsigned* el ) {
+   FeMesh_Algorithms* self = (FeMesh_Algorithms*)_self;
+   int nEls, *els;
+   int curRank, ii;
+   unsigned curDim, curEl;
+   int nLocals, owner;
+   Mesh_ElementType* elType;
+
+   *dim = Mesh_GetDimSize( self->mesh );
+   MPI_Comm_size( MPI_COMM_WORLD, &curRank );
+   nLocals = Mesh_GetLocalSize( self->mesh, (MeshTopology_Dim)(*dim) );
+   if( !SpatialTree_Search( self->tree, pnt, &nEls, &els ) )
+      return False;
+
+   *el = nLocals;
+   elType = Mesh_GetElementType( self->mesh, 0 );
+   for( ii = 0; ii < nEls; ii++ ) {
+     if( FeMesh_ElementType_ElementHasPoint( elType, els[ii], pnt, (MeshTopology_Dim*)(&curDim), &curEl ) ) {
+       if( curEl >= (unsigned)nLocals ) {
+         owner = Mesh_GetOwner( self->mesh, (MeshTopology_Dim)curDim, curEl - nLocals );
+            owner = Comm_RankLocalToGlobal( self->mesh->topo->comm, owner );
+            if( owner <= curRank ) {
+               curRank = owner;
+               *el = curEl;
+            }
+         } else if( self->rank <= curRank && curEl < *el ) {
+            curRank = self->rank;
+            *el = curEl;
+         }
+      }
+   }
+
+   return True;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeMesh_ElementType.c
--- a/Discretisation/src/FeMesh_ElementType.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,142 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FeMesh_ElementType.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type FeMesh_ElementType_Type = "FeMesh_ElementType";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-FeMesh_ElementType* FeMesh_ElementType_New() {
-	/* Variables set in this function */
-	SizeT                                                    _sizeOfSelf = sizeof(FeMesh_ElementType);
-	Type                                                            type = FeMesh_ElementType_Type;
-	Stg_Class_DeleteFunction*                                    _delete = _FeMesh_ElementType_Delete;
-	Stg_Class_PrintFunction*                                      _print = _FeMesh_ElementType_Print;
-	Stg_Class_CopyFunction*                                        _copy = NULL;
-	Mesh_ElementType_UpdateFunc*                              updateFunc = Mesh_HexType_Update;
-	Mesh_ElementType_ElementHasPointFunc*            elementHasPointFunc = FeMesh_ElementType_ElementHasPoint;
-	Mesh_ElementType_GetMinimumSeparationFunc*  getMinimumSeparationFunc = Mesh_HexType_GetMinimumSeparation;
-	Mesh_ElementType_GetCentroidFunc*                    getCentroidFunc = _Mesh_ElementType_GetCentroid;
-
-	return _FeMesh_ElementType_New(  FEMESH_ELEMENTTYPE_PASSARGS  );
-}
-
-FeMesh_ElementType* _FeMesh_ElementType_New(  FEMESH_ELEMENTTYPE_DEFARGS  ) {
-	FeMesh_ElementType* self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(FeMesh_ElementType) );
-	self = (FeMesh_ElementType*)_Mesh_HexType_New(  MESH_HEXTYPE_PASSARGS  );
-
-	/* Virtual info */
-
-	/* FeMesh_ElementType info */
-	_FeMesh_ElementType_Init( self );
-
-	return self;
-}
-
-void _FeMesh_ElementType_Init( FeMesh_ElementType* self ) {
-	assert( self && Stg_CheckType( self, FeMesh_ElementType ) );
-
-	_Mesh_HexType_Init( (Mesh_HexType*)self );
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _FeMesh_ElementType_Delete( void* elementType ) {
-	FeMesh_ElementType*	self = (FeMesh_ElementType*)elementType;
-
-	/* Delete the parent. */
-	_Mesh_HexType_Delete( self );
-}
-
-void _FeMesh_ElementType_Print( void* elementType, Stream* stream ) {
-	FeMesh_ElementType*	self = (FeMesh_ElementType*)elementType;
-	Stream*			elementTypeStream;
-
-	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"FeMesh_ElementTypeStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "FeMesh_ElementType (ptr): (%p)\n", self );
-	_Mesh_HexType_Print( self, stream );
-}
-
-Bool FeMesh_ElementType_ElementHasPoint( void* hexType, unsigned elInd, double* point, 
-					 MeshTopology_Dim* dim, unsigned* ind )
-{
-	FeMesh_ElementType* self = (FeMesh_ElementType*)hexType;
-	int nDims, ii;
-
-	assert( self && Stg_CheckType( self, FeMesh_ElementType ) );
-	assert( Mesh_GetDimSize( self->mesh ) <= 3 );
-
-	FeMesh_CoordGlobalToLocal( self->mesh, elInd, point, self->local );
-	nDims = Mesh_GetDimSize( self->mesh );
-	for( ii = 0; ii < nDims; ii++ ) {
-		if( self->local[ii] < -1.0 || self->local[ii] > 1.0 )
-			return False;
-	}
-
-	*dim = (MeshTopology_Dim)nDims;
-	*ind = elInd;
-	return True;
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeMesh_ElementType.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/FeMesh_ElementType.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,142 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FeMesh_ElementType.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type FeMesh_ElementType_Type = "FeMesh_ElementType";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+FeMesh_ElementType* FeMesh_ElementType_New() {
+	/* Variables set in this function */
+	SizeT                                                    _sizeOfSelf = sizeof(FeMesh_ElementType);
+	Type                                                            type = FeMesh_ElementType_Type;
+	Stg_Class_DeleteFunction*                                    _delete = _FeMesh_ElementType_Delete;
+	Stg_Class_PrintFunction*                                      _print = _FeMesh_ElementType_Print;
+	Stg_Class_CopyFunction*                                        _copy = NULL;
+	Mesh_ElementType_UpdateFunc*                              updateFunc = Mesh_HexType_Update;
+	Mesh_ElementType_ElementHasPointFunc*            elementHasPointFunc = FeMesh_ElementType_ElementHasPoint;
+	Mesh_ElementType_GetMinimumSeparationFunc*  getMinimumSeparationFunc = Mesh_HexType_GetMinimumSeparation;
+	Mesh_ElementType_GetCentroidFunc*                    getCentroidFunc = _Mesh_ElementType_GetCentroid;
+
+	return _FeMesh_ElementType_New(  FEMESH_ELEMENTTYPE_PASSARGS  );
+}
+
+FeMesh_ElementType* _FeMesh_ElementType_New(  FEMESH_ELEMENTTYPE_DEFARGS  ) {
+	FeMesh_ElementType* self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(FeMesh_ElementType) );
+	self = (FeMesh_ElementType*)_Mesh_HexType_New(  MESH_HEXTYPE_PASSARGS  );
+
+	/* Virtual info */
+
+	/* FeMesh_ElementType info */
+	_FeMesh_ElementType_Init( self );
+
+	return self;
+}
+
+void _FeMesh_ElementType_Init( FeMesh_ElementType* self ) {
+	assert( self && Stg_CheckType( self, FeMesh_ElementType ) );
+
+	_Mesh_HexType_Init( (Mesh_HexType*)self );
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _FeMesh_ElementType_Delete( void* elementType ) {
+	FeMesh_ElementType*	self = (FeMesh_ElementType*)elementType;
+
+	/* Delete the parent. */
+	_Mesh_HexType_Delete( self );
+}
+
+void _FeMesh_ElementType_Print( void* elementType, Stream* stream ) {
+	FeMesh_ElementType*	self = (FeMesh_ElementType*)elementType;
+	Stream*			elementTypeStream;
+
+	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"FeMesh_ElementTypeStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "FeMesh_ElementType (ptr): (%p)\n", self );
+	_Mesh_HexType_Print( self, stream );
+}
+
+Bool FeMesh_ElementType_ElementHasPoint( void* hexType, unsigned elInd, double* point, 
+					 MeshTopology_Dim* dim, unsigned* ind )
+{
+	FeMesh_ElementType* self = (FeMesh_ElementType*)hexType;
+	int nDims, ii;
+
+	assert( self && Stg_CheckType( self, FeMesh_ElementType ) );
+	assert( Mesh_GetDimSize( self->mesh ) <= 3 );
+
+	FeMesh_CoordGlobalToLocal( self->mesh, elInd, point, self->local );
+	nDims = Mesh_GetDimSize( self->mesh );
+	for( ii = 0; ii < nDims; ii++ ) {
+		if( self->local[ii] < -1.0 || self->local[ii] > 1.0 )
+			return False;
+	}
+
+	*dim = (MeshTopology_Dim)nDims;
+	*ind = elInd;
+	return True;
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeSwarmVariable.c
--- a/Discretisation/src/FeSwarmVariable.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FeSwarmVariable.c 1117 2008-05-02 02:50:02Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "types.h"
-#include "FeVariable.h"
-#include "FeMesh.h"
-#include "FeSwarmVariable.h"
-
-#include <assert.h>
-
-const Type FeSwarmVariable_Type = "FeSwarmVariable";
-
-void* _FeSwarmVariable_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(FeSwarmVariable);
-	Type                                                         type = FeSwarmVariable_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _FeSwarmVariable_Delete;
-	Stg_Class_PrintFunction*                                   _print = _FeSwarmVariable_Print;
-	Stg_Class_CopyFunction*                                     _copy = _FeSwarmVariable_Copy;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _FeSwarmVariable_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _FeSwarmVariable_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _FeSwarmVariable_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _FeSwarmVariable_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _FeSwarmVariable_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _FeSwarmVariable_Destroy;
-	AllocationType                                 nameAllocationType = NON_GLOBAL;
-	SwarmVariable_ValueAtFunction*                           _valueAt = _FeSwarmVariable_ValueAt;
-	SwarmVariable_GetGlobalValueFunction*      _getMinGlobalMagnitude = _FeSwarmVariable_GetMinGlobalMagnitude;
-	SwarmVariable_GetGlobalValueFunction*      _getMaxGlobalMagnitude = _FeSwarmVariable_GetMaxGlobalMagnitude;
-
-	return _FeSwarmVariable_New(  FESWARMVARIABLE_PASSARGS  );
-}
-
-FeSwarmVariable* _FeSwarmVariable_New(  FESWARMVARIABLE_DEFARGS  ) {
-	FeSwarmVariable* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(FeSwarmVariable) );
-	self = (FeSwarmVariable*) _SwarmVariable_New(  SWARMVARIABLE_PASSARGS  );
-
-	return self;
-}
-
-void _FeSwarmVariable_Init( void* swarmVariable, FeVariable* feVariable ) {
-	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
-
-	self->feVariable = feVariable;
-   /* variable does not store data, so is not checkpointed */
-   self->isCheckpointedAndReloaded = False;
-}
-
-void _FeSwarmVariable_Delete( void* _swarmVariable ) {
-	FeSwarmVariable* self = (FeSwarmVariable*) _swarmVariable;
-
-	_SwarmVariable_Delete( self );
-}
-
-void _FeSwarmVariable_Print( void* _swarmVariable, Stream* stream ) {
-	FeSwarmVariable* self = (FeSwarmVariable*) _swarmVariable;
-
-	_SwarmVariable_Print( self, stream );
-
-	Journal_PrintPointer( stream, self->feVariable );
-}
-
-void* _FeSwarmVariable_Copy( const void* swarmVariable, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	FeSwarmVariable*	self = (FeSwarmVariable*)swarmVariable;
-	FeSwarmVariable*	newFeSwarmVariable;
-	
-	newFeSwarmVariable = (FeSwarmVariable*)_SwarmVariable_Copy( self, dest, deep, nameExt, ptrMap );
-	
-	newFeSwarmVariable->feVariable = self->feVariable;
-	
-	return (void*)newFeSwarmVariable;
-}
-
-void _FeSwarmVariable_AssignFromXML( void* swarmVariable, Stg_ComponentFactory* cf, void* data ) {
-	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
-
-	_SwarmVariable_AssignFromXML( self, cf, data );
-
-	_FeSwarmVariable_Init( self, Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"FeVariable", FeVariable, True, data )  );
-}
-
-void _FeSwarmVariable_Build( void* swarmVariable, void* data ) {
-	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
-
-	Stg_Component_Build( self->feVariable, data, False );
-}
-
-void _FeSwarmVariable_Initialise( void* swarmVariable, void* data ) {
-	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
-
-	Stg_Component_Initialise( self->feVariable, data, False );
-}
-
-void _FeSwarmVariable_Execute( void* swarmVariable, void* data ) {}
-
-void _FeSwarmVariable_Destroy( void* swarmVariable, void* data ) {
-	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
-
-	_SwarmVariable_Destroy( self, data );
-}
-
-void _FeSwarmVariable_ValueAt( void* swarmVariable, Particle_Index lParticle_I, double* value ) {
-	FeSwarmVariable*  self = (FeSwarmVariable*) swarmVariable;
-	FeMesh*           mesh = self->feVariable->feMesh;
-	Swarm*            swarm = self->swarm;
-	GlobalParticle*   particle = (GlobalParticle*) Swarm_ParticleAt( swarm, lParticle_I );
-	double            xi[3];
-
-	/* check if the swarm is using a GlobalCoordSystem, if not FAIL */
-	Journal_Firewall( (swarm->particleLayout->coordSystem == GlobalCoordSystem), 
-		Journal_Register( Error_Type, (Name)"FeSwarmVariable"  ),
-			"Error in function %s: FeSwarmVariables require swarms with GlobalCoordSystems\n"
-			"This FeSwarmVariable, %s, uses the swarm %s, which doesn't have a GlobalCoordSystem\n",
-			__func__, self->name, swarm->name );
-	FeMesh_CoordGlobalToLocal( mesh, particle->owningCell, particle->coord, xi );
-	FeVariable_InterpolateWithinElement( self->feVariable, particle->owningCell, xi, value );
-}
-
-
-double _FeSwarmVariable_GetMinGlobalMagnitude( void* swarmVariable ) {
-	FeSwarmVariable*  self = (FeSwarmVariable*) swarmVariable;
-
-	return FieldVariable_GetMinGlobalFieldMagnitude( self->feVariable );
-}
-double _FeSwarmVariable_GetMaxGlobalMagnitude( void* swarmVariable ) {
-	FeSwarmVariable*  self = (FeSwarmVariable*) swarmVariable;
-
-	return FieldVariable_GetMaxGlobalFieldMagnitude( self->feVariable );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeSwarmVariable.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/FeSwarmVariable.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,177 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FeSwarmVariable.c 1117 2008-05-02 02:50:02Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "types.h"
+#include "FeVariable.h"
+#include "FeMesh.h"
+#include "FeSwarmVariable.h"
+
+#include <assert.h>
+
+const Type FeSwarmVariable_Type = "FeSwarmVariable";
+
+void* _FeSwarmVariable_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(FeSwarmVariable);
+	Type                                                         type = FeSwarmVariable_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _FeSwarmVariable_Delete;
+	Stg_Class_PrintFunction*                                   _print = _FeSwarmVariable_Print;
+	Stg_Class_CopyFunction*                                     _copy = _FeSwarmVariable_Copy;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _FeSwarmVariable_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _FeSwarmVariable_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _FeSwarmVariable_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _FeSwarmVariable_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _FeSwarmVariable_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _FeSwarmVariable_Destroy;
+	AllocationType                                 nameAllocationType = NON_GLOBAL;
+	SwarmVariable_ValueAtFunction*                           _valueAt = _FeSwarmVariable_ValueAt;
+	SwarmVariable_GetGlobalValueFunction*      _getMinGlobalMagnitude = _FeSwarmVariable_GetMinGlobalMagnitude;
+	SwarmVariable_GetGlobalValueFunction*      _getMaxGlobalMagnitude = _FeSwarmVariable_GetMaxGlobalMagnitude;
+
+	return _FeSwarmVariable_New(  FESWARMVARIABLE_PASSARGS  );
+}
+
+FeSwarmVariable* _FeSwarmVariable_New(  FESWARMVARIABLE_DEFARGS  ) {
+	FeSwarmVariable* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(FeSwarmVariable) );
+	self = (FeSwarmVariable*) _SwarmVariable_New(  SWARMVARIABLE_PASSARGS  );
+
+	return self;
+}
+
+void _FeSwarmVariable_Init( void* swarmVariable, FeVariable* feVariable ) {
+	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
+
+	self->feVariable = feVariable;
+   /* variable does not store data, so is not checkpointed */
+   self->isCheckpointedAndReloaded = False;
+}
+
+void _FeSwarmVariable_Delete( void* _swarmVariable ) {
+	FeSwarmVariable* self = (FeSwarmVariable*) _swarmVariable;
+
+	_SwarmVariable_Delete( self );
+}
+
+void _FeSwarmVariable_Print( void* _swarmVariable, Stream* stream ) {
+	FeSwarmVariable* self = (FeSwarmVariable*) _swarmVariable;
+
+	_SwarmVariable_Print( self, stream );
+
+	Journal_PrintPointer( stream, self->feVariable );
+}
+
+void* _FeSwarmVariable_Copy( const void* swarmVariable, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	FeSwarmVariable*	self = (FeSwarmVariable*)swarmVariable;
+	FeSwarmVariable*	newFeSwarmVariable;
+	
+	newFeSwarmVariable = (FeSwarmVariable*)_SwarmVariable_Copy( self, dest, deep, nameExt, ptrMap );
+	
+	newFeSwarmVariable->feVariable = self->feVariable;
+	
+	return (void*)newFeSwarmVariable;
+}
+
+void _FeSwarmVariable_AssignFromXML( void* swarmVariable, Stg_ComponentFactory* cf, void* data ) {
+	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
+
+	_SwarmVariable_AssignFromXML( self, cf, data );
+
+	_FeSwarmVariable_Init( self, Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"FeVariable", FeVariable, True, data )  );
+}
+
+void _FeSwarmVariable_Build( void* swarmVariable, void* data ) {
+	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
+
+	Stg_Component_Build( self->feVariable, data, False );
+}
+
+void _FeSwarmVariable_Initialise( void* swarmVariable, void* data ) {
+	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
+
+	Stg_Component_Initialise( self->feVariable, data, False );
+}
+
+void _FeSwarmVariable_Execute( void* swarmVariable, void* data ) {}
+
+void _FeSwarmVariable_Destroy( void* swarmVariable, void* data ) {
+	FeSwarmVariable* self = (FeSwarmVariable*) swarmVariable;
+
+	_SwarmVariable_Destroy( self, data );
+}
+
+void _FeSwarmVariable_ValueAt( void* swarmVariable, Particle_Index lParticle_I, double* value ) {
+	FeSwarmVariable*  self = (FeSwarmVariable*) swarmVariable;
+	FeMesh*           mesh = self->feVariable->feMesh;
+	Swarm*            swarm = self->swarm;
+	GlobalParticle*   particle = (GlobalParticle*) Swarm_ParticleAt( swarm, lParticle_I );
+	double            xi[3];
+
+	/* check if the swarm is using a GlobalCoordSystem, if not FAIL */
+	Journal_Firewall( (swarm->particleLayout->coordSystem == GlobalCoordSystem), 
+		Journal_Register( Error_Type, (Name)"FeSwarmVariable"  ),
+			"Error in function %s: FeSwarmVariables require swarms with GlobalCoordSystems\n"
+			"This FeSwarmVariable, %s, uses the swarm %s, which doesn't have a GlobalCoordSystem\n",
+			__func__, self->name, swarm->name );
+	FeMesh_CoordGlobalToLocal( mesh, particle->owningCell, particle->coord, xi );
+	FeVariable_InterpolateWithinElement( self->feVariable, particle->owningCell, xi, value );
+}
+
+
+double _FeSwarmVariable_GetMinGlobalMagnitude( void* swarmVariable ) {
+	FeSwarmVariable*  self = (FeSwarmVariable*) swarmVariable;
+
+	return FieldVariable_GetMinGlobalFieldMagnitude( self->feVariable );
+}
+double _FeSwarmVariable_GetMaxGlobalMagnitude( void* swarmVariable ) {
+	FeSwarmVariable*  self = (FeSwarmVariable*) swarmVariable;
+
+	return FieldVariable_GetMaxGlobalFieldMagnitude( self->feVariable );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeVariable.c
--- a/Discretisation/src/FeVariable.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2725 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FeVariable.c 1224 2008-09-10 13:28:46Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include "units.h"
-#include "types.h"
-#include "ElementType.h"
-#include "ElementType_Register.h"
-#include "Element.h"
-#include "FeMesh.h"
-#include "FeEquationNumber.h"
-#include "FeVariable.h"
-#include "LinkedDofInfo.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-#if defined(READ_HDF5) || defined(WRITE_HDF5)
-#include <hdf5.h>
-#endif
-
-const Type FeVariable_Type = "FeVariable";
-const Name defaultFeVariableFeEquationNumberName = "defaultFeVariableFeEqName";
-
-/** MPI Tags */
-static const int DOF_VALUES_TAG = 10;
-
-/** Global objects */
-Stg_ObjectList* FeVariable_FileFormatImportExportList = NULL;
-
-FeVariable* FeVariable_New_FromTemplate(
-	Name							name,
-	DomainContext*				context,
-	void*							_templateFeVariable,
-	DofLayout*					dofLayout, 
-	void*							ics,
-	Bool							isReferenceSolution,
-	Bool							loadReferenceEachTimestep,
-	FieldVariable_Register*	fV_Register )
-{
-  FeVariable*	templateFeVariable = (FeVariable*)_templateFeVariable;
-	FeVariable*	newFeVariable = NULL;
-	
-	newFeVariable = FeVariable_New_Full(
-		name, 
-		context,
-		templateFeVariable->feMesh,
-		templateFeVariable->geometryMesh,
-		dofLayout,
-		templateFeVariable->bcs,
-		ics,
-		templateFeVariable->linkedDofInfo,
-		templateFeVariable,
-		templateFeVariable->fieldComponentCount,
-		templateFeVariable->dim,
-		templateFeVariable->isCheckpointedAndReloaded,
-		isReferenceSolution,
-		loadReferenceEachTimestep,
-		templateFeVariable->communicator,
-		fV_Register );
-
-	newFeVariable->templateFeVariable = templateFeVariable;
-
-	return newFeVariable;
-}
-
-FeVariable* FeVariable_New(
-	Name							name,
-	DomainContext*				context,
-	void*							feMesh,
-	void*							geometryMesh,
-	DofLayout*					dofLayout, 
-	void*							bcs,
-	void*							ics,
-	void*							linkedDofInfo,
-	Dimension_Index			dim,
-	Bool							isCheckpointedAndReloaded,
-	Bool							isReferenceSolution,
-	Bool							loadReferenceEachTimestep,
-	FieldVariable_Register*	fV_Register )		
-{
-	assert( Class_IsSuper( ((FeMesh*)feMesh)->topo, IGraph ) );
-
-	return FeVariable_New_Full(
-		name,
-		context,
-		feMesh,
-		geometryMesh,
-		dofLayout,
-		bcs,
-		ics,
-		linkedDofInfo,
-		NULL,
-		dofLayout->_totalVarCount,
-		dim,
-		isCheckpointedAndReloaded,
-		isReferenceSolution,
-		loadReferenceEachTimestep,
-		((IGraph*)((FeMesh*)feMesh)->topo)->remotes[MT_VERTEX]->comm->mpiComm, 
-		fV_Register );
-}
-
-FeVariable* FeVariable_New_Full(
-	Name							name,
-	DomainContext*				context,
-	void*							feMesh,
-	void*							geometryMesh,
-	DofLayout*					dofLayout, 
-	void*							bcs,
-	void*							ics,
-	void*							linkedDofInfo,
-	void*							templateFeVariable,
-	Index							fieldComponentCount,
-	Dimension_Index			dim,
-	Bool							isCheckpointedAndReloaded,
-	Bool							isReferenceSolution,
-	Bool							loadReferenceEachTimestep,
-	MPI_Comm						communicator,
-	FieldVariable_Register*	fieldVariable_Register )		
-{
-  FeVariable* self = (FeVariable*)_FeVariable_DefaultNew( name );
-
-	self->isConstructed = True;
-	_FieldVariable_Init( (FieldVariable*)self, context, fieldComponentCount, dim, isCheckpointedAndReloaded, communicator, fieldVariable_Register );
-	_FeVariable_Init( self, feMesh, geometryMesh, dofLayout, bcs, ics, linkedDofInfo, templateFeVariable, isReferenceSolution, loadReferenceEachTimestep );
-
-	return self;
-}
-
-void* _FeVariable_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                         _sizeOfSelf = sizeof(FeVariable);
-	Type                                                                 type = FeVariable_Type;
-	Stg_Class_DeleteFunction*                                         _delete = _FeVariable_Delete;
-	Stg_Class_PrintFunction*                                           _print = _FeVariable_Print;
-	Stg_Class_CopyFunction*                                             _copy = _FeVariable_Copy;
-	Stg_Component_DefaultConstructorFunction*             _defaultConstructor = (Stg_Component_DefaultConstructorFunction*)_FeVariable_DefaultNew;
-	Stg_Component_ConstructFunction*                               _construct = _FeVariable_AssignFromXML;
-	Stg_Component_BuildFunction*                                       _build = _FeVariable_Build;
-	Stg_Component_InitialiseFunction*                             _initialise = _FeVariable_Initialise;
-	Stg_Component_ExecuteFunction*                                   _execute = _FeVariable_Execute;
-	Stg_Component_DestroyFunction*                                   _destroy = _FeVariable_Destroy;
-	AllocationType                                         nameAllocationType = NON_GLOBAL;
-	FieldVariable_InterpolateValueAtFunction*             _interpolateValueAt = _FeVariable_InterpolateValueAt;
-	FieldVariable_GetValueFunction*               _getMinGlobalFieldMagnitude = _FeVariable_GetMinGlobalFieldMagnitude;
-	FieldVariable_GetValueFunction*               _getMaxGlobalFieldMagnitude = _FeVariable_GetMaxGlobalFieldMagnitude;
-	FieldVariable_GetCoordFunction*                  _getMinAndMaxLocalCoords = _FeVariable_GetMinAndMaxLocalCoords;
-	FieldVariable_GetCoordFunction*                 _getMinAndMaxGlobalCoords = _FeVariable_GetMinAndMaxGlobalCoords;
-	FeVariable_InterpolateWithinElementFunction*    _interpolateWithinElement = _FeVariable_InterpolateNodeValuesToElLocalCoord;
-	FeVariable_GetValueAtNodeFunction*                        _getValueAtNode = _FeVariable_GetValueAtNode;
-	FeVariable_SyncShadowValuesFunc*                        _syncShadowValues = _FeVariable_SyncShadowValues;
-
-	return _FeVariable_New(  FEVARIABLE_PASSARGS  ); /* feVariableList */
-}
-
-FeVariable* _FeVariable_New(  FEVARIABLE_DEFARGS  ) {
-	FeVariable* self;
-	
-	/** Allocate memory */
-	assert( _sizeOfSelf >= sizeof(FeVariable) );
-	
-	self = (FeVariable*) _FieldVariable_New(  FIELDVARIABLE_PASSARGS  );
-	
-	/** General info */
-	
-	/** Virtual functions */
-	self->_interpolateWithinElement = _interpolateWithinElement;
-	self->_getValueAtNode = _getValueAtNode;
-	self->_syncShadowValues = _syncShadowValues;
-	
-	/** FeVariable info */
-	
-	return self;
-}
-
-
-void _FeVariable_Init( 
-	FeVariable*	self,
-	void*			feMesh,
-	void*			geometryMesh,
-	DofLayout*	dofLayout, 
-	void*			bcs,
-	void*			ics,
-	void*			linkedDofInfo,
-	void*			templateFeVariable,
-	Bool			isReferenceSolution,
-	Bool			loadReferenceEachTimestep )
-{
-	Stream* errorStream = Journal_Register( Error_Type, (Name)self->type  );
-	/** General and Virtual info should already be set */
-	
-	/** FeVariable info */
-	self->debug = Stream_RegisterChild( StgFEM_Discretisation_Debug, self->type );
-	self->feMesh = Stg_CheckType( feMesh, FeMesh );
-	/** Set pointer for geometry mesh - if none is provided then it'll use the feMesh */
-	self->geometryMesh = ( geometryMesh ?  Stg_CheckType( geometryMesh, FeMesh ) : Stg_CheckType( feMesh, FeMesh ) );
-	self->dofLayout = dofLayout;
-	if ( bcs )
-		self->bcs = Stg_CheckType( bcs, VariableCondition );
-	if ( ics )
-		self->ics = Stg_CheckType( ics, VariableCondition );
-	if ( linkedDofInfo )
-		self->linkedDofInfo = Stg_CheckType( linkedDofInfo, LinkedDofInfo );
-	self->shadowValuesSynchronised = False;
-
-	if ( templateFeVariable )
-		self->templateFeVariable = Stg_CheckType( templateFeVariable, FeVariable );
-	if( !isReferenceSolution ) {
-		if ( self->templateFeVariable ) {
-			self->eqNum = self->templateFeVariable->eqNum;
-		}
-		else {
-                  self->eqNum = FeEquationNumber_New( defaultFeVariableFeEquationNumberName, self->context, self->feMesh, self->dofLayout, self->bcs, (LinkedDofInfo*)linkedDofInfo );
-			self->eqNum->removeBCs = self->removeBCs;
-		}
-	}
-	else
-		self->eqNum = NULL;
-
-	self->isReferenceSolution = isReferenceSolution;
-	self->loadReferenceEachTimestep = loadReferenceEachTimestep;
-	Journal_Firewall( (self->loadReferenceEachTimestep != True), errorStream, "The loadReferenceEachTimestep feature isn't implemented yet, sorry.\n" );
-
-	self->dynamicBCs[0] = NULL;
-	self->dynamicBCs[1] = NULL;
-	self->dynamicBCs[2] = NULL;
-
-	self->buildEqNums = True;
-
-	self->inc = IArray_New();
-}
-
-void _FeVariable_Delete( void* variable ) {
-	FeVariable* self = (FeVariable*)variable;
-	Journal_DPrintf( self->debug, "In %s- for \"%s\":\n", __func__, self->name );
-	
-	/** Stg_Class_Delete parent*/
-	_Stg_Component_Delete( self );
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-/** --- Virtual Function Implementations --- */
-
-void _FeVariable_Print( void* variable, Stream* stream ) {
-	FeVariable* self = (FeVariable*)variable;
-	
-	/** General info */
-	Journal_Printf( stream, "FeVariable (ptr): %p\n", self );
-	
-	/** Print parent */
-	_Stg_Component_Print( self, stream );
-	
-	/** Virtual info */
-	
-	/** FeVariable info */
-	Stg_Class_Print( self->feMesh, stream );
-	if ( self->dofLayout ) {
-		Stg_Class_Print( self->dofLayout, stream );
-	}
-	else {
-		Journal_Printf( stream, "\tdofLayout: (null)... not provided (may be Operator type)\n" );
-	}
-	if ( self->bcs ) {
-		Stg_Class_Print( self->bcs, stream );
-	}
-	else {
-		Journal_Printf( stream, "\tbcs: (null)... not provided (may be Operator type)\n" );
-	}
-	if ( self->ics ) {
-		Stg_Class_Print( self->ics, stream );
-	}
-	else {
-		Journal_Printf( stream, "\tics: (null)... not provided (may be Operator type)\n" );
-	}
-
-	if ( self->linkedDofInfo ) {
-		Stg_Class_Print( self->linkedDofInfo, stream );
-	}
-	else {
-		Journal_Printf( stream, "\tlinkedDofInfo: (null)... not provided\n" );
-	}
-	
-	if( self->eqNum ) {
-		Stg_Class_Print( self->eqNum, stream );
-	}
-	else {
-		Journal_Printf( stream, "\teqNum: (null)... not built yet\n" );
-	}
-}
-
-void* _FeVariable_Copy( const void* feVariable, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-	FeVariable*	newFeVariable;
-	PtrMap*		map = ptrMap;
-	Bool		ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newFeVariable = (FeVariable*)_FieldVariable_Copy( self, dest, deep, nameExt, map );
-
-	newFeVariable->templateFeVariable = self->templateFeVariable;
-	
-	if( deep ) {
-		newFeVariable->debug = self->debug; 
-		newFeVariable->feMesh = (FeMesh*)Stg_Class_Copy( self->feMesh, NULL, deep, nameExt, map );
-		newFeVariable->dofLayout = (DofLayout*)Stg_Class_Copy( self->dofLayout, NULL, deep, nameExt, map );
-		newFeVariable->bcs = (VariableCondition*)Stg_Class_Copy( self->bcs, NULL, deep, nameExt, map );
-		newFeVariable->ics = self->ics ? (VariableCondition*)Stg_Class_Copy( self->ics, NULL, deep, nameExt, map ) : NULL;
-		if ( self->linkedDofInfo == NULL ) {
-			newFeVariable->linkedDofInfo = NULL;
-		}
-		else {
-			newFeVariable->linkedDofInfo = (LinkedDofInfo*)Stg_Class_Copy( self->linkedDofInfo, NULL,
-				deep, nameExt, map );
-		}
-
-		if( !self->isReferenceSolution ) {
-			if ( self->templateFeVariable ) {
-				newFeVariable->eqNum = self->eqNum;
-			}
-			else {
-				newFeVariable->eqNum = (FeEquationNumber*)Stg_Class_Copy( self->eqNum, NULL, deep, nameExt, map );
-			}
-		}
-		else
-			newFeVariable->eqNum = NULL;
-	}
-	else {
-		newFeVariable->debug = self->debug;
-		newFeVariable->feMesh = self->feMesh;
-		newFeVariable->geometryMesh = self->geometryMesh;
-		newFeVariable->dofLayout = self->dofLayout;
-		newFeVariable->bcs = self->bcs;
-		newFeVariable->ics = self->ics;
-		newFeVariable->linkedDofInfo = self->linkedDofInfo;
-		newFeVariable->eqNum = self->eqNum;
-	}
-	
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-	
-	return (void*)newFeVariable;
-}
-
-
-void _FeVariable_Build( void* variable, void* data ) {
-	FeVariable* self = (FeVariable*)variable;
-	DomainContext*   context = (DomainContext*)data;
-	unsigned dim, numNodes;
-	
-	if ( False == self->isBuilt ) {
-		self->isBuilt = True;
-	
-		Journal_DPrintf( self->debug, "In %s- for %s:\n", __func__, self->name );
-		Stream_IndentBranch( StgFEM_Debug );
-
-		/** build the BCs */
-		Stg_Component_Build( self->feMesh, data, False );
-		if ( self->dofLayout ) Stg_Component_Build( self->dofLayout, data, False );
-		if ( self->bcs       ) Stg_Component_Build( self->bcs,       data, False );
-		
-		/** only bother building the ics specified via XML/construct if we are not in restart mode
-		  - otherwise, we will use the checkpointed values anyway */
-		if ( self->ics && !(context && (True == context->loadFromCheckPoint) ) ) {
-			Stg_Component_Build( self->ics, data, False );
-		}
-
-		if ( self->linkedDofInfo )	Stg_Component_Build( self->linkedDofInfo, data, False );
-
-
-		/** Extract component count. */
-		if ( self->dofLayout ) self->fieldComponentCount = self->dofLayout->_totalVarCount;
-
-		dim = Mesh_GetDimSize(self->feMesh);
-		/** allocate GNx here */
-		/* At least this will work for meshes with names other
-			than those listed above. I spent three hours finding
-			this out.*/
-		numNodes = FeMesh_GetElementNodeSize(self->feMesh, 0);
-
-		self->GNx = Memory_Alloc_2DArray( double, dim, numNodes, (Name)"Global Shape Function Derivatives" );
-		
-		/** don't build the equation numbers for fields that aren't being solved for 
-		 * (ie: error and reference fields) */
-		if( !self->isReferenceSolution && self->buildEqNums  ) {
-			Stg_Component_Build( self->eqNum, data, False );
-		}
-
-		Stream_UnIndentBranch( StgFEM_Debug );
-	}
-}
-
-void _FeVariable_AssignFromXML( void* variable, Stg_ComponentFactory* cf, void* data ) {
-	FeVariable*         self = (FeVariable*)variable;
-	FeMesh*             feMesh = NULL;
-	FeMesh*             geometryMesh = NULL;
-	DofLayout*          dofLayout = NULL;
-	VariableCondition*  bc = NULL;
-	VariableCondition*  ic = NULL;
-	LinkedDofInfo*      linkedDofInfo 	= NULL;
-	Bool                isReferenceSolution = False;
-	Bool                loadReferenceEachTimestep = False;
-
-	_FieldVariable_AssignFromXML( self, cf, data );
-
-	feMesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"FEMesh", FeMesh, True, data  );
-	geometryMesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"GeometryMesh", FeMesh, False, data  );
-	dofLayout = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)DofLayout_Type, DofLayout, True, data  );
-
-	ic = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"IC", VariableCondition, False, data  );
-	bc = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"BC", VariableCondition, False, data  );
-	linkedDofInfo = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"LinkedDofInfo", LinkedDofInfo, False, data  );
-
-	isReferenceSolution = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"isReferenceSolution", False  );
-	loadReferenceEachTimestep = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"loadReferenceEachTimestep", False  );
-
-	/** TODO: should really be a parameter */
-	self->removeBCs = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"removeBCs", True  );
-
-	_FeVariable_Init( self, feMesh, geometryMesh, dofLayout, bc, ic, linkedDofInfo, NULL, isReferenceSolution, loadReferenceEachTimestep );
-}
-
-void _FeVariable_Initialise( void* variable, void* data ) {
-	FeVariable* 	self = (FeVariable*)variable;
-	DomainContext*	context = self->context; 
-	char*				inputPathString = NULL;
-   Dictionary_Entry_Value* feVarsList = NULL;
-	
-	Journal_DPrintf( self->debug, "In %s- for %s:\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-	
-	/** do basic mesh initialisation */
-	Stg_Component_Initialise( self->feMesh, data, False );
-	Stg_Component_Initialise( self->dofLayout, data, False );
-
-	if ( self->linkedDofInfo ) {
-		Stg_Component_Initialise( self->linkedDofInfo, data, False );
-	}
-
-	if( !self->isReferenceSolution ) {	
-		Stg_Component_Initialise( self->eqNum, data, False );
-	}
-
-	if ( context ) {
-		/** Get the input path string once here - single point of control */
-		inputPathString = Context_GetCheckPointReadPrefixString( context );
-	}
-	/** If the reference solution option is enabled, just load this up regardless of checkpointing options below.
-	 * Want to allow option of disabling this feature, if you're manually setting up a FeVariable without a context etc. */
-	if ( context && self->isReferenceSolution ) {
-		char * filename = NULL;
-		Journal_DPrintf( self->debug, "Reference FeVariable -> loading nodal values from file.\n" );
-		
-		 
-#ifdef READ_HDF5
-		Stg_asprintf( &filename, "%s%s.%.5u.h5", inputPathString, self->name, context->restartTimestep );
-#else
-		Stg_asprintf( &filename, "%s%s.%.5u.dat", inputPathString, self->name, context->restartTimestep );
-#endif
-		FeVariable_ReadFromFile( self, filename );
-
-		Memory_Free( filename );
-		Stream_UnIndentBranch( StgFEM_Debug );
-		return;
-	}
-
-	/** Setting up whether to load from checkpointing */
-	if ( self->ics || ((context && (True == context->loadFromCheckPoint) )&& (self->isCheckpointedAndReloaded)) )  {
-		Journal_DPrintf( self->debug, "applying the I.C.s for this Variable:\n" ); 
-		Stream_Indent( self->debug );
-	
-		if ( self->ics && !(context && (True == context->loadFromCheckPoint) && (True == self->isCheckpointedAndReloaded)) ) {
-			Journal_DPrintf( self->debug, "regular (non-restart) mode -> applying ICs specified in XML/constructor\n" );
-			Stg_Component_Initialise( self->ics, context, False );
-			VariableCondition_Apply( self->ics, context );
-		}
-		else {
-			char * filename = NULL;
-			Journal_DPrintf( self->debug, "restart from checkpoint mode -> loading checkpointed "
-				"nodal values as initial conditions, ignoring ics specified via XML/constructor\n" );
-			 
-#ifdef READ_HDF5
-			Stg_asprintf( &filename, "%s%s.%.5u.h5", inputPathString, self->name, context->restartTimestep );
-         if (!context->interpolateRestart)
-            FeVariable_ReadFromFile( self, filename );
-         else {
-            char * meshFilename = NULL;
-            if (!strcmp(self->feMesh->generator->type, CartesianGenerator_Type))
-               Stg_asprintf( &meshFilename, "%sMesh.%s.%.5u.h5", inputPathString, self->feMesh->name, context->restartTimestep );
-            else
-               Stg_asprintf( &meshFilename, "%sMesh.%s.%.5u.h5", inputPathString, ((C0Generator*)(self->feMesh->generator))->elMesh->name, context->restartTimestep );
-            FeVariable_InterpolateFromFile( self, context, filename, meshFilename );
-            Memory_Free( meshFilename );
-         }
-			
-#else
-			Stg_asprintf( &filename, "%s%s.%.5u.dat", inputPathString, self->name, context->restartTimestep );
-			FeVariable_ReadFromFile( self, filename );
-#endif
-
-			Memory_Free( filename );
-			
-		}
-	}
-	Memory_Free( inputPathString );
-	Stream_UnIndent( self->debug );
-
-	if( context ) {
-   		/** also include check to see if this fevariable should be checkpointed, just incase it didn't go through the 
-		fieldvariable construct phase */ 
-		feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"fieldVariablesToCheckpoint" );
-		if ( NULL == feVarsList  ) {
-		feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"FieldVariablesToCheckpoint" );
-		}
-		if (feVarsList != NULL ) {
-			Index                    listLength = Dictionary_Entry_Value_GetCount( feVarsList );
-			Index                    var_I = 0;
-			Dictionary_Entry_Value*  feVarDictValue = NULL;
-			char*                    fieldVariableName;
-   
-			for ( var_I = 0; var_I < listLength; var_I++  ) {
-				feVarDictValue = Dictionary_Entry_Value_GetElement( feVarsList, var_I );
-				fieldVariableName = Dictionary_Entry_Value_AsString( feVarDictValue ); 
-				if ( 0 == strcmp( self->name, fieldVariableName ) ) {
-					self->isCheckpointedAndReloaded = True;
-					break;
-				}
-			}
-		}
-
-		feVarsList = NULL;
-		/** also include check to see if this fevariable should be saved for analysis purposes */ 
-		feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"fieldVariablesToSave" );
-		if ( NULL == feVarsList  ) {
-			feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"FieldVariablesToSave" );	
-		}
-		if (feVarsList != NULL ) {
-			Index                    listLength = Dictionary_Entry_Value_GetCount( feVarsList );
-			Index                    var_I = 0;
-			Dictionary_Entry_Value*  feVarDictValue = NULL;
-			char*                    fieldVariableName;
-   
-			for ( var_I = 0; var_I < listLength; var_I++  ) {
-				feVarDictValue = Dictionary_Entry_Value_GetElement( feVarsList, var_I );
-				fieldVariableName = Dictionary_Entry_Value_AsString( feVarDictValue ); 
-				if ( 0 == strcmp( self->name, fieldVariableName ) ) {
-					self->isSavedData = True;
-					break;
-				}
-			}
-		}
-	}
-   
-	if ( self->bcs ) {
-		Stg_Component_Initialise( self->bcs, context, False );
-		Journal_DPrintf( self->debug, "applying the B.C.s for this Variable.\n" ); 
-		VariableCondition_Apply( self->bcs, context );
-	}
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void FeVariable_ApplyBCs( void* variable, void* data ) {
-	FeVariable* self = (FeVariable*)variable;
-
-        /** This is an unpleasant hack; we really need to reevaluate our BC code. */
-	if( self->dynamicBCs[0] ) {
-		VariableCondition_Apply( self->dynamicBCs[0], data );
-	}
-	if( self->dynamicBCs[1] ) {
-		VariableCondition_Apply( self->dynamicBCs[1], data );
-	}
-	if( self->dynamicBCs[2] ) {
-		VariableCondition_Apply( self->dynamicBCs[2], data );
-	}
-	if ( self->bcs ) {
-		Journal_DPrintf( self->debug, "In %s- for %s:\n", __func__, self->name );
-		Journal_DPrintf( self->debug, "applying the B.C.s for this Variable.\n" ); 
-		VariableCondition_Apply( self->bcs, data );
-	}
-}
-
-Bool FeVariable_IsBC( void* variable, int node, int dof ) {
-	FeVariable* self = (FeVariable*)variable;
-
-	assert( self );
-	if( self->dynamicBCs[0] && 
-	    self->dynamicBCs[0]->var == DofLayout_GetVariable( self->dofLayout, node, dof ) && 
-	    IMap_Has( self->dynamicBCs[0]->vcMap, node ) )
-	{
-		return True;
-	}
-
-	if( self->dynamicBCs[1] && 
-	    self->dynamicBCs[1]->var == DofLayout_GetVariable( self->dofLayout, node, dof ) && 
-	    IMap_Has( self->dynamicBCs[1]->vcMap, node ) )
-	{
-		return True;
-	}
-
-	if( self->dynamicBCs[2] && 
-	    self->dynamicBCs[2]->var == DofLayout_GetVariable( self->dofLayout, node, dof ) && 
-	    IMap_Has( self->dynamicBCs[2]->vcMap, node ) )
-	{
-		return True;
-	}
-
-	if( self->bcs && 
-	    VariableCondition_IsCondition( self->bcs, node, self->dofLayout->varIndices[node][dof] ) )
-	{
-		return True;
-	}
-
-	return False;
-}
-
-
-void _FeVariable_Execute( void* variable, void* data ) {
-}
-
-void _FeVariable_Destroy( void* variable, void* data ) {
-	FeVariable* self = (FeVariable*)variable;
-
-	Memory_Free( self->GNx );
-
-	Stream_IndentBranch( StgFEM_Debug );
-
-	if( self->eqNum && ( NULL == self->templateFeVariable ) ) {
-		_Stg_Component_Delete( self->eqNum );
-      self->eqNum = NULL;
-	}
-	/** feMesh bc and doflayout are purposely not deleted */
-
-   if( self->inc == NULL ) {
-      NewClass_Delete( self->inc );
-      self->inc = NULL;
-   }
-
-	_FieldVariable_Destroy( self, data );
-}
-
-void FeVariable_PrintLocalDiscreteValues( void* variable, Stream* stream ) {
-	FeVariable* self = (FeVariable*)variable;
-
-	Journal_Printf( stream, "In %s: for FeVariable \"%s\":\n", __func__, self->name );
-
-	_FeVariable_PrintLocalOrDomainValues( variable, FeMesh_GetNodeLocalSize( self->feMesh ), stream );
-}
-
-unsigned _FeVariable_ClosestNode( FeVariable* self, double* crd ) {
-	assert( self );
-	return Mesh_NearestVertex( self->feMesh, crd );
-}
-
-
-InterpolationResult _FeVariable_InterpolateValueAt( void* variable, double* globalCoord, double* value ) {
-	FeVariable*				self = (FeVariable*)variable;
-	Element_DomainIndex	elementCoordIn = (unsigned)-1;
-	Coord						elLocalCoord={0,0,0};
-	InterpolationResult	retValue;
-
-
-	retValue = FeVariable_GetElementLocalCoordAtGlobalCoord( self, globalCoord, elLocalCoord, &elementCoordIn );
-	
-	if ( retValue == LOCAL ) {
-		/** Now interpolate the value at that coordinate, using shape functions */
-		self->_interpolateWithinElement( self, elementCoordIn, elLocalCoord, value );
-	}
-	else if ( retValue == SHADOW ) {
-		if ( False == self->shadowValuesSynchronised ) {
-			Stream* warningStr = Journal_Register( Error_Type, (Name)self->type  );
-			Journal_Printf( warningStr, "Warning - in %s: user asking to interpolate a value at "
-				"coord (%g,%g,%g), which is in shadow space, but "
-				"FeVariable_SyncShadowValues() hasn't been called yet.\n", 
-				__func__, globalCoord[0], globalCoord[1], globalCoord[2] );
-			return retValue;		
-		}
-		/** Now interpolate the value at that coordinate, using shape functions */
-		self->_interpolateWithinElement( self, elementCoordIn, elLocalCoord, value );
-	}
-	
-	return retValue;
-}
-
-
-double _FeVariable_GetMinGlobalFieldMagnitude( void* feVariable ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-	FeMesh*		feMesh = self->feMesh;
-	int		node_lI=0;
-	int		nodeLocalCount = FeMesh_GetNodeLocalSize( feMesh );
-	double		min = 0;
-	double		globalMin = 0;
-	double		currValue;
-
-	min = FeVariable_GetScalarAtNode( self, 0 );
-	
-	/** Find upper and lower bounds on this processor */
-	for ( node_lI = 0 ; node_lI < nodeLocalCount ; node_lI++ ) {
-		currValue = FeVariable_GetScalarAtNode( self, node_lI );
-		if ( currValue < min ) {
-			min = currValue;
-		}	
-	}
-
-	/** Find upper and lower bounds on all processors */
-	MPI_Allreduce( &min, &globalMin, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
-	return globalMin;
-}
-
-
-double _FeVariable_GetMaxGlobalFieldMagnitude( void* feVariable ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-	int		node_lI=0;
-	int		nodeLocalCount = FeMesh_GetNodeLocalSize( self->feMesh );
-	double		max = 0;
-	double		globalMax = 0;
-	double		currValue;
-
-	max = FeVariable_GetScalarAtNode( self, 0 );
-	
-	/** Find upper and lower bounds on this processor */
-	for ( node_lI = 0 ; node_lI < nodeLocalCount ; node_lI++ ) {
-		currValue = FeVariable_GetScalarAtNode( self, node_lI );
-		if ( currValue > max ) {
-			max = currValue;
-		}	
-	}
-
-	/** Find upper and lower bounds on all processors */
-	MPI_Allreduce( &max, &globalMax, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD );
-	return globalMax;
-}
-
-void _FeVariable_GetMinAndMaxLocalCoords( void* feVariable, double* min, double* max ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-
-	assert( self && Stg_CheckType( self, FeVariable ) );
-
-	Mesh_GetLocalCoordRange( self->feMesh, min, max );
-}
-
-
-void _FeVariable_GetMinAndMaxGlobalCoords( void* feVariable, double* min, double* max ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-
-	assert( self && Stg_CheckType( self, FeVariable ) );
-
-	Mesh_GetGlobalCoordRange( self->feMesh, min, max );
-}
-
-double FeVariable_GetScalarAtNode( void* feVariable, Node_LocalIndex lNode_I ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-	Dof_Index	dofCountThisNode = 0;
-	Dof_Index	nodeLocalDof_I = 0;
-	double      value[ MAX_FIELD_COMPONENTS ];
-	
-	/**
-	if( self->type != OperatorFeVariable_Type && self->dofLayout )
-		dofCountThisNode = self->dofLayout->dofCounts[lNode_I];
-	else {
-	*/
-	dofCountThisNode = self->fieldComponentCount;
-	/**
-	}
-	*/
-
-	FeVariable_GetValueAtNode( self, lNode_I, value );
-
-	if ( dofCountThisNode > 1) {
-		double		magnitude=0;
-		for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
-			magnitude += value[ nodeLocalDof_I ] * value[ nodeLocalDof_I ];
-		}
-		return sqrt( magnitude );
-	}
-	else 
-		return value[0];
-
-}	
-
-
-void _FeVariable_GetValueAtNode( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-	Variable*	currVariable = NULL;
-	Dof_Index	dofCountThisNode = 0;
-	Dof_Index	nodeLocalDof_I = 0;
-
-	dofCountThisNode = self->dofLayout->dofCounts[dNode_I];
-	
-	for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
-		currVariable = DofLayout_GetVariable( self->dofLayout, dNode_I, nodeLocalDof_I );
-		value[ nodeLocalDof_I ] = Variable_GetValueDouble( currVariable, dNode_I );
-	}
-}
-
-/** Finds the value of the field at the node and broadcasts it to the rest of the processors */
-void FeVariable_GetValueAtNodeGlobal( void* feVariable, Node_GlobalIndex gNode_I, double* value ) {
-	FeVariable*        self         = (FeVariable*) feVariable;
-	FeMesh*            mesh         = self->feMesh;
-	Element_LocalIndex lNode_I;
-	int                rootRankL     = 0;
-	int                rootRankG     = 0;
-	MPI_Comm           comm         = self->communicator;
-	
-	/** Find Local Index */
-	if ( Mesh_GlobalToDomain( mesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
-		/** If node is on local processor, then get value of field */
-		FeVariable_GetValueAtNode( self, lNode_I, value );
-		MPI_Comm_rank( comm, (int*)&rootRankL );
-	}
-	
-	/** Send to other processors */
-	MPI_Allreduce( &rootRankL, &rootRankG, 1, MPI_INT, MPI_MAX, comm );
-	MPI_Bcast( value, self->fieldComponentCount, MPI_DOUBLE, rootRankG, comm );
-}
-
-/** Finds the coordinate of the node and broadcasts it to the rest of the processors */
-void FeVariable_GetCoordAtNodeGlobal( void* feVariable, Node_GlobalIndex gNode_I, double* coord ) {
-	FeVariable*        self         = (FeVariable*) feVariable;
-	FeMesh*            mesh         = self->feMesh;
-	Element_LocalIndex lNode_I;
-	int                rootRankL     = 0;
-	int                rootRankG     = 0;
-	MPI_Comm           comm         = self->communicator;
-
-	/** Find Local Index */
-	if ( Mesh_GlobalToDomain( mesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
-		/** If node is on local processor, then get value of field */
-		memcpy( coord, Mesh_GetVertex( mesh, lNode_I ), self->dim * sizeof(double) );
-		MPI_Comm_rank( comm, (int*)&rootRankL );
-	}
-	
-	/** Send to other processors */
-	MPI_Allreduce( &rootRankL, &rootRankG, 1, MPI_INT, MPI_MAX, comm );
-	MPI_Bcast( coord, self->dim, MPI_DOUBLE, rootRankG, comm );
-}
-
-
-void FeVariable_ZeroField( void* feVariable ) {
-	FeVariable* self = (FeVariable*) feVariable;
-	double*     values =  Memory_Alloc_Array( double, self->fieldComponentCount, "tempValues" );
-	Index       lNode_I, lNodeCount;
-
-	lNodeCount = FeMesh_GetNodeLocalSize( self->feMesh );
-
-	memset( values, 0, self->fieldComponentCount * sizeof(double) );
-
-	for( lNode_I = 0 ; lNode_I < lNodeCount; lNode_I++ ) {
-		FeVariable_SetValueAtNode( self, lNode_I, values );
-	}
-
-	Memory_Free( values );
-}
-	
-/** --- Public Functions --- */
-
-InterpolationResult FeVariable_GetElementLocalCoordAtGlobalCoord( void* feVariable, double* globalCoord, double* elLocalCoord,
-		Element_DomainIndex* elementCoordInPtr )
-{
-	FeVariable*		self = (FeVariable*)feVariable;
-	InterpolationResult	retValue;
-	unsigned		elInd;
-
-	/** locate which mesh element given coord is in : use inclusive upper boundaries to save
-	   the need to use shadow space if possible */
-	if( !Mesh_SearchElements( self->feMesh, globalCoord, &elInd ) ) {
-		Bool			outsideGlobal = False;
-		double			min[3], max[3];
-		Dimension_Index		dim_I=0;
-
-		FieldVariable_GetMinAndMaxGlobalCoords( self, min, max );
-		for ( dim_I = 0; dim_I < self->dim; dim_I++ ) {
-			if ( ( globalCoord[dim_I] < min[dim_I] ) || (globalCoord[dim_I] > max[dim_I] ) ) {
-				outsideGlobal = True;
-			}
-		}
-
-		if ( outsideGlobal == True ) {
-			return OUTSIDE_GLOBAL;
-		}
-		else {
-			return OTHER_PROC;
-		}
-	}
-	else /** We found the coord is within a local or shadow element */ {
-		ElementType*		elementType = NULL;
-
-		*elementCoordInPtr = elInd;
-		if ( elInd < FeMesh_GetElementLocalSize( self->feMesh ) ) {
-			retValue = LOCAL;
-		}
-		else {
-			retValue = SHADOW;
-		}
-
-		/** convert global coordinate to local co-ordinates of element the coord is in */
-		elementType = FeMesh_GetElementType( self->feMesh, (*elementCoordInPtr) );
-		ElementType_ConvertGlobalCoordToElLocal( elementType, self->feMesh, *elementCoordInPtr, 
-							 globalCoord, elLocalCoord );
-	}
-
-	return retValue;
-}
-
-
-void FeVariable_SetValueAtNode( void* feVariable, Node_DomainIndex dNode_I, double* componentValues ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-	Dof_Index	dofCountThisNode = 0;
-	Dof_Index	nodeLocalDof_I = 0;
-
-	dofCountThisNode = self->dofLayout->dofCounts[dNode_I];
-	
-	for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
-		DofLayout_SetValueDouble( (self)->dofLayout, dNode_I, nodeLocalDof_I, componentValues[nodeLocalDof_I] );
-	}
-}
-
-
-void FeVariable_PrintLocalDiscreteValues_2dBox( void* variable, Stream* stream ) {
-	FeVariable*		self = (FeVariable*)variable;
-	Node_LocalIndex		node_lI=0;
-	Index			x_I, y_I;
-	Index			ii;
-	Dof_Index		dof_I=0;
-	Dof_Index		currNodeNumDofs=0;
-	Index			nx = 0;
-	Index			ny = 0;
-	double			dx = 0;
-	double			dy = 0;
-	DofLayout*		dofLayout = self->dofLayout;
-	Stream*			eStream = Journal_Register( Error_Type, (Name)self->type  );
-	Index			minLocalNodeX;
-	Index			minLocalNodeY;
-	Index			maxLocalNodeX;
-	Index			maxLocalNodeY;
-	Grid*			vertGrid;
-	unsigned		inds[2];
-	unsigned		vertInd;
-	double*			verts[2];
-	unsigned		*localOrigin, *localRange;
-	double			min[2], max[2];
-
-	if( ExtensionManager_GetHandle( self->feMesh->info, (Name)"vertexGrid" ) == (unsigned)-1 || 
-	    Mesh_GetDimSize( self->feMesh ) != 2  )
-	  {
-		Journal_Printf( eStream, "Warning: %s called on variable \"%s\", but this isn't stored on a "
-			"regular 2D mesh - so just returning.\n", __func__, self->name );
-		return;
-	}
-
-	vertGrid = *(Grid**)ExtensionManager_Get( self->feMesh->info, self->feMesh, 
-					      ExtensionManager_GetHandle( self->feMesh->info, (Name)"vertexGrid" ) );
-	localOrigin = (unsigned* )ExtensionManager_Get( self->feMesh->info, self->feMesh, 
-						       ExtensionManager_GetHandle( self->feMesh->info, (Name)"localOrigin" ) );
-	localRange = (unsigned* )ExtensionManager_Get( self->feMesh->info, self->feMesh, 
-						      ExtensionManager_GetHandle( self->feMesh->info, (Name)"localRange" )  );
-
-	memcpy( inds, localOrigin, Mesh_GetDimSize( self->feMesh ) * sizeof(unsigned) );
-	insist( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, Grid_Project( vertGrid, inds ), &vertInd ), == True );
-	verts[0] = Mesh_GetVertex( self->feMesh, vertInd );
-	inds[0]++;
-	inds[1]++;
-	insist( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, Grid_Project( vertGrid, inds ), &vertInd ), == True );
-	verts[1] = Mesh_GetVertex( self->feMesh, vertInd );
-	
-	nx = vertGrid->sizes[0];
-	ny = vertGrid->sizes[1];
-	dx = verts[1][0] - verts[0][0];
-	dy = verts[1][1] - verts[0][1];
-
-
-
-	minLocalNodeX = localOrigin[0];
-	minLocalNodeY = localOrigin[1];
-	maxLocalNodeX = minLocalNodeX + localRange[0] + 1;
-	maxLocalNodeY = minLocalNodeY + localRange[1] + 1;
-
-	Mesh_GetGlobalCoordRange( self->feMesh, min, max );
-
-	Journal_Printf( stream, "display of Values in 2D box X:{%5.2f-%5.2f}, Y:{%5.2f-%5.2f}\n",
-		min[I_AXIS], max[I_AXIS],
-		min[J_AXIS], max[J_AXIS] );
-	Journal_Printf( stream, "\twith %d elements in X (dx=%5.2f) and %d elements in Y (dy=%5.2f)\n\n",
-		nx-1, dx, ny-1, dy );
-
-	/**Header*/
-	for (ii=0;ii<10;ii++) Journal_Printf( stream, " " );
-	for ( x_I=0; x_I < nx; x_I++ ) {
-		Journal_Printf( stream, "|  xNode=%3d   ", x_I );
-	}
-	Journal_Printf( stream, "|\n", x_I );
-
-	for ( y_I= ny-1; y_I != (unsigned)-1; y_I-- ) {
-		/**Blocks */
-		for (ii=0;ii<10;ii++) Journal_Printf( stream, " " );
-		for ( x_I=0; x_I < nx; x_I++ ) {
-			if (y_I == ny-1) {
-				Journal_Printf( stream, "-" );
-			}
-			else if (x_I==0) {
-				Journal_Printf( stream, "|" );
-			}	
-			else {
-				Journal_Printf( stream, "*" );
-			}	
-			for (ii=0;ii<14;ii++) Journal_Printf( stream, "-" );
-		}
-		if (y_I == ny-1) {
-			Journal_Printf( stream, "-\n" );
-		}	
-		else {
-			Journal_Printf( stream, "|\n" );
-		}	
-
-
-		/** Now a row of y values */
-		Journal_Printf( stream, "yNode=%3d |", y_I );
-		for ( x_I=0; x_I < nx; x_I++ ) {
-		
-			if ( ( y_I >= minLocalNodeY ) && ( y_I < maxLocalNodeY )
-				&& ( x_I >= minLocalNodeX ) && ( x_I < maxLocalNodeX ) ) {
-
-				inds[0] = x_I;
-				inds[1] = y_I;
-				node_lI = RegularMeshUtils_Node_3DTo1D( self->feMesh, inds );
-				insist( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, node_lI, &node_lI ), == True );
-				currNodeNumDofs = dofLayout->dofCounts[node_lI];
-
-				if ( currNodeNumDofs == 1 ) {
-					Journal_Printf( stream, "   " );
-				}
-				Journal_Printf( stream, "(" );
-				for ( dof_I=0; dof_I < currNodeNumDofs - 1 ; dof_I++ ) {
-					Journal_Printf( stream, "%5.2f,", DofLayout_GetValueDouble( dofLayout, node_lI, dof_I ) );
-				}
-				Journal_Printf( stream, "%5.2f )", DofLayout_GetValueDouble( dofLayout, node_lI, dof_I ) );
-				
-				if ( currNodeNumDofs == 1 ) {
-					Journal_Printf( stream, "   " );
-				}
-				Journal_Printf( stream, "|" );
-			}
-			else {
-				for (ii=0;ii<14;ii++) Journal_Printf( stream, "X" );
-				Journal_Printf( stream, "|" );
-			}
-		}
-		Journal_Printf( stream, "\n" );
-	}
-	
-	/**Blocks */
-	for (ii=0;ii<10;ii++) Journal_Printf( stream, " " );
-	for ( x_I=0; x_I < nx; x_I++ ) {
-		Journal_Printf( stream, "-" );
-		for (ii=0;ii<14;ii++) Journal_Printf( stream, "-" );
-	}
-	Journal_Printf( stream, "-\n", x_I );
-}
-
-
-Bool FeVariable_InterpolateDerivativesAt( void* variable, double* globalCoord, double* value ) {
-	FeVariable*	        self                 = (FeVariable*)variable;
-	Element_DomainIndex	elementCoordIn       = (unsigned)-1;
-	Coord               elLocalCoord         = {0,0,0};
-
-	/** Need a special rule for points on this processor's boundary: instead of the normal
-	   rule, "round" the point to lie inside the local space, rather than shadow */
-	
-	/** locate which mesh element given coord is in : use inclusive upper boundaries to save
-		the need to use shadow space if possible */
-	if ( !Mesh_Algorithms_SearchElements( self->feMesh->algorithms, globalCoord, 
-					     &elementCoordIn ) )
-	{
-		/** If coord isn't inside domain elements list, bail out */
-		return False;
-	}	
-	else /** We found the coord is within a local or shadow element */ {
-		if ( elementCoordIn >= FeMesh_GetElementLocalSize( self->feMesh ) ) {
-			if ( False == self->shadowValuesSynchronised ) {
-				Stream* warningStr = Journal_Register( Error_Type, (Name)self->type  );
-				Journal_Printf( warningStr, "Warning - in %s: user asking to interpolate derivatives "
-					"to coord (%g,%g,%g), which is in shadow space, but "
-					"FeVariable_SyncShadowValues() hasn't been called yet.\n", 
-					__func__, globalCoord[0], globalCoord[1], globalCoord[2] );
-				return False;	
-			}
-		}
-
-		/** convert global coordinate to local co-ordinates of element the coord is in */
-		FeMesh_CoordGlobalToLocal( self->feMesh, elementCoordIn, globalCoord, elLocalCoord );
-
-		/** Now interpolate the value at that coordinate, using shape functions */
-		FeVariable_InterpolateDerivativesToElLocalCoord( self, elementCoordIn, elLocalCoord, value );
-	}	
-	
-	return True;
-}
-
-void FeVariable_InterpolateDerivativesToElLocalCoord( void* _feVariable, Element_DomainIndex lElement_I, Coord elLocalCoord, double* value ) {
-	FeVariable*			self = (FeVariable*) _feVariable;
-	ElementType*		elementType = FeMesh_GetElementType( self->feMesh, lElement_I );
-	double**				GNx; 
-	double				detJac;
-	Dimension_Index	dim = self->dim;
-
-	GNx = self->GNx;
-
-	/** Evaluate Global Shape Functions */
-	ElementType_ShapeFunctionsGlobalDerivs( 
-			elementType,
-			self->feMesh, lElement_I,
-			elLocalCoord, dim, &detJac, GNx );
-
-	/** Do Interpolation */
-	FeVariable_InterpolateDerivatives_WithGNx( self, lElement_I, GNx, value );
-}
-
-void FeVariable_InterpolateDerivatives_WithGNx( void* _feVariable, Element_LocalIndex lElement_I, double** GNx, double* value ) {
-	FeVariable*             self = (FeVariable*) _feVariable;
-	Node_ElementLocalIndex  elLocalNode_I;
-	Node_LocalIndex         lNode_I;
-	Dof_Index               dof_I;
-	Dof_Index               dofCount;
-	/* Variable*               dofVariable; */
-	double                  nodeValue;
-	unsigned						nInc, *inc;
-	Dimension_Index         dim = self->dim;
-	double*						tmpVal;
-
-	/** Gets number of degrees of freedom - assuming it is the same throughout the mesh */
-	dofCount = self->dofLayout->dofCounts[0];
-
-	/** Initialise */
-	memset( value, 0, sizeof( double ) * dofCount * dim );
-	tmpVal = (double*)malloc( dim*dofCount*sizeof(double) );
-
-	FeMesh_GetElementNodes( self->feMesh, lElement_I, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = (unsigned*)IArray_GetPtr( self->inc );
-
-		/** Interpolate derivative from nodes */
-        for ( elLocalNode_I = 0 ; elLocalNode_I < nInc ; elLocalNode_I++) {
-
-                lNode_I      = inc[ elLocalNode_I ];
-                FeVariable_GetValueAtNode( self, lNode_I, tmpVal );
-                /*dofVariable  = DofLayout_GetVariable( self->dofLayout, lNode_I, dof_I );*/
-                /*nodeValue    = Variable_GetValueDouble( dofVariable, lNode_I );*/
-
-                for ( dof_I = 0 ; dof_I < dofCount ; dof_I++ ) {
-                        nodeValue = tmpVal[dof_I];
-			
-			value[dof_I*dim + 0] += GNx[0][elLocalNode_I] * nodeValue;
-			value[dof_I*dim + 1] += GNx[1][elLocalNode_I] * nodeValue;
-			if( dim == 3 ) 
-				value[dof_I*dim + 2] += GNx[2][elLocalNode_I] * nodeValue;	
-		}
-	}
-
-        free( tmpVal );
-}
-
-void FeVariable_InterpolateValue_WithNi( void* _feVariable, Element_LocalIndex lElement_I, double* Ni, double* value ) {
-	FeVariable*             self        = (FeVariable*) _feVariable;
-	Node_ElementLocalIndex  elLocalNode_I;
-	Node_LocalIndex         lNode_I;
-	Dof_Index               dof_I;
-	Dof_Index               dofCount;
-	Variable*               dofVariable;
-	double                  nodeValue;
-	unsigned		nInc, *inc;
-
-	/** Gets number of degrees of freedom - assuming it is the same throughout the mesh */
-	dofCount = self->dofLayout->dofCounts[0];
-
-	/** Initialise */
-	memset( value, 0, sizeof( double ) * dofCount );
-
-	FeMesh_GetElementNodes( self->feMesh, lElement_I, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = (unsigned*)IArray_GetPtr( self->inc );
-
-	for ( dof_I = 0 ; dof_I < dofCount ; dof_I++ ) {
-		/** Interpolate derivative from nodes */
-		for ( elLocalNode_I = 0 ; elLocalNode_I < nInc ; elLocalNode_I++) {
-			lNode_I      = inc[ elLocalNode_I ];
-			dofVariable  = DofLayout_GetVariable( self->dofLayout, lNode_I, dof_I );
-			nodeValue    = Variable_GetValueDouble( dofVariable, lNode_I );
-
-			value[dof_I] += Ni[elLocalNode_I] * nodeValue;
-		}
-	}
-}
-
-void FeVariable_GetMinimumSeparation( void* feVariable, double* minSeparationPtr, double minSeparationEachDim[3] ) {
-	FeVariable*	self = (FeVariable*)feVariable;
-
-	assert( self && Stg_CheckType( self, FeVariable ) );
-
-	Mesh_GetMinimumSeparation( self->feMesh, minSeparationPtr, minSeparationEachDim );
-}	
-
-
-void _FeVariable_SyncShadowValues( void* feVariable ) {
-	FeVariable*		self = (FeVariable*)feVariable;
-	DofLayout*		dofLayout;
-	Sync*			vertSync;
-	unsigned		var_i;
-
-	assert( self );
-
-	/** Shortcuts. */
-	dofLayout = self->dofLayout;
-	if( !dofLayout ) {
-		self->shadowValuesSynchronised = True;
-		return;
-	}
-
-	/** Create a distributed array based on the mesh's vertices. */
-	vertSync = Mesh_GetSync( self->feMesh, MT_VERTEX );
-
-	/**
-	** For each variable in the dof layout, we need to create a distributed array and update
-	** shadow values.
-	*/
-
-	for( var_i = 0; var_i < dofLayout->_totalVarCount; var_i++ ) {
-		unsigned	varInd;
-		Variable*	var;
-		unsigned	field_i;
-
-		/** Get the variable. */
-		varInd = dofLayout->_varIndicesMapping[var_i];
-		var = Variable_Register_GetByIndex( dofLayout->_variableRegister, varInd );
-
-		/** Each field of the variable will need to be handled individually. */
-		for( field_i = 0; field_i < var->offsetCount; field_i++ ) {
-			unsigned	offs, size;
-			Stg_Byte	*arrayStart, *arrayEnd;
-
-			offs = var->offsets[field_i];
-			size = var->dataSizes[field_i];
-
-			arrayStart = (Stg_Byte*)var->arrayPtr + offs;
-			arrayEnd = arrayStart + var->structSize * FeMesh_GetNodeLocalSize( self->feMesh );
-			Sync_SyncArray( vertSync, arrayStart, var->structSize, 
-					arrayEnd, var->structSize, 
-					size );
-		}
-	}
-
-	self->shadowValuesSynchronised = True;
-
-#if 0
-	Neighbour_Index			nbr_I = 0;
-	Node_Index			node_stI = 0;
-	Node_DomainIndex		node_dI = 0;
-	Node_LocalIndex			node_lI = 0;
-	Dof_Index			nodalDof_I = 0;
-	Processor_Index			nbrRank = 0;
-	Index*				incomingDofTotals = NULL;			
-	double**			incomingDofValues = NULL;
-	MPI_Request**			incomingDofValRequests = NULL;
-	Node_Index			myShadowNodesOnThisNbrCount = 0;
-	Dof_Index		incomingDof_I;
-	Index*			outgoingDofTotals = NULL;
-	double**		outgoingDofValues = NULL;
-	MPI_Request**		outgoingDofValRequests = NULL;
-	Node_Index		nbrShadowNodesOnMeCount = 0;
-	Dof_Index		outgoingDof_I;
-	MPI_Status			status;
-	int				incomingDofValueSetsYetToReceive;
-	Bool*				incomingDofValueSetsReceived;
-
-	Journal_DPrintf( self->debug, "In %s- for feVariable \"%s\":\n", __func__, self->name );
-	Stream_Indent( self->debug );
-
-	if ( ( 1 == mesh->layout->decomp->procsInUse ) || ( 0 == mesh->layout->decomp->shadowDepth ) ) {
-		Journal_DPrintf( self->debug, "No shadow nodes: nothing to do - returning.\n" );
-		Stream_UnIndent( self->debug );
-		return;
-	}
-
-	self->shadowValuesSynchronised = True;
-
-	/** allocate memory for incoming info */
-	incomingDofTotals = Memory_Alloc_Array( Index, mesh->procNbrInfo->procNbrCnt, "incomingDofTotals" );
-	incomingDofValues = Memory_Alloc_Array( double*, mesh->procNbrInfo->procNbrCnt, "incomingDofValues" );
-	incomingDofValRequests = Memory_Alloc_Array( MPI_Request*, mesh->procNbrInfo->procNbrCnt, "incomingDofValRequests" );
-	incomingDofValueSetsReceived = Memory_Alloc_Array( Bool, mesh->procNbrInfo->procNbrCnt, "incomingDofValueSets" );
-	incomingDofValueSetsYetToReceive = 0;
-	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
-		myShadowNodesOnThisNbrCount = mesh->nodeShadowInfo->procShadowCnt[nbr_I];
-		incomingDofTotals[nbr_I] = 0;
-		incomingDofValues[nbr_I] = NULL;
-		incomingDofValRequests[nbr_I] = NULL;
-		incomingDofValueSetsReceived[nbr_I] = False;
-
-		if ( myShadowNodesOnThisNbrCount > 0 ) {
-			for( node_stI = 0; node_stI < myShadowNodesOnThisNbrCount; node_stI++ ) {
-				node_dI = mesh->nodeShadowInfo->procShadowTbl[nbr_I][node_stI];
-				incomingDofTotals[nbr_I] += self->dofLayout->dofCounts[node_dI];
-			}	
-			incomingDofValues[nbr_I] = Memory_Alloc_Array( double, incomingDofTotals[nbr_I],
-				"incomingDofValues[]" );
-			incomingDofValRequests[nbr_I] = Memory_Alloc( MPI_Request, "incomingDofValRequest" );	
-			incomingDofValueSetsYetToReceive++;
-		}
-	}
-	/** allocate memory for outgoing info */
-	outgoingDofTotals = Memory_Alloc_Array( Index, mesh->procNbrInfo->procNbrCnt, "outgoingDofTotals" );
-	outgoingDofValues = Memory_Alloc_Array( double*, mesh->procNbrInfo->procNbrCnt, "outgoingDofValues" );
-	outgoingDofValRequests = Memory_Alloc_Array( MPI_Request*, mesh->procNbrInfo->procNbrCnt, "outgoingDofValRequests" );
-	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
-		nbrShadowNodesOnMeCount = mesh->nodeShadowInfo->procShadowedCnt[nbr_I];
-		outgoingDofTotals[nbr_I] = 0;
-		outgoingDofValues[nbr_I] = NULL;
-		outgoingDofValRequests[nbr_I] = NULL;
-
-		if ( nbrShadowNodesOnMeCount > 0 ) {
-			for( node_stI = 0; node_stI < nbrShadowNodesOnMeCount; node_stI++ ) {
-				node_lI = mesh->nodeShadowInfo->procShadowedTbl[nbr_I][node_stI];
-				outgoingDofTotals[nbr_I] += self->dofLayout->dofCounts[node_lI];
-			}	
-			outgoingDofValues[nbr_I] = Memory_Alloc_Array( double, outgoingDofTotals[nbr_I],
-				"outgoingDofValues[]" );
-			outgoingDofValRequests[nbr_I] = Memory_Alloc( MPI_Request, "outgoingDofValRequest" );	
-		}
-	}	
-
-	Journal_DPrintfL( self->debug, 2, "Starting non-blocking recv's of incoming values\n" );
-	Stream_Indent( self->debug );
-	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
-		myShadowNodesOnThisNbrCount = mesh->nodeShadowInfo->procShadowCnt[nbr_I];
-		if ( myShadowNodesOnThisNbrCount > 0 ) {
-			nbrRank = mesh->procNbrInfo->procNbrTbl[nbr_I];
-			Journal_DPrintfL( self->debug, 2, "Start recv from proc %u - %u values\n", nbrRank, incomingDofTotals[nbr_I] );
-			MPI_Irecv( incomingDofValues[nbr_I], incomingDofTotals[nbr_I], MPI_DOUBLE, nbrRank,
-				DOF_VALUES_TAG, self->communicator, incomingDofValRequests[nbr_I] );
-		}
-	}
-	Stream_UnIndent( self->debug );
-
-	Journal_DPrintfL( self->debug, 2, "Non-blocking send out required shadow values to neighbours\n" );
-	Stream_Indent( self->debug );
-	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
-		if ( mesh->nodeShadowInfo->procShadowedCnt[nbr_I] > 0 ) {
-			nbrRank = mesh->procNbrInfo->procNbrTbl[nbr_I];
-
-			outgoingDof_I = 0;
-			for( node_stI = 0; node_stI < mesh->nodeShadowInfo->procShadowedCnt[nbr_I]; node_stI++ ) {
-				node_lI = mesh->nodeShadowInfo->procShadowedTbl[nbr_I][node_stI];
-				for ( nodalDof_I=0; nodalDof_I < self->dofLayout->dofCounts[node_lI]; nodalDof_I++ ) {
-					outgoingDofValues[nbr_I][outgoingDof_I] =
-						DofLayout_GetValueDouble( self->dofLayout, node_lI, nodalDof_I );
-					outgoingDof_I++;
-				}
-			}
-			Journal_DPrintfL( self->debug, 2, "Start send to proc %u - %u values\n", nbrRank, outgoingDofTotals[nbr_I] );
-			MPI_Isend( outgoingDofValues[nbr_I], outgoingDofTotals[nbr_I], MPI_DOUBLE, nbrRank,
-				DOF_VALUES_TAG, self->communicator, outgoingDofValRequests[nbr_I] );
-		}
-	}
-	Stream_UnIndent( self->debug );
-
-	Journal_DPrintfL( self->debug, 2, "Receiving and updating shadow values I need from neighbours:\n" );
-	Stream_Indent( self->debug );
-	while ( incomingDofValueSetsYetToReceive > 0 ) {
-		int	testFlag = 0;
-
-		for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
-
-			if ( ( mesh->nodeShadowInfo->procShadowCnt[nbr_I] > 0 )
-				&& ( False == incomingDofValueSetsReceived[nbr_I] ) )
-			{
-				MPI_Test( incomingDofValRequests[nbr_I], &testFlag, &status );
-				if ( False == testFlag ) {
-					continue;
-				}
-				else {
-					Journal_DPrintfL( self->debug, 2, "Recv'd a batch of values from proc %u: updating...\n",
-						nbrRank );
-					/** update the appropriate values from recv'd set */
-					incomingDof_I = 0;
-					for( node_stI = 0; node_stI < mesh->nodeShadowInfo->procShadowCnt[nbr_I]; node_stI++ ) {
-						node_dI = mesh->nodeShadowInfo->procShadowTbl[nbr_I][node_stI];
-						for ( nodalDof_I=0; nodalDof_I < self->dofLayout->dofCounts[node_dI]; nodalDof_I++ ) {
-							DofLayout_SetValueDouble( self->dofLayout, node_dI, nodalDof_I,
-								incomingDofValues[nbr_I][incomingDof_I] );
-							incomingDof_I++;	
-						}
-					}
-					incomingDofValueSetsReceived[nbr_I] = True;
-					incomingDofValueSetsYetToReceive--;
-				}
-			}	
-		}	
-	}
-	Journal_DPrintfL( self->debug, 2, "Done.\n" );
-	Stream_UnIndent( self->debug );
-
-	Journal_DPrintfL( self->debug, 2, "Making sure outgoing sends have completed...\n" );
-	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
-		if ( mesh->nodeShadowInfo->procShadowCnt[nbr_I] > 0 ) {
-			MPI_Wait( outgoingDofValRequests[nbr_I], &status );
-		}
-	}
-	Journal_DPrintfL( self->debug, 2, "Done.\n" );
-
-	/** clean up temporary memory */
-	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
-		myShadowNodesOnThisNbrCount = mesh->nodeShadowInfo->procShadowCnt[nbr_I];
-		if ( myShadowNodesOnThisNbrCount > 0 ) {
-			Memory_Free( incomingDofValues[nbr_I] );
-			Memory_Free( incomingDofValRequests[nbr_I] );
-		}	
-	}
-	Memory_Free( incomingDofTotals );
-	Memory_Free( incomingDofValues );
-	Memory_Free( incomingDofValRequests );
-	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
-		nbrShadowNodesOnMeCount = mesh->nodeShadowInfo->procShadowedCnt[nbr_I];
-		if ( nbrShadowNodesOnMeCount > 0 ) {
-			Memory_Free( outgoingDofValues[nbr_I] );
-			Memory_Free( outgoingDofValRequests[nbr_I] );
-		}	
-	}
-	Memory_Free( outgoingDofTotals );
-	Memory_Free( outgoingDofValues );
-	Memory_Free( outgoingDofValRequests );
-	
-	Stream_UnIndent( self->debug );
-#endif
-}
-
-
-void FeVariable_PrintDomainDiscreteValues( void* variable, Stream* stream ) {
-	FeVariable* self = (FeVariable*)variable;
-
-	Journal_Printf( stream, "In %s: for FeVariable \"%s\":\n", __func__, self->name );
-
-	_FeVariable_PrintLocalOrDomainValues( variable, FeMesh_GetNodeDomainSize( self->feMesh ), stream );
-}
-
-void FeVariable_PrintCoordsAndValues( void* _feVariable, Stream* stream ) {
-	FeVariable*         self            = (FeVariable*) _feVariable;
-	Node_LocalIndex     node_I          = 0;
-	Node_LocalIndex     nodeLocalCount  = FeMesh_GetNodeLocalSize( self->feMesh );
-	Dof_Index           currNodeNumDofs;
-	Dof_Index           nodeLocalDof_I;
-	Variable*           currVariable;
-	double*             nodeCoord;
-	
-	/** Print Header of stream */
-	Journal_Printf( stream, "# FeVariable - %s\n", self->name );
-	Journal_Printf( stream, "#    x coord   |    y coord   |    z coord" );
-	currNodeNumDofs = self->dofLayout->dofCounts[ 0 ];
-	for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-		currVariable = DofLayout_GetVariable( self->dofLayout, node_I, nodeLocalDof_I );
-		Journal_Printf( stream, "  |  %s", currVariable->name );
-	}
-	Journal_Printf(stream, "\n");
-	
-	/** Loop over local nodes */
-	for( node_I=0; node_I < nodeLocalCount ; node_I++ ) {
-		currNodeNumDofs = self->dofLayout->dofCounts[ node_I ];
-
-		/** Get Coordinate of Node */
-		nodeCoord = Mesh_GetVertex( self->feMesh, node_I );
-		Journal_Printf( stream, "%12.6g   %12.6g   %12.6g   ", 
-				nodeCoord[ I_AXIS ], nodeCoord[ J_AXIS ], nodeCoord[ K_AXIS ] );
-		
-		/** Print each dof */
-		for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-			currVariable = DofLayout_GetVariable( self->dofLayout, node_I, nodeLocalDof_I );
-			Journal_Printf( stream, "%12.6g   ", Variable_GetValueDouble( currVariable, node_I ) );
-		}
-		Journal_Printf( stream, "\n" );
-	}	
-}
-
-
-/** --- Private Functions --- */
-
-void _FeVariable_InterpolateNodeValuesToElLocalCoord( void* feVariable, Element_DomainIndex element_lI, Coord elLocalCoord, double* value ) {
-	FeVariable*         self       = (FeVariable*) feVariable;
-	ElementType*		elementType=NULL;
-	Dof_Index		nodeLocalDof_I=0;
-	Dof_Index		dofCountThisNode=0;
-	Node_ElementLocalIndex	elLocalNode_I=0;
-	double*			shapeFuncsEvaluatedAtCoord=NULL;
-	Node_LocalIndex		lNode_I=0;
-	Variable*		currVariable=NULL;
-	double			dofValueAtCurrNode=0;
-	unsigned		nInc, *inc;
-
-	FeMesh_GetElementNodes( self->feMesh, element_lI, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = (unsigned*)IArray_GetPtr( self->inc );
-
-	/** Gets number of degrees of freedom - assuming it is the same throughout the mesh */
-	dofCountThisNode = self->dofLayout->dofCounts[lNode_I];
-
-	/** evaluate shape function values of current element at elLocalCoords */
-	elementType = FeMesh_GetElementType( self->feMesh, element_lI );
-	shapeFuncsEvaluatedAtCoord = AllocArray( double, nInc );
-	ElementType_EvaluateShapeFunctionsAt( elementType, elLocalCoord, shapeFuncsEvaluatedAtCoord );
-
-	for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
-		value[nodeLocalDof_I] = 0;
-	}
-
-	/** Now for each node, add that node's contribution at point */
-	for ( elLocalNode_I=0; elLocalNode_I < nInc; elLocalNode_I++ ) {
-		lNode_I = inc[elLocalNode_I];
-		
-		for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
-			currVariable = DofLayout_GetVariable( self->dofLayout, lNode_I, nodeLocalDof_I );
-			dofValueAtCurrNode = Variable_GetValueDouble( currVariable, lNode_I );
-			value[nodeLocalDof_I] += dofValueAtCurrNode * shapeFuncsEvaluatedAtCoord[elLocalNode_I];
-		}	
-	}
-	FreeArray( shapeFuncsEvaluatedAtCoord );
-}
-
-void _FeVariable_PrintLocalOrDomainValues( void* variable, Index localOrDomainCount, Stream* stream ) {
-	FeVariable* self = (FeVariable*)variable;
-	Node_Index 		node_I = 0;
-	Node_GlobalIndex 	gNode_I = 0;
-	Dof_Index		currNodeNumDofs;
-	Dof_Index		nodeLocalDof_I;
-	Dof_EquationNumber	currEqNum;
-	Variable*		currVariable;
-	
-	for( node_I=0; node_I < localOrDomainCount; node_I++ ) {
-		gNode_I = FeMesh_NodeDomainToGlobal( self->feMesh, node_I );
-		Journal_Printf( stream, "node %d (global index %d):\n", node_I, gNode_I );
-		
-		currNodeNumDofs = self->fieldComponentCount;
-		
-		
-		/** Print each dof */
-		for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-			currVariable = DofLayout_GetVariable( self->dofLayout, node_I, nodeLocalDof_I );
-			Journal_Printf( stream, "\tdof %d \"%s\": %6g - ", nodeLocalDof_I, currVariable->name,
-				Variable_GetValueDouble( currVariable, node_I ) );
-			currEqNum = self->eqNum->destinationArray[node_I][nodeLocalDof_I];
-			if ( currEqNum == -1 ) {
-				Journal_Printf( stream, "(from BC)", currEqNum );
-			}
-			else {
-				Journal_Printf( stream, "(eq num %d)", currEqNum );
-			}	
-			Journal_Printf( stream, "\n", currEqNum );
-		}
-	}
-}
-
-InterpolationResult FeVariable_InterpolateFromMeshLocalCoord( void* feVariable, FeMesh* mesh, Element_DomainIndex dElement_I, double* localCoord, double* value ) {
-	FeVariable*          self               = (FeVariable*)         feVariable;
-
-	if ( mesh == self->feMesh ) {
-		/** If the meshes are identical - then we can just interpolate within the elements because the elements are the same */
-		FeVariable_InterpolateWithinElement( self, dElement_I, localCoord, value );
-                return LOCAL;
-	}
-	else {
-		Coord               globalCoord;
-
-		/** If the meshes are different - then we must find the global coordinates and interpolate to that */
-		FeMesh_CoordLocalToGlobal( mesh, dElement_I, localCoord, globalCoord );
-		return FieldVariable_InterpolateValueAt( feVariable, globalCoord, value );
-	}
-	
-}
-
-/** TODO: can't assume all swarms have particles of type integrationPoint anymore.
-   should check that the given swarm does have I.P for the rest of these functions.*/
-double FeVariable_IntegrateElement_AxisIndependent( 
-		void* feVariable, void* _swarm, 
-		Element_DomainIndex dElement_I, Dimension_Index dim, 
-		Axis axis0, Axis axis1, Axis axis2 ) 
-{
-	FeVariable*          self               = (FeVariable*)         feVariable;
-	Swarm*               swarm              = (Swarm*)              _swarm;
-	FeMesh*			feMesh             = self->feMesh;
-	FeMesh*			mesh;
-	ElementType*         elementType;
-	Cell_LocalIndex      cell_I;
-	Particle_InCellIndex cParticle_I;
-	Particle_InCellIndex cellParticleCount;
-	IntegrationPoint*    particle;
-	double               detJac;
-	double               integral;
-	double               value;
-	
-	/** Initialise Summation of Integral */
-	integral = 0.0;
-
-	/** Use feVariable's mesh as geometry mesh if one isn't passed in */
-	if( Stg_Class_IsInstance( feMesh->algorithms, Mesh_CentroidAlgorithms_Type ) )
-		mesh = (FeMesh*)((Mesh_CentroidAlgorithms*)feMesh->algorithms)->elMesh;
-	else
-		mesh = feMesh;
-	elementType = FeMesh_GetElementType( mesh, dElement_I );
-
-	/** Determine number of particles in element */
-	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, dElement_I );
-	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-
-	/** Loop over all particles in element */
-	for( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
-		/** Get Pointer to particle */
-		particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
-
-		/** Interpolate Value of Field at Particle */
-		FeVariable_InterpolateWithinElement( feVariable, dElement_I, particle->xi, &value );
-
-		Journal_DPrintfL( self->debug, 3, "%s: Integrating element %d - particle %d - Value = %g\n", self->name, dElement_I, cParticle_I, value );
-
-		/** Calculate Determinant of Jacobian */
-		detJac = ElementType_JacobianDeterminant_AxisIndependent( 
-				elementType, mesh, dElement_I, particle->xi, dim, axis0, axis1, axis2 );
-
-		/** Sum Integral */
-		integral += detJac * particle->weight * value;
-	}
-	
-	return integral;
-}
-
-double FeVariable_Integrate( void* feVariable, void* _swarm ) {
-	FeVariable*          self               = (FeVariable*)         feVariable;
-	Swarm*               swarm              = (Swarm*)              _swarm;
-	FeMesh*			feMesh             = self->feMesh;
-	Element_LocalIndex   lElement_I;
-	Element_LocalIndex   elementLocalCount  = FeMesh_GetElementLocalSize( feMesh );
-	double               integral, integralGlobal;
-	
-	/** Initialise Summation of Integral */
-	integral = 0.0;
-
-	/** Loop over all local elements */
-	for ( lElement_I = 0 ; lElement_I < elementLocalCount ; lElement_I++ ) {
-		integral += FeVariable_IntegrateElement( self, swarm, lElement_I );
-		Journal_DPrintfL( self->debug, 3, "%s: Integrating element %d - Accumulated Integral = %g\n", self->name, lElement_I, integral );
-	}
-		
-	/** Gather and sum integrals from other processors */
-	MPI_Allreduce( &integral, &integralGlobal, 1, MPI_DOUBLE, MPI_SUM, self->communicator );
-
-	return integralGlobal;
-}
-
-double FeVariable_AverageTopLayer( void* feVariable, void* swarm, Axis layerAxis ) {
-	FeVariable*                self               = (FeVariable*)         feVariable;
-	Grid*			elGrid;
-
-	elGrid = *(Grid**)ExtensionManager_Get( self->feMesh->info, self->feMesh, 
-						ExtensionManager_GetHandle( self->feMesh->info, (Name)"elementGrid" )  );
-
-	return FeVariable_AverageLayer( self, swarm, layerAxis, elGrid->sizes[1] - 1 );
-}
-
-double FeVariable_AverageBottomLayer( void* feVariable, void* swarm, Axis layerAxis ) {
-	FeVariable*                self               = (FeVariable*)         feVariable;
-
-	return FeVariable_AverageLayer( self, swarm, layerAxis, 0 );
-}
-
-double FeVariable_AverageLayer( void* feVariable, void* swarm, Axis layerAxis, Index layerIndex ) {
-	FeVariable*                self               = (FeVariable*)         feVariable;
-	Axis                       aAxis              = ( layerAxis == I_AXIS ? J_AXIS : I_AXIS );
-	Axis                       bAxis              = ( layerAxis == K_AXIS ? J_AXIS : K_AXIS );
-	Dimension_Index            dim                = self->dim;
-	double                     integral;
-	double                     layerThickness     = 0.0;
-	double			sendThickness;
-	Grid*			vertGrid;
-	unsigned*		inds;
-	double			heights[2];
-	unsigned		localInd[2], globalInd[2];
-	double			*min, *max;
-	int		d_i;
-	
-	integral = FeVariable_IntegrateLayer( self, swarm, layerAxis, layerIndex );
-
-	/** Calculate layer thickness.  This assumes the mesh is regular. */
-	vertGrid = *(Grid**)ExtensionManager_Get( self->feMesh->info, self->feMesh, 
-						  ExtensionManager_GetHandle( self->feMesh->info, (Name)"vertexGrid" )  );
-	inds = Memory_Alloc_Array_Unnamed( unsigned, Mesh_GetDimSize( self->feMesh ) );
-	for( d_i = 0; d_i < Mesh_GetDimSize( self->feMesh ); d_i++ ) {
-		if( d_i != layerAxis )
-			inds[d_i] = 0;
-		else
-			inds[d_i] = layerIndex;
-	}
-	globalInd[0] = Grid_Project( vertGrid, inds );
-	inds[layerAxis]++;
-	globalInd[1] = Grid_Project( vertGrid, inds );
-	if( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, globalInd[0], &localInd[0] ) && 
-	    Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, globalInd[1], &localInd[1] ) )
-	{
-		heights[0] = Mesh_GetVertex( self->feMesh, localInd[0] )[layerAxis];
-		heights[1] = Mesh_GetVertex( self->feMesh, localInd[1] )[layerAxis];
-		sendThickness = heights[1] - heights[0];
-	}
-	else {
-		sendThickness = 0.0;
-	}
-	MPI_Allreduce( &sendThickness, &layerThickness, 1, MPI_DOUBLE, MPI_MAX, self->communicator );
-	FreeArray( inds );
-
-	min = Memory_Alloc_Array_Unnamed( double, Mesh_GetDimSize( self->feMesh ) );
-	max = Memory_Alloc_Array_Unnamed( double, Mesh_GetDimSize( self->feMesh ) );
-	Mesh_GetGlobalCoordRange( self->feMesh, min, max );
-	integral /= layerThickness * (max[aAxis] - min[aAxis]);
-	if ( dim == 3 )
-		integral /= max[ bAxis ] - min[ bAxis ];
-	FreeArray( min );
-	FreeArray( max );
-
-	return integral;
-}
-
-
-double FeVariable_IntegrateLayer_AxisIndependent( 
-		void* feVariable, void* _swarm,
-		Axis layerAxis, Index layerIndex, Dimension_Index dim, 
-		Axis axis0, Axis axis1, Axis axis2 ) 
-{ 
-	FeVariable*                self               = (FeVariable*)         feVariable;
-	Swarm*                     swarm              = (Swarm*)              _swarm;
-	Element_LocalIndex         lElement_I;
-	Element_GlobalIndex        gElement_I;
-	IJK                        elementIJK;
-	double                     elementIntegral;
-	double                     integral;
-	double                     integralGlobal;
-
-	Journal_DPrintf( self->debug, "In %s() for FeVariable \"%s\":\n", __func__, self->name );
-
-	/** Initialise Sumation of Integral */
-	integral = 0.0;
-
-	Stream_Indent( self->debug );
-	for ( gElement_I = 0 ; gElement_I < FeMesh_GetElementGlobalSize( self->feMesh ); gElement_I++ ) {
-		RegularMeshUtils_Element_1DTo3D( self->feMesh, gElement_I, elementIJK );
-
-		/** Check if element is in layer plane */
-		if ( elementIJK[ layerAxis ] != layerIndex )
-			continue;
-
-		/** Check if element is local */
-		if( !FeMesh_ElementGlobalToDomain( self->feMesh, gElement_I, &lElement_I ) || 
-		    lElement_I >= FeMesh_GetElementLocalSize( self->feMesh ) )
-		{
-			continue;
-		}
-
-		elementIntegral = FeVariable_IntegrateElement_AxisIndependent( self, swarm, lElement_I, dim, axis0, axis1, axis2 );
-		Journal_DPrintfL( self->debug, 2, "Integral of element %d was %f\n", lElement_I, elementIntegral );
-		integral += elementIntegral;
-	}
-	Stream_UnIndent( self->debug );
-
-
-	/** Gather and sum integrals from other processors */
-	MPI_Allreduce( &integral, &integralGlobal, 1, MPI_DOUBLE, MPI_SUM, self->communicator );
-
-	Journal_DPrintf( self->debug, "Calculated global integral of layer %d in Axis %d was %f\n", layerIndex, layerAxis, integralGlobal );
-	return integralGlobal;
-}
-
-
-double FeVariable_AveragePlane( void* feVariable, Axis planeAxis, double planeHeight ) {
-	FeVariable*                self               = (FeVariable*)         feVariable;
-	double                     integral;
-	Axis                       aAxis              = ( planeAxis == I_AXIS ? J_AXIS : I_AXIS );
-	Axis                       bAxis              = ( planeAxis == K_AXIS ? J_AXIS : K_AXIS );
-	Dimension_Index            dim                = self->dim;
-	double				min[3], max[3];
-	
-	integral = FeVariable_IntegratePlane( self, planeAxis, planeHeight );
-
-	Mesh_GetGlobalCoordRange( self->feMesh, min, max );
-
-	integral /= max[ aAxis ] - min[ aAxis ];
-	if ( dim == 3 )
-		integral /= max[ bAxis ] - min[ bAxis ];
-
-	return integral;
-}
-
-double FeVariable_IntegratePlane( void* feVariable, Axis planeAxis, double planeHeight ) {
-	FeVariable*                self               = (FeVariable*)         feVariable;
-	IJK                        planeIJK;
-	Element_LocalIndex         lElement_I;
-	Element_GlobalIndex        gElement_I;
-	Element_LocalIndex         elementLocalCount  = FeMesh_GetElementLocalSize( self->feMesh );
-	Axis                       aAxis              = ( planeAxis == I_AXIS ? J_AXIS : I_AXIS );
-	Axis                       bAxis              = ( planeAxis == K_AXIS ? J_AXIS : K_AXIS );
-	double                     integral;
-	/** Swarm Stuff */
-	Swarm*                     tmpSwarm;
-	Bool                       dimExists[]        = { False, False, False };
-	ExtensionManager_Register* extensionMgr_Register;
-	SingleCellLayout*          singleCellLayout;
-	GaussParticleLayout*       gaussParticleLayout;
-	Particle_Index             lParticle_I;
-	IntegrationPoint*          particle;
-	/** Plane location stuff */
-	double                     storedXi_J_AXIS;
-	Coord                      planeCoord;
-	double                     planeXi           = -1;
-	double                     planeXiGlobal;
-	Index                      planeLayer        = 0;
-	Index                      planeLayerGlobal;
-	Particle_InCellIndex       particlesPerDim[] = {2,2,2};
-
-	/** Find Elements which plane cuts through */
-	memcpy( planeCoord, Mesh_GetVertex( self->feMesh, 0 ), sizeof( Coord ) );
-	planeCoord[ planeAxis ] = planeHeight;
-
-	if( Mesh_Algorithms_SearchElements( self->feMesh->algorithms, planeCoord, &lElement_I ) && 
-	    lElement_I < elementLocalCount )
-	{
-		Coord		planeXiCoord;
-
-		gElement_I = FeMesh_ElementDomainToGlobal( self->feMesh, lElement_I );
-		RegularMeshUtils_Element_1DTo3D( self->feMesh, gElement_I, planeIJK );
-		planeLayer = planeIJK[ planeAxis ];
-		
-		/** Find Local Coordinate of plane */
-		FeMesh_CoordGlobalToLocal( self->feMesh, lElement_I, planeCoord, planeXiCoord );
-		planeXi = planeXiCoord[ planeAxis ];
-	}
-	
-	/** Should be broadcast */
-	MPI_Allreduce( &planeXi,    &planeXiGlobal, 1, MPI_DOUBLE, MPI_MAX, self->communicator );
-	MPI_Allreduce( &planeLayer, &planeLayerGlobal, 1, MPI_UNSIGNED, MPI_MAX, self->communicator );
-
-	/** Create Swarm in plane */
-	extensionMgr_Register = ExtensionManager_Register_New();
-	dimExists[ aAxis ] = True;
-	if (self->dim == 3)
-		dimExists[ bAxis ] = True;
-	
-	singleCellLayout = SingleCellLayout_New( "cellLayout", (AbstractContext*)self->context, dimExists, NULL, NULL );
-	particlesPerDim[ planeAxis ] = 1;
-	gaussParticleLayout = GaussParticleLayout_New( "particleLayout", NULL, LocalCoordSystem, True, self->dim - 1, particlesPerDim );
-	tmpSwarm = Swarm_New( 
-			"tmpgaussSwarm", NULL,
-			singleCellLayout, 
-			gaussParticleLayout,
-			self->dim,
-			sizeof(IntegrationPoint), 
-			extensionMgr_Register, 
-			NULL,
-			self->communicator,
-		        NULL	);
-	Stg_Component_Build( tmpSwarm, NULL, False );
-
-	/** Change Positions of the particles */
-	Stg_Component_Initialise( tmpSwarm, NULL, False );
-	for ( lParticle_I = 0 ; lParticle_I < tmpSwarm->particleLocalCount ; lParticle_I++ ) {
-		particle = (IntegrationPoint*) Swarm_ParticleAt( tmpSwarm, lParticle_I );
-
-		storedXi_J_AXIS = particle->xi[ J_AXIS ];
-		particle->xi[ aAxis ]     = particle->xi[ I_AXIS ];
-		particle->xi[ bAxis ]     = storedXi_J_AXIS;
-		particle->xi[ planeAxis ] = planeXiGlobal;
-	}
-	
-	integral = FeVariable_IntegrateLayer_AxisIndependent( self, tmpSwarm, planeAxis, planeLayerGlobal, 
-			self->dim - 1, aAxis, bAxis, planeAxis );
-
-	/** Delete */
-	Stg_Class_Delete( tmpSwarm );
-	Stg_Class_Delete( gaussParticleLayout );
-	Stg_Class_Delete( singleCellLayout );
-	Stg_Class_Delete( extensionMgr_Register );
-	
-	return integral;
-}
-
-
-void FeVariable_ImportExportInfo_Delete( void* ptr ) {
-	/** Nothing to do - the ObjectAdaptor will take care of deleting the actual struct itself */
-}
-
-void FeVariable_SaveToFile( void* feVariable, Name filename, Bool saveCoords ) {
-	FeVariable*       self = (FeVariable*)feVariable;
-	Node_LocalIndex   lNode_I;
-	Node_GlobalIndex  gNode_I;
-	double*           coord;
-	Dof_Index         dof_I;
-	Dof_Index         dofAtEachNodeCount;
-	double            variableValues[MAX_FIELD_COMPONENTS];	
-	MPI_Comm	         comm = Comm_GetMPIComm( Mesh_GetCommTopology( self->feMesh, MT_VERTEX ) );
-	int               myRank;
-	int               nProcs;
-	MPI_Status        status;
-   Stream*           errorStr = Journal_Register( Error_Type, (Name)self->type  );
-   const int         FINISHED_WRITING_TAG = 100;
-   int               confirmation = 0;
-   MeshGenerator*    theGenerator;
-   
-#ifdef WRITE_HDF5
-   hid_t             file, fileSpace, fileData;
-   hid_t             memSpace;
-   hsize_t           start[2], count[2], size[2];
-   double*           buf;
-#else
-   FILE*             outputFile;
-#endif 
-
-	lNode_I = 0; gNode_I = 0;
-
-	MPI_Comm_size( comm, (int*)&nProcs );
-	MPI_Comm_rank( comm, (int*)&myRank );
-	
-	/** Note: assumes same number of dofs at each node */
-	dofAtEachNodeCount = self->fieldComponentCount;
-	
-#ifdef WRITE_HDF5
-	/** wait for go-ahead from process ranked lower than me, to avoid competition writing to file */
-	if ( myRank != 0 ) {
-		MPI_Recv( &confirmation, 1, MPI_INT, myRank - 1, FINISHED_WRITING_TAG, comm, &status );
-	}	
-
-   /** Open the file */
-	if ( myRank == 0 ) {
-      hid_t      attribData_id, attrib_id, group_id;
-      hsize_t    a_dims;
-      int        attribData;
-      Grid**     grid;
-      unsigned*  sizes;
-      
-      /** Open the HDF5 output file. */
-      file = H5Fcreate( filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
-      Journal_Firewall( file >= 0, errorStr,
-         "Error in %s for %s '%s' - Cannot create file %s.\n", 
-         __func__, self->type, self->name, filename );
-
-      /** create file attribute */
-      /** first store the fevariable checkpointing version */
-      a_dims = 1;
-      attribData = FeCHECKPOINT_V2;
-      attribData_id = H5Screate_simple(1, &a_dims, NULL);
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-         group_id  = H5Gopen(file, "/");
-         attrib_id = H5Acreate(group_id, "checkpoint file version", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
-      #else
-         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
-         attrib_id = H5Acreate2(group_id, "checkpoint file version", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
-      #endif
-      H5Awrite(attrib_id, H5T_NATIVE_INT, &attribData);
-      H5Aclose(attrib_id);
-      H5Gclose(group_id);
-      H5Sclose(attribData_id);
-
-      /** store the fevariable dimensionality */
-      a_dims = 1;
-      attribData = self->dim;
-      attribData_id = H5Screate_simple(1, &a_dims, NULL);
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-         group_id  = H5Gopen(file, "/");
-         attrib_id = H5Acreate(group_id, "dimensions", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
-      #else
-         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
-         attrib_id = H5Acreate2(group_id, "dimensions", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
-      #endif
-      H5Awrite(attrib_id, H5T_NATIVE_INT, &attribData);
-      H5Aclose(attrib_id);
-      H5Gclose(group_id);
-      H5Sclose(attribData_id);
-      
-      /** get the generator */
-      if( Stg_Class_IsInstance( self->feMesh->generator, MeshAdaptor_Type )) 
-         theGenerator = ((MeshAdaptor*)self->feMesh->generator)->generator;
-      else 
-         theGenerator = self->feMesh->generator;
-
-      /** store the mesh resolution if mesh is cartesian */
-      if ( Stg_Class_IsInstance( theGenerator, CartesianGenerator_Type ) ) {
-         a_dims = self->dim;
-         grid   = (Grid**) Mesh_GetExtension( self->feMesh, Grid*, "elementGrid" );	
-         sizes  =          Grid_GetSizes( *grid ); /** global no. of elements in each dim */
-         
-         attribData_id = H5Screate_simple(1, &a_dims, NULL);
-         #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-            group_id  = H5Gopen(file, "/");
-            attrib_id = H5Acreate(group_id, "mesh resolution", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
-         #else
-            group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
-            attrib_id = H5Acreate2(group_id, "mesh resolution", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
-         #endif
-         H5Awrite(attrib_id, H5T_NATIVE_INT, sizes);
-         H5Aclose(attrib_id);
-         H5Gclose(group_id);
-         H5Sclose(attribData_id);
-      }       
-      size[0] = Mesh_GetGlobalSize( self->feMesh, (MeshTopology_Dim)0 );;
-      size[1] = dofAtEachNodeCount;
-      if( saveCoords )
-         size[1] += self->dim;
-      
-      /** Create filespace */   
-      fileSpace = H5Screate_simple( 2, size, NULL );         
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData  = H5Dcreate( file, "/data", H5T_NATIVE_DOUBLE, fileSpace, H5P_DEFAULT );
-      #else
-      fileData  = H5Dcreate2( file, "/data", H5T_NATIVE_DOUBLE, fileSpace,
-                                  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
-      #endif
-	} else {
-      /** Open the HDF5 output file. */
-      file = H5Fopen( filename, H5F_ACC_RDWR, H5P_DEFAULT );
-      Journal_Firewall( file >= 0, errorStr,
-         "Error in %s for %s '%s' - Cannot open file %s.\n", 
-         __func__, self->type, self->name, filename );
-
-      /** get the filespace */   
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData  = H5Dopen( file, "/data" );
-      #else
-      fileData  = H5Dopen2( file, "/data", H5P_DEFAULT );
-      #endif
-      /** get the filespace handle */
-      fileSpace = H5Dget_space(fileData);
-	}	
-	
-   /** get the section of fileSpace to write to... set start point to be the
-      global index of first local node */
-	count[0] = 1;
-	count[1] = dofAtEachNodeCount;
-   if( saveCoords )
-      count[1] += self->dim;
-
-   /** create memSpace */
-   memSpace = H5Screate_simple( 2, count, NULL );
-   H5Sselect_all( memSpace );
-
-   buf = Memory_Alloc_Array( double, count[1], "fileBuffer" );
-   
-   for ( lNode_I = 0; lNode_I < FeMesh_GetNodeLocalSize( self->feMesh ); lNode_I++ ) {
-
-	   /** If required, add coords to array */
-	   if( saveCoords ) {
-	      coord = Mesh_GetVertex( self->feMesh, lNode_I );
-	      buf[0] = coord[0];
-	      buf[1] = coord[1];
-	      if( self->dim == 3 )
-	         buf[2] = coord[2]; 
-	   }
-	   
-	   /** Add field value at current node to array */
-      FeVariable_GetValueAtNode( self, lNode_I, variableValues );
-		for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
-		   if( saveCoords )
-			   buf[dof_I + self->dim] = variableValues[dof_I];
-			else
-			   buf[dof_I] = variableValues[dof_I];   
-		}	
-
-      /** select the region of dataspace to write to  */
-      start[0] = FeMesh_NodeDomainToGlobal( self->feMesh, lNode_I );
-      start[1] = 0;
-      H5Sselect_hyperslab( fileSpace, H5S_SELECT_SET, start, NULL, count, NULL );
-      /** Write the array to file */
-      H5Dwrite( fileData, H5T_NATIVE_DOUBLE, memSpace, fileSpace, H5P_DEFAULT, buf );
-   }   
-   /** free memory! */
-   Memory_Free( buf );
-   
-   /** Close all handles */
-   H5Dclose( fileData );
-   H5Sclose( memSpace );
-   H5Sclose( fileSpace );
-   H5Fclose( file );
-   
-	/** send go-ahead to process ranked above me, to avoid competition writing to file */
-	if ( myRank != nProcs - 1 ) {
-		MPI_Ssend( &confirmation, 1, MPI_INT, myRank + 1, FINISHED_WRITING_TAG, comm );
-	}	
-
-#else
-	/** wait for go-ahead from process ranked lower than me, to avoid competition writing to file */
-	if ( myRank != 0 ) {
-		MPI_Recv( &confirmation, 1, MPI_INT, myRank - 1, FINISHED_WRITING_TAG, comm, &status );
-	}	
-
-   /** Open the file */
-	if ( myRank == 0 ) {
-		outputFile = fopen( filename, "w" );
-	}
-	else {
-		outputFile = fopen( filename, "a" );
-	}	
-	
-	Journal_Firewall(	outputFile != NULL, errorStr,
-		"Error in %s for %s '%s' - Cannot create file %s.\n", 
-		__func__, self->type, self->name, filename );
-		
-	for ( lNode_I = 0; lNode_I < FeMesh_GetNodeLocalSize( self->feMesh ); lNode_I++ ) {
-		gNode_I = FeMesh_NodeDomainToGlobal( self->feMesh, lNode_I );
-		fprintf( outputFile, "%u ", gNode_I );
-		
-		/** If required, write the node coords to file */		
-      if( saveCoords ) {
-		   coord = Mesh_GetVertex( self->feMesh, lNode_I );
-         if(self->dim == 2)
-            fprintf( outputFile, "%.15g %.15g 0 ", coord[0], coord[1]);
-         else
-            fprintf( outputFile, "%.15g %.15g %.15g ", coord[0], coord[1], coord[2] );
-      }
-		
-		/** Add field value at current node to the file */            
-		FeVariable_GetValueAtNode( self, lNode_I, variableValues );
-		for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
-			fprintf( outputFile, "%.15g ", variableValues[dof_I] );
-		}	
-		fprintf( outputFile, "\n" );
-	}
-	
-	/** Close the file */
-	fclose( outputFile );
-	
-   /** send go-ahead to process ranked above me, to avoid competition writing to file */
-	if ( myRank != nProcs - 1 ) {
-		MPI_Ssend( &confirmation, 1, MPI_INT, myRank + 1, FINISHED_WRITING_TAG, comm );
-	}	
-
-#endif
-}
-
-
-#define MAX_LINE_LENGTH_DEFINE 1024
-
-void FeVariable_ReadFromFile( void* feVariable, Name filename ) {
-	FeVariable*        self = (FeVariable*)feVariable;
-	Node_LocalIndex    lNode_I = 0;
-	Node_GlobalIndex   gNode_I = 0;
-	Dof_Index          dof_I;
-	Dof_Index          dofAtEachNodeCount;
-#ifndef READ_HDF5
-	FILE*              inputFile;
-#endif
-	double             variableVal;
-	Processor_Index    proc_I;
-	MPI_Comm	          comm = Comm_GetMPIComm( Mesh_GetCommTopology( self->feMesh, MT_VERTEX ) );
-	unsigned		       rank;
-	unsigned		       nRanks;
-	int                nDims;
-	Bool               savedCoords = False;
-	Stream*            errorStr = Journal_Register( Error_Type, (Name)self->type  );
-   MeshGenerator*    theGenerator;
-	
-#ifdef READ_HDF5
-   hid_t                   file, fileSpace, fileData, error;
-   unsigned                totalNodes, ii, noffset;
-   hid_t                   memSpace;
-   hsize_t                 start[2], count[2], size[2], maxSize[2];
-   double*                 buf; 
-   FeCheckpointFileVersion ver;
-   hid_t                   attrib_id, group_id;
-   herr_t                  status;   
-#else
-   unsigned          uTemp;  
-   double            temp[3];  
-   int               count = 0;     
-   char               lineString[MAX_LINE_LENGTH_DEFINE];
-	const unsigned int MAX_LINE_LENGTH = MAX_LINE_LENGTH_DEFINE;
-   int               offset, n;
-#endif   	
-
-	MPI_Comm_rank( comm, (int*)&rank );
-	MPI_Comm_size( comm, (int*)&nRanks );
-	
-	dofAtEachNodeCount = self->fieldComponentCount;
-	proc_I = 0;
-	nDims = 0;
-	
-#ifdef READ_HDF5	
-   
-   /** Open the file and data set. */
-	file = H5Fopen( filename, H5F_ACC_RDONLY, H5P_DEFAULT );
-	
-	Journal_Firewall(	file >= 0, errorStr,
-		"Error in %s for %s '%s' - Cannot open file %s.\n", 
-		__func__, self->type, self->name, filename );
-
-   /** get the file attributes to sanity and version checks */
-   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      group_id  = H5Gopen(file, "/");
-      attrib_id = H5Aopen_name(group_id, "checkpoint file version");
-   #else
-      group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
-      attrib_id = H5Aopen(group_id, "checkpoint file version", H5P_DEFAULT);
-   #endif
-   /** if this attribute does not exist (attrib_id < 0) then we assume FeCHECKPOINT_V1 and continue without checking attributes */
-   if(attrib_id < 0)
-      ver = FeCHECKPOINT_V1;
-   else {
-      int checkVer;
-      int ndims;
-      int res[self->dim];
-      Grid**     grid;
-      unsigned*  sizes;
-
-      /** check for known checkpointing version type */
-
-      status = H5Aread(attrib_id, H5T_NATIVE_INT, &checkVer);
-      H5Aclose(attrib_id);
-      if(checkVer == 2)
-         ver = FeCHECKPOINT_V2;
-      else
-         Journal_Firewall( (0), errorStr,
-            "\n\nError in %s for %s '%s'\n"
-            "Unknown checkpoint version (%u) for checkpoint file (%s).\n", 
-            __func__, self->type, self->name, (unsigned int) checkVer, filename);
-
-      /** check for correct number of dimensions */
-
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-         attrib_id = H5Aopen_name(group_id, "dimensions");
-      #else
-         attrib_id = H5Aopen(group_id, "dimensions", H5P_DEFAULT);
-      #endif
-      status = H5Aread(attrib_id, H5T_NATIVE_INT, &ndims);
-      H5Aclose(attrib_id);      
-      Journal_Firewall( (ndims == self->dim), errorStr,
-         "\n\nError in %s for %s '%s'\n"
-         "Number of dimensions (%u) for checkpoint file (%s) does not correspond to simulation dimensions (%u).\n", 
-         __func__, self->type, self->name, (unsigned int) ndims, filename,
-         self->dim);
-
-      /** get the generator */
-      if( Stg_Class_IsInstance( self->feMesh->generator, MeshAdaptor_Type )) 
-         theGenerator = ((MeshAdaptor*)self->feMesh->generator)->generator;
-      else 
-         theGenerator = self->feMesh->generator;
-
-      /** check for correct mesh size if expecting a cartesian mesh*/
-      if ( Stg_Class_IsInstance( theGenerator, CartesianGenerator_Type ) ) {
-         
-         #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-            attrib_id = H5Aopen_name(group_id, "mesh resolution");
-         #else
-            attrib_id = H5Aopen(group_id, "mesh resolution", H5P_DEFAULT);
-         #endif
-         status = H5Aread(attrib_id, H5T_NATIVE_INT, &res);
-         H5Aclose(attrib_id);
-   
-         grid   = (Grid**) Mesh_GetExtension( self->feMesh, Grid*, "elementGrid" );	
-         sizes  =          Grid_GetSizes( *grid ); /** global no. of elements in each dim */
-         if(self->dim == 2)
-            Journal_Firewall( 
-               ( (sizes[0] == res[0]) && (sizes[1] == res[1]) ), 
-               errorStr,
-               "\n\nError in %s for %s '%s'\n"
-               "Size of mesh (%u,%u) for checkpoint file (%s) does not correspond to simulation mesh size (%u,%u).\n\n"
-               "If you would like to interpolate checkpoint data to simulation mesh size\n"
-               "    please re-launch using '--interpolateRestart=1' flag\n\n", 
-               __func__, self->type, self->name, 
-               (unsigned int) res[0], (unsigned int) res[1],
-               filename,
-               (unsigned int) sizes[0], (unsigned int) sizes[1]);
-         else
-            Journal_Firewall( 
-               ( (sizes[0] == res[0]) && (sizes[1] == res[1]) && (sizes[2] == res[2]) ), 
-               errorStr,
-               "\n\nError in %s for %s '%s'\n"
-               "Size of mesh (%u,%u,%u) for checkpoint file (%s) does not correspond to simulation mesh size (%u,%u,%u).\n\n"
-               "If you would like to interpolate checkpoint data to simulation mesh size\n"
-               "    please re-launch using '--interpolateRestart=1' flag\n\n", 
-               __func__, self->type, self->name, 
-               (unsigned int) res[0], (unsigned int) res[1], (unsigned int) res[2],
-               filename,
-               (unsigned int) sizes[0], (unsigned int) sizes[1], (unsigned int) sizes[2]);
-      }
-   }
-   H5Gclose(group_id);
-   
-   /** account for different versions of checkpointing */
-	switch ( ver ) {
-		case FeCHECKPOINT_V1:
-         noffset = 1;
-			break;
-		case FeCHECKPOINT_V2:
-         noffset = 0;
-			break;
-		default:
-			Journal_Firewall( 0, errorStr,
-				"Error: in %s: unknown checkpoint file version.\n",
-				__func__ ); 
-	}
-   
-	/** Prepare to read vertices from file */		
-   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-	fileData = H5Dopen( file, "/data" );
-   #else
-	fileData = H5Dopen2( file, "/data", H5P_DEFAULT );
-   #endif
-	fileSpace = H5Dget_space( fileData );
-   
-   /** Get size of dataspace to determine if coords are in file */
-   H5Sget_simple_extent_dims( fileSpace, size, maxSize ); 
-
-   if( maxSize[1] > dofAtEachNodeCount + noffset ) 
-      savedCoords = True;
-       
-   start[1] = 0;
-	count[0] = 1;
-	count[1] = dofAtEachNodeCount + noffset ;
-	if( savedCoords )  
-	   count[1] += self->dim;
-	   
-   memSpace = H5Screate_simple( 2, count, NULL );
-   totalNodes = Mesh_GetGlobalSize( self->feMesh, (MeshTopology_Dim)0 );
-   buf = Memory_Alloc_Array( double, count[1], "fileBuffer" );
-
-   Journal_Firewall( (maxSize[0] == totalNodes), errorStr,
-      "\n\nError in %s for %s '%s'\n"
-      "Number of node values (%u) stored in %s does not correspond to total number of requested mesh nodes (%u).\n", 
-      __func__, self->type, self->name, (unsigned int)maxSize[0], filename, totalNodes);
-   
-         
-   /** Read from HDF5 checkpint file */
-   for( ii=0; ii<totalNodes; ii++ ) {   
-	   start[0] = ii;
-               
-      H5Sselect_hyperslab( fileSpace, H5S_SELECT_SET, start, NULL, count, NULL );
-      H5Sselect_all( memSpace );
-         
-      error = H5Dread( fileData, H5T_NATIVE_DOUBLE, memSpace, fileSpace, H5P_DEFAULT, buf );
-      gNode_I = ii;
-
-      Journal_Firewall( error >= 0, errorStr,
-         "\n\nError in %s for %s '%s' - Cannot read data in %s.\n", 
-         __func__, self->type, self->name, filename );
-      
-      if( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, gNode_I, &lNode_I ) && 
-		   lNode_I < Mesh_GetLocalSize( self->feMesh, MT_VERTEX ) )
-		{
-		   for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
-		      if( savedCoords )
-		         variableVal = buf[dof_I + self->dim + noffset ];
-		      else
-				   variableVal = buf[dof_I + noffset ];
-				DofLayout_SetValueDouble( self->dofLayout, lNode_I, dof_I, variableVal );
-			}  
-		}
-	}   
-   Memory_Free( buf );
-
-   /** Close all handles */
-   H5Dclose( fileData );
-   H5Sclose( memSpace );
-   H5Sclose( fileSpace );
-   H5Fclose( file );
-   
-#else   
-
-	/** This loop used to stop 2 processors trying to open the file at the same time, which
-	  * seems to cause problems */
-	for ( proc_I = 0; proc_I < nRanks; proc_I++ ) {
-		MPI_Barrier( comm );
-		if ( proc_I == rank ) {
-			/** Do the following since in parallel on some systems, the file
-			 * doesn't get re-opened at the start automatically. */
-			inputFile = fopen( filename, "r" );
-
-			if ( False == inputFile ) {
-				Journal_Firewall( 0, errorStr, "Error- in %s(), for feVariable \"%s\": Couldn't import from file: "
-					"\"%s\" - aborting.\n", __func__, self->name, filename );
-					
-			}
-			rewind( inputFile );
-	
-		}
-	}
-   
-   /** Need to determine whether checkpoint file contains coordinates */
-   fgets( lineString, MAX_LINE_LENGTH, inputFile );
-   
-   sscanf( lineString, "%u%n ", &uTemp, &offset );
-   while( sscanf( lineString + offset, "%lf%n ", &temp[0], &n ) )
-   {
-      offset += n;
-      count ++;
-      if( offset >= strlen( lineString ) - 2 )
-         break;
-   }   
- 
-   if( count > dofAtEachNodeCount + 1 ) 
-      savedCoords = True;
-    
-   rewind( inputFile );
-      
-	/** Need to re-set the geometry here, in case we're loading from a checkpoint that had compression/squashing BCs,
-		and hence ended up with a smaller mesh than the original */
-	nDims = Mesh_GetDimSize( self->feMesh );
-	while ( !feof(inputFile) ) {
-		fscanf( inputFile, "%u ", &gNode_I );
-		
-		if( savedCoords ) 
-		   fscanf( inputFile, "%lg %lg %lg ", &temp[0], &temp[1], &temp[2] );
-		   
-		if( FeMesh_NodeGlobalToDomain( self->feMesh, gNode_I, &lNode_I ) && 
-		    lNode_I < FeMesh_GetNodeLocalSize( self->feMesh ) )
-		{
-			for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
-				fscanf( inputFile, "%lg ", &variableVal );
-				DofLayout_SetValueDouble( self->dofLayout, lNode_I, dof_I, variableVal );
-			}
-		}
-		else {
-			fgets( lineString, MAX_LINE_LENGTH, inputFile );
-		}
-	}
-	fclose( inputFile );
-#endif	
-
-	Mesh_DeformationUpdate( self->feMesh );
-
-	/** Sync shadow values now, as all procs should have required input */
-	FeVariable_SyncShadowValues( self );
-}
-
-void FeVariable_InterpolateFromFile( void* feVariable, DomainContext* context, Name feVarFilename, const char* meshFilename ){
-	FeVariable*							self = (FeVariable*)feVariable;
-   Stream*								errorStr = Journal_Register( Error_Type, (Name)self->type  );   
-#ifdef READ_HDF5
-   CartesianGenerator*				gen;
-   C0Generator*						C0gen;
-   FeMesh								*feMesh, *C0feMesh, *elementMesh;
-   DofLayout*							dofs;
-   Variable_Register*				varReg;
-   Variable*							var;
-   FeVariable*							feVar;
-   hid_t									file, fileData;
-   unsigned								totalNodes, ii;
-   hid_t									attrib_id, group_id;
-   herr_t								status;
-   int									res[3];
-   int									checkVer;
-   int									ndims;
-	double								crdMin[3], crdMax[3];
-	double*								value;
-	unsigned								nDomainVerts;
-	static double*						arrayPtr;
-   char*									varName[9];
-
-   /** Open the file and data set. */
-	file = H5Fopen( meshFilename, H5F_ACC_RDONLY, H5P_DEFAULT );
-	
-	Journal_Firewall(	file >= 0, errorStr, "Error in %s for %s '%s' - Cannot open file %s.\n", __func__, self->type, self->name, meshFilename );
-
-   /** get the file attributes to sanity and version checks */
-   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      group_id  = H5Gopen(file, "/");
-      attrib_id = H5Aopen_name(group_id, "checkpoint file version");
-   #else
-      group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
-      attrib_id = H5Aopen(group_id, "checkpoint file version", H5P_DEFAULT);
-   #endif
-   /** if this attribute does not exist (attrib_id < 0) then we assume MeshCHECKPOINT_V1 which is not supported  */
-   if(attrib_id < 0)
-      Journal_Firewall( 0, errorStr,"\nError in %s for %s '%s' \n\n Interpolation restart not supported for Version 1 Checkpoint files \n\n", __func__, self->type, self->name );
-
-   /** check for known checkpointing version type */
-
-   status = H5Aread(attrib_id, H5T_NATIVE_INT, &checkVer);
-   H5Aclose(attrib_id);
-   if(checkVer != 2)
-      Journal_Firewall( (0), errorStr, "\n\nError in %s for %s '%s'\n" "Unknown checkpoint version (%u) for checkpoint file (%s).\n", __func__,
-			 self->type, self->name, (unsigned int) checkVer, meshFilename);
-
-   /** check for correct number of dimensions */
-
-   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      attrib_id = H5Aopen_name(group_id, "dimensions");
-   #else
-      attrib_id = H5Aopen(group_id, "dimensions", H5P_DEFAULT);
-   #endif
-   status = H5Aread(attrib_id, H5T_NATIVE_INT, &ndims);
-   H5Aclose(attrib_id);      
-   Journal_Firewall( (ndims == self->dim), errorStr,
-      "\n\nError in %s for %s '%s'\n"
-      "Number of dimensions (%u) for checkpoint file (%s) does not correspond to simulation dimensions (%u).\n", 
-      __func__, self->type, self->name, (unsigned int) ndims, meshFilename,
-      self->dim);
-
-   /** check for correct mesh size if expecting a cartesian mesh*/
-   
-   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      attrib_id = H5Aopen_name(group_id, "mesh resolution");
-   #else
-      attrib_id = H5Aopen(group_id, "mesh resolution", H5P_DEFAULT);
-   #endif
-   status = H5Aread(attrib_id, H5T_NATIVE_INT, &res);
-   H5Aclose(attrib_id);
-
-   /** Read in minimum coord. */
-   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData = H5Dopen( file, "/min" );
-   #else
-      fileData = H5Dopen2( file, "/min", H5P_DEFAULT );
-   #endif
-   H5Dread( fileData, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &crdMin );
-   H5Dclose( fileData );
-      
-   /** Read in maximum coord. */
-   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData = H5Dopen( file, "/max" );
-   #else
-      fileData = H5Dopen2( file, "/max", H5P_DEFAULT );
-   #endif
-   H5Dread( fileData, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &crdMax );
-   H5Dclose( fileData );
-
-   /** Close all handles */
-   H5Gclose(group_id);
-   H5Fclose( file );
-
-   /** create a cartesian mesh generator which will be required for the fevariable creation */
-   gen = CartesianGenerator_New( "", NULL );
-   /** use the feVariable dimension size for mesh generator */
-   CartesianGenerator_SetDimSize( gen, self->dim );
-   /** use the element size read in from the checkpoint file for the new mesh generator */
-   CartesianGenerator_SetTopologyParams( gen, (unsigned*)res, 0, NULL, NULL );
-	/** use the feVariable's mesh's generator's crdMin and crdMax (which have been previously read in from checkpointed mesh file  */
-   CartesianGenerator_SetGeometryParams( gen, crdMin, crdMax );
-   /** set it so that the generator does not read in the mesh from a file - we will 
-              explicitly do this after we build the feMesh using the provided mesh checkpoint file */
-   gen->readFromFile = False;
-   /** create a feMesh */
-   feMesh = FeMesh_New( "", NULL );
-   /** set feMesh to use generator we just created  */
-   Mesh_SetGenerator( feMesh, gen );
-   /** set the feMesh family to be the same as that of the feVariable we are initialising/interpolating ie constant, linear, etc 
-       unless we are initialising a constant mesh, in which case we set the element family to linear, and the mesh will be used 
-       as the elementMesh for the C0 generator */
-   if (!strcmp(self->feMesh->generator->type, CartesianGenerator_Type)){
-      FeMesh_SetElementFamily( feMesh, self->feMesh->feElFamily );
-      /** set periodicity according to current simulation */
-      gen->periodic[0] = ((CartesianGenerator*)self->feMesh->generator)->periodic[0];
-      gen->periodic[1] = ((CartesianGenerator*)self->feMesh->generator)->periodic[1];
-      gen->periodic[2] = ((CartesianGenerator*)self->feMesh->generator)->periodic[2];
-   } else if (!strcmp(self->feMesh->generator->type, C0Generator_Type)){
-      FeMesh_SetElementFamily( feMesh, "linear" );
-      /** set periodicity according to current simulation */
-      gen->periodic[0] = ((CartesianGenerator*)((C0Generator*)self->feMesh->generator)->elMesh)->periodic[0];
-      gen->periodic[1] = ((CartesianGenerator*)((C0Generator*)self->feMesh->generator)->elMesh)->periodic[1];
-      gen->periodic[2] = ((CartesianGenerator*)((C0Generator*)self->feMesh->generator)->elMesh)->periodic[2];
-   } else
-      Journal_Firewall( 0, errorStr,"\nError in %s for %s '%s' \n\n Interpolation restart not supported for this mesh type \n\n", __func__, self->type, self->name );
-
-   /** now build the mesh, then read in the required coordinates from the given file */
-   Stg_Component_Build( feMesh, NULL, False );
-   CartesianGenerator_ReadFromHDF5(  gen, (Mesh*) feMesh, meshFilename );
-
-   /** where we are dealing with a constant mesh feVariable, we have to build a new C0 mesh */ 
-   if (!strcmp(self->feMesh->generator->type, C0Generator_Type)){
-      elementMesh = feMesh;
-      /** create the C0 generator */
-      C0gen = C0Generator_New( "", (AbstractContext*)self->context );
-      /** set it's element mesh to the feMesh create just above */
-      C0Generator_SetElementMesh( C0gen, (void*) elementMesh );
-      /** create a new feMesh */
-      C0feMesh = FeMesh_New( "", NULL );
-      /** set feMesh to use generator we just created, and set its type to constant mesh  */
-      Mesh_SetGenerator( C0feMesh, C0gen );
-      FeMesh_SetElementFamily( C0feMesh, self->feMesh->feElFamily );
-      /** now build the mesh, which will generate the mesh using the provided generator */
-      Stg_Component_Build( C0feMesh, NULL, False );
-      /** reset the feMesh pointer to point to this C0 mesh */
-      feMesh = C0feMesh;
-   }
-   Stg_Component_Initialise( feMesh, NULL, False );
-   /** get the number of mesh vertices stored locally */   
-   nDomainVerts = Mesh_GetDomainSize( feMesh, MT_VERTEX );   
-
-   varReg = Variable_Register_New();
-   if (self->fieldComponentCount == 1){
-     var = Variable_NewScalar( "interpolation_temp_scalar", (AbstractContext*)self->context, Variable_DataType_Double, (Index*)&nDomainVerts, NULL, (void **)(&arrayPtr), varReg );
-   } else {
-      unsigned var_I;
-		for( var_I = 0; var_I < self->fieldComponentCount; var_I++  )
-			Stg_asprintf( &varName[var_I], "%s-loaded-Component-%d", self->name, var_I );
-      var = Variable_NewVector( "interpolation_temp_vector", 
-											(AbstractContext*)self->context,
-                                 Variable_DataType_Double,
-                                 self->fieldComponentCount,
-                                 &nDomainVerts,
-                                 NULL,
-                                 (void**)&arrayPtr,
-                                 varReg, 
-                                 varName[0], varName[1], varName[2], varName[3], varName[4],
-                                 varName[5], varName[6], varName[7], varName[8] );
-   }
-   Variable_Register_Add( varReg, var);
-   var->allocateSelf = True;   
-   Stg_Component_Build( var, NULL, False );
-
-   dofs = DofLayout_New( "interpolation_temp_dof", self->context, varReg, nDomainVerts, feMesh );
-	if( self->fieldComponentCount == 1 )
-		DofLayout_AddAllFromVariableArray( dofs, 1, &var );
-	else {
-      unsigned   var_I, node_I;
-      Variable*  variable;
-		for( var_I = 0; var_I < self->fieldComponentCount; var_I++ ) {
-			variable = Variable_Register_GetByName( varReg, varName[var_I] );
-			variable->arrayPtrPtr = &var->arrayPtr;
-
-			for( node_I = 0; node_I < nDomainVerts; node_I++ )
-				DofLayout_AddDof_ByVarName( dofs, varName[var_I], node_I );
-
-			Memory_Free( varName[var_I] );
-      }
-   }
-   Stg_Component_Build( dofs, NULL, False );
-   Stg_Component_Initialise( dofs, NULL, False );
-
-   feVar = FeVariable_New(
-		"interpolation_temp_fevar", 
-		self->context,
-  		feMesh, 
-  		NULL, 
-		dofs, 
-		NULL, 
-		NULL, 
-		NULL, 
-		self->fieldComponentCount, 
-		False, 
-		True, 
-		False, 
-		NULL );
-
-   Stg_Component_Build( feVar, context, False );
-   /** not sure why these aren't being set correctly, so a little (tri/ha)ckery */
-   feVar->fieldComponentCount = self->fieldComponentCount;
-   feVar->dim = self->dim;
-   FeVariable_ReadFromFile( feVar, feVarFilename );
-   feVar->_syncShadowValues( feVar );
-
-   totalNodes = Mesh_GetLocalSize( self->feMesh, MT_VERTEX );
-   value = Memory_Alloc_Array( double, self->fieldComponentCount, "interValue" );
-         
-   /** step through nodes, interpolating the required values from our newly created feVariable */
-   for( ii=0; ii<totalNodes; ii++ ) {
-      feVar->_interpolateValueAt( feVar, Mesh_GetVertex( self->feMesh, ii ), value);
-      FeVariable_SetValueAtNode( self, ii, value);
-   }
-   Memory_Free( value );
-
-   /** our work is done, so we clean up after ourselves */
-   _FeVariable_Delete(feVar);
-   _DofLayout_Delete(dofs);
-   _Variable_Delete(var);
-   _Variable_Register_Delete(varReg);
-   _FeMesh_Delete(feMesh);
-
-   if (!strcmp(self->feMesh->generator->type, C0Generator_Type)){
-      _C0Generator_Delete(C0gen);
-      _FeMesh_Delete(elementMesh);
-   }
-   _CartesianGenerator_Delete(gen);
-
-#else
-   Journal_Firewall(!context->interpolateRestart, 
-               errorStr,"\n\n Interpolation restart not supported for ASCII checkpoint files \n\n");
-#endif   
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FeVariable.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/FeVariable.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,2725 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FeVariable.c 1224 2008-09-10 13:28:46Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include "units.h"
+#include "types.h"
+#include "ElementType.h"
+#include "ElementType_Register.h"
+#include "Element.h"
+#include "FeMesh.h"
+#include "FeEquationNumber.h"
+#include "FeVariable.h"
+#include "LinkedDofInfo.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#if defined(READ_HDF5) || defined(WRITE_HDF5)
+#include <hdf5.h>
+#endif
+
+const Type FeVariable_Type = "FeVariable";
+const Name defaultFeVariableFeEquationNumberName = "defaultFeVariableFeEqName";
+
+/** MPI Tags */
+static const int DOF_VALUES_TAG = 10;
+
+/** Global objects */
+Stg_ObjectList* FeVariable_FileFormatImportExportList = NULL;
+
+FeVariable* FeVariable_New_FromTemplate(
+	Name							name,
+	DomainContext*				context,
+	void*							_templateFeVariable,
+	DofLayout*					dofLayout, 
+	void*							ics,
+	Bool							isReferenceSolution,
+	Bool							loadReferenceEachTimestep,
+	FieldVariable_Register*	fV_Register )
+{
+  FeVariable*	templateFeVariable = (FeVariable*)_templateFeVariable;
+	FeVariable*	newFeVariable = NULL;
+	
+	newFeVariable = FeVariable_New_Full(
+		name, 
+		context,
+		templateFeVariable->feMesh,
+		templateFeVariable->geometryMesh,
+		dofLayout,
+		templateFeVariable->bcs,
+		ics,
+		templateFeVariable->linkedDofInfo,
+		templateFeVariable,
+		templateFeVariable->fieldComponentCount,
+		templateFeVariable->dim,
+		templateFeVariable->isCheckpointedAndReloaded,
+		isReferenceSolution,
+		loadReferenceEachTimestep,
+		templateFeVariable->communicator,
+		fV_Register );
+
+	newFeVariable->templateFeVariable = templateFeVariable;
+
+	return newFeVariable;
+}
+
+FeVariable* FeVariable_New(
+	Name							name,
+	DomainContext*				context,
+	void*							feMesh,
+	void*							geometryMesh,
+	DofLayout*					dofLayout, 
+	void*							bcs,
+	void*							ics,
+	void*							linkedDofInfo,
+	Dimension_Index			dim,
+	Bool							isCheckpointedAndReloaded,
+	Bool							isReferenceSolution,
+	Bool							loadReferenceEachTimestep,
+	FieldVariable_Register*	fV_Register )		
+{
+	assert( Class_IsSuper( ((FeMesh*)feMesh)->topo, IGraph ) );
+
+	return FeVariable_New_Full(
+		name,
+		context,
+		feMesh,
+		geometryMesh,
+		dofLayout,
+		bcs,
+		ics,
+		linkedDofInfo,
+		NULL,
+		dofLayout->_totalVarCount,
+		dim,
+		isCheckpointedAndReloaded,
+		isReferenceSolution,
+		loadReferenceEachTimestep,
+		((IGraph*)((FeMesh*)feMesh)->topo)->remotes[MT_VERTEX]->comm->mpiComm, 
+		fV_Register );
+}
+
+FeVariable* FeVariable_New_Full(
+	Name							name,
+	DomainContext*				context,
+	void*							feMesh,
+	void*							geometryMesh,
+	DofLayout*					dofLayout, 
+	void*							bcs,
+	void*							ics,
+	void*							linkedDofInfo,
+	void*							templateFeVariable,
+	Index							fieldComponentCount,
+	Dimension_Index			dim,
+	Bool							isCheckpointedAndReloaded,
+	Bool							isReferenceSolution,
+	Bool							loadReferenceEachTimestep,
+	MPI_Comm						communicator,
+	FieldVariable_Register*	fieldVariable_Register )		
+{
+  FeVariable* self = (FeVariable*)_FeVariable_DefaultNew( name );
+
+	self->isConstructed = True;
+	_FieldVariable_Init( (FieldVariable*)self, context, fieldComponentCount, dim, isCheckpointedAndReloaded, communicator, fieldVariable_Register );
+	_FeVariable_Init( self, feMesh, geometryMesh, dofLayout, bcs, ics, linkedDofInfo, templateFeVariable, isReferenceSolution, loadReferenceEachTimestep );
+
+	return self;
+}
+
+void* _FeVariable_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                         _sizeOfSelf = sizeof(FeVariable);
+	Type                                                                 type = FeVariable_Type;
+	Stg_Class_DeleteFunction*                                         _delete = _FeVariable_Delete;
+	Stg_Class_PrintFunction*                                           _print = _FeVariable_Print;
+	Stg_Class_CopyFunction*                                             _copy = _FeVariable_Copy;
+	Stg_Component_DefaultConstructorFunction*             _defaultConstructor = (Stg_Component_DefaultConstructorFunction*)_FeVariable_DefaultNew;
+	Stg_Component_ConstructFunction*                               _construct = _FeVariable_AssignFromXML;
+	Stg_Component_BuildFunction*                                       _build = _FeVariable_Build;
+	Stg_Component_InitialiseFunction*                             _initialise = _FeVariable_Initialise;
+	Stg_Component_ExecuteFunction*                                   _execute = _FeVariable_Execute;
+	Stg_Component_DestroyFunction*                                   _destroy = _FeVariable_Destroy;
+	AllocationType                                         nameAllocationType = NON_GLOBAL;
+	FieldVariable_InterpolateValueAtFunction*             _interpolateValueAt = _FeVariable_InterpolateValueAt;
+	FieldVariable_GetValueFunction*               _getMinGlobalFieldMagnitude = _FeVariable_GetMinGlobalFieldMagnitude;
+	FieldVariable_GetValueFunction*               _getMaxGlobalFieldMagnitude = _FeVariable_GetMaxGlobalFieldMagnitude;
+	FieldVariable_GetCoordFunction*                  _getMinAndMaxLocalCoords = _FeVariable_GetMinAndMaxLocalCoords;
+	FieldVariable_GetCoordFunction*                 _getMinAndMaxGlobalCoords = _FeVariable_GetMinAndMaxGlobalCoords;
+	FeVariable_InterpolateWithinElementFunction*    _interpolateWithinElement = _FeVariable_InterpolateNodeValuesToElLocalCoord;
+	FeVariable_GetValueAtNodeFunction*                        _getValueAtNode = _FeVariable_GetValueAtNode;
+	FeVariable_SyncShadowValuesFunc*                        _syncShadowValues = _FeVariable_SyncShadowValues;
+
+	return _FeVariable_New(  FEVARIABLE_PASSARGS  ); /* feVariableList */
+}
+
+FeVariable* _FeVariable_New(  FEVARIABLE_DEFARGS  ) {
+	FeVariable* self;
+	
+	/** Allocate memory */
+	assert( _sizeOfSelf >= sizeof(FeVariable) );
+	
+	self = (FeVariable*) _FieldVariable_New(  FIELDVARIABLE_PASSARGS  );
+	
+	/** General info */
+	
+	/** Virtual functions */
+	self->_interpolateWithinElement = _interpolateWithinElement;
+	self->_getValueAtNode = _getValueAtNode;
+	self->_syncShadowValues = _syncShadowValues;
+	
+	/** FeVariable info */
+	
+	return self;
+}
+
+
+void _FeVariable_Init( 
+	FeVariable*	self,
+	void*			feMesh,
+	void*			geometryMesh,
+	DofLayout*	dofLayout, 
+	void*			bcs,
+	void*			ics,
+	void*			linkedDofInfo,
+	void*			templateFeVariable,
+	Bool			isReferenceSolution,
+	Bool			loadReferenceEachTimestep )
+{
+	Stream* errorStream = Journal_Register( Error_Type, (Name)self->type  );
+	/** General and Virtual info should already be set */
+	
+	/** FeVariable info */
+	self->debug = Stream_RegisterChild( StgFEM_Discretisation_Debug, self->type );
+	self->feMesh = Stg_CheckType( feMesh, FeMesh );
+	/** Set pointer for geometry mesh - if none is provided then it'll use the feMesh */
+	self->geometryMesh = ( geometryMesh ?  Stg_CheckType( geometryMesh, FeMesh ) : Stg_CheckType( feMesh, FeMesh ) );
+	self->dofLayout = dofLayout;
+	if ( bcs )
+		self->bcs = Stg_CheckType( bcs, VariableCondition );
+	if ( ics )
+		self->ics = Stg_CheckType( ics, VariableCondition );
+	if ( linkedDofInfo )
+		self->linkedDofInfo = Stg_CheckType( linkedDofInfo, LinkedDofInfo );
+	self->shadowValuesSynchronised = False;
+
+	if ( templateFeVariable )
+		self->templateFeVariable = Stg_CheckType( templateFeVariable, FeVariable );
+	if( !isReferenceSolution ) {
+		if ( self->templateFeVariable ) {
+			self->eqNum = self->templateFeVariable->eqNum;
+		}
+		else {
+                  self->eqNum = FeEquationNumber_New( defaultFeVariableFeEquationNumberName, self->context, self->feMesh, self->dofLayout, self->bcs, (LinkedDofInfo*)linkedDofInfo );
+			self->eqNum->removeBCs = self->removeBCs;
+		}
+	}
+	else
+		self->eqNum = NULL;
+
+	self->isReferenceSolution = isReferenceSolution;
+	self->loadReferenceEachTimestep = loadReferenceEachTimestep;
+	Journal_Firewall( (self->loadReferenceEachTimestep != True), errorStream, "The loadReferenceEachTimestep feature isn't implemented yet, sorry.\n" );
+
+	self->dynamicBCs[0] = NULL;
+	self->dynamicBCs[1] = NULL;
+	self->dynamicBCs[2] = NULL;
+
+	self->buildEqNums = True;
+
+	self->inc = IArray_New();
+}
+
+void _FeVariable_Delete( void* variable ) {
+	FeVariable* self = (FeVariable*)variable;
+	Journal_DPrintf( self->debug, "In %s- for \"%s\":\n", __func__, self->name );
+	
+	/** Stg_Class_Delete parent*/
+	_Stg_Component_Delete( self );
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+/** --- Virtual Function Implementations --- */
+
+void _FeVariable_Print( void* variable, Stream* stream ) {
+	FeVariable* self = (FeVariable*)variable;
+	
+	/** General info */
+	Journal_Printf( stream, "FeVariable (ptr): %p\n", self );
+	
+	/** Print parent */
+	_Stg_Component_Print( self, stream );
+	
+	/** Virtual info */
+	
+	/** FeVariable info */
+	Stg_Class_Print( self->feMesh, stream );
+	if ( self->dofLayout ) {
+		Stg_Class_Print( self->dofLayout, stream );
+	}
+	else {
+		Journal_Printf( stream, "\tdofLayout: (null)... not provided (may be Operator type)\n" );
+	}
+	if ( self->bcs ) {
+		Stg_Class_Print( self->bcs, stream );
+	}
+	else {
+		Journal_Printf( stream, "\tbcs: (null)... not provided (may be Operator type)\n" );
+	}
+	if ( self->ics ) {
+		Stg_Class_Print( self->ics, stream );
+	}
+	else {
+		Journal_Printf( stream, "\tics: (null)... not provided (may be Operator type)\n" );
+	}
+
+	if ( self->linkedDofInfo ) {
+		Stg_Class_Print( self->linkedDofInfo, stream );
+	}
+	else {
+		Journal_Printf( stream, "\tlinkedDofInfo: (null)... not provided\n" );
+	}
+	
+	if( self->eqNum ) {
+		Stg_Class_Print( self->eqNum, stream );
+	}
+	else {
+		Journal_Printf( stream, "\teqNum: (null)... not built yet\n" );
+	}
+}
+
+void* _FeVariable_Copy( const void* feVariable, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+	FeVariable*	newFeVariable;
+	PtrMap*		map = ptrMap;
+	Bool		ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newFeVariable = (FeVariable*)_FieldVariable_Copy( self, dest, deep, nameExt, map );
+
+	newFeVariable->templateFeVariable = self->templateFeVariable;
+	
+	if( deep ) {
+		newFeVariable->debug = self->debug; 
+		newFeVariable->feMesh = (FeMesh*)Stg_Class_Copy( self->feMesh, NULL, deep, nameExt, map );
+		newFeVariable->dofLayout = (DofLayout*)Stg_Class_Copy( self->dofLayout, NULL, deep, nameExt, map );
+		newFeVariable->bcs = (VariableCondition*)Stg_Class_Copy( self->bcs, NULL, deep, nameExt, map );
+		newFeVariable->ics = self->ics ? (VariableCondition*)Stg_Class_Copy( self->ics, NULL, deep, nameExt, map ) : NULL;
+		if ( self->linkedDofInfo == NULL ) {
+			newFeVariable->linkedDofInfo = NULL;
+		}
+		else {
+			newFeVariable->linkedDofInfo = (LinkedDofInfo*)Stg_Class_Copy( self->linkedDofInfo, NULL,
+				deep, nameExt, map );
+		}
+
+		if( !self->isReferenceSolution ) {
+			if ( self->templateFeVariable ) {
+				newFeVariable->eqNum = self->eqNum;
+			}
+			else {
+				newFeVariable->eqNum = (FeEquationNumber*)Stg_Class_Copy( self->eqNum, NULL, deep, nameExt, map );
+			}
+		}
+		else
+			newFeVariable->eqNum = NULL;
+	}
+	else {
+		newFeVariable->debug = self->debug;
+		newFeVariable->feMesh = self->feMesh;
+		newFeVariable->geometryMesh = self->geometryMesh;
+		newFeVariable->dofLayout = self->dofLayout;
+		newFeVariable->bcs = self->bcs;
+		newFeVariable->ics = self->ics;
+		newFeVariable->linkedDofInfo = self->linkedDofInfo;
+		newFeVariable->eqNum = self->eqNum;
+	}
+	
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+	
+	return (void*)newFeVariable;
+}
+
+
+void _FeVariable_Build( void* variable, void* data ) {
+	FeVariable* self = (FeVariable*)variable;
+	DomainContext*   context = (DomainContext*)data;
+	unsigned dim, numNodes;
+	
+	if ( False == self->isBuilt ) {
+		self->isBuilt = True;
+	
+		Journal_DPrintf( self->debug, "In %s- for %s:\n", __func__, self->name );
+		Stream_IndentBranch( StgFEM_Debug );
+
+		/** build the BCs */
+		Stg_Component_Build( self->feMesh, data, False );
+		if ( self->dofLayout ) Stg_Component_Build( self->dofLayout, data, False );
+		if ( self->bcs       ) Stg_Component_Build( self->bcs,       data, False );
+		
+		/** only bother building the ics specified via XML/construct if we are not in restart mode
+		  - otherwise, we will use the checkpointed values anyway */
+		if ( self->ics && !(context && (True == context->loadFromCheckPoint) ) ) {
+			Stg_Component_Build( self->ics, data, False );
+		}
+
+		if ( self->linkedDofInfo )	Stg_Component_Build( self->linkedDofInfo, data, False );
+
+
+		/** Extract component count. */
+		if ( self->dofLayout ) self->fieldComponentCount = self->dofLayout->_totalVarCount;
+
+		dim = Mesh_GetDimSize(self->feMesh);
+		/** allocate GNx here */
+		/* At least this will work for meshes with names other
+			than those listed above. I spent three hours finding
+			this out.*/
+		numNodes = FeMesh_GetElementNodeSize(self->feMesh, 0);
+
+		self->GNx = Memory_Alloc_2DArray( double, dim, numNodes, (Name)"Global Shape Function Derivatives" );
+		
+		/** don't build the equation numbers for fields that aren't being solved for 
+		 * (ie: error and reference fields) */
+		if( !self->isReferenceSolution && self->buildEqNums  ) {
+			Stg_Component_Build( self->eqNum, data, False );
+		}
+
+		Stream_UnIndentBranch( StgFEM_Debug );
+	}
+}
+
+void _FeVariable_AssignFromXML( void* variable, Stg_ComponentFactory* cf, void* data ) {
+	FeVariable*         self = (FeVariable*)variable;
+	FeMesh*             feMesh = NULL;
+	FeMesh*             geometryMesh = NULL;
+	DofLayout*          dofLayout = NULL;
+	VariableCondition*  bc = NULL;
+	VariableCondition*  ic = NULL;
+	LinkedDofInfo*      linkedDofInfo 	= NULL;
+	Bool                isReferenceSolution = False;
+	Bool                loadReferenceEachTimestep = False;
+
+	_FieldVariable_AssignFromXML( self, cf, data );
+
+	feMesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"FEMesh", FeMesh, True, data  );
+	geometryMesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"GeometryMesh", FeMesh, False, data  );
+	dofLayout = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)DofLayout_Type, DofLayout, True, data  );
+
+	ic = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"IC", VariableCondition, False, data  );
+	bc = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"BC", VariableCondition, False, data  );
+	linkedDofInfo = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"LinkedDofInfo", LinkedDofInfo, False, data  );
+
+	isReferenceSolution = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"isReferenceSolution", False  );
+	loadReferenceEachTimestep = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"loadReferenceEachTimestep", False  );
+
+	/** TODO: should really be a parameter */
+	self->removeBCs = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"removeBCs", True  );
+
+	_FeVariable_Init( self, feMesh, geometryMesh, dofLayout, bc, ic, linkedDofInfo, NULL, isReferenceSolution, loadReferenceEachTimestep );
+}
+
+void _FeVariable_Initialise( void* variable, void* data ) {
+	FeVariable* 	self = (FeVariable*)variable;
+	DomainContext*	context = self->context; 
+	char*				inputPathString = NULL;
+   Dictionary_Entry_Value* feVarsList = NULL;
+	
+	Journal_DPrintf( self->debug, "In %s- for %s:\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+	
+	/** do basic mesh initialisation */
+	Stg_Component_Initialise( self->feMesh, data, False );
+	Stg_Component_Initialise( self->dofLayout, data, False );
+
+	if ( self->linkedDofInfo ) {
+		Stg_Component_Initialise( self->linkedDofInfo, data, False );
+	}
+
+	if( !self->isReferenceSolution ) {	
+		Stg_Component_Initialise( self->eqNum, data, False );
+	}
+
+	if ( context ) {
+		/** Get the input path string once here - single point of control */
+		inputPathString = Context_GetCheckPointReadPrefixString( context );
+	}
+	/** If the reference solution option is enabled, just load this up regardless of checkpointing options below.
+	 * Want to allow option of disabling this feature, if you're manually setting up a FeVariable without a context etc. */
+	if ( context && self->isReferenceSolution ) {
+		char * filename = NULL;
+		Journal_DPrintf( self->debug, "Reference FeVariable -> loading nodal values from file.\n" );
+		
+		 
+#ifdef READ_HDF5
+		Stg_asprintf( &filename, "%s%s.%.5u.h5", inputPathString, self->name, context->restartTimestep );
+#else
+		Stg_asprintf( &filename, "%s%s.%.5u.dat", inputPathString, self->name, context->restartTimestep );
+#endif
+		FeVariable_ReadFromFile( self, filename );
+
+		Memory_Free( filename );
+		Stream_UnIndentBranch( StgFEM_Debug );
+		return;
+	}
+
+	/** Setting up whether to load from checkpointing */
+	if ( self->ics || ((context && (True == context->loadFromCheckPoint) )&& (self->isCheckpointedAndReloaded)) )  {
+		Journal_DPrintf( self->debug, "applying the I.C.s for this Variable:\n" ); 
+		Stream_Indent( self->debug );
+	
+		if ( self->ics && !(context && (True == context->loadFromCheckPoint) && (True == self->isCheckpointedAndReloaded)) ) {
+			Journal_DPrintf( self->debug, "regular (non-restart) mode -> applying ICs specified in XML/constructor\n" );
+			Stg_Component_Initialise( self->ics, context, False );
+			VariableCondition_Apply( self->ics, context );
+		}
+		else {
+			char * filename = NULL;
+			Journal_DPrintf( self->debug, "restart from checkpoint mode -> loading checkpointed "
+				"nodal values as initial conditions, ignoring ics specified via XML/constructor\n" );
+			 
+#ifdef READ_HDF5
+			Stg_asprintf( &filename, "%s%s.%.5u.h5", inputPathString, self->name, context->restartTimestep );
+         if (!context->interpolateRestart)
+            FeVariable_ReadFromFile( self, filename );
+         else {
+            char * meshFilename = NULL;
+            if (!strcmp(self->feMesh->generator->type, CartesianGenerator_Type))
+               Stg_asprintf( &meshFilename, "%sMesh.%s.%.5u.h5", inputPathString, self->feMesh->name, context->restartTimestep );
+            else
+               Stg_asprintf( &meshFilename, "%sMesh.%s.%.5u.h5", inputPathString, ((C0Generator*)(self->feMesh->generator))->elMesh->name, context->restartTimestep );
+            FeVariable_InterpolateFromFile( self, context, filename, meshFilename );
+            Memory_Free( meshFilename );
+         }
+			
+#else
+			Stg_asprintf( &filename, "%s%s.%.5u.dat", inputPathString, self->name, context->restartTimestep );
+			FeVariable_ReadFromFile( self, filename );
+#endif
+
+			Memory_Free( filename );
+			
+		}
+	}
+	Memory_Free( inputPathString );
+	Stream_UnIndent( self->debug );
+
+	if( context ) {
+   		/** also include check to see if this fevariable should be checkpointed, just incase it didn't go through the 
+		fieldvariable construct phase */ 
+		feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"fieldVariablesToCheckpoint" );
+		if ( NULL == feVarsList  ) {
+		feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"FieldVariablesToCheckpoint" );
+		}
+		if (feVarsList != NULL ) {
+			Index                    listLength = Dictionary_Entry_Value_GetCount( feVarsList );
+			Index                    var_I = 0;
+			Dictionary_Entry_Value*  feVarDictValue = NULL;
+			char*                    fieldVariableName;
+   
+			for ( var_I = 0; var_I < listLength; var_I++  ) {
+				feVarDictValue = Dictionary_Entry_Value_GetElement( feVarsList, var_I );
+				fieldVariableName = Dictionary_Entry_Value_AsString( feVarDictValue ); 
+				if ( 0 == strcmp( self->name, fieldVariableName ) ) {
+					self->isCheckpointedAndReloaded = True;
+					break;
+				}
+			}
+		}
+
+		feVarsList = NULL;
+		/** also include check to see if this fevariable should be saved for analysis purposes */ 
+		feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"fieldVariablesToSave" );
+		if ( NULL == feVarsList  ) {
+			feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"FieldVariablesToSave" );	
+		}
+		if (feVarsList != NULL ) {
+			Index                    listLength = Dictionary_Entry_Value_GetCount( feVarsList );
+			Index                    var_I = 0;
+			Dictionary_Entry_Value*  feVarDictValue = NULL;
+			char*                    fieldVariableName;
+   
+			for ( var_I = 0; var_I < listLength; var_I++  ) {
+				feVarDictValue = Dictionary_Entry_Value_GetElement( feVarsList, var_I );
+				fieldVariableName = Dictionary_Entry_Value_AsString( feVarDictValue ); 
+				if ( 0 == strcmp( self->name, fieldVariableName ) ) {
+					self->isSavedData = True;
+					break;
+				}
+			}
+		}
+	}
+   
+	if ( self->bcs ) {
+		Stg_Component_Initialise( self->bcs, context, False );
+		Journal_DPrintf( self->debug, "applying the B.C.s for this Variable.\n" ); 
+		VariableCondition_Apply( self->bcs, context );
+	}
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void FeVariable_ApplyBCs( void* variable, void* data ) {
+	FeVariable* self = (FeVariable*)variable;
+
+        /** This is an unpleasant hack; we really need to reevaluate our BC code. */
+	if( self->dynamicBCs[0] ) {
+		VariableCondition_Apply( self->dynamicBCs[0], data );
+	}
+	if( self->dynamicBCs[1] ) {
+		VariableCondition_Apply( self->dynamicBCs[1], data );
+	}
+	if( self->dynamicBCs[2] ) {
+		VariableCondition_Apply( self->dynamicBCs[2], data );
+	}
+	if ( self->bcs ) {
+		Journal_DPrintf( self->debug, "In %s- for %s:\n", __func__, self->name );
+		Journal_DPrintf( self->debug, "applying the B.C.s for this Variable.\n" ); 
+		VariableCondition_Apply( self->bcs, data );
+	}
+}
+
+Bool FeVariable_IsBC( void* variable, int node, int dof ) {
+	FeVariable* self = (FeVariable*)variable;
+
+	assert( self );
+	if( self->dynamicBCs[0] && 
+	    self->dynamicBCs[0]->var == DofLayout_GetVariable( self->dofLayout, node, dof ) && 
+	    IMap_Has( self->dynamicBCs[0]->vcMap, node ) )
+	{
+		return True;
+	}
+
+	if( self->dynamicBCs[1] && 
+	    self->dynamicBCs[1]->var == DofLayout_GetVariable( self->dofLayout, node, dof ) && 
+	    IMap_Has( self->dynamicBCs[1]->vcMap, node ) )
+	{
+		return True;
+	}
+
+	if( self->dynamicBCs[2] && 
+	    self->dynamicBCs[2]->var == DofLayout_GetVariable( self->dofLayout, node, dof ) && 
+	    IMap_Has( self->dynamicBCs[2]->vcMap, node ) )
+	{
+		return True;
+	}
+
+	if( self->bcs && 
+	    VariableCondition_IsCondition( self->bcs, node, self->dofLayout->varIndices[node][dof] ) )
+	{
+		return True;
+	}
+
+	return False;
+}
+
+
+void _FeVariable_Execute( void* variable, void* data ) {
+}
+
+void _FeVariable_Destroy( void* variable, void* data ) {
+	FeVariable* self = (FeVariable*)variable;
+
+	Memory_Free( self->GNx );
+
+	Stream_IndentBranch( StgFEM_Debug );
+
+	if( self->eqNum && ( NULL == self->templateFeVariable ) ) {
+		_Stg_Component_Delete( self->eqNum );
+      self->eqNum = NULL;
+	}
+	/** feMesh bc and doflayout are purposely not deleted */
+
+   if( self->inc == NULL ) {
+      NewClass_Delete( self->inc );
+      self->inc = NULL;
+   }
+
+	_FieldVariable_Destroy( self, data );
+}
+
+void FeVariable_PrintLocalDiscreteValues( void* variable, Stream* stream ) {
+	FeVariable* self = (FeVariable*)variable;
+
+	Journal_Printf( stream, "In %s: for FeVariable \"%s\":\n", __func__, self->name );
+
+	_FeVariable_PrintLocalOrDomainValues( variable, FeMesh_GetNodeLocalSize( self->feMesh ), stream );
+}
+
+unsigned _FeVariable_ClosestNode( FeVariable* self, double* crd ) {
+	assert( self );
+	return Mesh_NearestVertex( self->feMesh, crd );
+}
+
+
+InterpolationResult _FeVariable_InterpolateValueAt( void* variable, double* globalCoord, double* value ) {
+	FeVariable*				self = (FeVariable*)variable;
+	Element_DomainIndex	elementCoordIn = (unsigned)-1;
+	Coord						elLocalCoord={0,0,0};
+	InterpolationResult	retValue;
+
+
+	retValue = FeVariable_GetElementLocalCoordAtGlobalCoord( self, globalCoord, elLocalCoord, &elementCoordIn );
+	
+	if ( retValue == LOCAL ) {
+		/** Now interpolate the value at that coordinate, using shape functions */
+		self->_interpolateWithinElement( self, elementCoordIn, elLocalCoord, value );
+	}
+	else if ( retValue == SHADOW ) {
+		if ( False == self->shadowValuesSynchronised ) {
+			Stream* warningStr = Journal_Register( Error_Type, (Name)self->type  );
+			Journal_Printf( warningStr, "Warning - in %s: user asking to interpolate a value at "
+				"coord (%g,%g,%g), which is in shadow space, but "
+				"FeVariable_SyncShadowValues() hasn't been called yet.\n", 
+				__func__, globalCoord[0], globalCoord[1], globalCoord[2] );
+			return retValue;		
+		}
+		/** Now interpolate the value at that coordinate, using shape functions */
+		self->_interpolateWithinElement( self, elementCoordIn, elLocalCoord, value );
+	}
+	
+	return retValue;
+}
+
+
+double _FeVariable_GetMinGlobalFieldMagnitude( void* feVariable ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+	FeMesh*		feMesh = self->feMesh;
+	int		node_lI=0;
+	int		nodeLocalCount = FeMesh_GetNodeLocalSize( feMesh );
+	double		min = 0;
+	double		globalMin = 0;
+	double		currValue;
+
+	min = FeVariable_GetScalarAtNode( self, 0 );
+	
+	/** Find upper and lower bounds on this processor */
+	for ( node_lI = 0 ; node_lI < nodeLocalCount ; node_lI++ ) {
+		currValue = FeVariable_GetScalarAtNode( self, node_lI );
+		if ( currValue < min ) {
+			min = currValue;
+		}	
+	}
+
+	/** Find upper and lower bounds on all processors */
+	MPI_Allreduce( &min, &globalMin, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
+	return globalMin;
+}
+
+
+double _FeVariable_GetMaxGlobalFieldMagnitude( void* feVariable ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+	int		node_lI=0;
+	int		nodeLocalCount = FeMesh_GetNodeLocalSize( self->feMesh );
+	double		max = 0;
+	double		globalMax = 0;
+	double		currValue;
+
+	max = FeVariable_GetScalarAtNode( self, 0 );
+	
+	/** Find upper and lower bounds on this processor */
+	for ( node_lI = 0 ; node_lI < nodeLocalCount ; node_lI++ ) {
+		currValue = FeVariable_GetScalarAtNode( self, node_lI );
+		if ( currValue > max ) {
+			max = currValue;
+		}	
+	}
+
+	/** Find upper and lower bounds on all processors */
+	MPI_Allreduce( &max, &globalMax, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD );
+	return globalMax;
+}
+
+void _FeVariable_GetMinAndMaxLocalCoords( void* feVariable, double* min, double* max ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+
+	assert( self && Stg_CheckType( self, FeVariable ) );
+
+	Mesh_GetLocalCoordRange( self->feMesh, min, max );
+}
+
+
+void _FeVariable_GetMinAndMaxGlobalCoords( void* feVariable, double* min, double* max ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+
+	assert( self && Stg_CheckType( self, FeVariable ) );
+
+	Mesh_GetGlobalCoordRange( self->feMesh, min, max );
+}
+
+double FeVariable_GetScalarAtNode( void* feVariable, Node_LocalIndex lNode_I ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+	Dof_Index	dofCountThisNode = 0;
+	Dof_Index	nodeLocalDof_I = 0;
+	double      value[ MAX_FIELD_COMPONENTS ];
+	
+	/**
+	if( self->type != OperatorFeVariable_Type && self->dofLayout )
+		dofCountThisNode = self->dofLayout->dofCounts[lNode_I];
+	else {
+	*/
+	dofCountThisNode = self->fieldComponentCount;
+	/**
+	}
+	*/
+
+	FeVariable_GetValueAtNode( self, lNode_I, value );
+
+	if ( dofCountThisNode > 1) {
+		double		magnitude=0;
+		for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
+			magnitude += value[ nodeLocalDof_I ] * value[ nodeLocalDof_I ];
+		}
+		return sqrt( magnitude );
+	}
+	else 
+		return value[0];
+
+}	
+
+
+void _FeVariable_GetValueAtNode( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+	Variable*	currVariable = NULL;
+	Dof_Index	dofCountThisNode = 0;
+	Dof_Index	nodeLocalDof_I = 0;
+
+	dofCountThisNode = self->dofLayout->dofCounts[dNode_I];
+	
+	for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
+		currVariable = DofLayout_GetVariable( self->dofLayout, dNode_I, nodeLocalDof_I );
+		value[ nodeLocalDof_I ] = Variable_GetValueDouble( currVariable, dNode_I );
+	}
+}
+
+/** Finds the value of the field at the node and broadcasts it to the rest of the processors */
+void FeVariable_GetValueAtNodeGlobal( void* feVariable, Node_GlobalIndex gNode_I, double* value ) {
+	FeVariable*        self         = (FeVariable*) feVariable;
+	FeMesh*            mesh         = self->feMesh;
+	Element_LocalIndex lNode_I;
+	int                rootRankL     = 0;
+	int                rootRankG     = 0;
+	MPI_Comm           comm         = self->communicator;
+	
+	/** Find Local Index */
+	if ( Mesh_GlobalToDomain( mesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
+		/** If node is on local processor, then get value of field */
+		FeVariable_GetValueAtNode( self, lNode_I, value );
+		MPI_Comm_rank( comm, (int*)&rootRankL );
+	}
+	
+	/** Send to other processors */
+	MPI_Allreduce( &rootRankL, &rootRankG, 1, MPI_INT, MPI_MAX, comm );
+	MPI_Bcast( value, self->fieldComponentCount, MPI_DOUBLE, rootRankG, comm );
+}
+
+/** Finds the coordinate of the node and broadcasts it to the rest of the processors */
+void FeVariable_GetCoordAtNodeGlobal( void* feVariable, Node_GlobalIndex gNode_I, double* coord ) {
+	FeVariable*        self         = (FeVariable*) feVariable;
+	FeMesh*            mesh         = self->feMesh;
+	Element_LocalIndex lNode_I;
+	int                rootRankL     = 0;
+	int                rootRankG     = 0;
+	MPI_Comm           comm         = self->communicator;
+
+	/** Find Local Index */
+	if ( Mesh_GlobalToDomain( mesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
+		/** If node is on local processor, then get value of field */
+		memcpy( coord, Mesh_GetVertex( mesh, lNode_I ), self->dim * sizeof(double) );
+		MPI_Comm_rank( comm, (int*)&rootRankL );
+	}
+	
+	/** Send to other processors */
+	MPI_Allreduce( &rootRankL, &rootRankG, 1, MPI_INT, MPI_MAX, comm );
+	MPI_Bcast( coord, self->dim, MPI_DOUBLE, rootRankG, comm );
+}
+
+
+void FeVariable_ZeroField( void* feVariable ) {
+	FeVariable* self = (FeVariable*) feVariable;
+	double*     values =  Memory_Alloc_Array( double, self->fieldComponentCount, "tempValues" );
+	Index       lNode_I, lNodeCount;
+
+	lNodeCount = FeMesh_GetNodeLocalSize( self->feMesh );
+
+	memset( values, 0, self->fieldComponentCount * sizeof(double) );
+
+	for( lNode_I = 0 ; lNode_I < lNodeCount; lNode_I++ ) {
+		FeVariable_SetValueAtNode( self, lNode_I, values );
+	}
+
+	Memory_Free( values );
+}
+	
+/** --- Public Functions --- */
+
+InterpolationResult FeVariable_GetElementLocalCoordAtGlobalCoord( void* feVariable, double* globalCoord, double* elLocalCoord,
+		Element_DomainIndex* elementCoordInPtr )
+{
+	FeVariable*		self = (FeVariable*)feVariable;
+	InterpolationResult	retValue;
+	unsigned		elInd;
+
+	/** locate which mesh element given coord is in : use inclusive upper boundaries to save
+	   the need to use shadow space if possible */
+	if( !Mesh_SearchElements( self->feMesh, globalCoord, &elInd ) ) {
+		Bool			outsideGlobal = False;
+		double			min[3], max[3];
+		Dimension_Index		dim_I=0;
+
+		FieldVariable_GetMinAndMaxGlobalCoords( self, min, max );
+		for ( dim_I = 0; dim_I < self->dim; dim_I++ ) {
+			if ( ( globalCoord[dim_I] < min[dim_I] ) || (globalCoord[dim_I] > max[dim_I] ) ) {
+				outsideGlobal = True;
+			}
+		}
+
+		if ( outsideGlobal == True ) {
+			return OUTSIDE_GLOBAL;
+		}
+		else {
+			return OTHER_PROC;
+		}
+	}
+	else /** We found the coord is within a local or shadow element */ {
+		ElementType*		elementType = NULL;
+
+		*elementCoordInPtr = elInd;
+		if ( elInd < FeMesh_GetElementLocalSize( self->feMesh ) ) {
+			retValue = LOCAL;
+		}
+		else {
+			retValue = SHADOW;
+		}
+
+		/** convert global coordinate to local co-ordinates of element the coord is in */
+		elementType = FeMesh_GetElementType( self->feMesh, (*elementCoordInPtr) );
+		ElementType_ConvertGlobalCoordToElLocal( elementType, self->feMesh, *elementCoordInPtr, 
+							 globalCoord, elLocalCoord );
+	}
+
+	return retValue;
+}
+
+
+void FeVariable_SetValueAtNode( void* feVariable, Node_DomainIndex dNode_I, double* componentValues ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+	Dof_Index	dofCountThisNode = 0;
+	Dof_Index	nodeLocalDof_I = 0;
+
+	dofCountThisNode = self->dofLayout->dofCounts[dNode_I];
+	
+	for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
+		DofLayout_SetValueDouble( (self)->dofLayout, dNode_I, nodeLocalDof_I, componentValues[nodeLocalDof_I] );
+	}
+}
+
+
+void FeVariable_PrintLocalDiscreteValues_2dBox( void* variable, Stream* stream ) {
+	FeVariable*		self = (FeVariable*)variable;
+	Node_LocalIndex		node_lI=0;
+	Index			x_I, y_I;
+	Index			ii;
+	Dof_Index		dof_I=0;
+	Dof_Index		currNodeNumDofs=0;
+	Index			nx = 0;
+	Index			ny = 0;
+	double			dx = 0;
+	double			dy = 0;
+	DofLayout*		dofLayout = self->dofLayout;
+	Stream*			eStream = Journal_Register( Error_Type, (Name)self->type  );
+	Index			minLocalNodeX;
+	Index			minLocalNodeY;
+	Index			maxLocalNodeX;
+	Index			maxLocalNodeY;
+	Grid*			vertGrid;
+	unsigned		inds[2];
+	unsigned		vertInd;
+	double*			verts[2];
+	unsigned		*localOrigin, *localRange;
+	double			min[2], max[2];
+
+	if( ExtensionManager_GetHandle( self->feMesh->info, (Name)"vertexGrid" ) == (unsigned)-1 || 
+	    Mesh_GetDimSize( self->feMesh ) != 2  )
+	  {
+		Journal_Printf( eStream, "Warning: %s called on variable \"%s\", but this isn't stored on a "
+			"regular 2D mesh - so just returning.\n", __func__, self->name );
+		return;
+	}
+
+	vertGrid = *(Grid**)ExtensionManager_Get( self->feMesh->info, self->feMesh, 
+					      ExtensionManager_GetHandle( self->feMesh->info, (Name)"vertexGrid" ) );
+	localOrigin = (unsigned* )ExtensionManager_Get( self->feMesh->info, self->feMesh, 
+						       ExtensionManager_GetHandle( self->feMesh->info, (Name)"localOrigin" ) );
+	localRange = (unsigned* )ExtensionManager_Get( self->feMesh->info, self->feMesh, 
+						      ExtensionManager_GetHandle( self->feMesh->info, (Name)"localRange" )  );
+
+	memcpy( inds, localOrigin, Mesh_GetDimSize( self->feMesh ) * sizeof(unsigned) );
+	insist( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, Grid_Project( vertGrid, inds ), &vertInd ), == True );
+	verts[0] = Mesh_GetVertex( self->feMesh, vertInd );
+	inds[0]++;
+	inds[1]++;
+	insist( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, Grid_Project( vertGrid, inds ), &vertInd ), == True );
+	verts[1] = Mesh_GetVertex( self->feMesh, vertInd );
+	
+	nx = vertGrid->sizes[0];
+	ny = vertGrid->sizes[1];
+	dx = verts[1][0] - verts[0][0];
+	dy = verts[1][1] - verts[0][1];
+
+
+
+	minLocalNodeX = localOrigin[0];
+	minLocalNodeY = localOrigin[1];
+	maxLocalNodeX = minLocalNodeX + localRange[0] + 1;
+	maxLocalNodeY = minLocalNodeY + localRange[1] + 1;
+
+	Mesh_GetGlobalCoordRange( self->feMesh, min, max );
+
+	Journal_Printf( stream, "display of Values in 2D box X:{%5.2f-%5.2f}, Y:{%5.2f-%5.2f}\n",
+		min[I_AXIS], max[I_AXIS],
+		min[J_AXIS], max[J_AXIS] );
+	Journal_Printf( stream, "\twith %d elements in X (dx=%5.2f) and %d elements in Y (dy=%5.2f)\n\n",
+		nx-1, dx, ny-1, dy );
+
+	/**Header*/
+	for (ii=0;ii<10;ii++) Journal_Printf( stream, " " );
+	for ( x_I=0; x_I < nx; x_I++ ) {
+		Journal_Printf( stream, "|  xNode=%3d   ", x_I );
+	}
+	Journal_Printf( stream, "|\n", x_I );
+
+	for ( y_I= ny-1; y_I != (unsigned)-1; y_I-- ) {
+		/**Blocks */
+		for (ii=0;ii<10;ii++) Journal_Printf( stream, " " );
+		for ( x_I=0; x_I < nx; x_I++ ) {
+			if (y_I == ny-1) {
+				Journal_Printf( stream, "-" );
+			}
+			else if (x_I==0) {
+				Journal_Printf( stream, "|" );
+			}	
+			else {
+				Journal_Printf( stream, "*" );
+			}	
+			for (ii=0;ii<14;ii++) Journal_Printf( stream, "-" );
+		}
+		if (y_I == ny-1) {
+			Journal_Printf( stream, "-\n" );
+		}	
+		else {
+			Journal_Printf( stream, "|\n" );
+		}	
+
+
+		/** Now a row of y values */
+		Journal_Printf( stream, "yNode=%3d |", y_I );
+		for ( x_I=0; x_I < nx; x_I++ ) {
+		
+			if ( ( y_I >= minLocalNodeY ) && ( y_I < maxLocalNodeY )
+				&& ( x_I >= minLocalNodeX ) && ( x_I < maxLocalNodeX ) ) {
+
+				inds[0] = x_I;
+				inds[1] = y_I;
+				node_lI = RegularMeshUtils_Node_3DTo1D( self->feMesh, inds );
+				insist( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, node_lI, &node_lI ), == True );
+				currNodeNumDofs = dofLayout->dofCounts[node_lI];
+
+				if ( currNodeNumDofs == 1 ) {
+					Journal_Printf( stream, "   " );
+				}
+				Journal_Printf( stream, "(" );
+				for ( dof_I=0; dof_I < currNodeNumDofs - 1 ; dof_I++ ) {
+					Journal_Printf( stream, "%5.2f,", DofLayout_GetValueDouble( dofLayout, node_lI, dof_I ) );
+				}
+				Journal_Printf( stream, "%5.2f )", DofLayout_GetValueDouble( dofLayout, node_lI, dof_I ) );
+				
+				if ( currNodeNumDofs == 1 ) {
+					Journal_Printf( stream, "   " );
+				}
+				Journal_Printf( stream, "|" );
+			}
+			else {
+				for (ii=0;ii<14;ii++) Journal_Printf( stream, "X" );
+				Journal_Printf( stream, "|" );
+			}
+		}
+		Journal_Printf( stream, "\n" );
+	}
+	
+	/**Blocks */
+	for (ii=0;ii<10;ii++) Journal_Printf( stream, " " );
+	for ( x_I=0; x_I < nx; x_I++ ) {
+		Journal_Printf( stream, "-" );
+		for (ii=0;ii<14;ii++) Journal_Printf( stream, "-" );
+	}
+	Journal_Printf( stream, "-\n", x_I );
+}
+
+
+Bool FeVariable_InterpolateDerivativesAt( void* variable, double* globalCoord, double* value ) {
+	FeVariable*	        self                 = (FeVariable*)variable;
+	Element_DomainIndex	elementCoordIn       = (unsigned)-1;
+	Coord               elLocalCoord         = {0,0,0};
+
+	/** Need a special rule for points on this processor's boundary: instead of the normal
+	   rule, "round" the point to lie inside the local space, rather than shadow */
+	
+	/** locate which mesh element given coord is in : use inclusive upper boundaries to save
+		the need to use shadow space if possible */
+	if ( !Mesh_Algorithms_SearchElements( self->feMesh->algorithms, globalCoord, 
+					     &elementCoordIn ) )
+	{
+		/** If coord isn't inside domain elements list, bail out */
+		return False;
+	}	
+	else /** We found the coord is within a local or shadow element */ {
+		if ( elementCoordIn >= FeMesh_GetElementLocalSize( self->feMesh ) ) {
+			if ( False == self->shadowValuesSynchronised ) {
+				Stream* warningStr = Journal_Register( Error_Type, (Name)self->type  );
+				Journal_Printf( warningStr, "Warning - in %s: user asking to interpolate derivatives "
+					"to coord (%g,%g,%g), which is in shadow space, but "
+					"FeVariable_SyncShadowValues() hasn't been called yet.\n", 
+					__func__, globalCoord[0], globalCoord[1], globalCoord[2] );
+				return False;	
+			}
+		}
+
+		/** convert global coordinate to local co-ordinates of element the coord is in */
+		FeMesh_CoordGlobalToLocal( self->feMesh, elementCoordIn, globalCoord, elLocalCoord );
+
+		/** Now interpolate the value at that coordinate, using shape functions */
+		FeVariable_InterpolateDerivativesToElLocalCoord( self, elementCoordIn, elLocalCoord, value );
+	}	
+	
+	return True;
+}
+
+void FeVariable_InterpolateDerivativesToElLocalCoord( void* _feVariable, Element_DomainIndex lElement_I, Coord elLocalCoord, double* value ) {
+	FeVariable*			self = (FeVariable*) _feVariable;
+	ElementType*		elementType = FeMesh_GetElementType( self->feMesh, lElement_I );
+	double**				GNx; 
+	double				detJac;
+	Dimension_Index	dim = self->dim;
+
+	GNx = self->GNx;
+
+	/** Evaluate Global Shape Functions */
+	ElementType_ShapeFunctionsGlobalDerivs( 
+			elementType,
+			self->feMesh, lElement_I,
+			elLocalCoord, dim, &detJac, GNx );
+
+	/** Do Interpolation */
+	FeVariable_InterpolateDerivatives_WithGNx( self, lElement_I, GNx, value );
+}
+
+void FeVariable_InterpolateDerivatives_WithGNx( void* _feVariable, Element_LocalIndex lElement_I, double** GNx, double* value ) {
+	FeVariable*             self = (FeVariable*) _feVariable;
+	Node_ElementLocalIndex  elLocalNode_I;
+	Node_LocalIndex         lNode_I;
+	Dof_Index               dof_I;
+	Dof_Index               dofCount;
+	/* Variable*               dofVariable; */
+	double                  nodeValue;
+	unsigned						nInc, *inc;
+	Dimension_Index         dim = self->dim;
+	double*						tmpVal;
+
+	/** Gets number of degrees of freedom - assuming it is the same throughout the mesh */
+	dofCount = self->dofLayout->dofCounts[0];
+
+	/** Initialise */
+	memset( value, 0, sizeof( double ) * dofCount * dim );
+	tmpVal = (double*)malloc( dim*dofCount*sizeof(double) );
+
+	FeMesh_GetElementNodes( self->feMesh, lElement_I, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = (unsigned*)IArray_GetPtr( self->inc );
+
+		/** Interpolate derivative from nodes */
+        for ( elLocalNode_I = 0 ; elLocalNode_I < nInc ; elLocalNode_I++) {
+
+                lNode_I      = inc[ elLocalNode_I ];
+                FeVariable_GetValueAtNode( self, lNode_I, tmpVal );
+                /*dofVariable  = DofLayout_GetVariable( self->dofLayout, lNode_I, dof_I );*/
+                /*nodeValue    = Variable_GetValueDouble( dofVariable, lNode_I );*/
+
+                for ( dof_I = 0 ; dof_I < dofCount ; dof_I++ ) {
+                        nodeValue = tmpVal[dof_I];
+			
+			value[dof_I*dim + 0] += GNx[0][elLocalNode_I] * nodeValue;
+			value[dof_I*dim + 1] += GNx[1][elLocalNode_I] * nodeValue;
+			if( dim == 3 ) 
+				value[dof_I*dim + 2] += GNx[2][elLocalNode_I] * nodeValue;	
+		}
+	}
+
+        free( tmpVal );
+}
+
+void FeVariable_InterpolateValue_WithNi( void* _feVariable, Element_LocalIndex lElement_I, double* Ni, double* value ) {
+	FeVariable*             self        = (FeVariable*) _feVariable;
+	Node_ElementLocalIndex  elLocalNode_I;
+	Node_LocalIndex         lNode_I;
+	Dof_Index               dof_I;
+	Dof_Index               dofCount;
+	Variable*               dofVariable;
+	double                  nodeValue;
+	unsigned		nInc, *inc;
+
+	/** Gets number of degrees of freedom - assuming it is the same throughout the mesh */
+	dofCount = self->dofLayout->dofCounts[0];
+
+	/** Initialise */
+	memset( value, 0, sizeof( double ) * dofCount );
+
+	FeMesh_GetElementNodes( self->feMesh, lElement_I, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = (unsigned*)IArray_GetPtr( self->inc );
+
+	for ( dof_I = 0 ; dof_I < dofCount ; dof_I++ ) {
+		/** Interpolate derivative from nodes */
+		for ( elLocalNode_I = 0 ; elLocalNode_I < nInc ; elLocalNode_I++) {
+			lNode_I      = inc[ elLocalNode_I ];
+			dofVariable  = DofLayout_GetVariable( self->dofLayout, lNode_I, dof_I );
+			nodeValue    = Variable_GetValueDouble( dofVariable, lNode_I );
+
+			value[dof_I] += Ni[elLocalNode_I] * nodeValue;
+		}
+	}
+}
+
+void FeVariable_GetMinimumSeparation( void* feVariable, double* minSeparationPtr, double minSeparationEachDim[3] ) {
+	FeVariable*	self = (FeVariable*)feVariable;
+
+	assert( self && Stg_CheckType( self, FeVariable ) );
+
+	Mesh_GetMinimumSeparation( self->feMesh, minSeparationPtr, minSeparationEachDim );
+}	
+
+
+void _FeVariable_SyncShadowValues( void* feVariable ) {
+	FeVariable*		self = (FeVariable*)feVariable;
+	DofLayout*		dofLayout;
+	Sync*			vertSync;
+	unsigned		var_i;
+
+	assert( self );
+
+	/** Shortcuts. */
+	dofLayout = self->dofLayout;
+	if( !dofLayout ) {
+		self->shadowValuesSynchronised = True;
+		return;
+	}
+
+	/** Create a distributed array based on the mesh's vertices. */
+	vertSync = Mesh_GetSync( self->feMesh, MT_VERTEX );
+
+	/**
+	** For each variable in the dof layout, we need to create a distributed array and update
+	** shadow values.
+	*/
+
+	for( var_i = 0; var_i < dofLayout->_totalVarCount; var_i++ ) {
+		unsigned	varInd;
+		Variable*	var;
+		unsigned	field_i;
+
+		/** Get the variable. */
+		varInd = dofLayout->_varIndicesMapping[var_i];
+		var = Variable_Register_GetByIndex( dofLayout->_variableRegister, varInd );
+
+		/** Each field of the variable will need to be handled individually. */
+		for( field_i = 0; field_i < var->offsetCount; field_i++ ) {
+			unsigned	offs, size;
+			Stg_Byte	*arrayStart, *arrayEnd;
+
+			offs = var->offsets[field_i];
+			size = var->dataSizes[field_i];
+
+			arrayStart = (Stg_Byte*)var->arrayPtr + offs;
+			arrayEnd = arrayStart + var->structSize * FeMesh_GetNodeLocalSize( self->feMesh );
+			Sync_SyncArray( vertSync, arrayStart, var->structSize, 
+					arrayEnd, var->structSize, 
+					size );
+		}
+	}
+
+	self->shadowValuesSynchronised = True;
+
+#if 0
+	Neighbour_Index			nbr_I = 0;
+	Node_Index			node_stI = 0;
+	Node_DomainIndex		node_dI = 0;
+	Node_LocalIndex			node_lI = 0;
+	Dof_Index			nodalDof_I = 0;
+	Processor_Index			nbrRank = 0;
+	Index*				incomingDofTotals = NULL;			
+	double**			incomingDofValues = NULL;
+	MPI_Request**			incomingDofValRequests = NULL;
+	Node_Index			myShadowNodesOnThisNbrCount = 0;
+	Dof_Index		incomingDof_I;
+	Index*			outgoingDofTotals = NULL;
+	double**		outgoingDofValues = NULL;
+	MPI_Request**		outgoingDofValRequests = NULL;
+	Node_Index		nbrShadowNodesOnMeCount = 0;
+	Dof_Index		outgoingDof_I;
+	MPI_Status			status;
+	int				incomingDofValueSetsYetToReceive;
+	Bool*				incomingDofValueSetsReceived;
+
+	Journal_DPrintf( self->debug, "In %s- for feVariable \"%s\":\n", __func__, self->name );
+	Stream_Indent( self->debug );
+
+	if ( ( 1 == mesh->layout->decomp->procsInUse ) || ( 0 == mesh->layout->decomp->shadowDepth ) ) {
+		Journal_DPrintf( self->debug, "No shadow nodes: nothing to do - returning.\n" );
+		Stream_UnIndent( self->debug );
+		return;
+	}
+
+	self->shadowValuesSynchronised = True;
+
+	/** allocate memory for incoming info */
+	incomingDofTotals = Memory_Alloc_Array( Index, mesh->procNbrInfo->procNbrCnt, "incomingDofTotals" );
+	incomingDofValues = Memory_Alloc_Array( double*, mesh->procNbrInfo->procNbrCnt, "incomingDofValues" );
+	incomingDofValRequests = Memory_Alloc_Array( MPI_Request*, mesh->procNbrInfo->procNbrCnt, "incomingDofValRequests" );
+	incomingDofValueSetsReceived = Memory_Alloc_Array( Bool, mesh->procNbrInfo->procNbrCnt, "incomingDofValueSets" );
+	incomingDofValueSetsYetToReceive = 0;
+	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
+		myShadowNodesOnThisNbrCount = mesh->nodeShadowInfo->procShadowCnt[nbr_I];
+		incomingDofTotals[nbr_I] = 0;
+		incomingDofValues[nbr_I] = NULL;
+		incomingDofValRequests[nbr_I] = NULL;
+		incomingDofValueSetsReceived[nbr_I] = False;
+
+		if ( myShadowNodesOnThisNbrCount > 0 ) {
+			for( node_stI = 0; node_stI < myShadowNodesOnThisNbrCount; node_stI++ ) {
+				node_dI = mesh->nodeShadowInfo->procShadowTbl[nbr_I][node_stI];
+				incomingDofTotals[nbr_I] += self->dofLayout->dofCounts[node_dI];
+			}	
+			incomingDofValues[nbr_I] = Memory_Alloc_Array( double, incomingDofTotals[nbr_I],
+				"incomingDofValues[]" );
+			incomingDofValRequests[nbr_I] = Memory_Alloc( MPI_Request, "incomingDofValRequest" );	
+			incomingDofValueSetsYetToReceive++;
+		}
+	}
+	/** allocate memory for outgoing info */
+	outgoingDofTotals = Memory_Alloc_Array( Index, mesh->procNbrInfo->procNbrCnt, "outgoingDofTotals" );
+	outgoingDofValues = Memory_Alloc_Array( double*, mesh->procNbrInfo->procNbrCnt, "outgoingDofValues" );
+	outgoingDofValRequests = Memory_Alloc_Array( MPI_Request*, mesh->procNbrInfo->procNbrCnt, "outgoingDofValRequests" );
+	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
+		nbrShadowNodesOnMeCount = mesh->nodeShadowInfo->procShadowedCnt[nbr_I];
+		outgoingDofTotals[nbr_I] = 0;
+		outgoingDofValues[nbr_I] = NULL;
+		outgoingDofValRequests[nbr_I] = NULL;
+
+		if ( nbrShadowNodesOnMeCount > 0 ) {
+			for( node_stI = 0; node_stI < nbrShadowNodesOnMeCount; node_stI++ ) {
+				node_lI = mesh->nodeShadowInfo->procShadowedTbl[nbr_I][node_stI];
+				outgoingDofTotals[nbr_I] += self->dofLayout->dofCounts[node_lI];
+			}	
+			outgoingDofValues[nbr_I] = Memory_Alloc_Array( double, outgoingDofTotals[nbr_I],
+				"outgoingDofValues[]" );
+			outgoingDofValRequests[nbr_I] = Memory_Alloc( MPI_Request, "outgoingDofValRequest" );	
+		}
+	}	
+
+	Journal_DPrintfL( self->debug, 2, "Starting non-blocking recv's of incoming values\n" );
+	Stream_Indent( self->debug );
+	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
+		myShadowNodesOnThisNbrCount = mesh->nodeShadowInfo->procShadowCnt[nbr_I];
+		if ( myShadowNodesOnThisNbrCount > 0 ) {
+			nbrRank = mesh->procNbrInfo->procNbrTbl[nbr_I];
+			Journal_DPrintfL( self->debug, 2, "Start recv from proc %u - %u values\n", nbrRank, incomingDofTotals[nbr_I] );
+			MPI_Irecv( incomingDofValues[nbr_I], incomingDofTotals[nbr_I], MPI_DOUBLE, nbrRank,
+				DOF_VALUES_TAG, self->communicator, incomingDofValRequests[nbr_I] );
+		}
+	}
+	Stream_UnIndent( self->debug );
+
+	Journal_DPrintfL( self->debug, 2, "Non-blocking send out required shadow values to neighbours\n" );
+	Stream_Indent( self->debug );
+	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
+		if ( mesh->nodeShadowInfo->procShadowedCnt[nbr_I] > 0 ) {
+			nbrRank = mesh->procNbrInfo->procNbrTbl[nbr_I];
+
+			outgoingDof_I = 0;
+			for( node_stI = 0; node_stI < mesh->nodeShadowInfo->procShadowedCnt[nbr_I]; node_stI++ ) {
+				node_lI = mesh->nodeShadowInfo->procShadowedTbl[nbr_I][node_stI];
+				for ( nodalDof_I=0; nodalDof_I < self->dofLayout->dofCounts[node_lI]; nodalDof_I++ ) {
+					outgoingDofValues[nbr_I][outgoingDof_I] =
+						DofLayout_GetValueDouble( self->dofLayout, node_lI, nodalDof_I );
+					outgoingDof_I++;
+				}
+			}
+			Journal_DPrintfL( self->debug, 2, "Start send to proc %u - %u values\n", nbrRank, outgoingDofTotals[nbr_I] );
+			MPI_Isend( outgoingDofValues[nbr_I], outgoingDofTotals[nbr_I], MPI_DOUBLE, nbrRank,
+				DOF_VALUES_TAG, self->communicator, outgoingDofValRequests[nbr_I] );
+		}
+	}
+	Stream_UnIndent( self->debug );
+
+	Journal_DPrintfL( self->debug, 2, "Receiving and updating shadow values I need from neighbours:\n" );
+	Stream_Indent( self->debug );
+	while ( incomingDofValueSetsYetToReceive > 0 ) {
+		int	testFlag = 0;
+
+		for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
+
+			if ( ( mesh->nodeShadowInfo->procShadowCnt[nbr_I] > 0 )
+				&& ( False == incomingDofValueSetsReceived[nbr_I] ) )
+			{
+				MPI_Test( incomingDofValRequests[nbr_I], &testFlag, &status );
+				if ( False == testFlag ) {
+					continue;
+				}
+				else {
+					Journal_DPrintfL( self->debug, 2, "Recv'd a batch of values from proc %u: updating...\n",
+						nbrRank );
+					/** update the appropriate values from recv'd set */
+					incomingDof_I = 0;
+					for( node_stI = 0; node_stI < mesh->nodeShadowInfo->procShadowCnt[nbr_I]; node_stI++ ) {
+						node_dI = mesh->nodeShadowInfo->procShadowTbl[nbr_I][node_stI];
+						for ( nodalDof_I=0; nodalDof_I < self->dofLayout->dofCounts[node_dI]; nodalDof_I++ ) {
+							DofLayout_SetValueDouble( self->dofLayout, node_dI, nodalDof_I,
+								incomingDofValues[nbr_I][incomingDof_I] );
+							incomingDof_I++;	
+						}
+					}
+					incomingDofValueSetsReceived[nbr_I] = True;
+					incomingDofValueSetsYetToReceive--;
+				}
+			}	
+		}	
+	}
+	Journal_DPrintfL( self->debug, 2, "Done.\n" );
+	Stream_UnIndent( self->debug );
+
+	Journal_DPrintfL( self->debug, 2, "Making sure outgoing sends have completed...\n" );
+	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
+		if ( mesh->nodeShadowInfo->procShadowCnt[nbr_I] > 0 ) {
+			MPI_Wait( outgoingDofValRequests[nbr_I], &status );
+		}
+	}
+	Journal_DPrintfL( self->debug, 2, "Done.\n" );
+
+	/** clean up temporary memory */
+	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
+		myShadowNodesOnThisNbrCount = mesh->nodeShadowInfo->procShadowCnt[nbr_I];
+		if ( myShadowNodesOnThisNbrCount > 0 ) {
+			Memory_Free( incomingDofValues[nbr_I] );
+			Memory_Free( incomingDofValRequests[nbr_I] );
+		}	
+	}
+	Memory_Free( incomingDofTotals );
+	Memory_Free( incomingDofValues );
+	Memory_Free( incomingDofValRequests );
+	for ( nbr_I=0; nbr_I < mesh->procNbrInfo->procNbrCnt; nbr_I++ ) {
+		nbrShadowNodesOnMeCount = mesh->nodeShadowInfo->procShadowedCnt[nbr_I];
+		if ( nbrShadowNodesOnMeCount > 0 ) {
+			Memory_Free( outgoingDofValues[nbr_I] );
+			Memory_Free( outgoingDofValRequests[nbr_I] );
+		}	
+	}
+	Memory_Free( outgoingDofTotals );
+	Memory_Free( outgoingDofValues );
+	Memory_Free( outgoingDofValRequests );
+	
+	Stream_UnIndent( self->debug );
+#endif
+}
+
+
+void FeVariable_PrintDomainDiscreteValues( void* variable, Stream* stream ) {
+	FeVariable* self = (FeVariable*)variable;
+
+	Journal_Printf( stream, "In %s: for FeVariable \"%s\":\n", __func__, self->name );
+
+	_FeVariable_PrintLocalOrDomainValues( variable, FeMesh_GetNodeDomainSize( self->feMesh ), stream );
+}
+
+void FeVariable_PrintCoordsAndValues( void* _feVariable, Stream* stream ) {
+	FeVariable*         self            = (FeVariable*) _feVariable;
+	Node_LocalIndex     node_I          = 0;
+	Node_LocalIndex     nodeLocalCount  = FeMesh_GetNodeLocalSize( self->feMesh );
+	Dof_Index           currNodeNumDofs;
+	Dof_Index           nodeLocalDof_I;
+	Variable*           currVariable;
+	double*             nodeCoord;
+	
+	/** Print Header of stream */
+	Journal_Printf( stream, "# FeVariable - %s\n", self->name );
+	Journal_Printf( stream, "#    x coord   |    y coord   |    z coord" );
+	currNodeNumDofs = self->dofLayout->dofCounts[ 0 ];
+	for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+		currVariable = DofLayout_GetVariable( self->dofLayout, node_I, nodeLocalDof_I );
+		Journal_Printf( stream, "  |  %s", currVariable->name );
+	}
+	Journal_Printf(stream, "\n");
+	
+	/** Loop over local nodes */
+	for( node_I=0; node_I < nodeLocalCount ; node_I++ ) {
+		currNodeNumDofs = self->dofLayout->dofCounts[ node_I ];
+
+		/** Get Coordinate of Node */
+		nodeCoord = Mesh_GetVertex( self->feMesh, node_I );
+		Journal_Printf( stream, "%12.6g   %12.6g   %12.6g   ", 
+				nodeCoord[ I_AXIS ], nodeCoord[ J_AXIS ], nodeCoord[ K_AXIS ] );
+		
+		/** Print each dof */
+		for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+			currVariable = DofLayout_GetVariable( self->dofLayout, node_I, nodeLocalDof_I );
+			Journal_Printf( stream, "%12.6g   ", Variable_GetValueDouble( currVariable, node_I ) );
+		}
+		Journal_Printf( stream, "\n" );
+	}	
+}
+
+
+/** --- Private Functions --- */
+
+void _FeVariable_InterpolateNodeValuesToElLocalCoord( void* feVariable, Element_DomainIndex element_lI, Coord elLocalCoord, double* value ) {
+	FeVariable*         self       = (FeVariable*) feVariable;
+	ElementType*		elementType=NULL;
+	Dof_Index		nodeLocalDof_I=0;
+	Dof_Index		dofCountThisNode=0;
+	Node_ElementLocalIndex	elLocalNode_I=0;
+	double*			shapeFuncsEvaluatedAtCoord=NULL;
+	Node_LocalIndex		lNode_I=0;
+	Variable*		currVariable=NULL;
+	double			dofValueAtCurrNode=0;
+	unsigned		nInc, *inc;
+
+	FeMesh_GetElementNodes( self->feMesh, element_lI, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = (unsigned*)IArray_GetPtr( self->inc );
+
+	/** Gets number of degrees of freedom - assuming it is the same throughout the mesh */
+	dofCountThisNode = self->dofLayout->dofCounts[lNode_I];
+
+	/** evaluate shape function values of current element at elLocalCoords */
+	elementType = FeMesh_GetElementType( self->feMesh, element_lI );
+	shapeFuncsEvaluatedAtCoord = AllocArray( double, nInc );
+	ElementType_EvaluateShapeFunctionsAt( elementType, elLocalCoord, shapeFuncsEvaluatedAtCoord );
+
+	for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
+		value[nodeLocalDof_I] = 0;
+	}
+
+	/** Now for each node, add that node's contribution at point */
+	for ( elLocalNode_I=0; elLocalNode_I < nInc; elLocalNode_I++ ) {
+		lNode_I = inc[elLocalNode_I];
+		
+		for ( nodeLocalDof_I=0; nodeLocalDof_I < dofCountThisNode; nodeLocalDof_I++ ) {
+			currVariable = DofLayout_GetVariable( self->dofLayout, lNode_I, nodeLocalDof_I );
+			dofValueAtCurrNode = Variable_GetValueDouble( currVariable, lNode_I );
+			value[nodeLocalDof_I] += dofValueAtCurrNode * shapeFuncsEvaluatedAtCoord[elLocalNode_I];
+		}	
+	}
+	FreeArray( shapeFuncsEvaluatedAtCoord );
+}
+
+void _FeVariable_PrintLocalOrDomainValues( void* variable, Index localOrDomainCount, Stream* stream ) {
+	FeVariable* self = (FeVariable*)variable;
+	Node_Index 		node_I = 0;
+	Node_GlobalIndex 	gNode_I = 0;
+	Dof_Index		currNodeNumDofs;
+	Dof_Index		nodeLocalDof_I;
+	Dof_EquationNumber	currEqNum;
+	Variable*		currVariable;
+	
+	for( node_I=0; node_I < localOrDomainCount; node_I++ ) {
+		gNode_I = FeMesh_NodeDomainToGlobal( self->feMesh, node_I );
+		Journal_Printf( stream, "node %d (global index %d):\n", node_I, gNode_I );
+		
+		currNodeNumDofs = self->fieldComponentCount;
+		
+		
+		/** Print each dof */
+		for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+			currVariable = DofLayout_GetVariable( self->dofLayout, node_I, nodeLocalDof_I );
+			Journal_Printf( stream, "\tdof %d \"%s\": %6g - ", nodeLocalDof_I, currVariable->name,
+				Variable_GetValueDouble( currVariable, node_I ) );
+			currEqNum = self->eqNum->destinationArray[node_I][nodeLocalDof_I];
+			if ( currEqNum == -1 ) {
+				Journal_Printf( stream, "(from BC)", currEqNum );
+			}
+			else {
+				Journal_Printf( stream, "(eq num %d)", currEqNum );
+			}	
+			Journal_Printf( stream, "\n", currEqNum );
+		}
+	}
+}
+
+InterpolationResult FeVariable_InterpolateFromMeshLocalCoord( void* feVariable, FeMesh* mesh, Element_DomainIndex dElement_I, double* localCoord, double* value ) {
+	FeVariable*          self               = (FeVariable*)         feVariable;
+
+	if ( mesh == self->feMesh ) {
+		/** If the meshes are identical - then we can just interpolate within the elements because the elements are the same */
+		FeVariable_InterpolateWithinElement( self, dElement_I, localCoord, value );
+                return LOCAL;
+	}
+	else {
+		Coord               globalCoord;
+
+		/** If the meshes are different - then we must find the global coordinates and interpolate to that */
+		FeMesh_CoordLocalToGlobal( mesh, dElement_I, localCoord, globalCoord );
+		return FieldVariable_InterpolateValueAt( feVariable, globalCoord, value );
+	}
+	
+}
+
+/** TODO: can't assume all swarms have particles of type integrationPoint anymore.
+   should check that the given swarm does have I.P for the rest of these functions.*/
+double FeVariable_IntegrateElement_AxisIndependent( 
+		void* feVariable, void* _swarm, 
+		Element_DomainIndex dElement_I, Dimension_Index dim, 
+		Axis axis0, Axis axis1, Axis axis2 ) 
+{
+	FeVariable*          self               = (FeVariable*)         feVariable;
+	Swarm*               swarm              = (Swarm*)              _swarm;
+	FeMesh*			feMesh             = self->feMesh;
+	FeMesh*			mesh;
+	ElementType*         elementType;
+	Cell_LocalIndex      cell_I;
+	Particle_InCellIndex cParticle_I;
+	Particle_InCellIndex cellParticleCount;
+	IntegrationPoint*    particle;
+	double               detJac;
+	double               integral;
+	double               value;
+	
+	/** Initialise Summation of Integral */
+	integral = 0.0;
+
+	/** Use feVariable's mesh as geometry mesh if one isn't passed in */
+	if( Stg_Class_IsInstance( feMesh->algorithms, Mesh_CentroidAlgorithms_Type ) )
+		mesh = (FeMesh*)((Mesh_CentroidAlgorithms*)feMesh->algorithms)->elMesh;
+	else
+		mesh = feMesh;
+	elementType = FeMesh_GetElementType( mesh, dElement_I );
+
+	/** Determine number of particles in element */
+	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, dElement_I );
+	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+
+	/** Loop over all particles in element */
+	for( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
+		/** Get Pointer to particle */
+		particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
+
+		/** Interpolate Value of Field at Particle */
+		FeVariable_InterpolateWithinElement( feVariable, dElement_I, particle->xi, &value );
+
+		Journal_DPrintfL( self->debug, 3, "%s: Integrating element %d - particle %d - Value = %g\n", self->name, dElement_I, cParticle_I, value );
+
+		/** Calculate Determinant of Jacobian */
+		detJac = ElementType_JacobianDeterminant_AxisIndependent( 
+				elementType, mesh, dElement_I, particle->xi, dim, axis0, axis1, axis2 );
+
+		/** Sum Integral */
+		integral += detJac * particle->weight * value;
+	}
+	
+	return integral;
+}
+
+double FeVariable_Integrate( void* feVariable, void* _swarm ) {
+	FeVariable*          self               = (FeVariable*)         feVariable;
+	Swarm*               swarm              = (Swarm*)              _swarm;
+	FeMesh*			feMesh             = self->feMesh;
+	Element_LocalIndex   lElement_I;
+	Element_LocalIndex   elementLocalCount  = FeMesh_GetElementLocalSize( feMesh );
+	double               integral, integralGlobal;
+	
+	/** Initialise Summation of Integral */
+	integral = 0.0;
+
+	/** Loop over all local elements */
+	for ( lElement_I = 0 ; lElement_I < elementLocalCount ; lElement_I++ ) {
+		integral += FeVariable_IntegrateElement( self, swarm, lElement_I );
+		Journal_DPrintfL( self->debug, 3, "%s: Integrating element %d - Accumulated Integral = %g\n", self->name, lElement_I, integral );
+	}
+		
+	/** Gather and sum integrals from other processors */
+	MPI_Allreduce( &integral, &integralGlobal, 1, MPI_DOUBLE, MPI_SUM, self->communicator );
+
+	return integralGlobal;
+}
+
+double FeVariable_AverageTopLayer( void* feVariable, void* swarm, Axis layerAxis ) {
+	FeVariable*                self               = (FeVariable*)         feVariable;
+	Grid*			elGrid;
+
+	elGrid = *(Grid**)ExtensionManager_Get( self->feMesh->info, self->feMesh, 
+						ExtensionManager_GetHandle( self->feMesh->info, (Name)"elementGrid" )  );
+
+	return FeVariable_AverageLayer( self, swarm, layerAxis, elGrid->sizes[1] - 1 );
+}
+
+double FeVariable_AverageBottomLayer( void* feVariable, void* swarm, Axis layerAxis ) {
+	FeVariable*                self               = (FeVariable*)         feVariable;
+
+	return FeVariable_AverageLayer( self, swarm, layerAxis, 0 );
+}
+
+double FeVariable_AverageLayer( void* feVariable, void* swarm, Axis layerAxis, Index layerIndex ) {
+	FeVariable*                self               = (FeVariable*)         feVariable;
+	Axis                       aAxis              = ( layerAxis == I_AXIS ? J_AXIS : I_AXIS );
+	Axis                       bAxis              = ( layerAxis == K_AXIS ? J_AXIS : K_AXIS );
+	Dimension_Index            dim                = self->dim;
+	double                     integral;
+	double                     layerThickness     = 0.0;
+	double			sendThickness;
+	Grid*			vertGrid;
+	unsigned*		inds;
+	double			heights[2];
+	unsigned		localInd[2], globalInd[2];
+	double			*min, *max;
+	int		d_i;
+	
+	integral = FeVariable_IntegrateLayer( self, swarm, layerAxis, layerIndex );
+
+	/** Calculate layer thickness.  This assumes the mesh is regular. */
+	vertGrid = *(Grid**)ExtensionManager_Get( self->feMesh->info, self->feMesh, 
+						  ExtensionManager_GetHandle( self->feMesh->info, (Name)"vertexGrid" )  );
+	inds = Memory_Alloc_Array_Unnamed( unsigned, Mesh_GetDimSize( self->feMesh ) );
+	for( d_i = 0; d_i < Mesh_GetDimSize( self->feMesh ); d_i++ ) {
+		if( d_i != layerAxis )
+			inds[d_i] = 0;
+		else
+			inds[d_i] = layerIndex;
+	}
+	globalInd[0] = Grid_Project( vertGrid, inds );
+	inds[layerAxis]++;
+	globalInd[1] = Grid_Project( vertGrid, inds );
+	if( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, globalInd[0], &localInd[0] ) && 
+	    Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, globalInd[1], &localInd[1] ) )
+	{
+		heights[0] = Mesh_GetVertex( self->feMesh, localInd[0] )[layerAxis];
+		heights[1] = Mesh_GetVertex( self->feMesh, localInd[1] )[layerAxis];
+		sendThickness = heights[1] - heights[0];
+	}
+	else {
+		sendThickness = 0.0;
+	}
+	MPI_Allreduce( &sendThickness, &layerThickness, 1, MPI_DOUBLE, MPI_MAX, self->communicator );
+	FreeArray( inds );
+
+	min = Memory_Alloc_Array_Unnamed( double, Mesh_GetDimSize( self->feMesh ) );
+	max = Memory_Alloc_Array_Unnamed( double, Mesh_GetDimSize( self->feMesh ) );
+	Mesh_GetGlobalCoordRange( self->feMesh, min, max );
+	integral /= layerThickness * (max[aAxis] - min[aAxis]);
+	if ( dim == 3 )
+		integral /= max[ bAxis ] - min[ bAxis ];
+	FreeArray( min );
+	FreeArray( max );
+
+	return integral;
+}
+
+
+double FeVariable_IntegrateLayer_AxisIndependent( 
+		void* feVariable, void* _swarm,
+		Axis layerAxis, Index layerIndex, Dimension_Index dim, 
+		Axis axis0, Axis axis1, Axis axis2 ) 
+{ 
+	FeVariable*                self               = (FeVariable*)         feVariable;
+	Swarm*                     swarm              = (Swarm*)              _swarm;
+	Element_LocalIndex         lElement_I;
+	Element_GlobalIndex        gElement_I;
+	IJK                        elementIJK;
+	double                     elementIntegral;
+	double                     integral;
+	double                     integralGlobal;
+
+	Journal_DPrintf( self->debug, "In %s() for FeVariable \"%s\":\n", __func__, self->name );
+
+	/** Initialise Sumation of Integral */
+	integral = 0.0;
+
+	Stream_Indent( self->debug );
+	for ( gElement_I = 0 ; gElement_I < FeMesh_GetElementGlobalSize( self->feMesh ); gElement_I++ ) {
+		RegularMeshUtils_Element_1DTo3D( self->feMesh, gElement_I, elementIJK );
+
+		/** Check if element is in layer plane */
+		if ( elementIJK[ layerAxis ] != layerIndex )
+			continue;
+
+		/** Check if element is local */
+		if( !FeMesh_ElementGlobalToDomain( self->feMesh, gElement_I, &lElement_I ) || 
+		    lElement_I >= FeMesh_GetElementLocalSize( self->feMesh ) )
+		{
+			continue;
+		}
+
+		elementIntegral = FeVariable_IntegrateElement_AxisIndependent( self, swarm, lElement_I, dim, axis0, axis1, axis2 );
+		Journal_DPrintfL( self->debug, 2, "Integral of element %d was %f\n", lElement_I, elementIntegral );
+		integral += elementIntegral;
+	}
+	Stream_UnIndent( self->debug );
+
+
+	/** Gather and sum integrals from other processors */
+	MPI_Allreduce( &integral, &integralGlobal, 1, MPI_DOUBLE, MPI_SUM, self->communicator );
+
+	Journal_DPrintf( self->debug, "Calculated global integral of layer %d in Axis %d was %f\n", layerIndex, layerAxis, integralGlobal );
+	return integralGlobal;
+}
+
+
+double FeVariable_AveragePlane( void* feVariable, Axis planeAxis, double planeHeight ) {
+	FeVariable*                self               = (FeVariable*)         feVariable;
+	double                     integral;
+	Axis                       aAxis              = ( planeAxis == I_AXIS ? J_AXIS : I_AXIS );
+	Axis                       bAxis              = ( planeAxis == K_AXIS ? J_AXIS : K_AXIS );
+	Dimension_Index            dim                = self->dim;
+	double				min[3], max[3];
+	
+	integral = FeVariable_IntegratePlane( self, planeAxis, planeHeight );
+
+	Mesh_GetGlobalCoordRange( self->feMesh, min, max );
+
+	integral /= max[ aAxis ] - min[ aAxis ];
+	if ( dim == 3 )
+		integral /= max[ bAxis ] - min[ bAxis ];
+
+	return integral;
+}
+
+double FeVariable_IntegratePlane( void* feVariable, Axis planeAxis, double planeHeight ) {
+	FeVariable*                self               = (FeVariable*)         feVariable;
+	IJK                        planeIJK;
+	Element_LocalIndex         lElement_I;
+	Element_GlobalIndex        gElement_I;
+	Element_LocalIndex         elementLocalCount  = FeMesh_GetElementLocalSize( self->feMesh );
+	Axis                       aAxis              = ( planeAxis == I_AXIS ? J_AXIS : I_AXIS );
+	Axis                       bAxis              = ( planeAxis == K_AXIS ? J_AXIS : K_AXIS );
+	double                     integral;
+	/** Swarm Stuff */
+	Swarm*                     tmpSwarm;
+	Bool                       dimExists[]        = { False, False, False };
+	ExtensionManager_Register* extensionMgr_Register;
+	SingleCellLayout*          singleCellLayout;
+	GaussParticleLayout*       gaussParticleLayout;
+	Particle_Index             lParticle_I;
+	IntegrationPoint*          particle;
+	/** Plane location stuff */
+	double                     storedXi_J_AXIS;
+	Coord                      planeCoord;
+	double                     planeXi           = -1;
+	double                     planeXiGlobal;
+	Index                      planeLayer        = 0;
+	Index                      planeLayerGlobal;
+	Particle_InCellIndex       particlesPerDim[] = {2,2,2};
+
+	/** Find Elements which plane cuts through */
+	memcpy( planeCoord, Mesh_GetVertex( self->feMesh, 0 ), sizeof( Coord ) );
+	planeCoord[ planeAxis ] = planeHeight;
+
+	if( Mesh_Algorithms_SearchElements( self->feMesh->algorithms, planeCoord, &lElement_I ) && 
+	    lElement_I < elementLocalCount )
+	{
+		Coord		planeXiCoord;
+
+		gElement_I = FeMesh_ElementDomainToGlobal( self->feMesh, lElement_I );
+		RegularMeshUtils_Element_1DTo3D( self->feMesh, gElement_I, planeIJK );
+		planeLayer = planeIJK[ planeAxis ];
+		
+		/** Find Local Coordinate of plane */
+		FeMesh_CoordGlobalToLocal( self->feMesh, lElement_I, planeCoord, planeXiCoord );
+		planeXi = planeXiCoord[ planeAxis ];
+	}
+	
+	/** Should be broadcast */
+	MPI_Allreduce( &planeXi,    &planeXiGlobal, 1, MPI_DOUBLE, MPI_MAX, self->communicator );
+	MPI_Allreduce( &planeLayer, &planeLayerGlobal, 1, MPI_UNSIGNED, MPI_MAX, self->communicator );
+
+	/** Create Swarm in plane */
+	extensionMgr_Register = ExtensionManager_Register_New();
+	dimExists[ aAxis ] = True;
+	if (self->dim == 3)
+		dimExists[ bAxis ] = True;
+	
+	singleCellLayout = SingleCellLayout_New( "cellLayout", (AbstractContext*)self->context, dimExists, NULL, NULL );
+	particlesPerDim[ planeAxis ] = 1;
+	gaussParticleLayout = GaussParticleLayout_New( "particleLayout", NULL, LocalCoordSystem, True, self->dim - 1, particlesPerDim );
+	tmpSwarm = Swarm_New( 
+			"tmpgaussSwarm", NULL,
+			singleCellLayout, 
+			gaussParticleLayout,
+			self->dim,
+			sizeof(IntegrationPoint), 
+			extensionMgr_Register, 
+			NULL,
+			self->communicator,
+		        NULL	);
+	Stg_Component_Build( tmpSwarm, NULL, False );
+
+	/** Change Positions of the particles */
+	Stg_Component_Initialise( tmpSwarm, NULL, False );
+	for ( lParticle_I = 0 ; lParticle_I < tmpSwarm->particleLocalCount ; lParticle_I++ ) {
+		particle = (IntegrationPoint*) Swarm_ParticleAt( tmpSwarm, lParticle_I );
+
+		storedXi_J_AXIS = particle->xi[ J_AXIS ];
+		particle->xi[ aAxis ]     = particle->xi[ I_AXIS ];
+		particle->xi[ bAxis ]     = storedXi_J_AXIS;
+		particle->xi[ planeAxis ] = planeXiGlobal;
+	}
+	
+	integral = FeVariable_IntegrateLayer_AxisIndependent( self, tmpSwarm, planeAxis, planeLayerGlobal, 
+			self->dim - 1, aAxis, bAxis, planeAxis );
+
+	/** Delete */
+	Stg_Class_Delete( tmpSwarm );
+	Stg_Class_Delete( gaussParticleLayout );
+	Stg_Class_Delete( singleCellLayout );
+	Stg_Class_Delete( extensionMgr_Register );
+	
+	return integral;
+}
+
+
+void FeVariable_ImportExportInfo_Delete( void* ptr ) {
+	/** Nothing to do - the ObjectAdaptor will take care of deleting the actual struct itself */
+}
+
+void FeVariable_SaveToFile( void* feVariable, Name filename, Bool saveCoords ) {
+	FeVariable*       self = (FeVariable*)feVariable;
+	Node_LocalIndex   lNode_I;
+	Node_GlobalIndex  gNode_I;
+	double*           coord;
+	Dof_Index         dof_I;
+	Dof_Index         dofAtEachNodeCount;
+	double            variableValues[MAX_FIELD_COMPONENTS];	
+	MPI_Comm	         comm = Comm_GetMPIComm( Mesh_GetCommTopology( self->feMesh, MT_VERTEX ) );
+	int               myRank;
+	int               nProcs;
+	MPI_Status        status;
+   Stream*           errorStr = Journal_Register( Error_Type, (Name)self->type  );
+   const int         FINISHED_WRITING_TAG = 100;
+   int               confirmation = 0;
+   MeshGenerator*    theGenerator;
+   
+#ifdef WRITE_HDF5
+   hid_t             file, fileSpace, fileData;
+   hid_t             memSpace;
+   hsize_t           start[2], count[2], size[2];
+   double*           buf;
+#else
+   FILE*             outputFile;
+#endif 
+
+	lNode_I = 0; gNode_I = 0;
+
+	MPI_Comm_size( comm, (int*)&nProcs );
+	MPI_Comm_rank( comm, (int*)&myRank );
+	
+	/** Note: assumes same number of dofs at each node */
+	dofAtEachNodeCount = self->fieldComponentCount;
+	
+#ifdef WRITE_HDF5
+	/** wait for go-ahead from process ranked lower than me, to avoid competition writing to file */
+	if ( myRank != 0 ) {
+		MPI_Recv( &confirmation, 1, MPI_INT, myRank - 1, FINISHED_WRITING_TAG, comm, &status );
+	}	
+
+   /** Open the file */
+	if ( myRank == 0 ) {
+      hid_t      attribData_id, attrib_id, group_id;
+      hsize_t    a_dims;
+      int        attribData;
+      Grid**     grid;
+      unsigned*  sizes;
+      
+      /** Open the HDF5 output file. */
+      file = H5Fcreate( filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
+      Journal_Firewall( file >= 0, errorStr,
+         "Error in %s for %s '%s' - Cannot create file %s.\n", 
+         __func__, self->type, self->name, filename );
+
+      /** create file attribute */
+      /** first store the fevariable checkpointing version */
+      a_dims = 1;
+      attribData = FeCHECKPOINT_V2;
+      attribData_id = H5Screate_simple(1, &a_dims, NULL);
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+         group_id  = H5Gopen(file, "/");
+         attrib_id = H5Acreate(group_id, "checkpoint file version", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
+      #else
+         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
+         attrib_id = H5Acreate2(group_id, "checkpoint file version", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
+      #endif
+      H5Awrite(attrib_id, H5T_NATIVE_INT, &attribData);
+      H5Aclose(attrib_id);
+      H5Gclose(group_id);
+      H5Sclose(attribData_id);
+
+      /** store the fevariable dimensionality */
+      a_dims = 1;
+      attribData = self->dim;
+      attribData_id = H5Screate_simple(1, &a_dims, NULL);
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+         group_id  = H5Gopen(file, "/");
+         attrib_id = H5Acreate(group_id, "dimensions", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
+      #else
+         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
+         attrib_id = H5Acreate2(group_id, "dimensions", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
+      #endif
+      H5Awrite(attrib_id, H5T_NATIVE_INT, &attribData);
+      H5Aclose(attrib_id);
+      H5Gclose(group_id);
+      H5Sclose(attribData_id);
+      
+      /** get the generator */
+      if( Stg_Class_IsInstance( self->feMesh->generator, MeshAdaptor_Type )) 
+         theGenerator = ((MeshAdaptor*)self->feMesh->generator)->generator;
+      else 
+         theGenerator = self->feMesh->generator;
+
+      /** store the mesh resolution if mesh is cartesian */
+      if ( Stg_Class_IsInstance( theGenerator, CartesianGenerator_Type ) ) {
+         a_dims = self->dim;
+         grid   = (Grid**) Mesh_GetExtension( self->feMesh, Grid*, "elementGrid" );	
+         sizes  =          Grid_GetSizes( *grid ); /** global no. of elements in each dim */
+         
+         attribData_id = H5Screate_simple(1, &a_dims, NULL);
+         #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+            group_id  = H5Gopen(file, "/");
+            attrib_id = H5Acreate(group_id, "mesh resolution", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
+         #else
+            group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
+            attrib_id = H5Acreate2(group_id, "mesh resolution", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
+         #endif
+         H5Awrite(attrib_id, H5T_NATIVE_INT, sizes);
+         H5Aclose(attrib_id);
+         H5Gclose(group_id);
+         H5Sclose(attribData_id);
+      }       
+      size[0] = Mesh_GetGlobalSize( self->feMesh, (MeshTopology_Dim)0 );;
+      size[1] = dofAtEachNodeCount;
+      if( saveCoords )
+         size[1] += self->dim;
+      
+      /** Create filespace */   
+      fileSpace = H5Screate_simple( 2, size, NULL );         
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData  = H5Dcreate( file, "/data", H5T_NATIVE_DOUBLE, fileSpace, H5P_DEFAULT );
+      #else
+      fileData  = H5Dcreate2( file, "/data", H5T_NATIVE_DOUBLE, fileSpace,
+                                  H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
+      #endif
+	} else {
+      /** Open the HDF5 output file. */
+      file = H5Fopen( filename, H5F_ACC_RDWR, H5P_DEFAULT );
+      Journal_Firewall( file >= 0, errorStr,
+         "Error in %s for %s '%s' - Cannot open file %s.\n", 
+         __func__, self->type, self->name, filename );
+
+      /** get the filespace */   
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData  = H5Dopen( file, "/data" );
+      #else
+      fileData  = H5Dopen2( file, "/data", H5P_DEFAULT );
+      #endif
+      /** get the filespace handle */
+      fileSpace = H5Dget_space(fileData);
+	}	
+	
+   /** get the section of fileSpace to write to... set start point to be the
+      global index of first local node */
+	count[0] = 1;
+	count[1] = dofAtEachNodeCount;
+   if( saveCoords )
+      count[1] += self->dim;
+
+   /** create memSpace */
+   memSpace = H5Screate_simple( 2, count, NULL );
+   H5Sselect_all( memSpace );
+
+   buf = Memory_Alloc_Array( double, count[1], "fileBuffer" );
+   
+   for ( lNode_I = 0; lNode_I < FeMesh_GetNodeLocalSize( self->feMesh ); lNode_I++ ) {
+
+	   /** If required, add coords to array */
+	   if( saveCoords ) {
+	      coord = Mesh_GetVertex( self->feMesh, lNode_I );
+	      buf[0] = coord[0];
+	      buf[1] = coord[1];
+	      if( self->dim == 3 )
+	         buf[2] = coord[2]; 
+	   }
+	   
+	   /** Add field value at current node to array */
+      FeVariable_GetValueAtNode( self, lNode_I, variableValues );
+		for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
+		   if( saveCoords )
+			   buf[dof_I + self->dim] = variableValues[dof_I];
+			else
+			   buf[dof_I] = variableValues[dof_I];   
+		}	
+
+      /** select the region of dataspace to write to  */
+      start[0] = FeMesh_NodeDomainToGlobal( self->feMesh, lNode_I );
+      start[1] = 0;
+      H5Sselect_hyperslab( fileSpace, H5S_SELECT_SET, start, NULL, count, NULL );
+      /** Write the array to file */
+      H5Dwrite( fileData, H5T_NATIVE_DOUBLE, memSpace, fileSpace, H5P_DEFAULT, buf );
+   }   
+   /** free memory! */
+   Memory_Free( buf );
+   
+   /** Close all handles */
+   H5Dclose( fileData );
+   H5Sclose( memSpace );
+   H5Sclose( fileSpace );
+   H5Fclose( file );
+   
+	/** send go-ahead to process ranked above me, to avoid competition writing to file */
+	if ( myRank != nProcs - 1 ) {
+		MPI_Ssend( &confirmation, 1, MPI_INT, myRank + 1, FINISHED_WRITING_TAG, comm );
+	}	
+
+#else
+	/** wait for go-ahead from process ranked lower than me, to avoid competition writing to file */
+	if ( myRank != 0 ) {
+		MPI_Recv( &confirmation, 1, MPI_INT, myRank - 1, FINISHED_WRITING_TAG, comm, &status );
+	}	
+
+   /** Open the file */
+	if ( myRank == 0 ) {
+		outputFile = fopen( filename, "w" );
+	}
+	else {
+		outputFile = fopen( filename, "a" );
+	}	
+	
+	Journal_Firewall(	outputFile != NULL, errorStr,
+		"Error in %s for %s '%s' - Cannot create file %s.\n", 
+		__func__, self->type, self->name, filename );
+		
+	for ( lNode_I = 0; lNode_I < FeMesh_GetNodeLocalSize( self->feMesh ); lNode_I++ ) {
+		gNode_I = FeMesh_NodeDomainToGlobal( self->feMesh, lNode_I );
+		fprintf( outputFile, "%u ", gNode_I );
+		
+		/** If required, write the node coords to file */		
+      if( saveCoords ) {
+		   coord = Mesh_GetVertex( self->feMesh, lNode_I );
+         if(self->dim == 2)
+            fprintf( outputFile, "%.15g %.15g 0 ", coord[0], coord[1]);
+         else
+            fprintf( outputFile, "%.15g %.15g %.15g ", coord[0], coord[1], coord[2] );
+      }
+		
+		/** Add field value at current node to the file */            
+		FeVariable_GetValueAtNode( self, lNode_I, variableValues );
+		for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
+			fprintf( outputFile, "%.15g ", variableValues[dof_I] );
+		}	
+		fprintf( outputFile, "\n" );
+	}
+	
+	/** Close the file */
+	fclose( outputFile );
+	
+   /** send go-ahead to process ranked above me, to avoid competition writing to file */
+	if ( myRank != nProcs - 1 ) {
+		MPI_Ssend( &confirmation, 1, MPI_INT, myRank + 1, FINISHED_WRITING_TAG, comm );
+	}	
+
+#endif
+}
+
+
+#define MAX_LINE_LENGTH_DEFINE 1024
+
+void FeVariable_ReadFromFile( void* feVariable, Name filename ) {
+	FeVariable*        self = (FeVariable*)feVariable;
+	Node_LocalIndex    lNode_I = 0;
+	Node_GlobalIndex   gNode_I = 0;
+	Dof_Index          dof_I;
+	Dof_Index          dofAtEachNodeCount;
+#ifndef READ_HDF5
+	FILE*              inputFile;
+#endif
+	double             variableVal;
+	Processor_Index    proc_I;
+	MPI_Comm	          comm = Comm_GetMPIComm( Mesh_GetCommTopology( self->feMesh, MT_VERTEX ) );
+	unsigned		       rank;
+	unsigned		       nRanks;
+	int                nDims;
+	Bool               savedCoords = False;
+	Stream*            errorStr = Journal_Register( Error_Type, (Name)self->type  );
+   MeshGenerator*    theGenerator;
+	
+#ifdef READ_HDF5
+   hid_t                   file, fileSpace, fileData, error;
+   unsigned                totalNodes, ii, noffset;
+   hid_t                   memSpace;
+   hsize_t                 start[2], count[2], size[2], maxSize[2];
+   double*                 buf; 
+   FeCheckpointFileVersion ver;
+   hid_t                   attrib_id, group_id;
+   herr_t                  status;   
+#else
+   unsigned          uTemp;  
+   double            temp[3];  
+   int               count = 0;     
+   char               lineString[MAX_LINE_LENGTH_DEFINE];
+	const unsigned int MAX_LINE_LENGTH = MAX_LINE_LENGTH_DEFINE;
+   int               offset, n;
+#endif   	
+
+	MPI_Comm_rank( comm, (int*)&rank );
+	MPI_Comm_size( comm, (int*)&nRanks );
+	
+	dofAtEachNodeCount = self->fieldComponentCount;
+	proc_I = 0;
+	nDims = 0;
+	
+#ifdef READ_HDF5	
+   
+   /** Open the file and data set. */
+	file = H5Fopen( filename, H5F_ACC_RDONLY, H5P_DEFAULT );
+	
+	Journal_Firewall(	file >= 0, errorStr,
+		"Error in %s for %s '%s' - Cannot open file %s.\n", 
+		__func__, self->type, self->name, filename );
+
+   /** get the file attributes to sanity and version checks */
+   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      group_id  = H5Gopen(file, "/");
+      attrib_id = H5Aopen_name(group_id, "checkpoint file version");
+   #else
+      group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
+      attrib_id = H5Aopen(group_id, "checkpoint file version", H5P_DEFAULT);
+   #endif
+   /** if this attribute does not exist (attrib_id < 0) then we assume FeCHECKPOINT_V1 and continue without checking attributes */
+   if(attrib_id < 0)
+      ver = FeCHECKPOINT_V1;
+   else {
+      int checkVer;
+      int ndims;
+      int res[self->dim];
+      Grid**     grid;
+      unsigned*  sizes;
+
+      /** check for known checkpointing version type */
+
+      status = H5Aread(attrib_id, H5T_NATIVE_INT, &checkVer);
+      H5Aclose(attrib_id);
+      if(checkVer == 2)
+         ver = FeCHECKPOINT_V2;
+      else
+         Journal_Firewall( (0), errorStr,
+            "\n\nError in %s for %s '%s'\n"
+            "Unknown checkpoint version (%u) for checkpoint file (%s).\n", 
+            __func__, self->type, self->name, (unsigned int) checkVer, filename);
+
+      /** check for correct number of dimensions */
+
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+         attrib_id = H5Aopen_name(group_id, "dimensions");
+      #else
+         attrib_id = H5Aopen(group_id, "dimensions", H5P_DEFAULT);
+      #endif
+      status = H5Aread(attrib_id, H5T_NATIVE_INT, &ndims);
+      H5Aclose(attrib_id);      
+      Journal_Firewall( (ndims == self->dim), errorStr,
+         "\n\nError in %s for %s '%s'\n"
+         "Number of dimensions (%u) for checkpoint file (%s) does not correspond to simulation dimensions (%u).\n", 
+         __func__, self->type, self->name, (unsigned int) ndims, filename,
+         self->dim);
+
+      /** get the generator */
+      if( Stg_Class_IsInstance( self->feMesh->generator, MeshAdaptor_Type )) 
+         theGenerator = ((MeshAdaptor*)self->feMesh->generator)->generator;
+      else 
+         theGenerator = self->feMesh->generator;
+
+      /** check for correct mesh size if expecting a cartesian mesh*/
+      if ( Stg_Class_IsInstance( theGenerator, CartesianGenerator_Type ) ) {
+         
+         #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+            attrib_id = H5Aopen_name(group_id, "mesh resolution");
+         #else
+            attrib_id = H5Aopen(group_id, "mesh resolution", H5P_DEFAULT);
+         #endif
+         status = H5Aread(attrib_id, H5T_NATIVE_INT, &res);
+         H5Aclose(attrib_id);
+   
+         grid   = (Grid**) Mesh_GetExtension( self->feMesh, Grid*, "elementGrid" );	
+         sizes  =          Grid_GetSizes( *grid ); /** global no. of elements in each dim */
+         if(self->dim == 2)
+            Journal_Firewall( 
+               ( (sizes[0] == res[0]) && (sizes[1] == res[1]) ), 
+               errorStr,
+               "\n\nError in %s for %s '%s'\n"
+               "Size of mesh (%u,%u) for checkpoint file (%s) does not correspond to simulation mesh size (%u,%u).\n\n"
+               "If you would like to interpolate checkpoint data to simulation mesh size\n"
+               "    please re-launch using '--interpolateRestart=1' flag\n\n", 
+               __func__, self->type, self->name, 
+               (unsigned int) res[0], (unsigned int) res[1],
+               filename,
+               (unsigned int) sizes[0], (unsigned int) sizes[1]);
+         else
+            Journal_Firewall( 
+               ( (sizes[0] == res[0]) && (sizes[1] == res[1]) && (sizes[2] == res[2]) ), 
+               errorStr,
+               "\n\nError in %s for %s '%s'\n"
+               "Size of mesh (%u,%u,%u) for checkpoint file (%s) does not correspond to simulation mesh size (%u,%u,%u).\n\n"
+               "If you would like to interpolate checkpoint data to simulation mesh size\n"
+               "    please re-launch using '--interpolateRestart=1' flag\n\n", 
+               __func__, self->type, self->name, 
+               (unsigned int) res[0], (unsigned int) res[1], (unsigned int) res[2],
+               filename,
+               (unsigned int) sizes[0], (unsigned int) sizes[1], (unsigned int) sizes[2]);
+      }
+   }
+   H5Gclose(group_id);
+   
+   /** account for different versions of checkpointing */
+	switch ( ver ) {
+		case FeCHECKPOINT_V1:
+         noffset = 1;
+			break;
+		case FeCHECKPOINT_V2:
+         noffset = 0;
+			break;
+		default:
+			Journal_Firewall( 0, errorStr,
+				"Error: in %s: unknown checkpoint file version.\n",
+				__func__ ); 
+	}
+   
+	/** Prepare to read vertices from file */		
+   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+	fileData = H5Dopen( file, "/data" );
+   #else
+	fileData = H5Dopen2( file, "/data", H5P_DEFAULT );
+   #endif
+	fileSpace = H5Dget_space( fileData );
+   
+   /** Get size of dataspace to determine if coords are in file */
+   H5Sget_simple_extent_dims( fileSpace, size, maxSize ); 
+
+   if( maxSize[1] > dofAtEachNodeCount + noffset ) 
+      savedCoords = True;
+       
+   start[1] = 0;
+	count[0] = 1;
+	count[1] = dofAtEachNodeCount + noffset ;
+	if( savedCoords )  
+	   count[1] += self->dim;
+	   
+   memSpace = H5Screate_simple( 2, count, NULL );
+   totalNodes = Mesh_GetGlobalSize( self->feMesh, (MeshTopology_Dim)0 );
+   buf = Memory_Alloc_Array( double, count[1], "fileBuffer" );
+
+   Journal_Firewall( (maxSize[0] == totalNodes), errorStr,
+      "\n\nError in %s for %s '%s'\n"
+      "Number of node values (%u) stored in %s does not correspond to total number of requested mesh nodes (%u).\n", 
+      __func__, self->type, self->name, (unsigned int)maxSize[0], filename, totalNodes);
+   
+         
+   /** Read from HDF5 checkpint file */
+   for( ii=0; ii<totalNodes; ii++ ) {   
+	   start[0] = ii;
+               
+      H5Sselect_hyperslab( fileSpace, H5S_SELECT_SET, start, NULL, count, NULL );
+      H5Sselect_all( memSpace );
+         
+      error = H5Dread( fileData, H5T_NATIVE_DOUBLE, memSpace, fileSpace, H5P_DEFAULT, buf );
+      gNode_I = ii;
+
+      Journal_Firewall( error >= 0, errorStr,
+         "\n\nError in %s for %s '%s' - Cannot read data in %s.\n", 
+         __func__, self->type, self->name, filename );
+      
+      if( Mesh_GlobalToDomain( self->feMesh, MT_VERTEX, gNode_I, &lNode_I ) && 
+		   lNode_I < Mesh_GetLocalSize( self->feMesh, MT_VERTEX ) )
+		{
+		   for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
+		      if( savedCoords )
+		         variableVal = buf[dof_I + self->dim + noffset ];
+		      else
+				   variableVal = buf[dof_I + noffset ];
+				DofLayout_SetValueDouble( self->dofLayout, lNode_I, dof_I, variableVal );
+			}  
+		}
+	}   
+   Memory_Free( buf );
+
+   /** Close all handles */
+   H5Dclose( fileData );
+   H5Sclose( memSpace );
+   H5Sclose( fileSpace );
+   H5Fclose( file );
+   
+#else   
+
+	/** This loop used to stop 2 processors trying to open the file at the same time, which
+	  * seems to cause problems */
+	for ( proc_I = 0; proc_I < nRanks; proc_I++ ) {
+		MPI_Barrier( comm );
+		if ( proc_I == rank ) {
+			/** Do the following since in parallel on some systems, the file
+			 * doesn't get re-opened at the start automatically. */
+			inputFile = fopen( filename, "r" );
+
+			if ( False == inputFile ) {
+				Journal_Firewall( 0, errorStr, "Error- in %s(), for feVariable \"%s\": Couldn't import from file: "
+					"\"%s\" - aborting.\n", __func__, self->name, filename );
+					
+			}
+			rewind( inputFile );
+	
+		}
+	}
+   
+   /** Need to determine whether checkpoint file contains coordinates */
+   fgets( lineString, MAX_LINE_LENGTH, inputFile );
+   
+   sscanf( lineString, "%u%n ", &uTemp, &offset );
+   while( sscanf( lineString + offset, "%lf%n ", &temp[0], &n ) )
+   {
+      offset += n;
+      count ++;
+      if( offset >= strlen( lineString ) - 2 )
+         break;
+   }   
+ 
+   if( count > dofAtEachNodeCount + 1 ) 
+      savedCoords = True;
+    
+   rewind( inputFile );
+      
+	/** Need to re-set the geometry here, in case we're loading from a checkpoint that had compression/squashing BCs,
+		and hence ended up with a smaller mesh than the original */
+	nDims = Mesh_GetDimSize( self->feMesh );
+	while ( !feof(inputFile) ) {
+		fscanf( inputFile, "%u ", &gNode_I );
+		
+		if( savedCoords ) 
+		   fscanf( inputFile, "%lg %lg %lg ", &temp[0], &temp[1], &temp[2] );
+		   
+		if( FeMesh_NodeGlobalToDomain( self->feMesh, gNode_I, &lNode_I ) && 
+		    lNode_I < FeMesh_GetNodeLocalSize( self->feMesh ) )
+		{
+			for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
+				fscanf( inputFile, "%lg ", &variableVal );
+				DofLayout_SetValueDouble( self->dofLayout, lNode_I, dof_I, variableVal );
+			}
+		}
+		else {
+			fgets( lineString, MAX_LINE_LENGTH, inputFile );
+		}
+	}
+	fclose( inputFile );
+#endif	
+
+	Mesh_DeformationUpdate( self->feMesh );
+
+	/** Sync shadow values now, as all procs should have required input */
+	FeVariable_SyncShadowValues( self );
+}
+
+void FeVariable_InterpolateFromFile( void* feVariable, DomainContext* context, Name feVarFilename, const char* meshFilename ){
+	FeVariable*							self = (FeVariable*)feVariable;
+   Stream*								errorStr = Journal_Register( Error_Type, (Name)self->type  );   
+#ifdef READ_HDF5
+   CartesianGenerator*				gen;
+   C0Generator*						C0gen;
+   FeMesh								*feMesh, *C0feMesh, *elementMesh;
+   DofLayout*							dofs;
+   Variable_Register*				varReg;
+   Variable*							var;
+   FeVariable*							feVar;
+   hid_t									file, fileData;
+   unsigned								totalNodes, ii;
+   hid_t									attrib_id, group_id;
+   herr_t								status;
+   int									res[3];
+   int									checkVer;
+   int									ndims;
+	double								crdMin[3], crdMax[3];
+	double*								value;
+	unsigned								nDomainVerts;
+	static double*						arrayPtr;
+   char*									varName[9];
+
+   /** Open the file and data set. */
+	file = H5Fopen( meshFilename, H5F_ACC_RDONLY, H5P_DEFAULT );
+	
+	Journal_Firewall(	file >= 0, errorStr, "Error in %s for %s '%s' - Cannot open file %s.\n", __func__, self->type, self->name, meshFilename );
+
+   /** get the file attributes to sanity and version checks */
+   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      group_id  = H5Gopen(file, "/");
+      attrib_id = H5Aopen_name(group_id, "checkpoint file version");
+   #else
+      group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
+      attrib_id = H5Aopen(group_id, "checkpoint file version", H5P_DEFAULT);
+   #endif
+   /** if this attribute does not exist (attrib_id < 0) then we assume MeshCHECKPOINT_V1 which is not supported  */
+   if(attrib_id < 0)
+      Journal_Firewall( 0, errorStr,"\nError in %s for %s '%s' \n\n Interpolation restart not supported for Version 1 Checkpoint files \n\n", __func__, self->type, self->name );
+
+   /** check for known checkpointing version type */
+
+   status = H5Aread(attrib_id, H5T_NATIVE_INT, &checkVer);
+   H5Aclose(attrib_id);
+   if(checkVer != 2)
+      Journal_Firewall( (0), errorStr, "\n\nError in %s for %s '%s'\n" "Unknown checkpoint version (%u) for checkpoint file (%s).\n", __func__,
+			 self->type, self->name, (unsigned int) checkVer, meshFilename);
+
+   /** check for correct number of dimensions */
+
+   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      attrib_id = H5Aopen_name(group_id, "dimensions");
+   #else
+      attrib_id = H5Aopen(group_id, "dimensions", H5P_DEFAULT);
+   #endif
+   status = H5Aread(attrib_id, H5T_NATIVE_INT, &ndims);
+   H5Aclose(attrib_id);      
+   Journal_Firewall( (ndims == self->dim), errorStr,
+      "\n\nError in %s for %s '%s'\n"
+      "Number of dimensions (%u) for checkpoint file (%s) does not correspond to simulation dimensions (%u).\n", 
+      __func__, self->type, self->name, (unsigned int) ndims, meshFilename,
+      self->dim);
+
+   /** check for correct mesh size if expecting a cartesian mesh*/
+   
+   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      attrib_id = H5Aopen_name(group_id, "mesh resolution");
+   #else
+      attrib_id = H5Aopen(group_id, "mesh resolution", H5P_DEFAULT);
+   #endif
+   status = H5Aread(attrib_id, H5T_NATIVE_INT, &res);
+   H5Aclose(attrib_id);
+
+   /** Read in minimum coord. */
+   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData = H5Dopen( file, "/min" );
+   #else
+      fileData = H5Dopen2( file, "/min", H5P_DEFAULT );
+   #endif
+   H5Dread( fileData, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &crdMin );
+   H5Dclose( fileData );
+      
+   /** Read in maximum coord. */
+   #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData = H5Dopen( file, "/max" );
+   #else
+      fileData = H5Dopen2( file, "/max", H5P_DEFAULT );
+   #endif
+   H5Dread( fileData, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, &crdMax );
+   H5Dclose( fileData );
+
+   /** Close all handles */
+   H5Gclose(group_id);
+   H5Fclose( file );
+
+   /** create a cartesian mesh generator which will be required for the fevariable creation */
+   gen = CartesianGenerator_New( "", NULL );
+   /** use the feVariable dimension size for mesh generator */
+   CartesianGenerator_SetDimSize( gen, self->dim );
+   /** use the element size read in from the checkpoint file for the new mesh generator */
+   CartesianGenerator_SetTopologyParams( gen, (unsigned*)res, 0, NULL, NULL );
+	/** use the feVariable's mesh's generator's crdMin and crdMax (which have been previously read in from checkpointed mesh file  */
+   CartesianGenerator_SetGeometryParams( gen, crdMin, crdMax );
+   /** set it so that the generator does not read in the mesh from a file - we will 
+              explicitly do this after we build the feMesh using the provided mesh checkpoint file */
+   gen->readFromFile = False;
+   /** create a feMesh */
+   feMesh = FeMesh_New( "", NULL );
+   /** set feMesh to use generator we just created  */
+   Mesh_SetGenerator( feMesh, gen );
+   /** set the feMesh family to be the same as that of the feVariable we are initialising/interpolating ie constant, linear, etc 
+       unless we are initialising a constant mesh, in which case we set the element family to linear, and the mesh will be used 
+       as the elementMesh for the C0 generator */
+   if (!strcmp(self->feMesh->generator->type, CartesianGenerator_Type)){
+      FeMesh_SetElementFamily( feMesh, self->feMesh->feElFamily );
+      /** set periodicity according to current simulation */
+      gen->periodic[0] = ((CartesianGenerator*)self->feMesh->generator)->periodic[0];
+      gen->periodic[1] = ((CartesianGenerator*)self->feMesh->generator)->periodic[1];
+      gen->periodic[2] = ((CartesianGenerator*)self->feMesh->generator)->periodic[2];
+   } else if (!strcmp(self->feMesh->generator->type, C0Generator_Type)){
+      FeMesh_SetElementFamily( feMesh, "linear" );
+      /** set periodicity according to current simulation */
+      gen->periodic[0] = ((CartesianGenerator*)((C0Generator*)self->feMesh->generator)->elMesh)->periodic[0];
+      gen->periodic[1] = ((CartesianGenerator*)((C0Generator*)self->feMesh->generator)->elMesh)->periodic[1];
+      gen->periodic[2] = ((CartesianGenerator*)((C0Generator*)self->feMesh->generator)->elMesh)->periodic[2];
+   } else
+      Journal_Firewall( 0, errorStr,"\nError in %s for %s '%s' \n\n Interpolation restart not supported for this mesh type \n\n", __func__, self->type, self->name );
+
+   /** now build the mesh, then read in the required coordinates from the given file */
+   Stg_Component_Build( feMesh, NULL, False );
+   CartesianGenerator_ReadFromHDF5(  gen, (Mesh*) feMesh, meshFilename );
+
+   /** where we are dealing with a constant mesh feVariable, we have to build a new C0 mesh */ 
+   if (!strcmp(self->feMesh->generator->type, C0Generator_Type)){
+      elementMesh = feMesh;
+      /** create the C0 generator */
+      C0gen = C0Generator_New( "", (AbstractContext*)self->context );
+      /** set it's element mesh to the feMesh create just above */
+      C0Generator_SetElementMesh( C0gen, (void*) elementMesh );
+      /** create a new feMesh */
+      C0feMesh = FeMesh_New( "", NULL );
+      /** set feMesh to use generator we just created, and set its type to constant mesh  */
+      Mesh_SetGenerator( C0feMesh, C0gen );
+      FeMesh_SetElementFamily( C0feMesh, self->feMesh->feElFamily );
+      /** now build the mesh, which will generate the mesh using the provided generator */
+      Stg_Component_Build( C0feMesh, NULL, False );
+      /** reset the feMesh pointer to point to this C0 mesh */
+      feMesh = C0feMesh;
+   }
+   Stg_Component_Initialise( feMesh, NULL, False );
+   /** get the number of mesh vertices stored locally */   
+   nDomainVerts = Mesh_GetDomainSize( feMesh, MT_VERTEX );   
+
+   varReg = Variable_Register_New();
+   if (self->fieldComponentCount == 1){
+     var = Variable_NewScalar( "interpolation_temp_scalar", (AbstractContext*)self->context, Variable_DataType_Double, (Index*)&nDomainVerts, NULL, (void **)(&arrayPtr), varReg );
+   } else {
+      unsigned var_I;
+		for( var_I = 0; var_I < self->fieldComponentCount; var_I++  )
+			Stg_asprintf( &varName[var_I], "%s-loaded-Component-%d", self->name, var_I );
+      var = Variable_NewVector( "interpolation_temp_vector", 
+											(AbstractContext*)self->context,
+                                 Variable_DataType_Double,
+                                 self->fieldComponentCount,
+                                 &nDomainVerts,
+                                 NULL,
+                                 (void**)&arrayPtr,
+                                 varReg, 
+                                 varName[0], varName[1], varName[2], varName[3], varName[4],
+                                 varName[5], varName[6], varName[7], varName[8] );
+   }
+   Variable_Register_Add( varReg, var);
+   var->allocateSelf = True;   
+   Stg_Component_Build( var, NULL, False );
+
+   dofs = DofLayout_New( "interpolation_temp_dof", self->context, varReg, nDomainVerts, feMesh );
+	if( self->fieldComponentCount == 1 )
+		DofLayout_AddAllFromVariableArray( dofs, 1, &var );
+	else {
+      unsigned   var_I, node_I;
+      Variable*  variable;
+		for( var_I = 0; var_I < self->fieldComponentCount; var_I++ ) {
+			variable = Variable_Register_GetByName( varReg, varName[var_I] );
+			variable->arrayPtrPtr = &var->arrayPtr;
+
+			for( node_I = 0; node_I < nDomainVerts; node_I++ )
+				DofLayout_AddDof_ByVarName( dofs, varName[var_I], node_I );
+
+			Memory_Free( varName[var_I] );
+      }
+   }
+   Stg_Component_Build( dofs, NULL, False );
+   Stg_Component_Initialise( dofs, NULL, False );
+
+   feVar = FeVariable_New(
+		"interpolation_temp_fevar", 
+		self->context,
+  		feMesh, 
+  		NULL, 
+		dofs, 
+		NULL, 
+		NULL, 
+		NULL, 
+		self->fieldComponentCount, 
+		False, 
+		True, 
+		False, 
+		NULL );
+
+   Stg_Component_Build( feVar, context, False );
+   /** not sure why these aren't being set correctly, so a little (tri/ha)ckery */
+   feVar->fieldComponentCount = self->fieldComponentCount;
+   feVar->dim = self->dim;
+   FeVariable_ReadFromFile( feVar, feVarFilename );
+   feVar->_syncShadowValues( feVar );
+
+   totalNodes = Mesh_GetLocalSize( self->feMesh, MT_VERTEX );
+   value = Memory_Alloc_Array( double, self->fieldComponentCount, "interValue" );
+         
+   /** step through nodes, interpolating the required values from our newly created feVariable */
+   for( ii=0; ii<totalNodes; ii++ ) {
+      feVar->_interpolateValueAt( feVar, Mesh_GetVertex( self->feMesh, ii ), value);
+      FeVariable_SetValueAtNode( self, ii, value);
+   }
+   Memory_Free( value );
+
+   /** our work is done, so we clean up after ourselves */
+   _FeVariable_Delete(feVar);
+   _DofLayout_Delete(dofs);
+   _Variable_Delete(var);
+   _Variable_Register_Delete(varReg);
+   _FeMesh_Delete(feMesh);
+
+   if (!strcmp(self->feMesh->generator->type, C0Generator_Type)){
+      _C0Generator_Delete(C0gen);
+      _FeMesh_Delete(elementMesh);
+   }
+   _CartesianGenerator_Delete(gen);
+
+#else
+   Journal_Firewall(!context->interpolateRestart, 
+               errorStr,"\n\n Interpolation restart not supported for ASCII checkpoint files \n\n");
+#endif   
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FieldTest.c
--- a/Discretisation/src/FieldTest.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1166 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FieldTest.c 1095 2008-04-03 06:29:29Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "types.h"
-#include "FieldTest.h"
-#include "FeVariable.h"
-#include "ElementType.h"
-#include "FeMesh.h"
-#include "OperatorFeVariable.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-const Type FieldTest_Type = "FieldTest";
-
-FieldTest* fieldTestSingleton = NULL;
-
-void* _FieldTest_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(FieldTest);
-	Type                                                      type = FieldTest_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _FieldTest_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _FieldTest_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _FieldTest_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-FieldTest* _FieldTest_New(  FIELDTEST_DEFARGS  )
-{
-	FieldTest*			self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(FieldTest) );
-	/* Construct using parent */
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (FieldTest*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-
-	self->normalise = False;
-	self->epsilon = 0.0001;
-	self->referenceSolnFromFile = False;
-
-	/* Assign singleton ptr */
-	fieldTestSingleton = self;
-	return self;
-}
-
-void _FieldTest_Delete( void* fieldTest ) {
-	FieldTest* 	self 	= (FieldTest*)fieldTest;
-	
-	/*if( self->integrationSwarm ) Stg_Class_Delete( self->integrationSwarm );*/
-        /*
-	if( self->fieldCount ) {
-		Memory_Free( self->gAnalyticSq );
-		Memory_Free( self->gErrorSq    );
-		Memory_Free( self->gError      );
-		Memory_Free( self->gErrorNorm  );
-
-		Memory_Free( self->analyticSolnForFeVarKey );
-		Memory_Free( self->_analyticSolutionList );
-	}
-
-	if( self->swarmVarCount ) {
-	   Index swarmVar_I;
-		for( swarmVar_I = 0; swarmVar_I < self->swarmVarCount; swarmVar_I++ ) 
-			Memory_Free(self->swarmVarNameList[swarmVar_I]); 
-		Memory_Free( self->swarmVarNameList );
-	}
-	
-	Memory_Free( self->referenceSolnPath );
-	Memory_Free( self->expectedFileName );
-	Memory_Free( self->expectedFilePath );
-	Memory_Free( self->dumpExpectedFileName );
-        */
-	
-	/* Stg_Class_Delete parent*/
-	_Stg_Component_Delete( self );
-}
-
-void _FieldTest_Print( void* fieldTest, Stream* stream ) {
-	FieldTest* self = (FieldTest*)fieldTest;
-	
-	/* Print parent */
-	_Stg_Component_Print( self, stream );
-	
-}
-
-void* _FieldTest_Copy( const void* fieldTest, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	abort();
-	return NULL;
-}
-
-void _FieldTest_AssignFromXML( void* fieldTest, Stg_ComponentFactory* cf, void* data ) {
-	FieldTest*					self = (FieldTest*)fieldTest;
-	Dictionary*					dict = cf->rootDict;
-	Dictionary_Entry_Value*	dictEntryVal = Dictionary_Get( dict, (Dictionary_Entry_Key)"pluginData" );
-	Dictionary*					pluginDict =  Dictionary_Entry_Value_AsDictionary( dictEntryVal  );
-	/* get the pluginDict from the xml, needed for rejig */
-	Dictionary*					pluginDict2	= Codelet_GetPluginDictionary( self, cf->rootDict );
-	Dictionary_Entry_Value*	fieldList;
-	Dictionary_Entry_Value*	swarmVarList = Dictionary_Get( dict, (Dictionary_Entry_Key)"NumericSwarmVariableNames"  );
-	FieldVariable_Register*	fV_Register;
-	Index							feVariable_I/*, referenceFieldCount*/;
-	Index							swarmVar_I;
-	char*							fieldName;
-	Hook*							generateErrorFields;
-	Hook*							physicsTestHook;
-	Stream*						errStream = Journal_Register( Error_Type, (Name)"FieldTests"  );
-
-	Journal_Firewall( pluginDict != NULL , errStream, "\nError in %s: No pluginData xml was defined ... aborting\n", __func__ );
-
-	self->context = Stg_ComponentFactory_ConstructByName( cf, Dictionary_GetString( pluginDict2, (Dictionary_Entry_Key)"Context"  ), DomainContext, False, data );
-	if( !self->context ) 
-		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", DomainContext, True, data  );
-
-	fV_Register = self->context->fieldVariable_Register;
-
-	fieldList = Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"NumericFields" );
-	self->fieldCount = fieldList ? Dictionary_Entry_Value_GetCount( fieldList ) / 2 : 0;
-
-	if( self->fieldCount  ) {
-		self->numericFieldList   	= Memory_Alloc_Array( FeVariable*, self->fieldCount, "numeric fields" );
-		self->referenceFieldList 	= Memory_Alloc_Array( FeVariable*, self->fieldCount, "reference fields" );
-		self->errorFieldList     	= Memory_Alloc_Array( FeVariable*, self->fieldCount, "error fields" );
-		self->referenceMagFieldList	= Memory_Alloc_Array( OperatorFeVariable*, self->fieldCount, "reference field magnitudes" );
-		self->errorMagFieldList		= Memory_Alloc_Array( OperatorFeVariable*, self->fieldCount, "error field magnitudes" );
-	
-		if( !self->referenceSolnFromFile ) {
-			self->analyticSolnForFeVarKey = Memory_Alloc_Array( unsigned, self->fieldCount, 
-								    "analytic solution index for ith feVariable" );
-		}
-#if 0	
-		else {
-			fieldList = Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"ReferenceFields" );
-			referenceFieldCount = fieldList ? Dictionary_Entry_Value_GetCount( fieldList ) : assert(0);
-
-			for( feVariable_I = 0; feVariable_I < referenceFieldCount; feVariable_I++ ) {
-				referenceSolnFileList
-			}
-		}
-#endif
-
-		for( feVariable_I = 0; feVariable_I < self->fieldCount; feVariable_I++ ) {
-			/* read in the FeVariable from the tuple */
-			fieldName = ( fieldList  ) ? 
-				    StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( fieldList, 2 * feVariable_I ) ) ):
-				    StG_Strdup( Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"FeVariable" ) );
-			
-			self->numericFieldList[feVariable_I] = (FeVariable* ) FieldVariable_Register_GetByName( fV_Register, fieldName );
-
-			if( !self->numericFieldList[feVariable_I] ) {
-				/* if the numericFieldList[x] can't be found in register 
-					 and can't be constructed through the factory then 
-					 skip this entry and take one off self->fieldCount 
-					 needed for simple regression test
-				 */
-				self->numericFieldList[feVariable_I] = Stg_ComponentFactory_ConstructByName( cf, (Name)fieldName, FeVariable, False, data ); 
-				if( self->numericFieldList[feVariable_I]==NULL  ) { 
-					self->fieldCount--; 
-					continue; 
-				}
-			}
-
-			/* ...and the corresponding analytic function ptr index - these have to be consistent with how they're ordered in the plugin */
-			self->analyticSolnForFeVarKey[feVariable_I] = Dictionary_Entry_Value_AsUnsignedInt( 
-									Dictionary_Entry_Value_GetElement( fieldList, 2 * feVariable_I + 1 ) );
-			Memory_Free( fieldName );
-		}
-	}
-
-	self->integrationSwarm 	= (Swarm*)LiveComponentRegister_Get( cf->LCRegister, Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"IntegrationSwarm" ) ) );
-	self->constantMesh     	= (FeMesh* )LiveComponentRegister_Get( cf->LCRegister, Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"ConstantMesh"     ) ) );
-	self->elementMesh      	= (FeMesh* )LiveComponentRegister_Get( cf->LCRegister, Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"ElementMesh"      ) ) );
-
-	self->swarmVarCount = swarmVarList ? Dictionary_Entry_Value_GetCount( swarmVarList ) : 0;
-	if( self->swarmVarCount  ) {
-		self->swarmVarNameList = Memory_Alloc_Array( Name, self->swarmVarCount, "numeric swarm variable names" );
-	
-		for( swarmVar_I = 0; swarmVar_I < self->swarmVarCount; swarmVar_I++ ) {
-			self->swarmVarNameList[swarmVar_I] = ( swarmVarList ) ? 
-					StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( swarmVarList, swarmVar_I ) ) ):
-					StG_Strdup( Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"SwarmVariable" )  );
-		}	
-	}
-	
-	self->referenceSolnPath     = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"referenceSolutionFilePath" ) )  );
-	self->normalise             = Dictionary_Entry_Value_AsBool( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"normaliseByAnalyticSolution" )  );
-	self->epsilon               = Dictionary_Entry_Value_AsDouble( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"epsilon" )  );
-	self->testTimestep          = Dictionary_GetInt_WithDefault( pluginDict, (Dictionary_Entry_Key)"testTimestep", 0  );
-	self->referenceSolnFromFile = Dictionary_Entry_Value_AsBool( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"useReferenceSolutionFromFile" )  );
-	self->appendToAnalysisFile  = Dictionary_GetBool_WithDefault( pluginDict, (Dictionary_Entry_Key)"appendToAnalysisFile", False  ) ;
-
-	/* for the physics test */
-	self->expectedFileName     = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"expectedFileName" ) )  );
-	self->expectedFilePath     = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"expectedFilePath" ) )  );
-	self->dumpExpectedFileName = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"expectedOutputFileName" ) )  );
-	self->expectedPass     = False;
-
-	/* set up the entry point */
-	generateErrorFields = Hook_New( "Generate error fields hook", (void*)FieldTest_GenerateErrFields, self->name );
-	_EntryPoint_AppendHook( Context_GetEntryPoint( self->context, AbstractContext_EP_FrequentOutput ), generateErrorFields );
-
-	/* entry point for the fisix test func */
-	if( strlen(self->expectedFileName) > 1 ) {
-          physicsTestHook = Hook_New( "Physics test hook", (void*)FieldTest_EvaluatePhysicsTest, self->name );
-		_EntryPoint_AppendHook( Context_GetEntryPoint( self->context, AbstractContext_EP_FrequentOutput ), physicsTestHook );
-	}
-
-	self->LCRegister = cf->LCRegister;
-}
-
-void _FieldTest_Build( void* fieldTest, void* data ) {
-	FieldTest* 		self 		= (FieldTest*) fieldTest;
-	Index			field_I;
-	//Index			swarm_I;
-
-	if( self->constantMesh ) Stg_Component_Build( self->constantMesh,  data, False );
-
-	for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
-		FieldTest_BuildAnalyticField( self, field_I );
-		FieldTest_BuildErrField( self, field_I );
-	
-		Stg_Component_Build( self->numericFieldList[field_I], data, False );
-		Stg_Component_Build( self->errorFieldList[field_I], data, False );
-
-		Stg_Component_Build( self->referenceFieldList[field_I], data, False );
-		Stg_Component_Build( self->errorFieldList[field_I], data, False );
-	}
-
-	/*for( swarm_I = 0; swarm_I < self->swarmCount; swarm_I++ ) {
-		FieldTest_BuildAnalyticSwarm( self->referenceMesh, self->numericSwarmList[swarm_I], 
-					       self->context, &self->referenceSwarmList[swarm_I] );
-		FieldTest_BuildErrSwarm( self->constantMesh, self->numericSwarmList[swarm_I], 
-					 self->context, &self->referenceSwarmList[swarm_I] );
-	}*/
-
-	if( self->fieldCount ) {
-		self->gAnalyticSq = Memory_Alloc_2DArray( double, self->fieldCount, 9, (Name)"global reference solution squared"  );
-		self->gErrorSq 	  = Memory_Alloc_2DArray( double, self->fieldCount, 9, (Name)"global L2 error squared"  );
-		self->gError	  = Memory_Alloc_2DArray( double, self->fieldCount, 9, (Name)"global L2 error"  );
-		self->gErrorNorm  = Memory_Alloc_2DArray( double, self->fieldCount, 9, (Name)"global L2 error normalised"  );
-	}
-}
-
-void _FieldTest_Initialise( void* fieldTest, void* data ) {
-	FieldTest* 		self 		= (FieldTest*) fieldTest;
-	Index			field_I;
-	FILE*			expected_fp;
-	char*			expectedFilename;
-	int			num_time_steps;
-	int			dof_i, dim_i;
-	int			expected_i 	= 0;
-
-	for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
-		Stg_Component_Initialise( self->numericFieldList[field_I], data, False );
-		Stg_Component_Initialise( self->errorFieldList[field_I], data, False );
-		Stg_Component_Initialise( self->referenceFieldList[field_I], data, False );
-		if( self->referenceMagFieldList[field_I] )
-			Stg_Component_Initialise( self->referenceMagFieldList[field_I], data, False );
-		if( self->errorMagFieldList[field_I] )
-			Stg_Component_Initialise( self->errorMagFieldList[field_I], data, False );
-	}
-
-	/* load the reference solution from file if req'd */
-	if( self->referenceSolnFromFile ) {
-		char *referenceSolnFileName;
-		for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
-			/* create the name of the reference file, the apprendix is handled by FieldTest_LoadReferenceSolutionFromFile */
-			referenceSolnFileName = Memory_Alloc_Array_Unnamed( char, strlen((char*)self->referenceSolnPath) + 1 + strlen((char*)self->numericFieldList[field_I]->name) + 1 + 5 + strlen(".h5x\0") );
-#ifdef READ_HDF5
-			sprintf( referenceSolnFileName, "%s/%s.%.5d.h5", self->referenceSolnPath, self->numericFieldList[field_I]->name, self->testTimestep );
-#else
-			sprintf( referenceSolnFileName, "%s/%s.%.5d.dat", self->referenceSolnPath, self->numericFieldList[field_I]->name, self->testTimestep );
-#endif
-			FeVariable_ReadFromFile( self->referenceFieldList[field_I], referenceSolnFileName );
-
-	/*		FieldTest_LoadReferenceSolutionFromFile( self->referenceFieldList[field_I],
-																								referenceSolnFileName,
-																								self->referenceSolnPath, self->context ); */
-			Memory_Free( referenceSolnFileName );
-		}
-	}
-	/* calculate the analytic solutions */
-	else {
-		for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
-			FieldTest_CalculateAnalyticSolutionForField( self, field_I ); 
-			FeVariable_ZeroField( self->errorFieldList[field_I] );
-		}
-	}
-
-	if( strlen(self->expectedFileName) > 1 && strcmp( self->expectedFileName, "false" ) ) {
-		/* if the self->expectedFileName == False then don't go here */
-		expectedFilename = Memory_Alloc_Array_Unnamed( char, strlen(self->expectedFilePath) + strlen(self->expectedFileName) + 1 );
-		sprintf( expectedFilename, "%s%s", self->expectedFilePath, self->expectedFileName );
-
-		expected_fp = fopen( expectedFilename, "r" );
-
-		fscanf( expected_fp, "%d %d", &self->expectedDofs, &num_time_steps );
-	
-		self->expected  = Memory_Alloc_Array_Unnamed( Event, num_time_steps + 1 );
-		self->numeric   = Memory_Alloc_Array_Unnamed( Event, self->context->maxTimeSteps + 1 );
-		self->tolerance = Memory_Alloc_Array_Unnamed( Event, num_time_steps + 1 );
-
-		while ( !feof( expected_fp ) ) {
-			fscanf( expected_fp, "%lf ", &self->expected[expected_i].time );
-			
-			for( dim_i = 0; dim_i < self->context->dim; dim_i++ )
-				fscanf( expected_fp, "%lf ", &self->expected[expected_i].place[dim_i] );
-
-			for( dof_i = 0; dof_i < self->expectedDofs; dof_i++ )
-				fscanf( expected_fp, "%lf ", &self->expected[expected_i].value[dof_i] );
-
-			fscanf( expected_fp, "%lf ", &self->tolerance[expected_i].time );
-			
-			for( dim_i = 0; dim_i < self->context->dim; dim_i++ )
-				fscanf( expected_fp, "%lf ", &self->tolerance[expected_i].place[dim_i] );
-
-			for( dof_i = 0; dof_i < self->expectedDofs; dof_i++ )
-				fscanf( expected_fp, "%lf ", &self->tolerance[expected_i].value[dof_i] );
-
-			expected_i++;
-		}
-		fclose( expected_fp );
-
-		Memory_Free( expectedFilename );
-	}
-}
-
-void FieldTest_CalculateAnalyticSolutionForField( void* fieldTest, Index field_I ) {
-	FieldTest* 			self 		= (FieldTest*) fieldTest;
-	FeVariable*			analyticField	= self->referenceFieldList[field_I];
-	FeMesh*				analyticMesh	= analyticField->feMesh;
-	FieldTest_AnalyticSolutionFunc*	analyticSolution;
-	Index				lNode_I;
-	Index				lMeshSize	= Mesh_GetLocalSize( analyticMesh, MT_VERTEX );
-	double*				coord;
-	double*				value;
-	
-	analyticSolution = self->_analyticSolutionList[self->analyticSolnForFeVarKey[field_I]];
-	value = Memory_Alloc_Array_Unnamed( double, analyticField->fieldComponentCount );
-	memset( value, 0, analyticField->fieldComponentCount * sizeof(double) );
-
-	for( lNode_I = 0; lNode_I < lMeshSize; lNode_I++ ) {
-		coord = Mesh_GetVertex( analyticMesh, lNode_I );
-		analyticSolution( self, coord, value );
-		FeVariable_SetValueAtNode( analyticField, lNode_I, value );
-	}
-
-	Memory_Free( value );
-}
-
-void _FieldTest_Execute( void* fieldTest, void* data ) {
-}
-
-void _FieldTest_Destroy( void* fieldTest, void* data ) {
-	FieldTest* self = (FieldTest*) fieldTest;
-
-	if( self->fieldCount ) {
-		Memory_Free( self->numericFieldList );
-		Memory_Free( self->referenceFieldList );
-		Memory_Free( self->errorFieldList );
-		Memory_Free( self->referenceMagFieldList );
-		Memory_Free( self->errorMagFieldList );
-
-		Memory_Free( self->gAnalyticSq );
-		Memory_Free( self->gErrorSq );
-		Memory_Free( self->gError );
-		Memory_Free( self->gErrorNorm );
-	}
-
-	if( strlen(self->expectedFileName) > 1 ) {
-		Memory_Free( self->expected );
-		Memory_Free( self->numeric );
-		Memory_Free( self->tolerance );
-	}
-	if( !self->referenceSolnFromFile ) {
-		Memory_Free( self->analyticSolnForFeVarKey );
-		Memory_Free( self->_analyticSolutionList );
-	}
-
-	Stg_Component_Destroy( self, data, False );
-}
-
-void FieldTest_BuildAnalyticField( void* fieldTest, Index field_I ) {
-	FieldTest*				self = (FieldTest*) fieldTest;
-	FeVariable*				numericField = self->numericFieldList[field_I];
-	FeMesh*					referenceMesh = numericField->feMesh;
-	DomainContext*			context = self->context;
-	Variable_Register*	variable_Register	= context->variable_Register;
-	char*						tmpName;
-	Dof_Index				componentsCount = numericField->fieldComponentCount;
-	char*						varName[9];
-	unsigned					var_I;
-	unsigned					node_I;
-	Variable*				variable;
-	Variable*				baseVariable = NULL;
-	DofLayout*				referenceDofLayout	= NULL;
-
-	unsigned					nDomainVerts = Mesh_GetDomainSize( referenceMesh, MT_VERTEX );
-	static double*			arrayPtr;
-
-	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"AnalyticVariable" );
-
-	if( componentsCount == 1  ) {
-		arrayPtr = Memory_Alloc_Array_Unnamed( double, nDomainVerts );
-		baseVariable = Variable_NewScalar( tmpName, (AbstractContext*)self->context, Variable_DataType_Double, (Index*)&nDomainVerts, NULL, (void**)&arrayPtr, variable_Register );
-	}
-	else {
-		for( var_I = 0; var_I < componentsCount; var_I++  )
-			Stg_asprintf( &varName[var_I], "%s-Component-%d", tmpName, var_I );
-
-		arrayPtr = Memory_Alloc_Array_Unnamed( double, nDomainVerts * componentsCount );
-		baseVariable = Variable_NewVector( tmpName, 
-							(AbstractContext*)self->context,
-						   Variable_DataType_Double, 
-						   componentsCount, 
-						   &nDomainVerts,
-						   NULL, 
-						   (void**)&arrayPtr, 
-						   variable_Register,
-						   varName[0], varName[1], varName[2], 
-						   varName[3], varName[4], varName[5], 
-						   varName[6], varName[7], varName[8] );
-	}
-	Memory_Free( tmpName );
-
-	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"AnalyticDofLayout"  );
-
-	referenceDofLayout = DofLayout_New( tmpName, self->context, variable_Register, Mesh_GetDomainSize( referenceMesh, MT_VERTEX ), referenceMesh );
-
-	if( componentsCount == 1 )
-		DofLayout_AddAllFromVariableArray( referenceDofLayout, 1, &baseVariable );
-	else {
-		for( var_I = 0; var_I < componentsCount; var_I++ ) {
-			variable = Variable_Register_GetByName( variable_Register, varName[var_I] );
-			variable->arrayPtrPtr = &baseVariable->arrayPtr;
-
-			for( node_I = 0; node_I < Mesh_GetDomainSize( referenceMesh, MT_VERTEX ); node_I++ )
-				DofLayout_AddDof_ByVarName( referenceDofLayout, varName[var_I], node_I );
-
-			Memory_Free( varName[var_I] );
-		}
-
-	}
-
-	Stg_Component_Build( referenceDofLayout, NULL, False );
-	Stg_Component_Initialise( referenceDofLayout, NULL, False );
-
-	Memory_Free( tmpName );
-
-	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"Analytic"  );
-
-	self->referenceFieldList[field_I] = FeVariable_New( tmpName, self->context, referenceMesh, referenceMesh, referenceDofLayout, NULL, NULL, NULL, 
-		Mesh_GetDimSize( referenceMesh ), False, False, False, context->fieldVariable_Register );
-	self->referenceFieldList[field_I]->context = context;
-	/* so that the eqnation numbers don't get built for this guy */
-	self->referenceFieldList[field_I]->buildEqNums = False;
-
-	if( componentsCount > Mesh_GetDimSize( referenceMesh ) ) {
-		/* we're dealing with a tensor, so use invariant */
-		tmpName = Stg_Object_AppendSuffix( self->referenceFieldList[field_I], (Name)"Invariant"  );
-		self->referenceMagFieldList[field_I] = OperatorFeVariable_NewUnary( tmpName, self->context, self->referenceFieldList[field_I], "SymmetricTensor_Invariant" );
-		self->referenceMagFieldList[field_I]->context = context;
-	} else {
-		/* we're dealing with a vector, so use magnitude */
-		tmpName = Stg_Object_AppendSuffix( self->referenceFieldList[field_I], (Name)"Magnitude"  );
-		self->referenceMagFieldList[field_I] = OperatorFeVariable_NewUnary( tmpName, self->context, self->referenceFieldList[field_I], "Magnitude" );
-		self->referenceMagFieldList[field_I]->context = context;
-	}
-
-	Memory_Free( tmpName );
-	Stg_Component_Build( self->referenceMagFieldList[field_I], context, False );
-	self->referenceMagFieldList[field_I]->_operator = Operator_NewFromName( self->referenceMagFieldList[field_I]->operatorName, 
-		self->referenceFieldList[field_I]->fieldComponentCount, context->dim );
-	self->referenceMagFieldList[field_I]->fieldComponentCount = self->referenceMagFieldList[field_I]->_operator->resultDofs;
-	_OperatorFeVariable_SetFunctions( self->referenceMagFieldList[field_I] );
-
-	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) baseVariable );
-	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) referenceDofLayout );
-	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) self->referenceFieldList[field_I] );
-	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) self->referenceMagFieldList[field_I] );
-}
-
-void FieldTest_BuildErrField( void* fieldTest, Index field_I ) {
-	FieldTest*				self = (FieldTest*) fieldTest;
-	FeMesh*					constantMesh = self->constantMesh;
-	FeVariable*				numericField = self->numericFieldList[field_I];
-	DomainContext*			context = self->context;
-	Variable_Register*	variable_Register	= context->variable_Register;
-	char*						tmpName;
-	Dof_Index				componentsCount = numericField->fieldComponentCount;
-	char*						varName[9];
-	unsigned					var_I;
-	unsigned					node_I;
-	Variable*				variable;
-	Variable*				baseVariable = NULL;
-	DofLayout*				errorDofLayout = NULL;
-	unsigned					nDomainVerts = Mesh_GetDomainSize( constantMesh, MT_VERTEX );
-	static void*			arrayPtr;
-
-	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"ErrorVariable" );
-
-	if( componentsCount == 1  ) {
-		arrayPtr = Memory_Alloc_Array_Unnamed( double, nDomainVerts );
-		baseVariable = Variable_NewScalar( tmpName, (AbstractContext*)self->context, Variable_DataType_Double, (Index*)&nDomainVerts, NULL, &arrayPtr, variable_Register );
-	}
-	else {
-		for( var_I = 0; var_I < componentsCount; var_I++  )
-			Stg_asprintf( &varName[var_I], "%s-Component-%d", tmpName, var_I );
-
-		arrayPtr = Memory_Alloc_Array_Unnamed( double, nDomainVerts * componentsCount );
-		baseVariable = Variable_NewVector( tmpName, (AbstractContext*)self->context, Variable_DataType_Double, componentsCount, &nDomainVerts, 
-						   NULL, (void**)&arrayPtr, variable_Register,
-						   varName[0], varName[1], varName[2], varName[3], varName[4],
-						   varName[5], varName[6], varName[7], varName[8] );
-	}
-	Memory_Free( tmpName );
-
-	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"ErrorDofLayout"  );
-
-	errorDofLayout = DofLayout_New( tmpName, self->context, variable_Register, Mesh_GetDomainSize( constantMesh, MT_VERTEX ), constantMesh );
-
-	if( componentsCount == 1 )
-		DofLayout_AddAllFromVariableArray( errorDofLayout, 1, &baseVariable );
-	else {
-		for( var_I = 0; var_I < componentsCount; var_I++ ) {
-			variable = Variable_Register_GetByName( variable_Register, varName[var_I] );
-			variable->arrayPtrPtr = &baseVariable->arrayPtr;
-
-			for( node_I = 0; node_I < Mesh_GetDomainSize( constantMesh, MT_VERTEX ); node_I++ )
-				DofLayout_AddDof_ByVarName( errorDofLayout, varName[var_I], node_I );
-
-			Memory_Free( varName[var_I] );
-		}
-		
-		//errorDofLayout->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, componentsCount );
-		//errorDofLayout->baseVariables[0] = baseVariable;
-	}
-	
-	Stg_Component_Build( errorDofLayout, NULL, False );
-	Stg_Component_Initialise( errorDofLayout, NULL, False );
-
-	Memory_Free( tmpName );
-
-	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"Error"  );
-
-	self->errorFieldList[field_I] = FeVariable_New( tmpName, self->context, constantMesh, constantMesh, errorDofLayout, NULL, NULL, NULL, 
-		Mesh_GetDimSize( constantMesh ), False, False, False, context->fieldVariable_Register );
-	/* so that the eqnation numbers don't get built for this guy */
-	self->errorFieldList[field_I]->buildEqNums = False;
-
-	if( componentsCount > Mesh_GetDimSize( constantMesh ) ) {
-		/* we're dealing with a tensor, so use invariant */
-		tmpName = Stg_Object_AppendSuffix( self->errorFieldList[field_I], (Name)"Invariant"  );
-		self->errorMagFieldList[field_I] = OperatorFeVariable_NewUnary( tmpName, self->context, self->errorFieldList[field_I], "SymmetricTensor_Invariant" );
-		self->errorMagFieldList[field_I]->context = context;
-	} else {
-		/* we're dealing with a vector, so use magnitude */
-		tmpName = Stg_Object_AppendSuffix( self->errorFieldList[field_I], (Name)"Magnitude"  );
-		self->errorMagFieldList[field_I] = OperatorFeVariable_NewUnary( tmpName, self->context, self->errorFieldList[field_I], "Magnitude" );
-		self->errorMagFieldList[field_I]->context = context;
-	}
-	Memory_Free( tmpName );
-	Stg_Component_Build( self->errorMagFieldList[field_I], context, False );
-	self->errorMagFieldList[field_I]->_operator = Operator_NewFromName( self->errorMagFieldList[field_I]->operatorName, 
-		self->errorFieldList[field_I]->fieldComponentCount, context->dim );
-	self->errorMagFieldList[field_I]->fieldComponentCount = self->errorMagFieldList[field_I]->_operator->resultDofs;
-	_OperatorFeVariable_SetFunctions( self->errorMagFieldList[field_I] );
-
-	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) baseVariable );
-	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) errorDofLayout );
-	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) self->errorFieldList[field_I] );
-	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) self->errorMagFieldList[field_I] );
-}
-
-void FieldTest_LoadReferenceSolutionFromFile( FeVariable* feVariable, Name referenceSolnName, Name referenceSolnPath, DomainContext* context ) {
-	FeMesh*			feMesh			= feVariable->feMesh;
-	char*			filename;
-	unsigned		nx = 0, ny = 0, nz = 0, total;
-	unsigned		lineNum = 0;
-	double			resolution[3];
-	double*			coord;
-	Index			node_I, dim_I;
-	unsigned		increments[3];
-	double			value[3];
-	unsigned		lineNum0;
-	unsigned		dofAtEachNodeCount, dof_I;
-	unsigned		meshSize 		= Mesh_GetLocalSize( feMesh, MT_VERTEX );
-	unsigned		nDims			= Mesh_GetDimSize( feMesh );
-	double			vertex0[3], coordPrime[3];
-	double			Ni[27], values[27][3];
-	unsigned		shapeFunc_I;
-	double			*posx, *posy, *posz;
-	double			**variables;
-	unsigned		numShapeFuncs 		= ( nDims == 3 ) ? 27 : 9;
-	double 			xi, eta, zeta;
-	double 			a0, b0, c0;
-	double 			a1, b1, c1;
-	double 			a2, b2, c2;
-	double 			m0, m1, m2, m3, m4, m5, m6;
-#ifdef READ_HDF5
-	hid_t			inputFile;
-	hid_t 			dataSet, memSpace, dataSpace;
-	hsize_t 		start[2], count[2], hSize;
-#endif
-	int 			sizes[3];
-	double* 		data;
-	int 			dataPos = 0;
-	double			nodeDummy;
-
-	Stg_Component_Initialise( feMesh,     context, False );
-	Stg_Component_Initialise( feVariable, context, False );
-
-	dofAtEachNodeCount = feVariable->fieldComponentCount;
-													  /* .  h5  \0 */
-	filename = Memory_Alloc_Array_Unnamed( char, strlen(referenceSolnPath) + strlen(referenceSolnName) + 1 + 2 + 1 );
-	sprintf( filename, "%s%s.h5", referenceSolnPath, referenceSolnName );
-#ifdef READ_HDF5
-	inputFile = H5Fopen( filename, H5F_ACC_RDONLY, H5P_DEFAULT );
-#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-	dataSet = H5Dopen( inputFile, "/size" );
-#else
-	dataSet = H5Dopen2( inputFile, "/size", H5P_DEFAULT );
-#endif
-	H5Dread( dataSet, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, sizes );
-	nx = sizes[0];
-	ny = sizes[1];
-	total = nx * ny;
-	if( nDims == 3 ) {
-		nz = sizes[2];
-		total *= nz;
-	}
-	H5Dclose( dataSet );
-
-	posx = Memory_Alloc_Array_Unnamed( double, total );
-	posy = Memory_Alloc_Array_Unnamed( double, total );
-	if( nDims == 3 ) posz = Memory_Alloc_Array_Unnamed( double, total );
-	variables = Memory_Alloc_2DArray_Unnamed( double, total, dofAtEachNodeCount );
-	data = Memory_Alloc_Array_Unnamed( double, nDims + dofAtEachNodeCount );
-
-	hSize = nDims + dofAtEachNodeCount;
-	memSpace = H5Screate_simple( 1, &hSize, NULL );
-	H5Sselect_all( memSpace );
-#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-	dataSet = H5Dopen( inputFile, "/data" );
-#else
-	dataSet = H5Dopen2( inputFile, "/data", H5P_DEFAULT );
-#endif
-	dataSpace = H5Dget_space( dataSet );
-	start[0] = 0;
-	start[1] = 0;
-	count[0] = 1;
-	count[1] = nDims + dofAtEachNodeCount;
-	H5Sselect_hyperslab( dataSpace, H5S_SELECT_SET, start, NULL, count, NULL );
-	for( lineNum = 0; lineNum < total; lineNum++ ) {
-		start[0] = lineNum;
-		H5Sselect_hyperslab( dataSpace, H5S_SELECT_SET, start, NULL, count, NULL );
-		H5Dread( dataSet, H5T_NATIVE_DOUBLE, memSpace, dataSpace, H5P_DEFAULT, data );
-
-      dataPos  = 0;
-		nodeDummy = data[dataPos++];
-		posx[lineNum] = data[dataPos++];
-		posy[lineNum] = data[dataPos++];
-		if( nDims == 3 ) posz[lineNum] = data[dataPos++];
-
-		for( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ )
-			variables[lineNum][dof_I] = data[dataPos++];
-	}
-
-	H5Sclose( memSpace );
-	H5Sclose( dataSpace );
-	H5Dclose( dataSet );
-#endif
-	Memory_Free( data );
-
-	resolution[0] = posx[1]  - posx[0];
-	resolution[1] = posy[nx] - posy[0];
-	if( nDims == 3 ) resolution[2] = posz[nx*ny] - posz[0];
-
-	for( node_I = 0; node_I < meshSize; node_I++ ) {
-		coord = Mesh_GetVertex( feMesh, node_I );
-		increments[0] = (unsigned)( ( coord[0] - posx[0] ) / resolution[0] );
-		increments[1] = (unsigned)( ( coord[1] - posy[0] ) / resolution[1] );
-		if( nDims == 3 ) increments[2] = (unsigned)( ( coord[2] - posz[0] ) / resolution[2] );
-			
-		for( dim_I = 0; dim_I < nDims; dim_I++ ) 
-			if( increments[dim_I] % 2 == 1 )
-				increments[dim_I]--;
-		if( increments[0] >= nx - 2 )
-			increments[0] = nx - 3;
-		if( increments[1] >= ny - 2 )
-			increments[1] = ny - 3;
-		if( nDims == 3 && increments[2] >= nz - 2 )
-			increments[2] = nz - 3;
-
-		lineNum0 = increments[0] + nx * increments[1];
-		if( nDims == 3 ) lineNum0 += nx * ny * increments[2];
-		if( lineNum0 >= total )
-			Journal_Printf( context->info, "interpolation error: node value: %d resolution size: %d\n", lineNum0, total );
-			
-		vertex0[0] = posx[lineNum0];
-		vertex0[1] = posy[lineNum0];
-		if( nDims == 3 ) vertex0[2] = posz[lineNum0];
-		
-		/* for quadratic elements the resolution is twice the distance between the nodes */
-		for( dim_I = 0; dim_I < nDims; dim_I++ )
-			coordPrime[dim_I] = ( coord[dim_I] - vertex0[dim_I] ) / resolution[dim_I] - 1.0;
-
-		/* assign the shape functions & interpolate quadratically */
-		if( nDims == 2 ) {
-			xi = coordPrime[0]; eta = coordPrime[1];
-			a0 = xi - 1.0; b0 = eta - 1.0;
-			a1 = 1.0 - xi * xi; b1 = 1.0 - eta * eta;
-			a2 = xi + 1.0; b2 = eta + 1.0;
-			m0 = 0.5 * xi; m1 = 0.5 * eta; m2 = 0.25 * xi * eta;
-
-			Ni[0] = m2 * a0 * b0; Ni[1] = m1 * a1 * b0; Ni[2] = m2 * a2 * b0;
-			Ni[3] = m0 * a0 * b1; Ni[4] =      a1 * b1; Ni[5] = m0 * a2 * b1;
-			Ni[6] = m2 * a0 * b2; Ni[7] = m1 * a1 * b2; Ni[8] = m2 * a2 * b2;
-
-			for( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
-				values[0][dof_I] = variables[lineNum0][dof_I];
-				values[1][dof_I] = variables[lineNum0+1][dof_I];
-				values[2][dof_I] = variables[lineNum0+2][dof_I];
-				values[3][dof_I] = variables[lineNum0+nx][dof_I];
-				values[4][dof_I] = variables[lineNum0+nx+1][dof_I];
-				values[5][dof_I] = variables[lineNum0+nx+2][dof_I];
-				values[6][dof_I] = variables[lineNum0+(2*nx)][dof_I];
-				values[7][dof_I] = variables[lineNum0+(2*nx)+1][dof_I];
-				values[8][dof_I] = variables[lineNum0+(2*nx)+2][dof_I];
-					
-				value[dof_I] = 0.0;
-				for( shapeFunc_I = 0; shapeFunc_I < numShapeFuncs; shapeFunc_I++ )
-					value[dof_I] += Ni[shapeFunc_I] * values[shapeFunc_I][dof_I];
-			}
-		}
-		else {
-			xi = coordPrime[0]; eta = coordPrime[1]; zeta = coordPrime[2];
-			a0 = xi - 1.0; b0 = eta - 1.0; c0 = zeta - 1.0;
-			a1 = 1.0 - xi * xi; b1 = 1.0 - eta * eta; c1 = 1.0 - zeta * zeta;
-			a2 = xi + 1.0; b2 = eta + 1.0; c2 = zeta + 1.0;
-			m0 = 0.5 * xi; m1 = 0.5 * eta; m2 = 0.5 * zeta;
-			m3 = 0.25 * xi * eta; m4 = 0.25 * xi * zeta; m5 = 0.25 * eta * zeta;
-			m6 = 0.125 * xi * eta * zeta;
-
-			Ni[0]  = m6 * a0 * b0 * c0; Ni[1]  = m5 * a1 * b0 * c0; Ni[2]  = m6 * a2 * b0 * c0;
-			Ni[3]  = m4 * a0 * b1 * c0; Ni[4]  = m2 * a1 * b1 * c0; Ni[5]  = m4 * a2 * b1 * c0;
-			Ni[6]  = m6 * a0 * b2 * c0; Ni[7]  = m5 * a1 * b2 * c0; Ni[8]  = m6 * a2 * b2 * c0;
-
-			Ni[9]  = m3 * a0 * b0 * c1; Ni[10] = m1 * a1 * b0 * c1; Ni[11] = m3 * a2 * b0 * c1;
-			Ni[12] = m0 * a0 * b1 * c1; Ni[13] =      a1 * b1 * c1; Ni[14] = m0 * a2 * b1 * c1;
-			Ni[15] = m3 * a0 * b2 * c1; Ni[16] = m1 * a1 * b2 * c1; Ni[17] = m3 * a2 * b2 * c1;
-
-			Ni[18] = m6 * a0 * b0 * c2; Ni[19] = m5 * a1 * b0 * c2; Ni[20] = m6 * a2 * b0 * c2;
-			Ni[21] = m4 * a0 * b1 * c2; Ni[22] = m2 * a1 * b1 * c2; Ni[23] = m4 * a2 * b1 * c2;
-			Ni[24] = m6 * a0 * b2 * c2; Ni[25] = m5 * a1 * b2 * c2; Ni[26] = m6 * a2 * b2 * c2;
-				
-			for( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
-				values[0][dof_I]  = variables[lineNum0][dof_I];
-				values[1][dof_I]  = variables[lineNum0+1][dof_I];
-				values[2][dof_I]  = variables[lineNum0+2][dof_I];
-				values[3][dof_I]  = variables[lineNum0+nx][dof_I];
-				values[4][dof_I]  = variables[lineNum0+nx+1][dof_I];
-				values[5][dof_I]  = variables[lineNum0+nx+2][dof_I];
-				values[6][dof_I]  = variables[lineNum0+(2*nx)][dof_I];
-				values[7][dof_I]  = variables[lineNum0+(2*nx)+1][dof_I];
-				values[8][dof_I]  = variables[lineNum0+(2*nx)+2][dof_I];
-
-				values[9][dof_I]  = variables[lineNum0+(nx*ny)][dof_I];
-				values[10][dof_I] = variables[lineNum0+(nx*ny)+1][dof_I];
-				values[11][dof_I] = variables[lineNum0+(nx*ny)+2][dof_I];
-				values[12][dof_I] = variables[lineNum0+(nx*ny)+nx][dof_I];
-				values[13][dof_I] = variables[lineNum0+(nx*ny)+nx+1][dof_I];
-				values[14][dof_I] = variables[lineNum0+(nx*ny)+nx+2][dof_I];
-				values[15][dof_I] = variables[lineNum0+(nx*ny)+(2*nx)][dof_I];
-				values[16][dof_I] = variables[lineNum0+(nx*ny)+(2*nx)+1][dof_I];
-				values[17][dof_I] = variables[lineNum0+(nx*ny)+(2*nx)+2][dof_I];
-
-				values[18][dof_I] = variables[lineNum0+(2*nx*ny)][dof_I];
-				values[19][dof_I] = variables[lineNum0+(2*nx*ny)+1][dof_I];
-				values[20][dof_I] = variables[lineNum0+(2*nx*ny)+2][dof_I];
-				values[21][dof_I] = variables[lineNum0+(2*nx*ny)+nx][dof_I];
-				values[22][dof_I] = variables[lineNum0+(2*nx*ny)+nx+1][dof_I];
-				values[23][dof_I] = variables[lineNum0+(2*nx*ny)+nx+2][dof_I];
-				values[24][dof_I] = variables[lineNum0+(2*nx*ny)+(2*nx)][dof_I];
-				values[25][dof_I] = variables[lineNum0+(2*nx*ny)+(2*nx)+1][dof_I];
-				values[26][dof_I] = variables[lineNum0+(2*nx*ny)+(2*nx)+2][dof_I];
-
-				value[dof_I] = 0.0;
-				for( shapeFunc_I = 0; shapeFunc_I < numShapeFuncs; shapeFunc_I++ )
-					value[dof_I] += Ni[shapeFunc_I] * values[shapeFunc_I][dof_I];
-			}
-		}
-
-		FeVariable_SetValueAtNode( feVariable, node_I, value );
-	}
-
-	Memory_Free( filename );
-	Memory_Free( posx );
-	Memory_Free( posy );
-	if( nDims == 3 ) Memory_Free( posz );
-	Memory_Free( variables );
-
-#ifdef READ_HDF5
-	H5Fclose( inputFile );
-#endif
-}
-
-void _FieldTest_DumpToAnalysisFile( FieldTest* self, Stream* analysisStream ) {
-	int			field_I, numDofs, dim, dof_I;
-	/* double		error; */
-	FeVariable*	errorField;
-
-	for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
-		/* should be using MT_VOLUME for the reference field mesh, but seems to have a bug */
-		errorField = self->errorFieldList[field_I];
-		numDofs	   = self->numericFieldList[field_I]->fieldComponentCount;
-		dim = self->numericFieldList[field_I]->dim;
-
-#if 0
-		/* Fancy error measurements of magnitudes and 2ndInvars, no needed
-		 * but I'm leaving it in incase */
-		if( dim == numDofs ) {
-			/* It's a vector */
-			error = StGermain_VectorMagnitude( self->gErrorNorm[field_I], dim );
-		} else if ( numDofs > self->numericFieldList[field_I]->dim ) {
-			/* Assume it's a symmetric tensor */
-			error = SymmetricTensor_2ndInvariant( self->gErrorNorm[field_I], dim );	
-		} else {
-			/* It's a scalar */
-			error = self->gErrorNorm[field_I][0];
-		}
-		Journal_Printf( analysisStream, "%.8e ", error );
-#endif
-		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
-			if(self->normalise)
-				Journal_RPrintf( analysisStream, "%.8e ", self->gErrorNorm[field_I][dof_I] );
-			else
-				Journal_RPrintf( analysisStream, "%.8e ", self->gErrorSq[field_I][dof_I] );
-		}
-
-	}
-}
-
-/* by default, success of the physics test is set to false. this is reset if the test passes */
-void FieldTest_EvaluatePhysicsTest( void* _context, void* data ) {
-	DomainContext*			context			= (DomainContext*)_context;
-	/* dodgy!!! - not sure how else to pass the self reference at an entry point */
-	FieldTest*			self			= fieldTestSingleton;
-	FieldTest_ExpectedResultFunc*	expectedFunc		= self->expectedFunc;
-	FILE*				dumpExpectedFilePtr;
-	char*				dumpExpectedFileName;
-	int				dim_i, dof_i;
-
-	if( expectedFunc( self->expectedData, context, self->expected, self->numeric, self->tolerance ) )
-		self->expectedPass = True;
-
-	if( strlen(self->dumpExpectedFileName) > 1 ) {
-		dumpExpectedFileName = Memory_Alloc_Array_Unnamed( char, strlen(self->expectedFilePath) + 
-									 strlen(self->dumpExpectedFileName) + 5 );
-		sprintf( dumpExpectedFileName, "%s%s.out", self->expectedFilePath, self->dumpExpectedFileName );
-		dumpExpectedFilePtr = fopen( dumpExpectedFileName, "a" );
-
-		fprintf( dumpExpectedFilePtr, "%.8e ", self->numeric[context->timeStep].time );
-		for( dim_i = 0; dim_i < context->dim; dim_i++ )
-			fprintf( dumpExpectedFilePtr, "%.8e ", self->numeric[context->timeStep].place[dim_i] );
-		for( dof_i = 0; dof_i < self->expectedDofs; dof_i++ )
-			fprintf( dumpExpectedFilePtr, "%.8e ", self->numeric[context->timeStep].value[dof_i] );
-
-		fprintf( dumpExpectedFilePtr, "\n" );
-
-		if( context->timeStep == context->maxTimeSteps ) {
-			if( self->expectedPass )
-				fprintf( dumpExpectedFilePtr, "test result: PASS\n" );
-			else
-				fprintf( dumpExpectedFilePtr, "test result: FAIL\n" );
-		}
-
-		Memory_Free( dumpExpectedFileName );
-		fclose( dumpExpectedFilePtr );
-	}
-}
-
-void FieldTest_GenerateErrFields( void* _context, void* data ) {
-	DomainContext*	context = (DomainContext*)_context;
-	/* this a really dodgy way to get the self ptr, as will only work if the textual name is consistent with that in 
-	 * the XML - need to find a way to add an entry point which allows the self ptr to be passed as a void * */
-	//FieldTest* 		self 			= LiveComponentRegister_Get( context->CF->LCRegister, (Name)"NumericFields"  );
-	/* this is also a dodgy way to get the self ptr, as its obtained from a global variable */
-	FieldTest*		self = fieldTestSingleton;
-	FeVariable*		errorField;
-	Index				lMeshSize, lElement_I;
-	double			elErrorSq[9], elNormSq[9], elError[9];
-	double			lAnalyticSq[9], gAnalyticSq[9];
-	double			lErrorSq[9], gErrorSq[9];
-	Bool				normalise = self->normalise;
-	Index				numDofs, dof_I, fieldCount;
-	Index				field_I;
-	Stream*			analysisStream;
-	/* double			eps = self->epsilon; */
-	
-	/* if testTimestep is NOT initialise and NOT equal to the current timestep
-	 * we skip this function */
-	if( self->testTimestep != context->timeStep && self->testTimestep != 0 )
-		return;
-
-	fieldCount = self->fieldCount;
-
-	if( self->appendToAnalysisFile ) {
-		/* append (or create if not found ) a file to report results */
-		double length, elementResI;
-		char* filename;
-		analysisStream = Journal_Register( Info_Type, (Name)self->type  );
-		Stg_asprintf( &filename, "%s-analysis.cvg", self->name );
-		Stream_AppendFile( analysisStream, filename );
-		Memory_Free( filename );
-
-		/* write heading names in file */
-		Journal_RPrintf( analysisStream, "#Res ");
-		for(field_I = 0 ; field_I < fieldCount ; field_I++ ) {
-			numDofs = self->numericFieldList[field_I]->fieldComponentCount;
-			for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
-				Journal_RPrintf( analysisStream, "%s%d ", self->numericFieldList[field_I]->name, dof_I+1 );
-			}
-		}
-		length = Dictionary_GetDouble( context->CF->rootDict, "maxX" ) - Dictionary_GetDouble( context->CF->rootDict, "minX" ) ;
-		elementResI = Dictionary_GetInt( context->CF->rootDict, (Dictionary_Entry_Key)"elementResI"  );
-		/* assume square resolution */
-		Journal_RPrintf( analysisStream, "\n%e ", length/elementResI );
-	}
-
-	for( field_I = 0; field_I < fieldCount; field_I++ ) {
-		/* should be using MT_VOLUME for the reference field mesh, but seems to have a bug */
-		lMeshSize  = Mesh_GetLocalSize( self->constantMesh, MT_VERTEX );
-		errorField = self->errorFieldList[field_I];
-		numDofs	   = self->numericFieldList[field_I]->fieldComponentCount;
-
-		assert( !strcmp( errorField->feMesh->name, "constantMesh" ) );
-
-		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
-			lAnalyticSq[dof_I] = 0.0;
-			lErrorSq[dof_I]    = 0.0;
-		}
-	
-		for( lElement_I = 0; lElement_I < lMeshSize; lElement_I++ ) {
-			for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
-				elErrorSq[dof_I] = 0.0;
-				elNormSq[dof_I]  = 0.0;
-			}
-
-			if( self->referenceSolnFromFile )
-				FieldTest_ElementErrReferenceFromField( self, field_I, lElement_I, elErrorSq, elNormSq );
-			else
-				FieldTest_ElementErrAnalyticFromField( self, field_I, lElement_I, elErrorSq, elNormSq );
-
-			for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
-					lAnalyticSq[dof_I] += elNormSq[dof_I];
-					lErrorSq[dof_I]    += elErrorSq[dof_I];
-					//elError[dof_I] = normalise ? sqrt( elErrorSq[dof_I] / ( elNormSq[dof_I] + eps ) ) : sqrt( elErrorSq[dof_I] );
-					elError[dof_I] = normalise ? sqrt( elErrorSq[dof_I] / ( elNormSq[dof_I] ) ) : sqrt( elErrorSq[dof_I] );
-			}
-
-			/* constant mesh, so node and element indices map 1:1 */
-			FeVariable_SetValueAtNode( errorField, lElement_I, elError );
-		}
-	
-		MPI_Allreduce( lAnalyticSq, gAnalyticSq, numDofs, MPI_DOUBLE, MPI_SUM, self->referenceFieldList[field_I]->communicator );
-		MPI_Allreduce( lErrorSq,    gErrorSq,    numDofs, MPI_DOUBLE, MPI_SUM, self->referenceFieldList[field_I]->communicator );
-
-		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
-			self->gAnalyticSq[field_I][dof_I] = gAnalyticSq[dof_I];
-			self->gErrorSq[field_I][dof_I]    = gErrorSq[dof_I];
-			self->gErrorNorm[field_I][dof_I]  = sqrt( gErrorSq[dof_I] / gAnalyticSq[dof_I] );
-
-			if( normalise ) {
-				Journal_RPrintf( context->info, "%s - dof %d normalised global error: %.8e\n", 
-				     	self->numericFieldList[field_I]->name, dof_I, self->gErrorNorm[field_I][dof_I] );
-			}
-			else {
-				Journal_RPrintf( context->info, "%s - dof %d global error: %.8e\n",
-					self->numericFieldList[field_I]->name, dof_I, sqrt( self->gErrorSq[field_I][dof_I] ) );
-			}
-		}
-	}
-
-	if( self->appendToAnalysisFile ) {
-		_FieldTest_DumpToAnalysisFile( self, analysisStream );
-		Journal_RPrintf( analysisStream, "\n" );
-		Stream_CloseAndFreeFile( analysisStream );
-	}
-}
-
-void FieldTest_ElementErrReferenceFromField( void* fieldTest, Index field_I, Index lElement_I, double* elErrorSq, double* elNormSq ) {
-	FieldTest* 		self 			= (FieldTest*) fieldTest;
-	FeVariable*		referenceField		= self->referenceFieldList[field_I];
-	FeVariable*		numericField		= self->numericFieldList[field_I];
-	FeMesh*			referenceMesh		= referenceField->feMesh;
-	FeMesh*			elementMesh		= self->elementMesh;
-	Index			constantElNode		= lElement_I;
-	double*			coord			= Mesh_GetVertex( self->constantMesh, constantElNode );
-	unsigned		nDims			= Mesh_GetDimSize( referenceMesh );
-	Index			el_I, elementMeshElem;
-	ElementType*		elType;
-	Swarm*			intSwarm		= self->integrationSwarm;
-	Index			cell_I;
-	unsigned		cellParticleCount;
-	Index			cParticle_I;
-	IntegrationPoint*	cParticle;
-	double			*xi, weight;
-	double			globalCoord[3];
-	double			detJac;
-	double			reference[9], numeric[9];
-	Index			numDofs			= numericField->fieldComponentCount;
-	Index			dof_I;
-
-	/* don't assume that the constant error field mesh & reference field mesh necessarily map 1:1 */
-	Mesh_SearchElements( referenceMesh, coord, &el_I );
-	Mesh_SearchElements( elementMesh, coord, &elementMeshElem );
-	elType = FeMesh_GetElementType( elementMesh, elementMeshElem );
-
-	cell_I = CellLayout_MapElementIdToCellId( intSwarm->cellLayout, el_I );
-	cellParticleCount = intSwarm->cellParticleCountTbl[cell_I];
-
-	for( cParticle_I = 0; cParticle_I < cellParticleCount; cParticle_I++ ) {
-		cParticle = (IntegrationPoint*) Swarm_ParticleInCellAt( intSwarm, cell_I, cParticle_I );
-		xi 	  = cParticle->xi;
-		weight	  = cParticle->weight;
-
-		FeMesh_CoordLocalToGlobal( referenceMesh, el_I, xi, globalCoord );
-		FieldVariable_InterpolateValueAt( referenceField, globalCoord, reference );
-		FieldVariable_InterpolateValueAt( numericField,   globalCoord, numeric   );
-
-		detJac = ElementType_JacobianDeterminant( elType, elementMesh, elementMeshElem, xi, nDims );
-
-		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
-			elErrorSq[dof_I] += ( numeric[dof_I] - reference[dof_I] ) * ( numeric[dof_I] - reference[dof_I] ) 
-					    * weight * detJac;
-			elNormSq[dof_I]  += reference[dof_I] * reference[dof_I] * weight * detJac;
-		}
-	}
-}
-
-void FieldTest_ElementErrAnalyticFromField( void* fieldTest, Index field_I, Index lElement_I, double* elErrorSq, double* elNormSq ) {
-	FieldTest*			self = (FieldTest*) fieldTest;
-	FeVariable*			numericField = self->numericFieldList[field_I];
-	FeMesh*				elementMesh = self->elementMesh;
-	Index					constantElNode = lElement_I;
-	double*				coord = Mesh_GetVertex( self->constantMesh, constantElNode );
-	unsigned				nDims = Mesh_GetDimSize( elementMesh );
-	Index					el_I;
-	ElementType*		elType;
-	Swarm*				intSwarm = self->integrationSwarm;
-	Index					cell_I;
-	unsigned				cellParticleCount;
-	Index					cParticle_I;
-	IntegrationPoint*	cParticle;
-	double				*xi, weight;
-	double				globalCoord[3];
-	double				detJac;
-	double				analytic[9], numeric[9];
-	Index					numDofs = numericField->fieldComponentCount;
-	Index					dof_I;
-	/* corresponding analytic solution function for this feVariable, as assigned in the plugin */
-	FieldTest_AnalyticSolutionFunc*	analyticSolution = self->_analyticSolutionList[self->analyticSolnForFeVarKey[field_I]];
-
-	/* don't assume that the constant error field mesh & reference field mesh necessarily map 1:1 */
-	Mesh_SearchElements( elementMesh, coord, &el_I );
-	elType = FeMesh_GetElementType( elementMesh, el_I );
-
-	cell_I = CellLayout_MapElementIdToCellId( intSwarm->cellLayout, el_I );
-	cellParticleCount = intSwarm->cellParticleCountTbl[cell_I];
-
-	for( cParticle_I = 0; cParticle_I < cellParticleCount; cParticle_I++ ) {
-		cParticle = (IntegrationPoint*) Swarm_ParticleInCellAt( intSwarm, cell_I, cParticle_I );
-		xi	  = cParticle->xi;
-		weight    = cParticle->weight;
-
-		detJac = ElementType_JacobianDeterminant( elType, elementMesh, el_I, xi, nDims );
-
-		FeMesh_CoordLocalToGlobal( elementMesh, el_I, xi, globalCoord );
-		analyticSolution( self, globalCoord, analytic );
-		FieldVariable_InterpolateValueAt( numericField, globalCoord, numeric );
-
-		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
-			elErrorSq[dof_I] += ( numeric[dof_I] - analytic[dof_I] ) * ( numeric[dof_I] - analytic[dof_I] ) * weight * detJac;
-			elNormSq[dof_I]  += analytic[dof_I] * analytic[dof_I] * weight * detJac;
-		}
-	}
-}
-
-void FieldTest_ElementErrAnalyticFromSwarm( void* fieldTest, Index var_I, Index lElement_I, double* elErrorSq, double* elNormSq ) {
-}
-
-void FieldTest_ElementErrReferenceFromSwarm( void* fieldTest, Index var_I, Index lElement_I, double* elErrorSq, double* elNormSq ) {
-}
-
-/* the first index 'func_I' denotes the index of the function in the analytic solution list to be applied to calculate
- * the analytic field at index 'field_I' in the analytic field list.
- *
- * the analytic fields are in the same order as their numeric counterparts are read in from the XML */
-void FieldTest_AddAnalyticSolutionFuncToListAtIndex( void* fieldTest, Index func_I, FieldTest_AnalyticSolutionFunc* func, Index field_I ) {
-	FieldTest* 	self 	= (FieldTest*) fieldTest;
-
-	self->_analyticSolutionList[func_I] = func;
-	self->analyticSolnForFeVarKey[field_I] = func_I;
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FieldTest.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/FieldTest.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,1166 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FieldTest.c 1095 2008-04-03 06:29:29Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "types.h"
+#include "FieldTest.h"
+#include "FeVariable.h"
+#include "ElementType.h"
+#include "FeMesh.h"
+#include "OperatorFeVariable.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+const Type FieldTest_Type = "FieldTest";
+
+FieldTest* fieldTestSingleton = NULL;
+
+void* _FieldTest_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(FieldTest);
+	Type                                                      type = FieldTest_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _FieldTest_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _FieldTest_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _FieldTest_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+FieldTest* _FieldTest_New(  FIELDTEST_DEFARGS  )
+{
+	FieldTest*			self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(FieldTest) );
+	/* Construct using parent */
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (FieldTest*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+
+	self->normalise = False;
+	self->epsilon = 0.0001;
+	self->referenceSolnFromFile = False;
+
+	/* Assign singleton ptr */
+	fieldTestSingleton = self;
+	return self;
+}
+
+void _FieldTest_Delete( void* fieldTest ) {
+	FieldTest* 	self 	= (FieldTest*)fieldTest;
+	
+	/*if( self->integrationSwarm ) Stg_Class_Delete( self->integrationSwarm );*/
+        /*
+	if( self->fieldCount ) {
+		Memory_Free( self->gAnalyticSq );
+		Memory_Free( self->gErrorSq    );
+		Memory_Free( self->gError      );
+		Memory_Free( self->gErrorNorm  );
+
+		Memory_Free( self->analyticSolnForFeVarKey );
+		Memory_Free( self->_analyticSolutionList );
+	}
+
+	if( self->swarmVarCount ) {
+	   Index swarmVar_I;
+		for( swarmVar_I = 0; swarmVar_I < self->swarmVarCount; swarmVar_I++ ) 
+			Memory_Free(self->swarmVarNameList[swarmVar_I]); 
+		Memory_Free( self->swarmVarNameList );
+	}
+	
+	Memory_Free( self->referenceSolnPath );
+	Memory_Free( self->expectedFileName );
+	Memory_Free( self->expectedFilePath );
+	Memory_Free( self->dumpExpectedFileName );
+        */
+	
+	/* Stg_Class_Delete parent*/
+	_Stg_Component_Delete( self );
+}
+
+void _FieldTest_Print( void* fieldTest, Stream* stream ) {
+	FieldTest* self = (FieldTest*)fieldTest;
+	
+	/* Print parent */
+	_Stg_Component_Print( self, stream );
+	
+}
+
+void* _FieldTest_Copy( const void* fieldTest, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	abort();
+	return NULL;
+}
+
+void _FieldTest_AssignFromXML( void* fieldTest, Stg_ComponentFactory* cf, void* data ) {
+	FieldTest*					self = (FieldTest*)fieldTest;
+	Dictionary*					dict = cf->rootDict;
+	Dictionary_Entry_Value*	dictEntryVal = Dictionary_Get( dict, (Dictionary_Entry_Key)"pluginData" );
+	Dictionary*					pluginDict =  Dictionary_Entry_Value_AsDictionary( dictEntryVal  );
+	/* get the pluginDict from the xml, needed for rejig */
+	Dictionary*					pluginDict2	= Codelet_GetPluginDictionary( self, cf->rootDict );
+	Dictionary_Entry_Value*	fieldList;
+	Dictionary_Entry_Value*	swarmVarList = Dictionary_Get( dict, (Dictionary_Entry_Key)"NumericSwarmVariableNames"  );
+	FieldVariable_Register*	fV_Register;
+	Index							feVariable_I/*, referenceFieldCount*/;
+	Index							swarmVar_I;
+	char*							fieldName;
+	Hook*							generateErrorFields;
+	Hook*							physicsTestHook;
+	Stream*						errStream = Journal_Register( Error_Type, (Name)"FieldTests"  );
+
+	Journal_Firewall( pluginDict != NULL , errStream, "\nError in %s: No pluginData xml was defined ... aborting\n", __func__ );
+
+	self->context = Stg_ComponentFactory_ConstructByName( cf, Dictionary_GetString( pluginDict2, (Dictionary_Entry_Key)"Context"  ), DomainContext, False, data );
+	if( !self->context ) 
+		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", DomainContext, True, data  );
+
+	fV_Register = self->context->fieldVariable_Register;
+
+	fieldList = Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"NumericFields" );
+	self->fieldCount = fieldList ? Dictionary_Entry_Value_GetCount( fieldList ) / 2 : 0;
+
+	if( self->fieldCount  ) {
+		self->numericFieldList   	= Memory_Alloc_Array( FeVariable*, self->fieldCount, "numeric fields" );
+		self->referenceFieldList 	= Memory_Alloc_Array( FeVariable*, self->fieldCount, "reference fields" );
+		self->errorFieldList     	= Memory_Alloc_Array( FeVariable*, self->fieldCount, "error fields" );
+		self->referenceMagFieldList	= Memory_Alloc_Array( OperatorFeVariable*, self->fieldCount, "reference field magnitudes" );
+		self->errorMagFieldList		= Memory_Alloc_Array( OperatorFeVariable*, self->fieldCount, "error field magnitudes" );
+	
+		if( !self->referenceSolnFromFile ) {
+			self->analyticSolnForFeVarKey = Memory_Alloc_Array( unsigned, self->fieldCount, 
+								    "analytic solution index for ith feVariable" );
+		}
+#if 0	
+		else {
+			fieldList = Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"ReferenceFields" );
+			referenceFieldCount = fieldList ? Dictionary_Entry_Value_GetCount( fieldList ) : assert(0);
+
+			for( feVariable_I = 0; feVariable_I < referenceFieldCount; feVariable_I++ ) {
+				referenceSolnFileList
+			}
+		}
+#endif
+
+		for( feVariable_I = 0; feVariable_I < self->fieldCount; feVariable_I++ ) {
+			/* read in the FeVariable from the tuple */
+			fieldName = ( fieldList  ) ? 
+				    StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( fieldList, 2 * feVariable_I ) ) ):
+				    StG_Strdup( Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"FeVariable" ) );
+			
+			self->numericFieldList[feVariable_I] = (FeVariable* ) FieldVariable_Register_GetByName( fV_Register, fieldName );
+
+			if( !self->numericFieldList[feVariable_I] ) {
+				/* if the numericFieldList[x] can't be found in register 
+					 and can't be constructed through the factory then 
+					 skip this entry and take one off self->fieldCount 
+					 needed for simple regression test
+				 */
+				self->numericFieldList[feVariable_I] = Stg_ComponentFactory_ConstructByName( cf, (Name)fieldName, FeVariable, False, data ); 
+				if( self->numericFieldList[feVariable_I]==NULL  ) { 
+					self->fieldCount--; 
+					continue; 
+				}
+			}
+
+			/* ...and the corresponding analytic function ptr index - these have to be consistent with how they're ordered in the plugin */
+			self->analyticSolnForFeVarKey[feVariable_I] = Dictionary_Entry_Value_AsUnsignedInt( 
+									Dictionary_Entry_Value_GetElement( fieldList, 2 * feVariable_I + 1 ) );
+			Memory_Free( fieldName );
+		}
+	}
+
+	self->integrationSwarm 	= (Swarm*)LiveComponentRegister_Get( cf->LCRegister, Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"IntegrationSwarm" ) ) );
+	self->constantMesh     	= (FeMesh* )LiveComponentRegister_Get( cf->LCRegister, Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"ConstantMesh"     ) ) );
+	self->elementMesh      	= (FeMesh* )LiveComponentRegister_Get( cf->LCRegister, Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"ElementMesh"      ) ) );
+
+	self->swarmVarCount = swarmVarList ? Dictionary_Entry_Value_GetCount( swarmVarList ) : 0;
+	if( self->swarmVarCount  ) {
+		self->swarmVarNameList = Memory_Alloc_Array( Name, self->swarmVarCount, "numeric swarm variable names" );
+	
+		for( swarmVar_I = 0; swarmVar_I < self->swarmVarCount; swarmVar_I++ ) {
+			self->swarmVarNameList[swarmVar_I] = ( swarmVarList ) ? 
+					StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( swarmVarList, swarmVar_I ) ) ):
+					StG_Strdup( Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"SwarmVariable" )  );
+		}	
+	}
+	
+	self->referenceSolnPath     = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"referenceSolutionFilePath" ) )  );
+	self->normalise             = Dictionary_Entry_Value_AsBool( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"normaliseByAnalyticSolution" )  );
+	self->epsilon               = Dictionary_Entry_Value_AsDouble( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"epsilon" )  );
+	self->testTimestep          = Dictionary_GetInt_WithDefault( pluginDict, (Dictionary_Entry_Key)"testTimestep", 0  );
+	self->referenceSolnFromFile = Dictionary_Entry_Value_AsBool( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"useReferenceSolutionFromFile" )  );
+	self->appendToAnalysisFile  = Dictionary_GetBool_WithDefault( pluginDict, (Dictionary_Entry_Key)"appendToAnalysisFile", False  ) ;
+
+	/* for the physics test */
+	self->expectedFileName     = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"expectedFileName" ) )  );
+	self->expectedFilePath     = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"expectedFilePath" ) )  );
+	self->dumpExpectedFileName = StG_Strdup( Dictionary_Entry_Value_AsString( Dictionary_Get( pluginDict, (Dictionary_Entry_Key)"expectedOutputFileName" ) )  );
+	self->expectedPass     = False;
+
+	/* set up the entry point */
+	generateErrorFields = Hook_New( "Generate error fields hook", (void*)FieldTest_GenerateErrFields, self->name );
+	_EntryPoint_AppendHook( Context_GetEntryPoint( self->context, AbstractContext_EP_FrequentOutput ), generateErrorFields );
+
+	/* entry point for the fisix test func */
+	if( strlen(self->expectedFileName) > 1 ) {
+          physicsTestHook = Hook_New( "Physics test hook", (void*)FieldTest_EvaluatePhysicsTest, self->name );
+		_EntryPoint_AppendHook( Context_GetEntryPoint( self->context, AbstractContext_EP_FrequentOutput ), physicsTestHook );
+	}
+
+	self->LCRegister = cf->LCRegister;
+}
+
+void _FieldTest_Build( void* fieldTest, void* data ) {
+	FieldTest* 		self 		= (FieldTest*) fieldTest;
+	Index			field_I;
+	//Index			swarm_I;
+
+	if( self->constantMesh ) Stg_Component_Build( self->constantMesh,  data, False );
+
+	for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
+		FieldTest_BuildAnalyticField( self, field_I );
+		FieldTest_BuildErrField( self, field_I );
+	
+		Stg_Component_Build( self->numericFieldList[field_I], data, False );
+		Stg_Component_Build( self->errorFieldList[field_I], data, False );
+
+		Stg_Component_Build( self->referenceFieldList[field_I], data, False );
+		Stg_Component_Build( self->errorFieldList[field_I], data, False );
+	}
+
+	/*for( swarm_I = 0; swarm_I < self->swarmCount; swarm_I++ ) {
+		FieldTest_BuildAnalyticSwarm( self->referenceMesh, self->numericSwarmList[swarm_I], 
+					       self->context, &self->referenceSwarmList[swarm_I] );
+		FieldTest_BuildErrSwarm( self->constantMesh, self->numericSwarmList[swarm_I], 
+					 self->context, &self->referenceSwarmList[swarm_I] );
+	}*/
+
+	if( self->fieldCount ) {
+		self->gAnalyticSq = Memory_Alloc_2DArray( double, self->fieldCount, 9, (Name)"global reference solution squared"  );
+		self->gErrorSq 	  = Memory_Alloc_2DArray( double, self->fieldCount, 9, (Name)"global L2 error squared"  );
+		self->gError	  = Memory_Alloc_2DArray( double, self->fieldCount, 9, (Name)"global L2 error"  );
+		self->gErrorNorm  = Memory_Alloc_2DArray( double, self->fieldCount, 9, (Name)"global L2 error normalised"  );
+	}
+}
+
+void _FieldTest_Initialise( void* fieldTest, void* data ) {
+	FieldTest* 		self 		= (FieldTest*) fieldTest;
+	Index			field_I;
+	FILE*			expected_fp;
+	char*			expectedFilename;
+	int			num_time_steps;
+	int			dof_i, dim_i;
+	int			expected_i 	= 0;
+
+	for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
+		Stg_Component_Initialise( self->numericFieldList[field_I], data, False );
+		Stg_Component_Initialise( self->errorFieldList[field_I], data, False );
+		Stg_Component_Initialise( self->referenceFieldList[field_I], data, False );
+		if( self->referenceMagFieldList[field_I] )
+			Stg_Component_Initialise( self->referenceMagFieldList[field_I], data, False );
+		if( self->errorMagFieldList[field_I] )
+			Stg_Component_Initialise( self->errorMagFieldList[field_I], data, False );
+	}
+
+	/* load the reference solution from file if req'd */
+	if( self->referenceSolnFromFile ) {
+		char *referenceSolnFileName;
+		for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
+			/* create the name of the reference file, the apprendix is handled by FieldTest_LoadReferenceSolutionFromFile */
+			referenceSolnFileName = Memory_Alloc_Array_Unnamed( char, strlen((char*)self->referenceSolnPath) + 1 + strlen((char*)self->numericFieldList[field_I]->name) + 1 + 5 + strlen(".h5x\0") );
+#ifdef READ_HDF5
+			sprintf( referenceSolnFileName, "%s/%s.%.5d.h5", self->referenceSolnPath, self->numericFieldList[field_I]->name, self->testTimestep );
+#else
+			sprintf( referenceSolnFileName, "%s/%s.%.5d.dat", self->referenceSolnPath, self->numericFieldList[field_I]->name, self->testTimestep );
+#endif
+			FeVariable_ReadFromFile( self->referenceFieldList[field_I], referenceSolnFileName );
+
+	/*		FieldTest_LoadReferenceSolutionFromFile( self->referenceFieldList[field_I],
+																								referenceSolnFileName,
+																								self->referenceSolnPath, self->context ); */
+			Memory_Free( referenceSolnFileName );
+		}
+	}
+	/* calculate the analytic solutions */
+	else {
+		for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
+			FieldTest_CalculateAnalyticSolutionForField( self, field_I ); 
+			FeVariable_ZeroField( self->errorFieldList[field_I] );
+		}
+	}
+
+	if( strlen(self->expectedFileName) > 1 && strcmp( self->expectedFileName, "false" ) ) {
+		/* if the self->expectedFileName == False then don't go here */
+		expectedFilename = Memory_Alloc_Array_Unnamed( char, strlen(self->expectedFilePath) + strlen(self->expectedFileName) + 1 );
+		sprintf( expectedFilename, "%s%s", self->expectedFilePath, self->expectedFileName );
+
+		expected_fp = fopen( expectedFilename, "r" );
+
+		fscanf( expected_fp, "%d %d", &self->expectedDofs, &num_time_steps );
+	
+		self->expected  = Memory_Alloc_Array_Unnamed( Event, num_time_steps + 1 );
+		self->numeric   = Memory_Alloc_Array_Unnamed( Event, self->context->maxTimeSteps + 1 );
+		self->tolerance = Memory_Alloc_Array_Unnamed( Event, num_time_steps + 1 );
+
+		while ( !feof( expected_fp ) ) {
+			fscanf( expected_fp, "%lf ", &self->expected[expected_i].time );
+			
+			for( dim_i = 0; dim_i < self->context->dim; dim_i++ )
+				fscanf( expected_fp, "%lf ", &self->expected[expected_i].place[dim_i] );
+
+			for( dof_i = 0; dof_i < self->expectedDofs; dof_i++ )
+				fscanf( expected_fp, "%lf ", &self->expected[expected_i].value[dof_i] );
+
+			fscanf( expected_fp, "%lf ", &self->tolerance[expected_i].time );
+			
+			for( dim_i = 0; dim_i < self->context->dim; dim_i++ )
+				fscanf( expected_fp, "%lf ", &self->tolerance[expected_i].place[dim_i] );
+
+			for( dof_i = 0; dof_i < self->expectedDofs; dof_i++ )
+				fscanf( expected_fp, "%lf ", &self->tolerance[expected_i].value[dof_i] );
+
+			expected_i++;
+		}
+		fclose( expected_fp );
+
+		Memory_Free( expectedFilename );
+	}
+}
+
+void FieldTest_CalculateAnalyticSolutionForField( void* fieldTest, Index field_I ) {
+	FieldTest* 			self 		= (FieldTest*) fieldTest;
+	FeVariable*			analyticField	= self->referenceFieldList[field_I];
+	FeMesh*				analyticMesh	= analyticField->feMesh;
+	FieldTest_AnalyticSolutionFunc*	analyticSolution;
+	Index				lNode_I;
+	Index				lMeshSize	= Mesh_GetLocalSize( analyticMesh, MT_VERTEX );
+	double*				coord;
+	double*				value;
+	
+	analyticSolution = self->_analyticSolutionList[self->analyticSolnForFeVarKey[field_I]];
+	value = Memory_Alloc_Array_Unnamed( double, analyticField->fieldComponentCount );
+	memset( value, 0, analyticField->fieldComponentCount * sizeof(double) );
+
+	for( lNode_I = 0; lNode_I < lMeshSize; lNode_I++ ) {
+		coord = Mesh_GetVertex( analyticMesh, lNode_I );
+		analyticSolution( self, coord, value );
+		FeVariable_SetValueAtNode( analyticField, lNode_I, value );
+	}
+
+	Memory_Free( value );
+}
+
+void _FieldTest_Execute( void* fieldTest, void* data ) {
+}
+
+void _FieldTest_Destroy( void* fieldTest, void* data ) {
+	FieldTest* self = (FieldTest*) fieldTest;
+
+	if( self->fieldCount ) {
+		Memory_Free( self->numericFieldList );
+		Memory_Free( self->referenceFieldList );
+		Memory_Free( self->errorFieldList );
+		Memory_Free( self->referenceMagFieldList );
+		Memory_Free( self->errorMagFieldList );
+
+		Memory_Free( self->gAnalyticSq );
+		Memory_Free( self->gErrorSq );
+		Memory_Free( self->gError );
+		Memory_Free( self->gErrorNorm );
+	}
+
+	if( strlen(self->expectedFileName) > 1 ) {
+		Memory_Free( self->expected );
+		Memory_Free( self->numeric );
+		Memory_Free( self->tolerance );
+	}
+	if( !self->referenceSolnFromFile ) {
+		Memory_Free( self->analyticSolnForFeVarKey );
+		Memory_Free( self->_analyticSolutionList );
+	}
+
+	Stg_Component_Destroy( self, data, False );
+}
+
+void FieldTest_BuildAnalyticField( void* fieldTest, Index field_I ) {
+	FieldTest*				self = (FieldTest*) fieldTest;
+	FeVariable*				numericField = self->numericFieldList[field_I];
+	FeMesh*					referenceMesh = numericField->feMesh;
+	DomainContext*			context = self->context;
+	Variable_Register*	variable_Register	= context->variable_Register;
+	char*						tmpName;
+	Dof_Index				componentsCount = numericField->fieldComponentCount;
+	char*						varName[9];
+	unsigned					var_I;
+	unsigned					node_I;
+	Variable*				variable;
+	Variable*				baseVariable = NULL;
+	DofLayout*				referenceDofLayout	= NULL;
+
+	unsigned					nDomainVerts = Mesh_GetDomainSize( referenceMesh, MT_VERTEX );
+	static double*			arrayPtr;
+
+	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"AnalyticVariable" );
+
+	if( componentsCount == 1  ) {
+		arrayPtr = Memory_Alloc_Array_Unnamed( double, nDomainVerts );
+		baseVariable = Variable_NewScalar( tmpName, (AbstractContext*)self->context, Variable_DataType_Double, (Index*)&nDomainVerts, NULL, (void**)&arrayPtr, variable_Register );
+	}
+	else {
+		for( var_I = 0; var_I < componentsCount; var_I++  )
+			Stg_asprintf( &varName[var_I], "%s-Component-%d", tmpName, var_I );
+
+		arrayPtr = Memory_Alloc_Array_Unnamed( double, nDomainVerts * componentsCount );
+		baseVariable = Variable_NewVector( tmpName, 
+							(AbstractContext*)self->context,
+						   Variable_DataType_Double, 
+						   componentsCount, 
+						   &nDomainVerts,
+						   NULL, 
+						   (void**)&arrayPtr, 
+						   variable_Register,
+						   varName[0], varName[1], varName[2], 
+						   varName[3], varName[4], varName[5], 
+						   varName[6], varName[7], varName[8] );
+	}
+	Memory_Free( tmpName );
+
+	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"AnalyticDofLayout"  );
+
+	referenceDofLayout = DofLayout_New( tmpName, self->context, variable_Register, Mesh_GetDomainSize( referenceMesh, MT_VERTEX ), referenceMesh );
+
+	if( componentsCount == 1 )
+		DofLayout_AddAllFromVariableArray( referenceDofLayout, 1, &baseVariable );
+	else {
+		for( var_I = 0; var_I < componentsCount; var_I++ ) {
+			variable = Variable_Register_GetByName( variable_Register, varName[var_I] );
+			variable->arrayPtrPtr = &baseVariable->arrayPtr;
+
+			for( node_I = 0; node_I < Mesh_GetDomainSize( referenceMesh, MT_VERTEX ); node_I++ )
+				DofLayout_AddDof_ByVarName( referenceDofLayout, varName[var_I], node_I );
+
+			Memory_Free( varName[var_I] );
+		}
+
+	}
+
+	Stg_Component_Build( referenceDofLayout, NULL, False );
+	Stg_Component_Initialise( referenceDofLayout, NULL, False );
+
+	Memory_Free( tmpName );
+
+	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"Analytic"  );
+
+	self->referenceFieldList[field_I] = FeVariable_New( tmpName, self->context, referenceMesh, referenceMesh, referenceDofLayout, NULL, NULL, NULL, 
+		Mesh_GetDimSize( referenceMesh ), False, False, False, context->fieldVariable_Register );
+	self->referenceFieldList[field_I]->context = context;
+	/* so that the eqnation numbers don't get built for this guy */
+	self->referenceFieldList[field_I]->buildEqNums = False;
+
+	if( componentsCount > Mesh_GetDimSize( referenceMesh ) ) {
+		/* we're dealing with a tensor, so use invariant */
+		tmpName = Stg_Object_AppendSuffix( self->referenceFieldList[field_I], (Name)"Invariant"  );
+		self->referenceMagFieldList[field_I] = OperatorFeVariable_NewUnary( tmpName, self->context, self->referenceFieldList[field_I], "SymmetricTensor_Invariant" );
+		self->referenceMagFieldList[field_I]->context = context;
+	} else {
+		/* we're dealing with a vector, so use magnitude */
+		tmpName = Stg_Object_AppendSuffix( self->referenceFieldList[field_I], (Name)"Magnitude"  );
+		self->referenceMagFieldList[field_I] = OperatorFeVariable_NewUnary( tmpName, self->context, self->referenceFieldList[field_I], "Magnitude" );
+		self->referenceMagFieldList[field_I]->context = context;
+	}
+
+	Memory_Free( tmpName );
+	Stg_Component_Build( self->referenceMagFieldList[field_I], context, False );
+	self->referenceMagFieldList[field_I]->_operator = Operator_NewFromName( self->referenceMagFieldList[field_I]->operatorName, 
+		self->referenceFieldList[field_I]->fieldComponentCount, context->dim );
+	self->referenceMagFieldList[field_I]->fieldComponentCount = self->referenceMagFieldList[field_I]->_operator->resultDofs;
+	_OperatorFeVariable_SetFunctions( self->referenceMagFieldList[field_I] );
+
+	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) baseVariable );
+	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) referenceDofLayout );
+	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) self->referenceFieldList[field_I] );
+	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) self->referenceMagFieldList[field_I] );
+}
+
+void FieldTest_BuildErrField( void* fieldTest, Index field_I ) {
+	FieldTest*				self = (FieldTest*) fieldTest;
+	FeMesh*					constantMesh = self->constantMesh;
+	FeVariable*				numericField = self->numericFieldList[field_I];
+	DomainContext*			context = self->context;
+	Variable_Register*	variable_Register	= context->variable_Register;
+	char*						tmpName;
+	Dof_Index				componentsCount = numericField->fieldComponentCount;
+	char*						varName[9];
+	unsigned					var_I;
+	unsigned					node_I;
+	Variable*				variable;
+	Variable*				baseVariable = NULL;
+	DofLayout*				errorDofLayout = NULL;
+	unsigned					nDomainVerts = Mesh_GetDomainSize( constantMesh, MT_VERTEX );
+	static void*			arrayPtr;
+
+	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"ErrorVariable" );
+
+	if( componentsCount == 1  ) {
+		arrayPtr = Memory_Alloc_Array_Unnamed( double, nDomainVerts );
+		baseVariable = Variable_NewScalar( tmpName, (AbstractContext*)self->context, Variable_DataType_Double, (Index*)&nDomainVerts, NULL, &arrayPtr, variable_Register );
+	}
+	else {
+		for( var_I = 0; var_I < componentsCount; var_I++  )
+			Stg_asprintf( &varName[var_I], "%s-Component-%d", tmpName, var_I );
+
+		arrayPtr = Memory_Alloc_Array_Unnamed( double, nDomainVerts * componentsCount );
+		baseVariable = Variable_NewVector( tmpName, (AbstractContext*)self->context, Variable_DataType_Double, componentsCount, &nDomainVerts, 
+						   NULL, (void**)&arrayPtr, variable_Register,
+						   varName[0], varName[1], varName[2], varName[3], varName[4],
+						   varName[5], varName[6], varName[7], varName[8] );
+	}
+	Memory_Free( tmpName );
+
+	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"ErrorDofLayout"  );
+
+	errorDofLayout = DofLayout_New( tmpName, self->context, variable_Register, Mesh_GetDomainSize( constantMesh, MT_VERTEX ), constantMesh );
+
+	if( componentsCount == 1 )
+		DofLayout_AddAllFromVariableArray( errorDofLayout, 1, &baseVariable );
+	else {
+		for( var_I = 0; var_I < componentsCount; var_I++ ) {
+			variable = Variable_Register_GetByName( variable_Register, varName[var_I] );
+			variable->arrayPtrPtr = &baseVariable->arrayPtr;
+
+			for( node_I = 0; node_I < Mesh_GetDomainSize( constantMesh, MT_VERTEX ); node_I++ )
+				DofLayout_AddDof_ByVarName( errorDofLayout, varName[var_I], node_I );
+
+			Memory_Free( varName[var_I] );
+		}
+		
+		//errorDofLayout->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, componentsCount );
+		//errorDofLayout->baseVariables[0] = baseVariable;
+	}
+	
+	Stg_Component_Build( errorDofLayout, NULL, False );
+	Stg_Component_Initialise( errorDofLayout, NULL, False );
+
+	Memory_Free( tmpName );
+
+	tmpName = Stg_Object_AppendSuffix( numericField, (Name)"Error"  );
+
+	self->errorFieldList[field_I] = FeVariable_New( tmpName, self->context, constantMesh, constantMesh, errorDofLayout, NULL, NULL, NULL, 
+		Mesh_GetDimSize( constantMesh ), False, False, False, context->fieldVariable_Register );
+	/* so that the eqnation numbers don't get built for this guy */
+	self->errorFieldList[field_I]->buildEqNums = False;
+
+	if( componentsCount > Mesh_GetDimSize( constantMesh ) ) {
+		/* we're dealing with a tensor, so use invariant */
+		tmpName = Stg_Object_AppendSuffix( self->errorFieldList[field_I], (Name)"Invariant"  );
+		self->errorMagFieldList[field_I] = OperatorFeVariable_NewUnary( tmpName, self->context, self->errorFieldList[field_I], "SymmetricTensor_Invariant" );
+		self->errorMagFieldList[field_I]->context = context;
+	} else {
+		/* we're dealing with a vector, so use magnitude */
+		tmpName = Stg_Object_AppendSuffix( self->errorFieldList[field_I], (Name)"Magnitude"  );
+		self->errorMagFieldList[field_I] = OperatorFeVariable_NewUnary( tmpName, self->context, self->errorFieldList[field_I], "Magnitude" );
+		self->errorMagFieldList[field_I]->context = context;
+	}
+	Memory_Free( tmpName );
+	Stg_Component_Build( self->errorMagFieldList[field_I], context, False );
+	self->errorMagFieldList[field_I]->_operator = Operator_NewFromName( self->errorMagFieldList[field_I]->operatorName, 
+		self->errorFieldList[field_I]->fieldComponentCount, context->dim );
+	self->errorMagFieldList[field_I]->fieldComponentCount = self->errorMagFieldList[field_I]->_operator->resultDofs;
+	_OperatorFeVariable_SetFunctions( self->errorMagFieldList[field_I] );
+
+	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) baseVariable );
+	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) errorDofLayout );
+	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) self->errorFieldList[field_I] );
+	LiveComponentRegister_Add( context->CF->LCRegister, (Stg_Component*) self->errorMagFieldList[field_I] );
+}
+
+void FieldTest_LoadReferenceSolutionFromFile( FeVariable* feVariable, Name referenceSolnName, Name referenceSolnPath, DomainContext* context ) {
+	FeMesh*			feMesh			= feVariable->feMesh;
+	char*			filename;
+	unsigned		nx = 0, ny = 0, nz = 0, total;
+	unsigned		lineNum = 0;
+	double			resolution[3];
+	double*			coord;
+	Index			node_I, dim_I;
+	unsigned		increments[3];
+	double			value[3];
+	unsigned		lineNum0;
+	unsigned		dofAtEachNodeCount, dof_I;
+	unsigned		meshSize 		= Mesh_GetLocalSize( feMesh, MT_VERTEX );
+	unsigned		nDims			= Mesh_GetDimSize( feMesh );
+	double			vertex0[3], coordPrime[3];
+	double			Ni[27], values[27][3];
+	unsigned		shapeFunc_I;
+	double			*posx, *posy, *posz;
+	double			**variables;
+	unsigned		numShapeFuncs 		= ( nDims == 3 ) ? 27 : 9;
+	double 			xi, eta, zeta;
+	double 			a0, b0, c0;
+	double 			a1, b1, c1;
+	double 			a2, b2, c2;
+	double 			m0, m1, m2, m3, m4, m5, m6;
+#ifdef READ_HDF5
+	hid_t			inputFile;
+	hid_t 			dataSet, memSpace, dataSpace;
+	hsize_t 		start[2], count[2], hSize;
+#endif
+	int 			sizes[3];
+	double* 		data;
+	int 			dataPos = 0;
+	double			nodeDummy;
+
+	Stg_Component_Initialise( feMesh,     context, False );
+	Stg_Component_Initialise( feVariable, context, False );
+
+	dofAtEachNodeCount = feVariable->fieldComponentCount;
+													  /* .  h5  \0 */
+	filename = Memory_Alloc_Array_Unnamed( char, strlen(referenceSolnPath) + strlen(referenceSolnName) + 1 + 2 + 1 );
+	sprintf( filename, "%s%s.h5", referenceSolnPath, referenceSolnName );
+#ifdef READ_HDF5
+	inputFile = H5Fopen( filename, H5F_ACC_RDONLY, H5P_DEFAULT );
+#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+	dataSet = H5Dopen( inputFile, "/size" );
+#else
+	dataSet = H5Dopen2( inputFile, "/size", H5P_DEFAULT );
+#endif
+	H5Dread( dataSet, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, sizes );
+	nx = sizes[0];
+	ny = sizes[1];
+	total = nx * ny;
+	if( nDims == 3 ) {
+		nz = sizes[2];
+		total *= nz;
+	}
+	H5Dclose( dataSet );
+
+	posx = Memory_Alloc_Array_Unnamed( double, total );
+	posy = Memory_Alloc_Array_Unnamed( double, total );
+	if( nDims == 3 ) posz = Memory_Alloc_Array_Unnamed( double, total );
+	variables = Memory_Alloc_2DArray_Unnamed( double, total, dofAtEachNodeCount );
+	data = Memory_Alloc_Array_Unnamed( double, nDims + dofAtEachNodeCount );
+
+	hSize = nDims + dofAtEachNodeCount;
+	memSpace = H5Screate_simple( 1, &hSize, NULL );
+	H5Sselect_all( memSpace );
+#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+	dataSet = H5Dopen( inputFile, "/data" );
+#else
+	dataSet = H5Dopen2( inputFile, "/data", H5P_DEFAULT );
+#endif
+	dataSpace = H5Dget_space( dataSet );
+	start[0] = 0;
+	start[1] = 0;
+	count[0] = 1;
+	count[1] = nDims + dofAtEachNodeCount;
+	H5Sselect_hyperslab( dataSpace, H5S_SELECT_SET, start, NULL, count, NULL );
+	for( lineNum = 0; lineNum < total; lineNum++ ) {
+		start[0] = lineNum;
+		H5Sselect_hyperslab( dataSpace, H5S_SELECT_SET, start, NULL, count, NULL );
+		H5Dread( dataSet, H5T_NATIVE_DOUBLE, memSpace, dataSpace, H5P_DEFAULT, data );
+
+      dataPos  = 0;
+		nodeDummy = data[dataPos++];
+		posx[lineNum] = data[dataPos++];
+		posy[lineNum] = data[dataPos++];
+		if( nDims == 3 ) posz[lineNum] = data[dataPos++];
+
+		for( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ )
+			variables[lineNum][dof_I] = data[dataPos++];
+	}
+
+	H5Sclose( memSpace );
+	H5Sclose( dataSpace );
+	H5Dclose( dataSet );
+#endif
+	Memory_Free( data );
+
+	resolution[0] = posx[1]  - posx[0];
+	resolution[1] = posy[nx] - posy[0];
+	if( nDims == 3 ) resolution[2] = posz[nx*ny] - posz[0];
+
+	for( node_I = 0; node_I < meshSize; node_I++ ) {
+		coord = Mesh_GetVertex( feMesh, node_I );
+		increments[0] = (unsigned)( ( coord[0] - posx[0] ) / resolution[0] );
+		increments[1] = (unsigned)( ( coord[1] - posy[0] ) / resolution[1] );
+		if( nDims == 3 ) increments[2] = (unsigned)( ( coord[2] - posz[0] ) / resolution[2] );
+			
+		for( dim_I = 0; dim_I < nDims; dim_I++ ) 
+			if( increments[dim_I] % 2 == 1 )
+				increments[dim_I]--;
+		if( increments[0] >= nx - 2 )
+			increments[0] = nx - 3;
+		if( increments[1] >= ny - 2 )
+			increments[1] = ny - 3;
+		if( nDims == 3 && increments[2] >= nz - 2 )
+			increments[2] = nz - 3;
+
+		lineNum0 = increments[0] + nx * increments[1];
+		if( nDims == 3 ) lineNum0 += nx * ny * increments[2];
+		if( lineNum0 >= total )
+			Journal_Printf( context->info, "interpolation error: node value: %d resolution size: %d\n", lineNum0, total );
+			
+		vertex0[0] = posx[lineNum0];
+		vertex0[1] = posy[lineNum0];
+		if( nDims == 3 ) vertex0[2] = posz[lineNum0];
+		
+		/* for quadratic elements the resolution is twice the distance between the nodes */
+		for( dim_I = 0; dim_I < nDims; dim_I++ )
+			coordPrime[dim_I] = ( coord[dim_I] - vertex0[dim_I] ) / resolution[dim_I] - 1.0;
+
+		/* assign the shape functions & interpolate quadratically */
+		if( nDims == 2 ) {
+			xi = coordPrime[0]; eta = coordPrime[1];
+			a0 = xi - 1.0; b0 = eta - 1.0;
+			a1 = 1.0 - xi * xi; b1 = 1.0 - eta * eta;
+			a2 = xi + 1.0; b2 = eta + 1.0;
+			m0 = 0.5 * xi; m1 = 0.5 * eta; m2 = 0.25 * xi * eta;
+
+			Ni[0] = m2 * a0 * b0; Ni[1] = m1 * a1 * b0; Ni[2] = m2 * a2 * b0;
+			Ni[3] = m0 * a0 * b1; Ni[4] =      a1 * b1; Ni[5] = m0 * a2 * b1;
+			Ni[6] = m2 * a0 * b2; Ni[7] = m1 * a1 * b2; Ni[8] = m2 * a2 * b2;
+
+			for( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
+				values[0][dof_I] = variables[lineNum0][dof_I];
+				values[1][dof_I] = variables[lineNum0+1][dof_I];
+				values[2][dof_I] = variables[lineNum0+2][dof_I];
+				values[3][dof_I] = variables[lineNum0+nx][dof_I];
+				values[4][dof_I] = variables[lineNum0+nx+1][dof_I];
+				values[5][dof_I] = variables[lineNum0+nx+2][dof_I];
+				values[6][dof_I] = variables[lineNum0+(2*nx)][dof_I];
+				values[7][dof_I] = variables[lineNum0+(2*nx)+1][dof_I];
+				values[8][dof_I] = variables[lineNum0+(2*nx)+2][dof_I];
+					
+				value[dof_I] = 0.0;
+				for( shapeFunc_I = 0; shapeFunc_I < numShapeFuncs; shapeFunc_I++ )
+					value[dof_I] += Ni[shapeFunc_I] * values[shapeFunc_I][dof_I];
+			}
+		}
+		else {
+			xi = coordPrime[0]; eta = coordPrime[1]; zeta = coordPrime[2];
+			a0 = xi - 1.0; b0 = eta - 1.0; c0 = zeta - 1.0;
+			a1 = 1.0 - xi * xi; b1 = 1.0 - eta * eta; c1 = 1.0 - zeta * zeta;
+			a2 = xi + 1.0; b2 = eta + 1.0; c2 = zeta + 1.0;
+			m0 = 0.5 * xi; m1 = 0.5 * eta; m2 = 0.5 * zeta;
+			m3 = 0.25 * xi * eta; m4 = 0.25 * xi * zeta; m5 = 0.25 * eta * zeta;
+			m6 = 0.125 * xi * eta * zeta;
+
+			Ni[0]  = m6 * a0 * b0 * c0; Ni[1]  = m5 * a1 * b0 * c0; Ni[2]  = m6 * a2 * b0 * c0;
+			Ni[3]  = m4 * a0 * b1 * c0; Ni[4]  = m2 * a1 * b1 * c0; Ni[5]  = m4 * a2 * b1 * c0;
+			Ni[6]  = m6 * a0 * b2 * c0; Ni[7]  = m5 * a1 * b2 * c0; Ni[8]  = m6 * a2 * b2 * c0;
+
+			Ni[9]  = m3 * a0 * b0 * c1; Ni[10] = m1 * a1 * b0 * c1; Ni[11] = m3 * a2 * b0 * c1;
+			Ni[12] = m0 * a0 * b1 * c1; Ni[13] =      a1 * b1 * c1; Ni[14] = m0 * a2 * b1 * c1;
+			Ni[15] = m3 * a0 * b2 * c1; Ni[16] = m1 * a1 * b2 * c1; Ni[17] = m3 * a2 * b2 * c1;
+
+			Ni[18] = m6 * a0 * b0 * c2; Ni[19] = m5 * a1 * b0 * c2; Ni[20] = m6 * a2 * b0 * c2;
+			Ni[21] = m4 * a0 * b1 * c2; Ni[22] = m2 * a1 * b1 * c2; Ni[23] = m4 * a2 * b1 * c2;
+			Ni[24] = m6 * a0 * b2 * c2; Ni[25] = m5 * a1 * b2 * c2; Ni[26] = m6 * a2 * b2 * c2;
+				
+			for( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
+				values[0][dof_I]  = variables[lineNum0][dof_I];
+				values[1][dof_I]  = variables[lineNum0+1][dof_I];
+				values[2][dof_I]  = variables[lineNum0+2][dof_I];
+				values[3][dof_I]  = variables[lineNum0+nx][dof_I];
+				values[4][dof_I]  = variables[lineNum0+nx+1][dof_I];
+				values[5][dof_I]  = variables[lineNum0+nx+2][dof_I];
+				values[6][dof_I]  = variables[lineNum0+(2*nx)][dof_I];
+				values[7][dof_I]  = variables[lineNum0+(2*nx)+1][dof_I];
+				values[8][dof_I]  = variables[lineNum0+(2*nx)+2][dof_I];
+
+				values[9][dof_I]  = variables[lineNum0+(nx*ny)][dof_I];
+				values[10][dof_I] = variables[lineNum0+(nx*ny)+1][dof_I];
+				values[11][dof_I] = variables[lineNum0+(nx*ny)+2][dof_I];
+				values[12][dof_I] = variables[lineNum0+(nx*ny)+nx][dof_I];
+				values[13][dof_I] = variables[lineNum0+(nx*ny)+nx+1][dof_I];
+				values[14][dof_I] = variables[lineNum0+(nx*ny)+nx+2][dof_I];
+				values[15][dof_I] = variables[lineNum0+(nx*ny)+(2*nx)][dof_I];
+				values[16][dof_I] = variables[lineNum0+(nx*ny)+(2*nx)+1][dof_I];
+				values[17][dof_I] = variables[lineNum0+(nx*ny)+(2*nx)+2][dof_I];
+
+				values[18][dof_I] = variables[lineNum0+(2*nx*ny)][dof_I];
+				values[19][dof_I] = variables[lineNum0+(2*nx*ny)+1][dof_I];
+				values[20][dof_I] = variables[lineNum0+(2*nx*ny)+2][dof_I];
+				values[21][dof_I] = variables[lineNum0+(2*nx*ny)+nx][dof_I];
+				values[22][dof_I] = variables[lineNum0+(2*nx*ny)+nx+1][dof_I];
+				values[23][dof_I] = variables[lineNum0+(2*nx*ny)+nx+2][dof_I];
+				values[24][dof_I] = variables[lineNum0+(2*nx*ny)+(2*nx)][dof_I];
+				values[25][dof_I] = variables[lineNum0+(2*nx*ny)+(2*nx)+1][dof_I];
+				values[26][dof_I] = variables[lineNum0+(2*nx*ny)+(2*nx)+2][dof_I];
+
+				value[dof_I] = 0.0;
+				for( shapeFunc_I = 0; shapeFunc_I < numShapeFuncs; shapeFunc_I++ )
+					value[dof_I] += Ni[shapeFunc_I] * values[shapeFunc_I][dof_I];
+			}
+		}
+
+		FeVariable_SetValueAtNode( feVariable, node_I, value );
+	}
+
+	Memory_Free( filename );
+	Memory_Free( posx );
+	Memory_Free( posy );
+	if( nDims == 3 ) Memory_Free( posz );
+	Memory_Free( variables );
+
+#ifdef READ_HDF5
+	H5Fclose( inputFile );
+#endif
+}
+
+void _FieldTest_DumpToAnalysisFile( FieldTest* self, Stream* analysisStream ) {
+	int			field_I, numDofs, dim, dof_I;
+	/* double		error; */
+	FeVariable*	errorField;
+
+	for( field_I = 0; field_I < self->fieldCount; field_I++ ) {
+		/* should be using MT_VOLUME for the reference field mesh, but seems to have a bug */
+		errorField = self->errorFieldList[field_I];
+		numDofs	   = self->numericFieldList[field_I]->fieldComponentCount;
+		dim = self->numericFieldList[field_I]->dim;
+
+#if 0
+		/* Fancy error measurements of magnitudes and 2ndInvars, no needed
+		 * but I'm leaving it in incase */
+		if( dim == numDofs ) {
+			/* It's a vector */
+			error = StGermain_VectorMagnitude( self->gErrorNorm[field_I], dim );
+		} else if ( numDofs > self->numericFieldList[field_I]->dim ) {
+			/* Assume it's a symmetric tensor */
+			error = SymmetricTensor_2ndInvariant( self->gErrorNorm[field_I], dim );	
+		} else {
+			/* It's a scalar */
+			error = self->gErrorNorm[field_I][0];
+		}
+		Journal_Printf( analysisStream, "%.8e ", error );
+#endif
+		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
+			if(self->normalise)
+				Journal_RPrintf( analysisStream, "%.8e ", self->gErrorNorm[field_I][dof_I] );
+			else
+				Journal_RPrintf( analysisStream, "%.8e ", self->gErrorSq[field_I][dof_I] );
+		}
+
+	}
+}
+
+/* by default, success of the physics test is set to false. this is reset if the test passes */
+void FieldTest_EvaluatePhysicsTest( void* _context, void* data ) {
+	DomainContext*			context			= (DomainContext*)_context;
+	/* dodgy!!! - not sure how else to pass the self reference at an entry point */
+	FieldTest*			self			= fieldTestSingleton;
+	FieldTest_ExpectedResultFunc*	expectedFunc		= self->expectedFunc;
+	FILE*				dumpExpectedFilePtr;
+	char*				dumpExpectedFileName;
+	int				dim_i, dof_i;
+
+	if( expectedFunc( self->expectedData, context, self->expected, self->numeric, self->tolerance ) )
+		self->expectedPass = True;
+
+	if( strlen(self->dumpExpectedFileName) > 1 ) {
+		dumpExpectedFileName = Memory_Alloc_Array_Unnamed( char, strlen(self->expectedFilePath) + 
+									 strlen(self->dumpExpectedFileName) + 5 );
+		sprintf( dumpExpectedFileName, "%s%s.out", self->expectedFilePath, self->dumpExpectedFileName );
+		dumpExpectedFilePtr = fopen( dumpExpectedFileName, "a" );
+
+		fprintf( dumpExpectedFilePtr, "%.8e ", self->numeric[context->timeStep].time );
+		for( dim_i = 0; dim_i < context->dim; dim_i++ )
+			fprintf( dumpExpectedFilePtr, "%.8e ", self->numeric[context->timeStep].place[dim_i] );
+		for( dof_i = 0; dof_i < self->expectedDofs; dof_i++ )
+			fprintf( dumpExpectedFilePtr, "%.8e ", self->numeric[context->timeStep].value[dof_i] );
+
+		fprintf( dumpExpectedFilePtr, "\n" );
+
+		if( context->timeStep == context->maxTimeSteps ) {
+			if( self->expectedPass )
+				fprintf( dumpExpectedFilePtr, "test result: PASS\n" );
+			else
+				fprintf( dumpExpectedFilePtr, "test result: FAIL\n" );
+		}
+
+		Memory_Free( dumpExpectedFileName );
+		fclose( dumpExpectedFilePtr );
+	}
+}
+
+void FieldTest_GenerateErrFields( void* _context, void* data ) {
+	DomainContext*	context = (DomainContext*)_context;
+	/* this a really dodgy way to get the self ptr, as will only work if the textual name is consistent with that in 
+	 * the XML - need to find a way to add an entry point which allows the self ptr to be passed as a void * */
+	//FieldTest* 		self 			= LiveComponentRegister_Get( context->CF->LCRegister, (Name)"NumericFields"  );
+	/* this is also a dodgy way to get the self ptr, as its obtained from a global variable */
+	FieldTest*		self = fieldTestSingleton;
+	FeVariable*		errorField;
+	Index				lMeshSize, lElement_I;
+	double			elErrorSq[9], elNormSq[9], elError[9];
+	double			lAnalyticSq[9], gAnalyticSq[9];
+	double			lErrorSq[9], gErrorSq[9];
+	Bool				normalise = self->normalise;
+	Index				numDofs, dof_I, fieldCount;
+	Index				field_I;
+	Stream*			analysisStream;
+	/* double			eps = self->epsilon; */
+	
+	/* if testTimestep is NOT initialise and NOT equal to the current timestep
+	 * we skip this function */
+	if( self->testTimestep != context->timeStep && self->testTimestep != 0 )
+		return;
+
+	fieldCount = self->fieldCount;
+
+	if( self->appendToAnalysisFile ) {
+		/* append (or create if not found ) a file to report results */
+		double length, elementResI;
+		char* filename;
+		analysisStream = Journal_Register( Info_Type, (Name)self->type  );
+		Stg_asprintf( &filename, "%s-analysis.cvg", self->name );
+		Stream_AppendFile( analysisStream, filename );
+		Memory_Free( filename );
+
+		/* write heading names in file */
+		Journal_RPrintf( analysisStream, "#Res ");
+		for(field_I = 0 ; field_I < fieldCount ; field_I++ ) {
+			numDofs = self->numericFieldList[field_I]->fieldComponentCount;
+			for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
+				Journal_RPrintf( analysisStream, "%s%d ", self->numericFieldList[field_I]->name, dof_I+1 );
+			}
+		}
+		length = Dictionary_GetDouble( context->CF->rootDict, "maxX" ) - Dictionary_GetDouble( context->CF->rootDict, "minX" ) ;
+		elementResI = Dictionary_GetInt( context->CF->rootDict, (Dictionary_Entry_Key)"elementResI"  );
+		/* assume square resolution */
+		Journal_RPrintf( analysisStream, "\n%e ", length/elementResI );
+	}
+
+	for( field_I = 0; field_I < fieldCount; field_I++ ) {
+		/* should be using MT_VOLUME for the reference field mesh, but seems to have a bug */
+		lMeshSize  = Mesh_GetLocalSize( self->constantMesh, MT_VERTEX );
+		errorField = self->errorFieldList[field_I];
+		numDofs	   = self->numericFieldList[field_I]->fieldComponentCount;
+
+		assert( !strcmp( errorField->feMesh->name, "constantMesh" ) );
+
+		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
+			lAnalyticSq[dof_I] = 0.0;
+			lErrorSq[dof_I]    = 0.0;
+		}
+	
+		for( lElement_I = 0; lElement_I < lMeshSize; lElement_I++ ) {
+			for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
+				elErrorSq[dof_I] = 0.0;
+				elNormSq[dof_I]  = 0.0;
+			}
+
+			if( self->referenceSolnFromFile )
+				FieldTest_ElementErrReferenceFromField( self, field_I, lElement_I, elErrorSq, elNormSq );
+			else
+				FieldTest_ElementErrAnalyticFromField( self, field_I, lElement_I, elErrorSq, elNormSq );
+
+			for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
+					lAnalyticSq[dof_I] += elNormSq[dof_I];
+					lErrorSq[dof_I]    += elErrorSq[dof_I];
+					//elError[dof_I] = normalise ? sqrt( elErrorSq[dof_I] / ( elNormSq[dof_I] + eps ) ) : sqrt( elErrorSq[dof_I] );
+					elError[dof_I] = normalise ? sqrt( elErrorSq[dof_I] / ( elNormSq[dof_I] ) ) : sqrt( elErrorSq[dof_I] );
+			}
+
+			/* constant mesh, so node and element indices map 1:1 */
+			FeVariable_SetValueAtNode( errorField, lElement_I, elError );
+		}
+	
+		MPI_Allreduce( lAnalyticSq, gAnalyticSq, numDofs, MPI_DOUBLE, MPI_SUM, self->referenceFieldList[field_I]->communicator );
+		MPI_Allreduce( lErrorSq,    gErrorSq,    numDofs, MPI_DOUBLE, MPI_SUM, self->referenceFieldList[field_I]->communicator );
+
+		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
+			self->gAnalyticSq[field_I][dof_I] = gAnalyticSq[dof_I];
+			self->gErrorSq[field_I][dof_I]    = gErrorSq[dof_I];
+			self->gErrorNorm[field_I][dof_I]  = sqrt( gErrorSq[dof_I] / gAnalyticSq[dof_I] );
+
+			if( normalise ) {
+				Journal_RPrintf( context->info, "%s - dof %d normalised global error: %.8e\n", 
+				     	self->numericFieldList[field_I]->name, dof_I, self->gErrorNorm[field_I][dof_I] );
+			}
+			else {
+				Journal_RPrintf( context->info, "%s - dof %d global error: %.8e\n",
+					self->numericFieldList[field_I]->name, dof_I, sqrt( self->gErrorSq[field_I][dof_I] ) );
+			}
+		}
+	}
+
+	if( self->appendToAnalysisFile ) {
+		_FieldTest_DumpToAnalysisFile( self, analysisStream );
+		Journal_RPrintf( analysisStream, "\n" );
+		Stream_CloseAndFreeFile( analysisStream );
+	}
+}
+
+void FieldTest_ElementErrReferenceFromField( void* fieldTest, Index field_I, Index lElement_I, double* elErrorSq, double* elNormSq ) {
+	FieldTest* 		self 			= (FieldTest*) fieldTest;
+	FeVariable*		referenceField		= self->referenceFieldList[field_I];
+	FeVariable*		numericField		= self->numericFieldList[field_I];
+	FeMesh*			referenceMesh		= referenceField->feMesh;
+	FeMesh*			elementMesh		= self->elementMesh;
+	Index			constantElNode		= lElement_I;
+	double*			coord			= Mesh_GetVertex( self->constantMesh, constantElNode );
+	unsigned		nDims			= Mesh_GetDimSize( referenceMesh );
+	Index			el_I, elementMeshElem;
+	ElementType*		elType;
+	Swarm*			intSwarm		= self->integrationSwarm;
+	Index			cell_I;
+	unsigned		cellParticleCount;
+	Index			cParticle_I;
+	IntegrationPoint*	cParticle;
+	double			*xi, weight;
+	double			globalCoord[3];
+	double			detJac;
+	double			reference[9], numeric[9];
+	Index			numDofs			= numericField->fieldComponentCount;
+	Index			dof_I;
+
+	/* don't assume that the constant error field mesh & reference field mesh necessarily map 1:1 */
+	Mesh_SearchElements( referenceMesh, coord, &el_I );
+	Mesh_SearchElements( elementMesh, coord, &elementMeshElem );
+	elType = FeMesh_GetElementType( elementMesh, elementMeshElem );
+
+	cell_I = CellLayout_MapElementIdToCellId( intSwarm->cellLayout, el_I );
+	cellParticleCount = intSwarm->cellParticleCountTbl[cell_I];
+
+	for( cParticle_I = 0; cParticle_I < cellParticleCount; cParticle_I++ ) {
+		cParticle = (IntegrationPoint*) Swarm_ParticleInCellAt( intSwarm, cell_I, cParticle_I );
+		xi 	  = cParticle->xi;
+		weight	  = cParticle->weight;
+
+		FeMesh_CoordLocalToGlobal( referenceMesh, el_I, xi, globalCoord );
+		FieldVariable_InterpolateValueAt( referenceField, globalCoord, reference );
+		FieldVariable_InterpolateValueAt( numericField,   globalCoord, numeric   );
+
+		detJac = ElementType_JacobianDeterminant( elType, elementMesh, elementMeshElem, xi, nDims );
+
+		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
+			elErrorSq[dof_I] += ( numeric[dof_I] - reference[dof_I] ) * ( numeric[dof_I] - reference[dof_I] ) 
+					    * weight * detJac;
+			elNormSq[dof_I]  += reference[dof_I] * reference[dof_I] * weight * detJac;
+		}
+	}
+}
+
+void FieldTest_ElementErrAnalyticFromField( void* fieldTest, Index field_I, Index lElement_I, double* elErrorSq, double* elNormSq ) {
+	FieldTest*			self = (FieldTest*) fieldTest;
+	FeVariable*			numericField = self->numericFieldList[field_I];
+	FeMesh*				elementMesh = self->elementMesh;
+	Index					constantElNode = lElement_I;
+	double*				coord = Mesh_GetVertex( self->constantMesh, constantElNode );
+	unsigned				nDims = Mesh_GetDimSize( elementMesh );
+	Index					el_I;
+	ElementType*		elType;
+	Swarm*				intSwarm = self->integrationSwarm;
+	Index					cell_I;
+	unsigned				cellParticleCount;
+	Index					cParticle_I;
+	IntegrationPoint*	cParticle;
+	double				*xi, weight;
+	double				globalCoord[3];
+	double				detJac;
+	double				analytic[9], numeric[9];
+	Index					numDofs = numericField->fieldComponentCount;
+	Index					dof_I;
+	/* corresponding analytic solution function for this feVariable, as assigned in the plugin */
+	FieldTest_AnalyticSolutionFunc*	analyticSolution = self->_analyticSolutionList[self->analyticSolnForFeVarKey[field_I]];
+
+	/* don't assume that the constant error field mesh & reference field mesh necessarily map 1:1 */
+	Mesh_SearchElements( elementMesh, coord, &el_I );
+	elType = FeMesh_GetElementType( elementMesh, el_I );
+
+	cell_I = CellLayout_MapElementIdToCellId( intSwarm->cellLayout, el_I );
+	cellParticleCount = intSwarm->cellParticleCountTbl[cell_I];
+
+	for( cParticle_I = 0; cParticle_I < cellParticleCount; cParticle_I++ ) {
+		cParticle = (IntegrationPoint*) Swarm_ParticleInCellAt( intSwarm, cell_I, cParticle_I );
+		xi	  = cParticle->xi;
+		weight    = cParticle->weight;
+
+		detJac = ElementType_JacobianDeterminant( elType, elementMesh, el_I, xi, nDims );
+
+		FeMesh_CoordLocalToGlobal( elementMesh, el_I, xi, globalCoord );
+		analyticSolution( self, globalCoord, analytic );
+		FieldVariable_InterpolateValueAt( numericField, globalCoord, numeric );
+
+		for( dof_I = 0; dof_I < numDofs; dof_I++ ) {
+			elErrorSq[dof_I] += ( numeric[dof_I] - analytic[dof_I] ) * ( numeric[dof_I] - analytic[dof_I] ) * weight * detJac;
+			elNormSq[dof_I]  += analytic[dof_I] * analytic[dof_I] * weight * detJac;
+		}
+	}
+}
+
+void FieldTest_ElementErrAnalyticFromSwarm( void* fieldTest, Index var_I, Index lElement_I, double* elErrorSq, double* elNormSq ) {
+}
+
+void FieldTest_ElementErrReferenceFromSwarm( void* fieldTest, Index var_I, Index lElement_I, double* elErrorSq, double* elNormSq ) {
+}
+
+/* the first index 'func_I' denotes the index of the function in the analytic solution list to be applied to calculate
+ * the analytic field at index 'field_I' in the analytic field list.
+ *
+ * the analytic fields are in the same order as their numeric counterparts are read in from the XML */
+void FieldTest_AddAnalyticSolutionFuncToListAtIndex( void* fieldTest, Index func_I, FieldTest_AnalyticSolutionFunc* func, Index field_I ) {
+	FieldTest* 	self 	= (FieldTest*) fieldTest;
+
+	self->_analyticSolutionList[func_I] = func;
+	self->analyticSolnForFeVarKey[field_I] = func_I;
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Finalise.c
--- a/Discretisation/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType_Register.h"
-#include "Finalise.h"
-
-#include "FeVariable.h"
-#include <petsc.h>
-
-#include <stdio.h>
-
-Bool StgFEM_Discretisation_Finalise( void ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	Stream_IndentBranch( StgFEM_Debug );
-
-	_ElementType_Register_Delete( elementType_Register );
-
-	PetscFinalize();
-	
-	Stream_UnIndentBranch( StgFEM_Debug );
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,69 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType_Register.h"
+#include "Finalise.h"
+
+#include "FeVariable.h"
+#include <petsc.h>
+
+#include <stdio.h>
+
+Bool StgFEM_Discretisation_Finalise( void ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	Stream_IndentBranch( StgFEM_Debug );
+
+	_ElementType_Register_Delete( elementType_Register );
+
+	PetscFinalize();
+	
+	Stream_UnIndentBranch( StgFEM_Debug );
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FunctionSuite.c
--- a/Discretisation/src/FunctionSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/* Suite of functions for evaluating diagnostic properties from StG.
- * components (ie: Swarms, FeVariables, OperatorFeVariables)
- *
- * */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <math.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "types.h"
-#include "FeMesh.h"
-#include "FeVariable.h"
-#include "FunctionSuite.h"
-
-/* root mean squared velocity, takes in a velocity squared
- * OperatorFeVariable and an integration Swarm */
-double StgFEM_Vrms( FeVariable* velsq, Swarm* swarm ) {
-	Mesh*		mesh		= (Mesh*) velsq->feMesh;
-	double		max[3], min[3];
-	double		volume;
-	double		integral;
-	double		vrms;
-	unsigned	dim		= Mesh_GetDimSize( mesh );
-
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-
-	integral = FeVariable_Integrate( velsq, swarm );
-
-	volume = ( max[I_AXIS] - min[I_AXIS] ) * ( max[J_AXIS] - min[J_AXIS] );
-	if( dim == 3 )
-		volume *= ( max[K_AXIS] - min[K_AXIS] );
-
-	vrms = sqrt( integral / volume );
-
-	return vrms;
-}
-
-/* optimised version of the feVariable interpolation function. assumes constant number of dofs for each node */
-void StgFEM_InterpolateValue_WithNi( void* _feVariable, Element_LocalIndex lElement_I, double* Ni, double* value ) {
-	FeVariable*             self        = (FeVariable*) _feVariable;
-	Node_ElementLocalIndex  elLocalNode_I;
-	Node_LocalIndex         lNode_I;
-	Dof_Index               dof_I;
-	Dof_Index               dofCount;
-	Variable*               dofVariable;
-	double                  nodeValue;
-	unsigned		nInc, *inc;
-
-	/* Gets number of degrees of freedom - assuming it is the same throughout the mesh */
-	dofCount = self->dofLayout->dofCounts[0];
-
-	/* Initialise */
-	memset( value, 0, sizeof( double )*dofCount );
-
-	FeMesh_GetElementNodes( self->feMesh, lElement_I, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = (unsigned*)IArray_GetPtr( self->inc );
-
-	for ( dof_I = 0; dof_I < dofCount; dof_I++ ) {
-		dofVariable = DofLayout_GetVariable( self->dofLayout, 0, dof_I );
-		for ( elLocalNode_I = 0 ; elLocalNode_I < nInc ; elLocalNode_I++) {
-			lNode_I      = inc[ elLocalNode_I ];
-			nodeValue    = Variable_GetValueDouble( dofVariable, lNode_I );
-			value[dof_I] += Ni[elLocalNode_I] * nodeValue;
-		}
-	}
-}
-
-/* optimised version of the feVariable interpolate derivatives function. assumes constant number of dofs for each node */
-void StgFEM_InterpolateDerivatives_WithGNx( void* _feVariable, Element_LocalIndex lElement_I, double** GNx, double* value ) {
-	FeVariable*             self        = (FeVariable*) _feVariable;
-	Node_ElementLocalIndex  elLocalNode_I;
-	Node_LocalIndex         lNode_I;
-	Dof_Index               dof_I, dim_I;
-	Dof_Index               dofCount;
-	Variable*               dofVariable;
-	double                  nodeValue;
-	unsigned		nInc, *inc;
-	Dimension_Index         dim         = self->dim;
-
-	/* Gets number of degrees of freedom - assuming it is the same throughout the mesh */
-	dofCount = self->dofLayout->dofCounts[0];
-
-	/* Initialise */
-	memset( value, 0, sizeof( double )*dofCount*dim );
-
-	FeMesh_GetElementNodes( self->feMesh, lElement_I, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = (unsigned*)IArray_GetPtr( self->inc );
-
-	for ( dof_I = 0 ; dof_I < dofCount ; dof_I++ ) {
-		dofVariable  = DofLayout_GetVariable( self->dofLayout, 0, dof_I );
-		/* Interpolate derivative from nodes */
-		for ( elLocalNode_I = 0; elLocalNode_I < nInc; elLocalNode_I++) {
-			lNode_I      = inc[ elLocalNode_I ];
-			nodeValue    = Variable_GetValueDouble( dofVariable, lNode_I );
-			
-			for( dim_I = 0; dim_I < dim; dim_I++ )
-				value[dof_I*dim + dim_I] += GNx[dim_I][elLocalNode_I] * nodeValue;
-		}
-	}
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/FunctionSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/FunctionSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,109 @@
+/* Suite of functions for evaluating diagnostic properties from StG.
+ * components (ie: Swarms, FeVariables, OperatorFeVariables)
+ *
+ * */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "types.h"
+#include "FeMesh.h"
+#include "FeVariable.h"
+#include "FunctionSuite.h"
+
+/* root mean squared velocity, takes in a velocity squared
+ * OperatorFeVariable and an integration Swarm */
+double StgFEM_Vrms( FeVariable* velsq, Swarm* swarm ) {
+	Mesh*		mesh		= (Mesh*) velsq->feMesh;
+	double		max[3], min[3];
+	double		volume;
+	double		integral;
+	double		vrms;
+	unsigned	dim		= Mesh_GetDimSize( mesh );
+
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+
+	integral = FeVariable_Integrate( velsq, swarm );
+
+	volume = ( max[I_AXIS] - min[I_AXIS] ) * ( max[J_AXIS] - min[J_AXIS] );
+	if( dim == 3 )
+		volume *= ( max[K_AXIS] - min[K_AXIS] );
+
+	vrms = sqrt( integral / volume );
+
+	return vrms;
+}
+
+/* optimised version of the feVariable interpolation function. assumes constant number of dofs for each node */
+void StgFEM_InterpolateValue_WithNi( void* _feVariable, Element_LocalIndex lElement_I, double* Ni, double* value ) {
+	FeVariable*             self        = (FeVariable*) _feVariable;
+	Node_ElementLocalIndex  elLocalNode_I;
+	Node_LocalIndex         lNode_I;
+	Dof_Index               dof_I;
+	Dof_Index               dofCount;
+	Variable*               dofVariable;
+	double                  nodeValue;
+	unsigned		nInc, *inc;
+
+	/* Gets number of degrees of freedom - assuming it is the same throughout the mesh */
+	dofCount = self->dofLayout->dofCounts[0];
+
+	/* Initialise */
+	memset( value, 0, sizeof( double )*dofCount );
+
+	FeMesh_GetElementNodes( self->feMesh, lElement_I, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = (unsigned*)IArray_GetPtr( self->inc );
+
+	for ( dof_I = 0; dof_I < dofCount; dof_I++ ) {
+		dofVariable = DofLayout_GetVariable( self->dofLayout, 0, dof_I );
+		for ( elLocalNode_I = 0 ; elLocalNode_I < nInc ; elLocalNode_I++) {
+			lNode_I      = inc[ elLocalNode_I ];
+			nodeValue    = Variable_GetValueDouble( dofVariable, lNode_I );
+			value[dof_I] += Ni[elLocalNode_I] * nodeValue;
+		}
+	}
+}
+
+/* optimised version of the feVariable interpolate derivatives function. assumes constant number of dofs for each node */
+void StgFEM_InterpolateDerivatives_WithGNx( void* _feVariable, Element_LocalIndex lElement_I, double** GNx, double* value ) {
+	FeVariable*             self        = (FeVariable*) _feVariable;
+	Node_ElementLocalIndex  elLocalNode_I;
+	Node_LocalIndex         lNode_I;
+	Dof_Index               dof_I, dim_I;
+	Dof_Index               dofCount;
+	Variable*               dofVariable;
+	double                  nodeValue;
+	unsigned		nInc, *inc;
+	Dimension_Index         dim         = self->dim;
+
+	/* Gets number of degrees of freedom - assuming it is the same throughout the mesh */
+	dofCount = self->dofLayout->dofCounts[0];
+
+	/* Initialise */
+	memset( value, 0, sizeof( double )*dofCount*dim );
+
+	FeMesh_GetElementNodes( self->feMesh, lElement_I, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = (unsigned*)IArray_GetPtr( self->inc );
+
+	for ( dof_I = 0 ; dof_I < dofCount ; dof_I++ ) {
+		dofVariable  = DofLayout_GetVariable( self->dofLayout, 0, dof_I );
+		/* Interpolate derivative from nodes */
+		for ( elLocalNode_I = 0; elLocalNode_I < nInc; elLocalNode_I++) {
+			lNode_I      = inc[ elLocalNode_I ];
+			nodeValue    = Variable_GetValueDouble( dofVariable, lNode_I );
+			
+			for( dim_I = 0; dim_I < dim; dim_I++ )
+				value[dof_I*dim + dim_I] += GNx[dim_I][elLocalNode_I] * nodeValue;
+		}
+	}
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Init.c
--- a/Discretisation/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 1218 2008-09-04 06:18:44Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <stdio.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-Stream* StgFEM_Debug = NULL;
-Stream* StgFEM_Warning = NULL;
-Stream* StgFEM_Discretisation_Debug = NULL;
-
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_Discretisation_Init( int* argc, char** argv[] ) {
-	Stg_ComponentRegister* componentRegister = Stg_ComponentRegister_Get_ComponentRegister();
-	int tmp;
-	
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	tmp = Stream_GetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context" )  );
-	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), 0 );
-	Journal_Printf( /* DO NOT CHANGE OR REMOVE */ Journal_Register( InfoStream_Type, (Name)"Context"  ), 
-		"StGermain FEM Discretisation Framework revision %s. Copyright (C) 2003-2005 VPAC.\n", VERSION );
-	Stream_Flush( Journal_Register( InfoStream_Type, (Name)"Context" )  );
-	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), tmp );
-	
-	/* initialise this level's streams */
-	StgFEM_Debug = Journal_Register( DebugStream_Type, (Name)"StgFEM"  );
-	StgFEM_Discretisation_Debug = Stream_RegisterChild( StgFEM_Debug, "Discretisation" );
-	StgFEM_Warning = Journal_Register( ErrorStream_Type, (Name)"StgFEM" );
-
-	elementType_Register = ElementType_Register_New( "elementType_Register"  );
-	ElementType_Register_Add( elementType_Register, (ElementType*)ConstantElementType_New( "constantElementType" ) );
-	ElementType_Register_Add( elementType_Register, (ElementType*)BilinearElementType_New( "bilinearElementType" ) );
-	ElementType_Register_Add( elementType_Register, (ElementType*)TrilinearElementType_New( "trilinearElementType" ) );
-	ElementType_Register_Add( elementType_Register, (ElementType*)LinearTriangleElementType_New( "linearElementType" ) );
-	ElementType_Register_Add( elementType_Register, (ElementType*)Biquadratic_New( "biquadraticElementType" ) );
-	ElementType_Register_Add( elementType_Register, (ElementType*)Triquadratic_New( "triquadraticElementType" ) );
-	
-	Stg_ComponentRegister_Add( componentRegister, FeVariable_Type, (Name)"0", _FeVariable_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, LinkedDofInfo_Type, (Name)"0", _LinkedDofInfo_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, OperatorFeVariable_Type, (Name)"0", _OperatorFeVariable_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, ShapeFeVariable_Type, (Name)"0", ShapeFeVariable_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, FeSwarmVariable_Type, (Name)"0", _FeSwarmVariable_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, FeMesh_Type, (Name)"0",
-                                   (Stg_Component_DefaultConstructorFunction*)_FeMesh_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, C0Generator_Type, (Name)"0",
-                                   (Stg_Component_DefaultConstructorFunction*)C0Generator_New  );
-	Stg_ComponentRegister_Add( componentRegister, C2Generator_Type, (Name)"0",
-                                   (Stg_Component_DefaultConstructorFunction*)C2Generator_New  );
-/*
-	Stg_ComponentRegister_Add( componentRegister, P1Generator_Type, (Name)"0", P1Generator_New  );
-*/
-	Stg_ComponentRegister_Add( componentRegister, Inner2DGenerator_Type, (Name)"0", (Stg_Component_DefaultConstructorFunction*)Inner2DGenerator_New  );
-	Stg_ComponentRegister_Add( componentRegister, FieldTest_Type, (Name)"0", _FieldTest_DefaultNew  );
-	
-	/** Register Parents for type checking */
-	RegisterParent( FeMesh_Algorithms_Type, Mesh_Algorithms_Type );
-	RegisterParent( FeMesh_ElementType_Type, Mesh_HexType_Type );
-	RegisterParent( ElementType_Type, Stg_Component_Type );
-	RegisterParent( BilinearElementType_Type, ElementType_Type );
-	RegisterParent( TrilinearElementType_Type, ElementType_Type );
-	RegisterParent( Biquadratic_Type, ElementType_Type );
-	RegisterParent( Triquadratic_Type, ElementType_Type );
-	RegisterParent( P1_Type, ElementType_Type );
-	RegisterParent( RegularTrilinear_Type, TrilinearElementType_Type );
-	RegisterParent( ConstantElementType_Type, ElementType_Type );
-	RegisterParent( LinearTriangleElementType_Type, ElementType_Type );
-	RegisterParent( ElementType_Register_Type, Stg_Component_Type );
-
-	RegisterParent( FeEquationNumber_Type, Stg_Component_Type );
-	RegisterParent( LinkedDofInfo_Type, Stg_Component_Type );
-	RegisterParent( FeMesh_Type, Mesh_Type );
-	RegisterParent( C0Generator_Type, MeshGenerator_Type );
-	RegisterParent( C2Generator_Type, CartesianGenerator_Type );
-/*
-	RegisterParent( P1Generator_Type, MeshGenerator_Type );
-*/
-	RegisterParent( Inner2DGenerator_Type, MeshGenerator_Type );
-	
-	RegisterParent( FeVariable_Type, FieldVariable_Type );
-	RegisterParent( OperatorFeVariable_Type, FeVariable_Type );
-	RegisterParent( ShapeFeVariable_Type, FeVariable_Type );
-	RegisterParent( FeSwarmVariable_Type, SwarmVariable_Type );
-
-	RegisterParent( FieldTest_Type, Stg_Component_Type );
-
-	{
-		PetscErrorCode	ec;
-		ec = PetscInitialize( argc, argv, (char*)0, NULL );
-		CheckPETScError( ec );
-	}
-
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,139 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 1218 2008-09-04 06:18:44Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <stdio.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+Stream* StgFEM_Debug = NULL;
+Stream* StgFEM_Warning = NULL;
+Stream* StgFEM_Discretisation_Debug = NULL;
+
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_Discretisation_Init( int* argc, char** argv[] ) {
+	Stg_ComponentRegister* componentRegister = Stg_ComponentRegister_Get_ComponentRegister();
+	int tmp;
+	
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	tmp = Stream_GetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context" )  );
+	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), 0 );
+	Journal_Printf( /* DO NOT CHANGE OR REMOVE */ Journal_Register( InfoStream_Type, (Name)"Context"  ), 
+		"StGermain FEM Discretisation Framework revision %s. Copyright (C) 2003-2005 VPAC.\n", VERSION );
+	Stream_Flush( Journal_Register( InfoStream_Type, (Name)"Context" )  );
+	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), tmp );
+	
+	/* initialise this level's streams */
+	StgFEM_Debug = Journal_Register( DebugStream_Type, (Name)"StgFEM"  );
+	StgFEM_Discretisation_Debug = Stream_RegisterChild( StgFEM_Debug, "Discretisation" );
+	StgFEM_Warning = Journal_Register( ErrorStream_Type, (Name)"StgFEM" );
+
+	elementType_Register = ElementType_Register_New( "elementType_Register"  );
+	ElementType_Register_Add( elementType_Register, (ElementType*)ConstantElementType_New( "constantElementType" ) );
+	ElementType_Register_Add( elementType_Register, (ElementType*)BilinearElementType_New( "bilinearElementType" ) );
+	ElementType_Register_Add( elementType_Register, (ElementType*)TrilinearElementType_New( "trilinearElementType" ) );
+	ElementType_Register_Add( elementType_Register, (ElementType*)LinearTriangleElementType_New( "linearElementType" ) );
+	ElementType_Register_Add( elementType_Register, (ElementType*)Biquadratic_New( "biquadraticElementType" ) );
+	ElementType_Register_Add( elementType_Register, (ElementType*)Triquadratic_New( "triquadraticElementType" ) );
+	
+	Stg_ComponentRegister_Add( componentRegister, FeVariable_Type, (Name)"0", _FeVariable_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, LinkedDofInfo_Type, (Name)"0", _LinkedDofInfo_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, OperatorFeVariable_Type, (Name)"0", _OperatorFeVariable_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, ShapeFeVariable_Type, (Name)"0", ShapeFeVariable_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, FeSwarmVariable_Type, (Name)"0", _FeSwarmVariable_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, FeMesh_Type, (Name)"0",
+                                   (Stg_Component_DefaultConstructorFunction*)_FeMesh_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, C0Generator_Type, (Name)"0",
+                                   (Stg_Component_DefaultConstructorFunction*)C0Generator_New  );
+	Stg_ComponentRegister_Add( componentRegister, C2Generator_Type, (Name)"0",
+                                   (Stg_Component_DefaultConstructorFunction*)C2Generator_New  );
+/*
+	Stg_ComponentRegister_Add( componentRegister, P1Generator_Type, (Name)"0", P1Generator_New  );
+*/
+	Stg_ComponentRegister_Add( componentRegister, Inner2DGenerator_Type, (Name)"0", (Stg_Component_DefaultConstructorFunction*)Inner2DGenerator_New  );
+	Stg_ComponentRegister_Add( componentRegister, FieldTest_Type, (Name)"0", _FieldTest_DefaultNew  );
+	
+	/** Register Parents for type checking */
+	RegisterParent( FeMesh_Algorithms_Type, Mesh_Algorithms_Type );
+	RegisterParent( FeMesh_ElementType_Type, Mesh_HexType_Type );
+	RegisterParent( ElementType_Type, Stg_Component_Type );
+	RegisterParent( BilinearElementType_Type, ElementType_Type );
+	RegisterParent( TrilinearElementType_Type, ElementType_Type );
+	RegisterParent( Biquadratic_Type, ElementType_Type );
+	RegisterParent( Triquadratic_Type, ElementType_Type );
+	RegisterParent( P1_Type, ElementType_Type );
+	RegisterParent( RegularTrilinear_Type, TrilinearElementType_Type );
+	RegisterParent( ConstantElementType_Type, ElementType_Type );
+	RegisterParent( LinearTriangleElementType_Type, ElementType_Type );
+	RegisterParent( ElementType_Register_Type, Stg_Component_Type );
+
+	RegisterParent( FeEquationNumber_Type, Stg_Component_Type );
+	RegisterParent( LinkedDofInfo_Type, Stg_Component_Type );
+	RegisterParent( FeMesh_Type, Mesh_Type );
+	RegisterParent( C0Generator_Type, MeshGenerator_Type );
+	RegisterParent( C2Generator_Type, CartesianGenerator_Type );
+/*
+	RegisterParent( P1Generator_Type, MeshGenerator_Type );
+*/
+	RegisterParent( Inner2DGenerator_Type, MeshGenerator_Type );
+	
+	RegisterParent( FeVariable_Type, FieldVariable_Type );
+	RegisterParent( OperatorFeVariable_Type, FeVariable_Type );
+	RegisterParent( ShapeFeVariable_Type, FeVariable_Type );
+	RegisterParent( FeSwarmVariable_Type, SwarmVariable_Type );
+
+	RegisterParent( FieldTest_Type, Stg_Component_Type );
+
+	{
+		PetscErrorCode	ec;
+		ec = PetscInitialize( argc, argv, (char*)0, NULL );
+		CheckPETScError( ec );
+	}
+
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Inner2DGenerator.c
--- a/Discretisation/src/Inner2DGenerator.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,392 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Inner2DGenerator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type Inner2DGenerator_Type = "Inner2DGenerator";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-Inner2DGenerator* Inner2DGenerator_New( Name name, AbstractContext* context ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(Inner2DGenerator);
-	Type                                                      type = Inner2DGenerator_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Inner2DGenerator_Delete;
-	Stg_Class_PrintFunction*                                _print = _Inner2DGenerator_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (void* (*)(Name))_Inner2DGenerator_New;
-	Stg_Component_ConstructFunction*                    _construct = _Inner2DGenerator_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Inner2DGenerator_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Inner2DGenerator_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _Inner2DGenerator_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = NULL;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-	MeshGenerator_SetDimSizeFunc*                   setDimSizeFunc = _MeshGenerator_SetDimSize;
-	MeshGenerator_GenerateFunc*                       generateFunc = (MeshGenerator_GenerateFunc*)Inner2DGenerator_Generate;
-
-	Inner2DGenerator* self = _Inner2DGenerator_New(  INNER2DGENERATOR_PASSARGS  );
-
-   _MeshGenerator_Init( (MeshGenerator*)self, context );
-   _Inner2DGenerator_Init( self );
-
-   return self;
-}
-
-Inner2DGenerator* _Inner2DGenerator_New(  INNER2DGENERATOR_DEFARGS  ) {
-	Inner2DGenerator*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Inner2DGenerator) );
-	self = (Inner2DGenerator*)_MeshGenerator_New(  MESHGENERATOR_PASSARGS  );
-
-	return self;
-}
-
-void _Inner2DGenerator_Init( Inner2DGenerator* self ) {
-	assert( self && Stg_CheckType( self, Inner2DGenerator ) );
-
-	self->elMesh = NULL;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _Inner2DGenerator_Delete( void* generator ) {
-	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
-
-	/* Delete the parent. */
-	_MeshGenerator_Delete( self );
-}
-
-void _Inner2DGenerator_Print( void* generator, Stream* stream ) {
-	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
-	
-	/* Set the Journal for printing informations */
-	Stream* generatorStream;
-	generatorStream = Journal_Register( InfoStream_Type, (Name)"Inner2DGeneratorStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "Inner2DGenerator (ptr): (%p)\n", self );
-	_MeshGenerator_Print( self, stream );
-}
-
-void _Inner2DGenerator_AssignFromXML( void* generator, Stg_ComponentFactory* cf, void* data ) {
-	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
-	Mesh*		elMesh;
-
-	assert( self );
-	assert( cf );
-
-	_MeshGenerator_AssignFromXML( self, cf, data );
-
-	elMesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"elementMesh", Mesh, True, data  );
-	Inner2DGenerator_SetElementMesh( self, elMesh );
-}
-
-void _Inner2DGenerator_Build( void* generator, void* data ) {
-	_MeshGenerator_Build( generator, data );
-}
-
-void _Inner2DGenerator_Initialise( void* generator, void* data ) {
-	_MeshGenerator_Initialise( generator, data );
-}
-
-void _Inner2DGenerator_Execute( void* generator, void* data ) {
-}
-
-void _Inner2DGenerator_Destroy( void* generator, void* data ) {
-	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
-
-   Stg_Component_Destroy( self->elMesh, data, False );
-   _MeshGenerator_Destroy( self, data );
-}
-
-void Inner2DGenerator_Generate( void* generator, void* _mesh ) {
-	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
-	FeMesh*		mesh = (FeMesh*)_mesh;
-	Grid**		grid;
-	Grid*		elGrid;
-
-	assert( self && Stg_CheckType( self, Inner2DGenerator ) );
-	assert( mesh && Stg_CheckType( mesh, FeMesh ) );
-
-	Inner2DGenerator_BuildTopology( self, mesh );
-	Inner2DGenerator_BuildGeometry( self, mesh );
-	Inner2DGenerator_BuildElementTypes( self, mesh );
-
-	elGrid = *(Grid**)ExtensionManager_Get( self->elMesh->info, self->elMesh, 
-					       ExtensionManager_GetHandle( self->elMesh->info, (Name)"elementGrid" )  );
-	ExtensionManager_Add( mesh->info, (Name)"elementGrid", sizeof(Grid*) );
-	grid = (Grid** )ExtensionManager_Get( mesh->info, mesh, 
-					     ExtensionManager_GetHandle( mesh->info, (Name)"elementGrid" ) );
-	*grid = Grid_New( );
-	Grid_SetNumDims( *grid, elGrid->nDims );
-	Grid_SetSizes( *grid, elGrid->sizes );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void Inner2DGenerator_SetElementMesh( void* generator, void* mesh ) {
-	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
-
-	assert( self && Stg_CheckType( self, Inner2DGenerator ) );
-
-	self->elMesh = (Mesh*)mesh;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-void Inner2DGenerator_BuildTopology( Inner2DGenerator* self, FeMesh* mesh ) {
-	Mesh*		elMesh;
-	MeshTopology	*topo, *elTopo;
-	unsigned	nDims;
-	unsigned	nIncEls, *incEls;
-	unsigned	nDomainEls;
-	Decomp		*elDecomp, *nodeDecomp;
-	Sync		*elSync, *nodeSync;
-	int		nLocals, *locals;
-	int		nRemotes, *remotes;
-	unsigned	global;
-	unsigned	e_i, l_i, r_i;
-
-	assert( self );
-	assert( mesh );
-
-	elMesh = self->elMesh;
-	nDims = Mesh_GetDimSize( elMesh );
-	elTopo = Mesh_GetTopology( elMesh );
-	elSync = Mesh_GetSync( elMesh, (MeshTopology_Dim)nDims );
-
-	topo = Mesh_GetTopology( mesh );
-	MeshTopology_SetComm( topo, MeshTopology_GetComm( elTopo ) );
-	MeshTopology_SetNumDims( topo, nDims );
-	IGraph_SetDomain( topo, nDims, elSync );
-
-	/* Need to redefine the nodes, nDims + 1 per parent element. */
-	elDecomp = (Decomp*)Sync_GetDecomp( elSync );
-	nodeDecomp = Decomp_New();
-
-	if( nDims == 2 ) {
-		nLocals = Decomp_GetNumLocals( elDecomp ) * 3;
-		locals = MemArray( int, nLocals, Inner2DGenerator_Type );
-		for( l_i = 0; l_i < Decomp_GetNumLocals( elDecomp ); l_i++ ) {
-			global = Decomp_LocalToGlobal( elDecomp, l_i );
-			locals[l_i * 3 + 0] = global * 3;
-			locals[l_i * 3 + 1] = global * 3 + 1;
-			locals[l_i * 3 + 2] = global * 3 + 2;
-		}
-	}
-	else if( nDims == 3 ) {
-		nLocals = Decomp_GetNumLocals( elDecomp ) * 4;
-		locals = MemArray( int, nLocals, Inner2DGenerator_Type );
-		for( l_i = 0; l_i < Decomp_GetNumLocals( elDecomp ); l_i++ ) {
-			global = Decomp_LocalToGlobal( elDecomp, l_i );
-			locals[l_i * 4 + 0] = global * 4;
-			locals[l_i * 4 + 1] = global * 4 + 1;
-			locals[l_i * 4 + 2] = global * 4 + 2;
-			locals[l_i * 4 + 3] = global * 4 + 3;
-		}
-	}
-	Decomp_SetLocals( nodeDecomp, nLocals, locals );
-	MemFree( locals );
-
-	nodeSync = Sync_New();
-	Sync_SetComm( nodeSync, Sync_GetComm( elSync ) );
-	Sync_SetDecomp( nodeSync, nodeDecomp );
-
-	if( nDims == 2 ) {
-		nRemotes = Sync_GetNumRemotes( elSync ) * 3;
-		remotes = MemArray( int, nRemotes, Inner2DGenerator_Type );
-		for( r_i = 0; r_i < Sync_GetNumRemotes( elSync ); r_i++ ) {
-			global = Sync_RemoteToGlobal( elSync, r_i );
-			remotes[r_i * 3 + 0] = global * 3;
-			remotes[r_i * 3 + 1] = global * 3 + 1;
-			remotes[r_i * 3 + 2] = global * 3 + 2;
-		}
-	}
-	else if( nDims == 3 ) {
-		nRemotes = Sync_GetNumRemotes( elSync ) * 4;
-		remotes = MemArray( int, nRemotes, Inner2DGenerator_Type );
-		for( r_i = 0; r_i < Sync_GetNumRemotes( elSync ); r_i++ ) {
-			global = Sync_RemoteToGlobal( elSync, r_i );
-			remotes[r_i * 4 + 0] = global * 4;
-			remotes[r_i * 4 + 1] = global * 4 + 1;
-			remotes[r_i * 4 + 2] = global * 4 + 2;
-			remotes[r_i * 4 + 3] = global * 4 + 3;
-		}
-	}
-	Sync_SetRemotes( nodeSync, nRemotes, remotes );
-	MemFree( remotes );
-
-	IGraph_SetDomain( topo, 0, nodeSync );
-
-	/* Same shadow depth. */
-	topo->shadDepth = elTopo->shadDepth;
-
-	/* Build the incidence. */
-	nDomainEls = Mesh_GetDomainSize( elMesh, (MeshTopology_Dim)nDims );
-	if( nDims == 2 ) {
-		nIncEls = 3;
-		incEls = MemArray( unsigned, 3, Inner2DGenerator_Type );
-		for( e_i = 0; e_i < nDomainEls; e_i++ ) {
-			incEls[0] = e_i * 3;
-			incEls[1] = e_i * 3 + 1;
-			incEls[2] = e_i * 3 + 2;
-			IGraph_SetIncidence( topo, nDims, e_i, 0, nIncEls, (int*)incEls );
-		}
-	}
-	else if( nDims == 3 ) {
-		nIncEls = 4;
-		incEls = MemArray( unsigned, 4, Inner2DGenerator_Type );
-		for( e_i = 0; e_i < nDomainEls; e_i++ ) {
-			incEls[0] = e_i * 4;
-			incEls[1] = e_i * 4 + 1;
-			incEls[2] = e_i * 4 + 2;
-			incEls[3] = e_i * 4 + 3;
-			IGraph_SetIncidence( topo, nDims, e_i, 0, nIncEls, (int*)incEls );
-		}
-	}
-	FreeArray( incEls );
-
-	IGraph_InvertIncidence( topo, MT_VERTEX, nDims );
-}
-
-void Inner2DGenerator_BuildGeometry( Inner2DGenerator* self, FeMesh* mesh ) {
-	Mesh*		elMesh;
-	double		localCrds[3][2] = {{-0.5, -0.5}, 
-					   {0.5, -0.5}, 
-					   {0, 0.5}};
-	double		globalCrd[2];
-	double		*vert;
-	unsigned	nDims;
-	unsigned	nDomainEls;
-	unsigned	e_i;
-
-	assert( self );
-	assert( mesh );
-
-	elMesh = self->elMesh;
-	nDims = Mesh_GetDimSize( elMesh );
-	nDomainEls = Mesh_GetDomainSize( elMesh, (MeshTopology_Dim)nDims );
-
-	if( nDims == 2 ) {
-		mesh->verts = AllocArray2D( double, nDomainEls * 3, nDims );
-		for( e_i = 0; e_i < nDomainEls; e_i++ ) {
-			unsigned elInd = e_i * 3;
-
-			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds[0], globalCrd );
-			vert = Mesh_GetVertex( mesh, elInd );
-			memcpy( vert, globalCrd, nDims * sizeof(double) );
-
-			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds[1], globalCrd );
-			vert = Mesh_GetVertex( mesh, elInd + 1 );
-			memcpy( vert, globalCrd, nDims * sizeof(double) );
-
-			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds[2], globalCrd );
-			vert = Mesh_GetVertex( mesh, elInd + 2 );
-			memcpy( vert, globalCrd, nDims * sizeof(double) );
-		}
-	}
-
-	else if( nDims == 3 ) {
-		double localCrds3D[4][3] = { {-0.5, -0.5, -0.5},
-		                             {0.25, 0.25, 0.25},
-		                             {0.5, -0.25, -0.5},
-		                             {-0.25, 0.5, 0.5} };
-		double globalCrd3D[3];
-
-		mesh->verts = AllocArray2D( double, nDomainEls * 4, nDims );
-		for( e_i = 0; e_i < nDomainEls; e_i++ ) {
-			unsigned elInd = e_i * 4;
-
-			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds3D[0], globalCrd3D );
-			vert = Mesh_GetVertex( mesh, elInd );
-			memcpy( vert, globalCrd3D, nDims * sizeof(double) );
-
-			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds3D[1], globalCrd3D );
-			vert = Mesh_GetVertex( mesh, elInd + 1 );
-			memcpy( vert, globalCrd3D, nDims * sizeof(double) );
-
-			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds3D[2], globalCrd3D );
-			vert = Mesh_GetVertex( mesh, elInd + 2 );
-			memcpy( vert, globalCrd3D, nDims * sizeof(double) );
-
-			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds3D[3], globalCrd3D );
-			vert = Mesh_GetVertex( mesh, elInd + 3 );
-			memcpy( vert, globalCrd3D, nDims * sizeof(double) );
-		}
-	}
-}
-
-void Inner2DGenerator_BuildElementTypes( Inner2DGenerator* self, FeMesh* mesh ) {
-	unsigned		nDomainEls;
-	Mesh_Algorithms*	algs;
-	unsigned		e_i;
-
-	assert( self );
-	assert( mesh );
-
-	mesh->nElTypes = 1;
-	mesh->elTypes = AllocNamedArray( Mesh_ElementType*, mesh->nElTypes, "Mesh::elTypes" );
-	mesh->elTypes[0] = (Mesh_ElementType*)Mesh_CentroidType_New();
-	Mesh_ElementType_SetMesh( mesh->elTypes[0], mesh );
-	Mesh_CentroidType_SetElementMesh( mesh->elTypes[0], self->elMesh );
-	nDomainEls = Mesh_GetDomainSize( mesh, Mesh_GetDimSize( mesh ) );
-	mesh->elTypeMap = AllocNamedArray( unsigned, nDomainEls, "Mesh::elTypeMap" );
-	for( e_i = 0; e_i < nDomainEls; e_i++ )
-		mesh->elTypeMap[e_i] = 0;
-
-	algs = (Mesh_Algorithms*)Mesh_CentroidAlgorithms_New( "", NULL );
-	Mesh_CentroidAlgorithms_SetElementMesh( algs, self->elMesh );
-	Mesh_SetAlgorithms( mesh, algs );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Inner2DGenerator.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/Inner2DGenerator.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,392 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Inner2DGenerator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type Inner2DGenerator_Type = "Inner2DGenerator";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+Inner2DGenerator* Inner2DGenerator_New( Name name, AbstractContext* context ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(Inner2DGenerator);
+	Type                                                      type = Inner2DGenerator_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Inner2DGenerator_Delete;
+	Stg_Class_PrintFunction*                                _print = _Inner2DGenerator_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (void* (*)(Name))_Inner2DGenerator_New;
+	Stg_Component_ConstructFunction*                    _construct = _Inner2DGenerator_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Inner2DGenerator_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Inner2DGenerator_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _Inner2DGenerator_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = NULL;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+	MeshGenerator_SetDimSizeFunc*                   setDimSizeFunc = _MeshGenerator_SetDimSize;
+	MeshGenerator_GenerateFunc*                       generateFunc = (MeshGenerator_GenerateFunc*)Inner2DGenerator_Generate;
+
+	Inner2DGenerator* self = _Inner2DGenerator_New(  INNER2DGENERATOR_PASSARGS  );
+
+   _MeshGenerator_Init( (MeshGenerator*)self, context );
+   _Inner2DGenerator_Init( self );
+
+   return self;
+}
+
+Inner2DGenerator* _Inner2DGenerator_New(  INNER2DGENERATOR_DEFARGS  ) {
+	Inner2DGenerator*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Inner2DGenerator) );
+	self = (Inner2DGenerator*)_MeshGenerator_New(  MESHGENERATOR_PASSARGS  );
+
+	return self;
+}
+
+void _Inner2DGenerator_Init( Inner2DGenerator* self ) {
+	assert( self && Stg_CheckType( self, Inner2DGenerator ) );
+
+	self->elMesh = NULL;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _Inner2DGenerator_Delete( void* generator ) {
+	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
+
+	/* Delete the parent. */
+	_MeshGenerator_Delete( self );
+}
+
+void _Inner2DGenerator_Print( void* generator, Stream* stream ) {
+	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
+	
+	/* Set the Journal for printing informations */
+	Stream* generatorStream;
+	generatorStream = Journal_Register( InfoStream_Type, (Name)"Inner2DGeneratorStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "Inner2DGenerator (ptr): (%p)\n", self );
+	_MeshGenerator_Print( self, stream );
+}
+
+void _Inner2DGenerator_AssignFromXML( void* generator, Stg_ComponentFactory* cf, void* data ) {
+	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
+	Mesh*		elMesh;
+
+	assert( self );
+	assert( cf );
+
+	_MeshGenerator_AssignFromXML( self, cf, data );
+
+	elMesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"elementMesh", Mesh, True, data  );
+	Inner2DGenerator_SetElementMesh( self, elMesh );
+}
+
+void _Inner2DGenerator_Build( void* generator, void* data ) {
+	_MeshGenerator_Build( generator, data );
+}
+
+void _Inner2DGenerator_Initialise( void* generator, void* data ) {
+	_MeshGenerator_Initialise( generator, data );
+}
+
+void _Inner2DGenerator_Execute( void* generator, void* data ) {
+}
+
+void _Inner2DGenerator_Destroy( void* generator, void* data ) {
+	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
+
+   Stg_Component_Destroy( self->elMesh, data, False );
+   _MeshGenerator_Destroy( self, data );
+}
+
+void Inner2DGenerator_Generate( void* generator, void* _mesh ) {
+	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
+	FeMesh*		mesh = (FeMesh*)_mesh;
+	Grid**		grid;
+	Grid*		elGrid;
+
+	assert( self && Stg_CheckType( self, Inner2DGenerator ) );
+	assert( mesh && Stg_CheckType( mesh, FeMesh ) );
+
+	Inner2DGenerator_BuildTopology( self, mesh );
+	Inner2DGenerator_BuildGeometry( self, mesh );
+	Inner2DGenerator_BuildElementTypes( self, mesh );
+
+	elGrid = *(Grid**)ExtensionManager_Get( self->elMesh->info, self->elMesh, 
+					       ExtensionManager_GetHandle( self->elMesh->info, (Name)"elementGrid" )  );
+	ExtensionManager_Add( mesh->info, (Name)"elementGrid", sizeof(Grid*) );
+	grid = (Grid** )ExtensionManager_Get( mesh->info, mesh, 
+					     ExtensionManager_GetHandle( mesh->info, (Name)"elementGrid" ) );
+	*grid = Grid_New( );
+	Grid_SetNumDims( *grid, elGrid->nDims );
+	Grid_SetSizes( *grid, elGrid->sizes );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void Inner2DGenerator_SetElementMesh( void* generator, void* mesh ) {
+	Inner2DGenerator*	self = (Inner2DGenerator*)generator;
+
+	assert( self && Stg_CheckType( self, Inner2DGenerator ) );
+
+	self->elMesh = (Mesh*)mesh;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+void Inner2DGenerator_BuildTopology( Inner2DGenerator* self, FeMesh* mesh ) {
+	Mesh*		elMesh;
+	MeshTopology	*topo, *elTopo;
+	unsigned	nDims;
+	unsigned	nIncEls, *incEls;
+	unsigned	nDomainEls;
+	Decomp		*elDecomp, *nodeDecomp;
+	Sync		*elSync, *nodeSync;
+	int		nLocals, *locals;
+	int		nRemotes, *remotes;
+	unsigned	global;
+	unsigned	e_i, l_i, r_i;
+
+	assert( self );
+	assert( mesh );
+
+	elMesh = self->elMesh;
+	nDims = Mesh_GetDimSize( elMesh );
+	elTopo = Mesh_GetTopology( elMesh );
+	elSync = Mesh_GetSync( elMesh, (MeshTopology_Dim)nDims );
+
+	topo = Mesh_GetTopology( mesh );
+	MeshTopology_SetComm( topo, MeshTopology_GetComm( elTopo ) );
+	MeshTopology_SetNumDims( topo, nDims );
+	IGraph_SetDomain( topo, nDims, elSync );
+
+	/* Need to redefine the nodes, nDims + 1 per parent element. */
+	elDecomp = (Decomp*)Sync_GetDecomp( elSync );
+	nodeDecomp = Decomp_New();
+
+	if( nDims == 2 ) {
+		nLocals = Decomp_GetNumLocals( elDecomp ) * 3;
+		locals = MemArray( int, nLocals, Inner2DGenerator_Type );
+		for( l_i = 0; l_i < Decomp_GetNumLocals( elDecomp ); l_i++ ) {
+			global = Decomp_LocalToGlobal( elDecomp, l_i );
+			locals[l_i * 3 + 0] = global * 3;
+			locals[l_i * 3 + 1] = global * 3 + 1;
+			locals[l_i * 3 + 2] = global * 3 + 2;
+		}
+	}
+	else if( nDims == 3 ) {
+		nLocals = Decomp_GetNumLocals( elDecomp ) * 4;
+		locals = MemArray( int, nLocals, Inner2DGenerator_Type );
+		for( l_i = 0; l_i < Decomp_GetNumLocals( elDecomp ); l_i++ ) {
+			global = Decomp_LocalToGlobal( elDecomp, l_i );
+			locals[l_i * 4 + 0] = global * 4;
+			locals[l_i * 4 + 1] = global * 4 + 1;
+			locals[l_i * 4 + 2] = global * 4 + 2;
+			locals[l_i * 4 + 3] = global * 4 + 3;
+		}
+	}
+	Decomp_SetLocals( nodeDecomp, nLocals, locals );
+	MemFree( locals );
+
+	nodeSync = Sync_New();
+	Sync_SetComm( nodeSync, Sync_GetComm( elSync ) );
+	Sync_SetDecomp( nodeSync, nodeDecomp );
+
+	if( nDims == 2 ) {
+		nRemotes = Sync_GetNumRemotes( elSync ) * 3;
+		remotes = MemArray( int, nRemotes, Inner2DGenerator_Type );
+		for( r_i = 0; r_i < Sync_GetNumRemotes( elSync ); r_i++ ) {
+			global = Sync_RemoteToGlobal( elSync, r_i );
+			remotes[r_i * 3 + 0] = global * 3;
+			remotes[r_i * 3 + 1] = global * 3 + 1;
+			remotes[r_i * 3 + 2] = global * 3 + 2;
+		}
+	}
+	else if( nDims == 3 ) {
+		nRemotes = Sync_GetNumRemotes( elSync ) * 4;
+		remotes = MemArray( int, nRemotes, Inner2DGenerator_Type );
+		for( r_i = 0; r_i < Sync_GetNumRemotes( elSync ); r_i++ ) {
+			global = Sync_RemoteToGlobal( elSync, r_i );
+			remotes[r_i * 4 + 0] = global * 4;
+			remotes[r_i * 4 + 1] = global * 4 + 1;
+			remotes[r_i * 4 + 2] = global * 4 + 2;
+			remotes[r_i * 4 + 3] = global * 4 + 3;
+		}
+	}
+	Sync_SetRemotes( nodeSync, nRemotes, remotes );
+	MemFree( remotes );
+
+	IGraph_SetDomain( topo, 0, nodeSync );
+
+	/* Same shadow depth. */
+	topo->shadDepth = elTopo->shadDepth;
+
+	/* Build the incidence. */
+	nDomainEls = Mesh_GetDomainSize( elMesh, (MeshTopology_Dim)nDims );
+	if( nDims == 2 ) {
+		nIncEls = 3;
+		incEls = MemArray( unsigned, 3, Inner2DGenerator_Type );
+		for( e_i = 0; e_i < nDomainEls; e_i++ ) {
+			incEls[0] = e_i * 3;
+			incEls[1] = e_i * 3 + 1;
+			incEls[2] = e_i * 3 + 2;
+			IGraph_SetIncidence( topo, nDims, e_i, 0, nIncEls, (int*)incEls );
+		}
+	}
+	else if( nDims == 3 ) {
+		nIncEls = 4;
+		incEls = MemArray( unsigned, 4, Inner2DGenerator_Type );
+		for( e_i = 0; e_i < nDomainEls; e_i++ ) {
+			incEls[0] = e_i * 4;
+			incEls[1] = e_i * 4 + 1;
+			incEls[2] = e_i * 4 + 2;
+			incEls[3] = e_i * 4 + 3;
+			IGraph_SetIncidence( topo, nDims, e_i, 0, nIncEls, (int*)incEls );
+		}
+	}
+	FreeArray( incEls );
+
+	IGraph_InvertIncidence( topo, MT_VERTEX, nDims );
+}
+
+void Inner2DGenerator_BuildGeometry( Inner2DGenerator* self, FeMesh* mesh ) {
+	Mesh*		elMesh;
+	double		localCrds[3][2] = {{-0.5, -0.5}, 
+					   {0.5, -0.5}, 
+					   {0, 0.5}};
+	double		globalCrd[2];
+	double		*vert;
+	unsigned	nDims;
+	unsigned	nDomainEls;
+	unsigned	e_i;
+
+	assert( self );
+	assert( mesh );
+
+	elMesh = self->elMesh;
+	nDims = Mesh_GetDimSize( elMesh );
+	nDomainEls = Mesh_GetDomainSize( elMesh, (MeshTopology_Dim)nDims );
+
+	if( nDims == 2 ) {
+		mesh->verts = AllocArray2D( double, nDomainEls * 3, nDims );
+		for( e_i = 0; e_i < nDomainEls; e_i++ ) {
+			unsigned elInd = e_i * 3;
+
+			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds[0], globalCrd );
+			vert = Mesh_GetVertex( mesh, elInd );
+			memcpy( vert, globalCrd, nDims * sizeof(double) );
+
+			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds[1], globalCrd );
+			vert = Mesh_GetVertex( mesh, elInd + 1 );
+			memcpy( vert, globalCrd, nDims * sizeof(double) );
+
+			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds[2], globalCrd );
+			vert = Mesh_GetVertex( mesh, elInd + 2 );
+			memcpy( vert, globalCrd, nDims * sizeof(double) );
+		}
+	}
+
+	else if( nDims == 3 ) {
+		double localCrds3D[4][3] = { {-0.5, -0.5, -0.5},
+		                             {0.25, 0.25, 0.25},
+		                             {0.5, -0.25, -0.5},
+		                             {-0.25, 0.5, 0.5} };
+		double globalCrd3D[3];
+
+		mesh->verts = AllocArray2D( double, nDomainEls * 4, nDims );
+		for( e_i = 0; e_i < nDomainEls; e_i++ ) {
+			unsigned elInd = e_i * 4;
+
+			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds3D[0], globalCrd3D );
+			vert = Mesh_GetVertex( mesh, elInd );
+			memcpy( vert, globalCrd3D, nDims * sizeof(double) );
+
+			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds3D[1], globalCrd3D );
+			vert = Mesh_GetVertex( mesh, elInd + 1 );
+			memcpy( vert, globalCrd3D, nDims * sizeof(double) );
+
+			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds3D[2], globalCrd3D );
+			vert = Mesh_GetVertex( mesh, elInd + 2 );
+			memcpy( vert, globalCrd3D, nDims * sizeof(double) );
+
+			FeMesh_CoordLocalToGlobal( elMesh, e_i, localCrds3D[3], globalCrd3D );
+			vert = Mesh_GetVertex( mesh, elInd + 3 );
+			memcpy( vert, globalCrd3D, nDims * sizeof(double) );
+		}
+	}
+}
+
+void Inner2DGenerator_BuildElementTypes( Inner2DGenerator* self, FeMesh* mesh ) {
+	unsigned		nDomainEls;
+	Mesh_Algorithms*	algs;
+	unsigned		e_i;
+
+	assert( self );
+	assert( mesh );
+
+	mesh->nElTypes = 1;
+	mesh->elTypes = AllocNamedArray( Mesh_ElementType*, mesh->nElTypes, "Mesh::elTypes" );
+	mesh->elTypes[0] = (Mesh_ElementType*)Mesh_CentroidType_New();
+	Mesh_ElementType_SetMesh( mesh->elTypes[0], mesh );
+	Mesh_CentroidType_SetElementMesh( mesh->elTypes[0], self->elMesh );
+	nDomainEls = Mesh_GetDomainSize( mesh, Mesh_GetDimSize( mesh ) );
+	mesh->elTypeMap = AllocNamedArray( unsigned, nDomainEls, "Mesh::elTypeMap" );
+	for( e_i = 0; e_i < nDomainEls; e_i++ )
+		mesh->elTypeMap[e_i] = 0;
+
+	algs = (Mesh_Algorithms*)Mesh_CentroidAlgorithms_New( "", NULL );
+	Mesh_CentroidAlgorithms_SetElementMesh( algs, self->elMesh );
+	Mesh_SetAlgorithms( mesh, algs );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/LinearTriangleElementType.c
--- a/Discretisation/src/LinearTriangleElementType.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LinearTriangleElementType.c 1177 2008-07-15 01:29:58Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType.h"
-#include "LinearTriangleElementType.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-const Type LinearTriangleElementType_Type = "LinearTriangleElementType";
-
-#define _LinearTriangleElementType_NodeCount 3
-
-LinearTriangleElementType* LinearTriangleElementType_New( Name name ) {
-  LinearTriangleElementType* self = (LinearTriangleElementType*)_LinearTriangleElementType_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, _LinearTriangleElementType_NodeCount );
-	_LinearTriangleElementType_Init( self );
-
-	return self;
-}
-
-void* _LinearTriangleElementType_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(LinearTriangleElementType);
-	Type                                                                                    type = LinearTriangleElementType_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _LinearTriangleElementType_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _LinearTriangleElementType_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = _LinearTriangleElementType_DefaultNew;
-	Stg_Component_ConstructFunction*                                                  _construct = _LinearTriangleElementType_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _LinearTriangleElementType_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _LinearTriangleElementType_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _LinearTriangleElementType_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _LinearTriangleElementType_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _LinearTriangleElementType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _LinearTriangleElementType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _LinearTriangularElementType_SurfaceNormal;
-
-	return _LinearTriangleElementType_New(  LINEARTRIANGLEELEMENTTYPE_PASSARGS  );
-}
-
-LinearTriangleElementType* _LinearTriangleElementType_New(  LINEARTRIANGLEELEMENTTYPE_DEFARGS  ) {
-	LinearTriangleElementType* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(LinearTriangleElementType) );
-	self = (LinearTriangleElementType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual functions */
-	
-	/* LinearTriangleElementType info */
-	
-	return self;
-}
-
-void _LinearTriangleElementType_Init( LinearTriangleElementType* self ) {
-	self->dim = 1;
-}
-
-void _LinearTriangleElementType_Delete( void* elementType ) {
-	LinearTriangleElementType* self = (LinearTriangleElementType*)elementType;
-
-	/* Stg_Class_Delete parent*/
-	_ElementType_Delete( self );
-}
-
-void _LinearTriangleElementType_Print( void* elementType, Stream* stream ) {
-	LinearTriangleElementType* self = (LinearTriangleElementType*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* linearTriangleElementTypeStream = stream;
-	
-	/* General info */
-	Journal_Printf( linearTriangleElementTypeStream, "LinearTriangleElementType (ptr): %p\n", self );
-	
-	/* Print parent */
-	_ElementType_Print( self, linearTriangleElementTypeStream );
-	
-	/* Virtual info */
-	
-	/* LinearTriangleElementType info */
-}
-
-void _LinearTriangleElementType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
-	LinearTriangleElementType* self = (LinearTriangleElementType*)elementType;
-
-	_LinearTriangleElementType_Init( self );
-}
-	
-void _LinearTriangleElementType_Build( void* elementType, void *data ){
-}
-	
-void _LinearTriangleElementType_Initialise( void* elementType, void *data ){
-}
-	
-void _LinearTriangleElementType_Execute( void* elementType, void *data ){
-}
-	
-void _LinearTriangleElementType_Destroy( void* elementType, void *data ){
-	LinearTriangleElementType* self = (LinearTriangleElementType*)elementType;
-
-	_ElementType_Destroy( self, data );
-}
-	
-/*
-
- - Shape function definitions
- - Local node numbering convention for linearTriangle element (xi, eta)
- - Local coordinate domain spans  0 <= xi,eta <= 1
-
-    eta
-     |
-     |____ xi
- 
-  eta
-   |
-   |
-2 \ 
-|  \
-|   \_____xi
-|    \ 
-0-----\1
-
-
-*/
-void _LinearTriangleElementType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues) {
-	double xi, eta, zeta;
-	
-	xi   = localCoord[0];
-	eta  = localCoord[1];
-	zeta = localCoord[2];	
-	
-	evaluatedValues[0] = 1.0 - xi - eta;
-	evaluatedValues[1] = xi;
-	evaluatedValues[2] = eta;	
-}
-
-
-void _LinearTriangleElementType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
-		double** const evaluatedDerivatives )
-{		
-	double xi, eta, zeta;
-	
-	xi   = localCoord[0];
-	eta  = localCoord[1];
-	zeta = localCoord[2];	
-		
-	/* derivatives wrt xi */
-	evaluatedDerivatives[0][0] = -1.0;
-	evaluatedDerivatives[0][1] =  1.0;
-	evaluatedDerivatives[0][2] =  0.0;
-	
-	/* derivatives wrt eta */	
-	evaluatedDerivatives[1][0] = - 1.0;
-	evaluatedDerivatives[1][1] =   0.0;
-	evaluatedDerivatives[1][2] =   1.0;
-}
-
-int _LinearTriangularElementType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* norm ) {
-	Stream* errStream = Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
-
-	Journal_Printf( errStream, "surface normal function not yet implemented for this element type.\n" );
-	assert( 0 );
-
-	norm = NULL;
-
-	return -1;
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/LinearTriangleElementType.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/LinearTriangleElementType.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,222 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LinearTriangleElementType.c 1177 2008-07-15 01:29:58Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType.h"
+#include "LinearTriangleElementType.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+const Type LinearTriangleElementType_Type = "LinearTriangleElementType";
+
+#define _LinearTriangleElementType_NodeCount 3
+
+LinearTriangleElementType* LinearTriangleElementType_New( Name name ) {
+  LinearTriangleElementType* self = (LinearTriangleElementType*)_LinearTriangleElementType_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, _LinearTriangleElementType_NodeCount );
+	_LinearTriangleElementType_Init( self );
+
+	return self;
+}
+
+void* _LinearTriangleElementType_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(LinearTriangleElementType);
+	Type                                                                                    type = LinearTriangleElementType_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _LinearTriangleElementType_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _LinearTriangleElementType_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = _LinearTriangleElementType_DefaultNew;
+	Stg_Component_ConstructFunction*                                                  _construct = _LinearTriangleElementType_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _LinearTriangleElementType_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _LinearTriangleElementType_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _LinearTriangleElementType_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _LinearTriangleElementType_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _LinearTriangleElementType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _LinearTriangleElementType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _LinearTriangularElementType_SurfaceNormal;
+
+	return _LinearTriangleElementType_New(  LINEARTRIANGLEELEMENTTYPE_PASSARGS  );
+}
+
+LinearTriangleElementType* _LinearTriangleElementType_New(  LINEARTRIANGLEELEMENTTYPE_DEFARGS  ) {
+	LinearTriangleElementType* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(LinearTriangleElementType) );
+	self = (LinearTriangleElementType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual functions */
+	
+	/* LinearTriangleElementType info */
+	
+	return self;
+}
+
+void _LinearTriangleElementType_Init( LinearTriangleElementType* self ) {
+	self->dim = 1;
+}
+
+void _LinearTriangleElementType_Delete( void* elementType ) {
+	LinearTriangleElementType* self = (LinearTriangleElementType*)elementType;
+
+	/* Stg_Class_Delete parent*/
+	_ElementType_Delete( self );
+}
+
+void _LinearTriangleElementType_Print( void* elementType, Stream* stream ) {
+	LinearTriangleElementType* self = (LinearTriangleElementType*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* linearTriangleElementTypeStream = stream;
+	
+	/* General info */
+	Journal_Printf( linearTriangleElementTypeStream, "LinearTriangleElementType (ptr): %p\n", self );
+	
+	/* Print parent */
+	_ElementType_Print( self, linearTriangleElementTypeStream );
+	
+	/* Virtual info */
+	
+	/* LinearTriangleElementType info */
+}
+
+void _LinearTriangleElementType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
+	LinearTriangleElementType* self = (LinearTriangleElementType*)elementType;
+
+	_LinearTriangleElementType_Init( self );
+}
+	
+void _LinearTriangleElementType_Build( void* elementType, void *data ){
+}
+	
+void _LinearTriangleElementType_Initialise( void* elementType, void *data ){
+}
+	
+void _LinearTriangleElementType_Execute( void* elementType, void *data ){
+}
+	
+void _LinearTriangleElementType_Destroy( void* elementType, void *data ){
+	LinearTriangleElementType* self = (LinearTriangleElementType*)elementType;
+
+	_ElementType_Destroy( self, data );
+}
+	
+/*
+
+ - Shape function definitions
+ - Local node numbering convention for linearTriangle element (xi, eta)
+ - Local coordinate domain spans  0 <= xi,eta <= 1
+
+    eta
+     |
+     |____ xi
+ 
+  eta
+   |
+   |
+2 \ 
+|  \
+|   \_____xi
+|    \ 
+0-----\1
+
+
+*/
+void _LinearTriangleElementType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues) {
+	double xi, eta, zeta;
+	
+	xi   = localCoord[0];
+	eta  = localCoord[1];
+	zeta = localCoord[2];	
+	
+	evaluatedValues[0] = 1.0 - xi - eta;
+	evaluatedValues[1] = xi;
+	evaluatedValues[2] = eta;	
+}
+
+
+void _LinearTriangleElementType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
+		double** const evaluatedDerivatives )
+{		
+	double xi, eta, zeta;
+	
+	xi   = localCoord[0];
+	eta  = localCoord[1];
+	zeta = localCoord[2];	
+		
+	/* derivatives wrt xi */
+	evaluatedDerivatives[0][0] = -1.0;
+	evaluatedDerivatives[0][1] =  1.0;
+	evaluatedDerivatives[0][2] =  0.0;
+	
+	/* derivatives wrt eta */	
+	evaluatedDerivatives[1][0] = - 1.0;
+	evaluatedDerivatives[1][1] =   0.0;
+	evaluatedDerivatives[1][2] =   1.0;
+}
+
+int _LinearTriangularElementType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* norm ) {
+	Stream* errStream = Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
+
+	Journal_Printf( errStream, "surface normal function not yet implemented for this element type.\n" );
+	assert( 0 );
+
+	norm = NULL;
+
+	return -1;
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/LinkedDofInfo.c
--- a/Discretisation/src/LinkedDofInfo.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,474 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LinkedDofInfo.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "LinkedDofInfo.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-/** Textual name of this class */
-const Type LinkedDofInfo_Type = "LinkedDofInfo";
-
-LinkedDofInfo* LinkedDofInfo_New( Name name, DomainContext* context, void* mesh, DofLayout* dofLayout, Dictionary* dictionary ) {
-  LinkedDofInfo* self = (LinkedDofInfo*)_LinkedDofInfo_DefaultNew( name );
-
-	self->isConstructed = True;	
-	_LinkedDofInfo_Init( self, context, mesh, dofLayout, dictionary );
-
-	return self;
-}
-
-void* _LinkedDofInfo_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(LinkedDofInfo);
-	Type                                                      type = LinkedDofInfo_Type;
-	Stg_Class_DeleteFunction*                              _delete = _LinkedDofInfo_Delete;
-	Stg_Class_PrintFunction*                                _print = _LinkedDofInfo_Print;
-	Stg_Class_CopyFunction*                                  _copy = _LinkedDofInfo_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinkedDofInfo_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _LinkedDofInfo_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _LinkedDofInfo_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _LinkedDofInfo_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _LinkedDofInfo_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _LinkedDofInfo_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-
-	return (void*)
-		_LinkedDofInfo_New(  LINKEDDOFINFO_PASSARGS  );
-}
-
-LinkedDofInfo* _LinkedDofInfo_New(  LINKEDDOFINFO_DEFARGS  ) {
-	LinkedDofInfo* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(LinkedDofInfo) );
-	self = (LinkedDofInfo*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual info */
-	self->_build = _build;
-	self->_initialise = _initialise;
-	
-	/* member info */
-	
-	return self;
-}
-	
-void _LinkedDofInfo_Init( void* linkedDofInfo, DomainContext* context, void* mesh, DofLayout* dofLayout, Dictionary* dictionary ) {
-	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
-
-	self->context = context;
-	self->dofLayout = dofLayout;
-	self->mesh = (Mesh*)mesh;
-	self->dictionary = dictionary;
-
-	/* Initially no sets */
-	self->linkedDofSetsCount = 0;
-	self->linkedDofSetsDelta = 4;
-	self->linkedDofSetsSize = self->linkedDofSetsDelta;
-	self->eqNumsOfLinkedDofs = Memory_Alloc_Array( int, self->linkedDofSetsSize, "linkedDofInfo->eqNumsOfLinkedDofs" );
-}
-
-void _LinkedDofInfo_Delete( void* linkedDofInfo ) {
-	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
-
-	_Stg_Component_Delete( self );
-}
-
-void _LinkedDofInfo_Print( void* linkedDofInfo, Stream* stream ) {
-	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
-	Index				dofSet_I = 0;
-	Node_Index		node_I = 0;
-	Dof_Index		nodeLocalDof_I = 0;
-	
-	/* General info */
-	Journal_Printf( stream, "LinkedDofInfo (ptr): %p\n", self );
-	
-	/* Print parent */
-	_Stg_Class_Print( self, stream );
-
-	Journal_Printf( stream, "%d Linked dof sets active:\n", self->linkedDofSetsCount );
-	Stream_Indent( stream );
-
-	for ( dofSet_I = 0; dofSet_I < self->linkedDofSetsCount; dofSet_I++ ) {
-		Journal_Printf( stream, "Set %u: has eqNum %d\n", dofSet_I, self->eqNumsOfLinkedDofs[dofSet_I] );
-	}
-	Stream_UnIndent( stream );
-
-	Journal_Printf( stream, "Linked dof sets table:\n", self->linkedDofSetsCount );
-	Stream_Indent( stream );
-
-	for ( node_I = 0; node_I < self->dofLayout->_numItemsInLayout; node_I++ ) {
-		Journal_Printf( stream, "Node %d: ", node_I );
-		for ( nodeLocalDof_I = 0; nodeLocalDof_I < self->dofLayout->dofCounts[node_I]; nodeLocalDof_I++ ) {
-			Journal_Printf( stream, "%d, ", self->linkedDofTbl[node_I][nodeLocalDof_I] );
-		}
-		Journal_Printf( stream, "\n" );
-	}
-	Stream_UnIndent( stream );
-}
-
-void _LinkedDofInfo_AssignFromXML( void* linkedDofInfo, Stg_ComponentFactory *cf, void* data ){
-	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
-	Dictionary*		dictionary;
-	Mesh*				mesh = NULL;
-	DofLayout*		dofLayout = NULL;
-	DomainContext*	context;
-
-	dictionary = Dictionary_GetDictionary( cf->componentDict, self->name );
-	
-	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", DomainContext, False, data );
-	if( !context  ) 
-		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", DomainContext, True, data  );
-
-	mesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Mesh", Mesh, True, data  );
-	dofLayout = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)DofLayout_Type, DofLayout, True, data  );
-
-	_LinkedDofInfo_Init( self, context, mesh, dofLayout, dictionary ); 
-}
-	
-void _LinkedDofInfo_Execute( void* linkedDofInfo, void *data ){
-}
-	
-void _LinkedDofInfo_Destroy( void* linkedDofInfo, void *data ){
-	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
-	
-	Memory_Free( self->linkedDofTbl );
-	Memory_Free( self->eqNumsOfLinkedDofs );
-}
-
-void* _LinkedDofInfo_Copy( const void* linkedDofInfo, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
-	LinkedDofInfo*	newLinkedDofInfo;
-	PtrMap*			map = ptrMap;
-	Bool				ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newLinkedDofInfo = (LinkedDofInfo*)_Stg_Class_Copy( self, dest, deep, nameExt, map );
-	
-	/* Virtual methods */
-	newLinkedDofInfo->linkedDofSetsCount = self->linkedDofSetsCount;
-	newLinkedDofInfo->linkedDofSetsSize = self->linkedDofSetsSize;
-	newLinkedDofInfo->linkedDofSetsDelta = self->linkedDofSetsDelta;
-	
-	if ( deep ) {
-		newLinkedDofInfo->dofLayout = (DofLayout*)Stg_Class_Copy( self->dofLayout, NULL, deep, nameExt, map );
-		newLinkedDofInfo->mesh = (Mesh*)Stg_Class_Copy( self->mesh, NULL, deep, nameExt, map );
-
-		if ( (newLinkedDofInfo->linkedDofTbl = (int**)PtrMap_Find( map, self->linkedDofTbl )) == NULL && self->linkedDofTbl ) {
-			Node_Index	node_I;
-			Dof_Index	dof_I;
-			newLinkedDofInfo->linkedDofTbl = Memory_Alloc_2DComplex( int, self->dofLayout->_numItemsInLayout, self->dofLayout->dofCounts, "linkedDofInfo->linkedDofTbl" );
-			for ( node_I = 0; node_I < self->dofLayout->_numItemsInLayout; node_I++ ) {
-				for ( dof_I = 0; dof_I < self->dofLayout->dofCounts[node_I]; dof_I++ ) {
-					newLinkedDofInfo->linkedDofTbl[node_I][dof_I] =
-						self->linkedDofTbl[node_I][dof_I];
-				}
-			}
-			PtrMap_Append( map, self->linkedDofTbl, newLinkedDofInfo->linkedDofTbl );
-		}
-		if ( (newLinkedDofInfo->eqNumsOfLinkedDofs = (int*)PtrMap_Find( map, self->eqNumsOfLinkedDofs )) == NULL && self->eqNumsOfLinkedDofs ) {	
-			newLinkedDofInfo->eqNumsOfLinkedDofs = Memory_Alloc_Array( int, self->linkedDofSetsCount, "linkedDofInfo->eqNumsOfLinkedDofs" );
-			memcpy( newLinkedDofInfo->eqNumsOfLinkedDofs, self->eqNumsOfLinkedDofs, self->linkedDofSetsCount * sizeof(int) );
-			PtrMap_Append( map, self->eqNumsOfLinkedDofs, newLinkedDofInfo->eqNumsOfLinkedDofs );
-		}
-	}
-	else {
-		newLinkedDofInfo->dofLayout = self->dofLayout;
-		newLinkedDofInfo->mesh = self->mesh;
-		newLinkedDofInfo->linkedDofTbl = self->linkedDofTbl;
-		newLinkedDofInfo->eqNumsOfLinkedDofs = self->eqNumsOfLinkedDofs;
-	}
-
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-
-	return (void*)newLinkedDofInfo;
-}
-
-void _LinkedDofInfo_Build( void* linkedDofInfo, void* data ) {
-	LinkedDofInfo*				self = (LinkedDofInfo*)linkedDofInfo;
-	Dictionary_Entry_Value*	linkSpecs = NULL;
-	Node_Index					node_I;
-	Node_Index					nodeLocalDof_I;
-	DofLayout*					dofLayout;
-
-	dofLayout = self->dofLayout;
-	Stg_Component_Build( self->dofLayout, data, False );
-	
-	self->linkedDofTbl = Memory_Alloc_2DComplex( int, dofLayout->_numItemsInLayout,
-		dofLayout->dofCounts, "linkedDofInfo->linkedDofTbl" );
-
-	/* Initially, set all dofs as not belonging to a set */
-	for ( node_I = 0 ; node_I < dofLayout->_numItemsInLayout; node_I++ ) {
-		for ( nodeLocalDof_I = 0; nodeLocalDof_I < dofLayout->dofCounts[node_I]; nodeLocalDof_I++ ) {
-			self->linkedDofTbl[node_I][nodeLocalDof_I] = -1;
-		}
-	}
-	
-	linkSpecs = Dictionary_Get( self->dictionary, (Dictionary_Entry_Key)"linkSpecifications" );
-
-	/* Note that the dictionary entry is optional - user may prefer to specify the sets
-	using the AddDofToSet and AddDofsToSet_FromIndexSet functions */
-	
-	if ( linkSpecs ) {
-		Index							numSpecs = 0;
-		Index							linkSpec_I;
-		Dictionary_Entry_Value*	linkSpec = NULL;
-		Dictionary*					linkSpecDict;
-		Index							dofSet = 0;
-		Dictionary_Entry_Value*	wallVal;
-		Dictionary_Entry_Value*	shapeVal;
-		Dictionary_Entry_Value*	wallPairVal;
-		Index							nodalDof;
-
-		numSpecs = Dictionary_Entry_Value_GetCount( linkSpecs );
-		
-		for ( linkSpec_I = 0; linkSpec_I < numSpecs; linkSpec_I++  ) {
-			linkSpec = Dictionary_Entry_Value_GetElement( linkSpecs, linkSpec_I );
-			linkSpecDict = Dictionary_Entry_Value_AsDictionary( linkSpec );
-			nodalDof = Dictionary_Entry_Value_AsUnsignedInt( Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"dof" ) );
-			
-			if ( nodalDof >= self->dofLayout->dofCounts[0]  ) {
-				Stream*  warningStr = Journal_Register( Error_Type, (Name)self->type  );
-
-				Journal_DPrintf( warningStr, "Warning- in %s: User requested a periodic BC on "
-					"dof %d, but only %d dofs are active. Ignoring.\n", __func__, nodalDof,
-					self->dofLayout->dofCounts[0] );
-				
-				continue;
-			}
-			
-			if ( ( wallVal = Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"wall" ) ) ) {
-				IndexSet*	indexSet = NULL;
-				char*		wallStr = Dictionary_Entry_Value_AsString( wallVal  );
-				
-				dofSet = Dictionary_Entry_Value_AsUnsignedInt( Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"dofSet" )  );
-				
-				if ( 0 == strcmp( wallStr, "left" ) ) {
-					indexSet = RegularMeshUtils_CreateGlobalLeftSet( self->mesh );
-				}
-				else if ( 0 == strcmp( wallStr, "right" ) ) {
-					indexSet = RegularMeshUtils_CreateGlobalRightSet( self->mesh );
-				}
-				else if ( 0 == strcmp( wallStr, "bottom" ) ) {
-					indexSet = RegularMeshUtils_CreateGlobalBottomSet( self->mesh );
-				}
-				else if ( 0 == strcmp( wallStr, "top" ) ) {
-					indexSet = RegularMeshUtils_CreateGlobalTopSet( self->mesh );
-				}
-				else if ( 0 == strcmp( wallStr, "front" ) ) {
-					indexSet = RegularMeshUtils_CreateGlobalFrontSet( self->mesh );
-				}
-				else if ( 0 == strcmp( wallStr, "back" ) ) {
-					indexSet = RegularMeshUtils_CreateGlobalBackSet( self->mesh );
-				}
-				else {
-					Stream*	errorStr = Journal_Register( Error_Type, (Name)self->type  );
-					Journal_Printf( errorStr, "Error in %s: unknown wall string \"%s\" given. "
-						"Exiting.\n", __func__, wallStr );
-					exit(EXIT_FAILURE);
-				}
-
-				while ( dofSet >= self->linkedDofSetsCount ) { 
-					LinkedDofInfo_AddDofSet( linkedDofInfo );
-				}
-				
-				LinkedDofInfo_AddDofsToSet_FromIndexSet( self, dofSet, indexSet, nodalDof );
-			}
-			else if ( ( shapeVal = Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"shape" ) ) ) {
-				char*             shapeStr = Dictionary_Entry_Value_AsString( shapeVal );
-				Stg_Shape*        shape = NULL;
-				Node_LocalIndex   lNode_I = 0;
-				AbstractContext*  context = (AbstractContext* ) data;
-				Stream*           errorStr = Journal_Register( Error_Type, (Name)self->type  );
-
-				Journal_Firewall( context && Stg_Class_IsInstance( context, AbstractContext_Type ),
-					errorStr, "Error - in %s(): you've asked to create a Shape linked dof "
-					"specification, but haven't passed in the context as the \"data\" parameter "
-					"to %s - hence the shape can't be found in the component factory.\n",
-					__func__, __func__ );
-
-				Journal_Firewall( context->CF != NULL, errorStr,
-					"Error - in %s(): you've asked to create a Shape linked dof "
-					"specification, but the context passed as the \"data\" parameter "
-					"doesn't have a valid component factory to find the shape in.\n",
-					__func__, __func__ );
-
-				dofSet = Dictionary_Entry_Value_AsUnsignedInt( Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"dofSet" ) );
-				while ( dofSet >= self->linkedDofSetsCount ) { 
-					LinkedDofInfo_AddDofSet( linkedDofInfo  );
-				}
-				
-				shape = Stg_ComponentFactory_ConstructByName( context->CF, (Name)shapeStr, Stg_Shape, True, data  );
-				
-				for ( lNode_I = 0; lNode_I < Mesh_GetLocalSize( self->mesh, MT_VERTEX ); lNode_I++ ) {
-					if ( Stg_Shape_IsCoordInside( shape, Mesh_GetVertex( self->mesh, lNode_I ) ) ) {
-						LinkedDofInfo_AddDofToSet( self, dofSet, lNode_I, nodalDof );
-					}
-				}	
-			}
-			else if ( ( wallPairVal = Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"wallPair" ) ) ) {
-				char*		wallPairStr = Dictionary_Entry_Value_AsString( wallPairVal  );
-				Index		dofSetStart_I = self->linkedDofSetsCount;
-				Index		dofSet_I = 0;
-				Index		numWallNodes;
-				Index		wallSetNode_I = 0;
-				Index		firstSetNode_I = 0;
-				Index		secondSetNode_I = 0;
-				IndexSet*	firstSet = NULL;
-				IndexSet*	secondSet = NULL;
-				Index		numExtraDofSetsNeeded = 0;
-				Index		globallyKnownExtraDofSetsNeeded = 0;
-
-				if ( 0 == strcmp( wallPairStr, "left-right" ) ) {
-					firstSet = RegularMeshUtils_CreateGlobalLeftSet( self->mesh );
-					secondSet = RegularMeshUtils_CreateGlobalRightSet( self->mesh );
-				}	
-				else if ( 0 == strcmp( wallPairStr, "back-front" ) ) {
-					firstSet = RegularMeshUtils_CreateGlobalBackSet( self->mesh );
-					secondSet = RegularMeshUtils_CreateGlobalFrontSet( self->mesh );
-				}
-				else if ( 0 == strcmp( wallPairStr, "bottom-top" ) ) {
-					firstSet = RegularMeshUtils_CreateGlobalBottomSet( self->mesh );
-					secondSet = RegularMeshUtils_CreateGlobalTopSet( self->mesh );
-				}
-				else {
-					Stream*	errorStr = Journal_Register( Error_Type, (Name)self->type  );
-					Journal_Printf( errorStr, "Error in %s: unknown wall pair string \"%s\" given. "
-						"Exiting.\n", __func__, wallPairStr );
-					exit(EXIT_FAILURE);
-				}
-		
-				numExtraDofSetsNeeded = IndexSet_UpdateMembersCount( firstSet );
-				numWallNodes = IndexSet_UpdateMembersCount( secondSet );
-				if ( numWallNodes > numExtraDofSetsNeeded ) {
-					numExtraDofSetsNeeded = numWallNodes;
-				}	
-				/* In parallel, there may be several processors in the middle who aren't holding the
-				 * walls, but need to know they exist. Hence use an MPI_Allreduce to get the count */
-				MPI_Allreduce( &numExtraDofSetsNeeded, &globallyKnownExtraDofSetsNeeded, 1, MPI_UNSIGNED,
-					       MPI_MAX, Mesh_GetCommTopology( self->mesh, MT_VERTEX )->mpiComm );
-
-				for( dofSet_I = 0; dofSet_I < globallyKnownExtraDofSetsNeeded; dofSet_I++ ) {	
-					LinkedDofInfo_AddDofSet( linkedDofInfo );
-				}	
-
-				/* The below for loops are 2 separate ones, since in the parallel case we don't
-				know that the current proc contains both walls */
-				numWallNodes = IndexSet_UpdateMembersCount( firstSet );
-				dofSet_I = dofSetStart_I;
-				for ( wallSetNode_I = 0; wallSetNode_I < numWallNodes; wallSetNode_I++ ) {
-					firstSetNode_I = IndexSet_GetIndexOfNthMember( firstSet, wallSetNode_I );
-					LinkedDofInfo_AddDofToSet( linkedDofInfo, dofSet_I, firstSetNode_I, nodalDof );
-					dofSet_I++;
-				}
-
-				numWallNodes = IndexSet_UpdateMembersCount( secondSet );
-				dofSet_I = dofSetStart_I;
-				for ( wallSetNode_I = 0; wallSetNode_I < numWallNodes; wallSetNode_I++ ) {
-					secondSetNode_I = IndexSet_GetIndexOfNthMember( secondSet, wallSetNode_I );
-					LinkedDofInfo_AddDofToSet( linkedDofInfo, dofSet_I, secondSetNode_I, nodalDof );
-					dofSet_I++;
-				}
-			}
-		}
-	}
-}
-
-void _LinkedDofInfo_Initialise( void* linkedDofInfo, void* data ) {
-}
-
-Index LinkedDofInfo_AddDofSet( void* linkedDofInfo ) {
-	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
-	Index				indexIntoArray;
-
-	if ( self->linkedDofSetsCount == self->linkedDofSetsSize ) {
-		self->linkedDofSetsSize += self->linkedDofSetsDelta;
-		self->eqNumsOfLinkedDofs = Memory_Realloc_Array( self->eqNumsOfLinkedDofs, int, self->linkedDofSetsSize );
-	}
-	/* Set the eq num to -1 since uninitialised */
-	self->eqNumsOfLinkedDofs[self->linkedDofSetsCount] = -1;
-	indexIntoArray = self->linkedDofSetsCount++;
-
-	return indexIntoArray;
-}
-
-void LinkedDofInfo_AddDofToSet( void* linkedDofInfo, Index linkedDofSet_I, Node_Index node_I, Dof_Index nodeLocalDof_I ) {
-	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
-	Stream*			errorStr = Journal_Register( Error_Type, (Name)self->type  );
-	
-	Journal_Firewall( node_I < self->dofLayout->_numItemsInLayout, errorStr, "Error- in %s: tried to add a dof at a "
-		"node that doesn't exist.\n", __func__ );
-	Journal_Firewall( nodeLocalDof_I < self->dofLayout->dofCounts[node_I], errorStr, "Error- in %s: tried to add a "
-		"dof %d that doesn't exist at current node %d (max index is %d).\n", __func__, nodeLocalDof_I, node_I, 
-		self->dofLayout->dofCounts[node_I]-1 );
-	
-	self->linkedDofTbl[node_I][nodeLocalDof_I] = linkedDofSet_I;
-}
-
-void LinkedDofInfo_AddDofsToSet_FromIndexSet( void* linkedDofInfo, Index linkedDofSet_I, IndexSet* nodeSet, Dof_Index nodeLocalDof_I ) {
-	LinkedDofInfo*		self = (LinkedDofInfo*)linkedDofInfo;
-	Node_DomainIndex	node_I;
-
-	for ( node_I = 0; node_I < nodeSet->size; node_I++ ) {
-		if ( IndexSet_IsMember( nodeSet, node_I ) ) {
-			self->linkedDofTbl[node_I][nodeLocalDof_I] = linkedDofSet_I;
-		}
-	}	
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/LinkedDofInfo.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/LinkedDofInfo.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,474 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LinkedDofInfo.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "LinkedDofInfo.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+/** Textual name of this class */
+const Type LinkedDofInfo_Type = "LinkedDofInfo";
+
+LinkedDofInfo* LinkedDofInfo_New( Name name, DomainContext* context, void* mesh, DofLayout* dofLayout, Dictionary* dictionary ) {
+  LinkedDofInfo* self = (LinkedDofInfo*)_LinkedDofInfo_DefaultNew( name );
+
+	self->isConstructed = True;	
+	_LinkedDofInfo_Init( self, context, mesh, dofLayout, dictionary );
+
+	return self;
+}
+
+void* _LinkedDofInfo_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(LinkedDofInfo);
+	Type                                                      type = LinkedDofInfo_Type;
+	Stg_Class_DeleteFunction*                              _delete = _LinkedDofInfo_Delete;
+	Stg_Class_PrintFunction*                                _print = _LinkedDofInfo_Print;
+	Stg_Class_CopyFunction*                                  _copy = _LinkedDofInfo_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinkedDofInfo_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _LinkedDofInfo_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _LinkedDofInfo_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _LinkedDofInfo_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _LinkedDofInfo_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _LinkedDofInfo_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+
+	return (void*)
+		_LinkedDofInfo_New(  LINKEDDOFINFO_PASSARGS  );
+}
+
+LinkedDofInfo* _LinkedDofInfo_New(  LINKEDDOFINFO_DEFARGS  ) {
+	LinkedDofInfo* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(LinkedDofInfo) );
+	self = (LinkedDofInfo*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual info */
+	self->_build = _build;
+	self->_initialise = _initialise;
+	
+	/* member info */
+	
+	return self;
+}
+	
+void _LinkedDofInfo_Init( void* linkedDofInfo, DomainContext* context, void* mesh, DofLayout* dofLayout, Dictionary* dictionary ) {
+	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
+
+	self->context = context;
+	self->dofLayout = dofLayout;
+	self->mesh = (Mesh*)mesh;
+	self->dictionary = dictionary;
+
+	/* Initially no sets */
+	self->linkedDofSetsCount = 0;
+	self->linkedDofSetsDelta = 4;
+	self->linkedDofSetsSize = self->linkedDofSetsDelta;
+	self->eqNumsOfLinkedDofs = Memory_Alloc_Array( int, self->linkedDofSetsSize, "linkedDofInfo->eqNumsOfLinkedDofs" );
+}
+
+void _LinkedDofInfo_Delete( void* linkedDofInfo ) {
+	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
+
+	_Stg_Component_Delete( self );
+}
+
+void _LinkedDofInfo_Print( void* linkedDofInfo, Stream* stream ) {
+	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
+	Index				dofSet_I = 0;
+	Node_Index		node_I = 0;
+	Dof_Index		nodeLocalDof_I = 0;
+	
+	/* General info */
+	Journal_Printf( stream, "LinkedDofInfo (ptr): %p\n", self );
+	
+	/* Print parent */
+	_Stg_Class_Print( self, stream );
+
+	Journal_Printf( stream, "%d Linked dof sets active:\n", self->linkedDofSetsCount );
+	Stream_Indent( stream );
+
+	for ( dofSet_I = 0; dofSet_I < self->linkedDofSetsCount; dofSet_I++ ) {
+		Journal_Printf( stream, "Set %u: has eqNum %d\n", dofSet_I, self->eqNumsOfLinkedDofs[dofSet_I] );
+	}
+	Stream_UnIndent( stream );
+
+	Journal_Printf( stream, "Linked dof sets table:\n", self->linkedDofSetsCount );
+	Stream_Indent( stream );
+
+	for ( node_I = 0; node_I < self->dofLayout->_numItemsInLayout; node_I++ ) {
+		Journal_Printf( stream, "Node %d: ", node_I );
+		for ( nodeLocalDof_I = 0; nodeLocalDof_I < self->dofLayout->dofCounts[node_I]; nodeLocalDof_I++ ) {
+			Journal_Printf( stream, "%d, ", self->linkedDofTbl[node_I][nodeLocalDof_I] );
+		}
+		Journal_Printf( stream, "\n" );
+	}
+	Stream_UnIndent( stream );
+}
+
+void _LinkedDofInfo_AssignFromXML( void* linkedDofInfo, Stg_ComponentFactory *cf, void* data ){
+	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
+	Dictionary*		dictionary;
+	Mesh*				mesh = NULL;
+	DofLayout*		dofLayout = NULL;
+	DomainContext*	context;
+
+	dictionary = Dictionary_GetDictionary( cf->componentDict, self->name );
+	
+	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", DomainContext, False, data );
+	if( !context  ) 
+		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", DomainContext, True, data  );
+
+	mesh = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Mesh", Mesh, True, data  );
+	dofLayout = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)DofLayout_Type, DofLayout, True, data  );
+
+	_LinkedDofInfo_Init( self, context, mesh, dofLayout, dictionary ); 
+}
+	
+void _LinkedDofInfo_Execute( void* linkedDofInfo, void *data ){
+}
+	
+void _LinkedDofInfo_Destroy( void* linkedDofInfo, void *data ){
+	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
+	
+	Memory_Free( self->linkedDofTbl );
+	Memory_Free( self->eqNumsOfLinkedDofs );
+}
+
+void* _LinkedDofInfo_Copy( const void* linkedDofInfo, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
+	LinkedDofInfo*	newLinkedDofInfo;
+	PtrMap*			map = ptrMap;
+	Bool				ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newLinkedDofInfo = (LinkedDofInfo*)_Stg_Class_Copy( self, dest, deep, nameExt, map );
+	
+	/* Virtual methods */
+	newLinkedDofInfo->linkedDofSetsCount = self->linkedDofSetsCount;
+	newLinkedDofInfo->linkedDofSetsSize = self->linkedDofSetsSize;
+	newLinkedDofInfo->linkedDofSetsDelta = self->linkedDofSetsDelta;
+	
+	if ( deep ) {
+		newLinkedDofInfo->dofLayout = (DofLayout*)Stg_Class_Copy( self->dofLayout, NULL, deep, nameExt, map );
+		newLinkedDofInfo->mesh = (Mesh*)Stg_Class_Copy( self->mesh, NULL, deep, nameExt, map );
+
+		if ( (newLinkedDofInfo->linkedDofTbl = (int**)PtrMap_Find( map, self->linkedDofTbl )) == NULL && self->linkedDofTbl ) {
+			Node_Index	node_I;
+			Dof_Index	dof_I;
+			newLinkedDofInfo->linkedDofTbl = Memory_Alloc_2DComplex( int, self->dofLayout->_numItemsInLayout, self->dofLayout->dofCounts, "linkedDofInfo->linkedDofTbl" );
+			for ( node_I = 0; node_I < self->dofLayout->_numItemsInLayout; node_I++ ) {
+				for ( dof_I = 0; dof_I < self->dofLayout->dofCounts[node_I]; dof_I++ ) {
+					newLinkedDofInfo->linkedDofTbl[node_I][dof_I] =
+						self->linkedDofTbl[node_I][dof_I];
+				}
+			}
+			PtrMap_Append( map, self->linkedDofTbl, newLinkedDofInfo->linkedDofTbl );
+		}
+		if ( (newLinkedDofInfo->eqNumsOfLinkedDofs = (int*)PtrMap_Find( map, self->eqNumsOfLinkedDofs )) == NULL && self->eqNumsOfLinkedDofs ) {	
+			newLinkedDofInfo->eqNumsOfLinkedDofs = Memory_Alloc_Array( int, self->linkedDofSetsCount, "linkedDofInfo->eqNumsOfLinkedDofs" );
+			memcpy( newLinkedDofInfo->eqNumsOfLinkedDofs, self->eqNumsOfLinkedDofs, self->linkedDofSetsCount * sizeof(int) );
+			PtrMap_Append( map, self->eqNumsOfLinkedDofs, newLinkedDofInfo->eqNumsOfLinkedDofs );
+		}
+	}
+	else {
+		newLinkedDofInfo->dofLayout = self->dofLayout;
+		newLinkedDofInfo->mesh = self->mesh;
+		newLinkedDofInfo->linkedDofTbl = self->linkedDofTbl;
+		newLinkedDofInfo->eqNumsOfLinkedDofs = self->eqNumsOfLinkedDofs;
+	}
+
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+
+	return (void*)newLinkedDofInfo;
+}
+
+void _LinkedDofInfo_Build( void* linkedDofInfo, void* data ) {
+	LinkedDofInfo*				self = (LinkedDofInfo*)linkedDofInfo;
+	Dictionary_Entry_Value*	linkSpecs = NULL;
+	Node_Index					node_I;
+	Node_Index					nodeLocalDof_I;
+	DofLayout*					dofLayout;
+
+	dofLayout = self->dofLayout;
+	Stg_Component_Build( self->dofLayout, data, False );
+	
+	self->linkedDofTbl = Memory_Alloc_2DComplex( int, dofLayout->_numItemsInLayout,
+		dofLayout->dofCounts, "linkedDofInfo->linkedDofTbl" );
+
+	/* Initially, set all dofs as not belonging to a set */
+	for ( node_I = 0 ; node_I < dofLayout->_numItemsInLayout; node_I++ ) {
+		for ( nodeLocalDof_I = 0; nodeLocalDof_I < dofLayout->dofCounts[node_I]; nodeLocalDof_I++ ) {
+			self->linkedDofTbl[node_I][nodeLocalDof_I] = -1;
+		}
+	}
+	
+	linkSpecs = Dictionary_Get( self->dictionary, (Dictionary_Entry_Key)"linkSpecifications" );
+
+	/* Note that the dictionary entry is optional - user may prefer to specify the sets
+	using the AddDofToSet and AddDofsToSet_FromIndexSet functions */
+	
+	if ( linkSpecs ) {
+		Index							numSpecs = 0;
+		Index							linkSpec_I;
+		Dictionary_Entry_Value*	linkSpec = NULL;
+		Dictionary*					linkSpecDict;
+		Index							dofSet = 0;
+		Dictionary_Entry_Value*	wallVal;
+		Dictionary_Entry_Value*	shapeVal;
+		Dictionary_Entry_Value*	wallPairVal;
+		Index							nodalDof;
+
+		numSpecs = Dictionary_Entry_Value_GetCount( linkSpecs );
+		
+		for ( linkSpec_I = 0; linkSpec_I < numSpecs; linkSpec_I++  ) {
+			linkSpec = Dictionary_Entry_Value_GetElement( linkSpecs, linkSpec_I );
+			linkSpecDict = Dictionary_Entry_Value_AsDictionary( linkSpec );
+			nodalDof = Dictionary_Entry_Value_AsUnsignedInt( Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"dof" ) );
+			
+			if ( nodalDof >= self->dofLayout->dofCounts[0]  ) {
+				Stream*  warningStr = Journal_Register( Error_Type, (Name)self->type  );
+
+				Journal_DPrintf( warningStr, "Warning- in %s: User requested a periodic BC on "
+					"dof %d, but only %d dofs are active. Ignoring.\n", __func__, nodalDof,
+					self->dofLayout->dofCounts[0] );
+				
+				continue;
+			}
+			
+			if ( ( wallVal = Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"wall" ) ) ) {
+				IndexSet*	indexSet = NULL;
+				char*		wallStr = Dictionary_Entry_Value_AsString( wallVal  );
+				
+				dofSet = Dictionary_Entry_Value_AsUnsignedInt( Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"dofSet" )  );
+				
+				if ( 0 == strcmp( wallStr, "left" ) ) {
+					indexSet = RegularMeshUtils_CreateGlobalLeftSet( self->mesh );
+				}
+				else if ( 0 == strcmp( wallStr, "right" ) ) {
+					indexSet = RegularMeshUtils_CreateGlobalRightSet( self->mesh );
+				}
+				else if ( 0 == strcmp( wallStr, "bottom" ) ) {
+					indexSet = RegularMeshUtils_CreateGlobalBottomSet( self->mesh );
+				}
+				else if ( 0 == strcmp( wallStr, "top" ) ) {
+					indexSet = RegularMeshUtils_CreateGlobalTopSet( self->mesh );
+				}
+				else if ( 0 == strcmp( wallStr, "front" ) ) {
+					indexSet = RegularMeshUtils_CreateGlobalFrontSet( self->mesh );
+				}
+				else if ( 0 == strcmp( wallStr, "back" ) ) {
+					indexSet = RegularMeshUtils_CreateGlobalBackSet( self->mesh );
+				}
+				else {
+					Stream*	errorStr = Journal_Register( Error_Type, (Name)self->type  );
+					Journal_Printf( errorStr, "Error in %s: unknown wall string \"%s\" given. "
+						"Exiting.\n", __func__, wallStr );
+					exit(EXIT_FAILURE);
+				}
+
+				while ( dofSet >= self->linkedDofSetsCount ) { 
+					LinkedDofInfo_AddDofSet( linkedDofInfo );
+				}
+				
+				LinkedDofInfo_AddDofsToSet_FromIndexSet( self, dofSet, indexSet, nodalDof );
+			}
+			else if ( ( shapeVal = Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"shape" ) ) ) {
+				char*             shapeStr = Dictionary_Entry_Value_AsString( shapeVal );
+				Stg_Shape*        shape = NULL;
+				Node_LocalIndex   lNode_I = 0;
+				AbstractContext*  context = (AbstractContext* ) data;
+				Stream*           errorStr = Journal_Register( Error_Type, (Name)self->type  );
+
+				Journal_Firewall( context && Stg_Class_IsInstance( context, AbstractContext_Type ),
+					errorStr, "Error - in %s(): you've asked to create a Shape linked dof "
+					"specification, but haven't passed in the context as the \"data\" parameter "
+					"to %s - hence the shape can't be found in the component factory.\n",
+					__func__, __func__ );
+
+				Journal_Firewall( context->CF != NULL, errorStr,
+					"Error - in %s(): you've asked to create a Shape linked dof "
+					"specification, but the context passed as the \"data\" parameter "
+					"doesn't have a valid component factory to find the shape in.\n",
+					__func__, __func__ );
+
+				dofSet = Dictionary_Entry_Value_AsUnsignedInt( Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"dofSet" ) );
+				while ( dofSet >= self->linkedDofSetsCount ) { 
+					LinkedDofInfo_AddDofSet( linkedDofInfo  );
+				}
+				
+				shape = Stg_ComponentFactory_ConstructByName( context->CF, (Name)shapeStr, Stg_Shape, True, data  );
+				
+				for ( lNode_I = 0; lNode_I < Mesh_GetLocalSize( self->mesh, MT_VERTEX ); lNode_I++ ) {
+					if ( Stg_Shape_IsCoordInside( shape, Mesh_GetVertex( self->mesh, lNode_I ) ) ) {
+						LinkedDofInfo_AddDofToSet( self, dofSet, lNode_I, nodalDof );
+					}
+				}	
+			}
+			else if ( ( wallPairVal = Dictionary_Get( linkSpecDict, (Dictionary_Entry_Key)"wallPair" ) ) ) {
+				char*		wallPairStr = Dictionary_Entry_Value_AsString( wallPairVal  );
+				Index		dofSetStart_I = self->linkedDofSetsCount;
+				Index		dofSet_I = 0;
+				Index		numWallNodes;
+				Index		wallSetNode_I = 0;
+				Index		firstSetNode_I = 0;
+				Index		secondSetNode_I = 0;
+				IndexSet*	firstSet = NULL;
+				IndexSet*	secondSet = NULL;
+				Index		numExtraDofSetsNeeded = 0;
+				Index		globallyKnownExtraDofSetsNeeded = 0;
+
+				if ( 0 == strcmp( wallPairStr, "left-right" ) ) {
+					firstSet = RegularMeshUtils_CreateGlobalLeftSet( self->mesh );
+					secondSet = RegularMeshUtils_CreateGlobalRightSet( self->mesh );
+				}	
+				else if ( 0 == strcmp( wallPairStr, "back-front" ) ) {
+					firstSet = RegularMeshUtils_CreateGlobalBackSet( self->mesh );
+					secondSet = RegularMeshUtils_CreateGlobalFrontSet( self->mesh );
+				}
+				else if ( 0 == strcmp( wallPairStr, "bottom-top" ) ) {
+					firstSet = RegularMeshUtils_CreateGlobalBottomSet( self->mesh );
+					secondSet = RegularMeshUtils_CreateGlobalTopSet( self->mesh );
+				}
+				else {
+					Stream*	errorStr = Journal_Register( Error_Type, (Name)self->type  );
+					Journal_Printf( errorStr, "Error in %s: unknown wall pair string \"%s\" given. "
+						"Exiting.\n", __func__, wallPairStr );
+					exit(EXIT_FAILURE);
+				}
+		
+				numExtraDofSetsNeeded = IndexSet_UpdateMembersCount( firstSet );
+				numWallNodes = IndexSet_UpdateMembersCount( secondSet );
+				if ( numWallNodes > numExtraDofSetsNeeded ) {
+					numExtraDofSetsNeeded = numWallNodes;
+				}	
+				/* In parallel, there may be several processors in the middle who aren't holding the
+				 * walls, but need to know they exist. Hence use an MPI_Allreduce to get the count */
+				MPI_Allreduce( &numExtraDofSetsNeeded, &globallyKnownExtraDofSetsNeeded, 1, MPI_UNSIGNED,
+					       MPI_MAX, Mesh_GetCommTopology( self->mesh, MT_VERTEX )->mpiComm );
+
+				for( dofSet_I = 0; dofSet_I < globallyKnownExtraDofSetsNeeded; dofSet_I++ ) {	
+					LinkedDofInfo_AddDofSet( linkedDofInfo );
+				}	
+
+				/* The below for loops are 2 separate ones, since in the parallel case we don't
+				know that the current proc contains both walls */
+				numWallNodes = IndexSet_UpdateMembersCount( firstSet );
+				dofSet_I = dofSetStart_I;
+				for ( wallSetNode_I = 0; wallSetNode_I < numWallNodes; wallSetNode_I++ ) {
+					firstSetNode_I = IndexSet_GetIndexOfNthMember( firstSet, wallSetNode_I );
+					LinkedDofInfo_AddDofToSet( linkedDofInfo, dofSet_I, firstSetNode_I, nodalDof );
+					dofSet_I++;
+				}
+
+				numWallNodes = IndexSet_UpdateMembersCount( secondSet );
+				dofSet_I = dofSetStart_I;
+				for ( wallSetNode_I = 0; wallSetNode_I < numWallNodes; wallSetNode_I++ ) {
+					secondSetNode_I = IndexSet_GetIndexOfNthMember( secondSet, wallSetNode_I );
+					LinkedDofInfo_AddDofToSet( linkedDofInfo, dofSet_I, secondSetNode_I, nodalDof );
+					dofSet_I++;
+				}
+			}
+		}
+	}
+}
+
+void _LinkedDofInfo_Initialise( void* linkedDofInfo, void* data ) {
+}
+
+Index LinkedDofInfo_AddDofSet( void* linkedDofInfo ) {
+	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
+	Index				indexIntoArray;
+
+	if ( self->linkedDofSetsCount == self->linkedDofSetsSize ) {
+		self->linkedDofSetsSize += self->linkedDofSetsDelta;
+		self->eqNumsOfLinkedDofs = Memory_Realloc_Array( self->eqNumsOfLinkedDofs, int, self->linkedDofSetsSize );
+	}
+	/* Set the eq num to -1 since uninitialised */
+	self->eqNumsOfLinkedDofs[self->linkedDofSetsCount] = -1;
+	indexIntoArray = self->linkedDofSetsCount++;
+
+	return indexIntoArray;
+}
+
+void LinkedDofInfo_AddDofToSet( void* linkedDofInfo, Index linkedDofSet_I, Node_Index node_I, Dof_Index nodeLocalDof_I ) {
+	LinkedDofInfo*	self = (LinkedDofInfo*)linkedDofInfo;
+	Stream*			errorStr = Journal_Register( Error_Type, (Name)self->type  );
+	
+	Journal_Firewall( node_I < self->dofLayout->_numItemsInLayout, errorStr, "Error- in %s: tried to add a dof at a "
+		"node that doesn't exist.\n", __func__ );
+	Journal_Firewall( nodeLocalDof_I < self->dofLayout->dofCounts[node_I], errorStr, "Error- in %s: tried to add a "
+		"dof %d that doesn't exist at current node %d (max index is %d).\n", __func__, nodeLocalDof_I, node_I, 
+		self->dofLayout->dofCounts[node_I]-1 );
+	
+	self->linkedDofTbl[node_I][nodeLocalDof_I] = linkedDofSet_I;
+}
+
+void LinkedDofInfo_AddDofsToSet_FromIndexSet( void* linkedDofInfo, Index linkedDofSet_I, IndexSet* nodeSet, Dof_Index nodeLocalDof_I ) {
+	LinkedDofInfo*		self = (LinkedDofInfo*)linkedDofInfo;
+	Node_DomainIndex	node_I;
+
+	for ( node_I = 0; node_I < nodeSet->size; node_I++ ) {
+		if ( IndexSet_IsMember( nodeSet, node_I ) ) {
+			self->linkedDofTbl[node_I][nodeLocalDof_I] = linkedDofSet_I;
+		}
+	}	
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/OperatorFeVariable.c
--- a/Discretisation/src/OperatorFeVariable.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,685 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: OperatorFeVariable.c 1137 2008-05-23 05:57:48Z RobertTurnbull $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "types.h"
-#include "FeVariable.h"
-#include "OperatorFeVariable.h"
-#include "FeMesh.h"
-
-#include <assert.h>
-
-const Type OperatorFeVariable_Type = "OperatorFeVariable";
-
-OperatorFeVariable* OperatorFeVariable_NewUnary(
-	Name				name,
-	DomainContext*	context,
-	void*				_feVariable,
-	Name				operatorName )
-{
-	FeVariable*	feVariable = (FeVariable*) _feVariable;
-	Stream*		errorStream = Journal_Register( Error_Type, (Name)OperatorFeVariable_Type  );
-
-	Journal_Firewall( feVariable != NULL, errorStream, "In func %s: Trying to operate on NULL field.\n", __func__ );
-       	
-	return OperatorFeVariable_New( 
-		name,
-		context,
-		feVariable->feMesh,
-  		feVariable->geometryMesh,
-  		feVariable->dofLayout,                                                                                 
-  		feVariable->bcs,
-  		feVariable->ics,
-  		feVariable->linkedDofInfo,
-  		feVariable->templateFeVariable,    
-		OperatorFeVariable_UnaryInterpolationFunc, 
-		OperatorFeVariable_UnaryValueAtNodeFunc,
-		operatorName,
-		NULL,
-		1,
-		&feVariable, 
-		feVariable->dim,
-		feVariable->isCheckpointedAndReloaded,
-		feVariable->communicator,
-		feVariable->fieldVariable_Register );
-}
-
-OperatorFeVariable* OperatorFeVariable_NewUnary_OwnOperator(
-	Name				name,
-	DomainContext*	context,
-	void*				_feVariable,
-	Operator*		ownOperator )
-{
-	FeVariable*	feVariable = (FeVariable*) _feVariable;
-	Stream*		errorStream = Journal_Register( Error_Type, (Name)OperatorFeVariable_Type  );
-
-	Journal_Firewall( feVariable != NULL, errorStream, "In func %s: Trying to operate on NULL field.\n", __func__ );
-       	
-	return OperatorFeVariable_New( 
-		name,
-		context,
-		feVariable->feMesh,
-  		feVariable->geometryMesh,
-  		feVariable->dofLayout,                                                                                 
-  		feVariable->bcs,
-  		feVariable->ics,
-  		feVariable->linkedDofInfo,
-  		feVariable->templateFeVariable,    
-		OperatorFeVariable_UnaryInterpolationFunc, 
-		OperatorFeVariable_UnaryValueAtNodeFunc,
-		ownOperator->name,
-		ownOperator,
-		1,
-		&feVariable, 
-		feVariable->dim,
-		feVariable->isCheckpointedAndReloaded,
-		feVariable->communicator,
-		feVariable->fieldVariable_Register );
-}
-
-OperatorFeVariable* OperatorFeVariable_NewBinary(
-	Name				name,
-	DomainContext*	context,
-	void*				_feVariable1,
-	void*				_feVariable2,
-	Name				operatorName )
-{
-	FeVariable*	feVariableList[2];
-	Stream*		errorStream = Journal_Register( Error_Type, (Name)OperatorFeVariable_Type  );
-	
-	Journal_Firewall( _feVariable1 != NULL, errorStream, "In func %s: First field to operate on is NULL.\n", __func__ );
-	Journal_Firewall( _feVariable2 != NULL, errorStream, "In func %s: Second field to operate on is NULL.\n", __func__ );
-       
-	feVariableList[0] = (FeVariable*) _feVariable1;
-	feVariableList[1] = (FeVariable*) _feVariable2;
-	
-	return OperatorFeVariable_New( 
-		name,
-		context,
-		feVariableList[0]->feMesh,
-  		feVariableList[0]->geometryMesh,
-  		feVariableList[0]->dofLayout,                                                                                 
-  		feVariableList[0]->bcs,
-  		feVariableList[0]->ics,
-  		feVariableList[0]->linkedDofInfo,
-  		feVariableList[0]->templateFeVariable,    
-		OperatorFeVariable_BinaryInterpolationFunc, 
-		OperatorFeVariable_BinaryValueAtNodeFunc,
-		operatorName,
-		NULL,
-		2, 
-		feVariableList, 
-		feVariableList[0]->dim,
-		feVariableList[0]->isCheckpointedAndReloaded,
-		feVariableList[0]->communicator,
-		feVariableList[0]->fieldVariable_Register );
-}
-
-OperatorFeVariable* OperatorFeVariable_New( 
-	Name														name,
-	DomainContext*											context,
-	void*														feMesh,
-  	void*														geometryMesh,
-  	DofLayout*												dofLayout,                                                                                 
-  	void*														bcs,
-  	void*														ics,
-  	void*														linkedDofInfo,
-  	void*														templateFeVariable,    
-	FeVariable_InterpolateWithinElementFunction*	interpolateWithinElement,
-	FeVariable_GetValueAtNodeFunction*				getValueAtNode,
-	Name														operatorName,
-	Operator*                                    ownOperator,
-	Index														feVariableCount,
-	FeVariable**											feVariableList,
-	Dimension_Index										dim,
-	Bool														isCheckpointedAndReloaded,
-	MPI_Comm													communicator,
-	FieldVariable_Register*								fieldVariable_Register )
-{
-  OperatorFeVariable* self = (OperatorFeVariable*)_OperatorFeVariable_DefaultNew( name );
-
-	self->isConstructed = True;
-	_FieldVariable_Init( (FieldVariable*)self, context, feVariableCount, dim, isCheckpointedAndReloaded, communicator, fieldVariable_Register );                                                                                                          
-   _FeVariable_Init( (FeVariable*)self, feMesh, geometryMesh, dofLayout, bcs, ics, linkedDofInfo, templateFeVariable, True, False );
-	_OperatorFeVariable_Init( self, operatorName, feVariableCount, feVariableList, ownOperator );
-
-	return self;
-}
-
-void* _OperatorFeVariable_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                         _sizeOfSelf = sizeof(OperatorFeVariable);
-	Type                                                                 type = OperatorFeVariable_Type;
-	Stg_Class_DeleteFunction*                                         _delete = _OperatorFeVariable_Delete;
-	Stg_Class_PrintFunction*                                           _print = _OperatorFeVariable_Print;
-	Stg_Class_CopyFunction*                                             _copy = _OperatorFeVariable_Copy;
-	Stg_Component_DefaultConstructorFunction*             _defaultConstructor = (Stg_Component_DefaultConstructorFunction*)_OperatorFeVariable_DefaultNew;
-	Stg_Component_ConstructFunction*                               _construct = _OperatorFeVariable_AssignFromXML;
-	Stg_Component_BuildFunction*                                       _build = _OperatorFeVariable_Build;
-	Stg_Component_InitialiseFunction*                             _initialise = _OperatorFeVariable_Initialise;
-	Stg_Component_ExecuteFunction*                                   _execute = _OperatorFeVariable_Execute;
-	Stg_Component_DestroyFunction*                                   _destroy = _OperatorFeVariable_Destroy;
-	AllocationType                                         nameAllocationType = NON_GLOBAL;
-	FieldVariable_InterpolateValueAtFunction*             _interpolateValueAt = _OperatorFeVariable_InterpolateValueAt;
-	FieldVariable_GetValueFunction*               _getMinGlobalFieldMagnitude = _FeVariable_GetMinGlobalFieldMagnitude;
-	FieldVariable_GetValueFunction*               _getMaxGlobalFieldMagnitude = _FeVariable_GetMaxGlobalFieldMagnitude;
-	FieldVariable_GetCoordFunction*                  _getMinAndMaxLocalCoords = _FeVariable_GetMinAndMaxLocalCoords;
-	FieldVariable_GetCoordFunction*                 _getMinAndMaxGlobalCoords = _FeVariable_GetMinAndMaxGlobalCoords;
-	FeVariable_InterpolateWithinElementFunction*    _interpolateWithinElement = _OperatorFeVariable_InterpolateWithinElement;
-	FeVariable_GetValueAtNodeFunction*                        _getValueAtNode = _OperatorFeVariable_GetValueAtNode;
-	FeVariable_SyncShadowValuesFunc*                        _syncShadowValues = _OperatorFeVariable_SyncShadowValues;
-
-	return _OperatorFeVariable_New(  OPERATORFEVARIABLE_PASSARGS  ); /* feVariableList_renamed */
-}
-
-OperatorFeVariable* _OperatorFeVariable_New(  OPERATORFEVARIABLE_DEFARGS  ) {
-	OperatorFeVariable* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(OperatorFeVariable) );
-	self = (OperatorFeVariable*) _FeVariable_New(  FEVARIABLE_PASSARGS  );
-
-	return self;
-}
-
-void _OperatorFeVariable_Init( void* oFeVar, Name operatorName, Index feVariableCount, FeVariable** feVariableList, Operator* ownOperator ) {
-	OperatorFeVariable*	self = (OperatorFeVariable*) oFeVar;
-	FeVariable*				feVariable;
-	Index						feVariable_I;
-	Stream*					errorStream = Journal_Register( Error_Type, (Name)self->type  );
-
-	/* Assign values to object */
-	self->feVariableCount = feVariableCount;
-	self->operatorName =operatorName;
-	self->_operator = ownOperator;
-
-	/* Copy field variable list */
-	self->feVariableList = Memory_Alloc_Array( FeVariable*, feVariableCount, "Array of Field Variables" );
-	memcpy( self->feVariableList, feVariableList, feVariableCount * sizeof( FeVariable* ) );
-
-	for ( feVariable_I = 0 ; feVariable_I < feVariableCount ; feVariable_I++ ) {
-		feVariable = feVariableList[ feVariable_I ];
-		Journal_Firewall( feVariable != NULL,
-				errorStream, "In func %s: Field Variable %u in list is NULL.\n", __func__, feVariable_I );
-		Journal_Firewall( feVariable->fieldComponentCount <= MAX_FIELD_COMPONENTS,
-				errorStream, "In func %s: Field Variable '%s' has too many components.\n", __func__, feVariable->name );
-	}
-}
-
-void _OperatorFeVariable_Delete( void* _feVariable ) {
-	OperatorFeVariable* self = (OperatorFeVariable*) _feVariable;
-
-	_FeVariable_Delete( self );
-}
-
-void _OperatorFeVariable_Print( void* _feVariable, Stream* stream ) {
-	OperatorFeVariable* self = (OperatorFeVariable*) _feVariable;
-	Index               feVariable_I;
-
-	_FeVariable_Print( self, stream );
-
-	Journal_PrintValue( stream, self->feVariableCount );
-	for ( feVariable_I = 0 ; feVariable_I < self->feVariableCount ; feVariable_I++ ) 
-		Journal_Printf( stream, "\tFeVariable %u - '%s'\n", feVariable_I, self->feVariableList[ feVariable_I ]->name );
-
-}
-
-void* _OperatorFeVariable_Copy( const void* feVariable, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	OperatorFeVariable*	self = (OperatorFeVariable*)feVariable;
-	OperatorFeVariable*	newOperatorFeVariable;
-	
-	newOperatorFeVariable = (OperatorFeVariable*)_FeVariable_Copy( self, dest, deep, nameExt, ptrMap );
-	
-	newOperatorFeVariable->_operator = self->_operator;
-	newOperatorFeVariable->feVariableCount = self->feVariableCount;
-	
-	if (deep) {
-		newOperatorFeVariable->feVariableList = Memory_Alloc_Array( FeVariable*, self->feVariableCount, "Array of Field Variables" );
-		memcpy( newOperatorFeVariable->feVariableList, self->feVariableList, self->feVariableCount * sizeof( FeVariable* ) );
-	}
-	else 
-		newOperatorFeVariable->feVariableList = self->feVariableList;
-	
-	return (void*)newOperatorFeVariable;
-}
-
-void _OperatorFeVariable_AssignFromXML( void* feVariable, Stg_ComponentFactory* cf, void* data ) {
-	OperatorFeVariable*     self = (OperatorFeVariable*) feVariable;
-	Dictionary*             dictionary = Dictionary_GetDictionary( cf->componentDict, self->name );
-	Dictionary_Entry_Value* list;
-	Index                   feVariableCount = 0;
-	Index                   feVariable_I;
-	FieldVariable_Register* fV_Register;     
-	Name                    feVariableName;
-	Name                    operatorName;
-	FeVariable**            feVariableList;
-	
-	/* Construct Parent */
-	_FieldVariable_AssignFromXML( self, cf, data );
-
-	fV_Register = self->context->fieldVariable_Register;
-
-	operatorName = Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"Operator", ""  );
-
-	list = Dictionary_Get( dictionary, (Dictionary_Entry_Key)"FeVariables" );
-	
-	feVariableCount = ( list ? Dictionary_Entry_Value_GetCount(list) : 1  );
-	feVariableList = Memory_Alloc_Array( FeVariable*, feVariableCount, "FeVars" );
-
-	for ( feVariable_I = 0 ; feVariable_I < feVariableCount ; feVariable_I++ ) {
-		feVariableName = (list ?  Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( list, feVariable_I ) ) :
-			Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"FeVariable" )  );
-
-		/* Check in fV_Register first before assuming in LiveComponentRegister */
-		Journal_PrintfL( cf->infoStream, 2, "Looking for FeVariable '%s' in fieldVariable_Register.\n", feVariableName );
-		feVariableList[feVariable_I] = (FeVariable*) FieldVariable_Register_GetByName( fV_Register, feVariableName );
-		
-		if ( !feVariableList[feVariable_I] )
-			feVariableList[feVariable_I] = 
-		Stg_ComponentFactory_ConstructByName( cf, (Name)feVariableName, FeVariable, True, data ); 
-	}
-
-	_FeVariable_Init( (FeVariable* ) self, feVariableList[0]->feMesh, feVariableList[0]->geometryMesh, feVariableList[0]->dofLayout, NULL, NULL, NULL, NULL, True, False );
-	_OperatorFeVariable_Init( self, operatorName, feVariableCount, feVariableList, NULL );
-
-	Memory_Free( feVariableList );
-}
-
-void _OperatorFeVariable_Build( void* feVariable, void* data ) {
-	OperatorFeVariable*	self = (OperatorFeVariable*) feVariable;
-	Index						feVariable_I;
-	Stream*					errorStream = Journal_Register( Error_Type, (Name)self->type  );
-
-   _FeVariable_Build( self, data );
-   
-	for ( feVariable_I = 0 ; feVariable_I < self->feVariableCount ; feVariable_I++ ) 
-		Stg_Component_Build( self->feVariableList[ feVariable_I ] , data, False );
-
-	if ( !self->_operator){
-		/* Check if we are using a gradient operator */
-		if ( strcasecmp( self->operatorName, "gradient" ) == 0 ) {
-			self->useGradient = True;
-			assert( self->feVariableCount == 1 );
-			self->fieldComponentCount = self->feVariableList[0]->fieldComponentCount * self->dim;
-		}
-		else {
-			/* just use normal operator */
-			self->useGradient = False;
-			/* Added 5 May 2006 by P Sunter: in the case of VectorScale, the fieldComponentCount should be based
-			on the 2nd operator. Also make sure the 2nd operator has at least as may dofs per node as the first. */
-			if ( self->feVariableCount == 2 ) {
-				Journal_Firewall( self->feVariableList[1]->fieldComponentCount >= self->feVariableList[0]->fieldComponentCount,
-					errorStream, "Error - in %s: tried to create a %s operator from feVariables \"%s\" "
-					"and \"%s\" - who have fieldCounts %d and %d - unsupported since operations "
-					"such as VectorScale require the 2nd feVariable to have >= the first's field count.\n",
-					__func__, self->operatorName, self->feVariableList[0]->name, self->feVariableList[1]->name,
-					self->feVariableList[0]->fieldComponentCount, self->feVariableList[1]->fieldComponentCount );
-				self->_operator  = Operator_NewFromName( self->operatorName, self->feVariableList[1]->fieldComponentCount,
-					self->dim );
-			}
-			else {	
-				self->_operator  = Operator_NewFromName( self->operatorName, self->feVariableList[0]->fieldComponentCount,
-					self->dim );
-			}
-	
-			self->fieldComponentCount = self->_operator->resultDofs; /* reset this value from that which is from operator */
-		}
-	}
-	else {
-		self->useGradient = False;
-		self->fieldComponentCount = self->_operator->resultDofs; /* reset this value from that which is from operator */
-	}		
-		
-	_OperatorFeVariable_SetFunctions( self );
-}
-
-void _OperatorFeVariable_Initialise( void* feVariable, void* data ) {
-	OperatorFeVariable*     self = (OperatorFeVariable*) feVariable;
-	DomainContext*          context = self->context;
-	Index                   feVariable_I;
-	Dictionary_Entry_Value* feVarsList = NULL;
-
-	for ( feVariable_I = 0 ; feVariable_I < self->feVariableCount ; feVariable_I++ ) 
-		Stg_Component_Initialise( self->feVariableList[ feVariable_I ] , data, False );
-
-   /* also include check to see if this fevariable should be checkpointed, just incase it didn't go through the fieldvariable construct phase */ 
-   feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"fieldVariablesToCheckpoint" );
-   if ( NULL == feVarsList  ) {
-      feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"FieldVariablesToCheckpoint" );
-   }
-   if (feVarsList != NULL ) {
-      Index                    listLength = Dictionary_Entry_Value_GetCount( feVarsList );
-      Index                    var_I = 0;
-      Dictionary_Entry_Value*  feVarDictValue = NULL;
-      char*                    fieldVariableName;
-   
-      for ( var_I = 0; var_I < listLength; var_I++  ) {
-         feVarDictValue = Dictionary_Entry_Value_GetElement( feVarsList, var_I );
-         fieldVariableName = Dictionary_Entry_Value_AsString( feVarDictValue ); 
-         if ( 0 == strcmp( self->name, fieldVariableName ) ) {
-            self->isCheckpointedAndReloaded = True;
-            break;
-         }
-      }
-   }
-
-   feVarsList = NULL;
-   /** also include check to see if this fevariable should be saved for analysis purposes */ 
-   feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"fieldVariablesToSave" );
-   if ( NULL == feVarsList  ) {
-      feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"FieldVariablesToSave" );
-   }
-   if (feVarsList != NULL ) {
-      Index                    listLength = Dictionary_Entry_Value_GetCount( feVarsList );
-      Index                    var_I = 0;
-      Dictionary_Entry_Value*  feVarDictValue = NULL;
-      char*                    fieldVariableName;
-   
-      for ( var_I = 0; var_I < listLength; var_I++  ) {
-         feVarDictValue = Dictionary_Entry_Value_GetElement( feVarsList, var_I );
-         fieldVariableName = Dictionary_Entry_Value_AsString( feVarDictValue ); 
-         if ( 0 == strcmp( self->name, fieldVariableName ) ) {
-            self->isSavedData = True;
-            break;
-         }
-      }
-   }
-}
-
-void _OperatorFeVariable_Execute( void* feVariable, void* data ) {}
-
-void _OperatorFeVariable_Destroy( void* feVariable, void* data ) {
-	OperatorFeVariable* self = (OperatorFeVariable*) feVariable;
-
-	Memory_Free( self->feVariableList );
-
-	_FeVariable_Destroy( self, data );
-}
-
-void _OperatorFeVariable_SetFunctions( void* feVariable ) {
-	OperatorFeVariable* self = (OperatorFeVariable*) feVariable;
-	Stream*             error = Journal_Register( Error_Type, (Name)self->type );
-
-	if ( self->useGradient  ) {
-		Journal_Firewall( self->feVariableCount == 1, error, "Cannot use gradient operators for multiple variables.\n" );
-		self->_interpolateWithinElement = OperatorFeVariable_GradientInterpolationFunc;
-		self->_getValueAtNode = OperatorFeVariable_GradientValueAtNodeFunc;
-	}
-	else {
-		switch ( self->feVariableCount ) {
-			case 1:
-				self->_interpolateWithinElement = OperatorFeVariable_UnaryInterpolationFunc; 
-				self->_getValueAtNode = OperatorFeVariable_UnaryValueAtNodeFunc; break;
-			case 2:
-				self->_interpolateWithinElement = OperatorFeVariable_BinaryInterpolationFunc; 
-				self->_getValueAtNode = OperatorFeVariable_BinaryValueAtNodeFunc; break;
-			default: {
-				Journal_Firewall( False, error,
-						"Cannot use '%s' with feVariableCount = %u.\n", __func__, self->feVariableCount );
-			}
-		}
-	}
-}
-void _OperatorFeVariable_InterpolateWithinElement( void* feVariable, Element_DomainIndex dElement_I, Coord coord, double* value ) {
-	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
-
-	_OperatorFeVariable_SetFunctions( self );
-	FeVariable_InterpolateWithinElement( self, dElement_I, coord, value );
-}
-
-void _OperatorFeVariable_GetValueAtNode( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
-	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
-
-	_OperatorFeVariable_SetFunctions( self );
-	FeVariable_GetValueAtNode( self, dNode_I, value );
-}
-
-void _OperatorFeVariable_SyncShadowValues( void* feVariable ) {
-	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
-	int v_i;
-
-	assert( self );
-	for( v_i = 0; v_i < self->feVariableCount; v_i++ )
-		FeVariable_SyncShadowValues( self->feVariableList[v_i] );
-	self->shadowValuesSynchronised = True;
-}
-
-
-/** Private Functions */
-Bool _OperatorFeVariable_CheckIfValidToInterpolateInShadowSpace( OperatorFeVariable* self ){
-	int                     feVar_I;
-	FeVariable*             currFeVar;
-	Bool                    parentIsValid;
-
-	for ( feVar_I=0; feVar_I < self->feVariableCount; feVar_I++ ) {
-		currFeVar = self->feVariableList[feVar_I];
-		if( Stg_Class_IsInstance( currFeVar, FeVariable_Type ) ) {
-			if ( False == currFeVar->shadowValuesSynchronised ) {
-        	        	return False;
-        	}
-			else {
-				return True;
-			}
-		}
-		else {
-			parentIsValid = _OperatorFeVariable_CheckIfValidToInterpolateInShadowSpace(
-				(OperatorFeVariable*)currFeVar );
-			if ( False == parentIsValid ) {
-				return False;
-			}
-		} 
-	}
-
-	return True;
-}
-
-
-/** Needed to over-ride the standard _FeVariable_InterpolateValueAt() since for operator fe variables, as long as the
-base fe variable has been shadowed, this operatorFeVar can be calculated in shadow space */
-InterpolationResult _OperatorFeVariable_InterpolateValueAt( void* variable, Coord globalCoord, double* value ) {
-	OperatorFeVariable*     self = (OperatorFeVariable*)variable;
-	Element_DomainIndex     elementCoordIn = (unsigned)-1;
-	Coord                   elLocalCoord={0,0,0};
-	InterpolationResult     retValue;
-	Bool                    validToInterpolateInShadowSpace;
-
-
-	retValue = FeVariable_GetElementLocalCoordAtGlobalCoord( self, globalCoord, elLocalCoord, &elementCoordIn );
-
-	if ( retValue == LOCAL ) {
-		/* Now interpolate the value at that coordinate, using shape functions */
-		self->_interpolateWithinElement( self, elementCoordIn, elLocalCoord, value );
-	}
-	else if ( retValue == SHADOW ) {
-		validToInterpolateInShadowSpace = _OperatorFeVariable_CheckIfValidToInterpolateInShadowSpace(self);	
-			
-		if ( False == validToInterpolateInShadowSpace ) {
-			Stream* warningStr = Journal_Register( Error_Type, (Name)self->type  );
-			Journal_Printf( warningStr, "Warning - in %s, for OperatorFeVar \"%s\": user asking to "
-				"interpolate a value at "
-				"coord (%g,%g,%g), which is in shadow space, but "
-				"FeVariable_SyncShadowValues() hasn't been called on FeVariables this one is "
-				"derived from yet.\n",
-				__func__, self->name, globalCoord[0], globalCoord[1], globalCoord[2] );
-			return retValue;
-		}
-		/* Now interpolate the value at that coordinate, using shape functions */
-		self->_interpolateWithinElement( self, elementCoordIn, elLocalCoord, value );
-	}
-
-	return retValue;
-}
-
-
-
-void OperatorFeVariable_UnaryInterpolationFunc( void* feVariable, Element_DomainIndex dElement_I, Coord localCoord, double* value ) {
-	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
-	FeVariable*         field0          = self->feVariableList[0];
-	double              fieldValue0[ MAX_FIELD_COMPONENTS ]; 
-
-	field0->_interpolateWithinElement( field0, dElement_I, localCoord, fieldValue0 );
-	Operator_CarryOutUnaryOperation( self->_operator, fieldValue0, value );
-
-#ifdef DEBUG
-	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-		Dimension_Index dim_I;
-		Dof_Index       dof_I;
-		Journal_DPrintf( self->debug, "%s Unary Op: El %d, xi = ( ", self->name, dElement_I );
-		for ( dim_I = 0 ; dim_I < self->dim ; dim_I++ ) 
-			Journal_DPrintf( self->debug, "%g ", localCoord[ dim_I ] );
-
-		/* Field 0 */
-		Journal_DPrintf( self->debug, ") - %s = [ ", field0->name );
-		for ( dof_I = 0 ; dof_I < field0->fieldComponentCount ; dof_I++ ) 
-			Journal_DPrintf( self->debug, "%g ", fieldValue0[ dof_I ] );
-
-		/* Result */
-		Journal_DPrintf( self->debug, "] - Result = [ " );
-		for ( dof_I = 0 ; dof_I < self->fieldComponentCount ; dof_I++ ) 
-			Journal_DPrintf( self->debug, "%g ", value[ dof_I ] );
-		Journal_DPrintf( self->debug, "]\n" );
-	}
-#endif
-	
-}
-
-void OperatorFeVariable_BinaryInterpolationFunc( void* feVariable, Element_DomainIndex dElement_I, Coord localCoord, double* value ) {
-	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
-	FeVariable*         field0          = self->feVariableList[0];
-	FeVariable*         field1          = self->feVariableList[1];
-	FeMesh*             mesh            = self->feMesh;
-	double              fieldValue0[ MAX_FIELD_COMPONENTS ]; 
-	double              fieldValue1[ MAX_FIELD_COMPONENTS ]; 
-	
-	FeVariable_InterpolateFromMeshLocalCoord( field0, mesh, dElement_I, localCoord, fieldValue0 );
-	FeVariable_InterpolateFromMeshLocalCoord( field1, mesh, dElement_I, localCoord, fieldValue1 );
-	
-	Operator_CarryOutBinaryOperation( self->_operator, fieldValue0, fieldValue1, value );
-
-#ifdef DEBUG
-	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-		Dimension_Index dim_I;
-		Dof_Index       dof_I;
-		Journal_DPrintf( self->debug, "%s Binary Op: El %d, xi = ( ", self->name, dElement_I );
-		for ( dim_I = 0 ; dim_I < self->dim ; dim_I++ ) 
-			Journal_DPrintf( self->debug, "%g ", localCoord[ dim_I ] );
-
-		/* Field 0 */
-		Journal_DPrintf( self->debug, ") - %s = [ ", field0->name );
-		for ( dof_I = 0 ; dof_I < field0->fieldComponentCount ; dof_I++ ) 
-			Journal_DPrintf( self->debug, "%g ", fieldValue0[ dof_I ] );
-
-		/* Field 1 */
-		Journal_DPrintf( self->debug, "] - %s = [ ", field1->name );
-		for ( dof_I = 0 ; dof_I < field1->fieldComponentCount ; dof_I++ ) 
-			Journal_DPrintf( self->debug, "%g ", fieldValue1[ dof_I ] );
-
-		/* Result */
-		Journal_DPrintf( self->debug, "] - Result = [ " );
-		for ( dof_I = 0 ; dof_I < self->fieldComponentCount ; dof_I++ ) 
-			Journal_DPrintf( self->debug, "%g ", value[ dof_I ] );
-		Journal_DPrintf( self->debug, "]\n" );
-	}
-#endif
-}
-
-void OperatorFeVariable_GradientInterpolationFunc( void* feVariable, Element_DomainIndex dElement_I, Coord localCoord, double* value ) {
-	OperatorFeVariable* self = (OperatorFeVariable*) feVariable;
-	FeVariable*         field0 = self->feVariableList[0];
-	
-	FeVariable_InterpolateDerivativesToElLocalCoord( field0, dElement_I, localCoord, value );
-}
-
-void OperatorFeVariable_UnaryValueAtNodeFunc( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
-	OperatorFeVariable* self = (OperatorFeVariable*) feVariable;
-	FeVariable*         field0 = self->feVariableList[0];
-	double              fieldValue0[ MAX_FIELD_COMPONENTS ]; 
-	
-	FeVariable_GetValueAtNode( field0, dNode_I, fieldValue0 );
-	Operator_CarryOutUnaryOperation( self->_operator, fieldValue0, value );
-}
-
-void OperatorFeVariable_BinaryValueAtNodeFunc( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
-	OperatorFeVariable*	self = (OperatorFeVariable*) feVariable;
-	FeVariable*				field0 = self->feVariableList[0];
-	FeVariable*				field1 = self->feVariableList[1];
-	double					fieldValue0[ MAX_FIELD_COMPONENTS ]; 
-	double					fieldValue1[ MAX_FIELD_COMPONENTS ]; 
-	double*					coord;
-	Element_DomainIndex	field0Element;
-	Element_DomainIndex	field1Element;
-	Coord						field0LocalCoord;
-	Coord						field1LocalCoord;
-
-	if( field0->feMesh == self->feMesh && field1->feMesh == self->feMesh ) {
-		FeVariable_GetValueAtNode( field0, dNode_I, fieldValue0 );
-		FeVariable_GetValueAtNode( field1, dNode_I, fieldValue1 );
-	}
-	/* field variables are using different meshes, so interpolate the values of each based on the global coord */
-	else {  
-		coord = Mesh_GetVertex( self->feMesh, dNode_I );
-		assert( Mesh_SearchElements( field0->feMesh, coord, &field0Element ) );
-		FeMesh_CoordGlobalToLocal( field0->feMesh, field0Element, coord, field0LocalCoord );
-		FeVariable_InterpolateWithinElement( field0, field0Element, field0LocalCoord, fieldValue0 );
-		
-		assert( Mesh_SearchElements( field1->feMesh, coord, &field1Element ) ); 
-		FeMesh_CoordGlobalToLocal( field1->feMesh, field1Element, coord, field1LocalCoord );
-		FeVariable_InterpolateWithinElement( field1, field1Element, field1LocalCoord, fieldValue1 );
-	}
-	Operator_CarryOutBinaryOperation( self->_operator, fieldValue0, fieldValue1, value );
-}
-
-void OperatorFeVariable_GradientValueAtNodeFunc( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
-	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
-	Mesh*               mesh            = (Mesh*) self->feMesh;
-	double*             coord;
-
-	coord = Mesh_GetVertex( mesh, dNode_I );
-
-	memset( value, 0, self->fieldComponentCount * sizeof(double) );
-	FeVariable_InterpolateDerivativesAt( self->feVariableList[0], coord, value );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/OperatorFeVariable.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/OperatorFeVariable.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,685 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: OperatorFeVariable.c 1137 2008-05-23 05:57:48Z RobertTurnbull $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "types.h"
+#include "FeVariable.h"
+#include "OperatorFeVariable.h"
+#include "FeMesh.h"
+
+#include <assert.h>
+
+const Type OperatorFeVariable_Type = "OperatorFeVariable";
+
+OperatorFeVariable* OperatorFeVariable_NewUnary(
+	Name				name,
+	DomainContext*	context,
+	void*				_feVariable,
+	Name				operatorName )
+{
+	FeVariable*	feVariable = (FeVariable*) _feVariable;
+	Stream*		errorStream = Journal_Register( Error_Type, (Name)OperatorFeVariable_Type  );
+
+	Journal_Firewall( feVariable != NULL, errorStream, "In func %s: Trying to operate on NULL field.\n", __func__ );
+       	
+	return OperatorFeVariable_New( 
+		name,
+		context,
+		feVariable->feMesh,
+  		feVariable->geometryMesh,
+  		feVariable->dofLayout,                                                                                 
+  		feVariable->bcs,
+  		feVariable->ics,
+  		feVariable->linkedDofInfo,
+  		feVariable->templateFeVariable,    
+		OperatorFeVariable_UnaryInterpolationFunc, 
+		OperatorFeVariable_UnaryValueAtNodeFunc,
+		operatorName,
+		NULL,
+		1,
+		&feVariable, 
+		feVariable->dim,
+		feVariable->isCheckpointedAndReloaded,
+		feVariable->communicator,
+		feVariable->fieldVariable_Register );
+}
+
+OperatorFeVariable* OperatorFeVariable_NewUnary_OwnOperator(
+	Name				name,
+	DomainContext*	context,
+	void*				_feVariable,
+	Operator*		ownOperator )
+{
+	FeVariable*	feVariable = (FeVariable*) _feVariable;
+	Stream*		errorStream = Journal_Register( Error_Type, (Name)OperatorFeVariable_Type  );
+
+	Journal_Firewall( feVariable != NULL, errorStream, "In func %s: Trying to operate on NULL field.\n", __func__ );
+       	
+	return OperatorFeVariable_New( 
+		name,
+		context,
+		feVariable->feMesh,
+  		feVariable->geometryMesh,
+  		feVariable->dofLayout,                                                                                 
+  		feVariable->bcs,
+  		feVariable->ics,
+  		feVariable->linkedDofInfo,
+  		feVariable->templateFeVariable,    
+		OperatorFeVariable_UnaryInterpolationFunc, 
+		OperatorFeVariable_UnaryValueAtNodeFunc,
+		ownOperator->name,
+		ownOperator,
+		1,
+		&feVariable, 
+		feVariable->dim,
+		feVariable->isCheckpointedAndReloaded,
+		feVariable->communicator,
+		feVariable->fieldVariable_Register );
+}
+
+OperatorFeVariable* OperatorFeVariable_NewBinary(
+	Name				name,
+	DomainContext*	context,
+	void*				_feVariable1,
+	void*				_feVariable2,
+	Name				operatorName )
+{
+	FeVariable*	feVariableList[2];
+	Stream*		errorStream = Journal_Register( Error_Type, (Name)OperatorFeVariable_Type  );
+	
+	Journal_Firewall( _feVariable1 != NULL, errorStream, "In func %s: First field to operate on is NULL.\n", __func__ );
+	Journal_Firewall( _feVariable2 != NULL, errorStream, "In func %s: Second field to operate on is NULL.\n", __func__ );
+       
+	feVariableList[0] = (FeVariable*) _feVariable1;
+	feVariableList[1] = (FeVariable*) _feVariable2;
+	
+	return OperatorFeVariable_New( 
+		name,
+		context,
+		feVariableList[0]->feMesh,
+  		feVariableList[0]->geometryMesh,
+  		feVariableList[0]->dofLayout,                                                                                 
+  		feVariableList[0]->bcs,
+  		feVariableList[0]->ics,
+  		feVariableList[0]->linkedDofInfo,
+  		feVariableList[0]->templateFeVariable,    
+		OperatorFeVariable_BinaryInterpolationFunc, 
+		OperatorFeVariable_BinaryValueAtNodeFunc,
+		operatorName,
+		NULL,
+		2, 
+		feVariableList, 
+		feVariableList[0]->dim,
+		feVariableList[0]->isCheckpointedAndReloaded,
+		feVariableList[0]->communicator,
+		feVariableList[0]->fieldVariable_Register );
+}
+
+OperatorFeVariable* OperatorFeVariable_New( 
+	Name														name,
+	DomainContext*											context,
+	void*														feMesh,
+  	void*														geometryMesh,
+  	DofLayout*												dofLayout,                                                                                 
+  	void*														bcs,
+  	void*														ics,
+  	void*														linkedDofInfo,
+  	void*														templateFeVariable,    
+	FeVariable_InterpolateWithinElementFunction*	interpolateWithinElement,
+	FeVariable_GetValueAtNodeFunction*				getValueAtNode,
+	Name														operatorName,
+	Operator*                                    ownOperator,
+	Index														feVariableCount,
+	FeVariable**											feVariableList,
+	Dimension_Index										dim,
+	Bool														isCheckpointedAndReloaded,
+	MPI_Comm													communicator,
+	FieldVariable_Register*								fieldVariable_Register )
+{
+  OperatorFeVariable* self = (OperatorFeVariable*)_OperatorFeVariable_DefaultNew( name );
+
+	self->isConstructed = True;
+	_FieldVariable_Init( (FieldVariable*)self, context, feVariableCount, dim, isCheckpointedAndReloaded, communicator, fieldVariable_Register );                                                                                                          
+   _FeVariable_Init( (FeVariable*)self, feMesh, geometryMesh, dofLayout, bcs, ics, linkedDofInfo, templateFeVariable, True, False );
+	_OperatorFeVariable_Init( self, operatorName, feVariableCount, feVariableList, ownOperator );
+
+	return self;
+}
+
+void* _OperatorFeVariable_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                         _sizeOfSelf = sizeof(OperatorFeVariable);
+	Type                                                                 type = OperatorFeVariable_Type;
+	Stg_Class_DeleteFunction*                                         _delete = _OperatorFeVariable_Delete;
+	Stg_Class_PrintFunction*                                           _print = _OperatorFeVariable_Print;
+	Stg_Class_CopyFunction*                                             _copy = _OperatorFeVariable_Copy;
+	Stg_Component_DefaultConstructorFunction*             _defaultConstructor = (Stg_Component_DefaultConstructorFunction*)_OperatorFeVariable_DefaultNew;
+	Stg_Component_ConstructFunction*                               _construct = _OperatorFeVariable_AssignFromXML;
+	Stg_Component_BuildFunction*                                       _build = _OperatorFeVariable_Build;
+	Stg_Component_InitialiseFunction*                             _initialise = _OperatorFeVariable_Initialise;
+	Stg_Component_ExecuteFunction*                                   _execute = _OperatorFeVariable_Execute;
+	Stg_Component_DestroyFunction*                                   _destroy = _OperatorFeVariable_Destroy;
+	AllocationType                                         nameAllocationType = NON_GLOBAL;
+	FieldVariable_InterpolateValueAtFunction*             _interpolateValueAt = _OperatorFeVariable_InterpolateValueAt;
+	FieldVariable_GetValueFunction*               _getMinGlobalFieldMagnitude = _FeVariable_GetMinGlobalFieldMagnitude;
+	FieldVariable_GetValueFunction*               _getMaxGlobalFieldMagnitude = _FeVariable_GetMaxGlobalFieldMagnitude;
+	FieldVariable_GetCoordFunction*                  _getMinAndMaxLocalCoords = _FeVariable_GetMinAndMaxLocalCoords;
+	FieldVariable_GetCoordFunction*                 _getMinAndMaxGlobalCoords = _FeVariable_GetMinAndMaxGlobalCoords;
+	FeVariable_InterpolateWithinElementFunction*    _interpolateWithinElement = _OperatorFeVariable_InterpolateWithinElement;
+	FeVariable_GetValueAtNodeFunction*                        _getValueAtNode = _OperatorFeVariable_GetValueAtNode;
+	FeVariable_SyncShadowValuesFunc*                        _syncShadowValues = _OperatorFeVariable_SyncShadowValues;
+
+	return _OperatorFeVariable_New(  OPERATORFEVARIABLE_PASSARGS  ); /* feVariableList_renamed */
+}
+
+OperatorFeVariable* _OperatorFeVariable_New(  OPERATORFEVARIABLE_DEFARGS  ) {
+	OperatorFeVariable* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(OperatorFeVariable) );
+	self = (OperatorFeVariable*) _FeVariable_New(  FEVARIABLE_PASSARGS  );
+
+	return self;
+}
+
+void _OperatorFeVariable_Init( void* oFeVar, Name operatorName, Index feVariableCount, FeVariable** feVariableList, Operator* ownOperator ) {
+	OperatorFeVariable*	self = (OperatorFeVariable*) oFeVar;
+	FeVariable*				feVariable;
+	Index						feVariable_I;
+	Stream*					errorStream = Journal_Register( Error_Type, (Name)self->type  );
+
+	/* Assign values to object */
+	self->feVariableCount = feVariableCount;
+	self->operatorName =operatorName;
+	self->_operator = ownOperator;
+
+	/* Copy field variable list */
+	self->feVariableList = Memory_Alloc_Array( FeVariable*, feVariableCount, "Array of Field Variables" );
+	memcpy( self->feVariableList, feVariableList, feVariableCount * sizeof( FeVariable* ) );
+
+	for ( feVariable_I = 0 ; feVariable_I < feVariableCount ; feVariable_I++ ) {
+		feVariable = feVariableList[ feVariable_I ];
+		Journal_Firewall( feVariable != NULL,
+				errorStream, "In func %s: Field Variable %u in list is NULL.\n", __func__, feVariable_I );
+		Journal_Firewall( feVariable->fieldComponentCount <= MAX_FIELD_COMPONENTS,
+				errorStream, "In func %s: Field Variable '%s' has too many components.\n", __func__, feVariable->name );
+	}
+}
+
+void _OperatorFeVariable_Delete( void* _feVariable ) {
+	OperatorFeVariable* self = (OperatorFeVariable*) _feVariable;
+
+	_FeVariable_Delete( self );
+}
+
+void _OperatorFeVariable_Print( void* _feVariable, Stream* stream ) {
+	OperatorFeVariable* self = (OperatorFeVariable*) _feVariable;
+	Index               feVariable_I;
+
+	_FeVariable_Print( self, stream );
+
+	Journal_PrintValue( stream, self->feVariableCount );
+	for ( feVariable_I = 0 ; feVariable_I < self->feVariableCount ; feVariable_I++ ) 
+		Journal_Printf( stream, "\tFeVariable %u - '%s'\n", feVariable_I, self->feVariableList[ feVariable_I ]->name );
+
+}
+
+void* _OperatorFeVariable_Copy( const void* feVariable, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	OperatorFeVariable*	self = (OperatorFeVariable*)feVariable;
+	OperatorFeVariable*	newOperatorFeVariable;
+	
+	newOperatorFeVariable = (OperatorFeVariable*)_FeVariable_Copy( self, dest, deep, nameExt, ptrMap );
+	
+	newOperatorFeVariable->_operator = self->_operator;
+	newOperatorFeVariable->feVariableCount = self->feVariableCount;
+	
+	if (deep) {
+		newOperatorFeVariable->feVariableList = Memory_Alloc_Array( FeVariable*, self->feVariableCount, "Array of Field Variables" );
+		memcpy( newOperatorFeVariable->feVariableList, self->feVariableList, self->feVariableCount * sizeof( FeVariable* ) );
+	}
+	else 
+		newOperatorFeVariable->feVariableList = self->feVariableList;
+	
+	return (void*)newOperatorFeVariable;
+}
+
+void _OperatorFeVariable_AssignFromXML( void* feVariable, Stg_ComponentFactory* cf, void* data ) {
+	OperatorFeVariable*     self = (OperatorFeVariable*) feVariable;
+	Dictionary*             dictionary = Dictionary_GetDictionary( cf->componentDict, self->name );
+	Dictionary_Entry_Value* list;
+	Index                   feVariableCount = 0;
+	Index                   feVariable_I;
+	FieldVariable_Register* fV_Register;     
+	Name                    feVariableName;
+	Name                    operatorName;
+	FeVariable**            feVariableList;
+	
+	/* Construct Parent */
+	_FieldVariable_AssignFromXML( self, cf, data );
+
+	fV_Register = self->context->fieldVariable_Register;
+
+	operatorName = Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"Operator", ""  );
+
+	list = Dictionary_Get( dictionary, (Dictionary_Entry_Key)"FeVariables" );
+	
+	feVariableCount = ( list ? Dictionary_Entry_Value_GetCount(list) : 1  );
+	feVariableList = Memory_Alloc_Array( FeVariable*, feVariableCount, "FeVars" );
+
+	for ( feVariable_I = 0 ; feVariable_I < feVariableCount ; feVariable_I++ ) {
+		feVariableName = (list ?  Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( list, feVariable_I ) ) :
+			Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"FeVariable" )  );
+
+		/* Check in fV_Register first before assuming in LiveComponentRegister */
+		Journal_PrintfL( cf->infoStream, 2, "Looking for FeVariable '%s' in fieldVariable_Register.\n", feVariableName );
+		feVariableList[feVariable_I] = (FeVariable*) FieldVariable_Register_GetByName( fV_Register, feVariableName );
+		
+		if ( !feVariableList[feVariable_I] )
+			feVariableList[feVariable_I] = 
+		Stg_ComponentFactory_ConstructByName( cf, (Name)feVariableName, FeVariable, True, data ); 
+	}
+
+	_FeVariable_Init( (FeVariable* ) self, feVariableList[0]->feMesh, feVariableList[0]->geometryMesh, feVariableList[0]->dofLayout, NULL, NULL, NULL, NULL, True, False );
+	_OperatorFeVariable_Init( self, operatorName, feVariableCount, feVariableList, NULL );
+
+	Memory_Free( feVariableList );
+}
+
+void _OperatorFeVariable_Build( void* feVariable, void* data ) {
+	OperatorFeVariable*	self = (OperatorFeVariable*) feVariable;
+	Index						feVariable_I;
+	Stream*					errorStream = Journal_Register( Error_Type, (Name)self->type  );
+
+   _FeVariable_Build( self, data );
+   
+	for ( feVariable_I = 0 ; feVariable_I < self->feVariableCount ; feVariable_I++ ) 
+		Stg_Component_Build( self->feVariableList[ feVariable_I ] , data, False );
+
+	if ( !self->_operator){
+		/* Check if we are using a gradient operator */
+		if ( strcasecmp( self->operatorName, "gradient" ) == 0 ) {
+			self->useGradient = True;
+			assert( self->feVariableCount == 1 );
+			self->fieldComponentCount = self->feVariableList[0]->fieldComponentCount * self->dim;
+		}
+		else {
+			/* just use normal operator */
+			self->useGradient = False;
+			/* Added 5 May 2006 by P Sunter: in the case of VectorScale, the fieldComponentCount should be based
+			on the 2nd operator. Also make sure the 2nd operator has at least as may dofs per node as the first. */
+			if ( self->feVariableCount == 2 ) {
+				Journal_Firewall( self->feVariableList[1]->fieldComponentCount >= self->feVariableList[0]->fieldComponentCount,
+					errorStream, "Error - in %s: tried to create a %s operator from feVariables \"%s\" "
+					"and \"%s\" - who have fieldCounts %d and %d - unsupported since operations "
+					"such as VectorScale require the 2nd feVariable to have >= the first's field count.\n",
+					__func__, self->operatorName, self->feVariableList[0]->name, self->feVariableList[1]->name,
+					self->feVariableList[0]->fieldComponentCount, self->feVariableList[1]->fieldComponentCount );
+				self->_operator  = Operator_NewFromName( self->operatorName, self->feVariableList[1]->fieldComponentCount,
+					self->dim );
+			}
+			else {	
+				self->_operator  = Operator_NewFromName( self->operatorName, self->feVariableList[0]->fieldComponentCount,
+					self->dim );
+			}
+	
+			self->fieldComponentCount = self->_operator->resultDofs; /* reset this value from that which is from operator */
+		}
+	}
+	else {
+		self->useGradient = False;
+		self->fieldComponentCount = self->_operator->resultDofs; /* reset this value from that which is from operator */
+	}		
+		
+	_OperatorFeVariable_SetFunctions( self );
+}
+
+void _OperatorFeVariable_Initialise( void* feVariable, void* data ) {
+	OperatorFeVariable*     self = (OperatorFeVariable*) feVariable;
+	DomainContext*          context = self->context;
+	Index                   feVariable_I;
+	Dictionary_Entry_Value* feVarsList = NULL;
+
+	for ( feVariable_I = 0 ; feVariable_I < self->feVariableCount ; feVariable_I++ ) 
+		Stg_Component_Initialise( self->feVariableList[ feVariable_I ] , data, False );
+
+   /* also include check to see if this fevariable should be checkpointed, just incase it didn't go through the fieldvariable construct phase */ 
+   feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"fieldVariablesToCheckpoint" );
+   if ( NULL == feVarsList  ) {
+      feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"FieldVariablesToCheckpoint" );
+   }
+   if (feVarsList != NULL ) {
+      Index                    listLength = Dictionary_Entry_Value_GetCount( feVarsList );
+      Index                    var_I = 0;
+      Dictionary_Entry_Value*  feVarDictValue = NULL;
+      char*                    fieldVariableName;
+   
+      for ( var_I = 0; var_I < listLength; var_I++  ) {
+         feVarDictValue = Dictionary_Entry_Value_GetElement( feVarsList, var_I );
+         fieldVariableName = Dictionary_Entry_Value_AsString( feVarDictValue ); 
+         if ( 0 == strcmp( self->name, fieldVariableName ) ) {
+            self->isCheckpointedAndReloaded = True;
+            break;
+         }
+      }
+   }
+
+   feVarsList = NULL;
+   /** also include check to see if this fevariable should be saved for analysis purposes */ 
+   feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"fieldVariablesToSave" );
+   if ( NULL == feVarsList  ) {
+      feVarsList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)"FieldVariablesToSave" );
+   }
+   if (feVarsList != NULL ) {
+      Index                    listLength = Dictionary_Entry_Value_GetCount( feVarsList );
+      Index                    var_I = 0;
+      Dictionary_Entry_Value*  feVarDictValue = NULL;
+      char*                    fieldVariableName;
+   
+      for ( var_I = 0; var_I < listLength; var_I++  ) {
+         feVarDictValue = Dictionary_Entry_Value_GetElement( feVarsList, var_I );
+         fieldVariableName = Dictionary_Entry_Value_AsString( feVarDictValue ); 
+         if ( 0 == strcmp( self->name, fieldVariableName ) ) {
+            self->isSavedData = True;
+            break;
+         }
+      }
+   }
+}
+
+void _OperatorFeVariable_Execute( void* feVariable, void* data ) {}
+
+void _OperatorFeVariable_Destroy( void* feVariable, void* data ) {
+	OperatorFeVariable* self = (OperatorFeVariable*) feVariable;
+
+	Memory_Free( self->feVariableList );
+
+	_FeVariable_Destroy( self, data );
+}
+
+void _OperatorFeVariable_SetFunctions( void* feVariable ) {
+	OperatorFeVariable* self = (OperatorFeVariable*) feVariable;
+	Stream*             error = Journal_Register( Error_Type, (Name)self->type );
+
+	if ( self->useGradient  ) {
+		Journal_Firewall( self->feVariableCount == 1, error, "Cannot use gradient operators for multiple variables.\n" );
+		self->_interpolateWithinElement = OperatorFeVariable_GradientInterpolationFunc;
+		self->_getValueAtNode = OperatorFeVariable_GradientValueAtNodeFunc;
+	}
+	else {
+		switch ( self->feVariableCount ) {
+			case 1:
+				self->_interpolateWithinElement = OperatorFeVariable_UnaryInterpolationFunc; 
+				self->_getValueAtNode = OperatorFeVariable_UnaryValueAtNodeFunc; break;
+			case 2:
+				self->_interpolateWithinElement = OperatorFeVariable_BinaryInterpolationFunc; 
+				self->_getValueAtNode = OperatorFeVariable_BinaryValueAtNodeFunc; break;
+			default: {
+				Journal_Firewall( False, error,
+						"Cannot use '%s' with feVariableCount = %u.\n", __func__, self->feVariableCount );
+			}
+		}
+	}
+}
+void _OperatorFeVariable_InterpolateWithinElement( void* feVariable, Element_DomainIndex dElement_I, Coord coord, double* value ) {
+	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
+
+	_OperatorFeVariable_SetFunctions( self );
+	FeVariable_InterpolateWithinElement( self, dElement_I, coord, value );
+}
+
+void _OperatorFeVariable_GetValueAtNode( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
+	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
+
+	_OperatorFeVariable_SetFunctions( self );
+	FeVariable_GetValueAtNode( self, dNode_I, value );
+}
+
+void _OperatorFeVariable_SyncShadowValues( void* feVariable ) {
+	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
+	int v_i;
+
+	assert( self );
+	for( v_i = 0; v_i < self->feVariableCount; v_i++ )
+		FeVariable_SyncShadowValues( self->feVariableList[v_i] );
+	self->shadowValuesSynchronised = True;
+}
+
+
+/** Private Functions */
+Bool _OperatorFeVariable_CheckIfValidToInterpolateInShadowSpace( OperatorFeVariable* self ){
+	int                     feVar_I;
+	FeVariable*             currFeVar;
+	Bool                    parentIsValid;
+
+	for ( feVar_I=0; feVar_I < self->feVariableCount; feVar_I++ ) {
+		currFeVar = self->feVariableList[feVar_I];
+		if( Stg_Class_IsInstance( currFeVar, FeVariable_Type ) ) {
+			if ( False == currFeVar->shadowValuesSynchronised ) {
+        	        	return False;
+        	}
+			else {
+				return True;
+			}
+		}
+		else {
+			parentIsValid = _OperatorFeVariable_CheckIfValidToInterpolateInShadowSpace(
+				(OperatorFeVariable*)currFeVar );
+			if ( False == parentIsValid ) {
+				return False;
+			}
+		} 
+	}
+
+	return True;
+}
+
+
+/** Needed to over-ride the standard _FeVariable_InterpolateValueAt() since for operator fe variables, as long as the
+base fe variable has been shadowed, this operatorFeVar can be calculated in shadow space */
+InterpolationResult _OperatorFeVariable_InterpolateValueAt( void* variable, Coord globalCoord, double* value ) {
+	OperatorFeVariable*     self = (OperatorFeVariable*)variable;
+	Element_DomainIndex     elementCoordIn = (unsigned)-1;
+	Coord                   elLocalCoord={0,0,0};
+	InterpolationResult     retValue;
+	Bool                    validToInterpolateInShadowSpace;
+
+
+	retValue = FeVariable_GetElementLocalCoordAtGlobalCoord( self, globalCoord, elLocalCoord, &elementCoordIn );
+
+	if ( retValue == LOCAL ) {
+		/* Now interpolate the value at that coordinate, using shape functions */
+		self->_interpolateWithinElement( self, elementCoordIn, elLocalCoord, value );
+	}
+	else if ( retValue == SHADOW ) {
+		validToInterpolateInShadowSpace = _OperatorFeVariable_CheckIfValidToInterpolateInShadowSpace(self);	
+			
+		if ( False == validToInterpolateInShadowSpace ) {
+			Stream* warningStr = Journal_Register( Error_Type, (Name)self->type  );
+			Journal_Printf( warningStr, "Warning - in %s, for OperatorFeVar \"%s\": user asking to "
+				"interpolate a value at "
+				"coord (%g,%g,%g), which is in shadow space, but "
+				"FeVariable_SyncShadowValues() hasn't been called on FeVariables this one is "
+				"derived from yet.\n",
+				__func__, self->name, globalCoord[0], globalCoord[1], globalCoord[2] );
+			return retValue;
+		}
+		/* Now interpolate the value at that coordinate, using shape functions */
+		self->_interpolateWithinElement( self, elementCoordIn, elLocalCoord, value );
+	}
+
+	return retValue;
+}
+
+
+
+void OperatorFeVariable_UnaryInterpolationFunc( void* feVariable, Element_DomainIndex dElement_I, Coord localCoord, double* value ) {
+	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
+	FeVariable*         field0          = self->feVariableList[0];
+	double              fieldValue0[ MAX_FIELD_COMPONENTS ]; 
+
+	field0->_interpolateWithinElement( field0, dElement_I, localCoord, fieldValue0 );
+	Operator_CarryOutUnaryOperation( self->_operator, fieldValue0, value );
+
+#ifdef DEBUG
+	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+		Dimension_Index dim_I;
+		Dof_Index       dof_I;
+		Journal_DPrintf( self->debug, "%s Unary Op: El %d, xi = ( ", self->name, dElement_I );
+		for ( dim_I = 0 ; dim_I < self->dim ; dim_I++ ) 
+			Journal_DPrintf( self->debug, "%g ", localCoord[ dim_I ] );
+
+		/* Field 0 */
+		Journal_DPrintf( self->debug, ") - %s = [ ", field0->name );
+		for ( dof_I = 0 ; dof_I < field0->fieldComponentCount ; dof_I++ ) 
+			Journal_DPrintf( self->debug, "%g ", fieldValue0[ dof_I ] );
+
+		/* Result */
+		Journal_DPrintf( self->debug, "] - Result = [ " );
+		for ( dof_I = 0 ; dof_I < self->fieldComponentCount ; dof_I++ ) 
+			Journal_DPrintf( self->debug, "%g ", value[ dof_I ] );
+		Journal_DPrintf( self->debug, "]\n" );
+	}
+#endif
+	
+}
+
+void OperatorFeVariable_BinaryInterpolationFunc( void* feVariable, Element_DomainIndex dElement_I, Coord localCoord, double* value ) {
+	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
+	FeVariable*         field0          = self->feVariableList[0];
+	FeVariable*         field1          = self->feVariableList[1];
+	FeMesh*             mesh            = self->feMesh;
+	double              fieldValue0[ MAX_FIELD_COMPONENTS ]; 
+	double              fieldValue1[ MAX_FIELD_COMPONENTS ]; 
+	
+	FeVariable_InterpolateFromMeshLocalCoord( field0, mesh, dElement_I, localCoord, fieldValue0 );
+	FeVariable_InterpolateFromMeshLocalCoord( field1, mesh, dElement_I, localCoord, fieldValue1 );
+	
+	Operator_CarryOutBinaryOperation( self->_operator, fieldValue0, fieldValue1, value );
+
+#ifdef DEBUG
+	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+		Dimension_Index dim_I;
+		Dof_Index       dof_I;
+		Journal_DPrintf( self->debug, "%s Binary Op: El %d, xi = ( ", self->name, dElement_I );
+		for ( dim_I = 0 ; dim_I < self->dim ; dim_I++ ) 
+			Journal_DPrintf( self->debug, "%g ", localCoord[ dim_I ] );
+
+		/* Field 0 */
+		Journal_DPrintf( self->debug, ") - %s = [ ", field0->name );
+		for ( dof_I = 0 ; dof_I < field0->fieldComponentCount ; dof_I++ ) 
+			Journal_DPrintf( self->debug, "%g ", fieldValue0[ dof_I ] );
+
+		/* Field 1 */
+		Journal_DPrintf( self->debug, "] - %s = [ ", field1->name );
+		for ( dof_I = 0 ; dof_I < field1->fieldComponentCount ; dof_I++ ) 
+			Journal_DPrintf( self->debug, "%g ", fieldValue1[ dof_I ] );
+
+		/* Result */
+		Journal_DPrintf( self->debug, "] - Result = [ " );
+		for ( dof_I = 0 ; dof_I < self->fieldComponentCount ; dof_I++ ) 
+			Journal_DPrintf( self->debug, "%g ", value[ dof_I ] );
+		Journal_DPrintf( self->debug, "]\n" );
+	}
+#endif
+}
+
+void OperatorFeVariable_GradientInterpolationFunc( void* feVariable, Element_DomainIndex dElement_I, Coord localCoord, double* value ) {
+	OperatorFeVariable* self = (OperatorFeVariable*) feVariable;
+	FeVariable*         field0 = self->feVariableList[0];
+	
+	FeVariable_InterpolateDerivativesToElLocalCoord( field0, dElement_I, localCoord, value );
+}
+
+void OperatorFeVariable_UnaryValueAtNodeFunc( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
+	OperatorFeVariable* self = (OperatorFeVariable*) feVariable;
+	FeVariable*         field0 = self->feVariableList[0];
+	double              fieldValue0[ MAX_FIELD_COMPONENTS ]; 
+	
+	FeVariable_GetValueAtNode( field0, dNode_I, fieldValue0 );
+	Operator_CarryOutUnaryOperation( self->_operator, fieldValue0, value );
+}
+
+void OperatorFeVariable_BinaryValueAtNodeFunc( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
+	OperatorFeVariable*	self = (OperatorFeVariable*) feVariable;
+	FeVariable*				field0 = self->feVariableList[0];
+	FeVariable*				field1 = self->feVariableList[1];
+	double					fieldValue0[ MAX_FIELD_COMPONENTS ]; 
+	double					fieldValue1[ MAX_FIELD_COMPONENTS ]; 
+	double*					coord;
+	Element_DomainIndex	field0Element;
+	Element_DomainIndex	field1Element;
+	Coord						field0LocalCoord;
+	Coord						field1LocalCoord;
+
+	if( field0->feMesh == self->feMesh && field1->feMesh == self->feMesh ) {
+		FeVariable_GetValueAtNode( field0, dNode_I, fieldValue0 );
+		FeVariable_GetValueAtNode( field1, dNode_I, fieldValue1 );
+	}
+	/* field variables are using different meshes, so interpolate the values of each based on the global coord */
+	else {  
+		coord = Mesh_GetVertex( self->feMesh, dNode_I );
+		assert( Mesh_SearchElements( field0->feMesh, coord, &field0Element ) );
+		FeMesh_CoordGlobalToLocal( field0->feMesh, field0Element, coord, field0LocalCoord );
+		FeVariable_InterpolateWithinElement( field0, field0Element, field0LocalCoord, fieldValue0 );
+		
+		assert( Mesh_SearchElements( field1->feMesh, coord, &field1Element ) ); 
+		FeMesh_CoordGlobalToLocal( field1->feMesh, field1Element, coord, field1LocalCoord );
+		FeVariable_InterpolateWithinElement( field1, field1Element, field1LocalCoord, fieldValue1 );
+	}
+	Operator_CarryOutBinaryOperation( self->_operator, fieldValue0, fieldValue1, value );
+}
+
+void OperatorFeVariable_GradientValueAtNodeFunc( void* feVariable, Node_DomainIndex dNode_I, double* value ) {
+	OperatorFeVariable* self            = (OperatorFeVariable*) feVariable;
+	Mesh*               mesh            = (Mesh*) self->feMesh;
+	double*             coord;
+
+	coord = Mesh_GetVertex( mesh, dNode_I );
+
+	memset( value, 0, self->fieldComponentCount * sizeof(double) );
+	FeVariable_InterpolateDerivativesAt( self->feVariableList[0], coord, value );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/P1.c
--- a/Discretisation/src/P1.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: P1.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type P1_Type = "P1";
-
-#define P1_NODECOUNT 3
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-P1* P1_New( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(P1);
-	Type                                                                                    type = P1_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _P1_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _P1_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_P1_New;
-	Stg_Component_ConstructFunction*                                                  _construct = _P1_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _P1_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _P1_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _P1_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _P1_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = P1_EvalBasis;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = P1_EvalLocalDerivs;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = NULL;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _P1_SurfaceNormal;
-
-	return _P1_New(  P1_PASSARGS  );
-}
-
-P1* _P1_New(  P1_DEFARGS  ) {
-	P1* self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(P1) );
-	self = (P1*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-
-	/* Virtual info */
-
-	/* P1 info */
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, P1_NODECOUNT );
-	_P1_Init( self );
-
-	return self;
-}
-
-void _P1_Init( P1* self ) {
-	assert( self && Stg_CheckType( self, P1 ) );
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _P1_Delete( void* elementType ) {
-	P1* self = (P1*)elementType;
-
-	/* Delete the parent. */
-	_ElementType_Delete( self );
-}
-
-void _P1_Print( void* elementType, Stream* stream ) {
-	P1*	self = (P1*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* elementTypeStream;
-	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"P1Stream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "P1 (ptr): (%p)\n", self );
-	_ElementType_Print( self, stream );
-}
-
-void _P1_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
-}
-
-void _P1_Build( void* elementType, void* data ) {
-}
-
-void _P1_Initialise( void* elementType, void* data ) {
-}
-
-void _P1_Execute( void* elementType, void* data ) {
-}
-
-void _P1_Destroy( void* elementType, void* data ) {
-	P1* self = (P1*)elementType;
-
-	_ElementType_Destroy( self, data );	
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void P1_EvalBasis( void* elementType, const double* localCoord, double* basis ) {
-	double	xi = localCoord[0], eta = localCoord[1];
-	double	a0 = xi - 1.0, b0 = eta - 1.0;
-	double	a1 = 1.0 - xi * xi, b1 = 1.0 - eta * eta;
-	double	a2 = xi + 1.0, b2 = eta + 1.0;
-	double	m0 = 0.5 * xi;
-	double	m1 = 0.5 * eta;
-	double	m2 = 0.25 * xi * eta;
-
-	basis[0] = m2 * a0 * b0;
-	basis[1] = m1 * a1 * b0;
-	basis[2] = m2 * a2 * b0;
-
-	basis[3] = m0 * a0 * b1;
-	basis[4] = a1 * b1;
-	basis[5] = m0 * a2 * b1;
-
-	basis[6] = m2 * a0 * b2;
-	basis[7] = m1 * a1 * b2;
-	basis[8] = m2 * a2 * b2;
-}
-
-void P1_EvalLocalDerivs( void* elementType, const double* localCoord, double** derivs ) {
-	double	xi = localCoord[0], eta = localCoord[1];
-	double	a0 = xi - 1.0, b0 = eta - 1.0;
-	double	a1 = xi + 1.0, b1 = eta + 1.0;
-	double	a2 = 2.0 * xi - 1.0, b2 = 2.0 * eta - 1.0;
-	double	a3 = 2.0 * xi + 1.0, b3 = 2.0 * eta + 1.0;
-	double	a4 = 1.0 - xi * xi, b4 = 1.0 - eta * eta;
-	double	m0 = 0.25 * xi;
-	double	m1 = 0.25 * eta;
-	double	m2 = -xi * eta;
-
-	/* Corner nodes. */
-	derivs[0][0] = m1 * a2 * b0;
-	derivs[0][2] = m1 * a3 * b0;
-	derivs[0][6] = m1 * a2 * b1;
-	derivs[0][8] = m1 * a3 * b1;
-	derivs[1][0] = m0 * a0 * b2;
-	derivs[1][2] = m0 * a1 * b2;
-	derivs[1][6] = m0 * a0 * b3;
-	derivs[1][8] = m0 * a1 * b3;
-
-	/* Side nodes. */
-	derivs[0][1] = m2 * b0;
-	derivs[0][7] = m2 * b1;
-	derivs[0][3] = 0.5 * a2 * b4;
-	derivs[0][5] = 0.5 * a3 * b4;
-	derivs[1][1] = 0.5 * a4 * b2;
-	derivs[1][7] = 0.5 * a4 * b3;
-	derivs[1][3] = m2 * a0;
-	derivs[1][5] = m2 * a1;
-
-	/* Center node. */
-	derivs[0][4] = -2.0 * xi * b4;
-	derivs[1][4] = -2.0 * eta * a4;
-}
-
-int _P1_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
-	Stream* errStream = Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
-
-	Journal_Printf( errStream, "surface normal function not implemented for this element type.\n" );
-	assert( 0 );
-
-	normal = NULL;
-
-	return -1;
-}
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/P1.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/P1.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,216 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: P1.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type P1_Type = "P1";
+
+#define P1_NODECOUNT 3
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+P1* P1_New( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(P1);
+	Type                                                                                    type = P1_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _P1_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _P1_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_P1_New;
+	Stg_Component_ConstructFunction*                                                  _construct = _P1_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _P1_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _P1_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _P1_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _P1_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = P1_EvalBasis;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = P1_EvalLocalDerivs;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = NULL;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _P1_SurfaceNormal;
+
+	return _P1_New(  P1_PASSARGS  );
+}
+
+P1* _P1_New(  P1_DEFARGS  ) {
+	P1* self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(P1) );
+	self = (P1*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+
+	/* Virtual info */
+
+	/* P1 info */
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, P1_NODECOUNT );
+	_P1_Init( self );
+
+	return self;
+}
+
+void _P1_Init( P1* self ) {
+	assert( self && Stg_CheckType( self, P1 ) );
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _P1_Delete( void* elementType ) {
+	P1* self = (P1*)elementType;
+
+	/* Delete the parent. */
+	_ElementType_Delete( self );
+}
+
+void _P1_Print( void* elementType, Stream* stream ) {
+	P1*	self = (P1*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* elementTypeStream;
+	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"P1Stream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "P1 (ptr): (%p)\n", self );
+	_ElementType_Print( self, stream );
+}
+
+void _P1_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
+}
+
+void _P1_Build( void* elementType, void* data ) {
+}
+
+void _P1_Initialise( void* elementType, void* data ) {
+}
+
+void _P1_Execute( void* elementType, void* data ) {
+}
+
+void _P1_Destroy( void* elementType, void* data ) {
+	P1* self = (P1*)elementType;
+
+	_ElementType_Destroy( self, data );	
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void P1_EvalBasis( void* elementType, const double* localCoord, double* basis ) {
+	double	xi = localCoord[0], eta = localCoord[1];
+	double	a0 = xi - 1.0, b0 = eta - 1.0;
+	double	a1 = 1.0 - xi * xi, b1 = 1.0 - eta * eta;
+	double	a2 = xi + 1.0, b2 = eta + 1.0;
+	double	m0 = 0.5 * xi;
+	double	m1 = 0.5 * eta;
+	double	m2 = 0.25 * xi * eta;
+
+	basis[0] = m2 * a0 * b0;
+	basis[1] = m1 * a1 * b0;
+	basis[2] = m2 * a2 * b0;
+
+	basis[3] = m0 * a0 * b1;
+	basis[4] = a1 * b1;
+	basis[5] = m0 * a2 * b1;
+
+	basis[6] = m2 * a0 * b2;
+	basis[7] = m1 * a1 * b2;
+	basis[8] = m2 * a2 * b2;
+}
+
+void P1_EvalLocalDerivs( void* elementType, const double* localCoord, double** derivs ) {
+	double	xi = localCoord[0], eta = localCoord[1];
+	double	a0 = xi - 1.0, b0 = eta - 1.0;
+	double	a1 = xi + 1.0, b1 = eta + 1.0;
+	double	a2 = 2.0 * xi - 1.0, b2 = 2.0 * eta - 1.0;
+	double	a3 = 2.0 * xi + 1.0, b3 = 2.0 * eta + 1.0;
+	double	a4 = 1.0 - xi * xi, b4 = 1.0 - eta * eta;
+	double	m0 = 0.25 * xi;
+	double	m1 = 0.25 * eta;
+	double	m2 = -xi * eta;
+
+	/* Corner nodes. */
+	derivs[0][0] = m1 * a2 * b0;
+	derivs[0][2] = m1 * a3 * b0;
+	derivs[0][6] = m1 * a2 * b1;
+	derivs[0][8] = m1 * a3 * b1;
+	derivs[1][0] = m0 * a0 * b2;
+	derivs[1][2] = m0 * a1 * b2;
+	derivs[1][6] = m0 * a0 * b3;
+	derivs[1][8] = m0 * a1 * b3;
+
+	/* Side nodes. */
+	derivs[0][1] = m2 * b0;
+	derivs[0][7] = m2 * b1;
+	derivs[0][3] = 0.5 * a2 * b4;
+	derivs[0][5] = 0.5 * a3 * b4;
+	derivs[1][1] = 0.5 * a4 * b2;
+	derivs[1][7] = 0.5 * a4 * b3;
+	derivs[1][3] = m2 * a0;
+	derivs[1][5] = m2 * a1;
+
+	/* Center node. */
+	derivs[0][4] = -2.0 * xi * b4;
+	derivs[1][4] = -2.0 * eta * a4;
+}
+
+int _P1_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
+	Stream* errStream = Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
+
+	Journal_Printf( errStream, "surface normal function not implemented for this element type.\n" );
+	assert( 0 );
+
+	normal = NULL;
+
+	return -1;
+}
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/RegularBilinear.c
--- a/Discretisation/src/RegularBilinear.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: RegularBilinear.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type RegularBilinear_Type = "RegularBilinear";
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-#define REGULARBILINEAR_NODECOUNT 4
-
-RegularBilinear* RegularBilinear_New( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(RegularBilinear);
-	Type                                                                                    type = RegularBilinear_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _RegularBilinear_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _RegularBilinear_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_RegularBilinear_New;
-	Stg_Component_ConstructFunction*                                                  _construct = _RegularBilinear_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _RegularBilinear_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _RegularBilinear_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _RegularBilinear_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _RegularBilinear_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _BilinearElementType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _BilinearElementType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _BilinearElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
-
-	return _RegularBilinear_New(  REGULARBILINEAR_PASSARGS  );
-}
-
-RegularBilinear* _RegularBilinear_New(  REGULARBILINEAR_DEFARGS  ) {
-	RegularBilinear*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(RegularBilinear) );
-	self = (RegularBilinear*)_BilinearElementType_New(  BILINEARELEMENTTYPE_PASSARGS  );
-
-	/* Virtual info */
-
-	/* RegularBilinear info */
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, REGULARBILINEAR_NODECOUNT );
-   _BilinearElementType_Init( (BilinearElementType*)self );
-	_RegularBilinear_Init( self );
-
-	return self;
-}
-
-void _RegularBilinear_Init( RegularBilinear* self ) {
-	assert( self && Stg_CheckType( self, RegularBilinear ) );
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _RegularBilinear_Delete( void* elementType ) {
-	RegularBilinear* self = (RegularBilinear*)elementType;
-
-	/* Delete the parent. */
-	_BilinearElementType_Delete( self );
-}
-
-void _RegularBilinear_Print( void* elementType, Stream* stream ) {
-	RegularBilinear*	self = (RegularBilinear*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* elementTypeStream;
-	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"RegularBilinearStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "RegularBilinear (ptr): (%p)\n", self );
-	_BilinearElementType_Print( self, stream );
-}
-
-void _RegularBilinear_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
-}
-
-void _RegularBilinear_Build( void* elementType, void* data ) {
-	_BilinearElementType_Build( elementType, data );
-}
-
-void _RegularBilinear_Initialise( void* elementType, void* data ) {
-	_BilinearElementType_Initialise( elementType, data );
-}
-
-void _RegularBilinear_Execute( void* elementType, void* data ) {
-}
-
-void _RegularBilinear_Destroy( void* elementType, void* data ) {
-	RegularBilinear* self = (RegularBilinear*)elementType;
-
-	_BilinearElementType_Destroy( self, data );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-#if 0
-void RegularBilinear_ConvertGlobalCoordToElLocal( void* elementType, void* mesh, unsigned element, 
-						  const double* globalCoord, double* localCoord )
-{
-	RegularBilinear*	self = (RegularBilinear*)elementType;
-	unsigned		nInc, *inc;
-	double*			vert[2];
-	double			w;
-
-	assert( self && Stg_CheckType( self, RegularBilinear ) );
-
-	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = IArray_GetSize( self->inc );
-
-	vert[0] = Mesh_GetVertex( mesh, inc[0] );
-	vert[1] = Mesh_GetVertex( mesh, inc[3] );
-	w = vert[1][0] - vert[0][0];
-	localCoord[0] = 2.0 * (globalCoord[0] - vert[0][0]) / w - 1.0;
-	w = vert[1][1] - vert[0][1];
-	localCoord[1] = 2.0 * (globalCoord[1] - vert[0][1]) / w - 1.0;
-
-	assert( localCoord[0] >= -1.0 && localCoord[0] <= 1.0 );
-	assert( localCoord[1] >= -1.0 && localCoord[1] <= 1.0 );
-}
-#endif
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/RegularBilinear.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/RegularBilinear.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,178 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: RegularBilinear.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type RegularBilinear_Type = "RegularBilinear";
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+#define REGULARBILINEAR_NODECOUNT 4
+
+RegularBilinear* RegularBilinear_New( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(RegularBilinear);
+	Type                                                                                    type = RegularBilinear_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _RegularBilinear_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _RegularBilinear_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_RegularBilinear_New;
+	Stg_Component_ConstructFunction*                                                  _construct = _RegularBilinear_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _RegularBilinear_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _RegularBilinear_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _RegularBilinear_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _RegularBilinear_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _BilinearElementType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _BilinearElementType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _BilinearElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
+
+	return _RegularBilinear_New(  REGULARBILINEAR_PASSARGS  );
+}
+
+RegularBilinear* _RegularBilinear_New(  REGULARBILINEAR_DEFARGS  ) {
+	RegularBilinear*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(RegularBilinear) );
+	self = (RegularBilinear*)_BilinearElementType_New(  BILINEARELEMENTTYPE_PASSARGS  );
+
+	/* Virtual info */
+
+	/* RegularBilinear info */
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, REGULARBILINEAR_NODECOUNT );
+   _BilinearElementType_Init( (BilinearElementType*)self );
+	_RegularBilinear_Init( self );
+
+	return self;
+}
+
+void _RegularBilinear_Init( RegularBilinear* self ) {
+	assert( self && Stg_CheckType( self, RegularBilinear ) );
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _RegularBilinear_Delete( void* elementType ) {
+	RegularBilinear* self = (RegularBilinear*)elementType;
+
+	/* Delete the parent. */
+	_BilinearElementType_Delete( self );
+}
+
+void _RegularBilinear_Print( void* elementType, Stream* stream ) {
+	RegularBilinear*	self = (RegularBilinear*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* elementTypeStream;
+	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"RegularBilinearStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "RegularBilinear (ptr): (%p)\n", self );
+	_BilinearElementType_Print( self, stream );
+}
+
+void _RegularBilinear_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
+}
+
+void _RegularBilinear_Build( void* elementType, void* data ) {
+	_BilinearElementType_Build( elementType, data );
+}
+
+void _RegularBilinear_Initialise( void* elementType, void* data ) {
+	_BilinearElementType_Initialise( elementType, data );
+}
+
+void _RegularBilinear_Execute( void* elementType, void* data ) {
+}
+
+void _RegularBilinear_Destroy( void* elementType, void* data ) {
+	RegularBilinear* self = (RegularBilinear*)elementType;
+
+	_BilinearElementType_Destroy( self, data );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+#if 0
+void RegularBilinear_ConvertGlobalCoordToElLocal( void* elementType, void* mesh, unsigned element, 
+						  const double* globalCoord, double* localCoord )
+{
+	RegularBilinear*	self = (RegularBilinear*)elementType;
+	unsigned		nInc, *inc;
+	double*			vert[2];
+	double			w;
+
+	assert( self && Stg_CheckType( self, RegularBilinear ) );
+
+	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = IArray_GetSize( self->inc );
+
+	vert[0] = Mesh_GetVertex( mesh, inc[0] );
+	vert[1] = Mesh_GetVertex( mesh, inc[3] );
+	w = vert[1][0] - vert[0][0];
+	localCoord[0] = 2.0 * (globalCoord[0] - vert[0][0]) / w - 1.0;
+	w = vert[1][1] - vert[0][1];
+	localCoord[1] = 2.0 * (globalCoord[1] - vert[0][1]) / w - 1.0;
+
+	assert( localCoord[0] >= -1.0 && localCoord[0] <= 1.0 );
+	assert( localCoord[1] >= -1.0 && localCoord[1] <= 1.0 );
+}
+#endif
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/RegularTrilinear.c
--- a/Discretisation/src/RegularTrilinear.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,182 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: RegularTrilinear.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-
-/* Textual name of this class */
-const Type RegularTrilinear_Type = "RegularTrilinear";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-#define REGULARTRILINEAR_NODECOUNT 8
-
-RegularTrilinear* RegularTrilinear_New( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(RegularTrilinear);
-	Type                                                                                    type = RegularTrilinear_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _RegularTrilinear_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _RegularTrilinear_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_RegularTrilinear_New;
-	Stg_Component_ConstructFunction*                                                  _construct = _RegularTrilinear_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _RegularTrilinear_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _RegularTrilinear_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _RegularTrilinear_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _RegularTrilinear_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _TrilinearElementType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _TrilinearElementType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _TrilinearElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
-
-	return _RegularTrilinear_New(  REGULARTRILINEAR_PASSARGS  );
-}
-
-RegularTrilinear* _RegularTrilinear_New(  REGULARTRILINEAR_DEFARGS  ) {
-	RegularTrilinear*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(RegularTrilinear) );
-	self = (RegularTrilinear*)_TrilinearElementType_New(  TRILINEARELEMENTTYPE_PASSARGS  );
-
-	/* Virtual info */
-
-	/* RegularTrilinear info */
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, REGULARTRILINEAR_NODECOUNT );
-   _TrilinearElementType_Init( (TrilinearElementType*)self );
-	_RegularTrilinear_Init( self );
-
-	return self;
-}
-
-void _RegularTrilinear_Init( RegularTrilinear* self ) {
-	assert( self && Stg_CheckType( self, RegularTrilinear ) );
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _RegularTrilinear_Delete( void* elementType ) {
-	RegularTrilinear*	self = (RegularTrilinear*)elementType;
-
-	/* Delete the parent. */
-	_TrilinearElementType_Delete( self );
-}
-
-void _RegularTrilinear_Print( void* elementType, Stream* stream ) {
-	RegularTrilinear*	self = (RegularTrilinear*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* elementTypeStream;
-	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"RegularTrilinearStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "RegularTrilinear (ptr): (%p)\n", self );
-	_TrilinearElementType_Print( self, stream );
-}
-
-void _RegularTrilinear_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
-}
-
-void _RegularTrilinear_Build( void* elementType, void* data ) {
-	_TrilinearElementType_Build( elementType, data );
-}
-
-void _RegularTrilinear_Initialise( void* elementType, void* data ) {
-	_TrilinearElementType_Initialise( elementType, data );
-}
-
-void _RegularTrilinear_Execute( void* elementType, void* data ) {
-}
-
-void _RegularTrilinear_Destroy( void* elementType, void* data ) {
-	RegularTrilinear*	self = (RegularTrilinear*)elementType;
-
-	_TrilinearElementType_Destroy( self, data );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-#if 0
-void RegularTrilinear_ConvertGlobalCoordToElLocal( void* elementType, void* mesh, unsigned element, 
-						   const double* globalCoord, double* localCoord )
-{
-	RegularTrilinear*	self = (RegularTrilinear*)elementType;
-	unsigned		nInc, *inc;
-	double*			vert[2];
-	double			w;
-
-	assert( self && Stg_CheckType( self, RegularTrilinear ) );
-
-	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = IArray_GetSize( self->inc );
-
-	vert[0] = Mesh_GetVertex( mesh, inc[0] );
-	vert[1] = Mesh_GetVertex( mesh, inc[7] );
-	w = vert[1][0] - vert[0][0];
-	localCoord[0] = 2.0 * (globalCoord[0] - vert[0][0]) / w - 1.0;
-	w = vert[1][1] - vert[0][1];
-	localCoord[1] = 2.0 * (globalCoord[1] - vert[0][1]) / w - 1.0;
-	w = vert[1][2] - vert[0][2];
-	localCoord[2] = 2.0 * (globalCoord[2] - vert[0][2]) / w - 1.0;
-
-	assert( Num_InRange( localCoord[0], -1.0, 1.0 ) );
-	assert( Num_InRange( localCoord[1], -1.0, 1.0 ) );
-	assert( Num_InRange( localCoord[2], -1.0, 1.0 ) );
-}
-#endif
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/RegularTrilinear.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/RegularTrilinear.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,182 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: RegularTrilinear.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+
+/* Textual name of this class */
+const Type RegularTrilinear_Type = "RegularTrilinear";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+#define REGULARTRILINEAR_NODECOUNT 8
+
+RegularTrilinear* RegularTrilinear_New( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(RegularTrilinear);
+	Type                                                                                    type = RegularTrilinear_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _RegularTrilinear_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _RegularTrilinear_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_RegularTrilinear_New;
+	Stg_Component_ConstructFunction*                                                  _construct = _RegularTrilinear_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _RegularTrilinear_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _RegularTrilinear_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _RegularTrilinear_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _RegularTrilinear_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _TrilinearElementType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _TrilinearElementType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _TrilinearElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
+
+	return _RegularTrilinear_New(  REGULARTRILINEAR_PASSARGS  );
+}
+
+RegularTrilinear* _RegularTrilinear_New(  REGULARTRILINEAR_DEFARGS  ) {
+	RegularTrilinear*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(RegularTrilinear) );
+	self = (RegularTrilinear*)_TrilinearElementType_New(  TRILINEARELEMENTTYPE_PASSARGS  );
+
+	/* Virtual info */
+
+	/* RegularTrilinear info */
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, REGULARTRILINEAR_NODECOUNT );
+   _TrilinearElementType_Init( (TrilinearElementType*)self );
+	_RegularTrilinear_Init( self );
+
+	return self;
+}
+
+void _RegularTrilinear_Init( RegularTrilinear* self ) {
+	assert( self && Stg_CheckType( self, RegularTrilinear ) );
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _RegularTrilinear_Delete( void* elementType ) {
+	RegularTrilinear*	self = (RegularTrilinear*)elementType;
+
+	/* Delete the parent. */
+	_TrilinearElementType_Delete( self );
+}
+
+void _RegularTrilinear_Print( void* elementType, Stream* stream ) {
+	RegularTrilinear*	self = (RegularTrilinear*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* elementTypeStream;
+	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"RegularTrilinearStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "RegularTrilinear (ptr): (%p)\n", self );
+	_TrilinearElementType_Print( self, stream );
+}
+
+void _RegularTrilinear_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
+}
+
+void _RegularTrilinear_Build( void* elementType, void* data ) {
+	_TrilinearElementType_Build( elementType, data );
+}
+
+void _RegularTrilinear_Initialise( void* elementType, void* data ) {
+	_TrilinearElementType_Initialise( elementType, data );
+}
+
+void _RegularTrilinear_Execute( void* elementType, void* data ) {
+}
+
+void _RegularTrilinear_Destroy( void* elementType, void* data ) {
+	RegularTrilinear*	self = (RegularTrilinear*)elementType;
+
+	_TrilinearElementType_Destroy( self, data );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+#if 0
+void RegularTrilinear_ConvertGlobalCoordToElLocal( void* elementType, void* mesh, unsigned element, 
+						   const double* globalCoord, double* localCoord )
+{
+	RegularTrilinear*	self = (RegularTrilinear*)elementType;
+	unsigned		nInc, *inc;
+	double*			vert[2];
+	double			w;
+
+	assert( self && Stg_CheckType( self, RegularTrilinear ) );
+
+	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = IArray_GetSize( self->inc );
+
+	vert[0] = Mesh_GetVertex( mesh, inc[0] );
+	vert[1] = Mesh_GetVertex( mesh, inc[7] );
+	w = vert[1][0] - vert[0][0];
+	localCoord[0] = 2.0 * (globalCoord[0] - vert[0][0]) / w - 1.0;
+	w = vert[1][1] - vert[0][1];
+	localCoord[1] = 2.0 * (globalCoord[1] - vert[0][1]) / w - 1.0;
+	w = vert[1][2] - vert[0][2];
+	localCoord[2] = 2.0 * (globalCoord[2] - vert[0][2]) / w - 1.0;
+
+	assert( Num_InRange( localCoord[0], -1.0, 1.0 ) );
+	assert( Num_InRange( localCoord[1], -1.0, 1.0 ) );
+	assert( Num_InRange( localCoord[2], -1.0, 1.0 ) );
+}
+#endif
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/ShapeFeVariable.c
--- a/Discretisation/src/ShapeFeVariable.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: ShapeFeVariable.c 532 2006-04-04 00:21:59Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "types.h"
-#include "FeMesh.h"
-#include "FeVariable.h"
-#include "ShapeFeVariable.h"
-
-#include <assert.h>
-
-const Type ShapeFeVariable_Type = "ShapeFeVariable";
-
-void* ShapeFeVariable_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                       _sizeOfSelf = sizeof(ShapeFeVariable);
-	Type                                                               type = ShapeFeVariable_Type;
-	Stg_Class_DeleteFunction*                                       _delete = _ShapeFeVariable_Delete;
-	Stg_Class_PrintFunction*                                         _print = _ShapeFeVariable_Print;
-	Stg_Class_CopyFunction*                                           _copy = _ShapeFeVariable_Copy;
-	Stg_Component_DefaultConstructorFunction*           _defaultConstructor = (Stg_Component_DefaultConstructorFunction*)ShapeFeVariable_DefaultNew;
-	Stg_Component_ConstructFunction*                             _construct = _ShapeFeVariable_AssignFromXML;
-	Stg_Component_BuildFunction*                                     _build = _ShapeFeVariable_Build;
-	Stg_Component_InitialiseFunction*                           _initialise = _ShapeFeVariable_Initialise;
-	Stg_Component_ExecuteFunction*                                 _execute = _ShapeFeVariable_Execute;
-	Stg_Component_DestroyFunction*                                 _destroy = _ShapeFeVariable_Destroy;
-	FieldVariable_InterpolateValueAtFunction*           _interpolateValueAt = _FeVariable_InterpolateValueAt;
-	FieldVariable_GetValueFunction*             _getMinGlobalFieldMagnitude = _FeVariable_GetMinGlobalFieldMagnitude;
-	FieldVariable_GetValueFunction*             _getMaxGlobalFieldMagnitude = _FeVariable_GetMaxGlobalFieldMagnitude;
-	FieldVariable_GetCoordFunction*                _getMinAndMaxLocalCoords = _FeVariable_GetMinAndMaxLocalCoords;
-	FieldVariable_GetCoordFunction*               _getMinAndMaxGlobalCoords = _FeVariable_GetMinAndMaxGlobalCoords;
-	FeVariable_InterpolateWithinElementFunction*  _interpolateWithinElement = _FeVariable_InterpolateNodeValuesToElLocalCoord;
-	FeVariable_GetValueAtNodeFunction*                      _getValueAtNode = _FeVariable_GetValueAtNode;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType                             nameAllocationType = (AllocationType)ZERO;
-	FeVariable_SyncShadowValuesFunc*            _syncShadowValues = ZERO;
-
-	return (ShapeFeVariable*) _ShapeFeVariable_New(  SHAPEFEVARIABLE_PASSARGS  );
-}			
-
-ShapeFeVariable* _ShapeFeVariable_New(  SHAPEFEVARIABLE_DEFARGS  ) {
-	ShapeFeVariable* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(ShapeFeVariable) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-	_syncShadowValues  = _FeVariable_SyncShadowValues;
-
-	self = (ShapeFeVariable*) _FeVariable_New(  FEVARIABLE_PASSARGS  );
-
-	return self;
-}
-
-void _ShapeFeVariable_Init( void* shapeFeVariable, Stg_Shape* shape ) {
-	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
-
-	self->shape = shape;
-	
-	/* EP_AppendClassHook( Context_GetEntryPoint( context, AbstractContext_EP_UpdateClass ),	ParticleFeVariable_Update, self ); */
-}
-
-void _ShapeFeVariable_Delete( void* _shapeFeVariable ) {
-	ShapeFeVariable* self = (ShapeFeVariable*) _shapeFeVariable;
-
-	_FeVariable_Delete( self );
-}
-
-void _ShapeFeVariable_Print( void* _shapeFeVariable, Stream* stream ) {
-	ShapeFeVariable* self = (ShapeFeVariable*) _shapeFeVariable;
-
-	/* Print parent */
-	_FeVariable_Print( self, stream );
-
-	Journal_PrintPointer( stream, self->shape );
-}
-
-void* _ShapeFeVariable_Copy( const void* shapeFeVariable, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	/* ShapeFeVariable*	self = (ShapeFeVariable*)shapeFeVariable; */
-	ShapeFeVariable* newShapeFeVariable;
-	
-	assert(0);
-	return (void*)newShapeFeVariable;
-}
-
-void _ShapeFeVariable_AssignFromXML( void* shapeFeVariable, Stg_ComponentFactory* cf, void* data ) {
-	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
-
-	_FeVariable_AssignFromXML( self, cf, data );
-
-	_ShapeFeVariable_Init( self, Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Shape", Stg_Shape, True, data )   ) ;
-}
-
-void _ShapeFeVariable_Build( void* shapeFeVariable, void* data ) {
-	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
-
-	Stg_Component_Build( self->shape, data, False );
-	_FeVariable_Build( self, data );
-}
-
-void _ShapeFeVariable_Initialise( void* shapeFeVariable, void* data ) {
-	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
-	Node_DomainIndex node_dI = 0;
-
-	Stg_Component_Initialise( self->shape, data, False );
-	_FeVariable_Initialise( self, data );
-
-	/* Set up the basic "level set" describing if nodes are inside the shape or not */
-	for ( node_dI = 0; node_dI < Mesh_GetDomainSize( self->feMesh, MT_VERTEX ); node_dI++ ) {
-		if ( True == Stg_Shape_IsCoordInside( self->shape, Mesh_GetVertex( self->feMesh, node_dI ) ) ) {
-			/* set value = 1 */
-			FeVariable_SetComponentAtNode( self, node_dI, 0, 1 );
-		}		
-		else {
-			/* set value = 0 */
-			FeVariable_SetComponentAtNode( self, node_dI, 0, 0 );
-		}
-	}
-}
-
-void _ShapeFeVariable_Execute( void* shapeFeVariable, void* data ) {
-	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
-	
-	_FeVariable_Execute( self, data );
-}
-
-void _ShapeFeVariable_Destroy( void* shapeFeVariable, void* data ) {
-	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
-	
-	_FeVariable_Destroy( self, data );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/ShapeFeVariable.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/ShapeFeVariable.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,178 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: ShapeFeVariable.c 532 2006-04-04 00:21:59Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "types.h"
+#include "FeMesh.h"
+#include "FeVariable.h"
+#include "ShapeFeVariable.h"
+
+#include <assert.h>
+
+const Type ShapeFeVariable_Type = "ShapeFeVariable";
+
+void* ShapeFeVariable_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                       _sizeOfSelf = sizeof(ShapeFeVariable);
+	Type                                                               type = ShapeFeVariable_Type;
+	Stg_Class_DeleteFunction*                                       _delete = _ShapeFeVariable_Delete;
+	Stg_Class_PrintFunction*                                         _print = _ShapeFeVariable_Print;
+	Stg_Class_CopyFunction*                                           _copy = _ShapeFeVariable_Copy;
+	Stg_Component_DefaultConstructorFunction*           _defaultConstructor = (Stg_Component_DefaultConstructorFunction*)ShapeFeVariable_DefaultNew;
+	Stg_Component_ConstructFunction*                             _construct = _ShapeFeVariable_AssignFromXML;
+	Stg_Component_BuildFunction*                                     _build = _ShapeFeVariable_Build;
+	Stg_Component_InitialiseFunction*                           _initialise = _ShapeFeVariable_Initialise;
+	Stg_Component_ExecuteFunction*                                 _execute = _ShapeFeVariable_Execute;
+	Stg_Component_DestroyFunction*                                 _destroy = _ShapeFeVariable_Destroy;
+	FieldVariable_InterpolateValueAtFunction*           _interpolateValueAt = _FeVariable_InterpolateValueAt;
+	FieldVariable_GetValueFunction*             _getMinGlobalFieldMagnitude = _FeVariable_GetMinGlobalFieldMagnitude;
+	FieldVariable_GetValueFunction*             _getMaxGlobalFieldMagnitude = _FeVariable_GetMaxGlobalFieldMagnitude;
+	FieldVariable_GetCoordFunction*                _getMinAndMaxLocalCoords = _FeVariable_GetMinAndMaxLocalCoords;
+	FieldVariable_GetCoordFunction*               _getMinAndMaxGlobalCoords = _FeVariable_GetMinAndMaxGlobalCoords;
+	FeVariable_InterpolateWithinElementFunction*  _interpolateWithinElement = _FeVariable_InterpolateNodeValuesToElLocalCoord;
+	FeVariable_GetValueAtNodeFunction*                      _getValueAtNode = _FeVariable_GetValueAtNode;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType                             nameAllocationType = (AllocationType)ZERO;
+	FeVariable_SyncShadowValuesFunc*            _syncShadowValues = ZERO;
+
+	return (ShapeFeVariable*) _ShapeFeVariable_New(  SHAPEFEVARIABLE_PASSARGS  );
+}			
+
+ShapeFeVariable* _ShapeFeVariable_New(  SHAPEFEVARIABLE_DEFARGS  ) {
+	ShapeFeVariable* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(ShapeFeVariable) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+	_syncShadowValues  = _FeVariable_SyncShadowValues;
+
+	self = (ShapeFeVariable*) _FeVariable_New(  FEVARIABLE_PASSARGS  );
+
+	return self;
+}
+
+void _ShapeFeVariable_Init( void* shapeFeVariable, Stg_Shape* shape ) {
+	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
+
+	self->shape = shape;
+	
+	/* EP_AppendClassHook( Context_GetEntryPoint( context, AbstractContext_EP_UpdateClass ),	ParticleFeVariable_Update, self ); */
+}
+
+void _ShapeFeVariable_Delete( void* _shapeFeVariable ) {
+	ShapeFeVariable* self = (ShapeFeVariable*) _shapeFeVariable;
+
+	_FeVariable_Delete( self );
+}
+
+void _ShapeFeVariable_Print( void* _shapeFeVariable, Stream* stream ) {
+	ShapeFeVariable* self = (ShapeFeVariable*) _shapeFeVariable;
+
+	/* Print parent */
+	_FeVariable_Print( self, stream );
+
+	Journal_PrintPointer( stream, self->shape );
+}
+
+void* _ShapeFeVariable_Copy( const void* shapeFeVariable, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	/* ShapeFeVariable*	self = (ShapeFeVariable*)shapeFeVariable; */
+	ShapeFeVariable* newShapeFeVariable;
+	
+	assert(0);
+	return (void*)newShapeFeVariable;
+}
+
+void _ShapeFeVariable_AssignFromXML( void* shapeFeVariable, Stg_ComponentFactory* cf, void* data ) {
+	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
+
+	_FeVariable_AssignFromXML( self, cf, data );
+
+	_ShapeFeVariable_Init( self, Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Shape", Stg_Shape, True, data )   ) ;
+}
+
+void _ShapeFeVariable_Build( void* shapeFeVariable, void* data ) {
+	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
+
+	Stg_Component_Build( self->shape, data, False );
+	_FeVariable_Build( self, data );
+}
+
+void _ShapeFeVariable_Initialise( void* shapeFeVariable, void* data ) {
+	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
+	Node_DomainIndex node_dI = 0;
+
+	Stg_Component_Initialise( self->shape, data, False );
+	_FeVariable_Initialise( self, data );
+
+	/* Set up the basic "level set" describing if nodes are inside the shape or not */
+	for ( node_dI = 0; node_dI < Mesh_GetDomainSize( self->feMesh, MT_VERTEX ); node_dI++ ) {
+		if ( True == Stg_Shape_IsCoordInside( self->shape, Mesh_GetVertex( self->feMesh, node_dI ) ) ) {
+			/* set value = 1 */
+			FeVariable_SetComponentAtNode( self, node_dI, 0, 1 );
+		}		
+		else {
+			/* set value = 0 */
+			FeVariable_SetComponentAtNode( self, node_dI, 0, 0 );
+		}
+	}
+}
+
+void _ShapeFeVariable_Execute( void* shapeFeVariable, void* data ) {
+	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
+	
+	_FeVariable_Execute( self, data );
+}
+
+void _ShapeFeVariable_Destroy( void* shapeFeVariable, void* data ) {
+	ShapeFeVariable* self = (ShapeFeVariable*) shapeFeVariable;
+	
+	_FeVariable_Destroy( self, data );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/TrilinearElementType.c
--- a/Discretisation/src/TrilinearElementType.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,388 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: TrilinearElementType.c 1180 2008-07-16 01:34:25Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType.h"
-#include "TrilinearElementType.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-const Type TrilinearElementType_Type = "TrilinearElementType";
-
-#define _TrilinearElementType_NodeCount 8
-
-void* _TrilinearElementType_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(TrilinearElementType);
-	Type                                                                                    type = TrilinearElementType_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _TrilinearElementType_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _TrilinearElementType_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = _TrilinearElementType_DefaultNew;
-	Stg_Component_ConstructFunction*                                                  _construct = _TrilinearElementType_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _TrilinearElementType_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _TrilinearElementType_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _TrilinearElementType_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _TrilinearElementType_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _TrilinearElementType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _TrilinearElementType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _TrilinearElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
-
-	return _TrilinearElementType_New(  TRILINEARELEMENTTYPE_PASSARGS  );
-}
-
-TrilinearElementType* TrilinearElementType_New( Name name ) {
-  TrilinearElementType* self = (TrilinearElementType*)_TrilinearElementType_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, _TrilinearElementType_NodeCount );
-	_TrilinearElementType_Init( self );
-
-	return self;	
-}
-
-TrilinearElementType* _TrilinearElementType_New(  TRILINEARELEMENTTYPE_DEFARGS  ) {
-	TrilinearElementType*		self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(TrilinearElementType) );
-	self = (TrilinearElementType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual functions */
-	
-	/* TrilinearElementType info */
-	
-	return self;
-}
-
-void _TrilinearElementType_Init( TrilinearElementType* self ) {
-	Dimension_Index dim, dim_I=0;
-
-	/* General and Virtual info should already be set */
-	
-	/* TrilinearElementType info */
-	dim = self->dim = 3;
-	for ( dim_I = 0; dim_I < dim; dim_I++ ) {
-		self->minElLocalCoord[dim_I] = -1;
-		self->maxElLocalCoord[dim_I] = 1;
-		self->elLocalLength[dim_I] = self->maxElLocalCoord[dim_I] - self->minElLocalCoord[dim_I];
-	}
-
-	/* Set up the tetrahedral indices. */
-	self->tetInds = Memory_Alloc_2DArray( unsigned, 10, 4, (Name)"Mesh_HexType::tetInds" );
-	self->tetInds[0][0] = 0; self->tetInds[0][1] = 1; self->tetInds[0][2] = 2; self->tetInds[0][3] = 4;
-	self->tetInds[1][0] = 1; self->tetInds[1][1] = 2; self->tetInds[1][2] = 3; self->tetInds[1][3] = 7;
-	self->tetInds[2][0] = 1; self->tetInds[2][1] = 4; self->tetInds[2][2] = 5; self->tetInds[2][3] = 7;
-	self->tetInds[3][0] = 2; self->tetInds[3][1] = 4; self->tetInds[3][2] = 6; self->tetInds[3][3] = 7;
-	self->tetInds[4][0] = 1; self->tetInds[4][1] = 2; self->tetInds[4][2] = 4; self->tetInds[4][3] = 7;
-	self->tetInds[5][0] = 0; self->tetInds[5][1] = 1; self->tetInds[5][2] = 3; self->tetInds[5][3] = 5;
-	self->tetInds[6][0] = 0; self->tetInds[6][1] = 4; self->tetInds[6][2] = 5; self->tetInds[6][3] = 6;
-	self->tetInds[7][0] = 0; self->tetInds[7][1] = 2; self->tetInds[7][2] = 3; self->tetInds[7][3] = 6;
-	self->tetInds[8][0] = 3; self->tetInds[8][1] = 5; self->tetInds[8][2] = 6; self->tetInds[8][3] = 7;
-	self->tetInds[9][0] = 0; self->tetInds[9][1] = 3; self->tetInds[9][2] = 5; self->tetInds[9][3] = 6;
-}
-
-void _TrilinearElementType_Delete( void* elementType ) {
-	TrilinearElementType* self = (TrilinearElementType*)elementType;
-	
-	/* Stg_Class_Delete parent*/
-	_ElementType_Delete( self  );
-}
-
-void _TrilinearElementType_Print( void* elementType, Stream* stream ) {
-	TrilinearElementType* self = (TrilinearElementType*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* trilinearElementTypeStream = stream;
-	
-	/* General info */
-	Journal_Printf( trilinearElementTypeStream, "TrilinearElementType (ptr): %p\n", self );
-	
-	/* Print parent */
-	_ElementType_Print( self, trilinearElementTypeStream );
-	
-	/* Virtual info */
-	
-	/* TrilinearElementType info */
-}
-
-void _TrilinearElementType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
-	
-}
-	
-void _TrilinearElementType_Initialise( void* elementType, void *data ){
-	TrilinearElementType* 	self = (TrilinearElementType*)elementType;
-	unsigned**		faceNodes;
-
-	faceNodes = Memory_Alloc_2DArray( unsigned, 6, 4, (Name)"node indices for element faces"  );
-
-	faceNodes[0][0] = 0; faceNodes[0][1] = 1; faceNodes[0][2] = 4; faceNodes[0][3] = 5;
-	/* the top face */
-	faceNodes[1][0] = 2; faceNodes[1][1] = 3; faceNodes[1][2] = 6; faceNodes[1][3] = 7;
-	faceNodes[2][0] = 0; faceNodes[2][1] = 4; faceNodes[2][2] = 2; faceNodes[2][3] = 6;
-	faceNodes[3][0] = 1; faceNodes[3][1] = 5; faceNodes[3][2] = 3; faceNodes[3][3] = 7;
-	faceNodes[4][0] = 0; faceNodes[4][1] = 1; faceNodes[4][2] = 2; faceNodes[4][3] = 3;
-	faceNodes[5][0] = 4; faceNodes[5][1] = 5; faceNodes[5][2] = 6; faceNodes[5][3] = 7;
-
-	self->faceNodes = faceNodes;
-
-	self->evaluatedShapeFunc = Memory_Alloc_Array( double, self->nodeCount, "evaluatedShapeFuncs" );
-	self->GNi = Memory_Alloc_2DArray( double, self->dim, self->nodeCount, (Name)"localShapeFuncDerivitives"  );
-
-}
-	
-void _TrilinearElementType_Execute( void* elementType, void *data ){
-	
-}
-	
-void _TrilinearElementType_Destroy( void* elementType, void *data ){
-	TrilinearElementType* 	self = (TrilinearElementType*)elementType;
-
-	Memory_Free( self->faceNodes );
-	Memory_Free( self->evaluatedShapeFunc );
-	Memory_Free( self->GNi );
-
-	FreeArray( self->tetInds );
-
-	_ElementType_Destroy( self, data );
-}
-
-void _TrilinearElementType_Build( void* elementType, void *data ) {
-}
-
-#if 0
-void _TrilinearElementType_ConvertGlobalCoordToElementLocal( void* elementType, Element_DomainIndex element,const Coord globalCoord, Coord localCoord ) 
-{
-	TrilinearElementType*	self = (TrilinearElementType*)elementType;
-	Dimension_Index		dim_I;
-
-	for ( dim_I=0; dim_I < 3; dim_I++ ) {
-	}
-}
-#endif
-
-
-/*
-
- - Shape function definitions
- - Local node numbering convention for billinear, trilinear element (xi, eta, zeta)
- - Local coordinate domain spans  -1 <= xi,eta,zeta <= 1
-
-    eta
-     |
-     |____ xi
-    /
-   /
- zeta
-
-
-  eta
-   |
-3-----2
-|  |__|___xi
-|     |
-0-----1
-(zeta = -1 plane)
-
-
-  eta
-   |
-7-----6
-|  |__|___xi
-|     |
-4-----5
-(zeta = +1 plane)
-
-
-*/
-void _TrilinearElementType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
-	double xi, eta, zeta;
-	
-	xi   = localCoord[0];
-	eta  = localCoord[1];
-	zeta = localCoord[2];	
-	
-	evaluatedValues[0] = 0.125*( 1.0-xi )*( 1.0-eta )*( 1.0-zeta );
-	evaluatedValues[2] = 0.125*( 1.0-xi )*( 1.0+eta )*( 1.0-zeta );
-	evaluatedValues[3] = 0.125*( 1.0+xi )*( 1.0+eta )*( 1.0-zeta );
-	evaluatedValues[1] = 0.125*( 1.0+xi )*( 1.0-eta )*( 1.0-zeta );
-	
-	evaluatedValues[4] = 0.125*( 1.0-xi )*( 1.0-eta )*( 1.0+zeta );
-	evaluatedValues[6] = 0.125*( 1.0-xi )*( 1.0+eta )*( 1.0+zeta );
-	evaluatedValues[7] = 0.125*( 1.0+xi )*( 1.0+eta )*( 1.0+zeta );
-	evaluatedValues[5] = 0.125*( 1.0+xi )*( 1.0-eta )*( 1.0+zeta );
-}
-
-
-void _TrilinearElementType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
-		double** const evaluatedDerivatives )
-{		
-	double xi, eta, zeta;
-	
-	xi   = localCoord[0];
-	eta  = localCoord[1];
-	zeta = localCoord[2];	
-	
-	/* derivatives wrt xi */
-	evaluatedDerivatives[0][0] = - 0.125*( 1.0-eta )*( 1.0-zeta );
-	evaluatedDerivatives[0][2] = - 0.125*( 1.0+eta )*( 1.0-zeta );
-	evaluatedDerivatives[0][3] =   0.125*( 1.0+eta )*( 1.0-zeta );
-	evaluatedDerivatives[0][1] =   0.125*( 1.0-eta )*( 1.0-zeta );
-	evaluatedDerivatives[0][4] = - 0.125*( 1.0-eta )*( 1.0+zeta );
-	evaluatedDerivatives[0][6] = - 0.125*( 1.0+eta )*( 1.0+zeta );
-	evaluatedDerivatives[0][7] =   0.125*( 1.0+eta )*( 1.0+zeta );
-	evaluatedDerivatives[0][5] =   0.125*( 1.0-eta )*( 1.0+zeta );
-	
-	/* derivatives wrt eta */	
-	evaluatedDerivatives[1][0] = - 0.125*( 1.0-xi )*( 1.0-zeta );
-	evaluatedDerivatives[1][2] =   0.125*( 1.0-xi )*( 1.0-zeta );
-	evaluatedDerivatives[1][3] =   0.125*( 1.0+xi )*( 1.0-zeta );
-	evaluatedDerivatives[1][1] = - 0.125*( 1.0+xi )*( 1.0-zeta );
-	evaluatedDerivatives[1][4] = - 0.125*( 1.0-xi )*( 1.0+zeta );
-	evaluatedDerivatives[1][6] =   0.125*( 1.0-xi )*( 1.0+zeta );
-	evaluatedDerivatives[1][7] =   0.125*( 1.0+xi )*( 1.0+zeta );
-	evaluatedDerivatives[1][5] = - 0.125*( 1.0+xi )*( 1.0+zeta );
-	
-	/* derivatives wrt zeta */		
-	evaluatedDerivatives[2][0] = -0.125*( 1.0-xi )*( 1.0-eta );
-	evaluatedDerivatives[2][2] = -0.125*( 1.0-xi )*( 1.0+eta );
-	evaluatedDerivatives[2][3] = -0.125*( 1.0+xi )*( 1.0+eta );
-	evaluatedDerivatives[2][1] = -0.125*( 1.0+xi )*( 1.0-eta );
-	evaluatedDerivatives[2][4] =  0.125*( 1.0-xi )*( 1.0-eta );
-	evaluatedDerivatives[2][6] =  0.125*( 1.0-xi )*( 1.0+eta );
-	evaluatedDerivatives[2][7] =  0.125*( 1.0+xi )*( 1.0+eta );
-	evaluatedDerivatives[2][5] =  0.125*( 1.0+xi )*( 1.0-eta );
-}
-
-
-#if 0
-void _TrilinearElementType_ConvertGlobalCoordToElLocal(
-		void*		elementType,
-		void*		_mesh, 
-		unsigned	element, 
-		const double*	globalCoord,
-		double*		elLocalCoord )
-{
-	TrilinearElementType*	self = (TrilinearElementType*)elementType;
-	Mesh*			mesh = (Mesh*)_mesh;
-	unsigned		inside;
-	double			bc[4];
-	static double		lCrds[8][3] = {{-1.0, -1.0, -1.0}, {1.0, -1.0, -1.0}, 
-					       {-1.0, 1.0, -1.0}, {1.0, 1.0, -1.0}, 
-					       {-1.0, -1.0, 1.0}, {1.0, -1.0, 1.0}, 
-					       {-1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}};
-	unsigned		nInc, *inc;
-	unsigned		bc_i;
-
-	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, self->inc );
-	nInc = IArray_GetSize( self->inc );
-	inc = IArray_GetPtr( self->inc );
-	assert( nInc == 8 );
-
-	insist( Simplex_Search3D( mesh->verts, inc, 10, self->tetInds, (double*)globalCoord, bc, &inside ), == True );
-
-	elLocalCoord[0] = bc[0] * lCrds[self->tetInds[inside][0]][0];
-	elLocalCoord[1] = bc[0] * lCrds[self->tetInds[inside][0]][1];
-	elLocalCoord[2] = bc[0] * lCrds[self->tetInds[inside][0]][2];
-	for( bc_i = 1; bc_i < 4; bc_i++ ) {
-		elLocalCoord[0] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][0];
-		elLocalCoord[1] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][1];
-		elLocalCoord[2] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][2];
-	}
-}
-#endif
-
-double _TrilinearElementType_JacobianDeterminantSurface( void* elementType, void* _mesh, unsigned element_I, const double localCoord[],
-	       						 unsigned face_I, unsigned norm ) 
-{
-	TrilinearElementType*	self		= (TrilinearElementType*) elementType;
-	Mesh*			mesh		= (Mesh*)_mesh;
-	unsigned		surfaceDim[2];
-	double			x[4], y[4];
-	double			s, t;
-	double			dxds, dxdt, dyds, dydt;
-	double			detJac;
-	unsigned		nodes[4];
-
-	surfaceDim[0] = ( norm + 1 ) % 3;
-	surfaceDim[1] = ( norm + 2 ) % 3;
-
-	s = localCoord[surfaceDim[0]];
-	t = localCoord[surfaceDim[1]];
-
-	ElementType_GetFaceNodes( self, mesh, element_I, face_I, 4, nodes );
-
-	x[0] = Mesh_GetVertex( mesh, nodes[0] )[surfaceDim[0]];
-	x[1] = Mesh_GetVertex( mesh, nodes[1] )[surfaceDim[0]];
-	x[2] = Mesh_GetVertex( mesh, nodes[2] )[surfaceDim[0]];
-	x[3] = Mesh_GetVertex( mesh, nodes[3] )[surfaceDim[0]];
-
-	y[0] = Mesh_GetVertex( mesh, nodes[0] )[surfaceDim[1]];
-	y[1] = Mesh_GetVertex( mesh, nodes[1] )[surfaceDim[1]];
-	y[2] = Mesh_GetVertex( mesh, nodes[2] )[surfaceDim[1]];
-	y[3] = Mesh_GetVertex( mesh, nodes[3] )[surfaceDim[1]];
-
-	dxds = 0.25 * ( - ( 1.0 - t )*x[0] + ( 1.0 - t )*x[1] - ( 1.0 + t )*x[2] + ( 1.0 + t )*x[3] );
-	dyds = 0.25 * ( - ( 1.0 - t )*y[0] + ( 1.0 - t )*y[1] - ( 1.0 + t )*y[2] + ( 1.0 + t )*y[3] );
-	dxdt = 0.25 * ( - ( 1.0 - s )*x[0] - ( 1.0 + s )*x[1] + ( 1.0 - s )*x[2] + ( 1.0 + s )*x[3] );
-	dydt = 0.25 * ( - ( 1.0 - s )*y[0] - ( 1.0 + s )*y[1] + ( 1.0 - s )*y[2] + ( 1.0 + s )*y[3] );
-	
-	detJac = dxds * dydt - dxdt * dyds;
-
-	return fabs( detJac );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/TrilinearElementType.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/TrilinearElementType.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,388 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: TrilinearElementType.c 1180 2008-07-16 01:34:25Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType.h"
+#include "TrilinearElementType.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+const Type TrilinearElementType_Type = "TrilinearElementType";
+
+#define _TrilinearElementType_NodeCount 8
+
+void* _TrilinearElementType_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(TrilinearElementType);
+	Type                                                                                    type = TrilinearElementType_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _TrilinearElementType_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _TrilinearElementType_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = _TrilinearElementType_DefaultNew;
+	Stg_Component_ConstructFunction*                                                  _construct = _TrilinearElementType_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _TrilinearElementType_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _TrilinearElementType_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _TrilinearElementType_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _TrilinearElementType_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _TrilinearElementType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _TrilinearElementType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _TrilinearElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
+
+	return _TrilinearElementType_New(  TRILINEARELEMENTTYPE_PASSARGS  );
+}
+
+TrilinearElementType* TrilinearElementType_New( Name name ) {
+  TrilinearElementType* self = (TrilinearElementType*)_TrilinearElementType_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, _TrilinearElementType_NodeCount );
+	_TrilinearElementType_Init( self );
+
+	return self;	
+}
+
+TrilinearElementType* _TrilinearElementType_New(  TRILINEARELEMENTTYPE_DEFARGS  ) {
+	TrilinearElementType*		self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(TrilinearElementType) );
+	self = (TrilinearElementType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual functions */
+	
+	/* TrilinearElementType info */
+	
+	return self;
+}
+
+void _TrilinearElementType_Init( TrilinearElementType* self ) {
+	Dimension_Index dim, dim_I=0;
+
+	/* General and Virtual info should already be set */
+	
+	/* TrilinearElementType info */
+	dim = self->dim = 3;
+	for ( dim_I = 0; dim_I < dim; dim_I++ ) {
+		self->minElLocalCoord[dim_I] = -1;
+		self->maxElLocalCoord[dim_I] = 1;
+		self->elLocalLength[dim_I] = self->maxElLocalCoord[dim_I] - self->minElLocalCoord[dim_I];
+	}
+
+	/* Set up the tetrahedral indices. */
+	self->tetInds = Memory_Alloc_2DArray( unsigned, 10, 4, (Name)"Mesh_HexType::tetInds" );
+	self->tetInds[0][0] = 0; self->tetInds[0][1] = 1; self->tetInds[0][2] = 2; self->tetInds[0][3] = 4;
+	self->tetInds[1][0] = 1; self->tetInds[1][1] = 2; self->tetInds[1][2] = 3; self->tetInds[1][3] = 7;
+	self->tetInds[2][0] = 1; self->tetInds[2][1] = 4; self->tetInds[2][2] = 5; self->tetInds[2][3] = 7;
+	self->tetInds[3][0] = 2; self->tetInds[3][1] = 4; self->tetInds[3][2] = 6; self->tetInds[3][3] = 7;
+	self->tetInds[4][0] = 1; self->tetInds[4][1] = 2; self->tetInds[4][2] = 4; self->tetInds[4][3] = 7;
+	self->tetInds[5][0] = 0; self->tetInds[5][1] = 1; self->tetInds[5][2] = 3; self->tetInds[5][3] = 5;
+	self->tetInds[6][0] = 0; self->tetInds[6][1] = 4; self->tetInds[6][2] = 5; self->tetInds[6][3] = 6;
+	self->tetInds[7][0] = 0; self->tetInds[7][1] = 2; self->tetInds[7][2] = 3; self->tetInds[7][3] = 6;
+	self->tetInds[8][0] = 3; self->tetInds[8][1] = 5; self->tetInds[8][2] = 6; self->tetInds[8][3] = 7;
+	self->tetInds[9][0] = 0; self->tetInds[9][1] = 3; self->tetInds[9][2] = 5; self->tetInds[9][3] = 6;
+}
+
+void _TrilinearElementType_Delete( void* elementType ) {
+	TrilinearElementType* self = (TrilinearElementType*)elementType;
+	
+	/* Stg_Class_Delete parent*/
+	_ElementType_Delete( self  );
+}
+
+void _TrilinearElementType_Print( void* elementType, Stream* stream ) {
+	TrilinearElementType* self = (TrilinearElementType*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* trilinearElementTypeStream = stream;
+	
+	/* General info */
+	Journal_Printf( trilinearElementTypeStream, "TrilinearElementType (ptr): %p\n", self );
+	
+	/* Print parent */
+	_ElementType_Print( self, trilinearElementTypeStream );
+	
+	/* Virtual info */
+	
+	/* TrilinearElementType info */
+}
+
+void _TrilinearElementType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
+	
+}
+	
+void _TrilinearElementType_Initialise( void* elementType, void *data ){
+	TrilinearElementType* 	self = (TrilinearElementType*)elementType;
+	unsigned**		faceNodes;
+
+	faceNodes = Memory_Alloc_2DArray( unsigned, 6, 4, (Name)"node indices for element faces"  );
+
+	faceNodes[0][0] = 0; faceNodes[0][1] = 1; faceNodes[0][2] = 4; faceNodes[0][3] = 5;
+	/* the top face */
+	faceNodes[1][0] = 2; faceNodes[1][1] = 3; faceNodes[1][2] = 6; faceNodes[1][3] = 7;
+	faceNodes[2][0] = 0; faceNodes[2][1] = 4; faceNodes[2][2] = 2; faceNodes[2][3] = 6;
+	faceNodes[3][0] = 1; faceNodes[3][1] = 5; faceNodes[3][2] = 3; faceNodes[3][3] = 7;
+	faceNodes[4][0] = 0; faceNodes[4][1] = 1; faceNodes[4][2] = 2; faceNodes[4][3] = 3;
+	faceNodes[5][0] = 4; faceNodes[5][1] = 5; faceNodes[5][2] = 6; faceNodes[5][3] = 7;
+
+	self->faceNodes = faceNodes;
+
+	self->evaluatedShapeFunc = Memory_Alloc_Array( double, self->nodeCount, "evaluatedShapeFuncs" );
+	self->GNi = Memory_Alloc_2DArray( double, self->dim, self->nodeCount, (Name)"localShapeFuncDerivitives"  );
+
+}
+	
+void _TrilinearElementType_Execute( void* elementType, void *data ){
+	
+}
+	
+void _TrilinearElementType_Destroy( void* elementType, void *data ){
+	TrilinearElementType* 	self = (TrilinearElementType*)elementType;
+
+	Memory_Free( self->faceNodes );
+	Memory_Free( self->evaluatedShapeFunc );
+	Memory_Free( self->GNi );
+
+	FreeArray( self->tetInds );
+
+	_ElementType_Destroy( self, data );
+}
+
+void _TrilinearElementType_Build( void* elementType, void *data ) {
+}
+
+#if 0
+void _TrilinearElementType_ConvertGlobalCoordToElementLocal( void* elementType, Element_DomainIndex element,const Coord globalCoord, Coord localCoord ) 
+{
+	TrilinearElementType*	self = (TrilinearElementType*)elementType;
+	Dimension_Index		dim_I;
+
+	for ( dim_I=0; dim_I < 3; dim_I++ ) {
+	}
+}
+#endif
+
+
+/*
+
+ - Shape function definitions
+ - Local node numbering convention for billinear, trilinear element (xi, eta, zeta)
+ - Local coordinate domain spans  -1 <= xi,eta,zeta <= 1
+
+    eta
+     |
+     |____ xi
+    /
+   /
+ zeta
+
+
+  eta
+   |
+3-----2
+|  |__|___xi
+|     |
+0-----1
+(zeta = -1 plane)
+
+
+  eta
+   |
+7-----6
+|  |__|___xi
+|     |
+4-----5
+(zeta = +1 plane)
+
+
+*/
+void _TrilinearElementType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
+	double xi, eta, zeta;
+	
+	xi   = localCoord[0];
+	eta  = localCoord[1];
+	zeta = localCoord[2];	
+	
+	evaluatedValues[0] = 0.125*( 1.0-xi )*( 1.0-eta )*( 1.0-zeta );
+	evaluatedValues[2] = 0.125*( 1.0-xi )*( 1.0+eta )*( 1.0-zeta );
+	evaluatedValues[3] = 0.125*( 1.0+xi )*( 1.0+eta )*( 1.0-zeta );
+	evaluatedValues[1] = 0.125*( 1.0+xi )*( 1.0-eta )*( 1.0-zeta );
+	
+	evaluatedValues[4] = 0.125*( 1.0-xi )*( 1.0-eta )*( 1.0+zeta );
+	evaluatedValues[6] = 0.125*( 1.0-xi )*( 1.0+eta )*( 1.0+zeta );
+	evaluatedValues[7] = 0.125*( 1.0+xi )*( 1.0+eta )*( 1.0+zeta );
+	evaluatedValues[5] = 0.125*( 1.0+xi )*( 1.0-eta )*( 1.0+zeta );
+}
+
+
+void _TrilinearElementType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
+		double** const evaluatedDerivatives )
+{		
+	double xi, eta, zeta;
+	
+	xi   = localCoord[0];
+	eta  = localCoord[1];
+	zeta = localCoord[2];	
+	
+	/* derivatives wrt xi */
+	evaluatedDerivatives[0][0] = - 0.125*( 1.0-eta )*( 1.0-zeta );
+	evaluatedDerivatives[0][2] = - 0.125*( 1.0+eta )*( 1.0-zeta );
+	evaluatedDerivatives[0][3] =   0.125*( 1.0+eta )*( 1.0-zeta );
+	evaluatedDerivatives[0][1] =   0.125*( 1.0-eta )*( 1.0-zeta );
+	evaluatedDerivatives[0][4] = - 0.125*( 1.0-eta )*( 1.0+zeta );
+	evaluatedDerivatives[0][6] = - 0.125*( 1.0+eta )*( 1.0+zeta );
+	evaluatedDerivatives[0][7] =   0.125*( 1.0+eta )*( 1.0+zeta );
+	evaluatedDerivatives[0][5] =   0.125*( 1.0-eta )*( 1.0+zeta );
+	
+	/* derivatives wrt eta */	
+	evaluatedDerivatives[1][0] = - 0.125*( 1.0-xi )*( 1.0-zeta );
+	evaluatedDerivatives[1][2] =   0.125*( 1.0-xi )*( 1.0-zeta );
+	evaluatedDerivatives[1][3] =   0.125*( 1.0+xi )*( 1.0-zeta );
+	evaluatedDerivatives[1][1] = - 0.125*( 1.0+xi )*( 1.0-zeta );
+	evaluatedDerivatives[1][4] = - 0.125*( 1.0-xi )*( 1.0+zeta );
+	evaluatedDerivatives[1][6] =   0.125*( 1.0-xi )*( 1.0+zeta );
+	evaluatedDerivatives[1][7] =   0.125*( 1.0+xi )*( 1.0+zeta );
+	evaluatedDerivatives[1][5] = - 0.125*( 1.0+xi )*( 1.0+zeta );
+	
+	/* derivatives wrt zeta */		
+	evaluatedDerivatives[2][0] = -0.125*( 1.0-xi )*( 1.0-eta );
+	evaluatedDerivatives[2][2] = -0.125*( 1.0-xi )*( 1.0+eta );
+	evaluatedDerivatives[2][3] = -0.125*( 1.0+xi )*( 1.0+eta );
+	evaluatedDerivatives[2][1] = -0.125*( 1.0+xi )*( 1.0-eta );
+	evaluatedDerivatives[2][4] =  0.125*( 1.0-xi )*( 1.0-eta );
+	evaluatedDerivatives[2][6] =  0.125*( 1.0-xi )*( 1.0+eta );
+	evaluatedDerivatives[2][7] =  0.125*( 1.0+xi )*( 1.0+eta );
+	evaluatedDerivatives[2][5] =  0.125*( 1.0+xi )*( 1.0-eta );
+}
+
+
+#if 0
+void _TrilinearElementType_ConvertGlobalCoordToElLocal(
+		void*		elementType,
+		void*		_mesh, 
+		unsigned	element, 
+		const double*	globalCoord,
+		double*		elLocalCoord )
+{
+	TrilinearElementType*	self = (TrilinearElementType*)elementType;
+	Mesh*			mesh = (Mesh*)_mesh;
+	unsigned		inside;
+	double			bc[4];
+	static double		lCrds[8][3] = {{-1.0, -1.0, -1.0}, {1.0, -1.0, -1.0}, 
+					       {-1.0, 1.0, -1.0}, {1.0, 1.0, -1.0}, 
+					       {-1.0, -1.0, 1.0}, {1.0, -1.0, 1.0}, 
+					       {-1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}};
+	unsigned		nInc, *inc;
+	unsigned		bc_i;
+
+	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, self->inc );
+	nInc = IArray_GetSize( self->inc );
+	inc = IArray_GetPtr( self->inc );
+	assert( nInc == 8 );
+
+	insist( Simplex_Search3D( mesh->verts, inc, 10, self->tetInds, (double*)globalCoord, bc, &inside ), == True );
+
+	elLocalCoord[0] = bc[0] * lCrds[self->tetInds[inside][0]][0];
+	elLocalCoord[1] = bc[0] * lCrds[self->tetInds[inside][0]][1];
+	elLocalCoord[2] = bc[0] * lCrds[self->tetInds[inside][0]][2];
+	for( bc_i = 1; bc_i < 4; bc_i++ ) {
+		elLocalCoord[0] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][0];
+		elLocalCoord[1] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][1];
+		elLocalCoord[2] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][2];
+	}
+}
+#endif
+
+double _TrilinearElementType_JacobianDeterminantSurface( void* elementType, void* _mesh, unsigned element_I, const double localCoord[],
+	       						 unsigned face_I, unsigned norm ) 
+{
+	TrilinearElementType*	self		= (TrilinearElementType*) elementType;
+	Mesh*			mesh		= (Mesh*)_mesh;
+	unsigned		surfaceDim[2];
+	double			x[4], y[4];
+	double			s, t;
+	double			dxds, dxdt, dyds, dydt;
+	double			detJac;
+	unsigned		nodes[4];
+
+	surfaceDim[0] = ( norm + 1 ) % 3;
+	surfaceDim[1] = ( norm + 2 ) % 3;
+
+	s = localCoord[surfaceDim[0]];
+	t = localCoord[surfaceDim[1]];
+
+	ElementType_GetFaceNodes( self, mesh, element_I, face_I, 4, nodes );
+
+	x[0] = Mesh_GetVertex( mesh, nodes[0] )[surfaceDim[0]];
+	x[1] = Mesh_GetVertex( mesh, nodes[1] )[surfaceDim[0]];
+	x[2] = Mesh_GetVertex( mesh, nodes[2] )[surfaceDim[0]];
+	x[3] = Mesh_GetVertex( mesh, nodes[3] )[surfaceDim[0]];
+
+	y[0] = Mesh_GetVertex( mesh, nodes[0] )[surfaceDim[1]];
+	y[1] = Mesh_GetVertex( mesh, nodes[1] )[surfaceDim[1]];
+	y[2] = Mesh_GetVertex( mesh, nodes[2] )[surfaceDim[1]];
+	y[3] = Mesh_GetVertex( mesh, nodes[3] )[surfaceDim[1]];
+
+	dxds = 0.25 * ( - ( 1.0 - t )*x[0] + ( 1.0 - t )*x[1] - ( 1.0 + t )*x[2] + ( 1.0 + t )*x[3] );
+	dyds = 0.25 * ( - ( 1.0 - t )*y[0] + ( 1.0 - t )*y[1] - ( 1.0 + t )*y[2] + ( 1.0 + t )*y[3] );
+	dxdt = 0.25 * ( - ( 1.0 - s )*x[0] - ( 1.0 + s )*x[1] + ( 1.0 - s )*x[2] + ( 1.0 + s )*x[3] );
+	dydt = 0.25 * ( - ( 1.0 - s )*y[0] - ( 1.0 + s )*y[1] + ( 1.0 - s )*y[2] + ( 1.0 + s )*y[3] );
+	
+	detJac = dxds * dydt - dxdt * dyds;
+
+	return fabs( detJac );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/TrilinearInnerElType.c
--- a/Discretisation/src/TrilinearInnerElType.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,323 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: TrilinearInnerElType.c 832 2007-05-16 01:11:18Z DaveLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "ElementType.h"
-#include "TrilinearInnerElType.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-const Type TrilinearInnerElType_Type = "TrilinearInnerElType";
-
-#define _TrilinearInnerElType_NodeCount 4
-
-void* _TrilinearInnerElType_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(TrilinearInnerElType);
-	Type                                                                                    type = TrilinearInnerElType_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _TrilinearInnerElType_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _TrilinearInnerElType_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = _TrilinearInnerElType_DefaultNew;
-	Stg_Component_ConstructFunction*                                                  _construct = _TrilinearInnerElType_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _TrilinearInnerElType_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _TrilinearInnerElType_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _TrilinearInnerElType_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _TrilinearInnerElType_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _TrilinearInnerElType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _TrilinearInnerElType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _TrilinearInnerElType_SurfaceNormal;
-
-	return _TrilinearInnerElType_New(  TRILINEARINNERELTYPE_PASSARGS  );
-}
-
-TrilinearInnerElType* TrilinearInnerElType_New( Name name ) {
-  TrilinearInnerElType* self = (TrilinearInnerElType*)_TrilinearInnerElType_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, _TrilinearInnerElType_NodeCount );
-	_TrilinearInnerElType_Init( self );
-
-	return self;
-}
-
-TrilinearInnerElType* _TrilinearInnerElType_New(  TRILINEARINNERELTYPE_DEFARGS  ) {
-	TrilinearInnerElType* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(TrilinearInnerElType) );
-	self = (TrilinearInnerElType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual functions */
-	
-	/* TrilinearInnerElType info */
-	
-	return self;
-}
-
-void _TrilinearInnerElType_Init( TrilinearInnerElType* self ) {
-	Dimension_Index dim_I=0;
-
-	/* General and Virtual info should already be set */
-	
-	/* TriInnerEllementType info */
-	for ( dim_I = 0; dim_I < 3; dim_I++ ) {
-		self->minElLocalCoord[dim_I] = -1;
-		self->maxElLocalCoord[dim_I] = 1;
-		self->elLocalLength[dim_I] = self->maxElLocalCoord[dim_I] - self->minElLocalCoord[dim_I];
-	}
-
-	/* Set up the tetrahedral indices. */
-	self->tetInds = Memory_Alloc_2DArray( unsigned, 10, 4, (Name)"Mesh_HexType::tetInds" );
-	self->tetInds[0][0] = 0; self->tetInds[0][1] = 1; self->tetInds[0][2] = 2; self->tetInds[0][3] = 4;
-	self->tetInds[1][0] = 1; self->tetInds[1][1] = 2; self->tetInds[1][2] = 3; self->tetInds[1][3] = 7;
-	self->tetInds[2][0] = 1; self->tetInds[2][1] = 4; self->tetInds[2][2] = 5; self->tetInds[2][3] = 7;
-	self->tetInds[3][0] = 2; self->tetInds[3][1] = 4; self->tetInds[3][2] = 6; self->tetInds[3][3] = 7;
-	self->tetInds[4][0] = 1; self->tetInds[4][1] = 2; self->tetInds[4][2] = 4; self->tetInds[4][3] = 7;
-	self->tetInds[5][0] = 0; self->tetInds[5][1] = 1; self->tetInds[5][2] = 3; self->tetInds[5][3] = 5;
-	self->tetInds[6][0] = 0; self->tetInds[6][1] = 4; self->tetInds[6][2] = 5; self->tetInds[6][3] = 6;
-	self->tetInds[7][0] = 0; self->tetInds[7][1] = 2; self->tetInds[7][2] = 3; self->tetInds[7][3] = 6;
-	self->tetInds[8][0] = 3; self->tetInds[8][1] = 5; self->tetInds[8][2] = 6; self->tetInds[8][3] = 7;
-	self->tetInds[9][0] = 0; self->tetInds[9][1] = 3; self->tetInds[9][2] = 5; self->tetInds[9][3] = 6;
-}
-
-void _TrilinearInnerElType_Delete( void* elementType ) {
-	TrilinearInnerElType* self = (TrilinearInnerElType*)elementType;
-
-	/* Stg_Class_Delete parent*/
-	_ElementType_Delete( self  );
-}
-
-void _TrilinearInnerElType_Print( void* elementType, Stream* stream ) {
-	TrilinearInnerElType* self = (TrilinearInnerElType*)elementType;
-	
-	/* Set the Journal for printing informations */
-	Stream* trilinearInnerElTypeStream = stream;
-	
-	/* General info */
-	Journal_Printf( trilinearInnerElTypeStream, "TrilinearInnerElType (ptr): %p\n", self );
-	
-	/* Print parent */
-	_ElementType_Print( self, trilinearInnerElTypeStream );
-	
-	/* Virtual info */
-	
-	/* TrilinearInnerElType info */
-}
-
-void _TrilinearInnerElType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
-	
-}
-	
-void _TrilinearInnerElType_Initialise( void* elementType, void *data ){
-	
-}
-	
-void _TrilinearInnerElType_Execute( void* elementType, void *data ){
-	
-}
-	
-void _TrilinearInnerElType_Destroy( void* elementType, void *data ){
-	TrilinearInnerElType* self = (TrilinearInnerElType*)elementType;
-	
-	FreeArray( self->tetInds );
-
-	_ElementType_Destroy( self, data );
-}
-
-void _TrilinearInnerElType_Build( void* elementType, void *data ) {
-	
-}
-
-#if 0
-void _TrilinearInnerElType_ConvertGlobalCoordToElementLocal( void* elementType, Element_DomainIndex element,const Coord globalCoord, Coord localCoord ) 
-{
-	TrilinearInnerElType*	self = (TrilinearInnerElType*)elementType;
-	Dimension_Index		dim_I;
-
-	for ( dim_I=0; dim_I < 3; dim_I++ ) {
-	}
-}
-#endif
-
-
-/*
-
- - Shape function definitions
- - Local node numbering convention for billinear, trilinear element (xi, eta, zeta)
- - Local coordinate domain spans  -1 <= xi,eta,zeta <= 1
-
-    eta
-     |
-     |____ xi
-    /
-   /
- zeta
-
-
-  eta
-   |
-3-----2
-|  |__|___xi
-|     |
-0-----1
-(zeta = -1 plane)
-
-
-  eta
-   |
-7-----6
-|  |__|___xi
-|     |
-4-----5
-(zeta = +1 plane)
-
-
-*/
-void _TrilinearInnerElType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
-	double xi, eta, zeta;
-	double fac;
-	
-	xi   = localCoord[0];
-	eta  = localCoord[1];
-	zeta = localCoord[2];	
-	
-	fac = 1.0/9.0;
-
-	evaluatedValues[0] = fac*( - 4.0*xi - 20.0*eta + 12.0*zeta + 3.0 );
-	evaluatedValues[1] = fac*(  16.0*xi - 64.0*eta + 60.0*zeta + 6.0 );
-	evaluatedValues[2] = fac*(            36.0*eta - 36.0*zeta       );
-	evaluatedValues[3] = fac*( -12.0*xi + 48.0*eta - 36.0*zeta       );
-}
-
-
-
-void _TrilinearInnerElType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
-		double** const evaluatedDerivatives )
-{		
-	double xi, eta, zeta;
-	double fac;
-	
-	xi   = localCoord[0];
-	eta  = localCoord[1];
-	zeta = localCoord[2];	
-	
-	fac = 1.0/9.0;
-	                       
-	evaluatedDerivatives[0][0] = fac*( - 4.0 ); 
-	evaluatedDerivatives[0][1] = fac*(  16.0 ); 
-	evaluatedDerivatives[0][2] =         0.0  ; 
-	evaluatedDerivatives[0][3] = fac*( -12.0 ); 
-	                             
-	evaluatedDerivatives[1][0] = fac*( -20.0 );	
-	evaluatedDerivatives[1][1] = fac*( -64.0 );	
-	evaluatedDerivatives[1][2] =         4.0  ;	
-	evaluatedDerivatives[1][3] = fac*(  48.0 );	
-	                            
-	evaluatedDerivatives[2][0] = fac*(  12.0 );
-	evaluatedDerivatives[2][1] = fac*(  60.0 );
-	evaluatedDerivatives[2][2] =       - 4.0  ;
-	evaluatedDerivatives[2][3] =       - 4.0  ;
-}
-
-/* get rid of this function and just use the superclass (elementType) version, as for BilinearInner class?? */
-/*
-void _TrilinearInnerElType_ConvertGlobalCoordToElLocal(
-		void*		elementType,
-		void*		_mesh, 
-		unsigned	element, 
-		const double*	globalCoord,
-		double*		elLocalCoord )
-{
-	TrilinearInnerElType*	self = (TrilinearInnerElType*)elementType;
-	Mesh*			mesh = (Mesh*)_mesh;
-	unsigned		inside;
-	double			bc[4];
-	static double		lCrds[8][3] = {{-1.0, -1.0, -1.0}, {1.0, -1.0, -1.0}, 
-					       {-1.0, 1.0, -1.0}, {1.0, 1.0, -1.0}, 
-					       {-1.0, -1.0, 1.0}, {1.0, -1.0, 1.0}, 
-					       {-1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}};
-	unsigned		nInc, *inc;
-	unsigned		bc_i;
-
-	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, &nInc, &inc );
-	assert( nInc == 8 );
-
-	insist( Simplex_Search3D( mesh->verts, inc, 10, self->tetInds, (double*)globalCoord, bc, &inside ), == True );
-
-	elLocalCoord[0] = bc[0] * lCrds[self->tetInds[inside][0]][0];
-	elLocalCoord[1] = bc[0] * lCrds[self->tetInds[inside][0]][1];
-	elLocalCoord[2] = bc[0] * lCrds[self->tetInds[inside][0]][2];
-	for( bc_i = 1; bc_i < 4; bc_i++ ) {
-		elLocalCoord[0] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][0];
-		elLocalCoord[1] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][1];
-		elLocalCoord[2] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][2];
-	}
-}*/
-
-int _TrilinearInnerElType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
-	Stream* errStream = Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
-
-	Journal_Printf( errStream, "Surface normal function not yet implemented for this element type.\n" );
-	assert( 0 );
-
-	normal = NULL;
-
-	return -1;
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/TrilinearInnerElType.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/TrilinearInnerElType.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,323 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: TrilinearInnerElType.c 832 2007-05-16 01:11:18Z DaveLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "ElementType.h"
+#include "TrilinearInnerElType.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+const Type TrilinearInnerElType_Type = "TrilinearInnerElType";
+
+#define _TrilinearInnerElType_NodeCount 4
+
+void* _TrilinearInnerElType_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(TrilinearInnerElType);
+	Type                                                                                    type = TrilinearInnerElType_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _TrilinearInnerElType_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _TrilinearInnerElType_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = _TrilinearInnerElType_DefaultNew;
+	Stg_Component_ConstructFunction*                                                  _construct = _TrilinearInnerElType_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _TrilinearInnerElType_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _TrilinearInnerElType_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _TrilinearInnerElType_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _TrilinearInnerElType_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _TrilinearInnerElType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _TrilinearInnerElType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _TrilinearInnerElType_SurfaceNormal;
+
+	return _TrilinearInnerElType_New(  TRILINEARINNERELTYPE_PASSARGS  );
+}
+
+TrilinearInnerElType* TrilinearInnerElType_New( Name name ) {
+  TrilinearInnerElType* self = (TrilinearInnerElType*)_TrilinearInnerElType_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, _TrilinearInnerElType_NodeCount );
+	_TrilinearInnerElType_Init( self );
+
+	return self;
+}
+
+TrilinearInnerElType* _TrilinearInnerElType_New(  TRILINEARINNERELTYPE_DEFARGS  ) {
+	TrilinearInnerElType* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(TrilinearInnerElType) );
+	self = (TrilinearInnerElType*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual functions */
+	
+	/* TrilinearInnerElType info */
+	
+	return self;
+}
+
+void _TrilinearInnerElType_Init( TrilinearInnerElType* self ) {
+	Dimension_Index dim_I=0;
+
+	/* General and Virtual info should already be set */
+	
+	/* TriInnerEllementType info */
+	for ( dim_I = 0; dim_I < 3; dim_I++ ) {
+		self->minElLocalCoord[dim_I] = -1;
+		self->maxElLocalCoord[dim_I] = 1;
+		self->elLocalLength[dim_I] = self->maxElLocalCoord[dim_I] - self->minElLocalCoord[dim_I];
+	}
+
+	/* Set up the tetrahedral indices. */
+	self->tetInds = Memory_Alloc_2DArray( unsigned, 10, 4, (Name)"Mesh_HexType::tetInds" );
+	self->tetInds[0][0] = 0; self->tetInds[0][1] = 1; self->tetInds[0][2] = 2; self->tetInds[0][3] = 4;
+	self->tetInds[1][0] = 1; self->tetInds[1][1] = 2; self->tetInds[1][2] = 3; self->tetInds[1][3] = 7;
+	self->tetInds[2][0] = 1; self->tetInds[2][1] = 4; self->tetInds[2][2] = 5; self->tetInds[2][3] = 7;
+	self->tetInds[3][0] = 2; self->tetInds[3][1] = 4; self->tetInds[3][2] = 6; self->tetInds[3][3] = 7;
+	self->tetInds[4][0] = 1; self->tetInds[4][1] = 2; self->tetInds[4][2] = 4; self->tetInds[4][3] = 7;
+	self->tetInds[5][0] = 0; self->tetInds[5][1] = 1; self->tetInds[5][2] = 3; self->tetInds[5][3] = 5;
+	self->tetInds[6][0] = 0; self->tetInds[6][1] = 4; self->tetInds[6][2] = 5; self->tetInds[6][3] = 6;
+	self->tetInds[7][0] = 0; self->tetInds[7][1] = 2; self->tetInds[7][2] = 3; self->tetInds[7][3] = 6;
+	self->tetInds[8][0] = 3; self->tetInds[8][1] = 5; self->tetInds[8][2] = 6; self->tetInds[8][3] = 7;
+	self->tetInds[9][0] = 0; self->tetInds[9][1] = 3; self->tetInds[9][2] = 5; self->tetInds[9][3] = 6;
+}
+
+void _TrilinearInnerElType_Delete( void* elementType ) {
+	TrilinearInnerElType* self = (TrilinearInnerElType*)elementType;
+
+	/* Stg_Class_Delete parent*/
+	_ElementType_Delete( self  );
+}
+
+void _TrilinearInnerElType_Print( void* elementType, Stream* stream ) {
+	TrilinearInnerElType* self = (TrilinearInnerElType*)elementType;
+	
+	/* Set the Journal for printing informations */
+	Stream* trilinearInnerElTypeStream = stream;
+	
+	/* General info */
+	Journal_Printf( trilinearInnerElTypeStream, "TrilinearInnerElType (ptr): %p\n", self );
+	
+	/* Print parent */
+	_ElementType_Print( self, trilinearInnerElTypeStream );
+	
+	/* Virtual info */
+	
+	/* TrilinearInnerElType info */
+}
+
+void _TrilinearInnerElType_AssignFromXML( void* elementType, Stg_ComponentFactory *cf, void* data ){
+	
+}
+	
+void _TrilinearInnerElType_Initialise( void* elementType, void *data ){
+	
+}
+	
+void _TrilinearInnerElType_Execute( void* elementType, void *data ){
+	
+}
+	
+void _TrilinearInnerElType_Destroy( void* elementType, void *data ){
+	TrilinearInnerElType* self = (TrilinearInnerElType*)elementType;
+	
+	FreeArray( self->tetInds );
+
+	_ElementType_Destroy( self, data );
+}
+
+void _TrilinearInnerElType_Build( void* elementType, void *data ) {
+	
+}
+
+#if 0
+void _TrilinearInnerElType_ConvertGlobalCoordToElementLocal( void* elementType, Element_DomainIndex element,const Coord globalCoord, Coord localCoord ) 
+{
+	TrilinearInnerElType*	self = (TrilinearInnerElType*)elementType;
+	Dimension_Index		dim_I;
+
+	for ( dim_I=0; dim_I < 3; dim_I++ ) {
+	}
+}
+#endif
+
+
+/*
+
+ - Shape function definitions
+ - Local node numbering convention for billinear, trilinear element (xi, eta, zeta)
+ - Local coordinate domain spans  -1 <= xi,eta,zeta <= 1
+
+    eta
+     |
+     |____ xi
+    /
+   /
+ zeta
+
+
+  eta
+   |
+3-----2
+|  |__|___xi
+|     |
+0-----1
+(zeta = -1 plane)
+
+
+  eta
+   |
+7-----6
+|  |__|___xi
+|     |
+4-----5
+(zeta = +1 plane)
+
+
+*/
+void _TrilinearInnerElType_SF_allNodes( void* elementType, const double localCoord[], double* const evaluatedValues ) {
+	double xi, eta, zeta;
+	double fac;
+	
+	xi   = localCoord[0];
+	eta  = localCoord[1];
+	zeta = localCoord[2];	
+	
+	fac = 1.0/9.0;
+
+	evaluatedValues[0] = fac*( - 4.0*xi - 20.0*eta + 12.0*zeta + 3.0 );
+	evaluatedValues[1] = fac*(  16.0*xi - 64.0*eta + 60.0*zeta + 6.0 );
+	evaluatedValues[2] = fac*(            36.0*eta - 36.0*zeta       );
+	evaluatedValues[3] = fac*( -12.0*xi + 48.0*eta - 36.0*zeta       );
+}
+
+
+
+void _TrilinearInnerElType_SF_allLocalDerivs_allNodes( void* elementType, const double localCoord[],
+		double** const evaluatedDerivatives )
+{		
+	double xi, eta, zeta;
+	double fac;
+	
+	xi   = localCoord[0];
+	eta  = localCoord[1];
+	zeta = localCoord[2];	
+	
+	fac = 1.0/9.0;
+	                       
+	evaluatedDerivatives[0][0] = fac*( - 4.0 ); 
+	evaluatedDerivatives[0][1] = fac*(  16.0 ); 
+	evaluatedDerivatives[0][2] =         0.0  ; 
+	evaluatedDerivatives[0][3] = fac*( -12.0 ); 
+	                             
+	evaluatedDerivatives[1][0] = fac*( -20.0 );	
+	evaluatedDerivatives[1][1] = fac*( -64.0 );	
+	evaluatedDerivatives[1][2] =         4.0  ;	
+	evaluatedDerivatives[1][3] = fac*(  48.0 );	
+	                            
+	evaluatedDerivatives[2][0] = fac*(  12.0 );
+	evaluatedDerivatives[2][1] = fac*(  60.0 );
+	evaluatedDerivatives[2][2] =       - 4.0  ;
+	evaluatedDerivatives[2][3] =       - 4.0  ;
+}
+
+/* get rid of this function and just use the superclass (elementType) version, as for BilinearInner class?? */
+/*
+void _TrilinearInnerElType_ConvertGlobalCoordToElLocal(
+		void*		elementType,
+		void*		_mesh, 
+		unsigned	element, 
+		const double*	globalCoord,
+		double*		elLocalCoord )
+{
+	TrilinearInnerElType*	self = (TrilinearInnerElType*)elementType;
+	Mesh*			mesh = (Mesh*)_mesh;
+	unsigned		inside;
+	double			bc[4];
+	static double		lCrds[8][3] = {{-1.0, -1.0, -1.0}, {1.0, -1.0, -1.0}, 
+					       {-1.0, 1.0, -1.0}, {1.0, 1.0, -1.0}, 
+					       {-1.0, -1.0, 1.0}, {1.0, -1.0, 1.0}, 
+					       {-1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}};
+	unsigned		nInc, *inc;
+	unsigned		bc_i;
+
+	Mesh_GetIncidence( mesh, MT_VOLUME, element, MT_VERTEX, &nInc, &inc );
+	assert( nInc == 8 );
+
+	insist( Simplex_Search3D( mesh->verts, inc, 10, self->tetInds, (double*)globalCoord, bc, &inside ), == True );
+
+	elLocalCoord[0] = bc[0] * lCrds[self->tetInds[inside][0]][0];
+	elLocalCoord[1] = bc[0] * lCrds[self->tetInds[inside][0]][1];
+	elLocalCoord[2] = bc[0] * lCrds[self->tetInds[inside][0]][2];
+	for( bc_i = 1; bc_i < 4; bc_i++ ) {
+		elLocalCoord[0] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][0];
+		elLocalCoord[1] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][1];
+		elLocalCoord[2] += bc[bc_i] * lCrds[self->tetInds[inside][bc_i]][2];
+	}
+}*/
+
+int _TrilinearInnerElType_SurfaceNormal( void* elementType, unsigned element_I, unsigned dim, double* xi, double* normal ) {
+	Stream* errStream = Journal_Register( ErrorStream_Type, (Name)ElementType_Type  );
+
+	Journal_Printf( errStream, "Surface normal function not yet implemented for this element type.\n" );
+	assert( 0 );
+
+	normal = NULL;
+
+	return -1;
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Triquadratic.c
--- a/Discretisation/src/Triquadratic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,446 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Dave Lee, Computational Engineer, VPAC. (dave at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Biquadratic.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation.h"
-
-#include "Triquadratic.h"
-
-/* Textual name of this class */
-const Type Triquadratic_Type = "Triquadratic";
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-#define TRIQUADRATICNODECOUNT 27
-
-Triquadratic* Triquadratic_New( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(Triquadratic);
-	Type                                                                                    type = Triquadratic_Type;
-	Stg_Class_DeleteFunction*                                                            _delete = _Triquadratic_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _Triquadratic_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_Triquadratic_New;
-	Stg_Component_ConstructFunction*                                                  _construct = _Triquadratic_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _Triquadratic_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _Triquadratic_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _Triquadratic_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _Triquadratic_Destroy;
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = Triquadratic_EvalBasis;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = Triquadratic_EvalLocalDerivs;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = Triquadratic_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
-
-	return _Triquadratic_New(  TRIQUADRATIC_PASSARGS  );
-}
-
-Triquadratic* _Triquadratic_New(  TRIQUADRATIC_DEFARGS  ) {
-	Triquadratic*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Triquadratic) );
-	self = (Triquadratic*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
-
-	/* Virtual info */
-
-	/* Triquadratic info */
-	self->isConstructed = True;
-	_ElementType_Init( (ElementType*)self, TRIQUADRATICNODECOUNT );
-	_Triquadratic_Init( self );
-
-	return self;
-}
-
-void _Triquadratic_Init( Triquadratic* self ) {
-	assert( self && Stg_CheckType( self, Triquadratic ) );
-
-	self->dim = 3;
-}
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _Triquadratic_Delete( void* elementType ) {
-	Triquadratic*	self = (Triquadratic*)elementType;
-
-	/* Delete the parent */
-	_ElementType_Delete( self );
-}
-
-void _Triquadratic_Print( void* elementType, Stream* stream ) {
-	Triquadratic*	self = (Triquadratic*)elementType;
-
-	/* Set the Journal for printing informations */
-	Stream* elementTypeStream;
-	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"TriquadraticStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "Triquadratic (ptr): (%p)\n", self );
-	_ElementType_Print( self, stream );
-}
-
-void _Triquadratic_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
-}
-
-void _Triquadratic_Build( void* elementType, void* data ) {
-}
-
-void _Triquadratic_Initialise( void* elementType, void* data ) {
-	Triquadratic*	self 		= (Triquadratic*)elementType;
-	unsigned**	faceNodes;
-
-	faceNodes = Memory_Alloc_2DArray( unsigned, 6, 9, (Name)"node indices for element faces"  );
-
-	faceNodes[0][0] =  0; faceNodes[0][1] =  1; faceNodes[0][2] =  2;
-	faceNodes[0][3] =  9; faceNodes[0][4] = 10; faceNodes[0][5] = 11;
-	faceNodes[0][6] = 18; faceNodes[0][7] = 19; faceNodes[0][8] = 20;
-
-	faceNodes[1][0] =  6; faceNodes[1][1] =  7; faceNodes[1][2] =  8;
-	faceNodes[1][3] = 15; faceNodes[1][4] = 16; faceNodes[1][5] = 17;
-	faceNodes[1][6] = 24; faceNodes[1][7] = 25; faceNodes[1][8] = 26;
-
-	faceNodes[2][0] =  0; faceNodes[2][1] =  9; faceNodes[2][2] = 18;
-	faceNodes[2][3] =  3; faceNodes[2][4] = 12; faceNodes[2][5] = 21;
-	faceNodes[2][6] =  6; faceNodes[2][7] = 15; faceNodes[2][8] = 24;
-
-	faceNodes[3][0] =  2; faceNodes[3][1] = 11; faceNodes[3][2] = 20;
-	faceNodes[3][3] =  5; faceNodes[3][4] = 14; faceNodes[3][5] = 23;
-	faceNodes[3][6] =  8; faceNodes[3][7] = 17; faceNodes[3][8] = 26;
-
-	faceNodes[4][0] =  0; faceNodes[4][1] =  1; faceNodes[4][2] =  2;
-	faceNodes[4][3] =  3; faceNodes[4][4] =  4; faceNodes[4][5] =  5;
-	faceNodes[4][6] =  6; faceNodes[4][7] =  7; faceNodes[4][8] =  8;
-
-	faceNodes[5][0] = 18; faceNodes[5][1] = 19; faceNodes[5][2] = 20;
-	faceNodes[5][3] = 21; faceNodes[5][4] = 22; faceNodes[5][5] = 23;
-	faceNodes[5][6] = 24; faceNodes[5][7] = 25; faceNodes[5][8] = 26;
-
-	self->faceNodes = faceNodes;
-
-	self->evaluatedShapeFunc = Memory_Alloc_Array( double, self->nodeCount, "evaluatedShapeFuncs" );
-	self->GNi = Memory_Alloc_2DArray( double, self->dim, self->nodeCount, (Name)"evaluatedShapeFuncDerivatives"  );
-}
-
-void _Triquadratic_Execute( void* elementType, void* data ) {
-}
-
-void _Triquadratic_Destroy( void* elementType, void* data ) {
-	Triquadratic*	self 		= (Triquadratic*)elementType;
-
-	Memory_Free( self->faceNodes );
-	Memory_Free( self->evaluatedShapeFunc );
-	Memory_Free( self->GNi );
-
-	_ElementType_Destroy( elementType, data );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-/*
-
- - Shape function definitions
- - Local node numbering convention for billinear, trilinear element (xi, eta, zeta)
- - Local coordinate domain spans  -1 <= xi,eta,zeta <= 1
-
-    eta
-     |
-     |____ xi
-    /
-   /
- zeta
-
-
-  eta
-   |
-3-----2
-|  |__|___xi
-|     |
-0-----1
-(zeta = -1 plane)
-
-
-  eta
-   |
-7-----6
-|  |__|___xi
-|     |
-4-----5
-(zeta = +1 plane)
-
-
-*/
-
-void Triquadratic_EvalBasis( void* elementType, const double* localCoord, double* basis ) {
-	double xi = localCoord[0], eta = localCoord[1], zeta = localCoord[2];
-	double a0 = xi - 1.0, b0 = eta - 1.0, c0 = zeta - 1.0;
-	double a1 = 1.0 - xi * xi, b1 = 1.0 - eta * eta, c1 = 1.0 - zeta * zeta;
-	double a2 = xi + 1.0, b2 = eta + 1.0, c2 = zeta + 1.0;
-	double m0 = 0.5 * xi;
-	double m1 = 0.5 * eta;
-	double m2 = 0.5 * zeta;
-	double m3 = 0.25 * xi * eta;
-	double m4 = 0.25 * xi * zeta;
-	double m5 = 0.25 * eta * zeta;
-	double m6 = 0.125 * xi * eta * zeta;
-
-	basis[0]  = m6 * a0 * b0 * c0;
-	basis[1]  = m5 * a1 * b0 * c0;
-	basis[2]  = m6 * a2 * b0 * c0;
-
-	basis[3]  = m4 * a0 * b1 * c0;
-	basis[4]  = m2 * a1 * b1 * c0;
-	basis[5]  = m4 * a2 * b1 * c0;
-
-	basis[6]  = m6 * a0 * b2 * c0;
-	basis[7]  = m5 * a1 * b2 * c0;
-	basis[8]  = m6 * a2 * b2 * c0;
-
-
-	basis[9]  = m3 * a0 * b0 * c1;
-	basis[10] = m1 * a1 * b0 * c1;
-	basis[11] = m3 * a2 * b0 * c1;
-
-	basis[12] = m0 * a0 * b1 * c1;
-	basis[13] =      a1 * b1 * c1;
-	basis[14] = m0 * a2 * b1 * c1;
-
-	basis[15] = m3 * a0 * b2 * c1;
-	basis[16] = m1 * a1 * b2 * c1;
-	basis[17] = m3 * a2 * b2 * c1;
-
-
-	basis[18] = m6 * a0 * b0 * c2;
-	basis[19] = m5 * a1 * b0 * c2;
-	basis[20] = m6 * a2 * b0 * c2;
-
-	basis[21] = m4 * a0 * b1 * c2;
-	basis[22] = m2 * a1 * b1 * c2;
-	basis[23] = m4 * a2 * b1 * c2;
-
-	basis[24] = m6 * a0 * b2 * c2;
-	basis[25] = m5 * a1 * b2 * c2;
-	basis[26] = m6 * a2 * b2 * c2;
-}
-
-void Triquadratic_EvalLocalDerivs( void* elementType, const double* localCoord, double** derivs ) {
-	double xi = localCoord[0], eta = localCoord[1], zeta = localCoord[2];
-	double a0 = xi - 1.0, b0 = eta - 1.0, c0 = zeta - 1.0;
-	double a1 = 1.0 - xi * xi, b1 = 1.0 - eta * eta, c1 = 1.0 - zeta * zeta;
-	double a2 = xi + 1.0, b2 = eta + 1.0, c2 = zeta + 1.0;
-	double m0 = 0.5 * xi;
-	double m1 = 0.5 * eta;
-	double m2 = 0.5 * zeta;
-	double m3 = 0.25 * xi * eta;
-	double m4 = 0.25 * xi * zeta;
-	double m5 = 0.25 * eta * zeta;
-	double a3 = xi - 0.5, b3 = eta - 0.5, c3 = zeta - 0.5;
-	double a4 = -2.0 * xi, b4 = -2.0 * eta, c4 = -2.0 * zeta;
-	double a5 = xi + 0.5, b5 = eta + 0.5, c5 = zeta + 0.5;
-
-	/* first face perp. to zeta */
-	derivs[0][0]  = a3 * m5 * b0 * c0;
-	derivs[1][0]  = b3 * m4 * a0 * c0;
-	derivs[2][0]  = c3 * m3 * a0 * b0;
-
-	derivs[0][1]  = a4 * m5 * b0 * c0;
-	derivs[1][1]  = b3 * m2 * a1 * c0;
-	derivs[2][1]  = c3 * m1 * a1 * b0;
-
-	derivs[0][2]  = a5 * m5 * b0 * c0;
-	derivs[1][2]  = b3 * m4 * a2 * c0;
-	derivs[2][2]  = c3 * m3 * a2 * b0;
-
-
-	derivs[0][3]  = a3 * m2 * b1 * c0;
-	derivs[1][3]  = b4 * m4 * a0 * c0;
-	derivs[2][3]  = c3 * m0 * a0 * b1;
-
-	derivs[0][4]  = a4 * m2 * b1 * c0;
-	derivs[1][4]  = b4 * m2 * a1 * c0;
-	derivs[2][4]  = c3 *      a1 * b1;
-
-	derivs[0][5]  = a5 * m2 * b1 * c0;
-	derivs[1][5]  = b4 * m4 * a2 * c0;
-	derivs[2][5]  = c3 * m0 * a2 * b1;
-
-
-	derivs[0][6]  = a3 * m5 * b2 * c0;
-	derivs[1][6]  = b5 * m4 * a0 * c0;
-	derivs[2][6]  = c3 * m3 * a0 * b2;
-
-	derivs[0][7]  = a4 * m5 * b2 * c0;
-	derivs[1][7]  = b5 * m2 * a1 * c0;
-	derivs[2][7]  = c3 * m1 * a1 * b2;
-
-	derivs[0][8]  = a5 * m5 * b2 * c0;
-	derivs[1][8]  = b5 * m4 * a2 * c0;
-	derivs[2][8]  = c3 * m3 * a2 * b2;
-
-	/* second face perp. to zeta */
-	derivs[0][9]  = a3 * m1 * b0 * c1;
-	derivs[1][9]  = b3 * m0 * a0 * c1;
-	derivs[2][9]  = c4 * m3 * a0 * b0;
-
-	derivs[0][10] = a4 * m1 * b0 * c1;
-	derivs[1][10] = b3 *      a1 * c1;
-	derivs[2][10] = c4 * m1 * a1 * b0;
-
-	derivs[0][11] = a5 * m1 * b0 * c1;
-	derivs[1][11] = b3 * m0 * a2 * c1;
-	derivs[2][11] = c4 * m3 * a2 * b0;
-
-
-	derivs[0][12] = a3 *      b1 * c1;
-	derivs[1][12] = b4 * m0 * a0 * c1;
-	derivs[2][12] = c4 * m0 * a0 * b1;
-
-	derivs[0][13] = a4 *      b1 * c1;
-	derivs[1][13] = b4 *      a1 * c1;
-	derivs[2][13] = c4 *      a1 * b1;
-
-	derivs[0][14] = a5 *      b1 * c1;
-	derivs[1][14] = b4 * m0 * a2 * c1;
-	derivs[2][14] = c4 * m0 * a2 * b1;
-
-
-	derivs[0][15] = a3 * m1 * b2 * c1;
-	derivs[1][15] = b5 * m0 * a0 * c1;
-	derivs[2][15] = c4 * m3 * a0 * b2;
-
-	derivs[0][16] = a4 * m1 * b2 * c1;
-	derivs[1][16] = b5 *      a1 * c1;
-	derivs[2][16] = c4 * m1 * a1 * b2;
-
-	derivs[0][17] = a5 * m1 * b2 * c1;
-	derivs[1][17] = b5 * m0 * a2 * c1;
-	derivs[2][17] = c4 * m3 * a2 * b2;
-
-	/* back face perp. to zeta */
-	derivs[0][18] = a3 * m5 * b0 * c2;
-	derivs[1][18] = b3 * m4 * a0 * c2;
-	derivs[2][18] = c5 * m3 * a0 * b0;
-
-	derivs[0][19] = a4 * m5 * b0 * c2;
-	derivs[1][19] = b3 * m2 * a1 * c2;
-	derivs[2][19] = c5 * m1 * a1 * b0;
-
-	derivs[0][20] = a5 * m5 * b0 * c2;
-	derivs[1][20] = b3 * m4 * a2 * c2;
-	derivs[2][20] = c5 * m3 * a2 * b0;
-
-
-	derivs[0][21] = a3 * m2 * b1 * c2;
-	derivs[1][21] = b4 * m4 * a0 * c2;
-	derivs[2][21] = c5 * m0 * a0 * b1;
-
-	derivs[0][22] = a4 * m2 * b1 * c2;
-	derivs[1][22] = b4 * m2 * a1 * c2;
-	derivs[2][22] = c5 *      a1 * b1;
-
-	derivs[0][23] = a5 * m2 * b1 * c2;
-	derivs[1][23] = b4 * m4 * a2 * c2;
-	derivs[2][23] = c5 * m0 * a2 * b1;
-
-
-	derivs[0][24] = a3 * m5 * b2 * c2;
-	derivs[1][24] = b5 * m4 * a0 * c2;
-	derivs[2][24] = c5 * m3 * a0 * b2;
-
-	derivs[0][25] = a4 * m5 * b2 * c2;
-	derivs[1][25] = b5 * m2 * a1 * c2;
-	derivs[2][25] = c5 * m1 * a1 * b2;
-
-	derivs[0][26] = a5 * m5 * b2 * c2;
-	derivs[1][26] = b5 * m4 * a2 * c2;
-	derivs[2][26] = c5 * m3 * a2 * b2;
-}
-
-double Triquadratic_JacobianDeterminantSurface( void* elementType, void* _mesh, unsigned element_I, const double localCoord[],
-	       					unsigned face_I, unsigned norm ) 
-{
-	Triquadratic*		self		= (Triquadratic*) elementType;
-	Mesh*			mesh		= (Mesh*)_mesh;
-	unsigned		surfaceDim[2];
-	double			x[9], y[9];
-	double			s, t;
-	double			dxds, dxdt, dyds, dydt;
-	double			detJac;
-	Index			node_i;
-	double			s0, s1, s2, t0, t1, t2;
-	double			ds0, ds1, ds2, dt0, dt1, dt2;
-	unsigned		nodes[9];
-
-	surfaceDim[0] = ( norm + 1 ) % 3;
-	surfaceDim[1] = ( norm + 2 ) % 3;
-
-	s = localCoord[surfaceDim[0]];
-	t = localCoord[surfaceDim[1]];
-
-	s0 = 0.5 * s * ( s - 1.0 ); s1 = 1.0 - s * s; s2 = 0.5 * s * ( s + 1.0 );
-	t0 = 0.5 * t * ( t - 1.0 ); t1 = 1.0 - t * t; t2 = 0.5 * t * ( t + 1.0 );
-
-	ds0 = s - 0.5; ds1 = -2.0 * s; ds2 = s + 0.5;
-	dt0 = t - 0.5; dt1 = -2.0 * t; dt2 = t + 0.5;
-
-	ElementType_GetFaceNodes( self, mesh, element_I, face_I, 9, nodes );
-
-	for( node_i = 0; node_i < 9; node_i++ ) {
-		x[node_i] = Mesh_GetVertex( mesh, nodes[node_i] )[surfaceDim[0]];
-		y[node_i] = Mesh_GetVertex( mesh, nodes[node_i] )[surfaceDim[1]];
-	}
-
-	dxds = ds0*t0*x[0] + ds1*t0*x[1] + ds2*t0*x[2] + ds0*t1*x[3] + ds1*t1*x[4] + ds2*t1*x[5] + ds0*t2*x[6] + ds1*t2*x[7] + ds2*t2*x[8];
-	dxdt = s0*dt0*x[0] + s1*dt0*x[1] + s2*dt0*x[2] + s0*dt1*x[3] + s1*dt1*x[4] + s2*dt1*x[5] + s0*dt2*x[6] + s1*dt2*x[8] + s2*dt2*x[8];
-	dyds = ds0*t0*y[0] + ds1*t0*y[1] + ds2*t0*y[2] + ds0*t1*y[3] + ds1*t1*y[4] + ds2*t1*y[5] + ds0*t2*y[6] + ds1*t2*y[7] + ds2*t2*y[8];
-	dydt = s0*dt0*y[0] + s1*dt0*y[1] + s2*dt0*y[2] + s0*dt1*y[3] + s1*dt1*y[4] + s2*dt1*y[5] + s0*dt2*y[6] + s1*dt2*y[8] + s2*dt2*y[8];
-
-	detJac = dxds * dydt - dxdt * dyds;
-
-	return fabs( detJac );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/src/Triquadratic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/src/Triquadratic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,446 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Dave Lee, Computational Engineer, VPAC. (dave at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Biquadratic.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation.h"
+
+#include "Triquadratic.h"
+
+/* Textual name of this class */
+const Type Triquadratic_Type = "Triquadratic";
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+#define TRIQUADRATICNODECOUNT 27
+
+Triquadratic* Triquadratic_New( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(Triquadratic);
+	Type                                                                                    type = Triquadratic_Type;
+	Stg_Class_DeleteFunction*                                                            _delete = _Triquadratic_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _Triquadratic_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = (void* (*)(Name))_Triquadratic_New;
+	Stg_Component_ConstructFunction*                                                  _construct = _Triquadratic_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _Triquadratic_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _Triquadratic_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _Triquadratic_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _Triquadratic_Destroy;
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = Triquadratic_EvalBasis;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = Triquadratic_EvalLocalDerivs;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = Triquadratic_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
+
+	return _Triquadratic_New(  TRIQUADRATIC_PASSARGS  );
+}
+
+Triquadratic* _Triquadratic_New(  TRIQUADRATIC_DEFARGS  ) {
+	Triquadratic*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Triquadratic) );
+	self = (Triquadratic*)_ElementType_New(  ELEMENTTYPE_PASSARGS  );
+
+	/* Virtual info */
+
+	/* Triquadratic info */
+	self->isConstructed = True;
+	_ElementType_Init( (ElementType*)self, TRIQUADRATICNODECOUNT );
+	_Triquadratic_Init( self );
+
+	return self;
+}
+
+void _Triquadratic_Init( Triquadratic* self ) {
+	assert( self && Stg_CheckType( self, Triquadratic ) );
+
+	self->dim = 3;
+}
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _Triquadratic_Delete( void* elementType ) {
+	Triquadratic*	self = (Triquadratic*)elementType;
+
+	/* Delete the parent */
+	_ElementType_Delete( self );
+}
+
+void _Triquadratic_Print( void* elementType, Stream* stream ) {
+	Triquadratic*	self = (Triquadratic*)elementType;
+
+	/* Set the Journal for printing informations */
+	Stream* elementTypeStream;
+	elementTypeStream = Journal_Register( InfoStream_Type, (Name)"TriquadraticStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "Triquadratic (ptr): (%p)\n", self );
+	_ElementType_Print( self, stream );
+}
+
+void _Triquadratic_AssignFromXML( void* elementType, Stg_ComponentFactory* cf, void* data ) {
+}
+
+void _Triquadratic_Build( void* elementType, void* data ) {
+}
+
+void _Triquadratic_Initialise( void* elementType, void* data ) {
+	Triquadratic*	self 		= (Triquadratic*)elementType;
+	unsigned**	faceNodes;
+
+	faceNodes = Memory_Alloc_2DArray( unsigned, 6, 9, (Name)"node indices for element faces"  );
+
+	faceNodes[0][0] =  0; faceNodes[0][1] =  1; faceNodes[0][2] =  2;
+	faceNodes[0][3] =  9; faceNodes[0][4] = 10; faceNodes[0][5] = 11;
+	faceNodes[0][6] = 18; faceNodes[0][7] = 19; faceNodes[0][8] = 20;
+
+	faceNodes[1][0] =  6; faceNodes[1][1] =  7; faceNodes[1][2] =  8;
+	faceNodes[1][3] = 15; faceNodes[1][4] = 16; faceNodes[1][5] = 17;
+	faceNodes[1][6] = 24; faceNodes[1][7] = 25; faceNodes[1][8] = 26;
+
+	faceNodes[2][0] =  0; faceNodes[2][1] =  9; faceNodes[2][2] = 18;
+	faceNodes[2][3] =  3; faceNodes[2][4] = 12; faceNodes[2][5] = 21;
+	faceNodes[2][6] =  6; faceNodes[2][7] = 15; faceNodes[2][8] = 24;
+
+	faceNodes[3][0] =  2; faceNodes[3][1] = 11; faceNodes[3][2] = 20;
+	faceNodes[3][3] =  5; faceNodes[3][4] = 14; faceNodes[3][5] = 23;
+	faceNodes[3][6] =  8; faceNodes[3][7] = 17; faceNodes[3][8] = 26;
+
+	faceNodes[4][0] =  0; faceNodes[4][1] =  1; faceNodes[4][2] =  2;
+	faceNodes[4][3] =  3; faceNodes[4][4] =  4; faceNodes[4][5] =  5;
+	faceNodes[4][6] =  6; faceNodes[4][7] =  7; faceNodes[4][8] =  8;
+
+	faceNodes[5][0] = 18; faceNodes[5][1] = 19; faceNodes[5][2] = 20;
+	faceNodes[5][3] = 21; faceNodes[5][4] = 22; faceNodes[5][5] = 23;
+	faceNodes[5][6] = 24; faceNodes[5][7] = 25; faceNodes[5][8] = 26;
+
+	self->faceNodes = faceNodes;
+
+	self->evaluatedShapeFunc = Memory_Alloc_Array( double, self->nodeCount, "evaluatedShapeFuncs" );
+	self->GNi = Memory_Alloc_2DArray( double, self->dim, self->nodeCount, (Name)"evaluatedShapeFuncDerivatives"  );
+}
+
+void _Triquadratic_Execute( void* elementType, void* data ) {
+}
+
+void _Triquadratic_Destroy( void* elementType, void* data ) {
+	Triquadratic*	self 		= (Triquadratic*)elementType;
+
+	Memory_Free( self->faceNodes );
+	Memory_Free( self->evaluatedShapeFunc );
+	Memory_Free( self->GNi );
+
+	_ElementType_Destroy( elementType, data );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+/*
+
+ - Shape function definitions
+ - Local node numbering convention for billinear, trilinear element (xi, eta, zeta)
+ - Local coordinate domain spans  -1 <= xi,eta,zeta <= 1
+
+    eta
+     |
+     |____ xi
+    /
+   /
+ zeta
+
+
+  eta
+   |
+3-----2
+|  |__|___xi
+|     |
+0-----1
+(zeta = -1 plane)
+
+
+  eta
+   |
+7-----6
+|  |__|___xi
+|     |
+4-----5
+(zeta = +1 plane)
+
+
+*/
+
+void Triquadratic_EvalBasis( void* elementType, const double* localCoord, double* basis ) {
+	double xi = localCoord[0], eta = localCoord[1], zeta = localCoord[2];
+	double a0 = xi - 1.0, b0 = eta - 1.0, c0 = zeta - 1.0;
+	double a1 = 1.0 - xi * xi, b1 = 1.0 - eta * eta, c1 = 1.0 - zeta * zeta;
+	double a2 = xi + 1.0, b2 = eta + 1.0, c2 = zeta + 1.0;
+	double m0 = 0.5 * xi;
+	double m1 = 0.5 * eta;
+	double m2 = 0.5 * zeta;
+	double m3 = 0.25 * xi * eta;
+	double m4 = 0.25 * xi * zeta;
+	double m5 = 0.25 * eta * zeta;
+	double m6 = 0.125 * xi * eta * zeta;
+
+	basis[0]  = m6 * a0 * b0 * c0;
+	basis[1]  = m5 * a1 * b0 * c0;
+	basis[2]  = m6 * a2 * b0 * c0;
+
+	basis[3]  = m4 * a0 * b1 * c0;
+	basis[4]  = m2 * a1 * b1 * c0;
+	basis[5]  = m4 * a2 * b1 * c0;
+
+	basis[6]  = m6 * a0 * b2 * c0;
+	basis[7]  = m5 * a1 * b2 * c0;
+	basis[8]  = m6 * a2 * b2 * c0;
+
+
+	basis[9]  = m3 * a0 * b0 * c1;
+	basis[10] = m1 * a1 * b0 * c1;
+	basis[11] = m3 * a2 * b0 * c1;
+
+	basis[12] = m0 * a0 * b1 * c1;
+	basis[13] =      a1 * b1 * c1;
+	basis[14] = m0 * a2 * b1 * c1;
+
+	basis[15] = m3 * a0 * b2 * c1;
+	basis[16] = m1 * a1 * b2 * c1;
+	basis[17] = m3 * a2 * b2 * c1;
+
+
+	basis[18] = m6 * a0 * b0 * c2;
+	basis[19] = m5 * a1 * b0 * c2;
+	basis[20] = m6 * a2 * b0 * c2;
+
+	basis[21] = m4 * a0 * b1 * c2;
+	basis[22] = m2 * a1 * b1 * c2;
+	basis[23] = m4 * a2 * b1 * c2;
+
+	basis[24] = m6 * a0 * b2 * c2;
+	basis[25] = m5 * a1 * b2 * c2;
+	basis[26] = m6 * a2 * b2 * c2;
+}
+
+void Triquadratic_EvalLocalDerivs( void* elementType, const double* localCoord, double** derivs ) {
+	double xi = localCoord[0], eta = localCoord[1], zeta = localCoord[2];
+	double a0 = xi - 1.0, b0 = eta - 1.0, c0 = zeta - 1.0;
+	double a1 = 1.0 - xi * xi, b1 = 1.0 - eta * eta, c1 = 1.0 - zeta * zeta;
+	double a2 = xi + 1.0, b2 = eta + 1.0, c2 = zeta + 1.0;
+	double m0 = 0.5 * xi;
+	double m1 = 0.5 * eta;
+	double m2 = 0.5 * zeta;
+	double m3 = 0.25 * xi * eta;
+	double m4 = 0.25 * xi * zeta;
+	double m5 = 0.25 * eta * zeta;
+	double a3 = xi - 0.5, b3 = eta - 0.5, c3 = zeta - 0.5;
+	double a4 = -2.0 * xi, b4 = -2.0 * eta, c4 = -2.0 * zeta;
+	double a5 = xi + 0.5, b5 = eta + 0.5, c5 = zeta + 0.5;
+
+	/* first face perp. to zeta */
+	derivs[0][0]  = a3 * m5 * b0 * c0;
+	derivs[1][0]  = b3 * m4 * a0 * c0;
+	derivs[2][0]  = c3 * m3 * a0 * b0;
+
+	derivs[0][1]  = a4 * m5 * b0 * c0;
+	derivs[1][1]  = b3 * m2 * a1 * c0;
+	derivs[2][1]  = c3 * m1 * a1 * b0;
+
+	derivs[0][2]  = a5 * m5 * b0 * c0;
+	derivs[1][2]  = b3 * m4 * a2 * c0;
+	derivs[2][2]  = c3 * m3 * a2 * b0;
+
+
+	derivs[0][3]  = a3 * m2 * b1 * c0;
+	derivs[1][3]  = b4 * m4 * a0 * c0;
+	derivs[2][3]  = c3 * m0 * a0 * b1;
+
+	derivs[0][4]  = a4 * m2 * b1 * c0;
+	derivs[1][4]  = b4 * m2 * a1 * c0;
+	derivs[2][4]  = c3 *      a1 * b1;
+
+	derivs[0][5]  = a5 * m2 * b1 * c0;
+	derivs[1][5]  = b4 * m4 * a2 * c0;
+	derivs[2][5]  = c3 * m0 * a2 * b1;
+
+
+	derivs[0][6]  = a3 * m5 * b2 * c0;
+	derivs[1][6]  = b5 * m4 * a0 * c0;
+	derivs[2][6]  = c3 * m3 * a0 * b2;
+
+	derivs[0][7]  = a4 * m5 * b2 * c0;
+	derivs[1][7]  = b5 * m2 * a1 * c0;
+	derivs[2][7]  = c3 * m1 * a1 * b2;
+
+	derivs[0][8]  = a5 * m5 * b2 * c0;
+	derivs[1][8]  = b5 * m4 * a2 * c0;
+	derivs[2][8]  = c3 * m3 * a2 * b2;
+
+	/* second face perp. to zeta */
+	derivs[0][9]  = a3 * m1 * b0 * c1;
+	derivs[1][9]  = b3 * m0 * a0 * c1;
+	derivs[2][9]  = c4 * m3 * a0 * b0;
+
+	derivs[0][10] = a4 * m1 * b0 * c1;
+	derivs[1][10] = b3 *      a1 * c1;
+	derivs[2][10] = c4 * m1 * a1 * b0;
+
+	derivs[0][11] = a5 * m1 * b0 * c1;
+	derivs[1][11] = b3 * m0 * a2 * c1;
+	derivs[2][11] = c4 * m3 * a2 * b0;
+
+
+	derivs[0][12] = a3 *      b1 * c1;
+	derivs[1][12] = b4 * m0 * a0 * c1;
+	derivs[2][12] = c4 * m0 * a0 * b1;
+
+	derivs[0][13] = a4 *      b1 * c1;
+	derivs[1][13] = b4 *      a1 * c1;
+	derivs[2][13] = c4 *      a1 * b1;
+
+	derivs[0][14] = a5 *      b1 * c1;
+	derivs[1][14] = b4 * m0 * a2 * c1;
+	derivs[2][14] = c4 * m0 * a2 * b1;
+
+
+	derivs[0][15] = a3 * m1 * b2 * c1;
+	derivs[1][15] = b5 * m0 * a0 * c1;
+	derivs[2][15] = c4 * m3 * a0 * b2;
+
+	derivs[0][16] = a4 * m1 * b2 * c1;
+	derivs[1][16] = b5 *      a1 * c1;
+	derivs[2][16] = c4 * m1 * a1 * b2;
+
+	derivs[0][17] = a5 * m1 * b2 * c1;
+	derivs[1][17] = b5 * m0 * a2 * c1;
+	derivs[2][17] = c4 * m3 * a2 * b2;
+
+	/* back face perp. to zeta */
+	derivs[0][18] = a3 * m5 * b0 * c2;
+	derivs[1][18] = b3 * m4 * a0 * c2;
+	derivs[2][18] = c5 * m3 * a0 * b0;
+
+	derivs[0][19] = a4 * m5 * b0 * c2;
+	derivs[1][19] = b3 * m2 * a1 * c2;
+	derivs[2][19] = c5 * m1 * a1 * b0;
+
+	derivs[0][20] = a5 * m5 * b0 * c2;
+	derivs[1][20] = b3 * m4 * a2 * c2;
+	derivs[2][20] = c5 * m3 * a2 * b0;
+
+
+	derivs[0][21] = a3 * m2 * b1 * c2;
+	derivs[1][21] = b4 * m4 * a0 * c2;
+	derivs[2][21] = c5 * m0 * a0 * b1;
+
+	derivs[0][22] = a4 * m2 * b1 * c2;
+	derivs[1][22] = b4 * m2 * a1 * c2;
+	derivs[2][22] = c5 *      a1 * b1;
+
+	derivs[0][23] = a5 * m2 * b1 * c2;
+	derivs[1][23] = b4 * m4 * a2 * c2;
+	derivs[2][23] = c5 * m0 * a2 * b1;
+
+
+	derivs[0][24] = a3 * m5 * b2 * c2;
+	derivs[1][24] = b5 * m4 * a0 * c2;
+	derivs[2][24] = c5 * m3 * a0 * b2;
+
+	derivs[0][25] = a4 * m5 * b2 * c2;
+	derivs[1][25] = b5 * m2 * a1 * c2;
+	derivs[2][25] = c5 * m1 * a1 * b2;
+
+	derivs[0][26] = a5 * m5 * b2 * c2;
+	derivs[1][26] = b5 * m4 * a2 * c2;
+	derivs[2][26] = c5 * m3 * a2 * b2;
+}
+
+double Triquadratic_JacobianDeterminantSurface( void* elementType, void* _mesh, unsigned element_I, const double localCoord[],
+	       					unsigned face_I, unsigned norm ) 
+{
+	Triquadratic*		self		= (Triquadratic*) elementType;
+	Mesh*			mesh		= (Mesh*)_mesh;
+	unsigned		surfaceDim[2];
+	double			x[9], y[9];
+	double			s, t;
+	double			dxds, dxdt, dyds, dydt;
+	double			detJac;
+	Index			node_i;
+	double			s0, s1, s2, t0, t1, t2;
+	double			ds0, ds1, ds2, dt0, dt1, dt2;
+	unsigned		nodes[9];
+
+	surfaceDim[0] = ( norm + 1 ) % 3;
+	surfaceDim[1] = ( norm + 2 ) % 3;
+
+	s = localCoord[surfaceDim[0]];
+	t = localCoord[surfaceDim[1]];
+
+	s0 = 0.5 * s * ( s - 1.0 ); s1 = 1.0 - s * s; s2 = 0.5 * s * ( s + 1.0 );
+	t0 = 0.5 * t * ( t - 1.0 ); t1 = 1.0 - t * t; t2 = 0.5 * t * ( t + 1.0 );
+
+	ds0 = s - 0.5; ds1 = -2.0 * s; ds2 = s + 0.5;
+	dt0 = t - 0.5; dt1 = -2.0 * t; dt2 = t + 0.5;
+
+	ElementType_GetFaceNodes( self, mesh, element_I, face_I, 9, nodes );
+
+	for( node_i = 0; node_i < 9; node_i++ ) {
+		x[node_i] = Mesh_GetVertex( mesh, nodes[node_i] )[surfaceDim[0]];
+		y[node_i] = Mesh_GetVertex( mesh, nodes[node_i] )[surfaceDim[1]];
+	}
+
+	dxds = ds0*t0*x[0] + ds1*t0*x[1] + ds2*t0*x[2] + ds0*t1*x[3] + ds1*t1*x[4] + ds2*t1*x[5] + ds0*t2*x[6] + ds1*t2*x[7] + ds2*t2*x[8];
+	dxdt = s0*dt0*x[0] + s1*dt0*x[1] + s2*dt0*x[2] + s0*dt1*x[3] + s1*dt1*x[4] + s2*dt1*x[5] + s0*dt2*x[6] + s1*dt2*x[8] + s2*dt2*x[8];
+	dyds = ds0*t0*y[0] + ds1*t0*y[1] + ds2*t0*y[2] + ds0*t1*y[3] + ds1*t1*y[4] + ds2*t1*y[5] + ds0*t2*y[6] + ds1*t2*y[7] + ds2*t2*y[8];
+	dydt = s0*dt0*y[0] + s1*dt0*y[1] + s2*dt0*y[2] + s0*dt1*y[3] + s1*dt1*y[4] + s2*dt1*y[5] + s0*dt2*y[6] + s1*dt2*y[8] + s2*dt2*y[8];
+
+	detJac = dxds * dydt - dxdt * dyds;
+
+	return fabs( detJac );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/C2GeneratorSuite.c
--- a/Discretisation/tests/C2GeneratorSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,681 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** Role:
-**   Tests the C2GeneratorSuite
-**
-** $Id: testTemplate.c 3462 2006-02-19 06:53:24Z WalterLandry $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include "C2GeneratorSuite.h"
-
-typedef struct {
-	Mesh*	mesh;
-} C2GeneratorSuiteData;
-
-void C2GeneratorSuite_Setup( C2GeneratorSuiteData* data ) {
-	C2Generator* gen;
-	int nRanks;
-	unsigned sizes[3];
-	double minCrd[3];
-	double maxCrd[3];
-
-	Journal_Enable_AllTypedStream( False );
-
-	insist( MPI_Comm_size( MPI_COMM_WORLD, &nRanks ), == MPI_SUCCESS );
-	sizes[0] = sizes[1] = sizes[2] = nRanks * 4;
-	minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
-	maxCrd[0] = minCrd[1] = minCrd[2] = (double)nRanks;
-
-	gen = C2Generator_New( "", NULL );
-	MeshGenerator_SetDimSize( gen, 3 );
-	CartesianGenerator_SetShadowDepth( gen, 1 );
-	C2Generator_SetTopologyParams( gen, sizes, 0, NULL, NULL );
-	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-   Stg_Component_Build( gen, NULL, False );
-   Stg_Component_Initialise( gen, NULL, False );
-
-	data->mesh = Mesh_New( "", NULL );
-	CartesianGenerator_Generate( gen, data->mesh, NULL );
-   /* need 2 lines below to setup mesh */
-   Stg_Component_Build( data->mesh, NULL, False );
-   Stg_Component_Initialise( data->mesh, NULL, False );
-}
-
-void C2GeneratorSuite_Teardown( C2GeneratorSuiteData* data ) {
-	Stg_Component_Destroy( data->mesh, NULL, True );
-}
-
-void C2GeneratorSuite_TestElementVertexInc( C2GeneratorSuiteData* data ) {
-	unsigned	dim		= Mesh_GetDimSize( data->mesh );
-	Sync*		elSync		= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, dim );
-	Sync*		vertSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_VERTEX );
-	Grid*		elGrid		= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "elementGrid" );
-	Grid*		vertGrid	= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "vertexGrid" );
-	IArray*		inc		= IArray_New();
-	unsigned*	incVerts;
-	unsigned	nIncVerts;
-	unsigned	el_i;
-	unsigned	gEl;
-	unsigned	dimInds[3];
-	unsigned	gNode0, gNode1, gNode2;
-	int		checkNodes;
-
-	for( el_i = 0; el_i < Mesh_GetLocalSize( data->mesh, (MeshTopology_Dim)dim ); el_i++ ) {
-		gEl = Sync_DomainToGlobal( elSync, el_i );
-		Grid_Lift( elGrid, gEl, dimInds );
-		dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
-
-		MeshTopology_GetIncidence( (IGraph*)data->mesh->topo, dim, el_i, MT_VERTEX, inc );
-		nIncVerts = IArray_GetSize( inc );
-		incVerts = (unsigned*)IArray_GetPtr( inc );
-
-		pcu_check_true( nIncVerts == 27 );
-
-		gNode0 = Grid_Project( vertGrid, dimInds );
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
-		dimInds[0] -= 2; dimInds[1]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[3] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[4] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[5] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
-		dimInds[0] -= 2; dimInds[1]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[6] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[7] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[8] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0 -= 2; gNode0 -= 2 * vertGrid->sizes[0]; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
-		dimInds[0] -= 2; dimInds[1] -= 2; dimInds[2]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[9] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[10] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[11] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
-		dimInds[0] -= 2; dimInds[1]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[12] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[13] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[14] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
-		dimInds[0] -= 2; dimInds[1]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[15] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[16] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[17] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0 -= 2; gNode0 -= 2 * vertGrid->sizes[0]; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
-		dimInds[0] -= 2; dimInds[1] -= 2; dimInds[2]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[18] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[19] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[20] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
-		dimInds[0] -= 2; dimInds[1]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[21] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[22] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[23] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
-		dimInds[0] -= 2; dimInds[1]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[24] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[25] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-
-		gNode0++;
-		dimInds[0]++;
-		gNode1 = Grid_Project( vertGrid, dimInds );
-		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[26] );
-		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-		pcu_check_true( checkNodes );
-	}
-
-	NewClass_Delete( inc );
-}
-
-void C2GeneratorSuite_TestEdgeVertexInc( C2GeneratorSuiteData* data ) {
-	Grid*		elGrid		= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "elementGrid" );
-	Grid*		vertGrid	= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "vertexGrid" );
-	Grid*		edgeGrid_0	= Grid_New();
-	Grid*		edgeGrid_1	= Grid_New();
-	Grid*		edgeGrid_2	= Grid_New();
-	Sync*		vertSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_VERTEX );
-	Sync*		edgeSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_EDGE );
-	IArray*		inc		= IArray_New();
-	unsigned*	incVerts;
-	unsigned	nIncVerts;
-	unsigned	dim		= ((IGraph*)data->mesh->topo)->nDims;
-	unsigned	sizes[3];
-	unsigned	edge_i;
-	unsigned	gEdge;
-	unsigned	dimInds[3];
-	unsigned	gNode0, gNode1, gNode2;
-	int		checkNodes;
-
-	sizes[0] = elGrid->sizes[0];
-	sizes[1] = elGrid->sizes[1] + 1;
-	sizes[2] = elGrid->sizes[2] + 1;
-	Grid_SetNumDims( edgeGrid_0, dim );
-	Grid_SetSizes( edgeGrid_0, sizes );
-	sizes[0] = elGrid->sizes[0] + 1;
-	sizes[1] = elGrid->sizes[1];
-	sizes[2] = elGrid->sizes[2] + 1;
-	Grid_SetNumDims( edgeGrid_1, dim );
-	Grid_SetSizes( edgeGrid_1, sizes );
-	sizes[0] = elGrid->sizes[0] + 1;
-	sizes[1] = elGrid->sizes[1] + 1;
-	sizes[2] = elGrid->sizes[2];
-	Grid_SetNumDims( edgeGrid_2, dim );
-	Grid_SetSizes( edgeGrid_2, sizes );
-
-	for( edge_i = 0; edge_i < Sync_GetNumDomains( edgeSync ); edge_i++ ) {
-		gEdge = Sync_DomainToGlobal( edgeSync, edge_i );
-
-		MeshTopology_GetIncidence( (IGraph*)data->mesh->topo, MT_EDGE, edge_i, MT_VERTEX, inc );
-		nIncVerts = IArray_GetSize( inc );
-		incVerts = (unsigned*)IArray_GetPtr( inc );
-
-		pcu_check_true( nIncVerts == 3 );
-
-		if( gEdge < edgeGrid_0->nPoints ) {
-			Grid_Lift( edgeGrid_0, gEdge, dimInds );
-			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
-
-			gNode0 = Grid_Project( vertGrid, dimInds );
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-		}
-		else if( gEdge < edgeGrid_0->nPoints + edgeGrid_1->nPoints ) {
-			Grid_Lift( edgeGrid_1, gEdge - edgeGrid_0->nPoints, dimInds );
-			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
-
-			gNode0 = Grid_Project( vertGrid, dimInds );
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0];
-			dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0];
-			dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-		}
-		else if( gEdge < edgeGrid_0->nPoints + edgeGrid_1->nPoints + edgeGrid_2->nPoints ) {
-			Grid_Lift( edgeGrid_2, gEdge - edgeGrid_0->nPoints - edgeGrid_1->nPoints, dimInds );
-			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
-
-			gNode0 = Grid_Project( vertGrid, dimInds );
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
-			dimInds[2]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
-			dimInds[2]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-		}
-	}
-
-	FreeObject( edgeGrid_0 );
-	FreeObject( edgeGrid_1 );
-	FreeObject( edgeGrid_2 );
-
-	NewClass_Delete( inc );
-}
-
-void C2GeneratorSuite_TestFaceVertexInc( C2GeneratorSuiteData* data ) {
-	Grid*		elGrid		= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "elementGrid" );
-	Grid*		vertGrid	= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "vertexGrid" );
-	Grid*		faceGrid_0	= Grid_New();
-	Grid*		faceGrid_1	= Grid_New();
-	Grid*		faceGrid_2	= Grid_New();
-	Sync*		vertSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_VERTEX );
-	Sync*		faceSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_FACE );
-	IArray*		inc		= IArray_New();
-	unsigned*	incVerts;
-	unsigned	nIncVerts;
-	unsigned	dim		= ((IGraph*)data->mesh->topo)->nDims;
-	unsigned	sizes[3];
-	unsigned	face_i;
-	unsigned	gFace;
-	unsigned	dimInds[3];
-	unsigned	gNode0, gNode1, gNode2;
-	int		checkNodes;
-
-	sizes[0] = elGrid->sizes[0];
-	sizes[1] = elGrid->sizes[1];
-	sizes[2] = elGrid->sizes[2] + 1;
-	Grid_SetNumDims( faceGrid_0, dim );
-	Grid_SetSizes( faceGrid_0, sizes );
-	sizes[0] = elGrid->sizes[0];
-	sizes[1] = elGrid->sizes[1] + 1;
-	sizes[2] = elGrid->sizes[2];
-	Grid_SetNumDims( faceGrid_1, dim );
-	Grid_SetSizes( faceGrid_1, sizes );
-	sizes[0] = elGrid->sizes[0] + 1;
-	sizes[1] = elGrid->sizes[1];
-	sizes[2] = elGrid->sizes[2];
-	Grid_SetNumDims( faceGrid_2, dim );
-	Grid_SetSizes( faceGrid_2, sizes );
-
-	for( face_i = 0; face_i < ((IGraph*)data->mesh->topo)->remotes[MT_FACE]->nDomains; face_i++ ) {
-		gFace = Sync_DomainToGlobal( faceSync, face_i );
-
-		MeshTopology_GetIncidence( (IGraph*)data->mesh->topo, MT_FACE, face_i, MT_VERTEX, inc );
-		nIncVerts = IArray_GetSize( inc );
-		incVerts = (unsigned*)IArray_GetPtr( inc );
-
-		pcu_check_true( nIncVerts == 9 );
-
-		if( gFace < faceGrid_0->nPoints ) {
-			Grid_Lift( faceGrid_0, gFace, dimInds );
-			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
-
-			gNode0 = Grid_Project( vertGrid, dimInds );
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 -= 2; gNode0 += vertGrid->sizes[0];
-			dimInds[0] -= 2; dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[3] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[4] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[5] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 -= 2; gNode0 += vertGrid->sizes[0];
-			dimInds[0] -= 2; dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[6] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[7] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-			
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[8] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-		}
-		else if( gFace < faceGrid_0->nPoints + faceGrid_1->nPoints ) {
-			Grid_Lift( faceGrid_1, gFace - faceGrid_0->nPoints, dimInds );
-			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
-
-			gNode0 = Grid_Project( vertGrid, dimInds );
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 -= 2; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
-			dimInds[0] -= 2; dimInds[2]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[3] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[4] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[5] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 -= 2; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
-			dimInds[0] -= 2; dimInds[2]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[6] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[7] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0++;
-			dimInds[0]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[8] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-		}
-		else if( gFace < faceGrid_0->nPoints + faceGrid_1->nPoints + faceGrid_2->nPoints ) {
-			Grid_Lift( faceGrid_2, gFace - faceGrid_0->nPoints - faceGrid_1->nPoints, dimInds );
-			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
-
-			gNode0 = Grid_Project( vertGrid, dimInds );
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0];
-			dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0];
-			dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 -= 2 * vertGrid->sizes[0]; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
-			dimInds[1] -= 2; dimInds[2]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[3] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0];
-			dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[4] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0];
-			dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[5] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 -= 2 * vertGrid->sizes[0]; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
-			dimInds[1] -= 2; dimInds[2]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[6] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0];
-			dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[7] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-
-			gNode0 += vertGrid->sizes[0];
-			dimInds[1]++;
-			gNode1 = Grid_Project( vertGrid, dimInds );
-			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[8] );
-			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
-			pcu_check_true( checkNodes );
-		}
-	}
-
-	FreeObject( faceGrid_0 );
-	FreeObject( faceGrid_1 );
-	FreeObject( faceGrid_2 );
-
-	NewClass_Delete( inc );
-}
-void C2GeneratorSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, C2GeneratorSuiteData );
-   pcu_suite_setFixtures( suite, C2GeneratorSuite_Setup, C2GeneratorSuite_Teardown );
-   pcu_suite_addTest( suite, C2GeneratorSuite_TestElementVertexInc );
-   pcu_suite_addTest( suite, C2GeneratorSuite_TestEdgeVertexInc );
-   pcu_suite_addTest( suite, C2GeneratorSuite_TestFaceVertexInc );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/C2GeneratorSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/tests/C2GeneratorSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,681 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** Role:
+**   Tests the C2GeneratorSuite
+**
+** $Id: testTemplate.c 3462 2006-02-19 06:53:24Z WalterLandry $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include "C2GeneratorSuite.h"
+
+typedef struct {
+	Mesh*	mesh;
+} C2GeneratorSuiteData;
+
+void C2GeneratorSuite_Setup( C2GeneratorSuiteData* data ) {
+	C2Generator* gen;
+	int nRanks;
+	unsigned sizes[3];
+	double minCrd[3];
+	double maxCrd[3];
+
+	Journal_Enable_AllTypedStream( False );
+
+	insist( MPI_Comm_size( MPI_COMM_WORLD, &nRanks ), == MPI_SUCCESS );
+	sizes[0] = sizes[1] = sizes[2] = nRanks * 4;
+	minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
+	maxCrd[0] = minCrd[1] = minCrd[2] = (double)nRanks;
+
+	gen = C2Generator_New( "", NULL );
+	MeshGenerator_SetDimSize( gen, 3 );
+	CartesianGenerator_SetShadowDepth( gen, 1 );
+	C2Generator_SetTopologyParams( gen, sizes, 0, NULL, NULL );
+	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+   Stg_Component_Build( gen, NULL, False );
+   Stg_Component_Initialise( gen, NULL, False );
+
+	data->mesh = Mesh_New( "", NULL );
+	CartesianGenerator_Generate( gen, data->mesh, NULL );
+   /* need 2 lines below to setup mesh */
+   Stg_Component_Build( data->mesh, NULL, False );
+   Stg_Component_Initialise( data->mesh, NULL, False );
+}
+
+void C2GeneratorSuite_Teardown( C2GeneratorSuiteData* data ) {
+	Stg_Component_Destroy( data->mesh, NULL, True );
+}
+
+void C2GeneratorSuite_TestElementVertexInc( C2GeneratorSuiteData* data ) {
+	unsigned	dim		= Mesh_GetDimSize( data->mesh );
+	Sync*		elSync		= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, dim );
+	Sync*		vertSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_VERTEX );
+	Grid*		elGrid		= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "elementGrid" );
+	Grid*		vertGrid	= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "vertexGrid" );
+	IArray*		inc		= IArray_New();
+	unsigned*	incVerts;
+	unsigned	nIncVerts;
+	unsigned	el_i;
+	unsigned	gEl;
+	unsigned	dimInds[3];
+	unsigned	gNode0, gNode1, gNode2;
+	int		checkNodes;
+
+	for( el_i = 0; el_i < Mesh_GetLocalSize( data->mesh, (MeshTopology_Dim)dim ); el_i++ ) {
+		gEl = Sync_DomainToGlobal( elSync, el_i );
+		Grid_Lift( elGrid, gEl, dimInds );
+		dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
+
+		MeshTopology_GetIncidence( (IGraph*)data->mesh->topo, dim, el_i, MT_VERTEX, inc );
+		nIncVerts = IArray_GetSize( inc );
+		incVerts = (unsigned*)IArray_GetPtr( inc );
+
+		pcu_check_true( nIncVerts == 27 );
+
+		gNode0 = Grid_Project( vertGrid, dimInds );
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
+		dimInds[0] -= 2; dimInds[1]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[3] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[4] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[5] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
+		dimInds[0] -= 2; dimInds[1]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[6] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[7] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[8] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0 -= 2; gNode0 -= 2 * vertGrid->sizes[0]; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
+		dimInds[0] -= 2; dimInds[1] -= 2; dimInds[2]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[9] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[10] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[11] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
+		dimInds[0] -= 2; dimInds[1]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[12] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[13] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[14] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
+		dimInds[0] -= 2; dimInds[1]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[15] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[16] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[17] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0 -= 2; gNode0 -= 2 * vertGrid->sizes[0]; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
+		dimInds[0] -= 2; dimInds[1] -= 2; dimInds[2]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[18] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[19] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[20] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
+		dimInds[0] -= 2; dimInds[1]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[21] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[22] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[23] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0 -= 2; gNode0 += vertGrid->sizes[0];
+		dimInds[0] -= 2; dimInds[1]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[24] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[25] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+
+		gNode0++;
+		dimInds[0]++;
+		gNode1 = Grid_Project( vertGrid, dimInds );
+		gNode2 = Sync_DomainToGlobal( vertSync, incVerts[26] );
+		checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+		pcu_check_true( checkNodes );
+	}
+
+	NewClass_Delete( inc );
+}
+
+void C2GeneratorSuite_TestEdgeVertexInc( C2GeneratorSuiteData* data ) {
+	Grid*		elGrid		= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "elementGrid" );
+	Grid*		vertGrid	= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "vertexGrid" );
+	Grid*		edgeGrid_0	= Grid_New();
+	Grid*		edgeGrid_1	= Grid_New();
+	Grid*		edgeGrid_2	= Grid_New();
+	Sync*		vertSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_VERTEX );
+	Sync*		edgeSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_EDGE );
+	IArray*		inc		= IArray_New();
+	unsigned*	incVerts;
+	unsigned	nIncVerts;
+	unsigned	dim		= ((IGraph*)data->mesh->topo)->nDims;
+	unsigned	sizes[3];
+	unsigned	edge_i;
+	unsigned	gEdge;
+	unsigned	dimInds[3];
+	unsigned	gNode0, gNode1, gNode2;
+	int		checkNodes;
+
+	sizes[0] = elGrid->sizes[0];
+	sizes[1] = elGrid->sizes[1] + 1;
+	sizes[2] = elGrid->sizes[2] + 1;
+	Grid_SetNumDims( edgeGrid_0, dim );
+	Grid_SetSizes( edgeGrid_0, sizes );
+	sizes[0] = elGrid->sizes[0] + 1;
+	sizes[1] = elGrid->sizes[1];
+	sizes[2] = elGrid->sizes[2] + 1;
+	Grid_SetNumDims( edgeGrid_1, dim );
+	Grid_SetSizes( edgeGrid_1, sizes );
+	sizes[0] = elGrid->sizes[0] + 1;
+	sizes[1] = elGrid->sizes[1] + 1;
+	sizes[2] = elGrid->sizes[2];
+	Grid_SetNumDims( edgeGrid_2, dim );
+	Grid_SetSizes( edgeGrid_2, sizes );
+
+	for( edge_i = 0; edge_i < Sync_GetNumDomains( edgeSync ); edge_i++ ) {
+		gEdge = Sync_DomainToGlobal( edgeSync, edge_i );
+
+		MeshTopology_GetIncidence( (IGraph*)data->mesh->topo, MT_EDGE, edge_i, MT_VERTEX, inc );
+		nIncVerts = IArray_GetSize( inc );
+		incVerts = (unsigned*)IArray_GetPtr( inc );
+
+		pcu_check_true( nIncVerts == 3 );
+
+		if( gEdge < edgeGrid_0->nPoints ) {
+			Grid_Lift( edgeGrid_0, gEdge, dimInds );
+			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
+
+			gNode0 = Grid_Project( vertGrid, dimInds );
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+		}
+		else if( gEdge < edgeGrid_0->nPoints + edgeGrid_1->nPoints ) {
+			Grid_Lift( edgeGrid_1, gEdge - edgeGrid_0->nPoints, dimInds );
+			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
+
+			gNode0 = Grid_Project( vertGrid, dimInds );
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0];
+			dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0];
+			dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+		}
+		else if( gEdge < edgeGrid_0->nPoints + edgeGrid_1->nPoints + edgeGrid_2->nPoints ) {
+			Grid_Lift( edgeGrid_2, gEdge - edgeGrid_0->nPoints - edgeGrid_1->nPoints, dimInds );
+			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
+
+			gNode0 = Grid_Project( vertGrid, dimInds );
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
+			dimInds[2]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
+			dimInds[2]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+		}
+	}
+
+	FreeObject( edgeGrid_0 );
+	FreeObject( edgeGrid_1 );
+	FreeObject( edgeGrid_2 );
+
+	NewClass_Delete( inc );
+}
+
+void C2GeneratorSuite_TestFaceVertexInc( C2GeneratorSuiteData* data ) {
+	Grid*		elGrid		= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "elementGrid" );
+	Grid*		vertGrid	= *(Grid**)Mesh_GetExtension( data->mesh, Grid**, "vertexGrid" );
+	Grid*		faceGrid_0	= Grid_New();
+	Grid*		faceGrid_1	= Grid_New();
+	Grid*		faceGrid_2	= Grid_New();
+	Sync*		vertSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_VERTEX );
+	Sync*		faceSync	= (Sync*)IGraph_GetDomain( (IGraph*)data->mesh->topo, MT_FACE );
+	IArray*		inc		= IArray_New();
+	unsigned*	incVerts;
+	unsigned	nIncVerts;
+	unsigned	dim		= ((IGraph*)data->mesh->topo)->nDims;
+	unsigned	sizes[3];
+	unsigned	face_i;
+	unsigned	gFace;
+	unsigned	dimInds[3];
+	unsigned	gNode0, gNode1, gNode2;
+	int		checkNodes;
+
+	sizes[0] = elGrid->sizes[0];
+	sizes[1] = elGrid->sizes[1];
+	sizes[2] = elGrid->sizes[2] + 1;
+	Grid_SetNumDims( faceGrid_0, dim );
+	Grid_SetSizes( faceGrid_0, sizes );
+	sizes[0] = elGrid->sizes[0];
+	sizes[1] = elGrid->sizes[1] + 1;
+	sizes[2] = elGrid->sizes[2];
+	Grid_SetNumDims( faceGrid_1, dim );
+	Grid_SetSizes( faceGrid_1, sizes );
+	sizes[0] = elGrid->sizes[0] + 1;
+	sizes[1] = elGrid->sizes[1];
+	sizes[2] = elGrid->sizes[2];
+	Grid_SetNumDims( faceGrid_2, dim );
+	Grid_SetSizes( faceGrid_2, sizes );
+
+	for( face_i = 0; face_i < ((IGraph*)data->mesh->topo)->remotes[MT_FACE]->nDomains; face_i++ ) {
+		gFace = Sync_DomainToGlobal( faceSync, face_i );
+
+		MeshTopology_GetIncidence( (IGraph*)data->mesh->topo, MT_FACE, face_i, MT_VERTEX, inc );
+		nIncVerts = IArray_GetSize( inc );
+		incVerts = (unsigned*)IArray_GetPtr( inc );
+
+		pcu_check_true( nIncVerts == 9 );
+
+		if( gFace < faceGrid_0->nPoints ) {
+			Grid_Lift( faceGrid_0, gFace, dimInds );
+			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
+
+			gNode0 = Grid_Project( vertGrid, dimInds );
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 -= 2; gNode0 += vertGrid->sizes[0];
+			dimInds[0] -= 2; dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[3] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[4] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[5] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 -= 2; gNode0 += vertGrid->sizes[0];
+			dimInds[0] -= 2; dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[6] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[7] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+			
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[8] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+		}
+		else if( gFace < faceGrid_0->nPoints + faceGrid_1->nPoints ) {
+			Grid_Lift( faceGrid_1, gFace - faceGrid_0->nPoints, dimInds );
+			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
+
+			gNode0 = Grid_Project( vertGrid, dimInds );
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 -= 2; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
+			dimInds[0] -= 2; dimInds[2]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[3] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[4] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[5] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 -= 2; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
+			dimInds[0] -= 2; dimInds[2]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[6] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[7] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0++;
+			dimInds[0]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[8] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+		}
+		else if( gFace < faceGrid_0->nPoints + faceGrid_1->nPoints + faceGrid_2->nPoints ) {
+			Grid_Lift( faceGrid_2, gFace - faceGrid_0->nPoints - faceGrid_1->nPoints, dimInds );
+			dimInds[0] *= 2; dimInds[1] *= 2; dimInds[2] *= 2;
+
+			gNode0 = Grid_Project( vertGrid, dimInds );
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[0] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0];
+			dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[1] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0];
+			dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[2] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 -= 2 * vertGrid->sizes[0]; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
+			dimInds[1] -= 2; dimInds[2]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[3] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0];
+			dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[4] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0];
+			dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[5] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 -= 2 * vertGrid->sizes[0]; gNode0 += vertGrid->sizes[0] * vertGrid->sizes[1];
+			dimInds[1] -= 2; dimInds[2]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[6] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0];
+			dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[7] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+
+			gNode0 += vertGrid->sizes[0];
+			dimInds[1]++;
+			gNode1 = Grid_Project( vertGrid, dimInds );
+			gNode2 = Sync_DomainToGlobal( vertSync, incVerts[8] );
+			checkNodes = (gNode0 == gNode1) && (gNode1 == gNode2);
+			pcu_check_true( checkNodes );
+		}
+	}
+
+	FreeObject( faceGrid_0 );
+	FreeObject( faceGrid_1 );
+	FreeObject( faceGrid_2 );
+
+	NewClass_Delete( inc );
+}
+void C2GeneratorSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, C2GeneratorSuiteData );
+   pcu_suite_setFixtures( suite, C2GeneratorSuite_Setup, C2GeneratorSuite_Teardown );
+   pcu_suite_addTest( suite, C2GeneratorSuite_TestElementVertexInc );
+   pcu_suite_addTest( suite, C2GeneratorSuite_TestEdgeVertexInc );
+   pcu_suite_addTest( suite, C2GeneratorSuite_TestFaceVertexInc );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/ElementTypeRegisterSuite.c
--- a/Discretisation/tests/ElementTypeRegisterSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** Role:
-**   Tests the ElementTypeRegisterSuite
-**
-** $Id: testElementTypeRegister.c 3462 2006-02-19 06:53:24Z WalterLandry $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include "ElementTypeRegisterSuite.h"
-
-typedef struct {
-	ElementType_Register*	etReg;
-} ElementTypeRegisterSuiteData;
-
-void ElementTypeRegisterSuite_Setup( ElementTypeRegisterSuiteData* data ) {
-	data->etReg = ElementType_Register_New( "elementType_Register" );
-
-	Journal_Enable_AllTypedStream( False );
-
-	_ElementType_Register_Init( data->etReg );
-
-	ElementType_Register_Add( data->etReg, (ElementType*)ConstantElementType_New( "constant" ) );
-	ElementType_Register_Add( data->etReg, (ElementType*)BilinearElementType_New( "bilinear" ) );
-	ElementType_Register_Add( data->etReg, (ElementType*)TrilinearElementType_New( "trilinear" ) );
-	ElementType_Register_Add( data->etReg, (ElementType*)Biquadratic_New( "biquadratic" ) );
-	ElementType_Register_Add( data->etReg, (ElementType*)Triquadratic_New( "triquadratic" ) );
-}
-
-void ElementTypeRegisterSuite_Teardown( ElementTypeRegisterSuiteData* data ) {
-	Stg_Class_Delete( data->etReg );
-}
-
-void ElementTypeRegisterSuite_Test( ElementTypeRegisterSuiteData* data ) {
-	/* Variables set in this function */
-	SizeT                                                                            _sizeOfSelf = sizeof(ConstantElementType);
-	Type                                                                                    type = "TestElementType_0";
-	Stg_Class_DeleteFunction*                                                            _delete = _ConstantElementType_Delete;
-	Stg_Class_PrintFunction*                                                              _print = _ConstantElementType_Print;
-	Stg_Class_CopyFunction*                                                                _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = ConstantElementType_DefaultNew;
-	Stg_Component_ConstructFunction*                                                  _construct = _ConstantElementType_AssignFromXML;
-	Stg_Component_BuildFunction*                                                          _build = _ConstantElementType_Build;
-	Stg_Component_InitialiseFunction*                                                _initialise = _ConstantElementType_Initialise;
-	Stg_Component_ExecuteFunction*                                                      _execute = _ConstantElementType_Execute;
-	Stg_Component_DestroyFunction*                                                      _destroy = _ConstantElementType_Destroy;
-	Name                                                                                    name = "TestElementType_0_Name";
-	AllocationType                                                            nameAllocationType = NON_GLOBAL;
-	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _ConstantElementType_SF_allNodes;
-	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _ConstantElementType_SF_allLocalDerivs_allNodes;
-	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ConstantElementType_ConvertGlobalCoordToElLocal;
-	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
-	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
-
-	ElementType* elType;
-	//unsigned	numTypes	= data->etReg->count;
-	unsigned	newIndex;
-	unsigned	testIndex;
-	
-	/* manually create extra types to test the list re-sizing */
-	newIndex = ElementType_Register_Add( data->etReg, _ElementType_New(  ELEMENTTYPE_PASSARGS  ) );
-	pcu_check_true( newIndex == data->etReg->count - 1 );
-	
-	type = "TestElementType_1";
-	name = "TestElementType_1_Name";
-
-	newIndex = ElementType_Register_Add( data->etReg, _ElementType_New(  ELEMENTTYPE_PASSARGS  ) );
-	pcu_check_true( newIndex == data->etReg->count - 1 );
-
-	type = "TestElementType_2";
-	name = "TestElementType_2_Name";
-
-	newIndex = ElementType_Register_Add( data->etReg, _ElementType_New(  ELEMENTTYPE_PASSARGS  ) );
-	pcu_check_true( newIndex == data->etReg->count - 1 );
-
-	testIndex = ElementType_Register_GetIndex( data->etReg, ConstantElementType_Type );
-	elType    = ElementType_Register_At( data->etReg, testIndex );
-	pcu_check_true( !strcmp( elType->type, ConstantElementType_Type ) );
-
-	testIndex = ElementType_Register_GetIndex( data->etReg, BilinearElementType_Type );
-	elType    = ElementType_Register_At( data->etReg, testIndex );
-	pcu_check_true( !strcmp( elType->type, BilinearElementType_Type ) );
-
-	testIndex = ElementType_Register_GetIndex( data->etReg, TrilinearElementType_Type );
-	elType    = ElementType_Register_At( data->etReg, testIndex );
-	pcu_check_true( !strcmp( elType->type, TrilinearElementType_Type ) );
-
-	testIndex = ElementType_Register_GetIndex( data->etReg, Biquadratic_Type );
-	elType    = ElementType_Register_At( data->etReg, testIndex );
-	pcu_check_true( !strcmp( elType->type, Biquadratic_Type ) );
-
-	testIndex = ElementType_Register_GetIndex( data->etReg, Triquadratic_Type );
-	elType    = ElementType_Register_At( data->etReg, testIndex );
-	pcu_check_true( !strcmp( elType->type, Triquadratic_Type ) );
-}
-
-void ElementTypeRegisterSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, ElementTypeRegisterSuiteData );
-   pcu_suite_setFixtures( suite, ElementTypeRegisterSuite_Setup, ElementTypeRegisterSuite_Teardown );
-   pcu_suite_addTest( suite, ElementTypeRegisterSuite_Test );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/ElementTypeRegisterSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/tests/ElementTypeRegisterSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,134 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** Role:
+**   Tests the ElementTypeRegisterSuite
+**
+** $Id: testElementTypeRegister.c 3462 2006-02-19 06:53:24Z WalterLandry $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include "ElementTypeRegisterSuite.h"
+
+typedef struct {
+	ElementType_Register*	etReg;
+} ElementTypeRegisterSuiteData;
+
+void ElementTypeRegisterSuite_Setup( ElementTypeRegisterSuiteData* data ) {
+	data->etReg = ElementType_Register_New( "elementType_Register" );
+
+	Journal_Enable_AllTypedStream( False );
+
+	_ElementType_Register_Init( data->etReg );
+
+	ElementType_Register_Add( data->etReg, (ElementType*)ConstantElementType_New( "constant" ) );
+	ElementType_Register_Add( data->etReg, (ElementType*)BilinearElementType_New( "bilinear" ) );
+	ElementType_Register_Add( data->etReg, (ElementType*)TrilinearElementType_New( "trilinear" ) );
+	ElementType_Register_Add( data->etReg, (ElementType*)Biquadratic_New( "biquadratic" ) );
+	ElementType_Register_Add( data->etReg, (ElementType*)Triquadratic_New( "triquadratic" ) );
+}
+
+void ElementTypeRegisterSuite_Teardown( ElementTypeRegisterSuiteData* data ) {
+	Stg_Class_Delete( data->etReg );
+}
+
+void ElementTypeRegisterSuite_Test( ElementTypeRegisterSuiteData* data ) {
+	/* Variables set in this function */
+	SizeT                                                                            _sizeOfSelf = sizeof(ConstantElementType);
+	Type                                                                                    type = "TestElementType_0";
+	Stg_Class_DeleteFunction*                                                            _delete = _ConstantElementType_Delete;
+	Stg_Class_PrintFunction*                                                              _print = _ConstantElementType_Print;
+	Stg_Class_CopyFunction*                                                                _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*                                _defaultConstructor = ConstantElementType_DefaultNew;
+	Stg_Component_ConstructFunction*                                                  _construct = _ConstantElementType_AssignFromXML;
+	Stg_Component_BuildFunction*                                                          _build = _ConstantElementType_Build;
+	Stg_Component_InitialiseFunction*                                                _initialise = _ConstantElementType_Initialise;
+	Stg_Component_ExecuteFunction*                                                      _execute = _ConstantElementType_Execute;
+	Stg_Component_DestroyFunction*                                                      _destroy = _ConstantElementType_Destroy;
+	Name                                                                                    name = "TestElementType_0_Name";
+	AllocationType                                                            nameAllocationType = NON_GLOBAL;
+	ElementType_EvaluateShapeFunctionsAtFunction*                      _evaluateShapeFunctionsAt = _ConstantElementType_SF_allNodes;
+	ElementType_EvaluateShapeFunctionLocalDerivsAtFunction*  _evaluateShapeFunctionLocalDerivsAt = _ConstantElementType_SF_allLocalDerivs_allNodes;
+	ElementType_ConvertGlobalCoordToElLocalFunction*                _convertGlobalCoordToElLocal = _ConstantElementType_ConvertGlobalCoordToElLocal;
+	ElementType_JacobianDeterminantSurfaceFunction*                  _jacobianDeterminantSurface = _ElementType_JacobianDeterminantSurface;
+	ElementType_SurfaceNormalFunction*                                            _surfaceNormal = _ElementType_SurfaceNormal;
+
+	ElementType* elType;
+	//unsigned	numTypes	= data->etReg->count;
+	unsigned	newIndex;
+	unsigned	testIndex;
+	
+	/* manually create extra types to test the list re-sizing */
+	newIndex = ElementType_Register_Add( data->etReg, _ElementType_New(  ELEMENTTYPE_PASSARGS  ) );
+	pcu_check_true( newIndex == data->etReg->count - 1 );
+	
+	type = "TestElementType_1";
+	name = "TestElementType_1_Name";
+
+	newIndex = ElementType_Register_Add( data->etReg, _ElementType_New(  ELEMENTTYPE_PASSARGS  ) );
+	pcu_check_true( newIndex == data->etReg->count - 1 );
+
+	type = "TestElementType_2";
+	name = "TestElementType_2_Name";
+
+	newIndex = ElementType_Register_Add( data->etReg, _ElementType_New(  ELEMENTTYPE_PASSARGS  ) );
+	pcu_check_true( newIndex == data->etReg->count - 1 );
+
+	testIndex = ElementType_Register_GetIndex( data->etReg, ConstantElementType_Type );
+	elType    = ElementType_Register_At( data->etReg, testIndex );
+	pcu_check_true( !strcmp( elType->type, ConstantElementType_Type ) );
+
+	testIndex = ElementType_Register_GetIndex( data->etReg, BilinearElementType_Type );
+	elType    = ElementType_Register_At( data->etReg, testIndex );
+	pcu_check_true( !strcmp( elType->type, BilinearElementType_Type ) );
+
+	testIndex = ElementType_Register_GetIndex( data->etReg, TrilinearElementType_Type );
+	elType    = ElementType_Register_At( data->etReg, testIndex );
+	pcu_check_true( !strcmp( elType->type, TrilinearElementType_Type ) );
+
+	testIndex = ElementType_Register_GetIndex( data->etReg, Biquadratic_Type );
+	elType    = ElementType_Register_At( data->etReg, testIndex );
+	pcu_check_true( !strcmp( elType->type, Biquadratic_Type ) );
+
+	testIndex = ElementType_Register_GetIndex( data->etReg, Triquadratic_Type );
+	elType    = ElementType_Register_At( data->etReg, testIndex );
+	pcu_check_true( !strcmp( elType->type, Triquadratic_Type ) );
+}
+
+void ElementTypeRegisterSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, ElementTypeRegisterSuiteData );
+   pcu_suite_setFixtures( suite, ElementTypeRegisterSuite_Setup, ElementTypeRegisterSuite_Teardown );
+   pcu_suite_addTest( suite, ElementTypeRegisterSuite_Test );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/ElementTypeSuite.c
--- a/Discretisation/tests/ElementTypeSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,559 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** Role:
-**   Tests the ElementTypeSuite
-**
-** $Id: testElementType.c 3462 2006-02-19 06:53:24Z WalterLandry $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include "ElementTypeSuite.h"
-
-#define TOLERANCE 1.0e-8
-#define EPSILON 1.0e-8
-
-typedef struct {
-	Dictionary*	dict;
-} ElementTypeSuiteData;
-
-FeMesh* BuildMeshLinear( unsigned nDims, unsigned* sizes, double* minCrd, double* maxCrd ) {
-	CartesianGenerator*	gen;
-	FeMesh*					feMesh;
-	unsigned					maxDecomp[3] = {0, 1, 1};
-
-	gen = CartesianGenerator_New( "", NULL );
-	CartesianGenerator_SetDimSize( gen, nDims );
-	CartesianGenerator_SetTopologyParams( gen, sizes, 0, NULL, maxDecomp );
-	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-	CartesianGenerator_SetShadowDepth( gen, 0 );
-
-	feMesh = FeMesh_New( "", NULL );
-	Mesh_SetGenerator( feMesh, gen );
-	FeMesh_SetElementFamily( feMesh, "linear" );
-	Stg_Component_Build( feMesh, NULL, False );
-	Stg_Component_Initialise( feMesh, NULL, False );
-
-	return feMesh;
-}
-
-FeMesh* BuildMeshQuadratic( unsigned nDims, unsigned* sizes, double* minCrd, double* maxCrd ) {
-	CartesianGenerator*	gen;
-	FeMesh*					feMesh;
-	unsigned					maxDecomp[3] = {0, 1, 1};
-
-	gen = (CartesianGenerator*)C2Generator_New( "", NULL );
-	CartesianGenerator_SetDimSize( gen, nDims );
-	C2Generator_SetTopologyParams( gen, sizes, 0, NULL, maxDecomp );
-	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-	CartesianGenerator_SetShadowDepth( gen, 0 );
-
-	feMesh = FeMesh_New( "", NULL );
-	Mesh_SetGenerator( feMesh, gen );
-	FeMesh_SetElementFamily( feMesh, "quadratic" );
-	Stg_Component_Build( feMesh, NULL, False );
-	Stg_Component_Initialise( feMesh, NULL, False );
-
-	return feMesh;
-}
-
-void ElementTypeSuite_Setup( ElementTypeSuiteData* data ) {
-	Journal_Enable_AllTypedStream( False );
-
-	data->dict = Dictionary_New();
-}
-
-void ElementTypeSuite_Teardown( ElementTypeSuiteData* data ) {
-	Stg_Class_Delete( data->dict );
-}
-
-void ElementTypeSuite_TestLinear2D( ElementTypeSuiteData* data ) {
-	FeMesh*		feMesh;
-	unsigned	maxTests	= 40;
-	unsigned	test_i;
-	Coord		gCoord, lCoord, gCoord_fromLocal;
-	unsigned	el, elNodeCount, elNode_i;
-	ElementType*	elType;
-	IArray*		inc		= IArray_New();
-	unsigned*	elNodes;
-	double		Ni[4];
-	double		vecNorm;
-	int		dim		= 2;
-	unsigned	sizes[3]	= { 6, 6, 1 };
-	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
-	double		maxCrd[3]	= { 1.2, 1.2, 1.2 };
-
-	feMesh = BuildMeshLinear( dim, sizes, minCrd, maxCrd );
-
-	srand48( 0 );
-	for( test_i = 0; test_i < maxTests; test_i++ ) {
-		gCoord[I_AXIS] = drand48();
-		gCoord[J_AXIS] = drand48();
-	
-		Mesh_Algorithms_SearchElements( feMesh->algorithms, gCoord, &el );
-		elNodeCount = FeMesh_GetElementNodeSize( feMesh, el );
-		elType = FeMesh_GetElementType( feMesh, el );
-		_ElementType_ConvertGlobalCoordToElLocal( elType, feMesh, el, gCoord, lCoord );
-		ElementType_EvaluateShapeFunctionsAt( elType, lCoord, Ni );
-
-		Mesh_GetIncidence( feMesh, (MeshTopology_Dim)dim, el, MT_VERTEX, inc );
-		elNodes = (unsigned*)IArray_GetPtr( inc );
-		memset( gCoord_fromLocal, 0, sizeof( double ) * dim );
-		for( elNode_i = 0; elNode_i < elNodeCount; elNode_i++ ) {
-			gCoord_fromLocal[I_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][I_AXIS];
-			gCoord_fromLocal[J_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][J_AXIS];
-		}
-
-		vecNorm = sqrt( (gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS])*(gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS]) + 
-				(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS])*(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS]) );
-
-		pcu_check_true( vecNorm < TOLERANCE );
-	}
-
-	NewClass_Delete( inc );
-	Stg_Component_Destroy( feMesh, NULL, True );	
-}
-
-void ElementTypeSuite_TestLinear3D( ElementTypeSuiteData* data ) {
-	FeMesh*		feMesh;
-	unsigned	maxTests	= 40;
-	unsigned	test_i;
-	Coord		gCoord, lCoord, gCoord_fromLocal;
-	unsigned	el, elNodeCount, elNode_i;
-	ElementType*	elType;
-	IArray*		inc		= IArray_New();
-	unsigned*	elNodes;
-	double		Ni[8];
-	double		vecNorm;
-	int		dim		= 3;
-	unsigned	sizes[3]	= { 6, 6, 1 };
-	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
-	double		maxCrd[3]	= { 1.2, 1.2, 1.2 };
-
-	feMesh = BuildMeshLinear( dim, sizes, minCrd, maxCrd );
-
-	srand48( 0 );
-	for( test_i = 0; test_i < maxTests; test_i++ ) {
-		gCoord[I_AXIS] = drand48();
-		gCoord[J_AXIS] = drand48();
-		gCoord[K_AXIS] = drand48();
-	
-		Mesh_Algorithms_SearchElements( feMesh->algorithms, gCoord, &el );
-		elNodeCount = FeMesh_GetElementNodeSize( feMesh, el );
-		elType = FeMesh_GetElementType( feMesh, el );
-		_ElementType_ConvertGlobalCoordToElLocal( elType, feMesh, el, gCoord, lCoord );
-		ElementType_EvaluateShapeFunctionsAt( elType, lCoord, Ni );
-
-		Mesh_GetIncidence( feMesh, (MeshTopology_Dim)dim, el, MT_VERTEX, inc );
-		elNodes = (unsigned*)IArray_GetPtr( inc );
-		memset( gCoord_fromLocal, 0, sizeof( double ) * dim );
-		for( elNode_i = 0; elNode_i < elNodeCount; elNode_i++ ) {
-			gCoord_fromLocal[I_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][I_AXIS];
-			gCoord_fromLocal[J_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][J_AXIS];
-			gCoord_fromLocal[K_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][K_AXIS];
-		}
-
-		vecNorm = sqrt( (gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS])*(gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS]) + 
-				(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS])*(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS]) +
-				(gCoord[K_AXIS] - gCoord_fromLocal[K_AXIS])*(gCoord[K_AXIS] - gCoord_fromLocal[K_AXIS]) );
-
-		pcu_check_true( vecNorm < TOLERANCE );
-	}
-
-	NewClass_Delete( inc );
-	Stg_Component_Destroy( feMesh, NULL, True );	
-}
-
-void ElementTypeSuite_TestQuadratic2D( ElementTypeSuiteData* data ) {
-	FeMesh*		feMesh;
-	unsigned	maxTests	= 40;
-	unsigned	test_i;
-	Coord		gCoord, lCoord, gCoord_fromLocal;
-	unsigned	el, elNodeCount, elNode_i;
-	ElementType*	elType;
-	IArray*		inc		= IArray_New();
-	unsigned*	elNodes;
-	double		Ni[9];
-	double		vecNorm;
-	int		dim		= 2;
-	unsigned	sizes[3]	= { 6, 6, 1 };
-	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
-	double		maxCrd[3]	= { 1.2, 1.2, 1.2 };
-
-	feMesh = BuildMeshQuadratic( dim, sizes, minCrd, maxCrd );
-
-	srand48( 0 );
-	for( test_i = 0; test_i < maxTests; test_i++ ) {
-		gCoord[I_AXIS] = drand48();
-		gCoord[J_AXIS] = drand48();
-	
-		Mesh_Algorithms_SearchElements( feMesh->algorithms, gCoord, &el );
-		elNodeCount = FeMesh_GetElementNodeSize( feMesh, el );
-		elType = FeMesh_GetElementType( feMesh, el );
-		_ElementType_ConvertGlobalCoordToElLocal( elType, feMesh, el, gCoord, lCoord );
-		ElementType_EvaluateShapeFunctionsAt( elType, lCoord, Ni );
-
-		Mesh_GetIncidence( feMesh, (MeshTopology_Dim)dim, el, MT_VERTEX, inc );
-		elNodes = (unsigned*)IArray_GetPtr( inc );
-		memset( gCoord_fromLocal, 0, sizeof( double ) * dim );
-		for( elNode_i = 0; elNode_i < elNodeCount; elNode_i++ ) {
-			gCoord_fromLocal[I_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][I_AXIS];
-			gCoord_fromLocal[J_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][J_AXIS];
-		}
-
-		vecNorm = sqrt( (gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS])*(gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS]) + 
-				(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS])*(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS]) );
-
-		pcu_check_true( vecNorm < TOLERANCE );
-	}
-
-	NewClass_Delete( inc );
-	Stg_Component_Destroy( feMesh, NULL, True );	
-}
-
-void ElementTypeSuite_TestQuadratic3D( ElementTypeSuiteData* data ) {
-	FeMesh*		feMesh;
-	unsigned	maxTests	= 40;
-	unsigned	test_i;
-	Coord		gCoord, lCoord, gCoord_fromLocal;
-	unsigned	el, elNodeCount, elNode_i;
-	ElementType*	elType;
-	IArray*		inc		= IArray_New();
-	unsigned*	elNodes;
-	double		Ni[27];
-	double		vecNorm;
-	int		dim		= 3;
-	unsigned	sizes[3]	= { 6, 6, 1 };
-	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
-	double		maxCrd[3]	= { 1.2, 1.2, 1.2 };
-
-	feMesh = BuildMeshQuadratic( dim, sizes, minCrd, maxCrd );
-
-	srand48( 0 );
-	for( test_i = 0; test_i < maxTests; test_i++ ) {
-		gCoord[I_AXIS] = drand48();
-		gCoord[J_AXIS] = drand48();
-		gCoord[K_AXIS] = drand48();
-	
-		Mesh_Algorithms_SearchElements( feMesh->algorithms, gCoord, &el );
-		elNodeCount = FeMesh_GetElementNodeSize( feMesh, el );
-		elType = FeMesh_GetElementType( feMesh, el );
-		_ElementType_ConvertGlobalCoordToElLocal( elType, feMesh, el, gCoord, lCoord );
-		ElementType_EvaluateShapeFunctionsAt( elType, lCoord, Ni );
-
-		Mesh_GetIncidence( feMesh, (MeshTopology_Dim)dim, el, MT_VERTEX, inc );
-		elNodes = (unsigned*)IArray_GetPtr( inc );
-		memset( gCoord_fromLocal, 0, sizeof( double ) * dim );
-		for( elNode_i = 0; elNode_i < elNodeCount; elNode_i++ ) {
-			gCoord_fromLocal[I_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][I_AXIS];
-			gCoord_fromLocal[J_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][J_AXIS];
-			gCoord_fromLocal[K_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][K_AXIS];
-		}
-
-		vecNorm = sqrt( (gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS])*(gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS]) + 
-				(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS])*(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS]) +
-				(gCoord[K_AXIS] - gCoord_fromLocal[K_AXIS])*(gCoord[K_AXIS] - gCoord_fromLocal[K_AXIS]) );
-
-		pcu_check_true( vecNorm < TOLERANCE );
-	}
-
-	NewClass_Delete( inc );
-	Stg_Component_Destroy( feMesh, NULL, True );	
-}
-
-void ElementTypeSuite_TestSurfaceJacobian_Linear2D( ElementTypeSuiteData* data ) {
-	FeMesh*		feMesh;
-	ElementType*	elType;
-	unsigned	sizes[2]	= { 4, 3 };
-	double		minCrd[2]	= { 0.0, 0.0 };
-	double		maxCrd[2]	= { 4.0, 3.0 };
-	double		xi[4][2][2]; /* [face][point][dim] */
-	unsigned	face_i, ip_i;
-	double		norm[3];
-	unsigned	faceIndex;
-	unsigned	faceAxis[4]	= { 1, 1, 0, 0 };
-	double		weight		= 1.0;
-	double		detJac;
-	double		faceLen;
-
-	xi[0][0][0] = -0.57735026918962584;	xi[0][0][1] = -1.0;
-	xi[0][1][0] = +0.57735026918962584;	xi[0][1][1] = -1.0;
-
-	xi[1][0][0] = -0.57735026918962584;	xi[1][0][1] = +1.0;
-	xi[1][1][0] = +0.57735026918962584;	xi[1][1][1] = +1.0;
-
-	xi[2][0][0] = -1.0;			xi[2][0][1] = -0.57735026918962584;
-	xi[2][1][0] = -1.0;			xi[2][1][1] = +0.57735026918962584;
-
-	xi[3][0][0] = +1.0;			xi[3][0][1] = -0.57735026918962584;
-	xi[3][1][0] = +1.0;			xi[3][1][1] = +0.57735026918962584;
-
-	feMesh = BuildMeshLinear( 2, sizes, minCrd, maxCrd );
-	elType = FeMesh_GetElementType( feMesh, 0 );
-
-	for( face_i = 0; face_i < 4; face_i++ ) {
-		faceLen = 0.0;
-		for( ip_i = 0; ip_i < 2; ip_i++ ) {
-			faceIndex = ElementType_SurfaceNormal( elType, 0, 2, xi[face_i][ip_i], norm );
-			detJac = ElementType_JacobianDeterminantSurface( elType, feMesh, 0, xi[face_i][ip_i], faceIndex, faceAxis[face_i] );
-
-			faceLen += detJac * weight;
-		}
-
-		pcu_check_true( fabs( faceLen - 1.0 ) < EPSILON );
-	}
-
-	Stg_Component_Destroy( feMesh, NULL, True );
-}
-
-void ElementTypeSuite_TestSurfaceJacobian_Linear3D( ElementTypeSuiteData* data ) {
-	FeMesh*		feMesh;
-	ElementType*	elType;
-	unsigned	sizes[3]	= { 4, 3, 5 };
-	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
-	double		maxCrd[3]	= { 4.0, 3.0, 5.0 };
-	double		xi[6][4][3]; /* [face][point][dim] */
-	unsigned	face_i, ip_i;
-	double		norm[3];
-	unsigned	faceIndex;
-	unsigned	faceAxis[6]	= { 1, 1, 0, 0, 2, 2 };
-	double		weight		= 1.0;
-	double		detJac;
-	double		faceArea;
-
-	xi[0][0][0] = -0.57735026918962584;	xi[0][0][1] = -1.0;			xi[0][0][2] = -0.57735026918962584;
-	xi[0][1][0] = +0.57735026918962584;	xi[0][1][1] = -1.0;			xi[0][1][2] = -0.57735026918962584;
-	xi[0][2][0] = -0.57735026918962584;	xi[0][2][1] = -1.0;			xi[0][2][2] = +0.57735026918962584;
-	xi[0][3][0] = +0.57735026918962584;	xi[0][3][1] = -1.0;			xi[0][3][2] = +0.57735026918962584;
-
-	xi[1][0][0] = -0.57735026918962584;	xi[1][0][1] = +1.0;			xi[1][0][2] = -0.57735026918962584;
-	xi[1][1][0] = +0.57735026918962584;	xi[1][1][1] = +1.0;			xi[1][1][2] = -0.57735026918962584;
-	xi[1][2][0] = -0.57735026918962584;	xi[1][2][1] = +1.0;			xi[1][2][2] = +0.57735026918962584;
-	xi[1][3][0] = +0.57735026918962584;	xi[1][3][1] = +1.0;			xi[1][3][2] = +0.57735026918962584;
-
-	xi[2][0][0] = -1.0;			xi[2][0][1] = -0.57735026918962584;	xi[2][0][2] = -0.57735026918962584;
-	xi[2][1][0] = -1.0;			xi[2][1][1] = +0.57735026918962584;	xi[2][1][2] = -0.57735026918962584;
-	xi[2][2][0] = -1.0;			xi[2][2][1] = -0.57735026918962584;	xi[2][2][2] = +0.57735026918962584;
-	xi[2][3][0] = -1.0;			xi[2][3][1] = +0.57735026918962584;	xi[2][3][2] = +0.57735026918962584;
-
-	xi[3][0][0] = +1.0;			xi[3][0][1] = -0.57735026918962584;	xi[3][0][2] = -0.57735026918962584;
-	xi[3][1][0] = +1.0;			xi[3][1][1] = +0.57735026918962584;	xi[3][1][2] = -0.57735026918962584;
-	xi[3][2][0] = +1.0;			xi[3][2][1] = -0.57735026918962584;	xi[3][2][2] = +0.57735026918962584;
-	xi[3][3][0] = +1.0;			xi[3][3][1] = +0.57735026918962584;	xi[3][3][2] = +0.57735026918962584;
-
-	xi[4][0][0] = -0.57735026918962584;	xi[4][0][1] = -0.57735026918962584;	xi[4][0][2] = -1.0;
-	xi[4][1][0] = +0.57735026918962584;	xi[4][1][1] = -0.57735026918962584;	xi[4][1][2] = -1.0;
-	xi[4][2][0] = -0.57735026918962584;	xi[4][2][1] = +0.57735026918962584;	xi[4][2][2] = -1.0;
-	xi[4][3][0] = +0.57735026918962584;	xi[4][3][1] = +0.57735026918962584;	xi[4][3][2] = -1.0;
-
-	xi[5][0][0] = -0.57735026918962584;	xi[5][0][1] = -0.57735026918962584;	xi[5][0][2] = +1.0;
-	xi[5][1][0] = +0.57735026918962584;	xi[5][1][1] = -0.57735026918962584;	xi[5][1][2] = +1.0;
-	xi[5][2][0] = -0.57735026918962584;	xi[5][2][1] = +0.57735026918962584;	xi[5][2][2] = +1.0;
-	xi[5][3][0] = +0.57735026918962584;	xi[5][3][1] = +0.57735026918962584;	xi[5][3][2] = +1.0;
-
-	feMesh = BuildMeshLinear( 3, sizes, minCrd, maxCrd );
-	elType = FeMesh_GetElementType( feMesh, 0 );
-
-	for( face_i = 0; face_i < 6; face_i++ ) {
-		faceArea = 0.0;
-		for( ip_i = 0; ip_i < 4; ip_i++ ) {
-			faceIndex = ElementType_SurfaceNormal( elType, 0, 3, xi[face_i][ip_i], norm );
-			detJac = ElementType_JacobianDeterminantSurface( elType, feMesh, 0, xi[face_i][ip_i], faceIndex, faceAxis[face_i] );
-
-			faceArea += detJac * weight;
-		}
-
-		pcu_check_true( fabs( faceArea - 1.0 ) < EPSILON );
-	}
-
-	Stg_Component_Destroy( feMesh, NULL, True );
-}
-
-void ElementTypeSuite_TestSurfaceJacobian_Quadratic2D( ElementTypeSuiteData* data ) {
-	FeMesh*		feMesh;
-	ElementType*	elType;
-	unsigned	sizes[2]	= { 4, 3 };
-	double		minCrd[2]	= { 0.0, 0.0 };
-	double		maxCrd[2]	= { 4.0, 3.0 };
-	double		xi[4][3][2]; /* [face][point][dim] */
-	unsigned	face_i, ip_i;
-	double		norm[3];
-	unsigned	faceIndex;
-	unsigned	faceAxis[4]	= { 1, 1, 0, 0 };
-	double		weight[3]	= { 0.5555555555555555, 0.8888888888888889, 0.5555555555555555 };
-	double		detJac;
-	double		faceLen;
-
-	xi[0][0][0] = -0.7745966692414834;	xi[0][0][1] = -1.0;
-	xi[0][1][0] = 0.0;			xi[0][1][1] = -1.0;
-	xi[0][2][0] = +0.7745966692414834;	xi[0][2][1] = -1.0;
-
-	xi[1][0][0] = -0.7745966692414834;	xi[1][0][1] = +1.0;
-	xi[1][1][0] = 0.0;			xi[1][1][1] = +1.0;
-	xi[1][2][0] = +0.7745966692414834;	xi[1][2][1] = +1.0;
-
-	xi[2][0][0] = -1.0;			xi[2][0][1] = -0.7745966692414834;
-	xi[2][1][0] = -1.0;			xi[2][1][1] = 0.0;
-	xi[2][2][0] = -1.0;			xi[2][2][1] = +0.7745966692414834;
-
-	xi[3][0][0] = +1.0;			xi[3][0][1] = -0.7745966692414834;
-	xi[3][1][0] = +1.0;			xi[3][1][1] = 0.0;
-	xi[3][2][0] = +1.0;			xi[3][2][1] = +0.7745966692414834;
-
-	feMesh = BuildMeshQuadratic( 2, sizes, minCrd, maxCrd );
-	elType = FeMesh_GetElementType( feMesh, 0 );
-
-	for( face_i = 0; face_i < 4; face_i++ ) {
-		faceLen = 0.0;
-		for( ip_i = 0; ip_i < 3; ip_i++ ) {
-			faceIndex = ElementType_SurfaceNormal( elType, 0, 2, xi[face_i][ip_i], norm );
-			detJac = ElementType_JacobianDeterminantSurface( elType, feMesh, 0, xi[face_i][ip_i], faceIndex, faceAxis[face_i] );
-
-			faceLen += detJac * weight[ip_i];
-		}
-
-		pcu_check_true( fabs( faceLen - 1.0 ) < EPSILON );
-	}
-
-	Stg_Component_Destroy( feMesh, NULL, True );
-}
-
-void ElementTypeSuite_TestSurfaceJacobian_Quadratic3D( ElementTypeSuiteData* data ) {
-	FeMesh*		feMesh;
-	ElementType*	elType;
-	unsigned	sizes[3]	= { 4, 3, 5 };
-	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
-	double		maxCrd[3]	= { 4.0, 3.0, 5.0 };
-	double		xi[6][9][3]; /* [face][point][dim] */
-	unsigned	face_i, ip_i;
-	double		norm[3];
-	unsigned	faceIndex;
-	unsigned	faceAxis[6]	= { 1, 1, 0, 0, 2, 2 };
-	double		weight[9]	= { 0.30864197530864201, 0.49382716049382713, 0.30864197530864201, 
-					    0.49382716049382713, 0.79012345679012341, 0.49382716049382713, 
-					    0.30864197530864201, 0.49382716049382713, 0.30864197530864201 };
-	double		detJac;
-	double		faceArea;
-
-	xi[0][0][0] = -0.7745966692414834;	xi[0][0][1] = -1.0;			xi[0][0][2] = -0.7745966692414834;
-	xi[0][1][0] = 0.0;			xi[0][1][1] = -1.0;			xi[0][1][2] = -0.7745966692414834;
-	xi[0][2][0] = +0.7745966692414834;	xi[0][2][1] = -1.0;			xi[0][2][2] = -0.7745966692414834;
-	xi[0][3][0] = -0.7745966692414834;	xi[0][3][1] = -1.0;			xi[0][3][2] = 0.0;
-	xi[0][4][0] = 0.0;			xi[0][4][1] = -1.0;			xi[0][4][2] = 0.0;
-	xi[0][5][0] = +0.7745966692414834;	xi[0][5][1] = -1.0;			xi[0][5][2] = 0.0;
-	xi[0][6][0] = -0.7745966692414834;	xi[0][6][1] = -1.0;			xi[0][6][2] = +0.7745966692414834;
-	xi[0][7][0] = 0.0;			xi[0][7][1] = -1.0;			xi[0][7][2] = +0.7745966692414834;
-	xi[0][8][0] = +0.7745966692414834;	xi[0][8][1] = -1.0;			xi[0][8][2] = +0.7745966692414834;
-
-	xi[1][0][0] = -0.7745966692414834;	xi[1][0][1] = +1.0;			xi[1][0][2] = -0.7745966692414834;
-	xi[1][1][0] = 0.0;			xi[1][1][1] = +1.0;			xi[1][1][2] = -0.7745966692414834;
-	xi[1][2][0] = +0.7745966692414834;	xi[1][2][1] = +1.0;			xi[1][2][2] = -0.7745966692414834;
-	xi[1][3][0] = -0.7745966692414834;	xi[1][3][1] = +1.0;			xi[1][3][2] = 0.0;
-	xi[1][4][0] = 0.0;			xi[1][4][1] = +1.0;			xi[1][4][2] = 0.0;
-	xi[1][5][0] = +0.7745966692414834;	xi[1][5][1] = +1.0;			xi[1][5][2] = 0.0;
-	xi[1][6][0] = -0.7745966692414834;	xi[1][6][1] = +1.0;			xi[1][6][2] = +0.7745966692414834;
-	xi[1][7][0] = 0.0;			xi[1][7][1] = -1.0;			xi[1][7][2] = +0.7745966692414834;
-	xi[1][8][0] = +0.7745966692414834;	xi[1][8][1] = -1.0;			xi[1][8][2] = +0.7745966692414834;
-
-	xi[2][0][0] = -1.0;			xi[2][0][1] = -0.7745966692414834;	xi[2][0][2] = -0.7745966692414834;
-	xi[2][1][0] = -1.0;			xi[2][1][1] = 0.0;			xi[2][1][2] = -0.7745966692414834;
-	xi[2][2][0] = -1.0;			xi[2][2][1] = +0.7745966692414834;	xi[2][2][2] = -0.7745966692414834;
-	xi[2][3][0] = -1.0;			xi[2][3][1] = -0.7745966692414834;	xi[2][3][2] = 0.0;
-	xi[2][4][0] = -1.0;			xi[2][4][1] = 0.0;			xi[2][4][2] = 0.0;
-	xi[2][5][0] = -1.0;			xi[2][5][1] = +0.7745966692414834;	xi[2][5][2] = 0.0;
-	xi[2][6][0] = -1.0;			xi[2][6][1] = -0.7745966692414834;	xi[2][6][2] = +0.7745966692414834;
-	xi[2][7][0] = -1.0;			xi[2][7][1] = 0.0;			xi[2][7][2] = +0.7745966692414834;
-	xi[2][8][0] = -1.0;			xi[2][8][1] = +0.7745966692414834;	xi[2][8][2] = +0.7745966692414834;
-
-	xi[3][0][0] = +1.0;			xi[3][0][1] = -0.7745966692414834;	xi[3][0][2] = -0.7745966692414834;
-	xi[3][1][0] = +1.0;			xi[3][1][1] = 0.0;			xi[3][1][2] = -0.7745966692414834;
-	xi[3][2][0] = +1.0;			xi[3][2][1] = +0.7745966692414834;	xi[3][2][2] = -0.7745966692414834;
-	xi[3][3][0] = +1.0;			xi[3][3][1] = -0.7745966692414834;	xi[3][3][2] = 0.0;
-	xi[3][4][0] = +1.0;			xi[3][4][1] = 0.0;			xi[3][4][2] = 0.0;
-	xi[3][5][0] = +1.0;			xi[3][5][1] = +0.7745966692414834;	xi[3][5][2] = 0.0;
-	xi[3][6][0] = +1.0;			xi[3][6][1] = -0.7745966692414834;	xi[3][6][2] = +0.7745966692414834;
-	xi[3][7][0] = +1.0;			xi[3][7][1] = 0.0;			xi[3][7][2] = +0.7745966692414834;
-	xi[3][8][0] = +1.0;			xi[3][8][1] = +0.7745966692414834;	xi[3][8][2] = +0.7745966692414834;
-
-	xi[4][0][0] = -0.7745966692414834;	xi[4][0][1] = -0.7745966692414834;	xi[4][0][2] = -1.0;
-	xi[4][1][0] = 0.0;			xi[4][1][1] = -0.7745966692414834;	xi[4][1][2] = -1.0;
-	xi[4][2][0] = +0.7745966692414834;	xi[4][2][1] = -0.7745966692414834;	xi[4][2][2] = -1.0;
-	xi[4][3][0] = -0.7745966692414834;	xi[4][3][1] = 0.0;			xi[4][3][2] = -1.0;
-	xi[4][4][0] = 0.0;			xi[4][4][1] = 0.0;			xi[4][4][2] = -1.0;
-	xi[4][5][0] = +0.7745966692414834;	xi[4][5][1] = 0.0;			xi[4][5][2] = -1.0;
-	xi[4][6][0] = -0.7745966692414834;	xi[4][6][1] = +0.7745966692414834;	xi[4][6][2] = -1.0;
-	xi[4][7][0] = 0.0;			xi[4][7][1] = +0.7745966692414834;	xi[4][7][2] = -1.0;
-	xi[4][8][0] = +0.7745966692414834;	xi[4][8][1] = +0.7745966692414834;	xi[4][8][2] = -1.0;
-
-	xi[5][0][0] = -0.7745966692414834;	xi[5][0][1] = -0.7745966692414834;	xi[5][0][2] = +1.0;
-	xi[5][1][0] = 0.0;			xi[5][1][1] = -0.7745966692414834;	xi[5][1][2] = +1.0;
-	xi[5][2][0] = +0.7745966692414834;	xi[5][2][1] = -0.7745966692414834;	xi[5][2][2] = +1.0;
-	xi[5][3][0] = -0.7745966692414834;	xi[5][3][1] = 0.0;			xi[5][3][2] = +1.0;
-	xi[5][4][0] = 0.0;			xi[5][4][1] = 0.0;			xi[5][4][2] = +1.0;
-	xi[5][5][0] = +0.7745966692414834;	xi[5][5][1] = 0.0;			xi[5][5][2] = +1.0;
-	xi[5][6][0] = -0.7745966692414834;	xi[5][6][1] = +0.7745966692414834;	xi[5][6][2] = +1.0;
-	xi[5][7][0] = 0.0;			xi[5][7][1] = +0.7745966692414834;	xi[5][7][2] = +1.0;
-	xi[5][8][0] = +0.7745966692414834;	xi[5][8][1] = +0.7745966692414834;	xi[5][8][2] = +1.0;
-
-	feMesh = BuildMeshQuadratic( 3, sizes, minCrd, maxCrd );
-	elType = FeMesh_GetElementType( feMesh, 0 );
-
-	for( face_i = 0; face_i < 6; face_i++ ) {
-		faceArea = 0.0;
-		for( ip_i = 0; ip_i < 9; ip_i++ ) {
-			faceIndex = ElementType_SurfaceNormal( elType, 0, 3, xi[face_i][ip_i], norm );
-			detJac = ElementType_JacobianDeterminantSurface( elType, feMesh, 0, xi[face_i][ip_i], faceIndex, faceAxis[face_i] );
-
-			faceArea += detJac * weight[ip_i];
-		}
-
-		pcu_check_true( fabs( faceArea - 1.0 ) < EPSILON );
-	}
-
-	Stg_Component_Destroy( feMesh, NULL, True );
-}
-
-void ElementTypeSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, ElementTypeSuiteData );
-   pcu_suite_setFixtures( suite, ElementTypeSuite_Setup, ElementTypeSuite_Teardown );
-   pcu_suite_addTest( suite, ElementTypeSuite_TestLinear2D );
-   pcu_suite_addTest( suite, ElementTypeSuite_TestLinear3D );
-   pcu_suite_addTest( suite, ElementTypeSuite_TestQuadratic2D );
-   pcu_suite_addTest( suite, ElementTypeSuite_TestQuadratic3D );
-   pcu_suite_addTest( suite, ElementTypeSuite_TestSurfaceJacobian_Linear2D );
-   pcu_suite_addTest( suite, ElementTypeSuite_TestSurfaceJacobian_Linear3D );
-   pcu_suite_addTest( suite, ElementTypeSuite_TestSurfaceJacobian_Quadratic2D );
-   pcu_suite_addTest( suite, ElementTypeSuite_TestSurfaceJacobian_Quadratic3D );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/ElementTypeSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/tests/ElementTypeSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,559 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** Role:
+**   Tests the ElementTypeSuite
+**
+** $Id: testElementType.c 3462 2006-02-19 06:53:24Z WalterLandry $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include "ElementTypeSuite.h"
+
+#define TOLERANCE 1.0e-8
+#define EPSILON 1.0e-8
+
+typedef struct {
+	Dictionary*	dict;
+} ElementTypeSuiteData;
+
+FeMesh* BuildMeshLinear( unsigned nDims, unsigned* sizes, double* minCrd, double* maxCrd ) {
+	CartesianGenerator*	gen;
+	FeMesh*					feMesh;
+	unsigned					maxDecomp[3] = {0, 1, 1};
+
+	gen = CartesianGenerator_New( "", NULL );
+	CartesianGenerator_SetDimSize( gen, nDims );
+	CartesianGenerator_SetTopologyParams( gen, sizes, 0, NULL, maxDecomp );
+	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+	CartesianGenerator_SetShadowDepth( gen, 0 );
+
+	feMesh = FeMesh_New( "", NULL );
+	Mesh_SetGenerator( feMesh, gen );
+	FeMesh_SetElementFamily( feMesh, "linear" );
+	Stg_Component_Build( feMesh, NULL, False );
+	Stg_Component_Initialise( feMesh, NULL, False );
+
+	return feMesh;
+}
+
+FeMesh* BuildMeshQuadratic( unsigned nDims, unsigned* sizes, double* minCrd, double* maxCrd ) {
+	CartesianGenerator*	gen;
+	FeMesh*					feMesh;
+	unsigned					maxDecomp[3] = {0, 1, 1};
+
+	gen = (CartesianGenerator*)C2Generator_New( "", NULL );
+	CartesianGenerator_SetDimSize( gen, nDims );
+	C2Generator_SetTopologyParams( gen, sizes, 0, NULL, maxDecomp );
+	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+	CartesianGenerator_SetShadowDepth( gen, 0 );
+
+	feMesh = FeMesh_New( "", NULL );
+	Mesh_SetGenerator( feMesh, gen );
+	FeMesh_SetElementFamily( feMesh, "quadratic" );
+	Stg_Component_Build( feMesh, NULL, False );
+	Stg_Component_Initialise( feMesh, NULL, False );
+
+	return feMesh;
+}
+
+void ElementTypeSuite_Setup( ElementTypeSuiteData* data ) {
+	Journal_Enable_AllTypedStream( False );
+
+	data->dict = Dictionary_New();
+}
+
+void ElementTypeSuite_Teardown( ElementTypeSuiteData* data ) {
+	Stg_Class_Delete( data->dict );
+}
+
+void ElementTypeSuite_TestLinear2D( ElementTypeSuiteData* data ) {
+	FeMesh*		feMesh;
+	unsigned	maxTests	= 40;
+	unsigned	test_i;
+	Coord		gCoord, lCoord, gCoord_fromLocal;
+	unsigned	el, elNodeCount, elNode_i;
+	ElementType*	elType;
+	IArray*		inc		= IArray_New();
+	unsigned*	elNodes;
+	double		Ni[4];
+	double		vecNorm;
+	int		dim		= 2;
+	unsigned	sizes[3]	= { 6, 6, 1 };
+	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
+	double		maxCrd[3]	= { 1.2, 1.2, 1.2 };
+
+	feMesh = BuildMeshLinear( dim, sizes, minCrd, maxCrd );
+
+	srand48( 0 );
+	for( test_i = 0; test_i < maxTests; test_i++ ) {
+		gCoord[I_AXIS] = drand48();
+		gCoord[J_AXIS] = drand48();
+	
+		Mesh_Algorithms_SearchElements( feMesh->algorithms, gCoord, &el );
+		elNodeCount = FeMesh_GetElementNodeSize( feMesh, el );
+		elType = FeMesh_GetElementType( feMesh, el );
+		_ElementType_ConvertGlobalCoordToElLocal( elType, feMesh, el, gCoord, lCoord );
+		ElementType_EvaluateShapeFunctionsAt( elType, lCoord, Ni );
+
+		Mesh_GetIncidence( feMesh, (MeshTopology_Dim)dim, el, MT_VERTEX, inc );
+		elNodes = (unsigned*)IArray_GetPtr( inc );
+		memset( gCoord_fromLocal, 0, sizeof( double ) * dim );
+		for( elNode_i = 0; elNode_i < elNodeCount; elNode_i++ ) {
+			gCoord_fromLocal[I_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][I_AXIS];
+			gCoord_fromLocal[J_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][J_AXIS];
+		}
+
+		vecNorm = sqrt( (gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS])*(gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS]) + 
+				(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS])*(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS]) );
+
+		pcu_check_true( vecNorm < TOLERANCE );
+	}
+
+	NewClass_Delete( inc );
+	Stg_Component_Destroy( feMesh, NULL, True );	
+}
+
+void ElementTypeSuite_TestLinear3D( ElementTypeSuiteData* data ) {
+	FeMesh*		feMesh;
+	unsigned	maxTests	= 40;
+	unsigned	test_i;
+	Coord		gCoord, lCoord, gCoord_fromLocal;
+	unsigned	el, elNodeCount, elNode_i;
+	ElementType*	elType;
+	IArray*		inc		= IArray_New();
+	unsigned*	elNodes;
+	double		Ni[8];
+	double		vecNorm;
+	int		dim		= 3;
+	unsigned	sizes[3]	= { 6, 6, 1 };
+	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
+	double		maxCrd[3]	= { 1.2, 1.2, 1.2 };
+
+	feMesh = BuildMeshLinear( dim, sizes, minCrd, maxCrd );
+
+	srand48( 0 );
+	for( test_i = 0; test_i < maxTests; test_i++ ) {
+		gCoord[I_AXIS] = drand48();
+		gCoord[J_AXIS] = drand48();
+		gCoord[K_AXIS] = drand48();
+	
+		Mesh_Algorithms_SearchElements( feMesh->algorithms, gCoord, &el );
+		elNodeCount = FeMesh_GetElementNodeSize( feMesh, el );
+		elType = FeMesh_GetElementType( feMesh, el );
+		_ElementType_ConvertGlobalCoordToElLocal( elType, feMesh, el, gCoord, lCoord );
+		ElementType_EvaluateShapeFunctionsAt( elType, lCoord, Ni );
+
+		Mesh_GetIncidence( feMesh, (MeshTopology_Dim)dim, el, MT_VERTEX, inc );
+		elNodes = (unsigned*)IArray_GetPtr( inc );
+		memset( gCoord_fromLocal, 0, sizeof( double ) * dim );
+		for( elNode_i = 0; elNode_i < elNodeCount; elNode_i++ ) {
+			gCoord_fromLocal[I_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][I_AXIS];
+			gCoord_fromLocal[J_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][J_AXIS];
+			gCoord_fromLocal[K_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][K_AXIS];
+		}
+
+		vecNorm = sqrt( (gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS])*(gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS]) + 
+				(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS])*(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS]) +
+				(gCoord[K_AXIS] - gCoord_fromLocal[K_AXIS])*(gCoord[K_AXIS] - gCoord_fromLocal[K_AXIS]) );
+
+		pcu_check_true( vecNorm < TOLERANCE );
+	}
+
+	NewClass_Delete( inc );
+	Stg_Component_Destroy( feMesh, NULL, True );	
+}
+
+void ElementTypeSuite_TestQuadratic2D( ElementTypeSuiteData* data ) {
+	FeMesh*		feMesh;
+	unsigned	maxTests	= 40;
+	unsigned	test_i;
+	Coord		gCoord, lCoord, gCoord_fromLocal;
+	unsigned	el, elNodeCount, elNode_i;
+	ElementType*	elType;
+	IArray*		inc		= IArray_New();
+	unsigned*	elNodes;
+	double		Ni[9];
+	double		vecNorm;
+	int		dim		= 2;
+	unsigned	sizes[3]	= { 6, 6, 1 };
+	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
+	double		maxCrd[3]	= { 1.2, 1.2, 1.2 };
+
+	feMesh = BuildMeshQuadratic( dim, sizes, minCrd, maxCrd );
+
+	srand48( 0 );
+	for( test_i = 0; test_i < maxTests; test_i++ ) {
+		gCoord[I_AXIS] = drand48();
+		gCoord[J_AXIS] = drand48();
+	
+		Mesh_Algorithms_SearchElements( feMesh->algorithms, gCoord, &el );
+		elNodeCount = FeMesh_GetElementNodeSize( feMesh, el );
+		elType = FeMesh_GetElementType( feMesh, el );
+		_ElementType_ConvertGlobalCoordToElLocal( elType, feMesh, el, gCoord, lCoord );
+		ElementType_EvaluateShapeFunctionsAt( elType, lCoord, Ni );
+
+		Mesh_GetIncidence( feMesh, (MeshTopology_Dim)dim, el, MT_VERTEX, inc );
+		elNodes = (unsigned*)IArray_GetPtr( inc );
+		memset( gCoord_fromLocal, 0, sizeof( double ) * dim );
+		for( elNode_i = 0; elNode_i < elNodeCount; elNode_i++ ) {
+			gCoord_fromLocal[I_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][I_AXIS];
+			gCoord_fromLocal[J_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][J_AXIS];
+		}
+
+		vecNorm = sqrt( (gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS])*(gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS]) + 
+				(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS])*(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS]) );
+
+		pcu_check_true( vecNorm < TOLERANCE );
+	}
+
+	NewClass_Delete( inc );
+	Stg_Component_Destroy( feMesh, NULL, True );	
+}
+
+void ElementTypeSuite_TestQuadratic3D( ElementTypeSuiteData* data ) {
+	FeMesh*		feMesh;
+	unsigned	maxTests	= 40;
+	unsigned	test_i;
+	Coord		gCoord, lCoord, gCoord_fromLocal;
+	unsigned	el, elNodeCount, elNode_i;
+	ElementType*	elType;
+	IArray*		inc		= IArray_New();
+	unsigned*	elNodes;
+	double		Ni[27];
+	double		vecNorm;
+	int		dim		= 3;
+	unsigned	sizes[3]	= { 6, 6, 1 };
+	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
+	double		maxCrd[3]	= { 1.2, 1.2, 1.2 };
+
+	feMesh = BuildMeshQuadratic( dim, sizes, minCrd, maxCrd );
+
+	srand48( 0 );
+	for( test_i = 0; test_i < maxTests; test_i++ ) {
+		gCoord[I_AXIS] = drand48();
+		gCoord[J_AXIS] = drand48();
+		gCoord[K_AXIS] = drand48();
+	
+		Mesh_Algorithms_SearchElements( feMesh->algorithms, gCoord, &el );
+		elNodeCount = FeMesh_GetElementNodeSize( feMesh, el );
+		elType = FeMesh_GetElementType( feMesh, el );
+		_ElementType_ConvertGlobalCoordToElLocal( elType, feMesh, el, gCoord, lCoord );
+		ElementType_EvaluateShapeFunctionsAt( elType, lCoord, Ni );
+
+		Mesh_GetIncidence( feMesh, (MeshTopology_Dim)dim, el, MT_VERTEX, inc );
+		elNodes = (unsigned*)IArray_GetPtr( inc );
+		memset( gCoord_fromLocal, 0, sizeof( double ) * dim );
+		for( elNode_i = 0; elNode_i < elNodeCount; elNode_i++ ) {
+			gCoord_fromLocal[I_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][I_AXIS];
+			gCoord_fromLocal[J_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][J_AXIS];
+			gCoord_fromLocal[K_AXIS] += Ni[elNode_i] * feMesh->verts[elNodes[elNode_i]][K_AXIS];
+		}
+
+		vecNorm = sqrt( (gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS])*(gCoord[I_AXIS] - gCoord_fromLocal[I_AXIS]) + 
+				(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS])*(gCoord[J_AXIS] - gCoord_fromLocal[J_AXIS]) +
+				(gCoord[K_AXIS] - gCoord_fromLocal[K_AXIS])*(gCoord[K_AXIS] - gCoord_fromLocal[K_AXIS]) );
+
+		pcu_check_true( vecNorm < TOLERANCE );
+	}
+
+	NewClass_Delete( inc );
+	Stg_Component_Destroy( feMesh, NULL, True );	
+}
+
+void ElementTypeSuite_TestSurfaceJacobian_Linear2D( ElementTypeSuiteData* data ) {
+	FeMesh*		feMesh;
+	ElementType*	elType;
+	unsigned	sizes[2]	= { 4, 3 };
+	double		minCrd[2]	= { 0.0, 0.0 };
+	double		maxCrd[2]	= { 4.0, 3.0 };
+	double		xi[4][2][2]; /* [face][point][dim] */
+	unsigned	face_i, ip_i;
+	double		norm[3];
+	unsigned	faceIndex;
+	unsigned	faceAxis[4]	= { 1, 1, 0, 0 };
+	double		weight		= 1.0;
+	double		detJac;
+	double		faceLen;
+
+	xi[0][0][0] = -0.57735026918962584;	xi[0][0][1] = -1.0;
+	xi[0][1][0] = +0.57735026918962584;	xi[0][1][1] = -1.0;
+
+	xi[1][0][0] = -0.57735026918962584;	xi[1][0][1] = +1.0;
+	xi[1][1][0] = +0.57735026918962584;	xi[1][1][1] = +1.0;
+
+	xi[2][0][0] = -1.0;			xi[2][0][1] = -0.57735026918962584;
+	xi[2][1][0] = -1.0;			xi[2][1][1] = +0.57735026918962584;
+
+	xi[3][0][0] = +1.0;			xi[3][0][1] = -0.57735026918962584;
+	xi[3][1][0] = +1.0;			xi[3][1][1] = +0.57735026918962584;
+
+	feMesh = BuildMeshLinear( 2, sizes, minCrd, maxCrd );
+	elType = FeMesh_GetElementType( feMesh, 0 );
+
+	for( face_i = 0; face_i < 4; face_i++ ) {
+		faceLen = 0.0;
+		for( ip_i = 0; ip_i < 2; ip_i++ ) {
+			faceIndex = ElementType_SurfaceNormal( elType, 0, 2, xi[face_i][ip_i], norm );
+			detJac = ElementType_JacobianDeterminantSurface( elType, feMesh, 0, xi[face_i][ip_i], faceIndex, faceAxis[face_i] );
+
+			faceLen += detJac * weight;
+		}
+
+		pcu_check_true( fabs( faceLen - 1.0 ) < EPSILON );
+	}
+
+	Stg_Component_Destroy( feMesh, NULL, True );
+}
+
+void ElementTypeSuite_TestSurfaceJacobian_Linear3D( ElementTypeSuiteData* data ) {
+	FeMesh*		feMesh;
+	ElementType*	elType;
+	unsigned	sizes[3]	= { 4, 3, 5 };
+	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
+	double		maxCrd[3]	= { 4.0, 3.0, 5.0 };
+	double		xi[6][4][3]; /* [face][point][dim] */
+	unsigned	face_i, ip_i;
+	double		norm[3];
+	unsigned	faceIndex;
+	unsigned	faceAxis[6]	= { 1, 1, 0, 0, 2, 2 };
+	double		weight		= 1.0;
+	double		detJac;
+	double		faceArea;
+
+	xi[0][0][0] = -0.57735026918962584;	xi[0][0][1] = -1.0;			xi[0][0][2] = -0.57735026918962584;
+	xi[0][1][0] = +0.57735026918962584;	xi[0][1][1] = -1.0;			xi[0][1][2] = -0.57735026918962584;
+	xi[0][2][0] = -0.57735026918962584;	xi[0][2][1] = -1.0;			xi[0][2][2] = +0.57735026918962584;
+	xi[0][3][0] = +0.57735026918962584;	xi[0][3][1] = -1.0;			xi[0][3][2] = +0.57735026918962584;
+
+	xi[1][0][0] = -0.57735026918962584;	xi[1][0][1] = +1.0;			xi[1][0][2] = -0.57735026918962584;
+	xi[1][1][0] = +0.57735026918962584;	xi[1][1][1] = +1.0;			xi[1][1][2] = -0.57735026918962584;
+	xi[1][2][0] = -0.57735026918962584;	xi[1][2][1] = +1.0;			xi[1][2][2] = +0.57735026918962584;
+	xi[1][3][0] = +0.57735026918962584;	xi[1][3][1] = +1.0;			xi[1][3][2] = +0.57735026918962584;
+
+	xi[2][0][0] = -1.0;			xi[2][0][1] = -0.57735026918962584;	xi[2][0][2] = -0.57735026918962584;
+	xi[2][1][0] = -1.0;			xi[2][1][1] = +0.57735026918962584;	xi[2][1][2] = -0.57735026918962584;
+	xi[2][2][0] = -1.0;			xi[2][2][1] = -0.57735026918962584;	xi[2][2][2] = +0.57735026918962584;
+	xi[2][3][0] = -1.0;			xi[2][3][1] = +0.57735026918962584;	xi[2][3][2] = +0.57735026918962584;
+
+	xi[3][0][0] = +1.0;			xi[3][0][1] = -0.57735026918962584;	xi[3][0][2] = -0.57735026918962584;
+	xi[3][1][0] = +1.0;			xi[3][1][1] = +0.57735026918962584;	xi[3][1][2] = -0.57735026918962584;
+	xi[3][2][0] = +1.0;			xi[3][2][1] = -0.57735026918962584;	xi[3][2][2] = +0.57735026918962584;
+	xi[3][3][0] = +1.0;			xi[3][3][1] = +0.57735026918962584;	xi[3][3][2] = +0.57735026918962584;
+
+	xi[4][0][0] = -0.57735026918962584;	xi[4][0][1] = -0.57735026918962584;	xi[4][0][2] = -1.0;
+	xi[4][1][0] = +0.57735026918962584;	xi[4][1][1] = -0.57735026918962584;	xi[4][1][2] = -1.0;
+	xi[4][2][0] = -0.57735026918962584;	xi[4][2][1] = +0.57735026918962584;	xi[4][2][2] = -1.0;
+	xi[4][3][0] = +0.57735026918962584;	xi[4][3][1] = +0.57735026918962584;	xi[4][3][2] = -1.0;
+
+	xi[5][0][0] = -0.57735026918962584;	xi[5][0][1] = -0.57735026918962584;	xi[5][0][2] = +1.0;
+	xi[5][1][0] = +0.57735026918962584;	xi[5][1][1] = -0.57735026918962584;	xi[5][1][2] = +1.0;
+	xi[5][2][0] = -0.57735026918962584;	xi[5][2][1] = +0.57735026918962584;	xi[5][2][2] = +1.0;
+	xi[5][3][0] = +0.57735026918962584;	xi[5][3][1] = +0.57735026918962584;	xi[5][3][2] = +1.0;
+
+	feMesh = BuildMeshLinear( 3, sizes, minCrd, maxCrd );
+	elType = FeMesh_GetElementType( feMesh, 0 );
+
+	for( face_i = 0; face_i < 6; face_i++ ) {
+		faceArea = 0.0;
+		for( ip_i = 0; ip_i < 4; ip_i++ ) {
+			faceIndex = ElementType_SurfaceNormal( elType, 0, 3, xi[face_i][ip_i], norm );
+			detJac = ElementType_JacobianDeterminantSurface( elType, feMesh, 0, xi[face_i][ip_i], faceIndex, faceAxis[face_i] );
+
+			faceArea += detJac * weight;
+		}
+
+		pcu_check_true( fabs( faceArea - 1.0 ) < EPSILON );
+	}
+
+	Stg_Component_Destroy( feMesh, NULL, True );
+}
+
+void ElementTypeSuite_TestSurfaceJacobian_Quadratic2D( ElementTypeSuiteData* data ) {
+	FeMesh*		feMesh;
+	ElementType*	elType;
+	unsigned	sizes[2]	= { 4, 3 };
+	double		minCrd[2]	= { 0.0, 0.0 };
+	double		maxCrd[2]	= { 4.0, 3.0 };
+	double		xi[4][3][2]; /* [face][point][dim] */
+	unsigned	face_i, ip_i;
+	double		norm[3];
+	unsigned	faceIndex;
+	unsigned	faceAxis[4]	= { 1, 1, 0, 0 };
+	double		weight[3]	= { 0.5555555555555555, 0.8888888888888889, 0.5555555555555555 };
+	double		detJac;
+	double		faceLen;
+
+	xi[0][0][0] = -0.7745966692414834;	xi[0][0][1] = -1.0;
+	xi[0][1][0] = 0.0;			xi[0][1][1] = -1.0;
+	xi[0][2][0] = +0.7745966692414834;	xi[0][2][1] = -1.0;
+
+	xi[1][0][0] = -0.7745966692414834;	xi[1][0][1] = +1.0;
+	xi[1][1][0] = 0.0;			xi[1][1][1] = +1.0;
+	xi[1][2][0] = +0.7745966692414834;	xi[1][2][1] = +1.0;
+
+	xi[2][0][0] = -1.0;			xi[2][0][1] = -0.7745966692414834;
+	xi[2][1][0] = -1.0;			xi[2][1][1] = 0.0;
+	xi[2][2][0] = -1.0;			xi[2][2][1] = +0.7745966692414834;
+
+	xi[3][0][0] = +1.0;			xi[3][0][1] = -0.7745966692414834;
+	xi[3][1][0] = +1.0;			xi[3][1][1] = 0.0;
+	xi[3][2][0] = +1.0;			xi[3][2][1] = +0.7745966692414834;
+
+	feMesh = BuildMeshQuadratic( 2, sizes, minCrd, maxCrd );
+	elType = FeMesh_GetElementType( feMesh, 0 );
+
+	for( face_i = 0; face_i < 4; face_i++ ) {
+		faceLen = 0.0;
+		for( ip_i = 0; ip_i < 3; ip_i++ ) {
+			faceIndex = ElementType_SurfaceNormal( elType, 0, 2, xi[face_i][ip_i], norm );
+			detJac = ElementType_JacobianDeterminantSurface( elType, feMesh, 0, xi[face_i][ip_i], faceIndex, faceAxis[face_i] );
+
+			faceLen += detJac * weight[ip_i];
+		}
+
+		pcu_check_true( fabs( faceLen - 1.0 ) < EPSILON );
+	}
+
+	Stg_Component_Destroy( feMesh, NULL, True );
+}
+
+void ElementTypeSuite_TestSurfaceJacobian_Quadratic3D( ElementTypeSuiteData* data ) {
+	FeMesh*		feMesh;
+	ElementType*	elType;
+	unsigned	sizes[3]	= { 4, 3, 5 };
+	double		minCrd[3]	= { 0.0, 0.0, 0.0 };
+	double		maxCrd[3]	= { 4.0, 3.0, 5.0 };
+	double		xi[6][9][3]; /* [face][point][dim] */
+	unsigned	face_i, ip_i;
+	double		norm[3];
+	unsigned	faceIndex;
+	unsigned	faceAxis[6]	= { 1, 1, 0, 0, 2, 2 };
+	double		weight[9]	= { 0.30864197530864201, 0.49382716049382713, 0.30864197530864201, 
+					    0.49382716049382713, 0.79012345679012341, 0.49382716049382713, 
+					    0.30864197530864201, 0.49382716049382713, 0.30864197530864201 };
+	double		detJac;
+	double		faceArea;
+
+	xi[0][0][0] = -0.7745966692414834;	xi[0][0][1] = -1.0;			xi[0][0][2] = -0.7745966692414834;
+	xi[0][1][0] = 0.0;			xi[0][1][1] = -1.0;			xi[0][1][2] = -0.7745966692414834;
+	xi[0][2][0] = +0.7745966692414834;	xi[0][2][1] = -1.0;			xi[0][2][2] = -0.7745966692414834;
+	xi[0][3][0] = -0.7745966692414834;	xi[0][3][1] = -1.0;			xi[0][3][2] = 0.0;
+	xi[0][4][0] = 0.0;			xi[0][4][1] = -1.0;			xi[0][4][2] = 0.0;
+	xi[0][5][0] = +0.7745966692414834;	xi[0][5][1] = -1.0;			xi[0][5][2] = 0.0;
+	xi[0][6][0] = -0.7745966692414834;	xi[0][6][1] = -1.0;			xi[0][6][2] = +0.7745966692414834;
+	xi[0][7][0] = 0.0;			xi[0][7][1] = -1.0;			xi[0][7][2] = +0.7745966692414834;
+	xi[0][8][0] = +0.7745966692414834;	xi[0][8][1] = -1.0;			xi[0][8][2] = +0.7745966692414834;
+
+	xi[1][0][0] = -0.7745966692414834;	xi[1][0][1] = +1.0;			xi[1][0][2] = -0.7745966692414834;
+	xi[1][1][0] = 0.0;			xi[1][1][1] = +1.0;			xi[1][1][2] = -0.7745966692414834;
+	xi[1][2][0] = +0.7745966692414834;	xi[1][2][1] = +1.0;			xi[1][2][2] = -0.7745966692414834;
+	xi[1][3][0] = -0.7745966692414834;	xi[1][3][1] = +1.0;			xi[1][3][2] = 0.0;
+	xi[1][4][0] = 0.0;			xi[1][4][1] = +1.0;			xi[1][4][2] = 0.0;
+	xi[1][5][0] = +0.7745966692414834;	xi[1][5][1] = +1.0;			xi[1][5][2] = 0.0;
+	xi[1][6][0] = -0.7745966692414834;	xi[1][6][1] = +1.0;			xi[1][6][2] = +0.7745966692414834;
+	xi[1][7][0] = 0.0;			xi[1][7][1] = -1.0;			xi[1][7][2] = +0.7745966692414834;
+	xi[1][8][0] = +0.7745966692414834;	xi[1][8][1] = -1.0;			xi[1][8][2] = +0.7745966692414834;
+
+	xi[2][0][0] = -1.0;			xi[2][0][1] = -0.7745966692414834;	xi[2][0][2] = -0.7745966692414834;
+	xi[2][1][0] = -1.0;			xi[2][1][1] = 0.0;			xi[2][1][2] = -0.7745966692414834;
+	xi[2][2][0] = -1.0;			xi[2][2][1] = +0.7745966692414834;	xi[2][2][2] = -0.7745966692414834;
+	xi[2][3][0] = -1.0;			xi[2][3][1] = -0.7745966692414834;	xi[2][3][2] = 0.0;
+	xi[2][4][0] = -1.0;			xi[2][4][1] = 0.0;			xi[2][4][2] = 0.0;
+	xi[2][5][0] = -1.0;			xi[2][5][1] = +0.7745966692414834;	xi[2][5][2] = 0.0;
+	xi[2][6][0] = -1.0;			xi[2][6][1] = -0.7745966692414834;	xi[2][6][2] = +0.7745966692414834;
+	xi[2][7][0] = -1.0;			xi[2][7][1] = 0.0;			xi[2][7][2] = +0.7745966692414834;
+	xi[2][8][0] = -1.0;			xi[2][8][1] = +0.7745966692414834;	xi[2][8][2] = +0.7745966692414834;
+
+	xi[3][0][0] = +1.0;			xi[3][0][1] = -0.7745966692414834;	xi[3][0][2] = -0.7745966692414834;
+	xi[3][1][0] = +1.0;			xi[3][1][1] = 0.0;			xi[3][1][2] = -0.7745966692414834;
+	xi[3][2][0] = +1.0;			xi[3][2][1] = +0.7745966692414834;	xi[3][2][2] = -0.7745966692414834;
+	xi[3][3][0] = +1.0;			xi[3][3][1] = -0.7745966692414834;	xi[3][3][2] = 0.0;
+	xi[3][4][0] = +1.0;			xi[3][4][1] = 0.0;			xi[3][4][2] = 0.0;
+	xi[3][5][0] = +1.0;			xi[3][5][1] = +0.7745966692414834;	xi[3][5][2] = 0.0;
+	xi[3][6][0] = +1.0;			xi[3][6][1] = -0.7745966692414834;	xi[3][6][2] = +0.7745966692414834;
+	xi[3][7][0] = +1.0;			xi[3][7][1] = 0.0;			xi[3][7][2] = +0.7745966692414834;
+	xi[3][8][0] = +1.0;			xi[3][8][1] = +0.7745966692414834;	xi[3][8][2] = +0.7745966692414834;
+
+	xi[4][0][0] = -0.7745966692414834;	xi[4][0][1] = -0.7745966692414834;	xi[4][0][2] = -1.0;
+	xi[4][1][0] = 0.0;			xi[4][1][1] = -0.7745966692414834;	xi[4][1][2] = -1.0;
+	xi[4][2][0] = +0.7745966692414834;	xi[4][2][1] = -0.7745966692414834;	xi[4][2][2] = -1.0;
+	xi[4][3][0] = -0.7745966692414834;	xi[4][3][1] = 0.0;			xi[4][3][2] = -1.0;
+	xi[4][4][0] = 0.0;			xi[4][4][1] = 0.0;			xi[4][4][2] = -1.0;
+	xi[4][5][0] = +0.7745966692414834;	xi[4][5][1] = 0.0;			xi[4][5][2] = -1.0;
+	xi[4][6][0] = -0.7745966692414834;	xi[4][6][1] = +0.7745966692414834;	xi[4][6][2] = -1.0;
+	xi[4][7][0] = 0.0;			xi[4][7][1] = +0.7745966692414834;	xi[4][7][2] = -1.0;
+	xi[4][8][0] = +0.7745966692414834;	xi[4][8][1] = +0.7745966692414834;	xi[4][8][2] = -1.0;
+
+	xi[5][0][0] = -0.7745966692414834;	xi[5][0][1] = -0.7745966692414834;	xi[5][0][2] = +1.0;
+	xi[5][1][0] = 0.0;			xi[5][1][1] = -0.7745966692414834;	xi[5][1][2] = +1.0;
+	xi[5][2][0] = +0.7745966692414834;	xi[5][2][1] = -0.7745966692414834;	xi[5][2][2] = +1.0;
+	xi[5][3][0] = -0.7745966692414834;	xi[5][3][1] = 0.0;			xi[5][3][2] = +1.0;
+	xi[5][4][0] = 0.0;			xi[5][4][1] = 0.0;			xi[5][4][2] = +1.0;
+	xi[5][5][0] = +0.7745966692414834;	xi[5][5][1] = 0.0;			xi[5][5][2] = +1.0;
+	xi[5][6][0] = -0.7745966692414834;	xi[5][6][1] = +0.7745966692414834;	xi[5][6][2] = +1.0;
+	xi[5][7][0] = 0.0;			xi[5][7][1] = +0.7745966692414834;	xi[5][7][2] = +1.0;
+	xi[5][8][0] = +0.7745966692414834;	xi[5][8][1] = +0.7745966692414834;	xi[5][8][2] = +1.0;
+
+	feMesh = BuildMeshQuadratic( 3, sizes, minCrd, maxCrd );
+	elType = FeMesh_GetElementType( feMesh, 0 );
+
+	for( face_i = 0; face_i < 6; face_i++ ) {
+		faceArea = 0.0;
+		for( ip_i = 0; ip_i < 9; ip_i++ ) {
+			faceIndex = ElementType_SurfaceNormal( elType, 0, 3, xi[face_i][ip_i], norm );
+			detJac = ElementType_JacobianDeterminantSurface( elType, feMesh, 0, xi[face_i][ip_i], faceIndex, faceAxis[face_i] );
+
+			faceArea += detJac * weight[ip_i];
+		}
+
+		pcu_check_true( fabs( faceArea - 1.0 ) < EPSILON );
+	}
+
+	Stg_Component_Destroy( feMesh, NULL, True );
+}
+
+void ElementTypeSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, ElementTypeSuiteData );
+   pcu_suite_setFixtures( suite, ElementTypeSuite_Setup, ElementTypeSuite_Teardown );
+   pcu_suite_addTest( suite, ElementTypeSuite_TestLinear2D );
+   pcu_suite_addTest( suite, ElementTypeSuite_TestLinear3D );
+   pcu_suite_addTest( suite, ElementTypeSuite_TestQuadratic2D );
+   pcu_suite_addTest( suite, ElementTypeSuite_TestQuadratic3D );
+   pcu_suite_addTest( suite, ElementTypeSuite_TestSurfaceJacobian_Linear2D );
+   pcu_suite_addTest( suite, ElementTypeSuite_TestSurfaceJacobian_Linear3D );
+   pcu_suite_addTest( suite, ElementTypeSuite_TestSurfaceJacobian_Quadratic2D );
+   pcu_suite_addTest( suite, ElementTypeSuite_TestSurfaceJacobian_Quadratic3D );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/FeEquationNumberSuite.c
--- a/Discretisation/tests/FeEquationNumberSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,335 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** Role:
-**   Tests the FeEquationNumberSuite
-**
-** $Id: testFeEquationNumber.c 3462 2006-02-19 06:53:24Z WalterLandry $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include "FeEquationNumberSuite.h"
-
-typedef struct {
-} FeEquationNumberSuiteData;
-
-FeEquationNumber* buildEqNum() {
-   CartesianGenerator*	gen;
-   FeMesh*					feMesh;
-   DofLayout*				dofs;
-   FeEquationNumber*		eqNum;
-   Variable_Register*	varReg;
-   Variable*				vars[2];
-   int						maxDecomp[3] = {0, 1, 1};
-   int						sizes[3];
-   double					minCrd[3];
-   double					maxCrd[3];
-   SizeT						dataOffs = 1;
-   Variable_DataType		dataType = Variable_DataType_Double;
-   int						nDataTypes = 1;
-   char*						dataNames = "nothing";
-   static SizeT			structSize = sizeof(double);
-   static int				arraySize;
-   static void*			arrayPtrs[2];
-   int						nRanks;
-
-   MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
-   sizes[0] = nRanks * 2;
-   sizes[1] = sizes[2] = 2;
-   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
-   maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
-
-   gen = CartesianGenerator_New( "", NULL );
-   CartesianGenerator_SetDimSize( gen, 3 );
-   CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
-   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-   CartesianGenerator_SetShadowDepth( gen, 0 );
-
-   feMesh = FeMesh_New( "", NULL );
-   Mesh_SetGenerator( feMesh, gen );
-   FeMesh_SetElementFamily( feMesh, "linear" );
-   Stg_Component_Build( feMesh, NULL, False );
-
-   varReg = Variable_Register_New();
-
-   arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-   arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize );
-   arrayPtrs[1] = Memory_Alloc_Array_Unnamed( double, arraySize );
-   vars[0] = Variable_New( "one", NULL, 1, &dataOffs, &dataType, (unsigned*)&nDataTypes, 
-                           (Name*)(&dataNames), &structSize, (unsigned*)&arraySize, NULL, arrayPtrs, varReg );
-   vars[1] = Variable_New( "two", NULL, 1, &dataOffs, &dataType, (unsigned*)&nDataTypes, 
-                           (Name*)(&dataNames), &structSize, (unsigned*)&arraySize, NULL, arrayPtrs + 1, varReg );
-
-   dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
-   dofs->nBaseVariables = 2;
-   dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 2 );
-   dofs->baseVariables[0] = vars[0];
-   dofs->baseVariables[1] = vars[1];
-   Stg_Component_Build( dofs, NULL, False );
-   Stg_Component_Initialise( dofs, NULL, False );
-
-   eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, NULL, NULL );
-   Stg_Component_Build( eqNum, NULL, False );
-   Stg_Component_Initialise( eqNum, NULL, False );
-
-   return eqNum;
-}
-
-FeEquationNumber* buildEqNumBCs() {
-   CartesianGenerator*				gen;
-   FeMesh*								feMesh;
-   DofLayout*							dofs;
-   FeEquationNumber*					eqNum;
-   Variable_Register*				varReg;
-   Variable*							vars[2];
-   int									maxDecomp[3] = {0, 1, 1};
-   int									sizes[3];
-   double								minCrd[3];
-   double								maxCrd[3];
-   SizeT									dataOffs = 1;
-   Variable_DataType					dataType = Variable_DataType_Double;
-   int									nDataTypes = 1;
-   char*									dataNames = "nothing";
-   static SizeT						structSize = sizeof(double);
-   static int							arraySize;
-   static void*						arrayPtrs[2];
-   int									nRanks;
-   VariableCondition*				bcs;
-   ConditionFunction_Register*	cfReg;
-   Dictionary*							dict;
-   XML_IO_Handler*					ioHandler;
-   char									filename[PCU_PATH_MAX];
-
-   MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
-   sizes[0] = nRanks * 2;
-   sizes[1] = sizes[2] = 2;
-   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
-   maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
-
-   gen = CartesianGenerator_New( "", NULL );
-   CartesianGenerator_SetDimSize( gen, 3 );
-   CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
-   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-   CartesianGenerator_SetShadowDepth( gen, 0 );
-
-   feMesh = FeMesh_New( "", NULL );
-   Mesh_SetGenerator( feMesh, gen );
-   FeMesh_SetElementFamily( feMesh, "linear" );
-   Stg_Component_Build( feMesh, NULL, False );
-
-   varReg = Variable_Register_New();
-   cfReg = ConditionFunction_Register_New();
-
-   arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-   arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize );
-   arrayPtrs[1] = Memory_Alloc_Array_Unnamed( double, arraySize );
-   vars[0] = Variable_New( "one", NULL, 1, &dataOffs, &dataType, (unsigned*)&nDataTypes, 
-                           (Name*)(&dataNames), &structSize, (unsigned*)&arraySize, NULL, arrayPtrs, varReg );
-	vars[1] = Variable_New( "two", NULL, 1, &dataOffs, &dataType, (unsigned*)&nDataTypes, 
-                                (Name*)(&dataNames), &structSize, (unsigned*)&arraySize, NULL, arrayPtrs + 1, varReg );
-
-   dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
-   dofs->nBaseVariables = 2;
-   dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 2 );
-   dofs->baseVariables[0] = vars[0];
-   dofs->baseVariables[1] = vars[1];
-   Stg_Component_Build( dofs, NULL, False );
-   Stg_Component_Initialise( dofs, NULL, False );
-
-   ioHandler = XML_IO_Handler_New();
-   dict = Dictionary_New();
-   pcu_filename_input( "wallVC.xml", filename );
-   IO_Handler_ReadAllFromFile( ioHandler, filename, dict );
-   bcs = (VariableCondition*)WallVC_New( "", NULL, "wallVC", varReg, cfReg, dict, feMesh );
-   Stg_Component_Build( bcs, NULL, False );
-   Stg_Component_Initialise( bcs, NULL, False );
-
-   eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, bcs, NULL );
-   Stg_Component_Build( eqNum, NULL, False );
-   Stg_Component_Initialise( eqNum, NULL, False );
-
-   return eqNum;
-}
-
-void FeEquationNumberSuite_Setup( FeEquationNumberSuiteData* data ) {
-	Journal_Enable_AllTypedStream( False );
-}
-
-void FeEquationNumberSuite_Teardown( FeEquationNumberSuiteData* data ) {
-}
-
-void FeEquationNumberSuite_TestLocal( FeEquationNumberSuiteData* data ) {
-   FeEquationNumber*	eqNum;
-   FeMesh*				feMesh;
-   int					eqNumsPerProc;
-   int					curEqNum;
-   int					nDofs;
-   int					rank;
-   int					n_i, dof_i;
-
-   eqNum = buildEqNum();
-   pcu_check_true( eqNum );
-
-   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
-   feMesh = eqNum->feMesh;
-   eqNumsPerProc = (Mesh_GetDimSize( feMesh ) == 3) ? 27 : (Mesh_GetDimSize( feMesh ) == 2) ? 9 : 3;
-   curEqNum = eqNumsPerProc * rank;
-   if( rank >= 1 )
-      curEqNum -= (eqNumsPerProc / 3) * (rank - 1);
-   curEqNum *= 2;
-
-   for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, MT_VERTEX ); n_i++ ) {
-      nDofs = eqNum->dofLayout->dofCounts[n_i];
-      for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
-	 if( eqNum->destinationArray[n_i][dof_i] != curEqNum++ )
-	    break;
-      }
-      if( dof_i < nDofs )
-	 break;
-   }
-   pcu_check_true( n_i == Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ) );
-
-   FreeObject( eqNum );
-}
-
-void FeEquationNumberSuite_TestShadow( FeEquationNumberSuiteData* data ) {
-   FeEquationNumber*	eqNum;
-   FeMesh*				feMesh;
-   int					eqNumsPerProc;
-   int					curEqNum;
-   int					nDofs;
-   int					rank;
-   int					nLocalNodes, nDomainNodes;
-   int					n_i, dof_i;
-
-   eqNum = buildEqNum();
-   pcu_check_true( eqNum );
-
-   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
-   feMesh = eqNum->feMesh;
-   eqNumsPerProc = (Mesh_GetDimSize( feMesh ) == 3) ? 27 : (Mesh_GetDimSize( feMesh ) == 2) ? 9 : 3;
-   if( rank >= 2 ) {
-      curEqNum = eqNumsPerProc;
-      curEqNum += 2 * (eqNumsPerProc / 3) * (rank - 2);
-      curEqNum += 1;
-   }
-   else if( rank == 1 )
-      curEqNum = 2;
-   curEqNum *= 2;
-
-   nLocalNodes = Mesh_GetLocalSize( feMesh, MT_VERTEX );
-   nDomainNodes = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-   for( n_i = nLocalNodes; n_i < nDomainNodes; n_i++ ) {
-      nDofs = eqNum->dofLayout->dofCounts[n_i];
-      for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
-	 if( eqNum->destinationArray[n_i][dof_i] != curEqNum++ )
-	    break;
-      }
-      if( dof_i < nDofs )
-	 break;
-
-      if( rank == 1 )
-	 curEqNum += 4;
-      else
-	 curEqNum += 2;
-   }
-   pcu_check_true( n_i == Mesh_GetDomainSize( feMesh, (MeshTopology_Dim)0 ) );
-
-   FreeObject( eqNum );
-}
-
-void FeEquationNumberSuite_TestBCs( FeEquationNumberSuiteData* data ) {
-   FeEquationNumber*	eqNum;
-   FeMesh*				feMesh;
-   unsigned				nLocalNodes, nDomainNodes;
-   unsigned				eqNumsPerProc;
-   unsigned				curEqNum;
-   unsigned				nDofs;
-   unsigned				dof_i;
-   unsigned				eq;
-   int					rank;
-   unsigned				n_i;
-
-   eqNum = buildEqNumBCs();
-   pcu_check_true( eqNum );
-
-   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
-   feMesh = eqNum->feMesh;
-   eqNumsPerProc = (Mesh_GetDimSize( feMesh ) == 3) ? 18 : (Mesh_GetDimSize( feMesh ) == 2) ? 6 : 0;
-   if( rank >= 2 ) {
-      curEqNum = eqNumsPerProc;
-      curEqNum += 2 * (eqNumsPerProc / 3) * (rank - 2);
-      curEqNum += 1;
-   }
-   else if( rank == 1 )
-      curEqNum = 2;
-   curEqNum *= 2;
-
-   nLocalNodes = Mesh_GetLocalSize( feMesh, MT_VERTEX );
-   nDomainNodes = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-   for( n_i = nLocalNodes; n_i < nDomainNodes; n_i++ ) {
-      nDofs = eqNum->dofLayout->dofCounts[n_i];
-      for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
-	 eq = eqNum->destinationArray[n_i][dof_i];
-
-	 if( n_i % 3 == 0 ) {
-	    if( eq != (unsigned)-1 )
-	       break;
-	 }
-	 else if( eq != curEqNum++ )
-	    break;
-      }
-      if( dof_i < nDofs )
-	 break;
-
-      if( n_i % 3 != 0 ) {
-	 if( rank == 1 )
-	    curEqNum += 4;
-	 else
-	    curEqNum += 2;
-      }
-   }
-   pcu_check_true( n_i == nDomainNodes );
-
-   FreeObject( eqNum );
-}
-
-void FeEquationNumberSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, FeEquationNumberSuiteData );
-   pcu_suite_setFixtures( suite, FeEquationNumberSuite_Setup, FeEquationNumberSuite_Teardown );
-   pcu_suite_addTest( suite, FeEquationNumberSuite_TestLocal );
-   pcu_suite_addTest( suite, FeEquationNumberSuite_TestShadow );
-   pcu_suite_addTest( suite, FeEquationNumberSuite_TestBCs );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/FeEquationNumberSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/tests/FeEquationNumberSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,335 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** Role:
+**   Tests the FeEquationNumberSuite
+**
+** $Id: testFeEquationNumber.c 3462 2006-02-19 06:53:24Z WalterLandry $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include "FeEquationNumberSuite.h"
+
+typedef struct {
+} FeEquationNumberSuiteData;
+
+FeEquationNumber* buildEqNum() {
+   CartesianGenerator*	gen;
+   FeMesh*					feMesh;
+   DofLayout*				dofs;
+   FeEquationNumber*		eqNum;
+   Variable_Register*	varReg;
+   Variable*				vars[2];
+   int						maxDecomp[3] = {0, 1, 1};
+   int						sizes[3];
+   double					minCrd[3];
+   double					maxCrd[3];
+   SizeT						dataOffs = 1;
+   Variable_DataType		dataType = Variable_DataType_Double;
+   int						nDataTypes = 1;
+   char*						dataNames = "nothing";
+   static SizeT			structSize = sizeof(double);
+   static int				arraySize;
+   static void*			arrayPtrs[2];
+   int						nRanks;
+
+   MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
+   sizes[0] = nRanks * 2;
+   sizes[1] = sizes[2] = 2;
+   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
+   maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
+
+   gen = CartesianGenerator_New( "", NULL );
+   CartesianGenerator_SetDimSize( gen, 3 );
+   CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
+   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+   CartesianGenerator_SetShadowDepth( gen, 0 );
+
+   feMesh = FeMesh_New( "", NULL );
+   Mesh_SetGenerator( feMesh, gen );
+   FeMesh_SetElementFamily( feMesh, "linear" );
+   Stg_Component_Build( feMesh, NULL, False );
+
+   varReg = Variable_Register_New();
+
+   arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+   arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize );
+   arrayPtrs[1] = Memory_Alloc_Array_Unnamed( double, arraySize );
+   vars[0] = Variable_New( "one", NULL, 1, &dataOffs, &dataType, (unsigned*)&nDataTypes, 
+                           (Name*)(&dataNames), &structSize, (unsigned*)&arraySize, NULL, arrayPtrs, varReg );
+   vars[1] = Variable_New( "two", NULL, 1, &dataOffs, &dataType, (unsigned*)&nDataTypes, 
+                           (Name*)(&dataNames), &structSize, (unsigned*)&arraySize, NULL, arrayPtrs + 1, varReg );
+
+   dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
+   dofs->nBaseVariables = 2;
+   dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 2 );
+   dofs->baseVariables[0] = vars[0];
+   dofs->baseVariables[1] = vars[1];
+   Stg_Component_Build( dofs, NULL, False );
+   Stg_Component_Initialise( dofs, NULL, False );
+
+   eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, NULL, NULL );
+   Stg_Component_Build( eqNum, NULL, False );
+   Stg_Component_Initialise( eqNum, NULL, False );
+
+   return eqNum;
+}
+
+FeEquationNumber* buildEqNumBCs() {
+   CartesianGenerator*				gen;
+   FeMesh*								feMesh;
+   DofLayout*							dofs;
+   FeEquationNumber*					eqNum;
+   Variable_Register*				varReg;
+   Variable*							vars[2];
+   int									maxDecomp[3] = {0, 1, 1};
+   int									sizes[3];
+   double								minCrd[3];
+   double								maxCrd[3];
+   SizeT									dataOffs = 1;
+   Variable_DataType					dataType = Variable_DataType_Double;
+   int									nDataTypes = 1;
+   char*									dataNames = "nothing";
+   static SizeT						structSize = sizeof(double);
+   static int							arraySize;
+   static void*						arrayPtrs[2];
+   int									nRanks;
+   VariableCondition*				bcs;
+   ConditionFunction_Register*	cfReg;
+   Dictionary*							dict;
+   XML_IO_Handler*					ioHandler;
+   char									filename[PCU_PATH_MAX];
+
+   MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
+   sizes[0] = nRanks * 2;
+   sizes[1] = sizes[2] = 2;
+   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
+   maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
+
+   gen = CartesianGenerator_New( "", NULL );
+   CartesianGenerator_SetDimSize( gen, 3 );
+   CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
+   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+   CartesianGenerator_SetShadowDepth( gen, 0 );
+
+   feMesh = FeMesh_New( "", NULL );
+   Mesh_SetGenerator( feMesh, gen );
+   FeMesh_SetElementFamily( feMesh, "linear" );
+   Stg_Component_Build( feMesh, NULL, False );
+
+   varReg = Variable_Register_New();
+   cfReg = ConditionFunction_Register_New();
+
+   arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+   arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize );
+   arrayPtrs[1] = Memory_Alloc_Array_Unnamed( double, arraySize );
+   vars[0] = Variable_New( "one", NULL, 1, &dataOffs, &dataType, (unsigned*)&nDataTypes, 
+                           (Name*)(&dataNames), &structSize, (unsigned*)&arraySize, NULL, arrayPtrs, varReg );
+	vars[1] = Variable_New( "two", NULL, 1, &dataOffs, &dataType, (unsigned*)&nDataTypes, 
+                                (Name*)(&dataNames), &structSize, (unsigned*)&arraySize, NULL, arrayPtrs + 1, varReg );
+
+   dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
+   dofs->nBaseVariables = 2;
+   dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 2 );
+   dofs->baseVariables[0] = vars[0];
+   dofs->baseVariables[1] = vars[1];
+   Stg_Component_Build( dofs, NULL, False );
+   Stg_Component_Initialise( dofs, NULL, False );
+
+   ioHandler = XML_IO_Handler_New();
+   dict = Dictionary_New();
+   pcu_filename_input( "wallVC.xml", filename );
+   IO_Handler_ReadAllFromFile( ioHandler, filename, dict );
+   bcs = (VariableCondition*)WallVC_New( "", NULL, "wallVC", varReg, cfReg, dict, feMesh );
+   Stg_Component_Build( bcs, NULL, False );
+   Stg_Component_Initialise( bcs, NULL, False );
+
+   eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, bcs, NULL );
+   Stg_Component_Build( eqNum, NULL, False );
+   Stg_Component_Initialise( eqNum, NULL, False );
+
+   return eqNum;
+}
+
+void FeEquationNumberSuite_Setup( FeEquationNumberSuiteData* data ) {
+	Journal_Enable_AllTypedStream( False );
+}
+
+void FeEquationNumberSuite_Teardown( FeEquationNumberSuiteData* data ) {
+}
+
+void FeEquationNumberSuite_TestLocal( FeEquationNumberSuiteData* data ) {
+   FeEquationNumber*	eqNum;
+   FeMesh*				feMesh;
+   int					eqNumsPerProc;
+   int					curEqNum;
+   int					nDofs;
+   int					rank;
+   int					n_i, dof_i;
+
+   eqNum = buildEqNum();
+   pcu_check_true( eqNum );
+
+   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+   feMesh = eqNum->feMesh;
+   eqNumsPerProc = (Mesh_GetDimSize( feMesh ) == 3) ? 27 : (Mesh_GetDimSize( feMesh ) == 2) ? 9 : 3;
+   curEqNum = eqNumsPerProc * rank;
+   if( rank >= 1 )
+      curEqNum -= (eqNumsPerProc / 3) * (rank - 1);
+   curEqNum *= 2;
+
+   for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, MT_VERTEX ); n_i++ ) {
+      nDofs = eqNum->dofLayout->dofCounts[n_i];
+      for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
+	 if( eqNum->destinationArray[n_i][dof_i] != curEqNum++ )
+	    break;
+      }
+      if( dof_i < nDofs )
+	 break;
+   }
+   pcu_check_true( n_i == Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ) );
+
+   FreeObject( eqNum );
+}
+
+void FeEquationNumberSuite_TestShadow( FeEquationNumberSuiteData* data ) {
+   FeEquationNumber*	eqNum;
+   FeMesh*				feMesh;
+   int					eqNumsPerProc;
+   int					curEqNum;
+   int					nDofs;
+   int					rank;
+   int					nLocalNodes, nDomainNodes;
+   int					n_i, dof_i;
+
+   eqNum = buildEqNum();
+   pcu_check_true( eqNum );
+
+   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+   feMesh = eqNum->feMesh;
+   eqNumsPerProc = (Mesh_GetDimSize( feMesh ) == 3) ? 27 : (Mesh_GetDimSize( feMesh ) == 2) ? 9 : 3;
+   if( rank >= 2 ) {
+      curEqNum = eqNumsPerProc;
+      curEqNum += 2 * (eqNumsPerProc / 3) * (rank - 2);
+      curEqNum += 1;
+   }
+   else if( rank == 1 )
+      curEqNum = 2;
+   curEqNum *= 2;
+
+   nLocalNodes = Mesh_GetLocalSize( feMesh, MT_VERTEX );
+   nDomainNodes = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+   for( n_i = nLocalNodes; n_i < nDomainNodes; n_i++ ) {
+      nDofs = eqNum->dofLayout->dofCounts[n_i];
+      for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
+	 if( eqNum->destinationArray[n_i][dof_i] != curEqNum++ )
+	    break;
+      }
+      if( dof_i < nDofs )
+	 break;
+
+      if( rank == 1 )
+	 curEqNum += 4;
+      else
+	 curEqNum += 2;
+   }
+   pcu_check_true( n_i == Mesh_GetDomainSize( feMesh, (MeshTopology_Dim)0 ) );
+
+   FreeObject( eqNum );
+}
+
+void FeEquationNumberSuite_TestBCs( FeEquationNumberSuiteData* data ) {
+   FeEquationNumber*	eqNum;
+   FeMesh*				feMesh;
+   unsigned				nLocalNodes, nDomainNodes;
+   unsigned				eqNumsPerProc;
+   unsigned				curEqNum;
+   unsigned				nDofs;
+   unsigned				dof_i;
+   unsigned				eq;
+   int					rank;
+   unsigned				n_i;
+
+   eqNum = buildEqNumBCs();
+   pcu_check_true( eqNum );
+
+   MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+   feMesh = eqNum->feMesh;
+   eqNumsPerProc = (Mesh_GetDimSize( feMesh ) == 3) ? 18 : (Mesh_GetDimSize( feMesh ) == 2) ? 6 : 0;
+   if( rank >= 2 ) {
+      curEqNum = eqNumsPerProc;
+      curEqNum += 2 * (eqNumsPerProc / 3) * (rank - 2);
+      curEqNum += 1;
+   }
+   else if( rank == 1 )
+      curEqNum = 2;
+   curEqNum *= 2;
+
+   nLocalNodes = Mesh_GetLocalSize( feMesh, MT_VERTEX );
+   nDomainNodes = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+   for( n_i = nLocalNodes; n_i < nDomainNodes; n_i++ ) {
+      nDofs = eqNum->dofLayout->dofCounts[n_i];
+      for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
+	 eq = eqNum->destinationArray[n_i][dof_i];
+
+	 if( n_i % 3 == 0 ) {
+	    if( eq != (unsigned)-1 )
+	       break;
+	 }
+	 else if( eq != curEqNum++ )
+	    break;
+      }
+      if( dof_i < nDofs )
+	 break;
+
+      if( n_i % 3 != 0 ) {
+	 if( rank == 1 )
+	    curEqNum += 4;
+	 else
+	    curEqNum += 2;
+      }
+   }
+   pcu_check_true( n_i == nDomainNodes );
+
+   FreeObject( eqNum );
+}
+
+void FeEquationNumberSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, FeEquationNumberSuiteData );
+   pcu_suite_setFixtures( suite, FeEquationNumberSuite_Setup, FeEquationNumberSuite_Teardown );
+   pcu_suite_addTest( suite, FeEquationNumberSuite_TestLocal );
+   pcu_suite_addTest( suite, FeEquationNumberSuite_TestShadow );
+   pcu_suite_addTest( suite, FeEquationNumberSuite_TestBCs );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/FeVariableSuite.c
--- a/Discretisation/tests/FeVariableSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,283 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** Role:
-**   Tests the FeVariableSuite
-**
-** $Id: testFeVariable.c 3462 2006-02-19 06:53:24Z WalterLandry $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include "FeVariableSuite.h"
-
-#define EPSILON 1.0E-6
-
-typedef struct {
-} FeVariableSuiteData;
-
-struct _Particle {
-	__IntegrationPoint;
-};
-
-FeVariable* BuildFeVariable_AsPosition( unsigned dim ) {
-	CartesianGenerator*		gen;
-	FeMesh*						feMesh;
-	DofLayout*					dofs;
-	FeEquationNumber*			eqNum;
-	Variable_Register*		varReg;
-	int							maxDecomp[3] = {0, 1, 1};
-	int							sizes[3];
-	double						minCrd[3];
-	double						maxCrd[3];
-	static int					arraySize;
-	static double*				arrayPtrs[3];
-	int							nRanks;
-	Variable*					var;
-	FieldVariable_Register*	fieldReg;
-	FeVariable*					feVar;
-	int							n_i;
-
-	MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
-	sizes[0] = nRanks * 3;
-	sizes[1] = sizes[2] = 3;
-	minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
-	maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
-
-	gen = CartesianGenerator_New( "", NULL );
-	CartesianGenerator_SetDimSize( gen, dim );
-	CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
-	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-	CartesianGenerator_SetShadowDepth( gen, 0 );
-
-	feMesh = FeMesh_New( "", NULL );
-	Mesh_SetGenerator( feMesh, gen );
-	FeMesh_SetElementFamily( feMesh, "linear" );
-	Stg_Component_Build( feMesh, NULL, False );
-
-	varReg = Variable_Register_New();
-
-	arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-	arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize * dim );
-
-	var = Variable_NewVector( "velocity", NULL, Variable_DataType_Double, dim, (unsigned*)&arraySize, NULL,
-		(void**)arrayPtrs, varReg, "vx", "vy", "vz" );
-	Variable_Register_BuildAll( varReg );
-
-	dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
-	dofs->nBaseVariables = dim;
-	dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, dim );
-	dofs->baseVariables[0] = var->components[0];
-	dofs->baseVariables[1] = var->components[1];
-	dofs->baseVariables[2] = var->components[2];
-	Stg_Component_Build( dofs, NULL, False );
-	Stg_Component_Initialise( dofs, NULL, False );
-	
-	eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, NULL, NULL );
-	Stg_Component_Build( eqNum, NULL, False );
-	Stg_Component_Initialise( eqNum, NULL, False );
-
-	fieldReg = FieldVariable_Register_New();
-	feVar = FeVariable_New( "velocity", NULL, feMesh, NULL, dofs, NULL, NULL, NULL, dim, True, False, False, fieldReg );
-
-	for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ); n_i++ ) {
-		double* pos = Mesh_GetVertex( feMesh, n_i );
-		Variable_SetValue( var, n_i, pos );
-	}
-
-	/* Build and initialise system */
-	Stg_Component_Build( feVar, 0, False );
-	Stg_Component_Initialise( feVar, 0, False );
-
-	return feVar;
-}
-
-FeVariable* BuildFeVariable_AsConstant( unsigned dim ) {
-	CartesianGenerator*		gen;
-	FeMesh*						feMesh;
-	DofLayout*					dofs;
-	FeEquationNumber*			eqNum;
-	Variable_Register*		varReg;
-	int							maxDecomp[3] = {0, 1, 1};
-	int							sizes[3];
-	double						minCrd[3];
-	double						maxCrd[3];
-	static int					arraySize;
-	static double*				arrayPtr;
-	int							nRanks;
-	Variable*					var;
-	FieldVariable_Register*	fieldReg;
-	FeVariable*					feVar;
-	int							n_i;
-	double constant[3] = {1.0, 1.0, 1.0};
-
-	MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
-	sizes[0] = nRanks * 3;
-	sizes[1] = sizes[2] = 3;
-	minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
-	maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
-
-	gen = CartesianGenerator_New( "", NULL );
-	CartesianGenerator_SetDimSize( gen, dim );
-	CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
-	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-	CartesianGenerator_SetShadowDepth( gen, 0 );
-
-	feMesh = FeMesh_New( "", NULL );
-	Mesh_SetGenerator( feMesh, gen );
-	FeMesh_SetElementFamily( feMesh, "linear" );
-	Stg_Component_Build( feMesh, NULL, False );
-
-	varReg = Variable_Register_New();
-
-	arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-	arrayPtr = Memory_Alloc_Array_Unnamed( double, arraySize );
-
-	var = Variable_NewScalar( "pressure", NULL, Variable_DataType_Double, (Index*)(unsigned*)&arraySize, NULL, (void**)&arrayPtr, varReg );
-	Variable_Register_BuildAll( varReg  );
-
-	dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
-	dofs->nBaseVariables = 1;
-	dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 1 );
-	dofs->baseVariables[0] = var;
-	Stg_Component_Build( dofs, NULL, False );
-	Stg_Component_Initialise( dofs, NULL, False );
-	
-	eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, NULL, NULL );
-	Stg_Component_Build( eqNum, NULL, False );
-	Stg_Component_Initialise( eqNum, NULL, False );
-
-	fieldReg = FieldVariable_Register_New();
-	feVar = FeVariable_New( "pressure", NULL, feMesh, NULL, dofs, NULL, NULL, NULL, dim, True, False, False, fieldReg );
-
-	for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ); n_i++ ) {
-		Variable_SetValue( var, n_i, constant );
-	}
-
-	/* Build and initialise system */
-	Stg_Component_Build( feVar, 0, False );
-	Stg_Component_Initialise( feVar, 0, False );
-
-	return feVar;
-}
-
-Swarm* BuildSwarm( FeMesh* mesh ) {
-	ElementCellLayout*		elCellLayout;
-	GaussParticleLayout* 		gaussLayout;
-	ExtensionManager_Register*	extMgr_Reg;
-	Swarm*				swarm;
-	unsigned			dim		= Mesh_GetDimSize( mesh );
-	unsigned			partPerDim[3]	= { 2, 2, 2 };
-	
-	extMgr_Reg = ExtensionManager_Register_New();
-	elCellLayout = ElementCellLayout_New( "elementCellLayout", NULL, mesh );
-	gaussLayout = GaussParticleLayout_New( "gaussParticleLayout", NULL, LocalCoordSystem, True, dim, partPerDim );
-	swarm = Swarm_New( "gaussSwarm", NULL, elCellLayout, gaussLayout, dim, sizeof(Particle), extMgr_Reg, NULL, MPI_COMM_WORLD, NULL );
-
-	Stg_Component_Build( swarm, NULL, True );
-	Stg_Component_Initialise( swarm, NULL, True );
-
-	return swarm;
-}
-
-void FeVariableSuite_Setup( FeVariableSuiteData* data ) {
-}
-
-void FeVariableSuite_Teardown( FeVariableSuiteData* data ) {
-}
-
-void FeVariableSuite_Interpolate( FeVariableSuiteData* data ) {
-	FeVariable*		feVar		= BuildFeVariable_AsPosition( 3 );
-	IArray*			inc		= IArray_New();
-	unsigned		el_i;
-	unsigned		vert_i;
-	unsigned		nVerts;
-	unsigned*		verts;
-	double*			vert;
-	double			value[3];
-	InterpolationResult	interpRes;
-	unsigned		dim_i;
-
-	for( el_i = 0; el_i < Mesh_GetDomainSize( feVar->feMesh, (MeshTopology_Dim)3 ); el_i++ ) {
-          Mesh_GetIncidence( feVar->feMesh, (MeshTopology_Dim)3, el_i, MT_VERTEX, inc );
-		nVerts = IArray_GetSize( inc );
-		verts = (unsigned*)IArray_GetPtr( inc );
-
-		for( vert_i = 0; vert_i < nVerts; vert_i++ ) {
-			vert = Mesh_GetVertex( feVar->feMesh, verts[vert_i] );
-			interpRes = FieldVariable_InterpolateValueAt( feVar, vert, value );
-
-			if( interpRes != LOCAL && interpRes != SHADOW )
-				continue;
-
-			for( dim_i = 0; dim_i < 3; dim_i++ ) {
-				pcu_check_true( fabs( vert[dim_i] - value[dim_i] ) < EPSILON );
-			}
-		}
-	}
-
-	NewClass_Delete( inc );
-	Stg_Component_Destroy( feVar, NULL, True );
-}
-
-void FeVariableSuite_Integrate( FeVariableSuiteData* data ) {
-	FeVariable*			feVar;
-	Swarm*				swarm;
-	double				globalMin[3];
-	double				globalMax[3];
-	double				volFromSize	= 1.0;
-	double				volFromInt;
-	unsigned			dim_i;
-
-	feVar = BuildFeVariable_AsConstant( 3 );
-	swarm = BuildSwarm( feVar->feMesh );
-
-	Mesh_GetGlobalCoordRange( feVar->feMesh, globalMin, globalMax );
-	for( dim_i = 0; dim_i < 3; dim_i++ )
-		volFromSize *= globalMax[dim_i] - globalMin[dim_i];
-
-	volFromInt = FeVariable_Integrate( feVar, swarm );
-
-	pcu_check_true( fabs( volFromSize - volFromInt ) < EPSILON );
-	
-	Stg_Component_Destroy( feVar, NULL, True );
-	Stg_Component_Destroy( swarm, NULL, True );
-}
-
-void FeVariableSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, FeVariableSuiteData );
-   pcu_suite_setFixtures( suite, FeVariableSuite_Setup, FeVariableSuite_Teardown );
-   pcu_suite_addTest( suite, FeVariableSuite_Interpolate );
-   pcu_suite_addTest( suite, FeVariableSuite_Integrate );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/FeVariableSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/tests/FeVariableSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,283 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** Role:
+**   Tests the FeVariableSuite
+**
+** $Id: testFeVariable.c 3462 2006-02-19 06:53:24Z WalterLandry $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include "FeVariableSuite.h"
+
+#define EPSILON 1.0E-6
+
+typedef struct {
+} FeVariableSuiteData;
+
+struct _Particle {
+	__IntegrationPoint;
+};
+
+FeVariable* BuildFeVariable_AsPosition( unsigned dim ) {
+	CartesianGenerator*		gen;
+	FeMesh*						feMesh;
+	DofLayout*					dofs;
+	FeEquationNumber*			eqNum;
+	Variable_Register*		varReg;
+	int							maxDecomp[3] = {0, 1, 1};
+	int							sizes[3];
+	double						minCrd[3];
+	double						maxCrd[3];
+	static int					arraySize;
+	static double*				arrayPtrs[3];
+	int							nRanks;
+	Variable*					var;
+	FieldVariable_Register*	fieldReg;
+	FeVariable*					feVar;
+	int							n_i;
+
+	MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
+	sizes[0] = nRanks * 3;
+	sizes[1] = sizes[2] = 3;
+	minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
+	maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
+
+	gen = CartesianGenerator_New( "", NULL );
+	CartesianGenerator_SetDimSize( gen, dim );
+	CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
+	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+	CartesianGenerator_SetShadowDepth( gen, 0 );
+
+	feMesh = FeMesh_New( "", NULL );
+	Mesh_SetGenerator( feMesh, gen );
+	FeMesh_SetElementFamily( feMesh, "linear" );
+	Stg_Component_Build( feMesh, NULL, False );
+
+	varReg = Variable_Register_New();
+
+	arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+	arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize * dim );
+
+	var = Variable_NewVector( "velocity", NULL, Variable_DataType_Double, dim, (unsigned*)&arraySize, NULL,
+		(void**)arrayPtrs, varReg, "vx", "vy", "vz" );
+	Variable_Register_BuildAll( varReg );
+
+	dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
+	dofs->nBaseVariables = dim;
+	dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, dim );
+	dofs->baseVariables[0] = var->components[0];
+	dofs->baseVariables[1] = var->components[1];
+	dofs->baseVariables[2] = var->components[2];
+	Stg_Component_Build( dofs, NULL, False );
+	Stg_Component_Initialise( dofs, NULL, False );
+	
+	eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, NULL, NULL );
+	Stg_Component_Build( eqNum, NULL, False );
+	Stg_Component_Initialise( eqNum, NULL, False );
+
+	fieldReg = FieldVariable_Register_New();
+	feVar = FeVariable_New( "velocity", NULL, feMesh, NULL, dofs, NULL, NULL, NULL, dim, True, False, False, fieldReg );
+
+	for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ); n_i++ ) {
+		double* pos = Mesh_GetVertex( feMesh, n_i );
+		Variable_SetValue( var, n_i, pos );
+	}
+
+	/* Build and initialise system */
+	Stg_Component_Build( feVar, 0, False );
+	Stg_Component_Initialise( feVar, 0, False );
+
+	return feVar;
+}
+
+FeVariable* BuildFeVariable_AsConstant( unsigned dim ) {
+	CartesianGenerator*		gen;
+	FeMesh*						feMesh;
+	DofLayout*					dofs;
+	FeEquationNumber*			eqNum;
+	Variable_Register*		varReg;
+	int							maxDecomp[3] = {0, 1, 1};
+	int							sizes[3];
+	double						minCrd[3];
+	double						maxCrd[3];
+	static int					arraySize;
+	static double*				arrayPtr;
+	int							nRanks;
+	Variable*					var;
+	FieldVariable_Register*	fieldReg;
+	FeVariable*					feVar;
+	int							n_i;
+	double constant[3] = {1.0, 1.0, 1.0};
+
+	MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
+	sizes[0] = nRanks * 3;
+	sizes[1] = sizes[2] = 3;
+	minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
+	maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
+
+	gen = CartesianGenerator_New( "", NULL );
+	CartesianGenerator_SetDimSize( gen, dim );
+	CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
+	CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+	CartesianGenerator_SetShadowDepth( gen, 0 );
+
+	feMesh = FeMesh_New( "", NULL );
+	Mesh_SetGenerator( feMesh, gen );
+	FeMesh_SetElementFamily( feMesh, "linear" );
+	Stg_Component_Build( feMesh, NULL, False );
+
+	varReg = Variable_Register_New();
+
+	arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+	arrayPtr = Memory_Alloc_Array_Unnamed( double, arraySize );
+
+	var = Variable_NewScalar( "pressure", NULL, Variable_DataType_Double, (Index*)(unsigned*)&arraySize, NULL, (void**)&arrayPtr, varReg );
+	Variable_Register_BuildAll( varReg  );
+
+	dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
+	dofs->nBaseVariables = 1;
+	dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 1 );
+	dofs->baseVariables[0] = var;
+	Stg_Component_Build( dofs, NULL, False );
+	Stg_Component_Initialise( dofs, NULL, False );
+	
+	eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, NULL, NULL );
+	Stg_Component_Build( eqNum, NULL, False );
+	Stg_Component_Initialise( eqNum, NULL, False );
+
+	fieldReg = FieldVariable_Register_New();
+	feVar = FeVariable_New( "pressure", NULL, feMesh, NULL, dofs, NULL, NULL, NULL, dim, True, False, False, fieldReg );
+
+	for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ); n_i++ ) {
+		Variable_SetValue( var, n_i, constant );
+	}
+
+	/* Build and initialise system */
+	Stg_Component_Build( feVar, 0, False );
+	Stg_Component_Initialise( feVar, 0, False );
+
+	return feVar;
+}
+
+Swarm* BuildSwarm( FeMesh* mesh ) {
+	ElementCellLayout*		elCellLayout;
+	GaussParticleLayout* 		gaussLayout;
+	ExtensionManager_Register*	extMgr_Reg;
+	Swarm*				swarm;
+	unsigned			dim		= Mesh_GetDimSize( mesh );
+	unsigned			partPerDim[3]	= { 2, 2, 2 };
+	
+	extMgr_Reg = ExtensionManager_Register_New();
+	elCellLayout = ElementCellLayout_New( "elementCellLayout", NULL, mesh );
+	gaussLayout = GaussParticleLayout_New( "gaussParticleLayout", NULL, LocalCoordSystem, True, dim, partPerDim );
+	swarm = Swarm_New( "gaussSwarm", NULL, elCellLayout, gaussLayout, dim, sizeof(Particle), extMgr_Reg, NULL, MPI_COMM_WORLD, NULL );
+
+	Stg_Component_Build( swarm, NULL, True );
+	Stg_Component_Initialise( swarm, NULL, True );
+
+	return swarm;
+}
+
+void FeVariableSuite_Setup( FeVariableSuiteData* data ) {
+}
+
+void FeVariableSuite_Teardown( FeVariableSuiteData* data ) {
+}
+
+void FeVariableSuite_Interpolate( FeVariableSuiteData* data ) {
+	FeVariable*		feVar		= BuildFeVariable_AsPosition( 3 );
+	IArray*			inc		= IArray_New();
+	unsigned		el_i;
+	unsigned		vert_i;
+	unsigned		nVerts;
+	unsigned*		verts;
+	double*			vert;
+	double			value[3];
+	InterpolationResult	interpRes;
+	unsigned		dim_i;
+
+	for( el_i = 0; el_i < Mesh_GetDomainSize( feVar->feMesh, (MeshTopology_Dim)3 ); el_i++ ) {
+          Mesh_GetIncidence( feVar->feMesh, (MeshTopology_Dim)3, el_i, MT_VERTEX, inc );
+		nVerts = IArray_GetSize( inc );
+		verts = (unsigned*)IArray_GetPtr( inc );
+
+		for( vert_i = 0; vert_i < nVerts; vert_i++ ) {
+			vert = Mesh_GetVertex( feVar->feMesh, verts[vert_i] );
+			interpRes = FieldVariable_InterpolateValueAt( feVar, vert, value );
+
+			if( interpRes != LOCAL && interpRes != SHADOW )
+				continue;
+
+			for( dim_i = 0; dim_i < 3; dim_i++ ) {
+				pcu_check_true( fabs( vert[dim_i] - value[dim_i] ) < EPSILON );
+			}
+		}
+	}
+
+	NewClass_Delete( inc );
+	Stg_Component_Destroy( feVar, NULL, True );
+}
+
+void FeVariableSuite_Integrate( FeVariableSuiteData* data ) {
+	FeVariable*			feVar;
+	Swarm*				swarm;
+	double				globalMin[3];
+	double				globalMax[3];
+	double				volFromSize	= 1.0;
+	double				volFromInt;
+	unsigned			dim_i;
+
+	feVar = BuildFeVariable_AsConstant( 3 );
+	swarm = BuildSwarm( feVar->feMesh );
+
+	Mesh_GetGlobalCoordRange( feVar->feMesh, globalMin, globalMax );
+	for( dim_i = 0; dim_i < 3; dim_i++ )
+		volFromSize *= globalMax[dim_i] - globalMin[dim_i];
+
+	volFromInt = FeVariable_Integrate( feVar, swarm );
+
+	pcu_check_true( fabs( volFromSize - volFromInt ) < EPSILON );
+	
+	Stg_Component_Destroy( feVar, NULL, True );
+	Stg_Component_Destroy( swarm, NULL, True );
+}
+
+void FeVariableSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, FeVariableSuiteData );
+   pcu_suite_setFixtures( suite, FeVariableSuite_Setup, FeVariableSuite_Teardown );
+   pcu_suite_addTest( suite, FeVariableSuite_Interpolate );
+   pcu_suite_addTest( suite, FeVariableSuite_Integrate );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/TrilinearElementTypeSuite.c
--- a/Discretisation/tests/TrilinearElementTypeSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,135 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** Role:
-**   Tests the TrilinearElementTypeSuite
-**
-** $Id: testTrilinearElementType.c 3462 2006-02-19 06:53:24Z WalterLandry $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include "TrilinearElementTypeSuite.h"
-
-typedef struct {
-} TrilinearElementTypeSuiteData;
-
-FeMesh* buildMesh() {
-   CartesianGenerator*	gen;
-   int						nRanks;
-   unsigned					sizes[3];
-   double					minCrd[3];
-   double					maxCrd[3];
-   FeMesh*					mesh;
-
-   insist( MPI_Comm_size( MPI_COMM_WORLD, &nRanks ), == MPI_SUCCESS );
-   sizes[0] = sizes[1] = sizes[2] = nRanks * 4;
-   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
-   maxCrd[0] = minCrd[1] = minCrd[2] = (double)nRanks;
-
-   gen = CartesianGenerator_New( "", NULL );
-   MeshGenerator_SetDimSize( gen, 3 );
-   CartesianGenerator_SetShadowDepth( gen, 1 );
-   CartesianGenerator_SetTopologyParams( gen, sizes, 0, NULL, NULL );
-   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-
-   mesh = FeMesh_New( "", NULL );
-   Mesh_SetGenerator( mesh, gen );
-   FeMesh_SetElementFamily( mesh, "linear" );
-   Stg_Component_Build( mesh, NULL, False );
-
-   return mesh;
-}
-
-void TrilinearElementTypeSuite_Setup( TrilinearElementTypeSuiteData* data ) {
-	Journal_Enable_AllTypedStream( False );
-
-	//Stream_RedirectAllToFile( "TrilinearElementTypeSuite" );
-}
-
-void TrilinearElementTypeSuite_Teardown( TrilinearElementTypeSuiteData* data ) {
-	//Stream_PurgeAllRedirectedFiles();
-}
-
-void TrilinearElementTypeSuite_TestShape( TrilinearElementTypeSuiteData* data ) {
-   FeMesh*		mesh = NULL;
-   int			nEls, nVerts, nDims;
-   const int	*verts;
-   double*		vert = NULL;
-   double		lCrd[3] = { 0.0, 0.0, 0.0 };
-	double		basis[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
-   IArray*		inc;
-   int			e_i, v_i, v_j;
-
-   mesh = buildMesh();
-   pcu_check_true( mesh );
-   Stg_Component_Initialise( mesh, data, True );
-
-   nDims = Mesh_GetDimSize( mesh );
-   nEls = Mesh_GetDomainSize( mesh, (MeshTopology_Dim)nDims );
-   inc = IArray_New();
-
-   for( e_i = 0; e_i < nEls; e_i++ ) {
-     Mesh_GetIncidence( mesh, (MeshTopology_Dim)nDims, e_i, (MeshTopology_Dim)0, inc );
-      nVerts = IArray_GetSize( inc );
-      verts = IArray_GetPtr( inc );
-
-      for( v_i = 0; v_i < nVerts; v_i++ ) {
-			vert = Mesh_GetVertex( mesh, verts[v_i] );
-			FeMesh_CoordGlobalToLocal( mesh, e_i, vert, lCrd );
-			FeMesh_EvalBasis( mesh, e_i, lCrd, basis );
-
-			for( v_j = 0; v_j < nVerts; v_j++ ) {
-				if( (v_i == v_j && !Num_Approx( basis[v_j], 1.0 )) || (v_i != v_j && !Num_Approx( basis[v_j], 0.0 )) ) {
-					break;
-				}
-			}
-			if( v_j < nVerts )
-				break;
-      }
-      if( v_i < nVerts )
-			break;
-   }
-   pcu_check_true( e_i == nEls );
-
-   NewClass_Delete( inc );
-
-   _Stg_Component_Delete( mesh );
-}
-
-void TrilinearElementTypeSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, TrilinearElementTypeSuiteData );
-   pcu_suite_setFixtures( suite, TrilinearElementTypeSuite_Setup, TrilinearElementTypeSuite_Teardown );
-   pcu_suite_addTest( suite, TrilinearElementTypeSuite_TestShape );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 Discretisation/tests/TrilinearElementTypeSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Discretisation/tests/TrilinearElementTypeSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,135 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** Role:
+**   Tests the TrilinearElementTypeSuite
+**
+** $Id: testTrilinearElementType.c 3462 2006-02-19 06:53:24Z WalterLandry $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include "TrilinearElementTypeSuite.h"
+
+typedef struct {
+} TrilinearElementTypeSuiteData;
+
+FeMesh* buildMesh() {
+   CartesianGenerator*	gen;
+   int						nRanks;
+   unsigned					sizes[3];
+   double					minCrd[3];
+   double					maxCrd[3];
+   FeMesh*					mesh;
+
+   insist( MPI_Comm_size( MPI_COMM_WORLD, &nRanks ), == MPI_SUCCESS );
+   sizes[0] = sizes[1] = sizes[2] = nRanks * 4;
+   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
+   maxCrd[0] = minCrd[1] = minCrd[2] = (double)nRanks;
+
+   gen = CartesianGenerator_New( "", NULL );
+   MeshGenerator_SetDimSize( gen, 3 );
+   CartesianGenerator_SetShadowDepth( gen, 1 );
+   CartesianGenerator_SetTopologyParams( gen, sizes, 0, NULL, NULL );
+   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+
+   mesh = FeMesh_New( "", NULL );
+   Mesh_SetGenerator( mesh, gen );
+   FeMesh_SetElementFamily( mesh, "linear" );
+   Stg_Component_Build( mesh, NULL, False );
+
+   return mesh;
+}
+
+void TrilinearElementTypeSuite_Setup( TrilinearElementTypeSuiteData* data ) {
+	Journal_Enable_AllTypedStream( False );
+
+	//Stream_RedirectAllToFile( "TrilinearElementTypeSuite" );
+}
+
+void TrilinearElementTypeSuite_Teardown( TrilinearElementTypeSuiteData* data ) {
+	//Stream_PurgeAllRedirectedFiles();
+}
+
+void TrilinearElementTypeSuite_TestShape( TrilinearElementTypeSuiteData* data ) {
+   FeMesh*		mesh = NULL;
+   int			nEls, nVerts, nDims;
+   const int	*verts;
+   double*		vert = NULL;
+   double		lCrd[3] = { 0.0, 0.0, 0.0 };
+	double		basis[8] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
+   IArray*		inc;
+   int			e_i, v_i, v_j;
+
+   mesh = buildMesh();
+   pcu_check_true( mesh );
+   Stg_Component_Initialise( mesh, data, True );
+
+   nDims = Mesh_GetDimSize( mesh );
+   nEls = Mesh_GetDomainSize( mesh, (MeshTopology_Dim)nDims );
+   inc = IArray_New();
+
+   for( e_i = 0; e_i < nEls; e_i++ ) {
+     Mesh_GetIncidence( mesh, (MeshTopology_Dim)nDims, e_i, (MeshTopology_Dim)0, inc );
+      nVerts = IArray_GetSize( inc );
+      verts = IArray_GetPtr( inc );
+
+      for( v_i = 0; v_i < nVerts; v_i++ ) {
+			vert = Mesh_GetVertex( mesh, verts[v_i] );
+			FeMesh_CoordGlobalToLocal( mesh, e_i, vert, lCrd );
+			FeMesh_EvalBasis( mesh, e_i, lCrd, basis );
+
+			for( v_j = 0; v_j < nVerts; v_j++ ) {
+				if( (v_i == v_j && !Num_Approx( basis[v_j], 1.0 )) || (v_i != v_j && !Num_Approx( basis[v_j], 0.0 )) ) {
+					break;
+				}
+			}
+			if( v_j < nVerts )
+				break;
+      }
+      if( v_i < nVerts )
+			break;
+   }
+   pcu_check_true( e_i == nEls );
+
+   NewClass_Delete( inc );
+
+   _Stg_Component_Delete( mesh );
+}
+
+void TrilinearElementTypeSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, TrilinearElementTypeSuiteData );
+   pcu_suite_setFixtures( suite, TrilinearElementTypeSuite_Setup, TrilinearElementTypeSuite_Teardown );
+   pcu_suite_addTest( suite, TrilinearElementTypeSuite_TestShape );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SConscript
--- a/SConscript	Wed May 11 14:43:33 2011 -0700
+++ b/SConscript	Thu May 12 11:19:05 2011 -0700
@@ -60,8 +60,8 @@ for d in dirs:
     defs = env.Install(inc_dir, Glob(src_dir + '/*.def'))
 
     # Build our source files.
-    srcs = Glob(src_dir + '/*.c')
-    srcs = [s for s in srcs if s.path.find('-meta.c') == -1]
+    srcs = Glob(src_dir + '/*.cxx')
+    srcs = [s for s in srcs if s.path.find('-meta.cxx') == -1]
     objs += env.SharedObject(srcs, CPPDEFINES=cpp_defs)
 
     # Build any meta files.
@@ -73,7 +73,7 @@ for d in dirs:
         env.Depends(hdrs + objs, defs)
 
     # Build any test suites we might find.
-    suites += env.Object(Glob(tst_dir + '/*Suite.c'))
+    suites += env.Object(Glob(tst_dir + '/*Suite.cxx'))
 
     # Install any test expected and input files
     tst_exp += env.Install(tst_install_dir + '/expected', Glob(tst_exp_dir + '/*'))
@@ -118,8 +118,8 @@ for d in dirs:
 
     env.Install('include/StgFEM/' + d.split('/')[-1], Glob(d + '/*.h'))
 
-    srcs = Glob(d + '/*.c')
-    srcs = [s for s in srcs if s.path.find('-meta.c') == -1]
+    srcs = Glob(d + '/*.cxx')
+    srcs = [s for s in srcs if s.path.find('-meta.cxx') == -1]
     cur_objs = env.SharedObject(srcs, CPPDEFINES=cpp_defs)
     cur_objs += env.stgSharedMeta(Glob(d + '/*.meta'), CPPDEFINES=cpp_defs)
 
@@ -220,7 +220,7 @@ if env['static_libs']:
     reg_c += '\n   stg_num_modules += %d;\n'%len(pl_regs)
     reg_c += '}\n'
 
-    reg_filename = os.path.join(env['build_dir'], 'StgFEM', 'stgfem_static_modules.c')
+    reg_filename = os.path.join(env['build_dir'], 'StgFEM', 'stgfem_static_modules.cxx')
     if not os.path.exists(os.path.dirname(reg_filename)):
         os.makedirs(os.path.dirname(reg_filename))
     reg_file = open(reg_filename, 'w')
@@ -229,12 +229,12 @@ if env['static_libs']:
     reg_obj = env.Object(reg_filename)
 
     # Add our register function to the StGermain module file.
-    f = open(File(env['build_dir'] + '/StGermain/stg_static_modules.c').abspath, 'r')
+    f = open(File(env['build_dir'] + '/StGermain/stg_static_modules.cxx').abspath, 'r')
     txt = f.readlines()
     f.close()
     txt.insert(-2, '   stgfem_register_static_modules();\n')
     txt.insert(0, 'void stgfem_register_static_modules();\n')
-    f = open(File(env['build_dir'] + '/StGermain/stg_static_modules.c').abspath, 'w')
+    f = open(File(env['build_dir'] + '/StGermain/stg_static_modules.cxx').abspath, 'w')
     f.writelines(txt)
     f.close()
 
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/AdvectionDiffusionSLE.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/AdvectionDiffusionSLE.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,461 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: AdvectionDiffusionSLE.c 999 2008-01-09 04:13:42Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <assert.h>
-#include <string.h>
-
-#include "mpi.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-
-#include "types.h"
-#include "AdvectionDiffusionSLE.h"
-#include "UpwindParameter.h"
-#include "Residual.h"
-#include "Multicorrector.h"
-#include "Timestep.h"
-
-const Type AdvectionDiffusionSLE_Type = "AdvectionDiffusionSLE";
-
-AdvectionDiffusionSLE* AdvectionDiffusionSLE_New( 
-	Name							name,
-	SLE_Solver*					solver,
-	FiniteElementContext*	context,
-	Bool							isNonLinear,
-	double						nonLinearTolerance,
-	Iteration_Index			nonLinearMaxIterations,
-	Bool							killNonConvergent,		
-	EntryPoint_Register*		entryPoint_Register,
-	MPI_Comm						comm,
-	FeVariable*					phiField,
-	ForceVector*				residual,
-	Stg_Component*				massMatrix,
-	Dimension_Index			dim,
-	double						courantFactor,
-	Variable_Register*		variable_Register,
-	FieldVariable_Register*	fieldVariable_Register ) 
-{	
-	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*) _AdvectionDiffusionSLE_DefaultNew( name );
-
-	self->isConstructed = True;	
-	_SystemLinearEquations_Init( self, solver, NULL, context, False, isNonLinear, nonLinearTolerance,
-		nonLinearMaxIterations, killNonConvergent, 1, "", "", entryPoint_Register, comm );
-	_AdvectionDiffusionSLE_Init( self, phiField, residual, massMatrix, dim, courantFactor, variable_Register, fieldVariable_Register );
-
-	 return self;
-}
-
-/* Creation implementation / Virtual constructor */
-AdvectionDiffusionSLE* _AdvectionDiffusionSLE_New(  ADVECTIONDIFFUSIONSLE_DEFARGS  )
-{
-	AdvectionDiffusionSLE* self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(AdvectionDiffusionSLE) );
-	self = (AdvectionDiffusionSLE*) _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_PASSARGS  );
-
-	return self;
-}
-
-void _AdvectionDiffusionSLE_Init(
-	void*							sle,
-	FeVariable*					phiField,
-	ForceVector*				residual,
-	Stg_Component*				massMatrix,
-	Dimension_Index			dim,
-	double						courantFactor,
-	Variable_Register*		variable_Register,  
-	FieldVariable_Register*	fieldVariable_Register )		
-{
-	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*)sle;
-
-	/* Assign values */
-	self->phiField = phiField;
-	self->residual = residual;
-	self->massMatrix = massMatrix;
-	self->dim = dim;
-	self->courantFactor = courantFactor;
-
-	/* Solution Vectors are loaded up as part of the algorithm so we can remove this one */
-	EP_Remove( self->executeEP, "UpdateSolutionOntoNodes" );
-	EP_Remove( self->executeEP, "MatrixSetup" );
-	EP_Remove( self->executeEP, "VectorSetup" );
-
-	/* Put Pointer of Solver onto vectors */
-	if (residual) {
-		residual->applicationDepExtraInfo   = (Stg_Component*) self;
-		SystemLinearEquations_AddForceVector( self, residual );
-	}
-	if (massMatrix && Stg_Class_IsInstance( massMatrix, ForceVector_Type ) ) {
-		((ForceVector*) massMatrix)->applicationDepExtraInfo = (Stg_Component*) self;
-		SystemLinearEquations_AddForceVector( self, massMatrix );
-	}
-	else if (massMatrix && Stg_Class_IsInstance( massMatrix, StiffnessMatrix_Type ) ) {
-		((StiffnessMatrix*) massMatrix)->applicationDepInfo = (Stg_Component*) self;
-		SystemLinearEquations_AddStiffnessMatrix( self, massMatrix );
-	}
-
-	self->variableReg = variable_Register;
-	self->fieldVariableReg = fieldVariable_Register;
-
-	if ( self->context ) {
-		/* Create a specific name for the calcDt hook */
-		char* tmpName = Memory_Alloc_Array_Unnamed( char, strlen(self->name) + 7 + 1 );
-		sprintf( tmpName, "%s_CalcDt", self->name );
-		EntryPoint_AppendClassHook( self->context->calcDtEP, tmpName, (void*)AdvectionDiffusionSLE_CalculateDt, self->type, self );
-		//EP_AppendClassHook( self->context->calcDtEP, AdvectionDiffusionSLE_CalculateDt, self );
-		Memory_Free( tmpName );
-	}
-}	
-
-/** Virtual Functions from "Class" Class */
-void _AdvectionDiffusionSLE_Delete( void* sle ) {
-	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*)sle;
-
-	_SystemLinearEquations_Delete( self );
-}
-
-void _AdvectionDiffusionSLE_Print( void* sle, Stream* stream ) {
-	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*) sle;
-	
-	Journal_Printf( stream, "Printing contents of SLE Advection Diffusion '%s':\n", self->name );
-	Stream_Indent( stream );
-		Journal_PrintPointer( stream, self );
-		_Stg_Component_Print( self, stream );
-
-		Journal_Printf( stream, "Items from Constructor:\n");
-		Stream_Indent( stream );
-			Journal_PrintPointer( stream, self->phiField );
-			Journal_PrintPointer( stream, self->residual );
-			Journal_PrintPointer( stream, self->massMatrix );
-			Journal_PrintUnsignedInt( stream, self->dim );
-		Stream_UnIndent( stream );
-
-		Journal_Printf( stream, "Items from created by SLE self:\n");
-		Stream_Indent( stream );
-			Journal_PrintPointer( stream, self->phiDotArray );
-			Journal_PrintPointer( stream, self->phiDotField );
-			Journal_PrintPointer( stream, self->phiDotDofLayout );
-			Journal_PrintPointer( stream, self->phiVector );
-			Journal_PrintPointer( stream, self->phiDotVector );
-		Stream_UnIndent( stream );
-
-		Journal_Printf( stream, "Parameters set from dictionary:\n");
-		Stream_Indent( stream );
-			Journal_PrintDouble( stream, self->courantFactor );
-		Stream_UnIndent( stream );
-					
-		Journal_Printf( stream, "Stored Values:\n");
-		Stream_Indent( stream );
-			Journal_PrintDouble( stream, self->maxDiffusivity );
-		Stream_UnIndent( stream );
-
-	Stream_UnIndent( stream );
-}
-
-
-void* _AdvectionDiffusionSLE_Copy( const void* _sle, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	AdvectionDiffusionSLE*	self = (AdvectionDiffusionSLE*) _sle;
-	AdvectionDiffusionSLE*	newSLE;
-	
-	newSLE = (AdvectionDiffusionSLE*)_SystemLinearEquations_Copy( self, dest, deep, nameExt, ptrMap );
-	
-	/* TODO: Copy Method */
-	abort();
-	
-	return (void*)newSLE;
-}
-
-void* _AdvectionDiffusionSLE_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                       _sizeOfSelf = sizeof(AdvectionDiffusionSLE);
-	Type                                                               type = AdvectionDiffusionSLE_Type;
-	Stg_Class_DeleteFunction*                                       _delete = _AdvectionDiffusionSLE_Delete;
-	Stg_Class_PrintFunction*                                         _print = _AdvectionDiffusionSLE_Print;
-	Stg_Class_CopyFunction*                                           _copy = _AdvectionDiffusionSLE_Copy;
-	Stg_Component_DefaultConstructorFunction*           _defaultConstructor = _AdvectionDiffusionSLE_DefaultNew;
-	Stg_Component_ConstructFunction*                             _construct = _AdvectionDiffusionSLE_AssignFromXML;
-	Stg_Component_BuildFunction*                                     _build = _AdvectionDiffusionSLE_Build;
-	Stg_Component_InitialiseFunction*                           _initialise = _AdvectionDiffusionSLE_Initialise;
-	Stg_Component_ExecuteFunction*                                 _execute = _AdvectionDiffusionSLE_Execute;
-	Stg_Component_DestroyFunction*                                 _destroy = _AdvectionDiffusionSLE_Destroy;
-	SystemLinearEquations_LM_SetupFunction*                       _LM_Setup = _SystemLinearEquations_LM_Setup;
-	SystemLinearEquations_MatrixSetupFunction*                 _matrixSetup = _SystemLinearEquations_MatrixSetup;
-	SystemLinearEquations_VectorSetupFunction*                 _vectorSetup = _SystemLinearEquations_VectorSetup;
-	SystemLinearEquations_MG_SelectStiffMatsFunc*        _mgSelectStiffMats = _SystemLinearEquations_MG_SelectStiffMats;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType                                            nameAllocationType = (AllocationType)ZERO;
-	SystemLinearEquations_UpdateSolutionOntoNodesFunc*  _updateSolutionOntoNodes = ZERO;
-
-	return (void*) _AdvectionDiffusionSLE_New(  ADVECTIONDIFFUSIONSLE_PASSARGS  );
-}
-
-void _AdvectionDiffusionSLE_AssignFromXML( void* sle, Stg_ComponentFactory* cf, void* data ) {
-	AdvectionDiffusionSLE*	self = (AdvectionDiffusionSLE*) sle;
-	Stream*						error = Journal_Register( Error_Type, (Name)self->type  );
-	FeVariable*					phiField;
-	ForceVector*				residual;
-	Stg_Component*				massMatrix;
-	Dimension_Index			dim;
-	double						courantFactor;
-	FieldVariable_Register*	fieldVariable_Register;
-	Variable_Register*		variable_Register;
-
-	/* Construct Parent */
-	_SystemLinearEquations_AssignFromXML( self, cf, data );
-
-	/* Get Registers */
-	variable_Register = self->context->variable_Register; 
-	assert( variable_Register );
-	fieldVariable_Register = self->context->fieldVariable_Register; 
-	assert( fieldVariable_Register );
-
-	/* Get Dependency Stg_Components */
-	phiField   =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PhiField", FeVariable, True, data  );
-	residual   =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Residual", ForceVector, True, data  );
-	massMatrix =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"MassMatrix", Stg_Component, True, data  );
-
-	dim = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"dim", 0  );
-
-	courantFactor = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"courantFactor", 0.5  );
-	Journal_Firewall( 0.0 < courantFactor && courantFactor <= 1.0, 
-		error, "In func %s: CourantFactor read in from dictionary = %2.4f - This must be from 0 - 1.\n", 
-		__func__, courantFactor );
-
-	_AdvectionDiffusionSLE_Init(
-		self,
-		phiField,
-		residual,
-		massMatrix,
-		dim,
-		courantFactor,
-		variable_Register, 
-		fieldVariable_Register );
-}
-
-void _AdvectionDiffusionSLE_Destroy( void* sle, void* data ) {
-	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*) sle;
-
-	Memory_Free( self->phiDotArray );
-
-	_SystemLinearEquations_Destroy( self, data );
-}
-
-/** Virtual Functions from "Stg_Component" Class */
-void _AdvectionDiffusionSLE_Build( void* sle, void* data ) {
-	AdvectionDiffusionSLE*	self = (AdvectionDiffusionSLE*) sle;
-	Stream*						errorStream = Journal_MyStream( Error_Type, self );
-	Index							forceTerm_I;
-	Index							forceTermCount = Stg_ObjectList_Count( self->residual->forceTermList );
-	ForceTerm*					forceTerm;
-	unsigned int				*nodeDomainCountPtr;
-	Variable*					variable;
-	Node_DomainIndex			node_I;
-
-	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
-
-	/* Create New FeVariable for Phi Dot */
-	if (self->phiField) {
-		Variable_Register*			variable_Register;
-		FieldVariable_Register*		fieldVariable_Register;
-		char*								fieldName, *dofName, *fieldDotName, *phiVecName, *phiDotVecName;
-
-		variable_Register = self->variableReg;
-		fieldVariable_Register = self->fieldVariableReg;
-
-		Stg_Component_Build( self->phiField->feMesh, NULL, False );
-
-		assert( Class_IsSuper( self->phiField->feMesh->topo, IGraph ) );
-		nodeDomainCountPtr = (unsigned*)(&((IGraph*)self->phiField->feMesh->topo)->remotes[MT_VERTEX]->nDomains);
-
- 		/* must create unique names otherwise multiple instances of this component
-		* will index incorrect instances of this component's data */
-		fieldName = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+8 );
-		sprintf( fieldName, "%s-phiDot", self->name );
-
-		dofName = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+11 );
-		sprintf( dofName, "%s-dofLayout", self->name );
-
-		fieldDotName  = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+13 );
-		sprintf( fieldDotName, "%s-phiDotField", self->name );
-
-		phiVecName = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+11 );
-		sprintf( phiVecName, "%s-phiVector", self->name );
-
-		phiDotVecName = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+14 );
-		sprintf( phiDotVecName, "%s-phiDotVector", self->name );
-
-		variable = Variable_NewScalar( fieldName, (AbstractContext*)self->context, Variable_DataType_Double, (Index*)nodeDomainCountPtr, NULL, (void**)&self->phiDotArray, variable_Register  );
-
-		self->phiDotDofLayout = DofLayout_New( dofName, (DomainContext*)self->context, variable_Register, *nodeDomainCountPtr, NULL );
-		//self->phiDotDofLayout = DofLayout_New( "dofLayout1", variable_Register, *nodeDomainCountPtr, NULL );
-		for( node_I = 0; node_I < *nodeDomainCountPtr ; node_I++ ) 
-			DofLayout_AddDof_ByVarName( self->phiDotDofLayout, variable->name, node_I );
-
-		self->phiDotField = FeVariable_New_FromTemplate(
-			fieldDotName,
-			(DomainContext*) self->context,
-			self->phiField,
-			self->phiDotDofLayout,
-			NULL,
-			False, False,
-			fieldVariable_Register );
-		self->phiDotField->context = (DomainContext*)self->context;
-
-		/* Construct Solution Vectors */
-		self->phiVector = SolutionVector_New( phiVecName, self->context, self->phiField->communicator, self->phiField );
-		self->phiDotVector = SolutionVector_New( phiDotVecName, self->context, self->phiField->communicator, self->phiDotField );
-
-		/* free original name variables */
-		Memory_Free(fieldName);
-		Memory_Free(dofName);
-		Memory_Free(fieldDotName);
-		Memory_Free(phiVecName);
-		Memory_Free(phiDotVecName);
-	}
-
-	_SystemLinearEquations_Build( self, data );
-
-	/* Get pointer to residual force term 
-	 * All Advection Diffusion SLE's need a force term of type AdvDiffResidualForceTerm for the algorithm to work
-	 * this chunk of code is making sure that one and only one is registered to the force vector */
-	for ( forceTerm_I = 0 ; forceTerm_I < forceTermCount ; forceTerm_I++ ) {
-		forceTerm = (ForceTerm*) Stg_ObjectList_At( self->residual->forceTermList, forceTerm_I );
-
-		if ( Stg_Class_IsInstance( forceTerm, AdvDiffResidualForceTerm_Type ) ) {
-			/* Check to make sure this force term is unique */
-			if (self->advDiffResidualForceTerm != NULL) {
-				Journal_Firewall( self->advDiffResidualForceTerm == NULL, errorStream, 
-						"Error - More than one force term of type '%s' registered on %s '%s'. \n\tThey are %s and %s.\n", 
-						AdvDiffResidualForceTerm_Type, self->type, self->name, 
-						self->advDiffResidualForceTerm->name, forceTerm->name);
-			}
-
-			/* Store pointer to force term */
-			self->advDiffResidualForceTerm = (AdvDiffResidualForceTerm*) forceTerm;
-                       
-			/* HACK */
-			Stg_Component_Build( self->advDiffResidualForceTerm->velocityField, data, False );
-
-		}
-	}
-	/* Ensure that there is at least one force term with proper residual type */
-	Journal_Firewall( self->advDiffResidualForceTerm != NULL, errorStream,
-			"Error - No force terms of type '%s' registered on %s '%s'.\n",
-			AdvDiffResidualForceTerm_Type, self->type, self->name );
-
-	if ( self->phiDotField ) {
-		self->phiDotArray = Memory_Alloc_Array( 
-			double, Mesh_GetDomainSize( self->phiDotField->feMesh, MT_VERTEX ), "phiDotArray" );
-	}
-
-	/* Force Vectors */
-	if ( self->residual )
-		Stg_Component_Build( self->residual, data, False );
-	if ( self->massMatrix )
-		Stg_Component_Build( self->massMatrix, data, False );
-	
-	/* Solution Vectors */
-	if ( self->phiVector )
-		Stg_Component_Build( self->phiVector, data, False );
-	if ( self->phiDotVector )
-		Stg_Component_Build( self->phiDotVector, data, False );
-}
-
-void _AdvectionDiffusionSLE_Initialise( void* sle, void* data ) {
-	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*) sle;
-	FiniteElementContext* context = (FiniteElementContext*) data;
-
-	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
-
-	_SystemLinearEquations_Initialise( self, data );
-	
-	Stg_Component_Initialise( self->phiDotField, data, False );
-
-/* 	Stream* stream = Journal_Register( Info_Type, (Name)self->type  ); */
-/* 	FeVariable_PrintLocalDiscreteValues( self->phiDotField, stream ); */
-	
-	if ( False == context->loadFromCheckPoint ) {
-		DofLayout_SetAllToZero( self->phiDotField->dofLayout );
-	}
-
-	/* Force Vectors */
-	Stg_Component_Initialise( self->residual, data, False );
-	Stg_Component_Initialise( self->massMatrix, data, False );
-	
-	/* Solution Vectors */
-	Stg_Component_Initialise( self->phiVector, data, False );
-	Stg_Component_Initialise( self->phiDotVector, data, False );
-
-	AdvectionDiffusionSLE_ResetStoredValues( self );
-}
-
-void _AdvectionDiffusionSLE_Execute( void* sle, void* _context ) {
-	AdvectionDiffusionSLE*     self  = (AdvectionDiffusionSLE*) sle;
-	FiniteElementContext*      context = (FiniteElementContext*) _context;
-	double                     dt      = context->dt;
-	
-	AdvectionDiffusionSLE_ResetStoredValues( self );
-	self->currentDt = dt;
-	
-	_SystemLinearEquations_Execute( self, context );
-}
-
-
-//Vector* _AdvectionDiffusionSLE_GetResidual( void* sle, Index fv_I ) {
-Vec _AdvectionDiffusionSLE_GetResidual( void* sle, Index fv_I ) {
-	AdvectionDiffusionSLE* self  = (AdvectionDiffusionSLE*) sle;
-	return self->residual->vector;
-}
-
-#define SMALL_VALUE 1.0e-99
-
-void AdvectionDiffusionSLE_ResetStoredValues( void* sle ) {
-	AdvectionDiffusionSLE* self  = (AdvectionDiffusionSLE*) sle;
-	
-	self->maxDiffusivity = SMALL_VALUE;
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/AdvectionDiffusionSLE.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/AdvectionDiffusionSLE.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,461 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: AdvectionDiffusionSLE.c 999 2008-01-09 04:13:42Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <assert.h>
+#include <string.h>
+
+#include "mpi.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+
+#include "types.h"
+#include "AdvectionDiffusionSLE.h"
+#include "UpwindParameter.h"
+#include "Residual.h"
+#include "Multicorrector.h"
+#include "Timestep.h"
+
+const Type AdvectionDiffusionSLE_Type = "AdvectionDiffusionSLE";
+
+AdvectionDiffusionSLE* AdvectionDiffusionSLE_New( 
+	Name							name,
+	SLE_Solver*					solver,
+	FiniteElementContext*	context,
+	Bool							isNonLinear,
+	double						nonLinearTolerance,
+	Iteration_Index			nonLinearMaxIterations,
+	Bool							killNonConvergent,		
+	EntryPoint_Register*		entryPoint_Register,
+	MPI_Comm						comm,
+	FeVariable*					phiField,
+	ForceVector*				residual,
+	Stg_Component*				massMatrix,
+	Dimension_Index			dim,
+	double						courantFactor,
+	Variable_Register*		variable_Register,
+	FieldVariable_Register*	fieldVariable_Register ) 
+{	
+	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*) _AdvectionDiffusionSLE_DefaultNew( name );
+
+	self->isConstructed = True;	
+	_SystemLinearEquations_Init( self, solver, NULL, context, False, isNonLinear, nonLinearTolerance,
+		nonLinearMaxIterations, killNonConvergent, 1, "", "", entryPoint_Register, comm );
+	_AdvectionDiffusionSLE_Init( self, phiField, residual, massMatrix, dim, courantFactor, variable_Register, fieldVariable_Register );
+
+	 return self;
+}
+
+/* Creation implementation / Virtual constructor */
+AdvectionDiffusionSLE* _AdvectionDiffusionSLE_New(  ADVECTIONDIFFUSIONSLE_DEFARGS  )
+{
+	AdvectionDiffusionSLE* self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(AdvectionDiffusionSLE) );
+	self = (AdvectionDiffusionSLE*) _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_PASSARGS  );
+
+	return self;
+}
+
+void _AdvectionDiffusionSLE_Init(
+	void*							sle,
+	FeVariable*					phiField,
+	ForceVector*				residual,
+	Stg_Component*				massMatrix,
+	Dimension_Index			dim,
+	double						courantFactor,
+	Variable_Register*		variable_Register,  
+	FieldVariable_Register*	fieldVariable_Register )		
+{
+	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*)sle;
+
+	/* Assign values */
+	self->phiField = phiField;
+	self->residual = residual;
+	self->massMatrix = massMatrix;
+	self->dim = dim;
+	self->courantFactor = courantFactor;
+
+	/* Solution Vectors are loaded up as part of the algorithm so we can remove this one */
+	EP_Remove( self->executeEP, "UpdateSolutionOntoNodes" );
+	EP_Remove( self->executeEP, "MatrixSetup" );
+	EP_Remove( self->executeEP, "VectorSetup" );
+
+	/* Put Pointer of Solver onto vectors */
+	if (residual) {
+		residual->applicationDepExtraInfo   = (Stg_Component*) self;
+		SystemLinearEquations_AddForceVector( self, residual );
+	}
+	if (massMatrix && Stg_Class_IsInstance( massMatrix, ForceVector_Type ) ) {
+		((ForceVector*) massMatrix)->applicationDepExtraInfo = (Stg_Component*) self;
+		SystemLinearEquations_AddForceVector( self, massMatrix );
+	}
+	else if (massMatrix && Stg_Class_IsInstance( massMatrix, StiffnessMatrix_Type ) ) {
+		((StiffnessMatrix*) massMatrix)->applicationDepInfo = (Stg_Component*) self;
+		SystemLinearEquations_AddStiffnessMatrix( self, massMatrix );
+	}
+
+	self->variableReg = variable_Register;
+	self->fieldVariableReg = fieldVariable_Register;
+
+	if ( self->context ) {
+		/* Create a specific name for the calcDt hook */
+		char* tmpName = Memory_Alloc_Array_Unnamed( char, strlen(self->name) + 7 + 1 );
+		sprintf( tmpName, "%s_CalcDt", self->name );
+		EntryPoint_AppendClassHook( self->context->calcDtEP, tmpName, (void*)AdvectionDiffusionSLE_CalculateDt, self->type, self );
+		//EP_AppendClassHook( self->context->calcDtEP, AdvectionDiffusionSLE_CalculateDt, self );
+		Memory_Free( tmpName );
+	}
+}	
+
+/** Virtual Functions from "Class" Class */
+void _AdvectionDiffusionSLE_Delete( void* sle ) {
+	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*)sle;
+
+	_SystemLinearEquations_Delete( self );
+}
+
+void _AdvectionDiffusionSLE_Print( void* sle, Stream* stream ) {
+	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*) sle;
+	
+	Journal_Printf( stream, "Printing contents of SLE Advection Diffusion '%s':\n", self->name );
+	Stream_Indent( stream );
+		Journal_PrintPointer( stream, self );
+		_Stg_Component_Print( self, stream );
+
+		Journal_Printf( stream, "Items from Constructor:\n");
+		Stream_Indent( stream );
+			Journal_PrintPointer( stream, self->phiField );
+			Journal_PrintPointer( stream, self->residual );
+			Journal_PrintPointer( stream, self->massMatrix );
+			Journal_PrintUnsignedInt( stream, self->dim );
+		Stream_UnIndent( stream );
+
+		Journal_Printf( stream, "Items from created by SLE self:\n");
+		Stream_Indent( stream );
+			Journal_PrintPointer( stream, self->phiDotArray );
+			Journal_PrintPointer( stream, self->phiDotField );
+			Journal_PrintPointer( stream, self->phiDotDofLayout );
+			Journal_PrintPointer( stream, self->phiVector );
+			Journal_PrintPointer( stream, self->phiDotVector );
+		Stream_UnIndent( stream );
+
+		Journal_Printf( stream, "Parameters set from dictionary:\n");
+		Stream_Indent( stream );
+			Journal_PrintDouble( stream, self->courantFactor );
+		Stream_UnIndent( stream );
+					
+		Journal_Printf( stream, "Stored Values:\n");
+		Stream_Indent( stream );
+			Journal_PrintDouble( stream, self->maxDiffusivity );
+		Stream_UnIndent( stream );
+
+	Stream_UnIndent( stream );
+}
+
+
+void* _AdvectionDiffusionSLE_Copy( const void* _sle, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	AdvectionDiffusionSLE*	self = (AdvectionDiffusionSLE*) _sle;
+	AdvectionDiffusionSLE*	newSLE;
+	
+	newSLE = (AdvectionDiffusionSLE*)_SystemLinearEquations_Copy( self, dest, deep, nameExt, ptrMap );
+	
+	/* TODO: Copy Method */
+	abort();
+	
+	return (void*)newSLE;
+}
+
+void* _AdvectionDiffusionSLE_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                       _sizeOfSelf = sizeof(AdvectionDiffusionSLE);
+	Type                                                               type = AdvectionDiffusionSLE_Type;
+	Stg_Class_DeleteFunction*                                       _delete = _AdvectionDiffusionSLE_Delete;
+	Stg_Class_PrintFunction*                                         _print = _AdvectionDiffusionSLE_Print;
+	Stg_Class_CopyFunction*                                           _copy = _AdvectionDiffusionSLE_Copy;
+	Stg_Component_DefaultConstructorFunction*           _defaultConstructor = _AdvectionDiffusionSLE_DefaultNew;
+	Stg_Component_ConstructFunction*                             _construct = _AdvectionDiffusionSLE_AssignFromXML;
+	Stg_Component_BuildFunction*                                     _build = _AdvectionDiffusionSLE_Build;
+	Stg_Component_InitialiseFunction*                           _initialise = _AdvectionDiffusionSLE_Initialise;
+	Stg_Component_ExecuteFunction*                                 _execute = _AdvectionDiffusionSLE_Execute;
+	Stg_Component_DestroyFunction*                                 _destroy = _AdvectionDiffusionSLE_Destroy;
+	SystemLinearEquations_LM_SetupFunction*                       _LM_Setup = _SystemLinearEquations_LM_Setup;
+	SystemLinearEquations_MatrixSetupFunction*                 _matrixSetup = _SystemLinearEquations_MatrixSetup;
+	SystemLinearEquations_VectorSetupFunction*                 _vectorSetup = _SystemLinearEquations_VectorSetup;
+	SystemLinearEquations_MG_SelectStiffMatsFunc*        _mgSelectStiffMats = _SystemLinearEquations_MG_SelectStiffMats;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType                                            nameAllocationType = (AllocationType)ZERO;
+	SystemLinearEquations_UpdateSolutionOntoNodesFunc*  _updateSolutionOntoNodes = ZERO;
+
+	return (void*) _AdvectionDiffusionSLE_New(  ADVECTIONDIFFUSIONSLE_PASSARGS  );
+}
+
+void _AdvectionDiffusionSLE_AssignFromXML( void* sle, Stg_ComponentFactory* cf, void* data ) {
+	AdvectionDiffusionSLE*	self = (AdvectionDiffusionSLE*) sle;
+	Stream*						error = Journal_Register( Error_Type, (Name)self->type  );
+	FeVariable*					phiField;
+	ForceVector*				residual;
+	Stg_Component*				massMatrix;
+	Dimension_Index			dim;
+	double						courantFactor;
+	FieldVariable_Register*	fieldVariable_Register;
+	Variable_Register*		variable_Register;
+
+	/* Construct Parent */
+	_SystemLinearEquations_AssignFromXML( self, cf, data );
+
+	/* Get Registers */
+	variable_Register = self->context->variable_Register; 
+	assert( variable_Register );
+	fieldVariable_Register = self->context->fieldVariable_Register; 
+	assert( fieldVariable_Register );
+
+	/* Get Dependency Stg_Components */
+	phiField   =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PhiField", FeVariable, True, data  );
+	residual   =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Residual", ForceVector, True, data  );
+	massMatrix =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"MassMatrix", Stg_Component, True, data  );
+
+	dim = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"dim", 0  );
+
+	courantFactor = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"courantFactor", 0.5  );
+	Journal_Firewall( 0.0 < courantFactor && courantFactor <= 1.0, 
+		error, "In func %s: CourantFactor read in from dictionary = %2.4f - This must be from 0 - 1.\n", 
+		__func__, courantFactor );
+
+	_AdvectionDiffusionSLE_Init(
+		self,
+		phiField,
+		residual,
+		massMatrix,
+		dim,
+		courantFactor,
+		variable_Register, 
+		fieldVariable_Register );
+}
+
+void _AdvectionDiffusionSLE_Destroy( void* sle, void* data ) {
+	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*) sle;
+
+	Memory_Free( self->phiDotArray );
+
+	_SystemLinearEquations_Destroy( self, data );
+}
+
+/** Virtual Functions from "Stg_Component" Class */
+void _AdvectionDiffusionSLE_Build( void* sle, void* data ) {
+	AdvectionDiffusionSLE*	self = (AdvectionDiffusionSLE*) sle;
+	Stream*						errorStream = Journal_MyStream( Error_Type, self );
+	Index							forceTerm_I;
+	Index							forceTermCount = Stg_ObjectList_Count( self->residual->forceTermList );
+	ForceTerm*					forceTerm;
+	unsigned int				*nodeDomainCountPtr;
+	Variable*					variable;
+	Node_DomainIndex			node_I;
+
+	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
+
+	/* Create New FeVariable for Phi Dot */
+	if (self->phiField) {
+		Variable_Register*			variable_Register;
+		FieldVariable_Register*		fieldVariable_Register;
+		char*								fieldName, *dofName, *fieldDotName, *phiVecName, *phiDotVecName;
+
+		variable_Register = self->variableReg;
+		fieldVariable_Register = self->fieldVariableReg;
+
+		Stg_Component_Build( self->phiField->feMesh, NULL, False );
+
+		assert( Class_IsSuper( self->phiField->feMesh->topo, IGraph ) );
+		nodeDomainCountPtr = (unsigned*)(&((IGraph*)self->phiField->feMesh->topo)->remotes[MT_VERTEX]->nDomains);
+
+ 		/* must create unique names otherwise multiple instances of this component
+		* will index incorrect instances of this component's data */
+		fieldName = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+8 );
+		sprintf( fieldName, "%s-phiDot", self->name );
+
+		dofName = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+11 );
+		sprintf( dofName, "%s-dofLayout", self->name );
+
+		fieldDotName  = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+13 );
+		sprintf( fieldDotName, "%s-phiDotField", self->name );
+
+		phiVecName = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+11 );
+		sprintf( phiVecName, "%s-phiVector", self->name );
+
+		phiDotVecName = Memory_Alloc_Array_Unnamed( char, strlen(self->name)+14 );
+		sprintf( phiDotVecName, "%s-phiDotVector", self->name );
+
+		variable = Variable_NewScalar( fieldName, (AbstractContext*)self->context, Variable_DataType_Double, (Index*)nodeDomainCountPtr, NULL, (void**)&self->phiDotArray, variable_Register  );
+
+		self->phiDotDofLayout = DofLayout_New( dofName, (DomainContext*)self->context, variable_Register, *nodeDomainCountPtr, NULL );
+		//self->phiDotDofLayout = DofLayout_New( "dofLayout1", variable_Register, *nodeDomainCountPtr, NULL );
+		for( node_I = 0; node_I < *nodeDomainCountPtr ; node_I++ ) 
+			DofLayout_AddDof_ByVarName( self->phiDotDofLayout, variable->name, node_I );
+
+		self->phiDotField = FeVariable_New_FromTemplate(
+			fieldDotName,
+			(DomainContext*) self->context,
+			self->phiField,
+			self->phiDotDofLayout,
+			NULL,
+			False, False,
+			fieldVariable_Register );
+		self->phiDotField->context = (DomainContext*)self->context;
+
+		/* Construct Solution Vectors */
+		self->phiVector = SolutionVector_New( phiVecName, self->context, self->phiField->communicator, self->phiField );
+		self->phiDotVector = SolutionVector_New( phiDotVecName, self->context, self->phiField->communicator, self->phiDotField );
+
+		/* free original name variables */
+		Memory_Free(fieldName);
+		Memory_Free(dofName);
+		Memory_Free(fieldDotName);
+		Memory_Free(phiVecName);
+		Memory_Free(phiDotVecName);
+	}
+
+	_SystemLinearEquations_Build( self, data );
+
+	/* Get pointer to residual force term 
+	 * All Advection Diffusion SLE's need a force term of type AdvDiffResidualForceTerm for the algorithm to work
+	 * this chunk of code is making sure that one and only one is registered to the force vector */
+	for ( forceTerm_I = 0 ; forceTerm_I < forceTermCount ; forceTerm_I++ ) {
+		forceTerm = (ForceTerm*) Stg_ObjectList_At( self->residual->forceTermList, forceTerm_I );
+
+		if ( Stg_Class_IsInstance( forceTerm, AdvDiffResidualForceTerm_Type ) ) {
+			/* Check to make sure this force term is unique */
+			if (self->advDiffResidualForceTerm != NULL) {
+				Journal_Firewall( self->advDiffResidualForceTerm == NULL, errorStream, 
+						"Error - More than one force term of type '%s' registered on %s '%s'. \n\tThey are %s and %s.\n", 
+						AdvDiffResidualForceTerm_Type, self->type, self->name, 
+						self->advDiffResidualForceTerm->name, forceTerm->name);
+			}
+
+			/* Store pointer to force term */
+			self->advDiffResidualForceTerm = (AdvDiffResidualForceTerm*) forceTerm;
+                       
+			/* HACK */
+			Stg_Component_Build( self->advDiffResidualForceTerm->velocityField, data, False );
+
+		}
+	}
+	/* Ensure that there is at least one force term with proper residual type */
+	Journal_Firewall( self->advDiffResidualForceTerm != NULL, errorStream,
+			"Error - No force terms of type '%s' registered on %s '%s'.\n",
+			AdvDiffResidualForceTerm_Type, self->type, self->name );
+
+	if ( self->phiDotField ) {
+		self->phiDotArray = Memory_Alloc_Array( 
+			double, Mesh_GetDomainSize( self->phiDotField->feMesh, MT_VERTEX ), "phiDotArray" );
+	}
+
+	/* Force Vectors */
+	if ( self->residual )
+		Stg_Component_Build( self->residual, data, False );
+	if ( self->massMatrix )
+		Stg_Component_Build( self->massMatrix, data, False );
+	
+	/* Solution Vectors */
+	if ( self->phiVector )
+		Stg_Component_Build( self->phiVector, data, False );
+	if ( self->phiDotVector )
+		Stg_Component_Build( self->phiDotVector, data, False );
+}
+
+void _AdvectionDiffusionSLE_Initialise( void* sle, void* data ) {
+	AdvectionDiffusionSLE* self = (AdvectionDiffusionSLE*) sle;
+	FiniteElementContext* context = (FiniteElementContext*) data;
+
+	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
+
+	_SystemLinearEquations_Initialise( self, data );
+	
+	Stg_Component_Initialise( self->phiDotField, data, False );
+
+/* 	Stream* stream = Journal_Register( Info_Type, (Name)self->type  ); */
+/* 	FeVariable_PrintLocalDiscreteValues( self->phiDotField, stream ); */
+	
+	if ( False == context->loadFromCheckPoint ) {
+		DofLayout_SetAllToZero( self->phiDotField->dofLayout );
+	}
+
+	/* Force Vectors */
+	Stg_Component_Initialise( self->residual, data, False );
+	Stg_Component_Initialise( self->massMatrix, data, False );
+	
+	/* Solution Vectors */
+	Stg_Component_Initialise( self->phiVector, data, False );
+	Stg_Component_Initialise( self->phiDotVector, data, False );
+
+	AdvectionDiffusionSLE_ResetStoredValues( self );
+}
+
+void _AdvectionDiffusionSLE_Execute( void* sle, void* _context ) {
+	AdvectionDiffusionSLE*     self  = (AdvectionDiffusionSLE*) sle;
+	FiniteElementContext*      context = (FiniteElementContext*) _context;
+	double                     dt      = context->dt;
+	
+	AdvectionDiffusionSLE_ResetStoredValues( self );
+	self->currentDt = dt;
+	
+	_SystemLinearEquations_Execute( self, context );
+}
+
+
+//Vector* _AdvectionDiffusionSLE_GetResidual( void* sle, Index fv_I ) {
+Vec _AdvectionDiffusionSLE_GetResidual( void* sle, Index fv_I ) {
+	AdvectionDiffusionSLE* self  = (AdvectionDiffusionSLE*) sle;
+	return self->residual->vector;
+}
+
+#define SMALL_VALUE 1.0e-99
+
+void AdvectionDiffusionSLE_ResetStoredValues( void* sle ) {
+	AdvectionDiffusionSLE* self  = (AdvectionDiffusionSLE*) sle;
+	
+	self->maxDiffusivity = SMALL_VALUE;
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Finalise.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Finalise.h"
-
-#include <stdio.h>
-
-Bool StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Finalise( void ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,58 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Finalise.h"
+
+#include <stdio.h>
+
+Bool StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Finalise( void ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Init.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Init.h"
-#include "AdvectionDiffusion.h"
-
-#include <stdio.h>
-
-Stream* StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Debug = NULL;
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Init( int* argc, char** argv[] ) {
-	Stg_ComponentRegister* componentRegister = Stg_ComponentRegister_Get_ComponentRegister();
-
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	/* initialise this level's streams */
-	StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Debug = Stream_RegisterChild( StgFEM_SLE_Debug,
-		"ProvidedSystems_AdvectionDiffusion" );
-
-	Stg_ComponentRegister_Add( componentRegister, AdvectionDiffusionSLE_Type, (Name)"0", _AdvectionDiffusionSLE_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, AdvDiffResidualForceTerm_Type, (Name)"0", _AdvDiffResidualForceTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, LumpedMassMatrixForceTerm_Type, (Name)"0", _LumpedMassMatrixForceTerm_DefaultNew  );
-	Stg_ComponentRegister_Add( componentRegister, AdvDiffMulticorrector_Type, (Name)"0", _AdvDiffMulticorrector_DefaultNew  );
-
-	RegisterParent( AdvectionDiffusionSLE_Type,     SystemLinearEquations_Type );
-	RegisterParent( AdvDiffResidualForceTerm_Type,  ForceTerm_Type );
-	RegisterParent( LumpedMassMatrixForceTerm_Type, ForceTerm_Type );
-	RegisterParent( AdvDiffMulticorrector_Type,     SLE_Solver_Type );
-	
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,79 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Init.h"
+#include "AdvectionDiffusion.h"
+
+#include <stdio.h>
+
+Stream* StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Debug = NULL;
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Init( int* argc, char** argv[] ) {
+	Stg_ComponentRegister* componentRegister = Stg_ComponentRegister_Get_ComponentRegister();
+
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	/* initialise this level's streams */
+	StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Debug = Stream_RegisterChild( StgFEM_SLE_Debug,
+		"ProvidedSystems_AdvectionDiffusion" );
+
+	Stg_ComponentRegister_Add( componentRegister, AdvectionDiffusionSLE_Type, (Name)"0", _AdvectionDiffusionSLE_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, AdvDiffResidualForceTerm_Type, (Name)"0", _AdvDiffResidualForceTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, LumpedMassMatrixForceTerm_Type, (Name)"0", _LumpedMassMatrixForceTerm_DefaultNew  );
+	Stg_ComponentRegister_Add( componentRegister, AdvDiffMulticorrector_Type, (Name)"0", _AdvDiffMulticorrector_DefaultNew  );
+
+	RegisterParent( AdvectionDiffusionSLE_Type,     SystemLinearEquations_Type );
+	RegisterParent( AdvDiffResidualForceTerm_Type,  ForceTerm_Type );
+	RegisterParent( LumpedMassMatrixForceTerm_Type, ForceTerm_Type );
+	RegisterParent( AdvDiffMulticorrector_Type,     SLE_Solver_Type );
+	
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/LumpedMassMatrixForceTerm.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/LumpedMassMatrixForceTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,236 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LumpedMassMatrixForceTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
-
-#include "types.h"
-#include "LumpedMassMatrixForceTerm.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type LumpedMassMatrixForceTerm_Type = "LumpedMassMatrixForceTerm";
-
-LumpedMassMatrixForceTerm* LumpedMassMatrixForceTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	ForceVector*				forceVector,
-	Swarm*						integrationSwarm )
-{
-	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*) _LumpedMassMatrixForceTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ForceTerm_Init( self, context, forceVector, integrationSwarm, NULL );
-	_LumpedMassMatrixForceTerm_Init( self );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-LumpedMassMatrixForceTerm* _LumpedMassMatrixForceTerm_New(  LUMPEDMASSMATRIXFORCETERM_DEFARGS  )
-{
-	LumpedMassMatrixForceTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(LumpedMassMatrixForceTerm) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (LumpedMassMatrixForceTerm*) _ForceTerm_New(  FORCETERM_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _LumpedMassMatrixForceTerm_Init( void* forceTerm ) {
-}
-
-void _LumpedMassMatrixForceTerm_Delete( void* forceTerm ) {
-	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
-
-	_ForceTerm_Delete( self );
-}
-
-void _LumpedMassMatrixForceTerm_Print( void* forceTerm, Stream* stream ) {
-	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
-	
-	_ForceTerm_Print( self, stream );
-
-	/* General info */
-}
-
-void* _LumpedMassMatrixForceTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(LumpedMassMatrixForceTerm);
-	Type                                                      type = LumpedMassMatrixForceTerm_Type;
-	Stg_Class_DeleteFunction*                              _delete = _LumpedMassMatrixForceTerm_Delete;
-	Stg_Class_PrintFunction*                                _print = _LumpedMassMatrixForceTerm_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LumpedMassMatrixForceTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _LumpedMassMatrixForceTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _LumpedMassMatrixForceTerm_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _LumpedMassMatrixForceTerm_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _LumpedMassMatrixForceTerm_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _LumpedMassMatrixForceTerm_Destroy;
-	ForceTerm_AssembleElementFunction*            _assembleElement = _LumpedMassMatrixForceTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_LumpedMassMatrixForceTerm_New(  LUMPEDMASSMATRIXFORCETERM_PASSARGS  );
-}
-
-void _LumpedMassMatrixForceTerm_AssignFromXML( void* forceTerm, Stg_ComponentFactory* cf, void* data ) {
-	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
-
-	/* Construct Parent */
-	_ForceTerm_AssignFromXML( self, cf, data );
-
-	_LumpedMassMatrixForceTerm_Init( self );
-}
-
-void _LumpedMassMatrixForceTerm_Build( void* forceTerm, void* data ) {
-	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
-
-	_ForceTerm_Build( self, data );
-}
-
-void _LumpedMassMatrixForceTerm_Initialise( void* forceTerm, void* data ) {
-	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
-
-	_ForceTerm_Initialise( self, data );
-}
-
-void _LumpedMassMatrixForceTerm_Execute( void* forceTerm, void* data ) {
-	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
-
-	_ForceTerm_Execute( self, data );
-}
-
-void _LumpedMassMatrixForceTerm_Destroy( void* forceTerm, void* data ) {
-	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
-
-	_ForceTerm_Destroy( self, data );
-}
-
-void _LumpedMassMatrixForceTerm_AssembleElement( void* forceTerm, ForceVector* forceVector ,Element_LocalIndex lElement_I, double* elForceVector ) {
-	LumpedMassMatrixForceTerm* self = Stg_CheckType( forceTerm, LumpedMassMatrixForceTerm );
-
-#if 0
-	if ( Stg_Class_IsInstance( mesh->layout->elementLayout, ParallelPipedHexaEL_Type ) ) {
-		ForceTerm_SetAssembleElementFunction( self, _LumpedMassMatrixForceTerm_AssembleElement_Box  );
-	}
-	else {
-#endif
-		ForceTerm_SetAssembleElementFunction( self, _LumpedMassMatrixForceTerm_AssembleElement_General  );
-#if 0
-	}
-#endif
-
-	ForceTerm_AssembleElement( self, forceVector, lElement_I, elForceVector );
-}
-
-void _LumpedMassMatrixForceTerm_AssembleElement_General( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elForceVector ) {
-	LumpedMassMatrixForceTerm* self              = Stg_CheckType( forceTerm, LumpedMassMatrixForceTerm );
-	FeVariable*                feVariable        = forceVector->feVariable;
-	Dimension_Index            dim               = forceVector->dim;
-	Swarm*                     swarm             = self->integrationSwarm;
-	FeMesh*				feMesh              = feVariable->feMesh;
-	ElementType*               elementType       = FeMesh_GetElementType( feMesh, lElement_I );
-	Cell_Index                 cell_I            = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
-	Particle_InCellIndex       cellParticleCount;
-	Particle_InCellIndex       cParticle_I;
-	IntegrationPoint*          particle;
-	Node_Index                 nodeRow_I;
-	Node_Index                 nodeColumn_I;
-	double                     factor;
-	double                     detJac;
-	double                     shapeFunc[27];
-	unsigned			elementNodeCount;
-
-	elementNodeCount = FeMesh_GetElementNodeSize( feMesh, lElement_I );
-	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-	
-	for( cParticle_I = 0 ; cParticle_I < cellParticleCount; cParticle_I++ ) {
-		/* Find this particle in the element */
-		particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
-
-		/* Evalutate Shape Functions and Jacobian Determinant */
-		ElementType_EvaluateShapeFunctionsAt( elementType, particle->xi, shapeFunc );
-		detJac = ElementType_JacobianDeterminant( elementType, feMesh, lElement_I, particle->xi, dim );
-	
-		/* Integrate \int_{\Omgea} N_i N_i d\Omega and lump onto vector in one step */
-		factor = detJac * particle->weight;
-		for ( nodeRow_I = 0 ; nodeRow_I < elementNodeCount ; nodeRow_I++ ) 
-			for ( nodeColumn_I = 0 ; nodeColumn_I < elementNodeCount ; nodeColumn_I++ ) 
-				elForceVector[ nodeRow_I ] += shapeFunc[ nodeRow_I ] * shapeFunc[ nodeColumn_I ] * factor ; 
-	}
-}
-
-/** Shortcut for doing above calculation, optimised for a box shaped element */
-void _LumpedMassMatrixForceTerm_AssembleElement_Box( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elForceVector ) {
-	FeVariable*                feVariable        = forceVector->feVariable;
-	Dimension_Index            dim               = forceVector->dim;
-	FeMesh*			feMesh              = feVariable->feMesh;
-	Element_NodeIndex          elementNodeCount;
-	ElementType*               elementType;
-	Node_Index                 node_I;
-	double                     detJac;
-	Coord                      xi = {0.0,0.0,0.0};
-
-	elementNodeCount = FeMesh_GetElementNodeSize( feMesh, lElement_I );
-	elementType = FeMesh_GetElementType( feMesh, lElement_I );
-	
-	detJac = ElementType_JacobianDeterminant( elementType, feMesh, lElement_I, xi, dim );
-	for ( node_I = 0 ; node_I < elementNodeCount ; node_I++ ) 
-		elForceVector[ node_I ] = detJac;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/LumpedMassMatrixForceTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/LumpedMassMatrixForceTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,236 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LumpedMassMatrixForceTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
+
+#include "types.h"
+#include "LumpedMassMatrixForceTerm.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type LumpedMassMatrixForceTerm_Type = "LumpedMassMatrixForceTerm";
+
+LumpedMassMatrixForceTerm* LumpedMassMatrixForceTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	ForceVector*				forceVector,
+	Swarm*						integrationSwarm )
+{
+	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*) _LumpedMassMatrixForceTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ForceTerm_Init( self, context, forceVector, integrationSwarm, NULL );
+	_LumpedMassMatrixForceTerm_Init( self );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+LumpedMassMatrixForceTerm* _LumpedMassMatrixForceTerm_New(  LUMPEDMASSMATRIXFORCETERM_DEFARGS  )
+{
+	LumpedMassMatrixForceTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(LumpedMassMatrixForceTerm) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (LumpedMassMatrixForceTerm*) _ForceTerm_New(  FORCETERM_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _LumpedMassMatrixForceTerm_Init( void* forceTerm ) {
+}
+
+void _LumpedMassMatrixForceTerm_Delete( void* forceTerm ) {
+	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
+
+	_ForceTerm_Delete( self );
+}
+
+void _LumpedMassMatrixForceTerm_Print( void* forceTerm, Stream* stream ) {
+	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
+	
+	_ForceTerm_Print( self, stream );
+
+	/* General info */
+}
+
+void* _LumpedMassMatrixForceTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(LumpedMassMatrixForceTerm);
+	Type                                                      type = LumpedMassMatrixForceTerm_Type;
+	Stg_Class_DeleteFunction*                              _delete = _LumpedMassMatrixForceTerm_Delete;
+	Stg_Class_PrintFunction*                                _print = _LumpedMassMatrixForceTerm_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LumpedMassMatrixForceTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _LumpedMassMatrixForceTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _LumpedMassMatrixForceTerm_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _LumpedMassMatrixForceTerm_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _LumpedMassMatrixForceTerm_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _LumpedMassMatrixForceTerm_Destroy;
+	ForceTerm_AssembleElementFunction*            _assembleElement = _LumpedMassMatrixForceTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_LumpedMassMatrixForceTerm_New(  LUMPEDMASSMATRIXFORCETERM_PASSARGS  );
+}
+
+void _LumpedMassMatrixForceTerm_AssignFromXML( void* forceTerm, Stg_ComponentFactory* cf, void* data ) {
+	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
+
+	/* Construct Parent */
+	_ForceTerm_AssignFromXML( self, cf, data );
+
+	_LumpedMassMatrixForceTerm_Init( self );
+}
+
+void _LumpedMassMatrixForceTerm_Build( void* forceTerm, void* data ) {
+	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
+
+	_ForceTerm_Build( self, data );
+}
+
+void _LumpedMassMatrixForceTerm_Initialise( void* forceTerm, void* data ) {
+	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
+
+	_ForceTerm_Initialise( self, data );
+}
+
+void _LumpedMassMatrixForceTerm_Execute( void* forceTerm, void* data ) {
+	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
+
+	_ForceTerm_Execute( self, data );
+}
+
+void _LumpedMassMatrixForceTerm_Destroy( void* forceTerm, void* data ) {
+	LumpedMassMatrixForceTerm* self = (LumpedMassMatrixForceTerm*)forceTerm;
+
+	_ForceTerm_Destroy( self, data );
+}
+
+void _LumpedMassMatrixForceTerm_AssembleElement( void* forceTerm, ForceVector* forceVector ,Element_LocalIndex lElement_I, double* elForceVector ) {
+	LumpedMassMatrixForceTerm* self = Stg_CheckType( forceTerm, LumpedMassMatrixForceTerm );
+
+#if 0
+	if ( Stg_Class_IsInstance( mesh->layout->elementLayout, ParallelPipedHexaEL_Type ) ) {
+		ForceTerm_SetAssembleElementFunction( self, _LumpedMassMatrixForceTerm_AssembleElement_Box  );
+	}
+	else {
+#endif
+		ForceTerm_SetAssembleElementFunction( self, _LumpedMassMatrixForceTerm_AssembleElement_General  );
+#if 0
+	}
+#endif
+
+	ForceTerm_AssembleElement( self, forceVector, lElement_I, elForceVector );
+}
+
+void _LumpedMassMatrixForceTerm_AssembleElement_General( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elForceVector ) {
+	LumpedMassMatrixForceTerm* self              = Stg_CheckType( forceTerm, LumpedMassMatrixForceTerm );
+	FeVariable*                feVariable        = forceVector->feVariable;
+	Dimension_Index            dim               = forceVector->dim;
+	Swarm*                     swarm             = self->integrationSwarm;
+	FeMesh*				feMesh              = feVariable->feMesh;
+	ElementType*               elementType       = FeMesh_GetElementType( feMesh, lElement_I );
+	Cell_Index                 cell_I            = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
+	Particle_InCellIndex       cellParticleCount;
+	Particle_InCellIndex       cParticle_I;
+	IntegrationPoint*          particle;
+	Node_Index                 nodeRow_I;
+	Node_Index                 nodeColumn_I;
+	double                     factor;
+	double                     detJac;
+	double                     shapeFunc[27];
+	unsigned			elementNodeCount;
+
+	elementNodeCount = FeMesh_GetElementNodeSize( feMesh, lElement_I );
+	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+	
+	for( cParticle_I = 0 ; cParticle_I < cellParticleCount; cParticle_I++ ) {
+		/* Find this particle in the element */
+		particle = (IntegrationPoint*) Swarm_ParticleInCellAt( swarm, cell_I, cParticle_I );
+
+		/* Evalutate Shape Functions and Jacobian Determinant */
+		ElementType_EvaluateShapeFunctionsAt( elementType, particle->xi, shapeFunc );
+		detJac = ElementType_JacobianDeterminant( elementType, feMesh, lElement_I, particle->xi, dim );
+	
+		/* Integrate \int_{\Omgea} N_i N_i d\Omega and lump onto vector in one step */
+		factor = detJac * particle->weight;
+		for ( nodeRow_I = 0 ; nodeRow_I < elementNodeCount ; nodeRow_I++ ) 
+			for ( nodeColumn_I = 0 ; nodeColumn_I < elementNodeCount ; nodeColumn_I++ ) 
+				elForceVector[ nodeRow_I ] += shapeFunc[ nodeRow_I ] * shapeFunc[ nodeColumn_I ] * factor ; 
+	}
+}
+
+/** Shortcut for doing above calculation, optimised for a box shaped element */
+void _LumpedMassMatrixForceTerm_AssembleElement_Box( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elForceVector ) {
+	FeVariable*                feVariable        = forceVector->feVariable;
+	Dimension_Index            dim               = forceVector->dim;
+	FeMesh*			feMesh              = feVariable->feMesh;
+	Element_NodeIndex          elementNodeCount;
+	ElementType*               elementType;
+	Node_Index                 node_I;
+	double                     detJac;
+	Coord                      xi = {0.0,0.0,0.0};
+
+	elementNodeCount = FeMesh_GetElementNodeSize( feMesh, lElement_I );
+	elementType = FeMesh_GetElementType( feMesh, lElement_I );
+	
+	detJac = ElementType_JacobianDeterminant( elementType, feMesh, lElement_I, xi, dim );
+	for ( node_I = 0 ; node_I < elementNodeCount ; node_I++ ) 
+		elForceVector[ node_I ] = detJac;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/MassMatrix_Assembly.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/MassMatrix_Assembly.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: MassMatrix_Assembly.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
-
-#include "types.h"
-#include "AdvectionDiffusionSLE.h"
-#include "Multicorrector.h"
-#include "Residual.h"
-
-#include <string.h>
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/MassMatrix_Assembly.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/MassMatrix_Assembly.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,56 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: MassMatrix_Assembly.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
+
+#include "types.h"
+#include "AdvectionDiffusionSLE.h"
+#include "Multicorrector.h"
+#include "Residual.h"
+
+#include <string.h>
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Multicorrector.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/Multicorrector.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Multicorrector.c 985 2007-11-21 00:20:24Z MirkoVelic $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
-
-#include "types.h"
-#include "AdvectionDiffusionSLE.h"
-#include "Multicorrector.h"
-#include "Residual.h"
-#include "MassMatrix_Assembly.h"
-
-#include <assert.h>
-
-/* Textual name of this class */
-const Type AdvDiffMulticorrector_Type = "AdvDiffMulticorrector";
-
-AdvDiffMulticorrector* AdvDiffMulticorrector_New( 
-		Name                                                name,
-		double                                              gamma,
-		Iteration_Index                                     multiCorrectorIterations )
-{
-	AdvDiffMulticorrector* self = (AdvDiffMulticorrector*) _AdvDiffMulticorrector_DefaultNew( name );
-
-	AdvDiffMulticorrector_InitAll( self, gamma, multiCorrectorIterations );
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-AdvDiffMulticorrector* _AdvDiffMulticorrector_New(  ADVDIFFMULTICORRECTOR_DEFARGS  )
-{
-	AdvDiffMulticorrector* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(AdvDiffMulticorrector) );
-	self = (AdvDiffMulticorrector*) _SLE_Solver_New(  SLE_SOLVER_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _AdvDiffMulticorrector_Init( 
-		AdvDiffMulticorrector*                              self, 
-		double                                              gamma,
-		Iteration_Index                                     multiCorrectorIterations )
-{
-	self->gamma                    = gamma;
-	self->multiCorrectorIterations = multiCorrectorIterations;
-}
-
-void AdvDiffMulticorrector_InitAll( 
-		void*                                               solver,
-		double                                              gamma,
-		Iteration_Index                                     multiCorrectorIterations )
-{
-	AdvDiffMulticorrector* self = (AdvDiffMulticorrector*) solver;
-
-	SLE_Solver_InitAll( self, False, 0 );
-	_AdvDiffMulticorrector_Init( self, gamma, multiCorrectorIterations );
-}
-
-void _AdvDiffMulticorrector_Delete( void* solver ) {
-	AdvDiffMulticorrector* self = (AdvDiffMulticorrector*)solver;
-
-	//FreeObject( self->matrixSolver );
-	KSPDestroy( self->matrixSolver );
-
-	_SLE_Solver_Delete( self );
-}
-
-void _AdvDiffMulticorrector_Print( void* solver, Stream* stream ) {
-	AdvDiffMulticorrector* self = (AdvDiffMulticorrector*)solver;
-	
-	_SLE_Solver_Print( self, stream );
-
-	Journal_PrintValue( stream, self->gamma );
-	Journal_PrintValue( stream, self->multiCorrectorIterations );
-}
-
-void* _AdvDiffMulticorrector_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(AdvDiffMulticorrector);
-	Type                                                      type = AdvDiffMulticorrector_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AdvDiffMulticorrector_Delete;
-	Stg_Class_PrintFunction*                                _print = _AdvDiffMulticorrector_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _AdvDiffMulticorrector_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _AdvDiffMulticorrector_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _AdvDiffMulticorrector_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AdvDiffMulticorrector_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AdvDiffMulticorrector_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AdvDiffMulticorrector_Destroy;
-	SLE_Solver_SolverSetupFunction*                   _solverSetup = _AdvDiffMulticorrector_SolverSetup;
-	SLE_Solver_SolveFunction*                               _solve = _AdvDiffMulticorrector_Solve;
-	SLE_Solver_GetResidualFunc*                       _getResidual = NULL;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_AdvDiffMulticorrector_New(  ADVDIFFMULTICORRECTOR_PASSARGS  );
-}
-
-void _AdvDiffMulticorrector_AssignFromXML( void* solver, Stg_ComponentFactory* cf, void* data ) {
-	AdvDiffMulticorrector*                     self             = (AdvDiffMulticorrector*)solver;
-	double                                     gamma;
-	Iteration_Index                            multiCorrectorIterations;
-
-	/* Construct Parent */
-	_SLE_Solver_AssignFromXML( self, cf, data );
-
-	gamma = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"gamma", 0.5  );
-	multiCorrectorIterations = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"multiCorrectorIterations", 2  );
-
-	_AdvDiffMulticorrector_Init( self, gamma, multiCorrectorIterations );
-
-	if( self->matrixSolver == PETSC_NULL ) {
-		KSPCreate( MPI_COMM_WORLD, &self->matrixSolver );
-	}
-}
-
-void _AdvDiffMulticorrector_Build( void* solver, void* data ) {
-	AdvDiffMulticorrector* self   = Stg_CheckType( solver, AdvDiffMulticorrector );
-
-	_SLE_Solver_Build( self, data );
-}
-
-void _AdvDiffMulticorrector_Initialise( void* solver, void* data ) {
-	AdvDiffMulticorrector*             self             = (AdvDiffMulticorrector*)solver;
-
-	_SLE_Solver_Initialise( self, data );
-}
-
-void _AdvDiffMulticorrector_Execute( void* solver, void* data ) {
-	_SLE_Solver_Execute( solver, data );
-}
-
-void _AdvDiffMulticorrector_Destroy( void* solver, void* data ) {
-	_SLE_Solver_Destroy( solver, data );
-}
-
-void _AdvDiffMulticorrector_SolverSetup( void* solver, void* data ) {
-	AdvDiffMulticorrector* self   = Stg_CheckType( solver, AdvDiffMulticorrector );
-	AdvectionDiffusionSLE* sle    = Stg_CheckType( data, AdvectionDiffusionSLE );
-	
-	__AdvDiffResidualForceTerm_UpdateLocalMemory( sle );
-
-	if ( self->matrixSolver && Stg_Class_IsInstance( sle->massMatrix, StiffnessMatrix_Type ) ) {
-		StiffnessMatrix* massMatrix = Stg_CheckType( sle->massMatrix, StiffnessMatrix );
-		KSPSetOperators( self->matrixSolver, massMatrix->matrix, massMatrix->matrix, DIFFERENT_NONZERO_PATTERN );
-	}
-}
-
-/* See Brooks, Hughes 1982 Section 4.2 
- * All equations refer to this paper if not otherwise indicated */
-void _AdvDiffMulticorrector_Solve( void* solver, void* _sle ) {
-	AdvDiffMulticorrector* self   = (AdvDiffMulticorrector*) solver;
-	AdvectionDiffusionSLE* sle    = (AdvectionDiffusionSLE*) _sle;
-	double                 dt     = sle->currentDt;
-	Index                  iteration_I;
-	Vec                    deltaPhiDot;
-
-	Journal_DPrintf( sle->debug, "In func %s:\n", __func__ );
-
-        /* First apply BC's */
-
-        FeVariable_ApplyBCs( sle->phiVector->feVariable, self->context );
-        FeVariable_ApplyBCs( sle->phiDotVector->feVariable, self->context );
-
-	/* Put mesh data onto vectors */
-	SolutionVector_LoadCurrentFeVariableValuesOntoVector( sle->phiVector );
-	SolutionVector_LoadCurrentFeVariableValuesOntoVector( sle->phiDotVector );
-
-	/* Solve for predictor step */
-	AdvDiffMulticorrector_Predictors( self, sle, dt );
-
-	/* Allocate Memory For Corrector Step */
-	//Vector_Duplicate( sle->phiVector->vector, (void**)&deltaPhiDot );
-	//Vector_SetLocalSize( deltaPhiDot, Vector_GetLocalSize( sle->phiVector->vector ) );
-	VecDuplicate( sle->phiVector->vector, &deltaPhiDot );
-
-	/* Multi-corrector Steps */
-	for ( iteration_I = 0 ; iteration_I < self->multiCorrectorIterations ; iteration_I++ ) {
-		AdvDiffMulticorrector_Solution( self, sle, deltaPhiDot );
-		AdvDiffMulticorrector_Correctors( self, sle, deltaPhiDot, dt );
-
-		/* Put solutions onto meshes */
-		SolutionVector_UpdateSolutionOntoNodes( sle->phiVector );
-		SolutionVector_UpdateSolutionOntoNodes( sle->phiDotVector );
-
-		SystemLinearEquations_ZeroAllVectors( sle, NULL );
-	}
-
-	/* Clean Up */
-	//FreeObject( deltaPhiDot );
-	VecDestroy( deltaPhiDot );
-}
-
-void ViewPETScVector( Vec vec, Stream* stream ) {
-	PetscInt	size;
-	PetscScalar*	array;
-	unsigned	entry_i;
-
-	if( !stream )
-		stream = Journal_Register( Info_Type, (Name)"tmp"  );
-
-	VecGetLocalSize( vec, &size );
-	VecGetArray( vec, &array );
-	
-	for( entry_i = 0; entry_i < size; entry_i++ )
-		Journal_Printf( stream, "\t%u: \t %.12g\n", entry_i, array[entry_i] );
-
-	VecRestoreArray( vec, &array );
-}
-
-/** See Eqns. 4.2.3-4 */
-void AdvDiffMulticorrector_Predictors( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, double dt ) {
-	double factor       = dt * ( 1.0 - self->gamma );
-	Stream* debugStream = sle->debug;
-
-	Journal_DPrintf( debugStream, "In func %s:\n", __func__ );
-
-	#if DEBUG
-	if ( Stream_IsPrintableLevel( debugStream, 3 ) ) {
-		Journal_DPrintf( debugStream, "At start of %s:\n", __func__ );
-		Stream_Indent( debugStream );
-
-		Journal_PrintValue( debugStream, dt );
-		Journal_PrintValue( debugStream, self->gamma );
-		Journal_PrintValue( debugStream, factor );
-
-		Journal_DPrintf( debugStream, "Phi:\n" );
-		ViewPETScVector( sle->phiVector->vector, debugStream );
-		Journal_DPrintf( debugStream, "Phi Dot:\n" );
-		ViewPETScVector( sle->phiDotVector->vector, debugStream );
-
-		Stream_UnIndent( debugStream );
-	}
-	#endif
-
-	/* Calculate Predictor for \phi - 
-	 * Eq. 4.2.3: \phi_{n+1}^{(0)} = \phi_n + \Delta t(1 - \gamma)\dot \phi_n */
-	//Vector_AddScaled( sle->phiVector->vector, factor, sle->phiDotVector->vector ); 
-	VecAXPY( sle->phiVector->vector, factor, sle->phiDotVector->vector ); 
-	
-	/* Calculate Predictor for \dot \phi - 
-	 * Eq. 4.2.4: \dot \phi_{n+1}^{(0)} = 0 */
-	//Vector_Zero( sle->phiDotVector->vector );
-	VecSet( sle->phiDotVector->vector, 0.0 );
-
-	#if DEBUG
-	if ( Stream_IsPrintableLevel( debugStream, 3 ) ) {
-		Journal_DPrintf( debugStream, "At end of %s: Phi is:\n", __func__ );
-		ViewPETScVector( sle->phiVector->vector, debugStream );
-	}
-	#endif
-}
-	
-	
-void AdvDiffMulticorrector_Solution( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot ) {
-	Journal_DPrintf( sle->debug, "In func %s:\n", __func__ );
-
-	/* Calculate Residual - See Eq. 4.2.6 */
-	SystemLinearEquations_VectorSetup( sle, NULL );
-	SystemLinearEquations_MatrixSetup( sle, NULL );
-
-	/* Calculate Mass Matrix out of three options - fully explicit, fully implicit, split operators */
-	AdvDiffMulticorrector_CalculatePhiDot( self, sle, deltaPhiDot );
-
-	#if DEBUG
-	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-		Journal_DPrintf( self->debug, "Delta Phi Dot is:\n" );
-		ViewPETScVector( deltaPhiDot, self->debug );
-	}
-	#endif
-}
-
-
-	
-/* Correct \phi and \dot \phi - See Eqns. 4.2.7-8 */
-void AdvDiffMulticorrector_Correctors( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot, double dt ) {
-	double factor = dt * self->gamma;
-	
-	Journal_DPrintf( sle->debug, "In func %s:\n", __func__ );
-
-	/* Add correction to \phi - Eq. 4.2.7 */
-	//Vector_AddScaled( sle->phiVector->vector, factor, deltaPhiDot );
-	VecAXPY( sle->phiVector->vector, factor, deltaPhiDot );
-	
-	/* Add correction to \dot \phi - Eq. 4.2.8 */
-	//Vector_AddScaled( sle->phiDotVector->vector, 1.0, deltaPhiDot );
-	VecAXPY( sle->phiDotVector->vector, 1.0, deltaPhiDot );
-}
-
-
-void AdvDiffMulticorrector_CalculatePhiDot( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot ) {
-	Stg_Component* massMatrix = sle->massMatrix;
-
-	if ( Stg_Class_IsInstance( massMatrix, ForceVector_Type ) ) 
-		_AdvDiffMulticorrector_CalculatePhiDot_Explicit( self, sle, deltaPhiDot );
-	else if ( Stg_Class_IsInstance( massMatrix, StiffnessMatrix_Type ) )
-		_AdvDiffMulticorrector_CalculatePhiDot_Implicit( self, sle, deltaPhiDot );
-	else {
-		Journal_Firewall( False, Journal_Register( Error_Type, (Name)self->type  ),
-				"Error in func '%s': Cannot understand type '%s' for mass matrix '%s'.\n",
-				__func__, massMatrix->name, massMatrix->type );
-	}
-}
-
-/* Lump all things onto diagonal of matrix - which is stored as a vector - Eq. 4.2.11 */
-void _AdvDiffMulticorrector_CalculatePhiDot_Explicit( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot ) {
-	ForceVector* massMatrix = Stg_CheckType( sle->massMatrix, ForceVector );
-
-	/* Calculate change in \dot \phi - See Eq. 4.2.5 */
-	VecPointwiseDivide( deltaPhiDot, sle->residual->vector, massMatrix->vector );
-}
-
-void _AdvDiffMulticorrector_CalculatePhiDot_Implicit( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot ) {
-
-	KSPSolve( self->matrixSolver, deltaPhiDot, sle->residual->vector );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Multicorrector.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/Multicorrector.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,364 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Multicorrector.c 985 2007-11-21 00:20:24Z MirkoVelic $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
+
+#include "types.h"
+#include "AdvectionDiffusionSLE.h"
+#include "Multicorrector.h"
+#include "Residual.h"
+#include "MassMatrix_Assembly.h"
+
+#include <assert.h>
+
+/* Textual name of this class */
+const Type AdvDiffMulticorrector_Type = "AdvDiffMulticorrector";
+
+AdvDiffMulticorrector* AdvDiffMulticorrector_New( 
+		Name                                                name,
+		double                                              gamma,
+		Iteration_Index                                     multiCorrectorIterations )
+{
+	AdvDiffMulticorrector* self = (AdvDiffMulticorrector*) _AdvDiffMulticorrector_DefaultNew( name );
+
+	AdvDiffMulticorrector_InitAll( self, gamma, multiCorrectorIterations );
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+AdvDiffMulticorrector* _AdvDiffMulticorrector_New(  ADVDIFFMULTICORRECTOR_DEFARGS  )
+{
+	AdvDiffMulticorrector* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(AdvDiffMulticorrector) );
+	self = (AdvDiffMulticorrector*) _SLE_Solver_New(  SLE_SOLVER_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _AdvDiffMulticorrector_Init( 
+		AdvDiffMulticorrector*                              self, 
+		double                                              gamma,
+		Iteration_Index                                     multiCorrectorIterations )
+{
+	self->gamma                    = gamma;
+	self->multiCorrectorIterations = multiCorrectorIterations;
+}
+
+void AdvDiffMulticorrector_InitAll( 
+		void*                                               solver,
+		double                                              gamma,
+		Iteration_Index                                     multiCorrectorIterations )
+{
+	AdvDiffMulticorrector* self = (AdvDiffMulticorrector*) solver;
+
+	SLE_Solver_InitAll( self, False, 0 );
+	_AdvDiffMulticorrector_Init( self, gamma, multiCorrectorIterations );
+}
+
+void _AdvDiffMulticorrector_Delete( void* solver ) {
+	AdvDiffMulticorrector* self = (AdvDiffMulticorrector*)solver;
+
+	//FreeObject( self->matrixSolver );
+	KSPDestroy( self->matrixSolver );
+
+	_SLE_Solver_Delete( self );
+}
+
+void _AdvDiffMulticorrector_Print( void* solver, Stream* stream ) {
+	AdvDiffMulticorrector* self = (AdvDiffMulticorrector*)solver;
+	
+	_SLE_Solver_Print( self, stream );
+
+	Journal_PrintValue( stream, self->gamma );
+	Journal_PrintValue( stream, self->multiCorrectorIterations );
+}
+
+void* _AdvDiffMulticorrector_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(AdvDiffMulticorrector);
+	Type                                                      type = AdvDiffMulticorrector_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AdvDiffMulticorrector_Delete;
+	Stg_Class_PrintFunction*                                _print = _AdvDiffMulticorrector_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _AdvDiffMulticorrector_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _AdvDiffMulticorrector_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _AdvDiffMulticorrector_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AdvDiffMulticorrector_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AdvDiffMulticorrector_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AdvDiffMulticorrector_Destroy;
+	SLE_Solver_SolverSetupFunction*                   _solverSetup = _AdvDiffMulticorrector_SolverSetup;
+	SLE_Solver_SolveFunction*                               _solve = _AdvDiffMulticorrector_Solve;
+	SLE_Solver_GetResidualFunc*                       _getResidual = NULL;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_AdvDiffMulticorrector_New(  ADVDIFFMULTICORRECTOR_PASSARGS  );
+}
+
+void _AdvDiffMulticorrector_AssignFromXML( void* solver, Stg_ComponentFactory* cf, void* data ) {
+	AdvDiffMulticorrector*                     self             = (AdvDiffMulticorrector*)solver;
+	double                                     gamma;
+	Iteration_Index                            multiCorrectorIterations;
+
+	/* Construct Parent */
+	_SLE_Solver_AssignFromXML( self, cf, data );
+
+	gamma = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"gamma", 0.5  );
+	multiCorrectorIterations = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"multiCorrectorIterations", 2  );
+
+	_AdvDiffMulticorrector_Init( self, gamma, multiCorrectorIterations );
+
+	if( self->matrixSolver == PETSC_NULL ) {
+		KSPCreate( MPI_COMM_WORLD, &self->matrixSolver );
+	}
+}
+
+void _AdvDiffMulticorrector_Build( void* solver, void* data ) {
+	AdvDiffMulticorrector* self   = Stg_CheckType( solver, AdvDiffMulticorrector );
+
+	_SLE_Solver_Build( self, data );
+}
+
+void _AdvDiffMulticorrector_Initialise( void* solver, void* data ) {
+	AdvDiffMulticorrector*             self             = (AdvDiffMulticorrector*)solver;
+
+	_SLE_Solver_Initialise( self, data );
+}
+
+void _AdvDiffMulticorrector_Execute( void* solver, void* data ) {
+	_SLE_Solver_Execute( solver, data );
+}
+
+void _AdvDiffMulticorrector_Destroy( void* solver, void* data ) {
+	_SLE_Solver_Destroy( solver, data );
+}
+
+void _AdvDiffMulticorrector_SolverSetup( void* solver, void* data ) {
+	AdvDiffMulticorrector* self   = Stg_CheckType( solver, AdvDiffMulticorrector );
+	AdvectionDiffusionSLE* sle    = Stg_CheckType( data, AdvectionDiffusionSLE );
+	
+	__AdvDiffResidualForceTerm_UpdateLocalMemory( sle );
+
+	if ( self->matrixSolver && Stg_Class_IsInstance( sle->massMatrix, StiffnessMatrix_Type ) ) {
+		StiffnessMatrix* massMatrix = Stg_CheckType( sle->massMatrix, StiffnessMatrix );
+		KSPSetOperators( self->matrixSolver, massMatrix->matrix, massMatrix->matrix, DIFFERENT_NONZERO_PATTERN );
+	}
+}
+
+/* See Brooks, Hughes 1982 Section 4.2 
+ * All equations refer to this paper if not otherwise indicated */
+void _AdvDiffMulticorrector_Solve( void* solver, void* _sle ) {
+	AdvDiffMulticorrector* self   = (AdvDiffMulticorrector*) solver;
+	AdvectionDiffusionSLE* sle    = (AdvectionDiffusionSLE*) _sle;
+	double                 dt     = sle->currentDt;
+	Index                  iteration_I;
+	Vec                    deltaPhiDot;
+
+	Journal_DPrintf( sle->debug, "In func %s:\n", __func__ );
+
+        /* First apply BC's */
+
+        FeVariable_ApplyBCs( sle->phiVector->feVariable, self->context );
+        FeVariable_ApplyBCs( sle->phiDotVector->feVariable, self->context );
+
+	/* Put mesh data onto vectors */
+	SolutionVector_LoadCurrentFeVariableValuesOntoVector( sle->phiVector );
+	SolutionVector_LoadCurrentFeVariableValuesOntoVector( sle->phiDotVector );
+
+	/* Solve for predictor step */
+	AdvDiffMulticorrector_Predictors( self, sle, dt );
+
+	/* Allocate Memory For Corrector Step */
+	//Vector_Duplicate( sle->phiVector->vector, (void**)&deltaPhiDot );
+	//Vector_SetLocalSize( deltaPhiDot, Vector_GetLocalSize( sle->phiVector->vector ) );
+	VecDuplicate( sle->phiVector->vector, &deltaPhiDot );
+
+	/* Multi-corrector Steps */
+	for ( iteration_I = 0 ; iteration_I < self->multiCorrectorIterations ; iteration_I++ ) {
+		AdvDiffMulticorrector_Solution( self, sle, deltaPhiDot );
+		AdvDiffMulticorrector_Correctors( self, sle, deltaPhiDot, dt );
+
+		/* Put solutions onto meshes */
+		SolutionVector_UpdateSolutionOntoNodes( sle->phiVector );
+		SolutionVector_UpdateSolutionOntoNodes( sle->phiDotVector );
+
+		SystemLinearEquations_ZeroAllVectors( sle, NULL );
+	}
+
+	/* Clean Up */
+	//FreeObject( deltaPhiDot );
+	VecDestroy( deltaPhiDot );
+}
+
+void ViewPETScVector( Vec vec, Stream* stream ) {
+	PetscInt	size;
+	PetscScalar*	array;
+	unsigned	entry_i;
+
+	if( !stream )
+		stream = Journal_Register( Info_Type, (Name)"tmp"  );
+
+	VecGetLocalSize( vec, &size );
+	VecGetArray( vec, &array );
+	
+	for( entry_i = 0; entry_i < size; entry_i++ )
+		Journal_Printf( stream, "\t%u: \t %.12g\n", entry_i, array[entry_i] );
+
+	VecRestoreArray( vec, &array );
+}
+
+/** See Eqns. 4.2.3-4 */
+void AdvDiffMulticorrector_Predictors( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, double dt ) {
+	double factor       = dt * ( 1.0 - self->gamma );
+	Stream* debugStream = sle->debug;
+
+	Journal_DPrintf( debugStream, "In func %s:\n", __func__ );
+
+	#if DEBUG
+	if ( Stream_IsPrintableLevel( debugStream, 3 ) ) {
+		Journal_DPrintf( debugStream, "At start of %s:\n", __func__ );
+		Stream_Indent( debugStream );
+
+		Journal_PrintValue( debugStream, dt );
+		Journal_PrintValue( debugStream, self->gamma );
+		Journal_PrintValue( debugStream, factor );
+
+		Journal_DPrintf( debugStream, "Phi:\n" );
+		ViewPETScVector( sle->phiVector->vector, debugStream );
+		Journal_DPrintf( debugStream, "Phi Dot:\n" );
+		ViewPETScVector( sle->phiDotVector->vector, debugStream );
+
+		Stream_UnIndent( debugStream );
+	}
+	#endif
+
+	/* Calculate Predictor for \phi - 
+	 * Eq. 4.2.3: \phi_{n+1}^{(0)} = \phi_n + \Delta t(1 - \gamma)\dot \phi_n */
+	//Vector_AddScaled( sle->phiVector->vector, factor, sle->phiDotVector->vector ); 
+	VecAXPY( sle->phiVector->vector, factor, sle->phiDotVector->vector ); 
+	
+	/* Calculate Predictor for \dot \phi - 
+	 * Eq. 4.2.4: \dot \phi_{n+1}^{(0)} = 0 */
+	//Vector_Zero( sle->phiDotVector->vector );
+	VecSet( sle->phiDotVector->vector, 0.0 );
+
+	#if DEBUG
+	if ( Stream_IsPrintableLevel( debugStream, 3 ) ) {
+		Journal_DPrintf( debugStream, "At end of %s: Phi is:\n", __func__ );
+		ViewPETScVector( sle->phiVector->vector, debugStream );
+	}
+	#endif
+}
+	
+	
+void AdvDiffMulticorrector_Solution( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot ) {
+	Journal_DPrintf( sle->debug, "In func %s:\n", __func__ );
+
+	/* Calculate Residual - See Eq. 4.2.6 */
+	SystemLinearEquations_VectorSetup( sle, NULL );
+	SystemLinearEquations_MatrixSetup( sle, NULL );
+
+	/* Calculate Mass Matrix out of three options - fully explicit, fully implicit, split operators */
+	AdvDiffMulticorrector_CalculatePhiDot( self, sle, deltaPhiDot );
+
+	#if DEBUG
+	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+		Journal_DPrintf( self->debug, "Delta Phi Dot is:\n" );
+		ViewPETScVector( deltaPhiDot, self->debug );
+	}
+	#endif
+}
+
+
+	
+/* Correct \phi and \dot \phi - See Eqns. 4.2.7-8 */
+void AdvDiffMulticorrector_Correctors( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot, double dt ) {
+	double factor = dt * self->gamma;
+	
+	Journal_DPrintf( sle->debug, "In func %s:\n", __func__ );
+
+	/* Add correction to \phi - Eq. 4.2.7 */
+	//Vector_AddScaled( sle->phiVector->vector, factor, deltaPhiDot );
+	VecAXPY( sle->phiVector->vector, factor, deltaPhiDot );
+	
+	/* Add correction to \dot \phi - Eq. 4.2.8 */
+	//Vector_AddScaled( sle->phiDotVector->vector, 1.0, deltaPhiDot );
+	VecAXPY( sle->phiDotVector->vector, 1.0, deltaPhiDot );
+}
+
+
+void AdvDiffMulticorrector_CalculatePhiDot( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot ) {
+	Stg_Component* massMatrix = sle->massMatrix;
+
+	if ( Stg_Class_IsInstance( massMatrix, ForceVector_Type ) ) 
+		_AdvDiffMulticorrector_CalculatePhiDot_Explicit( self, sle, deltaPhiDot );
+	else if ( Stg_Class_IsInstance( massMatrix, StiffnessMatrix_Type ) )
+		_AdvDiffMulticorrector_CalculatePhiDot_Implicit( self, sle, deltaPhiDot );
+	else {
+		Journal_Firewall( False, Journal_Register( Error_Type, (Name)self->type  ),
+				"Error in func '%s': Cannot understand type '%s' for mass matrix '%s'.\n",
+				__func__, massMatrix->name, massMatrix->type );
+	}
+}
+
+/* Lump all things onto diagonal of matrix - which is stored as a vector - Eq. 4.2.11 */
+void _AdvDiffMulticorrector_CalculatePhiDot_Explicit( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot ) {
+	ForceVector* massMatrix = Stg_CheckType( sle->massMatrix, ForceVector );
+
+	/* Calculate change in \dot \phi - See Eq. 4.2.5 */
+	VecPointwiseDivide( deltaPhiDot, sle->residual->vector, massMatrix->vector );
+}
+
+void _AdvDiffMulticorrector_CalculatePhiDot_Implicit( AdvDiffMulticorrector* self, AdvectionDiffusionSLE* sle, Vec deltaPhiDot ) {
+
+	KSPSolve( self->matrixSolver, deltaPhiDot, sle->residual->vector );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Residual.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/Residual.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,458 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Residual.c 985 2007-11-21 00:20:24Z MirkoVelic $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
-#include <PICellerator/PICellerator.h>
-#include <Underworld/Underworld.h>
-
-#include "types.h"
-#include "AdvectionDiffusionSLE.h"
-#include "Residual.h"
-#include "UpwindParameter.h"
-
-#include <assert.h>
-#include <string.h>
-#include <stddef.h>
-
-/* Textual name of this class */
-const Type AdvDiffResidualForceTerm_Type = "AdvDiffResidualForceTerm";
-
-AdvDiffResidualForceTerm* AdvDiffResidualForceTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	ForceVector*				forceVector,
-	Swarm*						integrationSwarm,
-	Stg_Component*				sle, 
-	FeVariable*					velocityField,
-	double						defaultDiffusivity,
-        Swarm*						picSwarm,
-	void*		materials_Register,
-	AdvDiffResidualForceTerm_UpwindParamFuncType upwindFuncType )
-{
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*) _AdvDiffResidualForceTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ForceTerm_Init( self, context, forceVector, integrationSwarm, sle );
-	_AdvDiffResidualForceTerm_Init( self, velocityField, defaultDiffusivity,
-                                        picSwarm,
-                                        materials_Register, upwindFuncType );
-
-	return self;
-}
-
-void* _AdvDiffResidualForceTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                  _sizeOfSelf = sizeof(AdvDiffResidualForceTerm);
-	Type                                                          type = AdvDiffResidualForceTerm_Type;
-	Stg_Class_DeleteFunction*                                  _delete = _AdvDiffResidualForceTerm_Delete;
-	Stg_Class_PrintFunction*                                    _print = _AdvDiffResidualForceTerm_Print;
-	Stg_Class_CopyFunction*                                      _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*      _defaultConstructor = _AdvDiffResidualForceTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                        _construct = _AdvDiffResidualForceTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                                _build = _AdvDiffResidualForceTerm_Build;
-	Stg_Component_InitialiseFunction*                      _initialise = _AdvDiffResidualForceTerm_Initialise;
-	Stg_Component_ExecuteFunction*                            _execute = _AdvDiffResidualForceTerm_Execute;
-	Stg_Component_DestroyFunction*                            _destroy = _AdvDiffResidualForceTerm_Destroy;
-	ForceTerm_AssembleElementFunction*                _assembleElement = _AdvDiffResidualForceTerm_AssembleElement;
-	AdvDiffResidualForceTerm_UpwindParamFunction*         _upwindParam = _AdvDiffResidualForceTerm_UpwindParam;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_AdvDiffResidualForceTerm_New(  ADVDIFFRESIDUALFORCETERM_PASSARGS  );
-}
-
-/* Creation implementation / Virtual constructor */
-AdvDiffResidualForceTerm* _AdvDiffResidualForceTerm_New(  ADVDIFFRESIDUALFORCETERM_DEFARGS  )
-{
-	AdvDiffResidualForceTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(AdvDiffResidualForceTerm) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (AdvDiffResidualForceTerm*) _ForceTerm_New(  FORCETERM_PASSARGS  );
-	
-	/* Virtual info */
-	self->_upwindParam = _upwindParam;
-	
-	return self;
-}
-
-/*******************************************************************************
-  The following function scans all the elements of the mesh associated with
-  the residual forceterm phi to find the element with the most nodes.
-  Once the maximum number of nodes is found we then may allocate memory for
-  GNx etc that now live on the AdvDiffResidualForceTerm struct. This way we 
-  do not reallocate memory for these arrays for every element.
- *******************************************************************************/
-void __AdvDiffResidualForceTerm_UpdateLocalMemory( AdvectionDiffusionSLE* sle ){
-	FeVariable*				phiField = sle->phiField;
-	FeMesh*					phiMesh = phiField->feMesh;
-	Dimension_Index 		dim = phiField->dim;
-	Element_LocalIndex	e, n_elements;
-	Node_Index				max_elementNodeCount;
-
-	n_elements = FeMesh_GetElementLocalSize(phiMesh);//returns number of elements in a mesh
-
-	/* Scan all elements in Mesh to get max node count */
-	max_elementNodeCount = 0;
-
-	for(e=0;e<n_elements;e++){
-		ElementType *elementType = FeMesh_GetElementType( phiMesh, e );
-		Node_Index elementNodeCount = elementType->nodeCount;
-	
-		if( elementNodeCount > max_elementNodeCount){
-			max_elementNodeCount = elementNodeCount;
-		}
-	}
-       
-	sle->advDiffResidualForceTerm->GNx = Memory_Alloc_2DArray( double, dim, max_elementNodeCount, (Name)"(SUPG): Global Shape Function Derivatives" );
-	sle->advDiffResidualForceTerm->phiGrad = Memory_Alloc_Array(double, dim, "(SUPG): Gradient of the Advected Scalar");
-	sle->advDiffResidualForceTerm->Ni = Memory_Alloc_Array(double, max_elementNodeCount, "(SUPG): Gradient of the Advected Scalar");
-	sle->advDiffResidualForceTerm->SUPGNi = Memory_Alloc_Array(double, max_elementNodeCount, "(SUPG): Upwinded Shape Function");
-	sle->advDiffResidualForceTerm->incarray=IArray_New();
-}
-
-void __AdvDiffResidualForceTerm_FreeLocalMemory( AdvectionDiffusionSLE* sle ){
-	Memory_Free(sle->advDiffResidualForceTerm->GNx);
-	Memory_Free(sle->advDiffResidualForceTerm->phiGrad);
-	Memory_Free(sle->advDiffResidualForceTerm->Ni);
-	Memory_Free(sle->advDiffResidualForceTerm->SUPGNi);
-  
-	NewClass_Delete(sle->advDiffResidualForceTerm->incarray);
-}
-
-void _AdvDiffResidualForceTerm_Init(
-	void*			residual,
-	FeVariable*		velocityField,
-	double			defaultDiffusivity,
-        Swarm*			picSwarm,
-	void*	                materials_Register,
-	AdvDiffResidualForceTerm_UpwindParamFuncType	upwindFuncType ) //WHY IS THIS LINE HERE???
-{
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
-
-	self->velocityField = velocityField;
-	self->defaultDiffusivity = defaultDiffusivity;
-        self->picSwarm = picSwarm;
-	self->materials_Register  = materials_Register;
-	self->upwindParamType = upwindFuncType;
-}
-
-void _AdvDiffResidualForceTerm_Delete( void* residual ) {
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
-
-	_ForceTerm_Delete( self );
-}
-
-void _AdvDiffResidualForceTerm_Print( void* residual, Stream* stream ) {
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
-	
-	_ForceTerm_Print( self, stream );
-
-	Journal_Printf( stream, "self->calculateUpwindParam = %s\n", 
-		self->_upwindParam == AdvDiffResidualForceTerm_UpwindXiExact ? 
-			"AdvDiffResidualForceTerm_UpwindXiExact" :
-		self->_upwindParam == AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption ? 
-			"AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption" :
-		self->_upwindParam == AdvDiffResidualForceTerm_UpwindXiCriticalAssumption ? 
-		"AdvDiffResidualForceTerm_UpwindXiCriticalAssumption" : "Unknown"  );
-
-	/* General info */
-	Journal_PrintPointer( stream, self->velocityField );
-	Journal_PrintDouble( stream, self->defaultDiffusivity );
-}
-
-void _AdvDiffResidualForceTerm_AssignFromXML( void* residual, Stg_ComponentFactory* cf, void* data ) {
-	AdvDiffResidualForceTerm*							self = (AdvDiffResidualForceTerm*)residual;
-	FeVariable*												velocityField;
-	Name														upwindParamFuncName;
-	double													defaultDiffusivity;
-	Materials_Register*		materials_Register;
-	AdvDiffResidualForceTerm_UpwindParamFuncType	upwindFuncType = (AdvDiffResidualForceTerm_UpwindParamFuncType)0;
-        Swarm *picSwarm;
-
-	/* Construct Parent */
-	_ForceTerm_AssignFromXML( self, cf, data );
-
-	velocityField = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"VelocityField", FeVariable, True, data  );
-	upwindParamFuncName = Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"UpwindXiFunction", "Exact"  );
-
-	if ( strcasecmp( upwindParamFuncName, "DoublyAsymptoticAssumption" ) == 0 )
-		upwindFuncType = DoublyAsymptoticAssumption;
-	else if ( strcasecmp( upwindParamFuncName, "CriticalAssumption" ) == 0 )
-		upwindFuncType = CriticalAssumption;
-	else if ( strcasecmp( upwindParamFuncName, "Exact" ) == 0 )
-		upwindFuncType = Exact;
-	else 
-		Journal_Firewall( False, Journal_Register( Error_Type, (Name)self->type  ), "Cannot understand '%s'\n", upwindParamFuncName );
-
-	defaultDiffusivity = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"defaultDiffusivity", 1.0  );
-	picSwarm       = (Swarm*)Stg_ComponentFactory_ConstructByName( cf, (Name)"picIntegrationPoints", IntegrationPointsSwarm, True, data  ) ;
-	materials_Register = ((PICelleratorContext*)(self->context))->materials_Register;
-
-	_AdvDiffResidualForceTerm_Init( self, velocityField, defaultDiffusivity,
-                                        picSwarm, materials_Register,
-                                        upwindFuncType );
-}
-
-void _AdvDiffResidualForceTerm_Build( void* residual, void* data ) {
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
-	AdvDiffResidualForceTerm_MaterialExt*   materialExt;
-	Material_Index                   material_I;
-	Material*                        material;
-	Materials_Register*              materials_Register = (Materials_Register*)(self->materials_Register);
-	IntegrationPointsSwarm*          swarm              = (IntegrationPointsSwarm*)self->picSwarm;
-	MaterialPointsSwarm**            materialSwarms;
-	Index                            materialSwarm_I;
-	Stg_ComponentFactory*            cf;
-	char*                            name;
-
-	cf = self->context->CF;
-
-	_ForceTerm_Build( self, data );
-
-	Stg_Component_Build( self->velocityField, data, False );
-
-	/* Sort out material extension stuff */
-	self->materialExtHandle = Materials_Register_AddMaterialExtension( 
-			self->materials_Register, 
-			self->type, 
-			sizeof(AdvDiffResidualForceTerm_MaterialExt) );
-	for ( material_I = 0 ; material_I < Materials_Register_GetCount( materials_Register ) ; material_I++) {
-		material = Materials_Register_GetByIndex( materials_Register, material_I );
-		materialExt = (AdvDiffResidualForceTerm_MaterialExt*)ExtensionManager_GetFunc( material->extensionMgr, material, self->materialExtHandle );
-
-		materialExt->diffusivity = Stg_ComponentFactory_GetDouble( cf, material->name,
-                                                                           (Dictionary_Entry_Key)"diffusivity",
-                                                                           self->defaultDiffusivity );
-	}
-	
-	/* Create Swarm Variables of each material swarm this ip swarm is mapped against */
-	materialSwarms = IntegrationPointMapper_GetMaterialPointsSwarms( swarm->mapper, &(self->materialSwarmCount) );
-	self->diffusivitySwarmVariables = (void**)Memory_Alloc_Array( MaterialSwarmVariable*, self->materialSwarmCount, "DiffusivityVariables" );
-	
-	for ( materialSwarm_I = 0; materialSwarm_I < self->materialSwarmCount; ++materialSwarm_I ) {
-		name = Stg_Object_AppendSuffix( materialSwarms[materialSwarm_I], (Name)"Diffusivity"  );
-		self->diffusivitySwarmVariables[materialSwarm_I] = MaterialSwarmVariable_New( 
-				name,
-				(AbstractContext*)self->context,
-				materialSwarms[materialSwarm_I], 
-				1, 
-				(Materials_Register*)self->materials_Register, 
-				self->materialExtHandle, 
-				GetOffsetOfMember( *materialExt, diffusivity ) );
-		Memory_Free( name );
-
-		/* Build new Swarm Variables */
-		Stg_Component_Build( self->diffusivitySwarmVariables[materialSwarm_I], data, False );
-	}
-}
-
-void _AdvDiffResidualForceTerm_Initialise( void* residual, void* data ) {
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
-	Index                          i;
-
-	_ForceTerm_Initialise( self, data );
-
-	Stg_Component_Initialise( self->velocityField, data, False );
-
-	for ( i = 0; i < self->materialSwarmCount; ++i ) {
-		Stg_Component_Initialise( self->diffusivitySwarmVariables[i], data, False );
-	}
-}
-
-void _AdvDiffResidualForceTerm_Execute( void* residual, void* data ) {
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
-
-	_ForceTerm_Execute( self, data );
-}
-
-void _AdvDiffResidualForceTerm_Destroy( void* residual, void* data ) {
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
-	Index                          i;
-
-	for ( i = 0; i < self->materialSwarmCount; ++i ) {
-		_Stg_Component_Delete( self->diffusivitySwarmVariables[i] );
-	}
-	Memory_Free( self->diffusivitySwarmVariables );
-
-	_ForceTerm_Destroy( self, data );
-}
-
-void _AdvDiffResidualForceTerm_AssembleElement( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elementResidual ) {
-	AdvDiffResidualForceTerm*  self               = Stg_CheckType( forceTerm, AdvDiffResidualForceTerm );
-	AdvectionDiffusionSLE*     sle                = Stg_CheckType( self->extraInfo, AdvectionDiffusionSLE );
-	Swarm*                     swarm              = self->picSwarm;
-	Particle_Index             lParticle_I;
-	Particle_Index             cParticle_I;
-	Particle_Index             cellParticleCount;
-	Cell_Index                 cell_I;    
-	IntegrationPoint*          particle;
-	FeVariable*                phiField           = sle->phiField;
-	Dimension_Index            dim                = forceVector->dim;
-	double                     velocity[3];
-	double                     phi, phiDot;
-	double                     detJac;
-	double*                    xi;
-	double                     totalDerivative, diffusionTerm;
-	double                     diffusivity         = self->defaultDiffusivity;
-	ElementType*               elementType         = FeMesh_GetElementType( phiField->feMesh, lElement_I );
-	Node_Index                 elementNodeCount    = elementType->nodeCount;
-	Node_Index                 node_I;
-	double                     factor;
-
-	double**                   GNx;
-	double*                    phiGrad;
-	double*                    Ni;
-	double*                    SUPGNi;
-	double                     supgfactor;
-	double                     udotu, perturbation;
-	double                     upwindDiffusivity;
-
-	GNx     = self->GNx;
-	phiGrad = self->phiGrad;
-	Ni = self->Ni;
-	SUPGNi = self->SUPGNi;
-	
-	upwindDiffusivity  = AdvDiffResidualForceTerm_UpwindDiffusivity( self, sle, swarm, phiField->feMesh, lElement_I, dim );
-
-	/* Determine number of particles in element */
-	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
-	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
-	
-	for ( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
-		lParticle_I     = swarm->cellParticleTbl[cell_I][cParticle_I];
-
-		particle        = (IntegrationPoint*) Swarm_ParticleAt( swarm, lParticle_I );
-		xi              = particle->xi;
-		
-		/* Evaluate Shape Functions */
-		ElementType_EvaluateShapeFunctionsAt(elementType, xi, Ni);
-
-		/* Calculate Global Shape Function Derivatives */
-		ElementType_ShapeFunctionsGlobalDerivs( 
-			elementType,
-			phiField->feMesh, lElement_I,
-			xi, dim, &detJac, GNx );
-		
-		/* Calculate Velocity */
-		FeVariable_InterpolateFromMeshLocalCoord( self->velocityField, phiField->feMesh, lElement_I, xi, velocity );
-
-		/* Build the SUPG shape functions */
-		udotu = velocity[I_AXIS]*velocity[I_AXIS] + velocity[J_AXIS]*velocity[J_AXIS];
-		if(dim == 3) udotu += velocity[ K_AXIS ] * velocity[ K_AXIS ];
-
-		supgfactor = upwindDiffusivity / udotu;
-		for ( node_I = 0 ; node_I < elementNodeCount ; node_I++ ) {
-			/* In the case of per diffusion - just build regular shape functions */
-			if ( fabs(upwindDiffusivity) < SUPG_MIN_DIFFUSIVITY ) {
-				SUPGNi[node_I] = Ni[node_I];
-				continue;
-			}
-			
-			perturbation = velocity[ I_AXIS ] * GNx[ I_AXIS ][ node_I ] + velocity[ J_AXIS ] * GNx[ J_AXIS ][ node_I ];
-			if (dim == 3)
-					perturbation = perturbation + velocity[ K_AXIS ] * GNx[ K_AXIS ][ node_I ];
-			
-			/* p = \frac{\bar \kappa \hat u_j w_j }{ ||u|| } -  Eq. 3.2.25 */
-			perturbation = supgfactor * perturbation;
-			
-			SUPGNi[node_I] = Ni[node_I] + perturbation;
-		}  
-		
-		/* Calculate phi on particle */
-		_FeVariable_InterpolateNodeValuesToElLocalCoord( phiField, lElement_I, xi, &phi );
-
-		/* Calculate Gradients of Phi */
-		FeVariable_InterpolateDerivatives_WithGNx( phiField, lElement_I, GNx, phiGrad );
-
-		/* Calculate time derivative of phi */
-		_FeVariable_InterpolateNodeValuesToElLocalCoord( sle->phiDotField, lElement_I, xi, &phiDot );
-		
-		/* Calculate total derivative (i.e. Dphi/Dt = \dot \phi + u . \grad \phi) */
-		totalDerivative = phiDot + StGermain_VectorDotProduct( velocity, phiGrad, dim );
-
-		/* Get Diffusivity */
-		diffusivity = IntegrationPointMapper_GetDoubleFromMaterial(((IntegrationPointsSwarm *)swarm)->mapper, particle, self->materialExtHandle,
-
-		    offsetof(AdvDiffResidualForceTerm_MaterialExt, diffusivity));
-
-		/* Add to element residual */
-		factor = particle->weight * detJac;
-		for ( node_I = 0 ; node_I < elementNodeCount ; node_I++ ) {
-			/* Calculate Diffusion Term */
-			diffusionTerm = diffusivity * ( GNx[0][node_I] * phiGrad[0] + GNx[1][node_I] * phiGrad[1] );
-			if (dim == 3)
-				diffusionTerm += diffusivity * GNx[2][ node_I ] * phiGrad[2] ;
-			
-			elementResidual[ node_I ] -=  factor * ( SUPGNi[ node_I ] * totalDerivative + diffusionTerm );
-		}
-	}
-	
-}
-
-/* Virtual Function Implementations */
-double _AdvDiffResidualForceTerm_UpwindParam( void* residual, double pecletNumber ) {
-	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
-
-	switch ( self->upwindParamType ) {
-		case Exact:
-			self->_upwindParam = AdvDiffResidualForceTerm_UpwindXiExact; break;
-		case DoublyAsymptoticAssumption:
-			self->_upwindParam = AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption; break;
-		case CriticalAssumption:
-			self->_upwindParam = AdvDiffResidualForceTerm_UpwindXiCriticalAssumption; break;
-	}
-
-	return AdvDiffResidualForceTerm_UpwindParam( self, pecletNumber );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Residual.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/Residual.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,458 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Residual.c 985 2007-11-21 00:20:24Z MirkoVelic $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
+#include <PICellerator/PICellerator.h>
+#include <Underworld/Underworld.h>
+
+#include "types.h"
+#include "AdvectionDiffusionSLE.h"
+#include "Residual.h"
+#include "UpwindParameter.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stddef.h>
+
+/* Textual name of this class */
+const Type AdvDiffResidualForceTerm_Type = "AdvDiffResidualForceTerm";
+
+AdvDiffResidualForceTerm* AdvDiffResidualForceTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	ForceVector*				forceVector,
+	Swarm*						integrationSwarm,
+	Stg_Component*				sle, 
+	FeVariable*					velocityField,
+	double						defaultDiffusivity,
+        Swarm*						picSwarm,
+	void*		materials_Register,
+	AdvDiffResidualForceTerm_UpwindParamFuncType upwindFuncType )
+{
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*) _AdvDiffResidualForceTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ForceTerm_Init( self, context, forceVector, integrationSwarm, sle );
+	_AdvDiffResidualForceTerm_Init( self, velocityField, defaultDiffusivity,
+                                        picSwarm,
+                                        materials_Register, upwindFuncType );
+
+	return self;
+}
+
+void* _AdvDiffResidualForceTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                  _sizeOfSelf = sizeof(AdvDiffResidualForceTerm);
+	Type                                                          type = AdvDiffResidualForceTerm_Type;
+	Stg_Class_DeleteFunction*                                  _delete = _AdvDiffResidualForceTerm_Delete;
+	Stg_Class_PrintFunction*                                    _print = _AdvDiffResidualForceTerm_Print;
+	Stg_Class_CopyFunction*                                      _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*      _defaultConstructor = _AdvDiffResidualForceTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                        _construct = _AdvDiffResidualForceTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                                _build = _AdvDiffResidualForceTerm_Build;
+	Stg_Component_InitialiseFunction*                      _initialise = _AdvDiffResidualForceTerm_Initialise;
+	Stg_Component_ExecuteFunction*                            _execute = _AdvDiffResidualForceTerm_Execute;
+	Stg_Component_DestroyFunction*                            _destroy = _AdvDiffResidualForceTerm_Destroy;
+	ForceTerm_AssembleElementFunction*                _assembleElement = _AdvDiffResidualForceTerm_AssembleElement;
+	AdvDiffResidualForceTerm_UpwindParamFunction*         _upwindParam = _AdvDiffResidualForceTerm_UpwindParam;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_AdvDiffResidualForceTerm_New(  ADVDIFFRESIDUALFORCETERM_PASSARGS  );
+}
+
+/* Creation implementation / Virtual constructor */
+AdvDiffResidualForceTerm* _AdvDiffResidualForceTerm_New(  ADVDIFFRESIDUALFORCETERM_DEFARGS  )
+{
+	AdvDiffResidualForceTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(AdvDiffResidualForceTerm) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (AdvDiffResidualForceTerm*) _ForceTerm_New(  FORCETERM_PASSARGS  );
+	
+	/* Virtual info */
+	self->_upwindParam = _upwindParam;
+	
+	return self;
+}
+
+/*******************************************************************************
+  The following function scans all the elements of the mesh associated with
+  the residual forceterm phi to find the element with the most nodes.
+  Once the maximum number of nodes is found we then may allocate memory for
+  GNx etc that now live on the AdvDiffResidualForceTerm struct. This way we 
+  do not reallocate memory for these arrays for every element.
+ *******************************************************************************/
+void __AdvDiffResidualForceTerm_UpdateLocalMemory( AdvectionDiffusionSLE* sle ){
+	FeVariable*				phiField = sle->phiField;
+	FeMesh*					phiMesh = phiField->feMesh;
+	Dimension_Index 		dim = phiField->dim;
+	Element_LocalIndex	e, n_elements;
+	Node_Index				max_elementNodeCount;
+
+	n_elements = FeMesh_GetElementLocalSize(phiMesh);//returns number of elements in a mesh
+
+	/* Scan all elements in Mesh to get max node count */
+	max_elementNodeCount = 0;
+
+	for(e=0;e<n_elements;e++){
+		ElementType *elementType = FeMesh_GetElementType( phiMesh, e );
+		Node_Index elementNodeCount = elementType->nodeCount;
+	
+		if( elementNodeCount > max_elementNodeCount){
+			max_elementNodeCount = elementNodeCount;
+		}
+	}
+       
+	sle->advDiffResidualForceTerm->GNx = Memory_Alloc_2DArray( double, dim, max_elementNodeCount, (Name)"(SUPG): Global Shape Function Derivatives" );
+	sle->advDiffResidualForceTerm->phiGrad = Memory_Alloc_Array(double, dim, "(SUPG): Gradient of the Advected Scalar");
+	sle->advDiffResidualForceTerm->Ni = Memory_Alloc_Array(double, max_elementNodeCount, "(SUPG): Gradient of the Advected Scalar");
+	sle->advDiffResidualForceTerm->SUPGNi = Memory_Alloc_Array(double, max_elementNodeCount, "(SUPG): Upwinded Shape Function");
+	sle->advDiffResidualForceTerm->incarray=IArray_New();
+}
+
+void __AdvDiffResidualForceTerm_FreeLocalMemory( AdvectionDiffusionSLE* sle ){
+	Memory_Free(sle->advDiffResidualForceTerm->GNx);
+	Memory_Free(sle->advDiffResidualForceTerm->phiGrad);
+	Memory_Free(sle->advDiffResidualForceTerm->Ni);
+	Memory_Free(sle->advDiffResidualForceTerm->SUPGNi);
+  
+	NewClass_Delete(sle->advDiffResidualForceTerm->incarray);
+}
+
+void _AdvDiffResidualForceTerm_Init(
+	void*			residual,
+	FeVariable*		velocityField,
+	double			defaultDiffusivity,
+        Swarm*			picSwarm,
+	void*	                materials_Register,
+	AdvDiffResidualForceTerm_UpwindParamFuncType	upwindFuncType ) //WHY IS THIS LINE HERE???
+{
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
+
+	self->velocityField = velocityField;
+	self->defaultDiffusivity = defaultDiffusivity;
+        self->picSwarm = picSwarm;
+	self->materials_Register  = materials_Register;
+	self->upwindParamType = upwindFuncType;
+}
+
+void _AdvDiffResidualForceTerm_Delete( void* residual ) {
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
+
+	_ForceTerm_Delete( self );
+}
+
+void _AdvDiffResidualForceTerm_Print( void* residual, Stream* stream ) {
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
+	
+	_ForceTerm_Print( self, stream );
+
+	Journal_Printf( stream, "self->calculateUpwindParam = %s\n", 
+		self->_upwindParam == AdvDiffResidualForceTerm_UpwindXiExact ? 
+			"AdvDiffResidualForceTerm_UpwindXiExact" :
+		self->_upwindParam == AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption ? 
+			"AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption" :
+		self->_upwindParam == AdvDiffResidualForceTerm_UpwindXiCriticalAssumption ? 
+		"AdvDiffResidualForceTerm_UpwindXiCriticalAssumption" : "Unknown"  );
+
+	/* General info */
+	Journal_PrintPointer( stream, self->velocityField );
+	Journal_PrintDouble( stream, self->defaultDiffusivity );
+}
+
+void _AdvDiffResidualForceTerm_AssignFromXML( void* residual, Stg_ComponentFactory* cf, void* data ) {
+	AdvDiffResidualForceTerm*							self = (AdvDiffResidualForceTerm*)residual;
+	FeVariable*												velocityField;
+	Name														upwindParamFuncName;
+	double													defaultDiffusivity;
+	Materials_Register*		materials_Register;
+	AdvDiffResidualForceTerm_UpwindParamFuncType	upwindFuncType = (AdvDiffResidualForceTerm_UpwindParamFuncType)0;
+        Swarm *picSwarm;
+
+	/* Construct Parent */
+	_ForceTerm_AssignFromXML( self, cf, data );
+
+	velocityField = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"VelocityField", FeVariable, True, data  );
+	upwindParamFuncName = Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"UpwindXiFunction", "Exact"  );
+
+	if ( strcasecmp( upwindParamFuncName, "DoublyAsymptoticAssumption" ) == 0 )
+		upwindFuncType = DoublyAsymptoticAssumption;
+	else if ( strcasecmp( upwindParamFuncName, "CriticalAssumption" ) == 0 )
+		upwindFuncType = CriticalAssumption;
+	else if ( strcasecmp( upwindParamFuncName, "Exact" ) == 0 )
+		upwindFuncType = Exact;
+	else 
+		Journal_Firewall( False, Journal_Register( Error_Type, (Name)self->type  ), "Cannot understand '%s'\n", upwindParamFuncName );
+
+	defaultDiffusivity = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"defaultDiffusivity", 1.0  );
+	picSwarm       = (Swarm*)Stg_ComponentFactory_ConstructByName( cf, (Name)"picIntegrationPoints", IntegrationPointsSwarm, True, data  ) ;
+	materials_Register = ((PICelleratorContext*)(self->context))->materials_Register;
+
+	_AdvDiffResidualForceTerm_Init( self, velocityField, defaultDiffusivity,
+                                        picSwarm, materials_Register,
+                                        upwindFuncType );
+}
+
+void _AdvDiffResidualForceTerm_Build( void* residual, void* data ) {
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
+	AdvDiffResidualForceTerm_MaterialExt*   materialExt;
+	Material_Index                   material_I;
+	Material*                        material;
+	Materials_Register*              materials_Register = (Materials_Register*)(self->materials_Register);
+	IntegrationPointsSwarm*          swarm              = (IntegrationPointsSwarm*)self->picSwarm;
+	MaterialPointsSwarm**            materialSwarms;
+	Index                            materialSwarm_I;
+	Stg_ComponentFactory*            cf;
+	char*                            name;
+
+	cf = self->context->CF;
+
+	_ForceTerm_Build( self, data );
+
+	Stg_Component_Build( self->velocityField, data, False );
+
+	/* Sort out material extension stuff */
+	self->materialExtHandle = Materials_Register_AddMaterialExtension( 
+			self->materials_Register, 
+			self->type, 
+			sizeof(AdvDiffResidualForceTerm_MaterialExt) );
+	for ( material_I = 0 ; material_I < Materials_Register_GetCount( materials_Register ) ; material_I++) {
+		material = Materials_Register_GetByIndex( materials_Register, material_I );
+		materialExt = (AdvDiffResidualForceTerm_MaterialExt*)ExtensionManager_GetFunc( material->extensionMgr, material, self->materialExtHandle );
+
+		materialExt->diffusivity = Stg_ComponentFactory_GetDouble( cf, material->name,
+                                                                           (Dictionary_Entry_Key)"diffusivity",
+                                                                           self->defaultDiffusivity );
+	}
+	
+	/* Create Swarm Variables of each material swarm this ip swarm is mapped against */
+	materialSwarms = IntegrationPointMapper_GetMaterialPointsSwarms( swarm->mapper, &(self->materialSwarmCount) );
+	self->diffusivitySwarmVariables = (void**)Memory_Alloc_Array( MaterialSwarmVariable*, self->materialSwarmCount, "DiffusivityVariables" );
+	
+	for ( materialSwarm_I = 0; materialSwarm_I < self->materialSwarmCount; ++materialSwarm_I ) {
+		name = Stg_Object_AppendSuffix( materialSwarms[materialSwarm_I], (Name)"Diffusivity"  );
+		self->diffusivitySwarmVariables[materialSwarm_I] = MaterialSwarmVariable_New( 
+				name,
+				(AbstractContext*)self->context,
+				materialSwarms[materialSwarm_I], 
+				1, 
+				(Materials_Register*)self->materials_Register, 
+				self->materialExtHandle, 
+				GetOffsetOfMember( *materialExt, diffusivity ) );
+		Memory_Free( name );
+
+		/* Build new Swarm Variables */
+		Stg_Component_Build( self->diffusivitySwarmVariables[materialSwarm_I], data, False );
+	}
+}
+
+void _AdvDiffResidualForceTerm_Initialise( void* residual, void* data ) {
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
+	Index                          i;
+
+	_ForceTerm_Initialise( self, data );
+
+	Stg_Component_Initialise( self->velocityField, data, False );
+
+	for ( i = 0; i < self->materialSwarmCount; ++i ) {
+		Stg_Component_Initialise( self->diffusivitySwarmVariables[i], data, False );
+	}
+}
+
+void _AdvDiffResidualForceTerm_Execute( void* residual, void* data ) {
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
+
+	_ForceTerm_Execute( self, data );
+}
+
+void _AdvDiffResidualForceTerm_Destroy( void* residual, void* data ) {
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
+	Index                          i;
+
+	for ( i = 0; i < self->materialSwarmCount; ++i ) {
+		_Stg_Component_Delete( self->diffusivitySwarmVariables[i] );
+	}
+	Memory_Free( self->diffusivitySwarmVariables );
+
+	_ForceTerm_Destroy( self, data );
+}
+
+void _AdvDiffResidualForceTerm_AssembleElement( void* forceTerm, ForceVector* forceVector, Element_LocalIndex lElement_I, double* elementResidual ) {
+	AdvDiffResidualForceTerm*  self               = Stg_CheckType( forceTerm, AdvDiffResidualForceTerm );
+	AdvectionDiffusionSLE*     sle                = Stg_CheckType( self->extraInfo, AdvectionDiffusionSLE );
+	Swarm*                     swarm              = self->picSwarm;
+	Particle_Index             lParticle_I;
+	Particle_Index             cParticle_I;
+	Particle_Index             cellParticleCount;
+	Cell_Index                 cell_I;    
+	IntegrationPoint*          particle;
+	FeVariable*                phiField           = sle->phiField;
+	Dimension_Index            dim                = forceVector->dim;
+	double                     velocity[3];
+	double                     phi, phiDot;
+	double                     detJac;
+	double*                    xi;
+	double                     totalDerivative, diffusionTerm;
+	double                     diffusivity         = self->defaultDiffusivity;
+	ElementType*               elementType         = FeMesh_GetElementType( phiField->feMesh, lElement_I );
+	Node_Index                 elementNodeCount    = elementType->nodeCount;
+	Node_Index                 node_I;
+	double                     factor;
+
+	double**                   GNx;
+	double*                    phiGrad;
+	double*                    Ni;
+	double*                    SUPGNi;
+	double                     supgfactor;
+	double                     udotu, perturbation;
+	double                     upwindDiffusivity;
+
+	GNx     = self->GNx;
+	phiGrad = self->phiGrad;
+	Ni = self->Ni;
+	SUPGNi = self->SUPGNi;
+	
+	upwindDiffusivity  = AdvDiffResidualForceTerm_UpwindDiffusivity( self, sle, swarm, phiField->feMesh, lElement_I, dim );
+
+	/* Determine number of particles in element */
+	cell_I = CellLayout_MapElementIdToCellId( swarm->cellLayout, lElement_I );
+	cellParticleCount = swarm->cellParticleCountTbl[ cell_I ];
+	
+	for ( cParticle_I = 0 ; cParticle_I < cellParticleCount ; cParticle_I++ ) {
+		lParticle_I     = swarm->cellParticleTbl[cell_I][cParticle_I];
+
+		particle        = (IntegrationPoint*) Swarm_ParticleAt( swarm, lParticle_I );
+		xi              = particle->xi;
+		
+		/* Evaluate Shape Functions */
+		ElementType_EvaluateShapeFunctionsAt(elementType, xi, Ni);
+
+		/* Calculate Global Shape Function Derivatives */
+		ElementType_ShapeFunctionsGlobalDerivs( 
+			elementType,
+			phiField->feMesh, lElement_I,
+			xi, dim, &detJac, GNx );
+		
+		/* Calculate Velocity */
+		FeVariable_InterpolateFromMeshLocalCoord( self->velocityField, phiField->feMesh, lElement_I, xi, velocity );
+
+		/* Build the SUPG shape functions */
+		udotu = velocity[I_AXIS]*velocity[I_AXIS] + velocity[J_AXIS]*velocity[J_AXIS];
+		if(dim == 3) udotu += velocity[ K_AXIS ] * velocity[ K_AXIS ];
+
+		supgfactor = upwindDiffusivity / udotu;
+		for ( node_I = 0 ; node_I < elementNodeCount ; node_I++ ) {
+			/* In the case of per diffusion - just build regular shape functions */
+			if ( fabs(upwindDiffusivity) < SUPG_MIN_DIFFUSIVITY ) {
+				SUPGNi[node_I] = Ni[node_I];
+				continue;
+			}
+			
+			perturbation = velocity[ I_AXIS ] * GNx[ I_AXIS ][ node_I ] + velocity[ J_AXIS ] * GNx[ J_AXIS ][ node_I ];
+			if (dim == 3)
+					perturbation = perturbation + velocity[ K_AXIS ] * GNx[ K_AXIS ][ node_I ];
+			
+			/* p = \frac{\bar \kappa \hat u_j w_j }{ ||u|| } -  Eq. 3.2.25 */
+			perturbation = supgfactor * perturbation;
+			
+			SUPGNi[node_I] = Ni[node_I] + perturbation;
+		}  
+		
+		/* Calculate phi on particle */
+		_FeVariable_InterpolateNodeValuesToElLocalCoord( phiField, lElement_I, xi, &phi );
+
+		/* Calculate Gradients of Phi */
+		FeVariable_InterpolateDerivatives_WithGNx( phiField, lElement_I, GNx, phiGrad );
+
+		/* Calculate time derivative of phi */
+		_FeVariable_InterpolateNodeValuesToElLocalCoord( sle->phiDotField, lElement_I, xi, &phiDot );
+		
+		/* Calculate total derivative (i.e. Dphi/Dt = \dot \phi + u . \grad \phi) */
+		totalDerivative = phiDot + StGermain_VectorDotProduct( velocity, phiGrad, dim );
+
+		/* Get Diffusivity */
+		diffusivity = IntegrationPointMapper_GetDoubleFromMaterial(((IntegrationPointsSwarm *)swarm)->mapper, particle, self->materialExtHandle,
+
+		    offsetof(AdvDiffResidualForceTerm_MaterialExt, diffusivity));
+
+		/* Add to element residual */
+		factor = particle->weight * detJac;
+		for ( node_I = 0 ; node_I < elementNodeCount ; node_I++ ) {
+			/* Calculate Diffusion Term */
+			diffusionTerm = diffusivity * ( GNx[0][node_I] * phiGrad[0] + GNx[1][node_I] * phiGrad[1] );
+			if (dim == 3)
+				diffusionTerm += diffusivity * GNx[2][ node_I ] * phiGrad[2] ;
+			
+			elementResidual[ node_I ] -=  factor * ( SUPGNi[ node_I ] * totalDerivative + diffusionTerm );
+		}
+	}
+	
+}
+
+/* Virtual Function Implementations */
+double _AdvDiffResidualForceTerm_UpwindParam( void* residual, double pecletNumber ) {
+	AdvDiffResidualForceTerm* self = (AdvDiffResidualForceTerm*)residual;
+
+	switch ( self->upwindParamType ) {
+		case Exact:
+			self->_upwindParam = AdvDiffResidualForceTerm_UpwindXiExact; break;
+		case DoublyAsymptoticAssumption:
+			self->_upwindParam = AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption; break;
+		case CriticalAssumption:
+			self->_upwindParam = AdvDiffResidualForceTerm_UpwindXiCriticalAssumption; break;
+	}
+
+	return AdvDiffResidualForceTerm_UpwindParam( self, pecletNumber );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Timestep.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/Timestep.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,134 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Timestep.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-#include "mpi.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Timestep.h"
-
-#include "AdvectionDiffusionSLE.h"
-#include "Residual.h"
-#include <math.h>
-#include <assert.h>
-#include <string.h>
-
-
-double AdvectionDiffusionSLE_CalculateDt( void* advectionDiffusionSLE, FiniteElementContext* context ) {
-	AdvectionDiffusionSLE*     self   = (AdvectionDiffusionSLE*) advectionDiffusionSLE;
-	double                     advectionTimestep;
-	double                     diffusionTimestep;
-	double                     advectionTimestepGlobal;
-	double                     diffusionTimestepGlobal;
-	double                     timestep;
-	
-	Journal_DPrintf( self->debug, "In func: %s\n", __func__ );
-	
-	/*  It would be useful to introduce a limit to the change of step in here ... to prevent timesteps
-		from becoming arbitrarily large in a single step */ 
-	
-	/* Calculate Courant Number */
-	advectionTimestep = AdvectionDiffusionSLE_AdvectiveTimestep( self );
-	diffusionTimestep = AdvectionDiffusionSLE_DiffusiveTimestep( self );
-
-	MPI_Allreduce( &advectionTimestep, &advectionTimestepGlobal, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
-	MPI_Allreduce( &diffusionTimestep, &diffusionTimestepGlobal, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
-
-	Journal_DPrintf( self->debug, "%s Dominating. - Advective Timestep = %g - Diffusive Timestep = %g\n", 
-			advectionTimestepGlobal < diffusionTimestepGlobal ? "Advection" : "Diffusion",
-			advectionTimestepGlobal, diffusionTimestepGlobal);
-	
-	/* Calculate Time Step */
-	timestep = MIN( advectionTimestepGlobal, diffusionTimestepGlobal );
-
-	return timestep;
-}
-
-
-double AdvectionDiffusionSLE_DiffusiveTimestep( void* advectionDiffusionSLE ) {
-	AdvectionDiffusionSLE*    self              = (AdvectionDiffusionSLE*) advectionDiffusionSLE;
-	double                    minSeparation;
-	double                    minSeparationEachDim[3];
-
-	Journal_DPrintf( self->debug, "In func: %s\n", __func__ );
-	
-	FeVariable_GetMinimumSeparation( self->phiField, &minSeparation, minSeparationEachDim );
-
-	/* This is quite a conservative estimate */
-
-	return self->courantFactor * minSeparation * minSeparation / self->maxDiffusivity;
-}
-
-
-double AdvectionDiffusionSLE_AdvectiveTimestep( void* advectionDiffusionSLE ) {
-	AdvectionDiffusionSLE*    self              = (AdvectionDiffusionSLE*) advectionDiffusionSLE;
-	AdvDiffResidualForceTerm* residualForceTerm = self->advDiffResidualForceTerm;
-	FeVariable*               velocityField     = residualForceTerm->velocityField;
-	Node_LocalIndex           nodeLocalCount    = FeMesh_GetNodeLocalSize( self->phiField->feMesh );
-	Node_LocalIndex           node_I;
-	Dimension_Index           dim               = self->dim;
-	Dimension_Index           dim_I;
-	double                    timestep          = HUGE_VAL;
-	XYZ                       velocity;
-	double                    minSeparation;
-	double                    minSeparationEachDim[3];
-	double*                   meshCoord;
-	
-	Journal_DPrintf( self->debug, "In func: %s\n", __func__ );
-
-	FeVariable_GetMinimumSeparation( self->phiField, &minSeparation, minSeparationEachDim );
-
-	for( node_I = 0 ; node_I < nodeLocalCount ; node_I++ ){
-		meshCoord = Mesh_GetVertex( self->phiField->feMesh, node_I );
-		FieldVariable_InterpolateValueAt( velocityField, meshCoord, velocity );
-		
-		for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
-			if( velocity[ dim_I ] == 0.0 ) 
-				continue;
-			timestep = MIN( timestep, fabs( minSeparationEachDim[ dim_I ]/velocity[ dim_I ] ) );
-		}
-	}
-
-	return self->courantFactor * timestep;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/Timestep.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/Timestep.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,134 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Timestep.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#include "mpi.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Timestep.h"
+
+#include "AdvectionDiffusionSLE.h"
+#include "Residual.h"
+#include <math.h>
+#include <assert.h>
+#include <string.h>
+
+
+double AdvectionDiffusionSLE_CalculateDt( void* advectionDiffusionSLE, FiniteElementContext* context ) {
+	AdvectionDiffusionSLE*     self   = (AdvectionDiffusionSLE*) advectionDiffusionSLE;
+	double                     advectionTimestep;
+	double                     diffusionTimestep;
+	double                     advectionTimestepGlobal;
+	double                     diffusionTimestepGlobal;
+	double                     timestep;
+	
+	Journal_DPrintf( self->debug, "In func: %s\n", __func__ );
+	
+	/*  It would be useful to introduce a limit to the change of step in here ... to prevent timesteps
+		from becoming arbitrarily large in a single step */ 
+	
+	/* Calculate Courant Number */
+	advectionTimestep = AdvectionDiffusionSLE_AdvectiveTimestep( self );
+	diffusionTimestep = AdvectionDiffusionSLE_DiffusiveTimestep( self );
+
+	MPI_Allreduce( &advectionTimestep, &advectionTimestepGlobal, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
+	MPI_Allreduce( &diffusionTimestep, &diffusionTimestepGlobal, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
+
+	Journal_DPrintf( self->debug, "%s Dominating. - Advective Timestep = %g - Diffusive Timestep = %g\n", 
+			advectionTimestepGlobal < diffusionTimestepGlobal ? "Advection" : "Diffusion",
+			advectionTimestepGlobal, diffusionTimestepGlobal);
+	
+	/* Calculate Time Step */
+	timestep = MIN( advectionTimestepGlobal, diffusionTimestepGlobal );
+
+	return timestep;
+}
+
+
+double AdvectionDiffusionSLE_DiffusiveTimestep( void* advectionDiffusionSLE ) {
+	AdvectionDiffusionSLE*    self              = (AdvectionDiffusionSLE*) advectionDiffusionSLE;
+	double                    minSeparation;
+	double                    minSeparationEachDim[3];
+
+	Journal_DPrintf( self->debug, "In func: %s\n", __func__ );
+	
+	FeVariable_GetMinimumSeparation( self->phiField, &minSeparation, minSeparationEachDim );
+
+	/* This is quite a conservative estimate */
+
+	return self->courantFactor * minSeparation * minSeparation / self->maxDiffusivity;
+}
+
+
+double AdvectionDiffusionSLE_AdvectiveTimestep( void* advectionDiffusionSLE ) {
+	AdvectionDiffusionSLE*    self              = (AdvectionDiffusionSLE*) advectionDiffusionSLE;
+	AdvDiffResidualForceTerm* residualForceTerm = self->advDiffResidualForceTerm;
+	FeVariable*               velocityField     = residualForceTerm->velocityField;
+	Node_LocalIndex           nodeLocalCount    = FeMesh_GetNodeLocalSize( self->phiField->feMesh );
+	Node_LocalIndex           node_I;
+	Dimension_Index           dim               = self->dim;
+	Dimension_Index           dim_I;
+	double                    timestep          = HUGE_VAL;
+	XYZ                       velocity;
+	double                    minSeparation;
+	double                    minSeparationEachDim[3];
+	double*                   meshCoord;
+	
+	Journal_DPrintf( self->debug, "In func: %s\n", __func__ );
+
+	FeVariable_GetMinimumSeparation( self->phiField, &minSeparation, minSeparationEachDim );
+
+	for( node_I = 0 ; node_I < nodeLocalCount ; node_I++ ){
+		meshCoord = Mesh_GetVertex( self->phiField->feMesh, node_I );
+		FieldVariable_InterpolateValueAt( velocityField, meshCoord, velocity );
+		
+		for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
+			if( velocity[ dim_I ] == 0.0 ) 
+				continue;
+			timestep = MIN( timestep, fabs( minSeparationEachDim[ dim_I ]/velocity[ dim_I ] ) );
+		}
+	}
+
+	return self->courantFactor * timestep;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/UpwindParameter.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/src/UpwindParameter.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,208 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: UpwindParameter.c 985 2007-11-21 00:20:24Z MirkoVelic $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <math.h>
-#include <assert.h>
-#include <stddef.h>
-
-#include "mpi.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include <PICellerator/PICellerator.h>
-#include <Underworld/Underworld.h>
-
-#include "types.h"
-#include "AdvectionDiffusionSLE.h"
-#include "UpwindParameter.h"
-#include "Residual.h"
-
-#define ISQRT15 0.25819888974716112567
-
-/** AdvectionDiffusion_UpwindDiffusivity - See Brooks, Hughes 1982 Section 3.3 
- * All equations refer to this paper if not otherwise indicated */
-double AdvDiffResidualForceTerm_UpwindDiffusivity( 
-		AdvDiffResidualForceTerm* self, 
-		AdvectionDiffusionSLE* sle, 
-		Swarm* swarm, 
-		FeMesh* mesh, 
-		Element_LocalIndex lElement_I, 
-		Dimension_Index dim )
-{
-	FeVariable*                velocityField   = self->velocityField;
-	Coord                      xiElementCentre = {0.0,0.0,0.0};
-	double                     xiUpwind;
-	double                     velocityCentre[3];
-	double                     pecletNumber;
-	double                     lengthScale;
-	double                     upwindDiffusivity;
-	Dimension_Index            dim_I;
-	double*                    leastCoord;
-	double*                    greatestCoord;
-	Node_LocalIndex            nodeIndex_LeastValues, nodeIndex_GreatestValues;
-	unsigned                   nInc, *inc;
-	IArray*		 incArray;
-	
-	Cell_Index                 cell_I;
-	IntegrationPoint*          particle;
-	Particle_Index             lParticle_I;
-	double                     averageDiffusivity;
-	Particle_InCellIndex       cParticle_I;
-	Particle_InCellIndex       particleCount;
-	
-	/* Compute the average diffusivity */
-	/* Find Number of Particles in Element */
-	cell_I = CellLayout_MapElementIdToCellId( self->picSwarm->cellLayout, lElement_I );
-	particleCount = self->picSwarm->cellParticleCountTbl[ cell_I ];
-
-	/* Average diffusivity for element */
-        averageDiffusivity = 0.0;
-        for ( cParticle_I = 0 ; cParticle_I < particleCount ; cParticle_I++ ) {
-          lParticle_I = self->picSwarm->cellParticleTbl[cell_I][cParticle_I];
-          particle = (IntegrationPoint*) Swarm_ParticleAt( self->picSwarm, lParticle_I );
-
-          averageDiffusivity +=
-            IntegrationPointMapper_GetDoubleFromMaterial(((IntegrationPointsSwarm *)self->picSwarm)->mapper, particle, self->materialExtHandle,
-		    offsetof(AdvDiffResidualForceTerm_MaterialExt, diffusivity));
-        }
-        averageDiffusivity /= (double)particleCount;
-	
-	if (sle->maxDiffusivity < averageDiffusivity)
-		sle->maxDiffusivity = averageDiffusivity;
-	
-	
-	
-	
-	
-	
-	/* Change Diffusivity if it is too small */
-	if ( averageDiffusivity < SUPG_MIN_DIFFUSIVITY ) 
-		averageDiffusivity = SUPG_MIN_DIFFUSIVITY;
-	
-	/* Calculate Velocity At Middle of Element - See Eq. 3.3.6 */
-	FeVariable_InterpolateFromMeshLocalCoord( velocityField, mesh, lElement_I, xiElementCentre, velocityCentre );
-	
-	/* Calculate Length Scales - See Fig 3.4 - ASSUMES BOX MESH TODO - fix */
-	incArray = self->incarray;
-	FeMesh_GetElementNodes( mesh, lElement_I, incArray );
-	nInc = IArray_GetSize( incArray );
-	inc = (unsigned*)IArray_GetPtr( incArray );
-	
-	
-	nodeIndex_LeastValues = inc[0];
-	nodeIndex_GreatestValues = (dim == 2) ? inc[3] : inc[7];
-	leastCoord    = Mesh_GetVertex( mesh, nodeIndex_LeastValues );
-	greatestCoord = Mesh_GetVertex( mesh, nodeIndex_GreatestValues );
-	
-	upwindDiffusivity = 0.0;
-	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
-		lengthScale = greatestCoord[ dim_I ] - leastCoord[ dim_I ];
-		
-		/* Calculate Peclet Number (alpha) - See Eq. 3.3.5 */
-		pecletNumber = velocityCentre[ dim_I ] * lengthScale / (2.0 * averageDiffusivity);
-		
-		/* Calculate Upwind Local Coordinate - See Eq. 3.3.4 and (2.4.2, 3.3.1 and 3.3.2) */
-		xiUpwind = AdvDiffResidualForceTerm_UpwindParam( self, pecletNumber );
-		
-		/* Calculate Upwind Thermal Diffusivity - See Eq. 3.3.3  */
-		upwindDiffusivity += xiUpwind * velocityCentre[ dim_I ] * lengthScale;
-	}
-	upwindDiffusivity *= ISQRT15;         /* See Eq. 3.3.11 */
-	
-	
-	return upwindDiffusivity;
-}
-
-
-/** AdvectionDiffusion_UpwindXiExact - Brooks, Hughes 1982 equation 2.4.2
- *\f$ \bar \xi = coth( \alpha ) - \frac{1}{\alpha} \f$ */
-double AdvDiffResidualForceTerm_UpwindXiExact( void* residual, double pecletNumber ) {
-	if (fabs(pecletNumber) < 1.0e-8 )
-		return 0.33333333333333 * pecletNumber;
-	else if (pecletNumber < -20.0)
-		return -1.0 - 1.0/pecletNumber;
-	else if (pecletNumber > 20.0)
-		return +1.0 - 1.0/pecletNumber;
-		
-	return cosh( pecletNumber )/sinh( pecletNumber ) - 1.0/pecletNumber;
-}
-
-/** AdvectionDiffusion_UpwindXiDoublyAsymptoticAssumption - Brooks, Hughes 1982 equation 3.3.1
- * Simplification of \f$ \bar \xi = coth( \alpha ) - \frac{1}{\alpha} \f$ from Brooks, Hughes 1982 equation 2.4.2
- * \f[
-\bar \xi \sim \left\{ \begin{array}{rl} 
-             -1                 &for \quad \alpha <= -3 \\
-             \frac{\alpha}{3}   &for \quad -3 < \alpha <= 3 \\
-             +1                 &for \quad \alpha > +3
-             \end{array} \right.  
-           
-\f]*/
-double AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption( void* residual, double pecletNumber ) {
-	if (pecletNumber <= -3.0)
-		return -1;
-	else if (pecletNumber <= 3.0)
-		return 0.33333333333333 * pecletNumber;
-	else
-		return 1.0;
-}
-	
-/** AdvectionDiffusion_UpwindXiCriticalAssumption - Brooks, Hughes 1982 equation 3.3.2
- * Simplification of \f$ \bar \xi = coth( \alpha ) - \frac{1}{\alpha} \f$ from Brooks, Hughes 1982 equation 2.4.2
- * \f[
-  \bar \xi \sim \left\{ \begin{array}{rl}
-              -1 - \frac{1}{\alpha}   &for \quad \alpha <= -1 \\
-               0                      &for \quad -1 < \alpha <= +1 \\
-              +1 - \frac{1}{\alpha}   &for \quad \alpha > +1          
-              \end{array} \right.              
-\f]    */
-
-double AdvDiffResidualForceTerm_UpwindXiCriticalAssumption( void* residual, double pecletNumber ) {
-	if (pecletNumber <= -1.0)
-		return -1.0 - 1.0/pecletNumber;
-	else if (pecletNumber <= 1.0)
-		return 0.0;
-	else
-		return 1.0 - 1.0/pecletNumber;
-}
-	
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/src/UpwindParameter.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/src/UpwindParameter.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,208 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: UpwindParameter.c 985 2007-11-21 00:20:24Z MirkoVelic $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <math.h>
+#include <assert.h>
+#include <stddef.h>
+
+#include "mpi.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include <PICellerator/PICellerator.h>
+#include <Underworld/Underworld.h>
+
+#include "types.h"
+#include "AdvectionDiffusionSLE.h"
+#include "UpwindParameter.h"
+#include "Residual.h"
+
+#define ISQRT15 0.25819888974716112567
+
+/** AdvectionDiffusion_UpwindDiffusivity - See Brooks, Hughes 1982 Section 3.3 
+ * All equations refer to this paper if not otherwise indicated */
+double AdvDiffResidualForceTerm_UpwindDiffusivity( 
+		AdvDiffResidualForceTerm* self, 
+		AdvectionDiffusionSLE* sle, 
+		Swarm* swarm, 
+		FeMesh* mesh, 
+		Element_LocalIndex lElement_I, 
+		Dimension_Index dim )
+{
+	FeVariable*                velocityField   = self->velocityField;
+	Coord                      xiElementCentre = {0.0,0.0,0.0};
+	double                     xiUpwind;
+	double                     velocityCentre[3];
+	double                     pecletNumber;
+	double                     lengthScale;
+	double                     upwindDiffusivity;
+	Dimension_Index            dim_I;
+	double*                    leastCoord;
+	double*                    greatestCoord;
+	Node_LocalIndex            nodeIndex_LeastValues, nodeIndex_GreatestValues;
+	unsigned                   nInc, *inc;
+	IArray*		 incArray;
+	
+	Cell_Index                 cell_I;
+	IntegrationPoint*          particle;
+	Particle_Index             lParticle_I;
+	double                     averageDiffusivity;
+	Particle_InCellIndex       cParticle_I;
+	Particle_InCellIndex       particleCount;
+	
+	/* Compute the average diffusivity */
+	/* Find Number of Particles in Element */
+	cell_I = CellLayout_MapElementIdToCellId( self->picSwarm->cellLayout, lElement_I );
+	particleCount = self->picSwarm->cellParticleCountTbl[ cell_I ];
+
+	/* Average diffusivity for element */
+        averageDiffusivity = 0.0;
+        for ( cParticle_I = 0 ; cParticle_I < particleCount ; cParticle_I++ ) {
+          lParticle_I = self->picSwarm->cellParticleTbl[cell_I][cParticle_I];
+          particle = (IntegrationPoint*) Swarm_ParticleAt( self->picSwarm, lParticle_I );
+
+          averageDiffusivity +=
+            IntegrationPointMapper_GetDoubleFromMaterial(((IntegrationPointsSwarm *)self->picSwarm)->mapper, particle, self->materialExtHandle,
+		    offsetof(AdvDiffResidualForceTerm_MaterialExt, diffusivity));
+        }
+        averageDiffusivity /= (double)particleCount;
+	
+	if (sle->maxDiffusivity < averageDiffusivity)
+		sle->maxDiffusivity = averageDiffusivity;
+	
+	
+	
+	
+	
+	
+	/* Change Diffusivity if it is too small */
+	if ( averageDiffusivity < SUPG_MIN_DIFFUSIVITY ) 
+		averageDiffusivity = SUPG_MIN_DIFFUSIVITY;
+	
+	/* Calculate Velocity At Middle of Element - See Eq. 3.3.6 */
+	FeVariable_InterpolateFromMeshLocalCoord( velocityField, mesh, lElement_I, xiElementCentre, velocityCentre );
+	
+	/* Calculate Length Scales - See Fig 3.4 - ASSUMES BOX MESH TODO - fix */
+	incArray = self->incarray;
+	FeMesh_GetElementNodes( mesh, lElement_I, incArray );
+	nInc = IArray_GetSize( incArray );
+	inc = (unsigned*)IArray_GetPtr( incArray );
+	
+	
+	nodeIndex_LeastValues = inc[0];
+	nodeIndex_GreatestValues = (dim == 2) ? inc[3] : inc[7];
+	leastCoord    = Mesh_GetVertex( mesh, nodeIndex_LeastValues );
+	greatestCoord = Mesh_GetVertex( mesh, nodeIndex_GreatestValues );
+	
+	upwindDiffusivity = 0.0;
+	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
+		lengthScale = greatestCoord[ dim_I ] - leastCoord[ dim_I ];
+		
+		/* Calculate Peclet Number (alpha) - See Eq. 3.3.5 */
+		pecletNumber = velocityCentre[ dim_I ] * lengthScale / (2.0 * averageDiffusivity);
+		
+		/* Calculate Upwind Local Coordinate - See Eq. 3.3.4 and (2.4.2, 3.3.1 and 3.3.2) */
+		xiUpwind = AdvDiffResidualForceTerm_UpwindParam( self, pecletNumber );
+		
+		/* Calculate Upwind Thermal Diffusivity - See Eq. 3.3.3  */
+		upwindDiffusivity += xiUpwind * velocityCentre[ dim_I ] * lengthScale;
+	}
+	upwindDiffusivity *= ISQRT15;         /* See Eq. 3.3.11 */
+	
+	
+	return upwindDiffusivity;
+}
+
+
+/** AdvectionDiffusion_UpwindXiExact - Brooks, Hughes 1982 equation 2.4.2
+ *\f$ \bar \xi = coth( \alpha ) - \frac{1}{\alpha} \f$ */
+double AdvDiffResidualForceTerm_UpwindXiExact( void* residual, double pecletNumber ) {
+	if (fabs(pecletNumber) < 1.0e-8 )
+		return 0.33333333333333 * pecletNumber;
+	else if (pecletNumber < -20.0)
+		return -1.0 - 1.0/pecletNumber;
+	else if (pecletNumber > 20.0)
+		return +1.0 - 1.0/pecletNumber;
+		
+	return cosh( pecletNumber )/sinh( pecletNumber ) - 1.0/pecletNumber;
+}
+
+/** AdvectionDiffusion_UpwindXiDoublyAsymptoticAssumption - Brooks, Hughes 1982 equation 3.3.1
+ * Simplification of \f$ \bar \xi = coth( \alpha ) - \frac{1}{\alpha} \f$ from Brooks, Hughes 1982 equation 2.4.2
+ * \f[
+\bar \xi \sim \left\{ \begin{array}{rl} 
+             -1                 &for \quad \alpha <= -3 \\
+             \frac{\alpha}{3}   &for \quad -3 < \alpha <= 3 \\
+             +1                 &for \quad \alpha > +3
+             \end{array} \right.  
+           
+\f]*/
+double AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption( void* residual, double pecletNumber ) {
+	if (pecletNumber <= -3.0)
+		return -1;
+	else if (pecletNumber <= 3.0)
+		return 0.33333333333333 * pecletNumber;
+	else
+		return 1.0;
+}
+	
+/** AdvectionDiffusion_UpwindXiCriticalAssumption - Brooks, Hughes 1982 equation 3.3.2
+ * Simplification of \f$ \bar \xi = coth( \alpha ) - \frac{1}{\alpha} \f$ from Brooks, Hughes 1982 equation 2.4.2
+ * \f[
+  \bar \xi \sim \left\{ \begin{array}{rl}
+              -1 - \frac{1}{\alpha}   &for \quad \alpha <= -1 \\
+               0                      &for \quad -1 < \alpha <= +1 \\
+              +1 - \frac{1}{\alpha}   &for \quad \alpha > +1          
+              \end{array} \right.              
+\f]    */
+
+double AdvDiffResidualForceTerm_UpwindXiCriticalAssumption( void* residual, double pecletNumber ) {
+	if (pecletNumber <= -1.0)
+		return -1.0 - 1.0/pecletNumber;
+	else if (pecletNumber <= 1.0)
+		return 0.0;
+	else
+		return 1.0 - 1.0/pecletNumber;
+}
+	
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/tests/LumpedMassMatrixSuite.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/tests/LumpedMassMatrixSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,271 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** Role:
-**   Tests the LumpedMassMatrixSuite
-**
-** $Id: testTemplate.c 3462 2006-02-19 06:53:24Z WalterLandry $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h> 
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
-
-#include "LumpedMassMatrixSuite.h"
-
-#define CURR_MODULE_NAME "StgFEMContext.c"
-	
-typedef struct Node Node;
-typedef struct Element Element;
-
-struct Node {
-	double phi;
-};
-
-struct Element {
-	__FiniteElement_Element
-};
-
-struct _Particle {
-	Coord coord;
-};
-
-typedef struct {
-	MPI_Comm	comm;
-	int		rank;
-	int		nProcs;
-} LumpedMassMatrixSuiteData;
-
-void LumpedMassMatrixSuite_quadratic(Index index, Variable_Index var_I, void* context, void* result) {
-	*(double *)result = 20.0;
-}
-
-FeMesh* LumpedMassMatrixSuite_buildFeMesh( unsigned nDims, unsigned* size, double* minCrds, double* maxCrds, ExtensionManager_Register* emReg, ElementType_Register* etReg ) {
-	CartesianGenerator*	gen;
-	FeMesh*					feMesh;
-	unsigned					maxDecomp[3] = {0, 1, 1};
-
-	gen = CartesianGenerator_New( "", NULL );
-	gen->shadowDepth = 0;
-	CartesianGenerator_SetDimSize( gen, nDims );
-	CartesianGenerator_SetTopologyParams( gen, size, 0, NULL, maxDecomp );
-	CartesianGenerator_SetGeometryParams( gen, minCrds, maxCrds );
-
-	feMesh = FeMesh_New( "", NULL );
-	Mesh_SetExtensionManagerRegister( feMesh, emReg );
-	Mesh_SetGenerator( feMesh, gen );
-	FeMesh_SetElementFamily( feMesh, "linear" );
-
-	Mesh_SetTopologyDataSize( feMesh, MT_VERTEX, sizeof(Node) );
-	Mesh_SetTopologyDataSize( feMesh, (MeshTopology_Dim)nDims, sizeof(Element) );
-
-	Stg_Component_Build( feMesh, NULL, False );
-	Stg_Component_Initialise( feMesh, NULL, False );
-
-	return feMesh;
-}
-
-void LumpedMassMatrixSuite_Setup( LumpedMassMatrixSuiteData* data ) {
-	Journal_Enable_AllTypedStream( False );
-
-	/* MPI Initializations */
-	data->comm = MPI_COMM_WORLD;
-	MPI_Comm_rank( data->comm, &data->rank );
-	MPI_Comm_size( data->comm, &data->nProcs );
-}
-
-void LumpedMassMatrixSuite_Teardown( LumpedMassMatrixSuiteData* data ) {
-	Journal_Enable_AllTypedStream( True );
-}
-
-void LumpedMassMatrixSuite_TestLumpedMassMatrix( LumpedMassMatrixSuiteData* data ) {
-	Dictionary*						dictionary;
-	Dictionary_Entry_Value*		currBC;
-	Dictionary_Entry_Value*		bcList;
-	unsigned							nDims = 2;
-	unsigned							meshSize[3] = {2, 2, 0};
-	unsigned							nDomainVerts;
-	double							minCrds[3] = {0.0, 0.0, 0.0};
-	double							maxCrds[3] = {1.2, 1.2, 1.2};
-	FeMesh*							feMesh;
-	Node*								nodes;
-	DofLayout*						dofs;
-	ElementType_Register*		elementType_Register;
-	ExtensionManager_Register*	extensionMgr_Register;
-	WallVC*							wallVC;
-	FieldVariable_Register*		fV_Register;
-	FeVariable*						feVariable;
-	Variable_Register*			variableRegister;
-	FiniteElementContext*		context;
-	Index								i;
-	Dimension_Index				dim;
-	/* Swarm Stuff */
-	CellLayout*						singleCellLayout;
-	ParticleLayout*				gaussParticleLayout;
-	Swarm*							swarm;
-	unsigned							dimExists[] = { True, True, False };
-	/* Mass Matrix Stuff */
-	ForceVector*					massMatrix;
-	Vec								expectedMatrix;
-	PetscViewer						viewer;
-	PetscTruth						flg;
-	LumpedMassMatrixForceTerm*	massMatrixForceTerm;
-	Particle_InCellIndex			particlesPerDim[] = {2,2,2};
-	char								expected_file[PCU_PATH_MAX];
-
-	/* Read input */
-	dictionary = Dictionary_New();
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"outputPath", Dictionary_Entry_Value_FromString( "./output" )  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"rank", Dictionary_Entry_Value_FromUnsignedInt( data->rank )  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"numProcessors", Dictionary_Entry_Value_FromUnsignedInt( data->nProcs )  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"gaussParticlesX", Dictionary_Entry_Value_FromUnsignedInt( 2 )  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"gaussParticlesY", Dictionary_Entry_Value_FromUnsignedInt( 2 ) );
-
-	bcList = Dictionary_Entry_Value_NewList();
-	currBC = Dictionary_Entry_Value_NewStruct( );
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"name", Dictionary_Entry_Value_FromString( "phi" )  );
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"type", Dictionary_Entry_Value_FromString( "double" )  );
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"value", Dictionary_Entry_Value_FromDouble( -1.0f )  );
-	Dictionary_Entry_Value_AddElement( bcList, currBC );
-	currBC = Dictionary_Entry_Value_NewStruct();
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"wall", Dictionary_Entry_Value_FromString( "left" )  );
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"variables", bcList  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"boundaryCondition", currBC  );
-
-	/* Create Context */
-	context = FiniteElementContext_New( "context", 0,0, data->comm, dictionary );
-
-	dim = context->dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "dim", 2 );
-	
-	/* create the layout, dof and mesh to use */
-	extensionMgr_Register = ExtensionManager_Register_New();
-	elementType_Register = ElementType_Register_New("elementTypeRegister");
-	ElementType_Register_Add( elementType_Register, (ElementType*)ConstantElementType_New("constant") );
-	ElementType_Register_Add( elementType_Register, (ElementType*)BilinearElementType_New("bilinear") );
-	ElementType_Register_Add( elementType_Register, (ElementType*)TrilinearElementType_New("trilinear") );
-	
-	feMesh = (FeMesh*) LumpedMassMatrixSuite_buildFeMesh( nDims, meshSize, minCrds, maxCrds, extensionMgr_Register, elementType_Register );
-	nDomainVerts = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-	nodes = (Node*)Mesh_GetTopologyData( feMesh, MT_VERTEX );
-	
-	/* Create variable register */
-	variableRegister = Variable_Register_New();
-	
-	/* Create variables */
-	Variable_NewScalar( "phi", (AbstractContext*)context, Variable_DataType_Double, (Index*)&nDomainVerts, NULL, (void**)&nodes, variableRegister  );
-
-	dofs = DofLayout_New( "dofLayout", (DomainContext*)context, variableRegister, Mesh_GetDomainSize( feMesh, MT_VERTEX ), NULL );
-	for (i = 0; i < Mesh_GetDomainSize( feMesh, MT_VERTEX ); i++)
-		DofLayout_AddDof_ByVarName(dofs, "phi", i);
-	
-	wallVC = WallVC_New( "WallVC", (AbstractContext*)context, "boundaryCondition", variableRegister, NULL, dictionary, feMesh );
-
-	/* Create the finite element field variable*/
-	fV_Register = FieldVariable_Register_New();
-	feVariable = FeVariable_New( "phi", NULL, feMesh, NULL, dofs, wallVC, NULL, NULL, context->dim, False, False, False, fV_Register );
-	
-	/* Create Swarm */
-	if ( 3 == dim ) 
-		dimExists[K_AXIS] = True;
-	singleCellLayout= (CellLayout*)SingleCellLayout_New( "SingleCellLayout", (AbstractContext*)context, (Bool*)dimExists, NULL, NULL );
-	gaussParticleLayout = (ParticleLayout*)GaussParticleLayout_New( "GaussParticleLayout", NULL, LocalCoordSystem, True, dim, particlesPerDim );
-	swarm = Swarm_New( "gaussSwarm", (AbstractContext*)context, singleCellLayout, gaussParticleLayout,
-		dim, sizeof(IntegrationPoint), extensionMgr_Register, context->variable_Register, MPI_COMM_WORLD, NULL );
-	
-	/* Lumping of Mass Matrix */
-	massMatrix = ForceVector_New( "MassMatrix", context, feVariable, dim, context->entryPoint_Register, MPI_COMM_WORLD );
-	massMatrixForceTerm = LumpedMassMatrixForceTerm_New( "forceTerm", context, massMatrix, swarm );
-	EP_ReplaceAll( massMatrix->assembleForceVector, ForceVector_GlobalAssembly_General );
-	ForceTerm_SetAssembleElementFunction( massMatrixForceTerm, _LumpedMassMatrixForceTerm_AssembleElement_General );
-
-	/* Build */
-	Stg_Component_Build( feMesh, context, False );
-	Variable_Register_BuildAll( variableRegister );
-	Stg_Component_Build( wallVC, context, False );
-	Stg_Component_Build( dofs, context, False);
-	Stg_Component_Build( feVariable, context, False );
-	FeEquationNumber_BuildLocationMatrix( feVariable->eqNum );
-	Stg_Component_Build( singleCellLayout, context, False );
-	Stg_Component_Build( gaussParticleLayout, context, False );
-	Stg_Component_Build( swarm, context, False );
-	Stg_Component_Build( massMatrix, context, False );
-
-	/* Initialise */
-	Stg_Component_Initialise( feMesh, context, False );
-	Stg_Component_Initialise( feVariable, context, False );
-	Stg_Component_Initialise( swarm, context, False );
-	Stg_Component_Initialise( massMatrix, context, False );
-
-	/* Assemble */
-	if( data->rank == 0 ) {
-		ForceVector_Assemble( massMatrix );
-
-		PetscViewerCreate( MPI_COMM_WORLD, &viewer );
-		PetscViewerSetType( viewer, PETSC_VIEWER_BINARY );
-
-		pcu_filename_expected( "testLumpedMassMatrix.expected", expected_file );
-		PetscViewerBinaryOpen( MPI_COMM_WORLD, expected_file, FILE_MODE_READ, &viewer );
-	
-		VecLoad( viewer, VECMPI, &expectedMatrix );	
-
-		/* Try out optimised one */
-		VecSet( massMatrix->vector, 0.0 );
-	
-		/* Assemble */
-		ForceTerm_SetAssembleElementFunction( massMatrixForceTerm, _LumpedMassMatrixForceTerm_AssembleElement_Box );
-		ForceVector_Assemble( massMatrix );
-
-		/* Check vector */
-		VecEqual( (Vec)massMatrix->vector, expectedMatrix, &flg );
-		pcu_check_true( flg );
-	}
-
-	/* Destroy stuff */
-	_Stg_Component_Delete( massMatrix );
-	_Stg_Component_Delete( massMatrixForceTerm );
-	Stg_Class_Delete( fV_Register );
-	_Stg_Component_Delete( wallVC );
-	_Stg_Component_Delete( feMesh );
-	Stg_Class_Delete( elementType_Register );
-	Stg_Class_Delete( extensionMgr_Register );
-	_Stg_Component_Delete( dofs );
-	Stg_Class_Delete( dictionary );
-}
-
-void LumpedMassMatrixSuite( pcu_suite_t* suite ) {
-	pcu_suite_setData( suite, LumpedMassMatrixSuiteData );
-   pcu_suite_setFixtures( suite, LumpedMassMatrixSuite_Setup, LumpedMassMatrixSuite_Teardown );
-   pcu_suite_addTest( suite, LumpedMassMatrixSuite_TestLumpedMassMatrix );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/tests/LumpedMassMatrixSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/tests/LumpedMassMatrixSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,271 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** Role:
+**   Tests the LumpedMassMatrixSuite
+**
+** $Id: testTemplate.c 3462 2006-02-19 06:53:24Z WalterLandry $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h> 
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
+
+#include "LumpedMassMatrixSuite.h"
+
+#define CURR_MODULE_NAME "StgFEMContext.c"
+	
+typedef struct Node Node;
+typedef struct Element Element;
+
+struct Node {
+	double phi;
+};
+
+struct Element {
+	__FiniteElement_Element
+};
+
+struct _Particle {
+	Coord coord;
+};
+
+typedef struct {
+	MPI_Comm	comm;
+	int		rank;
+	int		nProcs;
+} LumpedMassMatrixSuiteData;
+
+void LumpedMassMatrixSuite_quadratic(Index index, Variable_Index var_I, void* context, void* result) {
+	*(double *)result = 20.0;
+}
+
+FeMesh* LumpedMassMatrixSuite_buildFeMesh( unsigned nDims, unsigned* size, double* minCrds, double* maxCrds, ExtensionManager_Register* emReg, ElementType_Register* etReg ) {
+	CartesianGenerator*	gen;
+	FeMesh*					feMesh;
+	unsigned					maxDecomp[3] = {0, 1, 1};
+
+	gen = CartesianGenerator_New( "", NULL );
+	gen->shadowDepth = 0;
+	CartesianGenerator_SetDimSize( gen, nDims );
+	CartesianGenerator_SetTopologyParams( gen, size, 0, NULL, maxDecomp );
+	CartesianGenerator_SetGeometryParams( gen, minCrds, maxCrds );
+
+	feMesh = FeMesh_New( "", NULL );
+	Mesh_SetExtensionManagerRegister( feMesh, emReg );
+	Mesh_SetGenerator( feMesh, gen );
+	FeMesh_SetElementFamily( feMesh, "linear" );
+
+	Mesh_SetTopologyDataSize( feMesh, MT_VERTEX, sizeof(Node) );
+	Mesh_SetTopologyDataSize( feMesh, (MeshTopology_Dim)nDims, sizeof(Element) );
+
+	Stg_Component_Build( feMesh, NULL, False );
+	Stg_Component_Initialise( feMesh, NULL, False );
+
+	return feMesh;
+}
+
+void LumpedMassMatrixSuite_Setup( LumpedMassMatrixSuiteData* data ) {
+	Journal_Enable_AllTypedStream( False );
+
+	/* MPI Initializations */
+	data->comm = MPI_COMM_WORLD;
+	MPI_Comm_rank( data->comm, &data->rank );
+	MPI_Comm_size( data->comm, &data->nProcs );
+}
+
+void LumpedMassMatrixSuite_Teardown( LumpedMassMatrixSuiteData* data ) {
+	Journal_Enable_AllTypedStream( True );
+}
+
+void LumpedMassMatrixSuite_TestLumpedMassMatrix( LumpedMassMatrixSuiteData* data ) {
+	Dictionary*						dictionary;
+	Dictionary_Entry_Value*		currBC;
+	Dictionary_Entry_Value*		bcList;
+	unsigned							nDims = 2;
+	unsigned							meshSize[3] = {2, 2, 0};
+	unsigned							nDomainVerts;
+	double							minCrds[3] = {0.0, 0.0, 0.0};
+	double							maxCrds[3] = {1.2, 1.2, 1.2};
+	FeMesh*							feMesh;
+	Node*								nodes;
+	DofLayout*						dofs;
+	ElementType_Register*		elementType_Register;
+	ExtensionManager_Register*	extensionMgr_Register;
+	WallVC*							wallVC;
+	FieldVariable_Register*		fV_Register;
+	FeVariable*						feVariable;
+	Variable_Register*			variableRegister;
+	FiniteElementContext*		context;
+	Index								i;
+	Dimension_Index				dim;
+	/* Swarm Stuff */
+	CellLayout*						singleCellLayout;
+	ParticleLayout*				gaussParticleLayout;
+	Swarm*							swarm;
+	unsigned							dimExists[] = { True, True, False };
+	/* Mass Matrix Stuff */
+	ForceVector*					massMatrix;
+	Vec								expectedMatrix;
+	PetscViewer						viewer;
+	PetscTruth						flg;
+	LumpedMassMatrixForceTerm*	massMatrixForceTerm;
+	Particle_InCellIndex			particlesPerDim[] = {2,2,2};
+	char								expected_file[PCU_PATH_MAX];
+
+	/* Read input */
+	dictionary = Dictionary_New();
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"outputPath", Dictionary_Entry_Value_FromString( "./output" )  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"rank", Dictionary_Entry_Value_FromUnsignedInt( data->rank )  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"numProcessors", Dictionary_Entry_Value_FromUnsignedInt( data->nProcs )  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"gaussParticlesX", Dictionary_Entry_Value_FromUnsignedInt( 2 )  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"gaussParticlesY", Dictionary_Entry_Value_FromUnsignedInt( 2 ) );
+
+	bcList = Dictionary_Entry_Value_NewList();
+	currBC = Dictionary_Entry_Value_NewStruct( );
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"name", Dictionary_Entry_Value_FromString( "phi" )  );
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"type", Dictionary_Entry_Value_FromString( "double" )  );
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"value", Dictionary_Entry_Value_FromDouble( -1.0f )  );
+	Dictionary_Entry_Value_AddElement( bcList, currBC );
+	currBC = Dictionary_Entry_Value_NewStruct();
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"wall", Dictionary_Entry_Value_FromString( "left" )  );
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"variables", bcList  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"boundaryCondition", currBC  );
+
+	/* Create Context */
+	context = FiniteElementContext_New( "context", 0,0, data->comm, dictionary );
+
+	dim = context->dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "dim", 2 );
+	
+	/* create the layout, dof and mesh to use */
+	extensionMgr_Register = ExtensionManager_Register_New();
+	elementType_Register = ElementType_Register_New("elementTypeRegister");
+	ElementType_Register_Add( elementType_Register, (ElementType*)ConstantElementType_New("constant") );
+	ElementType_Register_Add( elementType_Register, (ElementType*)BilinearElementType_New("bilinear") );
+	ElementType_Register_Add( elementType_Register, (ElementType*)TrilinearElementType_New("trilinear") );
+	
+	feMesh = (FeMesh*) LumpedMassMatrixSuite_buildFeMesh( nDims, meshSize, minCrds, maxCrds, extensionMgr_Register, elementType_Register );
+	nDomainVerts = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+	nodes = (Node*)Mesh_GetTopologyData( feMesh, MT_VERTEX );
+	
+	/* Create variable register */
+	variableRegister = Variable_Register_New();
+	
+	/* Create variables */
+	Variable_NewScalar( "phi", (AbstractContext*)context, Variable_DataType_Double, (Index*)&nDomainVerts, NULL, (void**)&nodes, variableRegister  );
+
+	dofs = DofLayout_New( "dofLayout", (DomainContext*)context, variableRegister, Mesh_GetDomainSize( feMesh, MT_VERTEX ), NULL );
+	for (i = 0; i < Mesh_GetDomainSize( feMesh, MT_VERTEX ); i++)
+		DofLayout_AddDof_ByVarName(dofs, "phi", i);
+	
+	wallVC = WallVC_New( "WallVC", (AbstractContext*)context, "boundaryCondition", variableRegister, NULL, dictionary, feMesh );
+
+	/* Create the finite element field variable*/
+	fV_Register = FieldVariable_Register_New();
+	feVariable = FeVariable_New( "phi", NULL, feMesh, NULL, dofs, wallVC, NULL, NULL, context->dim, False, False, False, fV_Register );
+	
+	/* Create Swarm */
+	if ( 3 == dim ) 
+		dimExists[K_AXIS] = True;
+	singleCellLayout= (CellLayout*)SingleCellLayout_New( "SingleCellLayout", (AbstractContext*)context, (Bool*)dimExists, NULL, NULL );
+	gaussParticleLayout = (ParticleLayout*)GaussParticleLayout_New( "GaussParticleLayout", NULL, LocalCoordSystem, True, dim, particlesPerDim );
+	swarm = Swarm_New( "gaussSwarm", (AbstractContext*)context, singleCellLayout, gaussParticleLayout,
+		dim, sizeof(IntegrationPoint), extensionMgr_Register, context->variable_Register, MPI_COMM_WORLD, NULL );
+	
+	/* Lumping of Mass Matrix */
+	massMatrix = ForceVector_New( "MassMatrix", context, feVariable, dim, context->entryPoint_Register, MPI_COMM_WORLD );
+	massMatrixForceTerm = LumpedMassMatrixForceTerm_New( "forceTerm", context, massMatrix, swarm );
+	EP_ReplaceAll( massMatrix->assembleForceVector, ForceVector_GlobalAssembly_General );
+	ForceTerm_SetAssembleElementFunction( massMatrixForceTerm, _LumpedMassMatrixForceTerm_AssembleElement_General );
+
+	/* Build */
+	Stg_Component_Build( feMesh, context, False );
+	Variable_Register_BuildAll( variableRegister );
+	Stg_Component_Build( wallVC, context, False );
+	Stg_Component_Build( dofs, context, False);
+	Stg_Component_Build( feVariable, context, False );
+	FeEquationNumber_BuildLocationMatrix( feVariable->eqNum );
+	Stg_Component_Build( singleCellLayout, context, False );
+	Stg_Component_Build( gaussParticleLayout, context, False );
+	Stg_Component_Build( swarm, context, False );
+	Stg_Component_Build( massMatrix, context, False );
+
+	/* Initialise */
+	Stg_Component_Initialise( feMesh, context, False );
+	Stg_Component_Initialise( feVariable, context, False );
+	Stg_Component_Initialise( swarm, context, False );
+	Stg_Component_Initialise( massMatrix, context, False );
+
+	/* Assemble */
+	if( data->rank == 0 ) {
+		ForceVector_Assemble( massMatrix );
+
+		PetscViewerCreate( MPI_COMM_WORLD, &viewer );
+		PetscViewerSetType( viewer, PETSC_VIEWER_BINARY );
+
+		pcu_filename_expected( "testLumpedMassMatrix.expected", expected_file );
+		PetscViewerBinaryOpen( MPI_COMM_WORLD, expected_file, FILE_MODE_READ, &viewer );
+	
+		VecLoad( viewer, VECMPI, &expectedMatrix );	
+
+		/* Try out optimised one */
+		VecSet( massMatrix->vector, 0.0 );
+	
+		/* Assemble */
+		ForceTerm_SetAssembleElementFunction( massMatrixForceTerm, _LumpedMassMatrixForceTerm_AssembleElement_Box );
+		ForceVector_Assemble( massMatrix );
+
+		/* Check vector */
+		VecEqual( (Vec)massMatrix->vector, expectedMatrix, &flg );
+		pcu_check_true( flg );
+	}
+
+	/* Destroy stuff */
+	_Stg_Component_Delete( massMatrix );
+	_Stg_Component_Delete( massMatrixForceTerm );
+	Stg_Class_Delete( fV_Register );
+	_Stg_Component_Delete( wallVC );
+	_Stg_Component_Delete( feMesh );
+	Stg_Class_Delete( elementType_Register );
+	Stg_Class_Delete( extensionMgr_Register );
+	_Stg_Component_Delete( dofs );
+	Stg_Class_Delete( dictionary );
+}
+
+void LumpedMassMatrixSuite( pcu_suite_t* suite ) {
+	pcu_suite_setData( suite, LumpedMassMatrixSuiteData );
+   pcu_suite_setFixtures( suite, LumpedMassMatrixSuite_Setup, LumpedMassMatrixSuite_Teardown );
+   pcu_suite_addTest( suite, LumpedMassMatrixSuite_TestLumpedMassMatrix );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/tests/UpwindXiSuite.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/tests/UpwindXiSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** Role:
-**   Tests the UpwindXiSuite
-**
-** $Id: testUpwindXi.c 3462 2006-02-19 06:53:24Z WalterLandry $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
-#include "UpwindXiSuite.h"
-
-typedef struct {
-} UpwindXiSuiteData;
-
-
-void UpwindXiSuite_Setup( UpwindXiSuiteData* data ) {
-	Journal_Enable_AllTypedStream( False );
-}
-
-void UpwindXiSuite_Teardown( UpwindXiSuiteData* data ) {
-}
-
-
-void UpwindXiSuite_Test( UpwindXiSuiteData* data ) {
-	Stream* dataStream;
-	double  minPercletNumber = -15.0;
-	double  maxPercletNumber = 15.0;
-	double  dPerceltNumber = 0.5;
-	double  perceltNumber;
-	char	expectedFile[PCU_PATH_MAX];
-	int	rank;
-	char	outputFilename[100];
-
-	MPI_Comm_rank( MPI_COMM_WORLD, &rank );
-	sprintf( outputFilename, "output_%2d.dat", rank );
-
-	Journal_Enable_TypedStream( InfoStream_Type, True );
-	dataStream = Journal_Register( Info_Type, (Name)"DataStream"  );
-	Stream_RedirectFile( dataStream, outputFilename );
-		
-	Journal_Printf( dataStream, "# File to compare code with Brooks, Hughes 1982 - Fig 3.3\n");
-	Journal_Printf( dataStream, "# Integration rule for the optimal upwind scheme, doubly asymptotic approximation and critical approximation.\n");
-	Journal_Printf( dataStream, "# Plot using line:\n");
-	Journal_Printf( dataStream, "# plot \"%s\" using 1:2 title \"Exact\" with line, ", "output.dat" );
-	Journal_Printf( dataStream, "\"%s\" using 1:3 title \"DoublyAsymptoticAssumption\" with line, ", "output.dat" );
-	Journal_Printf( dataStream, "\"%s\" using 1:4 title \"CriticalAssumption\" with line\n", "output.dat" );
-
-	Journal_Printf( dataStream, "# Perclet Number \t Exact \t DoublyAsymptoticAssumption \t CriticalAssumption\n" );
-	for ( perceltNumber = minPercletNumber ; perceltNumber < maxPercletNumber ; perceltNumber += dPerceltNumber )
-		Journal_Printf( dataStream, "%0.3g \t\t %0.3g \t\t %0.3g \t\t %0.3g\n", 
-				perceltNumber, 
-				AdvDiffResidualForceTerm_UpwindXiExact( NULL, perceltNumber),
-				AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption( NULL, perceltNumber),
-				AdvDiffResidualForceTerm_UpwindXiCriticalAssumption( NULL, perceltNumber) );
-
-	pcu_filename_expected( "UpwindXi.expected", expectedFile );
-	pcu_check_fileEq( outputFilename, expectedFile );
-	remove( outputFilename );
-	/*Journal_Purge( );*/
-}
-
-void UpwindXiSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, UpwindXiSuiteData );
-   pcu_suite_setFixtures( suite, UpwindXiSuite_Setup, UpwindXiSuite_Teardown );
-   pcu_suite_addTest( suite, UpwindXiSuite_Test );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/tests/UpwindXiSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/tests/UpwindXiSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,102 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**   Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**   Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**   Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**   Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**   Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**   Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** Role:
+**   Tests the UpwindXiSuite
+**
+** $Id: testUpwindXi.c 3462 2006-02-19 06:53:24Z WalterLandry $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
+#include "UpwindXiSuite.h"
+
+typedef struct {
+} UpwindXiSuiteData;
+
+
+void UpwindXiSuite_Setup( UpwindXiSuiteData* data ) {
+	Journal_Enable_AllTypedStream( False );
+}
+
+void UpwindXiSuite_Teardown( UpwindXiSuiteData* data ) {
+}
+
+
+void UpwindXiSuite_Test( UpwindXiSuiteData* data ) {
+	Stream* dataStream;
+	double  minPercletNumber = -15.0;
+	double  maxPercletNumber = 15.0;
+	double  dPerceltNumber = 0.5;
+	double  perceltNumber;
+	char	expectedFile[PCU_PATH_MAX];
+	int	rank;
+	char	outputFilename[100];
+
+	MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+	sprintf( outputFilename, "output_%2d.dat", rank );
+
+	Journal_Enable_TypedStream( InfoStream_Type, True );
+	dataStream = Journal_Register( Info_Type, (Name)"DataStream"  );
+	Stream_RedirectFile( dataStream, outputFilename );
+		
+	Journal_Printf( dataStream, "# File to compare code with Brooks, Hughes 1982 - Fig 3.3\n");
+	Journal_Printf( dataStream, "# Integration rule for the optimal upwind scheme, doubly asymptotic approximation and critical approximation.\n");
+	Journal_Printf( dataStream, "# Plot using line:\n");
+	Journal_Printf( dataStream, "# plot \"%s\" using 1:2 title \"Exact\" with line, ", "output.dat" );
+	Journal_Printf( dataStream, "\"%s\" using 1:3 title \"DoublyAsymptoticAssumption\" with line, ", "output.dat" );
+	Journal_Printf( dataStream, "\"%s\" using 1:4 title \"CriticalAssumption\" with line\n", "output.dat" );
+
+	Journal_Printf( dataStream, "# Perclet Number \t Exact \t DoublyAsymptoticAssumption \t CriticalAssumption\n" );
+	for ( perceltNumber = minPercletNumber ; perceltNumber < maxPercletNumber ; perceltNumber += dPerceltNumber )
+		Journal_Printf( dataStream, "%0.3g \t\t %0.3g \t\t %0.3g \t\t %0.3g\n", 
+				perceltNumber, 
+				AdvDiffResidualForceTerm_UpwindXiExact( NULL, perceltNumber),
+				AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption( NULL, perceltNumber),
+				AdvDiffResidualForceTerm_UpwindXiCriticalAssumption( NULL, perceltNumber) );
+
+	pcu_filename_expected( "UpwindXi.expected", expectedFile );
+	pcu_check_fileEq( outputFilename, expectedFile );
+	remove( outputFilename );
+	/*Journal_Purge( );*/
+}
+
+void UpwindXiSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, UpwindXiSuiteData );
+   pcu_suite_setFixtures( suite, UpwindXiSuite_Setup, UpwindXiSuite_Teardown );
+   pcu_suite_addTest( suite, UpwindXiSuite_Test );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testLumpedMassMatrix.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testLumpedMassMatrix.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,300 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: testLumpedMassMatrix.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include "petsc.h"
-
-
-typedef struct Node Node;
-typedef struct Element Element;
-
-struct Node {
-	double phi;
-};
-
-struct Element {
-	__FiniteElement_Element
-};
-
-struct _Particle {
-	Coord coord;
-};
-
-
-FeMesh* buildFeMesh( unsigned nDims, unsigned* size, 
-		     double* minCrds, double* maxCrds, 
-		     ExtensionManager_Register* emReg, 
-		     ElementType_Register* etReg )
-{
-	CartesianGenerator*	gen;
-	FeMesh*			feMesh;
-	unsigned		maxDecomp[3] = {0, 1, 1};
-
-	gen = CartesianGenerator_New( "", NULL );
-	gen->shadowDepth = 0;
-	CartesianGenerator_SetDimSize( gen, nDims );
-	CartesianGenerator_SetTopologyParams( gen, size, 0, NULL, maxDecomp );
-	CartesianGenerator_SetGeometryParams( gen, minCrds, maxCrds );
-
-	feMesh = FeMesh_New( "", NULL );
-	Mesh_SetExtensionManagerRegister( feMesh, emReg );
-	Mesh_SetGenerator( feMesh, gen );
-	FeMesh_SetElementFamily( feMesh, "linear" );
-
-	Mesh_SetTopologyDataSize( feMesh, MT_VERTEX, sizeof(Node) );
-	Mesh_SetTopologyDataSize( feMesh, nDims, sizeof(Element) );
-
-	Stg_Component_Build( feMesh, NULL, False );
-	Stg_Component_Initialise( feMesh, NULL, False );
-
-	return feMesh;
-}
-
-
-int main( int argc, char* argv[] ) {
-	MPI_Comm                   CommWorld;
-	int                        rank;
-	int                        numProcessors;
-	int                        procToWatch;
-	Dictionary*                dictionary;
-	Dictionary_Entry_Value*    currBC;
-	Dictionary_Entry_Value*	   bcList;
-
-	unsigned	nDims = 2;
-	unsigned	meshSize[3] = {2, 2, 0};
-	double		minCrds[3] = {0.0, 0.0, 0.0};
-	double		maxCrds[3] = {1.2, 1.2, 1.2};
-	FeMesh*		feMesh;
-	unsigned	nDomainVerts;
-	Node*		nodes;
-
-	DofLayout*                 dofs;
-	ElementType_Register*      elementType_Register;
-	ExtensionManager_Register* extensionMgr_Register;
-	WallVC*                    wallVC;
-	FieldVariable_Register*    fV_Register;
-	FeVariable*                feVariable;
-	Variable_Register*         variableRegister;
-	FiniteElementContext*      context;
-	Index                      i;
-	Dimension_Index            dim;
-	Stream*	                   stream;
-	/* Swarm Stuff */
-	CellLayout*                singleCellLayout;
-	ParticleLayout*            gaussParticleLayout;
-	Swarm*                     swarm;
-	unsigned int               dimExists[]     = { True, True, False };
-	/* Mass Matrix Stuff */
-	ForceVector*               massMatrix;
-	LumpedMassMatrixForceTerm* massMatrixForceTerm;
-	/* Stream Stuff */
-	Stream*                    outputStream;
-	Particle_InCellIndex       particlesPerDim[] = {2,2,2};
-	
-	/* 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 );
-	
-	StGermain_Init( &argc, &argv );
-	StgDomain_Init( &argc, &argv );
-	StgFEM_Discretisation_Init( &argc, &argv );
-	//StgFEM_SLE_LinearAlgebra_Init( &argc, &argv );
-	StgFEM_SLE_SystemSetup_Init( &argc, &argv );
-	StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Init( &argc, &argv );
-	MPI_Barrier( CommWorld ); /* Ensures copyright info always come first in output */
-	
-	stream = Journal_Register( Info_Type, (Name)"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, (Dictionary_Entry_Key)"outputPath", Dictionary_Entry_Value_FromString( "./output" )  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"rank", Dictionary_Entry_Value_FromUnsignedInt( rank )  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"numProcessors", Dictionary_Entry_Value_FromUnsignedInt( numProcessors )  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"gaussParticlesX", Dictionary_Entry_Value_FromUnsignedInt( 2 )  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"gaussParticlesY", Dictionary_Entry_Value_FromUnsignedInt( 2 ) );
-	
-	bcList = Dictionary_Entry_Value_NewList();
-	currBC = Dictionary_Entry_Value_NewStruct( );
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"name", Dictionary_Entry_Value_FromString( "phi" )  );
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"type", Dictionary_Entry_Value_FromString( "double" )  );
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"value", Dictionary_Entry_Value_FromDouble( -1.0f )  );
-	Dictionary_Entry_Value_AddElement( bcList, currBC );
-	currBC = Dictionary_Entry_Value_NewStruct();
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"wall", Dictionary_Entry_Value_FromString( "left" )  );
-	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"variables", bcList  );
-	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"boundaryCondition", currBC  );
-
-	/* Create Context */
-	context = FiniteElementContext_New( "context", 0,0, MPI_COMM_WORLD, dictionary );
-	dim = context->dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "dim", 2 );
-	Journal_Enable_TypedStream( DebugStream_Type, True );
-	Stream_SetLevelBranch( StgFEM_Debug, 3 );
-	Stream_EnableBranch( StgFEM_Debug, True );
-	
-	/* create the layout, dof and mesh to use */
-	extensionMgr_Register = ExtensionManager_Register_New();
-	elementType_Register = ElementType_Register_New("elementTypeRegister");
-	ElementType_Register_Add( elementType_Register, (ElementType*)ConstantElementType_New("constant") );
-	ElementType_Register_Add( elementType_Register, (ElementType*)BilinearElementType_New("bilinear") );
-	ElementType_Register_Add( elementType_Register, (ElementType*)TrilinearElementType_New("trilinear") );
-
-	feMesh = buildFeMesh( nDims, meshSize, minCrds, maxCrds, 
-			      extensionMgr_Register, elementType_Register );
-	nDomainVerts = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-	nodes = Mesh_GetTopologyData( feMesh, MT_VERTEX );
-	
-	/* Create variable register */
-	variableRegister = Variable_Register_New();
-	
-	/* Create variables */
-	Variable_NewScalar( 
-		"phi", 
-		Variable_DataType_Double, 
-		&nDomainVerts, 
-		NULL,
-		(void**)&nodes, 
-		variableRegister );
-
-	dofs = DofLayout_New( "dofLayout", variableRegister, Mesh_GetDomainSize( feMesh, MT_VERTEX ), NULL );
-	for (i = 0; i < Mesh_GetDomainSize( feMesh, MT_VERTEX ); i++)
-		DofLayout_AddDof_ByVarName(dofs, "phi", i);
-	
-	wallVC = WallVC_New( "WallVC", "boundaryCondition", variableRegister, NULL, dictionary, feMesh );
-
-	/* Create the finite element field variable*/
-	fV_Register = FieldVariable_Register_New();
-	feVariable = FeVariable_New( "phi", feMesh, NULL, dofs, wallVC, NULL, NULL, context->dim,
-		False, False, False, fV_Register );
-	
-	/* Create Stream */
-	outputStream = Journal_Register( InfoStream_Type, (Name)CURR_MODULE_NAME  );
-	Stream_RedirectFile( outputStream, "output/output.dat" );
-
-	/* Create Swarm */
-	if ( 3 == dim ) 
-		dimExists[K_AXIS] = True;
-	singleCellLayout    = (CellLayout*)SingleCellLayout_New( "SingleCellLayout", dimExists, NULL, NULL );
-	gaussParticleLayout = (ParticleLayout*)GaussParticleLayout_New( "GaussParticleLayout", dim, particlesPerDim );
-	swarm = Swarm_New( "gaussSwarm", singleCellLayout, gaussParticleLayout, dim,
-		sizeof(IntegrationPoint), context->extensionMgr_Register, context->variable_Register, MPI_COMM_WORLD, NULL );
-	
-	/* Lumping of Mass Matrix */
-	massMatrix = ForceVector_New( "MassMatrix", feVariable, dim, context->entryPoint_Register, MPI_COMM_WORLD );
-	massMatrixForceTerm = LumpedMassMatrixForceTerm_New( "forceTerm", massMatrix, swarm );
-	EP_ReplaceAll( massMatrix->assembleForceVector, ForceVector_GlobalAssembly_General );
-	ForceTerm_SetAssembleElementFunction( massMatrixForceTerm, _LumpedMassMatrixForceTerm_AssembleElement_General );
-
-	/* Build */
-	Stg_Component_Build( feMesh, context, False );
-	Variable_Register_BuildAll(variableRegister);
-	Stg_Component_Build( wallVC, context, False );
-	Stg_Component_Build( dofs, context, False);
-	Stg_Component_Build( feVariable, context, False );
-	FeEquationNumber_BuildLocationMatrix( feVariable->eqNum );
-	Stg_Component_Build( singleCellLayout,    context, False );
-	Stg_Component_Build( gaussParticleLayout, context, False );
-	Stg_Component_Build( swarm,               context, False );
-	Stg_Component_Build( massMatrix,          context, False );
-
-	/* Initialise */
-	Stg_Component_Initialise( feMesh,     context, False );
-	Stg_Component_Initialise( feVariable, context, False );
-	Stg_Component_Initialise( swarm,      context, False );
-	Stg_Component_Initialise( massMatrix, context, False );
-
-	/* Assemble */
-	ForceVector_Assemble( massMatrix );
-
-	/* Print out vector */
-	//Vector_View( massMatrix->vector, outputStream );
-
-	/* Try out optimised one */
-	//Vector_Zero( massMatrix->vector );
-	VecSet( massMatrix->vector, 0.0 );
-
-	/* Assemble */
-	ForceTerm_SetAssembleElementFunction( massMatrixForceTerm, _LumpedMassMatrixForceTerm_AssembleElement_Box );
-	ForceVector_Assemble( massMatrix );
-
-	/* Print out vector */
-	//Vector_View( massMatrix->vector, outputStream );	
-
-	/* Destroy stuff */
-	Stg_Class_Delete( massMatrix );
-	Stg_Class_Delete( massMatrixForceTerm );
-	Stg_Class_Delete( fV_Register );
-	Stg_Class_Delete( wallVC );
-	Stg_Class_Delete( feMesh );
-	Stg_Class_Delete( elementType_Register );
-	Stg_Class_Delete( extensionMgr_Register );
-	Stg_Class_Delete( dofs );
-	Stg_Class_Delete( dictionary );
-	
-	StgFEM_Discretisation_Finalise();
-	StgDomain_Finalise();
-	StGermain_Finalise();
-	
-	/* Close off MPI */
-	MPI_Finalize();
-	
-	return 0; /* success */
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testLumpedMassMatrix.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testLumpedMassMatrix.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,300 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: testLumpedMassMatrix.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "petsc.h"
+
+
+typedef struct Node Node;
+typedef struct Element Element;
+
+struct Node {
+	double phi;
+};
+
+struct Element {
+	__FiniteElement_Element
+};
+
+struct _Particle {
+	Coord coord;
+};
+
+
+FeMesh* buildFeMesh( unsigned nDims, unsigned* size, 
+		     double* minCrds, double* maxCrds, 
+		     ExtensionManager_Register* emReg, 
+		     ElementType_Register* etReg )
+{
+	CartesianGenerator*	gen;
+	FeMesh*			feMesh;
+	unsigned		maxDecomp[3] = {0, 1, 1};
+
+	gen = CartesianGenerator_New( "", NULL );
+	gen->shadowDepth = 0;
+	CartesianGenerator_SetDimSize( gen, nDims );
+	CartesianGenerator_SetTopologyParams( gen, size, 0, NULL, maxDecomp );
+	CartesianGenerator_SetGeometryParams( gen, minCrds, maxCrds );
+
+	feMesh = FeMesh_New( "", NULL );
+	Mesh_SetExtensionManagerRegister( feMesh, emReg );
+	Mesh_SetGenerator( feMesh, gen );
+	FeMesh_SetElementFamily( feMesh, "linear" );
+
+	Mesh_SetTopologyDataSize( feMesh, MT_VERTEX, sizeof(Node) );
+	Mesh_SetTopologyDataSize( feMesh, nDims, sizeof(Element) );
+
+	Stg_Component_Build( feMesh, NULL, False );
+	Stg_Component_Initialise( feMesh, NULL, False );
+
+	return feMesh;
+}
+
+
+int main( int argc, char* argv[] ) {
+	MPI_Comm                   CommWorld;
+	int                        rank;
+	int                        numProcessors;
+	int                        procToWatch;
+	Dictionary*                dictionary;
+	Dictionary_Entry_Value*    currBC;
+	Dictionary_Entry_Value*	   bcList;
+
+	unsigned	nDims = 2;
+	unsigned	meshSize[3] = {2, 2, 0};
+	double		minCrds[3] = {0.0, 0.0, 0.0};
+	double		maxCrds[3] = {1.2, 1.2, 1.2};
+	FeMesh*		feMesh;
+	unsigned	nDomainVerts;
+	Node*		nodes;
+
+	DofLayout*                 dofs;
+	ElementType_Register*      elementType_Register;
+	ExtensionManager_Register* extensionMgr_Register;
+	WallVC*                    wallVC;
+	FieldVariable_Register*    fV_Register;
+	FeVariable*                feVariable;
+	Variable_Register*         variableRegister;
+	FiniteElementContext*      context;
+	Index                      i;
+	Dimension_Index            dim;
+	Stream*	                   stream;
+	/* Swarm Stuff */
+	CellLayout*                singleCellLayout;
+	ParticleLayout*            gaussParticleLayout;
+	Swarm*                     swarm;
+	unsigned int               dimExists[]     = { True, True, False };
+	/* Mass Matrix Stuff */
+	ForceVector*               massMatrix;
+	LumpedMassMatrixForceTerm* massMatrixForceTerm;
+	/* Stream Stuff */
+	Stream*                    outputStream;
+	Particle_InCellIndex       particlesPerDim[] = {2,2,2};
+	
+	/* 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 );
+	
+	StGermain_Init( &argc, &argv );
+	StgDomain_Init( &argc, &argv );
+	StgFEM_Discretisation_Init( &argc, &argv );
+	//StgFEM_SLE_LinearAlgebra_Init( &argc, &argv );
+	StgFEM_SLE_SystemSetup_Init( &argc, &argv );
+	StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Init( &argc, &argv );
+	MPI_Barrier( CommWorld ); /* Ensures copyright info always come first in output */
+	
+	stream = Journal_Register( Info_Type, (Name)"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, (Dictionary_Entry_Key)"outputPath", Dictionary_Entry_Value_FromString( "./output" )  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"rank", Dictionary_Entry_Value_FromUnsignedInt( rank )  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"numProcessors", Dictionary_Entry_Value_FromUnsignedInt( numProcessors )  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"gaussParticlesX", Dictionary_Entry_Value_FromUnsignedInt( 2 )  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"gaussParticlesY", Dictionary_Entry_Value_FromUnsignedInt( 2 ) );
+	
+	bcList = Dictionary_Entry_Value_NewList();
+	currBC = Dictionary_Entry_Value_NewStruct( );
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"name", Dictionary_Entry_Value_FromString( "phi" )  );
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"type", Dictionary_Entry_Value_FromString( "double" )  );
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"value", Dictionary_Entry_Value_FromDouble( -1.0f )  );
+	Dictionary_Entry_Value_AddElement( bcList, currBC );
+	currBC = Dictionary_Entry_Value_NewStruct();
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"wall", Dictionary_Entry_Value_FromString( "left" )  );
+	Dictionary_Entry_Value_AddMember( currBC, (Dictionary_Entry_Key)"variables", bcList  );
+	Dictionary_Add( dictionary, (Dictionary_Entry_Key)"boundaryCondition", currBC  );
+
+	/* Create Context */
+	context = FiniteElementContext_New( "context", 0,0, MPI_COMM_WORLD, dictionary );
+	dim = context->dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "dim", 2 );
+	Journal_Enable_TypedStream( DebugStream_Type, True );
+	Stream_SetLevelBranch( StgFEM_Debug, 3 );
+	Stream_EnableBranch( StgFEM_Debug, True );
+	
+	/* create the layout, dof and mesh to use */
+	extensionMgr_Register = ExtensionManager_Register_New();
+	elementType_Register = ElementType_Register_New("elementTypeRegister");
+	ElementType_Register_Add( elementType_Register, (ElementType*)ConstantElementType_New("constant") );
+	ElementType_Register_Add( elementType_Register, (ElementType*)BilinearElementType_New("bilinear") );
+	ElementType_Register_Add( elementType_Register, (ElementType*)TrilinearElementType_New("trilinear") );
+
+	feMesh = buildFeMesh( nDims, meshSize, minCrds, maxCrds, 
+			      extensionMgr_Register, elementType_Register );
+	nDomainVerts = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+	nodes = Mesh_GetTopologyData( feMesh, MT_VERTEX );
+	
+	/* Create variable register */
+	variableRegister = Variable_Register_New();
+	
+	/* Create variables */
+	Variable_NewScalar( 
+		"phi", 
+		Variable_DataType_Double, 
+		&nDomainVerts, 
+		NULL,
+		(void**)&nodes, 
+		variableRegister );
+
+	dofs = DofLayout_New( "dofLayout", variableRegister, Mesh_GetDomainSize( feMesh, MT_VERTEX ), NULL );
+	for (i = 0; i < Mesh_GetDomainSize( feMesh, MT_VERTEX ); i++)
+		DofLayout_AddDof_ByVarName(dofs, "phi", i);
+	
+	wallVC = WallVC_New( "WallVC", "boundaryCondition", variableRegister, NULL, dictionary, feMesh );
+
+	/* Create the finite element field variable*/
+	fV_Register = FieldVariable_Register_New();
+	feVariable = FeVariable_New( "phi", feMesh, NULL, dofs, wallVC, NULL, NULL, context->dim,
+		False, False, False, fV_Register );
+	
+	/* Create Stream */
+	outputStream = Journal_Register( InfoStream_Type, (Name)CURR_MODULE_NAME  );
+	Stream_RedirectFile( outputStream, "output/output.dat" );
+
+	/* Create Swarm */
+	if ( 3 == dim ) 
+		dimExists[K_AXIS] = True;
+	singleCellLayout    = (CellLayout*)SingleCellLayout_New( "SingleCellLayout", dimExists, NULL, NULL );
+	gaussParticleLayout = (ParticleLayout*)GaussParticleLayout_New( "GaussParticleLayout", dim, particlesPerDim );
+	swarm = Swarm_New( "gaussSwarm", singleCellLayout, gaussParticleLayout, dim,
+		sizeof(IntegrationPoint), context->extensionMgr_Register, context->variable_Register, MPI_COMM_WORLD, NULL );
+	
+	/* Lumping of Mass Matrix */
+	massMatrix = ForceVector_New( "MassMatrix", feVariable, dim, context->entryPoint_Register, MPI_COMM_WORLD );
+	massMatrixForceTerm = LumpedMassMatrixForceTerm_New( "forceTerm", massMatrix, swarm );
+	EP_ReplaceAll( massMatrix->assembleForceVector, ForceVector_GlobalAssembly_General );
+	ForceTerm_SetAssembleElementFunction( massMatrixForceTerm, _LumpedMassMatrixForceTerm_AssembleElement_General );
+
+	/* Build */
+	Stg_Component_Build( feMesh, context, False );
+	Variable_Register_BuildAll(variableRegister);
+	Stg_Component_Build( wallVC, context, False );
+	Stg_Component_Build( dofs, context, False);
+	Stg_Component_Build( feVariable, context, False );
+	FeEquationNumber_BuildLocationMatrix( feVariable->eqNum );
+	Stg_Component_Build( singleCellLayout,    context, False );
+	Stg_Component_Build( gaussParticleLayout, context, False );
+	Stg_Component_Build( swarm,               context, False );
+	Stg_Component_Build( massMatrix,          context, False );
+
+	/* Initialise */
+	Stg_Component_Initialise( feMesh,     context, False );
+	Stg_Component_Initialise( feVariable, context, False );
+	Stg_Component_Initialise( swarm,      context, False );
+	Stg_Component_Initialise( massMatrix, context, False );
+
+	/* Assemble */
+	ForceVector_Assemble( massMatrix );
+
+	/* Print out vector */
+	//Vector_View( massMatrix->vector, outputStream );
+
+	/* Try out optimised one */
+	//Vector_Zero( massMatrix->vector );
+	VecSet( massMatrix->vector, 0.0 );
+
+	/* Assemble */
+	ForceTerm_SetAssembleElementFunction( massMatrixForceTerm, _LumpedMassMatrixForceTerm_AssembleElement_Box );
+	ForceVector_Assemble( massMatrix );
+
+	/* Print out vector */
+	//Vector_View( massMatrix->vector, outputStream );	
+
+	/* Destroy stuff */
+	Stg_Class_Delete( massMatrix );
+	Stg_Class_Delete( massMatrixForceTerm );
+	Stg_Class_Delete( fV_Register );
+	Stg_Class_Delete( wallVC );
+	Stg_Class_Delete( feMesh );
+	Stg_Class_Delete( elementType_Register );
+	Stg_Class_Delete( extensionMgr_Register );
+	Stg_Class_Delete( dofs );
+	Stg_Class_Delete( dictionary );
+	
+	StgFEM_Discretisation_Finalise();
+	StgDomain_Finalise();
+	StGermain_Finalise();
+	
+	/* Close off MPI */
+	MPI_Finalize();
+	
+	return 0; /* success */
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testUpwindXi.c
--- a/SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testUpwindXi.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: testUpwindXi.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
-
-int main( int argc, char* argv[] ) {
-	Stream* dataStream;
-	double  minPercletNumber = -15.0;
-	double  maxPercletNumber = 15.0;
-	double  dPerceltNumber = 0.5;
-	double  perceltNumber;
-	char*   dataFileName = "./output/output.dat";
-
-	MPI_Init( &argc, &argv );
-	StGermain_Init( &argc, &argv );
-
-	/* Create Data File */
-	dataStream    = Journal_Register( Info_Type, (Name)"DataStream"  );
-	Stream_RedirectFile( dataStream, dataFileName );
-
-	Journal_Printf( dataStream, "# File to compare code with Brooks, Hughes 1982 - Fig 3.3\n");
-	Journal_Printf( dataStream, "# Integration rule for the optimal upwind scheme, doubly asymptotic approximation and critical approximation.\n");
-	Journal_Printf( dataStream, "# Plot using line:\n");
-	Journal_Printf( dataStream, "# plot \"%s\" using 1:2 title \"Exact\" with line, ", dataFileName );
-	Journal_Printf( dataStream, "\"%s\" using 1:3 title \"DoublyAsymptoticAssumption\" with line, ", dataFileName );
-	Journal_Printf( dataStream, "\"%s\" using 1:4 title \"CriticalAssumption\" with line\n", dataFileName );
-
-	Journal_Printf( dataStream, "# Perclet Number \t Exact \t DoublyAsymptoticAssumption \t CriticalAssumption\n" );
-	for ( perceltNumber = minPercletNumber ; perceltNumber < maxPercletNumber ; perceltNumber += dPerceltNumber )
-		Journal_Printf( dataStream, "%0.3g \t\t %0.3g \t\t %0.3g \t\t %0.3g\n", 
-				perceltNumber, 
-				AdvDiffResidualForceTerm_UpwindXiExact( NULL, perceltNumber),
-				AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption( NULL, perceltNumber),
-				AdvDiffResidualForceTerm_UpwindXiCriticalAssumption( NULL, perceltNumber) );
-
-	StGermain_Finalise();
-	MPI_Finalize();
-
-	return EXIT_SUCCESS;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testUpwindXi.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/AdvectionDiffusion/tests/oldTesting/testUpwindXi.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,86 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: testUpwindXi.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
+
+int main( int argc, char* argv[] ) {
+	Stream* dataStream;
+	double  minPercletNumber = -15.0;
+	double  maxPercletNumber = 15.0;
+	double  dPerceltNumber = 0.5;
+	double  perceltNumber;
+	char*   dataFileName = "./output/output.dat";
+
+	MPI_Init( &argc, &argv );
+	StGermain_Init( &argc, &argv );
+
+	/* Create Data File */
+	dataStream    = Journal_Register( Info_Type, (Name)"DataStream"  );
+	Stream_RedirectFile( dataStream, dataFileName );
+
+	Journal_Printf( dataStream, "# File to compare code with Brooks, Hughes 1982 - Fig 3.3\n");
+	Journal_Printf( dataStream, "# Integration rule for the optimal upwind scheme, doubly asymptotic approximation and critical approximation.\n");
+	Journal_Printf( dataStream, "# Plot using line:\n");
+	Journal_Printf( dataStream, "# plot \"%s\" using 1:2 title \"Exact\" with line, ", dataFileName );
+	Journal_Printf( dataStream, "\"%s\" using 1:3 title \"DoublyAsymptoticAssumption\" with line, ", dataFileName );
+	Journal_Printf( dataStream, "\"%s\" using 1:4 title \"CriticalAssumption\" with line\n", dataFileName );
+
+	Journal_Printf( dataStream, "# Perclet Number \t Exact \t DoublyAsymptoticAssumption \t CriticalAssumption\n" );
+	for ( perceltNumber = minPercletNumber ; perceltNumber < maxPercletNumber ; perceltNumber += dPerceltNumber )
+		Journal_Printf( dataStream, "%0.3g \t\t %0.3g \t\t %0.3g \t\t %0.3g\n", 
+				perceltNumber, 
+				AdvDiffResidualForceTerm_UpwindXiExact( NULL, perceltNumber),
+				AdvDiffResidualForceTerm_UpwindXiDoublyAsymptoticAssumption( NULL, perceltNumber),
+				AdvDiffResidualForceTerm_UpwindXiCriticalAssumption( NULL, perceltNumber) );
+
+	StGermain_Finalise();
+	MPI_Finalize();
+
+	return EXIT_SUCCESS;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/Energy/src/Energy_SLE.c
--- a/SLE/ProvidedSystems/Energy/src/Energy_SLE.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Energy_SLE.c 999 2008-01-09 04:13:42Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Energy_SLE.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type Energy_SLE_Type = "Energy_SLE";
-
-Energy_SLE* Energy_SLE_New( 
-	Name							name,
-	SLE_Solver*					solver,
-	FiniteElementContext*	context,
-	Bool							isNonLinear,
-	double						nonLinearTolerance,
-	Iteration_Index			nonLinearMaxIterations,
-	Bool							killNonConvergent,
-	EntryPoint_Register*		entryPoint_Register,
-	MPI_Comm						comm,
-	StiffnessMatrix*			stiffMat,
-	SolutionVector*			solutionVec,
-	ForceVector*				fVector )
-{
-  Energy_SLE* self = (Energy_SLE*)_Energy_SLE_DefaultNew( name );
-
-	self->isConstructed = True;
-	_SystemLinearEquations_Init( self, solver, NULL, context, False, isNonLinear, nonLinearTolerance,
-		nonLinearMaxIterations, killNonConvergent, 1, "", "", entryPoint_Register, comm );
-	_Energy_SLE_Init( self, stiffMat, solutionVec, fVector );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-Energy_SLE* _Energy_SLE_New(  ENERGY_SLE_DEFARGS  )
-{
-	Energy_SLE* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Energy_SLE) );
-	self = (Energy_SLE*) _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_PASSARGS  );
-	
-	/* Virtual info */
-	return self;
-}
-
-void _Energy_SLE_Init( void* sle, StiffnessMatrix* stiffMat, SolutionVector* solutionVec, ForceVector* fVector ) {
-	Energy_SLE* self = (Energy_SLE*)sle;
-
-	self->stiffMat		= stiffMat;
-	self->solutionVec = solutionVec;
-	self->fVector     = fVector;
-
-	SystemLinearEquations_AddStiffnessMatrix( self, stiffMat );
-	SystemLinearEquations_AddSolutionVector( self, solutionVec );
-	SystemLinearEquations_AddForceVector( self, fVector );
-}
-
-void _Energy_SLE_Print( void* sle, Stream* stream ) {
-	Energy_SLE* self = (Energy_SLE*)sle;
-	
-	/* General info */
-	Journal_Printf( stream, "Energy_SLE (ptr): %p\n", self );
-	_SystemLinearEquations_Print( self, stream );
-
-	Journal_PrintString( stream, self->stiffMat->name );
-	Journal_PrintString( stream, self->solutionVec->name );
-	Journal_PrintString( stream, self->fVector->name );
-
-	Stg_Class_Print( self->solver, stream );
-}
-
-void* _Energy_SLE_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                            _sizeOfSelf = sizeof(Energy_SLE);
-	Type                                                                    type = Energy_SLE_Type;
-	Stg_Class_DeleteFunction*                                            _delete = _SystemLinearEquations_Delete;
-	Stg_Class_PrintFunction*                                              _print = _Energy_SLE_Print;
-	Stg_Class_CopyFunction*                                                _copy = _SystemLinearEquations_Copy;
-	Stg_Component_DefaultConstructorFunction*                _defaultConstructor = _Energy_SLE_DefaultNew;
-	Stg_Component_ConstructFunction*                                  _construct = _Energy_SLE_AssignFromXML;
-	Stg_Component_BuildFunction*                                          _build = _SystemLinearEquations_Build;
-	Stg_Component_InitialiseFunction*                                _initialise = _SystemLinearEquations_Initialise;
-	Stg_Component_ExecuteFunction*                                      _execute = _SystemLinearEquations_Execute;
-	Stg_Component_DestroyFunction*                                      _destroy = _SystemLinearEquations_Destroy;
-	SystemLinearEquations_LM_SetupFunction*                            _LM_Setup = _SystemLinearEquations_LM_Setup;
-	SystemLinearEquations_MatrixSetupFunction*                      _matrixSetup = _SystemLinearEquations_MatrixSetup;
-	SystemLinearEquations_VectorSetupFunction*                      _vectorSetup = _SystemLinearEquations_VectorSetup;
-	SystemLinearEquations_UpdateSolutionOntoNodesFunc*  _updateSolutionOntoNodes = _SystemLinearEquations_UpdateSolutionOntoNodes;
-	SystemLinearEquations_MG_SelectStiffMatsFunc*             _mgSelectStiffMats = _SystemLinearEquations_MG_SelectStiffMats;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_Energy_SLE_New(  ENERGY_SLE_PASSARGS  );
-}
-
-void _Energy_SLE_AssignFromXML( void* sle, Stg_ComponentFactory* cf, void* data ){
-	Energy_SLE*      self = (Energy_SLE*)sle;
-	StiffnessMatrix* stiffMat;
-	SolutionVector*  solutionVec;
-	ForceVector*     fVector;
-
-	/* Construct Parent */
-	_SystemLinearEquations_AssignFromXML( self, cf, data );
-
-	stiffMat    =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)StiffnessMatrix_Type, StiffnessMatrix, True, data   ) ;
-	solutionVec =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)SolutionVector_Type, SolutionVector, True, data   ) ;
-	fVector     =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)ForceVector_Type, ForceVector, True, data   ) ;
-
-	_Energy_SLE_Init( self, stiffMat, solutionVec, fVector );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/Energy/src/Energy_SLE.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/Energy/src/Energy_SLE.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,162 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Energy_SLE.c 999 2008-01-09 04:13:42Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Energy_SLE.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type Energy_SLE_Type = "Energy_SLE";
+
+Energy_SLE* Energy_SLE_New( 
+	Name							name,
+	SLE_Solver*					solver,
+	FiniteElementContext*	context,
+	Bool							isNonLinear,
+	double						nonLinearTolerance,
+	Iteration_Index			nonLinearMaxIterations,
+	Bool							killNonConvergent,
+	EntryPoint_Register*		entryPoint_Register,
+	MPI_Comm						comm,
+	StiffnessMatrix*			stiffMat,
+	SolutionVector*			solutionVec,
+	ForceVector*				fVector )
+{
+  Energy_SLE* self = (Energy_SLE*)_Energy_SLE_DefaultNew( name );
+
+	self->isConstructed = True;
+	_SystemLinearEquations_Init( self, solver, NULL, context, False, isNonLinear, nonLinearTolerance,
+		nonLinearMaxIterations, killNonConvergent, 1, "", "", entryPoint_Register, comm );
+	_Energy_SLE_Init( self, stiffMat, solutionVec, fVector );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+Energy_SLE* _Energy_SLE_New(  ENERGY_SLE_DEFARGS  )
+{
+	Energy_SLE* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Energy_SLE) );
+	self = (Energy_SLE*) _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_PASSARGS  );
+	
+	/* Virtual info */
+	return self;
+}
+
+void _Energy_SLE_Init( void* sle, StiffnessMatrix* stiffMat, SolutionVector* solutionVec, ForceVector* fVector ) {
+	Energy_SLE* self = (Energy_SLE*)sle;
+
+	self->stiffMat		= stiffMat;
+	self->solutionVec = solutionVec;
+	self->fVector     = fVector;
+
+	SystemLinearEquations_AddStiffnessMatrix( self, stiffMat );
+	SystemLinearEquations_AddSolutionVector( self, solutionVec );
+	SystemLinearEquations_AddForceVector( self, fVector );
+}
+
+void _Energy_SLE_Print( void* sle, Stream* stream ) {
+	Energy_SLE* self = (Energy_SLE*)sle;
+	
+	/* General info */
+	Journal_Printf( stream, "Energy_SLE (ptr): %p\n", self );
+	_SystemLinearEquations_Print( self, stream );
+
+	Journal_PrintString( stream, self->stiffMat->name );
+	Journal_PrintString( stream, self->solutionVec->name );
+	Journal_PrintString( stream, self->fVector->name );
+
+	Stg_Class_Print( self->solver, stream );
+}
+
+void* _Energy_SLE_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                            _sizeOfSelf = sizeof(Energy_SLE);
+	Type                                                                    type = Energy_SLE_Type;
+	Stg_Class_DeleteFunction*                                            _delete = _SystemLinearEquations_Delete;
+	Stg_Class_PrintFunction*                                              _print = _Energy_SLE_Print;
+	Stg_Class_CopyFunction*                                                _copy = _SystemLinearEquations_Copy;
+	Stg_Component_DefaultConstructorFunction*                _defaultConstructor = _Energy_SLE_DefaultNew;
+	Stg_Component_ConstructFunction*                                  _construct = _Energy_SLE_AssignFromXML;
+	Stg_Component_BuildFunction*                                          _build = _SystemLinearEquations_Build;
+	Stg_Component_InitialiseFunction*                                _initialise = _SystemLinearEquations_Initialise;
+	Stg_Component_ExecuteFunction*                                      _execute = _SystemLinearEquations_Execute;
+	Stg_Component_DestroyFunction*                                      _destroy = _SystemLinearEquations_Destroy;
+	SystemLinearEquations_LM_SetupFunction*                            _LM_Setup = _SystemLinearEquations_LM_Setup;
+	SystemLinearEquations_MatrixSetupFunction*                      _matrixSetup = _SystemLinearEquations_MatrixSetup;
+	SystemLinearEquations_VectorSetupFunction*                      _vectorSetup = _SystemLinearEquations_VectorSetup;
+	SystemLinearEquations_UpdateSolutionOntoNodesFunc*  _updateSolutionOntoNodes = _SystemLinearEquations_UpdateSolutionOntoNodes;
+	SystemLinearEquations_MG_SelectStiffMatsFunc*             _mgSelectStiffMats = _SystemLinearEquations_MG_SelectStiffMats;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_Energy_SLE_New(  ENERGY_SLE_PASSARGS  );
+}
+
+void _Energy_SLE_AssignFromXML( void* sle, Stg_ComponentFactory* cf, void* data ){
+	Energy_SLE*      self = (Energy_SLE*)sle;
+	StiffnessMatrix* stiffMat;
+	SolutionVector*  solutionVec;
+	ForceVector*     fVector;
+
+	/* Construct Parent */
+	_SystemLinearEquations_AssignFromXML( self, cf, data );
+
+	stiffMat    =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)StiffnessMatrix_Type, StiffnessMatrix, True, data   ) ;
+	solutionVec =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)SolutionVector_Type, SolutionVector, True, data   ) ;
+	fVector     =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)ForceVector_Type, ForceVector, True, data   ) ;
+
+	_Energy_SLE_Init( self, stiffMat, solutionVec, fVector );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/Energy/src/Energy_SLE_Solver.c
--- a/SLE/ProvidedSystems/Energy/src/Energy_SLE_Solver.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,299 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Energy_SLE_Solver.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Energy_SLE_Solver.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type Energy_SLE_Solver_Type = "Energy_SLE_Solver";
-
-PetscTruth Energy_SLE_HasNullSpace( Mat A );
-
-void* Energy_SLE_Solver_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(Energy_SLE_Solver);
-	Type                                                      type = Energy_SLE_Solver_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Energy_SLE_Solver_Delete;
-	Stg_Class_PrintFunction*                                _print = _Energy_SLE_Solver_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Energy_SLE_Solver_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = Energy_SLE_Solver_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _Energy_SLE_Solver_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Energy_SLE_Solver_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Energy_SLE_Solver_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _SLE_Solver_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _SLE_Solver_Destroy;
-	SLE_Solver_SolverSetupFunction*                   _solverSetup = _Energy_SLE_Solver_SolverSetup;
-	SLE_Solver_SolveFunction*                               _solve = _Energy_SLE_Solver_Solve;
-	SLE_Solver_GetResidualFunc*                       _getResidual = _Energy_SLE_GetResidual;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Energy_SLE_Solver_New(  ENERGY_SLE_SOLVER_PASSARGS  );
-}
-
-Energy_SLE_Solver* Energy_SLE_Solver_New( Name name, Bool useStatSolve, int statReps ) {
-	Energy_SLE_Solver* self = (Energy_SLE_Solver*) Energy_SLE_Solver_DefaultNew( name );
-
-	Energy_SLE_Solver_InitAll( self, useStatSolve, statReps ) ;
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-Energy_SLE_Solver* _Energy_SLE_Solver_New(  ENERGY_SLE_SOLVER_DEFARGS  )
-{
-	Energy_SLE_Solver* self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Energy_SLE_Solver) );
-	self = (Energy_SLE_Solver*) _SLE_Solver_New(  SLE_SOLVER_PASSARGS  );
-	
-	/* Virtual info */
-	return self;
-}
-	
-/* Initialisation implementation */
-void _Energy_SLE_Solver_Init( Energy_SLE_Solver* self ) {
-	self->isConstructed = True;
-	self->residual = NULL;
-	//self->matrixSolver = NULL;
-	self->matrixSolver = PETSC_NULL;
-}
-void Energy_SLE_Solver_InitAll( Energy_SLE_Solver* solver, Bool useStatSolve, int statReps ) {
-	Energy_SLE_Solver* self = (Energy_SLE_Solver*)solver;
-
-	SLE_Solver_InitAll( self, useStatSolve, statReps );
-}
-
-void _Energy_SLE_Solver_Delete( void* sle ) {
-	Energy_SLE_Solver* self = (Energy_SLE_Solver*)sle;
-
-	//FreeObject( self->matrixSolver );
-	KSPDestroy( self->matrixSolver );
-
-	if( self->residual != PETSC_NULL ) {
-		//FreeObject( self->residual );
-		VecDestroy( self->residual );
-	}
-}
-
-void _Energy_SLE_Solver_Print( void* solver, Stream* stream ) {
-	Energy_SLE_Solver* self = (Energy_SLE_Solver*)solver;
-	
-	/* Set the Journal for printing informations */
-	Stream* standard_SLE_SolverStream = stream;
-	
-	/* General info */
-	Journal_Printf( standard_SLE_SolverStream, "Energy_SLE_Solver (ptr): %p\n", self );
-
-	/* other info */
-	Journal_Printf( standard_SLE_SolverStream, "\tmatrixSolver (ptr): %p", self->matrixSolver );
-}
-
-
-void* _Energy_SLE_Solver_Copy( const void* standardSleSolver, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	Energy_SLE_Solver*	self = (Energy_SLE_Solver*)standardSleSolver;
-	Energy_SLE_Solver*	newEnergySleSolver;
-
-	newEnergySleSolver = (Energy_SLE_Solver*)_SLE_Solver_Copy( self, dest, deep, nameExt, ptrMap );
-	
-	newEnergySleSolver->matrixSolver = self->matrixSolver;
-	
-	return (void*)newEnergySleSolver;
-}
-
-void _Energy_SLE_Solver_AssignFromXML( void* sleSolver, Stg_ComponentFactory* cf, void* data ) {
-	Energy_SLE_Solver	*self = (Energy_SLE_Solver*)sleSolver;
-
-	assert( self && Stg_CheckType( self, Energy_SLE_Solver ) );
-	assert( cf && Stg_CheckType( cf, Stg_ComponentFactory ) );
-
-	_SLE_Solver_AssignFromXML( self, cf, data );
-}
-
-/* Build */
-void _Energy_SLE_Solver_Build( void* sleSolver, void* standardSLE ) {
-	Energy_SLE_Solver*	self = (Energy_SLE_Solver*)sleSolver;
-	SystemLinearEquations*	sle = (SystemLinearEquations*) standardSLE;
-	StiffnessMatrix*	stiffMat = (StiffnessMatrix*)sle->stiffnessMatrices->data[0];
-
-	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
-	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
-	Journal_DPrintf( self->debug, "building a standard L.A. solver for the \"%s\" matrix.\n", stiffMat->name );
-
-	Stg_Component_Build( stiffMat, standardSLE, False );
-
-	if( self->matrixSolver == PETSC_NULL )
-		KSPCreate( sle->comm, &self->matrixSolver );
-
-	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
-}
-
-
-void _Energy_SLE_Solver_Initialise( void* sleSolver, void* standardSLE ) {
-	Energy_SLE_Solver*	self = (Energy_SLE_Solver*)sleSolver;
-	SystemLinearEquations*	sle = (SystemLinearEquations*) standardSLE;
-	
-	/* Initialise parent. */
-	_SLE_Solver_Initialise( self, sle );
-}
-
-void _Energy_SLE_Solver_Execute( void* sleSolver, void* data ) {
-}
-	
-void _Energy_SLE_Solver_Destroy( void* sleSolver, void* data ) {
-}
-
-void _Energy_SLE_Solver_SolverSetup( void* sleSolver, void* standardSLE ) {
-	Energy_SLE_Solver* self = (Energy_SLE_Solver*)sleSolver;
-	SystemLinearEquations* sle = (SystemLinearEquations*) standardSLE;
-	StiffnessMatrix*	stiffMat = (StiffnessMatrix*)sle->stiffnessMatrices->data[0];
-	
-	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
-	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
-	
-	Journal_DPrintf( self->debug, "Initialising the L.A. solver for the \"%s\" matrix.\n", stiffMat->name );
-	KSPSetOperators( self->matrixSolver, stiffMat->matrix, stiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
-	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
-	
-	if( self->maxIterations > 0 ) {
-		KSPSetTolerances( self->matrixSolver, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, self->maxIterations );
-	}
-
-	VecDuplicate( ((ForceVector**)sle->forceVectors->data)[0]->vector, &self->residual );
-}
-
-
-void _Energy_SLE_Solver_Solve( void* sleSolver, void* standardSLE ) {
-	Energy_SLE_Solver*     self       = (Energy_SLE_Solver*)sleSolver;
-	SystemLinearEquations* sle        = (SystemLinearEquations*) standardSLE;
-	Iteration_Index        iterations;
-        PetscTruth isNull;
-        MatNullSpace nsp;
-
-	
-	Journal_DPrintf( self->debug, "In %s - for standard SLE solver\n", __func__ );
-	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
-	
-	if ( (sle->stiffnessMatrices->count > 1 ) ||
-		(sle->forceVectors->count > 1 ) )
-	{
-		Stream* warning = Stream_RegisterChild( StgFEM_Warning, self->type );
-		Journal_Printf( warning, "Warning: Energy solver unable to solve more that one matrix/vector.\n" );
-	}
-
-	if ( sle->solutionVectors->count > 1 ) {
-		Stream* warning = Stream_RegisterChild( StgFEM_Warning, self->type );
-		Journal_Printf( warning, "Warning: More than 1 solution vector provided to standard sle. Ignoring second and subsequent"
-			" solution vectors.\n" );
-	}
-
-        isNull = Energy_SLE_HasNullSpace(((StiffnessMatrix**)sle->stiffnessMatrices->data)[0]->matrix);
-        if(isNull) {
-            MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_TRUE, 0, PETSC_NULL, &nsp);
-            KSPSetNullSpace(self->matrixSolver, nsp);
-        }
-
-	KSPSolve( self->matrixSolver,
-		    ((ForceVector*) sle->forceVectors->data[0])->vector, 
-		    ((SolutionVector*) sle->solutionVectors->data[0])->vector );
-	KSPGetIterationNumber( self->matrixSolver, (PetscInt*)(&iterations) );
-
-	Journal_DPrintf( self->debug, "Solved after %u iterations.\n", iterations );
-	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
-	
-	/* calculate the residual */
-	/* TODO: need to make this optional */
-	MatMult( ((StiffnessMatrix**)sle->stiffnessMatrices->data)[0]->matrix, 
-		 ((SolutionVector**)sle->solutionVectors->data)[0]->vector, 
-		 self->residual );
-	VecAYPX( self->residual, -1.0, ((ForceVector**)sle->forceVectors->data)[0]->vector );
-
-        if(isNull)
-            MatNullSpaceDestroy(nsp);
-}
-
-
-Vec _Energy_SLE_GetResidual( void* sleSolver, Index fv_I ) {
-	Energy_SLE_Solver*	self = (Energy_SLE_Solver*)sleSolver;
-
-	return self->residual;
-}
-
-PetscTruth Energy_SLE_HasNullSpace( Mat A ) {
-    PetscInt N;
-    PetscScalar sum;
-    PetscReal nrm;
-    PetscTruth isNull;
-    Vec r, l;
-
-    MatGetVecs(A, &r, &l); /* l = A r */
-
-    VecGetSize(r, &N);
-    sum = 1.0/(PetscScalar)N;
-    VecSet(r, sum);
-
-    MatMult(A, r, l); /* {l} = [A] {r} */
-
-    VecNorm(l, NORM_2, &nrm);
-    if(nrm < 1.e-7)
-	isNull = PETSC_TRUE;
-    else
-	isNull = PETSC_FALSE;
-
-    VecDestroy(l);
-    VecDestroy(r);
-
-    return isNull;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/Energy/src/Energy_SLE_Solver.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/Energy/src/Energy_SLE_Solver.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,299 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Energy_SLE_Solver.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Energy_SLE_Solver.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type Energy_SLE_Solver_Type = "Energy_SLE_Solver";
+
+PetscTruth Energy_SLE_HasNullSpace( Mat A );
+
+void* Energy_SLE_Solver_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(Energy_SLE_Solver);
+	Type                                                      type = Energy_SLE_Solver_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Energy_SLE_Solver_Delete;
+	Stg_Class_PrintFunction*                                _print = _Energy_SLE_Solver_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Energy_SLE_Solver_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = Energy_SLE_Solver_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _Energy_SLE_Solver_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Energy_SLE_Solver_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Energy_SLE_Solver_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _SLE_Solver_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _SLE_Solver_Destroy;
+	SLE_Solver_SolverSetupFunction*                   _solverSetup = _Energy_SLE_Solver_SolverSetup;
+	SLE_Solver_SolveFunction*                               _solve = _Energy_SLE_Solver_Solve;
+	SLE_Solver_GetResidualFunc*                       _getResidual = _Energy_SLE_GetResidual;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Energy_SLE_Solver_New(  ENERGY_SLE_SOLVER_PASSARGS  );
+}
+
+Energy_SLE_Solver* Energy_SLE_Solver_New( Name name, Bool useStatSolve, int statReps ) {
+	Energy_SLE_Solver* self = (Energy_SLE_Solver*) Energy_SLE_Solver_DefaultNew( name );
+
+	Energy_SLE_Solver_InitAll( self, useStatSolve, statReps ) ;
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+Energy_SLE_Solver* _Energy_SLE_Solver_New(  ENERGY_SLE_SOLVER_DEFARGS  )
+{
+	Energy_SLE_Solver* self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Energy_SLE_Solver) );
+	self = (Energy_SLE_Solver*) _SLE_Solver_New(  SLE_SOLVER_PASSARGS  );
+	
+	/* Virtual info */
+	return self;
+}
+	
+/* Initialisation implementation */
+void _Energy_SLE_Solver_Init( Energy_SLE_Solver* self ) {
+	self->isConstructed = True;
+	self->residual = NULL;
+	//self->matrixSolver = NULL;
+	self->matrixSolver = PETSC_NULL;
+}
+void Energy_SLE_Solver_InitAll( Energy_SLE_Solver* solver, Bool useStatSolve, int statReps ) {
+	Energy_SLE_Solver* self = (Energy_SLE_Solver*)solver;
+
+	SLE_Solver_InitAll( self, useStatSolve, statReps );
+}
+
+void _Energy_SLE_Solver_Delete( void* sle ) {
+	Energy_SLE_Solver* self = (Energy_SLE_Solver*)sle;
+
+	//FreeObject( self->matrixSolver );
+	KSPDestroy( self->matrixSolver );
+
+	if( self->residual != PETSC_NULL ) {
+		//FreeObject( self->residual );
+		VecDestroy( self->residual );
+	}
+}
+
+void _Energy_SLE_Solver_Print( void* solver, Stream* stream ) {
+	Energy_SLE_Solver* self = (Energy_SLE_Solver*)solver;
+	
+	/* Set the Journal for printing informations */
+	Stream* standard_SLE_SolverStream = stream;
+	
+	/* General info */
+	Journal_Printf( standard_SLE_SolverStream, "Energy_SLE_Solver (ptr): %p\n", self );
+
+	/* other info */
+	Journal_Printf( standard_SLE_SolverStream, "\tmatrixSolver (ptr): %p", self->matrixSolver );
+}
+
+
+void* _Energy_SLE_Solver_Copy( const void* standardSleSolver, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	Energy_SLE_Solver*	self = (Energy_SLE_Solver*)standardSleSolver;
+	Energy_SLE_Solver*	newEnergySleSolver;
+
+	newEnergySleSolver = (Energy_SLE_Solver*)_SLE_Solver_Copy( self, dest, deep, nameExt, ptrMap );
+	
+	newEnergySleSolver->matrixSolver = self->matrixSolver;
+	
+	return (void*)newEnergySleSolver;
+}
+
+void _Energy_SLE_Solver_AssignFromXML( void* sleSolver, Stg_ComponentFactory* cf, void* data ) {
+	Energy_SLE_Solver	*self = (Energy_SLE_Solver*)sleSolver;
+
+	assert( self && Stg_CheckType( self, Energy_SLE_Solver ) );
+	assert( cf && Stg_CheckType( cf, Stg_ComponentFactory ) );
+
+	_SLE_Solver_AssignFromXML( self, cf, data );
+}
+
+/* Build */
+void _Energy_SLE_Solver_Build( void* sleSolver, void* standardSLE ) {
+	Energy_SLE_Solver*	self = (Energy_SLE_Solver*)sleSolver;
+	SystemLinearEquations*	sle = (SystemLinearEquations*) standardSLE;
+	StiffnessMatrix*	stiffMat = (StiffnessMatrix*)sle->stiffnessMatrices->data[0];
+
+	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
+	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
+	Journal_DPrintf( self->debug, "building a standard L.A. solver for the \"%s\" matrix.\n", stiffMat->name );
+
+	Stg_Component_Build( stiffMat, standardSLE, False );
+
+	if( self->matrixSolver == PETSC_NULL )
+		KSPCreate( sle->comm, &self->matrixSolver );
+
+	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
+}
+
+
+void _Energy_SLE_Solver_Initialise( void* sleSolver, void* standardSLE ) {
+	Energy_SLE_Solver*	self = (Energy_SLE_Solver*)sleSolver;
+	SystemLinearEquations*	sle = (SystemLinearEquations*) standardSLE;
+	
+	/* Initialise parent. */
+	_SLE_Solver_Initialise( self, sle );
+}
+
+void _Energy_SLE_Solver_Execute( void* sleSolver, void* data ) {
+}
+	
+void _Energy_SLE_Solver_Destroy( void* sleSolver, void* data ) {
+}
+
+void _Energy_SLE_Solver_SolverSetup( void* sleSolver, void* standardSLE ) {
+	Energy_SLE_Solver* self = (Energy_SLE_Solver*)sleSolver;
+	SystemLinearEquations* sle = (SystemLinearEquations*) standardSLE;
+	StiffnessMatrix*	stiffMat = (StiffnessMatrix*)sle->stiffnessMatrices->data[0];
+	
+	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
+	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
+	
+	Journal_DPrintf( self->debug, "Initialising the L.A. solver for the \"%s\" matrix.\n", stiffMat->name );
+	KSPSetOperators( self->matrixSolver, stiffMat->matrix, stiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
+	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
+	
+	if( self->maxIterations > 0 ) {
+		KSPSetTolerances( self->matrixSolver, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, self->maxIterations );
+	}
+
+	VecDuplicate( ((ForceVector**)sle->forceVectors->data)[0]->vector, &self->residual );
+}
+
+
+void _Energy_SLE_Solver_Solve( void* sleSolver, void* standardSLE ) {
+	Energy_SLE_Solver*     self       = (Energy_SLE_Solver*)sleSolver;
+	SystemLinearEquations* sle        = (SystemLinearEquations*) standardSLE;
+	Iteration_Index        iterations;
+        PetscTruth isNull;
+        MatNullSpace nsp;
+
+	
+	Journal_DPrintf( self->debug, "In %s - for standard SLE solver\n", __func__ );
+	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
+	
+	if ( (sle->stiffnessMatrices->count > 1 ) ||
+		(sle->forceVectors->count > 1 ) )
+	{
+		Stream* warning = Stream_RegisterChild( StgFEM_Warning, self->type );
+		Journal_Printf( warning, "Warning: Energy solver unable to solve more that one matrix/vector.\n" );
+	}
+
+	if ( sle->solutionVectors->count > 1 ) {
+		Stream* warning = Stream_RegisterChild( StgFEM_Warning, self->type );
+		Journal_Printf( warning, "Warning: More than 1 solution vector provided to standard sle. Ignoring second and subsequent"
+			" solution vectors.\n" );
+	}
+
+        isNull = Energy_SLE_HasNullSpace(((StiffnessMatrix**)sle->stiffnessMatrices->data)[0]->matrix);
+        if(isNull) {
+            MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_TRUE, 0, PETSC_NULL, &nsp);
+            KSPSetNullSpace(self->matrixSolver, nsp);
+        }
+
+	KSPSolve( self->matrixSolver,
+		    ((ForceVector*) sle->forceVectors->data[0])->vector, 
+		    ((SolutionVector*) sle->solutionVectors->data[0])->vector );
+	KSPGetIterationNumber( self->matrixSolver, (PetscInt*)(&iterations) );
+
+	Journal_DPrintf( self->debug, "Solved after %u iterations.\n", iterations );
+	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
+	
+	/* calculate the residual */
+	/* TODO: need to make this optional */
+	MatMult( ((StiffnessMatrix**)sle->stiffnessMatrices->data)[0]->matrix, 
+		 ((SolutionVector**)sle->solutionVectors->data)[0]->vector, 
+		 self->residual );
+	VecAYPX( self->residual, -1.0, ((ForceVector**)sle->forceVectors->data)[0]->vector );
+
+        if(isNull)
+            MatNullSpaceDestroy(nsp);
+}
+
+
+Vec _Energy_SLE_GetResidual( void* sleSolver, Index fv_I ) {
+	Energy_SLE_Solver*	self = (Energy_SLE_Solver*)sleSolver;
+
+	return self->residual;
+}
+
+PetscTruth Energy_SLE_HasNullSpace( Mat A ) {
+    PetscInt N;
+    PetscScalar sum;
+    PetscReal nrm;
+    PetscTruth isNull;
+    Vec r, l;
+
+    MatGetVecs(A, &r, &l); /* l = A r */
+
+    VecGetSize(r, &N);
+    sum = 1.0/(PetscScalar)N;
+    VecSet(r, sum);
+
+    MatMult(A, r, l); /* {l} = [A] {r} */
+
+    VecNorm(l, NORM_2, &nrm);
+    if(nrm < 1.e-7)
+	isNull = PETSC_TRUE;
+    else
+	isNull = PETSC_FALSE;
+
+    VecDestroy(l);
+    VecDestroy(r);
+
+    return isNull;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/Energy/src/Finalise.c
--- a/SLE/ProvidedSystems/Energy/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Finalise.h"
-
-#include <stdio.h>
-
-Bool StgFEM_SLE_ProvidedSystems_Energy_Finalise( void ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
-	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/Energy/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/Energy/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,60 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Finalise.h"
+
+#include <stdio.h>
+
+Bool StgFEM_SLE_ProvidedSystems_Energy_Finalise( void ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
+	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_Energy_Debug );
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/Energy/src/Init.c
--- a/SLE/ProvidedSystems/Energy/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Init.h"
-
-#include "Energy_SLE_Solver.h"
-#include "Energy_SLE.h"
-#include <stdio.h>
-
-Stream* StgFEM_SLE_ProvidedSystems_Energy_Debug = NULL;
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_SLE_ProvidedSystems_Energy_Init( int* argc, char** argv[] ) {
-
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	/* initialise this level's streams */
-	StgFEM_SLE_ProvidedSystems_Energy_Debug = Stream_RegisterChild( StgFEM_SLE_Debug, "ProvidedSystems_Energy" );
-	
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), Energy_SLE_Solver_Type , (Name)"0", Energy_SLE_Solver_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), Energy_SLE_Type , "0", _Energy_SLE_DefaultNew );
-
-	RegisterParent( Energy_SLE_Type,        SystemLinearEquations_Type );
-	RegisterParent( Energy_SLE_Solver_Type, SLE_Solver_Type );
-
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/Energy/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/Energy/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,74 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Init.h"
+
+#include "Energy_SLE_Solver.h"
+#include "Energy_SLE.h"
+#include <stdio.h>
+
+Stream* StgFEM_SLE_ProvidedSystems_Energy_Debug = NULL;
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_SLE_ProvidedSystems_Energy_Init( int* argc, char** argv[] ) {
+
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	/* initialise this level's streams */
+	StgFEM_SLE_ProvidedSystems_Energy_Debug = Stream_RegisterChild( StgFEM_SLE_Debug, "ProvidedSystems_Energy" );
+	
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), Energy_SLE_Solver_Type , (Name)"0", Energy_SLE_Solver_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), Energy_SLE_Type , "0", _Energy_SLE_DefaultNew );
+
+	RegisterParent( Energy_SLE_Type,        SystemLinearEquations_Type );
+	RegisterParent( Energy_SLE_Solver_Type, SLE_Solver_Type );
+
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Finalise.c
--- a/SLE/ProvidedSystems/StokesFlow/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Finalise.h"
-
-#include <stdio.h>
-
-Bool StgFEM_SLE_ProvidedSystems_StokesFlow_Finalise( void ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_StokesFlow_Debug );
-	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_StokesFlow_Debug );
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/StokesFlow/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,60 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Finalise.h"
+
+#include <stdio.h>
+
+Bool StgFEM_SLE_ProvidedSystems_StokesFlow_Finalise( void ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	Stream_IndentBranch( StgFEM_SLE_ProvidedSystems_StokesFlow_Debug );
+	Stream_UnIndentBranch( StgFEM_SLE_ProvidedSystems_StokesFlow_Debug );
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Init.c
--- a/SLE/ProvidedSystems/StokesFlow/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-
-#include "StokesFlow.h"
-
-#include <stdio.h>
-
-Stream* StgFEM_SLE_ProvidedSystems_StokesFlow_Debug = NULL;
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_SLE_ProvidedSystems_StokesFlow_Init( int* argc, char** argv[] ) {
-
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	/* initialise this level's streams */
-	StgFEM_SLE_ProvidedSystems_StokesFlow_Debug = Stream_RegisterChild( StgFEM_SLE_Debug,
-		"ProvidedSystems_StokesFlow" );
-
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), Stokes_SLE_Type , (Name)"0", _Stokes_SLE_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), Stokes_SLE_UzawaSolver_Type , "0", _Stokes_SLE_UzawaSolver_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), Stokes_SLE_PenaltySolver_Type , (Name)"0", Stokes_SLE_PenaltySolver_DefaultNew );  
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), UzawaPreconditionerTerm_Type , "0", _UzawaPreconditionerTerm_DefaultNew );
-
-	RegisterParent( Stokes_SLE_Type,               		SystemLinearEquations_Type );
-	RegisterParent( Stokes_SLE_PenaltySolver_Type, 		SLE_Solver_Type );
-	RegisterParent( Stokes_SLE_UzawaSolver_Type,   		SLE_Solver_Type );
-	RegisterParent( UzawaPreconditionerTerm_Type,  		StiffnessMatrixTerm_Type );
-	
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/StokesFlow/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,77 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+
+#include "StokesFlow.h"
+
+#include <stdio.h>
+
+Stream* StgFEM_SLE_ProvidedSystems_StokesFlow_Debug = NULL;
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_SLE_ProvidedSystems_StokesFlow_Init( int* argc, char** argv[] ) {
+
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	/* initialise this level's streams */
+	StgFEM_SLE_ProvidedSystems_StokesFlow_Debug = Stream_RegisterChild( StgFEM_SLE_Debug,
+		"ProvidedSystems_StokesFlow" );
+
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), Stokes_SLE_Type , (Name)"0", _Stokes_SLE_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), Stokes_SLE_UzawaSolver_Type , "0", _Stokes_SLE_UzawaSolver_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), Stokes_SLE_PenaltySolver_Type , (Name)"0", Stokes_SLE_PenaltySolver_DefaultNew );  
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), UzawaPreconditionerTerm_Type , "0", _UzawaPreconditionerTerm_DefaultNew );
+
+	RegisterParent( Stokes_SLE_Type,               		SystemLinearEquations_Type );
+	RegisterParent( Stokes_SLE_PenaltySolver_Type, 		SLE_Solver_Type );
+	RegisterParent( Stokes_SLE_UzawaSolver_Type,   		SLE_Solver_Type );
+	RegisterParent( UzawaPreconditionerTerm_Type,  		StiffnessMatrixTerm_Type );
+	
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE.c
--- a/SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,239 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Stokes_SLE.c 999 2008-01-09 04:13:42Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Stokes_SLE.h"
-#include "UpdateDt.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type Stokes_SLE_Type = "Stokes_SLE";
-
-Stokes_SLE* Stokes_SLE_New( 
-	Name							name,
-	SLE_Solver*					solver,
-	FiniteElementContext*	context,
-	Bool							isNonLinear,
-	double						nonLinearTolerance,
-	Iteration_Index			nonLinearMaxIterations,
-	Bool							killNonConvergent,		
-	EntryPoint_Register*		entryPoint_Register,
-	MPI_Comm						comm,
-	StiffnessMatrix*			kStiffMat,
-	StiffnessMatrix*			gStiffMat,
-	StiffnessMatrix*			dStiffMat,
-	StiffnessMatrix*			cStiffMat,
-	SolutionVector*			uSolnVec,
-	SolutionVector*			pSolnVec,
-	ForceVector*				fForceVec,
-	ForceVector*				hForceVec )
-{
-	Stokes_SLE* self = (Stokes_SLE*) _Stokes_SLE_DefaultNew( name );
-
-	self->isConstructed = True;
-	_SystemLinearEquations_Init( self, solver, NULL, context, False, isNonLinear, 
-      nonLinearTolerance, nonLinearMaxIterations, killNonConvergent, 1,  "", "", entryPoint_Register, comm ); 
-	_Stokes_SLE_Init( self, kStiffMat, gStiffMat, dStiffMat, cStiffMat, uSolnVec, pSolnVec, fForceVec, hForceVec );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-Stokes_SLE* _Stokes_SLE_New(  STOKES_SLE_DEFARGS  )
-{
-	Stokes_SLE* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Stokes_SLE) );
-	self = (Stokes_SLE*) _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _Stokes_SLE_Init( 
-		void*                                               sle, 
-		StiffnessMatrix*                                    kStiffMat,
-		StiffnessMatrix*                                    gStiffMat,
-		StiffnessMatrix*                                    dStiffMat,
-		StiffnessMatrix*                                    cStiffMat,
-		SolutionVector*                                     uSolnVec,
-		SolutionVector*                                     pSolnVec,
-		ForceVector*                                        fForceVec,
-		ForceVector*                                        hForceVec ) 
-{
-	Stokes_SLE* self = (Stokes_SLE*)sle;
-
-	self->kStiffMat = kStiffMat;
-	self->gStiffMat = gStiffMat;
-	self->dStiffMat = dStiffMat;
-	self->cStiffMat = cStiffMat;
-	self->uSolnVec  = uSolnVec; 
-	self->pSolnVec  = pSolnVec;
-	self->fForceVec = fForceVec;   
-	self->hForceVec = hForceVec;   
-
-	/* add the vecs and matrices to the Base SLE class's dynamic lists, so they can be 
-	initialised and built properly */
-	SystemLinearEquations_AddStiffnessMatrix( self, kStiffMat );
-	SystemLinearEquations_AddStiffnessMatrix( self, gStiffMat );
-
-	if ( dStiffMat ) 
-		SystemLinearEquations_AddStiffnessMatrix( self, dStiffMat );
-	if ( cStiffMat ) 
-		SystemLinearEquations_AddStiffnessMatrix( self, cStiffMat );
-
-	SystemLinearEquations_AddSolutionVector( self, uSolnVec );
-	SystemLinearEquations_AddSolutionVector( self, pSolnVec );
-	SystemLinearEquations_AddForceVector( self, fForceVec );
-	SystemLinearEquations_AddForceVector( self, hForceVec );
-
-	/* Put timestep function onto entry point */
-	if ( self->context )
-		EP_AppendClassHook( self->context->calcDtEP, Stokes_SLE_UpdateDt, self );
-}
-
-void _Stokes_SLE_Print( void* sle, Stream* stream ) {
-	Stokes_SLE* self = (Stokes_SLE*)sle;
-	/* Set the Journal for printing informations */
-	
-	/* General info */
-	Journal_Printf( stream, "Stokes_SLE (ptr): %p\n", self );
-	_SystemLinearEquations_Print( self, stream );
-
-	Journal_Printf( stream, "Name of discrete stress tensor (K) matrix = \"%s\" \n",self->kStiffMat->name );
-	Journal_Printf( stream, "Name of discrete gradient (G) matrix = \"%s\" \n",self->gStiffMat->name );
-	if (self->dStiffMat) {
-		Journal_Printf( stream, "Name of discrete divergence (D) matrix = \"%s\" \n",self->dStiffMat->name );
-	}
-	else {
-		Journal_Printf( stream, "No discrete divergence (D) matrix set up (Symmetric geometry).\n" );
-	}
-	if (self->cStiffMat) {
-		Journal_Printf( stream, "Name of compressibility (C) matrix = \"%s\" \n",self->cStiffMat->name );
-	}
-	else {
-		Journal_Printf( stream, "No compressibility (C) matrix set up (incompressible fluids)\n" );
-	}
-	Journal_Printf( stream, "Name of velocity (u) vector = \"%s\" \n",self->uSolnVec->name );
-	Journal_Printf( stream, "Name of pressure (p) vector = \"%s\" \n",self->pSolnVec->name );
-
-	Stg_Class_Print( self->solver, stream );
-}
-
-void* _Stokes_SLE_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                            _sizeOfSelf = sizeof(Stokes_SLE);
-	Type                                                                    type = Stokes_SLE_Type;
-	Stg_Class_DeleteFunction*                                            _delete = _SystemLinearEquations_Delete;
-	Stg_Class_PrintFunction*                                              _print = _Stokes_SLE_Print;
-	Stg_Class_CopyFunction*                                                _copy = _SystemLinearEquations_Copy;
-	Stg_Component_DefaultConstructorFunction*                _defaultConstructor = _Stokes_SLE_DefaultNew;
-	Stg_Component_ConstructFunction*                                  _construct = _Stokes_SLE_AssignFromXML;
-	Stg_Component_BuildFunction*                                          _build = _SystemLinearEquations_Build;
-	Stg_Component_InitialiseFunction*                                _initialise = _SystemLinearEquations_Initialise;
-	Stg_Component_ExecuteFunction*                                      _execute = _SystemLinearEquations_Execute;
-	Stg_Component_DestroyFunction*                                      _destroy = _SystemLinearEquations_Destroy;
-	SystemLinearEquations_LM_SetupFunction*                            _LM_Setup = _SystemLinearEquations_LM_Setup;
-	SystemLinearEquations_MatrixSetupFunction*                      _matrixSetup = _SystemLinearEquations_MatrixSetup;
-	SystemLinearEquations_VectorSetupFunction*                      _vectorSetup = _SystemLinearEquations_VectorSetup;
-	SystemLinearEquations_UpdateSolutionOntoNodesFunc*  _updateSolutionOntoNodes = _SystemLinearEquations_UpdateSolutionOntoNodes;
-	SystemLinearEquations_MG_SelectStiffMatsFunc*             _mgSelectStiffMats = _Stokes_SLE_MG_SelectStiffMats;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_Stokes_SLE_New(  STOKES_SLE_PASSARGS  );
-}
-
-void _Stokes_SLE_AssignFromXML( void* sle, Stg_ComponentFactory* cf, void* data ) {
-	Stokes_SLE*       self = (Stokes_SLE*)sle;
-	StiffnessMatrix*  kStiffMat;
-	StiffnessMatrix*  gStiffMat;
-	StiffnessMatrix*  dStiffMat;
-	StiffnessMatrix*  cStiffMat;
-	SolutionVector*   uSolnVec;
-	SolutionVector*   pSolnVec;
-	ForceVector*      fForceVec;
-	ForceVector*      hForceVec;
-
-	/* Construct Parent */
-	_SystemLinearEquations_AssignFromXML( self, cf, data );
-
-	kStiffMat =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"StressTensorMatrix", StiffnessMatrix, True, data  );
-	gStiffMat =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"GradientMatrix", StiffnessMatrix, True, data  );
-	dStiffMat =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"DivergenceMatrix", StiffnessMatrix, False, data  );
-	cStiffMat =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"CompressibilityMatrix", StiffnessMatrix, False, data  );
-
-	uSolnVec  =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"VelocityVector", SolutionVector, True, data  );
-	pSolnVec  =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PressureVector", SolutionVector, True, data  );
-
-	fForceVec =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ForceVector", ForceVector, True, data  );
-	hForceVec =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ContinuityForceVector", ForceVector, True, data  );
-
-	_Stokes_SLE_Init( self, kStiffMat, gStiffMat, dStiffMat, cStiffMat, uSolnVec, pSolnVec, fForceVec, hForceVec );
-}
-
-
-void _Stokes_SLE_MG_SelectStiffMats( void* _sle, unsigned* nSMs, StiffnessMatrix*** sms ) {
-	Stokes_SLE*	self = (Stokes_SLE*)_sle;
-	
-	/*
-	** In this implementation, only the velocity matrix will have MG applied.
-	*/
-	
-	*nSMs = 1;
-	*sms = Memory_Alloc_Array( StiffnessMatrix*, 1, "Stokes_SLE" );
-	(*sms)[0] = self->kStiffMat;
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,239 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Stokes_SLE.c 999 2008-01-09 04:13:42Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Stokes_SLE.h"
+#include "UpdateDt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type Stokes_SLE_Type = "Stokes_SLE";
+
+Stokes_SLE* Stokes_SLE_New( 
+	Name							name,
+	SLE_Solver*					solver,
+	FiniteElementContext*	context,
+	Bool							isNonLinear,
+	double						nonLinearTolerance,
+	Iteration_Index			nonLinearMaxIterations,
+	Bool							killNonConvergent,		
+	EntryPoint_Register*		entryPoint_Register,
+	MPI_Comm						comm,
+	StiffnessMatrix*			kStiffMat,
+	StiffnessMatrix*			gStiffMat,
+	StiffnessMatrix*			dStiffMat,
+	StiffnessMatrix*			cStiffMat,
+	SolutionVector*			uSolnVec,
+	SolutionVector*			pSolnVec,
+	ForceVector*				fForceVec,
+	ForceVector*				hForceVec )
+{
+	Stokes_SLE* self = (Stokes_SLE*) _Stokes_SLE_DefaultNew( name );
+
+	self->isConstructed = True;
+	_SystemLinearEquations_Init( self, solver, NULL, context, False, isNonLinear, 
+      nonLinearTolerance, nonLinearMaxIterations, killNonConvergent, 1,  "", "", entryPoint_Register, comm ); 
+	_Stokes_SLE_Init( self, kStiffMat, gStiffMat, dStiffMat, cStiffMat, uSolnVec, pSolnVec, fForceVec, hForceVec );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+Stokes_SLE* _Stokes_SLE_New(  STOKES_SLE_DEFARGS  )
+{
+	Stokes_SLE* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Stokes_SLE) );
+	self = (Stokes_SLE*) _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _Stokes_SLE_Init( 
+		void*                                               sle, 
+		StiffnessMatrix*                                    kStiffMat,
+		StiffnessMatrix*                                    gStiffMat,
+		StiffnessMatrix*                                    dStiffMat,
+		StiffnessMatrix*                                    cStiffMat,
+		SolutionVector*                                     uSolnVec,
+		SolutionVector*                                     pSolnVec,
+		ForceVector*                                        fForceVec,
+		ForceVector*                                        hForceVec ) 
+{
+	Stokes_SLE* self = (Stokes_SLE*)sle;
+
+	self->kStiffMat = kStiffMat;
+	self->gStiffMat = gStiffMat;
+	self->dStiffMat = dStiffMat;
+	self->cStiffMat = cStiffMat;
+	self->uSolnVec  = uSolnVec; 
+	self->pSolnVec  = pSolnVec;
+	self->fForceVec = fForceVec;   
+	self->hForceVec = hForceVec;   
+
+	/* add the vecs and matrices to the Base SLE class's dynamic lists, so they can be 
+	initialised and built properly */
+	SystemLinearEquations_AddStiffnessMatrix( self, kStiffMat );
+	SystemLinearEquations_AddStiffnessMatrix( self, gStiffMat );
+
+	if ( dStiffMat ) 
+		SystemLinearEquations_AddStiffnessMatrix( self, dStiffMat );
+	if ( cStiffMat ) 
+		SystemLinearEquations_AddStiffnessMatrix( self, cStiffMat );
+
+	SystemLinearEquations_AddSolutionVector( self, uSolnVec );
+	SystemLinearEquations_AddSolutionVector( self, pSolnVec );
+	SystemLinearEquations_AddForceVector( self, fForceVec );
+	SystemLinearEquations_AddForceVector( self, hForceVec );
+
+	/* Put timestep function onto entry point */
+	if ( self->context )
+		EP_AppendClassHook( self->context->calcDtEP, Stokes_SLE_UpdateDt, self );
+}
+
+void _Stokes_SLE_Print( void* sle, Stream* stream ) {
+	Stokes_SLE* self = (Stokes_SLE*)sle;
+	/* Set the Journal for printing informations */
+	
+	/* General info */
+	Journal_Printf( stream, "Stokes_SLE (ptr): %p\n", self );
+	_SystemLinearEquations_Print( self, stream );
+
+	Journal_Printf( stream, "Name of discrete stress tensor (K) matrix = \"%s\" \n",self->kStiffMat->name );
+	Journal_Printf( stream, "Name of discrete gradient (G) matrix = \"%s\" \n",self->gStiffMat->name );
+	if (self->dStiffMat) {
+		Journal_Printf( stream, "Name of discrete divergence (D) matrix = \"%s\" \n",self->dStiffMat->name );
+	}
+	else {
+		Journal_Printf( stream, "No discrete divergence (D) matrix set up (Symmetric geometry).\n" );
+	}
+	if (self->cStiffMat) {
+		Journal_Printf( stream, "Name of compressibility (C) matrix = \"%s\" \n",self->cStiffMat->name );
+	}
+	else {
+		Journal_Printf( stream, "No compressibility (C) matrix set up (incompressible fluids)\n" );
+	}
+	Journal_Printf( stream, "Name of velocity (u) vector = \"%s\" \n",self->uSolnVec->name );
+	Journal_Printf( stream, "Name of pressure (p) vector = \"%s\" \n",self->pSolnVec->name );
+
+	Stg_Class_Print( self->solver, stream );
+}
+
+void* _Stokes_SLE_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                            _sizeOfSelf = sizeof(Stokes_SLE);
+	Type                                                                    type = Stokes_SLE_Type;
+	Stg_Class_DeleteFunction*                                            _delete = _SystemLinearEquations_Delete;
+	Stg_Class_PrintFunction*                                              _print = _Stokes_SLE_Print;
+	Stg_Class_CopyFunction*                                                _copy = _SystemLinearEquations_Copy;
+	Stg_Component_DefaultConstructorFunction*                _defaultConstructor = _Stokes_SLE_DefaultNew;
+	Stg_Component_ConstructFunction*                                  _construct = _Stokes_SLE_AssignFromXML;
+	Stg_Component_BuildFunction*                                          _build = _SystemLinearEquations_Build;
+	Stg_Component_InitialiseFunction*                                _initialise = _SystemLinearEquations_Initialise;
+	Stg_Component_ExecuteFunction*                                      _execute = _SystemLinearEquations_Execute;
+	Stg_Component_DestroyFunction*                                      _destroy = _SystemLinearEquations_Destroy;
+	SystemLinearEquations_LM_SetupFunction*                            _LM_Setup = _SystemLinearEquations_LM_Setup;
+	SystemLinearEquations_MatrixSetupFunction*                      _matrixSetup = _SystemLinearEquations_MatrixSetup;
+	SystemLinearEquations_VectorSetupFunction*                      _vectorSetup = _SystemLinearEquations_VectorSetup;
+	SystemLinearEquations_UpdateSolutionOntoNodesFunc*  _updateSolutionOntoNodes = _SystemLinearEquations_UpdateSolutionOntoNodes;
+	SystemLinearEquations_MG_SelectStiffMatsFunc*             _mgSelectStiffMats = _Stokes_SLE_MG_SelectStiffMats;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_Stokes_SLE_New(  STOKES_SLE_PASSARGS  );
+}
+
+void _Stokes_SLE_AssignFromXML( void* sle, Stg_ComponentFactory* cf, void* data ) {
+	Stokes_SLE*       self = (Stokes_SLE*)sle;
+	StiffnessMatrix*  kStiffMat;
+	StiffnessMatrix*  gStiffMat;
+	StiffnessMatrix*  dStiffMat;
+	StiffnessMatrix*  cStiffMat;
+	SolutionVector*   uSolnVec;
+	SolutionVector*   pSolnVec;
+	ForceVector*      fForceVec;
+	ForceVector*      hForceVec;
+
+	/* Construct Parent */
+	_SystemLinearEquations_AssignFromXML( self, cf, data );
+
+	kStiffMat =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"StressTensorMatrix", StiffnessMatrix, True, data  );
+	gStiffMat =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"GradientMatrix", StiffnessMatrix, True, data  );
+	dStiffMat =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"DivergenceMatrix", StiffnessMatrix, False, data  );
+	cStiffMat =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"CompressibilityMatrix", StiffnessMatrix, False, data  );
+
+	uSolnVec  =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"VelocityVector", SolutionVector, True, data  );
+	pSolnVec  =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"PressureVector", SolutionVector, True, data  );
+
+	fForceVec =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ForceVector", ForceVector, True, data  );
+	hForceVec =  Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ContinuityForceVector", ForceVector, True, data  );
+
+	_Stokes_SLE_Init( self, kStiffMat, gStiffMat, dStiffMat, cStiffMat, uSolnVec, pSolnVec, fForceVec, hForceVec );
+}
+
+
+void _Stokes_SLE_MG_SelectStiffMats( void* _sle, unsigned* nSMs, StiffnessMatrix*** sms ) {
+	Stokes_SLE*	self = (Stokes_SLE*)_sle;
+	
+	/*
+	** In this implementation, only the velocity matrix will have MG applied.
+	*/
+	
+	*nSMs = 1;
+	*sms = Memory_Alloc_Array( StiffnessMatrix*, 1, "Stokes_SLE" );
+	(*sms)[0] = self->kStiffMat;
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_PenaltySolver.c
--- a/SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_PenaltySolver.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,304 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Stokes_SLE_PenaltySolver.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Stokes_SLE_PenaltySolver.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "Stokes_SLE.h"
-
-const Type Stokes_SLE_PenaltySolver_Type = "Stokes_SLE_PenaltySolver";
-
-void* Stokes_SLE_PenaltySolver_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(Stokes_SLE_PenaltySolver);
-	Type                                                      type = Stokes_SLE_PenaltySolver_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Stokes_SLE_PenaltySolver_Delete;
-	Stg_Class_PrintFunction*                                _print = _Stokes_SLE_PenaltySolver_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Stokes_SLE_PenaltySolver_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = Stokes_SLE_PenaltySolver_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _Stokes_SLE_PenaltySolver_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Stokes_SLE_PenaltySolver_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _SLE_Solver_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _SLE_Solver_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _SLE_Solver_Destroy;
-	SLE_Solver_SolverSetupFunction*                   _solverSetup = _Stokes_SLE_PenaltySolver_SolverSetup;
-	SLE_Solver_SolveFunction*                               _solve = _Stokes_SLE_PenaltySolver_Solve;
-	SLE_Solver_GetResidualFunc*                       _getResidual = _Stokes_SLE_PenaltySolver_GetResidual;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Stokes_SLE_PenaltySolver_New(  STOKES_SLE_PENALTYSOLVER_PASSARGS  );
-}
-
-Stokes_SLE_PenaltySolver* Stokes_SLE_PenaltySolver_New(
-		Name                                        name,
-		Bool                                        useStatSolve, 
-		int                                         statReps )
-{
-	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*) Stokes_SLE_PenaltySolver_DefaultNew( name );
-
-	Stokes_SLE_PenaltySolver_InitAll( self, useStatSolve, statReps );
-
-	return self;
-}
-
-
-/* Creation implementation / Virtual constructor */
-Stokes_SLE_PenaltySolver* _Stokes_SLE_PenaltySolver_New(  STOKES_SLE_PENALTYSOLVER_DEFARGS  )
-{
-	Stokes_SLE_PenaltySolver* self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Stokes_SLE_PenaltySolver) );
-	self = (Stokes_SLE_PenaltySolver*) _SLE_Solver_New(  SLE_SOLVER_PASSARGS  );
-
-	/* Virtual info */
-	return self;
-}
-
-
-void _Stokes_SLE_PenaltySolver_Init( void* solver ) {
-	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;
-
-	self->isConstructed       = True;
-}
-
-void Stokes_SLE_PenaltySolver_InitAll( 
-		void*                        solver,
-		Bool                         useStatSolve,
-		int                          statReps )
-{
-	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;
-
-	SLE_Solver_InitAll( self, useStatSolve, statReps );
-	_Stokes_SLE_PenaltySolver_Init( self );
-}
-
-
-void _Stokes_SLE_PenaltySolver_Delete( void* solver ) {
-	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;
-		
-	Journal_DPrintf( self->debug, "In: %s \n", __func__);
-
-	Stream_IndentBranch( StgFEM_Debug );
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}       
-
-
-void _Stokes_SLE_PenaltySolver_Print( void* solver, Stream* stream ) {
-	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;
-
-	_SLE_Solver_Print( self, stream );
-}
-
-
-void* _Stokes_SLE_PenaltySolver_Copy( const void* stokesSlePenaltySolver, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)stokesSlePenaltySolver;
-	Stokes_SLE_PenaltySolver*	newStokesSlePenaltySolver;
-	
-	newStokesSlePenaltySolver = (Stokes_SLE_PenaltySolver*)_SLE_Solver_Copy( self, dest, deep, nameExt, ptrMap );
-	
-	return (void*) newStokesSlePenaltySolver;
-}
-
-
-void _Stokes_SLE_PenaltySolver_Build( void* solver, void* stokesSLE ) {
-	Stokes_SLE_PenaltySolver*	self  = (Stokes_SLE_PenaltySolver*)solver;
-
- 	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _Stokes_SLE_PenaltySolver_AssignFromXML( void* solver, Stg_ComponentFactory* cf, void* data ) {
-	Stokes_SLE_PenaltySolver* self         = (Stokes_SLE_PenaltySolver*) solver;
-
-	_SLE_Solver_AssignFromXML( self, cf, data );
-	
-	_Stokes_SLE_PenaltySolver_Init( self );
-}
-
-void _Stokes_SLE_PenaltySolver_Execute( void* solver, void* data ) {
-}
-
-void _Stokes_SLE_PenaltySolver_Destroy( void* solver, void* data ) {
-}
-
-void _Stokes_SLE_PenaltySolver_Initialise( void* solver, void* stokesSLE ) {
-	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*) solver;
-	Stokes_SLE*             sle  = (Stokes_SLE*)             stokesSLE;
-	
-	/* Initialise Parent */
-	_SLE_Solver_Initialise( self, sle );
-}
-
-/* SolverSetup */
-void _Stokes_SLE_PenaltySolver_SolverSetup( void* solver, void* stokesSLE ) {
-	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*) solver;
-	
- 	Journal_DPrintf( self->debug, "In %s:\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _Stokes_SLE_PenaltySolver_Solve( void* solver,void* stokesSLE ) {
-	Stokes_SLE_PenaltySolver* self            = (Stokes_SLE_PenaltySolver*)solver;	
-	Stokes_SLE*             sle             = (Stokes_SLE*)stokesSLE;
-	/* Create shortcuts to stuff needed on sle */
-	Mat                     kMatrix         = sle->kStiffMat->matrix;
-	Mat                     gradMat         = sle->gStiffMat->matrix;
-	Mat                     divMat          = NULL;
-	Mat                     C_Mat           = sle->cStiffMat->matrix;
-	Vec                     uVec            = sle->uSolnVec->vector;
-	Vec                     pVec            = sle->pSolnVec->vector;
-	Vec                     fVec            = sle->fForceVec->vector;
-	Vec                     hVec            = sle->hForceVec->vector;
-	Vec     		hTempVec;
-	Vec    			fTempVec;
-	Mat    			GTrans;
-	KSP			sles_v;
-	double	 		negOne=-1.0;
-	double	 		one=1.0;
-	Mat    			kHat;
-	Mat    			C_InvMat;
-	Vec    			diagC;
-	PC			pc;
-
-	Journal_DPrintf( self->debug, "In %s():\n", __func__ );
-
-	VecDuplicate( hVec, &hTempVec );
-	VecDuplicate( fVec, &fTempVec );
-	VecDuplicate( pVec, &diagC );
-	
-	if( sle->dStiffMat == NULL ) {
-		Journal_DPrintf( self->debug, "Div matrix == NULL : Problem is assumed to be symmetric. ie Div = GTrans \n");
-#if( PETSC_VERSION_MAJOR <= 2 )
-		MatTranspose( gradMat, &GTrans );
-#else
-		MatTranspose( gradMat, MAT_INITIAL_MATRIX, &GTrans );
-#endif
-		divMat = GTrans;
-	}
-	else {
-		/* make a copy we can play with */
-		MatCreate( sle->comm, &GTrans );
-		MatCopy( sle->dStiffMat->matrix, GTrans, DIFFERENT_NONZERO_PATTERN );
-		divMat = GTrans;
-	}
-	
-	/* Create CInv */
-	MatGetDiagonal( C_Mat, diagC );
-	VecReciprocal( diagC );
-	MatDiagonalSet( C_Mat, diagC, INSERT_VALUES );
-	C_InvMat = C_Mat;				/* Use pointer CInv since C has been inverted */
-	
-	/* Build RHS : rhs = f - GCInv h */
-	MatMult( C_InvMat, hVec, hTempVec );
-	VecScale( hTempVec, negOne );
-	MatMultAdd( gradMat, hTempVec, fVec, fTempVec );
-	
-	/* Build G CInv GTrans */
-/* 	MatTranspose( gradMat, &GTrans ); */
-/* 	 since CInv is diagonal we can just scale mat entries by the diag vector */
-	MatDiagonalScale( divMat, diagC, PETSC_NULL );  /*  Div = CInve Div */
-        /* 	MatMatMult_any( &tmpMat, C, *divMat );	*/ /* tmpMat = CInv Div */
-	
-	
-	Journal_DPrintf( self->debug, "UpdivMat mat mat mult \n");
-	MatPtAP( gradMat, divMat, MAT_INITIAL_MATRIX, 1.0, &kHat );
-	Journal_DPrintf( self->debug, "done mult \n");
-	MatScale( kHat, -1 );
-	MatAXPY( kHat, one, kMatrix, SAME_NONZERO_PATTERN );
-	
-	/* Setup solver context and make sure that it uses a direct solver */
-	KSPCreate( sle->comm, &sles_v );
-	KSPSetOperators( sles_v, kHat, kHat, DIFFERENT_NONZERO_PATTERN );
-	KSPSetType( sles_v, KSPPREONLY );
-	KSPGetPC( sles_v, &pc );
-	PCSetType( pc, PCLU );
-
-	KSPSolve( sles_v, fTempVec, uVec );
-	
-	/* Recover p */
-	if( sle->dStiffMat == NULL ) {
-/* 		 since Div was modified when C is diagonal, re build the transpose */
-#if( PETSC_VERSION_MAJOR <= 2 )
-		MatTranspose( gradMat, &GTrans );
-#else
-		MatTranspose( gradMat, MAT_INITIAL_MATRIX, &GTrans );
-#endif
-		divMat = GTrans;
-	}
-	else {
-/* 		 never modified Div_null so set divMat to point back to it */
-		divMat = sle->dStiffMat->matrix;
-	}
-	MatMult( divMat, uVec, hTempVec );    /* hTemp = Div v */
-	VecAXPY( hVec, negOne, hTempVec );    /* hTemp = H - hTemp   : hTemp = H - Div v */
-	MatMult( C_InvMat, hTempVec, pVec );  /* p = CInv hTemp      : p = CInv ( H - Div v ) */
-	
-	if( kHat != PETSC_NULL )     MatDestroy( kHat );
-	if( fTempVec != PETSC_NULL ) VecDestroy( fTempVec );
-	if( hTempVec != PETSC_NULL ) VecDestroy( hTempVec );
-	if( diagC != PETSC_NULL )    VecDestroy( diagC );
-	if( sles_v != PETSC_NULL )   KSPDestroy( sles_v );
-	if( GTrans != PETSC_NULL )   MatDestroy( GTrans );
-}
-
-
-Vec _Stokes_SLE_PenaltySolver_GetResidual( void* solver, Index fv_I ) {
-/* 	 TODO */
-	return NULL;
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_PenaltySolver.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_PenaltySolver.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,304 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Stokes_SLE_PenaltySolver.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Stokes_SLE_PenaltySolver.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "Stokes_SLE.h"
+
+const Type Stokes_SLE_PenaltySolver_Type = "Stokes_SLE_PenaltySolver";
+
+void* Stokes_SLE_PenaltySolver_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(Stokes_SLE_PenaltySolver);
+	Type                                                      type = Stokes_SLE_PenaltySolver_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Stokes_SLE_PenaltySolver_Delete;
+	Stg_Class_PrintFunction*                                _print = _Stokes_SLE_PenaltySolver_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Stokes_SLE_PenaltySolver_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = Stokes_SLE_PenaltySolver_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _Stokes_SLE_PenaltySolver_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Stokes_SLE_PenaltySolver_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _SLE_Solver_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _SLE_Solver_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _SLE_Solver_Destroy;
+	SLE_Solver_SolverSetupFunction*                   _solverSetup = _Stokes_SLE_PenaltySolver_SolverSetup;
+	SLE_Solver_SolveFunction*                               _solve = _Stokes_SLE_PenaltySolver_Solve;
+	SLE_Solver_GetResidualFunc*                       _getResidual = _Stokes_SLE_PenaltySolver_GetResidual;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Stokes_SLE_PenaltySolver_New(  STOKES_SLE_PENALTYSOLVER_PASSARGS  );
+}
+
+Stokes_SLE_PenaltySolver* Stokes_SLE_PenaltySolver_New(
+		Name                                        name,
+		Bool                                        useStatSolve, 
+		int                                         statReps )
+{
+	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*) Stokes_SLE_PenaltySolver_DefaultNew( name );
+
+	Stokes_SLE_PenaltySolver_InitAll( self, useStatSolve, statReps );
+
+	return self;
+}
+
+
+/* Creation implementation / Virtual constructor */
+Stokes_SLE_PenaltySolver* _Stokes_SLE_PenaltySolver_New(  STOKES_SLE_PENALTYSOLVER_DEFARGS  )
+{
+	Stokes_SLE_PenaltySolver* self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Stokes_SLE_PenaltySolver) );
+	self = (Stokes_SLE_PenaltySolver*) _SLE_Solver_New(  SLE_SOLVER_PASSARGS  );
+
+	/* Virtual info */
+	return self;
+}
+
+
+void _Stokes_SLE_PenaltySolver_Init( void* solver ) {
+	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;
+
+	self->isConstructed       = True;
+}
+
+void Stokes_SLE_PenaltySolver_InitAll( 
+		void*                        solver,
+		Bool                         useStatSolve,
+		int                          statReps )
+{
+	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;
+
+	SLE_Solver_InitAll( self, useStatSolve, statReps );
+	_Stokes_SLE_PenaltySolver_Init( self );
+}
+
+
+void _Stokes_SLE_PenaltySolver_Delete( void* solver ) {
+	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;
+		
+	Journal_DPrintf( self->debug, "In: %s \n", __func__);
+
+	Stream_IndentBranch( StgFEM_Debug );
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}       
+
+
+void _Stokes_SLE_PenaltySolver_Print( void* solver, Stream* stream ) {
+	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)solver;
+
+	_SLE_Solver_Print( self, stream );
+}
+
+
+void* _Stokes_SLE_PenaltySolver_Copy( const void* stokesSlePenaltySolver, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*)stokesSlePenaltySolver;
+	Stokes_SLE_PenaltySolver*	newStokesSlePenaltySolver;
+	
+	newStokesSlePenaltySolver = (Stokes_SLE_PenaltySolver*)_SLE_Solver_Copy( self, dest, deep, nameExt, ptrMap );
+	
+	return (void*) newStokesSlePenaltySolver;
+}
+
+
+void _Stokes_SLE_PenaltySolver_Build( void* solver, void* stokesSLE ) {
+	Stokes_SLE_PenaltySolver*	self  = (Stokes_SLE_PenaltySolver*)solver;
+
+ 	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _Stokes_SLE_PenaltySolver_AssignFromXML( void* solver, Stg_ComponentFactory* cf, void* data ) {
+	Stokes_SLE_PenaltySolver* self         = (Stokes_SLE_PenaltySolver*) solver;
+
+	_SLE_Solver_AssignFromXML( self, cf, data );
+	
+	_Stokes_SLE_PenaltySolver_Init( self );
+}
+
+void _Stokes_SLE_PenaltySolver_Execute( void* solver, void* data ) {
+}
+
+void _Stokes_SLE_PenaltySolver_Destroy( void* solver, void* data ) {
+}
+
+void _Stokes_SLE_PenaltySolver_Initialise( void* solver, void* stokesSLE ) {
+	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*) solver;
+	Stokes_SLE*             sle  = (Stokes_SLE*)             stokesSLE;
+	
+	/* Initialise Parent */
+	_SLE_Solver_Initialise( self, sle );
+}
+
+/* SolverSetup */
+void _Stokes_SLE_PenaltySolver_SolverSetup( void* solver, void* stokesSLE ) {
+	Stokes_SLE_PenaltySolver* self = (Stokes_SLE_PenaltySolver*) solver;
+	
+ 	Journal_DPrintf( self->debug, "In %s:\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _Stokes_SLE_PenaltySolver_Solve( void* solver,void* stokesSLE ) {
+	Stokes_SLE_PenaltySolver* self            = (Stokes_SLE_PenaltySolver*)solver;	
+	Stokes_SLE*             sle             = (Stokes_SLE*)stokesSLE;
+	/* Create shortcuts to stuff needed on sle */
+	Mat                     kMatrix         = sle->kStiffMat->matrix;
+	Mat                     gradMat         = sle->gStiffMat->matrix;
+	Mat                     divMat          = NULL;
+	Mat                     C_Mat           = sle->cStiffMat->matrix;
+	Vec                     uVec            = sle->uSolnVec->vector;
+	Vec                     pVec            = sle->pSolnVec->vector;
+	Vec                     fVec            = sle->fForceVec->vector;
+	Vec                     hVec            = sle->hForceVec->vector;
+	Vec     		hTempVec;
+	Vec    			fTempVec;
+	Mat    			GTrans;
+	KSP			sles_v;
+	double	 		negOne=-1.0;
+	double	 		one=1.0;
+	Mat    			kHat;
+	Mat    			C_InvMat;
+	Vec    			diagC;
+	PC			pc;
+
+	Journal_DPrintf( self->debug, "In %s():\n", __func__ );
+
+	VecDuplicate( hVec, &hTempVec );
+	VecDuplicate( fVec, &fTempVec );
+	VecDuplicate( pVec, &diagC );
+	
+	if( sle->dStiffMat == NULL ) {
+		Journal_DPrintf( self->debug, "Div matrix == NULL : Problem is assumed to be symmetric. ie Div = GTrans \n");
+#if( PETSC_VERSION_MAJOR <= 2 )
+		MatTranspose( gradMat, &GTrans );
+#else
+		MatTranspose( gradMat, MAT_INITIAL_MATRIX, &GTrans );
+#endif
+		divMat = GTrans;
+	}
+	else {
+		/* make a copy we can play with */
+		MatCreate( sle->comm, &GTrans );
+		MatCopy( sle->dStiffMat->matrix, GTrans, DIFFERENT_NONZERO_PATTERN );
+		divMat = GTrans;
+	}
+	
+	/* Create CInv */
+	MatGetDiagonal( C_Mat, diagC );
+	VecReciprocal( diagC );
+	MatDiagonalSet( C_Mat, diagC, INSERT_VALUES );
+	C_InvMat = C_Mat;				/* Use pointer CInv since C has been inverted */
+	
+	/* Build RHS : rhs = f - GCInv h */
+	MatMult( C_InvMat, hVec, hTempVec );
+	VecScale( hTempVec, negOne );
+	MatMultAdd( gradMat, hTempVec, fVec, fTempVec );
+	
+	/* Build G CInv GTrans */
+/* 	MatTranspose( gradMat, &GTrans ); */
+/* 	 since CInv is diagonal we can just scale mat entries by the diag vector */
+	MatDiagonalScale( divMat, diagC, PETSC_NULL );  /*  Div = CInve Div */
+        /* 	MatMatMult_any( &tmpMat, C, *divMat );	*/ /* tmpMat = CInv Div */
+	
+	
+	Journal_DPrintf( self->debug, "UpdivMat mat mat mult \n");
+	MatPtAP( gradMat, divMat, MAT_INITIAL_MATRIX, 1.0, &kHat );
+	Journal_DPrintf( self->debug, "done mult \n");
+	MatScale( kHat, -1 );
+	MatAXPY( kHat, one, kMatrix, SAME_NONZERO_PATTERN );
+	
+	/* Setup solver context and make sure that it uses a direct solver */
+	KSPCreate( sle->comm, &sles_v );
+	KSPSetOperators( sles_v, kHat, kHat, DIFFERENT_NONZERO_PATTERN );
+	KSPSetType( sles_v, KSPPREONLY );
+	KSPGetPC( sles_v, &pc );
+	PCSetType( pc, PCLU );
+
+	KSPSolve( sles_v, fTempVec, uVec );
+	
+	/* Recover p */
+	if( sle->dStiffMat == NULL ) {
+/* 		 since Div was modified when C is diagonal, re build the transpose */
+#if( PETSC_VERSION_MAJOR <= 2 )
+		MatTranspose( gradMat, &GTrans );
+#else
+		MatTranspose( gradMat, MAT_INITIAL_MATRIX, &GTrans );
+#endif
+		divMat = GTrans;
+	}
+	else {
+/* 		 never modified Div_null so set divMat to point back to it */
+		divMat = sle->dStiffMat->matrix;
+	}
+	MatMult( divMat, uVec, hTempVec );    /* hTemp = Div v */
+	VecAXPY( hVec, negOne, hTempVec );    /* hTemp = H - hTemp   : hTemp = H - Div v */
+	MatMult( C_InvMat, hTempVec, pVec );  /* p = CInv hTemp      : p = CInv ( H - Div v ) */
+	
+	if( kHat != PETSC_NULL )     MatDestroy( kHat );
+	if( fTempVec != PETSC_NULL ) VecDestroy( fTempVec );
+	if( hTempVec != PETSC_NULL ) VecDestroy( hTempVec );
+	if( diagC != PETSC_NULL )    VecDestroy( diagC );
+	if( sles_v != PETSC_NULL )   KSPDestroy( sles_v );
+	if( GTrans != PETSC_NULL )   MatDestroy( GTrans );
+}
+
+
+Vec _Stokes_SLE_PenaltySolver_GetResidual( void* solver, Index fv_I ) {
+/* 	 TODO */
+	return NULL;
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_UzawaSolver.c
--- a/SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_UzawaSolver.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1048 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Stokes_SLE_UzawaSolver.c 1199 2008-08-08 04:03:32Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Stokes_SLE_UzawaSolver.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "Stokes_SLE.h"
-
-/* Macro to checking number integrity - i.e. checks if number is infinite or "not a number" */
-#define isGoodNumber( number ) \
-	( (! isnan( number ) ) && ( ! isinf( number ) ) )
-
-const Type Stokes_SLE_UzawaSolver_Type = "Stokes_SLE_UzawaSolver";
-
-void* _Stokes_SLE_UzawaSolver_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(Stokes_SLE_UzawaSolver);
-	Type                                                      type = Stokes_SLE_UzawaSolver_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Stokes_SLE_UzawaSolver_Delete;
-	Stg_Class_PrintFunction*                                _print = _Stokes_SLE_UzawaSolver_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Stokes_SLE_UzawaSolver_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _Stokes_SLE_UzawaSolver_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _Stokes_SLE_UzawaSolver_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Stokes_SLE_UzawaSolver_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Stokes_SLE_UzawaSolver_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _SLE_Solver_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _Stokes_SLE_UzawaSolver_Destroy;
-	SLE_Solver_SolverSetupFunction*                   _solverSetup = _Stokes_SLE_UzawaSolver_SolverSetup;
-	SLE_Solver_SolveFunction*                               _solve = _Stokes_SLE_UzawaSolver_Solve;
-	SLE_Solver_GetResidualFunc*                       _getResidual = _Stokes_SLE_UzawaSolver_GetResidual;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _Stokes_SLE_UzawaSolver_New(  STOKES_SLE_UZAWASOLVER_PASSARGS  );
-}
-
-Stokes_SLE_UzawaSolver* Stokes_SLE_UzawaSolver_New( 
-		Name                                        name,
-		Bool                                        useStatSolve, 
-		int                                         statReps,
-		StiffnessMatrix*                            preconditioner,
-		Iteration_Index                             maxUzawaIterations,
-		Iteration_Index                             minUzawaIterations,
-		double                                      tolerance,
-		Bool                                        useAbsoluteTolerance,
-                Bool                                        monitor )
-{		
-  Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)_Stokes_SLE_UzawaSolver_DefaultNew( name );
-
-	Stokes_SLE_UzawaSolver_InitAll( self, useStatSolve, statReps, preconditioner, maxUzawaIterations, minUzawaIterations, tolerance, useAbsoluteTolerance, monitor );
-
-	return self;
-}
-
-
-/* Creation implementation / Virtual constructor */
-Stokes_SLE_UzawaSolver* _Stokes_SLE_UzawaSolver_New(  STOKES_SLE_UZAWASOLVER_DEFARGS  )
-{
-	Stokes_SLE_UzawaSolver* self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Stokes_SLE_UzawaSolver) );
-	self = (Stokes_SLE_UzawaSolver*) _SLE_Solver_New(  SLE_SOLVER_PASSARGS  );
-
-	self->_formResidual  = _Stokes_SLE_UzawaSolver_FormResidual;
-        self->_getRhs        = _Stokes_SLE_UzawaSolver_GetRhs;
-	self->_getSolution   = _Stokes_SLE_UzawaSolver_GetSolution;
-	
-	/* Virtual info */
-	return self;
-}
-
-
-void _Stokes_SLE_UzawaSolver_Init( 
-		Stokes_SLE_UzawaSolver*      self,
-		StiffnessMatrix*             preconditioner, 
-		Iteration_Index              maxUzawaIterations,
-		Iteration_Index              minUzawaIterations,
-		double                       tolerance,
-		Bool                         useAbsoluteTolerance,
-                Bool                         monitor )
-{
-	self->isConstructed        = True;
-	self->tolerance            = tolerance;
-	self->maxUzawaIterations   = maxUzawaIterations;
-	self->minUzawaIterations   = minUzawaIterations;
-	self->preconditioner       = preconditioner;
-	self->useAbsoluteTolerance = useAbsoluteTolerance;
-        self->monitor              = monitor;
-}
-
-void Stokes_SLE_UzawaSolver_InitAll( 
-		void*                        solver,
-		Bool                         useStatSolve,
-		int                          statReps, 
-		StiffnessMatrix*             preconditioner, 
-		Iteration_Index              maxUzawaIterations,
-		Iteration_Index              minUzawaIterations,
-		double                       tolerance,
-		Bool                         useAbsoluteTolerance,
-                Bool                         monitor )
-{
-	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)solver;
-
-	SLE_Solver_InitAll( self, useStatSolve, statReps );
-	_Stokes_SLE_UzawaSolver_Init( self, preconditioner, maxUzawaIterations, minUzawaIterations, tolerance, useAbsoluteTolerance, monitor );
-}
-
-void _Stokes_SLE_UzawaSolver_Delete( void* solver ) {
-	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)solver;
-
-   _SLE_Solver_Delete( self );
-		
-}       
-
-
-void _Stokes_SLE_UzawaSolver_Print( void* solver, Stream* stream ) {
-	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)solver;
-
-	_SLE_Solver_Print( self, stream );
-
-	Journal_PrintValue( stream, self->tolerance );
-	Journal_PrintValue( stream, self->maxUzawaIterations );
-	Journal_PrintValue( stream, self->minUzawaIterations );
-}
-
-
-void* _Stokes_SLE_UzawaSolver_Copy( const void* stokesSleUzawaSolver, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)stokesSleUzawaSolver;
-	Stokes_SLE_UzawaSolver*	newStokesSleUzawaSolver;
-	
-	newStokesSleUzawaSolver = (Stokes_SLE_UzawaSolver*)_SLE_Solver_Copy( self, dest, deep, nameExt, ptrMap );
-	
-	newStokesSleUzawaSolver->velSolver           = self->velSolver;
-	newStokesSleUzawaSolver->pcSolver            = self->pcSolver;
-	newStokesSleUzawaSolver->preconditioner      = self->preconditioner;
-	newStokesSleUzawaSolver->pTempVec            = self->pTempVec;
-	newStokesSleUzawaSolver->rVec                = self->rVec;
-	newStokesSleUzawaSolver->sVec                = self->sVec;
-	newStokesSleUzawaSolver->fTempVec            = self->fTempVec;
-	newStokesSleUzawaSolver->vStarVec            = self->vStarVec;
-	newStokesSleUzawaSolver->tolerance           = self->tolerance;
-	newStokesSleUzawaSolver->maxUzawaIterations  = self->maxUzawaIterations;
-	newStokesSleUzawaSolver->minUzawaIterations  = self->minUzawaIterations;
-	newStokesSleUzawaSolver->useAbsoluteTolerance  = self->useAbsoluteTolerance;
-	newStokesSleUzawaSolver->monitor               = self->monitor;	
-
-	return (void*) newStokesSleUzawaSolver;
-}
-
-
-void _Stokes_SLE_UzawaSolver_Build( void* solver, void* stokesSLE ) {
-	Stokes_SLE_UzawaSolver*	self  = (Stokes_SLE_UzawaSolver*)solver;
-	Stokes_SLE*             sle   = (Stokes_SLE*)stokesSLE;
-
- 	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-	
- 	Journal_DPrintfL( self->debug, 2, "building a standard solver for the velocity system.\n" );
-	KSPCreate( sle->comm, &self->velSolver );
-	
-	/* Build Preconditioner */
-	if ( self->preconditioner ) {
-		Stg_Component_Build( self->preconditioner, stokesSLE, False );
-		SystemLinearEquations_AddStiffnessMatrix( sle, self->preconditioner );
-
-		Journal_DPrintfL( self->debug, 2, "build a standard solver for the preconditioner system.\n" );
-		KSPCreate( sle->comm, &self->pcSolver );
-	}
-	else 
-		self->pcSolver = PETSC_NULL;
-
-	if( self->pTempVec != PETSC_NULL ) VecDestroy( self->pTempVec );
-	if( self->rVec != PETSC_NULL )     VecDestroy( self->rVec );
-	if( self->sVec != PETSC_NULL )     VecDestroy( self->sVec );
-	if( self->fTempVec != PETSC_NULL ) VecDestroy( self->fTempVec );
-	if( self->vStarVec != PETSC_NULL ) VecDestroy( self->vStarVec );
-
- 	Journal_DPrintfL( self->debug, 2, "Allocate the auxillary vectors pTemp, r, s, fTemp and vStar.\n" ); 
-	VecDuplicate( sle->pSolnVec->vector, &self->pTempVec );
-	VecDuplicate( sle->pSolnVec->vector, &self->rVec );
-	VecDuplicate( sle->pSolnVec->vector, &self->sVec );
-
-	VecDuplicate( sle->fForceVec->vector, &self->fTempVec );
-	VecDuplicate( sle->fForceVec->vector, &self->vStarVec );
-
-	/* Need by the Picard nonlinear solver */
-//        Vector_Duplicate( sle->pTempVec->vector, (void**)&self->f_hat );
-//        Vector_SetLocalSize( self->vf_hat, Vector_GetLocalSize( sle->pTempVec->vector ) );
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _Stokes_SLE_UzawaSolver_AssignFromXML( void* solver, Stg_ComponentFactory* cf, void* data ) {
-	Stokes_SLE_UzawaSolver* self         = (Stokes_SLE_UzawaSolver*) solver;
-	double                  tolerance;
-	Iteration_Index         maxUzawaIterations, minUzawaIterations;
-	StiffnessMatrix*        preconditioner;
-	Bool                    useAbsoluteTolerance;
-	Bool                    monitor;
-
-	_SLE_Solver_AssignFromXML( self, cf, data );
-
-	tolerance            = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"tolerance", 1.0e-5  );
-	maxUzawaIterations   = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"maxIterations", 1000  );
-	minUzawaIterations   = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"minIterations", 1  );
-	useAbsoluteTolerance = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"useAbsoluteTolerance", False  );
-	monitor              = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"monitor", False  );
-
-	preconditioner = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Preconditioner", StiffnessMatrix, False, data  );
-
-	_Stokes_SLE_UzawaSolver_Init( self, preconditioner, maxUzawaIterations, minUzawaIterations, tolerance, useAbsoluteTolerance, monitor );
-
-	if( self->velSolver == PETSC_NULL ) {
-		KSPCreate( MPI_COMM_WORLD, &self->velSolver );
-	}
-}
-
-void _Stokes_SLE_UzawaSolver_Execute( void* solver, void* data ) {
-}
-
-void _Stokes_SLE_UzawaSolver_Destroy( void* solver, void* data ) {
-   Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*) solver;
-	Journal_DPrintf( self->debug, "In: %s \n", __func__);
-
-	Stream_IndentBranch( StgFEM_Debug );
-	Journal_DPrintfL( self->debug, 2, "Destroying Solver contexts.\n" );
-	KSPDestroy( self->velSolver );
-	KSPDestroy( self->pcSolver );
-
-	Journal_DPrintfL( self->debug, 2, "Destroying temporary solver vectors.\n" );
-	if( self->pTempVec != PETSC_NULL ) VecDestroy( self->pTempVec );
-	if( self->rVec != PETSC_NULL )     VecDestroy( self->rVec );
-	if( self->sVec != PETSC_NULL )     VecDestroy( self->sVec );
-	if( self->fTempVec != PETSC_NULL ) VecDestroy( self->fTempVec );
-	if( self->vStarVec != PETSC_NULL ) VecDestroy( self->vStarVec );
-	Stream_UnIndentBranch( StgFEM_Debug );
-   _SLE_Solver_Destroy( self, data );
-
-}
-
-void _Stokes_SLE_UzawaSolver_Initialise( void* solver, void* stokesSLE ) {
-	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*) solver;
-	Stokes_SLE*             sle  = (Stokes_SLE*)             stokesSLE;
-	
-	/* Initialise Parent */
-	_SLE_Solver_Initialise( self, sle );
-	
-	if ( sle->context && (True == sle->context->loadFromCheckPoint) ) {
-		/* The previous timestep's velocity solution will be helpful in iterating to a better
-		solution faster - and thus make restarting from checkpoint more repeatable compared
-		to original non-restart solution */
-		SolutionVector_LoadCurrentFeVariableValuesOntoVector( sle->uSolnVec );
-		SolutionVector_LoadCurrentFeVariableValuesOntoVector( sle->pSolnVec );
-	}
-
-}
-
-/* SolverSetup */
-
-void _Stokes_SLE_UzawaSolver_SolverSetup( void* solver, void* stokesSLE ) {
-	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*) solver;
-	Stokes_SLE*             sle  = (Stokes_SLE*)             stokesSLE;
-	
- 	Journal_DPrintf( self->debug, "In %s:\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	Journal_DPrintfL( self->debug, 1, "Setting up MatrixSolver for the velocity eqn.\n" );
-	KSPSetOperators( self->velSolver, sle->kStiffMat->matrix, sle->kStiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
-  	KSPSetFromOptions( self->velSolver );
-
-	if( self->pcSolver ) {
-		Journal_DPrintfL( self->debug, 1, "Setting up MatrixSolver for the Preconditioner.\n" );
-		KSPSetOperators( self->pcSolver, self->preconditioner->matrix, self->preconditioner->matrix, DIFFERENT_NONZERO_PATTERN );
-    		KSPSetFromOptions( self->pcSolver );
-	}
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-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;
-}
-
-void _remove_constant_nullsp( Vec v )
-{
-        PetscInt N;
-	PetscScalar sum;
-                
-	VecGetSize( v, &N );
-	if( N > 0 ) {
-		VecSum( v, &sum );
-		sum  = sum/( -1.0*N );
-		VecShift( v, sum );
-	}
-}
-
-/* from the depreciated Vector class */
-void _SLE_VectorView( Vec v, Stream* stream ) {
-	unsigned	entry_i;
-	PetscInt	size;
-	PetscScalar*	array;
-
-	VecGetSize( v, &size );
-	VecGetArray( v, &array );
-
-	Journal_Printf( stream, "%p = [", v );
-	for( entry_i = 0; entry_i < size; entry_i++ ) 
-		Journal_Printf( stream, "\t%u: \t %.12g\n", entry_i, array[entry_i] );
-	Journal_Printf( stream, "];\n" );
-
-	VecRestoreArray( v, &array );
-}
-
-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;
-
-	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" );
-	
-	KSPSetTolerances( velSolver, self->tolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
-	KSPSolve( velSolver, fVec, vStarVec );
-	KSPGetIterationNumber( velSolver, (PetscInt*)(&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{	
-		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 ) {
-			KSPSolve( pcSolver, rVec, qTempVec );
-		}
-		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!!!!
-		/*get initial wall time for inner loop*/
-		self->inneritsinitialtime = MPI_Wtime();
-		KSPSolve( velSolver, fTempVec, vStarVec );
-		/*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, (PetscInt*)(&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;
-	}	
-}
-
-void _Stokes_SLE_UzawaSolver_GetSolution( void *stokesSLE, void *solver, Vec *x )
-{
-	Stokes_SLE *sle = (Stokes_SLE*)stokesSLE;
-	Vec p = sle->pSolnVec->vector;
-
-	(*x) = p;
-}
-
-
-#undef __FUNCT__
-#define __FUNCT__ "_Stokes_SLE_UzawaSolver_GetRhs"
-void _Stokes_SLE_UzawaSolver_GetRhs( void *stokesSLE, void *solver, Vec rhs )
-{
-        Stokes_SLE_UzawaSolver *self = (Stokes_SLE_UzawaSolver*)solver;
-	Stokes_SLE *sle = (Stokes_SLE*)stokesSLE;
-	/* stg linear algebra */
-	KSP     A11_solver = self->velSolver;
-        Mat         A12 = sle->gStiffMat->matrix;
-        Vec         b1  = sle->fForceVec->vector;
-        Vec         b2  = sle->hForceVec->vector;
-        Vec         u_star = self->vStarVec;
-	
-	/* petsc variables */
-	KSP ksp_A11;
-
-	/* check operations will be valid */
-	if (sle->dStiffMat!=NULL) {   SETERRABORT( sle->comm, PETSC_ERR_SUP, "A21 must be NULL" ); }
-	if (A11_solver==NULL){    SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "vel_solver is NULL" ); }
-        if (A12==NULL){           SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "A12 is NULL" ); }
-        if (b1==NULL){       SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "b1 is NULL" ); }
-        if (b2==NULL){       SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "b2 is NULL" ); }
-        if (u_star==NULL){   SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "u* is NULL" ); }
-
-	/* Extract petsc objects */
-	ksp_A11 = A11_solver;
-
-	/* compute rhs = A12^T A11^{-1} b1 - b2 */
-	KSPSolve( ksp_A11, b1, u_star );         /* u* = A11^{-1} b1 */
-	MatMultTranspose( A12, u_star, rhs );    /* b2 = A12^T u* */
-	VecAXPY( rhs, -1.0, b2 );  /* rhs <- rhs - b2 */
-}
-
-
-/* Computes r = f_hat - S p */
-#undef __FUNCT__
-#define __FUNCT__ "_Stokes_SLE_UzawaSolver_FormResidual"
-void _Stokes_SLE_UzawaSolver_FormResidual( void *stokesSLE, void *solver, Vec r )
-{
-        Stokes_SLE_UzawaSolver *self = (Stokes_SLE_UzawaSolver*)solver;
-        Stokes_SLE *sle = (Stokes_SLE*)stokesSLE;
- 	/* stg linear algebra objects */
-        Mat         A12 = sle->gStiffMat->matrix;
-        Mat         A22 = NULL;
-        Vec         x2 = sle->pSolnVec->vector;
-        Vec         f_star = self->fTempVec;
-        Vec         u_star = self->vStarVec;
-	Vec         q_star = self->pTempVec;
-        KSP     A11_solver = self->velSolver;
-
-	/* petsc objects */
-	KSP ksp_A11;
-	PetscInt r_N, x2_N;
-
-        /* check operations will be valid */
-	if (A11_solver==NULL){   SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "vel_solver is NULL" ); }
-        if (sle->dStiffMat!=NULL) {  SETERRABORT( sle->comm, PETSC_ERR_SUP, "A21 must be NULL" ); }
-        if (A12==NULL){          SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "A12 is NULL" ); }
-        if (x2==NULL){         SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "x2 is NULL" ); }
-        if (u_star==NULL){     SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "u* is NULL" ); }
-        if (f_star==NULL){     SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "f* is NULL" ); }
-	if (q_star==NULL) {    SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "q* is NULL" ); }
-
-	A22 = PETSC_NULL;
-	if (sle->cStiffMat!=NULL) {
-		A22 = sle->cStiffMat->matrix;
-	}
-
-
-        /* Extract petsc objects */
-        ksp_A11 =     A11_solver;
-
-	/* Check sizes match */
-	VecGetSize( r, &r_N );
-	VecGetSize( x2, &x2_N );
-	if (r_N!=x2_N) {
-          SETERRABORT( sle->comm, PETSC_ERR_ARG_SIZ, "Solution vector for pressure is not compatible with residual vector" );
-	}	
-	
-	/* r = f_hat - (G^T K^{-1} G - M) p */
-	_Stokes_SLE_UzawaSolver_GetRhs( stokesSLE, solver, r );  /* r <- f_hat */
-
-	/* correct for non zero A22 */
-	if (A22!=PETSC_NULL) {
-		MatMultAdd( A22, x2, r, r );  /* r <- r + A22 p */
-	}
-
-	/* make correction r <- r - G^T K^{-1} G */
-	MatMult( A12, x2, f_star );                 /* f* <- A12 x2 */
-	KSPSolve( ksp_A11, f_star, u_star );        /* u* <- A11^{-1} f* */
-	MatMultTranspose( A12, u_star, q_star );    /* q* <- A12 u* */
-	
-	VecAXPY( r, -1.0, q_star );  /* r <- r - q* */
-}
-
-Vec _Stokes_SLE_UzawaSolver_GetResidual( void* solver, Index fv_I ) {
-	return NULL;
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_UzawaSolver.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_UzawaSolver.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,1048 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Stokes_SLE_UzawaSolver.c 1199 2008-08-08 04:03:32Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Stokes_SLE_UzawaSolver.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "Stokes_SLE.h"
+
+/* Macro to checking number integrity - i.e. checks if number is infinite or "not a number" */
+#define isGoodNumber( number ) \
+	( (! isnan( number ) ) && ( ! isinf( number ) ) )
+
+const Type Stokes_SLE_UzawaSolver_Type = "Stokes_SLE_UzawaSolver";
+
+void* _Stokes_SLE_UzawaSolver_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(Stokes_SLE_UzawaSolver);
+	Type                                                      type = Stokes_SLE_UzawaSolver_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Stokes_SLE_UzawaSolver_Delete;
+	Stg_Class_PrintFunction*                                _print = _Stokes_SLE_UzawaSolver_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Stokes_SLE_UzawaSolver_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _Stokes_SLE_UzawaSolver_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _Stokes_SLE_UzawaSolver_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Stokes_SLE_UzawaSolver_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Stokes_SLE_UzawaSolver_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _SLE_Solver_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _Stokes_SLE_UzawaSolver_Destroy;
+	SLE_Solver_SolverSetupFunction*                   _solverSetup = _Stokes_SLE_UzawaSolver_SolverSetup;
+	SLE_Solver_SolveFunction*                               _solve = _Stokes_SLE_UzawaSolver_Solve;
+	SLE_Solver_GetResidualFunc*                       _getResidual = _Stokes_SLE_UzawaSolver_GetResidual;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _Stokes_SLE_UzawaSolver_New(  STOKES_SLE_UZAWASOLVER_PASSARGS  );
+}
+
+Stokes_SLE_UzawaSolver* Stokes_SLE_UzawaSolver_New( 
+		Name                                        name,
+		Bool                                        useStatSolve, 
+		int                                         statReps,
+		StiffnessMatrix*                            preconditioner,
+		Iteration_Index                             maxUzawaIterations,
+		Iteration_Index                             minUzawaIterations,
+		double                                      tolerance,
+		Bool                                        useAbsoluteTolerance,
+                Bool                                        monitor )
+{		
+  Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)_Stokes_SLE_UzawaSolver_DefaultNew( name );
+
+	Stokes_SLE_UzawaSolver_InitAll( self, useStatSolve, statReps, preconditioner, maxUzawaIterations, minUzawaIterations, tolerance, useAbsoluteTolerance, monitor );
+
+	return self;
+}
+
+
+/* Creation implementation / Virtual constructor */
+Stokes_SLE_UzawaSolver* _Stokes_SLE_UzawaSolver_New(  STOKES_SLE_UZAWASOLVER_DEFARGS  )
+{
+	Stokes_SLE_UzawaSolver* self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Stokes_SLE_UzawaSolver) );
+	self = (Stokes_SLE_UzawaSolver*) _SLE_Solver_New(  SLE_SOLVER_PASSARGS  );
+
+	self->_formResidual  = _Stokes_SLE_UzawaSolver_FormResidual;
+        self->_getRhs        = _Stokes_SLE_UzawaSolver_GetRhs;
+	self->_getSolution   = _Stokes_SLE_UzawaSolver_GetSolution;
+	
+	/* Virtual info */
+	return self;
+}
+
+
+void _Stokes_SLE_UzawaSolver_Init( 
+		Stokes_SLE_UzawaSolver*      self,
+		StiffnessMatrix*             preconditioner, 
+		Iteration_Index              maxUzawaIterations,
+		Iteration_Index              minUzawaIterations,
+		double                       tolerance,
+		Bool                         useAbsoluteTolerance,
+                Bool                         monitor )
+{
+	self->isConstructed        = True;
+	self->tolerance            = tolerance;
+	self->maxUzawaIterations   = maxUzawaIterations;
+	self->minUzawaIterations   = minUzawaIterations;
+	self->preconditioner       = preconditioner;
+	self->useAbsoluteTolerance = useAbsoluteTolerance;
+        self->monitor              = monitor;
+}
+
+void Stokes_SLE_UzawaSolver_InitAll( 
+		void*                        solver,
+		Bool                         useStatSolve,
+		int                          statReps, 
+		StiffnessMatrix*             preconditioner, 
+		Iteration_Index              maxUzawaIterations,
+		Iteration_Index              minUzawaIterations,
+		double                       tolerance,
+		Bool                         useAbsoluteTolerance,
+                Bool                         monitor )
+{
+	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)solver;
+
+	SLE_Solver_InitAll( self, useStatSolve, statReps );
+	_Stokes_SLE_UzawaSolver_Init( self, preconditioner, maxUzawaIterations, minUzawaIterations, tolerance, useAbsoluteTolerance, monitor );
+}
+
+void _Stokes_SLE_UzawaSolver_Delete( void* solver ) {
+	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)solver;
+
+   _SLE_Solver_Delete( self );
+		
+}       
+
+
+void _Stokes_SLE_UzawaSolver_Print( void* solver, Stream* stream ) {
+	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)solver;
+
+	_SLE_Solver_Print( self, stream );
+
+	Journal_PrintValue( stream, self->tolerance );
+	Journal_PrintValue( stream, self->maxUzawaIterations );
+	Journal_PrintValue( stream, self->minUzawaIterations );
+}
+
+
+void* _Stokes_SLE_UzawaSolver_Copy( const void* stokesSleUzawaSolver, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*)stokesSleUzawaSolver;
+	Stokes_SLE_UzawaSolver*	newStokesSleUzawaSolver;
+	
+	newStokesSleUzawaSolver = (Stokes_SLE_UzawaSolver*)_SLE_Solver_Copy( self, dest, deep, nameExt, ptrMap );
+	
+	newStokesSleUzawaSolver->velSolver           = self->velSolver;
+	newStokesSleUzawaSolver->pcSolver            = self->pcSolver;
+	newStokesSleUzawaSolver->preconditioner      = self->preconditioner;
+	newStokesSleUzawaSolver->pTempVec            = self->pTempVec;
+	newStokesSleUzawaSolver->rVec                = self->rVec;
+	newStokesSleUzawaSolver->sVec                = self->sVec;
+	newStokesSleUzawaSolver->fTempVec            = self->fTempVec;
+	newStokesSleUzawaSolver->vStarVec            = self->vStarVec;
+	newStokesSleUzawaSolver->tolerance           = self->tolerance;
+	newStokesSleUzawaSolver->maxUzawaIterations  = self->maxUzawaIterations;
+	newStokesSleUzawaSolver->minUzawaIterations  = self->minUzawaIterations;
+	newStokesSleUzawaSolver->useAbsoluteTolerance  = self->useAbsoluteTolerance;
+	newStokesSleUzawaSolver->monitor               = self->monitor;	
+
+	return (void*) newStokesSleUzawaSolver;
+}
+
+
+void _Stokes_SLE_UzawaSolver_Build( void* solver, void* stokesSLE ) {
+	Stokes_SLE_UzawaSolver*	self  = (Stokes_SLE_UzawaSolver*)solver;
+	Stokes_SLE*             sle   = (Stokes_SLE*)stokesSLE;
+
+ 	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+	
+ 	Journal_DPrintfL( self->debug, 2, "building a standard solver for the velocity system.\n" );
+	KSPCreate( sle->comm, &self->velSolver );
+	
+	/* Build Preconditioner */
+	if ( self->preconditioner ) {
+		Stg_Component_Build( self->preconditioner, stokesSLE, False );
+		SystemLinearEquations_AddStiffnessMatrix( sle, self->preconditioner );
+
+		Journal_DPrintfL( self->debug, 2, "build a standard solver for the preconditioner system.\n" );
+		KSPCreate( sle->comm, &self->pcSolver );
+	}
+	else 
+		self->pcSolver = PETSC_NULL;
+
+	if( self->pTempVec != PETSC_NULL ) VecDestroy( self->pTempVec );
+	if( self->rVec != PETSC_NULL )     VecDestroy( self->rVec );
+	if( self->sVec != PETSC_NULL )     VecDestroy( self->sVec );
+	if( self->fTempVec != PETSC_NULL ) VecDestroy( self->fTempVec );
+	if( self->vStarVec != PETSC_NULL ) VecDestroy( self->vStarVec );
+
+ 	Journal_DPrintfL( self->debug, 2, "Allocate the auxillary vectors pTemp, r, s, fTemp and vStar.\n" ); 
+	VecDuplicate( sle->pSolnVec->vector, &self->pTempVec );
+	VecDuplicate( sle->pSolnVec->vector, &self->rVec );
+	VecDuplicate( sle->pSolnVec->vector, &self->sVec );
+
+	VecDuplicate( sle->fForceVec->vector, &self->fTempVec );
+	VecDuplicate( sle->fForceVec->vector, &self->vStarVec );
+
+	/* Need by the Picard nonlinear solver */
+//        Vector_Duplicate( sle->pTempVec->vector, (void**)&self->f_hat );
+//        Vector_SetLocalSize( self->vf_hat, Vector_GetLocalSize( sle->pTempVec->vector ) );
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _Stokes_SLE_UzawaSolver_AssignFromXML( void* solver, Stg_ComponentFactory* cf, void* data ) {
+	Stokes_SLE_UzawaSolver* self         = (Stokes_SLE_UzawaSolver*) solver;
+	double                  tolerance;
+	Iteration_Index         maxUzawaIterations, minUzawaIterations;
+	StiffnessMatrix*        preconditioner;
+	Bool                    useAbsoluteTolerance;
+	Bool                    monitor;
+
+	_SLE_Solver_AssignFromXML( self, cf, data );
+
+	tolerance            = Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"tolerance", 1.0e-5  );
+	maxUzawaIterations   = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"maxIterations", 1000  );
+	minUzawaIterations   = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"minIterations", 1  );
+	useAbsoluteTolerance = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"useAbsoluteTolerance", False  );
+	monitor              = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"monitor", False  );
+
+	preconditioner = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Preconditioner", StiffnessMatrix, False, data  );
+
+	_Stokes_SLE_UzawaSolver_Init( self, preconditioner, maxUzawaIterations, minUzawaIterations, tolerance, useAbsoluteTolerance, monitor );
+
+	if( self->velSolver == PETSC_NULL ) {
+		KSPCreate( MPI_COMM_WORLD, &self->velSolver );
+	}
+}
+
+void _Stokes_SLE_UzawaSolver_Execute( void* solver, void* data ) {
+}
+
+void _Stokes_SLE_UzawaSolver_Destroy( void* solver, void* data ) {
+   Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*) solver;
+	Journal_DPrintf( self->debug, "In: %s \n", __func__);
+
+	Stream_IndentBranch( StgFEM_Debug );
+	Journal_DPrintfL( self->debug, 2, "Destroying Solver contexts.\n" );
+	KSPDestroy( self->velSolver );
+	KSPDestroy( self->pcSolver );
+
+	Journal_DPrintfL( self->debug, 2, "Destroying temporary solver vectors.\n" );
+	if( self->pTempVec != PETSC_NULL ) VecDestroy( self->pTempVec );
+	if( self->rVec != PETSC_NULL )     VecDestroy( self->rVec );
+	if( self->sVec != PETSC_NULL )     VecDestroy( self->sVec );
+	if( self->fTempVec != PETSC_NULL ) VecDestroy( self->fTempVec );
+	if( self->vStarVec != PETSC_NULL ) VecDestroy( self->vStarVec );
+	Stream_UnIndentBranch( StgFEM_Debug );
+   _SLE_Solver_Destroy( self, data );
+
+}
+
+void _Stokes_SLE_UzawaSolver_Initialise( void* solver, void* stokesSLE ) {
+	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*) solver;
+	Stokes_SLE*             sle  = (Stokes_SLE*)             stokesSLE;
+	
+	/* Initialise Parent */
+	_SLE_Solver_Initialise( self, sle );
+	
+	if ( sle->context && (True == sle->context->loadFromCheckPoint) ) {
+		/* The previous timestep's velocity solution will be helpful in iterating to a better
+		solution faster - and thus make restarting from checkpoint more repeatable compared
+		to original non-restart solution */
+		SolutionVector_LoadCurrentFeVariableValuesOntoVector( sle->uSolnVec );
+		SolutionVector_LoadCurrentFeVariableValuesOntoVector( sle->pSolnVec );
+	}
+
+}
+
+/* SolverSetup */
+
+void _Stokes_SLE_UzawaSolver_SolverSetup( void* solver, void* stokesSLE ) {
+	Stokes_SLE_UzawaSolver* self = (Stokes_SLE_UzawaSolver*) solver;
+	Stokes_SLE*             sle  = (Stokes_SLE*)             stokesSLE;
+	
+ 	Journal_DPrintf( self->debug, "In %s:\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	Journal_DPrintfL( self->debug, 1, "Setting up MatrixSolver for the velocity eqn.\n" );
+	KSPSetOperators( self->velSolver, sle->kStiffMat->matrix, sle->kStiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
+  	KSPSetFromOptions( self->velSolver );
+
+	if( self->pcSolver ) {
+		Journal_DPrintfL( self->debug, 1, "Setting up MatrixSolver for the Preconditioner.\n" );
+		KSPSetOperators( self->pcSolver, self->preconditioner->matrix, self->preconditioner->matrix, DIFFERENT_NONZERO_PATTERN );
+    		KSPSetFromOptions( self->pcSolver );
+	}
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+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;
+}
+
+void _remove_constant_nullsp( Vec v )
+{
+        PetscInt N;
+	PetscScalar sum;
+                
+	VecGetSize( v, &N );
+	if( N > 0 ) {
+		VecSum( v, &sum );
+		sum  = sum/( -1.0*N );
+		VecShift( v, sum );
+	}
+}
+
+/* from the depreciated Vector class */
+void _SLE_VectorView( Vec v, Stream* stream ) {
+	unsigned	entry_i;
+	PetscInt	size;
+	PetscScalar*	array;
+
+	VecGetSize( v, &size );
+	VecGetArray( v, &array );
+
+	Journal_Printf( stream, "%p = [", v );
+	for( entry_i = 0; entry_i < size; entry_i++ ) 
+		Journal_Printf( stream, "\t%u: \t %.12g\n", entry_i, array[entry_i] );
+	Journal_Printf( stream, "];\n" );
+
+	VecRestoreArray( v, &array );
+}
+
+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;
+
+	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" );
+	
+	KSPSetTolerances( velSolver, self->tolerance, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
+	KSPSolve( velSolver, fVec, vStarVec );
+	KSPGetIterationNumber( velSolver, (PetscInt*)(&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{	
+		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 ) {
+			KSPSolve( pcSolver, rVec, qTempVec );
+		}
+		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!!!!
+		/*get initial wall time for inner loop*/
+		self->inneritsinitialtime = MPI_Wtime();
+		KSPSolve( velSolver, fTempVec, vStarVec );
+		/*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, (PetscInt*)(&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;
+	}	
+}
+
+void _Stokes_SLE_UzawaSolver_GetSolution( void *stokesSLE, void *solver, Vec *x )
+{
+	Stokes_SLE *sle = (Stokes_SLE*)stokesSLE;
+	Vec p = sle->pSolnVec->vector;
+
+	(*x) = p;
+}
+
+
+#undef __FUNCT__
+#define __FUNCT__ "_Stokes_SLE_UzawaSolver_GetRhs"
+void _Stokes_SLE_UzawaSolver_GetRhs( void *stokesSLE, void *solver, Vec rhs )
+{
+        Stokes_SLE_UzawaSolver *self = (Stokes_SLE_UzawaSolver*)solver;
+	Stokes_SLE *sle = (Stokes_SLE*)stokesSLE;
+	/* stg linear algebra */
+	KSP     A11_solver = self->velSolver;
+        Mat         A12 = sle->gStiffMat->matrix;
+        Vec         b1  = sle->fForceVec->vector;
+        Vec         b2  = sle->hForceVec->vector;
+        Vec         u_star = self->vStarVec;
+	
+	/* petsc variables */
+	KSP ksp_A11;
+
+	/* check operations will be valid */
+	if (sle->dStiffMat!=NULL) {   SETERRABORT( sle->comm, PETSC_ERR_SUP, "A21 must be NULL" ); }
+	if (A11_solver==NULL){    SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "vel_solver is NULL" ); }
+        if (A12==NULL){           SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "A12 is NULL" ); }
+        if (b1==NULL){       SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "b1 is NULL" ); }
+        if (b2==NULL){       SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "b2 is NULL" ); }
+        if (u_star==NULL){   SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "u* is NULL" ); }
+
+	/* Extract petsc objects */
+	ksp_A11 = A11_solver;
+
+	/* compute rhs = A12^T A11^{-1} b1 - b2 */
+	KSPSolve( ksp_A11, b1, u_star );         /* u* = A11^{-1} b1 */
+	MatMultTranspose( A12, u_star, rhs );    /* b2 = A12^T u* */
+	VecAXPY( rhs, -1.0, b2 );  /* rhs <- rhs - b2 */
+}
+
+
+/* Computes r = f_hat - S p */
+#undef __FUNCT__
+#define __FUNCT__ "_Stokes_SLE_UzawaSolver_FormResidual"
+void _Stokes_SLE_UzawaSolver_FormResidual( void *stokesSLE, void *solver, Vec r )
+{
+        Stokes_SLE_UzawaSolver *self = (Stokes_SLE_UzawaSolver*)solver;
+        Stokes_SLE *sle = (Stokes_SLE*)stokesSLE;
+ 	/* stg linear algebra objects */
+        Mat         A12 = sle->gStiffMat->matrix;
+        Mat         A22 = NULL;
+        Vec         x2 = sle->pSolnVec->vector;
+        Vec         f_star = self->fTempVec;
+        Vec         u_star = self->vStarVec;
+	Vec         q_star = self->pTempVec;
+        KSP     A11_solver = self->velSolver;
+
+	/* petsc objects */
+	KSP ksp_A11;
+	PetscInt r_N, x2_N;
+
+        /* check operations will be valid */
+	if (A11_solver==NULL){   SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "vel_solver is NULL" ); }
+        if (sle->dStiffMat!=NULL) {  SETERRABORT( sle->comm, PETSC_ERR_SUP, "A21 must be NULL" ); }
+        if (A12==NULL){          SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "A12 is NULL" ); }
+        if (x2==NULL){         SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "x2 is NULL" ); }
+        if (u_star==NULL){     SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "u* is NULL" ); }
+        if (f_star==NULL){     SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "f* is NULL" ); }
+	if (q_star==NULL) {    SETERRABORT( sle->comm, PETSC_ERR_ARG_NULL, "q* is NULL" ); }
+
+	A22 = PETSC_NULL;
+	if (sle->cStiffMat!=NULL) {
+		A22 = sle->cStiffMat->matrix;
+	}
+
+
+        /* Extract petsc objects */
+        ksp_A11 =     A11_solver;
+
+	/* Check sizes match */
+	VecGetSize( r, &r_N );
+	VecGetSize( x2, &x2_N );
+	if (r_N!=x2_N) {
+          SETERRABORT( sle->comm, PETSC_ERR_ARG_SIZ, "Solution vector for pressure is not compatible with residual vector" );
+	}	
+	
+	/* r = f_hat - (G^T K^{-1} G - M) p */
+	_Stokes_SLE_UzawaSolver_GetRhs( stokesSLE, solver, r );  /* r <- f_hat */
+
+	/* correct for non zero A22 */
+	if (A22!=PETSC_NULL) {
+		MatMultAdd( A22, x2, r, r );  /* r <- r + A22 p */
+	}
+
+	/* make correction r <- r - G^T K^{-1} G */
+	MatMult( A12, x2, f_star );                 /* f* <- A12 x2 */
+	KSPSolve( ksp_A11, f_star, u_star );        /* u* <- A11^{-1} f* */
+	MatMultTranspose( A12, u_star, q_star );    /* q* <- A12 u* */
+	
+	VecAXPY( r, -1.0, q_star );  /* r <- r - q* */
+}
+
+Vec _Stokes_SLE_UzawaSolver_GetResidual( void* solver, Index fv_I ) {
+	return NULL;
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/UpdateDt.c
--- a/SLE/ProvidedSystems/StokesFlow/src/UpdateDt.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: UpdateDt.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "types.h"
-#include "Stokes_SLE.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-double Stokes_SLE_UpdateDt( Stokes_SLE* self, FiniteElementContext* context ) {
-	double                  velMax        = 0;
-	double                  minSeparation = 0;
-	double                  minSeparationEachDim[3] = { 0, 0, 0 };
-	FeVariable*             velFeVar      = NULL;
-	double			localDt;
-	double			globalDt;
-        Dictionary*             dictionary = context->dictionary;
-        double factor;
-	
-        globalDt=Dictionary_GetDouble_WithDefault(dictionary,"dt",0.0);
-        
-        if(globalDt==0.0)
-          {
-            velFeVar = self->uSolnVec->feVariable;
-            velMax = FieldVariable_GetMaxGlobalFieldMagnitude( velFeVar );
-            
-            Journal_DPrintf( self->debug, "In func %s for SLE '%s' - Maximum global magnitude for field '%s' = %g.\n",
-                             __func__, self->name, velFeVar->name, velMax );
-            
-            FeVariable_GetMinimumSeparation( velFeVar, &minSeparation, minSeparationEachDim );
-            
-            factor=Dictionary_GetDouble_WithDefault(dictionary,"dtFactor",1.0);
-            localDt = factor*0.5 * minSeparation / velMax;
-
-            MPI_Allreduce( &localDt, &globalDt, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
-          }
-	return globalDt;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/UpdateDt.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/StokesFlow/src/UpdateDt.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,83 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: UpdateDt.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "types.h"
+#include "Stokes_SLE.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+double Stokes_SLE_UpdateDt( Stokes_SLE* self, FiniteElementContext* context ) {
+	double                  velMax        = 0;
+	double                  minSeparation = 0;
+	double                  minSeparationEachDim[3] = { 0, 0, 0 };
+	FeVariable*             velFeVar      = NULL;
+	double			localDt;
+	double			globalDt;
+        Dictionary*             dictionary = context->dictionary;
+        double factor;
+	
+        globalDt=Dictionary_GetDouble_WithDefault(dictionary,"dt",0.0);
+        
+        if(globalDt==0.0)
+          {
+            velFeVar = self->uSolnVec->feVariable;
+            velMax = FieldVariable_GetMaxGlobalFieldMagnitude( velFeVar );
+            
+            Journal_DPrintf( self->debug, "In func %s for SLE '%s' - Maximum global magnitude for field '%s' = %g.\n",
+                             __func__, self->name, velFeVar->name, velMax );
+            
+            FeVariable_GetMinimumSeparation( velFeVar, &minSeparation, minSeparationEachDim );
+            
+            factor=Dictionary_GetDouble_WithDefault(dictionary,"dtFactor",1.0);
+            localDt = factor*0.5 * minSeparation / velMax;
+
+            MPI_Allreduce( &localDt, &globalDt, 1, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD );
+          }
+	return globalDt;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/UzawaPreconditionerTerm.c
--- a/SLE/ProvidedSystems/StokesFlow/src/UzawaPreconditionerTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: UzawaPreconditionerTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
-
-#include "types.h"
-#include "UzawaPreconditionerTerm.h"
-#include "Stokes_SLE.h"
-
-#include <assert.h>
-#include <string.h>
-
-/* Textual name of this class */
-const Type UzawaPreconditionerTerm_Type = "UzawaPreconditionerTerm";
-
-UzawaPreconditionerTerm* UzawaPreconditionerTerm_New( 
-	Name							name,
-	FiniteElementContext*	context,
-	StiffnessMatrix*			stiffnessMatrix,
-	Swarm*						integrationSwarm )
-{
-	UzawaPreconditionerTerm* self = (UzawaPreconditionerTerm*) _UzawaPreconditionerTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
-	_UzawaPreconditionerTerm_Init( self );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-UzawaPreconditionerTerm* _UzawaPreconditionerTerm_New(  UZAWAPRECONDITIONERTERM_DEFARGS  )
-{
-	UzawaPreconditionerTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(UzawaPreconditionerTerm) );
-	self = (UzawaPreconditionerTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _UzawaPreconditionerTerm_Init( void* matrixTerm ) {
-}
-
-void _UzawaPreconditionerTerm_Delete( void* matrixTerm ) {
-	UzawaPreconditionerTerm* self = (UzawaPreconditionerTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Delete( self );
-}
-
-void _UzawaPreconditionerTerm_Print( void* matrixTerm, Stream* stream ) {
-	UzawaPreconditionerTerm* self = (UzawaPreconditionerTerm*)matrixTerm;
-	
-	_StiffnessMatrixTerm_Print( self, stream );
-
-	/* General info */
-}
-
-void* _UzawaPreconditionerTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(UzawaPreconditionerTerm);
-	Type                                                         type = UzawaPreconditionerTerm_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _UzawaPreconditionerTerm_Delete;
-	Stg_Class_PrintFunction*                                   _print = _UzawaPreconditionerTerm_Print;
-	Stg_Class_CopyFunction*                                     _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _UzawaPreconditionerTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _UzawaPreconditionerTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _UzawaPreconditionerTerm_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _UzawaPreconditionerTerm_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _UzawaPreconditionerTerm_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _UzawaPreconditionerTerm_Destroy;
-	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _UzawaPreconditionerTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*)_UzawaPreconditionerTerm_New(  UZAWAPRECONDITIONERTERM_PASSARGS  );
-}
-
-void _UzawaPreconditionerTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
-	UzawaPreconditionerTerm*            self             = (UzawaPreconditionerTerm*)matrixTerm;
-
-	/* Construct Parent */
-	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
-
-	_UzawaPreconditionerTerm_Init( self );
-}
-
-void _UzawaPreconditionerTerm_Build( void* matrixTerm, void* data ) {
-	UzawaPreconditionerTerm*             self             = (UzawaPreconditionerTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Build( self, data );
-}
-
-void _UzawaPreconditionerTerm_Initialise( void* matrixTerm, void* data ) {
-	UzawaPreconditionerTerm*             self             = (UzawaPreconditionerTerm*)matrixTerm;
-
-	_StiffnessMatrixTerm_Initialise( self, data );
-}
-
-void _UzawaPreconditionerTerm_Execute( void* matrixTerm, void* data ) {
-	_StiffnessMatrixTerm_Execute( matrixTerm, data );
-}
-
-void _UzawaPreconditionerTerm_Destroy( void* matrixTerm, void* data ) {
-	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
-}
-
-
-void _UzawaPreconditionerTerm_AssembleElement( 
-		void*                                              matrixTerm,
-		StiffnessMatrix*                                   stiffnessMatrix, 
-		Element_LocalIndex                                 lElement_I, 
-		SystemLinearEquations*                             _sle,
-		FiniteElementContext*                              context,
-		double**                                           elPreconditioner ) 
-{
-	Stokes_SLE*            sle              = Stg_DCheckType( _sle, Stokes_SLE );
-	StiffnessMatrix*       gMatrix          = sle->gStiffMat;
-	FeVariable*            gFeVariable_col  = gMatrix->columnVariable;
-	ElementType*           gElementType_col = FeMesh_GetElementType( gFeVariable_col->feMesh, lElement_I );
-	Node_ElementLocalIndex gColCount        = gElementType_col->nodeCount;
-	double**               gElementMatrix;
-
-	StiffnessMatrix*       kMatrix          = sle->kStiffMat;
-	FeVariable*            kFeVariable_row  = kMatrix->rowVariable;
-	ElementType*           kElementType_row = FeMesh_GetElementType( kFeVariable_row->feMesh, lElement_I );
-	Node_ElementLocalIndex kRowCount        = kElementType_row->nodeCount;
-
-	Index                  velocityDofCount;
-	Index                  pressureDofCount;
-	double**               kElementMatrix;
-
-	double**               kInverseG;
-	Index                  row_I;
-	Index                  col_I;
-	Index                  vel_I;
-
-	pressureDofCount = gColCount;
-	velocityDofCount = kRowCount * kMatrix->dim;
-
-	/* Allocate Memory */
-	gElementMatrix = Memory_Alloc_2DArray( double, velocityDofCount, pressureDofCount, (Name)"g element matrix"  );
-	memset( gElementMatrix[0], 0, sizeof(double) * velocityDofCount * pressureDofCount );
-	kElementMatrix = Memory_Alloc_2DArray( double, velocityDofCount, velocityDofCount, (Name)"k element matrix"  );
-	memset( kElementMatrix[0], 0, sizeof(double) * velocityDofCount * velocityDofCount );
-	kInverseG      = Memory_Alloc_2DArray( double, velocityDofCount, pressureDofCount, (Name)"[ diag(K) ]^-1 G"  );
-
-	/* Assemble Element G */
-	StiffnessMatrix_AssembleElement( gMatrix, lElement_I, _sle, context, gElementMatrix );
-
-	/* Assemble Element K */
-	StiffnessMatrix_AssembleElement( kMatrix, lElement_I, _sle, context, kElementMatrix );
-
-	/* Assemble [ diag(K) ]^-1 G */
-	for ( row_I = 0 ; row_I < velocityDofCount ; row_I++ ) {
-		for ( col_I = 0 ; col_I < pressureDofCount ; col_I++ ) {
-			kInverseG[ row_I ][ col_I ] = gElementMatrix[ row_I ][ col_I ] / kElementMatrix[ row_I ][ row_I ];
-		}
-	}
-
-	/* Assemble Gt [ diag(K) ]^-1 G */
-	for ( row_I = 0 ; row_I < pressureDofCount ; row_I++ ) {
-		for ( col_I = 0 ; col_I < pressureDofCount ; col_I++ ) {
-
-			for ( vel_I = 0 ; vel_I < velocityDofCount ; vel_I++ ) 
-				elPreconditioner[ row_I ][ col_I ] += gElementMatrix[ vel_I ][ col_I ] * kInverseG[ vel_I ][ row_I ];
-		}
-	}
-	Memory_Free( kInverseG );
-	Memory_Free( gElementMatrix );
-	Memory_Free( kElementMatrix );
-
-
-	/* Correct for Compressibility */
-	if ( sle->cStiffMat ) {
-		double**               mElementMatrix;
-		StiffnessMatrix*       cMatrix        = sle->cStiffMat;
-		
-		mElementMatrix = Memory_Alloc_2DArray( double, pressureDofCount, pressureDofCount, (Name)"m element matrix"  );
-		memset( mElementMatrix[0], 0, sizeof(double) * pressureDofCount * pressureDofCount );
-
-		StiffnessMatrix_AssembleElement( cMatrix, lElement_I, _sle, context, mElementMatrix );
-
-		for ( row_I = 0 ; row_I < pressureDofCount ; row_I++ ) {
-			for ( col_I = 0 ; col_I < pressureDofCount ; col_I++ ) {
-				elPreconditioner[ row_I ][ col_I ] -= mElementMatrix[ row_I ][ col_I ];
-			}
-		}
-
-		Memory_Free( mElementMatrix );
-	}
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/StokesFlow/src/UzawaPreconditionerTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/StokesFlow/src/UzawaPreconditionerTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,241 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: UzawaPreconditionerTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/SLE/SystemSetup/SystemSetup.h>
+
+#include "types.h"
+#include "UzawaPreconditionerTerm.h"
+#include "Stokes_SLE.h"
+
+#include <assert.h>
+#include <string.h>
+
+/* Textual name of this class */
+const Type UzawaPreconditionerTerm_Type = "UzawaPreconditionerTerm";
+
+UzawaPreconditionerTerm* UzawaPreconditionerTerm_New( 
+	Name							name,
+	FiniteElementContext*	context,
+	StiffnessMatrix*			stiffnessMatrix,
+	Swarm*						integrationSwarm )
+{
+	UzawaPreconditionerTerm* self = (UzawaPreconditionerTerm*) _UzawaPreconditionerTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, NULL );
+	_UzawaPreconditionerTerm_Init( self );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+UzawaPreconditionerTerm* _UzawaPreconditionerTerm_New(  UZAWAPRECONDITIONERTERM_DEFARGS  )
+{
+	UzawaPreconditionerTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(UzawaPreconditionerTerm) );
+	self = (UzawaPreconditionerTerm*) _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _UzawaPreconditionerTerm_Init( void* matrixTerm ) {
+}
+
+void _UzawaPreconditionerTerm_Delete( void* matrixTerm ) {
+	UzawaPreconditionerTerm* self = (UzawaPreconditionerTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Delete( self );
+}
+
+void _UzawaPreconditionerTerm_Print( void* matrixTerm, Stream* stream ) {
+	UzawaPreconditionerTerm* self = (UzawaPreconditionerTerm*)matrixTerm;
+	
+	_StiffnessMatrixTerm_Print( self, stream );
+
+	/* General info */
+}
+
+void* _UzawaPreconditionerTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(UzawaPreconditionerTerm);
+	Type                                                         type = UzawaPreconditionerTerm_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _UzawaPreconditionerTerm_Delete;
+	Stg_Class_PrintFunction*                                   _print = _UzawaPreconditionerTerm_Print;
+	Stg_Class_CopyFunction*                                     _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _UzawaPreconditionerTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _UzawaPreconditionerTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _UzawaPreconditionerTerm_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _UzawaPreconditionerTerm_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _UzawaPreconditionerTerm_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _UzawaPreconditionerTerm_Destroy;
+	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _UzawaPreconditionerTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*)_UzawaPreconditionerTerm_New(  UZAWAPRECONDITIONERTERM_PASSARGS  );
+}
+
+void _UzawaPreconditionerTerm_AssignFromXML( void* matrixTerm, Stg_ComponentFactory* cf, void* data ) {
+	UzawaPreconditionerTerm*            self             = (UzawaPreconditionerTerm*)matrixTerm;
+
+	/* Construct Parent */
+	_StiffnessMatrixTerm_AssignFromXML( self, cf, data );
+
+	_UzawaPreconditionerTerm_Init( self );
+}
+
+void _UzawaPreconditionerTerm_Build( void* matrixTerm, void* data ) {
+	UzawaPreconditionerTerm*             self             = (UzawaPreconditionerTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Build( self, data );
+}
+
+void _UzawaPreconditionerTerm_Initialise( void* matrixTerm, void* data ) {
+	UzawaPreconditionerTerm*             self             = (UzawaPreconditionerTerm*)matrixTerm;
+
+	_StiffnessMatrixTerm_Initialise( self, data );
+}
+
+void _UzawaPreconditionerTerm_Execute( void* matrixTerm, void* data ) {
+	_StiffnessMatrixTerm_Execute( matrixTerm, data );
+}
+
+void _UzawaPreconditionerTerm_Destroy( void* matrixTerm, void* data ) {
+	_StiffnessMatrixTerm_Destroy( matrixTerm, data );
+}
+
+
+void _UzawaPreconditionerTerm_AssembleElement( 
+		void*                                              matrixTerm,
+		StiffnessMatrix*                                   stiffnessMatrix, 
+		Element_LocalIndex                                 lElement_I, 
+		SystemLinearEquations*                             _sle,
+		FiniteElementContext*                              context,
+		double**                                           elPreconditioner ) 
+{
+	Stokes_SLE*            sle              = Stg_DCheckType( _sle, Stokes_SLE );
+	StiffnessMatrix*       gMatrix          = sle->gStiffMat;
+	FeVariable*            gFeVariable_col  = gMatrix->columnVariable;
+	ElementType*           gElementType_col = FeMesh_GetElementType( gFeVariable_col->feMesh, lElement_I );
+	Node_ElementLocalIndex gColCount        = gElementType_col->nodeCount;
+	double**               gElementMatrix;
+
+	StiffnessMatrix*       kMatrix          = sle->kStiffMat;
+	FeVariable*            kFeVariable_row  = kMatrix->rowVariable;
+	ElementType*           kElementType_row = FeMesh_GetElementType( kFeVariable_row->feMesh, lElement_I );
+	Node_ElementLocalIndex kRowCount        = kElementType_row->nodeCount;
+
+	Index                  velocityDofCount;
+	Index                  pressureDofCount;
+	double**               kElementMatrix;
+
+	double**               kInverseG;
+	Index                  row_I;
+	Index                  col_I;
+	Index                  vel_I;
+
+	pressureDofCount = gColCount;
+	velocityDofCount = kRowCount * kMatrix->dim;
+
+	/* Allocate Memory */
+	gElementMatrix = Memory_Alloc_2DArray( double, velocityDofCount, pressureDofCount, (Name)"g element matrix"  );
+	memset( gElementMatrix[0], 0, sizeof(double) * velocityDofCount * pressureDofCount );
+	kElementMatrix = Memory_Alloc_2DArray( double, velocityDofCount, velocityDofCount, (Name)"k element matrix"  );
+	memset( kElementMatrix[0], 0, sizeof(double) * velocityDofCount * velocityDofCount );
+	kInverseG      = Memory_Alloc_2DArray( double, velocityDofCount, pressureDofCount, (Name)"[ diag(K) ]^-1 G"  );
+
+	/* Assemble Element G */
+	StiffnessMatrix_AssembleElement( gMatrix, lElement_I, _sle, context, gElementMatrix );
+
+	/* Assemble Element K */
+	StiffnessMatrix_AssembleElement( kMatrix, lElement_I, _sle, context, kElementMatrix );
+
+	/* Assemble [ diag(K) ]^-1 G */
+	for ( row_I = 0 ; row_I < velocityDofCount ; row_I++ ) {
+		for ( col_I = 0 ; col_I < pressureDofCount ; col_I++ ) {
+			kInverseG[ row_I ][ col_I ] = gElementMatrix[ row_I ][ col_I ] / kElementMatrix[ row_I ][ row_I ];
+		}
+	}
+
+	/* Assemble Gt [ diag(K) ]^-1 G */
+	for ( row_I = 0 ; row_I < pressureDofCount ; row_I++ ) {
+		for ( col_I = 0 ; col_I < pressureDofCount ; col_I++ ) {
+
+			for ( vel_I = 0 ; vel_I < velocityDofCount ; vel_I++ ) 
+				elPreconditioner[ row_I ][ col_I ] += gElementMatrix[ vel_I ][ col_I ] * kInverseG[ vel_I ][ row_I ];
+		}
+	}
+	Memory_Free( kInverseG );
+	Memory_Free( gElementMatrix );
+	Memory_Free( kElementMatrix );
+
+
+	/* Correct for Compressibility */
+	if ( sle->cStiffMat ) {
+		double**               mElementMatrix;
+		StiffnessMatrix*       cMatrix        = sle->cStiffMat;
+		
+		mElementMatrix = Memory_Alloc_2DArray( double, pressureDofCount, pressureDofCount, (Name)"m element matrix"  );
+		memset( mElementMatrix[0], 0, sizeof(double) * pressureDofCount * pressureDofCount );
+
+		StiffnessMatrix_AssembleElement( cMatrix, lElement_I, _sle, context, mElementMatrix );
+
+		for ( row_I = 0 ; row_I < pressureDofCount ; row_I++ ) {
+			for ( col_I = 0 ; col_I < pressureDofCount ; col_I++ ) {
+				elPreconditioner[ row_I ][ col_I ] -= mElementMatrix[ row_I ][ col_I ];
+			}
+		}
+
+		Memory_Free( mElementMatrix );
+	}
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/src/Finalise.c
--- a/SLE/ProvidedSystems/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "StgFEM/SLE/ProvidedSystems/Energy/Energy.h"
-#include "StgFEM/SLE/ProvidedSystems/StokesFlow/StokesFlow.h"
-#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
-#include "Finalise.h"
-
-#include <stdio.h>
-
-Bool StgFEM_SLE_ProvidedSystems_Finalise( void ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	StgFEM_SLE_ProvidedSystems_Energy_Finalise();
-	StgFEM_SLE_ProvidedSystems_StokesFlow_Finalise();
-	StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Finalise();
-
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,64 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "StgFEM/SLE/ProvidedSystems/Energy/Energy.h"
+#include "StgFEM/SLE/ProvidedSystems/StokesFlow/StokesFlow.h"
+#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
+#include "Finalise.h"
+
+#include <stdio.h>
+
+Bool StgFEM_SLE_ProvidedSystems_Finalise( void ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	StgFEM_SLE_ProvidedSystems_Energy_Finalise();
+	StgFEM_SLE_ProvidedSystems_StokesFlow_Finalise();
+	StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Finalise();
+
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/src/Init.c
--- a/SLE/ProvidedSystems/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "StgFEM/SLE/ProvidedSystems/Energy/Energy.h"
-#include "StgFEM/SLE/ProvidedSystems/StokesFlow/StokesFlow.h"
-#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
-#include "Init.h"
-
-#include <stdio.h>
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_SLE_ProvidedSystems_Init( int* argc, char** argv[] ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	StgFEM_SLE_ProvidedSystems_Energy_Init( argc, argv );
-	StgFEM_SLE_ProvidedSystems_StokesFlow_Init( argc, argv );
-	StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Init( argc, argv );
-	
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/ProvidedSystems/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/ProvidedSystems/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,66 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "StgFEM/SLE/ProvidedSystems/Energy/Energy.h"
+#include "StgFEM/SLE/ProvidedSystems/StokesFlow/StokesFlow.h"
+#include "StgFEM/SLE/ProvidedSystems/AdvectionDiffusion/AdvectionDiffusion.h"
+#include "Init.h"
+
+#include <stdio.h>
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_SLE_ProvidedSystems_Init( int* argc, char** argv[] ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	StgFEM_SLE_ProvidedSystems_Energy_Init( argc, argv );
+	StgFEM_SLE_ProvidedSystems_StokesFlow_Init( argc, argv );
+	StgFEM_SLE_ProvidedSystems_AdvectionDiffusion_Init( argc, argv );
+	
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/Assembler.c
--- a/SLE/SystemSetup/src/Assembler.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,423 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Assembler.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "Discretisation/Discretisation.h"
-#include "SystemSetup.h"
-
-
-/* Textual name of this class */
-const Type Assembler_Type = "Assembler";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-Assembler* Assembler_New() {
-	/* Variables set in this function */
-	SizeT                      _sizeOfSelf = sizeof(Assembler);
-	Type                              type = Assembler_Type;
-	Stg_Class_DeleteFunction*      _delete = _Assembler_Delete;
-	Stg_Class_PrintFunction*        _print = _Assembler_Print;
-	Stg_Class_CopyFunction*          _copy = NULL;
-
-        return _Assembler_New(  ASSEMBLER_PASSARGS  );
-}
-
-Assembler* _Assembler_New(  ASSEMBLER_DEFARGS  ) {
-	Assembler*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(Assembler) );
-	self = (Assembler*)_Stg_Class_New(  STG_CLASS_PASSARGS  );
-
-	/* Virtual info */
-
-	/* Assembler info */
-	_Assembler_Init( self );
-
-	return self;
-}
-
-void _Assembler_Init( Assembler* self ) {
-	assert( self && Stg_CheckType( self, Assembler ) );
-
-	self->rowVar = NULL;
-	self->colVar = NULL;
-	self->swarm = NULL;
-	self->rowRCB = NULL;
-	self->rowUCB = NULL;
-	self->colRCB = NULL;
-	self->colUCB = NULL;
-	self->obj = NULL;
-
-	self->elInd = 0;
-	self->particle = NULL;
-	self->shapeFuncs = NULL;
-	self->detJac = 0.0;
-	self->globalDerivs = NULL;
-	self->rowInd = 0;
-	self->rowNodeInd = 0;
-	self->rowDofInd = 0;
-	self->rowEq = 0;
-	self->colInd = 0;
-	self->colNodeInd = 0;
-	self->colDofInd = 0;
-	self->colEq = 0;
-
-	self->rowInc = IArray_New();
-	self->colInc = IArray_New();
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _Assembler_Delete( void* assembler ) {
-	Assembler*	self = (Assembler*)assembler;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-
-	FreeArray( self->shapeFuncs );
-	FreeArray( self->globalDerivs );
-	NewClass_Delete( self->rowInc );
-	NewClass_Delete( self->colInc );
-
-	/* Delete the parent. */
-	_Stg_Class_Delete( self );
-}
-
-void _Assembler_Print( void* assembler, Stream* stream ) {
-	Assembler*	self = (Assembler*)assembler;
-	Stream* 	assemblerStream;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-	
-	/* Set the Journal for printing informations */
-	assemblerStream = Journal_Register( InfoStream_Type, (Name)"AssemblerStream"  );
-
-	/* Print parent */
-	Journal_Printf( stream, "Assembler (ptr): (%p)\n", self );
-	_Stg_Class_Print( self, stream );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void Assembler_SetVariables( void* assembler, FeVariable* rowVar, FeVariable* columnVar ) {
-	Assembler*	self = (Assembler*)assembler;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-	assert( rowVar || columnVar );
-
-	self->rowVar = rowVar ? rowVar : columnVar;
-	self->colVar = columnVar ? columnVar : rowVar;
-	Assembler_Update( self );
-}
-
-void Assembler_SetIntegrationSwarm( void* assembler, Swarm* swarm ) {
-	Assembler*	self = (Assembler*)assembler;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-
-	self->swarm = swarm;
-}
-
-void Assembler_SetCallbacks( void* assembler, 
-			     Assembler_CallbackType* particle, 
-                             Assembler_CallbackType* rowRestricted, 
-                             Assembler_CallbackType* rowUnrestricted, 
-                             Assembler_CallbackType* colRestricted, 
-                             Assembler_CallbackType* colUnrestricted, 
-                             void* object )
-{
-        Assembler*      self = (Assembler*)assembler;
-
-        assert( self && Stg_CheckType( self, Assembler ) );
-
-	self->partCB = particle;
-        self->rowRCB = rowRestricted;
-        self->rowUCB = rowUnrestricted;
-        self->colRCB = colRestricted;
-        self->colUCB = colUnrestricted;
-        self->obj = object;
-}
-
-void Assembler_Update( void* assembler ) {
-	Assembler*	self = (Assembler*)assembler;
-	unsigned	nDerivs, nDims;
-	unsigned	e_i;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-
-	nDerivs = 0;
-	nDims = 0;
-	if( self->rowVar ) {
-		FeMesh*	mesh = self->rowVar->feMesh;
-
-		nDims = Mesh_GetDimSize( mesh );
-		for( e_i = 0; e_i < FeMesh_GetElementLocalSize( mesh ); e_i++ ) {
-			if( FeMesh_GetElementNodeSize( mesh, e_i ) > nDerivs )
-				nDerivs = FeMesh_GetElementNodeSize( mesh, e_i );
-		}
-	}
-	self->shapeFuncs = ReallocArray( self->shapeFuncs, double, nDerivs );
-	self->globalDerivs = ReallocArray2D( self->globalDerivs, double, nDims, nDerivs );
-}
-
-void Assembler_IntegrateMatrixElement( void* assembler, unsigned element ) {
-	Assembler*		self = (Assembler*)assembler;
-	FeMesh*			mesh;
-	Swarm*			swarm;
-	unsigned		nDims;
-	unsigned		cellInd, nParticles;
-	ElementType*		elType;
-	unsigned		p_i;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-	assert( self->rowVar && self->colVar );
-
-	mesh = self->rowVar->feMesh;
-	nDims = Mesh_GetDimSize( mesh );
-	swarm = self->swarm;	assert( swarm );
-	assert( swarm->cellLayout );
-	assert( swarm->cellParticleCountTbl );
-	cellInd = CellLayout_MapElementIdToCellId( swarm->cellLayout, element );
-	nParticles = swarm->cellParticleCountTbl[cellInd];
-	elType = FeMesh_GetElementType( mesh, element );
-
-	for( p_i = 0; p_i < nParticles; p_i++ ) {
-		self->particle = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cellInd, p_i );
-		assert( self->particle );
-		ElementType_EvaluateShapeFunctionsAt( elType, self->particle->xi, self->shapeFuncs );
-		ElementType_ShapeFunctionsGlobalDerivs( elType, mesh, element, self->particle->xi, nDims, 
-							&self->detJac, self->globalDerivs );
-		if( self->partCB && !self->partCB( self->obj, self ) )
-			continue;
-
-		Assembler_LoopMatrixElement( self, element );
-	}
-}
-
-void Assembler_LoopMatrixElement( void* assembler, unsigned element ) {
-	Assembler*		self = (Assembler*)assembler;
-	unsigned		nDims;
-	FeVariable		*rowVar, *colVar;
-	FeMesh			*rowMesh, *colMesh;
-	FeEquationNumber	*rowEqNum, *colEqNum;
-	DofLayout		*rowDofs, *colDofs;
-	unsigned		nRowDofs, nColDofs;
-	unsigned		nRowElNodes, *rowElNodes;
-	unsigned		nColElNodes, *colElNodes;
-	int			rowEq, colEq;
-	unsigned		rowInd, colInd;
-	unsigned		n_i, n_j, dof_i, dof_j;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-	assert( self->rowVar && self->colVar );
-
-	self->elInd = element;
-	rowVar = self->rowVar;
-	colVar = self->colVar;
-	rowEqNum = rowVar->eqNum;			assert( rowEqNum );
-	colEqNum = colVar->eqNum;			assert( colEqNum );
-	rowMesh = rowVar->feMesh;
-	colMesh = colVar->feMesh;
-	rowDofs = rowVar->dofLayout;			assert( rowDofs );
-	colDofs = colVar->dofLayout;			assert( colDofs );
-	nDims = Mesh_GetDimSize( rowMesh );		assert( nDims );
-	Mesh_GetIncidence( rowMesh, (MeshTopology_Dim)nDims, element, MT_VERTEX, self->rowInc );
-	nRowElNodes = IArray_GetSize( self->rowInc );
-	rowElNodes = (unsigned*)IArray_GetPtr( self->rowInc );
-	Mesh_GetIncidence( colMesh, Mesh_GetDimSize( colMesh ), element, MT_VERTEX, 
-			   self->colInc );
-	nColElNodes = IArray_GetSize( self->colInc );
-	colElNodes = (unsigned*)IArray_GetPtr( self->colInc );
-	assert( FeMesh_GetElementLocalSize( rowMesh ) == FeMesh_GetElementLocalSize( colMesh ) );
-	assert( nDims == Mesh_GetDimSize( colMesh ) );
-	assert( rowEqNum->locationMatrix );
-	assert( colEqNum->locationMatrix );
-	assert( rowEqNum->locationMatrix[element] );
-	assert( colEqNum->locationMatrix[element] );
-	assert( rowDofs->dofCounts );
-	assert( colDofs->dofCounts );
-
-	rowInd = 0;
-	for( n_i = 0; n_i < nRowElNodes; n_i++ ) {
-		assert( rowEqNum->locationMatrix[element][n_i] );
-		nRowDofs = rowDofs->dofCounts[rowElNodes[n_i]];
-		for( dof_i = 0; dof_i < nRowDofs; dof_i++ ) {
-			rowEq = rowEqNum->locationMatrix[element][n_i][dof_i];
-
-			self->rowInd = rowInd++;
-			self->rowElNodeInd = n_i;
-			self->rowNodeInd = rowElNodes[n_i];
-			self->rowDofInd = dof_i;
-			self->rowEq = rowEq;
-			if( rowVar->bcs && FeVariable_IsBC( rowVar, rowElNodes[n_i], dof_i ) ) {
-				if( !self->rowRCB || !self->rowRCB( self->obj, self ) )
-					continue;
-			}
-			else if( self->rowUCB && !self->rowUCB( self->obj, self ) )
-				continue;
-
-			colInd = 0;
-			for( n_j = 0; n_j < nColElNodes; n_j++ ) {
-				assert( colEqNum->locationMatrix[element][n_j] );
-				nColDofs = colDofs->dofCounts[colElNodes[n_j]];
-				for( dof_j = 0; dof_j < nColDofs; dof_j++ ) {
-					colEq = colEqNum->locationMatrix[element][n_j][dof_j];
-
-					self->colInd = colInd++;
-					self->colElNodeInd = n_j;
-					self->colNodeInd = colElNodes[n_j];
-					self->colDofInd = dof_j;
-					self->colEq = colEq;
-					if( colVar->bcs && FeVariable_IsBC( colVar, colElNodes[n_j], dof_j ) ) {
-						if( self->colRCB )
-							self->colRCB( self->obj, self );
-					}
-					else if( self->colUCB )
-						self->colUCB( self->obj, self );
-				}
-			}
-		}
-	}
-}
-
-void Assembler_LoopMatrixDiagonal( void* assembler ) {
-	Assembler*		self = (Assembler*)assembler;
-	unsigned		nDims;
-	FeVariable		*rowVar;
-	FeMesh			*rowMesh;
-	FeEquationNumber	*rowEqNum;
-	DofLayout		*rowDofs;
-	unsigned		nRowDofs;
-	unsigned		nRowNodes;
-	int			rowEq;
-	unsigned		n_i, dof_i;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-	assert( self->rowVar && self->colVar );
-	assert( self->rowVar == self->colVar );
-
-	rowVar = self->rowVar;
-	rowEqNum = rowVar->eqNum;			assert( rowEqNum );
-	rowMesh = rowVar->feMesh;
-	rowDofs = rowVar->dofLayout;			assert( rowDofs );
-	nDims = Mesh_GetDimSize( rowMesh );		assert( nDims );
-	nRowNodes = FeMesh_GetNodeLocalSize( rowMesh );
-	assert( rowEqNum->destinationArray );
-	assert( rowDofs->dofCounts );
-
-	for( n_i = 0; n_i < nRowNodes; n_i++ ) {
-		assert( rowEqNum->destinationArray[n_i] );
-		nRowDofs = rowDofs->dofCounts[n_i];
-		for( dof_i = 0; dof_i < nRowDofs; dof_i++ ) {
-			rowEq = rowEqNum->destinationArray[n_i][dof_i];
-
-			self->rowNodeInd = n_i;
-			self->rowDofInd = dof_i;
-			self->rowEq = rowEq;
-			self->colNodeInd = n_i;
-			self->colDofInd = dof_i;
-			self->colEq = rowEq;
-			if( rowVar->bcs && FeVariable_IsBC( rowVar, n_i, dof_i ) ) {
-				if( self->rowRCB )
-					self->rowRCB( self->obj, self );
-			}
-			else if( self->rowUCB )
-				self->rowUCB( self->obj, self );
-		}
-	}
-}
-
-#if 0
-void Assembler_LoopVectorElement( void* assembler, unsigned element ) {
-	Assembler*		self = (Assembler*)assembler;
-	unsigned		nDims;
-	FeVariable		*rowVar;
-	FeMesh			*rowMesh;
-	FeEquationNumber	*rowEqNum;
-	DofLayout		*rowDofs;
-	unsigned		nRowDofs;
-	unsigned		nRowElNodes, *rowElNodes;
-	int			rowEq;
-	unsigned		n_i, dof_i;
-
-	assert( self && Stg_CheckType( self, Assembler ) );
-	assert( self->rowVar && self->colVar );
-	assert( self->colCB );
-
-	self->elInd = element;
-	rowVar = self->rowVar;
-	rowEqNum = rowVar->eqNum;			assert( rowEqNum );
-	rowMesh = rowVar->feMesh;
-	rowDofs = rowVar->dofLayout;			assert( rowDofs );
-	nDims = Mesh_GetDimSize( rowMesh );		assert( nDims );
-	Mesh_GetIncidence( rowMesh, nDims, element, MT_VERTEX, self->rowInc );
-	nRowElNodes = IArray_GetSize( self->rowInc );
-	rowElNodes = IArray_GetPtr( self->rowInc );
-	assert( rowEqNum->locationMatrix );
-	assert( rowEqNum->locationMatrix[element] );
-	assert( rowDofs->dofCounts );
-
-	for( n_i = 0; n_i < nRowElNodes; n_i++ ) {
-		assert( rowEqNum->locationMatrix[element][n_i] );
-		nRowDofs = rowDofs->dofCounts[rowElNodes[n_i]];
-		for( dof_i = 0; dof_i < nRowDofs; dof_i++ ) {
-			rowEq = rowEqNum->locationMatrix[element][n_i][dof_i];
-
-			self->rowNodeInd = n_i;
-			self->rowDofInd = dof_i;
-			self->rowEq = rowEq;
-			self->colCB( self );
-		}
-	}
-}
-#endif
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/Assembler.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/Assembler.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,423 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Assembler.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "Discretisation/Discretisation.h"
+#include "SystemSetup.h"
+
+
+/* Textual name of this class */
+const Type Assembler_Type = "Assembler";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+Assembler* Assembler_New() {
+	/* Variables set in this function */
+	SizeT                      _sizeOfSelf = sizeof(Assembler);
+	Type                              type = Assembler_Type;
+	Stg_Class_DeleteFunction*      _delete = _Assembler_Delete;
+	Stg_Class_PrintFunction*        _print = _Assembler_Print;
+	Stg_Class_CopyFunction*          _copy = NULL;
+
+        return _Assembler_New(  ASSEMBLER_PASSARGS  );
+}
+
+Assembler* _Assembler_New(  ASSEMBLER_DEFARGS  ) {
+	Assembler*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(Assembler) );
+	self = (Assembler*)_Stg_Class_New(  STG_CLASS_PASSARGS  );
+
+	/* Virtual info */
+
+	/* Assembler info */
+	_Assembler_Init( self );
+
+	return self;
+}
+
+void _Assembler_Init( Assembler* self ) {
+	assert( self && Stg_CheckType( self, Assembler ) );
+
+	self->rowVar = NULL;
+	self->colVar = NULL;
+	self->swarm = NULL;
+	self->rowRCB = NULL;
+	self->rowUCB = NULL;
+	self->colRCB = NULL;
+	self->colUCB = NULL;
+	self->obj = NULL;
+
+	self->elInd = 0;
+	self->particle = NULL;
+	self->shapeFuncs = NULL;
+	self->detJac = 0.0;
+	self->globalDerivs = NULL;
+	self->rowInd = 0;
+	self->rowNodeInd = 0;
+	self->rowDofInd = 0;
+	self->rowEq = 0;
+	self->colInd = 0;
+	self->colNodeInd = 0;
+	self->colDofInd = 0;
+	self->colEq = 0;
+
+	self->rowInc = IArray_New();
+	self->colInc = IArray_New();
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _Assembler_Delete( void* assembler ) {
+	Assembler*	self = (Assembler*)assembler;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+
+	FreeArray( self->shapeFuncs );
+	FreeArray( self->globalDerivs );
+	NewClass_Delete( self->rowInc );
+	NewClass_Delete( self->colInc );
+
+	/* Delete the parent. */
+	_Stg_Class_Delete( self );
+}
+
+void _Assembler_Print( void* assembler, Stream* stream ) {
+	Assembler*	self = (Assembler*)assembler;
+	Stream* 	assemblerStream;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+	
+	/* Set the Journal for printing informations */
+	assemblerStream = Journal_Register( InfoStream_Type, (Name)"AssemblerStream"  );
+
+	/* Print parent */
+	Journal_Printf( stream, "Assembler (ptr): (%p)\n", self );
+	_Stg_Class_Print( self, stream );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void Assembler_SetVariables( void* assembler, FeVariable* rowVar, FeVariable* columnVar ) {
+	Assembler*	self = (Assembler*)assembler;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+	assert( rowVar || columnVar );
+
+	self->rowVar = rowVar ? rowVar : columnVar;
+	self->colVar = columnVar ? columnVar : rowVar;
+	Assembler_Update( self );
+}
+
+void Assembler_SetIntegrationSwarm( void* assembler, Swarm* swarm ) {
+	Assembler*	self = (Assembler*)assembler;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+
+	self->swarm = swarm;
+}
+
+void Assembler_SetCallbacks( void* assembler, 
+			     Assembler_CallbackType* particle, 
+                             Assembler_CallbackType* rowRestricted, 
+                             Assembler_CallbackType* rowUnrestricted, 
+                             Assembler_CallbackType* colRestricted, 
+                             Assembler_CallbackType* colUnrestricted, 
+                             void* object )
+{
+        Assembler*      self = (Assembler*)assembler;
+
+        assert( self && Stg_CheckType( self, Assembler ) );
+
+	self->partCB = particle;
+        self->rowRCB = rowRestricted;
+        self->rowUCB = rowUnrestricted;
+        self->colRCB = colRestricted;
+        self->colUCB = colUnrestricted;
+        self->obj = object;
+}
+
+void Assembler_Update( void* assembler ) {
+	Assembler*	self = (Assembler*)assembler;
+	unsigned	nDerivs, nDims;
+	unsigned	e_i;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+
+	nDerivs = 0;
+	nDims = 0;
+	if( self->rowVar ) {
+		FeMesh*	mesh = self->rowVar->feMesh;
+
+		nDims = Mesh_GetDimSize( mesh );
+		for( e_i = 0; e_i < FeMesh_GetElementLocalSize( mesh ); e_i++ ) {
+			if( FeMesh_GetElementNodeSize( mesh, e_i ) > nDerivs )
+				nDerivs = FeMesh_GetElementNodeSize( mesh, e_i );
+		}
+	}
+	self->shapeFuncs = ReallocArray( self->shapeFuncs, double, nDerivs );
+	self->globalDerivs = ReallocArray2D( self->globalDerivs, double, nDims, nDerivs );
+}
+
+void Assembler_IntegrateMatrixElement( void* assembler, unsigned element ) {
+	Assembler*		self = (Assembler*)assembler;
+	FeMesh*			mesh;
+	Swarm*			swarm;
+	unsigned		nDims;
+	unsigned		cellInd, nParticles;
+	ElementType*		elType;
+	unsigned		p_i;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+	assert( self->rowVar && self->colVar );
+
+	mesh = self->rowVar->feMesh;
+	nDims = Mesh_GetDimSize( mesh );
+	swarm = self->swarm;	assert( swarm );
+	assert( swarm->cellLayout );
+	assert( swarm->cellParticleCountTbl );
+	cellInd = CellLayout_MapElementIdToCellId( swarm->cellLayout, element );
+	nParticles = swarm->cellParticleCountTbl[cellInd];
+	elType = FeMesh_GetElementType( mesh, element );
+
+	for( p_i = 0; p_i < nParticles; p_i++ ) {
+		self->particle = (IntegrationPoint*)Swarm_ParticleInCellAt( swarm, cellInd, p_i );
+		assert( self->particle );
+		ElementType_EvaluateShapeFunctionsAt( elType, self->particle->xi, self->shapeFuncs );
+		ElementType_ShapeFunctionsGlobalDerivs( elType, mesh, element, self->particle->xi, nDims, 
+							&self->detJac, self->globalDerivs );
+		if( self->partCB && !self->partCB( self->obj, self ) )
+			continue;
+
+		Assembler_LoopMatrixElement( self, element );
+	}
+}
+
+void Assembler_LoopMatrixElement( void* assembler, unsigned element ) {
+	Assembler*		self = (Assembler*)assembler;
+	unsigned		nDims;
+	FeVariable		*rowVar, *colVar;
+	FeMesh			*rowMesh, *colMesh;
+	FeEquationNumber	*rowEqNum, *colEqNum;
+	DofLayout		*rowDofs, *colDofs;
+	unsigned		nRowDofs, nColDofs;
+	unsigned		nRowElNodes, *rowElNodes;
+	unsigned		nColElNodes, *colElNodes;
+	int			rowEq, colEq;
+	unsigned		rowInd, colInd;
+	unsigned		n_i, n_j, dof_i, dof_j;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+	assert( self->rowVar && self->colVar );
+
+	self->elInd = element;
+	rowVar = self->rowVar;
+	colVar = self->colVar;
+	rowEqNum = rowVar->eqNum;			assert( rowEqNum );
+	colEqNum = colVar->eqNum;			assert( colEqNum );
+	rowMesh = rowVar->feMesh;
+	colMesh = colVar->feMesh;
+	rowDofs = rowVar->dofLayout;			assert( rowDofs );
+	colDofs = colVar->dofLayout;			assert( colDofs );
+	nDims = Mesh_GetDimSize( rowMesh );		assert( nDims );
+	Mesh_GetIncidence( rowMesh, (MeshTopology_Dim)nDims, element, MT_VERTEX, self->rowInc );
+	nRowElNodes = IArray_GetSize( self->rowInc );
+	rowElNodes = (unsigned*)IArray_GetPtr( self->rowInc );
+	Mesh_GetIncidence( colMesh, Mesh_GetDimSize( colMesh ), element, MT_VERTEX, 
+			   self->colInc );
+	nColElNodes = IArray_GetSize( self->colInc );
+	colElNodes = (unsigned*)IArray_GetPtr( self->colInc );
+	assert( FeMesh_GetElementLocalSize( rowMesh ) == FeMesh_GetElementLocalSize( colMesh ) );
+	assert( nDims == Mesh_GetDimSize( colMesh ) );
+	assert( rowEqNum->locationMatrix );
+	assert( colEqNum->locationMatrix );
+	assert( rowEqNum->locationMatrix[element] );
+	assert( colEqNum->locationMatrix[element] );
+	assert( rowDofs->dofCounts );
+	assert( colDofs->dofCounts );
+
+	rowInd = 0;
+	for( n_i = 0; n_i < nRowElNodes; n_i++ ) {
+		assert( rowEqNum->locationMatrix[element][n_i] );
+		nRowDofs = rowDofs->dofCounts[rowElNodes[n_i]];
+		for( dof_i = 0; dof_i < nRowDofs; dof_i++ ) {
+			rowEq = rowEqNum->locationMatrix[element][n_i][dof_i];
+
+			self->rowInd = rowInd++;
+			self->rowElNodeInd = n_i;
+			self->rowNodeInd = rowElNodes[n_i];
+			self->rowDofInd = dof_i;
+			self->rowEq = rowEq;
+			if( rowVar->bcs && FeVariable_IsBC( rowVar, rowElNodes[n_i], dof_i ) ) {
+				if( !self->rowRCB || !self->rowRCB( self->obj, self ) )
+					continue;
+			}
+			else if( self->rowUCB && !self->rowUCB( self->obj, self ) )
+				continue;
+
+			colInd = 0;
+			for( n_j = 0; n_j < nColElNodes; n_j++ ) {
+				assert( colEqNum->locationMatrix[element][n_j] );
+				nColDofs = colDofs->dofCounts[colElNodes[n_j]];
+				for( dof_j = 0; dof_j < nColDofs; dof_j++ ) {
+					colEq = colEqNum->locationMatrix[element][n_j][dof_j];
+
+					self->colInd = colInd++;
+					self->colElNodeInd = n_j;
+					self->colNodeInd = colElNodes[n_j];
+					self->colDofInd = dof_j;
+					self->colEq = colEq;
+					if( colVar->bcs && FeVariable_IsBC( colVar, colElNodes[n_j], dof_j ) ) {
+						if( self->colRCB )
+							self->colRCB( self->obj, self );
+					}
+					else if( self->colUCB )
+						self->colUCB( self->obj, self );
+				}
+			}
+		}
+	}
+}
+
+void Assembler_LoopMatrixDiagonal( void* assembler ) {
+	Assembler*		self = (Assembler*)assembler;
+	unsigned		nDims;
+	FeVariable		*rowVar;
+	FeMesh			*rowMesh;
+	FeEquationNumber	*rowEqNum;
+	DofLayout		*rowDofs;
+	unsigned		nRowDofs;
+	unsigned		nRowNodes;
+	int			rowEq;
+	unsigned		n_i, dof_i;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+	assert( self->rowVar && self->colVar );
+	assert( self->rowVar == self->colVar );
+
+	rowVar = self->rowVar;
+	rowEqNum = rowVar->eqNum;			assert( rowEqNum );
+	rowMesh = rowVar->feMesh;
+	rowDofs = rowVar->dofLayout;			assert( rowDofs );
+	nDims = Mesh_GetDimSize( rowMesh );		assert( nDims );
+	nRowNodes = FeMesh_GetNodeLocalSize( rowMesh );
+	assert( rowEqNum->destinationArray );
+	assert( rowDofs->dofCounts );
+
+	for( n_i = 0; n_i < nRowNodes; n_i++ ) {
+		assert( rowEqNum->destinationArray[n_i] );
+		nRowDofs = rowDofs->dofCounts[n_i];
+		for( dof_i = 0; dof_i < nRowDofs; dof_i++ ) {
+			rowEq = rowEqNum->destinationArray[n_i][dof_i];
+
+			self->rowNodeInd = n_i;
+			self->rowDofInd = dof_i;
+			self->rowEq = rowEq;
+			self->colNodeInd = n_i;
+			self->colDofInd = dof_i;
+			self->colEq = rowEq;
+			if( rowVar->bcs && FeVariable_IsBC( rowVar, n_i, dof_i ) ) {
+				if( self->rowRCB )
+					self->rowRCB( self->obj, self );
+			}
+			else if( self->rowUCB )
+				self->rowUCB( self->obj, self );
+		}
+	}
+}
+
+#if 0
+void Assembler_LoopVectorElement( void* assembler, unsigned element ) {
+	Assembler*		self = (Assembler*)assembler;
+	unsigned		nDims;
+	FeVariable		*rowVar;
+	FeMesh			*rowMesh;
+	FeEquationNumber	*rowEqNum;
+	DofLayout		*rowDofs;
+	unsigned		nRowDofs;
+	unsigned		nRowElNodes, *rowElNodes;
+	int			rowEq;
+	unsigned		n_i, dof_i;
+
+	assert( self && Stg_CheckType( self, Assembler ) );
+	assert( self->rowVar && self->colVar );
+	assert( self->colCB );
+
+	self->elInd = element;
+	rowVar = self->rowVar;
+	rowEqNum = rowVar->eqNum;			assert( rowEqNum );
+	rowMesh = rowVar->feMesh;
+	rowDofs = rowVar->dofLayout;			assert( rowDofs );
+	nDims = Mesh_GetDimSize( rowMesh );		assert( nDims );
+	Mesh_GetIncidence( rowMesh, nDims, element, MT_VERTEX, self->rowInc );
+	nRowElNodes = IArray_GetSize( self->rowInc );
+	rowElNodes = IArray_GetPtr( self->rowInc );
+	assert( rowEqNum->locationMatrix );
+	assert( rowEqNum->locationMatrix[element] );
+	assert( rowDofs->dofCounts );
+
+	for( n_i = 0; n_i < nRowElNodes; n_i++ ) {
+		assert( rowEqNum->locationMatrix[element][n_i] );
+		nRowDofs = rowDofs->dofCounts[rowElNodes[n_i]];
+		for( dof_i = 0; dof_i < nRowDofs; dof_i++ ) {
+			rowEq = rowEqNum->locationMatrix[element][n_i][dof_i];
+
+			self->rowNodeInd = n_i;
+			self->rowDofInd = dof_i;
+			self->rowEq = rowEq;
+			self->colCB( self );
+		}
+	}
+}
+#endif
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/EntryPoint.c
--- a/SLE/SystemSetup/src/EntryPoint.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: EntryPoint.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "EntryPoint.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <stdarg.h>
-
-/* Textual name of this class */
-const Type FeEntryPoint_Type = "FeEntryPoint";
-
-
-FeEntryPoint* FeEntryPoint_New( Name name, unsigned int castType ) {
-	/* Variables set in this function */
-	SizeT                       _sizeOfSelf = sizeof(FeEntryPoint);
-	Type                               type = FeEntryPoint_Type;
-	Stg_Class_DeleteFunction*       _delete = _EntryPoint_Delete;
-	Stg_Class_PrintFunction*         _print = _EntryPoint_Print;
-	Stg_Class_CopyFunction*           _copy = _EntryPoint_Copy;
-	EntryPoint_GetRunFunction*      _getRun = _FeEntryPoint_GetRun;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _FeEntryPoint_New(  FEENTRYPOINT_PASSARGS  );
-}
-
-void FeEntryPoint_Init( void* feEntryPoint, Name name, unsigned int castType ) {
-	FeEntryPoint* self = (FeEntryPoint*)feEntryPoint;
-	
-	/* General info */
-	self->type = FeEntryPoint_Type;
-	self->_sizeOfSelf = sizeof(FeEntryPoint);
-	self->_deleteSelf = False;
-	
-	/* Virtual info */
-	self->_delete = _EntryPoint_Delete;
-	self->_print = _EntryPoint_Print;
-	self->_copy = _EntryPoint_Copy;
-	self->_getRun = _FeEntryPoint_GetRun;
-	_Stg_Class_Init( (Stg_Class*)self );
-	_Stg_Object_Init( (Stg_Object*)self, name, GLOBAL );
-	_EntryPoint_Init( (EntryPoint*)self, castType );
-	
-	/* FeEntryPoint info */
-	_FeEntryPoint_Init( self );
-}
-
-FeEntryPoint* _FeEntryPoint_New(  FEENTRYPOINT_DEFARGS  )
-{
-	FeEntryPoint* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(FeEntryPoint) );
-	self = (FeEntryPoint*)_EntryPoint_New(  ENTRYPOINT_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual info */
-	
-	/* FeEntryPoint info */
-	_FeEntryPoint_Init( self );
-	
-	return self;
-}
-
-void _FeEntryPoint_Init( FeEntryPoint* self ) {
-	/* General and Virtual info should already be set */
-	
-	/* FeEntryPoint info */
-}
-
-
-Func_Ptr _FeEntryPoint_GetRun( void* feEntryPoint ) {
-	FeEntryPoint* self = (FeEntryPoint*)feEntryPoint;
-	
-	/* Most frequently called EPs are put first in the switch statement */
-	switch( self->castType ) {
-		case FeEntryPoint_AssembleStiffnessMatrix_CastType:
-			return (Func_Ptr)_FeEntryPoint_Run_AssembleStiffnessMatrix;
-		
-		case FeEntryPoint_AssembleForceVector_CastType:
-			return (Func_Ptr)_FeEntryPoint_Run_AssembleForceVector;
-		
-		default:
-			return (Func_Ptr)_EntryPoint_GetRun( self );
-	}
-}
-
-
-void _FeEntryPoint_Run_AssembleStiffnessMatrix( 
-		void* feEntryPoint, 
-		void* stiffnessMatrix, 
-		Bool bcRemoveQuery,
-		void* _sle,
-		void* _context )
-{
-	FeEntryPoint* self = (FeEntryPoint*)feEntryPoint;
-	Hook_Index hookIndex;
-  double wallTime;
-	
-	#ifdef USE_PROFILE
-		Stg_CallGraph_Push( stgCallGraph, _FeEntryPoint_Run_AssembleStiffnessMatrix, self->name );
-	#endif
-
-	for( hookIndex = 0; hookIndex < self->hooks->count; hookIndex++ ) {
-    wallTime = MPI_Wtime();
-
-		((FeEntryPoint_AssembleStiffnessMatrix_Function*)((Hook*)self->hooks->data[hookIndex])->funcPtr) (
-			stiffnessMatrix,
-			bcRemoveQuery,
-			_sle,
-			_context );
-
-    stg_profile_EntryPoint( self->name, self->hooks->data[hookIndex]->name, MPI_Wtime() - wallTime );
-	}
-
-	#ifdef USE_PROFILE
-		Stg_CallGraph_Pop( stgCallGraph );
-	#endif
-}
-
-void _FeEntryPoint_Run_AssembleForceVector( 
-		void* feEntryPoint, 
-		void* forceVector ) 
-{
-  FeEntryPoint* self = (FeEntryPoint*)feEntryPoint;
-  Hook_Index hookIndex;
-  double wallTime;
-	
-	#ifdef USE_PROFILE
-		Stg_CallGraph_Push( stgCallGraph, _FeEntryPoint_Run_AssembleForceVector, self->name );
-	#endif
-
-	for( hookIndex = 0; hookIndex < self->hooks->count; hookIndex++ ) {
-    wallTime = MPI_Wtime();
-
-    ((FeEntryPoint_AssembleForceVector_Function*)((Hook*)self->hooks->data[hookIndex])->funcPtr) (
-      forceVector );
-
-    stg_profile_EntryPoint( self->name, self->hooks->data[hookIndex]->name, MPI_Wtime() - wallTime );
-	}
-
-	#ifdef USE_PROFILE
-		Stg_CallGraph_Pop( stgCallGraph );
-	#endif
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/EntryPoint.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/EntryPoint.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,199 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: EntryPoint.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "EntryPoint.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+
+/* Textual name of this class */
+const Type FeEntryPoint_Type = "FeEntryPoint";
+
+
+FeEntryPoint* FeEntryPoint_New( Name name, unsigned int castType ) {
+	/* Variables set in this function */
+	SizeT                       _sizeOfSelf = sizeof(FeEntryPoint);
+	Type                               type = FeEntryPoint_Type;
+	Stg_Class_DeleteFunction*       _delete = _EntryPoint_Delete;
+	Stg_Class_PrintFunction*         _print = _EntryPoint_Print;
+	Stg_Class_CopyFunction*           _copy = _EntryPoint_Copy;
+	EntryPoint_GetRunFunction*      _getRun = _FeEntryPoint_GetRun;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _FeEntryPoint_New(  FEENTRYPOINT_PASSARGS  );
+}
+
+void FeEntryPoint_Init( void* feEntryPoint, Name name, unsigned int castType ) {
+	FeEntryPoint* self = (FeEntryPoint*)feEntryPoint;
+	
+	/* General info */
+	self->type = FeEntryPoint_Type;
+	self->_sizeOfSelf = sizeof(FeEntryPoint);
+	self->_deleteSelf = False;
+	
+	/* Virtual info */
+	self->_delete = _EntryPoint_Delete;
+	self->_print = _EntryPoint_Print;
+	self->_copy = _EntryPoint_Copy;
+	self->_getRun = _FeEntryPoint_GetRun;
+	_Stg_Class_Init( (Stg_Class*)self );
+	_Stg_Object_Init( (Stg_Object*)self, name, GLOBAL );
+	_EntryPoint_Init( (EntryPoint*)self, castType );
+	
+	/* FeEntryPoint info */
+	_FeEntryPoint_Init( self );
+}
+
+FeEntryPoint* _FeEntryPoint_New(  FEENTRYPOINT_DEFARGS  )
+{
+	FeEntryPoint* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(FeEntryPoint) );
+	self = (FeEntryPoint*)_EntryPoint_New(  ENTRYPOINT_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual info */
+	
+	/* FeEntryPoint info */
+	_FeEntryPoint_Init( self );
+	
+	return self;
+}
+
+void _FeEntryPoint_Init( FeEntryPoint* self ) {
+	/* General and Virtual info should already be set */
+	
+	/* FeEntryPoint info */
+}
+
+
+Func_Ptr _FeEntryPoint_GetRun( void* feEntryPoint ) {
+	FeEntryPoint* self = (FeEntryPoint*)feEntryPoint;
+	
+	/* Most frequently called EPs are put first in the switch statement */
+	switch( self->castType ) {
+		case FeEntryPoint_AssembleStiffnessMatrix_CastType:
+			return (Func_Ptr)_FeEntryPoint_Run_AssembleStiffnessMatrix;
+		
+		case FeEntryPoint_AssembleForceVector_CastType:
+			return (Func_Ptr)_FeEntryPoint_Run_AssembleForceVector;
+		
+		default:
+			return (Func_Ptr)_EntryPoint_GetRun( self );
+	}
+}
+
+
+void _FeEntryPoint_Run_AssembleStiffnessMatrix( 
+		void* feEntryPoint, 
+		void* stiffnessMatrix, 
+		Bool bcRemoveQuery,
+		void* _sle,
+		void* _context )
+{
+	FeEntryPoint* self = (FeEntryPoint*)feEntryPoint;
+	Hook_Index hookIndex;
+  double wallTime;
+	
+	#ifdef USE_PROFILE
+		Stg_CallGraph_Push( stgCallGraph, _FeEntryPoint_Run_AssembleStiffnessMatrix, self->name );
+	#endif
+
+	for( hookIndex = 0; hookIndex < self->hooks->count; hookIndex++ ) {
+    wallTime = MPI_Wtime();
+
+		((FeEntryPoint_AssembleStiffnessMatrix_Function*)((Hook*)self->hooks->data[hookIndex])->funcPtr) (
+			stiffnessMatrix,
+			bcRemoveQuery,
+			_sle,
+			_context );
+
+    stg_profile_EntryPoint( self->name, self->hooks->data[hookIndex]->name, MPI_Wtime() - wallTime );
+	}
+
+	#ifdef USE_PROFILE
+		Stg_CallGraph_Pop( stgCallGraph );
+	#endif
+}
+
+void _FeEntryPoint_Run_AssembleForceVector( 
+		void* feEntryPoint, 
+		void* forceVector ) 
+{
+  FeEntryPoint* self = (FeEntryPoint*)feEntryPoint;
+  Hook_Index hookIndex;
+  double wallTime;
+	
+	#ifdef USE_PROFILE
+		Stg_CallGraph_Push( stgCallGraph, _FeEntryPoint_Run_AssembleForceVector, self->name );
+	#endif
+
+	for( hookIndex = 0; hookIndex < self->hooks->count; hookIndex++ ) {
+    wallTime = MPI_Wtime();
+
+    ((FeEntryPoint_AssembleForceVector_Function*)((Hook*)self->hooks->data[hookIndex])->funcPtr) (
+      forceVector );
+
+    stg_profile_EntryPoint( self->name, self->hooks->data[hookIndex]->name, MPI_Wtime() - wallTime );
+	}
+
+	#ifdef USE_PROFILE
+		Stg_CallGraph_Pop( stgCallGraph );
+	#endif
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/Finalise.c
--- a/SLE/SystemSetup/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "Finalise.h"
-
-#include <stdio.h>
-
-Bool StgFEM_SLE_SystemSetup_Finalise( void ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	Stream_IndentBranch( StgFEM_Debug );
-	Stream_UnIndentBranch( StgFEM_Debug );
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,61 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "Finalise.h"
+
+#include <stdio.h>
+
+Bool StgFEM_SLE_SystemSetup_Finalise( void ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	Stream_IndentBranch( StgFEM_Debug );
+	Stream_UnIndentBranch( StgFEM_Debug );
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/FiniteElementContext.c
--- a/SLE/SystemSetup/src/FiniteElementContext.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,838 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Context.c 1207 2008-08-17 15:16:25Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "FiniteElementContext.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include "SystemLinearEquations.h"
-#include "SolutionVector.h"
-
-#ifdef WRITE_HDF5
-#include <hdf5.h>
-#endif
-
-#define FINISHED_WRITING_TAG 9
-
-/* Textual name of this class */
-const Type FiniteElementContext_Type = "FiniteElementContext";
-const Name defaultFiniteElementContextETypeRegisterName = "finiteElementContext";
-const Name FiniteElementContext_EP_CalcDt = "FiniteElementContext_EP_CalcDt";
-
-/* Constructors ------------------------------------------------------------------------------------------------------------------*/
-
-FiniteElementContext* FiniteElementContext_New(
-	Name			name,
-	double		start,
-	double		stop,
-	MPI_Comm		communicator,
-	Dictionary*	dictionary )
-{
-  FiniteElementContext* self = (FiniteElementContext*)FiniteElementContext_DefaultNew( name );
-
-	self->isConstructed = True;
-	_AbstractContext_Init( (AbstractContext*) self );
-	_DomainContext_Init( (DomainContext*) self );	
-	_FiniteElementContext_Init( self );
-
-	return self;
-}
-	
-void* FiniteElementContext_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(FiniteElementContext);
-	Type                                                      type = FiniteElementContext_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FiniteElementContext_Delete;
-	Stg_Class_PrintFunction*                                _print = _FiniteElementContext_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = FiniteElementContext_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _FiniteElementContext_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _AbstractContext_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _AbstractContext_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AbstractContext_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = (Stg_Component_DestroyFunction*)_FiniteElementContext_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-	AbstractContext_SetDt*                                  _setDt = _FiniteElementContext_SetDt;
-	double                                               startTime = 0;
-	double                                                stopTime = 0;
-	MPI_Comm                                          communicator = MPI_COMM_WORLD;
-	Dictionary*                                         dictionary = NULL;
-
-	return _FiniteElementContext_New(  FINITEELEMENTCONTEXT_PASSARGS  );
-}
-
-FiniteElementContext* _FiniteElementContext_New(  FINITEELEMENTCONTEXT_DEFARGS  ) {
-	FiniteElementContext* self;
-	
-	/* Allocate memory */
-	self = (FiniteElementContext*)_DomainContext_New(  DOMAINCONTEXT_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _FiniteElementContext_Init( FiniteElementContext* self ) {
-	/* Set up stream preferences */
-	Journal_Enable_NamedStream( InfoStream_Type, "StgFEM_VerboseConfig", False );
-
-	/* register this current stream (the context) as a child of the FE stream */
-	/* TODO: Want to be able to recombine this with the Abs context's debug stream at some stage */
-	self->debug = Stream_RegisterChild( StgFEM_Debug, FiniteElementContext_Type );
-	
-	/* set up s.l.e list */
-	self->slEquations = Stg_ObjectList_New();
-
-	/* Create Entry Point for Calculating timestep */
-	self->calcDtEP = EntryPoint_New( FiniteElementContext_EP_CalcDt, EntryPoint_Minimum_VoidPtr_CastType );
-	EntryPoint_Register_Add( self->entryPoint_Register, self->calcDtEP );
-	
-	/* Add hooks to existing entry points... use name "default" so that plugin, etc can exert same behaviour on other contexts*/
-	EntryPoint_Prepend( 
-		Context_GetEntryPoint( self, AbstractContext_EP_Build ),
-		"_FiniteElementContext_Build", 
-		(void*)_FiniteElementContext_Build, 
-		FiniteElementContext_Type );
-	EntryPoint_Prepend( 
-		Context_GetEntryPoint( self, AbstractContext_EP_Initialise ),
-		"_FiniteElementContext_Initialise", 
-		(void*)_FiniteElementContext_Initialise, 
-		FiniteElementContext_Type );
-	EntryPoint_Append( 
-		Context_GetEntryPoint( self, AbstractContext_EP_Solve ),
-		"_FiniteElementContext_Solve", 
-		(void*)_FiniteElementContext_Solve, 
-		FiniteElementContext_Type );
-	EntryPoint_Append( 
-		Context_GetEntryPoint( self, AbstractContext_EP_Solve ),
-		"_FiniteElementContext_PostSolve", 
-		(void*)_FiniteElementContext_PostSolve, 
-		FiniteElementContext_Type );
-	EntryPoint_Append( 
-		Context_GetEntryPoint( self, AbstractContext_EP_Dt ),
-		"_FiniteElementContext_GetDt", 
-		(void*)_FiniteElementContext_GetDt, 
-		FiniteElementContext_Type );
-
-	EntryPoint_Append(
-		Context_GetEntryPoint( self, AbstractContext_EP_Save ),
-		"_FiniteElementContext_SaveFeVariables",
-		(void*)_FiniteElementContext_SaveFeVariables,
-		FiniteElementContext_Type );
-
-	EntryPoint_Append(
-		Context_GetEntryPoint( self, AbstractContext_EP_DataSave ),
-		"_FiniteElementContext_SaveFeVariables",
-		(void*)_FiniteElementContext_SaveFeVariables,
-		FiniteElementContext_Type );
-	/* The FEM context needs to save gauss swarms so they can be re-loaded for restart later.
-	   This will automatically save material point swarms too if PICellerator is used.
-	 */
-	EntryPoint_Append(
-		Context_GetEntryPoint( self, AbstractContext_EP_Save ),
-		"_FiniteElementContext_SaveSwarms",
-		(void*)_FiniteElementContext_SaveSwarms,
-		FiniteElementContext_Type );
-
-	EntryPoint_Append(
-		Context_GetEntryPoint( self, AbstractContext_EP_Save ),
-		"_FiniteElementContext_SaveMesh",
-		(void*)_FiniteElementContext_SaveMesh,
-		FiniteElementContext_Type );
-
-	EntryPoint_Append(
-		Context_GetEntryPoint( self, AbstractContext_EP_DataSave ),
-		"_FiniteElementContext_SaveMesh",
-		(void*)_FiniteElementContext_SaveMesh,
-		FiniteElementContext_Type );
-}
-
-
-/* Virtual Functions -------------------------------------------------------------------------------------------------------------*/
-
-void _FiniteElementContext_Delete( void* context ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	
-	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
-
-	Stream_IndentBranch( StgFEM_Debug );
-	Journal_DPrintfL( self->debug, 2, "Deleting the element type register (and hence all element types).\n" );
-	Journal_DPrintfL( self->debug, 2, "Deleting all SLEs and the SLE list.\n" );
-	/* Disabling the next 2 lines as the slEquations and its object lists are 
-	deleted later on from the LiveComponentRegister (via LiveComponentRegister_DeleteAll) 
-	Stg_ObjectList_DeleteAllObjects( self->slEquations ); 
-	Stg_Class_Delete( self->slEquations ); */
-	Stream_UnIndentBranch( StgFEM_Debug );
-
-	/* Stg_Class_Delete parent */
-	_DomainContext_Delete( self );
-}
-
-void _FiniteElementContext_Destroy( void* context ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	
-   Stg_Class_Delete( self->slEquations );
-	_DomainContext_Destroy( self );
-}
-
-void _FiniteElementContext_Print( void* context, Stream* stream ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	
-	/* General info */
-	Journal_Printf( (void*) stream, "FiniteElementContext (ptr): %p\n", self );
-	
-	/* Print parent */
-	_DomainContext_Print( self, stream );
-
-	Journal_Printf( (void*) stream, "\tslEquations (ptr): %p\n", self->slEquations );
-	Stg_Class_Print( self->slEquations, stream );
-}
-
-
-void _FiniteElementContext_SetDt( void* context, double dt ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	
-	self->dt = dt;
-}
-
-
-/* Public Functions --------------------------------------------------------------------------------------------------------------*/
-
-void FiniteElementContext_AddSLE_Func( void* context, void* sle ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	
-	FiniteElementContext_AddSLE_Macro( self, sle );
-}
-
-
-SystemLinearEquations* FiniteElementContext_GetSLE_Func( void* context, Name sleName ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	
-	return FiniteElementContext_GetSLE_Macro( self, sleName );
-}
-
-
-/* EntryPoint Hooks --------------------------------------------------------------------------------------------------------------*/
-
-void _FiniteElementContext_AssignFromXML( void* context, Stg_ComponentFactory* cf, void* data ){
-	FiniteElementContext *self = (FiniteElementContext*) context;
-	Stream*  errorStream = Journal_Register( Error_Type, (Name)self->type  );
-
-	_DomainContext_AssignFromXML( context, cf, data );
-
-	self->dictionary = cf->rootDict;
-
-	self->dt = 0.0f;
-	self->prevTimestepDt = 0.0;
-	self->limitTimeStepIncreaseRate = Dictionary_GetBool_WithDefault( self->dictionary, (Dictionary_Entry_Key)"limitTimeStepIncreaseRate", False  );
-	self->maxTimeStepIncreasePercentage = Dictionary_GetDouble_WithDefault( self->dictionary, (Dictionary_Entry_Key)"maxTimeStepIncreasePercentage", 10.0  );
-	Journal_Firewall( self->maxTimeStepIncreasePercentage >= 0, errorStream,
-		"Error - in %s(): maxTimeStepIncreasePercentage must be >= 0\n", __func__ );
-
-	self->maxTimeStepSize = Dictionary_GetDouble_WithDefault( self->dictionary, (Dictionary_Entry_Key)"maxTimeStepSize", 0.0 );
-
-	_FiniteElementContext_Init( self );
-}
-
-void _FiniteElementContext_Build( void* context ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	SystemLinearEquations_Index sle_I;
-	
-	Stream_IndentBranch( StgFEM_Debug  );
-	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
-
-	/* build all the systems of linear equations */
-	for ( sle_I = 0; sle_I < self->slEquations->count; sle_I++ ) {
-		Stg_Component_Build( self->slEquations->data[sle_I], self, False );
-	}
-
-	/* TODO:
-	This call shouldn't really be necessary - each variable used should be built
-	by the FeVariable that needs it, via its dofLayout. However, unfortunately with
-	"Vector" variables that use it, the app fails without this call - since otherwise
-	the "velocity" variable doesn't get build, only "vx", "vy" and "vz".
-	Need to debug this properly later.
-	*/
-	Variable_Register_BuildAll( self->variable_Register );
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _FiniteElementContext_Initialise( void* context ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	SystemLinearEquations_Index sle_I;
-	
-	Stream_IndentBranch( StgFEM_Debug );
-	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
-
-	/* initialise all the systems of linear equations */
-	for ( sle_I = 0; sle_I < self->slEquations->count; sle_I++ ) {
-		Stg_Component_Initialise( self->slEquations->data[sle_I], self, False );
-	}
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _FiniteElementContext_Solve( void* context ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-	SystemLinearEquations_Index sle_I;
-	
-	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	/* solve all the systems of linear equations */
-	for ( sle_I = 0; sle_I < self->slEquations->count; sle_I++ ) {
-		SystemLinearEquations*	currentSLE = (SystemLinearEquations*)self->slEquations->data[sle_I];
-		Journal_DPrintf( self->debug, "Solving for this timestep the %s SLE:\n", self->slEquations->data[sle_I]->name );
-		/* TODO: FeVariable should have the option of rebuilding ID and LM, based on sim.
-		loop if geometry or BCs change...need to improve interface. */
-		/* We set the "force" flag to True here - want the SLE to be re-solved every timestep */
-		Stg_Component_Execute( currentSLE, self, True );
-	}
-	
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _FiniteElementContext_PostSolve( void* context ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-
-	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	FiniteElementContext_CalcNewDt( self ) ;
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-double _FiniteElementContext_GetDt( void* context ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-
-	return self->dt;
-}
-
-double FiniteElementContext_CalcNewDt( void* context ) {
-	FiniteElementContext* self = (FiniteElementContext*)context;
-
-	self->prevTimestepDt = self->dt;
-	
-	if ( self->calcDtEP->hooks->count == 0 ) {
-		self->dt = 0.0;
-	}
-	else {
-		self->dt = _EntryPoint_Run_Class_Minimum_VoidPtr( self->calcDtEP, self );
-	}	
-		
-	if ( ( self->timeStep > 1 ) && ( self->limitTimeStepIncreaseRate == True ) ) {
-		double  maxAllowedDt = self->prevTimestepDt * ( 1 + self->maxTimeStepIncreasePercentage / 100 );
-
-		if ( self->dt > maxAllowedDt ) {
-			int prevContextPrintingRank = Stream_GetPrintingRank( self->info );
-			/* We assume the dt calculation will be the same across all procs since its a global
-			  operation, so only print this once */
-			Stream_SetPrintingRank( self->info, 0 );
-			Journal_Printf( 
-				self->info, 
-				"In %s(): dt calculated was %g (time), but prev timestep's dt\n"
-				"was %g (time) and max allowed increase percentage is %.2f\n, thus limiting current\n"
-				"dt to %g (time).\n", 
-				__func__, 
-				self->dt, 
-				self->prevTimestepDt,
-				self->maxTimeStepIncreasePercentage, 
-				maxAllowedDt );
-			self->dt = maxAllowedDt;
-			Stream_SetPrintingRank( self->info, prevContextPrintingRank );
-		}
-	}
-
-        if( self->maxTimeStepSize > 0.0 ) {
-           if( self->dt > self->maxTimeStepSize )
-              self->dt = self->maxTimeStepSize;
-        }
-	
-	return self->dt;
-}
-
-
-void _FiniteElementContext_SaveFeVariables( void* context ) {
-	FiniteElementContext*     self = (FiniteElementContext*) context;
-	Index                     var_I = 0;
-	FieldVariable*            fieldVar = NULL;
-	FeVariable*               feVar = NULL;
-
-    /* Save the variables that have had their "isCheckpointedAndReloaded" flag enabled - 
-	 *  default is true, but the user may restrict the list by specifying the "FieldVariablesToCheckpoint"
-	 *  flag in their constructor - see _FeVariable_AssignFromXML().
-	 */ 	
-	for ( var_I = 0; var_I < self->fieldVariable_Register->objects->count; var_I++ ) {
-		fieldVar = FieldVariable_Register_GetByIndex( self->fieldVariable_Register, var_I );
-
-		if ( Stg_Class_IsInstance( fieldVar, FeVariable_Type ) ) {
-			feVar = (FeVariable*)fieldVar;	
-         if ( (feVar->isCheckpointedAndReloaded && (self->timeStep % self->checkpointEvery == 0))                                  ||
-              (feVar->isCheckpointedAndReloaded && (self->checkpointAtTimeInc && (self->currentTime >= self->nextCheckpointTime))) ||
-              (feVar->isSavedData               && (self->timeStep % self->saveDataEvery   == 0)) ){
-            char*			feVarSaveFileName     = NULL;
-            char*			feVarSaveFileNamePart = NULL;   
-
-            feVarSaveFileNamePart = Context_GetCheckPointWritePrefixString( (void*)self );
-
-#ifdef WRITE_HDF5
-            Stg_asprintf( &feVarSaveFileName, "%s%s.%.5u.h5" , feVarSaveFileNamePart, feVar->name, self->timeStep );
-#else
-            Stg_asprintf( &feVarSaveFileName, "%s%s.%.5u.dat", feVarSaveFileNamePart, feVar->name, self->timeStep );
-#endif
-            FeVariable_SaveToFile( feVar, feVarSaveFileName, 
-                   Dictionary_GetBool_WithDefault( self->dictionary, (Dictionary_Entry_Key)"saveCoordsWithFields", False ) );           
-
-            Memory_Free( feVarSaveFileName );
-            Memory_Free( feVarSaveFileNamePart );
-         }
-		}
-	}
-}
-
-
-void _FiniteElementContext_SaveSwarms( void* context ) {
-
-	Swarm_Register_SaveAllRegisteredSwarms( 
-		Swarm_Register_GetSwarm_Register( ), context );
-
-}
-
-
-void _FiniteElementContext_SaveMesh( void* context ) {
-   FiniteElementContext*   self;
-	Stream*                 info = Journal_Register( Info_Type, (Name)"Context" );
-   unsigned                componentCount = LiveComponentRegister_GetCount(stgLiveComponentRegister );
-   unsigned                compI;
-   Stg_Component*          stgComp;
-   FeMesh*                 mesh;
-   
-	Journal_Printf( info, "In %s(): about to save the mesh to disk:\n", __func__ );
-
-	self = (FiniteElementContext*) context;
-
-   /** search for entire live component register for feMesh types  **/
-   for( compI = 0 ; compI < componentCount ; compI++){
-      stgComp = LiveComponentRegister_At( stgLiveComponentRegister, compI );
-      /* check that component is of type FeMesh */
-      if ( Stg_Class_IsInstance( stgComp, FeMesh_Type ) ) {
-         mesh   = (FeMesh*)stgComp;
-         if( mesh->isCheckpointedAndReloaded == True && mesh->requiresCheckpointing == True ){         
-#ifdef WRITE_HDF5
-         _FiniteElementContext_DumpMeshHDF5( context, mesh );
-#else
-         _FiniteElementContext_DumpMeshAscii( context, mesh );
-#endif
-         }
-      }
-   }
-	Journal_Printf( info, "%s: saving of mesh completed.\n", __func__ );
-}
-
-#ifndef WRITE_HDF5
-void _FiniteElementContext_DumpMeshAscii( void* context, FeMesh* feMesh ) {
-   FiniteElementContext*   self = (FiniteElementContext*) context;
-   FieldVariable*    fieldVar = NULL;
-	FeVariable*       feVar = NULL;
-	Mesh* 			   mesh;
-	int 			      rank, nRanks;  
-	FILE*			      outputFile;
-	int               confirmation = 0;
-	MPI_Status        status;
-	Node_LocalIndex   lNode_I = 0;
-	Node_GlobalIndex  gNode_I = 0;
-	double*           coord;
-	unsigned          nDims;
-	char*             filename = NULL;
-	char*             meshSaveFileNamePart = NULL;
-
-   meshSaveFileNamePart = Context_GetCheckPointWritePrefixString( (void*)self );
-	
-   Stg_asprintf( &filename, "%sMesh.%s.%.5u.dat", meshSaveFileNamePart, feMesh->name, self->timeStep );
-	
-	MPI_Comm_rank( self->communicator, &rank);
-	MPI_Comm_size( self->communicator, &nRanks );	
-
-	mesh = (Mesh*)feMesh;
-	
-	nDims = Mesh_GetDimSize( mesh );	
-		
-	/* wait for go-ahead from process ranked lower than me, to avoid competition writing to file */
-	if ( rank != 0 ) {
-		MPI_Recv( &confirmation, 1, MPI_INT, rank - 1, FINISHED_WRITING_TAG, self->communicator, &status );
-	}	
-
-	if ( rank == 0 ) {
-		outputFile = fopen( filename, "w" );
-		assert( outputFile );
-		
-		/* Write min and max coords to file */
-		if( nDims == 2 ) {
-            		fprintf( outputFile, "Min: %.15g %.15g 0\n", mesh->minGlobalCrd[0], mesh->minGlobalCrd[1] );
-            		fprintf( outputFile, "Max: %.15g %.15g 0\n", mesh->maxGlobalCrd[0], mesh->maxGlobalCrd[1] );
-      		} 
-		else {
-            		fprintf( outputFile, "Min: %.15g %.15g %.15g\n", mesh->minGlobalCrd[0], mesh->minGlobalCrd[1], mesh->minGlobalCrd[2] );
-            		fprintf( outputFile, "Max: %.15g %.15g %.15g\n", mesh->maxGlobalCrd[0], mesh->maxGlobalCrd[1], mesh->maxGlobalCrd[2] );  
-		}
-	}
-	else {
-		outputFile = fopen( filename, "a" );
-		assert( outputFile );
-	}	
-
-   for ( lNode_I = 0; lNode_I < FeMesh_GetNodeLocalSize( mesh ); lNode_I++ ) {
-	   gNode_I = FeMesh_NodeDomainToGlobal( mesh, lNode_I );
-	   fprintf( outputFile, "%u ", gNode_I );
-	   coord = Mesh_GetVertex( mesh, lNode_I );
-                   
-      if(self->dim==2)
-         fprintf( outputFile, "%.15g %.15g 0\n", coord[0], coord[1] );
-      else
-         fprintf( outputFile, "%.15g %.15g %.15g\n", coord[0], coord[1], coord[2] );
-	}
-	
-	fclose( outputFile );
-	
-	/* send go-ahead from process ranked lower than me, to avoid competition writing to file */
-	if ( rank != nRanks - 1 ) {
-		MPI_Ssend( &confirmation, 1, MPI_INT, rank + 1, FINISHED_WRITING_TAG, self->communicator );
-	}	
-   Memory_Free( meshSaveFileNamePart );
-   Memory_Free( filename );
-
-}
-#endif
-
-#ifdef WRITE_HDF5
-void _FiniteElementContext_DumpMeshHDF5( void* context, FeMesh* mesh ) {
-   FiniteElementContext*   self = (FiniteElementContext*) context;
-   int                     rank, nRanks;
-   unsigned                nDims;
-   hid_t                   file, fileSpace, fileData, fileSpace2, fileData2;
-   hid_t                   memSpace;
-   hsize_t                 start[2], count[2], size[2];
-   unsigned                totalVerts;
-   Node_LocalIndex         lNode_I = 0;
-   Node_GlobalIndex        gNode_I = 0;
-   double*                 coord;
-   int                     buf_int[5];
-   MPI_Status              status;
-   int                     confirmation = 0;
-   Stream*                 errorStr = Journal_Register( Error_Type, (Name)self->type );
-   Element_LocalIndex      lElement_I;
-   Element_GlobalIndex     gElement_I;
-   Index                   maxNodes;
-   IArray*                 iarray = IArray_New( );
-   char*                   filename = NULL;
-   char*                   meshSaveFileNamePart = NULL;
-
-   /* don't dump irregular meshes, as havn't accounted for their connectivity yet...
-    * TODO: this is a hack, as we don't know about the IrregularQuadGenerator yet in StgFEM. Need to account
-    * for unstructured meshes at some point in the future... dave 01.10.09 */
-   if( !strcmp( mesh->generator->type, "IrregularQuadGenerator" ) )
-      return;
-
-   meshSaveFileNamePart = Context_GetCheckPointWritePrefixString( context );
-
-   MPI_Comm_rank( self->communicator, &rank);
-   MPI_Comm_size( self->communicator, &nRanks );   
-         
-   filename = NULL;
-   Stg_asprintf( &filename, "%sMesh.%s.%.5u.h5", meshSaveFileNamePart, mesh->name, self->timeStep );
-
-   nDims  = Mesh_GetDimSize( mesh );
-
-   /* wait for go-ahead from process ranked lower than me, to avoid competition writing to file */
-   if ( rank != 0 ) {
-      MPI_Recv( &confirmation, 1, MPI_INT, rank - 1, FINISHED_WRITING_TAG, self->communicator, &status );
-   }	
-
-   if ( rank == 0 ) {
-      hid_t      attribData_id, attrib_id, group_id;
-      hsize_t    a_dims;
-      int        attribData;
-      Grid**     grid;
-      unsigned*  sizes;
-
-      /* Open the HDF5 output file. */
-      file = H5Fcreate( filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
-      assert( file );
-
-      /** create file attribute */
-      /** first store the checkpointing version */
-      a_dims = 1;
-      attribData = MeshCHECKPOINT_V2;
-      attribData_id = H5Screate_simple(1, &a_dims, NULL);
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-         group_id  = H5Gopen(file, "/");
-         attrib_id = H5Acreate(group_id, "checkpoint file version", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
-      #else
-         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
-         attrib_id = H5Acreate2(group_id, "checkpoint file version", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
-      #endif
-      H5Awrite(attrib_id, H5T_NATIVE_INT, &attribData);
-      H5Aclose(attrib_id);
-      H5Gclose(group_id);
-      H5Sclose(attribData_id);
-
-      /** store the mesh dimensionality */
-      a_dims = 1;
-      attribData = self->dim;
-      attribData_id = H5Screate_simple(1, &a_dims, NULL);
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-         group_id  = H5Gopen(file, "/");
-         attrib_id = H5Acreate(group_id, "dimensions", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
-      #else
-         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
-         attrib_id = H5Acreate2(group_id, "dimensions", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
-      #endif
-      H5Awrite(attrib_id, H5T_NATIVE_INT, &attribData);
-      H5Aclose(attrib_id);
-      H5Gclose(group_id);
-      H5Sclose(attribData_id);
-       
-      /** store the mesh resolution */
-      a_dims = self->dim;
-      grid   = (Grid**) Mesh_GetExtension( mesh, Grid*, "elementGrid" );	
-      sizes  =          Grid_GetSizes( *grid ); /** global no. of elements in each dim */
-      
-      attribData_id = H5Screate_simple(1, &a_dims, NULL);
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-         group_id  = H5Gopen(file, "/");
-         attrib_id = H5Acreate(group_id, "mesh resolution", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
-      #else
-         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
-         attrib_id = H5Acreate2(group_id, "mesh resolution", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
-      #endif
-      H5Awrite(attrib_id, H5T_NATIVE_INT, sizes);
-      H5Aclose(attrib_id);
-      H5Gclose(group_id);
-      H5Sclose(attribData_id);
-   
-      /* Dump the min and max coords, and number of processes. */
-      count[0] = (hsize_t)nDims;
-      fileSpace = H5Screate_simple( 1, count, NULL );         
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData = H5Dcreate( file, "/min", H5T_NATIVE_DOUBLE, fileSpace, H5P_DEFAULT );
-      #else
-      fileData = H5Dcreate2( file, "/min", H5T_NATIVE_DOUBLE, fileSpace,
-                               H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
-      #endif
-                  
-      H5Dwrite( fileData, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, mesh->minGlobalCrd );
-      H5Dclose( fileData );
-      H5Sclose( fileSpace );
-         
-      fileSpace = H5Screate_simple( 1, count, NULL );       
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData = H5Dcreate( file, "/max", H5T_NATIVE_DOUBLE, fileSpace, H5P_DEFAULT );
-      #else
-      fileData = H5Dcreate2( file, "/max", H5T_NATIVE_DOUBLE, fileSpace,
-                               H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
-      #endif
-            
-      H5Dwrite( fileData, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, mesh->maxGlobalCrd );
-      H5Dclose( fileData );
-      H5Sclose( fileSpace );
-       
-      /* Write vertex coords to file */   
-      /* Create our output space and data objects. */
-      totalVerts = Mesh_GetGlobalSize( mesh, (MeshTopology_Dim)0 );
-      size[0] = (hsize_t)totalVerts;
-      size[1] = (hsize_t)nDims;
-      
-      fileSpace = H5Screate_simple( 2, size, NULL );
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData = H5Dcreate( file, "/vertices", H5T_NATIVE_DOUBLE, fileSpace, H5P_DEFAULT );
-      #else
-      fileData = H5Dcreate2( file, "/vertices", H5T_NATIVE_DOUBLE, fileSpace,
-                            H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
-      #endif
-
-      /* setup element connectivity dataspaces */
-      if (mesh->nElTypes == 1)
-         maxNodes = FeMesh_GetElementNodeSize( mesh, 0);
-      else {
-         /* determine the maximum number of nodes each element has */
-         maxNodes = 0;
-         for ( gElement_I = 0 ; gElement_I < FeMesh_GetElementGlobalSize(mesh); gElement_I++ ) {
-            unsigned numNodes;
-            numNodes = FeMesh_GetElementNodeSize( mesh, gElement_I);
-            if( maxNodes < numNodes ) maxNodes = numNodes;
-         }
-      }
-      
-      size[0] = (hsize_t)FeMesh_GetElementGlobalSize(mesh);
-      size[1] = (hsize_t)maxNodes;
-      /* Create our output space and data objects. */         
-      fileSpace2 = H5Screate_simple( 2, size, NULL );
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData2 = H5Dcreate( file, "/connectivity", H5T_NATIVE_INT, fileSpace2, H5P_DEFAULT );
-      #else
-      fileData2 = H5Dcreate2( file, "/connectivity", H5T_NATIVE_INT, fileSpace2,
-                            H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
-      #endif
-
-   } else {
-      /* Open the HDF5 output file. */
-      file = H5Fopen( filename, H5F_ACC_RDWR, H5P_DEFAULT );
-      Journal_Firewall( 
-         file >= 0, 
-         errorStr,
-         "Error in %s for %s '%s' - Cannot open file %s.\n", 
-         __func__, 
-         self->type, 
-         self->name, 
-         filename );
-
-      /* get the node filespace */   
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData  = H5Dopen( file, "/vertices" );
-      #else
-      fileData  = H5Dopen2( file, "/vertices", H5P_DEFAULT );
-      #endif
-      /* get the filespace handle */
-      fileSpace = H5Dget_space(fileData);
-
-      /* get the connectivity */   
-      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
-      fileData2  = H5Dopen( file, "/connectivity" );
-      #else
-      fileData2  = H5Dopen2( file, "/connectivity", H5P_DEFAULT );
-      #endif
-      /* get the filespace handle */
-      fileSpace2 = H5Dget_space(fileData2);
-   }	
-      
-   count[0] = 1;
-   count[1] = nDims;
-   memSpace = H5Screate_simple( 2, count, NULL );
-   H5Sselect_all( memSpace );
-                     
-   for ( lNode_I = 0; lNode_I < FeMesh_GetNodeLocalSize( mesh ); lNode_I++ ) {
-      gNode_I = FeMesh_NodeDomainToGlobal( mesh, lNode_I );
-      
-      coord = Mesh_GetVertex( mesh, lNode_I );
-      
-      /* select the region of dataspace to write to  */
-      start[1] = 0;
-      start[0] = gNode_I;
-      H5Sselect_hyperslab( fileSpace, H5S_SELECT_SET, start, NULL, count, NULL );
-      
-      H5Dwrite( fileData, H5T_NATIVE_DOUBLE, memSpace, fileSpace, H5P_DEFAULT, coord );
-   }
-   
-   /* Close off all our handles. */
-   H5Sclose( memSpace );
-   H5Dclose( fileData );
-   H5Sclose( fileSpace );
-
-   H5Sget_simple_extent_dims( fileSpace2, size, NULL );
-   count[0] = 1;
-   count[1] = size[1];
-   memSpace = H5Screate_simple( 2, count, NULL );
-   H5Sselect_all( memSpace );
-                     
-   for ( lElement_I = 0 ; lElement_I < FeMesh_GetElementLocalSize(mesh); lElement_I++ ) {
-      int*    nodeList, nodesPerEl;
-      int     node_I;
-      
-      gElement_I = FeMesh_ElementDomainToGlobal( mesh,lElement_I );
-
-      /* get element nodes */
-      FeMesh_GetElementNodes( mesh, lElement_I, iarray );
-      nodesPerEl = IArray_GetSize( iarray );
-      nodeList   = IArray_GetPtr(  iarray );
-      
-      for( node_I = 0 ; node_I < nodesPerEl ; node_I++ )
-         buf_int[node_I] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[node_I] );
-      /* some reordering is required to account for standard node ordering */ 
-      buf_int[3] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[2] );
-      buf_int[2] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[3] );
-      if( nDims == 3 ) {
-         buf_int[7] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[6] );
-         buf_int[6] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[7] );
-      }
-      /* select the region of dataspace to write to  */
-      start[1] = 0;
-      start[0] = gElement_I;
-      H5Sselect_hyperslab( fileSpace2, H5S_SELECT_SET, start, NULL, count, NULL );
-      
-      H5Dwrite( fileData2, H5T_NATIVE_INT, memSpace, fileSpace2, H5P_DEFAULT, buf_int );
-   }
-   
-   /* Close off all our handles. */
-   H5Sclose( memSpace );
-   H5Dclose( fileData2 );
-   H5Sclose( fileSpace2 );
-   H5Fclose( file );
-
-   /* send go-ahead from process ranked lower than me, to avoid competition writing to file */
-   if ( rank != nRanks - 1 ) {
-      MPI_Ssend( &confirmation, 1, MPI_INT, rank + 1, FINISHED_WRITING_TAG, self->communicator );
-   }	
-   
-   Memory_Free( filename );
-      
-   Memory_Free( meshSaveFileNamePart );
-   NewClass_Delete( iarray );
-}
-#endif
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/FiniteElementContext.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/FiniteElementContext.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,838 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Context.c 1207 2008-08-17 15:16:25Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "FiniteElementContext.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "SystemLinearEquations.h"
+#include "SolutionVector.h"
+
+#ifdef WRITE_HDF5
+#include <hdf5.h>
+#endif
+
+#define FINISHED_WRITING_TAG 9
+
+/* Textual name of this class */
+const Type FiniteElementContext_Type = "FiniteElementContext";
+const Name defaultFiniteElementContextETypeRegisterName = "finiteElementContext";
+const Name FiniteElementContext_EP_CalcDt = "FiniteElementContext_EP_CalcDt";
+
+/* Constructors ------------------------------------------------------------------------------------------------------------------*/
+
+FiniteElementContext* FiniteElementContext_New(
+	Name			name,
+	double		start,
+	double		stop,
+	MPI_Comm		communicator,
+	Dictionary*	dictionary )
+{
+  FiniteElementContext* self = (FiniteElementContext*)FiniteElementContext_DefaultNew( name );
+
+	self->isConstructed = True;
+	_AbstractContext_Init( (AbstractContext*) self );
+	_DomainContext_Init( (DomainContext*) self );	
+	_FiniteElementContext_Init( self );
+
+	return self;
+}
+	
+void* FiniteElementContext_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(FiniteElementContext);
+	Type                                                      type = FiniteElementContext_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FiniteElementContext_Delete;
+	Stg_Class_PrintFunction*                                _print = _FiniteElementContext_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = FiniteElementContext_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _FiniteElementContext_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _AbstractContext_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _AbstractContext_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AbstractContext_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = (Stg_Component_DestroyFunction*)_FiniteElementContext_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+	AbstractContext_SetDt*                                  _setDt = _FiniteElementContext_SetDt;
+	double                                               startTime = 0;
+	double                                                stopTime = 0;
+	MPI_Comm                                          communicator = MPI_COMM_WORLD;
+	Dictionary*                                         dictionary = NULL;
+
+	return _FiniteElementContext_New(  FINITEELEMENTCONTEXT_PASSARGS  );
+}
+
+FiniteElementContext* _FiniteElementContext_New(  FINITEELEMENTCONTEXT_DEFARGS  ) {
+	FiniteElementContext* self;
+	
+	/* Allocate memory */
+	self = (FiniteElementContext*)_DomainContext_New(  DOMAINCONTEXT_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _FiniteElementContext_Init( FiniteElementContext* self ) {
+	/* Set up stream preferences */
+	Journal_Enable_NamedStream( InfoStream_Type, "StgFEM_VerboseConfig", False );
+
+	/* register this current stream (the context) as a child of the FE stream */
+	/* TODO: Want to be able to recombine this with the Abs context's debug stream at some stage */
+	self->debug = Stream_RegisterChild( StgFEM_Debug, FiniteElementContext_Type );
+	
+	/* set up s.l.e list */
+	self->slEquations = Stg_ObjectList_New();
+
+	/* Create Entry Point for Calculating timestep */
+	self->calcDtEP = EntryPoint_New( FiniteElementContext_EP_CalcDt, EntryPoint_Minimum_VoidPtr_CastType );
+	EntryPoint_Register_Add( self->entryPoint_Register, self->calcDtEP );
+	
+	/* Add hooks to existing entry points... use name "default" so that plugin, etc can exert same behaviour on other contexts*/
+	EntryPoint_Prepend( 
+		Context_GetEntryPoint( self, AbstractContext_EP_Build ),
+		"_FiniteElementContext_Build", 
+		(void*)_FiniteElementContext_Build, 
+		FiniteElementContext_Type );
+	EntryPoint_Prepend( 
+		Context_GetEntryPoint( self, AbstractContext_EP_Initialise ),
+		"_FiniteElementContext_Initialise", 
+		(void*)_FiniteElementContext_Initialise, 
+		FiniteElementContext_Type );
+	EntryPoint_Append( 
+		Context_GetEntryPoint( self, AbstractContext_EP_Solve ),
+		"_FiniteElementContext_Solve", 
+		(void*)_FiniteElementContext_Solve, 
+		FiniteElementContext_Type );
+	EntryPoint_Append( 
+		Context_GetEntryPoint( self, AbstractContext_EP_Solve ),
+		"_FiniteElementContext_PostSolve", 
+		(void*)_FiniteElementContext_PostSolve, 
+		FiniteElementContext_Type );
+	EntryPoint_Append( 
+		Context_GetEntryPoint( self, AbstractContext_EP_Dt ),
+		"_FiniteElementContext_GetDt", 
+		(void*)_FiniteElementContext_GetDt, 
+		FiniteElementContext_Type );
+
+	EntryPoint_Append(
+		Context_GetEntryPoint( self, AbstractContext_EP_Save ),
+		"_FiniteElementContext_SaveFeVariables",
+		(void*)_FiniteElementContext_SaveFeVariables,
+		FiniteElementContext_Type );
+
+	EntryPoint_Append(
+		Context_GetEntryPoint( self, AbstractContext_EP_DataSave ),
+		"_FiniteElementContext_SaveFeVariables",
+		(void*)_FiniteElementContext_SaveFeVariables,
+		FiniteElementContext_Type );
+	/* The FEM context needs to save gauss swarms so they can be re-loaded for restart later.
+	   This will automatically save material point swarms too if PICellerator is used.
+	 */
+	EntryPoint_Append(
+		Context_GetEntryPoint( self, AbstractContext_EP_Save ),
+		"_FiniteElementContext_SaveSwarms",
+		(void*)_FiniteElementContext_SaveSwarms,
+		FiniteElementContext_Type );
+
+	EntryPoint_Append(
+		Context_GetEntryPoint( self, AbstractContext_EP_Save ),
+		"_FiniteElementContext_SaveMesh",
+		(void*)_FiniteElementContext_SaveMesh,
+		FiniteElementContext_Type );
+
+	EntryPoint_Append(
+		Context_GetEntryPoint( self, AbstractContext_EP_DataSave ),
+		"_FiniteElementContext_SaveMesh",
+		(void*)_FiniteElementContext_SaveMesh,
+		FiniteElementContext_Type );
+}
+
+
+/* Virtual Functions -------------------------------------------------------------------------------------------------------------*/
+
+void _FiniteElementContext_Delete( void* context ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	
+	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
+
+	Stream_IndentBranch( StgFEM_Debug );
+	Journal_DPrintfL( self->debug, 2, "Deleting the element type register (and hence all element types).\n" );
+	Journal_DPrintfL( self->debug, 2, "Deleting all SLEs and the SLE list.\n" );
+	/* Disabling the next 2 lines as the slEquations and its object lists are 
+	deleted later on from the LiveComponentRegister (via LiveComponentRegister_DeleteAll) 
+	Stg_ObjectList_DeleteAllObjects( self->slEquations ); 
+	Stg_Class_Delete( self->slEquations ); */
+	Stream_UnIndentBranch( StgFEM_Debug );
+
+	/* Stg_Class_Delete parent */
+	_DomainContext_Delete( self );
+}
+
+void _FiniteElementContext_Destroy( void* context ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	
+   Stg_Class_Delete( self->slEquations );
+	_DomainContext_Destroy( self );
+}
+
+void _FiniteElementContext_Print( void* context, Stream* stream ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	
+	/* General info */
+	Journal_Printf( (void*) stream, "FiniteElementContext (ptr): %p\n", self );
+	
+	/* Print parent */
+	_DomainContext_Print( self, stream );
+
+	Journal_Printf( (void*) stream, "\tslEquations (ptr): %p\n", self->slEquations );
+	Stg_Class_Print( self->slEquations, stream );
+}
+
+
+void _FiniteElementContext_SetDt( void* context, double dt ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	
+	self->dt = dt;
+}
+
+
+/* Public Functions --------------------------------------------------------------------------------------------------------------*/
+
+void FiniteElementContext_AddSLE_Func( void* context, void* sle ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	
+	FiniteElementContext_AddSLE_Macro( self, sle );
+}
+
+
+SystemLinearEquations* FiniteElementContext_GetSLE_Func( void* context, Name sleName ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	
+	return FiniteElementContext_GetSLE_Macro( self, sleName );
+}
+
+
+/* EntryPoint Hooks --------------------------------------------------------------------------------------------------------------*/
+
+void _FiniteElementContext_AssignFromXML( void* context, Stg_ComponentFactory* cf, void* data ){
+	FiniteElementContext *self = (FiniteElementContext*) context;
+	Stream*  errorStream = Journal_Register( Error_Type, (Name)self->type  );
+
+	_DomainContext_AssignFromXML( context, cf, data );
+
+	self->dictionary = cf->rootDict;
+
+	self->dt = 0.0f;
+	self->prevTimestepDt = 0.0;
+	self->limitTimeStepIncreaseRate = Dictionary_GetBool_WithDefault( self->dictionary, (Dictionary_Entry_Key)"limitTimeStepIncreaseRate", False  );
+	self->maxTimeStepIncreasePercentage = Dictionary_GetDouble_WithDefault( self->dictionary, (Dictionary_Entry_Key)"maxTimeStepIncreasePercentage", 10.0  );
+	Journal_Firewall( self->maxTimeStepIncreasePercentage >= 0, errorStream,
+		"Error - in %s(): maxTimeStepIncreasePercentage must be >= 0\n", __func__ );
+
+	self->maxTimeStepSize = Dictionary_GetDouble_WithDefault( self->dictionary, (Dictionary_Entry_Key)"maxTimeStepSize", 0.0 );
+
+	_FiniteElementContext_Init( self );
+}
+
+void _FiniteElementContext_Build( void* context ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	SystemLinearEquations_Index sle_I;
+	
+	Stream_IndentBranch( StgFEM_Debug  );
+	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
+
+	/* build all the systems of linear equations */
+	for ( sle_I = 0; sle_I < self->slEquations->count; sle_I++ ) {
+		Stg_Component_Build( self->slEquations->data[sle_I], self, False );
+	}
+
+	/* TODO:
+	This call shouldn't really be necessary - each variable used should be built
+	by the FeVariable that needs it, via its dofLayout. However, unfortunately with
+	"Vector" variables that use it, the app fails without this call - since otherwise
+	the "velocity" variable doesn't get build, only "vx", "vy" and "vz".
+	Need to debug this properly later.
+	*/
+	Variable_Register_BuildAll( self->variable_Register );
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _FiniteElementContext_Initialise( void* context ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	SystemLinearEquations_Index sle_I;
+	
+	Stream_IndentBranch( StgFEM_Debug );
+	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
+
+	/* initialise all the systems of linear equations */
+	for ( sle_I = 0; sle_I < self->slEquations->count; sle_I++ ) {
+		Stg_Component_Initialise( self->slEquations->data[sle_I], self, False );
+	}
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _FiniteElementContext_Solve( void* context ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+	SystemLinearEquations_Index sle_I;
+	
+	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	/* solve all the systems of linear equations */
+	for ( sle_I = 0; sle_I < self->slEquations->count; sle_I++ ) {
+		SystemLinearEquations*	currentSLE = (SystemLinearEquations*)self->slEquations->data[sle_I];
+		Journal_DPrintf( self->debug, "Solving for this timestep the %s SLE:\n", self->slEquations->data[sle_I]->name );
+		/* TODO: FeVariable should have the option of rebuilding ID and LM, based on sim.
+		loop if geometry or BCs change...need to improve interface. */
+		/* We set the "force" flag to True here - want the SLE to be re-solved every timestep */
+		Stg_Component_Execute( currentSLE, self, True );
+	}
+	
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _FiniteElementContext_PostSolve( void* context ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+
+	Journal_DPrintf( self->debug, "In: %s()\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	FiniteElementContext_CalcNewDt( self ) ;
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+double _FiniteElementContext_GetDt( void* context ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+
+	return self->dt;
+}
+
+double FiniteElementContext_CalcNewDt( void* context ) {
+	FiniteElementContext* self = (FiniteElementContext*)context;
+
+	self->prevTimestepDt = self->dt;
+	
+	if ( self->calcDtEP->hooks->count == 0 ) {
+		self->dt = 0.0;
+	}
+	else {
+		self->dt = _EntryPoint_Run_Class_Minimum_VoidPtr( self->calcDtEP, self );
+	}	
+		
+	if ( ( self->timeStep > 1 ) && ( self->limitTimeStepIncreaseRate == True ) ) {
+		double  maxAllowedDt = self->prevTimestepDt * ( 1 + self->maxTimeStepIncreasePercentage / 100 );
+
+		if ( self->dt > maxAllowedDt ) {
+			int prevContextPrintingRank = Stream_GetPrintingRank( self->info );
+			/* We assume the dt calculation will be the same across all procs since its a global
+			  operation, so only print this once */
+			Stream_SetPrintingRank( self->info, 0 );
+			Journal_Printf( 
+				self->info, 
+				"In %s(): dt calculated was %g (time), but prev timestep's dt\n"
+				"was %g (time) and max allowed increase percentage is %.2f\n, thus limiting current\n"
+				"dt to %g (time).\n", 
+				__func__, 
+				self->dt, 
+				self->prevTimestepDt,
+				self->maxTimeStepIncreasePercentage, 
+				maxAllowedDt );
+			self->dt = maxAllowedDt;
+			Stream_SetPrintingRank( self->info, prevContextPrintingRank );
+		}
+	}
+
+        if( self->maxTimeStepSize > 0.0 ) {
+           if( self->dt > self->maxTimeStepSize )
+              self->dt = self->maxTimeStepSize;
+        }
+	
+	return self->dt;
+}
+
+
+void _FiniteElementContext_SaveFeVariables( void* context ) {
+	FiniteElementContext*     self = (FiniteElementContext*) context;
+	Index                     var_I = 0;
+	FieldVariable*            fieldVar = NULL;
+	FeVariable*               feVar = NULL;
+
+    /* Save the variables that have had their "isCheckpointedAndReloaded" flag enabled - 
+	 *  default is true, but the user may restrict the list by specifying the "FieldVariablesToCheckpoint"
+	 *  flag in their constructor - see _FeVariable_AssignFromXML().
+	 */ 	
+	for ( var_I = 0; var_I < self->fieldVariable_Register->objects->count; var_I++ ) {
+		fieldVar = FieldVariable_Register_GetByIndex( self->fieldVariable_Register, var_I );
+
+		if ( Stg_Class_IsInstance( fieldVar, FeVariable_Type ) ) {
+			feVar = (FeVariable*)fieldVar;	
+         if ( (feVar->isCheckpointedAndReloaded && (self->timeStep % self->checkpointEvery == 0))                                  ||
+              (feVar->isCheckpointedAndReloaded && (self->checkpointAtTimeInc && (self->currentTime >= self->nextCheckpointTime))) ||
+              (feVar->isSavedData               && (self->timeStep % self->saveDataEvery   == 0)) ){
+            char*			feVarSaveFileName     = NULL;
+            char*			feVarSaveFileNamePart = NULL;   
+
+            feVarSaveFileNamePart = Context_GetCheckPointWritePrefixString( (void*)self );
+
+#ifdef WRITE_HDF5
+            Stg_asprintf( &feVarSaveFileName, "%s%s.%.5u.h5" , feVarSaveFileNamePart, feVar->name, self->timeStep );
+#else
+            Stg_asprintf( &feVarSaveFileName, "%s%s.%.5u.dat", feVarSaveFileNamePart, feVar->name, self->timeStep );
+#endif
+            FeVariable_SaveToFile( feVar, feVarSaveFileName, 
+                   Dictionary_GetBool_WithDefault( self->dictionary, (Dictionary_Entry_Key)"saveCoordsWithFields", False ) );           
+
+            Memory_Free( feVarSaveFileName );
+            Memory_Free( feVarSaveFileNamePart );
+         }
+		}
+	}
+}
+
+
+void _FiniteElementContext_SaveSwarms( void* context ) {
+
+	Swarm_Register_SaveAllRegisteredSwarms( 
+		Swarm_Register_GetSwarm_Register( ), context );
+
+}
+
+
+void _FiniteElementContext_SaveMesh( void* context ) {
+   FiniteElementContext*   self;
+	Stream*                 info = Journal_Register( Info_Type, (Name)"Context" );
+   unsigned                componentCount = LiveComponentRegister_GetCount(stgLiveComponentRegister );
+   unsigned                compI;
+   Stg_Component*          stgComp;
+   FeMesh*                 mesh;
+   
+	Journal_Printf( info, "In %s(): about to save the mesh to disk:\n", __func__ );
+
+	self = (FiniteElementContext*) context;
+
+   /** search for entire live component register for feMesh types  **/
+   for( compI = 0 ; compI < componentCount ; compI++){
+      stgComp = LiveComponentRegister_At( stgLiveComponentRegister, compI );
+      /* check that component is of type FeMesh */
+      if ( Stg_Class_IsInstance( stgComp, FeMesh_Type ) ) {
+         mesh   = (FeMesh*)stgComp;
+         if( mesh->isCheckpointedAndReloaded == True && mesh->requiresCheckpointing == True ){         
+#ifdef WRITE_HDF5
+         _FiniteElementContext_DumpMeshHDF5( context, mesh );
+#else
+         _FiniteElementContext_DumpMeshAscii( context, mesh );
+#endif
+         }
+      }
+   }
+	Journal_Printf( info, "%s: saving of mesh completed.\n", __func__ );
+}
+
+#ifndef WRITE_HDF5
+void _FiniteElementContext_DumpMeshAscii( void* context, FeMesh* feMesh ) {
+   FiniteElementContext*   self = (FiniteElementContext*) context;
+   FieldVariable*    fieldVar = NULL;
+	FeVariable*       feVar = NULL;
+	Mesh* 			   mesh;
+	int 			      rank, nRanks;  
+	FILE*			      outputFile;
+	int               confirmation = 0;
+	MPI_Status        status;
+	Node_LocalIndex   lNode_I = 0;
+	Node_GlobalIndex  gNode_I = 0;
+	double*           coord;
+	unsigned          nDims;
+	char*             filename = NULL;
+	char*             meshSaveFileNamePart = NULL;
+
+   meshSaveFileNamePart = Context_GetCheckPointWritePrefixString( (void*)self );
+	
+   Stg_asprintf( &filename, "%sMesh.%s.%.5u.dat", meshSaveFileNamePart, feMesh->name, self->timeStep );
+	
+	MPI_Comm_rank( self->communicator, &rank);
+	MPI_Comm_size( self->communicator, &nRanks );	
+
+	mesh = (Mesh*)feMesh;
+	
+	nDims = Mesh_GetDimSize( mesh );	
+		
+	/* wait for go-ahead from process ranked lower than me, to avoid competition writing to file */
+	if ( rank != 0 ) {
+		MPI_Recv( &confirmation, 1, MPI_INT, rank - 1, FINISHED_WRITING_TAG, self->communicator, &status );
+	}	
+
+	if ( rank == 0 ) {
+		outputFile = fopen( filename, "w" );
+		assert( outputFile );
+		
+		/* Write min and max coords to file */
+		if( nDims == 2 ) {
+            		fprintf( outputFile, "Min: %.15g %.15g 0\n", mesh->minGlobalCrd[0], mesh->minGlobalCrd[1] );
+            		fprintf( outputFile, "Max: %.15g %.15g 0\n", mesh->maxGlobalCrd[0], mesh->maxGlobalCrd[1] );
+      		} 
+		else {
+            		fprintf( outputFile, "Min: %.15g %.15g %.15g\n", mesh->minGlobalCrd[0], mesh->minGlobalCrd[1], mesh->minGlobalCrd[2] );
+            		fprintf( outputFile, "Max: %.15g %.15g %.15g\n", mesh->maxGlobalCrd[0], mesh->maxGlobalCrd[1], mesh->maxGlobalCrd[2] );  
+		}
+	}
+	else {
+		outputFile = fopen( filename, "a" );
+		assert( outputFile );
+	}	
+
+   for ( lNode_I = 0; lNode_I < FeMesh_GetNodeLocalSize( mesh ); lNode_I++ ) {
+	   gNode_I = FeMesh_NodeDomainToGlobal( mesh, lNode_I );
+	   fprintf( outputFile, "%u ", gNode_I );
+	   coord = Mesh_GetVertex( mesh, lNode_I );
+                   
+      if(self->dim==2)
+         fprintf( outputFile, "%.15g %.15g 0\n", coord[0], coord[1] );
+      else
+         fprintf( outputFile, "%.15g %.15g %.15g\n", coord[0], coord[1], coord[2] );
+	}
+	
+	fclose( outputFile );
+	
+	/* send go-ahead from process ranked lower than me, to avoid competition writing to file */
+	if ( rank != nRanks - 1 ) {
+		MPI_Ssend( &confirmation, 1, MPI_INT, rank + 1, FINISHED_WRITING_TAG, self->communicator );
+	}	
+   Memory_Free( meshSaveFileNamePart );
+   Memory_Free( filename );
+
+}
+#endif
+
+#ifdef WRITE_HDF5
+void _FiniteElementContext_DumpMeshHDF5( void* context, FeMesh* mesh ) {
+   FiniteElementContext*   self = (FiniteElementContext*) context;
+   int                     rank, nRanks;
+   unsigned                nDims;
+   hid_t                   file, fileSpace, fileData, fileSpace2, fileData2;
+   hid_t                   memSpace;
+   hsize_t                 start[2], count[2], size[2];
+   unsigned                totalVerts;
+   Node_LocalIndex         lNode_I = 0;
+   Node_GlobalIndex        gNode_I = 0;
+   double*                 coord;
+   int                     buf_int[5];
+   MPI_Status              status;
+   int                     confirmation = 0;
+   Stream*                 errorStr = Journal_Register( Error_Type, (Name)self->type );
+   Element_LocalIndex      lElement_I;
+   Element_GlobalIndex     gElement_I;
+   Index                   maxNodes;
+   IArray*                 iarray = IArray_New( );
+   char*                   filename = NULL;
+   char*                   meshSaveFileNamePart = NULL;
+
+   /* don't dump irregular meshes, as havn't accounted for their connectivity yet...
+    * TODO: this is a hack, as we don't know about the IrregularQuadGenerator yet in StgFEM. Need to account
+    * for unstructured meshes at some point in the future... dave 01.10.09 */
+   if( !strcmp( mesh->generator->type, "IrregularQuadGenerator" ) )
+      return;
+
+   meshSaveFileNamePart = Context_GetCheckPointWritePrefixString( context );
+
+   MPI_Comm_rank( self->communicator, &rank);
+   MPI_Comm_size( self->communicator, &nRanks );   
+         
+   filename = NULL;
+   Stg_asprintf( &filename, "%sMesh.%s.%.5u.h5", meshSaveFileNamePart, mesh->name, self->timeStep );
+
+   nDims  = Mesh_GetDimSize( mesh );
+
+   /* wait for go-ahead from process ranked lower than me, to avoid competition writing to file */
+   if ( rank != 0 ) {
+      MPI_Recv( &confirmation, 1, MPI_INT, rank - 1, FINISHED_WRITING_TAG, self->communicator, &status );
+   }	
+
+   if ( rank == 0 ) {
+      hid_t      attribData_id, attrib_id, group_id;
+      hsize_t    a_dims;
+      int        attribData;
+      Grid**     grid;
+      unsigned*  sizes;
+
+      /* Open the HDF5 output file. */
+      file = H5Fcreate( filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
+      assert( file );
+
+      /** create file attribute */
+      /** first store the checkpointing version */
+      a_dims = 1;
+      attribData = MeshCHECKPOINT_V2;
+      attribData_id = H5Screate_simple(1, &a_dims, NULL);
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+         group_id  = H5Gopen(file, "/");
+         attrib_id = H5Acreate(group_id, "checkpoint file version", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
+      #else
+         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
+         attrib_id = H5Acreate2(group_id, "checkpoint file version", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
+      #endif
+      H5Awrite(attrib_id, H5T_NATIVE_INT, &attribData);
+      H5Aclose(attrib_id);
+      H5Gclose(group_id);
+      H5Sclose(attribData_id);
+
+      /** store the mesh dimensionality */
+      a_dims = 1;
+      attribData = self->dim;
+      attribData_id = H5Screate_simple(1, &a_dims, NULL);
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+         group_id  = H5Gopen(file, "/");
+         attrib_id = H5Acreate(group_id, "dimensions", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
+      #else
+         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
+         attrib_id = H5Acreate2(group_id, "dimensions", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
+      #endif
+      H5Awrite(attrib_id, H5T_NATIVE_INT, &attribData);
+      H5Aclose(attrib_id);
+      H5Gclose(group_id);
+      H5Sclose(attribData_id);
+       
+      /** store the mesh resolution */
+      a_dims = self->dim;
+      grid   = (Grid**) Mesh_GetExtension( mesh, Grid*, "elementGrid" );	
+      sizes  =          Grid_GetSizes( *grid ); /** global no. of elements in each dim */
+      
+      attribData_id = H5Screate_simple(1, &a_dims, NULL);
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+         group_id  = H5Gopen(file, "/");
+         attrib_id = H5Acreate(group_id, "mesh resolution", H5T_STD_I32BE, attribData_id, H5P_DEFAULT);
+      #else
+         group_id  = H5Gopen2(file, "/", H5P_DEFAULT);
+         attrib_id = H5Acreate2(group_id, "mesh resolution", H5T_STD_I32BE, attribData_id, H5P_DEFAULT, H5P_DEFAULT);
+      #endif
+      H5Awrite(attrib_id, H5T_NATIVE_INT, sizes);
+      H5Aclose(attrib_id);
+      H5Gclose(group_id);
+      H5Sclose(attribData_id);
+   
+      /* Dump the min and max coords, and number of processes. */
+      count[0] = (hsize_t)nDims;
+      fileSpace = H5Screate_simple( 1, count, NULL );         
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData = H5Dcreate( file, "/min", H5T_NATIVE_DOUBLE, fileSpace, H5P_DEFAULT );
+      #else
+      fileData = H5Dcreate2( file, "/min", H5T_NATIVE_DOUBLE, fileSpace,
+                               H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
+      #endif
+                  
+      H5Dwrite( fileData, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, mesh->minGlobalCrd );
+      H5Dclose( fileData );
+      H5Sclose( fileSpace );
+         
+      fileSpace = H5Screate_simple( 1, count, NULL );       
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData = H5Dcreate( file, "/max", H5T_NATIVE_DOUBLE, fileSpace, H5P_DEFAULT );
+      #else
+      fileData = H5Dcreate2( file, "/max", H5T_NATIVE_DOUBLE, fileSpace,
+                               H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
+      #endif
+            
+      H5Dwrite( fileData, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, mesh->maxGlobalCrd );
+      H5Dclose( fileData );
+      H5Sclose( fileSpace );
+       
+      /* Write vertex coords to file */   
+      /* Create our output space and data objects. */
+      totalVerts = Mesh_GetGlobalSize( mesh, (MeshTopology_Dim)0 );
+      size[0] = (hsize_t)totalVerts;
+      size[1] = (hsize_t)nDims;
+      
+      fileSpace = H5Screate_simple( 2, size, NULL );
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData = H5Dcreate( file, "/vertices", H5T_NATIVE_DOUBLE, fileSpace, H5P_DEFAULT );
+      #else
+      fileData = H5Dcreate2( file, "/vertices", H5T_NATIVE_DOUBLE, fileSpace,
+                            H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
+      #endif
+
+      /* setup element connectivity dataspaces */
+      if (mesh->nElTypes == 1)
+         maxNodes = FeMesh_GetElementNodeSize( mesh, 0);
+      else {
+         /* determine the maximum number of nodes each element has */
+         maxNodes = 0;
+         for ( gElement_I = 0 ; gElement_I < FeMesh_GetElementGlobalSize(mesh); gElement_I++ ) {
+            unsigned numNodes;
+            numNodes = FeMesh_GetElementNodeSize( mesh, gElement_I);
+            if( maxNodes < numNodes ) maxNodes = numNodes;
+         }
+      }
+      
+      size[0] = (hsize_t)FeMesh_GetElementGlobalSize(mesh);
+      size[1] = (hsize_t)maxNodes;
+      /* Create our output space and data objects. */         
+      fileSpace2 = H5Screate_simple( 2, size, NULL );
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData2 = H5Dcreate( file, "/connectivity", H5T_NATIVE_INT, fileSpace2, H5P_DEFAULT );
+      #else
+      fileData2 = H5Dcreate2( file, "/connectivity", H5T_NATIVE_INT, fileSpace2,
+                            H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
+      #endif
+
+   } else {
+      /* Open the HDF5 output file. */
+      file = H5Fopen( filename, H5F_ACC_RDWR, H5P_DEFAULT );
+      Journal_Firewall( 
+         file >= 0, 
+         errorStr,
+         "Error in %s for %s '%s' - Cannot open file %s.\n", 
+         __func__, 
+         self->type, 
+         self->name, 
+         filename );
+
+      /* get the node filespace */   
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData  = H5Dopen( file, "/vertices" );
+      #else
+      fileData  = H5Dopen2( file, "/vertices", H5P_DEFAULT );
+      #endif
+      /* get the filespace handle */
+      fileSpace = H5Dget_space(fileData);
+
+      /* get the connectivity */   
+      #if H5_VERS_MAJOR == 1 && H5_VERS_MINOR < 8
+      fileData2  = H5Dopen( file, "/connectivity" );
+      #else
+      fileData2  = H5Dopen2( file, "/connectivity", H5P_DEFAULT );
+      #endif
+      /* get the filespace handle */
+      fileSpace2 = H5Dget_space(fileData2);
+   }	
+      
+   count[0] = 1;
+   count[1] = nDims;
+   memSpace = H5Screate_simple( 2, count, NULL );
+   H5Sselect_all( memSpace );
+                     
+   for ( lNode_I = 0; lNode_I < FeMesh_GetNodeLocalSize( mesh ); lNode_I++ ) {
+      gNode_I = FeMesh_NodeDomainToGlobal( mesh, lNode_I );
+      
+      coord = Mesh_GetVertex( mesh, lNode_I );
+      
+      /* select the region of dataspace to write to  */
+      start[1] = 0;
+      start[0] = gNode_I;
+      H5Sselect_hyperslab( fileSpace, H5S_SELECT_SET, start, NULL, count, NULL );
+      
+      H5Dwrite( fileData, H5T_NATIVE_DOUBLE, memSpace, fileSpace, H5P_DEFAULT, coord );
+   }
+   
+   /* Close off all our handles. */
+   H5Sclose( memSpace );
+   H5Dclose( fileData );
+   H5Sclose( fileSpace );
+
+   H5Sget_simple_extent_dims( fileSpace2, size, NULL );
+   count[0] = 1;
+   count[1] = size[1];
+   memSpace = H5Screate_simple( 2, count, NULL );
+   H5Sselect_all( memSpace );
+                     
+   for ( lElement_I = 0 ; lElement_I < FeMesh_GetElementLocalSize(mesh); lElement_I++ ) {
+      int*    nodeList, nodesPerEl;
+      int     node_I;
+      
+      gElement_I = FeMesh_ElementDomainToGlobal( mesh,lElement_I );
+
+      /* get element nodes */
+      FeMesh_GetElementNodes( mesh, lElement_I, iarray );
+      nodesPerEl = IArray_GetSize( iarray );
+      nodeList   = IArray_GetPtr(  iarray );
+      
+      for( node_I = 0 ; node_I < nodesPerEl ; node_I++ )
+         buf_int[node_I] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[node_I] );
+      /* some reordering is required to account for standard node ordering */ 
+      buf_int[3] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[2] );
+      buf_int[2] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[3] );
+      if( nDims == 3 ) {
+         buf_int[7] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[6] );
+         buf_int[6] = Mesh_DomainToGlobal( mesh, MT_VERTEX, nodeList[7] );
+      }
+      /* select the region of dataspace to write to  */
+      start[1] = 0;
+      start[0] = gElement_I;
+      H5Sselect_hyperslab( fileSpace2, H5S_SELECT_SET, start, NULL, count, NULL );
+      
+      H5Dwrite( fileData2, H5T_NATIVE_INT, memSpace, fileSpace2, H5P_DEFAULT, buf_int );
+   }
+   
+   /* Close off all our handles. */
+   H5Sclose( memSpace );
+   H5Dclose( fileData2 );
+   H5Sclose( fileSpace2 );
+   H5Fclose( file );
+
+   /* send go-ahead from process ranked lower than me, to avoid competition writing to file */
+   if ( rank != nRanks - 1 ) {
+      MPI_Ssend( &confirmation, 1, MPI_INT, rank + 1, FINISHED_WRITING_TAG, self->communicator );
+   }	
+   
+   Memory_Free( filename );
+      
+   Memory_Free( meshSaveFileNamePart );
+   NewClass_Delete( iarray );
+}
+#endif
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/ForceTerm.c
--- a/SLE/SystemSetup/src/ForceTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,278 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: ForceTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "FiniteElementContext.h"
-#include "ForceTerm.h"
-#include "SolutionVector.h"
-#include "ForceVector.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include "EntryPoint.h"
-
-/* Textual name of this class */
-const Type ForceTerm_Type = "ForceTerm";
-
-ForceTerm* ForceTerm_New(
-	Name							name,
-	FiniteElementContext*	context,
-	ForceVector*				forceVector,
-	Swarm*						integrationSwarm,
-	Stg_Component*				extraInfo )		
-{
-	ForceTerm* self = (ForceTerm*) _ForceTerm_DefaultNew( name );
-
-	self->isConstructed = True;
-	_ForceTerm_Init( self, context, forceVector, integrationSwarm, extraInfo );
-
-	return self;
-}
-
-void* _ForceTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(ForceTerm);
-	Type                                                      type = ForceTerm_Type;
-	Stg_Class_DeleteFunction*                              _delete = _ForceTerm_Delete;
-	Stg_Class_PrintFunction*                                _print = _ForceTerm_Print;
-	Stg_Class_CopyFunction*                                  _copy = _ForceTerm_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _ForceTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _ForceTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _ForceTerm_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _ForceTerm_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _ForceTerm_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _ForceTerm_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-	ForceTerm_AssembleElementFunction*            _assembleElement = _ForceTerm_AssembleElement;
-
-	return _ForceTerm_New(  FORCETERM_PASSARGS  );
-}
-
-ForceTerm* _ForceTerm_New(  FORCETERM_DEFARGS  ) {
-	ForceTerm* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(ForceTerm) );
-	self = (ForceTerm*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-
-	self->_assembleElement = _assembleElement;
-	
-	return self;
-}
-
-
-void _ForceTerm_Init(
-	void*							forceTerm,
-	FiniteElementContext*	context,
-	ForceVector*				forceVector,
-	Swarm*						integrationSwarm,
-	Stg_Component*				extraInfo )
-{
-	ForceTerm* self			= (ForceTerm*) forceTerm;
-	self->context 				= context;	
-	self->debug					= Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
-	self->extraInfo			= extraInfo;
-	self->integrationSwarm	= integrationSwarm;	
-   self->forceVector       = forceVector;
-
-	ForceVector_AddForceTerm( forceVector, self );
-}
-
-
-void _ForceTerm_Delete( void* forceTerm ) {
-	ForceTerm* self = (ForceTerm*)forceTerm;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-
-	/* Stg_Class_Delete parent*/
-	_Stg_Component_Delete( self );
-}
-
-
-void _ForceTerm_Print( void* forceTerm, Stream* stream ) {
-	ForceTerm* self = (ForceTerm*)forceTerm;
-
-	/* General info */
-	Journal_Printf( stream, "ForceTerm (ptr): %p\n", self );
-	
-	/* Print parent */
-	_Stg_Component_Print( self, stream );
-	
-	/* ForceTerm info */
-	Journal_Printf( stream, "\tintegrationSwarm (ptr): %p\n", self->integrationSwarm );
-	Journal_Printf( stream, "\textraInfo (ptr): %p\n", self->extraInfo );
-}
-
-
-void* _ForceTerm_Copy( const void* forceTerm, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	ForceTerm*	self = (ForceTerm*)forceTerm;
-	ForceTerm*	newForceTerm;
-	PtrMap*		map = ptrMap;
-	Bool			ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newForceTerm = (ForceTerm*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
-	
-	newForceTerm->extraInfo = self->extraInfo;
-	if( deep ) {
-		newForceTerm->integrationSwarm = (Swarm*)Stg_Class_Copy( self->integrationSwarm, NULL, deep, nameExt, map );
-	}
-	else {
-		newForceTerm->integrationSwarm = self->integrationSwarm;
-	}
-	
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-	
-	return (void*)newForceTerm;
-}
-
-void _ForceTerm_AssignFromXML( void* forceTerm, Stg_ComponentFactory* cf, void* data ) {
-	FiniteElementContext*	context;
-	ForceTerm*					self = (ForceTerm*)forceTerm;
-	Swarm*						swarm = NULL;
-	Stg_Component*				extraInfo;
-	ForceVector*				forceVector;
-
-	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
-
-	if( !context  )
-		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
-
-	forceVector = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ForceVector", ForceVector, True, data  ) ;
-	swarm       = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Swarm", Swarm, True, data  ) ;
-	extraInfo   = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ExtraInfo", Stg_Component, False, data  ) ;
-
-	_ForceTerm_Init( self, context, forceVector, swarm, extraInfo );
-}
-
-void _ForceTerm_Build( void* forceTerm, void* data ) {
-	ForceTerm* self = (ForceTerm*)forceTerm;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-	
-	/* ensure integrationSwarm is built */
-	Stg_Component_Build( self->integrationSwarm, data, False );
-	Stg_Component_Build( self->forceVector, data, False );
-
-	if ( self->extraInfo ) 
-		Stg_Component_Build( self->extraInfo, data, False );
-		
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _ForceTerm_Initialise( void* forceTerm, void* data ) {
-	ForceTerm* self = (ForceTerm*)forceTerm;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	Stg_Component_Initialise( self->integrationSwarm, data, False );
-	Stg_Component_Initialise( self->forceVector, data, False );
-	if ( self->extraInfo ) 
-		Stg_Component_Initialise( self->extraInfo, data, False );
-	
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _ForceTerm_Execute( void* forceTerm, void* data ) {
-}
-
-void _ForceTerm_Destroy( void* forceTerm, void* data ) {
-	ForceTerm* self = (ForceTerm*)forceTerm;
-
-	if ( self->extraInfo ) 
-      Stg_Component_Destroy( self->extraInfo, data, False );
-
-   Stg_Component_Destroy( self->integrationSwarm, data, False );
-   Stg_Component_Destroy( self->forceVector, data, False );
-}
-
-void ForceTerm_AssembleElement( 
-			void*                             forceTerm, 
-			ForceVector*                      forceVector, 
-			Element_LocalIndex                lElement_I,
-			double*                           elForceVecToAdd ) 
-{
-	ForceTerm* self = (ForceTerm*)forceTerm;
-
-	self->_assembleElement( self, forceVector, lElement_I, elForceVecToAdd );
-}
-	
-void _ForceTerm_AssembleElement( 
-			void*                             forceTerm, 
-			ForceVector*                      forceVector, 
-			Element_LocalIndex                lElement_I,
-			double*                           elForceVecToAdd ) 
-{
-	ForceTerm* self        = (ForceTerm*)forceTerm;
-	Stream*    errorStream = Journal_Register( Error_Type, (Name)self->type  );
-
-	Journal_Printf( errorStream, "Error in func %s for %s '%s' - "
-			"This function is the default function which should never be called - "
-			"Please set this virtual function with appropriate application dependent function.\n",
-			__func__, self->type, self->name );
-	abort();
-}	
-
-void ForceTerm_SetAssembleElementFunction( void* forceTerm, ForceTerm_AssembleElementFunction* assembleElementFunction ) {
-	ForceTerm* self        = (ForceTerm*)forceTerm;
-
-	self->_assembleElement = assembleElementFunction;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/ForceTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/ForceTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,278 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: ForceTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "FiniteElementContext.h"
+#include "ForceTerm.h"
+#include "SolutionVector.h"
+#include "ForceVector.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "EntryPoint.h"
+
+/* Textual name of this class */
+const Type ForceTerm_Type = "ForceTerm";
+
+ForceTerm* ForceTerm_New(
+	Name							name,
+	FiniteElementContext*	context,
+	ForceVector*				forceVector,
+	Swarm*						integrationSwarm,
+	Stg_Component*				extraInfo )		
+{
+	ForceTerm* self = (ForceTerm*) _ForceTerm_DefaultNew( name );
+
+	self->isConstructed = True;
+	_ForceTerm_Init( self, context, forceVector, integrationSwarm, extraInfo );
+
+	return self;
+}
+
+void* _ForceTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(ForceTerm);
+	Type                                                      type = ForceTerm_Type;
+	Stg_Class_DeleteFunction*                              _delete = _ForceTerm_Delete;
+	Stg_Class_PrintFunction*                                _print = _ForceTerm_Print;
+	Stg_Class_CopyFunction*                                  _copy = _ForceTerm_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _ForceTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _ForceTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _ForceTerm_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _ForceTerm_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _ForceTerm_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _ForceTerm_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+	ForceTerm_AssembleElementFunction*            _assembleElement = _ForceTerm_AssembleElement;
+
+	return _ForceTerm_New(  FORCETERM_PASSARGS  );
+}
+
+ForceTerm* _ForceTerm_New(  FORCETERM_DEFARGS  ) {
+	ForceTerm* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(ForceTerm) );
+	self = (ForceTerm*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+
+	self->_assembleElement = _assembleElement;
+	
+	return self;
+}
+
+
+void _ForceTerm_Init(
+	void*							forceTerm,
+	FiniteElementContext*	context,
+	ForceVector*				forceVector,
+	Swarm*						integrationSwarm,
+	Stg_Component*				extraInfo )
+{
+	ForceTerm* self			= (ForceTerm*) forceTerm;
+	self->context 				= context;	
+	self->debug					= Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
+	self->extraInfo			= extraInfo;
+	self->integrationSwarm	= integrationSwarm;	
+   self->forceVector       = forceVector;
+
+	ForceVector_AddForceTerm( forceVector, self );
+}
+
+
+void _ForceTerm_Delete( void* forceTerm ) {
+	ForceTerm* self = (ForceTerm*)forceTerm;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+
+	/* Stg_Class_Delete parent*/
+	_Stg_Component_Delete( self );
+}
+
+
+void _ForceTerm_Print( void* forceTerm, Stream* stream ) {
+	ForceTerm* self = (ForceTerm*)forceTerm;
+
+	/* General info */
+	Journal_Printf( stream, "ForceTerm (ptr): %p\n", self );
+	
+	/* Print parent */
+	_Stg_Component_Print( self, stream );
+	
+	/* ForceTerm info */
+	Journal_Printf( stream, "\tintegrationSwarm (ptr): %p\n", self->integrationSwarm );
+	Journal_Printf( stream, "\textraInfo (ptr): %p\n", self->extraInfo );
+}
+
+
+void* _ForceTerm_Copy( const void* forceTerm, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	ForceTerm*	self = (ForceTerm*)forceTerm;
+	ForceTerm*	newForceTerm;
+	PtrMap*		map = ptrMap;
+	Bool			ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newForceTerm = (ForceTerm*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
+	
+	newForceTerm->extraInfo = self->extraInfo;
+	if( deep ) {
+		newForceTerm->integrationSwarm = (Swarm*)Stg_Class_Copy( self->integrationSwarm, NULL, deep, nameExt, map );
+	}
+	else {
+		newForceTerm->integrationSwarm = self->integrationSwarm;
+	}
+	
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+	
+	return (void*)newForceTerm;
+}
+
+void _ForceTerm_AssignFromXML( void* forceTerm, Stg_ComponentFactory* cf, void* data ) {
+	FiniteElementContext*	context;
+	ForceTerm*					self = (ForceTerm*)forceTerm;
+	Swarm*						swarm = NULL;
+	Stg_Component*				extraInfo;
+	ForceVector*				forceVector;
+
+	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
+
+	if( !context  )
+		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
+
+	forceVector = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ForceVector", ForceVector, True, data  ) ;
+	swarm       = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Swarm", Swarm, True, data  ) ;
+	extraInfo   = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ExtraInfo", Stg_Component, False, data  ) ;
+
+	_ForceTerm_Init( self, context, forceVector, swarm, extraInfo );
+}
+
+void _ForceTerm_Build( void* forceTerm, void* data ) {
+	ForceTerm* self = (ForceTerm*)forceTerm;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+	
+	/* ensure integrationSwarm is built */
+	Stg_Component_Build( self->integrationSwarm, data, False );
+	Stg_Component_Build( self->forceVector, data, False );
+
+	if ( self->extraInfo ) 
+		Stg_Component_Build( self->extraInfo, data, False );
+		
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _ForceTerm_Initialise( void* forceTerm, void* data ) {
+	ForceTerm* self = (ForceTerm*)forceTerm;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	Stg_Component_Initialise( self->integrationSwarm, data, False );
+	Stg_Component_Initialise( self->forceVector, data, False );
+	if ( self->extraInfo ) 
+		Stg_Component_Initialise( self->extraInfo, data, False );
+	
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _ForceTerm_Execute( void* forceTerm, void* data ) {
+}
+
+void _ForceTerm_Destroy( void* forceTerm, void* data ) {
+	ForceTerm* self = (ForceTerm*)forceTerm;
+
+	if ( self->extraInfo ) 
+      Stg_Component_Destroy( self->extraInfo, data, False );
+
+   Stg_Component_Destroy( self->integrationSwarm, data, False );
+   Stg_Component_Destroy( self->forceVector, data, False );
+}
+
+void ForceTerm_AssembleElement( 
+			void*                             forceTerm, 
+			ForceVector*                      forceVector, 
+			Element_LocalIndex                lElement_I,
+			double*                           elForceVecToAdd ) 
+{
+	ForceTerm* self = (ForceTerm*)forceTerm;
+
+	self->_assembleElement( self, forceVector, lElement_I, elForceVecToAdd );
+}
+	
+void _ForceTerm_AssembleElement( 
+			void*                             forceTerm, 
+			ForceVector*                      forceVector, 
+			Element_LocalIndex                lElement_I,
+			double*                           elForceVecToAdd ) 
+{
+	ForceTerm* self        = (ForceTerm*)forceTerm;
+	Stream*    errorStream = Journal_Register( Error_Type, (Name)self->type  );
+
+	Journal_Printf( errorStream, "Error in func %s for %s '%s' - "
+			"This function is the default function which should never be called - "
+			"Please set this virtual function with appropriate application dependent function.\n",
+			__func__, self->type, self->name );
+	abort();
+}	
+
+void ForceTerm_SetAssembleElementFunction( void* forceTerm, ForceTerm_AssembleElementFunction* assembleElementFunction ) {
+	ForceTerm* self        = (ForceTerm*)forceTerm;
+
+	self->_assembleElement = assembleElementFunction;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/ForceVector.c
--- a/SLE/SystemSetup/src/ForceVector.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,558 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: ForceVector.c 1210 2008-08-25 01:17:12Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "FiniteElementContext.h"
-#include "SolutionVector.h"
-#include "ForceVector.h"
-#include "ForceTerm.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include "EntryPoint.h"
-#include "Assembler.h"
-
-
-Bool ForceVector_BCAsm_RowR( void* forceVec, Assembler* assm );
-
-
-/* Textual name of this class */
-const Type ForceVector_Type = "ForceVector";
-
-/** Name of this class' entry points */
-static const char	ForceVector_assembleForceVectorStr[] = "assembleForceVector";
-
-ForceVector* ForceVector_New(
-	Name							name,
-	FiniteElementContext*	context,
-	FeVariable*					feVariable,
-	Dimension_Index			dim,
-	void*							entryPoint_Register,
-	MPI_Comm						comm )		
-{
-  ForceVector* self = (ForceVector*)_ForceVector_DefaultNew( name );
-
-	self->isConstructed = True;
-	_SolutionVector_Init( (SolutionVector*)self, context, comm, feVariable ); 
-	_ForceVector_Init( self, dim, (EntryPoint_Register*)entryPoint_Register );
-
-	return self;
-}
-
-void* _ForceVector_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(ForceVector);
-	Type                                                      type = ForceVector_Type;
-	Stg_Class_DeleteFunction*                              _delete = _ForceVector_Delete;
-	Stg_Class_PrintFunction*                                _print = _ForceVector_Print;
-	Stg_Class_CopyFunction*                                  _copy = _ForceVector_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _ForceVector_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _ForceVector_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _ForceVector_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _ForceVector_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _ForceVector_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _ForceVector_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-
-	return _ForceVector_New(  FORCEVECTOR_PASSARGS  );
-}
-
-ForceVector* _ForceVector_New(  FORCEVECTOR_DEFARGS  ) {
-	ForceVector* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(ForceVector) );
-	self = (ForceVector*)_SolutionVector_New(  SOLUTIONVECTOR_PASSARGS  );
-	
-	return self;
-}
-
-
-void _ForceVector_Init( void* forceVector, Dimension_Index dim, EntryPoint_Register* entryPoint_Register ) {
-	ForceVector* self = (ForceVector*)  forceVector;
-	
-	/* ForceVector info */
-	self->dim = dim;
-	self->entryPoint_Register = entryPoint_Register;
-	
-	/* Create Stream */
-	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
-	
-	/* Create Entry Point for assembleForceVector */
-	Stg_asprintf( (char**)(&self->_assembleForceVectorEPName), "%s-%s", self->name, ForceVector_assembleForceVectorStr );
-	self->assembleForceVector = FeEntryPoint_New( self->_assembleForceVectorEPName, FeEntryPoint_AssembleForceVector_CastType );
-	EntryPoint_Register_Add( self->entryPoint_Register, self->assembleForceVector );	
-
-	/* Add default hook to assembleForceVector entry point */
-	EP_ReplaceAll( self->assembleForceVector, ForceVector_GlobalAssembly_General );
-
-	self->forceTermList = Stg_ObjectList_New();
-
-	self->bcAsm = Assembler_New();
-	self->inc = IArray_New();
-
-	self->nModifyCBs = 0;
- 	self->modifyCBs = NULL;
-}
-
-void _ForceVector_Delete( void* forceVector ) {
-	ForceVector* self = (ForceVector*)forceVector;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-
-	/* Stg_Class_Delete parent*/
-	_SolutionVector_Delete( self );
-}
-
-void _ForceVector_Print( void* forceVector, Stream* stream ) {
-	ForceVector* self = (ForceVector*)forceVector;
-	
-	/* General info */
-	Journal_Printf( stream, "ForceVector (ptr): %p\n", self );
-	
-	/* Print parent */
-	_SolutionVector_Print( self, stream );
-	
-	/* Virtual info */
-	
-	/* ForceVector info */
-	Journal_Printf( stream, "\tassembleForceVector e.p. (ptr): %p\n", self->assembleForceVector );
-	EntryPoint_PrintConcise( self->assembleForceVector, stream );
-
-	Journal_Printf( stream, "\tVector (ptr): %p\n", self->vector );
-	Journal_Printf( stream, "\tComm: %u\n", self->comm );
-	Journal_Printf( stream, "\tLocalSize: %u\n", self->localSize );
-}
-
-
-void* _ForceVector_Copy( const void* forceVector, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	ForceVector*	self = (ForceVector*)forceVector;
-	ForceVector*	newForceVector;
-	PtrMap*		map = ptrMap;
-	Bool		ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newForceVector = (ForceVector*)_SolutionVector_Copy( self, dest, deep, nameExt, map );
-	
-	/* TODO: copy vector? */
-	newForceVector->entryPoint_Register = self->entryPoint_Register;
-	newForceVector->localSize = self->localSize;
-	
-	if( deep ) {
-		newForceVector->assembleForceVector = (FeEntryPoint*)Stg_Class_Copy( self->assembleForceVector, NULL, deep, nameExt, map );
-		if( self->_assembleForceVectorEPName ) {
-			if( nameExt ) {
-				unsigned	nameLen = strlen( self->_assembleForceVectorEPName );
-				
-				newForceVector->_assembleForceVectorEPName = (char*)Memory_Alloc_Bytes_Unnamed( nameLen + strlen( nameExt ) + 1, "FV->vecEPName" );
-				memcpy( (char*)(newForceVector->_assembleForceVectorEPName), self->_assembleForceVectorEPName, nameLen );
-				strcpy( (char*)(newForceVector->_assembleForceVectorEPName) + nameLen, nameExt );
-			}
-			else {
-				newForceVector->_assembleForceVectorEPName = StG_Strdup( self->_assembleForceVectorEPName );
-			}
-		}
-		else {
-			newForceVector->_assembleForceVectorEPName = NULL;
-		}
-
-	}
-	else {
-		newForceVector->debug = self->debug;
-		newForceVector->_assembleForceVectorEPName = self->_assembleForceVectorEPName;
-		newForceVector->assembleForceVector = self->assembleForceVector;
-	}
-	
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-	
-	return (void*)newForceVector;
-}
-
-
-void _ForceVector_AssignFromXML( void* forceVector, Stg_ComponentFactory* cf, void* data ) {
-	ForceVector*    self = (ForceVector*)forceVector;
-	Dimension_Index dim = 0;
-	void*           entryPointRegister = NULL;
-
-	_SolutionVector_AssignFromXML( self, cf, data );
-	
-	dim = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"dim", 0 );
-
-	entryPointRegister = (void*)self->context->entryPoint_Register;
-	assert( entryPointRegister  );
-	
-	_ForceVector_Init( self, dim, (EntryPoint_Register*)entryPointRegister );
-}
-
-void _ForceVector_Build( void* forceVector, void* data ) {
-	ForceVector* self = (ForceVector*)forceVector;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-	/* ensure feVariable is built */
-	if( self->feVariable ) {
-		Stg_Component_Build( self->feVariable, data, False );
-	}	
-	
-	/* update the size depending on our now built feVariable */
-	self->localSize = self->feVariable->eqNum->localEqNumsOwnedCount;
-	/* assert( self->localSize ); */
-	
-	/* Allocate the vector */
-	Journal_DPrintfL( self->debug, 2, "Allocating the L.A. Force Vector with %d local entries.\n", self->localSize );
-	VecCreate( self->comm, &self->vector );
-	VecSetSizes( self->vector, (PetscInt)self->localSize, PETSC_DECIDE );
-	VecSetFromOptions( self->vector );
-#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
-	VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES );
-#elif( PETSC_VERSION_MAJOR >= 3 )
-	VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
-#endif
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-
-	Assembler_SetVariables( self->bcAsm, self->feVariable, NULL );
-	Assembler_SetCallbacks( self->bcAsm, 
-		NULL, 
-		ForceVector_BCAsm_RowR, NULL, 
-		NULL, NULL, 
-		self );
-}
-
-
-void _ForceVector_Initialise( void* forceVector, void* data ) {
-	ForceVector* self = (ForceVector*)forceVector;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-	/* ensure feVariable is initialised */
-	if( self->feVariable )
-		Stg_Component_Initialise( self->feVariable, data, False );
-	
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _ForceVector_Execute( void* forceVector, void* data ) {
-}
-
-void _ForceVector_Destroy( void* forceVector, void* data ) {
-	ForceVector* self = (ForceVector*)forceVector;
-
-	Memory_Free( self->_assembleForceVectorEPName );
-
-	/* Don't delete entry point: E.P register will delete it automatically */
-	Stg_Class_Delete( self->forceTermList );
-
-	NewClass_Delete( self->inc );
-
-	_SolutionVector_Destroy( self, data );
-}
-
-void ForceVector_Assemble( void* forceVector ) {
-	ForceVector* self = (ForceVector*)forceVector;
-        int ii;
-	
-	Journal_DPrintf( self->debug, "In %s - for vector \"%s\" - calling the \"%s\" E.P.\n", __func__, self->name,
-			 self->assembleForceVector->name );
-
-	/* Call the Entry point directly from the base class */
-	/* Note that it may be empty: this is deliberate. */
-	if ( 0 == self->assembleForceVector->hooks->count ) {
-		Journal_DPrintf( self->debug, "(E.P. has no hooks loaded -> no assembly required.)\n" ); 
-	}	
-	
-	((FeEntryPoint_AssembleForceVector_CallFunction*)EntryPoint_GetRun( self->assembleForceVector ))(
-		self->assembleForceVector,
-		self );
-
-        /* Run all the modify callbacks. */
-        for( ii = 0; ii < self->nModifyCBs; ii++ ) {
-           void* callback = self->modifyCBs[ii].callback;
-           void* object = self->modifyCBs[ii].object;
-           ((void(*)(void*))callback)( object );
-        }
-}
-
-
-void ForceVector_PrintElementForceVector(
-	ForceVector* self,
-	Element_LocalIndex element_lI,
-	Dof_EquationNumber** elementLM,
-	double* elForceVecToAdd )
-{
-	DofLayout*		dofLayout = self->feVariable->dofLayout;
-	FeMesh*			feMesh = self->feVariable->feMesh;
-	unsigned		nInc, *inc;
-	Dof_Index		dofsPerNode;
-	Node_LocalIndex		nodesThisEl;
-	Node_LocalIndex		node_I;
-	Dof_Index		dof_I;
-	Index			vec_I;
-	IArray*			incArray;
-
-	incArray = IArray_New();
-	FeMesh_GetElementNodes( feMesh, element_lI, incArray );
-	nInc = IArray_GetSize( incArray );
-	inc = (unsigned*)IArray_GetPtr( incArray );
-	dofsPerNode = dofLayout->dofCounts[inc[0]];
-	nodesThisEl = nInc;
-
-	for ( node_I=0; node_I < nodesThisEl; node_I++ ) {
-		for ( dof_I = 0; dof_I < dofsPerNode; dof_I++ ) {
-			vec_I = node_I * dofsPerNode + dof_I;
-
-			Journal_DPrintf( self->debug, "Entry[%d][%d] (LM (%4d)) = %.3f\n",
-					 node_I, dof_I,
-					 elementLM[node_I][dof_I],
-					 elForceVecToAdd[vec_I] ); 
-		}			
-	}
-
-	NewClass_Delete( incArray );
-}
-
-/* from the depreciated Vector class */
-void _ForceVector_VectorView( Vec v, Stream* stream ) {
-	unsigned	entry_i;
-	PetscInt	size;
-	PetscScalar*	array;
-
-	VecGetSize( v, &size );
-	VecGetArray( v, &array );
-
-	Journal_Printf( stream, "%p = [", v );
-	for( entry_i = 0; entry_i < size; entry_i++ ) 
-		Journal_Printf( stream, "\t%u: \t %.12g\n", entry_i, array[entry_i] );
-	Journal_Printf( stream, "];\n" );
-
-	VecRestoreArray( v, &array );
-}
-
-void ForceVector_GlobalAssembly_General( void* forceVector ) {
-	ForceVector*            self                 = (ForceVector*) forceVector;
-	FeVariable*             feVar                = self->feVariable;
-	Element_LocalIndex      element_lI;
-	Element_LocalIndex      elementLocalCount;
-	Node_ElementLocalIndex  nodeCountCurrElement = 0;
-	Element_Nodes           nodeIdsInCurrElement = 0;
-	Dof_Index               totalDofsThisElement = 0;
-	Dof_Index               totalDofsPrevElement = 0;
-	Dof_Index               dofCountLastNode     = 0;
-	Dof_EquationNumber**    elementLM            = NULL;
-	double*                 elForceVecToAdd      = NULL;
-	/* For output printing */
-	double                  outputPercentage=10;	/* Controls how often to give a status update of assembly progress */
-	int                     outputInterval;
-
-	Journal_DPrintf( self->debug, "In %s - for vector \"%s\"\n", __func__, self->name );
-	
-	Stream_IndentBranch( StgFEM_Debug );
-	
-	if ( Stg_ObjectList_Count( self->forceTermList ) > 0 ) {
-		elementLocalCount = FeMesh_GetElementLocalSize( feVar->feMesh );
-
-		/* Initialise Vector */
-		outputInterval = (int)( (outputPercentage/100.0)*(double)(elementLocalCount) );
-		if( outputInterval == 0 ) { outputInterval = elementLocalCount; }
-	
-		for( element_lI = 0; element_lI < elementLocalCount; element_lI++ ) {  
-			unsigned	nInc, *inc;
-		
-			FeMesh_GetElementNodes( feVar->feMesh, element_lI, self->inc );
-			nInc = IArray_GetSize( self->inc );
-			inc = (unsigned*)IArray_GetPtr( self->inc );
-			nodeCountCurrElement = nInc;
-			/* Get the local node ids */
-			nodeIdsInCurrElement = inc;
-
-			/* Set value of elementLM: will automatically just index into global LM table if built */
-			elementLM = FeEquationNumber_BuildOneElementLocationMatrix( feVar->eqNum, element_lI );
-
-			/* work out number of dofs at the node, using LM */
-			/* Since: Number of entries in LM table for this element = (by defn.) Number of dofs this element */
-			dofCountLastNode = feVar->dofLayout->dofCounts[nodeIdsInCurrElement[nodeCountCurrElement-1]]; 
-			totalDofsThisElement = &elementLM[nodeCountCurrElement-1][dofCountLastNode-1] - &elementLM[0][0] + 1;
-
-			if ( totalDofsThisElement > totalDofsPrevElement ) {
-				if (elForceVecToAdd) Memory_Free( elForceVecToAdd );
-				Journal_DPrintfL( self->debug, 2, "Reallocating elForceVecToAdd to size %d\n", totalDofsThisElement );
-				elForceVecToAdd = Memory_Alloc_Array( double, totalDofsThisElement, "elForceVecToAdd" );
-			}
-
-			/* Initialise Values to Zero */
-			memset( elForceVecToAdd, 0, totalDofsThisElement * sizeof(double) );
-		
-			/* Assemble this element's element force vector: going through each force term in list */
-			ForceVector_AssembleElement( self, element_lI, elForceVecToAdd );
-
-/*
-  #if DEBUG
-  if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-  Journal_DPrintf( self->debug, "Handling Element %d:\n", element_lI );
-  FeEquationNumber_PrintElementLocationMatrix( feVar->eqNum, elementLM,
-  element_lI, self->debug );
-				
-  Journal_DPrintf( self->debug, "El force Vec about to be added:\n" );
-  ForceVector_PrintElementForceVector( self, element_lI, elementLM, elForceVecToAdd );
-  }	
-  #endif
-*/
-
-                        /* When keeping BCs in we come across a bit of a problem in parallel. We're not
-                           allowed to add entries to the force vector here and then clobber it later with
-                           an insert in order to set the BC. So, what we'll do is just add zero here, that
-                           way later we can add the BC and it will be the same as inserting it.
-                           --- Luke, 20 May 2008 */
-                        if( !self->feVariable->eqNum->removeBCs ) {
-                           DofLayout* dofs;
-                           int nDofs, curInd;
-                           int ii, jj;
-
-                           dofs = self->feVariable->dofLayout; /* shortcut to the dof layout */
-                           curInd = 0; /* need a counter to track where we are in the element force vector */
-                           for( ii = 0; ii < nodeCountCurrElement; ii++ ) {
-                              nDofs = dofs->dofCounts[inc[ii]]; /* number of dofs on this node */
-                              for( jj = 0; jj < nDofs; jj++ ) {
-                                 if( !FeVariable_IsBC( self->feVariable, inc[ii], jj ) ) {
-                                    curInd++;
-                                    continue; /* only need to clear it if it's a bc */
-                                 }
-                                 elForceVecToAdd[curInd] = 0.0;
-                                 curInd++;
-                              }
-                           }
-                        }
-
-			/* Ok, assemble into global matrix */
-			//Vector_AddEntries( self->vector, totalDofsThisElement, (Index*)(elementLM[0]), elForceVecToAdd );
-			VecSetValues( self->vector, totalDofsThisElement, (PetscInt*)elementLM[0], elForceVecToAdd, ADD_VALUES );
-
-#if DEBUG
-			if( element_lI % outputInterval == 0 ) {
-				Journal_DPrintfL( self->debug, 2, "done %d percent of global force vector assembly (general) \n",
-						  (int)(100.0*((double)element_lI/(double)elementLocalCount)) );
-			}
-#endif
-
-			/* Cleanup: If we haven't built the big LM for all elements, free the temporary one */
-			if ( False == feVar->eqNum->locationMatrixBuilt ) {
-				Memory_Free( elementLM );
-			}
-			totalDofsPrevElement = totalDofsThisElement;
-		}
-
-		Memory_Free( elForceVecToAdd );
-	}
-	else {
-		Journal_DPrintf( self->debug, "No ForceTerms registered - returning.\n" );
-	}
-
-	/* If we're keeping BCs, insert them into the force vector. */
-	if( !feVar->eqNum->removeBCs )
-		Assembler_LoopVector( self->bcAsm );
-
-	//Vector_AssemblyBegin( self->vector );
-	//Vector_AssemblyEnd( self->vector ); 
-	VecAssemblyBegin( self->vector );
-	VecAssemblyEnd( self->vector );
-
-#if DEBUG
-	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-		Journal_DPrintf( self->debug, "Completely built vector %s is:\n", self->name );
-		_ForceVector_VectorView( self->vector, self->debug );
-	}
-#endif
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-		
-void ForceVector_AssembleElement( void* forceVector, Element_LocalIndex element_lI, double* elForceVecToAdd ) {
-	ForceVector*            self                 = (ForceVector*) forceVector;
-	Index                   forceTermCount       = Stg_ObjectList_Count( self->forceTermList );
-	Index                   forceTerm_I;
-	ForceTerm*              forceTerm;
-
-	for ( forceTerm_I = 0 ; forceTerm_I < forceTermCount ; forceTerm_I++ ) {
-		forceTerm = (ForceTerm*) Stg_ObjectList_At( self->forceTermList, forceTerm_I );
-
-		ForceTerm_AssembleElement( forceTerm, self, element_lI, elForceVecToAdd );
-	}
-}
-
-void ForceVector_AddForceTerm( void* forceVector, ForceTerm* forceTerm ) {
-	ForceVector*            self                 = (ForceVector*) forceVector;
-
-	Stg_ObjectList_Append( self->forceTermList, Stg_CheckType( forceTerm, ForceTerm ) );
-}
-
-Bool ForceVector_BCAsm_RowR( void* forceVec, Assembler* assm ) {
-	double	bc;
-
-	bc = DofLayout_GetValueDouble( assm->rowVar->dofLayout, 
-				       assm->rowNodeInd, 
-				       assm->rowDofInd );
-	//Vector_AddEntries( ((ForceVector*)forceVec)->vector, 1, &assm->rowEq, &bc );
-	VecSetValues( ((ForceVector*)forceVec)->vector, 1, (PetscInt*)(&assm->rowEq), &bc, ADD_VALUES );
-	return True;
-}
-
-void ForceVector_AddModifyCallback( ForceVector* self, void* callback, void* object ) {
-   self->nModifyCBs++;
-   self->modifyCBs = ReallocArray( self->modifyCBs, Callback, self->nModifyCBs );
-   self->modifyCBs[self->nModifyCBs - 1].callback = callback;
-   self->modifyCBs[self->nModifyCBs - 1].object = object;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/ForceVector.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/ForceVector.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,558 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: ForceVector.c 1210 2008-08-25 01:17:12Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "FiniteElementContext.h"
+#include "SolutionVector.h"
+#include "ForceVector.h"
+#include "ForceTerm.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "EntryPoint.h"
+#include "Assembler.h"
+
+
+Bool ForceVector_BCAsm_RowR( void* forceVec, Assembler* assm );
+
+
+/* Textual name of this class */
+const Type ForceVector_Type = "ForceVector";
+
+/** Name of this class' entry points */
+static const char	ForceVector_assembleForceVectorStr[] = "assembleForceVector";
+
+ForceVector* ForceVector_New(
+	Name							name,
+	FiniteElementContext*	context,
+	FeVariable*					feVariable,
+	Dimension_Index			dim,
+	void*							entryPoint_Register,
+	MPI_Comm						comm )		
+{
+  ForceVector* self = (ForceVector*)_ForceVector_DefaultNew( name );
+
+	self->isConstructed = True;
+	_SolutionVector_Init( (SolutionVector*)self, context, comm, feVariable ); 
+	_ForceVector_Init( self, dim, (EntryPoint_Register*)entryPoint_Register );
+
+	return self;
+}
+
+void* _ForceVector_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(ForceVector);
+	Type                                                      type = ForceVector_Type;
+	Stg_Class_DeleteFunction*                              _delete = _ForceVector_Delete;
+	Stg_Class_PrintFunction*                                _print = _ForceVector_Print;
+	Stg_Class_CopyFunction*                                  _copy = _ForceVector_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _ForceVector_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _ForceVector_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _ForceVector_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _ForceVector_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _ForceVector_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _ForceVector_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+
+	return _ForceVector_New(  FORCEVECTOR_PASSARGS  );
+}
+
+ForceVector* _ForceVector_New(  FORCEVECTOR_DEFARGS  ) {
+	ForceVector* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(ForceVector) );
+	self = (ForceVector*)_SolutionVector_New(  SOLUTIONVECTOR_PASSARGS  );
+	
+	return self;
+}
+
+
+void _ForceVector_Init( void* forceVector, Dimension_Index dim, EntryPoint_Register* entryPoint_Register ) {
+	ForceVector* self = (ForceVector*)  forceVector;
+	
+	/* ForceVector info */
+	self->dim = dim;
+	self->entryPoint_Register = entryPoint_Register;
+	
+	/* Create Stream */
+	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
+	
+	/* Create Entry Point for assembleForceVector */
+	Stg_asprintf( (char**)(&self->_assembleForceVectorEPName), "%s-%s", self->name, ForceVector_assembleForceVectorStr );
+	self->assembleForceVector = FeEntryPoint_New( self->_assembleForceVectorEPName, FeEntryPoint_AssembleForceVector_CastType );
+	EntryPoint_Register_Add( self->entryPoint_Register, self->assembleForceVector );	
+
+	/* Add default hook to assembleForceVector entry point */
+	EP_ReplaceAll( self->assembleForceVector, ForceVector_GlobalAssembly_General );
+
+	self->forceTermList = Stg_ObjectList_New();
+
+	self->bcAsm = Assembler_New();
+	self->inc = IArray_New();
+
+	self->nModifyCBs = 0;
+ 	self->modifyCBs = NULL;
+}
+
+void _ForceVector_Delete( void* forceVector ) {
+	ForceVector* self = (ForceVector*)forceVector;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+
+	/* Stg_Class_Delete parent*/
+	_SolutionVector_Delete( self );
+}
+
+void _ForceVector_Print( void* forceVector, Stream* stream ) {
+	ForceVector* self = (ForceVector*)forceVector;
+	
+	/* General info */
+	Journal_Printf( stream, "ForceVector (ptr): %p\n", self );
+	
+	/* Print parent */
+	_SolutionVector_Print( self, stream );
+	
+	/* Virtual info */
+	
+	/* ForceVector info */
+	Journal_Printf( stream, "\tassembleForceVector e.p. (ptr): %p\n", self->assembleForceVector );
+	EntryPoint_PrintConcise( self->assembleForceVector, stream );
+
+	Journal_Printf( stream, "\tVector (ptr): %p\n", self->vector );
+	Journal_Printf( stream, "\tComm: %u\n", self->comm );
+	Journal_Printf( stream, "\tLocalSize: %u\n", self->localSize );
+}
+
+
+void* _ForceVector_Copy( const void* forceVector, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	ForceVector*	self = (ForceVector*)forceVector;
+	ForceVector*	newForceVector;
+	PtrMap*		map = ptrMap;
+	Bool		ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newForceVector = (ForceVector*)_SolutionVector_Copy( self, dest, deep, nameExt, map );
+	
+	/* TODO: copy vector? */
+	newForceVector->entryPoint_Register = self->entryPoint_Register;
+	newForceVector->localSize = self->localSize;
+	
+	if( deep ) {
+		newForceVector->assembleForceVector = (FeEntryPoint*)Stg_Class_Copy( self->assembleForceVector, NULL, deep, nameExt, map );
+		if( self->_assembleForceVectorEPName ) {
+			if( nameExt ) {
+				unsigned	nameLen = strlen( self->_assembleForceVectorEPName );
+				
+				newForceVector->_assembleForceVectorEPName = (char*)Memory_Alloc_Bytes_Unnamed( nameLen + strlen( nameExt ) + 1, "FV->vecEPName" );
+				memcpy( (char*)(newForceVector->_assembleForceVectorEPName), self->_assembleForceVectorEPName, nameLen );
+				strcpy( (char*)(newForceVector->_assembleForceVectorEPName) + nameLen, nameExt );
+			}
+			else {
+				newForceVector->_assembleForceVectorEPName = StG_Strdup( self->_assembleForceVectorEPName );
+			}
+		}
+		else {
+			newForceVector->_assembleForceVectorEPName = NULL;
+		}
+
+	}
+	else {
+		newForceVector->debug = self->debug;
+		newForceVector->_assembleForceVectorEPName = self->_assembleForceVectorEPName;
+		newForceVector->assembleForceVector = self->assembleForceVector;
+	}
+	
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+	
+	return (void*)newForceVector;
+}
+
+
+void _ForceVector_AssignFromXML( void* forceVector, Stg_ComponentFactory* cf, void* data ) {
+	ForceVector*    self = (ForceVector*)forceVector;
+	Dimension_Index dim = 0;
+	void*           entryPointRegister = NULL;
+
+	_SolutionVector_AssignFromXML( self, cf, data );
+	
+	dim = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"dim", 0 );
+
+	entryPointRegister = (void*)self->context->entryPoint_Register;
+	assert( entryPointRegister  );
+	
+	_ForceVector_Init( self, dim, (EntryPoint_Register*)entryPointRegister );
+}
+
+void _ForceVector_Build( void* forceVector, void* data ) {
+	ForceVector* self = (ForceVector*)forceVector;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+	/* ensure feVariable is built */
+	if( self->feVariable ) {
+		Stg_Component_Build( self->feVariable, data, False );
+	}	
+	
+	/* update the size depending on our now built feVariable */
+	self->localSize = self->feVariable->eqNum->localEqNumsOwnedCount;
+	/* assert( self->localSize ); */
+	
+	/* Allocate the vector */
+	Journal_DPrintfL( self->debug, 2, "Allocating the L.A. Force Vector with %d local entries.\n", self->localSize );
+	VecCreate( self->comm, &self->vector );
+	VecSetSizes( self->vector, (PetscInt)self->localSize, PETSC_DECIDE );
+	VecSetFromOptions( self->vector );
+#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
+	VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES );
+#elif( PETSC_VERSION_MAJOR >= 3 )
+	VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
+#endif
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+
+	Assembler_SetVariables( self->bcAsm, self->feVariable, NULL );
+	Assembler_SetCallbacks( self->bcAsm, 
+		NULL, 
+		ForceVector_BCAsm_RowR, NULL, 
+		NULL, NULL, 
+		self );
+}
+
+
+void _ForceVector_Initialise( void* forceVector, void* data ) {
+	ForceVector* self = (ForceVector*)forceVector;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+	/* ensure feVariable is initialised */
+	if( self->feVariable )
+		Stg_Component_Initialise( self->feVariable, data, False );
+	
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _ForceVector_Execute( void* forceVector, void* data ) {
+}
+
+void _ForceVector_Destroy( void* forceVector, void* data ) {
+	ForceVector* self = (ForceVector*)forceVector;
+
+	Memory_Free( self->_assembleForceVectorEPName );
+
+	/* Don't delete entry point: E.P register will delete it automatically */
+	Stg_Class_Delete( self->forceTermList );
+
+	NewClass_Delete( self->inc );
+
+	_SolutionVector_Destroy( self, data );
+}
+
+void ForceVector_Assemble( void* forceVector ) {
+	ForceVector* self = (ForceVector*)forceVector;
+        int ii;
+	
+	Journal_DPrintf( self->debug, "In %s - for vector \"%s\" - calling the \"%s\" E.P.\n", __func__, self->name,
+			 self->assembleForceVector->name );
+
+	/* Call the Entry point directly from the base class */
+	/* Note that it may be empty: this is deliberate. */
+	if ( 0 == self->assembleForceVector->hooks->count ) {
+		Journal_DPrintf( self->debug, "(E.P. has no hooks loaded -> no assembly required.)\n" ); 
+	}	
+	
+	((FeEntryPoint_AssembleForceVector_CallFunction*)EntryPoint_GetRun( self->assembleForceVector ))(
+		self->assembleForceVector,
+		self );
+
+        /* Run all the modify callbacks. */
+        for( ii = 0; ii < self->nModifyCBs; ii++ ) {
+           void* callback = self->modifyCBs[ii].callback;
+           void* object = self->modifyCBs[ii].object;
+           ((void(*)(void*))callback)( object );
+        }
+}
+
+
+void ForceVector_PrintElementForceVector(
+	ForceVector* self,
+	Element_LocalIndex element_lI,
+	Dof_EquationNumber** elementLM,
+	double* elForceVecToAdd )
+{
+	DofLayout*		dofLayout = self->feVariable->dofLayout;
+	FeMesh*			feMesh = self->feVariable->feMesh;
+	unsigned		nInc, *inc;
+	Dof_Index		dofsPerNode;
+	Node_LocalIndex		nodesThisEl;
+	Node_LocalIndex		node_I;
+	Dof_Index		dof_I;
+	Index			vec_I;
+	IArray*			incArray;
+
+	incArray = IArray_New();
+	FeMesh_GetElementNodes( feMesh, element_lI, incArray );
+	nInc = IArray_GetSize( incArray );
+	inc = (unsigned*)IArray_GetPtr( incArray );
+	dofsPerNode = dofLayout->dofCounts[inc[0]];
+	nodesThisEl = nInc;
+
+	for ( node_I=0; node_I < nodesThisEl; node_I++ ) {
+		for ( dof_I = 0; dof_I < dofsPerNode; dof_I++ ) {
+			vec_I = node_I * dofsPerNode + dof_I;
+
+			Journal_DPrintf( self->debug, "Entry[%d][%d] (LM (%4d)) = %.3f\n",
+					 node_I, dof_I,
+					 elementLM[node_I][dof_I],
+					 elForceVecToAdd[vec_I] ); 
+		}			
+	}
+
+	NewClass_Delete( incArray );
+}
+
+/* from the depreciated Vector class */
+void _ForceVector_VectorView( Vec v, Stream* stream ) {
+	unsigned	entry_i;
+	PetscInt	size;
+	PetscScalar*	array;
+
+	VecGetSize( v, &size );
+	VecGetArray( v, &array );
+
+	Journal_Printf( stream, "%p = [", v );
+	for( entry_i = 0; entry_i < size; entry_i++ ) 
+		Journal_Printf( stream, "\t%u: \t %.12g\n", entry_i, array[entry_i] );
+	Journal_Printf( stream, "];\n" );
+
+	VecRestoreArray( v, &array );
+}
+
+void ForceVector_GlobalAssembly_General( void* forceVector ) {
+	ForceVector*            self                 = (ForceVector*) forceVector;
+	FeVariable*             feVar                = self->feVariable;
+	Element_LocalIndex      element_lI;
+	Element_LocalIndex      elementLocalCount;
+	Node_ElementLocalIndex  nodeCountCurrElement = 0;
+	Element_Nodes           nodeIdsInCurrElement = 0;
+	Dof_Index               totalDofsThisElement = 0;
+	Dof_Index               totalDofsPrevElement = 0;
+	Dof_Index               dofCountLastNode     = 0;
+	Dof_EquationNumber**    elementLM            = NULL;
+	double*                 elForceVecToAdd      = NULL;
+	/* For output printing */
+	double                  outputPercentage=10;	/* Controls how often to give a status update of assembly progress */
+	int                     outputInterval;
+
+	Journal_DPrintf( self->debug, "In %s - for vector \"%s\"\n", __func__, self->name );
+	
+	Stream_IndentBranch( StgFEM_Debug );
+	
+	if ( Stg_ObjectList_Count( self->forceTermList ) > 0 ) {
+		elementLocalCount = FeMesh_GetElementLocalSize( feVar->feMesh );
+
+		/* Initialise Vector */
+		outputInterval = (int)( (outputPercentage/100.0)*(double)(elementLocalCount) );
+		if( outputInterval == 0 ) { outputInterval = elementLocalCount; }
+	
+		for( element_lI = 0; element_lI < elementLocalCount; element_lI++ ) {  
+			unsigned	nInc, *inc;
+		
+			FeMesh_GetElementNodes( feVar->feMesh, element_lI, self->inc );
+			nInc = IArray_GetSize( self->inc );
+			inc = (unsigned*)IArray_GetPtr( self->inc );
+			nodeCountCurrElement = nInc;
+			/* Get the local node ids */
+			nodeIdsInCurrElement = inc;
+
+			/* Set value of elementLM: will automatically just index into global LM table if built */
+			elementLM = FeEquationNumber_BuildOneElementLocationMatrix( feVar->eqNum, element_lI );
+
+			/* work out number of dofs at the node, using LM */
+			/* Since: Number of entries in LM table for this element = (by defn.) Number of dofs this element */
+			dofCountLastNode = feVar->dofLayout->dofCounts[nodeIdsInCurrElement[nodeCountCurrElement-1]]; 
+			totalDofsThisElement = &elementLM[nodeCountCurrElement-1][dofCountLastNode-1] - &elementLM[0][0] + 1;
+
+			if ( totalDofsThisElement > totalDofsPrevElement ) {
+				if (elForceVecToAdd) Memory_Free( elForceVecToAdd );
+				Journal_DPrintfL( self->debug, 2, "Reallocating elForceVecToAdd to size %d\n", totalDofsThisElement );
+				elForceVecToAdd = Memory_Alloc_Array( double, totalDofsThisElement, "elForceVecToAdd" );
+			}
+
+			/* Initialise Values to Zero */
+			memset( elForceVecToAdd, 0, totalDofsThisElement * sizeof(double) );
+		
+			/* Assemble this element's element force vector: going through each force term in list */
+			ForceVector_AssembleElement( self, element_lI, elForceVecToAdd );
+
+/*
+  #if DEBUG
+  if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+  Journal_DPrintf( self->debug, "Handling Element %d:\n", element_lI );
+  FeEquationNumber_PrintElementLocationMatrix( feVar->eqNum, elementLM,
+  element_lI, self->debug );
+				
+  Journal_DPrintf( self->debug, "El force Vec about to be added:\n" );
+  ForceVector_PrintElementForceVector( self, element_lI, elementLM, elForceVecToAdd );
+  }	
+  #endif
+*/
+
+                        /* When keeping BCs in we come across a bit of a problem in parallel. We're not
+                           allowed to add entries to the force vector here and then clobber it later with
+                           an insert in order to set the BC. So, what we'll do is just add zero here, that
+                           way later we can add the BC and it will be the same as inserting it.
+                           --- Luke, 20 May 2008 */
+                        if( !self->feVariable->eqNum->removeBCs ) {
+                           DofLayout* dofs;
+                           int nDofs, curInd;
+                           int ii, jj;
+
+                           dofs = self->feVariable->dofLayout; /* shortcut to the dof layout */
+                           curInd = 0; /* need a counter to track where we are in the element force vector */
+                           for( ii = 0; ii < nodeCountCurrElement; ii++ ) {
+                              nDofs = dofs->dofCounts[inc[ii]]; /* number of dofs on this node */
+                              for( jj = 0; jj < nDofs; jj++ ) {
+                                 if( !FeVariable_IsBC( self->feVariable, inc[ii], jj ) ) {
+                                    curInd++;
+                                    continue; /* only need to clear it if it's a bc */
+                                 }
+                                 elForceVecToAdd[curInd] = 0.0;
+                                 curInd++;
+                              }
+                           }
+                        }
+
+			/* Ok, assemble into global matrix */
+			//Vector_AddEntries( self->vector, totalDofsThisElement, (Index*)(elementLM[0]), elForceVecToAdd );
+			VecSetValues( self->vector, totalDofsThisElement, (PetscInt*)elementLM[0], elForceVecToAdd, ADD_VALUES );
+
+#if DEBUG
+			if( element_lI % outputInterval == 0 ) {
+				Journal_DPrintfL( self->debug, 2, "done %d percent of global force vector assembly (general) \n",
+						  (int)(100.0*((double)element_lI/(double)elementLocalCount)) );
+			}
+#endif
+
+			/* Cleanup: If we haven't built the big LM for all elements, free the temporary one */
+			if ( False == feVar->eqNum->locationMatrixBuilt ) {
+				Memory_Free( elementLM );
+			}
+			totalDofsPrevElement = totalDofsThisElement;
+		}
+
+		Memory_Free( elForceVecToAdd );
+	}
+	else {
+		Journal_DPrintf( self->debug, "No ForceTerms registered - returning.\n" );
+	}
+
+	/* If we're keeping BCs, insert them into the force vector. */
+	if( !feVar->eqNum->removeBCs )
+		Assembler_LoopVector( self->bcAsm );
+
+	//Vector_AssemblyBegin( self->vector );
+	//Vector_AssemblyEnd( self->vector ); 
+	VecAssemblyBegin( self->vector );
+	VecAssemblyEnd( self->vector );
+
+#if DEBUG
+	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+		Journal_DPrintf( self->debug, "Completely built vector %s is:\n", self->name );
+		_ForceVector_VectorView( self->vector, self->debug );
+	}
+#endif
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+		
+void ForceVector_AssembleElement( void* forceVector, Element_LocalIndex element_lI, double* elForceVecToAdd ) {
+	ForceVector*            self                 = (ForceVector*) forceVector;
+	Index                   forceTermCount       = Stg_ObjectList_Count( self->forceTermList );
+	Index                   forceTerm_I;
+	ForceTerm*              forceTerm;
+
+	for ( forceTerm_I = 0 ; forceTerm_I < forceTermCount ; forceTerm_I++ ) {
+		forceTerm = (ForceTerm*) Stg_ObjectList_At( self->forceTermList, forceTerm_I );
+
+		ForceTerm_AssembleElement( forceTerm, self, element_lI, elForceVecToAdd );
+	}
+}
+
+void ForceVector_AddForceTerm( void* forceVector, ForceTerm* forceTerm ) {
+	ForceVector*            self                 = (ForceVector*) forceVector;
+
+	Stg_ObjectList_Append( self->forceTermList, Stg_CheckType( forceTerm, ForceTerm ) );
+}
+
+Bool ForceVector_BCAsm_RowR( void* forceVec, Assembler* assm ) {
+	double	bc;
+
+	bc = DofLayout_GetValueDouble( assm->rowVar->dofLayout, 
+				       assm->rowNodeInd, 
+				       assm->rowDofInd );
+	//Vector_AddEntries( ((ForceVector*)forceVec)->vector, 1, &assm->rowEq, &bc );
+	VecSetValues( ((ForceVector*)forceVec)->vector, 1, (PetscInt*)(&assm->rowEq), &bc, ADD_VALUES );
+	return True;
+}
+
+void ForceVector_AddModifyCallback( ForceVector* self, void* callback, void* object ) {
+   self->nModifyCBs++;
+   self->modifyCBs = ReallocArray( self->modifyCBs, Callback, self->nModifyCBs );
+   self->modifyCBs[self->nModifyCBs - 1].callback = callback;
+   self->modifyCBs[self->nModifyCBs - 1].object = object;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/Init.c
--- a/SLE/SystemSetup/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "SystemSetup.h"
-
-
-Stream* StgFEM_SLE_Debug = NULL;
-Stream* StgFEM_SLE_SystemSetup_Debug = NULL;
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_SLE_SystemSetup_Init( int* argc, char** argv[] ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	/* initialise this level's streams */
-	StgFEM_SLE_Debug = Stream_RegisterChild( StgFEM_Debug, "SLE" );
-	StgFEM_SLE_SystemSetup_Debug = Stream_RegisterChild( StgFEM_SLE_Debug, "SystemSetup" );
-	
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), FiniteElementContext_Type, (Name)"0", FiniteElementContext_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), ForceVector_Type, "0", _ForceVector_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), SolutionVector_Type, (Name)"0", _SolutionVector_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), StiffnessMatrix_Type, "0", StiffnessMatrix_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), StiffnessMatrixTerm_Type, (Name)"0", _StiffnessMatrixTerm_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), SystemLinearEquations_Type, "0", _SystemLinearEquations_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), ForceTerm_Type, (Name)"0", _ForceTerm_DefaultNew );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), 
-				   MultigridSolver_Type, "0", 
-				   (Stg_Component_DefaultConstructorFunction*)MultigridSolver_New );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), SROpGenerator_Type, (Name)"0", (Stg_Component_DefaultConstructorFunction*)SROpGenerator_New );
-	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), 
-				   PETScMGSolver_Type, "0", 
-				   (Stg_Component_DefaultConstructorFunction*)PETScMGSolver_New );
-
-	RegisterParent( SystemLinearEquations_Type,    Stg_Component_Type );
-	RegisterParent( SLE_Solver_Type,               Stg_Component_Type );
-	RegisterParent( StiffnessMatrix_Type,          Stg_Component_Type );
-	RegisterParent( StiffnessMatrixTerm_Type,      Stg_Component_Type );
-	RegisterParent( SolutionVector_Type,           Stg_Component_Type );
-	RegisterParent( ForceVector_Type,              SolutionVector_Type );
-	RegisterParent( ForceTerm_Type,                Stg_Component_Type );
-	RegisterParent( Assembler_Type, Stg_Class_Type );
-	RegisterParent( FiniteElementContext_Type,     DomainContext_Type );
-	RegisterParent( PETScMGSolver_Type, Stg_Component_Type );
-	RegisterParent( MultigridSolver_Type, Stg_Component_Type );
-	RegisterParent( MGOpGenerator_Type, Stg_Component_Type );
-	RegisterParent( SROpGenerator_Type, MGOpGenerator_Type);
-
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,95 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "SystemSetup.h"
+
+
+Stream* StgFEM_SLE_Debug = NULL;
+Stream* StgFEM_SLE_SystemSetup_Debug = NULL;
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_SLE_SystemSetup_Init( int* argc, char** argv[] ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	/* initialise this level's streams */
+	StgFEM_SLE_Debug = Stream_RegisterChild( StgFEM_Debug, "SLE" );
+	StgFEM_SLE_SystemSetup_Debug = Stream_RegisterChild( StgFEM_SLE_Debug, "SystemSetup" );
+	
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), FiniteElementContext_Type, (Name)"0", FiniteElementContext_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), ForceVector_Type, "0", _ForceVector_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), SolutionVector_Type, (Name)"0", _SolutionVector_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), StiffnessMatrix_Type, "0", StiffnessMatrix_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), StiffnessMatrixTerm_Type, (Name)"0", _StiffnessMatrixTerm_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), SystemLinearEquations_Type, "0", _SystemLinearEquations_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), ForceTerm_Type, (Name)"0", _ForceTerm_DefaultNew );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), 
+				   MultigridSolver_Type, "0", 
+				   (Stg_Component_DefaultConstructorFunction*)MultigridSolver_New );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister(), SROpGenerator_Type, (Name)"0", (Stg_Component_DefaultConstructorFunction*)SROpGenerator_New );
+	Stg_ComponentRegister_Add( Stg_ComponentRegister_Get_ComponentRegister( ), 
+				   PETScMGSolver_Type, "0", 
+				   (Stg_Component_DefaultConstructorFunction*)PETScMGSolver_New );
+
+	RegisterParent( SystemLinearEquations_Type,    Stg_Component_Type );
+	RegisterParent( SLE_Solver_Type,               Stg_Component_Type );
+	RegisterParent( StiffnessMatrix_Type,          Stg_Component_Type );
+	RegisterParent( StiffnessMatrixTerm_Type,      Stg_Component_Type );
+	RegisterParent( SolutionVector_Type,           Stg_Component_Type );
+	RegisterParent( ForceVector_Type,              SolutionVector_Type );
+	RegisterParent( ForceTerm_Type,                Stg_Component_Type );
+	RegisterParent( Assembler_Type, Stg_Class_Type );
+	RegisterParent( FiniteElementContext_Type,     DomainContext_Type );
+	RegisterParent( PETScMGSolver_Type, Stg_Component_Type );
+	RegisterParent( MultigridSolver_Type, Stg_Component_Type );
+	RegisterParent( MGOpGenerator_Type, Stg_Component_Type );
+	RegisterParent( SROpGenerator_Type, MGOpGenerator_Type);
+
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/MGOpGenerator.c
--- a/SLE/SystemSetup/src/MGOpGenerator.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: MGOpGenerator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-
-#include "SystemSetup.h"
-
-
-/* Textual name of this class */
-const Type MGOpGenerator_Type = "MGOpGenerator";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-MGOpGenerator* _MGOpGenerator_New(  MGOPGENERATOR_DEFARGS  ) {
-	MGOpGenerator*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(MGOpGenerator) );
-	self = (MGOpGenerator*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-
-	/* stuff previously housed in the MatrixSolver class */
-	self->solver = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
-	self->solver->ksp = PETSC_NULL;
-	self->solver->matrix = PETSC_NULL;
-	self->solver->inversion = PETSC_NULL;
-	self->solver->residual = PETSC_NULL;
-	self->solver->curRHS = PETSC_NULL;
-	self->solver->curSolution = PETSC_NULL;
-	self->solver->expiredResidual = True;
-	self->solver->matrixChanged = True;
-
-	/* Virtual info */
-	self->setNumLevelsFunc = setNumLevelsFunc;
-	self->hasExpiredFunc = hasExpiredFunc;
-	self->generateFunc = generateFunc;
-
-	/* MGOpGenerator info */
-	_MGOpGenerator_Init( self );
-
-	return self;
-}
-
-void _MGOpGenerator_Init( MGOpGenerator* self ) {
-	assert( self && Stg_CheckType( self, MGOpGenerator ) );
-
-	self->nLevels = 0;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _MGOpGenerator_Delete( void* mgOpGenerator ) {
-	MGOpGenerator*	self = (MGOpGenerator*)mgOpGenerator;
-
-	assert( self && Stg_CheckType( self, MGOpGenerator ) );
-
-	/* this stuff was previously taken care of in the MatrixSolver class */
-	if( self->solver ) {
-            /*if( self->solver->ksp != PETSC_NULL )         KSPDestroy( self->solver->ksp );*/
-		if( self->solver->matrix != PETSC_NULL )      MatDestroy( self->solver->matrix );
-		if( self->solver->inversion != PETSC_NULL )   MatDestroy( self->solver->inversion );
-		if( self->solver->residual != PETSC_NULL )    VecDestroy( self->solver->residual );
-		if( self->solver->curRHS != PETSC_NULL )      VecDestroy( self->solver->curRHS );
-		if( self->solver->curSolution != PETSC_NULL ) VecDestroy( self->solver->curSolution );
-		free( self->solver );
-	}
-
-	/* Delete the parent. */
-	_Stg_Component_Delete( self );
-}
-
-void _MGOpGenerator_Print( void* mgOpGenerator, Stream* stream ) {
-	MGOpGenerator*	self = (MGOpGenerator*)mgOpGenerator;
-	
-	/* Set the Journal for printing informations */
-	Stream* mgOpGeneratorStream;
-	mgOpGeneratorStream = Journal_Register( InfoStream_Type, (Name)"MGOpGeneratorStream"  );
-
-	assert( self && Stg_CheckType( self, MGOpGenerator ) );
-
-	/* Print parent */
-	Journal_Printf( stream, "MGOpGenerator (ptr): (%p)\n", self );
-	_Stg_Component_Print( self, stream );
-}
-
-void _MGOpGenerator_AssignFromXML( void* mgOpGenerator, Stg_ComponentFactory* cf, void* data ) {
-	MGOpGenerator*		self = (MGOpGenerator*)mgOpGenerator;
-
-	assert( self && Stg_CheckType( self, MGOpGenerator ) );
-	assert( cf );
-}
-
-void _MGOpGenerator_Build( void* mgOpGenerator, void* data ) {
-}
-
-void _MGOpGenerator_Initialise( void* mgOpGenerator, void* data ) {
-}
-
-void _MGOpGenerator_Execute( void* mgOpGenerator, void* data ) {
-}
-
-void _MGOpGenerator_Destroy( void* mgOpGenerator, void* data ) {
-}
-
-void _MGOpGenerator_SetNumLevels( void* mgOpGenerator, unsigned nLevels ) {
-	MGOpGenerator*		self = (MGOpGenerator*)mgOpGenerator;
-
-	assert( self && Stg_CheckType( self, MGOpGenerator ) );
-
-	self->nLevels = nLevels;
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void MGOpGenerator_SetMatrixSolver( void* mgOpGenerator, void* _solver ) {
-	MGOpGenerator*	self = (MGOpGenerator*)mgOpGenerator;
-	//MatrixSolver*	solver = (MatrixSolver*)_solver;
-	KSP		solver = (KSP)_solver;
-
-	assert( self && Stg_CheckType( self, MGOpGenerator ) );
-	//assert( solver && Stg_CheckType( solver, MatrixSolver ) );
-
-	//self->solver = solver;
-	self->solver->ksp = solver;
-}
-
-unsigned MGOpGenerator_GetNumLevels( void* mgOpGenerator ) {
-	MGOpGenerator*		self = (MGOpGenerator*)mgOpGenerator;
-
-	assert( self && Stg_CheckType( self, MGOpGenerator ) );
-
-	return self->nLevels;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/MGOpGenerator.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/MGOpGenerator.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,183 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: MGOpGenerator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+
+#include "SystemSetup.h"
+
+
+/* Textual name of this class */
+const Type MGOpGenerator_Type = "MGOpGenerator";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+MGOpGenerator* _MGOpGenerator_New(  MGOPGENERATOR_DEFARGS  ) {
+	MGOpGenerator*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(MGOpGenerator) );
+	self = (MGOpGenerator*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+
+	/* stuff previously housed in the MatrixSolver class */
+	self->solver = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
+	self->solver->ksp = PETSC_NULL;
+	self->solver->matrix = PETSC_NULL;
+	self->solver->inversion = PETSC_NULL;
+	self->solver->residual = PETSC_NULL;
+	self->solver->curRHS = PETSC_NULL;
+	self->solver->curSolution = PETSC_NULL;
+	self->solver->expiredResidual = True;
+	self->solver->matrixChanged = True;
+
+	/* Virtual info */
+	self->setNumLevelsFunc = setNumLevelsFunc;
+	self->hasExpiredFunc = hasExpiredFunc;
+	self->generateFunc = generateFunc;
+
+	/* MGOpGenerator info */
+	_MGOpGenerator_Init( self );
+
+	return self;
+}
+
+void _MGOpGenerator_Init( MGOpGenerator* self ) {
+	assert( self && Stg_CheckType( self, MGOpGenerator ) );
+
+	self->nLevels = 0;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _MGOpGenerator_Delete( void* mgOpGenerator ) {
+	MGOpGenerator*	self = (MGOpGenerator*)mgOpGenerator;
+
+	assert( self && Stg_CheckType( self, MGOpGenerator ) );
+
+	/* this stuff was previously taken care of in the MatrixSolver class */
+	if( self->solver ) {
+            /*if( self->solver->ksp != PETSC_NULL )         KSPDestroy( self->solver->ksp );*/
+		if( self->solver->matrix != PETSC_NULL )      MatDestroy( self->solver->matrix );
+		if( self->solver->inversion != PETSC_NULL )   MatDestroy( self->solver->inversion );
+		if( self->solver->residual != PETSC_NULL )    VecDestroy( self->solver->residual );
+		if( self->solver->curRHS != PETSC_NULL )      VecDestroy( self->solver->curRHS );
+		if( self->solver->curSolution != PETSC_NULL ) VecDestroy( self->solver->curSolution );
+		free( self->solver );
+	}
+
+	/* Delete the parent. */
+	_Stg_Component_Delete( self );
+}
+
+void _MGOpGenerator_Print( void* mgOpGenerator, Stream* stream ) {
+	MGOpGenerator*	self = (MGOpGenerator*)mgOpGenerator;
+	
+	/* Set the Journal for printing informations */
+	Stream* mgOpGeneratorStream;
+	mgOpGeneratorStream = Journal_Register( InfoStream_Type, (Name)"MGOpGeneratorStream"  );
+
+	assert( self && Stg_CheckType( self, MGOpGenerator ) );
+
+	/* Print parent */
+	Journal_Printf( stream, "MGOpGenerator (ptr): (%p)\n", self );
+	_Stg_Component_Print( self, stream );
+}
+
+void _MGOpGenerator_AssignFromXML( void* mgOpGenerator, Stg_ComponentFactory* cf, void* data ) {
+	MGOpGenerator*		self = (MGOpGenerator*)mgOpGenerator;
+
+	assert( self && Stg_CheckType( self, MGOpGenerator ) );
+	assert( cf );
+}
+
+void _MGOpGenerator_Build( void* mgOpGenerator, void* data ) {
+}
+
+void _MGOpGenerator_Initialise( void* mgOpGenerator, void* data ) {
+}
+
+void _MGOpGenerator_Execute( void* mgOpGenerator, void* data ) {
+}
+
+void _MGOpGenerator_Destroy( void* mgOpGenerator, void* data ) {
+}
+
+void _MGOpGenerator_SetNumLevels( void* mgOpGenerator, unsigned nLevels ) {
+	MGOpGenerator*		self = (MGOpGenerator*)mgOpGenerator;
+
+	assert( self && Stg_CheckType( self, MGOpGenerator ) );
+
+	self->nLevels = nLevels;
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void MGOpGenerator_SetMatrixSolver( void* mgOpGenerator, void* _solver ) {
+	MGOpGenerator*	self = (MGOpGenerator*)mgOpGenerator;
+	//MatrixSolver*	solver = (MatrixSolver*)_solver;
+	KSP		solver = (KSP)_solver;
+
+	assert( self && Stg_CheckType( self, MGOpGenerator ) );
+	//assert( solver && Stg_CheckType( solver, MatrixSolver ) );
+
+	//self->solver = solver;
+	self->solver->ksp = solver;
+}
+
+unsigned MGOpGenerator_GetNumLevels( void* mgOpGenerator ) {
+	MGOpGenerator*		self = (MGOpGenerator*)mgOpGenerator;
+
+	assert( self && Stg_CheckType( self, MGOpGenerator ) );
+
+	return self->nLevels;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/MultigridSolver.c
--- a/SLE/SystemSetup/src/MultigridSolver.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1233 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: MultigridSolver.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-
-#include "SystemSetup.h"
-
-
-/* Textual name of this class */
-const Type MultigridSolver_Type = "MultigridSolver";
-
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-MultigridSolver* MultigridSolver_New( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                    _sizeOfSelf = sizeof(MultigridSolver);
-	Type                                                            type = MultigridSolver_Type;
-	Stg_Class_DeleteFunction*                                    _delete = _MultigridSolver_Delete;
-	Stg_Class_PrintFunction*                                      _print = _MultigridSolver_Print;
-	Stg_Class_CopyFunction*                                        _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*        _defaultConstructor = (void* (*)(Name))_MultigridSolver_New;
-	Stg_Component_ConstructFunction*                          _construct = _MultigridSolver_AssignFromXML;
-	Stg_Component_BuildFunction*                                  _build = _MultigridSolver_Build;
-	Stg_Component_InitialiseFunction*                        _initialise = _MultigridSolver_Initialise;
-	Stg_Component_ExecuteFunction*                              _execute = _MultigridSolver_Execute;
-	Stg_Component_DestroyFunction*                              _destroy = _MultigridSolver_Destroy;
-	AllocationType                                    nameAllocationType = NON_GLOBAL;
-	MGSolver_SetCommFunc*                                    setCommFunc = MultigridSolver_SetComm;
-	MGSolver_SetMatrixFunc*                                setMatrixFunc = MultigridSolver_SetMatrix;
-	MGSolver_SetMaxIterationsFunc*                  setMaxIterationsFunc = MultigridSolver_SetMaxIterations;
-	MGSolver_SetRelativeToleranceFunc*          setRelativeToleranceFunc = MultigridSolver_SetRelativeTolerance;
-	MGSolver_SetAbsoluteToleranceFunc*          setAbsoluteToleranceFunc = MultigridSolver_SetAbsoluteTolerance;
-	MGSolver_SetUseInitialSolutionFunc*        setUseInitialSolutionFunc = MultigridSolver_SetUseInitialSolution;
-	MGSolver_SolveFunc*                                        solveFunc = MultigridSolver_Solve;
-	MGSolver_SetupFunc*                                        setupFunc = MultigridSolver_Setup;
-	MGSolver_GetSolveStatusFunc*                      getSolveStatusFunc = MultigridSolver_GetSolveStatus;
-	MGSolver_GetIterationsFunc*                        getIterationsFunc = MultigridSolver_GetIterations;
-	MGSolver_GetMaxIterationsFunc*                  getMaxIterationsFunc = MultigridSolver_GetMaxIterations;
-	MGSolver_GetResidualNormFunc*                    getResidualNormFunc = MultigridSolver_GetResidualNorm;
-
-	return _MultigridSolver_New(  MULTIGRIDSOLVER_PASSARGS  );
-}
-
-MultigridSolver* _MultigridSolver_New(  MULTIGRIDSOLVER_DEFARGS  ) {
-	MultigridSolver*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(MultigridSolver) );
-
-	self = (MultigridSolver*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-
-	/* function assignments previously in the MatrixSolver_New func */
-	self->setCommFunc = setCommFunc;
-	self->setMatrixFunc = setMatrixFunc;
-	self->setMaxIterationsFunc = setMaxIterationsFunc;
-	self->setRelativeToleranceFunc = setRelativeToleranceFunc;
-	self->setAbsoluteToleranceFunc = setAbsoluteToleranceFunc;
-	self->setUseInitialSolutionFunc = setUseInitialSolutionFunc;
-
-	self->solveFunc = solveFunc;
-	self->setupFunc = setupFunc;
-
-	self->getSolveStatusFunc = getSolveStatusFunc;
-	self->getIterationsFunc = getIterationsFunc;
-	self->getMaxIterationsFunc = getMaxIterationsFunc;
-	self->getResidualNormFunc = getResidualNormFunc;
-
-	/* Virtual info */
-
-	/* MultigridSolver info */
-	_MultigridSolver_Init( self );
-
-	return self;
-}
-
-void _MultigridSolver_Init( MultigridSolver* self ) {
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	/* these initialisations previously done in the MatrixSolver_Init func */
-	self->mgData = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
-
-	self->mgData->comm = MPI_COMM_WORLD;
-	KSPCreate( MPI_COMM_WORLD, &self->mgData->ksp );
-	self->mgData->matrix = PETSC_NULL;
-	self->mgData->inversion = PETSC_NULL;
-	self->mgData->residual = PETSC_NULL;
-	self->mgData->expiredResidual = True;
-	self->mgData->matrixChanged = True;
-
-	self->mgData->curRHS = PETSC_NULL;
-	self->mgData->curSolution = PETSC_NULL;
-	/* end of old MatrixSolver_Init initialisations */
-
-	self->nLevels = 0;
-	self->levels = NULL;
-	self->opGen = NULL;
-	self->solversChanged = True;
-	self->opsChanged = True;
-
-	self->curIt = 0;
-	self->maxIts = 500;
-	self->relTol = 1e-5;
-	self->rnorm = 0.0;
-	self->useInitial = False;
-	//self->outerSolver = NULL;
-	self->outerSolver = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
-	self->outerSolver->ksp = PETSC_NULL;
-	self->outerSolver->matrix = PETSC_NULL;
-	self->outerSolver->inversion = PETSC_NULL;
-	self->outerSolver->residual = PETSC_NULL;
-	self->outerSolver->curRHS = PETSC_NULL;
-	self->outerSolver->curSolution = PETSC_NULL;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _MultigridSolver_Delete( void* matrixSolver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	MultigridSolver_Destruct( self );
-
-	/* Delete the parent. */
-	_Stg_Component_Delete( self );
-}
-
-void _MultigridSolver_Print( void* matrixSolver, Stream* stream ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	
-	/* Set the Journal for printing informations */
-	Stream* matrixSolverStream;
-	matrixSolverStream = Journal_Register( InfoStream_Type, (Name)"MultigridSolverStream"  );
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	/* Print parent */
-	Journal_Printf( stream, "MultigridSolver (ptr): (%p)\n", self );
-	_Stg_Component_Print( self, stream );
-}
-
-void _MultigridSolver_AssignFromXML( void* matrixSolver, Stg_ComponentFactory* cf, void* data ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	unsigned		nLevels;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( cf );
-
-	nLevels = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"levels", 1  );
-	MultigridSolver_SetLevels( self, nLevels );
-	self->opGen = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"opGenerator", MGOpGenerator, True, data  );
-	MGOpGenerator_SetMatrixSolver( self->opGen, self );
-	MGOpGenerator_SetNumLevels( self->opGen, nLevels );
-}
-
-void _MultigridSolver_Build( void* matrixSolver, void* data ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	self->stream = Journal_Register( InfoStream_Type, (Name)"general" );
-	if( self->opGen  )
-		Stg_Component_Build( self->opGen, data, False );
-}
-
-void _MultigridSolver_Initialise( void* matrixSolver, void* data ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	if( self->opGen )
-		Stg_Component_Initialise( self->opGen, data, False );
-}
-
-void _MultigridSolver_Execute( void* matrixSolver, void* data ) {
-}
-
-void _MultigridSolver_Destroy( void* matrixSolver, void* data ) {
-}
-
-/* copied from the PETScMatrixSolver class, has been depreciated */
-void MultigridSolver_SetComm( void* matrixSolver, MPI_Comm comm ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	self->mgData->comm = comm;
-
-	if( self->mgData->ksp != PETSC_NULL )
-		KSPDestroy( self->mgData->ksp );
-	KSPCreate( comm, &self->mgData->ksp );
-}
-
-/* copied from the PETScMatrixSolver class, has been depreciated */
-void MultigridSolver_SetMatrix( void* matrixSolver, void* _matrix ) {
-	MultigridSolver*	self 	= (MultigridSolver*)matrixSolver;
-	Mat			matrix	= (Mat)_matrix;
-
-	self->mgData->matrix = matrix;
-	KSPSetOperators( self->mgData->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN );
-}
-
-void MultigridSolver_SetMaxIterations( void* matrixSolver, unsigned nIterations ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	self->maxIts = nIterations;
-}
-
-void MultigridSolver_SetRelativeTolerance( void* matrixSolver, double tolerance ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	self->relTol = tolerance;
-	self->solversChanged = True;
-}
-
-void MultigridSolver_SetAbsoluteTolerance( void* matrixSolver, double tolerance ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	//MatrixSolver_SetAbsoluteTolerance( self->outerSolver, tolerance );
-	KSPSetTolerances( self->outerSolver->ksp, PETSC_DEFAULT, tolerance, PETSC_DEFAULT, PETSC_DEFAULT );
-
-	self->solversChanged = True;
-}
-
-void MultigridSolver_SetUseInitialSolution( void* matrixSolver, Bool state ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	self->useInitial = state;
-}
-
-/* these functions were associated with the PETScMatrixSolver class, before it was
- * depreciated */
-Vec _GetResidual( MGSolver_PETScData* mgData ) {
-	if( mgData->expiredResidual ) {
-		VecDuplicate( mgData->curSolution, &mgData->residual );	
-		VecSetFromOptions( mgData->residual );
-#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
-		VecSetOption( mgData->residual, VEC_IGNORE_NEGATIVE_INDICES );
-#elif( PETSC_VERSION_MAJOR >= 3 )
-		VecSetOption( mgData->residual, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
-#endif
-		MatMult( mgData->matrix, mgData->curSolution, mgData->residual );
-		VecAYPX( mgData->residual, -1.0, mgData->curRHS );
-
-		mgData->expiredResidual = False;
-	}
-
-	return mgData->residual;
-}
-
-double _GetResidualNorm( MGSolver_PETScData* mgData ) {
-	PC			pc;
-	const KSPType		kspType;
-	const PCType		pcType;
-	PetscScalar		rnorm;
-	PetscErrorCode		ec;
-
-	ec = KSPGetType( mgData->ksp, &kspType );
-	CheckPETScError( ec );
-	ec = KSPGetPC( mgData->ksp, &pc );
-	CheckPETScError( ec );
-	ec = PCGetType( pc, &pcType );
-	CheckPETScError( ec );
-
-	if( !strcmp( kspType, KSPRICHARDSON ) && !strcmp( pcType, PCSOR ) ) {
-		Vec	residual;
-
-		//residual = MatrixSolver_GetResidual( mgData );
-		//rnorm = (PetscScalar)Vector_L2Norm( residual );
-		residual = _GetResidual( mgData );
-		VecNorm( residual, NORM_2, &rnorm );
-	}
-	else {
-		ec = KSPGetResidualNorm( mgData->ksp, &rnorm );
-		CheckPETScError( ec );
-	}
-
-	return (double)rnorm;
-}
-
-#define MultigridSolver_NormType_Preconditioned 1
-
-MGSolver_Status _GetSolveStatus( MGSolver_PETScData* mgData ) {
-	PC			pc;
-	const KSPType		kspType;
-	const PCType		pcType;
-	KSPConvergedReason	reason;
-	PetscErrorCode		ec;
-
-	ec = KSPGetType( mgData->ksp, &kspType );
-	CheckPETScError( ec );
-	ec = KSPGetPC( mgData->ksp, &pc );
-	CheckPETScError( ec );
-	ec = PCGetType( pc, &pcType );
-	CheckPETScError( ec );
-
-	if( !strcmp( kspType, KSPRICHARDSON ) && !strcmp( pcType, PCSOR ) ) {
-		double		rnorm;
-		PetscInt	curIt;
-
-		//rnorm = PETScMatrixSolver_GetResidualNorm( self );
-		//curIt = PETScMatrixSolver_GetIterations( self );
-		rnorm = _GetResidualNorm( mgData );
-		KSPGetIterationNumber( mgData->ksp, &curIt );
-		//PETScMatrixSolver_SetNormType( self, MultigridSolver_NormType_Preconditioned );
-		KSPSetNormType( mgData->ksp, (KSPNormType)MultigridSolver_NormType_Preconditioned );
-		ec = KSPDefaultConverged( mgData->ksp, curIt, (PetscScalar)rnorm, &reason, PETSC_NULL );
-		CheckPETScError( ec );
-	}
-	else {
-		ec = KSPGetConvergedReason( mgData->ksp, &reason );
-		CheckPETScError( ec );
-	}
-
-	return (MGSolver_Status)reason;
-}
-
-/* end of functions formerly defined in the PETScMatrixSolver class */
-
-void MultigridSolver_Solve( void* matrixSolver, void* _rhs, void* _solution ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	Vec			rhs = (Vec)_rhs;
-	Vec			solution = (Vec)_solution;
-	double wallTime;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	//assert( rhs && Stg_CheckType( rhs, Vector ) );
-	//assert( solution && Stg_CheckType( solution, Vector ) );
-
-	Journal_Printf( self->stream, "MultigridSolver: Starting solve ...\n" );
-	Stream_Indent( self->stream );
-
-	if( !self->useInitial ) {
-		Journal_Printf( self->stream, "Zeroing initial solution\n" );
-		//Vector_Zero( solution );
-		VecSet( solution, 0.0 );
-	}
-	else
-		Journal_Printf( self->stream, "Keeping initial solution\n" );
-
-	wallTime = MPI_Wtime();
-	MultigridSolver_Setup( self, rhs, solution );
-	stg_profile_Func( "MultigridSolver_Setup", MPI_Wtime() - wallTime);
-	self->curIt = 0;
-	//while( MatrixSolver_GetSolveStatus( self ) == MultigridSolver_Status_Iterating && self->curIt < self->maxIts ) {
-	while( _GetSolveStatus( self->mgData ) == MGSolver_Status_Iterating && self->curIt < self->maxIts ) {
-		Journal_Printf( self->stream, "Iteration %d: residual %.10lf\n", 
-				//self->curIt, MatrixSolver_GetResidualNorm( self->outerSolver ) );
-				self->curIt, _GetResidualNorm( self->outerSolver ) );
-		MultigridSolver_LevelCycle( self, self->nLevels - 1, rhs, solution );
-		self->curIt++;
-	}
-	Journal_Printf( self->stream, "Iteration %d: residual %.10lf\n", 
-			//self->curIt, MatrixSolver_GetResidualNorm( self->outerSolver ) );
-			self->curIt, _GetResidualNorm( self->outerSolver ) );
-
-	Stream_UnIndent( self->stream );
-	Journal_Printf( self->stream, "done.\n" );
-}
-
-void MultigridSolver_Setup( void* matrixSolver, void* rhs, void* solution ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	Bool			rebuildOps;
-	double wallTime;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	//_MatrixSolver_Setup( self, rhs, solution );
-	self->mgData->curRHS = (struct _p_Vec*)rhs;
-	self->mgData->curSolution = (struct _p_Vec*)solution;
-	self->mgData->expiredResidual = True;
-
-	/* Need to rebuild the operators? */
-	if( self->opGen )
-		rebuildOps = MGOpGenerator_HasExpired( self->opGen );
-	else
-		rebuildOps = False;
-	if( !rebuildOps ) {
-		unsigned		l_i;
-
-		for( l_i = 1; l_i < self->nLevels; l_i++ ) {
-			if( !MultigridSolver_GetRestriction( self, l_i ) || !MultigridSolver_GetProlongation( self, l_i ) ) {
-				rebuildOps = True;
-				break;
-			}
-		}
-	}
-
-	if( rebuildOps )
-		wallTime = MPI_Wtime();
-		MultigridSolver_UpdateOps( self );
-		stg_profile_Func( "MultigridSolver_UpdateOps", MPI_Wtime() - wallTime);
-	//if( self->matrixChanged || rebuildOps || self->opsChanged || self->solversChanged ) {
-	if( self->mgData->matrixChanged || rebuildOps || self->opsChanged || self->solversChanged ) {
-		wallTime = MPI_Wtime();
-		MultigridSolver_UpdateMatrices( self );
-		stg_profile_Func( "MultigridSolver_UpdateMatrices", MPI_Wtime() - wallTime);
-		
-		wallTime = MPI_Wtime();
-		MultigridSolver_UpdateWorkVectors( self );
-		stg_profile_Func( "MultigridSolver_UpdateWorkVectors", MPI_Wtime() - wallTime);
-
-
-	}
-	self->solversChanged = False;
-	//self->matrixChanged = False;
-	self->mgData->matrixChanged = False;
-	self->opsChanged = False;
-}
-
-MGSolver_Status MultigridSolver_GetSolveStatus( void* matrixSolver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	MGSolver_Status		outerStatus;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	//MatrixSolver_Solve( self->outerSolver, self->curRHS, self->curSolution );
-	//outerStatus = MatrixSolver_GetSolveStatus( self->outerSolver );
-	KSPSolve( self->outerSolver->ksp, self->mgData->curRHS, self->mgData->curSolution );
-	outerStatus = _GetSolveStatus( self->outerSolver );
-
-	if( outerStatus == MGSolver_Status_ConvergedIterations || 
-	    outerStatus == MGSolver_Status_DivergedIterations || 
-	    outerStatus == MGSolver_Status_Iterating )
-	{
-		return MGSolver_Status_Iterating;
-	}
-	else if( outerStatus == MGSolver_Status_ConvergedRelative )
-		return MGSolver_Status_ConvergedRelative;
-	else
-		return outerStatus;
-}
-
-unsigned MultigridSolver_GetIterations( void* matrixSolver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	return self->curIt;
-}
-
-unsigned MultigridSolver_GetMaxIterations( void* matrixSolver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	return self->maxIts;
-}
-
-double MultigridSolver_GetResidualNorm( void* matrixSolver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	return _GetResidualNorm( self->outerSolver );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void MultigridSolver_SetLevels( void* matrixSolver, unsigned nLevels ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	unsigned		nProcs;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	MultigridSolver_DestructLevels( self );
-
-	self->nLevels = nLevels;
-	self->levels = AllocArray( MultigridSolver_Level, nLevels );
-	//MPI_Comm_size( self->comm, (int*)&nProcs );
-	MPI_Comm_size( self->mgData->comm, (int*)&nProcs );
-
-	for( l_i = 0; l_i < nLevels; l_i++ ) {
-		MultigridSolver_Level*	level = self->levels + l_i;
-
-		//level->downSolver = NULL;
-		level->downSolver = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
-		level->nDownIts = 1;
-		//level->upSolver = NULL;
-		level->upSolver = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
-		level->nUpIts = l_i ? 1 : 0;
-		level->nCycles = 1;
-
-		level->A = NULL;
-		level->R = NULL;
-		level->P = NULL;
-
-		level->workRHS = NULL;
-		level->workSol = NULL;
-	}
-}
-
-void MultigridSolver_SetRestriction( void* matrixSolver, unsigned levelInd, void* _R ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	MultigridSolver_Level*	level;
-	//Matrix*			R = (Matrix*)_R;
-	Mat			R = (Mat)_R;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( levelInd < self->nLevels && levelInd > 0 );
-	//assert( !R || Stg_CheckType( R, Matrix ) );
-
-	level = self->levels + levelInd;
-	if( level->R != R )
-		self->opsChanged = True;
-	//if( level->R )
-	//	Stg_Class_RemoveRef( level->R );
-	level->R = R;
-	//if( R )
-	//	Stg_Class_AddRef( R );
-}
-
-void MultigridSolver_SetProlongation( void* matrixSolver, unsigned levelInd, void* _P ) {
-	MultigridSolver*	self 	= (MultigridSolver*)matrixSolver;
-	MultigridSolver_Level*	level;
-	Mat			P	= (Mat)_P;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( levelInd < self->nLevels && levelInd > 0 );
-	//assert( !P || Stg_CheckType( P, Matrix ) );
-
-	level = self->levels + levelInd;
-	if( level->P != P )
-		self->opsChanged = True;
-	//if( level->P )
-	//	Stg_Class_RemoveRef( level->P );
-	if( level->P != PETSC_NULL )
-		MatDestroy( level->P );
-	level->P = P;
-	//if( P )
-	//	Stg_Class_AddRef( P );
-}
-
-void MultigridSolver_SetLevelDownSolver( void* matrixSolver, unsigned levelInd, void* solver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	MultigridSolver_Level*	level;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( levelInd < self->nLevels );
-	//assert( !solver || Stg_CheckType( solver, MatrixSolver ) );
-
-	level = self->levels + levelInd;
-	if( level->downSolver != solver )
-		self->solversChanged = True;
-	if( level->downSolver ) {
-	//	Stg_Class_RemoveRef( level->downSolver );
-		if( level->downSolver->ksp != PETSC_NULL )         KSPDestroy( level->downSolver->ksp );
-		if( level->downSolver->matrix != PETSC_NULL )      MatDestroy( level->downSolver->matrix );
-		if( level->downSolver->inversion != PETSC_NULL )   MatDestroy( level->downSolver->inversion );
-		if( level->downSolver->residual != PETSC_NULL )    VecDestroy( level->downSolver->residual );
-		if( level->downSolver->curRHS != PETSC_NULL )      VecDestroy( level->downSolver->curRHS );
-		if( level->downSolver->curSolution != PETSC_NULL ) VecDestroy( level->downSolver->curSolution );
-		free( level->downSolver );
-	}
-	level->downSolver = (MGSolver_PETScData*)solver;
-	//if( solver )
-	//	Stg_Class_AddRef( solver );
-}
-
-void MultigridSolver_SetLevelDownIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( level < self->nLevels );
-
-	self->levels[level].nDownIts = nIts;
-	self->solversChanged = True;
-}
-
-/* this function was applying to the down solver before - pretty sure this is a mistake */
-void MultigridSolver_SetLevelUpSolver( void* matrixSolver, unsigned levelInd, void* solver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	MultigridSolver_Level*	level;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( levelInd < self->nLevels && levelInd > 0 );
-
-	level = self->levels + levelInd;
-	if( level->upSolver != solver )
-		self->solversChanged = True;
-	if( level->upSolver ) {
-	//	Stg_Class_RemoveRef( level->downSolver );
-		if( level->upSolver->ksp != PETSC_NULL )         KSPDestroy( level->upSolver->ksp );
-		if( level->upSolver->matrix != PETSC_NULL )      MatDestroy( level->upSolver->matrix );
-		if( level->upSolver->inversion != PETSC_NULL )   MatDestroy( level->upSolver->inversion );
-		if( level->upSolver->residual != PETSC_NULL )    VecDestroy( level->upSolver->residual );
-		if( level->upSolver->curRHS != PETSC_NULL )      VecDestroy( level->upSolver->curRHS );
-		if( level->upSolver->curSolution != PETSC_NULL ) VecDestroy( level->upSolver->curSolution );
-		free( level->upSolver );
-	}
-	level->upSolver = (MGSolver_PETScData*)solver;
-	//if( solver )
-	//	Stg_Class_AddRef( solver );
-}
-
-void MultigridSolver_SetLevelUpIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( level < self->nLevels );
-	assert( level > 0 );
-
-	self->levels[level].nUpIts = nIts;
-	self->solversChanged = True;
-}
-
-void MultigridSolver_SetLevelCycles( void* matrixSolver, unsigned level, unsigned nCycles ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( level < self->nLevels );
-	assert( level > 0 );
-
-	self->levels[level].nCycles = nCycles;
-	self->solversChanged = True;
-}
-
-void MultigridSolver_SetAllDownSolver( void* matrixSolver, void* solver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	for( l_i = 1; l_i < self->nLevels; l_i++ )
-		MultigridSolver_SetLevelDownSolver( self, l_i, solver );
-}
-
-void MultigridSolver_SetAllDownIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	for( l_i = 1; l_i < self->nLevels; l_i++ )
-		MultigridSolver_SetLevelDownIterations( self, l_i, nIts );
-}
-
-void MultigridSolver_SetAllUpSolver( void* matrixSolver, void* solver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	for( l_i = 1; l_i < self->nLevels; l_i++ )
-		MultigridSolver_SetLevelUpSolver( self, l_i, solver );
-}
-
-void MultigridSolver_SetAllUpIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	for( l_i = 1; l_i < self->nLevels; l_i++ )
-		MultigridSolver_SetLevelUpIterations( self, l_i, nIts );
-}
-
-void MultigridSolver_SetAllSolver( void* matrixSolver, void* solver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self );
-
-	MultigridSolver_SetAllDownSolver( self, solver );
-	MultigridSolver_SetAllUpSolver( self, solver );
-}
-
-void MultigridSolver_SetCoarseSolver( void* matrixSolver, void* solver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self );
-
-	MultigridSolver_SetLevelDownSolver( self, 0, solver );
-}
-
-unsigned MultigridSolver_GetNumLevels( void* matrixSolver ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	return self->nLevels;
-}
-
-Mat MultigridSolver_GetRestriction( void* matrixSolver, unsigned level ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( level < self->nLevels && level > 0 );
-
-	return self->levels[level].R;
-}
-
-Mat MultigridSolver_GetProlongation( void* matrixSolver, unsigned level ) {
-	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-	assert( level < self->nLevels && level > 0 );
-
-	return self->levels[level].P;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-void MultigridSolver_RestrictMatrix( MultigridSolver* self, MultigridSolver_Level* level, Mat* dstMatrix ) {
-	Mat		srcMat;
-	PetscInt	nSrcRows, nSrcCols;
-	PetscInt	nRRows, nRCols;
-
-#if( PETSC_VERSION_MAJOR > 2 )
-	PetscInt dummy;
-#endif
-
-	PetscScalar	fillRatio;
-	MatInfo		mInfo;
-	PetscInt	nRowsA, nRowsC;
-	PetscScalar	nzA, nzP, nzC;
-
-	assert( self );
-	assert( level );
-	assert( dstMatrix );
-
-	srcMat = level->downSolver->matrix;
-	MatGetSize( srcMat, &nSrcRows, &nSrcCols );
-	MatGetSize( level->R, &nRRows, &nRCols );
-	if( nRCols == nSrcRows ) {
-		//Matrix_PAPt( srcMat, level->R, (void**)dstMatrix );
-		/* this function implementation was commented out in the PETScMatrix function - not sure if it should 
-		 * be implemented here?? */
-		MatGetInfo( srcMat, MAT_GLOBAL_SUM, &mInfo );
-#if( PETSC_VERSION_MAJOR <= 2 )
-		nRowsA = mInfo.rows_global;
-#else
-		MatGetSize( srcMat, &nRowsA, &dummy );
-#endif
-		nzA = mInfo.nz_used;
-		MatGetInfo( level->R, MAT_GLOBAL_SUM, &mInfo );
-#if( PETSC_VERSION_MAJOR <= 2 )
-		nRowsC = mInfo.columns_global;
-#else
-		MatGetSize( level->R, &dummy, &nRowsC );
-#endif
-		nzP = mInfo.nz_used;
-
-		nzC = ( nRowsC / nRowsA ) * nzA;
-		fillRatio = nzC / ( nzA + nzP );
-
-		/* this function doesn't exist! */
-		//MatPAPt( srcMat, level->R, MAT_REUSE_MATRIX, fillRatio, dstMatrix );
-	}
-	else {
-		//Matrix_PtAP( srcMat, level->R, (void**)dstMatrix );
-		if( dstMatrix )
-			MatPtAP( srcMat, level->R, MAT_REUSE_MATRIX, 1.0, dstMatrix );
-		else 
-			MatPtAP( srcMat, level->R, MAT_INITIAL_MATRIX, 1.0, dstMatrix );
-	}
-}
-
-//void MultigridSolver_LevelCycle( MultigridSolver* self, unsigned levelInd, Vector* rhs, Vector* solution ) {
-void MultigridSolver_LevelCycle( MultigridSolver* self, unsigned levelInd, Vec rhs, Vec solution ) {
-	MultigridSolver_Level*	level;
-
-	assert( self );
-	assert( levelInd < self->nLevels );
-
-	Stream_Indent( self->stream );
-	level = self->levels + levelInd;
-
-	if( level->nDownIts ) {
-		Journal_Printf( self->stream, "Down-solve on level %d... ", levelInd );
-		//MatrixSolver_Solve( level->downSolver, rhs, solution );
-		//Journal_Printf( self->stream, "residual: %.10lf\n", MatrixSolver_GetResidualNorm( level->downSolver ) );
-		KSPSolve( level->downSolver->ksp, rhs, solution );
-		Journal_Printf( self->stream, "residual: %.10lf\n", _GetResidualNorm( level->downSolver ) );
-	}
-
-	if( levelInd > 0 ) {
-		MultigridSolver_Level*	nextLevel;
-		unsigned		c_i;
-
-		nextLevel = self->levels + (levelInd - 1);
-		if( level->R == level->P )
-			//Matrix_TransposeMultiply( level->R, MatrixSolver_GetResidual( level->downSolver ), nextLevel->workRHS );
-			MatMultTranspose( level->R, _GetResidual( level->downSolver ), nextLevel->workRHS );
-		else
-			//Matrix_Multiply( level->R, MatrixSolver_GetResidual( level->downSolver ), nextLevel->workRHS );
-			MatMult( level->R, _GetResidual( level->downSolver ), nextLevel->workRHS );
-		for( c_i = 0; c_i < level->nCycles; c_i++ )
-			MultigridSolver_LevelCycle( self, levelInd - 1, nextLevel->workRHS, nextLevel->workSol );
-		//Matrix_MultiplyAdd( level->P, nextLevel->workSol, solution, solution );
-		MatMultAdd( level->P, nextLevel->workSol, solution, solution );
-	}
-
-	if( level->nUpIts ) {
-		Journal_Printf( self->stream, "Up-solve on level %d... ", levelInd );
-		//MatrixSolver_Solve( level->upSolver, rhs, solution );
-		//Journal_Printf( self->stream, "residual: %.10lf\n", MatrixSolver_GetResidualNorm( level->upSolver ) );
-		KSPSolve( level->upSolver->ksp, rhs, solution );
-		Journal_Printf( self->stream, "residual: %.10lf\n", _GetResidualNorm( level->upSolver ) );
-	}
-
-	Stream_UnIndent( self->stream );
-}
-
-void MultigridSolver_UpdateSolvers( MultigridSolver* self ) {
-	MultigridSolver_Level*	level;
-	unsigned		l_i;
-	PetscInt		nDownIts, nUpIts;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	for( l_i = self->nLevels - 1; l_i < self->nLevels; l_i-- ) {
-		level = self->levels + l_i;
-
-		if( l_i > 0 ) {
-			KSPGetTolerances( level->downSolver->ksp, PETSC_NULL, PETSC_NULL, PETSC_NULL, &nDownIts );
-			KSPGetTolerances( level->upSolver->ksp, PETSC_NULL, PETSC_NULL, PETSC_NULL, &nUpIts );
-			if( /*MatrixSolver_GetMaxIterations( level->downSolver )*/nDownIts != level->nDownIts )
-				//MatrixSolver_SetMaxIterations( level->downSolver, level->nDownIts );
-				KSPSetTolerances( level->downSolver->ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nDownIts );
-			if( /*MatrixSolver_GetMaxIterations( level->upSolver )*/nUpIts != level->nUpIts )
-				//MatrixSolver_SetMaxIterations( level->upSolver, level->nUpIts );
-				KSPSetTolerances( level->upSolver->ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nUpIts );
-
-			if( l_i == self->nLevels - 1 )
-				//MatrixSolver_SetUseInitialSolution( level->downSolver, True );
-				KSPSetInitialGuessNonzero( level->downSolver->ksp, (PetscTruth)True );
-			else
-				//MatrixSolver_SetUseInitialSolution( level->downSolver, False );
-				KSPSetInitialGuessNonzero( level->downSolver->ksp, (PetscTruth)False );
-			//MatrixSolver_SetUseInitialSolution( level->upSolver, True );
-			KSPSetInitialGuessNonzero( level->upSolver->ksp, (PetscTruth)True );
-		}
-	}
-
-	//FreeObject( self->outerSolver );
-	self->outerSolver = MultigridSolver_CreateOuterSolver( self, self->mgData->matrix );
-	//MatrixSolver_SetRelativeTolerance( self->outerSolver, self->relTol );
-	KSPSetTolerances( self->outerSolver->ksp, self->relTol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
-}
-
-void MultigridSolver_UpdateMatrices( MultigridSolver* self ) {
-	MultigridSolver_Level*	level;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	for( l_i = self->nLevels - 1; l_i < self->nLevels; l_i-- ) {
-		level = self->levels + l_i;
-
-		Journal_Printf( self->stream, "Updating matrix on level %d...\n", l_i );
-
-		if( l_i < self->nLevels - 1 ) {
-			//Matrix*	mat;
-			Mat	mat;
-
-			if( level->downSolver )
-				//mat = MatrixSolver_GetMatrix( level->downSolver );
-				mat = level->downSolver->matrix; 
-			else
-				mat = NULL;
-			//if( mat ) {
-			if( mat != PETSC_NULL ) {
-				//KillObject( mat );
-				MatDestroy( mat );
-			}
-			MultigridSolver_RestrictMatrix( self, self->levels + l_i + 1, &mat );
-			level->A = mat;
-			if( level->downSolver ) {
-				//MatrixSolver_SetMatrix( level->downSolver, mat );
-				level->downSolver->matrix = mat;
-				KSPSetOperators( level->downSolver->ksp, mat, mat, DIFFERENT_NONZERO_PATTERN );
-			}
-			else {
-				if( l_i > 0 )
-					level->downSolver = MultigridSolver_CreateSmoother( self, mat );
-				else
-					level->downSolver = MultigridSolver_CreateCoarseSolver( self, mat );
-			}
-			if( l_i > 0 ) {
-				if( level->upSolver ) {
-					//MatrixSolver_SetMatrix( level->upSolver, mat );
-					level->upSolver->matrix = mat;
-					KSPSetOperators( level->upSolver->ksp, mat, mat, DIFFERENT_NONZERO_PATTERN );
-				}
-				else
-					level->upSolver = MultigridSolver_CreateSmoother( self, mat );
-			}
-		}
-		else {
-			level->A = self->mgData->matrix;
-			if( level->downSolver ) {
-				//MatrixSolver_SetMatrix( level->downSolver, self->matrix );
-				level->downSolver->matrix = self->mgData->matrix;
-				KSPSetOperators( level->downSolver->ksp, self->mgData->matrix, self->mgData->matrix, DIFFERENT_NONZERO_PATTERN );
-			}
-			else {
-				if( l_i > 0 )
-					level->downSolver = MultigridSolver_CreateSmoother( self, self->mgData->matrix );
-				else
-					level->downSolver = MultigridSolver_CreateCoarseSolver( self, self->mgData->matrix );
-			}
-			if( l_i > 0 ) {
-				if( level->upSolver ) {
-					//MatrixSolver_SetMatrix( level->upSolver, self->matrix );
-					level->upSolver->matrix = self->mgData->matrix;
-					KSPSetOperators( level->upSolver->ksp, self->mgData->matrix, self->mgData->matrix, DIFFERENT_NONZERO_PATTERN );
-				}
-				else
-					level->upSolver = MultigridSolver_CreateSmoother( self, self->mgData->matrix );
-			}
-		}
-
-		Journal_Printf( self->stream, "done\n" );
-	}
-
-	MultigridSolver_UpdateSolvers( self );
-	//MatrixSolver_SetMatrix( self->outerSolver, self->matrix );
-	self->outerSolver->matrix = self->mgData->matrix;
-	KSPSetOperators( self->outerSolver->ksp, self->mgData->matrix, self->mgData->matrix, DIFFERENT_NONZERO_PATTERN );
-}
-
-void MultigridSolver_UpdateOps( MultigridSolver* self ) {
-	MultigridSolver_Level*	level;
-	//Matrix			**pOps, **rOps;
-	Mat			*pOps, *rOps;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	MGOpGenerator_Generate( self->opGen, &pOps, &rOps );
-	for( l_i = 1; l_i < self->nLevels; l_i++ ) {
-		level = self->levels + l_i;
-
-		//if( !level->P ) {
-		if( level->P == PETSC_NULL ) {
-			level->P = pOps[l_i];
-			//Stg_Class_AddRef( level->P );
-		}
-		else
-			MatDestroy( pOps[l_i] );
-			//Stg_Class_RemoveRef( pOps[l_i] );
-
-
-		//if( !level->R ) {
-		if( level->R == PETSC_NULL ) {
-			level->R = rOps[l_i];
-			//Stg_Class_AddRef( level->R );
-		}
-		else
-			MatDestroy( rOps[l_i] );
-			//Stg_Class_RemoveRef( rOps[l_i] );
-	}
-
-	FreeArray( pOps );
-	FreeArray( rOps );
-}
-
-void MultigridSolver_UpdateWorkVectors( MultigridSolver* self ) {
-	MultigridSolver_Level*	level;
-	//unsigned		rowSize, colSize;
-	PetscInt		rowSize, colSize, vecSize;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	for( l_i = 0; l_i < self->nLevels - 1; l_i++ ) {
-		level = self->levels + l_i;
-
-		//Matrix_GetLocalSize( MatrixSolver_GetMatrix( level->downSolver ), &rowSize, &colSize );
-		MatGetLocalSize( level->downSolver->matrix, &rowSize, &colSize );
-
-		VecGetLocalSize( level->workSol, &vecSize );
-
-		//if( !level->workSol || Vector_GetLocalSize( level->workSol ) != rowSize ) {
-		if( !level->workSol || vecSize != rowSize ) {
-			//if( level->workSol )
-			//	Stg_Class_RemoveRef( level->workSol );
-			//Vector_Duplicate( self->curSolution, (void**)&level->workSol );
-			//Vector_SetLocalSize( level->workSol, rowSize );
-			if( level->workSol != PETSC_NULL )
-				VecDestroy( level->workSol );
-			VecCreate( self->mgData->comm, &level->workSol );
-			VecSetSizes( level->workSol, rowSize, PETSC_DECIDE );
-			VecSetFromOptions( level->workSol );
-#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
-			VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES );
-#elif( PETSC_VERSION_MAJOR >= 3 )
-			VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
-#endif
-		}
-
-		VecGetLocalSize( level->workRHS, &vecSize );
-
-		if( !level->workRHS || /*Vector_GetLocalSize( level->workRHS )*/vecSize != rowSize ) {
-			//if( level->workRHS )
-			//	Stg_Class_RemoveRef( level->workRHS );
-			//Vector_Duplicate( self->curSolution, (void**)&level->workRHS );
-			//Vector_SetLocalSize( level->workRHS, rowSize );
-			if( level->workRHS != PETSC_NULL )
-				VecDestroy( level->workRHS );
-			VecCreate( self->mgData->comm, &level->workRHS );
-			VecSetSizes( level->workRHS, rowSize, PETSC_DECIDE );
-			VecSetFromOptions( level->workRHS );
-#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
-			VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES );
-#elif( PETSC_VERSION_MAJOR >= 3 )
-			VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
-#endif
-		}
-	}
-}
-
-MGSolver_PETScData* MultigridSolver_CreateOuterSolver( MultigridSolver* self, Mat matrix ) {
-	//MatrixSolver*	outerSolver;
-  MGSolver_PETScData* 	outerSolver = (MGSolver_PETScData*)malloc( sizeof(MGSolver_PETScData) );
-	PC			pc;
-
-	/*
-	outerSolver = (MatrixSolver*)PETScMatrixSolver_New( "" );
-	PETScMatrixSolver_SetKSPType( outerSolver, PETScMatrixSolver_KSPType_Richardson );
-	PETScMatrixSolver_SetPCType( outerSolver, PETScMatrixSolver_PCType_SOR );
-	PETScMatrixSolver_SetMatrix( outerSolver, matrix );
-	PETScMatrixSolver_SetMaxIterations( outerSolver, 3 );
-	PETScMatrixSolver_SetUseInitialSolution( outerSolver, True );
-	PETScMatrixSolver_SetNormType( outerSolver, PETScMatrixSolver_NormType_Preconditioned );
-	*/
-	KSPCreate( MPI_COMM_WORLD, &outerSolver->ksp );
-	KSPSetType( outerSolver->ksp, KSPRICHARDSON );
-	KSPGetPC( outerSolver->ksp, &pc );
-	PCSetType( pc, PCSOR );
-	if( outerSolver->matrix != PETSC_NULL )
-		MatDestroy( outerSolver->matrix );
-	outerSolver->matrix = matrix;
-	KSPSetOperators( outerSolver->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN );
-	KSPSetTolerances( outerSolver->ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, (PetscInt)3 );
-	KSPSetInitialGuessNonzero( outerSolver->ksp, (PetscTruth)True );
-	KSPSetNormType( outerSolver->ksp, (KSPNormType)MultigridSolver_NormType_Preconditioned );
-
-	return outerSolver;
-}
-
-MGSolver_PETScData* MultigridSolver_CreateSmoother( MultigridSolver* self, Mat matrix ) {
-	//MatrixSolver*	smoother;
-  MGSolver_PETScData* smoother = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
-	//unsigned	nBlocks;
-	//KSP*		ksps;
-	PC		pc;
-	//PetscErrorCode	ec;
-
-	/*
-	smoother = (MatrixSolver*)PETScMatrixSolver_New( "" );
-	PETScMatrixSolver_SetKSPType( smoother, 
-				      PETScMatrixSolver_KSPType_Richardson );
-	PETScMatrixSolver_SetPCType( smoother, 
-				     PETScMatrixSolver_PCType_SOR );
-	MatrixSolver_SetMatrix( smoother, matrix );
-	*/
-	KSPCreate( MPI_COMM_WORLD, &smoother->ksp );
-	KSPSetType( smoother->ksp, KSPRICHARDSON );
-	KSPGetPC( smoother->ksp, &pc );
-	PCSetType( pc, PCSOR );
-	if( smoother->matrix != PETSC_NULL )
-		MatDestroy( smoother->matrix );
-	smoother->matrix = matrix;
-	KSPSetOperators( smoother->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN );
-
-	return smoother;
-}
-
-MGSolver_PETScData* MultigridSolver_CreateCoarseSolver( MultigridSolver* self, Mat matrix ) {
-	//MatrixSolver*	coarseSolver;
-	MGSolver_PETScData* courseSolver;
-	unsigned	nProcs;
-	PC		pc;
-
-	MPI_Comm_size( self->mgData->comm, (int*)&nProcs );
-
-	/*
-	coarseSolver = (MatrixSolver*)PETScMatrixSolver_New( "" );
-	PETScMatrixSolver_SetKSPType( coarseSolver, 
-				      PETScMatrixSolver_KSPType_PreOnly );
-	if( nProcs == 1 ) {
-		PETScMatrixSolver_SetPCType( coarseSolver, 
-					     PETScMatrixSolver_PCType_LU );
-	}
-	else {
-		PETScMatrixSolver_SetPCType( coarseSolver, 
-					     PETScMatrixSolver_PCType_RedundantLU );
-	}
-	MatrixSolver_SetMatrix( coarseSolver, matrix );
-	*/
-	KSPCreate( MPI_COMM_WORLD, &courseSolver->ksp );
-	KSPSetType( courseSolver->ksp, KSPPREONLY );
-	KSPGetPC( courseSolver->ksp, &pc );
-	if( nProcs == 1 )
-		PCSetType( pc, PCLU );
-	else {
-		PCSetType( pc, PCREDUNDANT );
-		PCRedundantGetPC( pc, &pc );
-		PCSetType( pc, PCLU );
-	}
-	if( courseSolver->matrix != PETSC_NULL )
-		MatDestroy( courseSolver->matrix );
-	courseSolver->matrix = matrix;
-	KSPSetOperators( courseSolver->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN );
-
-	return courseSolver;
-}
-
-void MultigridSolver_Destruct( MultigridSolver* self ) {
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	MultigridSolver_DestructLevels( self );
-	KillObject( self->opGen );
-}
-
-void MultigridSolver_DestructLevels( MultigridSolver* self ) {
-	unsigned	l_i;
-
-	assert( self && Stg_CheckType( self, MultigridSolver ) );
-
-	for( l_i = 0; l_i < self->nLevels; l_i++ ) {
-		MultigridSolver_Level*	level = self->levels + l_i;
-
-		if( level->downSolver ) {
-			//Stg_Class_RemoveRef( MatrixSolver_GetMatrix( level->downSolver ) );
-			//Stg_Class_RemoveRef( level->downSolver );
-			if( level->downSolver->ksp != PETSC_NULL )         KSPDestroy( level->downSolver->ksp );
-			if( level->downSolver->matrix != PETSC_NULL )      MatDestroy( level->downSolver->matrix );
-			if( level->downSolver->inversion != PETSC_NULL )   MatDestroy( level->downSolver->inversion );
-			if( level->downSolver->residual != PETSC_NULL )    VecDestroy( level->downSolver->residual );
-			if( level->downSolver->curRHS != PETSC_NULL )      VecDestroy( level->downSolver->curRHS );
-			if( level->downSolver->curSolution != PETSC_NULL ) VecDestroy( level->downSolver->curSolution );
-			free( level->downSolver );
-		}
-		if( level->upSolver ) {
-			//Stg_Class_RemoveRef( MatrixSolver_GetMatrix( level->upSolver ) );
-			//Stg_Class_RemoveRef( level->upSolver );
-			if( level->upSolver->ksp != PETSC_NULL )         KSPDestroy( level->upSolver->ksp );
-			if( level->upSolver->matrix != PETSC_NULL )      MatDestroy( level->upSolver->matrix );
-			if( level->upSolver->inversion != PETSC_NULL )   MatDestroy( level->upSolver->inversion );
-			if( level->upSolver->residual != PETSC_NULL )    VecDestroy( level->upSolver->residual );
-			if( level->upSolver->curRHS != PETSC_NULL )      VecDestroy( level->upSolver->curRHS );
-			if( level->upSolver->curSolution != PETSC_NULL ) VecDestroy( level->upSolver->curSolution );
-			free( level->upSolver );
-		}
-		if( level->R != PETSC_NULL )
-			//Stg_Class_RemoveRef( level->R );
-			MatDestroy( level->R );
-		if( level->P != PETSC_NULL )
-			//Stg_Class_RemoveRef( level->P );
-			MatDestroy( level->P );
-		if( level->workRHS != PETSC_NULL )
-			//Stg_Class_RemoveRef( level->workRHS );
-			VecDestroy( level->workRHS );
-		if( level->workSol != PETSC_NULL )
-			//Stg_Class_RemoveRef( level->workSol );
-			VecDestroy( level->workSol );
-	}
-
-	KillArray( self->levels );
-	self->nLevels = 0;
-	self->solversChanged = True;
-	self->opsChanged = True;
-
-	/* Temporary. */
-	//KillObject( self->outerSolver );
-	if( self->outerSolver->ksp )         KSPDestroy( self->outerSolver->ksp );
-	if( self->outerSolver->matrix )      MatDestroy( self->outerSolver->matrix );
-	if( self->outerSolver->inversion )   MatDestroy( self->outerSolver->inversion );
-	if( self->outerSolver->residual )    VecDestroy( self->outerSolver->residual );
-	if( self->outerSolver->curRHS )      VecDestroy( self->outerSolver->curRHS );
-	if( self->outerSolver->curSolution ) VecDestroy( self->outerSolver->curSolution );
-	free( self->outerSolver );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/MultigridSolver.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/MultigridSolver.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,1233 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: MultigridSolver.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+
+#include "SystemSetup.h"
+
+
+/* Textual name of this class */
+const Type MultigridSolver_Type = "MultigridSolver";
+
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+MultigridSolver* MultigridSolver_New( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                    _sizeOfSelf = sizeof(MultigridSolver);
+	Type                                                            type = MultigridSolver_Type;
+	Stg_Class_DeleteFunction*                                    _delete = _MultigridSolver_Delete;
+	Stg_Class_PrintFunction*                                      _print = _MultigridSolver_Print;
+	Stg_Class_CopyFunction*                                        _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*        _defaultConstructor = (void* (*)(Name))_MultigridSolver_New;
+	Stg_Component_ConstructFunction*                          _construct = _MultigridSolver_AssignFromXML;
+	Stg_Component_BuildFunction*                                  _build = _MultigridSolver_Build;
+	Stg_Component_InitialiseFunction*                        _initialise = _MultigridSolver_Initialise;
+	Stg_Component_ExecuteFunction*                              _execute = _MultigridSolver_Execute;
+	Stg_Component_DestroyFunction*                              _destroy = _MultigridSolver_Destroy;
+	AllocationType                                    nameAllocationType = NON_GLOBAL;
+	MGSolver_SetCommFunc*                                    setCommFunc = MultigridSolver_SetComm;
+	MGSolver_SetMatrixFunc*                                setMatrixFunc = MultigridSolver_SetMatrix;
+	MGSolver_SetMaxIterationsFunc*                  setMaxIterationsFunc = MultigridSolver_SetMaxIterations;
+	MGSolver_SetRelativeToleranceFunc*          setRelativeToleranceFunc = MultigridSolver_SetRelativeTolerance;
+	MGSolver_SetAbsoluteToleranceFunc*          setAbsoluteToleranceFunc = MultigridSolver_SetAbsoluteTolerance;
+	MGSolver_SetUseInitialSolutionFunc*        setUseInitialSolutionFunc = MultigridSolver_SetUseInitialSolution;
+	MGSolver_SolveFunc*                                        solveFunc = MultigridSolver_Solve;
+	MGSolver_SetupFunc*                                        setupFunc = MultigridSolver_Setup;
+	MGSolver_GetSolveStatusFunc*                      getSolveStatusFunc = MultigridSolver_GetSolveStatus;
+	MGSolver_GetIterationsFunc*                        getIterationsFunc = MultigridSolver_GetIterations;
+	MGSolver_GetMaxIterationsFunc*                  getMaxIterationsFunc = MultigridSolver_GetMaxIterations;
+	MGSolver_GetResidualNormFunc*                    getResidualNormFunc = MultigridSolver_GetResidualNorm;
+
+	return _MultigridSolver_New(  MULTIGRIDSOLVER_PASSARGS  );
+}
+
+MultigridSolver* _MultigridSolver_New(  MULTIGRIDSOLVER_DEFARGS  ) {
+	MultigridSolver*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(MultigridSolver) );
+
+	self = (MultigridSolver*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+
+	/* function assignments previously in the MatrixSolver_New func */
+	self->setCommFunc = setCommFunc;
+	self->setMatrixFunc = setMatrixFunc;
+	self->setMaxIterationsFunc = setMaxIterationsFunc;
+	self->setRelativeToleranceFunc = setRelativeToleranceFunc;
+	self->setAbsoluteToleranceFunc = setAbsoluteToleranceFunc;
+	self->setUseInitialSolutionFunc = setUseInitialSolutionFunc;
+
+	self->solveFunc = solveFunc;
+	self->setupFunc = setupFunc;
+
+	self->getSolveStatusFunc = getSolveStatusFunc;
+	self->getIterationsFunc = getIterationsFunc;
+	self->getMaxIterationsFunc = getMaxIterationsFunc;
+	self->getResidualNormFunc = getResidualNormFunc;
+
+	/* Virtual info */
+
+	/* MultigridSolver info */
+	_MultigridSolver_Init( self );
+
+	return self;
+}
+
+void _MultigridSolver_Init( MultigridSolver* self ) {
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	/* these initialisations previously done in the MatrixSolver_Init func */
+	self->mgData = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
+
+	self->mgData->comm = MPI_COMM_WORLD;
+	KSPCreate( MPI_COMM_WORLD, &self->mgData->ksp );
+	self->mgData->matrix = PETSC_NULL;
+	self->mgData->inversion = PETSC_NULL;
+	self->mgData->residual = PETSC_NULL;
+	self->mgData->expiredResidual = True;
+	self->mgData->matrixChanged = True;
+
+	self->mgData->curRHS = PETSC_NULL;
+	self->mgData->curSolution = PETSC_NULL;
+	/* end of old MatrixSolver_Init initialisations */
+
+	self->nLevels = 0;
+	self->levels = NULL;
+	self->opGen = NULL;
+	self->solversChanged = True;
+	self->opsChanged = True;
+
+	self->curIt = 0;
+	self->maxIts = 500;
+	self->relTol = 1e-5;
+	self->rnorm = 0.0;
+	self->useInitial = False;
+	//self->outerSolver = NULL;
+	self->outerSolver = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
+	self->outerSolver->ksp = PETSC_NULL;
+	self->outerSolver->matrix = PETSC_NULL;
+	self->outerSolver->inversion = PETSC_NULL;
+	self->outerSolver->residual = PETSC_NULL;
+	self->outerSolver->curRHS = PETSC_NULL;
+	self->outerSolver->curSolution = PETSC_NULL;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _MultigridSolver_Delete( void* matrixSolver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	MultigridSolver_Destruct( self );
+
+	/* Delete the parent. */
+	_Stg_Component_Delete( self );
+}
+
+void _MultigridSolver_Print( void* matrixSolver, Stream* stream ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	
+	/* Set the Journal for printing informations */
+	Stream* matrixSolverStream;
+	matrixSolverStream = Journal_Register( InfoStream_Type, (Name)"MultigridSolverStream"  );
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	/* Print parent */
+	Journal_Printf( stream, "MultigridSolver (ptr): (%p)\n", self );
+	_Stg_Component_Print( self, stream );
+}
+
+void _MultigridSolver_AssignFromXML( void* matrixSolver, Stg_ComponentFactory* cf, void* data ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	unsigned		nLevels;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( cf );
+
+	nLevels = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"levels", 1  );
+	MultigridSolver_SetLevels( self, nLevels );
+	self->opGen = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"opGenerator", MGOpGenerator, True, data  );
+	MGOpGenerator_SetMatrixSolver( self->opGen, self );
+	MGOpGenerator_SetNumLevels( self->opGen, nLevels );
+}
+
+void _MultigridSolver_Build( void* matrixSolver, void* data ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	self->stream = Journal_Register( InfoStream_Type, (Name)"general" );
+	if( self->opGen  )
+		Stg_Component_Build( self->opGen, data, False );
+}
+
+void _MultigridSolver_Initialise( void* matrixSolver, void* data ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	if( self->opGen )
+		Stg_Component_Initialise( self->opGen, data, False );
+}
+
+void _MultigridSolver_Execute( void* matrixSolver, void* data ) {
+}
+
+void _MultigridSolver_Destroy( void* matrixSolver, void* data ) {
+}
+
+/* copied from the PETScMatrixSolver class, has been depreciated */
+void MultigridSolver_SetComm( void* matrixSolver, MPI_Comm comm ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	self->mgData->comm = comm;
+
+	if( self->mgData->ksp != PETSC_NULL )
+		KSPDestroy( self->mgData->ksp );
+	KSPCreate( comm, &self->mgData->ksp );
+}
+
+/* copied from the PETScMatrixSolver class, has been depreciated */
+void MultigridSolver_SetMatrix( void* matrixSolver, void* _matrix ) {
+	MultigridSolver*	self 	= (MultigridSolver*)matrixSolver;
+	Mat			matrix	= (Mat)_matrix;
+
+	self->mgData->matrix = matrix;
+	KSPSetOperators( self->mgData->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN );
+}
+
+void MultigridSolver_SetMaxIterations( void* matrixSolver, unsigned nIterations ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	self->maxIts = nIterations;
+}
+
+void MultigridSolver_SetRelativeTolerance( void* matrixSolver, double tolerance ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	self->relTol = tolerance;
+	self->solversChanged = True;
+}
+
+void MultigridSolver_SetAbsoluteTolerance( void* matrixSolver, double tolerance ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	//MatrixSolver_SetAbsoluteTolerance( self->outerSolver, tolerance );
+	KSPSetTolerances( self->outerSolver->ksp, PETSC_DEFAULT, tolerance, PETSC_DEFAULT, PETSC_DEFAULT );
+
+	self->solversChanged = True;
+}
+
+void MultigridSolver_SetUseInitialSolution( void* matrixSolver, Bool state ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	self->useInitial = state;
+}
+
+/* these functions were associated with the PETScMatrixSolver class, before it was
+ * depreciated */
+Vec _GetResidual( MGSolver_PETScData* mgData ) {
+	if( mgData->expiredResidual ) {
+		VecDuplicate( mgData->curSolution, &mgData->residual );	
+		VecSetFromOptions( mgData->residual );
+#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
+		VecSetOption( mgData->residual, VEC_IGNORE_NEGATIVE_INDICES );
+#elif( PETSC_VERSION_MAJOR >= 3 )
+		VecSetOption( mgData->residual, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
+#endif
+		MatMult( mgData->matrix, mgData->curSolution, mgData->residual );
+		VecAYPX( mgData->residual, -1.0, mgData->curRHS );
+
+		mgData->expiredResidual = False;
+	}
+
+	return mgData->residual;
+}
+
+double _GetResidualNorm( MGSolver_PETScData* mgData ) {
+	PC			pc;
+	const KSPType		kspType;
+	const PCType		pcType;
+	PetscScalar		rnorm;
+	PetscErrorCode		ec;
+
+	ec = KSPGetType( mgData->ksp, &kspType );
+	CheckPETScError( ec );
+	ec = KSPGetPC( mgData->ksp, &pc );
+	CheckPETScError( ec );
+	ec = PCGetType( pc, &pcType );
+	CheckPETScError( ec );
+
+	if( !strcmp( kspType, KSPRICHARDSON ) && !strcmp( pcType, PCSOR ) ) {
+		Vec	residual;
+
+		//residual = MatrixSolver_GetResidual( mgData );
+		//rnorm = (PetscScalar)Vector_L2Norm( residual );
+		residual = _GetResidual( mgData );
+		VecNorm( residual, NORM_2, &rnorm );
+	}
+	else {
+		ec = KSPGetResidualNorm( mgData->ksp, &rnorm );
+		CheckPETScError( ec );
+	}
+
+	return (double)rnorm;
+}
+
+#define MultigridSolver_NormType_Preconditioned 1
+
+MGSolver_Status _GetSolveStatus( MGSolver_PETScData* mgData ) {
+	PC			pc;
+	const KSPType		kspType;
+	const PCType		pcType;
+	KSPConvergedReason	reason;
+	PetscErrorCode		ec;
+
+	ec = KSPGetType( mgData->ksp, &kspType );
+	CheckPETScError( ec );
+	ec = KSPGetPC( mgData->ksp, &pc );
+	CheckPETScError( ec );
+	ec = PCGetType( pc, &pcType );
+	CheckPETScError( ec );
+
+	if( !strcmp( kspType, KSPRICHARDSON ) && !strcmp( pcType, PCSOR ) ) {
+		double		rnorm;
+		PetscInt	curIt;
+
+		//rnorm = PETScMatrixSolver_GetResidualNorm( self );
+		//curIt = PETScMatrixSolver_GetIterations( self );
+		rnorm = _GetResidualNorm( mgData );
+		KSPGetIterationNumber( mgData->ksp, &curIt );
+		//PETScMatrixSolver_SetNormType( self, MultigridSolver_NormType_Preconditioned );
+		KSPSetNormType( mgData->ksp, (KSPNormType)MultigridSolver_NormType_Preconditioned );
+		ec = KSPDefaultConverged( mgData->ksp, curIt, (PetscScalar)rnorm, &reason, PETSC_NULL );
+		CheckPETScError( ec );
+	}
+	else {
+		ec = KSPGetConvergedReason( mgData->ksp, &reason );
+		CheckPETScError( ec );
+	}
+
+	return (MGSolver_Status)reason;
+}
+
+/* end of functions formerly defined in the PETScMatrixSolver class */
+
+void MultigridSolver_Solve( void* matrixSolver, void* _rhs, void* _solution ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	Vec			rhs = (Vec)_rhs;
+	Vec			solution = (Vec)_solution;
+	double wallTime;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	//assert( rhs && Stg_CheckType( rhs, Vector ) );
+	//assert( solution && Stg_CheckType( solution, Vector ) );
+
+	Journal_Printf( self->stream, "MultigridSolver: Starting solve ...\n" );
+	Stream_Indent( self->stream );
+
+	if( !self->useInitial ) {
+		Journal_Printf( self->stream, "Zeroing initial solution\n" );
+		//Vector_Zero( solution );
+		VecSet( solution, 0.0 );
+	}
+	else
+		Journal_Printf( self->stream, "Keeping initial solution\n" );
+
+	wallTime = MPI_Wtime();
+	MultigridSolver_Setup( self, rhs, solution );
+	stg_profile_Func( "MultigridSolver_Setup", MPI_Wtime() - wallTime);
+	self->curIt = 0;
+	//while( MatrixSolver_GetSolveStatus( self ) == MultigridSolver_Status_Iterating && self->curIt < self->maxIts ) {
+	while( _GetSolveStatus( self->mgData ) == MGSolver_Status_Iterating && self->curIt < self->maxIts ) {
+		Journal_Printf( self->stream, "Iteration %d: residual %.10lf\n", 
+				//self->curIt, MatrixSolver_GetResidualNorm( self->outerSolver ) );
+				self->curIt, _GetResidualNorm( self->outerSolver ) );
+		MultigridSolver_LevelCycle( self, self->nLevels - 1, rhs, solution );
+		self->curIt++;
+	}
+	Journal_Printf( self->stream, "Iteration %d: residual %.10lf\n", 
+			//self->curIt, MatrixSolver_GetResidualNorm( self->outerSolver ) );
+			self->curIt, _GetResidualNorm( self->outerSolver ) );
+
+	Stream_UnIndent( self->stream );
+	Journal_Printf( self->stream, "done.\n" );
+}
+
+void MultigridSolver_Setup( void* matrixSolver, void* rhs, void* solution ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	Bool			rebuildOps;
+	double wallTime;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	//_MatrixSolver_Setup( self, rhs, solution );
+	self->mgData->curRHS = (struct _p_Vec*)rhs;
+	self->mgData->curSolution = (struct _p_Vec*)solution;
+	self->mgData->expiredResidual = True;
+
+	/* Need to rebuild the operators? */
+	if( self->opGen )
+		rebuildOps = MGOpGenerator_HasExpired( self->opGen );
+	else
+		rebuildOps = False;
+	if( !rebuildOps ) {
+		unsigned		l_i;
+
+		for( l_i = 1; l_i < self->nLevels; l_i++ ) {
+			if( !MultigridSolver_GetRestriction( self, l_i ) || !MultigridSolver_GetProlongation( self, l_i ) ) {
+				rebuildOps = True;
+				break;
+			}
+		}
+	}
+
+	if( rebuildOps )
+		wallTime = MPI_Wtime();
+		MultigridSolver_UpdateOps( self );
+		stg_profile_Func( "MultigridSolver_UpdateOps", MPI_Wtime() - wallTime);
+	//if( self->matrixChanged || rebuildOps || self->opsChanged || self->solversChanged ) {
+	if( self->mgData->matrixChanged || rebuildOps || self->opsChanged || self->solversChanged ) {
+		wallTime = MPI_Wtime();
+		MultigridSolver_UpdateMatrices( self );
+		stg_profile_Func( "MultigridSolver_UpdateMatrices", MPI_Wtime() - wallTime);
+		
+		wallTime = MPI_Wtime();
+		MultigridSolver_UpdateWorkVectors( self );
+		stg_profile_Func( "MultigridSolver_UpdateWorkVectors", MPI_Wtime() - wallTime);
+
+
+	}
+	self->solversChanged = False;
+	//self->matrixChanged = False;
+	self->mgData->matrixChanged = False;
+	self->opsChanged = False;
+}
+
+MGSolver_Status MultigridSolver_GetSolveStatus( void* matrixSolver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	MGSolver_Status		outerStatus;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	//MatrixSolver_Solve( self->outerSolver, self->curRHS, self->curSolution );
+	//outerStatus = MatrixSolver_GetSolveStatus( self->outerSolver );
+	KSPSolve( self->outerSolver->ksp, self->mgData->curRHS, self->mgData->curSolution );
+	outerStatus = _GetSolveStatus( self->outerSolver );
+
+	if( outerStatus == MGSolver_Status_ConvergedIterations || 
+	    outerStatus == MGSolver_Status_DivergedIterations || 
+	    outerStatus == MGSolver_Status_Iterating )
+	{
+		return MGSolver_Status_Iterating;
+	}
+	else if( outerStatus == MGSolver_Status_ConvergedRelative )
+		return MGSolver_Status_ConvergedRelative;
+	else
+		return outerStatus;
+}
+
+unsigned MultigridSolver_GetIterations( void* matrixSolver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	return self->curIt;
+}
+
+unsigned MultigridSolver_GetMaxIterations( void* matrixSolver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	return self->maxIts;
+}
+
+double MultigridSolver_GetResidualNorm( void* matrixSolver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	return _GetResidualNorm( self->outerSolver );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void MultigridSolver_SetLevels( void* matrixSolver, unsigned nLevels ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	unsigned		nProcs;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	MultigridSolver_DestructLevels( self );
+
+	self->nLevels = nLevels;
+	self->levels = AllocArray( MultigridSolver_Level, nLevels );
+	//MPI_Comm_size( self->comm, (int*)&nProcs );
+	MPI_Comm_size( self->mgData->comm, (int*)&nProcs );
+
+	for( l_i = 0; l_i < nLevels; l_i++ ) {
+		MultigridSolver_Level*	level = self->levels + l_i;
+
+		//level->downSolver = NULL;
+		level->downSolver = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
+		level->nDownIts = 1;
+		//level->upSolver = NULL;
+		level->upSolver = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
+		level->nUpIts = l_i ? 1 : 0;
+		level->nCycles = 1;
+
+		level->A = NULL;
+		level->R = NULL;
+		level->P = NULL;
+
+		level->workRHS = NULL;
+		level->workSol = NULL;
+	}
+}
+
+void MultigridSolver_SetRestriction( void* matrixSolver, unsigned levelInd, void* _R ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	MultigridSolver_Level*	level;
+	//Matrix*			R = (Matrix*)_R;
+	Mat			R = (Mat)_R;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( levelInd < self->nLevels && levelInd > 0 );
+	//assert( !R || Stg_CheckType( R, Matrix ) );
+
+	level = self->levels + levelInd;
+	if( level->R != R )
+		self->opsChanged = True;
+	//if( level->R )
+	//	Stg_Class_RemoveRef( level->R );
+	level->R = R;
+	//if( R )
+	//	Stg_Class_AddRef( R );
+}
+
+void MultigridSolver_SetProlongation( void* matrixSolver, unsigned levelInd, void* _P ) {
+	MultigridSolver*	self 	= (MultigridSolver*)matrixSolver;
+	MultigridSolver_Level*	level;
+	Mat			P	= (Mat)_P;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( levelInd < self->nLevels && levelInd > 0 );
+	//assert( !P || Stg_CheckType( P, Matrix ) );
+
+	level = self->levels + levelInd;
+	if( level->P != P )
+		self->opsChanged = True;
+	//if( level->P )
+	//	Stg_Class_RemoveRef( level->P );
+	if( level->P != PETSC_NULL )
+		MatDestroy( level->P );
+	level->P = P;
+	//if( P )
+	//	Stg_Class_AddRef( P );
+}
+
+void MultigridSolver_SetLevelDownSolver( void* matrixSolver, unsigned levelInd, void* solver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	MultigridSolver_Level*	level;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( levelInd < self->nLevels );
+	//assert( !solver || Stg_CheckType( solver, MatrixSolver ) );
+
+	level = self->levels + levelInd;
+	if( level->downSolver != solver )
+		self->solversChanged = True;
+	if( level->downSolver ) {
+	//	Stg_Class_RemoveRef( level->downSolver );
+		if( level->downSolver->ksp != PETSC_NULL )         KSPDestroy( level->downSolver->ksp );
+		if( level->downSolver->matrix != PETSC_NULL )      MatDestroy( level->downSolver->matrix );
+		if( level->downSolver->inversion != PETSC_NULL )   MatDestroy( level->downSolver->inversion );
+		if( level->downSolver->residual != PETSC_NULL )    VecDestroy( level->downSolver->residual );
+		if( level->downSolver->curRHS != PETSC_NULL )      VecDestroy( level->downSolver->curRHS );
+		if( level->downSolver->curSolution != PETSC_NULL ) VecDestroy( level->downSolver->curSolution );
+		free( level->downSolver );
+	}
+	level->downSolver = (MGSolver_PETScData*)solver;
+	//if( solver )
+	//	Stg_Class_AddRef( solver );
+}
+
+void MultigridSolver_SetLevelDownIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( level < self->nLevels );
+
+	self->levels[level].nDownIts = nIts;
+	self->solversChanged = True;
+}
+
+/* this function was applying to the down solver before - pretty sure this is a mistake */
+void MultigridSolver_SetLevelUpSolver( void* matrixSolver, unsigned levelInd, void* solver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	MultigridSolver_Level*	level;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( levelInd < self->nLevels && levelInd > 0 );
+
+	level = self->levels + levelInd;
+	if( level->upSolver != solver )
+		self->solversChanged = True;
+	if( level->upSolver ) {
+	//	Stg_Class_RemoveRef( level->downSolver );
+		if( level->upSolver->ksp != PETSC_NULL )         KSPDestroy( level->upSolver->ksp );
+		if( level->upSolver->matrix != PETSC_NULL )      MatDestroy( level->upSolver->matrix );
+		if( level->upSolver->inversion != PETSC_NULL )   MatDestroy( level->upSolver->inversion );
+		if( level->upSolver->residual != PETSC_NULL )    VecDestroy( level->upSolver->residual );
+		if( level->upSolver->curRHS != PETSC_NULL )      VecDestroy( level->upSolver->curRHS );
+		if( level->upSolver->curSolution != PETSC_NULL ) VecDestroy( level->upSolver->curSolution );
+		free( level->upSolver );
+	}
+	level->upSolver = (MGSolver_PETScData*)solver;
+	//if( solver )
+	//	Stg_Class_AddRef( solver );
+}
+
+void MultigridSolver_SetLevelUpIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( level < self->nLevels );
+	assert( level > 0 );
+
+	self->levels[level].nUpIts = nIts;
+	self->solversChanged = True;
+}
+
+void MultigridSolver_SetLevelCycles( void* matrixSolver, unsigned level, unsigned nCycles ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( level < self->nLevels );
+	assert( level > 0 );
+
+	self->levels[level].nCycles = nCycles;
+	self->solversChanged = True;
+}
+
+void MultigridSolver_SetAllDownSolver( void* matrixSolver, void* solver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	for( l_i = 1; l_i < self->nLevels; l_i++ )
+		MultigridSolver_SetLevelDownSolver( self, l_i, solver );
+}
+
+void MultigridSolver_SetAllDownIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	for( l_i = 1; l_i < self->nLevels; l_i++ )
+		MultigridSolver_SetLevelDownIterations( self, l_i, nIts );
+}
+
+void MultigridSolver_SetAllUpSolver( void* matrixSolver, void* solver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	for( l_i = 1; l_i < self->nLevels; l_i++ )
+		MultigridSolver_SetLevelUpSolver( self, l_i, solver );
+}
+
+void MultigridSolver_SetAllUpIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	for( l_i = 1; l_i < self->nLevels; l_i++ )
+		MultigridSolver_SetLevelUpIterations( self, l_i, nIts );
+}
+
+void MultigridSolver_SetAllSolver( void* matrixSolver, void* solver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self );
+
+	MultigridSolver_SetAllDownSolver( self, solver );
+	MultigridSolver_SetAllUpSolver( self, solver );
+}
+
+void MultigridSolver_SetCoarseSolver( void* matrixSolver, void* solver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self );
+
+	MultigridSolver_SetLevelDownSolver( self, 0, solver );
+}
+
+unsigned MultigridSolver_GetNumLevels( void* matrixSolver ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	return self->nLevels;
+}
+
+Mat MultigridSolver_GetRestriction( void* matrixSolver, unsigned level ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( level < self->nLevels && level > 0 );
+
+	return self->levels[level].R;
+}
+
+Mat MultigridSolver_GetProlongation( void* matrixSolver, unsigned level ) {
+	MultigridSolver*	self = (MultigridSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+	assert( level < self->nLevels && level > 0 );
+
+	return self->levels[level].P;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+void MultigridSolver_RestrictMatrix( MultigridSolver* self, MultigridSolver_Level* level, Mat* dstMatrix ) {
+	Mat		srcMat;
+	PetscInt	nSrcRows, nSrcCols;
+	PetscInt	nRRows, nRCols;
+
+#if( PETSC_VERSION_MAJOR > 2 )
+	PetscInt dummy;
+#endif
+
+	PetscScalar	fillRatio;
+	MatInfo		mInfo;
+	PetscInt	nRowsA, nRowsC;
+	PetscScalar	nzA, nzP, nzC;
+
+	assert( self );
+	assert( level );
+	assert( dstMatrix );
+
+	srcMat = level->downSolver->matrix;
+	MatGetSize( srcMat, &nSrcRows, &nSrcCols );
+	MatGetSize( level->R, &nRRows, &nRCols );
+	if( nRCols == nSrcRows ) {
+		//Matrix_PAPt( srcMat, level->R, (void**)dstMatrix );
+		/* this function implementation was commented out in the PETScMatrix function - not sure if it should 
+		 * be implemented here?? */
+		MatGetInfo( srcMat, MAT_GLOBAL_SUM, &mInfo );
+#if( PETSC_VERSION_MAJOR <= 2 )
+		nRowsA = mInfo.rows_global;
+#else
+		MatGetSize( srcMat, &nRowsA, &dummy );
+#endif
+		nzA = mInfo.nz_used;
+		MatGetInfo( level->R, MAT_GLOBAL_SUM, &mInfo );
+#if( PETSC_VERSION_MAJOR <= 2 )
+		nRowsC = mInfo.columns_global;
+#else
+		MatGetSize( level->R, &dummy, &nRowsC );
+#endif
+		nzP = mInfo.nz_used;
+
+		nzC = ( nRowsC / nRowsA ) * nzA;
+		fillRatio = nzC / ( nzA + nzP );
+
+		/* this function doesn't exist! */
+		//MatPAPt( srcMat, level->R, MAT_REUSE_MATRIX, fillRatio, dstMatrix );
+	}
+	else {
+		//Matrix_PtAP( srcMat, level->R, (void**)dstMatrix );
+		if( dstMatrix )
+			MatPtAP( srcMat, level->R, MAT_REUSE_MATRIX, 1.0, dstMatrix );
+		else 
+			MatPtAP( srcMat, level->R, MAT_INITIAL_MATRIX, 1.0, dstMatrix );
+	}
+}
+
+//void MultigridSolver_LevelCycle( MultigridSolver* self, unsigned levelInd, Vector* rhs, Vector* solution ) {
+void MultigridSolver_LevelCycle( MultigridSolver* self, unsigned levelInd, Vec rhs, Vec solution ) {
+	MultigridSolver_Level*	level;
+
+	assert( self );
+	assert( levelInd < self->nLevels );
+
+	Stream_Indent( self->stream );
+	level = self->levels + levelInd;
+
+	if( level->nDownIts ) {
+		Journal_Printf( self->stream, "Down-solve on level %d... ", levelInd );
+		//MatrixSolver_Solve( level->downSolver, rhs, solution );
+		//Journal_Printf( self->stream, "residual: %.10lf\n", MatrixSolver_GetResidualNorm( level->downSolver ) );
+		KSPSolve( level->downSolver->ksp, rhs, solution );
+		Journal_Printf( self->stream, "residual: %.10lf\n", _GetResidualNorm( level->downSolver ) );
+	}
+
+	if( levelInd > 0 ) {
+		MultigridSolver_Level*	nextLevel;
+		unsigned		c_i;
+
+		nextLevel = self->levels + (levelInd - 1);
+		if( level->R == level->P )
+			//Matrix_TransposeMultiply( level->R, MatrixSolver_GetResidual( level->downSolver ), nextLevel->workRHS );
+			MatMultTranspose( level->R, _GetResidual( level->downSolver ), nextLevel->workRHS );
+		else
+			//Matrix_Multiply( level->R, MatrixSolver_GetResidual( level->downSolver ), nextLevel->workRHS );
+			MatMult( level->R, _GetResidual( level->downSolver ), nextLevel->workRHS );
+		for( c_i = 0; c_i < level->nCycles; c_i++ )
+			MultigridSolver_LevelCycle( self, levelInd - 1, nextLevel->workRHS, nextLevel->workSol );
+		//Matrix_MultiplyAdd( level->P, nextLevel->workSol, solution, solution );
+		MatMultAdd( level->P, nextLevel->workSol, solution, solution );
+	}
+
+	if( level->nUpIts ) {
+		Journal_Printf( self->stream, "Up-solve on level %d... ", levelInd );
+		//MatrixSolver_Solve( level->upSolver, rhs, solution );
+		//Journal_Printf( self->stream, "residual: %.10lf\n", MatrixSolver_GetResidualNorm( level->upSolver ) );
+		KSPSolve( level->upSolver->ksp, rhs, solution );
+		Journal_Printf( self->stream, "residual: %.10lf\n", _GetResidualNorm( level->upSolver ) );
+	}
+
+	Stream_UnIndent( self->stream );
+}
+
+void MultigridSolver_UpdateSolvers( MultigridSolver* self ) {
+	MultigridSolver_Level*	level;
+	unsigned		l_i;
+	PetscInt		nDownIts, nUpIts;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	for( l_i = self->nLevels - 1; l_i < self->nLevels; l_i-- ) {
+		level = self->levels + l_i;
+
+		if( l_i > 0 ) {
+			KSPGetTolerances( level->downSolver->ksp, PETSC_NULL, PETSC_NULL, PETSC_NULL, &nDownIts );
+			KSPGetTolerances( level->upSolver->ksp, PETSC_NULL, PETSC_NULL, PETSC_NULL, &nUpIts );
+			if( /*MatrixSolver_GetMaxIterations( level->downSolver )*/nDownIts != level->nDownIts )
+				//MatrixSolver_SetMaxIterations( level->downSolver, level->nDownIts );
+				KSPSetTolerances( level->downSolver->ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nDownIts );
+			if( /*MatrixSolver_GetMaxIterations( level->upSolver )*/nUpIts != level->nUpIts )
+				//MatrixSolver_SetMaxIterations( level->upSolver, level->nUpIts );
+				KSPSetTolerances( level->upSolver->ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nUpIts );
+
+			if( l_i == self->nLevels - 1 )
+				//MatrixSolver_SetUseInitialSolution( level->downSolver, True );
+				KSPSetInitialGuessNonzero( level->downSolver->ksp, (PetscTruth)True );
+			else
+				//MatrixSolver_SetUseInitialSolution( level->downSolver, False );
+				KSPSetInitialGuessNonzero( level->downSolver->ksp, (PetscTruth)False );
+			//MatrixSolver_SetUseInitialSolution( level->upSolver, True );
+			KSPSetInitialGuessNonzero( level->upSolver->ksp, (PetscTruth)True );
+		}
+	}
+
+	//FreeObject( self->outerSolver );
+	self->outerSolver = MultigridSolver_CreateOuterSolver( self, self->mgData->matrix );
+	//MatrixSolver_SetRelativeTolerance( self->outerSolver, self->relTol );
+	KSPSetTolerances( self->outerSolver->ksp, self->relTol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT );
+}
+
+void MultigridSolver_UpdateMatrices( MultigridSolver* self ) {
+	MultigridSolver_Level*	level;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	for( l_i = self->nLevels - 1; l_i < self->nLevels; l_i-- ) {
+		level = self->levels + l_i;
+
+		Journal_Printf( self->stream, "Updating matrix on level %d...\n", l_i );
+
+		if( l_i < self->nLevels - 1 ) {
+			//Matrix*	mat;
+			Mat	mat;
+
+			if( level->downSolver )
+				//mat = MatrixSolver_GetMatrix( level->downSolver );
+				mat = level->downSolver->matrix; 
+			else
+				mat = NULL;
+			//if( mat ) {
+			if( mat != PETSC_NULL ) {
+				//KillObject( mat );
+				MatDestroy( mat );
+			}
+			MultigridSolver_RestrictMatrix( self, self->levels + l_i + 1, &mat );
+			level->A = mat;
+			if( level->downSolver ) {
+				//MatrixSolver_SetMatrix( level->downSolver, mat );
+				level->downSolver->matrix = mat;
+				KSPSetOperators( level->downSolver->ksp, mat, mat, DIFFERENT_NONZERO_PATTERN );
+			}
+			else {
+				if( l_i > 0 )
+					level->downSolver = MultigridSolver_CreateSmoother( self, mat );
+				else
+					level->downSolver = MultigridSolver_CreateCoarseSolver( self, mat );
+			}
+			if( l_i > 0 ) {
+				if( level->upSolver ) {
+					//MatrixSolver_SetMatrix( level->upSolver, mat );
+					level->upSolver->matrix = mat;
+					KSPSetOperators( level->upSolver->ksp, mat, mat, DIFFERENT_NONZERO_PATTERN );
+				}
+				else
+					level->upSolver = MultigridSolver_CreateSmoother( self, mat );
+			}
+		}
+		else {
+			level->A = self->mgData->matrix;
+			if( level->downSolver ) {
+				//MatrixSolver_SetMatrix( level->downSolver, self->matrix );
+				level->downSolver->matrix = self->mgData->matrix;
+				KSPSetOperators( level->downSolver->ksp, self->mgData->matrix, self->mgData->matrix, DIFFERENT_NONZERO_PATTERN );
+			}
+			else {
+				if( l_i > 0 )
+					level->downSolver = MultigridSolver_CreateSmoother( self, self->mgData->matrix );
+				else
+					level->downSolver = MultigridSolver_CreateCoarseSolver( self, self->mgData->matrix );
+			}
+			if( l_i > 0 ) {
+				if( level->upSolver ) {
+					//MatrixSolver_SetMatrix( level->upSolver, self->matrix );
+					level->upSolver->matrix = self->mgData->matrix;
+					KSPSetOperators( level->upSolver->ksp, self->mgData->matrix, self->mgData->matrix, DIFFERENT_NONZERO_PATTERN );
+				}
+				else
+					level->upSolver = MultigridSolver_CreateSmoother( self, self->mgData->matrix );
+			}
+		}
+
+		Journal_Printf( self->stream, "done\n" );
+	}
+
+	MultigridSolver_UpdateSolvers( self );
+	//MatrixSolver_SetMatrix( self->outerSolver, self->matrix );
+	self->outerSolver->matrix = self->mgData->matrix;
+	KSPSetOperators( self->outerSolver->ksp, self->mgData->matrix, self->mgData->matrix, DIFFERENT_NONZERO_PATTERN );
+}
+
+void MultigridSolver_UpdateOps( MultigridSolver* self ) {
+	MultigridSolver_Level*	level;
+	//Matrix			**pOps, **rOps;
+	Mat			*pOps, *rOps;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	MGOpGenerator_Generate( self->opGen, &pOps, &rOps );
+	for( l_i = 1; l_i < self->nLevels; l_i++ ) {
+		level = self->levels + l_i;
+
+		//if( !level->P ) {
+		if( level->P == PETSC_NULL ) {
+			level->P = pOps[l_i];
+			//Stg_Class_AddRef( level->P );
+		}
+		else
+			MatDestroy( pOps[l_i] );
+			//Stg_Class_RemoveRef( pOps[l_i] );
+
+
+		//if( !level->R ) {
+		if( level->R == PETSC_NULL ) {
+			level->R = rOps[l_i];
+			//Stg_Class_AddRef( level->R );
+		}
+		else
+			MatDestroy( rOps[l_i] );
+			//Stg_Class_RemoveRef( rOps[l_i] );
+	}
+
+	FreeArray( pOps );
+	FreeArray( rOps );
+}
+
+void MultigridSolver_UpdateWorkVectors( MultigridSolver* self ) {
+	MultigridSolver_Level*	level;
+	//unsigned		rowSize, colSize;
+	PetscInt		rowSize, colSize, vecSize;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	for( l_i = 0; l_i < self->nLevels - 1; l_i++ ) {
+		level = self->levels + l_i;
+
+		//Matrix_GetLocalSize( MatrixSolver_GetMatrix( level->downSolver ), &rowSize, &colSize );
+		MatGetLocalSize( level->downSolver->matrix, &rowSize, &colSize );
+
+		VecGetLocalSize( level->workSol, &vecSize );
+
+		//if( !level->workSol || Vector_GetLocalSize( level->workSol ) != rowSize ) {
+		if( !level->workSol || vecSize != rowSize ) {
+			//if( level->workSol )
+			//	Stg_Class_RemoveRef( level->workSol );
+			//Vector_Duplicate( self->curSolution, (void**)&level->workSol );
+			//Vector_SetLocalSize( level->workSol, rowSize );
+			if( level->workSol != PETSC_NULL )
+				VecDestroy( level->workSol );
+			VecCreate( self->mgData->comm, &level->workSol );
+			VecSetSizes( level->workSol, rowSize, PETSC_DECIDE );
+			VecSetFromOptions( level->workSol );
+#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
+			VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES );
+#elif( PETSC_VERSION_MAJOR >= 3 )
+			VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
+#endif
+		}
+
+		VecGetLocalSize( level->workRHS, &vecSize );
+
+		if( !level->workRHS || /*Vector_GetLocalSize( level->workRHS )*/vecSize != rowSize ) {
+			//if( level->workRHS )
+			//	Stg_Class_RemoveRef( level->workRHS );
+			//Vector_Duplicate( self->curSolution, (void**)&level->workRHS );
+			//Vector_SetLocalSize( level->workRHS, rowSize );
+			if( level->workRHS != PETSC_NULL )
+				VecDestroy( level->workRHS );
+			VecCreate( self->mgData->comm, &level->workRHS );
+			VecSetSizes( level->workRHS, rowSize, PETSC_DECIDE );
+			VecSetFromOptions( level->workRHS );
+#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
+			VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES );
+#elif( PETSC_VERSION_MAJOR >= 3 )
+			VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
+#endif
+		}
+	}
+}
+
+MGSolver_PETScData* MultigridSolver_CreateOuterSolver( MultigridSolver* self, Mat matrix ) {
+	//MatrixSolver*	outerSolver;
+  MGSolver_PETScData* 	outerSolver = (MGSolver_PETScData*)malloc( sizeof(MGSolver_PETScData) );
+	PC			pc;
+
+	/*
+	outerSolver = (MatrixSolver*)PETScMatrixSolver_New( "" );
+	PETScMatrixSolver_SetKSPType( outerSolver, PETScMatrixSolver_KSPType_Richardson );
+	PETScMatrixSolver_SetPCType( outerSolver, PETScMatrixSolver_PCType_SOR );
+	PETScMatrixSolver_SetMatrix( outerSolver, matrix );
+	PETScMatrixSolver_SetMaxIterations( outerSolver, 3 );
+	PETScMatrixSolver_SetUseInitialSolution( outerSolver, True );
+	PETScMatrixSolver_SetNormType( outerSolver, PETScMatrixSolver_NormType_Preconditioned );
+	*/
+	KSPCreate( MPI_COMM_WORLD, &outerSolver->ksp );
+	KSPSetType( outerSolver->ksp, KSPRICHARDSON );
+	KSPGetPC( outerSolver->ksp, &pc );
+	PCSetType( pc, PCSOR );
+	if( outerSolver->matrix != PETSC_NULL )
+		MatDestroy( outerSolver->matrix );
+	outerSolver->matrix = matrix;
+	KSPSetOperators( outerSolver->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN );
+	KSPSetTolerances( outerSolver->ksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, (PetscInt)3 );
+	KSPSetInitialGuessNonzero( outerSolver->ksp, (PetscTruth)True );
+	KSPSetNormType( outerSolver->ksp, (KSPNormType)MultigridSolver_NormType_Preconditioned );
+
+	return outerSolver;
+}
+
+MGSolver_PETScData* MultigridSolver_CreateSmoother( MultigridSolver* self, Mat matrix ) {
+	//MatrixSolver*	smoother;
+  MGSolver_PETScData* smoother = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
+	//unsigned	nBlocks;
+	//KSP*		ksps;
+	PC		pc;
+	//PetscErrorCode	ec;
+
+	/*
+	smoother = (MatrixSolver*)PETScMatrixSolver_New( "" );
+	PETScMatrixSolver_SetKSPType( smoother, 
+				      PETScMatrixSolver_KSPType_Richardson );
+	PETScMatrixSolver_SetPCType( smoother, 
+				     PETScMatrixSolver_PCType_SOR );
+	MatrixSolver_SetMatrix( smoother, matrix );
+	*/
+	KSPCreate( MPI_COMM_WORLD, &smoother->ksp );
+	KSPSetType( smoother->ksp, KSPRICHARDSON );
+	KSPGetPC( smoother->ksp, &pc );
+	PCSetType( pc, PCSOR );
+	if( smoother->matrix != PETSC_NULL )
+		MatDestroy( smoother->matrix );
+	smoother->matrix = matrix;
+	KSPSetOperators( smoother->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN );
+
+	return smoother;
+}
+
+MGSolver_PETScData* MultigridSolver_CreateCoarseSolver( MultigridSolver* self, Mat matrix ) {
+	//MatrixSolver*	coarseSolver;
+	MGSolver_PETScData* courseSolver;
+	unsigned	nProcs;
+	PC		pc;
+
+	MPI_Comm_size( self->mgData->comm, (int*)&nProcs );
+
+	/*
+	coarseSolver = (MatrixSolver*)PETScMatrixSolver_New( "" );
+	PETScMatrixSolver_SetKSPType( coarseSolver, 
+				      PETScMatrixSolver_KSPType_PreOnly );
+	if( nProcs == 1 ) {
+		PETScMatrixSolver_SetPCType( coarseSolver, 
+					     PETScMatrixSolver_PCType_LU );
+	}
+	else {
+		PETScMatrixSolver_SetPCType( coarseSolver, 
+					     PETScMatrixSolver_PCType_RedundantLU );
+	}
+	MatrixSolver_SetMatrix( coarseSolver, matrix );
+	*/
+	KSPCreate( MPI_COMM_WORLD, &courseSolver->ksp );
+	KSPSetType( courseSolver->ksp, KSPPREONLY );
+	KSPGetPC( courseSolver->ksp, &pc );
+	if( nProcs == 1 )
+		PCSetType( pc, PCLU );
+	else {
+		PCSetType( pc, PCREDUNDANT );
+		PCRedundantGetPC( pc, &pc );
+		PCSetType( pc, PCLU );
+	}
+	if( courseSolver->matrix != PETSC_NULL )
+		MatDestroy( courseSolver->matrix );
+	courseSolver->matrix = matrix;
+	KSPSetOperators( courseSolver->ksp, matrix, matrix, DIFFERENT_NONZERO_PATTERN );
+
+	return courseSolver;
+}
+
+void MultigridSolver_Destruct( MultigridSolver* self ) {
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	MultigridSolver_DestructLevels( self );
+	KillObject( self->opGen );
+}
+
+void MultigridSolver_DestructLevels( MultigridSolver* self ) {
+	unsigned	l_i;
+
+	assert( self && Stg_CheckType( self, MultigridSolver ) );
+
+	for( l_i = 0; l_i < self->nLevels; l_i++ ) {
+		MultigridSolver_Level*	level = self->levels + l_i;
+
+		if( level->downSolver ) {
+			//Stg_Class_RemoveRef( MatrixSolver_GetMatrix( level->downSolver ) );
+			//Stg_Class_RemoveRef( level->downSolver );
+			if( level->downSolver->ksp != PETSC_NULL )         KSPDestroy( level->downSolver->ksp );
+			if( level->downSolver->matrix != PETSC_NULL )      MatDestroy( level->downSolver->matrix );
+			if( level->downSolver->inversion != PETSC_NULL )   MatDestroy( level->downSolver->inversion );
+			if( level->downSolver->residual != PETSC_NULL )    VecDestroy( level->downSolver->residual );
+			if( level->downSolver->curRHS != PETSC_NULL )      VecDestroy( level->downSolver->curRHS );
+			if( level->downSolver->curSolution != PETSC_NULL ) VecDestroy( level->downSolver->curSolution );
+			free( level->downSolver );
+		}
+		if( level->upSolver ) {
+			//Stg_Class_RemoveRef( MatrixSolver_GetMatrix( level->upSolver ) );
+			//Stg_Class_RemoveRef( level->upSolver );
+			if( level->upSolver->ksp != PETSC_NULL )         KSPDestroy( level->upSolver->ksp );
+			if( level->upSolver->matrix != PETSC_NULL )      MatDestroy( level->upSolver->matrix );
+			if( level->upSolver->inversion != PETSC_NULL )   MatDestroy( level->upSolver->inversion );
+			if( level->upSolver->residual != PETSC_NULL )    VecDestroy( level->upSolver->residual );
+			if( level->upSolver->curRHS != PETSC_NULL )      VecDestroy( level->upSolver->curRHS );
+			if( level->upSolver->curSolution != PETSC_NULL ) VecDestroy( level->upSolver->curSolution );
+			free( level->upSolver );
+		}
+		if( level->R != PETSC_NULL )
+			//Stg_Class_RemoveRef( level->R );
+			MatDestroy( level->R );
+		if( level->P != PETSC_NULL )
+			//Stg_Class_RemoveRef( level->P );
+			MatDestroy( level->P );
+		if( level->workRHS != PETSC_NULL )
+			//Stg_Class_RemoveRef( level->workRHS );
+			VecDestroy( level->workRHS );
+		if( level->workSol != PETSC_NULL )
+			//Stg_Class_RemoveRef( level->workSol );
+			VecDestroy( level->workSol );
+	}
+
+	KillArray( self->levels );
+	self->nLevels = 0;
+	self->solversChanged = True;
+	self->opsChanged = True;
+
+	/* Temporary. */
+	//KillObject( self->outerSolver );
+	if( self->outerSolver->ksp )         KSPDestroy( self->outerSolver->ksp );
+	if( self->outerSolver->matrix )      MatDestroy( self->outerSolver->matrix );
+	if( self->outerSolver->inversion )   MatDestroy( self->outerSolver->inversion );
+	if( self->outerSolver->residual )    VecDestroy( self->outerSolver->residual );
+	if( self->outerSolver->curRHS )      VecDestroy( self->outerSolver->curRHS );
+	if( self->outerSolver->curSolution ) VecDestroy( self->outerSolver->curSolution );
+	free( self->outerSolver );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/PETScMGSolver.c
--- a/SLE/SystemSetup/src/PETScMGSolver.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,764 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: PETScMGSolver.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-
-#include "SystemSetup.h"
-
-
-/* Textual name of this class */
-const Type PETScMGSolver_Type = "PETScMGSolver";
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-PETScMGSolver* PETScMGSolver_New( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                    _sizeOfSelf = sizeof(PETScMGSolver);
-	Type                                                            type = PETScMGSolver_Type;
-	Stg_Class_DeleteFunction*                                    _delete = _PETScMGSolver_Delete;
-	Stg_Class_PrintFunction*                                      _print = _PETScMGSolver_Print;
-	Stg_Class_CopyFunction*                                        _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*        _defaultConstructor = (void* (*)(Name))_PETScMGSolver_New;
-	Stg_Component_ConstructFunction*                          _construct = _PETScMGSolver_AssignFromXML;
-	Stg_Component_BuildFunction*                                  _build = _PETScMGSolver_Build;
-	Stg_Component_InitialiseFunction*                        _initialise = _PETScMGSolver_Initialise;
-	Stg_Component_ExecuteFunction*                              _execute = _PETScMGSolver_Execute;
-	Stg_Component_DestroyFunction*                              _destroy = _PETScMGSolver_Destroy;
-	AllocationType                                    nameAllocationType = NON_GLOBAL;
-	MGSolver_SetCommFunc*                                    setCommFunc = PETScMGSolver_SetComm;
-	MGSolver_SetMatrixFunc*                                setMatrixFunc = NULL;
-	MGSolver_SetMaxIterationsFunc*                  setMaxIterationsFunc = NULL;
-	MGSolver_SetRelativeToleranceFunc*          setRelativeToleranceFunc = NULL;
-	MGSolver_SetAbsoluteToleranceFunc*          setAbsoluteToleranceFunc = NULL;
-	MGSolver_SetUseInitialSolutionFunc*        setUseInitialSolutionFunc = NULL;
-	MGSolver_SolveFunc*                                        solveFunc = NULL;
-	MGSolver_SetupFunc*                                        setupFunc = PETScMGSolver_Setup;
-	MGSolver_GetSolveStatusFunc*                      getSolveStatusFunc = NULL;
-	MGSolver_GetIterationsFunc*                        getIterationsFunc = NULL;
-	MGSolver_GetMaxIterationsFunc*                  getMaxIterationsFunc = NULL;
-	MGSolver_GetResidualNormFunc*                    getResidualNormFunc = NULL;
-
-	return _PETScMGSolver_New(  PETSCMGSOLVER_PASSARGS  );
-}
-
-PETScMGSolver* _PETScMGSolver_New(  PETSCMGSOLVER_DEFARGS  ) {
-	PETScMGSolver*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(PETScMGSolver) );
-	//self = (PETScMGSolver*)_PETScMatrixSolver_New(  STG_COMPONENT_PASSARGS  );
-	self = (PETScMGSolver*)_Stg_Component_New( STG_COMPONENT_PASSARGS );
-
-	/* Virtual info */
-	/* from the depreciated MatrixSolver_New func */
-	self->setCommFunc = setCommFunc;
-	self->setMatrixFunc = setMatrixFunc;
-	self->setMaxIterationsFunc = setMaxIterationsFunc;
-	self->setRelativeToleranceFunc = setRelativeToleranceFunc;
-	self->setAbsoluteToleranceFunc = setAbsoluteToleranceFunc;
-	self->setUseInitialSolutionFunc = setUseInitialSolutionFunc;
-
-	self->solveFunc = solveFunc;
-	self->setupFunc = setupFunc;
-
-	self->getSolveStatusFunc = getSolveStatusFunc;
-	self->getIterationsFunc = getIterationsFunc;
-	self->getMaxIterationsFunc = getMaxIterationsFunc;
-	self->getResidualNormFunc = getResidualNormFunc;
-
-	/* PETScMGSolver info */
-	_PETScMGSolver_Init( self );
-
-	return self;
-}
-
-void _PETScMGSolver_Init( PETScMGSolver* self ) {
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	self->mgData = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
-
-	/* from the depreciated MatrixSolver_Init func */
-	self->mgData->comm = MPI_COMM_WORLD;
-	KSPCreate( MPI_COMM_WORLD, &self->mgData->ksp );
-	self->mgData->matrix = PETSC_NULL;
-	self->mgData->inversion = PETSC_NULL;
-	self->mgData->residual = PETSC_NULL;
-	self->mgData->expiredResidual = True;
-	self->mgData->matrixChanged = True;
-        self->mgData->optionsReady = False;
-
-	self->mgData->curRHS = PETSC_NULL;
-	self->mgData->curSolution = PETSC_NULL;
-	/* end of MatrixSolver_Init stuff */
-
-	self->nLevels = 0;
-	self->levels = NULL;
-	self->opGen = NULL;
-	self->solversChanged = True;
-	self->opsChanged = True;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _PETScMGSolver_Delete( void* matrixSolver ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	PETScMGSolver_Destruct( self );
-
-	/* Delete the parent. */
-	//_PETScMatrixSolver_Delete( self );
-	_Stg_Component_Delete( self );
-}
-
-void _PETScMGSolver_Print( void* matrixSolver, Stream* stream ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-	
-	/* Set the Journal for printing informations */
-	Stream* matrixSolverStream;
-	matrixSolverStream = Journal_Register( InfoStream_Type, (Name)"PETScMGSolverStream"  );
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	/* Print parent */
-	Journal_Printf( stream, "PETScMGSolver (ptr): (%p)\n", self );
-	//_PETScMatrixSolver_Print( self, stream );
-	_Stg_Component_Print( self, stream );
-}
-
-void _PETScMGSolver_AssignFromXML( void* matrixSolver, Stg_ComponentFactory* cf, void* data ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-	Bool		pure;
-	unsigned	nLevels;
-	unsigned	nCycles;
-	unsigned	nDownIts, nUpIts;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-	assert( cf );
-
-	//_PETScMatrixSolver_AssignFromXML( self, cf, data );
-
-	pure = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"pure", False  );
-	nLevels = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"levels", 1  );
-	nCycles = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"cycles", 1  );
-	nDownIts = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"downIterations", 1  );
-	nUpIts = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"upIterations", 1  );
-
-	self->pure = pure;
-	PETScMGSolver_SetLevels( self, nLevels );
-	PETScMGSolver_SetLevelCycles( self, nLevels - 1, nCycles );
-	PETScMGSolver_SetAllDownIterations( self, nDownIts );
-	PETScMGSolver_SetAllUpIterations( self, nUpIts );
-
-	self->opGen = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"opGenerator", MGOpGenerator, True, data  );
-	MGOpGenerator_SetMatrixSolver( self->opGen, self );
-	MGOpGenerator_SetNumLevels( self->opGen, nLevels );
-}
-
-void _PETScMGSolver_Build( void* matrixSolver, void* data ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	if( self->opGen )
-		Stg_Component_Build( self->opGen, data, False );
-}
-
-void _PETScMGSolver_Initialise( void* matrixSolver, void* data ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	if( self->opGen )
-		Stg_Component_Initialise( self->opGen, data, False );
-}
-
-void _PETScMGSolver_Execute( void* matrixSolver, void* data ) {
-}
-
-void _PETScMGSolver_Destroy( void* matrixSolver, void* data ) {
-}
-
-void PETScMGSolver_SetComm( void* matrixSolver, MPI_Comm comm ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-	PC		pc;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	//PETScMatrixSolver_SetComm( self, comm );
-	self->mgData->comm = comm;
-	if( self->mgData->ksp )
-		KSPDestroy( self->mgData->ksp );
-	KSPCreate( comm, &self->mgData->ksp );
-
-	if( self->pure )
-		//PETScMatrixSolver_SetKSPType( self, PETScMatrixSolver_KSPType_Richardson );
-		KSPSetType( self->mgData->ksp, KSPRICHARDSON );	
-	else
-		//PETScMatrixSolver_SetKSPType( self, PETScMatrixSolver_KSPType_FGMRes );
-		KSPSetType( self->mgData->ksp, KSPFGMRES );
-	//PETScMatrixSolver_SetPCType( self, PETScMatrixSolver_PCType_Multigrid );
-	KSPGetPC( self->mgData->ksp, &pc );
-	PCSetType( pc, PCMG );
-}
-
-void PETScMGSolver_Setup( void* matrixSolver, void* rhs, void* solution ) { 
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-	Bool		rebuildOps;
-	double          wallTime;
-	PetscErrorCode  ec;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	wallTime = MPI_Wtime();
-		
-	//_MatrixSolver_Setup( self, rhs, solution );
-	self->mgData->curRHS = (struct _p_Vec*)rhs;
-	self->mgData->curSolution = (struct _p_Vec*)solution;
-	self->mgData->expiredResidual = True;
-
-   	PetscPrintf( PETSC_COMM_WORLD, "_MatrixSolver_Setup %g\n", MPI_Wtime() - wallTime);
-
-
-	if( self->opGen )
-		rebuildOps = MGOpGenerator_HasExpired( self->opGen );
-	else
-		rebuildOps = False;
-	if( !rebuildOps ) {
-		unsigned		l_i;
-
-		for( l_i = 1; l_i < self->nLevels; l_i++ ) {
-			if( !self->levels[l_i].R || !self->levels[l_i].P ) {
-				rebuildOps = True;
-				break;
-			}
-		}
-	}
-
-	if( self->solversChanged || rebuildOps || self->opsChanged ) {
-		wallTime = MPI_Wtime();
-		PETScMGSolver_UpdateSolvers( self );
-        stg_profile_Func( "PETScMGSolver_UpdateSolvers", MPI_Wtime() - wallTime);
-	   	PetscPrintf( PETSC_COMM_WORLD, "PETScMGSolver_UpdateSolvers %g\n", MPI_Wtime() - wallTime);
-	}
-	if( rebuildOps ) {
-		wallTime = MPI_Wtime();
-		PETScMGSolver_UpdateOps( self );
-		stg_profile_Func( "PETScMGSolver_UpdateOps", MPI_Wtime() - wallTime);
-		PetscPrintf( PETSC_COMM_WORLD,  "PETScMGSolver_UpdateOps %g\n", MPI_Wtime() - wallTime);
-
-	}
-	//if( self->matrixChanged || self->solversChanged || rebuildOps || self->opsChanged ) {
-	if( self->mgData->matrixChanged || self->solversChanged || rebuildOps || self->opsChanged ) {
-		wallTime = MPI_Wtime();
-		PETScMGSolver_UpdateMatrices( self );
-		PETScMGSolver_UpdateWorkVectors( self );
-		stg_profile_Func( "PETScMGSolver_UpdateMats-WorkVecs", MPI_Wtime() - wallTime); 
-		PetscPrintf( PETSC_COMM_WORLD, "PETScMGSolver_UpdateMats-WorkVecs %g\n", MPI_Wtime() - wallTime); 
-	}
-
-	self->solversChanged = False;
-	//self->matrixChanged = False;
-	self->mgData->matrixChanged = False;
-	self->opsChanged = False;
-
-        //if( !self->optionsReady ) {
-        if( !self->mgData->optionsReady ) {
-		KSPSetOptionsPrefix( self->mgData->ksp, "A11_" );
-                ec = KSPSetFromOptions( self->mgData->ksp );
-                CheckPETScError( ec );
-                //self->optionsReady = True;
-                self->mgData->optionsReady = True;
-        }
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void PETScMGSolver_SetLevels( void* matrixSolver, unsigned nLevels ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-	unsigned	l_i;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	PETScMGSolver_DestructLevels( self );
-
-	self->nLevels = nLevels;
-	self->levels = AllocArray( PETScMGSolver_Level, nLevels );
-	for( l_i = 0; l_i < nLevels; l_i++ ) {
-		PETScMGSolver_Level*	level = self->levels + l_i;
-
-		level->nDownIts = 1;
-		level->nUpIts = (l_i == 0) ? 0 : 1;
-		level->nCycles = 1;
-		level->R = NULL;
-		level->P = NULL;
-		level->A = NULL;
-		level->workRes = NULL;
-		level->workSol = NULL;
-		level->workRHS = NULL;
-	}
-}
-
-//void PETScMGSolver_SetRestriction( void* matrixSolver, unsigned levelInd, void* R ) {
-void PETScMGSolver_SetRestriction( void* matrixSolver, unsigned levelInd, void* _R ) {
-	PETScMGSolver*		self 	= (PETScMGSolver*)matrixSolver;
-	PETScMGSolver_Level*	level;
-	Mat			R	= (Mat)_R;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-	assert( levelInd < self->nLevels && levelInd > 0 );
-	//assert( !R || Stg_CheckType( R, PETScMatrix ) );
-
-	level = self->levels + levelInd;
-	if( level->R != R )
-		self->opsChanged = True;
-	//if( R )
-	//	Stg_Class_AddRef( R );
-	//if( level->R )
-	//	Stg_Class_RemoveRef( level->R );
-	if( level->R != PETSC_NULL )
-		MatDestroy( level->R );
-	level->R = R;
-}
-
-void PETScMGSolver_SetProlongation( void* matrixSolver, unsigned levelInd, void* _P ) {
-	PETScMGSolver*		self 	= (PETScMGSolver*)matrixSolver;
-	PETScMGSolver_Level*	level;
-	Mat			P	= (Mat)_P;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-	assert( levelInd < self->nLevels && levelInd > 0 );
-	//assert( !P || Stg_CheckType( P, PETScMatrix ) );
-
-	level = self->levels + levelInd;
-	if( level->P != P )
-		self->opsChanged = True;
-	//if( P )
-	//	Stg_Class_AddRef( P );
-	//if( level->P )
-	//	Stg_Class_RemoveRef( level->P );
-	if( level->P != PETSC_NULL ) {
-		MatDestroy( level->P );
-		if(level->P == level->R)
-		    level->R = PETSC_NULL;
-	}
-	level->P = P;
-}
-
-void PETScMGSolver_SetLevelDownIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-	assert( level < self->nLevels );
-
-	self->levels[level].nDownIts = nIts;
-	self->solversChanged = True;
-}
-
-void PETScMGSolver_SetLevelUpIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-	assert( level < self->nLevels );
-	assert( level > 0 );
-
-	self->levels[level].nUpIts = nIts;
-	self->solversChanged = True;
-}
-
-void PETScMGSolver_SetLevelCycles( void* matrixSolver, unsigned level, unsigned nCycles ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-	assert( level < self->nLevels );
-	assert( level > 0 );
-
-	self->levels[level].nCycles = nCycles;
-	self->solversChanged = True;
-}
-
-void PETScMGSolver_SetAllDownIterations( void* matrixSolver, unsigned nIts ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-	unsigned	l_i;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	for( l_i = 1; l_i < self->nLevels; l_i++ )
-		PETScMGSolver_SetLevelDownIterations( self, l_i, nIts );
-}
-
-void PETScMGSolver_SetAllUpIterations( void* matrixSolver, unsigned nIts ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-	unsigned	l_i;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	for( l_i = 1; l_i < self->nLevels; l_i++ )
-		PETScMGSolver_SetLevelUpIterations( self, l_i, nIts );
-}
-
-unsigned PETScMGSolver_GetNumLevels( void* matrixSolver ) {
-	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	return self->nLevels;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-void PETScMGSolver_UpdateOps( PETScMGSolver* self ) {
-	PC		pc;
-	Mat		*pOps, *rOps;
-	PetscErrorCode	ec;
-	unsigned	l_i;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	ec = KSPGetPC( self->mgData->ksp, &pc );
-	CheckPETScError( ec );
-
-	MGOpGenerator_Generate( self->opGen, (Mat**)&pOps, (Mat**)&rOps );
-
-	for( l_i = 1; l_i < self->nLevels; l_i++ ) {
-		//assert( Stg_CheckType( pOps[l_i], PETScMatrix ) );
-		//assert( Stg_CheckType( rOps[l_i], PETScMatrix ) );
-
-		PETScMGSolver_SetProlongation( self, l_i, pOps[l_i] );
-#if( ((PETSC_VERSION_MAJOR==2) && (PETSC_VERSION_MINOR==3) && (PETSC_VERSION_SUBMINOR==3)) || (PETSC_VERSION_MAJOR==3) )
-			ec = PCMGSetInterpolation( pc, l_i, pOps[l_i] );
-#else
-			ec = PCMGSetInterpolate( pc, l_i, pOps[l_i] );
-#endif
-		CheckPETScError( ec );
-
-		PETScMGSolver_SetRestriction( self, l_i, rOps[l_i] );
-		ec = PCMGSetRestriction( pc, l_i, rOps[l_i] );
-		CheckPETScError( ec );
-	}
-
-	FreeArray( pOps );
-	FreeArray( rOps );
-}
-
-void PETScMGSolver_UpdateMatrices( PETScMGSolver* self ) {
-	Stream*			stream;
-	PETScMGSolver_Level*	level;
-	PC			pc;
-	KSP			levelKSP;
-	PetscErrorCode		ec;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-	//assert( self->matrix && Stg_CheckType( self->matrix, PETScMatrix ) );
-
-	stream = Journal_Register( InfoStream_Type, (Name)"general" ); assert( stream  );
-	Journal_Printf( stream, "Updating MG matrices ...\n" );
-
-	ec = KSPGetPC( self->mgData->ksp, &pc );
-	CheckPETScError( ec );
-
-	for( l_i = self->nLevels - 1; l_i < self->nLevels; l_i-- ) {
-		level = self->levels + l_i;
-
-		if( l_i == self->nLevels - 1 )
-			//level->A = (PETScMatrix*)self->matrix;
-			level->A = self->mgData->matrix;
-		else {
-                    if( level->A )
-                        MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_REUSE_MATRIX, 1.0, &level->A );
-                    else
-                        MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_INITIAL_MATRIX, 1.0, &level->A );
-			//Matrix_PtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, (void**)&level->A );
-
-/*
-			if( self->levels[l_i + 1].P )
-				MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_REUSE_MATRIX, 1.0, &level->A );
-			else
-				MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_INITIAL_MATRIX, 1.0, &level->A );
-*/
-		}
-
-		ec = PCMGGetSmootherDown( pc, l_i, &levelKSP );
-		CheckPETScError( ec );
-		//ec = KSPSetOperators( levelKSP, level->A->petscMat, level->A->petscMat, DIFFERENT_NONZERO_PATTERN );
-		ec = KSPSetOperators( levelKSP, level->A, level->A, DIFFERENT_NONZERO_PATTERN );
-		CheckPETScError( ec );
-		//ec = PCMGSetResidual( pc, l_i, PCMGDefaultResidual, level->A->petscMat );
-		ec = PCMGSetResidual( pc, l_i, PCMGDefaultResidual, level->A );
-		CheckPETScError( ec );
-
-		if( l_i > 0 ) {
-			PCMGGetSmootherUp( pc, l_i, &levelKSP );
-			//ec = KSPSetOperators( levelKSP, level->A->petscMat, level->A->petscMat, DIFFERENT_NONZERO_PATTERN );
-			ec = KSPSetOperators( levelKSP, level->A, level->A, DIFFERENT_NONZERO_PATTERN );
-			CheckPETScError( ec );
-		}
-	}
-
-	Journal_Printf( stream, "done\n" );
-}
-
-void PETScMGSolver_UpdateWorkVectors( PETScMGSolver* self ) {
-	PETScMGSolver_Level*	level;
-	PC			pc;
-	//unsigned		size;
-	PetscInt		size, vecSize;
-	PetscErrorCode		ec;
-	unsigned		l_i;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	if( self->nLevels == 1 )
-		return;
-
-	ec = KSPGetPC( self->mgData->ksp, &pc );
-	CheckPETScError( ec );
-
-	for( l_i = 0; l_i < self->nLevels; l_i++ ) {
-		level = self->levels + l_i;
-
-		//Matrix_GetLocalSize( level->A, &size, NULL );
-		MatGetLocalSize( level->A, &size, PETSC_NULL );
-
-                if( level->workRes )
-                    VecGetLocalSize( level->workRes, &vecSize );
-
-		if( l_i > 0 && (!level->workRes || /*Vector_GetLocalSize( level->workRes )*/vecSize != size) ) {
-			if( level->workRes )
-				VecDestroy( level->workRes );
-			//	FreeObject( level->workRes );
-			//Vector_Duplicate( self->curSolution, (void**)&level->workRes );
-			//Vector_SetLocalSize( level->workRes, size );
-			//ec = PCMGSetR( pc, l_i, level->workRes->petscVec );
-			VecCreate( MPI_COMM_WORLD, &level->workRes );
-			VecSetSizes( level->workRes, size, PETSC_DECIDE );
-			VecSetFromOptions( level->workRes );
-#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
-			VecSetOption( level->workRes, VEC_IGNORE_NEGATIVE_INDICES );
-#elif( PETSC_VERSION_MAJOR >= 3 )
-			VecSetOption( level->workRes, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
-#endif
-			ec = PCMGSetR( pc, l_i, level->workRes );
-			CheckPETScError( ec );
-		}
-
-		if( l_i < self->nLevels - 1 ) {
-                    if( level->workSol )
-			VecGetLocalSize( level->workSol, &vecSize );
-                    if( !level->workSol || /*Vector_GetLocalSize( level->workSol )*/vecSize != size ) {
-				if( level->workSol )
-					VecDestroy( level->workSol );
-				//	FreeObject( level->workSol );
-				//Vector_Duplicate( self->curSolution, (void**)&level->workSol );
-				//Vector_SetLocalSize( level->workSol, size );
-				//ec = PCMGSetX( pc, l_i, level->workSol->petscVec );
-				VecCreate( MPI_COMM_WORLD, &level->workSol );
-				VecSetSizes( level->workSol, size, PETSC_DECIDE );
-				VecSetFromOptions( level->workSol );
-#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
-				VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES );
-#elif( PETSC_VERSION_MAJOR >= 3 )
-				VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
-#endif
-				ec = PCMGSetX( pc, l_i, level->workSol );
-				CheckPETScError( ec );
-			}
-
-                    if( level->workRHS )
-			VecGetLocalSize( level->workRHS, &vecSize );
-                    if( !level->workRHS || /*Vector_GetLocalSize( level->workRHS )*/vecSize != size ) {
-				if( level->workRHS )
-					VecDestroy( level->workRHS );
-				//	FreeObject( level->workRHS );
-				//Vector_Duplicate( self->curSolution, (void**)&level->workRHS );
-				//Vector_SetLocalSize( level->workRHS, size );
-				//ec = PCMGSetRhs( pc, l_i, level->workRHS->petscVec );
-				VecCreate( MPI_COMM_WORLD, &level->workRHS );
-				VecSetSizes( level->workRHS, size, PETSC_DECIDE );
-				VecSetFromOptions( level->workRHS );
-#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
-				VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES );
-#elif( PETSC_VERSION_MAJOR >= 3 )
-				VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
-#endif
-				ec = PCMGSetRhs( pc, l_i, level->workRHS );
-				CheckPETScError( ec );
-			}
-		}
-	}
-}
-
-void PETScMGSolver_UpdateSolvers( PETScMGSolver* self ) {
-	PETScMGSolver_Level*	level;
-	PC			pc;
-	KSP			levelKSP;
-	PC			levelPC;
-	PetscErrorCode		ec;
-	unsigned		l_i;
-	PetscTruth              smoothers_differ, flag;
-	PetscMPIInt             size;
-        MPI_Comm                comm;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	ec = KSPGetPC( self->mgData->ksp, &pc );
-	CheckPETScError( ec );
-
-	ec = PCMGSetLevels( pc, self->nLevels, PETSC_NULL );
-	CheckPETScError( ec );
-	ec = PCMGSetType( pc, PC_MG_MULTIPLICATIVE );
-	CheckPETScError( ec );
-
-	ec=PetscOptionsGetTruth( PETSC_NULL, "-pc_mg_different_smoothers", &smoothers_differ, &flag ); CheckPETScError(ec);
-
-	ec=PetscObjectGetComm( (PetscObject)pc, &comm ); CheckPETScError(ec);
-	MPI_Comm_size( comm, &size );
-
-	for( l_i = 1; l_i < self->nLevels; l_i++ ) {
-		level = self->levels + l_i;
-
-		printf("Configuring MG level %d \n", l_i );
-		ec = PCMGGetSmootherDown( pc, l_i, &levelKSP );
-		CheckPETScError( ec );
-		if(smoothers_differ==PETSC_TRUE) { ec=KSPAppendOptionsPrefix( levelKSP, "down_" ); CheckPETScError(ec); }
-		ec = KSPSetType( levelKSP, KSPRICHARDSON ); CheckPETScError( ec );
-		ec = KSPGetPC( levelKSP, &levelPC ); CheckPETScError( ec );
-
-		if(size==1) {
-		  ec = PCSetType( levelPC, PCSOR ); CheckPETScError( ec );
-		}
-		/* This does not work - bug with the order the operators are created I guess */
-		/* For parallel jobs you best bet is to use the command line args and let petsc work it out */
-		/*
-		else {
-		  KSP *sub_ksp;
-		  PetscInt k, n_local, first_local;
-		  PC sub_pc;
-
-		  PCSetType( levelPC, PCBJACOBI );
-		  KSPSetUp( levelKSP );
-		  PCBJacobiGetSubKSP( levelPC, &n_local,&first_local,&sub_ksp);
-		  for(k=0;k<n_local;k++ ) {
-		    KSPSetType( sub_ksp[k], KSPFGMRES );
-		    KSPGetPC( sub_ksp[k], &sub_pc );
-		    PCSetType( sub_pc, PCSOR );
-		  }
-		}
-		*/
-		ec = KSPSetTolerances( levelKSP, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nDownIts ); CheckPETScError( ec );
-		if( l_i == self->nLevels - 1 ) { 
-		  ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_TRUE );  CheckPETScError( ec );
-		} 
-		else {  ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_FALSE ); CheckPETScError( ec );  }
-
-		ec = PCMGGetSmootherUp( pc, l_i, &levelKSP ); CheckPETScError( ec );
-		if(smoothers_differ==PETSC_TRUE) { ec=KSPAppendOptionsPrefix( levelKSP, "up_" ); CheckPETScError(ec); }
-		ec = KSPSetType( levelKSP, KSPRICHARDSON ); CheckPETScError( ec );
-		ec = KSPGetPC( levelKSP, &levelPC ); CheckPETScError( ec );
-		if(size==1) {
-		  ec = PCSetType( levelPC, PCSOR ); CheckPETScError( ec );
-		}
-		ec = KSPSetTolerances( levelKSP, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nUpIts ); CheckPETScError( ec );
-		ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_TRUE ); CheckPETScError( ec );
-
-		ec = PCMGSetCyclesOnLevel( pc, l_i, level->nCycles ); CheckPETScError( ec );
-	}
-}
-
-void PETScMGSolver_Destruct( PETScMGSolver* self ) {
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	PETScMGSolver_DestructLevels( self );
-	/*KillObject( self->opGen );*/
-}
-
-void PETScMGSolver_DestructLevels( PETScMGSolver* self ) {
-	unsigned	l_i;
-
-	assert( self && Stg_CheckType( self, PETScMGSolver ) );
-
-	for( l_i = 0; l_i < self->nLevels; l_i++ ) {
-		PETScMGSolver_Level*	level = self->levels + l_i;
-
-		/*
-		if( level->R )
-			Stg_Class_RemoveRef( level->R );
-		if( level->P )
-			Stg_Class_RemoveRef( level->P );
-		if( level->A )
-			Stg_Class_RemoveRef( level->A );
-		*/
-		if( level->R != PETSC_NULL && level->R != level->P )
-                    MatDestroy( level->R );
-		if( level->P != PETSC_NULL ) MatDestroy( level->P );
-/*
-		if( level->A != PETSC_NULL ) MatDestroy( level->A );
-*/
-
-		//FreeObject( level->workRes );
-		//FreeObject( level->workSol );
-		//FreeObject( level->workRHS );
-                if( level->workRes )
-                    VecDestroy( level->workRes );
-                if( level->workSol )
-                    VecDestroy( level->workSol );
-                if( level->workRHS )
-                    VecDestroy( level->workRHS );
-	}
-
-	KillArray( self->levels );
-	self->nLevels = 0;
-	self->solversChanged = True;
-	self->opsChanged = True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/PETScMGSolver.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/PETScMGSolver.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,764 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: PETScMGSolver.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+
+#include "SystemSetup.h"
+
+
+/* Textual name of this class */
+const Type PETScMGSolver_Type = "PETScMGSolver";
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+PETScMGSolver* PETScMGSolver_New( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                    _sizeOfSelf = sizeof(PETScMGSolver);
+	Type                                                            type = PETScMGSolver_Type;
+	Stg_Class_DeleteFunction*                                    _delete = _PETScMGSolver_Delete;
+	Stg_Class_PrintFunction*                                      _print = _PETScMGSolver_Print;
+	Stg_Class_CopyFunction*                                        _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*        _defaultConstructor = (void* (*)(Name))_PETScMGSolver_New;
+	Stg_Component_ConstructFunction*                          _construct = _PETScMGSolver_AssignFromXML;
+	Stg_Component_BuildFunction*                                  _build = _PETScMGSolver_Build;
+	Stg_Component_InitialiseFunction*                        _initialise = _PETScMGSolver_Initialise;
+	Stg_Component_ExecuteFunction*                              _execute = _PETScMGSolver_Execute;
+	Stg_Component_DestroyFunction*                              _destroy = _PETScMGSolver_Destroy;
+	AllocationType                                    nameAllocationType = NON_GLOBAL;
+	MGSolver_SetCommFunc*                                    setCommFunc = PETScMGSolver_SetComm;
+	MGSolver_SetMatrixFunc*                                setMatrixFunc = NULL;
+	MGSolver_SetMaxIterationsFunc*                  setMaxIterationsFunc = NULL;
+	MGSolver_SetRelativeToleranceFunc*          setRelativeToleranceFunc = NULL;
+	MGSolver_SetAbsoluteToleranceFunc*          setAbsoluteToleranceFunc = NULL;
+	MGSolver_SetUseInitialSolutionFunc*        setUseInitialSolutionFunc = NULL;
+	MGSolver_SolveFunc*                                        solveFunc = NULL;
+	MGSolver_SetupFunc*                                        setupFunc = PETScMGSolver_Setup;
+	MGSolver_GetSolveStatusFunc*                      getSolveStatusFunc = NULL;
+	MGSolver_GetIterationsFunc*                        getIterationsFunc = NULL;
+	MGSolver_GetMaxIterationsFunc*                  getMaxIterationsFunc = NULL;
+	MGSolver_GetResidualNormFunc*                    getResidualNormFunc = NULL;
+
+	return _PETScMGSolver_New(  PETSCMGSOLVER_PASSARGS  );
+}
+
+PETScMGSolver* _PETScMGSolver_New(  PETSCMGSOLVER_DEFARGS  ) {
+	PETScMGSolver*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(PETScMGSolver) );
+	//self = (PETScMGSolver*)_PETScMatrixSolver_New(  STG_COMPONENT_PASSARGS  );
+	self = (PETScMGSolver*)_Stg_Component_New( STG_COMPONENT_PASSARGS );
+
+	/* Virtual info */
+	/* from the depreciated MatrixSolver_New func */
+	self->setCommFunc = setCommFunc;
+	self->setMatrixFunc = setMatrixFunc;
+	self->setMaxIterationsFunc = setMaxIterationsFunc;
+	self->setRelativeToleranceFunc = setRelativeToleranceFunc;
+	self->setAbsoluteToleranceFunc = setAbsoluteToleranceFunc;
+	self->setUseInitialSolutionFunc = setUseInitialSolutionFunc;
+
+	self->solveFunc = solveFunc;
+	self->setupFunc = setupFunc;
+
+	self->getSolveStatusFunc = getSolveStatusFunc;
+	self->getIterationsFunc = getIterationsFunc;
+	self->getMaxIterationsFunc = getMaxIterationsFunc;
+	self->getResidualNormFunc = getResidualNormFunc;
+
+	/* PETScMGSolver info */
+	_PETScMGSolver_Init( self );
+
+	return self;
+}
+
+void _PETScMGSolver_Init( PETScMGSolver* self ) {
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	self->mgData = (MGSolver_PETScData*)malloc( sizeof( MGSolver_PETScData ) );
+
+	/* from the depreciated MatrixSolver_Init func */
+	self->mgData->comm = MPI_COMM_WORLD;
+	KSPCreate( MPI_COMM_WORLD, &self->mgData->ksp );
+	self->mgData->matrix = PETSC_NULL;
+	self->mgData->inversion = PETSC_NULL;
+	self->mgData->residual = PETSC_NULL;
+	self->mgData->expiredResidual = True;
+	self->mgData->matrixChanged = True;
+        self->mgData->optionsReady = False;
+
+	self->mgData->curRHS = PETSC_NULL;
+	self->mgData->curSolution = PETSC_NULL;
+	/* end of MatrixSolver_Init stuff */
+
+	self->nLevels = 0;
+	self->levels = NULL;
+	self->opGen = NULL;
+	self->solversChanged = True;
+	self->opsChanged = True;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _PETScMGSolver_Delete( void* matrixSolver ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	PETScMGSolver_Destruct( self );
+
+	/* Delete the parent. */
+	//_PETScMatrixSolver_Delete( self );
+	_Stg_Component_Delete( self );
+}
+
+void _PETScMGSolver_Print( void* matrixSolver, Stream* stream ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+	
+	/* Set the Journal for printing informations */
+	Stream* matrixSolverStream;
+	matrixSolverStream = Journal_Register( InfoStream_Type, (Name)"PETScMGSolverStream"  );
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	/* Print parent */
+	Journal_Printf( stream, "PETScMGSolver (ptr): (%p)\n", self );
+	//_PETScMatrixSolver_Print( self, stream );
+	_Stg_Component_Print( self, stream );
+}
+
+void _PETScMGSolver_AssignFromXML( void* matrixSolver, Stg_ComponentFactory* cf, void* data ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+	Bool		pure;
+	unsigned	nLevels;
+	unsigned	nCycles;
+	unsigned	nDownIts, nUpIts;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+	assert( cf );
+
+	//_PETScMatrixSolver_AssignFromXML( self, cf, data );
+
+	pure = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"pure", False  );
+	nLevels = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"levels", 1  );
+	nCycles = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"cycles", 1  );
+	nDownIts = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"downIterations", 1  );
+	nUpIts = Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"upIterations", 1  );
+
+	self->pure = pure;
+	PETScMGSolver_SetLevels( self, nLevels );
+	PETScMGSolver_SetLevelCycles( self, nLevels - 1, nCycles );
+	PETScMGSolver_SetAllDownIterations( self, nDownIts );
+	PETScMGSolver_SetAllUpIterations( self, nUpIts );
+
+	self->opGen = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"opGenerator", MGOpGenerator, True, data  );
+	MGOpGenerator_SetMatrixSolver( self->opGen, self );
+	MGOpGenerator_SetNumLevels( self->opGen, nLevels );
+}
+
+void _PETScMGSolver_Build( void* matrixSolver, void* data ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	if( self->opGen )
+		Stg_Component_Build( self->opGen, data, False );
+}
+
+void _PETScMGSolver_Initialise( void* matrixSolver, void* data ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	if( self->opGen )
+		Stg_Component_Initialise( self->opGen, data, False );
+}
+
+void _PETScMGSolver_Execute( void* matrixSolver, void* data ) {
+}
+
+void _PETScMGSolver_Destroy( void* matrixSolver, void* data ) {
+}
+
+void PETScMGSolver_SetComm( void* matrixSolver, MPI_Comm comm ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+	PC		pc;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	//PETScMatrixSolver_SetComm( self, comm );
+	self->mgData->comm = comm;
+	if( self->mgData->ksp )
+		KSPDestroy( self->mgData->ksp );
+	KSPCreate( comm, &self->mgData->ksp );
+
+	if( self->pure )
+		//PETScMatrixSolver_SetKSPType( self, PETScMatrixSolver_KSPType_Richardson );
+		KSPSetType( self->mgData->ksp, KSPRICHARDSON );	
+	else
+		//PETScMatrixSolver_SetKSPType( self, PETScMatrixSolver_KSPType_FGMRes );
+		KSPSetType( self->mgData->ksp, KSPFGMRES );
+	//PETScMatrixSolver_SetPCType( self, PETScMatrixSolver_PCType_Multigrid );
+	KSPGetPC( self->mgData->ksp, &pc );
+	PCSetType( pc, PCMG );
+}
+
+void PETScMGSolver_Setup( void* matrixSolver, void* rhs, void* solution ) { 
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+	Bool		rebuildOps;
+	double          wallTime;
+	PetscErrorCode  ec;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	wallTime = MPI_Wtime();
+		
+	//_MatrixSolver_Setup( self, rhs, solution );
+	self->mgData->curRHS = (struct _p_Vec*)rhs;
+	self->mgData->curSolution = (struct _p_Vec*)solution;
+	self->mgData->expiredResidual = True;
+
+   	PetscPrintf( PETSC_COMM_WORLD, "_MatrixSolver_Setup %g\n", MPI_Wtime() - wallTime);
+
+
+	if( self->opGen )
+		rebuildOps = MGOpGenerator_HasExpired( self->opGen );
+	else
+		rebuildOps = False;
+	if( !rebuildOps ) {
+		unsigned		l_i;
+
+		for( l_i = 1; l_i < self->nLevels; l_i++ ) {
+			if( !self->levels[l_i].R || !self->levels[l_i].P ) {
+				rebuildOps = True;
+				break;
+			}
+		}
+	}
+
+	if( self->solversChanged || rebuildOps || self->opsChanged ) {
+		wallTime = MPI_Wtime();
+		PETScMGSolver_UpdateSolvers( self );
+        stg_profile_Func( "PETScMGSolver_UpdateSolvers", MPI_Wtime() - wallTime);
+	   	PetscPrintf( PETSC_COMM_WORLD, "PETScMGSolver_UpdateSolvers %g\n", MPI_Wtime() - wallTime);
+	}
+	if( rebuildOps ) {
+		wallTime = MPI_Wtime();
+		PETScMGSolver_UpdateOps( self );
+		stg_profile_Func( "PETScMGSolver_UpdateOps", MPI_Wtime() - wallTime);
+		PetscPrintf( PETSC_COMM_WORLD,  "PETScMGSolver_UpdateOps %g\n", MPI_Wtime() - wallTime);
+
+	}
+	//if( self->matrixChanged || self->solversChanged || rebuildOps || self->opsChanged ) {
+	if( self->mgData->matrixChanged || self->solversChanged || rebuildOps || self->opsChanged ) {
+		wallTime = MPI_Wtime();
+		PETScMGSolver_UpdateMatrices( self );
+		PETScMGSolver_UpdateWorkVectors( self );
+		stg_profile_Func( "PETScMGSolver_UpdateMats-WorkVecs", MPI_Wtime() - wallTime); 
+		PetscPrintf( PETSC_COMM_WORLD, "PETScMGSolver_UpdateMats-WorkVecs %g\n", MPI_Wtime() - wallTime); 
+	}
+
+	self->solversChanged = False;
+	//self->matrixChanged = False;
+	self->mgData->matrixChanged = False;
+	self->opsChanged = False;
+
+        //if( !self->optionsReady ) {
+        if( !self->mgData->optionsReady ) {
+		KSPSetOptionsPrefix( self->mgData->ksp, "A11_" );
+                ec = KSPSetFromOptions( self->mgData->ksp );
+                CheckPETScError( ec );
+                //self->optionsReady = True;
+                self->mgData->optionsReady = True;
+        }
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void PETScMGSolver_SetLevels( void* matrixSolver, unsigned nLevels ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+	unsigned	l_i;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	PETScMGSolver_DestructLevels( self );
+
+	self->nLevels = nLevels;
+	self->levels = AllocArray( PETScMGSolver_Level, nLevels );
+	for( l_i = 0; l_i < nLevels; l_i++ ) {
+		PETScMGSolver_Level*	level = self->levels + l_i;
+
+		level->nDownIts = 1;
+		level->nUpIts = (l_i == 0) ? 0 : 1;
+		level->nCycles = 1;
+		level->R = NULL;
+		level->P = NULL;
+		level->A = NULL;
+		level->workRes = NULL;
+		level->workSol = NULL;
+		level->workRHS = NULL;
+	}
+}
+
+//void PETScMGSolver_SetRestriction( void* matrixSolver, unsigned levelInd, void* R ) {
+void PETScMGSolver_SetRestriction( void* matrixSolver, unsigned levelInd, void* _R ) {
+	PETScMGSolver*		self 	= (PETScMGSolver*)matrixSolver;
+	PETScMGSolver_Level*	level;
+	Mat			R	= (Mat)_R;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+	assert( levelInd < self->nLevels && levelInd > 0 );
+	//assert( !R || Stg_CheckType( R, PETScMatrix ) );
+
+	level = self->levels + levelInd;
+	if( level->R != R )
+		self->opsChanged = True;
+	//if( R )
+	//	Stg_Class_AddRef( R );
+	//if( level->R )
+	//	Stg_Class_RemoveRef( level->R );
+	if( level->R != PETSC_NULL )
+		MatDestroy( level->R );
+	level->R = R;
+}
+
+void PETScMGSolver_SetProlongation( void* matrixSolver, unsigned levelInd, void* _P ) {
+	PETScMGSolver*		self 	= (PETScMGSolver*)matrixSolver;
+	PETScMGSolver_Level*	level;
+	Mat			P	= (Mat)_P;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+	assert( levelInd < self->nLevels && levelInd > 0 );
+	//assert( !P || Stg_CheckType( P, PETScMatrix ) );
+
+	level = self->levels + levelInd;
+	if( level->P != P )
+		self->opsChanged = True;
+	//if( P )
+	//	Stg_Class_AddRef( P );
+	//if( level->P )
+	//	Stg_Class_RemoveRef( level->P );
+	if( level->P != PETSC_NULL ) {
+		MatDestroy( level->P );
+		if(level->P == level->R)
+		    level->R = PETSC_NULL;
+	}
+	level->P = P;
+}
+
+void PETScMGSolver_SetLevelDownIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+	assert( level < self->nLevels );
+
+	self->levels[level].nDownIts = nIts;
+	self->solversChanged = True;
+}
+
+void PETScMGSolver_SetLevelUpIterations( void* matrixSolver, unsigned level, unsigned nIts ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+	assert( level < self->nLevels );
+	assert( level > 0 );
+
+	self->levels[level].nUpIts = nIts;
+	self->solversChanged = True;
+}
+
+void PETScMGSolver_SetLevelCycles( void* matrixSolver, unsigned level, unsigned nCycles ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+	assert( level < self->nLevels );
+	assert( level > 0 );
+
+	self->levels[level].nCycles = nCycles;
+	self->solversChanged = True;
+}
+
+void PETScMGSolver_SetAllDownIterations( void* matrixSolver, unsigned nIts ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+	unsigned	l_i;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	for( l_i = 1; l_i < self->nLevels; l_i++ )
+		PETScMGSolver_SetLevelDownIterations( self, l_i, nIts );
+}
+
+void PETScMGSolver_SetAllUpIterations( void* matrixSolver, unsigned nIts ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+	unsigned	l_i;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	for( l_i = 1; l_i < self->nLevels; l_i++ )
+		PETScMGSolver_SetLevelUpIterations( self, l_i, nIts );
+}
+
+unsigned PETScMGSolver_GetNumLevels( void* matrixSolver ) {
+	PETScMGSolver*	self = (PETScMGSolver*)matrixSolver;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	return self->nLevels;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+void PETScMGSolver_UpdateOps( PETScMGSolver* self ) {
+	PC		pc;
+	Mat		*pOps, *rOps;
+	PetscErrorCode	ec;
+	unsigned	l_i;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	ec = KSPGetPC( self->mgData->ksp, &pc );
+	CheckPETScError( ec );
+
+	MGOpGenerator_Generate( self->opGen, (Mat**)&pOps, (Mat**)&rOps );
+
+	for( l_i = 1; l_i < self->nLevels; l_i++ ) {
+		//assert( Stg_CheckType( pOps[l_i], PETScMatrix ) );
+		//assert( Stg_CheckType( rOps[l_i], PETScMatrix ) );
+
+		PETScMGSolver_SetProlongation( self, l_i, pOps[l_i] );
+#if( ((PETSC_VERSION_MAJOR==2) && (PETSC_VERSION_MINOR==3) && (PETSC_VERSION_SUBMINOR==3)) || (PETSC_VERSION_MAJOR==3) )
+			ec = PCMGSetInterpolation( pc, l_i, pOps[l_i] );
+#else
+			ec = PCMGSetInterpolate( pc, l_i, pOps[l_i] );
+#endif
+		CheckPETScError( ec );
+
+		PETScMGSolver_SetRestriction( self, l_i, rOps[l_i] );
+		ec = PCMGSetRestriction( pc, l_i, rOps[l_i] );
+		CheckPETScError( ec );
+	}
+
+	FreeArray( pOps );
+	FreeArray( rOps );
+}
+
+void PETScMGSolver_UpdateMatrices( PETScMGSolver* self ) {
+	Stream*			stream;
+	PETScMGSolver_Level*	level;
+	PC			pc;
+	KSP			levelKSP;
+	PetscErrorCode		ec;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+	//assert( self->matrix && Stg_CheckType( self->matrix, PETScMatrix ) );
+
+	stream = Journal_Register( InfoStream_Type, (Name)"general" ); assert( stream  );
+	Journal_Printf( stream, "Updating MG matrices ...\n" );
+
+	ec = KSPGetPC( self->mgData->ksp, &pc );
+	CheckPETScError( ec );
+
+	for( l_i = self->nLevels - 1; l_i < self->nLevels; l_i-- ) {
+		level = self->levels + l_i;
+
+		if( l_i == self->nLevels - 1 )
+			//level->A = (PETScMatrix*)self->matrix;
+			level->A = self->mgData->matrix;
+		else {
+                    if( level->A )
+                        MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_REUSE_MATRIX, 1.0, &level->A );
+                    else
+                        MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_INITIAL_MATRIX, 1.0, &level->A );
+			//Matrix_PtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, (void**)&level->A );
+
+/*
+			if( self->levels[l_i + 1].P )
+				MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_REUSE_MATRIX, 1.0, &level->A );
+			else
+				MatPtAP( self->levels[l_i + 1].A, self->levels[l_i + 1].P, MAT_INITIAL_MATRIX, 1.0, &level->A );
+*/
+		}
+
+		ec = PCMGGetSmootherDown( pc, l_i, &levelKSP );
+		CheckPETScError( ec );
+		//ec = KSPSetOperators( levelKSP, level->A->petscMat, level->A->petscMat, DIFFERENT_NONZERO_PATTERN );
+		ec = KSPSetOperators( levelKSP, level->A, level->A, DIFFERENT_NONZERO_PATTERN );
+		CheckPETScError( ec );
+		//ec = PCMGSetResidual( pc, l_i, PCMGDefaultResidual, level->A->petscMat );
+		ec = PCMGSetResidual( pc, l_i, PCMGDefaultResidual, level->A );
+		CheckPETScError( ec );
+
+		if( l_i > 0 ) {
+			PCMGGetSmootherUp( pc, l_i, &levelKSP );
+			//ec = KSPSetOperators( levelKSP, level->A->petscMat, level->A->petscMat, DIFFERENT_NONZERO_PATTERN );
+			ec = KSPSetOperators( levelKSP, level->A, level->A, DIFFERENT_NONZERO_PATTERN );
+			CheckPETScError( ec );
+		}
+	}
+
+	Journal_Printf( stream, "done\n" );
+}
+
+void PETScMGSolver_UpdateWorkVectors( PETScMGSolver* self ) {
+	PETScMGSolver_Level*	level;
+	PC			pc;
+	//unsigned		size;
+	PetscInt		size, vecSize;
+	PetscErrorCode		ec;
+	unsigned		l_i;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	if( self->nLevels == 1 )
+		return;
+
+	ec = KSPGetPC( self->mgData->ksp, &pc );
+	CheckPETScError( ec );
+
+	for( l_i = 0; l_i < self->nLevels; l_i++ ) {
+		level = self->levels + l_i;
+
+		//Matrix_GetLocalSize( level->A, &size, NULL );
+		MatGetLocalSize( level->A, &size, PETSC_NULL );
+
+                if( level->workRes )
+                    VecGetLocalSize( level->workRes, &vecSize );
+
+		if( l_i > 0 && (!level->workRes || /*Vector_GetLocalSize( level->workRes )*/vecSize != size) ) {
+			if( level->workRes )
+				VecDestroy( level->workRes );
+			//	FreeObject( level->workRes );
+			//Vector_Duplicate( self->curSolution, (void**)&level->workRes );
+			//Vector_SetLocalSize( level->workRes, size );
+			//ec = PCMGSetR( pc, l_i, level->workRes->petscVec );
+			VecCreate( MPI_COMM_WORLD, &level->workRes );
+			VecSetSizes( level->workRes, size, PETSC_DECIDE );
+			VecSetFromOptions( level->workRes );
+#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
+			VecSetOption( level->workRes, VEC_IGNORE_NEGATIVE_INDICES );
+#elif( PETSC_VERSION_MAJOR >= 3 )
+			VecSetOption( level->workRes, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
+#endif
+			ec = PCMGSetR( pc, l_i, level->workRes );
+			CheckPETScError( ec );
+		}
+
+		if( l_i < self->nLevels - 1 ) {
+                    if( level->workSol )
+			VecGetLocalSize( level->workSol, &vecSize );
+                    if( !level->workSol || /*Vector_GetLocalSize( level->workSol )*/vecSize != size ) {
+				if( level->workSol )
+					VecDestroy( level->workSol );
+				//	FreeObject( level->workSol );
+				//Vector_Duplicate( self->curSolution, (void**)&level->workSol );
+				//Vector_SetLocalSize( level->workSol, size );
+				//ec = PCMGSetX( pc, l_i, level->workSol->petscVec );
+				VecCreate( MPI_COMM_WORLD, &level->workSol );
+				VecSetSizes( level->workSol, size, PETSC_DECIDE );
+				VecSetFromOptions( level->workSol );
+#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
+				VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES );
+#elif( PETSC_VERSION_MAJOR >= 3 )
+				VecSetOption( level->workSol, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
+#endif
+				ec = PCMGSetX( pc, l_i, level->workSol );
+				CheckPETScError( ec );
+			}
+
+                    if( level->workRHS )
+			VecGetLocalSize( level->workRHS, &vecSize );
+                    if( !level->workRHS || /*Vector_GetLocalSize( level->workRHS )*/vecSize != size ) {
+				if( level->workRHS )
+					VecDestroy( level->workRHS );
+				//	FreeObject( level->workRHS );
+				//Vector_Duplicate( self->curSolution, (void**)&level->workRHS );
+				//Vector_SetLocalSize( level->workRHS, size );
+				//ec = PCMGSetRhs( pc, l_i, level->workRHS->petscVec );
+				VecCreate( MPI_COMM_WORLD, &level->workRHS );
+				VecSetSizes( level->workRHS, size, PETSC_DECIDE );
+				VecSetFromOptions( level->workRHS );
+#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
+				VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES );
+#elif( PETSC_VERSION_MAJOR >= 3 )
+				VecSetOption( level->workRHS, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
+#endif
+				ec = PCMGSetRhs( pc, l_i, level->workRHS );
+				CheckPETScError( ec );
+			}
+		}
+	}
+}
+
+void PETScMGSolver_UpdateSolvers( PETScMGSolver* self ) {
+	PETScMGSolver_Level*	level;
+	PC			pc;
+	KSP			levelKSP;
+	PC			levelPC;
+	PetscErrorCode		ec;
+	unsigned		l_i;
+	PetscTruth              smoothers_differ, flag;
+	PetscMPIInt             size;
+        MPI_Comm                comm;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	ec = KSPGetPC( self->mgData->ksp, &pc );
+	CheckPETScError( ec );
+
+	ec = PCMGSetLevels( pc, self->nLevels, PETSC_NULL );
+	CheckPETScError( ec );
+	ec = PCMGSetType( pc, PC_MG_MULTIPLICATIVE );
+	CheckPETScError( ec );
+
+	ec=PetscOptionsGetTruth( PETSC_NULL, "-pc_mg_different_smoothers", &smoothers_differ, &flag ); CheckPETScError(ec);
+
+	ec=PetscObjectGetComm( (PetscObject)pc, &comm ); CheckPETScError(ec);
+	MPI_Comm_size( comm, &size );
+
+	for( l_i = 1; l_i < self->nLevels; l_i++ ) {
+		level = self->levels + l_i;
+
+		printf("Configuring MG level %d \n", l_i );
+		ec = PCMGGetSmootherDown( pc, l_i, &levelKSP );
+		CheckPETScError( ec );
+		if(smoothers_differ==PETSC_TRUE) { ec=KSPAppendOptionsPrefix( levelKSP, "down_" ); CheckPETScError(ec); }
+		ec = KSPSetType( levelKSP, KSPRICHARDSON ); CheckPETScError( ec );
+		ec = KSPGetPC( levelKSP, &levelPC ); CheckPETScError( ec );
+
+		if(size==1) {
+		  ec = PCSetType( levelPC, PCSOR ); CheckPETScError( ec );
+		}
+		/* This does not work - bug with the order the operators are created I guess */
+		/* For parallel jobs you best bet is to use the command line args and let petsc work it out */
+		/*
+		else {
+		  KSP *sub_ksp;
+		  PetscInt k, n_local, first_local;
+		  PC sub_pc;
+
+		  PCSetType( levelPC, PCBJACOBI );
+		  KSPSetUp( levelKSP );
+		  PCBJacobiGetSubKSP( levelPC, &n_local,&first_local,&sub_ksp);
+		  for(k=0;k<n_local;k++ ) {
+		    KSPSetType( sub_ksp[k], KSPFGMRES );
+		    KSPGetPC( sub_ksp[k], &sub_pc );
+		    PCSetType( sub_pc, PCSOR );
+		  }
+		}
+		*/
+		ec = KSPSetTolerances( levelKSP, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nDownIts ); CheckPETScError( ec );
+		if( l_i == self->nLevels - 1 ) { 
+		  ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_TRUE );  CheckPETScError( ec );
+		} 
+		else {  ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_FALSE ); CheckPETScError( ec );  }
+
+		ec = PCMGGetSmootherUp( pc, l_i, &levelKSP ); CheckPETScError( ec );
+		if(smoothers_differ==PETSC_TRUE) { ec=KSPAppendOptionsPrefix( levelKSP, "up_" ); CheckPETScError(ec); }
+		ec = KSPSetType( levelKSP, KSPRICHARDSON ); CheckPETScError( ec );
+		ec = KSPGetPC( levelKSP, &levelPC ); CheckPETScError( ec );
+		if(size==1) {
+		  ec = PCSetType( levelPC, PCSOR ); CheckPETScError( ec );
+		}
+		ec = KSPSetTolerances( levelKSP, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, level->nUpIts ); CheckPETScError( ec );
+		ec = KSPSetInitialGuessNonzero( levelKSP, PETSC_TRUE ); CheckPETScError( ec );
+
+		ec = PCMGSetCyclesOnLevel( pc, l_i, level->nCycles ); CheckPETScError( ec );
+	}
+}
+
+void PETScMGSolver_Destruct( PETScMGSolver* self ) {
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	PETScMGSolver_DestructLevels( self );
+	/*KillObject( self->opGen );*/
+}
+
+void PETScMGSolver_DestructLevels( PETScMGSolver* self ) {
+	unsigned	l_i;
+
+	assert( self && Stg_CheckType( self, PETScMGSolver ) );
+
+	for( l_i = 0; l_i < self->nLevels; l_i++ ) {
+		PETScMGSolver_Level*	level = self->levels + l_i;
+
+		/*
+		if( level->R )
+			Stg_Class_RemoveRef( level->R );
+		if( level->P )
+			Stg_Class_RemoveRef( level->P );
+		if( level->A )
+			Stg_Class_RemoveRef( level->A );
+		*/
+		if( level->R != PETSC_NULL && level->R != level->P )
+                    MatDestroy( level->R );
+		if( level->P != PETSC_NULL ) MatDestroy( level->P );
+/*
+		if( level->A != PETSC_NULL ) MatDestroy( level->A );
+*/
+
+		//FreeObject( level->workRes );
+		//FreeObject( level->workSol );
+		//FreeObject( level->workRHS );
+                if( level->workRes )
+                    VecDestroy( level->workRes );
+                if( level->workSol )
+                    VecDestroy( level->workSol );
+                if( level->workRHS )
+                    VecDestroy( level->workRHS );
+	}
+
+	KillArray( self->levels );
+	self->nLevels = 0;
+	self->solversChanged = True;
+	self->opsChanged = True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/SLE_Solver.c
--- a/SLE/SystemSetup/src/SLE_Solver.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,256 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: SLE_Solver.c 1125 2008-05-12 14:22:02Z DavidMay $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "FiniteElementContext.h"
-#include "SLE_Solver.h"
-
-#include <assert.h>
-
-/** Textual name of this class */
-const Type SLE_Solver_Type = "SLE_Solver";
-
-SLE_Solver* _SLE_Solver_New(  SLE_SOLVER_DEFARGS  )
-{	
-	SLE_Solver*		self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(SLE_Solver) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (SLE_Solver*) _Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual info */
-	self->_solverSetup = _solverSetup;
-	self->_solve = _solve;
-	self->_getResidual = _getResidual;
-
-	self->_formResidual = NULL;
-	self->_getRhs       = NULL;
-	self->_getSolution  = NULL;
-
-	return self;
-
-}
-
-void _SLE_Solver_Init( SLE_Solver* self, Bool useStatSolve, int statReps ) {
-	self->isConstructed = True;
-	self->extensionManager = ExtensionManager_New_OfExistingObject( self->name, self );
-	
-	self->debug         = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
-	self->info          = Journal_MyStream( Info_Type, self );
-	self->maxIterations = 0;
-
-	self->previoustimestep = 0;
-	self->currenttimestep = 0;
-	self->nonlinearitsinitialtime = 0; 
-	self->nonlinearitsendtime = 0; 
-	self->totalnonlinearitstime = 0; 
-	self->totalnumnonlinearits = 0; 
-	self->avgtimenonlinearits = 0; 	
-	self->inneritsinitialtime = 0; 
-	self->outeritsinitialtime = 0; 
-	self->inneritsendtime = 0; 
-	self->outeritsendtime = 0; 
-	self->totalinneritstime = 0; 
-	self->totalouteritstime = 0; 
-	self->totalnuminnerits = 0; 
-	self->totalnumouterits = 0; 
-	self->avgnuminnerits = 0; 
-	self->avgnumouterits = 0; 
-	self->avgtimeinnerits = 0; 
-	self->avgtimeouterits = 0;
-	
-	self->useStatSolve = useStatSolve;
-	self->nStatReps     = statReps;
-}
-
-void SLE_Solver_InitAll( void* sleSolver, Bool useStatSolve, int statReps ) {
-	_SLE_Solver_Init( (SLE_Solver*) sleSolver, useStatSolve, statReps );
-}
-
-void* _SLE_Solver_Copy( const void* sleSolver, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	SLE_Solver*		self = (SLE_Solver*)sleSolver;
-	SLE_Solver*		newSleSolver;
-	PtrMap*			map = ptrMap;
-	Bool			ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newSleSolver = (SLE_Solver*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
-	
-	/* virtual functions */
-	newSleSolver->_solverSetup  = self->_solverSetup;
-	newSleSolver->_solve        = self->_solve;
-	newSleSolver->maxIterations = self->maxIterations;
-
-	newSleSolver->inneritsinitialtime = self->inneritsinitialtime;
-	newSleSolver->outeritsinitialtime = self->outeritsinitialtime;
-	newSleSolver->nonlinearitsinitialtime = self->nonlinearitsinitialtime;
-	newSleSolver->inneritsendtime = self->inneritsendtime;
-	newSleSolver->outeritsendtime = self->outeritsendtime;
-	newSleSolver->nonlinearitsendtime = self->nonlinearitsendtime;
-	newSleSolver->totalinneritstime = self->totalinneritstime;
-	newSleSolver->totalouteritstime = self->totalouteritstime;
-	newSleSolver->totalnonlinearitstime = self->totalnonlinearitstime;
-	newSleSolver->totalnuminnerits = self->totalnuminnerits; 
-	newSleSolver->totalnumouterits = self->totalnumouterits; 
-	newSleSolver->totalnumnonlinearits = self->totalnumnonlinearits; 	
-	newSleSolver->avgnuminnerits = self->avgnuminnerits;
-    newSleSolver->avgnumouterits = self->avgnumouterits;
-	newSleSolver->avgtimeinnerits = self->avgtimeinnerits; 
-	newSleSolver->avgtimeouterits = self->avgtimeouterits; 
-	newSleSolver->avgtimenonlinearits = self->avgtimenonlinearits; 
-	newSleSolver->currenttimestep = self->currenttimestep; 
-	newSleSolver->previoustimestep = self->previoustimestep;
-	
-	if( deep ) {
-          if( (newSleSolver->debug = (Stream*)PtrMap_Find( map, self->debug )) == NULL ) {
-			newSleSolver->debug = (Stream*)Stg_Class_Copy( self->debug, NULL, deep, nameExt, map );
-			PtrMap_Append( map, self->debug, newSleSolver->debug );
-		}
-          if( (newSleSolver->extensionManager = (ExtensionManager*)PtrMap_Find( map, self->extensionManager )) == NULL ) {
-			newSleSolver->extensionManager = (ExtensionManager*)Stg_Class_Copy( self->extensionManager, NULL, deep, nameExt, map );
-			PtrMap_Append( map, self->extensionManager, newSleSolver->extensionManager );
-		}
-	}
-	else {
-		newSleSolver->debug = self->debug;
-		newSleSolver->extensionManager = (ExtensionManager*)Stg_Class_Copy( self->extensionManager, NULL, deep, nameExt, map );
-	}
-	
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-	
-	return (void*)newSleSolver;
-}
-
-
-void _SLE_Solver_Delete( void* sleSolver ) {
-	SLE_Solver* self = (SLE_Solver*)sleSolver;
-
-	_Stg_Component_Delete( self );	
-}
-
-void _SLE_Solver_Print( void* sleSolver, Stream* stream ) {
-	SLE_Solver*		self = (SLE_Solver*)sleSolver;
-
-	_Stg_Component_Print( self, stream );
-
-	Journal_PrintPointer( stream, self->extensionManager );
-	
-	Journal_PrintPointer( stream, self->_solverSetup );
-	Journal_PrintPointer( stream, self->_solve );
-	Journal_PrintPointer( stream, self->_getResidual );
-
-	Journal_PrintPointer( stream, self->debug );
-	Journal_PrintValue( stream, self->maxIterations );
-}
-
-void _SLE_Solver_Build( void* sleSolver, void* data ) {
-	/* Do nothing by default */
-}
-
-void _SLE_Solver_AssignFromXML( void* sleSolver, Stg_ComponentFactory* cf, void* data ) {
-	SLE_Solver*		self = (SLE_Solver*)sleSolver;
-	Bool            useStatSolve;
-	int             nStatReps;
-
-	self->context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
-	if( !self->context  )
-		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
-
-	useStatSolve = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"statSolve", False  );
-	nStatReps = Stg_ComponentFactory_GetInt( cf, self->name, (Dictionary_Entry_Key)"statReps", 0  );
-
-	_SLE_Solver_Init( self, useStatSolve, nStatReps );
-}
-
-void _SLE_Solver_Initialise( void* sleSolver, void* data ) {
-}
-
-
-void _SLE_Solver_Execute( void* sleSolver, void* data ) {
-	SLE_Solver*		self = (SLE_Solver*)sleSolver;
-
-	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
-
-	Stream_IndentBranch( StgFEM_Debug );
-	SLE_Solver_SolverSetup( self, data );
-	SLE_Solver_Solve( self, data );
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _SLE_Solver_Destroy( void* sleSolver, void* data ) {
-	SLE_Solver* self = (SLE_Solver*)sleSolver;
-
-	Stg_Class_Delete( self->extensionManager );
-}
-
-void SLE_Solver_SolverSetup( void* sleSolver, void* sle ) {
-	SLE_Solver*		self = (SLE_Solver*)sleSolver;
-	
-	self->_solverSetup( self, sle );
-}
-
-
-void SLE_Solver_Solve( void* sleSolver, void* sle ) {
-	SLE_Solver*		self = (SLE_Solver*)sleSolver;
-	
-	self->_solve( self, sle );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/SLE_Solver.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/SLE_Solver.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,256 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: SLE_Solver.c 1125 2008-05-12 14:22:02Z DavidMay $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "FiniteElementContext.h"
+#include "SLE_Solver.h"
+
+#include <assert.h>
+
+/** Textual name of this class */
+const Type SLE_Solver_Type = "SLE_Solver";
+
+SLE_Solver* _SLE_Solver_New(  SLE_SOLVER_DEFARGS  )
+{	
+	SLE_Solver*		self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(SLE_Solver) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (SLE_Solver*) _Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual info */
+	self->_solverSetup = _solverSetup;
+	self->_solve = _solve;
+	self->_getResidual = _getResidual;
+
+	self->_formResidual = NULL;
+	self->_getRhs       = NULL;
+	self->_getSolution  = NULL;
+
+	return self;
+
+}
+
+void _SLE_Solver_Init( SLE_Solver* self, Bool useStatSolve, int statReps ) {
+	self->isConstructed = True;
+	self->extensionManager = ExtensionManager_New_OfExistingObject( self->name, self );
+	
+	self->debug         = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
+	self->info          = Journal_MyStream( Info_Type, self );
+	self->maxIterations = 0;
+
+	self->previoustimestep = 0;
+	self->currenttimestep = 0;
+	self->nonlinearitsinitialtime = 0; 
+	self->nonlinearitsendtime = 0; 
+	self->totalnonlinearitstime = 0; 
+	self->totalnumnonlinearits = 0; 
+	self->avgtimenonlinearits = 0; 	
+	self->inneritsinitialtime = 0; 
+	self->outeritsinitialtime = 0; 
+	self->inneritsendtime = 0; 
+	self->outeritsendtime = 0; 
+	self->totalinneritstime = 0; 
+	self->totalouteritstime = 0; 
+	self->totalnuminnerits = 0; 
+	self->totalnumouterits = 0; 
+	self->avgnuminnerits = 0; 
+	self->avgnumouterits = 0; 
+	self->avgtimeinnerits = 0; 
+	self->avgtimeouterits = 0;
+	
+	self->useStatSolve = useStatSolve;
+	self->nStatReps     = statReps;
+}
+
+void SLE_Solver_InitAll( void* sleSolver, Bool useStatSolve, int statReps ) {
+	_SLE_Solver_Init( (SLE_Solver*) sleSolver, useStatSolve, statReps );
+}
+
+void* _SLE_Solver_Copy( const void* sleSolver, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	SLE_Solver*		self = (SLE_Solver*)sleSolver;
+	SLE_Solver*		newSleSolver;
+	PtrMap*			map = ptrMap;
+	Bool			ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newSleSolver = (SLE_Solver*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
+	
+	/* virtual functions */
+	newSleSolver->_solverSetup  = self->_solverSetup;
+	newSleSolver->_solve        = self->_solve;
+	newSleSolver->maxIterations = self->maxIterations;
+
+	newSleSolver->inneritsinitialtime = self->inneritsinitialtime;
+	newSleSolver->outeritsinitialtime = self->outeritsinitialtime;
+	newSleSolver->nonlinearitsinitialtime = self->nonlinearitsinitialtime;
+	newSleSolver->inneritsendtime = self->inneritsendtime;
+	newSleSolver->outeritsendtime = self->outeritsendtime;
+	newSleSolver->nonlinearitsendtime = self->nonlinearitsendtime;
+	newSleSolver->totalinneritstime = self->totalinneritstime;
+	newSleSolver->totalouteritstime = self->totalouteritstime;
+	newSleSolver->totalnonlinearitstime = self->totalnonlinearitstime;
+	newSleSolver->totalnuminnerits = self->totalnuminnerits; 
+	newSleSolver->totalnumouterits = self->totalnumouterits; 
+	newSleSolver->totalnumnonlinearits = self->totalnumnonlinearits; 	
+	newSleSolver->avgnuminnerits = self->avgnuminnerits;
+    newSleSolver->avgnumouterits = self->avgnumouterits;
+	newSleSolver->avgtimeinnerits = self->avgtimeinnerits; 
+	newSleSolver->avgtimeouterits = self->avgtimeouterits; 
+	newSleSolver->avgtimenonlinearits = self->avgtimenonlinearits; 
+	newSleSolver->currenttimestep = self->currenttimestep; 
+	newSleSolver->previoustimestep = self->previoustimestep;
+	
+	if( deep ) {
+          if( (newSleSolver->debug = (Stream*)PtrMap_Find( map, self->debug )) == NULL ) {
+			newSleSolver->debug = (Stream*)Stg_Class_Copy( self->debug, NULL, deep, nameExt, map );
+			PtrMap_Append( map, self->debug, newSleSolver->debug );
+		}
+          if( (newSleSolver->extensionManager = (ExtensionManager*)PtrMap_Find( map, self->extensionManager )) == NULL ) {
+			newSleSolver->extensionManager = (ExtensionManager*)Stg_Class_Copy( self->extensionManager, NULL, deep, nameExt, map );
+			PtrMap_Append( map, self->extensionManager, newSleSolver->extensionManager );
+		}
+	}
+	else {
+		newSleSolver->debug = self->debug;
+		newSleSolver->extensionManager = (ExtensionManager*)Stg_Class_Copy( self->extensionManager, NULL, deep, nameExt, map );
+	}
+	
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+	
+	return (void*)newSleSolver;
+}
+
+
+void _SLE_Solver_Delete( void* sleSolver ) {
+	SLE_Solver* self = (SLE_Solver*)sleSolver;
+
+	_Stg_Component_Delete( self );	
+}
+
+void _SLE_Solver_Print( void* sleSolver, Stream* stream ) {
+	SLE_Solver*		self = (SLE_Solver*)sleSolver;
+
+	_Stg_Component_Print( self, stream );
+
+	Journal_PrintPointer( stream, self->extensionManager );
+	
+	Journal_PrintPointer( stream, self->_solverSetup );
+	Journal_PrintPointer( stream, self->_solve );
+	Journal_PrintPointer( stream, self->_getResidual );
+
+	Journal_PrintPointer( stream, self->debug );
+	Journal_PrintValue( stream, self->maxIterations );
+}
+
+void _SLE_Solver_Build( void* sleSolver, void* data ) {
+	/* Do nothing by default */
+}
+
+void _SLE_Solver_AssignFromXML( void* sleSolver, Stg_ComponentFactory* cf, void* data ) {
+	SLE_Solver*		self = (SLE_Solver*)sleSolver;
+	Bool            useStatSolve;
+	int             nStatReps;
+
+	self->context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
+	if( !self->context  )
+		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
+
+	useStatSolve = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"statSolve", False  );
+	nStatReps = Stg_ComponentFactory_GetInt( cf, self->name, (Dictionary_Entry_Key)"statReps", 0  );
+
+	_SLE_Solver_Init( self, useStatSolve, nStatReps );
+}
+
+void _SLE_Solver_Initialise( void* sleSolver, void* data ) {
+}
+
+
+void _SLE_Solver_Execute( void* sleSolver, void* data ) {
+	SLE_Solver*		self = (SLE_Solver*)sleSolver;
+
+	Journal_DPrintf( self->debug, "In %s()\n", __func__ );
+
+	Stream_IndentBranch( StgFEM_Debug );
+	SLE_Solver_SolverSetup( self, data );
+	SLE_Solver_Solve( self, data );
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _SLE_Solver_Destroy( void* sleSolver, void* data ) {
+	SLE_Solver* self = (SLE_Solver*)sleSolver;
+
+	Stg_Class_Delete( self->extensionManager );
+}
+
+void SLE_Solver_SolverSetup( void* sleSolver, void* sle ) {
+	SLE_Solver*		self = (SLE_Solver*)sleSolver;
+	
+	self->_solverSetup( self, sle );
+}
+
+
+void SLE_Solver_Solve( void* sleSolver, void* sle ) {
+	SLE_Solver*		self = (SLE_Solver*)sleSolver;
+	
+	self->_solve( self, sle );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/SROpGenerator.c
--- a/SLE/SystemSetup/src/SROpGenerator.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1331 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: SROpGenerator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-
-#include "SystemSetup.h"
-
-#include "petsc.h"
-#include "petscvec.h"
-#include "petscmat.h"
-
-/* Textual name of this class */
-const Type SROpGenerator_Type = "SROpGenerator";
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Constructors
-*/
-
-SROpGenerator* SROpGenerator_New( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(SROpGenerator);
-	Type                                                      type = SROpGenerator_Type;
-	Stg_Class_DeleteFunction*                              _delete = _SROpGenerator_Delete;
-	Stg_Class_PrintFunction*                                _print = _SROpGenerator_Print;
-	Stg_Class_CopyFunction*                                  _copy = NULL;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (void* (*)(Name))SROpGenerator_New;
-	Stg_Component_ConstructFunction*                    _construct = _SROpGenerator_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _SROpGenerator_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _SROpGenerator_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _SROpGenerator_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _SROpGenerator_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-	MGOpGenerator_SetNumLevelsFunc*               setNumLevelsFunc = _MGOpGenerator_SetNumLevels;
-	MGOpGenerator_HasExpiredFunc*                   hasExpiredFunc = SROpGenerator_HasExpired;
-	MGOpGenerator_GenerateFunc*                       generateFunc = SROpGenerator_Generate;
-
-	return _SROpGenerator_New(  SROPGENERATOR_PASSARGS  );
-}
-
-SROpGenerator* _SROpGenerator_New(  SROPGENERATOR_DEFARGS  ) {
-	SROpGenerator*	self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(SROpGenerator) );
-	self = (SROpGenerator*)_MGOpGenerator_New(  MGOPGENERATOR_PASSARGS  );
-
-	/* Virtual info */
-
-	/* SROpGenerator info */
-	_SROpGenerator_Init( self );
-
-	return self;
-}
-
-void _SROpGenerator_Init( SROpGenerator* self ) {
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-
-	self->fineVar = NULL;
-	self->fineEqNum = NULL;
-	self->meshes = NULL;
-	self->topMaps = NULL;
-	self->eqNums = NULL;
-	self->nLocalEqNums = NULL;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Virtual functions
-*/
-
-void _SROpGenerator_Delete( void* srOpGenerator ) {
-	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-
-	/* Delete the parent. */
-	_MGOpGenerator_Delete( self );
-}
-
-void _SROpGenerator_Print( void* srOpGenerator, Stream* stream ) {
-	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
-	
-	/* Set the Journal for printing informations */
-	Stream* srOpGeneratorStream;
-	srOpGeneratorStream = Journal_Register( InfoStream_Type, (Name)"SROpGeneratorStream"  );
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-
-	/* Print parent */
-	Journal_Printf( stream, "SROpGenerator (ptr): (%p)\n", self );
-	_MGOpGenerator_Print( self, stream );
-}
-
-void _SROpGenerator_AssignFromXML( void* srOpGenerator, Stg_ComponentFactory* cf, void* data ) {
-	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
-	FeVariable*	var;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-
-	var = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"fineVariable", FeVariable, True, data  );
-	SROpGenerator_SetFineVariable( self, var );
-}
-
-void _SROpGenerator_Build( void* srOpGenerator, void* data ) {
-}
-
-void _SROpGenerator_Initialise( void* srOpGenerator, void* data ) {
-}
-
-void _SROpGenerator_Execute( void* srOpGenerator, void* data ) {
-}
-
-void _SROpGenerator_Destroy( void* srOpGenerator, void* data ) {
-}
-
-Bool SROpGenerator_HasExpired( void* srOpGenerator ) {
-	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-
-	return False;
-}
-
-//void SROpGenerator_Generate( void* srOpGenerator, Matrix*** pOps, Matrix*** rOps ) {
-void SROpGenerator_Generate( void* srOpGenerator, Mat** pOps, Mat** rOps ) {
-	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-	assert( pOps && rOps );
-
-	//*pOps = AllocArray( Matrix*, self->nLevels );
-	//*rOps = AllocArray( Matrix*, self->nLevels );
-	//memset( *pOps, 0, self->nLevels * sizeof(Matrix*) );
-	//memset( *rOps, 0, self->nLevels * sizeof(Matrix*) );
-	*pOps = AllocArray( Mat, self->nLevels );
-	*rOps = AllocArray( Mat, self->nLevels );
-	memset( *pOps, 0, self->nLevels * sizeof(Mat) );
-	memset( *rOps, 0, self->nLevels * sizeof(Mat) );
-
-/*
-	self->fineEqNum = self->fineVar->eqNum;
-	SROpGenerator_GenMeshes( self );
-	SROpGenerator_GenOps( self, *pOps, *rOps );
-	SROpGenerator_DestructMeshes( self );
-*/
-        SROpGenerator_Simple( self, *pOps, *rOps );
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------------------
-** Public Functions
-*/
-
-void SROpGenerator_SetFineVariable( void* srOpGenerator, void* _variable ) {
-	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
-	FeVariable*	variable = (FeVariable*)_variable;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-	assert( !variable || Stg_CheckType( variable, FeVariable ) );
-
-	SROpGenerator_DestructMeshes( self );
-	self->fineVar = variable;
-	self->fineEqNum = NULL;
-}
-
-
-/*----------------------------------------------------------------------------------------------------------------------------------
-** Private Functions
-*/
-
-void SROpGenerator_GenMeshes( SROpGenerator* self ) {
-	unsigned	nLevels;
-	unsigned	l_i;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-
-	nLevels = self->nLevels;
-	self->meshes = AllocArray( Mesh*, nLevels );
-	memset( self->meshes, 0, nLevels * sizeof(Mesh*) );
-	self->topMaps = AllocArray( unsigned*, nLevels );
-	memset( self->topMaps, 0, nLevels * sizeof(unsigned*) );
-	self->eqNums = AllocArray( unsigned**, nLevels );
-	memset( self->eqNums, 0, nLevels * sizeof(unsigned**) );
-	self->nLocalEqNums = AllocArray( unsigned, nLevels );
-	memset( self->nLocalEqNums, 0, nLevels * sizeof(unsigned) );
-	self->eqNumBases = AllocArray( unsigned, nLevels );
-	memset( self->eqNumBases, 0, nLevels * sizeof(unsigned) );
-
-	self->meshes[nLevels - 1] = (Mesh*)self->fineEqNum->feMesh;
-	self->eqNumBases[nLevels - 1] = self->fineEqNum->firstOwnedEqNum;
-	for( l_i = nLevels - 2; l_i < nLevels; l_i-- ) {
-		SROpGenerator_GenLevelMesh( self, l_i );
-		SROpGenerator_GenLevelTopMap( self, l_i );
-		SROpGenerator_GenLevelEqNums( self, l_i );
-	}
-}
-
-void SROpGenerator_GenLevelMesh( SROpGenerator* self, unsigned level ) {
-	Stream*			errorStream = Journal_Register( ErrorStream_Type, (Name)"SROpGenerator::GenLevelMesh"  );
-	Mesh			*fMesh, *cMesh;
-	CartesianGenerator	*fGen, *cGen;
-	unsigned		nDims;
-	unsigned*		cSize;
-	double			crdMin[3], crdMax[3];
-	unsigned		d_i;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-	assert( self->meshes );
-	assert( level < self->nLevels );
-
-	fMesh = self->meshes[level + 1];
-	nDims = Mesh_GetDimSize( fMesh );
-	fGen = (CartesianGenerator*)fMesh->generator;
-	Journal_Firewall( fGen && !strcmp( fGen->type, CartesianGenerator_Type ), 
-			  errorStream, 
-			  "\n" \
-			  "****************************************************************\n" \
-			  "* Error: Simple regular multigrid operator generation requires *\n" \
-			  "*        a fine mesh that has been generated with a            *\n" \
-			  "*        cartesian generator.                                  *\n" \
-			  "****************************************************************\n" \
-			  "\n" );
-
-	cGen = CartesianGenerator_New( "", NULL );
-	CartesianGenerator_SetDimSize( cGen, nDims );
-	cSize = AllocArray( unsigned, nDims );
-	for( d_i = 0; d_i < nDims; d_i++ )
-		cSize[d_i] = fGen->elGrid->sizes[d_i] / 2;
-	CartesianGenerator_SetTopologyParams( cGen, cSize, fGen->maxDecompDims, fGen->minDecomp, fGen->maxDecomp );
-	Mesh_GetGlobalCoordRange( fMesh, crdMin, crdMax );
-	CartesianGenerator_SetGeometryParams( cGen, crdMin, crdMax );
-	CartesianGenerator_SetShadowDepth( cGen, 0 );
-	FreeArray( cSize );
-
-	cMesh = (Mesh*)FeMesh_New( "", NULL );
-	Mesh_SetGenerator( cMesh, cGen );
-	FeMesh_SetElementFamily( cMesh, ((FeMesh*)fMesh)->feElFamily );
-	Stg_Component_Build( cMesh, NULL, False );
-	Stg_Component_Initialise( cMesh, NULL, False );
-	self->meshes[level] = cMesh;
-}
-
-void SROpGenerator_GenLevelTopMap( SROpGenerator* self, unsigned level ) {
-	Stream*		errorStream = Journal_Register( ErrorStream_Type, (Name)"SROpGenerator::GenLevelTopMap"  );
-	Mesh		*fMesh, *cMesh;
-	unsigned	nDomainNodes;
-	unsigned	nLevels;
-	unsigned	nDims;
-	unsigned	nearest;
-	double		*cVert, *fVert;
-	unsigned	d_i, n_i;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-	assert( self->meshes );
-	assert( level < self->nLevels );
-
-	fMesh = self->meshes[level + 1];
-	cMesh = self->meshes[level];
-	nDims = Mesh_GetDimSize( fMesh );
-	nLevels = self->nLevels;
-	nDomainNodes = Mesh_GetDomainSize( cMesh, MT_VERTEX );
-	self->topMaps[level] = ReallocArray( self->topMaps[level], unsigned, nDomainNodes );
-	for( n_i = 0; n_i < nDomainNodes; n_i++ ) {
-		cVert = Mesh_GetVertex( cMesh, n_i );
-		nearest = Mesh_NearestVertex( fMesh, cVert );
-		fVert = Mesh_GetVertex( fMesh, nearest );
-		for( d_i = 0; d_i < nDims; d_i++ ) {
-			if( !Num_Approx( cVert[d_i], fVert[d_i] ) )
-				break;
-		}
-
-		Journal_Firewall( d_i == nDims, 
-				  errorStream, 
-				  "\n" \
-				  "*****************************************************************\n" \
-				  "* Error: The finest grid could not be sub-sampled to all coarse *\n" \
-				  "*        levels. This is due to the size of the finest grid.    *\n" \
-				  "*****************************************************************\n" \
-				  "\n" );
-
-		if( level < nLevels - 2 )
-			self->topMaps[level][n_i] = self->topMaps[level + 1][nearest];
-		else
-			self->topMaps[level][n_i] = nearest;
-	}
-}
-
-void SROpGenerator_GenLevelEqNums( SROpGenerator* self, unsigned level ) {
-	Mesh*			cMesh;
-	unsigned*		nNodalDofs;
-	unsigned		nDomainNodes, nLocalNodes;
-	DofLayout*		dofLayout;
-	unsigned**		dstArray;
-	unsigned		curEqNum;
-	unsigned		maxDofs;
-	unsigned		topNode;
-	unsigned		base, subTotal;
-	MPI_Comm		comm;
-	unsigned		nProcs, rank;
-	MPI_Status		status;	
-	unsigned*		tuples;
-	Sync*			sync;
-	unsigned		n_i, dof_i;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-	assert( self->meshes && self->topMaps && self->eqNums );
-	assert( level < self->nLevels );
-
-	cMesh = self->meshes[level];
-	nDomainNodes = Mesh_GetDomainSize( cMesh, MT_VERTEX );
-	nLocalNodes = Mesh_GetLocalSize( cMesh, MT_VERTEX );
-	dofLayout = self->fineEqNum->dofLayout;
-	comm = Comm_GetMPIComm( Mesh_GetCommTopology( cMesh, MT_VERTEX ) );
-	MPI_Comm_size( comm, (int*)&nProcs );
-	MPI_Comm_rank( comm, (int*)&rank );
-
-	/* Allocate for destination array. */
-	nNodalDofs = AllocArray( unsigned, nDomainNodes );
-	for( n_i = 0; n_i < nDomainNodes; n_i++ )
-		nNodalDofs[n_i] = dofLayout->dofCounts[self->topMaps[level][n_i]];
-	dstArray = AllocComplex2D( unsigned, nDomainNodes, nNodalDofs );
-
-	/* Build initial destination array and store max dofs. */
-	curEqNum = 0;
-	maxDofs = 0;
-	for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
-		if( nNodalDofs[n_i] > maxDofs )
-			maxDofs = nNodalDofs[n_i];
-
-		topNode = self->topMaps[level][n_i];
-		for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
-			if( self->fineEqNum->destinationArray[topNode][dof_i] != (unsigned)-1 )
-				dstArray[n_i][dof_i] = curEqNum++;
-			else
-				dstArray[n_i][dof_i] = (unsigned)-1;
-		}
-	}
-
-	/* Order the equation numbers based on processor rank; cascade counts forward. */
-	base = 0;
-	subTotal = curEqNum;
-	if( rank > 0 ) {
-		insist( MPI_Recv( &base, 1, MPI_UNSIGNED, rank - 1, 6669, comm, &status ), == MPI_SUCCESS );
-		subTotal = base + curEqNum;
-	}
-	if( rank < nProcs - 1 )
-		insist( MPI_Send( &subTotal, 1, MPI_UNSIGNED, rank + 1, 6669, comm ), == MPI_SUCCESS );
-
-	/* Modify existing destination array and dump to a tuple array. */
-	tuples = AllocArray( unsigned, nDomainNodes * maxDofs );
-	for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
-		for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
-			if( dstArray[n_i][dof_i] != (unsigned)-1 )
-				dstArray[n_i][dof_i] += base;
-			tuples[n_i * maxDofs + dof_i] = dstArray[n_i][dof_i];
-		}
-	}
-
-	/* Update all other procs. */
-	sync = Mesh_GetSync( cMesh, MT_VERTEX );
-	Sync_SyncArray( sync, tuples, maxDofs * sizeof(unsigned), 
-			tuples + nLocalNodes * maxDofs, maxDofs * sizeof(unsigned), 
-			maxDofs * sizeof(unsigned) );
-
-	/* Update destination array's domain indices. */
-	for( n_i = nLocalNodes; n_i < nDomainNodes; n_i++ ) {
-		topNode = self->topMaps[level][n_i];
-		for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
-			if( self->fineEqNum->destinationArray[topNode][dof_i] != (unsigned)-1 )
-				dstArray[n_i][dof_i] = tuples[n_i * maxDofs + dof_i];
-			else
-				dstArray[n_i][dof_i] = -1;
-		}
-	}
-
-	/* Destroy arrays. */
-	FreeArray( nNodalDofs );
-	FreeArray( tuples );
-
-	self->eqNums[level] = dstArray;
-	self->nLocalEqNums[level] = curEqNum;
-	self->eqNumBases[level] = base;
-}
-
-//void SROpGenerator_GenOps( SROpGenerator* self, Matrix** pOps, Matrix** rOps ) {
-void SROpGenerator_GenOps( SROpGenerator* self, Mat* pOps, Mat* rOps ) {
-	unsigned	nLevels;
-	//Matrix		*fineMat, *P;
-	Mat		fineMat, P;
-	unsigned	nRows, nCols;
-	unsigned	l_i;
-	/* unsigned	nProcs; */
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-	assert( pOps && rOps );
-
-	//fineMat = MatrixSolver_GetMatrix( self->solver );
-	fineMat = self->solver->matrix;
-	nLevels = self->nLevels;
-
-	for( l_i = nLevels - 1; l_i > 0; l_i-- ) {
-		nRows = self->eqNums[l_i] ? self->nLocalEqNums[l_i] : 
-			self->fineEqNum->localEqNumsOwnedCount;
-		nCols = self->nLocalEqNums[l_i - 1];
-
-		//Matrix_Duplicate( fineMat, (void**)&P );
-		//Matrix_SetComm( P, fineMat->comm );
-		//Matrix_SetLocalSize( P, nRows, nCols );
-		MatCreate( self->solver->comm, &P );
-		MatSetSizes( P, nRows, nCols, PETSC_DETERMINE, PETSC_DETERMINE );
-		MatSetFromOptions( P );
-		//if( !strcmp( P->type, PETScMatrix_Type ) ) {
-		//	unsigned	*nDiagNonZeros, *nOffDiagNonZeros;
-		//
-		//	SROpGenerator_CalcOpNonZeros( self, l_i, &nDiagNonZeros, &nOffDiagNonZeros );
-			//PETScMatrix_SetNonZeroStructure( (PETScMatrix*)P, 0, nDiagNonZeros, nOffDiagNonZeros );
-		//	MPI_Comm_size( self->solver->comm, &nProcs );
-		//	if( nProcs > 1 )
-		//		MatMPIAIJSetPreallocation( P, PETSC_NULL, nDiagNonZeros, PETSC_NULL, nOffDiagNonZeros );
-		//	else
-		//		MatSeqAIJSetPreallocation( P, PETSC_NULL, nDiagNonZeros );
-		//	FreeArray( nDiagNonZeros );
-		//	FreeArray( nOffDiagNonZeros );
-		//}
-
-		SROpGenerator_GenLevelOp( self, l_i, P );
-		pOps[l_i] = P;
-		//Stg_Class_AddRef( P );
-		rOps[l_i] = P;
-		//Stg_Class_AddRef( P );
-	}
-}
-
-//void SROpGenerator_GenLevelOp( SROpGenerator* self, unsigned level, Matrix* P ) {
-void SROpGenerator_GenLevelOp( SROpGenerator* self, unsigned level, Mat P ) {
-	Mesh		*fMesh, *cMesh;
-	unsigned	nDims;
-	unsigned	nLocalFineNodes;
-	DofLayout*	dofLayout;
-	unsigned	ind;
-	unsigned	nInc, *inc;
-	unsigned	maxInc;
-	unsigned	fTopNode, cTopNode;
-	unsigned	fEqNum, cEqNum;
-	double		*localCoord, *basis;
-	IArray		*incArray;
-	unsigned	n_i, dof_i, inc_i, e_i;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-	assert( self->meshes );
-	assert( level < self->nLevels );
-	assert( P );
-
-	fMesh = self->meshes[level];
-	cMesh = self->meshes[level - 1];
-	nDims = Mesh_GetDimSize( fMesh );
-	nLocalFineNodes = Mesh_GetLocalSize( fMesh, MT_VERTEX );
-	dofLayout = self->fineEqNum->dofLayout;
-	localCoord = AllocArray( double, nDims );
-
-	maxInc = 0;
-	for( e_i = 0; e_i < Mesh_GetDomainSize( cMesh, (MeshTopology_Dim)nDims ); e_i++ ) {
-          nInc = Mesh_GetIncidenceSize( cMesh, (MeshTopology_Dim)nDims, e_i, MT_VERTEX );
-		if( nInc > maxInc )
-			maxInc = nInc;
-	}
-	basis = AllocArray( double, maxInc );
-
-	incArray = IArray_New();
-	for( n_i = 0; n_i < nLocalFineNodes; n_i++ ) {
-		if( self->topMaps[level] )
-			fTopNode = self->topMaps[level][n_i];
-		else
-			fTopNode = n_i;
-
-		for( dof_i = 0; dof_i < dofLayout->dofCounts[fTopNode]; dof_i++ ) {
-			if( self->eqNums[level] )
-				fEqNum = self->eqNums[level][n_i][dof_i];
-			else
-				fEqNum = self->fineEqNum->destinationArray[fTopNode][dof_i];
-
-			if( fEqNum == (unsigned)-1 )
-				continue;
-
-			insist( Mesh_SearchElements( cMesh, Mesh_GetVertex( fMesh, n_i ), &ind ), == True );
-			FeMesh_CoordGlobalToLocal( cMesh, ind, Mesh_GetVertex( fMesh, n_i ), localCoord );
-			FeMesh_EvalBasis( cMesh, ind, localCoord, basis );
-			Mesh_GetIncidence( cMesh, (MeshTopology_Dim)nDims, ind, MT_VERTEX, incArray );
-			nInc = IArray_GetSize( incArray );
-			inc = (unsigned*)IArray_GetPtr( incArray );
-			for( inc_i = 0; inc_i < nInc; inc_i++ ) {
-				cTopNode = self->topMaps[level - 1][inc[inc_i]];
-				cEqNum = self->eqNums[level - 1][inc[inc_i]][dof_i];
-				if( cEqNum != (unsigned)-1 && !Num_Approx( basis[inc_i], 0.0 ) )
-					//Matrix_InsertEntries( P, 1, &fEqNum, 1, &cEqNum, basis + inc_i );
-                                  MatSetValues( P, 1, (PetscInt*)(&fEqNum), 1, (PetscInt*)(&cEqNum), basis + inc_i, INSERT_VALUES );
-			}
-		}
-	}
-	NewClass_Delete( incArray );
-
-	FreeArray( localCoord );
-	FreeArray( basis );
-
-	//Matrix_AssemblyBegin( P );
-	//Matrix_AssemblyEnd( P );
-	MatAssemblyBegin( P, MAT_FINAL_ASSEMBLY );
-	MatAssemblyEnd( P, MAT_FINAL_ASSEMBLY );
-}
-
-void SROpGenerator_CalcOpNonZeros( SROpGenerator* self, unsigned level, 
-				   unsigned** nDiagNonZeros, unsigned** nOffDiagNonZeros )
-{
-	Mesh		*fMesh, *cMesh;
-	unsigned	nLocalFineNodes;
-	DofLayout*	dofLayout;
-	unsigned	dim, ind;
-	unsigned	nInc, *inc;
-	unsigned	fTopNode, cTopNode;
-	unsigned	fEqNum, cEqNum;
-	unsigned	nLocalEqNums;
-	IArray*		incArray;
-	unsigned	n_i, dof_i, dof_j, inc_i;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-	assert( self->meshes );
-	assert( level < self->nLevels );
-
-	fMesh = self->meshes[level];
-	cMesh = self->meshes[level - 1];
-	nLocalFineNodes = Mesh_GetLocalSize( fMesh, MT_VERTEX );
-	dofLayout = self->fineEqNum->dofLayout;
-	if( self->eqNums[level] )
-		nLocalEqNums = self->nLocalEqNums[level];
-	else
-		nLocalEqNums = self->fineEqNum->localEqNumsOwnedCount;
-
-	*nDiagNonZeros = AllocArray( unsigned, nLocalEqNums );
-	memset( *nDiagNonZeros, 0, nLocalEqNums * sizeof(unsigned) );
-	*nOffDiagNonZeros = AllocArray( unsigned, nLocalEqNums );
-	memset( *nOffDiagNonZeros, 0, nLocalEqNums * sizeof(unsigned) );
-
-	incArray = IArray_New();
-
-	for( n_i = 0; n_i < nLocalFineNodes; n_i++ ) {
-		if( self->topMaps[level] )
-			fTopNode = self->topMaps[level][n_i];
-		else
-			fTopNode = n_i;
-
-		for( dof_i = 0; dof_i < dofLayout->dofCounts[fTopNode]; dof_i++ ) {
-			if( self->eqNums[level] )
-				fEqNum = self->eqNums[level][n_i][dof_i];
-			else
-				fEqNum = self->fineEqNum->destinationArray[fTopNode][dof_i];
-
-			if( fEqNum == (unsigned)-1 )
-				continue;
-
-			insist( Mesh_SearchElements( cMesh, Mesh_GetVertex( fMesh, n_i ), &ind ), == True );
-			dim = Mesh_GetDimSize( fMesh );
-			if( dim == MT_VERTEX ) {
-				cTopNode = self->topMaps[level - 1][ind];
-				for( dof_j = 0; dof_j < dofLayout->dofCounts[cTopNode]; dof_j++ ) {
-					cEqNum = self->eqNums[level - 1][ind][dof_j];
-					if( cEqNum == (unsigned)-1 )
-						continue;
-
-					if( cEqNum - self->eqNumBases[level - 1] < nLocalEqNums )
-						(*nDiagNonZeros)[fEqNum - self->eqNumBases[level]]++;
-					else
-						(*nOffDiagNonZeros)[fEqNum - self->eqNumBases[level]]++;
-				}
-			}
-			else {
-				Mesh_GetIncidence( cMesh, (MeshTopology_Dim)dim, ind, MT_VERTEX, incArray );
-				nInc = IArray_GetSize( incArray );
-				inc = (unsigned*)IArray_GetPtr( incArray );
-				for( inc_i = 0; inc_i < nInc; inc_i++ ) {
-					cTopNode = self->topMaps[level - 1][inc[inc_i]];
-					for( dof_j = 0; dof_j < dofLayout->dofCounts[cTopNode]; dof_j++ ) {
-						cEqNum = self->eqNums[level - 1][inc[inc_i]][dof_j];
-						if( cEqNum == (unsigned)-1 )
-							continue;
-
-						if( cEqNum - self->eqNumBases[level - 1] < nLocalEqNums )
-							(*nDiagNonZeros)[fEqNum - self->eqNumBases[level]]++;
-						else
-							(*nOffDiagNonZeros)[fEqNum - self->eqNumBases[level]]++;
-					}
-				}
-			}
-		}
-	}
-
-	NewClass_Delete( incArray );
-}
-
-void SROpGenerator_DestructMeshes( SROpGenerator* self ) {
-	unsigned	nLevels;
-	unsigned	l_i;
-
-	assert( self && Stg_CheckType( self, SROpGenerator ) );
-
-	if( self->meshes ) {
-		nLevels = self->nLevels;
-		for( l_i = 0; l_i < nLevels - 1; l_i++ ) {
-			FreeObject( self->meshes[l_i] );
-			FreeArray( self->topMaps[l_i] );
-			FreeArray( self->eqNums[l_i] );
-		}
-		KillArray( self->meshes );
-		KillArray( self->topMaps );
-		KillArray( self->eqNums );
-		KillArray( self->nLocalEqNums );
-		KillArray( self->eqNumBases );
-	}
-}
-
-
-//void SROpGenerator_Simple( SROpGenerator *self, Matrix **pOps, Matrix **rOps ) {
-void SROpGenerator_Simple( SROpGenerator *self, Mat* pOps, Mat* rOps ) {
-   double t0;
-   if( self->nLevels > 1 ) {
-      //Matrix *P;
-      Mat P;
-      int ii;
-
-      t0 = MPI_Wtime();
-      P = SROpGenerator_SimpleFinestLevel( self );
-      PetscPrintf( PETSC_COMM_WORLD, "SROpGenerator_SimpleFinestLevel: time = %5.5e \n", MPI_Wtime()-t0 );
-      pOps[self->nLevels - 1] = rOps[self->nLevels - 1] = P;
-      for( ii = self->nLevels - 2; ii > 0; ii-- ) {
-	 t0 = MPI_Wtime();
-         P = SROpGenerator_SimpleCoarserLevel( self, ii );
-	 PetscPrintf( PETSC_COMM_WORLD, "  [%d] SROpGenerator_SimpleCoarserLevel: time = %5.5e \n",ii,  MPI_Wtime()-t0 );
-         pOps[ii] = rOps[ii] = P;
-      }
-   }
-}
-
-
-PetscErrorCode _VecGetOwnershipRanges( Vec X, PetscInt **_ranges )
-{
-  PetscInt start,end;
-  PetscMPIInt nproc,rank;
-  MPI_Comm comm;
-  Vec all, out;
-  VecScatter scat;
-  PetscInt *ranges,i;
-  PetscScalar *v;
-  double t0;
-
-  t0 = MPI_Wtime();
-
-  PetscObjectGetComm( (PetscObject)X, &comm );
-  MPI_Comm_size( comm, &nproc );
-  MPI_Comm_rank( comm, &rank );
-  VecGetOwnershipRange( X, &start, &end );
-
-  VecCreate( comm, &all );
-  VecSetSizes( all, PETSC_DECIDE, nproc+1 );
-  VecSetFromOptions( all );
-
-  VecSetValue( all, rank, (PetscScalar)start, INSERT_VALUES );
-  VecSetValue( all, rank+1, (PetscScalar)end, INSERT_VALUES );
-  VecAssemblyBegin( all );
-  VecAssemblyEnd( all );
-
-  VecScatterCreateToAll( all, &scat, &out );
-
-#if(PETSC_VERSION_SUBMINOR==2)
-  VecScatterBegin(all,out,INSERT_VALUES,SCATTER_FORWARD,scat);
-  VecScatterEnd(all,out,INSERT_VALUES,SCATTER_FORWARD,scat);
-#elif(PETSC_VERSION_SUBMINOR==3) 
-  VecScatterBegin(scat, all,out,INSERT_VALUES,SCATTER_FORWARD);
-  VecScatterEnd(scat, all,out,INSERT_VALUES,SCATTER_FORWARD);
-#endif
-
-  PetscMalloc( sizeof(PetscInt)*(nproc+1), &ranges );
-  VecGetArray( out, &v );
-  for( i=0; i<nproc+1; i++ ) {
-    ranges[i] = (PetscInt)v[i];
-  }
-  VecRestoreArray( out, &v );
-
-  *_ranges = ranges;
-
-  VecScatterDestroy( scat );
-  VecDestroy( out );
-  VecDestroy( all );
-
- 
-  PetscFunctionReturn(0);
-}
-
-
-/*
-Efficiency alert!!
-  This comments relates to both SROpGenerator_SimpleFinestLevel() and
-  SROpGenerator_SimpleCoarserLevel().
-  
-  For O(n) setup times, we MUST provide some information concerning the
-  preallocation of the nonzero structure for the restriction operators.
-
-  As a first hack we check the spatial dimension and choose a value accordingly. 
-  In doing so we have assumed that the fine grid is obtained by bisecting 
-  the coarse grid. Coarse grid nodes are hiearchical. We have also assumed
-  that the elements are quads (2d) and hexs (3d).
-  
-  The hack above made little effort to miminise memory usage and as such we allocate
-  the same amount of memory for the on and off diagonal parts of the restriction
-  operator. This kinda kills use in parallel.
-
-  An more accurate estimate has thus been implemented.
-*/
-//Matrix *SROpGenerator_SimpleFinestLevel( SROpGenerator *self ) {
-Mat SROpGenerator_SimpleFinestLevel( SROpGenerator *self ) {
-   FeMesh *mesh;
-   int nDims, nDofsPerNode;
-   int sideSizes[2][3];
-   int inds[2][3], offsInds[3], nOffs[3];
-   int nGlobalNodes[2];
-   int nGlobalEqs[2];
-   Grid *vertGrid, *elGrid, *grid[2], *offsGrid;
-   int nodes[8];
-   int nodeInd;
-   double dfrac;
-   int nEntries, indices[8];
-   double values[8];
-   Mat P;
-   //PETScMatrix *mat;
-   Mat mat;
-   int ii, jj, kk;
-   PetscInt o_nz, d_nz;
-   PetscInt *o_nnz, *d_nnz;
-   PetscInt sr,er, sc,ec, row_idx;
-   Vec vec_o_nnz, vec_d_nnz;
-   PetscScalar *v;
-   PetscTruth is_seq;
-   PetscInt p, proc_owner, *rranges,*cranges;
-   MPI_Comm comm;
-   PetscMPIInt nproc,rank;  
-
-   /* Calculate level side lengths. */
-   mesh = self->fineVar->feMesh;
-   nDims = Mesh_GetDimSize( mesh );
-
-   /* crude estimate of number of nonzeros in the on-off diagonal portitions of the matrix */
-   o_nz = d_nz = 0;
-   if( nDims == 2 ) {
-	o_nz = d_nz = 4;
-   }
-   if( nDims==3 ) {
-	o_nz = d_nz = 8;
-   }
-
-   nDofsPerNode = self->fineVar->dofLayout->dofCounts[0]; /* ASSUME */
-   elGrid = *Mesh_GetExtension( mesh, Grid**, "elementGrid" );
-   vertGrid = *Mesh_GetExtension( mesh, Grid**, "vertexGrid" );
-   nGlobalNodes[0] = nGlobalNodes[1] = 1;
-   for( ii = 0; ii < nDims; ii++ ) {
-      sideSizes[1][ii] = elGrid->sizes[ii];
-      sideSizes[0][ii] = elGrid->sizes[ii] / 2;
-      if( sideSizes[0][ii] * 2 != elGrid->sizes[ii] ) {
-         printf( "(MG) Error: Too many levels specified for geometric multigrid.\n" );
-         printf( "            Please modify mesh size or reduce number of levels.\n" );
-         exit( 1 );
-      }
-      sideSizes[1][ii]++; sideSizes[0][ii]++;
-      nGlobalNodes[1] *= sideSizes[1][ii];
-      nGlobalNodes[0] *= sideSizes[0][ii];
-   }
-
-   /* Have PETSc create the operator matrix and then extract local sizes
-      and offsets into the global vector. */
-   nGlobalEqs[1] = nGlobalNodes[1] * nDofsPerNode;
-   nGlobalEqs[0] = nGlobalNodes[0] * nDofsPerNode;
-/*
-   MatCreateMPIAIJ( MPI_COMM_WORLD,
-                    self->fineVar->eqNum->localEqNumsOwnedCount, PETSC_DECIDE,
-                    PETSC_DECIDE, nGlobalEqs[0],
-                    o_nz, PETSC_NULL, d_nz, PETSC_NULL, &P );
-
-*/
-   MatCreate( MPI_COMM_WORLD, &P );
-   MatSetSizes( P, self->fineVar->eqNum->localEqNumsOwnedCount, PETSC_DECIDE, PETSC_DECIDE, nGlobalEqs[0] ); 
-   MatSetType( P, MATAIJ );
-//   MatGetOwnershipRange( P, &sr, &er );
-
-   PetscObjectGetComm( (PetscObject)P, &comm );
-   MPI_Comm_size( comm, &nproc );
-   MPI_Comm_rank( comm, &rank );
-
-//   printf( "  sr,er = %d -> %d \n", sr, er );
-   {  Vec L,R;
-      PetscInt M,N, m,n;     
-      
-      MatGetSize( P, &M,&N );
-      MatGetLocalSize( P, &m,&n );
-//      PetscPrintf( PETSC_COMM_WORLD, "size = %D x %D \n", M, N );
-      MatGetVecs( P, &R, &L );
-      VecGetOwnershipRange( L, &sr,&er );
-      VecGetOwnershipRange( R, &sc,&ec );
-//      printf( "  [%d] mxn = %d x %d ; sr,er = %d -> %d ; sc,ec = %d -> %d \n", rank, m,n,  sr,er, sc,ec );
-
-      _VecGetOwnershipRanges( L, &rranges );
-      _VecGetOwnershipRanges( R, &cranges );
-
-      VecDestroy( L );
-      VecDestroy( R );
-    }
-  
-   PetscMalloc( sizeof(PetscInt)*(er-sr), &o_nnz );
-   PetscMalloc( sizeof(PetscInt)*(er-sr), &d_nnz );
-
-   /* Need a grid representing the coarse level. */
-   grid[0] = Grid_New();
-   offsGrid = Grid_New();
-   Grid_SetNumDims( grid[0], nDims );
-   Grid_SetNumDims( offsGrid, nDims );
-   Grid_SetSizes( grid[0], (unsigned*)(sideSizes[0]) );
-
-   /* Determine preallocation information */
-   MatGetVecs( P, PETSC_NULL, &vec_d_nnz );
-   VecDuplicate( vec_d_nnz, &vec_o_nnz );
-
-   /* Loop over fine nodes. */
-   for( ii = 0; ii < Mesh_GetLocalSize( mesh, (MeshTopology_Dim)0 ); ii++ ) {
-      nodeInd = Mesh_DomainToGlobal( mesh, (MeshTopology_Dim)0, ii );
-      Grid_Lift( vertGrid, nodeInd, (unsigned*)(inds[1]) );
-
-      /* An odd grid index means we need to interpolate from surrounding
-         coarse nodes in the current dimension. */
-      for( jj = 0; jj < nDims; jj++ ) {
-         /* Store the offsets we need to consider. */
-         nOffs[jj] = (inds[1][jj] & 1) ? 2 : 1;
-      }
-
-      /* 'Multiply' the offsets to build the set of nodes we need to
-         interpolate from. */
-      Grid_SetSizes( offsGrid, (unsigned*)nOffs );
-      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-         Grid_Lift( offsGrid, jj, (unsigned*)offsInds );
-         for( kk = 0; kk < nDims; kk++ )
-            inds[0][kk] = (inds[1][kk] >> 1) + offsInds[kk];
-
-         /* Store the coarse global node number. */
-         nodes[jj] = Grid_Project( grid[0], (unsigned*)(inds[0]) );
-      }
-
-      /* Insert this row into the operator matrix. */
-      nEntries = offsGrid->nPoints;
-      for( kk = 0; kk < nDofsPerNode; kk++ ) {
-         /* Skip the entire thing if it's a BC. */
-         if( self->fineVar->eqNum->destinationArray[ii][kk] == -1 )
-            continue;
-
-         row_idx = (PetscInt)(self->fineVar->eqNum->destinationArray[ii][kk]);
-
-
-         /* find owning proc */
-         proc_owner = -1;
-         for( p=0; p<nproc; p++ ) {
-            if( (row_idx>=rranges[p]) && (row_idx<rranges[p+1]) ) {
-               proc_owner = p;
-               break;
-            }
-         }
-
-
-         for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-            indices[jj] = nodes[jj] * nDofsPerNode + kk;
-          //  printf( "[%d]: (owner=%d): row=%d : c_index=%d \n", rank, proc_owner, row_idx, indices[jj] );
-	    if( (row_idx>=rranges[proc_owner]) && (row_idx<rranges[proc_owner+1]) ) {          
-               if( (indices[jj]>=cranges[proc_owner]) && (indices[jj]<cranges[proc_owner+1]) ) {
-                  VecSetValue( vec_d_nnz, row_idx, 1.0, ADD_VALUES );
-               }
-               else {
-                  VecSetValue( vec_o_nnz, row_idx, 1.0, ADD_VALUES );
-               }
-            }
-         }
-
-
-/*
-        for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-           indices[jj] = nodes[jj] * nDofsPerNode + kk;
-	   printf( "[%d]: row=%d : c_index=%d \n", rank, row_idx, indices[jj] );
-           if( (row_idx>=sr) && (row_idx<er) ) {
-              if( (indices[jj]>=sc) && (indices[jj]<ec) ) {
-                VecSetValue( vec_d_nnz, row_idx, 1.0, ADD_VALUES );
-              }
-            }
-           else {
-              VecSetValue( vec_o_nnz, row_idx, 1.0, ADD_VALUES );
-           }
-        }
-*/
-
-
-      }
-   }
-   VecAssemblyBegin( vec_d_nnz );
-   VecAssemblyEnd( vec_d_nnz );
-
-   VecAssemblyBegin( vec_o_nnz );
-   VecAssemblyEnd( vec_o_nnz );
-
-   VecGetArray( vec_d_nnz, &v );
-   for( kk=0; kk<(er-sr); kk++ ) {
-      d_nnz[kk] = (PetscInt)v[kk];
-   }
-   VecRestoreArray( vec_d_nnz, &v );
-
-   VecGetArray( vec_o_nnz, &v );
-   for( kk=0; kk<(er-sr); kk++ ) {
-      o_nnz[kk] = (PetscInt)v[kk];
-   }
-   VecRestoreArray( vec_o_nnz, &v );
-
-   PetscTypeCompare( (PetscObject)vec_o_nnz, VECSEQ, &is_seq );
-   if(nproc==1) {
-      MatSeqAIJSetPreallocation( P, PETSC_NULL, d_nnz );
-   }
-   else {
-//     for( kk=0; kk<(er-sr); kk++ ) {
-//       printf( "[%d]: row=%d : d_nnz=%d : o_nnz=%d \n", rank, kk+sr, d_nnz[kk], o_nnz[kk] );
-//     }
-      MatMPIAIJSetPreallocation( P, PETSC_NULL, d_nnz, PETSC_NULL, o_nnz );
-
-//    MatMPIAIJSetPreallocation( P, d_nz,PETSC_NULL, o_nz,PETSC_NULL );
-   }
-
-   /* Loop over fine nodes. */
-   for( ii = 0; ii < Mesh_GetLocalSize( mesh, (MeshTopology_Dim)0 ); ii++ ) {
-//      if( ii%5000 == 0 ) {
-//        PetscPrintf( PETSC_COMM_WORLD, "Done %d of %d \n", ii, Mesh_GetLocalSize( mesh, 0 ) );
-//      }
-      nodeInd = Mesh_DomainToGlobal( mesh, (MeshTopology_Dim)0, ii );
-      Grid_Lift( vertGrid, nodeInd, (unsigned*)(inds[1]) );
-
-      /* An odd grid index means we need to interpolate from surrounding
-         coarse nodes in the current dimension. */
-      for( jj = 0; jj < nDims; jj++ ) {
-         /* Store the offsets we need to consider. */
-         nOffs[jj] = (inds[1][jj] & 1) ? 2 : 1;
-      }
-
-      /* 'Multiply' the offsets to build the set of nodes we need to
-         interpolate from. */
-      Grid_SetSizes( offsGrid, (unsigned*)nOffs );
-      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-         Grid_Lift( offsGrid, jj, (unsigned*)offsInds );
-         for( kk = 0; kk < nDims; kk++ )
-            inds[0][kk] = (inds[1][kk] >> 1) + offsInds[kk];
-
-         /* Store the coarse global node number. */
-         nodes[jj] = Grid_Project( grid[0], (unsigned*)(inds[0]) );
-      }
-
-      /* Insert this row into the operator matrix. */
-      dfrac = 1.0 / (double)offsGrid->nPoints;
-      nEntries = offsGrid->nPoints;
-      for( kk = 0; kk < nDofsPerNode; kk++ ) {
-         /* Skip the entire thing if it's a BC. */
-         if( self->fineVar->eqNum->destinationArray[ii][kk] == -1 )
-            continue;
-
-         for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-            indices[jj] = nodes[jj] * nDofsPerNode + kk;
-            values[jj] = dfrac;
-         }
-         MatSetValues( P, 1, self->fineVar->eqNum->destinationArray[ii] + kk,
-                       nEntries, indices, values, INSERT_VALUES );
-      }
-   }
-//   PetscPrintf( PETSC_COMM_WORLD, "Done all MatSetValues \n");
-
-   /* Assemble the matrix. */
-   MatAssemblyBegin( P, MAT_FINAL_ASSEMBLY );
-   MatAssemblyEnd( P, MAT_FINAL_ASSEMBLY );
-
-/*
-   {
-      PetscInt M,N, m,n;
-      for( p=0; p<nproc; p++ ) {
-        PetscPrintf( PETSC_COMM_WORLD, "[%d]: r_range (%d->%d) ; c_range (%d->%d)\n", p, rranges[p], rranges[p+1], cranges[p], cranges[p+1] );
-      }
-
-      MatGetSize( P, &M,&N );
-      MatGetLocalSize( P, &m,&n );
-      PetscPrintf( PETSC_COMM_WORLD, "P_size = %D x %D \n", M, N );
-      MatGetOwnershipRange( P, &sr,&er );
-      printf( "  [%d] mxn = %d x %d ; sr,er = %d -> %d (local rows=%d) \n", rank, m,n,  sr,er, er-sr );
-    }
-    PetscViewerSetFormat( PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_DENSE );
-    MatView( P, PETSC_VIEWER_STDOUT_WORLD );
-*/
-
-   /* Piss off those grids. */
-   Stg_Class_Delete( grid[0] );
-
-   Stg_Class_Delete(offsGrid);
-
-   VecDestroy( vec_o_nnz );
-   VecDestroy( vec_d_nnz );
-   PetscFree( o_nnz );
-   PetscFree( d_nnz );
-   PetscFree( rranges );
-   PetscFree( cranges );
-
-
-   /* Create a new matrix. */
-   //mat = PETScMatrix_New( "" );
-   //mat->petscMat = P;
-   mat = P;
-   return mat;
-}
-
-//Matrix *SROpGenerator_SimpleCoarserLevel( SROpGenerator *self, int level ) {
-Mat SROpGenerator_SimpleCoarserLevel( SROpGenerator *self, int level ) {
-   FeMesh *mesh;
-   int nDims, nDofsPerNode, rowDof;
-   int sideSizes[2][3];
-   int inds[2][3], offsInds[3], nOffs[3];
-   int nGlobalNodes[2];
-   int nGlobalEqs[2];
-   int eqRangeBegin, eqRangeEnd;
-   Grid *vertGrid, *elGrid, *grid[2], *offsGrid;
-   int nodes[8];
-   int ifrac, nodeInd;
-   double dfrac;
-   int nEntries, indices[8];
-   double values[8];
-   Mat P;
-   //PETScMatrix *mat;
-   Mat mat; 
-   int ii, jj, kk;
-   PetscInt o_nz, d_nz;
-   PetscInt *o_nnz, *d_nnz;
-   PetscInt sr,er, sc,ec, row_idx;
-   Vec vec_o_nnz, vec_d_nnz;
-   PetscScalar *v;
-   PetscInt p, proc_owner, *row_ranges, *col_ranges;
-   MPI_Comm comm;
-   PetscMPIInt nproc;
-
-   /* Calculate depth fraction. */
-   ifrac = 1;
-   for( ii = 0; ii < self->nLevels - level - 1; ii++ )
-      ifrac *= 2;
-
-   /* Calculate level side lengths. */
-   mesh = self->fineVar->feMesh;
-   nDims = Mesh_GetDimSize( mesh );
-
-   /* crude estimate of number of nonzeros in the on-off diagonal portitions of the matrix */
-   o_nz = d_nz = 0;
-   if( nDims==2 ) {
-      o_nz = d_nz = 4;
-   }
-   if( nDims==3 ) {
-        o_nz = d_nz = 8;
-   }
-
-   nDofsPerNode = self->fineVar->dofLayout->dofCounts[0]; /* ASSUME */
-   elGrid = *Mesh_GetExtension( mesh, Grid**, "elementGrid" );
-   vertGrid = *Mesh_GetExtension( mesh, Grid**, "vertexGrid" );
-   nGlobalNodes[0] = nGlobalNodes[1] = 1;
-   for( ii = 0; ii < nDims; ii++ ) {
-      sideSizes[1][ii] = elGrid->sizes[ii] / ifrac;
-      sideSizes[0][ii] = elGrid->sizes[ii] / (ifrac * 2);
-      if( sideSizes[1][ii] * ifrac != elGrid->sizes[ii] || 
-          sideSizes[0][ii] * (ifrac * 2) != elGrid->sizes[ii] )
-      {
-         printf( "(MG) Error: Too many levels specified for geometric multigrid.\n" );
-         printf( "            Please modify mesh size or reduce number of levels.\n" );
-         exit( 1 );
-      }
-      sideSizes[1][ii]++; sideSizes[0][ii]++;
-      nGlobalNodes[1] *= sideSizes[1][ii];
-      nGlobalNodes[0] *= sideSizes[0][ii];
-   }
-
-   /* Have PETSc create the operator matrix and then extract local sizes
-      and offsets into the global vector. */
-   nGlobalEqs[1] = nGlobalNodes[1] * nDofsPerNode;
-   nGlobalEqs[0] = nGlobalNodes[0] * nDofsPerNode;
-
-/*
-   MatCreateMPIAIJ( MPI_COMM_WORLD,
-                    PETSC_DECIDE, PETSC_DECIDE, nGlobalEqs[1], nGlobalEqs[0],
-                    o_nz, PETSC_NULL, d_nz, PETSC_NULL, &P );
-   MatGetOwnershipRange( P, &eqRangeBegin, &eqRangeEnd );
-*/
-   MatCreate( MPI_COMM_WORLD, &P );
-   MatSetSizes( P, PETSC_DECIDE, PETSC_DECIDE, nGlobalEqs[1], nGlobalEqs[0] );
-   MatSetType( P, MATAIJ );
-   MatGetOwnershipRange( P, &eqRangeBegin, &eqRangeEnd );
-
-   {  
-      Vec L,R;
-      PetscInt M,N;
-      MatGetSize( P, &M,&N );
-//      PetscPrintf( PETSC_COMM_WORLD, "size = %D x %D \n", M, N );
-      MatGetVecs( P, &R, &L );
-      VecGetOwnershipRange( L, &sr,&er );
-      VecGetOwnershipRange( R, &sc,&ec );
-//      printf( "  2) sr,er = %d -> %d \n", sr, er );
-//      printf( "  2) sc,ec = %d -> %d \n", sc, ec );
-
-      _VecGetOwnershipRanges( L, &row_ranges );
-      _VecGetOwnershipRanges( R, &col_ranges );
-
-      VecDestroy( L );
-      VecDestroy( R );
-    }
-
-
-   PetscMalloc( sizeof(PetscInt)*(er-sr), &o_nnz );
-   PetscMalloc( sizeof(PetscInt)*(er-sr), &d_nnz );
-
-
-
-   /* Need a grid representing the coarse level. */
-   grid[1] = Grid_New();
-   grid[0] = Grid_New();
-   offsGrid = Grid_New();
-   Grid_SetNumDims( grid[1], nDims );
-   Grid_SetNumDims( grid[0], nDims );
-   Grid_SetNumDims( offsGrid, nDims );
-   Grid_SetSizes( grid[1], (unsigned*)(sideSizes[1]) );
-   Grid_SetSizes( grid[0], (unsigned*)(sideSizes[0]) );
-
-   /* Determine preallocation */
-   MatGetVecs( P, PETSC_NULL, &vec_d_nnz );
-   VecDuplicate( vec_d_nnz, &vec_o_nnz );
-   PetscObjectGetComm( (PetscObject)P, &comm );
-   MPI_Comm_size( comm, &nproc );
-
-
-
-   /* Loop over the finer of the two levels. */
-   for( ii = eqRangeBegin; ii < eqRangeEnd; ii++ ) {
-      /* Convert the global equation number to the global node index. */
-      nodeInd = ii / nDofsPerNode;
-      rowDof = ii - nodeInd * nDofsPerNode;
-      Grid_Lift( grid[1], nodeInd, (unsigned*)(inds[1]) );
-
-      /* An odd grid index means we need to interpolate from surrounding
-         coarse nodes in the current dimension. */
-      for( jj = 0; jj < nDims; jj++ ) {
-         /* Store the offsets we need to consider. */
-         nOffs[jj] = (inds[1][jj] & 1) ? 2 : 1;
-      }
-
-      /* 'Multiply' the offsets to build the set of nodes we need to
-         interpolate from. */
-      Grid_SetSizes( offsGrid, (unsigned*)(nOffs) );
-      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-        Grid_Lift( offsGrid, jj, (unsigned*)(offsInds) );
-         for( kk = 0; kk < nDims; kk++ )
-            inds[0][kk] = (inds[1][kk] >> 1) + offsInds[kk];
-
-         /* Store the coarse global node number. */
-         nodes[jj] = Grid_Project( grid[0], (unsigned*)(inds[0]) );
-      }
-
-      /* Insert this row into the operator matrix. */
-      row_idx = (PetscInt)ii;      
-      /* find owning proc */
-      proc_owner = -1;
-      for( p=0; p<nproc; p++ ) {
-         if( (row_idx>=row_ranges[p]) && (row_idx<row_ranges[p+1]) ) {
-            proc_owner = p;
-            break;
-         }
-      }
-/*
-      if( (row_idx>=sr) && (row_idx<er) ) { 
-        for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-          indices[jj] = nodes[jj] * nDofsPerNode + rowDof;
-          if( (indices[jj]>=sc) && (indices[jj]<ec) ) {
-            VecSetValue( vec_d_nnz, row_idx, 1.0, ADD_VALUES );
-          }
-        }
-      }
-      else {
-        VecSetValue( vec_o_nnz, row_idx, 1.0, ADD_VALUES );
-      }
-*/
-
-      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-         indices[jj] = nodes[jj] * nDofsPerNode + rowDof;
-//         printf("ridx=%d,cidx=%d : owner:%d rrange [%d-%d] : crange [%d-%d] \n", row_idx, indices[jj], proc_owner, row_ranges[proc_owner],row_ranges[proc_owner+1], col_ranges[proc_owner], col_ranges[proc_owner+1] );
-         if( (row_idx>=row_ranges[proc_owner]) && (row_idx<row_ranges[proc_owner+1]) ) {
-            if( (indices[jj]>=col_ranges[proc_owner]) && (indices[jj]<col_ranges[proc_owner+1]) ) {
-               VecSetValue( vec_d_nnz, row_idx, 1.0, ADD_VALUES );
-            }
-            else {
-               VecSetValue( vec_o_nnz, row_idx, 1.0, ADD_VALUES );
-            }
-         }
-      }
-
-   }
-  
-   VecAssemblyBegin( vec_d_nnz );
-   VecAssemblyEnd( vec_d_nnz );
-
-   VecAssemblyBegin( vec_o_nnz );
-   VecAssemblyEnd( vec_o_nnz );
-
-   VecGetArray( vec_d_nnz, &v );
-   for( kk=0; kk<(er-sr); kk++ ) {
-      d_nnz[kk] = (PetscInt)v[kk];
-   }
-   VecRestoreArray( vec_d_nnz, &v );
-
-   VecGetArray( vec_o_nnz, &v );
-   for( kk=0; kk<(er-sr); kk++ ) {
-      o_nnz[kk] = (PetscInt)v[kk];
-   }
-   VecRestoreArray( vec_o_nnz, &v );
-
-  
-   if(nproc==1) {
-      MatSeqAIJSetPreallocation( P, PETSC_NULL, d_nnz );
-   }
-   else {
-      MatMPIAIJSetPreallocation( P, PETSC_NULL, d_nnz, PETSC_NULL, o_nnz );
-   }
-
-
-   /* Loop over the finer of the two levels. */
-   for( ii = eqRangeBegin; ii < eqRangeEnd; ii++ ) {
-      /* Convert the global equation number to the global node index. */
-      nodeInd = ii / nDofsPerNode;
-      rowDof = ii - nodeInd * nDofsPerNode;
-      Grid_Lift( grid[1], nodeInd, (unsigned*)(inds[1]) );
-
-      /* An odd grid index means we need to interpolate from surrounding
-         coarse nodes in the current dimension. */
-      for( jj = 0; jj < nDims; jj++ ) {
-         /* Store the offsets we need to consider. */
-         nOffs[jj] = (inds[1][jj] & 1) ? 2 : 1;
-      }
-
-      /* 'Multiply' the offsets to build the set of nodes we need to
-         interpolate from. */
-      Grid_SetSizes( offsGrid, (unsigned*)(nOffs) );
-      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-        Grid_Lift( offsGrid, jj, (unsigned*)(offsInds) );
-         for( kk = 0; kk < nDims; kk++ )
-            inds[0][kk] = (inds[1][kk] >> 1) + offsInds[kk];
-
-         /* Store the coarse global node number. */
-         nodes[jj] = Grid_Project( grid[0], (unsigned*)(inds[0]) );
-      }
-
-      /* Insert this row into the operator matrix. */
-      dfrac = 1.0 / (double)offsGrid->nPoints;
-      nEntries = offsGrid->nPoints;
-      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
-         indices[jj] = nodes[jj] * nDofsPerNode + rowDof;
-         values[jj] = dfrac;
-      }
-      MatSetValues( P, 1, &ii, nEntries, indices, values, INSERT_VALUES );
-   }
-
-   /* Assemble the matrix. */
-   MatAssemblyBegin( P, MAT_FINAL_ASSEMBLY );
-   MatAssemblyEnd( P, MAT_FINAL_ASSEMBLY );
-
-   /* Piss off those grids. */
-   Stg_Class_Delete( grid[0] );
-   Stg_Class_Delete( grid[1] );
-   Stg_Class_Delete( offsGrid );
-
-   VecDestroy( vec_o_nnz );
-   VecDestroy( vec_d_nnz );
-   PetscFree( o_nnz );
-   PetscFree( d_nnz );
-   PetscFree( row_ranges );
-   PetscFree( col_ranges );
-
-
-   /* Create a new matrix. */
-   //mat = PETScMatrix_New( "" );
-   //mat->petscMat = P;
-   mat = P;
-   return mat;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/SROpGenerator.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/SROpGenerator.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,1331 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: SROpGenerator.c 3584 2006-05-16 11:11:07Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+
+#include "SystemSetup.h"
+
+#include "petsc.h"
+#include "petscvec.h"
+#include "petscmat.h"
+
+/* Textual name of this class */
+const Type SROpGenerator_Type = "SROpGenerator";
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Constructors
+*/
+
+SROpGenerator* SROpGenerator_New( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(SROpGenerator);
+	Type                                                      type = SROpGenerator_Type;
+	Stg_Class_DeleteFunction*                              _delete = _SROpGenerator_Delete;
+	Stg_Class_PrintFunction*                                _print = _SROpGenerator_Print;
+	Stg_Class_CopyFunction*                                  _copy = NULL;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = (void* (*)(Name))SROpGenerator_New;
+	Stg_Component_ConstructFunction*                    _construct = _SROpGenerator_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _SROpGenerator_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _SROpGenerator_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _SROpGenerator_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _SROpGenerator_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+	MGOpGenerator_SetNumLevelsFunc*               setNumLevelsFunc = _MGOpGenerator_SetNumLevels;
+	MGOpGenerator_HasExpiredFunc*                   hasExpiredFunc = SROpGenerator_HasExpired;
+	MGOpGenerator_GenerateFunc*                       generateFunc = SROpGenerator_Generate;
+
+	return _SROpGenerator_New(  SROPGENERATOR_PASSARGS  );
+}
+
+SROpGenerator* _SROpGenerator_New(  SROPGENERATOR_DEFARGS  ) {
+	SROpGenerator*	self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(SROpGenerator) );
+	self = (SROpGenerator*)_MGOpGenerator_New(  MGOPGENERATOR_PASSARGS  );
+
+	/* Virtual info */
+
+	/* SROpGenerator info */
+	_SROpGenerator_Init( self );
+
+	return self;
+}
+
+void _SROpGenerator_Init( SROpGenerator* self ) {
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+
+	self->fineVar = NULL;
+	self->fineEqNum = NULL;
+	self->meshes = NULL;
+	self->topMaps = NULL;
+	self->eqNums = NULL;
+	self->nLocalEqNums = NULL;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Virtual functions
+*/
+
+void _SROpGenerator_Delete( void* srOpGenerator ) {
+	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+
+	/* Delete the parent. */
+	_MGOpGenerator_Delete( self );
+}
+
+void _SROpGenerator_Print( void* srOpGenerator, Stream* stream ) {
+	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
+	
+	/* Set the Journal for printing informations */
+	Stream* srOpGeneratorStream;
+	srOpGeneratorStream = Journal_Register( InfoStream_Type, (Name)"SROpGeneratorStream"  );
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+
+	/* Print parent */
+	Journal_Printf( stream, "SROpGenerator (ptr): (%p)\n", self );
+	_MGOpGenerator_Print( self, stream );
+}
+
+void _SROpGenerator_AssignFromXML( void* srOpGenerator, Stg_ComponentFactory* cf, void* data ) {
+	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
+	FeVariable*	var;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+
+	var = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"fineVariable", FeVariable, True, data  );
+	SROpGenerator_SetFineVariable( self, var );
+}
+
+void _SROpGenerator_Build( void* srOpGenerator, void* data ) {
+}
+
+void _SROpGenerator_Initialise( void* srOpGenerator, void* data ) {
+}
+
+void _SROpGenerator_Execute( void* srOpGenerator, void* data ) {
+}
+
+void _SROpGenerator_Destroy( void* srOpGenerator, void* data ) {
+}
+
+Bool SROpGenerator_HasExpired( void* srOpGenerator ) {
+	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+
+	return False;
+}
+
+//void SROpGenerator_Generate( void* srOpGenerator, Matrix*** pOps, Matrix*** rOps ) {
+void SROpGenerator_Generate( void* srOpGenerator, Mat** pOps, Mat** rOps ) {
+	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+	assert( pOps && rOps );
+
+	//*pOps = AllocArray( Matrix*, self->nLevels );
+	//*rOps = AllocArray( Matrix*, self->nLevels );
+	//memset( *pOps, 0, self->nLevels * sizeof(Matrix*) );
+	//memset( *rOps, 0, self->nLevels * sizeof(Matrix*) );
+	*pOps = AllocArray( Mat, self->nLevels );
+	*rOps = AllocArray( Mat, self->nLevels );
+	memset( *pOps, 0, self->nLevels * sizeof(Mat) );
+	memset( *rOps, 0, self->nLevels * sizeof(Mat) );
+
+/*
+	self->fineEqNum = self->fineVar->eqNum;
+	SROpGenerator_GenMeshes( self );
+	SROpGenerator_GenOps( self, *pOps, *rOps );
+	SROpGenerator_DestructMeshes( self );
+*/
+        SROpGenerator_Simple( self, *pOps, *rOps );
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------------------
+** Public Functions
+*/
+
+void SROpGenerator_SetFineVariable( void* srOpGenerator, void* _variable ) {
+	SROpGenerator*	self = (SROpGenerator*)srOpGenerator;
+	FeVariable*	variable = (FeVariable*)_variable;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+	assert( !variable || Stg_CheckType( variable, FeVariable ) );
+
+	SROpGenerator_DestructMeshes( self );
+	self->fineVar = variable;
+	self->fineEqNum = NULL;
+}
+
+
+/*----------------------------------------------------------------------------------------------------------------------------------
+** Private Functions
+*/
+
+void SROpGenerator_GenMeshes( SROpGenerator* self ) {
+	unsigned	nLevels;
+	unsigned	l_i;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+
+	nLevels = self->nLevels;
+	self->meshes = AllocArray( Mesh*, nLevels );
+	memset( self->meshes, 0, nLevels * sizeof(Mesh*) );
+	self->topMaps = AllocArray( unsigned*, nLevels );
+	memset( self->topMaps, 0, nLevels * sizeof(unsigned*) );
+	self->eqNums = AllocArray( unsigned**, nLevels );
+	memset( self->eqNums, 0, nLevels * sizeof(unsigned**) );
+	self->nLocalEqNums = AllocArray( unsigned, nLevels );
+	memset( self->nLocalEqNums, 0, nLevels * sizeof(unsigned) );
+	self->eqNumBases = AllocArray( unsigned, nLevels );
+	memset( self->eqNumBases, 0, nLevels * sizeof(unsigned) );
+
+	self->meshes[nLevels - 1] = (Mesh*)self->fineEqNum->feMesh;
+	self->eqNumBases[nLevels - 1] = self->fineEqNum->firstOwnedEqNum;
+	for( l_i = nLevels - 2; l_i < nLevels; l_i-- ) {
+		SROpGenerator_GenLevelMesh( self, l_i );
+		SROpGenerator_GenLevelTopMap( self, l_i );
+		SROpGenerator_GenLevelEqNums( self, l_i );
+	}
+}
+
+void SROpGenerator_GenLevelMesh( SROpGenerator* self, unsigned level ) {
+	Stream*			errorStream = Journal_Register( ErrorStream_Type, (Name)"SROpGenerator::GenLevelMesh"  );
+	Mesh			*fMesh, *cMesh;
+	CartesianGenerator	*fGen, *cGen;
+	unsigned		nDims;
+	unsigned*		cSize;
+	double			crdMin[3], crdMax[3];
+	unsigned		d_i;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+	assert( self->meshes );
+	assert( level < self->nLevels );
+
+	fMesh = self->meshes[level + 1];
+	nDims = Mesh_GetDimSize( fMesh );
+	fGen = (CartesianGenerator*)fMesh->generator;
+	Journal_Firewall( fGen && !strcmp( fGen->type, CartesianGenerator_Type ), 
+			  errorStream, 
+			  "\n" \
+			  "****************************************************************\n" \
+			  "* Error: Simple regular multigrid operator generation requires *\n" \
+			  "*        a fine mesh that has been generated with a            *\n" \
+			  "*        cartesian generator.                                  *\n" \
+			  "****************************************************************\n" \
+			  "\n" );
+
+	cGen = CartesianGenerator_New( "", NULL );
+	CartesianGenerator_SetDimSize( cGen, nDims );
+	cSize = AllocArray( unsigned, nDims );
+	for( d_i = 0; d_i < nDims; d_i++ )
+		cSize[d_i] = fGen->elGrid->sizes[d_i] / 2;
+	CartesianGenerator_SetTopologyParams( cGen, cSize, fGen->maxDecompDims, fGen->minDecomp, fGen->maxDecomp );
+	Mesh_GetGlobalCoordRange( fMesh, crdMin, crdMax );
+	CartesianGenerator_SetGeometryParams( cGen, crdMin, crdMax );
+	CartesianGenerator_SetShadowDepth( cGen, 0 );
+	FreeArray( cSize );
+
+	cMesh = (Mesh*)FeMesh_New( "", NULL );
+	Mesh_SetGenerator( cMesh, cGen );
+	FeMesh_SetElementFamily( cMesh, ((FeMesh*)fMesh)->feElFamily );
+	Stg_Component_Build( cMesh, NULL, False );
+	Stg_Component_Initialise( cMesh, NULL, False );
+	self->meshes[level] = cMesh;
+}
+
+void SROpGenerator_GenLevelTopMap( SROpGenerator* self, unsigned level ) {
+	Stream*		errorStream = Journal_Register( ErrorStream_Type, (Name)"SROpGenerator::GenLevelTopMap"  );
+	Mesh		*fMesh, *cMesh;
+	unsigned	nDomainNodes;
+	unsigned	nLevels;
+	unsigned	nDims;
+	unsigned	nearest;
+	double		*cVert, *fVert;
+	unsigned	d_i, n_i;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+	assert( self->meshes );
+	assert( level < self->nLevels );
+
+	fMesh = self->meshes[level + 1];
+	cMesh = self->meshes[level];
+	nDims = Mesh_GetDimSize( fMesh );
+	nLevels = self->nLevels;
+	nDomainNodes = Mesh_GetDomainSize( cMesh, MT_VERTEX );
+	self->topMaps[level] = ReallocArray( self->topMaps[level], unsigned, nDomainNodes );
+	for( n_i = 0; n_i < nDomainNodes; n_i++ ) {
+		cVert = Mesh_GetVertex( cMesh, n_i );
+		nearest = Mesh_NearestVertex( fMesh, cVert );
+		fVert = Mesh_GetVertex( fMesh, nearest );
+		for( d_i = 0; d_i < nDims; d_i++ ) {
+			if( !Num_Approx( cVert[d_i], fVert[d_i] ) )
+				break;
+		}
+
+		Journal_Firewall( d_i == nDims, 
+				  errorStream, 
+				  "\n" \
+				  "*****************************************************************\n" \
+				  "* Error: The finest grid could not be sub-sampled to all coarse *\n" \
+				  "*        levels. This is due to the size of the finest grid.    *\n" \
+				  "*****************************************************************\n" \
+				  "\n" );
+
+		if( level < nLevels - 2 )
+			self->topMaps[level][n_i] = self->topMaps[level + 1][nearest];
+		else
+			self->topMaps[level][n_i] = nearest;
+	}
+}
+
+void SROpGenerator_GenLevelEqNums( SROpGenerator* self, unsigned level ) {
+	Mesh*			cMesh;
+	unsigned*		nNodalDofs;
+	unsigned		nDomainNodes, nLocalNodes;
+	DofLayout*		dofLayout;
+	unsigned**		dstArray;
+	unsigned		curEqNum;
+	unsigned		maxDofs;
+	unsigned		topNode;
+	unsigned		base, subTotal;
+	MPI_Comm		comm;
+	unsigned		nProcs, rank;
+	MPI_Status		status;	
+	unsigned*		tuples;
+	Sync*			sync;
+	unsigned		n_i, dof_i;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+	assert( self->meshes && self->topMaps && self->eqNums );
+	assert( level < self->nLevels );
+
+	cMesh = self->meshes[level];
+	nDomainNodes = Mesh_GetDomainSize( cMesh, MT_VERTEX );
+	nLocalNodes = Mesh_GetLocalSize( cMesh, MT_VERTEX );
+	dofLayout = self->fineEqNum->dofLayout;
+	comm = Comm_GetMPIComm( Mesh_GetCommTopology( cMesh, MT_VERTEX ) );
+	MPI_Comm_size( comm, (int*)&nProcs );
+	MPI_Comm_rank( comm, (int*)&rank );
+
+	/* Allocate for destination array. */
+	nNodalDofs = AllocArray( unsigned, nDomainNodes );
+	for( n_i = 0; n_i < nDomainNodes; n_i++ )
+		nNodalDofs[n_i] = dofLayout->dofCounts[self->topMaps[level][n_i]];
+	dstArray = AllocComplex2D( unsigned, nDomainNodes, nNodalDofs );
+
+	/* Build initial destination array and store max dofs. */
+	curEqNum = 0;
+	maxDofs = 0;
+	for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
+		if( nNodalDofs[n_i] > maxDofs )
+			maxDofs = nNodalDofs[n_i];
+
+		topNode = self->topMaps[level][n_i];
+		for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
+			if( self->fineEqNum->destinationArray[topNode][dof_i] != (unsigned)-1 )
+				dstArray[n_i][dof_i] = curEqNum++;
+			else
+				dstArray[n_i][dof_i] = (unsigned)-1;
+		}
+	}
+
+	/* Order the equation numbers based on processor rank; cascade counts forward. */
+	base = 0;
+	subTotal = curEqNum;
+	if( rank > 0 ) {
+		insist( MPI_Recv( &base, 1, MPI_UNSIGNED, rank - 1, 6669, comm, &status ), == MPI_SUCCESS );
+		subTotal = base + curEqNum;
+	}
+	if( rank < nProcs - 1 )
+		insist( MPI_Send( &subTotal, 1, MPI_UNSIGNED, rank + 1, 6669, comm ), == MPI_SUCCESS );
+
+	/* Modify existing destination array and dump to a tuple array. */
+	tuples = AllocArray( unsigned, nDomainNodes * maxDofs );
+	for( n_i = 0; n_i < nLocalNodes; n_i++ ) {
+		for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
+			if( dstArray[n_i][dof_i] != (unsigned)-1 )
+				dstArray[n_i][dof_i] += base;
+			tuples[n_i * maxDofs + dof_i] = dstArray[n_i][dof_i];
+		}
+	}
+
+	/* Update all other procs. */
+	sync = Mesh_GetSync( cMesh, MT_VERTEX );
+	Sync_SyncArray( sync, tuples, maxDofs * sizeof(unsigned), 
+			tuples + nLocalNodes * maxDofs, maxDofs * sizeof(unsigned), 
+			maxDofs * sizeof(unsigned) );
+
+	/* Update destination array's domain indices. */
+	for( n_i = nLocalNodes; n_i < nDomainNodes; n_i++ ) {
+		topNode = self->topMaps[level][n_i];
+		for( dof_i = 0; dof_i < nNodalDofs[n_i]; dof_i++ ) {
+			if( self->fineEqNum->destinationArray[topNode][dof_i] != (unsigned)-1 )
+				dstArray[n_i][dof_i] = tuples[n_i * maxDofs + dof_i];
+			else
+				dstArray[n_i][dof_i] = -1;
+		}
+	}
+
+	/* Destroy arrays. */
+	FreeArray( nNodalDofs );
+	FreeArray( tuples );
+
+	self->eqNums[level] = dstArray;
+	self->nLocalEqNums[level] = curEqNum;
+	self->eqNumBases[level] = base;
+}
+
+//void SROpGenerator_GenOps( SROpGenerator* self, Matrix** pOps, Matrix** rOps ) {
+void SROpGenerator_GenOps( SROpGenerator* self, Mat* pOps, Mat* rOps ) {
+	unsigned	nLevels;
+	//Matrix		*fineMat, *P;
+	Mat		fineMat, P;
+	unsigned	nRows, nCols;
+	unsigned	l_i;
+	/* unsigned	nProcs; */
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+	assert( pOps && rOps );
+
+	//fineMat = MatrixSolver_GetMatrix( self->solver );
+	fineMat = self->solver->matrix;
+	nLevels = self->nLevels;
+
+	for( l_i = nLevels - 1; l_i > 0; l_i-- ) {
+		nRows = self->eqNums[l_i] ? self->nLocalEqNums[l_i] : 
+			self->fineEqNum->localEqNumsOwnedCount;
+		nCols = self->nLocalEqNums[l_i - 1];
+
+		//Matrix_Duplicate( fineMat, (void**)&P );
+		//Matrix_SetComm( P, fineMat->comm );
+		//Matrix_SetLocalSize( P, nRows, nCols );
+		MatCreate( self->solver->comm, &P );
+		MatSetSizes( P, nRows, nCols, PETSC_DETERMINE, PETSC_DETERMINE );
+		MatSetFromOptions( P );
+		//if( !strcmp( P->type, PETScMatrix_Type ) ) {
+		//	unsigned	*nDiagNonZeros, *nOffDiagNonZeros;
+		//
+		//	SROpGenerator_CalcOpNonZeros( self, l_i, &nDiagNonZeros, &nOffDiagNonZeros );
+			//PETScMatrix_SetNonZeroStructure( (PETScMatrix*)P, 0, nDiagNonZeros, nOffDiagNonZeros );
+		//	MPI_Comm_size( self->solver->comm, &nProcs );
+		//	if( nProcs > 1 )
+		//		MatMPIAIJSetPreallocation( P, PETSC_NULL, nDiagNonZeros, PETSC_NULL, nOffDiagNonZeros );
+		//	else
+		//		MatSeqAIJSetPreallocation( P, PETSC_NULL, nDiagNonZeros );
+		//	FreeArray( nDiagNonZeros );
+		//	FreeArray( nOffDiagNonZeros );
+		//}
+
+		SROpGenerator_GenLevelOp( self, l_i, P );
+		pOps[l_i] = P;
+		//Stg_Class_AddRef( P );
+		rOps[l_i] = P;
+		//Stg_Class_AddRef( P );
+	}
+}
+
+//void SROpGenerator_GenLevelOp( SROpGenerator* self, unsigned level, Matrix* P ) {
+void SROpGenerator_GenLevelOp( SROpGenerator* self, unsigned level, Mat P ) {
+	Mesh		*fMesh, *cMesh;
+	unsigned	nDims;
+	unsigned	nLocalFineNodes;
+	DofLayout*	dofLayout;
+	unsigned	ind;
+	unsigned	nInc, *inc;
+	unsigned	maxInc;
+	unsigned	fTopNode, cTopNode;
+	unsigned	fEqNum, cEqNum;
+	double		*localCoord, *basis;
+	IArray		*incArray;
+	unsigned	n_i, dof_i, inc_i, e_i;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+	assert( self->meshes );
+	assert( level < self->nLevels );
+	assert( P );
+
+	fMesh = self->meshes[level];
+	cMesh = self->meshes[level - 1];
+	nDims = Mesh_GetDimSize( fMesh );
+	nLocalFineNodes = Mesh_GetLocalSize( fMesh, MT_VERTEX );
+	dofLayout = self->fineEqNum->dofLayout;
+	localCoord = AllocArray( double, nDims );
+
+	maxInc = 0;
+	for( e_i = 0; e_i < Mesh_GetDomainSize( cMesh, (MeshTopology_Dim)nDims ); e_i++ ) {
+          nInc = Mesh_GetIncidenceSize( cMesh, (MeshTopology_Dim)nDims, e_i, MT_VERTEX );
+		if( nInc > maxInc )
+			maxInc = nInc;
+	}
+	basis = AllocArray( double, maxInc );
+
+	incArray = IArray_New();
+	for( n_i = 0; n_i < nLocalFineNodes; n_i++ ) {
+		if( self->topMaps[level] )
+			fTopNode = self->topMaps[level][n_i];
+		else
+			fTopNode = n_i;
+
+		for( dof_i = 0; dof_i < dofLayout->dofCounts[fTopNode]; dof_i++ ) {
+			if( self->eqNums[level] )
+				fEqNum = self->eqNums[level][n_i][dof_i];
+			else
+				fEqNum = self->fineEqNum->destinationArray[fTopNode][dof_i];
+
+			if( fEqNum == (unsigned)-1 )
+				continue;
+
+			insist( Mesh_SearchElements( cMesh, Mesh_GetVertex( fMesh, n_i ), &ind ), == True );
+			FeMesh_CoordGlobalToLocal( cMesh, ind, Mesh_GetVertex( fMesh, n_i ), localCoord );
+			FeMesh_EvalBasis( cMesh, ind, localCoord, basis );
+			Mesh_GetIncidence( cMesh, (MeshTopology_Dim)nDims, ind, MT_VERTEX, incArray );
+			nInc = IArray_GetSize( incArray );
+			inc = (unsigned*)IArray_GetPtr( incArray );
+			for( inc_i = 0; inc_i < nInc; inc_i++ ) {
+				cTopNode = self->topMaps[level - 1][inc[inc_i]];
+				cEqNum = self->eqNums[level - 1][inc[inc_i]][dof_i];
+				if( cEqNum != (unsigned)-1 && !Num_Approx( basis[inc_i], 0.0 ) )
+					//Matrix_InsertEntries( P, 1, &fEqNum, 1, &cEqNum, basis + inc_i );
+                                  MatSetValues( P, 1, (PetscInt*)(&fEqNum), 1, (PetscInt*)(&cEqNum), basis + inc_i, INSERT_VALUES );
+			}
+		}
+	}
+	NewClass_Delete( incArray );
+
+	FreeArray( localCoord );
+	FreeArray( basis );
+
+	//Matrix_AssemblyBegin( P );
+	//Matrix_AssemblyEnd( P );
+	MatAssemblyBegin( P, MAT_FINAL_ASSEMBLY );
+	MatAssemblyEnd( P, MAT_FINAL_ASSEMBLY );
+}
+
+void SROpGenerator_CalcOpNonZeros( SROpGenerator* self, unsigned level, 
+				   unsigned** nDiagNonZeros, unsigned** nOffDiagNonZeros )
+{
+	Mesh		*fMesh, *cMesh;
+	unsigned	nLocalFineNodes;
+	DofLayout*	dofLayout;
+	unsigned	dim, ind;
+	unsigned	nInc, *inc;
+	unsigned	fTopNode, cTopNode;
+	unsigned	fEqNum, cEqNum;
+	unsigned	nLocalEqNums;
+	IArray*		incArray;
+	unsigned	n_i, dof_i, dof_j, inc_i;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+	assert( self->meshes );
+	assert( level < self->nLevels );
+
+	fMesh = self->meshes[level];
+	cMesh = self->meshes[level - 1];
+	nLocalFineNodes = Mesh_GetLocalSize( fMesh, MT_VERTEX );
+	dofLayout = self->fineEqNum->dofLayout;
+	if( self->eqNums[level] )
+		nLocalEqNums = self->nLocalEqNums[level];
+	else
+		nLocalEqNums = self->fineEqNum->localEqNumsOwnedCount;
+
+	*nDiagNonZeros = AllocArray( unsigned, nLocalEqNums );
+	memset( *nDiagNonZeros, 0, nLocalEqNums * sizeof(unsigned) );
+	*nOffDiagNonZeros = AllocArray( unsigned, nLocalEqNums );
+	memset( *nOffDiagNonZeros, 0, nLocalEqNums * sizeof(unsigned) );
+
+	incArray = IArray_New();
+
+	for( n_i = 0; n_i < nLocalFineNodes; n_i++ ) {
+		if( self->topMaps[level] )
+			fTopNode = self->topMaps[level][n_i];
+		else
+			fTopNode = n_i;
+
+		for( dof_i = 0; dof_i < dofLayout->dofCounts[fTopNode]; dof_i++ ) {
+			if( self->eqNums[level] )
+				fEqNum = self->eqNums[level][n_i][dof_i];
+			else
+				fEqNum = self->fineEqNum->destinationArray[fTopNode][dof_i];
+
+			if( fEqNum == (unsigned)-1 )
+				continue;
+
+			insist( Mesh_SearchElements( cMesh, Mesh_GetVertex( fMesh, n_i ), &ind ), == True );
+			dim = Mesh_GetDimSize( fMesh );
+			if( dim == MT_VERTEX ) {
+				cTopNode = self->topMaps[level - 1][ind];
+				for( dof_j = 0; dof_j < dofLayout->dofCounts[cTopNode]; dof_j++ ) {
+					cEqNum = self->eqNums[level - 1][ind][dof_j];
+					if( cEqNum == (unsigned)-1 )
+						continue;
+
+					if( cEqNum - self->eqNumBases[level - 1] < nLocalEqNums )
+						(*nDiagNonZeros)[fEqNum - self->eqNumBases[level]]++;
+					else
+						(*nOffDiagNonZeros)[fEqNum - self->eqNumBases[level]]++;
+				}
+			}
+			else {
+				Mesh_GetIncidence( cMesh, (MeshTopology_Dim)dim, ind, MT_VERTEX, incArray );
+				nInc = IArray_GetSize( incArray );
+				inc = (unsigned*)IArray_GetPtr( incArray );
+				for( inc_i = 0; inc_i < nInc; inc_i++ ) {
+					cTopNode = self->topMaps[level - 1][inc[inc_i]];
+					for( dof_j = 0; dof_j < dofLayout->dofCounts[cTopNode]; dof_j++ ) {
+						cEqNum = self->eqNums[level - 1][inc[inc_i]][dof_j];
+						if( cEqNum == (unsigned)-1 )
+							continue;
+
+						if( cEqNum - self->eqNumBases[level - 1] < nLocalEqNums )
+							(*nDiagNonZeros)[fEqNum - self->eqNumBases[level]]++;
+						else
+							(*nOffDiagNonZeros)[fEqNum - self->eqNumBases[level]]++;
+					}
+				}
+			}
+		}
+	}
+
+	NewClass_Delete( incArray );
+}
+
+void SROpGenerator_DestructMeshes( SROpGenerator* self ) {
+	unsigned	nLevels;
+	unsigned	l_i;
+
+	assert( self && Stg_CheckType( self, SROpGenerator ) );
+
+	if( self->meshes ) {
+		nLevels = self->nLevels;
+		for( l_i = 0; l_i < nLevels - 1; l_i++ ) {
+			FreeObject( self->meshes[l_i] );
+			FreeArray( self->topMaps[l_i] );
+			FreeArray( self->eqNums[l_i] );
+		}
+		KillArray( self->meshes );
+		KillArray( self->topMaps );
+		KillArray( self->eqNums );
+		KillArray( self->nLocalEqNums );
+		KillArray( self->eqNumBases );
+	}
+}
+
+
+//void SROpGenerator_Simple( SROpGenerator *self, Matrix **pOps, Matrix **rOps ) {
+void SROpGenerator_Simple( SROpGenerator *self, Mat* pOps, Mat* rOps ) {
+   double t0;
+   if( self->nLevels > 1 ) {
+      //Matrix *P;
+      Mat P;
+      int ii;
+
+      t0 = MPI_Wtime();
+      P = SROpGenerator_SimpleFinestLevel( self );
+      PetscPrintf( PETSC_COMM_WORLD, "SROpGenerator_SimpleFinestLevel: time = %5.5e \n", MPI_Wtime()-t0 );
+      pOps[self->nLevels - 1] = rOps[self->nLevels - 1] = P;
+      for( ii = self->nLevels - 2; ii > 0; ii-- ) {
+	 t0 = MPI_Wtime();
+         P = SROpGenerator_SimpleCoarserLevel( self, ii );
+	 PetscPrintf( PETSC_COMM_WORLD, "  [%d] SROpGenerator_SimpleCoarserLevel: time = %5.5e \n",ii,  MPI_Wtime()-t0 );
+         pOps[ii] = rOps[ii] = P;
+      }
+   }
+}
+
+
+PetscErrorCode _VecGetOwnershipRanges( Vec X, PetscInt **_ranges )
+{
+  PetscInt start,end;
+  PetscMPIInt nproc,rank;
+  MPI_Comm comm;
+  Vec all, out;
+  VecScatter scat;
+  PetscInt *ranges,i;
+  PetscScalar *v;
+  double t0;
+
+  t0 = MPI_Wtime();
+
+  PetscObjectGetComm( (PetscObject)X, &comm );
+  MPI_Comm_size( comm, &nproc );
+  MPI_Comm_rank( comm, &rank );
+  VecGetOwnershipRange( X, &start, &end );
+
+  VecCreate( comm, &all );
+  VecSetSizes( all, PETSC_DECIDE, nproc+1 );
+  VecSetFromOptions( all );
+
+  VecSetValue( all, rank, (PetscScalar)start, INSERT_VALUES );
+  VecSetValue( all, rank+1, (PetscScalar)end, INSERT_VALUES );
+  VecAssemblyBegin( all );
+  VecAssemblyEnd( all );
+
+  VecScatterCreateToAll( all, &scat, &out );
+
+#if(PETSC_VERSION_SUBMINOR==2)
+  VecScatterBegin(all,out,INSERT_VALUES,SCATTER_FORWARD,scat);
+  VecScatterEnd(all,out,INSERT_VALUES,SCATTER_FORWARD,scat);
+#elif(PETSC_VERSION_SUBMINOR==3) 
+  VecScatterBegin(scat, all,out,INSERT_VALUES,SCATTER_FORWARD);
+  VecScatterEnd(scat, all,out,INSERT_VALUES,SCATTER_FORWARD);
+#endif
+
+  PetscMalloc( sizeof(PetscInt)*(nproc+1), &ranges );
+  VecGetArray( out, &v );
+  for( i=0; i<nproc+1; i++ ) {
+    ranges[i] = (PetscInt)v[i];
+  }
+  VecRestoreArray( out, &v );
+
+  *_ranges = ranges;
+
+  VecScatterDestroy( scat );
+  VecDestroy( out );
+  VecDestroy( all );
+
+ 
+  PetscFunctionReturn(0);
+}
+
+
+/*
+Efficiency alert!!
+  This comments relates to both SROpGenerator_SimpleFinestLevel() and
+  SROpGenerator_SimpleCoarserLevel().
+  
+  For O(n) setup times, we MUST provide some information concerning the
+  preallocation of the nonzero structure for the restriction operators.
+
+  As a first hack we check the spatial dimension and choose a value accordingly. 
+  In doing so we have assumed that the fine grid is obtained by bisecting 
+  the coarse grid. Coarse grid nodes are hiearchical. We have also assumed
+  that the elements are quads (2d) and hexs (3d).
+  
+  The hack above made little effort to miminise memory usage and as such we allocate
+  the same amount of memory for the on and off diagonal parts of the restriction
+  operator. This kinda kills use in parallel.
+
+  An more accurate estimate has thus been implemented.
+*/
+//Matrix *SROpGenerator_SimpleFinestLevel( SROpGenerator *self ) {
+Mat SROpGenerator_SimpleFinestLevel( SROpGenerator *self ) {
+   FeMesh *mesh;
+   int nDims, nDofsPerNode;
+   int sideSizes[2][3];
+   int inds[2][3], offsInds[3], nOffs[3];
+   int nGlobalNodes[2];
+   int nGlobalEqs[2];
+   Grid *vertGrid, *elGrid, *grid[2], *offsGrid;
+   int nodes[8];
+   int nodeInd;
+   double dfrac;
+   int nEntries, indices[8];
+   double values[8];
+   Mat P;
+   //PETScMatrix *mat;
+   Mat mat;
+   int ii, jj, kk;
+   PetscInt o_nz, d_nz;
+   PetscInt *o_nnz, *d_nnz;
+   PetscInt sr,er, sc,ec, row_idx;
+   Vec vec_o_nnz, vec_d_nnz;
+   PetscScalar *v;
+   PetscTruth is_seq;
+   PetscInt p, proc_owner, *rranges,*cranges;
+   MPI_Comm comm;
+   PetscMPIInt nproc,rank;  
+
+   /* Calculate level side lengths. */
+   mesh = self->fineVar->feMesh;
+   nDims = Mesh_GetDimSize( mesh );
+
+   /* crude estimate of number of nonzeros in the on-off diagonal portitions of the matrix */
+   o_nz = d_nz = 0;
+   if( nDims == 2 ) {
+	o_nz = d_nz = 4;
+   }
+   if( nDims==3 ) {
+	o_nz = d_nz = 8;
+   }
+
+   nDofsPerNode = self->fineVar->dofLayout->dofCounts[0]; /* ASSUME */
+   elGrid = *Mesh_GetExtension( mesh, Grid**, "elementGrid" );
+   vertGrid = *Mesh_GetExtension( mesh, Grid**, "vertexGrid" );
+   nGlobalNodes[0] = nGlobalNodes[1] = 1;
+   for( ii = 0; ii < nDims; ii++ ) {
+      sideSizes[1][ii] = elGrid->sizes[ii];
+      sideSizes[0][ii] = elGrid->sizes[ii] / 2;
+      if( sideSizes[0][ii] * 2 != elGrid->sizes[ii] ) {
+         printf( "(MG) Error: Too many levels specified for geometric multigrid.\n" );
+         printf( "            Please modify mesh size or reduce number of levels.\n" );
+         exit( 1 );
+      }
+      sideSizes[1][ii]++; sideSizes[0][ii]++;
+      nGlobalNodes[1] *= sideSizes[1][ii];
+      nGlobalNodes[0] *= sideSizes[0][ii];
+   }
+
+   /* Have PETSc create the operator matrix and then extract local sizes
+      and offsets into the global vector. */
+   nGlobalEqs[1] = nGlobalNodes[1] * nDofsPerNode;
+   nGlobalEqs[0] = nGlobalNodes[0] * nDofsPerNode;
+/*
+   MatCreateMPIAIJ( MPI_COMM_WORLD,
+                    self->fineVar->eqNum->localEqNumsOwnedCount, PETSC_DECIDE,
+                    PETSC_DECIDE, nGlobalEqs[0],
+                    o_nz, PETSC_NULL, d_nz, PETSC_NULL, &P );
+
+*/
+   MatCreate( MPI_COMM_WORLD, &P );
+   MatSetSizes( P, self->fineVar->eqNum->localEqNumsOwnedCount, PETSC_DECIDE, PETSC_DECIDE, nGlobalEqs[0] ); 
+   MatSetType( P, MATAIJ );
+//   MatGetOwnershipRange( P, &sr, &er );
+
+   PetscObjectGetComm( (PetscObject)P, &comm );
+   MPI_Comm_size( comm, &nproc );
+   MPI_Comm_rank( comm, &rank );
+
+//   printf( "  sr,er = %d -> %d \n", sr, er );
+   {  Vec L,R;
+      PetscInt M,N, m,n;     
+      
+      MatGetSize( P, &M,&N );
+      MatGetLocalSize( P, &m,&n );
+//      PetscPrintf( PETSC_COMM_WORLD, "size = %D x %D \n", M, N );
+      MatGetVecs( P, &R, &L );
+      VecGetOwnershipRange( L, &sr,&er );
+      VecGetOwnershipRange( R, &sc,&ec );
+//      printf( "  [%d] mxn = %d x %d ; sr,er = %d -> %d ; sc,ec = %d -> %d \n", rank, m,n,  sr,er, sc,ec );
+
+      _VecGetOwnershipRanges( L, &rranges );
+      _VecGetOwnershipRanges( R, &cranges );
+
+      VecDestroy( L );
+      VecDestroy( R );
+    }
+  
+   PetscMalloc( sizeof(PetscInt)*(er-sr), &o_nnz );
+   PetscMalloc( sizeof(PetscInt)*(er-sr), &d_nnz );
+
+   /* Need a grid representing the coarse level. */
+   grid[0] = Grid_New();
+   offsGrid = Grid_New();
+   Grid_SetNumDims( grid[0], nDims );
+   Grid_SetNumDims( offsGrid, nDims );
+   Grid_SetSizes( grid[0], (unsigned*)(sideSizes[0]) );
+
+   /* Determine preallocation information */
+   MatGetVecs( P, PETSC_NULL, &vec_d_nnz );
+   VecDuplicate( vec_d_nnz, &vec_o_nnz );
+
+   /* Loop over fine nodes. */
+   for( ii = 0; ii < Mesh_GetLocalSize( mesh, (MeshTopology_Dim)0 ); ii++ ) {
+      nodeInd = Mesh_DomainToGlobal( mesh, (MeshTopology_Dim)0, ii );
+      Grid_Lift( vertGrid, nodeInd, (unsigned*)(inds[1]) );
+
+      /* An odd grid index means we need to interpolate from surrounding
+         coarse nodes in the current dimension. */
+      for( jj = 0; jj < nDims; jj++ ) {
+         /* Store the offsets we need to consider. */
+         nOffs[jj] = (inds[1][jj] & 1) ? 2 : 1;
+      }
+
+      /* 'Multiply' the offsets to build the set of nodes we need to
+         interpolate from. */
+      Grid_SetSizes( offsGrid, (unsigned*)nOffs );
+      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+         Grid_Lift( offsGrid, jj, (unsigned*)offsInds );
+         for( kk = 0; kk < nDims; kk++ )
+            inds[0][kk] = (inds[1][kk] >> 1) + offsInds[kk];
+
+         /* Store the coarse global node number. */
+         nodes[jj] = Grid_Project( grid[0], (unsigned*)(inds[0]) );
+      }
+
+      /* Insert this row into the operator matrix. */
+      nEntries = offsGrid->nPoints;
+      for( kk = 0; kk < nDofsPerNode; kk++ ) {
+         /* Skip the entire thing if it's a BC. */
+         if( self->fineVar->eqNum->destinationArray[ii][kk] == -1 )
+            continue;
+
+         row_idx = (PetscInt)(self->fineVar->eqNum->destinationArray[ii][kk]);
+
+
+         /* find owning proc */
+         proc_owner = -1;
+         for( p=0; p<nproc; p++ ) {
+            if( (row_idx>=rranges[p]) && (row_idx<rranges[p+1]) ) {
+               proc_owner = p;
+               break;
+            }
+         }
+
+
+         for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+            indices[jj] = nodes[jj] * nDofsPerNode + kk;
+          //  printf( "[%d]: (owner=%d): row=%d : c_index=%d \n", rank, proc_owner, row_idx, indices[jj] );
+	    if( (row_idx>=rranges[proc_owner]) && (row_idx<rranges[proc_owner+1]) ) {          
+               if( (indices[jj]>=cranges[proc_owner]) && (indices[jj]<cranges[proc_owner+1]) ) {
+                  VecSetValue( vec_d_nnz, row_idx, 1.0, ADD_VALUES );
+               }
+               else {
+                  VecSetValue( vec_o_nnz, row_idx, 1.0, ADD_VALUES );
+               }
+            }
+         }
+
+
+/*
+        for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+           indices[jj] = nodes[jj] * nDofsPerNode + kk;
+	   printf( "[%d]: row=%d : c_index=%d \n", rank, row_idx, indices[jj] );
+           if( (row_idx>=sr) && (row_idx<er) ) {
+              if( (indices[jj]>=sc) && (indices[jj]<ec) ) {
+                VecSetValue( vec_d_nnz, row_idx, 1.0, ADD_VALUES );
+              }
+            }
+           else {
+              VecSetValue( vec_o_nnz, row_idx, 1.0, ADD_VALUES );
+           }
+        }
+*/
+
+
+      }
+   }
+   VecAssemblyBegin( vec_d_nnz );
+   VecAssemblyEnd( vec_d_nnz );
+
+   VecAssemblyBegin( vec_o_nnz );
+   VecAssemblyEnd( vec_o_nnz );
+
+   VecGetArray( vec_d_nnz, &v );
+   for( kk=0; kk<(er-sr); kk++ ) {
+      d_nnz[kk] = (PetscInt)v[kk];
+   }
+   VecRestoreArray( vec_d_nnz, &v );
+
+   VecGetArray( vec_o_nnz, &v );
+   for( kk=0; kk<(er-sr); kk++ ) {
+      o_nnz[kk] = (PetscInt)v[kk];
+   }
+   VecRestoreArray( vec_o_nnz, &v );
+
+   PetscTypeCompare( (PetscObject)vec_o_nnz, VECSEQ, &is_seq );
+   if(nproc==1) {
+      MatSeqAIJSetPreallocation( P, PETSC_NULL, d_nnz );
+   }
+   else {
+//     for( kk=0; kk<(er-sr); kk++ ) {
+//       printf( "[%d]: row=%d : d_nnz=%d : o_nnz=%d \n", rank, kk+sr, d_nnz[kk], o_nnz[kk] );
+//     }
+      MatMPIAIJSetPreallocation( P, PETSC_NULL, d_nnz, PETSC_NULL, o_nnz );
+
+//    MatMPIAIJSetPreallocation( P, d_nz,PETSC_NULL, o_nz,PETSC_NULL );
+   }
+
+   /* Loop over fine nodes. */
+   for( ii = 0; ii < Mesh_GetLocalSize( mesh, (MeshTopology_Dim)0 ); ii++ ) {
+//      if( ii%5000 == 0 ) {
+//        PetscPrintf( PETSC_COMM_WORLD, "Done %d of %d \n", ii, Mesh_GetLocalSize( mesh, 0 ) );
+//      }
+      nodeInd = Mesh_DomainToGlobal( mesh, (MeshTopology_Dim)0, ii );
+      Grid_Lift( vertGrid, nodeInd, (unsigned*)(inds[1]) );
+
+      /* An odd grid index means we need to interpolate from surrounding
+         coarse nodes in the current dimension. */
+      for( jj = 0; jj < nDims; jj++ ) {
+         /* Store the offsets we need to consider. */
+         nOffs[jj] = (inds[1][jj] & 1) ? 2 : 1;
+      }
+
+      /* 'Multiply' the offsets to build the set of nodes we need to
+         interpolate from. */
+      Grid_SetSizes( offsGrid, (unsigned*)nOffs );
+      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+         Grid_Lift( offsGrid, jj, (unsigned*)offsInds );
+         for( kk = 0; kk < nDims; kk++ )
+            inds[0][kk] = (inds[1][kk] >> 1) + offsInds[kk];
+
+         /* Store the coarse global node number. */
+         nodes[jj] = Grid_Project( grid[0], (unsigned*)(inds[0]) );
+      }
+
+      /* Insert this row into the operator matrix. */
+      dfrac = 1.0 / (double)offsGrid->nPoints;
+      nEntries = offsGrid->nPoints;
+      for( kk = 0; kk < nDofsPerNode; kk++ ) {
+         /* Skip the entire thing if it's a BC. */
+         if( self->fineVar->eqNum->destinationArray[ii][kk] == -1 )
+            continue;
+
+         for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+            indices[jj] = nodes[jj] * nDofsPerNode + kk;
+            values[jj] = dfrac;
+         }
+         MatSetValues( P, 1, self->fineVar->eqNum->destinationArray[ii] + kk,
+                       nEntries, indices, values, INSERT_VALUES );
+      }
+   }
+//   PetscPrintf( PETSC_COMM_WORLD, "Done all MatSetValues \n");
+
+   /* Assemble the matrix. */
+   MatAssemblyBegin( P, MAT_FINAL_ASSEMBLY );
+   MatAssemblyEnd( P, MAT_FINAL_ASSEMBLY );
+
+/*
+   {
+      PetscInt M,N, m,n;
+      for( p=0; p<nproc; p++ ) {
+        PetscPrintf( PETSC_COMM_WORLD, "[%d]: r_range (%d->%d) ; c_range (%d->%d)\n", p, rranges[p], rranges[p+1], cranges[p], cranges[p+1] );
+      }
+
+      MatGetSize( P, &M,&N );
+      MatGetLocalSize( P, &m,&n );
+      PetscPrintf( PETSC_COMM_WORLD, "P_size = %D x %D \n", M, N );
+      MatGetOwnershipRange( P, &sr,&er );
+      printf( "  [%d] mxn = %d x %d ; sr,er = %d -> %d (local rows=%d) \n", rank, m,n,  sr,er, er-sr );
+    }
+    PetscViewerSetFormat( PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_DENSE );
+    MatView( P, PETSC_VIEWER_STDOUT_WORLD );
+*/
+
+   /* Piss off those grids. */
+   Stg_Class_Delete( grid[0] );
+
+   Stg_Class_Delete(offsGrid);
+
+   VecDestroy( vec_o_nnz );
+   VecDestroy( vec_d_nnz );
+   PetscFree( o_nnz );
+   PetscFree( d_nnz );
+   PetscFree( rranges );
+   PetscFree( cranges );
+
+
+   /* Create a new matrix. */
+   //mat = PETScMatrix_New( "" );
+   //mat->petscMat = P;
+   mat = P;
+   return mat;
+}
+
+//Matrix *SROpGenerator_SimpleCoarserLevel( SROpGenerator *self, int level ) {
+Mat SROpGenerator_SimpleCoarserLevel( SROpGenerator *self, int level ) {
+   FeMesh *mesh;
+   int nDims, nDofsPerNode, rowDof;
+   int sideSizes[2][3];
+   int inds[2][3], offsInds[3], nOffs[3];
+   int nGlobalNodes[2];
+   int nGlobalEqs[2];
+   int eqRangeBegin, eqRangeEnd;
+   Grid *vertGrid, *elGrid, *grid[2], *offsGrid;
+   int nodes[8];
+   int ifrac, nodeInd;
+   double dfrac;
+   int nEntries, indices[8];
+   double values[8];
+   Mat P;
+   //PETScMatrix *mat;
+   Mat mat; 
+   int ii, jj, kk;
+   PetscInt o_nz, d_nz;
+   PetscInt *o_nnz, *d_nnz;
+   PetscInt sr,er, sc,ec, row_idx;
+   Vec vec_o_nnz, vec_d_nnz;
+   PetscScalar *v;
+   PetscInt p, proc_owner, *row_ranges, *col_ranges;
+   MPI_Comm comm;
+   PetscMPIInt nproc;
+
+   /* Calculate depth fraction. */
+   ifrac = 1;
+   for( ii = 0; ii < self->nLevels - level - 1; ii++ )
+      ifrac *= 2;
+
+   /* Calculate level side lengths. */
+   mesh = self->fineVar->feMesh;
+   nDims = Mesh_GetDimSize( mesh );
+
+   /* crude estimate of number of nonzeros in the on-off diagonal portitions of the matrix */
+   o_nz = d_nz = 0;
+   if( nDims==2 ) {
+      o_nz = d_nz = 4;
+   }
+   if( nDims==3 ) {
+        o_nz = d_nz = 8;
+   }
+
+   nDofsPerNode = self->fineVar->dofLayout->dofCounts[0]; /* ASSUME */
+   elGrid = *Mesh_GetExtension( mesh, Grid**, "elementGrid" );
+   vertGrid = *Mesh_GetExtension( mesh, Grid**, "vertexGrid" );
+   nGlobalNodes[0] = nGlobalNodes[1] = 1;
+   for( ii = 0; ii < nDims; ii++ ) {
+      sideSizes[1][ii] = elGrid->sizes[ii] / ifrac;
+      sideSizes[0][ii] = elGrid->sizes[ii] / (ifrac * 2);
+      if( sideSizes[1][ii] * ifrac != elGrid->sizes[ii] || 
+          sideSizes[0][ii] * (ifrac * 2) != elGrid->sizes[ii] )
+      {
+         printf( "(MG) Error: Too many levels specified for geometric multigrid.\n" );
+         printf( "            Please modify mesh size or reduce number of levels.\n" );
+         exit( 1 );
+      }
+      sideSizes[1][ii]++; sideSizes[0][ii]++;
+      nGlobalNodes[1] *= sideSizes[1][ii];
+      nGlobalNodes[0] *= sideSizes[0][ii];
+   }
+
+   /* Have PETSc create the operator matrix and then extract local sizes
+      and offsets into the global vector. */
+   nGlobalEqs[1] = nGlobalNodes[1] * nDofsPerNode;
+   nGlobalEqs[0] = nGlobalNodes[0] * nDofsPerNode;
+
+/*
+   MatCreateMPIAIJ( MPI_COMM_WORLD,
+                    PETSC_DECIDE, PETSC_DECIDE, nGlobalEqs[1], nGlobalEqs[0],
+                    o_nz, PETSC_NULL, d_nz, PETSC_NULL, &P );
+   MatGetOwnershipRange( P, &eqRangeBegin, &eqRangeEnd );
+*/
+   MatCreate( MPI_COMM_WORLD, &P );
+   MatSetSizes( P, PETSC_DECIDE, PETSC_DECIDE, nGlobalEqs[1], nGlobalEqs[0] );
+   MatSetType( P, MATAIJ );
+   MatGetOwnershipRange( P, &eqRangeBegin, &eqRangeEnd );
+
+   {  
+      Vec L,R;
+      PetscInt M,N;
+      MatGetSize( P, &M,&N );
+//      PetscPrintf( PETSC_COMM_WORLD, "size = %D x %D \n", M, N );
+      MatGetVecs( P, &R, &L );
+      VecGetOwnershipRange( L, &sr,&er );
+      VecGetOwnershipRange( R, &sc,&ec );
+//      printf( "  2) sr,er = %d -> %d \n", sr, er );
+//      printf( "  2) sc,ec = %d -> %d \n", sc, ec );
+
+      _VecGetOwnershipRanges( L, &row_ranges );
+      _VecGetOwnershipRanges( R, &col_ranges );
+
+      VecDestroy( L );
+      VecDestroy( R );
+    }
+
+
+   PetscMalloc( sizeof(PetscInt)*(er-sr), &o_nnz );
+   PetscMalloc( sizeof(PetscInt)*(er-sr), &d_nnz );
+
+
+
+   /* Need a grid representing the coarse level. */
+   grid[1] = Grid_New();
+   grid[0] = Grid_New();
+   offsGrid = Grid_New();
+   Grid_SetNumDims( grid[1], nDims );
+   Grid_SetNumDims( grid[0], nDims );
+   Grid_SetNumDims( offsGrid, nDims );
+   Grid_SetSizes( grid[1], (unsigned*)(sideSizes[1]) );
+   Grid_SetSizes( grid[0], (unsigned*)(sideSizes[0]) );
+
+   /* Determine preallocation */
+   MatGetVecs( P, PETSC_NULL, &vec_d_nnz );
+   VecDuplicate( vec_d_nnz, &vec_o_nnz );
+   PetscObjectGetComm( (PetscObject)P, &comm );
+   MPI_Comm_size( comm, &nproc );
+
+
+
+   /* Loop over the finer of the two levels. */
+   for( ii = eqRangeBegin; ii < eqRangeEnd; ii++ ) {
+      /* Convert the global equation number to the global node index. */
+      nodeInd = ii / nDofsPerNode;
+      rowDof = ii - nodeInd * nDofsPerNode;
+      Grid_Lift( grid[1], nodeInd, (unsigned*)(inds[1]) );
+
+      /* An odd grid index means we need to interpolate from surrounding
+         coarse nodes in the current dimension. */
+      for( jj = 0; jj < nDims; jj++ ) {
+         /* Store the offsets we need to consider. */
+         nOffs[jj] = (inds[1][jj] & 1) ? 2 : 1;
+      }
+
+      /* 'Multiply' the offsets to build the set of nodes we need to
+         interpolate from. */
+      Grid_SetSizes( offsGrid, (unsigned*)(nOffs) );
+      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+        Grid_Lift( offsGrid, jj, (unsigned*)(offsInds) );
+         for( kk = 0; kk < nDims; kk++ )
+            inds[0][kk] = (inds[1][kk] >> 1) + offsInds[kk];
+
+         /* Store the coarse global node number. */
+         nodes[jj] = Grid_Project( grid[0], (unsigned*)(inds[0]) );
+      }
+
+      /* Insert this row into the operator matrix. */
+      row_idx = (PetscInt)ii;      
+      /* find owning proc */
+      proc_owner = -1;
+      for( p=0; p<nproc; p++ ) {
+         if( (row_idx>=row_ranges[p]) && (row_idx<row_ranges[p+1]) ) {
+            proc_owner = p;
+            break;
+         }
+      }
+/*
+      if( (row_idx>=sr) && (row_idx<er) ) { 
+        for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+          indices[jj] = nodes[jj] * nDofsPerNode + rowDof;
+          if( (indices[jj]>=sc) && (indices[jj]<ec) ) {
+            VecSetValue( vec_d_nnz, row_idx, 1.0, ADD_VALUES );
+          }
+        }
+      }
+      else {
+        VecSetValue( vec_o_nnz, row_idx, 1.0, ADD_VALUES );
+      }
+*/
+
+      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+         indices[jj] = nodes[jj] * nDofsPerNode + rowDof;
+//         printf("ridx=%d,cidx=%d : owner:%d rrange [%d-%d] : crange [%d-%d] \n", row_idx, indices[jj], proc_owner, row_ranges[proc_owner],row_ranges[proc_owner+1], col_ranges[proc_owner], col_ranges[proc_owner+1] );
+         if( (row_idx>=row_ranges[proc_owner]) && (row_idx<row_ranges[proc_owner+1]) ) {
+            if( (indices[jj]>=col_ranges[proc_owner]) && (indices[jj]<col_ranges[proc_owner+1]) ) {
+               VecSetValue( vec_d_nnz, row_idx, 1.0, ADD_VALUES );
+            }
+            else {
+               VecSetValue( vec_o_nnz, row_idx, 1.0, ADD_VALUES );
+            }
+         }
+      }
+
+   }
+  
+   VecAssemblyBegin( vec_d_nnz );
+   VecAssemblyEnd( vec_d_nnz );
+
+   VecAssemblyBegin( vec_o_nnz );
+   VecAssemblyEnd( vec_o_nnz );
+
+   VecGetArray( vec_d_nnz, &v );
+   for( kk=0; kk<(er-sr); kk++ ) {
+      d_nnz[kk] = (PetscInt)v[kk];
+   }
+   VecRestoreArray( vec_d_nnz, &v );
+
+   VecGetArray( vec_o_nnz, &v );
+   for( kk=0; kk<(er-sr); kk++ ) {
+      o_nnz[kk] = (PetscInt)v[kk];
+   }
+   VecRestoreArray( vec_o_nnz, &v );
+
+  
+   if(nproc==1) {
+      MatSeqAIJSetPreallocation( P, PETSC_NULL, d_nnz );
+   }
+   else {
+      MatMPIAIJSetPreallocation( P, PETSC_NULL, d_nnz, PETSC_NULL, o_nnz );
+   }
+
+
+   /* Loop over the finer of the two levels. */
+   for( ii = eqRangeBegin; ii < eqRangeEnd; ii++ ) {
+      /* Convert the global equation number to the global node index. */
+      nodeInd = ii / nDofsPerNode;
+      rowDof = ii - nodeInd * nDofsPerNode;
+      Grid_Lift( grid[1], nodeInd, (unsigned*)(inds[1]) );
+
+      /* An odd grid index means we need to interpolate from surrounding
+         coarse nodes in the current dimension. */
+      for( jj = 0; jj < nDims; jj++ ) {
+         /* Store the offsets we need to consider. */
+         nOffs[jj] = (inds[1][jj] & 1) ? 2 : 1;
+      }
+
+      /* 'Multiply' the offsets to build the set of nodes we need to
+         interpolate from. */
+      Grid_SetSizes( offsGrid, (unsigned*)(nOffs) );
+      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+        Grid_Lift( offsGrid, jj, (unsigned*)(offsInds) );
+         for( kk = 0; kk < nDims; kk++ )
+            inds[0][kk] = (inds[1][kk] >> 1) + offsInds[kk];
+
+         /* Store the coarse global node number. */
+         nodes[jj] = Grid_Project( grid[0], (unsigned*)(inds[0]) );
+      }
+
+      /* Insert this row into the operator matrix. */
+      dfrac = 1.0 / (double)offsGrid->nPoints;
+      nEntries = offsGrid->nPoints;
+      for( jj = 0; jj < offsGrid->nPoints; jj++ ) {
+         indices[jj] = nodes[jj] * nDofsPerNode + rowDof;
+         values[jj] = dfrac;
+      }
+      MatSetValues( P, 1, &ii, nEntries, indices, values, INSERT_VALUES );
+   }
+
+   /* Assemble the matrix. */
+   MatAssemblyBegin( P, MAT_FINAL_ASSEMBLY );
+   MatAssemblyEnd( P, MAT_FINAL_ASSEMBLY );
+
+   /* Piss off those grids. */
+   Stg_Class_Delete( grid[0] );
+   Stg_Class_Delete( grid[1] );
+   Stg_Class_Delete( offsGrid );
+
+   VecDestroy( vec_o_nnz );
+   VecDestroy( vec_d_nnz );
+   PetscFree( o_nnz );
+   PetscFree( d_nnz );
+   PetscFree( row_ranges );
+   PetscFree( col_ranges );
+
+
+   /* Create a new matrix. */
+   //mat = PETScMatrix_New( "" );
+   //mat->petscMat = P;
+   mat = P;
+   return mat;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/SolutionVector.c
--- a/SLE/SystemSetup/src/SolutionVector.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,769 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: SolutionVector.c 1071 2008-03-12 02:23:49Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "FiniteElementContext.h"
-#include "SolutionVector.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-/* Textual name of this class */
-const Type SolutionVector_Type = "SolutionVector";
-
-static const int VALUE_TAG = 1;
-static const int VALUE_REQUEST_TAG = 2;
-
-typedef struct RequestInfo {
-	Node_LocalIndex	lNode_I;
-	Dof_Index			nodeLocalDof_I;
-} RequestInfo;
-
-void _SolutionVector_ShareValuesNotStoredLocally(
-	SolutionVector*		self,
-	Index*					reqFromOthersCounts,
-	RequestInfo**			reqFromOthersInfos,
-	Dof_EquationNumber**	reqFromOthers,
-	double*					localSolnVecValues );
-
-SolutionVector* SolutionVector_New( Name name, FiniteElementContext* context, MPI_Comm comm, FeVariable* feVariable ) {
-  SolutionVector* self = (SolutionVector*)_SolutionVector_DefaultNew( name );
-
-	self->isConstructed = True;
-	_SolutionVector_Init( self, context, comm, feVariable );
-
-	return self;
-}
-
-void* _SolutionVector_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(SolutionVector);
-	Type                                                      type = SolutionVector_Type;
-	Stg_Class_DeleteFunction*                              _delete = _SolutionVector_Delete;
-	Stg_Class_PrintFunction*                                _print = _SolutionVector_Print;
-	Stg_Class_CopyFunction*                                  _copy = _SolutionVector_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _SolutionVector_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _SolutionVector_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _SolutionVector_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _SolutionVector_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _SolutionVector_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _SolutionVector_Destroy;
-	AllocationType                              nameAllocationType = NON_GLOBAL;
-
-	return _SolutionVector_New(  SOLUTIONVECTOR_PASSARGS  );
-}
-
-SolutionVector* _SolutionVector_New(  SOLUTIONVECTOR_DEFARGS  ) {
-	SolutionVector* self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(SolutionVector) );
-	self = (SolutionVector*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual info */
-	
-	return self;
-}
-
-void _SolutionVector_Init( SolutionVector* self, FiniteElementContext* context, MPI_Comm comm, FeVariable* feVariable ) {
-	/* General and Virtual info should already be set */
-	
-	/* SolutionVector info */
-	self->context = context;
-	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
-	self->comm = comm;
-	self->feVariable = feVariable;
-}
-
-void _SolutionVector_Delete( void* solutionVector ) {
-	SolutionVector* self = (SolutionVector*)solutionVector;
-	
-	Journal_DPrintf( self->debug, "In %s - for soln. vector %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-	
-	/* Stg_Class_Delete parent*/
-	_Stg_Component_Delete( self );
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _SolutionVector_Print( void* solutionVector, Stream* stream ) {
-	SolutionVector* self = (SolutionVector*)solutionVector;
-	
-	/* Set the Journal for printing informations */
-	Stream* solutionVectorStream = stream;
-	
-	/* General info */
-	Journal_Printf( solutionVectorStream, "SolutionVector (ptr): %p\n", self );
-	
-	/* Print parent */
-	_Stg_Component_Print( self, solutionVectorStream );
-	
-	/* Virtual info */
-	
-	/* SolutionVector info */
-
-	Stg_Class_Print( self->feVariable, solutionVectorStream );
-	Journal_Printf( solutionVectorStream, "\tComm: %u\n", self->comm );
-}
-
-
-void* _SolutionVector_Copy( const void* solutionVector, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	SolutionVector*	self = (SolutionVector*)solutionVector;
-	SolutionVector*	newSolutionVector;
-	PtrMap*		map = ptrMap;
-	Bool		ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newSolutionVector = (SolutionVector*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
-	
-	/* TODO: copy vector? */
-	newSolutionVector->vector = self->vector;
-	newSolutionVector->comm = self->comm;
-	
-	if( deep ) {
-		newSolutionVector->debug = (Stream*)Stg_Class_Copy( self->debug, NULL, deep, nameExt, map );
-		newSolutionVector->feVariable = (FeVariable*)Stg_Class_Copy( self->feVariable, NULL, deep, nameExt, map );
-	}
-	else {
-		newSolutionVector->debug = self->debug;
-		newSolutionVector->feVariable = self->feVariable;
-	}
-	
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-	
-	return (void*)newSolutionVector;
-}
-
-
-void _SolutionVector_AssignFromXML( void* solutionVector, Stg_ComponentFactory* cf, void* data ) {
-	SolutionVector*			self = (SolutionVector*)solutionVector;
-	FeVariable*					feVariable = NULL;
-	FiniteElementContext*	context;
-
-	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
-	if( !context  )
-		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
-
-	feVariable = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"FeVariable", FeVariable, True, data  ) ;
-	_SolutionVector_Init( self, context, MPI_COMM_WORLD, (FeVariable*)feVariable );
-}
-
-
-void _SolutionVector_Build( void* solutionVector, void* data ) {
-	SolutionVector* self = (SolutionVector*)solutionVector;
-	
-	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	/* ensure variables are built */
-	if( self->feVariable )
-		Stg_Component_Build( self->feVariable, 0, False );
-
-	/* Allocate the vector */
-//	self->vector = PETScVector_New( "" );
-//	Vector_SetComm( self->vector, self->comm );
-//	Vector_SetLocalSize( self->vector, self->feVariable->eqNum->localEqNumsOwnedCount );
-	VecCreate( self->comm, &self->vector );
-	VecSetSizes( self->vector, self->feVariable->eqNum->localEqNumsOwnedCount, PETSC_DECIDE );
-	VecSetFromOptions( self->vector );
-#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
-	VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES );
-#elif( PETSC_VERSION_MAJOR >= 3 )
-	VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
-#endif
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _SolutionVector_Initialise( void* solutionVector, void* data ) {
-	SolutionVector*          self = (SolutionVector *)solutionVector;
-	
-	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-	/* ensure variables are initialised */
-	if( self->feVariable ) {
-		Stg_Component_Initialise( self->feVariable, data, False );
-	}
-		
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _SolutionVector_Execute( void* solutionVector, void* data ) {
-}
-
-void _SolutionVector_Destroy( void* solutionVector, void* data ) {
-	SolutionVector* self = (SolutionVector*)solutionVector;
-
-	//FreeObject( self->vector );
-	if( self->vector != PETSC_NULL )
-		VecDestroy( self->vector );
-}
-
-void SolutionVector_ApplyBCsToVariables( void* solutionVector, void* data ) {
-	SolutionVector*		self = (SolutionVector *)solutionVector;
-
-	FeVariable_ApplyBCs( self->feVariable, data );
-}
-
-/* from the depreciated Vector class */
-void _SolutionVector_VectorView( Vec v, Stream* stream ) {
-	unsigned	entry_i;
-	PetscInt	size;
-	PetscScalar*	array;
-
-	VecGetSize( v, &size );
-	VecGetArray( v, &array );
-
-	Journal_Printf( stream, "%p = [", v );
-	for( entry_i = 0; entry_i < size; entry_i++ ) 
-		Journal_Printf( stream, "\t%u: \t %.12g\n", entry_i, array[entry_i] );
-	Journal_Printf( stream, "];\n" );
-
-	VecRestoreArray( v, &array );
-}
-
-void SolutionVector_UpdateSolutionOntoNodes( void* solutionVector ) {
-	SolutionVector*		self = (SolutionVector *)solutionVector;
-	double*			localSolnVecValues;
-	Node_LocalIndex 	lNode_I = 0;
-	Dof_Index		currNodeNumDofs;
-	Dof_Index		nodeLocalDof_I;
-	Partition_Index		ownerProc;
-	FeVariable*		feVar = self->feVariable;
-	FeMesh*			feMesh = feVar->feMesh;
-	MPI_Comm		mpiComm;
-	FeEquationNumber*	eqNum = feVar->eqNum;
-	Dof_EquationNumber	currEqNum;
-	Index			indexIntoLocalSolnVecValues;
-	Index*			reqFromOthersCounts;
-	Index*			reqFromOthersSizes;
-	RequestInfo**		reqFromOthersInfos;
-	Dof_EquationNumber**	reqFromOthers;
-	Comm*			comm;
-	Partition_Index		nProc;
-	Partition_Index		myRank;
-	Partition_Index		proc_I;
-	double			initialGuessAtNonLocalEqNumsRatio = 0.1;
-	double			ratioToIncreaseRequestArraySize = 1.5;
-	Index			newReqFromOthersSize;
-	
-	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	#if DEBUG
-	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-		Journal_DPrintf( self->debug, "Vector data:\n" );
-		_SolutionVector_VectorView( self->vector, self->debug );
-	}
-	#endif
-
-	comm = Mesh_GetCommTopology( feMesh, MT_VERTEX );
-	mpiComm = Comm_GetMPIComm( comm );
-	MPI_Comm_size( mpiComm, (int*)&nProc );
-	MPI_Comm_rank( mpiComm, (int*)&myRank );
-
-	/* allocate arrays for nodes that I want on each processor */
-	reqFromOthersCounts = Memory_Alloc_Array( Index, nProc, "reqFromOthersCounts" );
-	reqFromOthersSizes = Memory_Alloc_Array( Index, nProc, "reqFromOthersSizes" );
-	reqFromOthersInfos = Memory_Alloc_Array( RequestInfo*, nProc, "reqFromOthersInfos" );
-	reqFromOthers = Memory_Alloc_Array( Dof_EquationNumber*, nProc, "reqFromOthers" );
-	/* Allocate the arrays of req. values from others independently, as we don't know how large they'll be */
-	for ( proc_I=0; proc_I < nProc; proc_I++ ) {
-		reqFromOthersCounts[proc_I] = 0;
-
-		if (proc_I == myRank) continue;
-
-		/* Our initial guess at number of non-local eqNums is a small ratio of the number of local dofs */
-		reqFromOthersSizes[proc_I] = eqNum->localEqNumsOwnedCount * initialGuessAtNonLocalEqNumsRatio;
-		/* Special case for really small meshes: make sure it's at least 1 */
-		if (0 == reqFromOthersSizes[proc_I] ) {
-			reqFromOthersSizes[proc_I]++;
-		}
-		reqFromOthersInfos[proc_I] = Memory_Alloc_Array( RequestInfo, reqFromOthersSizes[proc_I], 
-			"reqFromOthersInfos[proc_I]" );
-		reqFromOthers[proc_I] = Memory_Alloc_Array( Dof_EquationNumber, reqFromOthersSizes[proc_I],
-			"reqFromOthers[proc_I]" );
-	}
-	
-	/* Get the locally held part of the vector */
-	//Vector_GetArray( self->vector, &localSolnVecValues );
-	VecGetArray( self->vector, &localSolnVecValues );
-	
-	for( lNode_I=0; lNode_I < Mesh_GetLocalSize( feMesh, MT_VERTEX ); lNode_I++ ) {
-		currNodeNumDofs = feVar->dofLayout->dofCounts[ lNode_I ];
-		Journal_DPrintfL( self->debug, 3, "getting solutions for local node %d, has %d dofs.\n", lNode_I, currNodeNumDofs );
-		
-		/* process each dof */
-		for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
-			Journal_DPrintfL( self->debug, 3, "\tdof %d: ", nodeLocalDof_I );
-			
-			currEqNum = eqNum->destinationArray[lNode_I][nodeLocalDof_I];
-			if( currEqNum != -1 ) {
-				Journal_DPrintfL( self->debug, 3, "is unconstrained, eqNum %d:", currEqNum );
-
-				if( STreeMap_HasKey( eqNum->ownedMap, &currEqNum ) ) {
-					indexIntoLocalSolnVecValues = *(int*)STreeMap_Map( eqNum->ownedMap, &currEqNum );
-					Journal_DPrintfL( self->debug, 3, "local -> just copying value %f\n",
-						localSolnVecValues[indexIntoLocalSolnVecValues] );
-					DofLayout_SetValueDouble( feVar->dofLayout, lNode_I, nodeLocalDof_I,
-						localSolnVecValues[indexIntoLocalSolnVecValues] );
-				}
-				else {
-					RequestInfo*	requestInfo;
-					
-					Journal_DPrintfL( self->debug, 3, "nonlocal -> add to req list " );
-					ownerProc = FeEquationNumber_CalculateOwningProcessorOfEqNum( eqNum, currEqNum ); 
-					Journal_DPrintfL( self->debug, 3, "from proc %d\n", ownerProc );
-					/* first check count & realloc if necessary */
-					if (reqFromOthersCounts[ownerProc] == reqFromOthersSizes[ownerProc] ) {
-						newReqFromOthersSize = reqFromOthersSizes[ownerProc] * ratioToIncreaseRequestArraySize;
-						if ( newReqFromOthersSize == reqFromOthersSizes[ownerProc] ) {
-							/* Special case: always increase by at least 1 */
-							newReqFromOthersSize++;
-						}
-						reqFromOthersSizes[ownerProc] = newReqFromOthersSize;
-						
-						Journal_DPrintfL( self->debug, 3, "req list from proc %d count %d now "
-							"equal to size, so reallocing to size %d\n", 
-							ownerProc, reqFromOthersCounts[ownerProc],
-							reqFromOthersSizes[ownerProc] );
-							
-						reqFromOthersInfos[ownerProc] = Memory_Realloc_Array(
-							reqFromOthersInfos[ownerProc], RequestInfo, reqFromOthersSizes[ownerProc] );
-						reqFromOthers[ownerProc] = Memory_Realloc_Array(
-							reqFromOthers[ownerProc], Dof_EquationNumber, reqFromOthersSizes[ownerProc] );
-					}
-					requestInfo = &reqFromOthersInfos[ownerProc][ reqFromOthersCounts[ownerProc] ];
-					requestInfo->lNode_I = lNode_I;
-					requestInfo->nodeLocalDof_I = nodeLocalDof_I;
-					reqFromOthers[ownerProc][reqFromOthersCounts[ownerProc]] = currEqNum;
-					(reqFromOthersCounts[ownerProc])++;
-				}	
-			}
-			else {
-				Journal_DPrintfL( self->debug, 3, "is a BC, so skipping...\n" );
-			}
-		}
-	}				
-	
-	if ( nProc > 1 ) {
-		_SolutionVector_ShareValuesNotStoredLocally( self, reqFromOthersCounts, reqFromOthersInfos, reqFromOthers,
-			localSolnVecValues );
-	}	
-
-	for ( proc_I=0; proc_I < nProc; proc_I++ ) {
-		if (proc_I == myRank) continue;
-		Memory_Free( reqFromOthers[proc_I] );
-		Memory_Free( reqFromOthersInfos[proc_I] );
-	}
-	Memory_Free( reqFromOthers );
-	Memory_Free( reqFromOthersInfos );
-	Memory_Free( reqFromOthersCounts );
-	Memory_Free( reqFromOthersSizes );
-
-	//Vector_RestoreArray( self->vector, &localSolnVecValues );
-	VecRestoreArray( self->vector, &localSolnVecValues );
-
-	/*
-	** Syncronise the FEVariable in question.
-	*/
-
-	FeVariable_SyncShadowValues( feVar );
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _SolutionVector_ShareValuesNotStoredLocally(
-	SolutionVector*		self,
-	Index*			reqFromOthersCounts,
-	RequestInfo**		reqFromOthersInfos,
-	Dof_EquationNumber**	reqFromOthers,
-	double*			localSolnVecValues )
-{
-
-	FeVariable*		feVar = self->feVariable;
-	FeMesh*			feMesh = feVar->feMesh;
-	FeEquationNumber*	eqNum = feVar->eqNum;
-	Comm*			comm;
-	MPI_Comm		mpiComm;
-	Partition_Index		nProc;
-	Partition_Index		myRank;
-	Partition_Index		proc_I;
-	Index			req_I;
-	Index			indexIntoLocalSolnVecValues;
-	MPI_Status		status;
-	Index*			reqFromMeCounts;
-	Dof_EquationNumber**	reqFromMe;
-	double**		reqValuesFromMe;
-	MPI_Request**		reqValuesFromMeHandles;
-	MPI_Request**		reqFromOthersHandles;
-	double**		reqValuesFromOthers;
-	MPI_Request**		reqValuesFromOthersHandles;
-	Bool*			reqValuesFromOthersReceived;
-	Partition_Index	     reqValueSetsFromOthersNotYetReceivedCount;
-	Dof_EquationNumber   totalRequestedFromOthers = 0;
-	Dof_EquationNumber   totalRequestedFromMe = 0;
-
-	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	comm = Mesh_GetCommTopology( feMesh, MT_VERTEX );
-	mpiComm = Comm_GetMPIComm( comm );
-	MPI_Comm_size( mpiComm, (int*)&nProc );
-	MPI_Comm_rank( mpiComm, (int*)&myRank );
-
-	reqFromMeCounts = Memory_Alloc_Array( Index, nProc, "reqFromMeCounts" );
-	reqFromOthersHandles = Memory_Alloc_Array_Unnamed( MPI_Request*, nProc );
-	reqValuesFromOthersHandles = Memory_Alloc_Array_Unnamed( MPI_Request*, nProc );
-	reqValuesFromMeHandles = Memory_Alloc_Array_Unnamed( MPI_Request*, nProc );
-	reqValuesFromOthers = Memory_Alloc_2DComplex( double, nProc, reqFromOthersCounts, "reqValuesFromOthers" );
-	reqValuesFromOthersReceived = Memory_Alloc_Array_Unnamed( Bool, nProc );
-
-	#if DEBUG
-	if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
-		Journal_DPrintf( self->debug, "Final list of vec values I need from other procs:\n" );
-		for ( proc_I=0; proc_I < nProc; proc_I++ ) {
-			if ( proc_I == myRank ) continue;
-			Journal_DPrintf( self->debug, "\t%d[0-%d]: ", proc_I, reqFromOthersCounts[proc_I] );
-			for ( req_I=0; req_I < reqFromOthersCounts[proc_I]; req_I++ ) {
-				RequestInfo* reqInfo = &reqFromOthersInfos[proc_I][req_I];
-				Journal_DPrintf( self->debug, "(lnode %d, dof %d -> %d ), ",
-					reqInfo->lNode_I, reqInfo->nodeLocalDof_I,
-					reqFromOthers[proc_I][req_I] );
-			}
-			Journal_DPrintf( self->debug, "\n" );
-		}
-	}	
-	#endif
-	
-	/* send out my request counts, receive the req. counts others want from me */
-	MPI_Alltoall( reqFromOthersCounts, 1, MPI_UNSIGNED,
-		      reqFromMeCounts, 1, MPI_UNSIGNED, mpiComm );
-
-	Journal_DPrintf( self->debug, "After MPI_Alltoall- counts are:\n" );
-	totalRequestedFromOthers = 0;
-	totalRequestedFromMe = 0;
-	Stream_Indent( self->debug );
-	Journal_DPrintf( self->debug, "reqFromOthersCounts: " );
-	for ( proc_I=0; proc_I < nProc; proc_I++ ) {
-		if ( proc_I == myRank ) continue;
-		Journal_DPrintf( self->debug, "\tp%d:%d, ", proc_I, reqFromOthersCounts[proc_I] );
-		totalRequestedFromOthers += reqFromOthersCounts[proc_I];
-	}
-	Journal_DPrintf( self->debug, "\n" );
-	Journal_DPrintf( self->debug, "reqFromMeCounts: " );
-	for ( proc_I=0; proc_I < nProc; proc_I++ ) {
-		if ( proc_I == myRank ) continue;
-		Journal_DPrintf( self->debug, "\tp%d:%d, ", proc_I, reqFromMeCounts[proc_I] );
-		totalRequestedFromMe += reqFromMeCounts[proc_I];
-	}
-	Journal_DPrintf( self->debug, "\n" );
-	Stream_UnIndent( self->debug );
-
-	if ( ( totalRequestedFromOthers == 0) && (totalRequestedFromMe == 0) ) 
-	{	
-		Journal_DPrintf( self->debug, "No vector values either required from others or "
-			"required by others from me, therefore cleaning up memory and returning.\n" );
-		Memory_Free( reqFromMeCounts );
-		Memory_Free( reqFromOthersHandles );
-		Memory_Free( reqValuesFromOthersHandles );
-		Memory_Free( reqValuesFromMeHandles );
-		Memory_Free( reqValuesFromOthers ); 
-		Memory_Free( reqValuesFromOthersReceived );
-		Stream_UnIndentBranch( StgFEM_Debug );
-		return;
-	}
-
-	Journal_DPrintfL( self->debug, 2, "Starting non-blocking sends of my lists of vector entry indices I want from others:\n" );
-	Stream_Indent( self->debug );
-	for( proc_I=0; proc_I < nProc; proc_I++) {
-		if ( proc_I == myRank ) continue; 
-/* Journal_Printf( Journal_Register( Info_Type, (Name)"mpi"  ),  "!!! line %d, proc_I %d: count = %u\n", __LINE__, proc_I, reqFromOthersCounts[proc_I] ); */
-		if ( reqFromOthersCounts[proc_I] > 0 ) {
-			Journal_DPrintfL( self->debug, 2, "Sending to proc %d the list of %d vector entry indices I want from it:\n"
-				"\t(tracking via reqFromOthersHandles[%d], tag %d)\n", proc_I,
-				reqFromOthersCounts[proc_I], proc_I, VALUE_REQUEST_TAG );
-
-			reqFromOthersHandles[proc_I] = Memory_Alloc_Unnamed( MPI_Request );
-			MPI_Isend( reqFromOthers[proc_I], reqFromOthersCounts[proc_I], MPI_UNSIGNED,
-				proc_I, VALUE_REQUEST_TAG, mpiComm, reqFromOthersHandles[proc_I] );
-		}	
-	}
-	Stream_UnIndent( self->debug );
-
-
-	Journal_DPrintfL( self->debug, 2, "Starting non-blocking receive of the vector entries I want from others:\n" );
-	Stream_Indent( self->debug );
-	for( proc_I=0; proc_I < nProc; proc_I++) {
-		if ( proc_I == myRank ) continue; 
-		if ( reqFromOthersCounts[proc_I] > 0 ) {
-			Journal_DPrintfL( self->debug, 2, "Posting recv reqst from proc %d for the %d vector entries I want from it:\n"
-				"\t(tracking via reqValuesFromOthersHandles[%d], tag %d)\n", proc_I,
-				reqFromOthersCounts[proc_I], proc_I, VALUE_TAG );
-			reqValuesFromOthersHandles[proc_I] = Memory_Alloc_Unnamed( MPI_Request );
-			MPI_Irecv( reqValuesFromOthers[proc_I], reqFromOthersCounts[proc_I], MPI_DOUBLE,
-				proc_I, VALUE_TAG, mpiComm, reqValuesFromOthersHandles[proc_I] );
-		}	
-	}
-	Stream_UnIndent( self->debug );
-
-	Journal_DPrintfL( self->debug, 2, "Starting blocking receive of the lists of vector entry indices "
-		"others want from me:\n" );
-	Stream_Indent( self->debug );
-	reqFromMe = Memory_Alloc_2DComplex( Dof_EquationNumber, nProc, reqFromMeCounts, "reqFromMe" );
-	reqValuesFromMe = Memory_Alloc_2DComplex( double, nProc, reqFromMeCounts, "reqValuesFromMe" );
-	for( proc_I=0; proc_I < nProc; proc_I++) {
-		if ( proc_I == myRank ) continue; 
-/* /Journal_Printf( Journal_Register( Info_Type, (Name)"mpi"  ),  "!!! line %d, proc_I %d: count = %u\n", __LINE__, proc_I, reqFromMeCounts[proc_I] ); */
-		if ( reqFromMeCounts[proc_I] > 0 ) {
-			MPI_Recv( reqFromMe[proc_I], reqFromMeCounts[proc_I], MPI_UNSIGNED,
-				proc_I, VALUE_REQUEST_TAG, mpiComm, &status );
-			Journal_DPrintfL( self->debug, 3, "Received a list of %u requested vector entry indices from proc %u, "
-				"with tag %d\n", reqFromMeCounts[proc_I], proc_I, status.MPI_TAG );
-		}	
-	}
-	Stream_UnIndent( self->debug );
-	
-	#if DEBUG
-	if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
-		Journal_DPrintf( self->debug, "Final lists of vector entry indices other procs want from me are:\n" );
-		Stream_Indent( self->debug );
-		for ( proc_I=0; proc_I < nProc; proc_I++ ) {
-			if ( proc_I == myRank ) continue;
-			if ( reqFromMeCounts[proc_I] > 0 ) {
-				Journal_DPrintf( self->debug, "%d[0-%d]: ", proc_I, reqFromMeCounts[proc_I] );
-				for ( req_I=0; req_I < reqFromMeCounts[proc_I]; req_I++ ) {
-					Journal_DPrintf( self->debug, "(eqNum %d), ", reqFromMe[proc_I][req_I] );
-				}
-				Journal_DPrintf( self->debug, "\n" );
-			}
-		}
-		Stream_UnIndent( self->debug );
-	}	
-	#endif
-	
-	/* for all those requested from me, non-blocking send out values */
-	Journal_DPrintfL( self->debug, 2, "Beginning non-blocking send out of vector entry lists requested by others:\n" );
-	Stream_Indent( self->debug );
-	for( proc_I=0; proc_I < nProc; proc_I++) {
-		if ( proc_I == myRank ) continue; 
-		if ( reqFromMeCounts[proc_I] > 0 ) {
-			Journal_DPrintfL( self->debug, 3, "list to proc %d is: ", proc_I );
-			for ( req_I=0; req_I < reqFromMeCounts[proc_I]; req_I++ ) {
-				/* look up and fill in correct value in array */
-				indexIntoLocalSolnVecValues = *(int*)STreeMap_Map( eqNum->ownedMap,
-										   reqFromMe[proc_I] + req_I );
-				reqValuesFromMe[proc_I][req_I] = localSolnVecValues[indexIntoLocalSolnVecValues];
-				Journal_DPrintfL( self->debug, 3, "%d=%f, ", reqFromMe[proc_I][req_I],
-					reqValuesFromMe[proc_I][req_I] );
-			}
-			Journal_DPrintfL( self->debug, 3, "\n" );
-			/* Non-blocking send out the now-complete list to this processor */
-			reqValuesFromMeHandles[proc_I] = Memory_Alloc_Unnamed( MPI_Request );
-			Journal_DPrintfL( self->debug, 2, "Sending to proc %d the list of %d vector entries they want:\n"
-				"\t(tracking via reqValuesFromMe[%d], tag %d)\n", proc_I,
-				reqFromMeCounts[proc_I], proc_I, VALUE_TAG );
-			MPI_Isend( reqValuesFromMe[proc_I], reqFromMeCounts[proc_I], MPI_DOUBLE,
-				proc_I, VALUE_TAG, mpiComm, reqValuesFromMeHandles[proc_I] );
-		}	
-	}
-	Stream_UnIndent( self->debug );
-	
-	Journal_DPrintfL( self->debug, 1, "Starting iterative-test receive of the vector entries I "
-		"requested from others:\n" );
-	/* Set up an array for keeping track of who we've received things from
-	 * already */
-	reqValueSetsFromOthersNotYetReceivedCount = nProc-1;
-	for( proc_I=0; proc_I < nProc; proc_I++) {
-		if ( proc_I == myRank ) continue; 
-		reqValuesFromOthersReceived[proc_I] = False;
-		if ( reqFromOthersCounts[proc_I] == 0 ) {
-			reqValueSetsFromOthersNotYetReceivedCount--;
-		}	
-	}	
-
-	#if DEBUG
-	Journal_DPrintfL( self->debug, 2, "(Expecting %d receives from procs: ",
-		reqValueSetsFromOthersNotYetReceivedCount );
-	for( proc_I=0; proc_I < nProc; proc_I++) {
-		if ( proc_I == myRank ) continue; 
-		if ( reqFromOthersCounts[proc_I] > 0 ) {
-			Journal_DPrintfL( self->debug, 2, "%d, ", proc_I );
-		}	
-	}	
-	Journal_DPrintfL( self->debug, 2, ")\n" );
-	#endif
-
-	Stream_Indent( self->debug );
-	/* now update the values at nodes that I requested from others, as they come in */
-	while ( reqValueSetsFromOthersNotYetReceivedCount ) {	
-		int flag = 0;
-
-		Journal_DPrintfL( self->debug, 3, "%d sets still to go...\n", reqValueSetsFromOthersNotYetReceivedCount );
-		for( proc_I=0; proc_I < nProc; proc_I++) {
-			if ( proc_I == myRank ) continue; 
-
-			if ( (reqFromOthersCounts[proc_I] > 0) && (False == reqValuesFromOthersReceived[proc_I]) ) {
-				MPI_Test( reqValuesFromOthersHandles[proc_I], &flag, &status );
-				if ( !flag ) {
-					/* No results yet from this proc -> continue to next. */
-					continue;
-				}
-				else {
-					RequestInfo* reqInfo;
-					Journal_DPrintfL( self->debug, 2, "received some requested "
-						"values (using reqValuesFromOthersHandles) from proc %d "
-						"(with tag %d, exp %d):", proc_I, status.MPI_TAG, VALUE_TAG );
-					/* go through each value received from that proc & update onto node */
-					for ( req_I=0; req_I < reqFromOthersCounts[proc_I]; req_I++ ) {
-						reqInfo = &reqFromOthersInfos[proc_I][req_I];
-						Journal_DPrintfL( self->debug, 3, "(lnode %d, dof %d -> %d )=%f, ",
-							reqInfo->lNode_I, reqInfo->nodeLocalDof_I,
-							reqFromOthers[proc_I][req_I], reqValuesFromOthers[proc_I][req_I] );
-						DofLayout_SetValueDouble( feVar->dofLayout, reqInfo->lNode_I, reqInfo->nodeLocalDof_I,
-							reqValuesFromOthers[proc_I][req_I] );
-					}
-					Journal_DPrintfL( self->debug, 2, "\n" );
-					reqValuesFromOthersReceived[proc_I] = True;
-					reqValueSetsFromOthersNotYetReceivedCount--;
-					Memory_Free( reqValuesFromOthersHandles[proc_I] );
-				}	
-			}	
-		}
-	}	
-	Stream_UnIndent( self->debug );
-
-	/* MPI_Wait to be sure all sends to others have completed */
-	Journal_DPrintfL( self->debug, 2, "Making sure all comms of this function finished:...\n" );
-	Stream_Indent( self->debug );
-
-	Journal_DPrintfL( self->debug, 2, "Confirming completion of my sends of "
-		"vector entry index lists I wanted from others were received:\n" );
-	Stream_Indent( self->debug );
-	for( proc_I=0; proc_I < nProc; proc_I++) {
-		if ( proc_I == myRank ) continue; 
-		if ( reqFromOthersCounts[proc_I] > 0 ) {
-			MPI_Wait( reqFromOthersHandles[proc_I], MPI_STATUS_IGNORE ); 
-			Journal_DPrintfL( self->debug, 2, "Confirmed wait on reqFromOthersHandles[%u]"
-				"\n", proc_I );
-			Memory_Free( reqFromOthersHandles[proc_I] );
-		}	
-	}	
-	Stream_UnIndent( self->debug );
-	Journal_DPrintfL( self->debug, 2, "done.\n" );
-
-	Journal_DPrintfL( self->debug, 2, "Confirming completion of my sends of "
-		"vector entry values requested by others were received:\n" );
-	Stream_Indent( self->debug );
-	for( proc_I=0; proc_I < nProc; proc_I++) {
-		if ( proc_I == myRank ) continue; 
-		if ( reqFromMeCounts[proc_I] > 0 ) {
-			MPI_Wait( reqValuesFromMeHandles[proc_I], MPI_STATUS_IGNORE );
-			Journal_DPrintfL( self->debug, 2, "Confirmed wait on reqValuesFromMeHandles[%u]"
-				"\n", proc_I );
-			Memory_Free( reqValuesFromMeHandles[proc_I] );
-		}
-	}	
-	Stream_UnIndent( self->debug );
-	Journal_DPrintfL( self->debug, 2, "done.\n" );
-
-	Stream_UnIndent( self->debug );
-	Journal_DPrintfL( self->debug, 2, "done.\n" );
-
-	Memory_Free( reqFromMeCounts );
-	Memory_Free( reqFromMe );
-	Memory_Free( reqValuesFromMe );
-	Memory_Free( reqValuesFromOthers );
-	Memory_Free( reqValuesFromOthersReceived );
-	Memory_Free( reqFromOthersHandles );
-	Memory_Free( reqValuesFromOthersHandles );
-	Memory_Free( reqValuesFromMeHandles );
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-	return;
-}
-
-
-void SolutionVector_LoadCurrentFeVariableValuesOntoVector( void* solutionVector ) {
-	SolutionVector*		self = (SolutionVector*)solutionVector;
-	FeVariable*		feVar = self->feVariable;
-	FeMesh*			feMesh = feVar->feMesh;
-	Node_LocalIndex		node_lI = 0;
-	Dof_Index		dof_I = 0;
-	double			value = 0;
-	Index			insertionIndex = 0;
-	
-	for ( node_lI = 0; node_lI < FeMesh_GetNodeLocalSize( feMesh ); node_lI++ ) {
-		for ( dof_I = 0; dof_I < feVar->dofLayout->dofCounts[node_lI]; dof_I++ ) {
-			value = DofLayout_GetValueDouble( feVar->dofLayout, node_lI, dof_I );
-			insertionIndex = feVar->eqNum->destinationArray[node_lI][dof_I];
-			//Vector_InsertEntries( self->vector, 1, &insertionIndex, &value );
-			VecSetValues( self->vector, 1, (PetscInt*)(&insertionIndex), &value, INSERT_VALUES );
-		}	
-	}
-
-	//Vector_AssemblyBegin( self->vector );
-	//Vector_AssemblyEnd( self->vector ); 
-	VecAssemblyBegin( self->vector );
-	VecAssemblyEnd( self->vector ); 
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/SolutionVector.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/SolutionVector.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,769 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: SolutionVector.c 1071 2008-03-12 02:23:49Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "FiniteElementContext.h"
+#include "SolutionVector.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+/* Textual name of this class */
+const Type SolutionVector_Type = "SolutionVector";
+
+static const int VALUE_TAG = 1;
+static const int VALUE_REQUEST_TAG = 2;
+
+typedef struct RequestInfo {
+	Node_LocalIndex	lNode_I;
+	Dof_Index			nodeLocalDof_I;
+} RequestInfo;
+
+void _SolutionVector_ShareValuesNotStoredLocally(
+	SolutionVector*		self,
+	Index*					reqFromOthersCounts,
+	RequestInfo**			reqFromOthersInfos,
+	Dof_EquationNumber**	reqFromOthers,
+	double*					localSolnVecValues );
+
+SolutionVector* SolutionVector_New( Name name, FiniteElementContext* context, MPI_Comm comm, FeVariable* feVariable ) {
+  SolutionVector* self = (SolutionVector*)_SolutionVector_DefaultNew( name );
+
+	self->isConstructed = True;
+	_SolutionVector_Init( self, context, comm, feVariable );
+
+	return self;
+}
+
+void* _SolutionVector_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(SolutionVector);
+	Type                                                      type = SolutionVector_Type;
+	Stg_Class_DeleteFunction*                              _delete = _SolutionVector_Delete;
+	Stg_Class_PrintFunction*                                _print = _SolutionVector_Print;
+	Stg_Class_CopyFunction*                                  _copy = _SolutionVector_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _SolutionVector_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _SolutionVector_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _SolutionVector_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _SolutionVector_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _SolutionVector_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _SolutionVector_Destroy;
+	AllocationType                              nameAllocationType = NON_GLOBAL;
+
+	return _SolutionVector_New(  SOLUTIONVECTOR_PASSARGS  );
+}
+
+SolutionVector* _SolutionVector_New(  SOLUTIONVECTOR_DEFARGS  ) {
+	SolutionVector* self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(SolutionVector) );
+	self = (SolutionVector*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual info */
+	
+	return self;
+}
+
+void _SolutionVector_Init( SolutionVector* self, FiniteElementContext* context, MPI_Comm comm, FeVariable* feVariable ) {
+	/* General and Virtual info should already be set */
+	
+	/* SolutionVector info */
+	self->context = context;
+	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
+	self->comm = comm;
+	self->feVariable = feVariable;
+}
+
+void _SolutionVector_Delete( void* solutionVector ) {
+	SolutionVector* self = (SolutionVector*)solutionVector;
+	
+	Journal_DPrintf( self->debug, "In %s - for soln. vector %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+	
+	/* Stg_Class_Delete parent*/
+	_Stg_Component_Delete( self );
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _SolutionVector_Print( void* solutionVector, Stream* stream ) {
+	SolutionVector* self = (SolutionVector*)solutionVector;
+	
+	/* Set the Journal for printing informations */
+	Stream* solutionVectorStream = stream;
+	
+	/* General info */
+	Journal_Printf( solutionVectorStream, "SolutionVector (ptr): %p\n", self );
+	
+	/* Print parent */
+	_Stg_Component_Print( self, solutionVectorStream );
+	
+	/* Virtual info */
+	
+	/* SolutionVector info */
+
+	Stg_Class_Print( self->feVariable, solutionVectorStream );
+	Journal_Printf( solutionVectorStream, "\tComm: %u\n", self->comm );
+}
+
+
+void* _SolutionVector_Copy( const void* solutionVector, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	SolutionVector*	self = (SolutionVector*)solutionVector;
+	SolutionVector*	newSolutionVector;
+	PtrMap*		map = ptrMap;
+	Bool		ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newSolutionVector = (SolutionVector*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
+	
+	/* TODO: copy vector? */
+	newSolutionVector->vector = self->vector;
+	newSolutionVector->comm = self->comm;
+	
+	if( deep ) {
+		newSolutionVector->debug = (Stream*)Stg_Class_Copy( self->debug, NULL, deep, nameExt, map );
+		newSolutionVector->feVariable = (FeVariable*)Stg_Class_Copy( self->feVariable, NULL, deep, nameExt, map );
+	}
+	else {
+		newSolutionVector->debug = self->debug;
+		newSolutionVector->feVariable = self->feVariable;
+	}
+	
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+	
+	return (void*)newSolutionVector;
+}
+
+
+void _SolutionVector_AssignFromXML( void* solutionVector, Stg_ComponentFactory* cf, void* data ) {
+	SolutionVector*			self = (SolutionVector*)solutionVector;
+	FeVariable*					feVariable = NULL;
+	FiniteElementContext*	context;
+
+	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
+	if( !context  )
+		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
+
+	feVariable = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"FeVariable", FeVariable, True, data  ) ;
+	_SolutionVector_Init( self, context, MPI_COMM_WORLD, (FeVariable*)feVariable );
+}
+
+
+void _SolutionVector_Build( void* solutionVector, void* data ) {
+	SolutionVector* self = (SolutionVector*)solutionVector;
+	
+	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	/* ensure variables are built */
+	if( self->feVariable )
+		Stg_Component_Build( self->feVariable, 0, False );
+
+	/* Allocate the vector */
+//	self->vector = PETScVector_New( "" );
+//	Vector_SetComm( self->vector, self->comm );
+//	Vector_SetLocalSize( self->vector, self->feVariable->eqNum->localEqNumsOwnedCount );
+	VecCreate( self->comm, &self->vector );
+	VecSetSizes( self->vector, self->feVariable->eqNum->localEqNumsOwnedCount, PETSC_DECIDE );
+	VecSetFromOptions( self->vector );
+#if( PETSC_VERSION_MAJOR <= 2 && PETSC_VERSION_MINOR >= 3 && PETSC_VERSION_SUBMINOR >= 3 )
+	VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES );
+#elif( PETSC_VERSION_MAJOR >= 3 )
+	VecSetOption( self->vector, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE );
+#endif
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _SolutionVector_Initialise( void* solutionVector, void* data ) {
+	SolutionVector*          self = (SolutionVector *)solutionVector;
+	
+	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+	/* ensure variables are initialised */
+	if( self->feVariable ) {
+		Stg_Component_Initialise( self->feVariable, data, False );
+	}
+		
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _SolutionVector_Execute( void* solutionVector, void* data ) {
+}
+
+void _SolutionVector_Destroy( void* solutionVector, void* data ) {
+	SolutionVector* self = (SolutionVector*)solutionVector;
+
+	//FreeObject( self->vector );
+	if( self->vector != PETSC_NULL )
+		VecDestroy( self->vector );
+}
+
+void SolutionVector_ApplyBCsToVariables( void* solutionVector, void* data ) {
+	SolutionVector*		self = (SolutionVector *)solutionVector;
+
+	FeVariable_ApplyBCs( self->feVariable, data );
+}
+
+/* from the depreciated Vector class */
+void _SolutionVector_VectorView( Vec v, Stream* stream ) {
+	unsigned	entry_i;
+	PetscInt	size;
+	PetscScalar*	array;
+
+	VecGetSize( v, &size );
+	VecGetArray( v, &array );
+
+	Journal_Printf( stream, "%p = [", v );
+	for( entry_i = 0; entry_i < size; entry_i++ ) 
+		Journal_Printf( stream, "\t%u: \t %.12g\n", entry_i, array[entry_i] );
+	Journal_Printf( stream, "];\n" );
+
+	VecRestoreArray( v, &array );
+}
+
+void SolutionVector_UpdateSolutionOntoNodes( void* solutionVector ) {
+	SolutionVector*		self = (SolutionVector *)solutionVector;
+	double*			localSolnVecValues;
+	Node_LocalIndex 	lNode_I = 0;
+	Dof_Index		currNodeNumDofs;
+	Dof_Index		nodeLocalDof_I;
+	Partition_Index		ownerProc;
+	FeVariable*		feVar = self->feVariable;
+	FeMesh*			feMesh = feVar->feMesh;
+	MPI_Comm		mpiComm;
+	FeEquationNumber*	eqNum = feVar->eqNum;
+	Dof_EquationNumber	currEqNum;
+	Index			indexIntoLocalSolnVecValues;
+	Index*			reqFromOthersCounts;
+	Index*			reqFromOthersSizes;
+	RequestInfo**		reqFromOthersInfos;
+	Dof_EquationNumber**	reqFromOthers;
+	Comm*			comm;
+	Partition_Index		nProc;
+	Partition_Index		myRank;
+	Partition_Index		proc_I;
+	double			initialGuessAtNonLocalEqNumsRatio = 0.1;
+	double			ratioToIncreaseRequestArraySize = 1.5;
+	Index			newReqFromOthersSize;
+	
+	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	#if DEBUG
+	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+		Journal_DPrintf( self->debug, "Vector data:\n" );
+		_SolutionVector_VectorView( self->vector, self->debug );
+	}
+	#endif
+
+	comm = Mesh_GetCommTopology( feMesh, MT_VERTEX );
+	mpiComm = Comm_GetMPIComm( comm );
+	MPI_Comm_size( mpiComm, (int*)&nProc );
+	MPI_Comm_rank( mpiComm, (int*)&myRank );
+
+	/* allocate arrays for nodes that I want on each processor */
+	reqFromOthersCounts = Memory_Alloc_Array( Index, nProc, "reqFromOthersCounts" );
+	reqFromOthersSizes = Memory_Alloc_Array( Index, nProc, "reqFromOthersSizes" );
+	reqFromOthersInfos = Memory_Alloc_Array( RequestInfo*, nProc, "reqFromOthersInfos" );
+	reqFromOthers = Memory_Alloc_Array( Dof_EquationNumber*, nProc, "reqFromOthers" );
+	/* Allocate the arrays of req. values from others independently, as we don't know how large they'll be */
+	for ( proc_I=0; proc_I < nProc; proc_I++ ) {
+		reqFromOthersCounts[proc_I] = 0;
+
+		if (proc_I == myRank) continue;
+
+		/* Our initial guess at number of non-local eqNums is a small ratio of the number of local dofs */
+		reqFromOthersSizes[proc_I] = eqNum->localEqNumsOwnedCount * initialGuessAtNonLocalEqNumsRatio;
+		/* Special case for really small meshes: make sure it's at least 1 */
+		if (0 == reqFromOthersSizes[proc_I] ) {
+			reqFromOthersSizes[proc_I]++;
+		}
+		reqFromOthersInfos[proc_I] = Memory_Alloc_Array( RequestInfo, reqFromOthersSizes[proc_I], 
+			"reqFromOthersInfos[proc_I]" );
+		reqFromOthers[proc_I] = Memory_Alloc_Array( Dof_EquationNumber, reqFromOthersSizes[proc_I],
+			"reqFromOthers[proc_I]" );
+	}
+	
+	/* Get the locally held part of the vector */
+	//Vector_GetArray( self->vector, &localSolnVecValues );
+	VecGetArray( self->vector, &localSolnVecValues );
+	
+	for( lNode_I=0; lNode_I < Mesh_GetLocalSize( feMesh, MT_VERTEX ); lNode_I++ ) {
+		currNodeNumDofs = feVar->dofLayout->dofCounts[ lNode_I ];
+		Journal_DPrintfL( self->debug, 3, "getting solutions for local node %d, has %d dofs.\n", lNode_I, currNodeNumDofs );
+		
+		/* process each dof */
+		for ( nodeLocalDof_I = 0; nodeLocalDof_I < currNodeNumDofs; nodeLocalDof_I++ ) {
+			Journal_DPrintfL( self->debug, 3, "\tdof %d: ", nodeLocalDof_I );
+			
+			currEqNum = eqNum->destinationArray[lNode_I][nodeLocalDof_I];
+			if( currEqNum != -1 ) {
+				Journal_DPrintfL( self->debug, 3, "is unconstrained, eqNum %d:", currEqNum );
+
+				if( STreeMap_HasKey( eqNum->ownedMap, &currEqNum ) ) {
+					indexIntoLocalSolnVecValues = *(int*)STreeMap_Map( eqNum->ownedMap, &currEqNum );
+					Journal_DPrintfL( self->debug, 3, "local -> just copying value %f\n",
+						localSolnVecValues[indexIntoLocalSolnVecValues] );
+					DofLayout_SetValueDouble( feVar->dofLayout, lNode_I, nodeLocalDof_I,
+						localSolnVecValues[indexIntoLocalSolnVecValues] );
+				}
+				else {
+					RequestInfo*	requestInfo;
+					
+					Journal_DPrintfL( self->debug, 3, "nonlocal -> add to req list " );
+					ownerProc = FeEquationNumber_CalculateOwningProcessorOfEqNum( eqNum, currEqNum ); 
+					Journal_DPrintfL( self->debug, 3, "from proc %d\n", ownerProc );
+					/* first check count & realloc if necessary */
+					if (reqFromOthersCounts[ownerProc] == reqFromOthersSizes[ownerProc] ) {
+						newReqFromOthersSize = reqFromOthersSizes[ownerProc] * ratioToIncreaseRequestArraySize;
+						if ( newReqFromOthersSize == reqFromOthersSizes[ownerProc] ) {
+							/* Special case: always increase by at least 1 */
+							newReqFromOthersSize++;
+						}
+						reqFromOthersSizes[ownerProc] = newReqFromOthersSize;
+						
+						Journal_DPrintfL( self->debug, 3, "req list from proc %d count %d now "
+							"equal to size, so reallocing to size %d\n", 
+							ownerProc, reqFromOthersCounts[ownerProc],
+							reqFromOthersSizes[ownerProc] );
+							
+						reqFromOthersInfos[ownerProc] = Memory_Realloc_Array(
+							reqFromOthersInfos[ownerProc], RequestInfo, reqFromOthersSizes[ownerProc] );
+						reqFromOthers[ownerProc] = Memory_Realloc_Array(
+							reqFromOthers[ownerProc], Dof_EquationNumber, reqFromOthersSizes[ownerProc] );
+					}
+					requestInfo = &reqFromOthersInfos[ownerProc][ reqFromOthersCounts[ownerProc] ];
+					requestInfo->lNode_I = lNode_I;
+					requestInfo->nodeLocalDof_I = nodeLocalDof_I;
+					reqFromOthers[ownerProc][reqFromOthersCounts[ownerProc]] = currEqNum;
+					(reqFromOthersCounts[ownerProc])++;
+				}	
+			}
+			else {
+				Journal_DPrintfL( self->debug, 3, "is a BC, so skipping...\n" );
+			}
+		}
+	}				
+	
+	if ( nProc > 1 ) {
+		_SolutionVector_ShareValuesNotStoredLocally( self, reqFromOthersCounts, reqFromOthersInfos, reqFromOthers,
+			localSolnVecValues );
+	}	
+
+	for ( proc_I=0; proc_I < nProc; proc_I++ ) {
+		if (proc_I == myRank) continue;
+		Memory_Free( reqFromOthers[proc_I] );
+		Memory_Free( reqFromOthersInfos[proc_I] );
+	}
+	Memory_Free( reqFromOthers );
+	Memory_Free( reqFromOthersInfos );
+	Memory_Free( reqFromOthersCounts );
+	Memory_Free( reqFromOthersSizes );
+
+	//Vector_RestoreArray( self->vector, &localSolnVecValues );
+	VecRestoreArray( self->vector, &localSolnVecValues );
+
+	/*
+	** Syncronise the FEVariable in question.
+	*/
+
+	FeVariable_SyncShadowValues( feVar );
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _SolutionVector_ShareValuesNotStoredLocally(
+	SolutionVector*		self,
+	Index*			reqFromOthersCounts,
+	RequestInfo**		reqFromOthersInfos,
+	Dof_EquationNumber**	reqFromOthers,
+	double*			localSolnVecValues )
+{
+
+	FeVariable*		feVar = self->feVariable;
+	FeMesh*			feMesh = feVar->feMesh;
+	FeEquationNumber*	eqNum = feVar->eqNum;
+	Comm*			comm;
+	MPI_Comm		mpiComm;
+	Partition_Index		nProc;
+	Partition_Index		myRank;
+	Partition_Index		proc_I;
+	Index			req_I;
+	Index			indexIntoLocalSolnVecValues;
+	MPI_Status		status;
+	Index*			reqFromMeCounts;
+	Dof_EquationNumber**	reqFromMe;
+	double**		reqValuesFromMe;
+	MPI_Request**		reqValuesFromMeHandles;
+	MPI_Request**		reqFromOthersHandles;
+	double**		reqValuesFromOthers;
+	MPI_Request**		reqValuesFromOthersHandles;
+	Bool*			reqValuesFromOthersReceived;
+	Partition_Index	     reqValueSetsFromOthersNotYetReceivedCount;
+	Dof_EquationNumber   totalRequestedFromOthers = 0;
+	Dof_EquationNumber   totalRequestedFromMe = 0;
+
+	Journal_DPrintf( self->debug, "In %s - for \"%s\"\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	comm = Mesh_GetCommTopology( feMesh, MT_VERTEX );
+	mpiComm = Comm_GetMPIComm( comm );
+	MPI_Comm_size( mpiComm, (int*)&nProc );
+	MPI_Comm_rank( mpiComm, (int*)&myRank );
+
+	reqFromMeCounts = Memory_Alloc_Array( Index, nProc, "reqFromMeCounts" );
+	reqFromOthersHandles = Memory_Alloc_Array_Unnamed( MPI_Request*, nProc );
+	reqValuesFromOthersHandles = Memory_Alloc_Array_Unnamed( MPI_Request*, nProc );
+	reqValuesFromMeHandles = Memory_Alloc_Array_Unnamed( MPI_Request*, nProc );
+	reqValuesFromOthers = Memory_Alloc_2DComplex( double, nProc, reqFromOthersCounts, "reqValuesFromOthers" );
+	reqValuesFromOthersReceived = Memory_Alloc_Array_Unnamed( Bool, nProc );
+
+	#if DEBUG
+	if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
+		Journal_DPrintf( self->debug, "Final list of vec values I need from other procs:\n" );
+		for ( proc_I=0; proc_I < nProc; proc_I++ ) {
+			if ( proc_I == myRank ) continue;
+			Journal_DPrintf( self->debug, "\t%d[0-%d]: ", proc_I, reqFromOthersCounts[proc_I] );
+			for ( req_I=0; req_I < reqFromOthersCounts[proc_I]; req_I++ ) {
+				RequestInfo* reqInfo = &reqFromOthersInfos[proc_I][req_I];
+				Journal_DPrintf( self->debug, "(lnode %d, dof %d -> %d ), ",
+					reqInfo->lNode_I, reqInfo->nodeLocalDof_I,
+					reqFromOthers[proc_I][req_I] );
+			}
+			Journal_DPrintf( self->debug, "\n" );
+		}
+	}	
+	#endif
+	
+	/* send out my request counts, receive the req. counts others want from me */
+	MPI_Alltoall( reqFromOthersCounts, 1, MPI_UNSIGNED,
+		      reqFromMeCounts, 1, MPI_UNSIGNED, mpiComm );
+
+	Journal_DPrintf( self->debug, "After MPI_Alltoall- counts are:\n" );
+	totalRequestedFromOthers = 0;
+	totalRequestedFromMe = 0;
+	Stream_Indent( self->debug );
+	Journal_DPrintf( self->debug, "reqFromOthersCounts: " );
+	for ( proc_I=0; proc_I < nProc; proc_I++ ) {
+		if ( proc_I == myRank ) continue;
+		Journal_DPrintf( self->debug, "\tp%d:%d, ", proc_I, reqFromOthersCounts[proc_I] );
+		totalRequestedFromOthers += reqFromOthersCounts[proc_I];
+	}
+	Journal_DPrintf( self->debug, "\n" );
+	Journal_DPrintf( self->debug, "reqFromMeCounts: " );
+	for ( proc_I=0; proc_I < nProc; proc_I++ ) {
+		if ( proc_I == myRank ) continue;
+		Journal_DPrintf( self->debug, "\tp%d:%d, ", proc_I, reqFromMeCounts[proc_I] );
+		totalRequestedFromMe += reqFromMeCounts[proc_I];
+	}
+	Journal_DPrintf( self->debug, "\n" );
+	Stream_UnIndent( self->debug );
+
+	if ( ( totalRequestedFromOthers == 0) && (totalRequestedFromMe == 0) ) 
+	{	
+		Journal_DPrintf( self->debug, "No vector values either required from others or "
+			"required by others from me, therefore cleaning up memory and returning.\n" );
+		Memory_Free( reqFromMeCounts );
+		Memory_Free( reqFromOthersHandles );
+		Memory_Free( reqValuesFromOthersHandles );
+		Memory_Free( reqValuesFromMeHandles );
+		Memory_Free( reqValuesFromOthers ); 
+		Memory_Free( reqValuesFromOthersReceived );
+		Stream_UnIndentBranch( StgFEM_Debug );
+		return;
+	}
+
+	Journal_DPrintfL( self->debug, 2, "Starting non-blocking sends of my lists of vector entry indices I want from others:\n" );
+	Stream_Indent( self->debug );
+	for( proc_I=0; proc_I < nProc; proc_I++) {
+		if ( proc_I == myRank ) continue; 
+/* Journal_Printf( Journal_Register( Info_Type, (Name)"mpi"  ),  "!!! line %d, proc_I %d: count = %u\n", __LINE__, proc_I, reqFromOthersCounts[proc_I] ); */
+		if ( reqFromOthersCounts[proc_I] > 0 ) {
+			Journal_DPrintfL( self->debug, 2, "Sending to proc %d the list of %d vector entry indices I want from it:\n"
+				"\t(tracking via reqFromOthersHandles[%d], tag %d)\n", proc_I,
+				reqFromOthersCounts[proc_I], proc_I, VALUE_REQUEST_TAG );
+
+			reqFromOthersHandles[proc_I] = Memory_Alloc_Unnamed( MPI_Request );
+			MPI_Isend( reqFromOthers[proc_I], reqFromOthersCounts[proc_I], MPI_UNSIGNED,
+				proc_I, VALUE_REQUEST_TAG, mpiComm, reqFromOthersHandles[proc_I] );
+		}	
+	}
+	Stream_UnIndent( self->debug );
+
+
+	Journal_DPrintfL( self->debug, 2, "Starting non-blocking receive of the vector entries I want from others:\n" );
+	Stream_Indent( self->debug );
+	for( proc_I=0; proc_I < nProc; proc_I++) {
+		if ( proc_I == myRank ) continue; 
+		if ( reqFromOthersCounts[proc_I] > 0 ) {
+			Journal_DPrintfL( self->debug, 2, "Posting recv reqst from proc %d for the %d vector entries I want from it:\n"
+				"\t(tracking via reqValuesFromOthersHandles[%d], tag %d)\n", proc_I,
+				reqFromOthersCounts[proc_I], proc_I, VALUE_TAG );
+			reqValuesFromOthersHandles[proc_I] = Memory_Alloc_Unnamed( MPI_Request );
+			MPI_Irecv( reqValuesFromOthers[proc_I], reqFromOthersCounts[proc_I], MPI_DOUBLE,
+				proc_I, VALUE_TAG, mpiComm, reqValuesFromOthersHandles[proc_I] );
+		}	
+	}
+	Stream_UnIndent( self->debug );
+
+	Journal_DPrintfL( self->debug, 2, "Starting blocking receive of the lists of vector entry indices "
+		"others want from me:\n" );
+	Stream_Indent( self->debug );
+	reqFromMe = Memory_Alloc_2DComplex( Dof_EquationNumber, nProc, reqFromMeCounts, "reqFromMe" );
+	reqValuesFromMe = Memory_Alloc_2DComplex( double, nProc, reqFromMeCounts, "reqValuesFromMe" );
+	for( proc_I=0; proc_I < nProc; proc_I++) {
+		if ( proc_I == myRank ) continue; 
+/* /Journal_Printf( Journal_Register( Info_Type, (Name)"mpi"  ),  "!!! line %d, proc_I %d: count = %u\n", __LINE__, proc_I, reqFromMeCounts[proc_I] ); */
+		if ( reqFromMeCounts[proc_I] > 0 ) {
+			MPI_Recv( reqFromMe[proc_I], reqFromMeCounts[proc_I], MPI_UNSIGNED,
+				proc_I, VALUE_REQUEST_TAG, mpiComm, &status );
+			Journal_DPrintfL( self->debug, 3, "Received a list of %u requested vector entry indices from proc %u, "
+				"with tag %d\n", reqFromMeCounts[proc_I], proc_I, status.MPI_TAG );
+		}	
+	}
+	Stream_UnIndent( self->debug );
+	
+	#if DEBUG
+	if ( Stream_IsPrintableLevel( self->debug, 2 ) ) {
+		Journal_DPrintf( self->debug, "Final lists of vector entry indices other procs want from me are:\n" );
+		Stream_Indent( self->debug );
+		for ( proc_I=0; proc_I < nProc; proc_I++ ) {
+			if ( proc_I == myRank ) continue;
+			if ( reqFromMeCounts[proc_I] > 0 ) {
+				Journal_DPrintf( self->debug, "%d[0-%d]: ", proc_I, reqFromMeCounts[proc_I] );
+				for ( req_I=0; req_I < reqFromMeCounts[proc_I]; req_I++ ) {
+					Journal_DPrintf( self->debug, "(eqNum %d), ", reqFromMe[proc_I][req_I] );
+				}
+				Journal_DPrintf( self->debug, "\n" );
+			}
+		}
+		Stream_UnIndent( self->debug );
+	}	
+	#endif
+	
+	/* for all those requested from me, non-blocking send out values */
+	Journal_DPrintfL( self->debug, 2, "Beginning non-blocking send out of vector entry lists requested by others:\n" );
+	Stream_Indent( self->debug );
+	for( proc_I=0; proc_I < nProc; proc_I++) {
+		if ( proc_I == myRank ) continue; 
+		if ( reqFromMeCounts[proc_I] > 0 ) {
+			Journal_DPrintfL( self->debug, 3, "list to proc %d is: ", proc_I );
+			for ( req_I=0; req_I < reqFromMeCounts[proc_I]; req_I++ ) {
+				/* look up and fill in correct value in array */
+				indexIntoLocalSolnVecValues = *(int*)STreeMap_Map( eqNum->ownedMap,
+										   reqFromMe[proc_I] + req_I );
+				reqValuesFromMe[proc_I][req_I] = localSolnVecValues[indexIntoLocalSolnVecValues];
+				Journal_DPrintfL( self->debug, 3, "%d=%f, ", reqFromMe[proc_I][req_I],
+					reqValuesFromMe[proc_I][req_I] );
+			}
+			Journal_DPrintfL( self->debug, 3, "\n" );
+			/* Non-blocking send out the now-complete list to this processor */
+			reqValuesFromMeHandles[proc_I] = Memory_Alloc_Unnamed( MPI_Request );
+			Journal_DPrintfL( self->debug, 2, "Sending to proc %d the list of %d vector entries they want:\n"
+				"\t(tracking via reqValuesFromMe[%d], tag %d)\n", proc_I,
+				reqFromMeCounts[proc_I], proc_I, VALUE_TAG );
+			MPI_Isend( reqValuesFromMe[proc_I], reqFromMeCounts[proc_I], MPI_DOUBLE,
+				proc_I, VALUE_TAG, mpiComm, reqValuesFromMeHandles[proc_I] );
+		}	
+	}
+	Stream_UnIndent( self->debug );
+	
+	Journal_DPrintfL( self->debug, 1, "Starting iterative-test receive of the vector entries I "
+		"requested from others:\n" );
+	/* Set up an array for keeping track of who we've received things from
+	 * already */
+	reqValueSetsFromOthersNotYetReceivedCount = nProc-1;
+	for( proc_I=0; proc_I < nProc; proc_I++) {
+		if ( proc_I == myRank ) continue; 
+		reqValuesFromOthersReceived[proc_I] = False;
+		if ( reqFromOthersCounts[proc_I] == 0 ) {
+			reqValueSetsFromOthersNotYetReceivedCount--;
+		}	
+	}	
+
+	#if DEBUG
+	Journal_DPrintfL( self->debug, 2, "(Expecting %d receives from procs: ",
+		reqValueSetsFromOthersNotYetReceivedCount );
+	for( proc_I=0; proc_I < nProc; proc_I++) {
+		if ( proc_I == myRank ) continue; 
+		if ( reqFromOthersCounts[proc_I] > 0 ) {
+			Journal_DPrintfL( self->debug, 2, "%d, ", proc_I );
+		}	
+	}	
+	Journal_DPrintfL( self->debug, 2, ")\n" );
+	#endif
+
+	Stream_Indent( self->debug );
+	/* now update the values at nodes that I requested from others, as they come in */
+	while ( reqValueSetsFromOthersNotYetReceivedCount ) {	
+		int flag = 0;
+
+		Journal_DPrintfL( self->debug, 3, "%d sets still to go...\n", reqValueSetsFromOthersNotYetReceivedCount );
+		for( proc_I=0; proc_I < nProc; proc_I++) {
+			if ( proc_I == myRank ) continue; 
+
+			if ( (reqFromOthersCounts[proc_I] > 0) && (False == reqValuesFromOthersReceived[proc_I]) ) {
+				MPI_Test( reqValuesFromOthersHandles[proc_I], &flag, &status );
+				if ( !flag ) {
+					/* No results yet from this proc -> continue to next. */
+					continue;
+				}
+				else {
+					RequestInfo* reqInfo;
+					Journal_DPrintfL( self->debug, 2, "received some requested "
+						"values (using reqValuesFromOthersHandles) from proc %d "
+						"(with tag %d, exp %d):", proc_I, status.MPI_TAG, VALUE_TAG );
+					/* go through each value received from that proc & update onto node */
+					for ( req_I=0; req_I < reqFromOthersCounts[proc_I]; req_I++ ) {
+						reqInfo = &reqFromOthersInfos[proc_I][req_I];
+						Journal_DPrintfL( self->debug, 3, "(lnode %d, dof %d -> %d )=%f, ",
+							reqInfo->lNode_I, reqInfo->nodeLocalDof_I,
+							reqFromOthers[proc_I][req_I], reqValuesFromOthers[proc_I][req_I] );
+						DofLayout_SetValueDouble( feVar->dofLayout, reqInfo->lNode_I, reqInfo->nodeLocalDof_I,
+							reqValuesFromOthers[proc_I][req_I] );
+					}
+					Journal_DPrintfL( self->debug, 2, "\n" );
+					reqValuesFromOthersReceived[proc_I] = True;
+					reqValueSetsFromOthersNotYetReceivedCount--;
+					Memory_Free( reqValuesFromOthersHandles[proc_I] );
+				}	
+			}	
+		}
+	}	
+	Stream_UnIndent( self->debug );
+
+	/* MPI_Wait to be sure all sends to others have completed */
+	Journal_DPrintfL( self->debug, 2, "Making sure all comms of this function finished:...\n" );
+	Stream_Indent( self->debug );
+
+	Journal_DPrintfL( self->debug, 2, "Confirming completion of my sends of "
+		"vector entry index lists I wanted from others were received:\n" );
+	Stream_Indent( self->debug );
+	for( proc_I=0; proc_I < nProc; proc_I++) {
+		if ( proc_I == myRank ) continue; 
+		if ( reqFromOthersCounts[proc_I] > 0 ) {
+			MPI_Wait( reqFromOthersHandles[proc_I], MPI_STATUS_IGNORE ); 
+			Journal_DPrintfL( self->debug, 2, "Confirmed wait on reqFromOthersHandles[%u]"
+				"\n", proc_I );
+			Memory_Free( reqFromOthersHandles[proc_I] );
+		}	
+	}	
+	Stream_UnIndent( self->debug );
+	Journal_DPrintfL( self->debug, 2, "done.\n" );
+
+	Journal_DPrintfL( self->debug, 2, "Confirming completion of my sends of "
+		"vector entry values requested by others were received:\n" );
+	Stream_Indent( self->debug );
+	for( proc_I=0; proc_I < nProc; proc_I++) {
+		if ( proc_I == myRank ) continue; 
+		if ( reqFromMeCounts[proc_I] > 0 ) {
+			MPI_Wait( reqValuesFromMeHandles[proc_I], MPI_STATUS_IGNORE );
+			Journal_DPrintfL( self->debug, 2, "Confirmed wait on reqValuesFromMeHandles[%u]"
+				"\n", proc_I );
+			Memory_Free( reqValuesFromMeHandles[proc_I] );
+		}
+	}	
+	Stream_UnIndent( self->debug );
+	Journal_DPrintfL( self->debug, 2, "done.\n" );
+
+	Stream_UnIndent( self->debug );
+	Journal_DPrintfL( self->debug, 2, "done.\n" );
+
+	Memory_Free( reqFromMeCounts );
+	Memory_Free( reqFromMe );
+	Memory_Free( reqValuesFromMe );
+	Memory_Free( reqValuesFromOthers );
+	Memory_Free( reqValuesFromOthersReceived );
+	Memory_Free( reqFromOthersHandles );
+	Memory_Free( reqValuesFromOthersHandles );
+	Memory_Free( reqValuesFromMeHandles );
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+	return;
+}
+
+
+void SolutionVector_LoadCurrentFeVariableValuesOntoVector( void* solutionVector ) {
+	SolutionVector*		self = (SolutionVector*)solutionVector;
+	FeVariable*		feVar = self->feVariable;
+	FeMesh*			feMesh = feVar->feMesh;
+	Node_LocalIndex		node_lI = 0;
+	Dof_Index		dof_I = 0;
+	double			value = 0;
+	Index			insertionIndex = 0;
+	
+	for ( node_lI = 0; node_lI < FeMesh_GetNodeLocalSize( feMesh ); node_lI++ ) {
+		for ( dof_I = 0; dof_I < feVar->dofLayout->dofCounts[node_lI]; dof_I++ ) {
+			value = DofLayout_GetValueDouble( feVar->dofLayout, node_lI, dof_I );
+			insertionIndex = feVar->eqNum->destinationArray[node_lI][dof_I];
+			//Vector_InsertEntries( self->vector, 1, &insertionIndex, &value );
+			VecSetValues( self->vector, 1, (PetscInt*)(&insertionIndex), &value, INSERT_VALUES );
+		}	
+	}
+
+	//Vector_AssemblyBegin( self->vector );
+	//Vector_AssemblyEnd( self->vector ); 
+	VecAssemblyBegin( self->vector );
+	VecAssemblyEnd( self->vector ); 
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/StiffnessMatrix.c
--- a/SLE/SystemSetup/src/StiffnessMatrix.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2909 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: StiffnessMatrix.c 1210 2008-08-25 01:17:12Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include <mpi.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "FiniteElementContext.h"
-#include "StiffnessMatrix.h"
-#include "StiffnessMatrixTerm.h"
-#include "SystemLinearEquations.h"
-#include "EntryPoint.h"
-#include "SolutionVector.h"
-#include "ForceVector.h"
-#include "Assembler.h"
-
-void __StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context );
-void StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context );
-Bool StiffnessMatrix_ZeroBCsAsm_RowR( void* stiffMat, Assembler* assm );
-Bool StiffnessMatrix_ZeroBCsAsm_ColR( void* stiffMat, Assembler* assm );
-Bool StiffnessMatrix_BCAsm_ColR( void* stiffMat, Assembler* assm );
-Bool StiffnessMatrix_TransBCAsm_ColR( void* stiffMat, Assembler* assm );
-Bool StiffnessMatrix_DiagBCsAsm_RowR( void* stiffMat, Assembler* assm );
-
-
-/* Textual name of this class */
-const Type StiffnessMatrix_Type = "StiffnessMatrix";
-
-/** First part of name for build entry point */
-static const char	StiffnessMatrix_assembleStiffnessMatrixStr[] = "assembleStiffnessMatrix";
-
-
-void* StiffnessMatrix_DefaultNew( Name name )
-{
-	/* Variables set in this function */
-	SizeT                                                               _sizeOfSelf = sizeof(StiffnessMatrix);
-	Type                                                                       type = StiffnessMatrix_Type;
-	Stg_Class_DeleteFunction*                                               _delete = _StiffnessMatrix_Delete;
-	Stg_Class_PrintFunction*                                                 _print = _StiffnessMatrix_Print;
-	Stg_Class_CopyFunction*                                                   _copy = _StiffnessMatrix_Copy;
-	Stg_Component_DefaultConstructorFunction*                   _defaultConstructor = StiffnessMatrix_DefaultNew;
-	Stg_Component_ConstructFunction*                                     _construct = _StiffnessMatrix_AssignFromXML;
-	Stg_Component_BuildFunction*                                             _build = _StiffnessMatrix_Build;
-	Stg_Component_InitialiseFunction*                                   _initialise = _StiffnessMatrix_Initialise;
-	Stg_Component_ExecuteFunction*                                         _execute = _StiffnessMatrix_Execute;
-	Stg_Component_DestroyFunction*                                         _destroy = _StiffnessMatrix_Destroy;
-	Bool                                                                   initFlag = False;
-	StiffnessMatrix_CalculateNonZeroEntriesFunction*       _calculateNonZeroEntries = StiffnessMatrix_CalcNonZeros;
-	void*                                                               rowVariable = NULL;
-	void*                                                            columnVariable = NULL;
-	void*                                                                       rhs = NULL;
-	Stg_Component*                                               applicationDepInfo = NULL;
-	Dimension_Index                                                             dim = 0;
-	Bool                                                                isNonLinear = False;
-	Bool                                              allowZeroElementContributions = False;
-	void*                                                       entryPoint_Register = NULL;
-	MPI_Comm                                                                   comm = 0;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _StiffnessMatrix_New(  STIFFNESSMATRIX_PASSARGS  );
-}
-
-
-StiffnessMatrix* StiffnessMatrix_New(
-	Name                                             name,
-	void*                                            rowVariable,
-	void*                                            columnVariable,
-	void*                                            rhs,
-	Stg_Component*                                   applicationDepInfo,
-	Dimension_Index                                  dim,
-	Bool                                             isNonLinear,
-	Bool                                             allowZeroElementContributions,
-	void*                                            entryPoint_Register,
-	MPI_Comm                                         comm )
-{
-	/* Variables set in this function */
-	SizeT                                                          _sizeOfSelf = sizeof(StiffnessMatrix);
-	Type                                                                  type = StiffnessMatrix_Type;
-	Stg_Class_DeleteFunction*                                          _delete = _StiffnessMatrix_Delete;
-	Stg_Class_PrintFunction*                                            _print = _StiffnessMatrix_Print;
-	Stg_Class_CopyFunction*                                              _copy = _StiffnessMatrix_Copy;
-	Stg_Component_DefaultConstructorFunction*              _defaultConstructor = StiffnessMatrix_DefaultNew;
-	Stg_Component_ConstructFunction*                                _construct = _StiffnessMatrix_AssignFromXML;
-	Stg_Component_BuildFunction*                                        _build = _StiffnessMatrix_Build;
-	Stg_Component_InitialiseFunction*                              _initialise = _StiffnessMatrix_Initialise;
-	Stg_Component_ExecuteFunction*                                    _execute = _StiffnessMatrix_Execute;
-	Stg_Component_DestroyFunction*                                    _destroy = _StiffnessMatrix_Destroy;
-	Bool                                                              initFlag = True;
-	StiffnessMatrix_CalculateNonZeroEntriesFunction*  _calculateNonZeroEntries = StiffnessMatrix_CalcNonZeros;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _StiffnessMatrix_New(  STIFFNESSMATRIX_PASSARGS  );
-}
-
-
-StiffnessMatrix* _StiffnessMatrix_New(  STIFFNESSMATRIX_DEFARGS  )
-{
-	StiffnessMatrix*	self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(StiffnessMatrix) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (StiffnessMatrix*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-	
-	/* General info */
-	
-	/* Virtual functions */
-	self->_calculateNonZeroEntries = _calculateNonZeroEntries;
-	
-	if( initFlag ){
-		_StiffnessMatrix_Init( self, rowVariable, columnVariable, rhs, applicationDepInfo, dim,
-				       isNonLinear, allowZeroElementContributions, entryPoint_Register, comm );
-	}
-	
-	return self;
-}
-
-void _StiffnessMatrix_Init(
-	StiffnessMatrix*                                 self,
-	void*                                            rowVariable,
-	void*                                            columnVariable,
-	void*                                            rhs,
-	Stg_Component*                                   applicationDepInfo,
-	Dimension_Index                                  dim,
-	Bool                                             isNonLinear,
-	Bool                                             allowZeroElementContributions,
-	void*                                            entryPoint_Register,
-	MPI_Comm                                         comm )
-{
-	Stream*		error = Journal_Register( ErrorStream_Type, (Name)self->type  );
-	Stream*		stream;
-
-	/* General and Virtual info should already be set */
-	stream = Journal_Register( Info_Type, (Name)self->type  );
-	Stream_SetPrintingRank( stream, 0 );
-	
-	/* StiffnessMatrix info */
-	self->isConstructed = True;
-	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
-	Journal_Firewall( (rowVariable != NULL), error, "Error: NULL row FeVariable provided to \"%s\" %s.\n", self->name, self->type );
-
-	self->rowVariable = (FeVariable*)rowVariable;
-	Journal_Firewall( (columnVariable != NULL), error, "Error: NULL column FeVariable provided to \"%s\" %s.\n", self->name, self->type );
-
-	self->columnVariable = (FeVariable*)columnVariable;
-	Journal_Firewall( (rhs != NULL), error, "Error: NULL rhs ForceVector provided to \"%s\" %s.\n", self->name, self->type );
-
-	self->rhs = (ForceVector*)rhs;
-	self->applicationDepInfo = applicationDepInfo;
-	self->comm = comm;
-	self->dim = dim;
-	self->isNonLinear = isNonLinear;
-	self->allowZeroElementContributions = allowZeroElementContributions;
-	
-	self->rowLocalSize = 0;
-	self->colLocalSize = 0;
-	self->nonZeroCount = 0;
-	self->diagonalNonZeroCount = 0;
-	self->offDiagonalNonZeroCount = 0;
-	self->diagonalNonZeroIndices = NULL;
-	self->offDiagonalNonZeroIndices = NULL;
-	
-	self->entryPoint_Register = (EntryPoint_Register*)entryPoint_Register;
-
-	Stg_asprintf( &self->_assembleStiffnessMatrixEPName, "%s-%s", self->name, StiffnessMatrix_assembleStiffnessMatrixStr );
-	self->assembleStiffnessMatrix = FeEntryPoint_New( self->_assembleStiffnessMatrixEPName, FeEntryPoint_AssembleStiffnessMatrix_CastType );
-
-	EntryPoint_Register_Add( self->entryPoint_Register, self->assembleStiffnessMatrix );
-
-	self->stiffnessMatrixTermList = Stg_ObjectList_New();
-
-	/* Set default function for Global Stiffness Matrix Assembly */
-	EP_ReplaceAll( self->assembleStiffnessMatrix, __StiffnessMatrix_NewAssemble );
-
-	/* We need some assembler contexts. */
-	self->zeroBCsAsm = Assembler_New();
-	self->bcAsm = Assembler_New();
-	self->transBCAsm = Assembler_New();
-
-	if( rowVariable == columnVariable )
-		self->diagBCsAsm = Assembler_New();
-
-	self->elStiffMat = NULL;
-	self->bcVals = NULL;
-	self->nRowDofs = 0;
-	self->nColDofs = 0;
-	self->transRHS = NULL;
-
-	self->rowInc = IArray_New();
-	self->colInc = IArray_New();
-
-	self->nModifyCBs = 0;
-	self->modifyCBs = NULL;
-
-	self->matrix = PETSC_NULL;
-	/* self->shellMatrix = NULL; */
-	/* self->useShellMatrix = False; */
-}
-
-void _StiffnessMatrix_Delete( void* stiffnessMatrix ) {
-	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
-	/* Stg_Class_Delete parent*/
-	_Stg_Component_Delete( self );
-	
-}
-
-void _StiffnessMatrix_Print( void* stiffnessMatrix, Stream* stream ) {
-	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
-	
-	/* Set the Journal for printing informations */
-	Stream* stiffnessMatrixStream = stream;
-	
-	/* General info */
-	Journal_Printf( stiffnessMatrixStream, "StiffnessMatrix (ptr): %p\n", self );
-	
-	/* Print parent */
-	_Stg_Component_Print( self, stiffnessMatrixStream );
-	
-	/* Virtual info */
-	Journal_Printf( stiffnessMatrixStream, "\t_build (func ptr): %p\n", self->_build );
-	
-	Journal_Printf( stiffnessMatrixStream, "\tassembleStiffnessMatrix e.p. (ptr): %p\n", self->assembleStiffnessMatrix );
-	EntryPoint_PrintConcise( self->assembleStiffnessMatrix, stream );
-	
-	/* StiffnessMatrix info */
-	Journal_Printf( stiffnessMatrixStream, "\trowVariable (ptr): %p\n", self->rowVariable );
-	Journal_Printf( stiffnessMatrixStream, "\t\tvariable name: %s\n", self->rowVariable->name );
-	Journal_Printf( stiffnessMatrixStream, "\tcolumnVariable (ptr): %p\n", self->columnVariable );
-	Journal_Printf( stiffnessMatrixStream, "\t\tvariable name: %s\n", self->columnVariable->name );
-	Journal_Printf( stiffnessMatrixStream, "\tMatrix (ptr): %p\n", self->matrix );
-	Journal_Printf( stiffnessMatrixStream, "\tComm: %u\n", self->comm );
-	Journal_Printf( stiffnessMatrixStream, "\trowLocalSize: %u\n", self->rowLocalSize );
-	Journal_Printf( stiffnessMatrixStream, "\tcolLocalSize: %u\n", self->colLocalSize );
-	Journal_Printf( stiffnessMatrixStream, "\tnonZeroCount: %u\n", self->nonZeroCount );
-	Journal_Printf( stiffnessMatrixStream, "\tisNonLinear: %s\n", StG_BoolToStringMap[self->isNonLinear] );
-	Journal_Printf( stiffnessMatrixStream, "\tallowZeroElementContributions: %s\n", StG_BoolToStringMap[self->allowZeroElementContributions] );
-}
-
-void* _StiffnessMatrix_Copy( const void* stiffnessMatrix, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	StiffnessMatrix*	self = (StiffnessMatrix*)stiffnessMatrix;
-	StiffnessMatrix*	newStiffnessMatrix;
-	PtrMap*			map = ptrMap;
-	Bool			ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newStiffnessMatrix = (StiffnessMatrix*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
-	
-	/* Virtual functions */
-	newStiffnessMatrix->_calculateNonZeroEntries = self->_calculateNonZeroEntries;
-	
-	/* TODO: copy matrix */
-	newStiffnessMatrix->matrix = self->matrix;
-/* 	newStiffnessMatrix->shellMatrix = self->shellMatrix; */
-	newStiffnessMatrix->entryPoint_Register = self->entryPoint_Register;
-	newStiffnessMatrix->comm = self->comm;
-	newStiffnessMatrix->rowLocalSize = self->rowLocalSize;
-	newStiffnessMatrix->colLocalSize = self->colLocalSize;
-	newStiffnessMatrix->dim = self->dim;
-	newStiffnessMatrix->nonZeroCount = self->nonZeroCount;
-	newStiffnessMatrix->diagonalNonZeroCount = self->diagonalNonZeroCount;
-	newStiffnessMatrix->offDiagonalNonZeroCount = self->offDiagonalNonZeroCount;
-	
-	if( deep ) {
-		newStiffnessMatrix->debug = (Stream*)Stg_Class_Copy( self->debug, NULL, deep, nameExt, map );
-		newStiffnessMatrix->rowVariable = (FeVariable*)Stg_Class_Copy( self->rowVariable, NULL, deep, nameExt, map );
-		newStiffnessMatrix->columnVariable = (FeVariable*)Stg_Class_Copy( self->columnVariable, NULL, deep, nameExt, map );
-		newStiffnessMatrix->rhs =(ForceVector*)Stg_Class_Copy( self->rhs, NULL, deep, nameExt, map );
-		newStiffnessMatrix->assembleStiffnessMatrix = (FeEntryPoint*)Stg_Class_Copy( self->assembleStiffnessMatrix, NULL, deep, nameExt, map );
-		
-		if( self->_assembleStiffnessMatrixEPName ) {
-			if( nameExt ) {
-				Stg_asprintf( &newStiffnessMatrix->_assembleStiffnessMatrixEPName, "%s%s", 
-					      self->_assembleStiffnessMatrixEPName, nameExt );
-			}
-			else {
-				newStiffnessMatrix->_assembleStiffnessMatrixEPName = StG_Strdup( self->_assembleStiffnessMatrixEPName );
-			}
-		}
-		else {
-			newStiffnessMatrix->_assembleStiffnessMatrixEPName = NULL;
-		}
-		
-		/* Arrays */
-		if( (newStiffnessMatrix->diagonalNonZeroIndices = (Index*)PtrMap_Find( map, self->diagonalNonZeroIndices )) == NULL ) {
-			if( self->diagonalNonZeroIndices ) {
-				newStiffnessMatrix->diagonalNonZeroIndices = Memory_Alloc_Array( Index, 
-												 newStiffnessMatrix->rowLocalSize, "diagonalNonZeroIndices" );
-				memcpy( newStiffnessMatrix->diagonalNonZeroIndices, self->diagonalNonZeroIndices, 
-					newStiffnessMatrix->rowLocalSize * sizeof( Index ) );
-				PtrMap_Append( map, self->diagonalNonZeroIndices, newStiffnessMatrix->diagonalNonZeroIndices );
-			}
-			else {
-				newStiffnessMatrix->diagonalNonZeroIndices = NULL;
-			}
-		}
-		
-		if( (newStiffnessMatrix->offDiagonalNonZeroIndices = (Index*)PtrMap_Find( map, self->offDiagonalNonZeroIndices )) == NULL ) {
-			if( self->offDiagonalNonZeroIndices ) {
-				newStiffnessMatrix->offDiagonalNonZeroIndices = Memory_Alloc_Array( Index, 
-												    newStiffnessMatrix->rowLocalSize, "diagonalNonZeroIndices" );
-				memcpy( newStiffnessMatrix->offDiagonalNonZeroIndices, self->offDiagonalNonZeroIndices, 
-					newStiffnessMatrix->rowLocalSize * sizeof( Index ) );
-				PtrMap_Append( map, self->offDiagonalNonZeroIndices, newStiffnessMatrix->offDiagonalNonZeroIndices );
-			}
-			else {
-				newStiffnessMatrix->offDiagonalNonZeroIndices = NULL;
-			}
-		}
-	}
-	else {
-		newStiffnessMatrix->debug = self->debug;
-		newStiffnessMatrix->rowVariable = self->rowVariable;
-		newStiffnessMatrix->columnVariable = self->columnVariable;
-		newStiffnessMatrix->rhs = self->rhs;
-		newStiffnessMatrix->diagonalNonZeroIndices = self->diagonalNonZeroIndices;
-		newStiffnessMatrix->offDiagonalNonZeroIndices = self->offDiagonalNonZeroIndices;
-	}
-	
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-	
-	return (void*)newStiffnessMatrix;
-}
-
-void _StiffnessMatrix_AssignFromXML( void* stiffnessMatrix, Stg_ComponentFactory* cf, void* data ) {
-	StiffnessMatrix* self               = (StiffnessMatrix*)stiffnessMatrix;
-	Stream*		 stream;
-	FeVariable*      rowVar             = NULL;
-	FeVariable*      colVar             = NULL;
-	ForceVector*     fVector            = NULL;
-	Stg_Component*   applicationDepInfo = NULL;
-	void*            entryPointRegister = NULL;
-	Dimension_Index  dim                = 0;
-	Bool             isNonLinear;
-	Bool             allowZeroElementContributions;
-	
-	self->context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
-	if( !self->context  )
-		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
-
-	rowVar             = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"RowVariable", FeVariable, True, data  );
-	colVar             = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ColumnVariable", FeVariable, True, data  );
-	fVector            = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"RHS", ForceVector, False, data  );
-	applicationDepInfo = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ApplicationDepInfo", Stg_Component, False, data);
-	
-	entryPointRegister = self->context->entryPoint_Register; 
-	assert( entryPointRegister  );
-	
-	dim = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"dim", 0 );
-	assert( dim  );
-
-	isNonLinear = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"isNonLinear", False  );
-
-	/* Default is to allow zero element contributions - to allow backward compatibility */
-	allowZeroElementContributions = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"allowZeroElementContributions", True  );
-
-	_StiffnessMatrix_Init( 
-		self, 
-		rowVar, 
-		colVar, 
-		fVector, 
-		applicationDepInfo, 
-		dim,
-		isNonLinear,
-		allowZeroElementContributions,
-		entryPointRegister, 
-		0 );
-
-	/* Do we need to use the transpose? */
-	self->transRHS = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"transposeRHS", ForceVector, False, data  );
-
-	/* Read the matrix type from the dictionary. */
-/* 	self->shellMatrix = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"matrix", PETScShellMatrix, False, data ); */
-/* 	if( !self->shellMatrix  ) { */
-/* 		self->useShellMatrix = False; */
-/* 	} */
-/* 	else { */
-/* 		EP_ReplaceAll( self->assembleStiffnessMatrix, StiffnessMatrix_ShellAssembly ); */
-
-/* 		self->useShellMatrix = True; */
-/* 	} */
-
-	/* Setup the stream. */
-	stream = Journal_Register( Info_Type, (Name)self->type  );
-	if( Dictionary_GetBool_WithDefault( cf->rootDict, (Dictionary_Entry_Key)"watchAll", False ) == True  )
-		Stream_SetPrintingRank( stream, STREAM_ALL_RANKS );
-	else {
-		unsigned	rankToWatch;
-
-		rankToWatch = Dictionary_GetUnsignedInt_WithDefault( cf->rootDict, "rankToWatch", 0 );
-		Stream_SetPrintingRank( stream, rankToWatch );
-	}
-}
-
-void _StiffnessMatrix_Build( void* stiffnessMatrix, void* data ) {
-	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
-
-	Journal_DPrintf( self->debug, "In %s - for matrix %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	/* ensure variables are built */
-	if( self->rowVariable )
-		Stg_Component_Build( self->rowVariable, data, False );
-
-	/* If we don't have a communicator, grab one off the mesh. */
-	if( !self->comm ) {
-		self->comm = Mesh_GetCommTopology( self->rowVariable->feMesh, MT_VERTEX )->mpiComm;
-		Journal_Firewall( (self->comm != 0), self->debug, "Error: NULL Comm provided to \"%s\" %s.\n",
-				  self->name, self->type );
-	}
-	
-	if( self->columnVariable )
-		Stg_Component_Build( self->columnVariable, data, False );
-
-   /* ensure the rhs vector is built */
-   Stg_Component_Build( self->rhs, data, False );
-
-	
-/* 	if( self->useShellMatrix ) */
-/* 		Stg_Component_Build( self->shellMatrix, data, False ); */
-	
-#if DEBUG
-	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-		Journal_DPrintf( self->debug, "Row variable(%s) I.D. array calc. as:\n", self->rowVariable->name );
-		FeEquationNumber_PrintDestinationArray( self->rowVariable->eqNum, self->debug );
-		Journal_DPrintf( self->debug, "Column variable(%s) I.D. array calc. as:\n", self->columnVariable->name );
-		FeEquationNumber_PrintDestinationArray( self->columnVariable->eqNum, self->debug );
-	}
-#endif
-	
-	/* update the row and column sizes for the variables */	
-	self->rowLocalSize = self->rowVariable->eqNum->localEqNumsOwnedCount;
-	assert( self->rowLocalSize );
-	self->colLocalSize = self->columnVariable->eqNum->localEqNumsOwnedCount;
-	assert( self->colLocalSize );
-	
-	/* update the number of non zero entries from the finite element variables */
-	StiffnessMatrix_CalcNonZeros( self );
-	
-	Journal_DPrintf( self->debug, "row(%s) localSize = %d : col(%s) localSize = %d \n", self->rowVariable->name,
-		self->rowLocalSize, self->columnVariable->name, self->colLocalSize );
-	
-	/* assert( self->nonZeroCount ); */
-
-	StiffnessMatrix_RefreshMatrix( self );
-
-	Journal_DPrintf( self->debug, "Matrix allocated.\n" );
-
-	Assembler_SetVariables( self->zeroBCsAsm, self->rowVariable, self->columnVariable );
-	Assembler_SetCallbacks( self->zeroBCsAsm, NULL, StiffnessMatrix_ZeroBCsAsm_RowR, NULL, 
-		StiffnessMatrix_ZeroBCsAsm_ColR, NULL, 
-		self );
-	Assembler_SetVariables( self->bcAsm, self->rowVariable, self->columnVariable );
-	Assembler_SetCallbacks( self->bcAsm, 
-		NULL, 
-		NULL, NULL, 
-		StiffnessMatrix_BCAsm_ColR, NULL, 
-		self );
-	Assembler_SetVariables( self->transBCAsm, self->columnVariable, self->rowVariable );
-	Assembler_SetCallbacks( self->transBCAsm, 
-		NULL, 
-		NULL, NULL, 
-		StiffnessMatrix_TransBCAsm_ColR, NULL, 
-		self );
-	if( self->rowVariable == self->columnVariable ) {
-		Assembler_SetVariables( self->diagBCsAsm, self->rowVariable, self->columnVariable );
-		Assembler_SetCallbacks( self->diagBCsAsm, 
-			NULL, 
-			StiffnessMatrix_DiagBCsAsm_RowR, NULL, 
-			NULL, NULL, 
-			self );
-	}
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _StiffnessMatrix_Initialise( void* stiffnessMatrix, void* data ) {
-	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
-	
-	Journal_DPrintf( self->debug, "In %s - for matrix %s\n", __func__, self->name );
-	/* ensure variables are initialised */
-	if( self->rowVariable )
-		Stg_Component_Initialise( self->rowVariable, data, False );
-	
-	if( self->columnVariable )
-		Stg_Component_Initialise( self->columnVariable, data, False );
-
-   /* ensure the rhs vector is built */
-   Stg_Component_Initialise( self->rhs, data, False );
-
-/* 	if( self->useShellMatrix ) */
-/* 		Stg_Component_Initialise( self->shellMatrix, data, False ); */
-}
-
-
-void _StiffnessMatrix_Execute( void* stiffnessMatrix, void* data ) {
-}
-
-void _StiffnessMatrix_Destroy( void* stiffnessMatrix, void* data ) {
-	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
-	
-	Journal_DPrintf( self->debug, "In %s - for matrix %s\n", __func__, self->name );
-	MatDestroy( self->matrix );
-	FreeObject( self->stiffnessMatrixTermList );
-	FreeArray( self->_assembleStiffnessMatrixEPName );
-	FreeArray( self->diagonalNonZeroIndices );
-	FreeArray( self->offDiagonalNonZeroIndices );
-	FreeObject( self->zeroBCsAsm );
-	FreeObject( self->bcAsm );
-	FreeObject( self->transBCAsm );
-	FreeObject( self->diagBCsAsm );
-	/* Don't delete entry points: E.P. register will delete them automatically */
-	NewClass_Delete( self->rowInc );
-	NewClass_Delete( self->colInc );
-
-
-}
-
-void StiffnessMatrix_CalculateNonZeroEntries( void* stiffnessMatrix ) {
-	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
-	
-	self->_calculateNonZeroEntries( self );
-}
-
-void _StiffnessMatrix_CalculateNonZeroEntries( void* stiffnessMatrix ) {
-	StiffnessMatrix*		self = (StiffnessMatrix*)stiffnessMatrix;
-	FeMesh*					rFeMesh = self->rowVariable->feMesh;
-	FeMesh*					cFeMesh = self->columnVariable->feMesh;
-	Dof_EquationNumber	currMatrixRow = 0;
-	Node_LocalIndex		rowNode_lI = 0;
-	Index						activeEqsAtCurrRowNodeCount = 0;
-#ifdef DEBUG
-	unsigned int			totalNonZeroEntries = 0;
-#endif
-
-	Journal_DPrintf( self->debug, "In %s - for matrix %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	assert ( self->rowVariable );
-	assert ( self->columnVariable );
-
-	Journal_DPrintfL( self->debug, 1, "row nodeLocalCount %d\n", FeMesh_GetNodeLocalSize( rFeMesh ) );
-	Journal_DPrintfL( self->debug, 1, "column nodeLocalCount %d\n", FeMesh_GetNodeLocalSize( cFeMesh ) );
-	
-	self->diagonalNonZeroIndices = Memory_Alloc_Array  ( Index, self->rowLocalSize, "diagonalNonZeroIndices" );
-	self->offDiagonalNonZeroIndices = Memory_Alloc_Array  ( Index, self->rowLocalSize, "offDiagonalNonZeroIndices" );
-	for ( rowNode_lI = 0; rowNode_lI < self->rowLocalSize; rowNode_lI++ ) { 
-		self->diagonalNonZeroIndices[rowNode_lI] = 0;
-		self->offDiagonalNonZeroIndices[rowNode_lI] = 0;
-	}
-
-	for( rowNode_lI = 0; rowNode_lI < FeMesh_GetNodeLocalSize( rFeMesh ); rowNode_lI++ ) { 
-		_StiffnessMatrix_CalcAndUpdateNonZeroEntriesAtRowNode( self, rowNode_lI, currMatrixRow, activeEqsAtCurrRowNodeCount );
-	}
-
-#ifdef DEBUG
-	for ( rowNode_lI = 0; rowNode_lI < self->rowLocalSize; rowNode_lI++ ) { 
-		totalNonZeroEntries += self->diagonalNonZeroIndices[rowNode_lI];
-		totalNonZeroEntries += self->offDiagonalNonZeroIndices[rowNode_lI];
-	}	
-
-	Journal_DPrintfL( self->debug, 1, "Calculated %d non-zero entries in Matrix (results in %d bytes storage)\n",
-			  totalNonZeroEntries, totalNonZeroEntries * sizeof(double) );
-#endif	
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _StiffnessMatrix_CalcAndUpdateNonZeroEntriesAtRowNode(
-	StiffnessMatrix*	self,
-	Node_LocalIndex		rowNode_lI,
-	Dof_EquationNumber	currMatrixRow,
-	Index			activeEqsAtCurrRowNode )
-{
-	FeMesh*			rFeMesh = self->rowVariable->feMesh;
-	FeMesh*			cFeMesh = self->columnVariable->feMesh;
-	DofLayout*		colDofLayout = self->columnVariable->dofLayout;
-	FeEquationNumber*	rowEqNum = self->rowVariable->eqNum;
-	FeEquationNumber*	colEqNum = self->columnVariable->eqNum;
-	Element_Index		rowNodeElement_I = 0;
-	Element_DomainIndex	element_dI = 0;
-	Node_DomainIndex	colNode_dI = 0;
-	Dof_Index		colNodeDof_I = 0;
-	Index*			countTableToAdjust = 0;
-	Dof_EquationNumber	currColEqNum = 0;
-	Node_DomainIndex*	uniqueRelatedColNodes = NULL;
-	Node_Index		uniqueRelatedColNodesCount = 0;
-	Node_Index		uniqueRelatedColNodes_AllocCount = 0;
-	Node_Index		uniqueRelatedColNode_I = 0;
-	Dof_Index		currNodeDof_I = 0;
-	Dof_EquationNumber	currDofMatrixRow = 0;
-	unsigned		nNodeInc, *nodeInc;
-
-	Journal_DPrintfL( self->debug, 3, "In %s - for row local node %d\n", __func__, rowNode_lI );
-	Stream_Indent( self->debug );
-
-	FeMesh_GetNodeElements( rFeMesh, rowNode_lI, self->rowInc );
-	nNodeInc = IArray_GetSize( self->rowInc );
-	nodeInc = (unsigned*)IArray_GetPtr( self->rowInc );
-	for ( rowNodeElement_I = 0; rowNodeElement_I < nNodeInc; rowNodeElement_I++ ) {
-		unsigned	nElInc;
-
-		/* note the dI (domain index) - some of these elements may be in shadow space */
-		element_dI = nodeInc[rowNodeElement_I];
-
-		nElInc = FeMesh_GetElementNodeSize( cFeMesh, element_dI );
-		uniqueRelatedColNodes_AllocCount += nElInc;
-	}
-	
-	Journal_DPrintfL( self->debug, 3, "Calculated the max possible number of unique related nodes as %d\n",
-			  uniqueRelatedColNodes_AllocCount );
-	uniqueRelatedColNodes = Memory_Alloc_Array( Node_DomainIndex, uniqueRelatedColNodes_AllocCount, "uniqueRelatedColNodes" );
-
-	_StiffnessMatrix_CalculatedListOfUniqueRelatedColNodes( self, rowNode_lI, uniqueRelatedColNodes, &uniqueRelatedColNodesCount);
-	
-	Journal_DPrintfL( self->debug, 3, "Searching the %d unique related col nodes for active dofs\n",
-			  uniqueRelatedColNodesCount );
-	Stream_Indent( self->debug );
-	for ( uniqueRelatedColNode_I = 0; uniqueRelatedColNode_I < uniqueRelatedColNodesCount; uniqueRelatedColNode_I++ ) {
-		colNode_dI = uniqueRelatedColNodes[uniqueRelatedColNode_I];
-
-		Journal_DPrintfL( self->debug, 3, "col node_dI %d: has %d dofs\n", colNode_dI, colDofLayout->dofCounts[colNode_dI] );
-		Stream_Indent( self->debug );
-		for ( colNodeDof_I = 0; colNodeDof_I < colDofLayout->dofCounts[colNode_dI]; colNodeDof_I++ ) {
-
-			currColEqNum = colEqNum->destinationArray[colNode_dI][colNodeDof_I];
-			Journal_DPrintfL( self->debug, 3, "dof %d: ", colNodeDof_I );
-			if ( currColEqNum == -1 ) {
-				Journal_DPrintfL( self->debug, 3, "is a BC.\n" );
-			}
-			else {
-				if( STreeMap_HasKey( colEqNum->ownedMap, &currColEqNum ) ) {
-					Journal_DPrintfL( self->debug, 3, "is diagonal (eq %d)\n", currColEqNum );
-					countTableToAdjust = self->diagonalNonZeroIndices;
-				}
-				else {
-					Journal_DPrintfL( self->debug, 3, "is off-diagonal (eq %d)\n", currColEqNum );
-					countTableToAdjust = self->offDiagonalNonZeroIndices;
-				}
-
-				for ( currNodeDof_I = 0; currNodeDof_I < self->rowVariable->dofLayout->dofCounts[rowNode_lI]; currNodeDof_I++) {
-					if ( -1 != rowEqNum->destinationArray[rowNode_lI][currNodeDof_I] ) {
-						currDofMatrixRow = *(int*)STreeMap_Map(
-							rowEqNum->ownedMap,
-							rowEqNum->destinationArray[rowNode_lI] + currNodeDof_I );
-
-						/* Because of periodic BCs, the eq num may be lower than the normal
-						 * lowest held on this processor, so we need to check this */
-						if ( currDofMatrixRow >= self->rowLocalSize ) {	
-							Journal_DPrintfL( self->debug, 3, "Found currDofMatRow(=%d) >= self->rowLocalSize(=%d) : for "
-									  "rowNode_lI=%d, currMatRow=%d, colNode_dI=%d, colNodeDof_I = %d, "
-									  "currNodeDof_I = %d\n", currDofMatrixRow,
-									  self->rowLocalSize, rowNode_lI, currMatrixRow,
-									  colNode_dI, colNodeDof_I, currNodeDof_I ); 
-						}		
-						else if ( currDofMatrixRow < 0 ) {	
-							Journal_DPrintfL( self->debug, 3, "Found currDofMatRow(=%d) < 0 : for "
-									  "rowNode_lI=%d, currMatRow=%d, colNode_dI=%d, colNodeDof_I = %d, "
-									  "currNodeDof_I = %d\n", currDofMatrixRow,
-									  rowNode_lI, currMatrixRow,
-									  colNode_dI, colNodeDof_I, currNodeDof_I ); 
-						}		
-						else {	
-							Journal_DPrintfL( self->debug, 3, "(incrementing app. count at row %d)\n",
-									  currDofMatrixRow );
-
-							countTableToAdjust[ currDofMatrixRow ] += 1;
-						}
-					}
-				}
-			}	
-		}	
-		Stream_UnIndent( self->debug );
-	}		
-	Stream_UnIndent( self->debug );
-
-	Journal_DPrintfL( self->debug, 3, "diagonal count\t%d off diagonal count\t%d\n", 
-			  self->diagonalNonZeroIndices[currMatrixRow], self->offDiagonalNonZeroIndices[currMatrixRow]);
-
-	Memory_Free( uniqueRelatedColNodes );
-
-/* 	 TODO: do we need to check that diag is set to at least 1, as the PETSc webpage on MatCreate_MPIAIJ suggests? */
-
-	Stream_UnIndent( self->debug );
-}			
-
-
-void _StiffnessMatrix_CalculatedListOfUniqueRelatedColNodes(
-	StiffnessMatrix*	self,
-	Node_LocalIndex		rowNode_lI,
-	Node_DomainIndex*	uniqueRelatedColNodes,
-	Node_Index*		uniqueRelatedColNodesCountPtr )
-{
-	FeMesh*			rFeMesh = self->rowVariable->feMesh;
-	FeMesh*			cFeMesh = self->columnVariable->feMesh;
-	Element_Index		rowNodeElement_I = 0;
-	Element_DomainIndex	element_dI = 0;
-	Node_Index		colElLocalNode_I = 0;
-	Node_DomainIndex	colNode_dI = 0;
-	Node_Index		uniqueRelatedColNode_I = 0;
-	unsigned		nNodeInc, *nodeInc;
-
-	FeMesh_GetNodeElements( rFeMesh, rowNode_lI, self->rowInc );
-	nNodeInc = IArray_GetSize( self->rowInc );
-	nodeInc = (unsigned*)IArray_GetPtr( self->rowInc );
-	Journal_DPrintfL( self->debug, 3, "Searching the %d elements this node belongs to for unique related col nodes:\n",
-			  nNodeInc );
-	
-	Stream_Indent( self->debug );
-	for ( rowNodeElement_I = 0; rowNodeElement_I < nNodeInc; rowNodeElement_I++ ) {
-		unsigned	nElInc, *elInc;
-
-		/* note the dI (domain index) - some of these elements may be in shadow space */
-		element_dI = nodeInc[rowNodeElement_I];
-
-		Journal_DPrintfL( self->debug, 3, "rowNodeElement_I: ", rowNodeElement_I );
-		Journal_DPrintfL( self->debug, 3, "domain element %d\n", element_dI );
-		
-		Stream_Indent( self->debug );
-		FeMesh_GetElementNodes( cFeMesh, element_dI, self->colInc );
-		nElInc = IArray_GetSize( self->colInc );
-		elInc = (unsigned*)IArray_GetPtr( self->colInc );
-		Journal_DPrintfL( self->debug, 3, "Searching the %d column var nodes in this el:\n", nElInc );
-		for ( colElLocalNode_I =0; colElLocalNode_I < nElInc; colElLocalNode_I++ ) {
-			colNode_dI = elInc[colElLocalNode_I];
-			
-			Journal_DPrintfL( self->debug, 3, "Col domain node %d: ", colNode_dI );
-			for ( uniqueRelatedColNode_I = 0; uniqueRelatedColNode_I < (*uniqueRelatedColNodesCountPtr); uniqueRelatedColNode_I++ )
-			{
-				if ( colNode_dI == uniqueRelatedColNodes[uniqueRelatedColNode_I] ) {
-					Journal_DPrintfL( self->debug, 3, "already in list -> skip to next.\n" );
-					break;
-				}
-			}
-			if ( uniqueRelatedColNode_I == (*uniqueRelatedColNodesCountPtr) ) {
-				Journal_DPrintfL( self->debug, 3, "is unique so far -> add to list.\n" );
-				uniqueRelatedColNodes[uniqueRelatedColNode_I] = colNode_dI;
-				(*uniqueRelatedColNodesCountPtr)++;
-			}
-		}
-		Stream_UnIndent( self->debug );
-	}
-	Stream_UnIndent( self->debug );
-}
-
-
-void StiffnessMatrix_Assemble( void* stiffnessMatrix, Bool bcRemoveQuery, void* _sle, void* _context ) {
-	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
-        int ii;
-
-	StiffnessMatrix_RefreshMatrix( self );
-
-	Journal_DPrintf( self->debug, "In %s - for matrix \"%s\" - calling the \"%s\" E.P.\n", __func__, self->name,
-			 self->assembleStiffnessMatrix->name );
-	/* Call the Entry point directly from the base class */
-	/* Note that it may be empty: this is deliberate. */
-	((FeEntryPoint_AssembleStiffnessMatrix_CallFunction*)EntryPoint_GetRun( self->assembleStiffnessMatrix ))(
-		self->assembleStiffnessMatrix,
-		self,
-		bcRemoveQuery,
-		_sle,
-		_context );
-
-        /* Run all the modify callbacks. */
-        for( ii = 0; ii < self->nModifyCBs; ii++ ) {
-           void* callback = self->modifyCBs[ii].callback;
-           void* object = self->modifyCBs[ii].object;
-           ((void(*)(void*))callback)( object );
-        }
-}
-
-
-void StiffnessMatrix_GlobalAssembly_General( void* stiffnessMatrix, Bool bcRemoveQuery, void* _sle, void* _context )
-{
-	StiffnessMatrix*        self = (StiffnessMatrix*)stiffnessMatrix;
-	SystemLinearEquations*  sle  = (SystemLinearEquations*)_sle;
-	FiniteElementContext*   context  = (FiniteElementContext*)_context;
-	
-	FeVariable*             feVars[MAX_FE_VARS]; /* Set later */
-	Index                   numFeVars = 2;
-	Index                   feVar_I;
-
-	/* Location Matrix for a single element - may be a ptr into full LM array */
-	Dof_EquationNumber**    elementLM[MAX_FE_VARS];
-	/* Number of dofs at an element: required for matrix assembly */
-	Dof_Index*              totalDofsThisElement[MAX_FE_VARS];
-	Dof_Index*              totalDofsPrevElement[MAX_FE_VARS];
-	/* The actual element stiffness matrix values, per element: filled in by this class's entry point */
-	double**                elStiffMatToAdd = NULL;
-
-	/* counts and indices used in building per-element locationMatrix and BC info */
-	Element_LocalIndex      nLocalElements;
-	Element_LocalIndex      element_lI;
-	Node_ElementLocalIndex	nodeCountThisEl;
-	/* Shortcut to node IDs at a particular element */
-	Element_Nodes           nodeIdsThisEl;
-
-	/* related to correction of BCs */
-	Bool                    makeBC_Corrections_row = False;
-	Bool                    modifiedRHS_Vec_cont = False;
-	Dof_Index*              bcLM_Id[ MAX_FE_VARS ] = { NULL, NULL };
-	double*                 bcValues[ MAX_FE_VARS ] = { NULL, NULL };
-	int                     nBC_NodalDof[ MAX_FE_VARS ] = { 0, 0 };
-	double*                 h2Add = NULL;
-	
-	/* For output printing */
-	double                  outputPercentage      = 10;	/* Controls how often to give a status update of assembly progress*/
-	int                     outputInterval;
-	double                  startTime, totalTime;
-	double                  matAddingStart;
-	double                  matAddingTime         = 0;
-	double                  elStiffMatBuildStart;
-	double                  elStiffMatBuildTime   = 0;
-	Bool			updateRHS;
-	MPI_Comm		comm;
-
-/* 	Mat			matrix		      = ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
-	Mat                     matrix = self->matrix;
-
-	/* Do some type checking */
-	assert( !sle || Stg_CheckType( sle, SystemLinearEquations ) );
-	assert( self->rhs || self->transRHS );
-
-	feVars[0] = self->rowVariable;
-	feVars[1] = self->columnVariable;
-
-	/* Get communicator. */
-	comm = Mesh_GetCommTopology( feVars[0]->feMesh, MT_VERTEX )->mpiComm;
-	
-	startTime = MPI_Wtime();
-
-	Journal_DPrintf( self->debug, "In %s - for matrix \"%s\"\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	Journal_Firewall( Stg_ObjectList_Count( self->stiffnessMatrixTermList ) != 0,
-			  Journal_Register( Error_Type, (Name)self->type ),
-			  "Error in func %s for %s '%s' - No StiffnessMatrixTerms registered.\n", 
-			  __func__, self->type, self->name );
-
-	totalDofsThisElement[ROW_VAR] = Memory_Alloc( Dof_Index, "el nodal dofs" );
-	totalDofsPrevElement[ROW_VAR] = Memory_Alloc( Dof_Index, "el nodal dofs (prev element)" );
-	*totalDofsPrevElement[ROW_VAR] = 0;
-	/* check if row variable and col variable are the same */
-	if ( self->rowVariable == self->columnVariable ) {
-		numFeVars = 1;
-		Journal_DPrintfL( self->debug, 2, "Detected both row and column FeVariable to assemble over are \"%s\", "
-				  "so only processing once per element.\n", self->rowVariable->name );
-		/* since Row and Col FeVars are same, set LM_col and totalDofsThisElement to be same as row ones */
-		totalDofsThisElement[COL_VAR] = totalDofsThisElement[ROW_VAR];	
-		totalDofsPrevElement[COL_VAR] = totalDofsPrevElement[ROW_VAR];	
-	}
-	else {
-		Journal_DPrintfL( self->debug, 2, "Since row FeVariable \"%s\" and column FeVariable \"%s\" to assemble over "
-				  "are different, processing both per element.\n", self->rowVariable->name, self->columnVariable->name );
-		totalDofsThisElement[COL_VAR] = Memory_Alloc( Dof_Index, "el nodal dofs (col)" );
-		totalDofsPrevElement[COL_VAR] = Memory_Alloc( Dof_Index, "el nodal dofs (col) (prev element)" );
-		*totalDofsPrevElement[COL_VAR] = 0;
-	}
-	
-	/* Assumes that both row and col variables have same number of variables */
-	nLocalElements = FeMesh_GetElementLocalSize( feVars[ROW_VAR]->feMesh );
-	
-	/* Initialise matrix */
-	MatZeroEntries( matrix );
-
-	outputInterval = (int)( (outputPercentage/100.0)*(double)(nLocalElements) );
-	if( outputInterval == 0 ) { outputInterval = nLocalElements; }
-
-	for( element_lI = 0; element_lI < nLocalElements; element_lI++ ) {  
-		
-		/* This loop is how we handle the possiblity of different row-column variables: if both variables are
-		 * the same, then numFeVars is set to 1 and the loop only progresses through once.
-		 -- PatrickSunter 13 September 2004 */
-		for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
-			FeEquationNumber* 		feEqNum = feVars[feVar_I]->eqNum;
-			DofLayout*			dofLayout = feVars[feVar_I]->dofLayout;
-			Dof_Index			dofCountLastNode;
-			unsigned			nDofsThisEl;
-			unsigned			n_i;
-
-			/* Get the local node ids */
-			FeMesh_GetElementNodes( feVars[feVar_I]->feMesh, element_lI, 
-						self->rowInc );
-			nodeCountThisEl = IArray_GetSize( self->rowInc );
-			nodeIdsThisEl = (unsigned*)IArray_GetPtr( self->rowInc );
-
-			/* Set value of elementLM: will automatically use large one if built */
-			elementLM[feVar_I] = FeEquationNumber_BuildOneElementLocationMatrix( feEqNum, element_lI );
-
-			/* work out number of dofs at the node, based on LM */
-			dofCountLastNode = dofLayout->dofCounts[nodeIdsThisEl[nodeCountThisEl-1]];
-			nDofsThisEl = dofLayout->dofCounts[nodeIdsThisEl[0]];
-			for( n_i = 1; n_i < nodeCountThisEl; n_i++ )
-				nDofsThisEl += dofLayout->dofCounts[nodeIdsThisEl[n_i]];
-			*totalDofsThisElement[feVar_I] = nDofsThisEl;
-/*
- *totalDofsThisElement[feVar_I] = &elementLM[feVar_I][nodeCountThisEl-1][dofCountLastNode-1]
- - &elementLM[feVar_I][0][0] + 1;
-*/
-
-			if ( *totalDofsThisElement[feVar_I] > *totalDofsPrevElement[feVar_I] ) {
-				Journal_DPrintfL( self->debug, 2, "Reallocating bcLM_Id and bcValues for fe var \"%s\" "
-						  "to size %d\n", feVars[feVar_I]->name, *totalDofsThisElement[feVar_I] );
-
-				if ( bcLM_Id[feVar_I] ) Memory_Free( bcLM_Id[feVar_I] );
-				bcLM_Id[feVar_I] = Memory_Alloc_Array( Dof_Index, *totalDofsThisElement[feVar_I], "bcLM_Id" );
-
-				if ( bcValues[feVar_I] ) Memory_Free( bcValues[feVar_I] );
-				bcValues[feVar_I] = Memory_Alloc_Array( double, *totalDofsThisElement[feVar_I], "bcValues" );
-			}
-		}
-
-		/* Reallocate el stiff mat and other arrays if necessary */
-		if ( (*totalDofsThisElement[ROW_VAR] != *totalDofsPrevElement[ROW_VAR]) ||
-		     (*totalDofsThisElement[COL_VAR] != *totalDofsPrevElement[COL_VAR]) )
-		{
-			if (h2Add) Memory_Free( h2Add );
-			Journal_DPrintfL( self->debug, 2, "Reallocating h2Add to size %d\n",
-					  *totalDofsThisElement[COL_VAR] ); 
-			h2Add = Memory_Alloc_Array( double, *totalDofsThisElement[COL_VAR], "h2Add" );
-			
-			if (elStiffMatToAdd) Memory_Free( elStiffMatToAdd );
-			Journal_DPrintfL( self->debug, 2, "Reallocating elStiffMatToAdd to size %d*%d\n",
-					  *totalDofsThisElement[ROW_VAR], *totalDofsThisElement[COL_VAR] ); 
-			elStiffMatToAdd = Memory_Alloc_2DArray( double, *totalDofsThisElement[ROW_VAR], *totalDofsThisElement[COL_VAR], (Name)"elStiffMatToAdd"  );
-		}
-
-		/* Initialise the elStiffMat to zero */
-		/* Note we have to dereference the ptr once ... so we don't clobber the ptrs, just the values */
-		memset( elStiffMatToAdd[0], 0, sizeof(double) * *totalDofsThisElement[ROW_VAR] * *totalDofsThisElement[COL_VAR] );
-
-		/* Assemble this element's element stiffness matrix: call the entry point */
-		elStiffMatBuildStart = MPI_Wtime();
-		StiffnessMatrix_AssembleElement( self, element_lI, sle, context, elStiffMatToAdd );
-		elStiffMatBuildTime += MPI_Wtime() - elStiffMatBuildStart;
-		if ( False == self->allowZeroElementContributions ) {
-			StiffnessMatrix_CheckElementAssembly( self, element_lI, elStiffMatToAdd, *totalDofsThisElement[ROW_VAR],
-							      *totalDofsThisElement[COL_VAR] );
-		}	
-
-		/* This loop is how we handle the possiblity of different row-column variables: if both variables are
-		 * the same, then numFeVars is set to 1 and the loop only progresses through once.
-		 -- PatrickSunter 13 September 2004 */
-		for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
-			/* Reset from previous calculation */
-			nBC_NodalDof[feVar_I] = 0;
-			makeBC_Corrections_row = False;
-
-			/* Check if we want to build table of corrected BC info for the matrix */
-			if( bcRemoveQuery == True ) {
-				unsigned	nNodeInc, *nodeInc;
-
-				FeMesh_GetElementNodes( feVars[feVar_I]->feMesh, element_lI, 
-							self->rowInc );
-				nNodeInc = IArray_GetSize( self->rowInc );
-				nodeInc = (unsigned*)IArray_GetPtr( self->rowInc );
-				_StiffnessMatrix_UpdateBC_CorrectionTables(
-					self,
-					feVars[feVar_I]->eqNum, 
-					feVars[feVar_I]->dofLayout,
-					elementLM[feVar_I],
-					nNodeInc, 
-					nodeInc, 
-					bcLM_Id[feVar_I],
-					bcValues[feVar_I],
-					&(nBC_NodalDof[feVar_I]) );
-			}
-		}
-
-		/* If there is only one feVar, use the same LM for both row and col insertion */
-		if ( numFeVars == 1 ) elementLM[COL_VAR] = elementLM[ROW_VAR];
-
-/*
-  #if DEBUG
-  if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
-  Journal_DPrintf( self->debug, "Handling Element %d:\n", element_lI );
-  for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
-  FeEquationNumber_PrintElementLocationMatrix( feVars[feVar_I]->eqNum,
-  elementLM[feVar_I], element_lI, self->debug );
-				
-  }
-			
-  Journal_DPrintf( self->debug, "El stiff Mat about to be added:\n" );
-  _StiffnessMatrix_PrintElementStiffnessMatrix( self, element_lI, elementLM[ROW_VAR],
-  elementLM[COL_VAR], elStiffMatToAdd );
-  }	
-  #endif
-*/
-
-
-		/*
-		** Need to make corrections to the RHS before filling in the matrix.  This is because we may modify the
-		** element matrix values before they get there.
-		*/
-
-		/* Set flag for making corrcetions to rhs from bc's */
-		if( nBC_NodalDof[ROW_VAR] != 0 ) {
-			makeBC_Corrections_row = True;
-			modifiedRHS_Vec_cont = True;	/* this guy only needs to be toggled once */
-		}
-		
-		if( makeBC_Corrections_row == True && bcRemoveQuery ) {
-			_StiffnessMatrix_CorrectForceVectorWithOneElementsBoundaryConditions(
-				self,
-				elementLM,
-				h2Add,
-				elStiffMatToAdd,
-				totalDofsThisElement,
-				bcLM_Id,
-				bcValues,
-				nBC_NodalDof[ROW_VAR], 
-				element_lI );
-		}
-
-		/*
-		** If not keeping BCs in, we may need to zero some of these element values, or set them to one.
-		*/
-
-		if( (!self->rowVariable || !self->rowVariable->eqNum->removeBCs) && 
-		    (!self->columnVariable || !self->columnVariable->eqNum->removeBCs) )
-		{
-			FeEquationNumber*	rowEqNum = self->rowVariable->eqNum;
-			FeEquationNumber*	colEqNum = self->columnVariable->eqNum;
-			unsigned		nRows = *totalDofsThisElement[ROW_VAR];
-			unsigned		row_i;
-
-			/* Loop over elementLM rows */
-			for( row_i = 0; row_i < nRows; row_i++ ) {
-				unsigned	rowEqInd;
-
-				rowEqInd = *(int*)STreeMap_Map( rowEqNum->ownedMap,
-								elementLM[ROW_VAR][0] + row_i );
-
-				/* If row is bc */
-				if( STree_Has( rowEqNum->bcEqNums, &rowEqInd ) ) {
-					unsigned	nCols = *totalDofsThisElement[COL_VAR];
-					unsigned	col_i;
-
-					/* Loop over elementLM cols */
-					for( col_i = 0; col_i < nCols; col_i++ ) {
-						unsigned	colEqInd;
-
-						colEqInd = *(int*)STreeMap_Map( colEqNum->ownedMap,
-										elementLM[COL_VAR][0] + col_i );
-
-						/* If col is bc */
-						if( STree_Has( colEqNum->bcEqNums, &colEqInd ) ) {
-							elStiffMatToAdd[0][row_i * nCols + col_i] = 0.0;
-						}
-						else {
-							elStiffMatToAdd[0][row_i * nCols + col_i] = 0.0;
-						}
-					}
-				}
-				else {
-					unsigned	nCols = *totalDofsThisElement[COL_VAR];
-					unsigned	col_i;
-
-					for( col_i = 0; col_i < nCols; col_i++ ) {
-						unsigned	colEqInd = elementLM[COL_VAR][0][col_i];
-
-						/* If col is bc */
-						if( STree_Has( colEqNum->bcEqNums, &colEqInd ) ) {
-							elStiffMatToAdd[0][row_i * nCols + col_i] = 0.0;
-						}
-					}
-				}
-			}
-		}
-
-		/* Add to the global matrix. */
-		matAddingStart = MPI_Wtime();
-		MatSetValues( matrix, *totalDofsThisElement[ROW_VAR], elementLM[ROW_VAR][0], *totalDofsThisElement[COL_VAR], 
-				elementLM[COL_VAR][0], elStiffMatToAdd[0], ADD_VALUES );
-		matAddingTime += MPI_Wtime() - matAddingStart;	
-		
-		
-#if DEBUG
-		if( element_lI % outputInterval == 0 ) {
-			Journal_DPrintfL( self->debug, 2, "done %d percent of global element stiffness assembly (general) \n",
-					  (int)(100.0*((double)element_lI/(double)nLocalElements)) );
-		}
-#endif
-
-		for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
-			/* Save the number of dofs in this element */
-			*totalDofsPrevElement[feVar_I] = *totalDofsThisElement[feVar_I];
-			/* If we haven't built the big LM for all elements, free the temporary one */
-			if ( False == feVars[feVar_I]->eqNum->locationMatrixBuilt ) {
-				Memory_Free( elementLM[feVar_I] );
-			}	
-		}	
-	}
-
-/* 	//////////////////////////////////////////////////////// */
-	MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
-	MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
-	
-	MPI_Allreduce( &modifiedRHS_Vec_cont, &updateRHS, 1, MPI_UNSIGNED, MPI_LOR, comm );
-	if( updateRHS == True && bcRemoveQuery ) {
-		/* stuff was submitted to vec (at least once) and needs to be assembled */
-		VecAssemblyBegin( self->rhs->vector );
-		VecAssemblyEnd( self->rhs->vector );
-	}
-/* 	//////////////////////////////////////////////////////// */
-
-	/*
-	** If keeping BCs in, modify the RHS to reflect BCs.
-	*/
-
-	if( (!self->rowVariable || !self->rowVariable->eqNum->removeBCs) && 
-	    (!self->columnVariable || !self->columnVariable->eqNum->removeBCs) )
-	{
-		FeEquationNumber*	colEqNum = self->columnVariable->eqNum;
-		FeMesh*			feMesh = self->columnVariable->feMesh;
-		DofLayout*		dofLayout = self->columnVariable->dofLayout;
-		unsigned		nNodes = FeMesh_GetNodeLocalSize( feMesh );
-		unsigned		node_i;
-
-		/* What to do if they aren't the same? */
-		assert( self->rowVariable == self->columnVariable );
-
-		for( node_i = 0; node_i < nNodes; node_i++ ) {
-			unsigned	nDofs = dofLayout->dofCounts[node_i];
-			unsigned	dof_i;
-
-			for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
-				unsigned	eqInd = colEqNum->destinationArray[node_i][dof_i];
-				int localEq;
-
-				localEq = *(int*)STreeMap_Map( colEqNum->ownedMap, &eqInd );
-				if( STree_Has( colEqNum->bcEqNums, &localEq ) ) {
-					double	bcVal = DofLayout_GetValueDouble( dofLayout, node_i, dof_i );
-					double	one = 1.0;
-
-					VecSetValues( self->rhs->vector, 1, (PetscInt*)(&eqInd), &bcVal, INSERT_VALUES );
-					MatSetValues( matrix, 1, (PetscInt*)(&eqInd), 1, (PetscInt*)(&eqInd), &one, INSERT_VALUES );
-				}
-			}
-		}
-
-		/* Need to reassemble. */
-		MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
-		MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
-		VecAssemblyBegin( self->rhs->vector );
-		VecAssemblyEnd( self->rhs->vector );
-	}
-
-	for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
-		Memory_Free( totalDofsThisElement[feVar_I] );
-		Memory_Free( totalDofsPrevElement[feVar_I] );
-		Memory_Free( bcLM_Id[feVar_I] );
-		Memory_Free( bcValues[feVar_I] );
-	}
-	Memory_Free( elStiffMatToAdd );
-	Memory_Free( h2Add );
-
-	totalTime = MPI_Wtime() - startTime;
-	Journal_DPrintfL( self->debug, 2, "Total time used by %s: %.5g s\n", __func__, totalTime );
-	Journal_DPrintfL( self->debug, 2, "Of which %.5g s spend building elStiffMats\n", elStiffMatBuildTime );
-	Journal_DPrintfL( self->debug, 2, "And %.5g s spend adding to global matrix\n", matAddingTime );
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-
-void _make_dirichlet_corrections_to_rhs(
-        int nr, int rows_to_keep[],
-        int nc, int cols_to_keep[],
-        double **ke, int n_cols, double bc_vals[],
-        double rhs[] )
-{
-        int i,j,I,J;
-
-        for( i=0; i<nr; i++ ) {
-                I = rows_to_keep[i];
-                rhs[I] = 0.0;
-
-                for( j=0; j<nc; j++ ) {
-                        J = cols_to_keep[j];
-                        rhs[I] = rhs[I] - ke[I][J] * bc_vals[J];
-                }
-        }
-
-}
-
-void _make_dirichlet_corrections_to_rhs_transpose(
-        int nr, int rows_to_keep[],
-        int nc, int cols_to_keep[],
-        double **ke, int n_cols, 
-	double bc_vals[], double rhs[] )
-{
-        int i,j,I,J;
-
-        for( i=0; i<nr; i++ ) {
-                I = rows_to_keep[i];
-                rhs[I] = 0.0;
-
-                for( j=0; j<nc; j++ ) {
-                        J = cols_to_keep[j];
-
-                        rhs[I] = rhs[I] - ke[J][I] * bc_vals[J];
-                }
-        }
-
-}
-
-#define LEOrder( i,i_d,i_dof ) ( (i)*(i_dof) + (i_d) )
-void _get_bc_values( FeVariable *colVar, int npe, int ndof, int el_nodes[], double bc_vals[] )
-{
-        double bc;
-        int n, d, n_i;
-
-        for( n=0; n<npe; n++ ) {
-		n_i = el_nodes[n];
-                for( d=0; d<ndof; d++ ) {
-			/* query node index to see if it is has a dirichlet boundary condition */
-			if( FeVariable_IsBC( colVar, n_i, d) == True ) {       
-                		bc = DofLayout_GetValueDouble( colVar->dofLayout, n_i,  d );
-				bc_vals[ LEOrder(n,d,ndof) ] = bc;
-			}
-			/* end bc query */
-                }
-        }
-}
-
-struct StiffMatAss_Log {
-	char *ass_type; /* one of { OPERATOR_ONLY, OPERATOR_WITH_BC_CORRECTIONS, OPERATOR_WITH_BC_CORRECTIONS_FROM_OP_TRANS, OP_BC_CORRECTIONS_ONLY, OP_BC_CORRECTIONS_FROM_OP_TRANS_ONLY } */
-	double total_TIME;
-	double cumulative_el_stiff_mat_ass_TIME;
-	double parallel_assembly_TIME;
-	double element_insertion_TIME;
-	int nr, nc;
-	int local_nr, local_nc;
-	int elements_assembled_for_bc_correction;
-	int elements_assembled;
-	
-	/* local timer info */
-	double dt_element_assembly, dt_total, dt_parallel_assembly, dt_el_insert;
-	double t0_element_assembly, t0_total, t0_parallel_assembly, t0_el_insert;
-};
-
-#define StiffMatAssLog_UpdateElementsAssembled( log ) (log)->elements_assembled++
-#define StiffMatAssLog_UpdateElementsAssembledForBC_Corrections( log ) (log)->elements_assembled_for_bc_correction++
-#define StiffMatAssLog_InitTimer_TotalTime( log ) (log)->t0_total = MPI_Wtime()
-#define StiffMatAssLog_InitTimer_ElementAssembly( log ) (log)->t0_element_assembly = MPI_Wtime()
-#define StiffMatAssLog_InitTimer_ParallelAssembly( log ) (log)->t0_parallel_assembly = MPI_Wtime()
-#define StiffMatAssLog_InitTimer_ElementInsertion( log ) (log)->t0_el_insert = MPI_Wtime()
-
-inline void StiffMatAssLog_AccumulateTime_Total( struct StiffMatAss_Log *log )
-{
-	log->dt_total = MPI_Wtime() - log->t0_total;	
-	log->total_TIME = log->total_TIME + log->dt_total;
-}
-
-inline void StiffMatAssLog_AccumulateTime_ElementAssembly( struct StiffMatAss_Log* log )
-{
-	log->dt_element_assembly = MPI_Wtime() - log->t0_element_assembly;	
-	log->cumulative_el_stiff_mat_ass_TIME = log->cumulative_el_stiff_mat_ass_TIME + log->dt_element_assembly;
-}
-
-
-inline void StiffMatAssLog_AccumulateTime_ParallelAssembly( struct StiffMatAss_Log *log )
-{
-	log->dt_parallel_assembly = MPI_Wtime() - log->t0_parallel_assembly;
-	log->parallel_assembly_TIME = log->parallel_assembly_TIME + log->dt_parallel_assembly;
-}
-
-inline void StiffMatAssLog_AccumulateTime_ElementInsertion( struct StiffMatAss_Log *log )
-{
-	log->dt_el_insert = MPI_Wtime() - log->t0_el_insert;
-	log->element_insertion_TIME = log->element_insertion_TIME + log->dt_el_insert;
-}
-
-inline void StiffMatAssLog_GetOperatorDimensions( struct StiffMatAss_Log *log, Mat matrix )
-{
-  MatGetSize( matrix, (PetscInt*)(&log->nr), (PetscInt*)(&log->nc) );
-  MatGetLocalSize( matrix, (PetscInt*)(&log->local_nr), (PetscInt*)(&log->local_nc) );
-}
-
-void StiffMatAssLog_Delete( struct StiffMatAss_Log** _log )
-{
-	struct StiffMatAss_Log *log = *_log;
-
-	if( log->ass_type != NULL ) free( log->ass_type );
-	free( log );
-	log = NULL;
-
-	*_log = log;
-}
-
-void StiffMatAssLog_Init( struct StiffMatAss_Log *log, const char type_name[] )
-{
-	if( log->ass_type != NULL ) free( log->ass_type );
-	asprintf( &log->ass_type, "%s", type_name );
-	
-	/* reset timers and counter */
-	log->total_TIME                           = 0.0;
-	log->cumulative_el_stiff_mat_ass_TIME     = 0.0;
-	log->parallel_assembly_TIME               = 0.0;
-	log->element_insertion_TIME               = 0.0;
-	log->nr           = log->nc               = 0;
-	log->local_nr     = log->local_nc         = 0;
-	log->elements_assembled_for_bc_correction = 0;
-	log->elements_assembled                   = 0;
-}
-
-struct StiffMatAss_Log* StiffMatAssLog_New( void )
-{
-        struct StiffMatAss_Log *log;
-
-        log = (struct StiffMatAss_Log*)malloc( sizeof(struct StiffMatAss_Log) );
-        log->ass_type = NULL;
-
-	StiffMatAssLog_Init( log, "UNINITIALISED" );
-
-        return log;
-}
-
-
-void StiffMatAssLog_Report_min_max( MPI_Comm comm, double local_val, double *min, double *max )
-{
-	MPI_Reduce ( &local_val, min, 1, MPI_DOUBLE, MPI_MIN, 0, comm );
-	MPI_Reduce ( &local_val, max, 1, MPI_DOUBLE, MPI_MAX, 0, comm );
-}
-
-void StiffMatAssLog_Report_sequential( StiffnessMatrix *self, struct StiffMatAss_Log *log )
-{
-	Journal_PrintfL( self->debug, 1, "GlobalStiffnessMatrix Assembly Report: %s \n", self->name );
-	Journal_PrintfL( self->debug, 1, "  Assembly type:            %s \n", log->ass_type );
-	Journal_PrintfL( self->debug, 1, "  Operator dimensions:      %d x %d (global) \n", log->nr, log->nc );
-	Journal_PrintfL( self->debug, 1, "  Total time:                                  %6.6e (sec)\n", log->total_TIME );
-	Journal_PrintfL( self->debug, 1, "  Assembling element stiffness matrices:       %6.6e (sec)\n", log->cumulative_el_stiff_mat_ass_TIME );
-	Journal_PrintfL( self->debug, 1, "  Parallel assembly:                           %6.6e (sec)\n", log->parallel_assembly_TIME ); 
-	Journal_PrintfL( self->debug, 1, "  Element insertion:                           %6.6e (sec)\n", log->element_insertion_TIME );
-	Journal_PrintfL( self->debug, 1, "  Element stiffness matrices assembled for operator:        %d \n", log->elements_assembled );
-	Journal_PrintfL( self->debug, 1, "  Element stiffness matrices assembled for bc corrections:  %d \n", log->elements_assembled_for_bc_correction );
-}	
-
-void StiffMatAssLog_Report_parallel( StiffnessMatrix *self, struct StiffMatAss_Log *log )
-{
-	double min, max;
-	int sum_i;
-	MPI_Comm comm = self->comm;
-	int init_stream_rank;
-
-	/* change stream to only print on rank 0 */
-        init_stream_rank = Stream_GetPrintingRank( self->debug );
-        Stream_SetPrintingRank( self->debug, 0 );
-
-        Journal_PrintfL( self->debug, 1, "GlobalStiffnessMatrix Assembly Report: %s \n", self->name );
-        Journal_PrintfL( self->debug, 1, "  Assembly type:                          %s \n", log->ass_type );
-        Journal_PrintfL( self->debug, 1, "  Operator dimensions:                                      %d x %d (global) \n", log->nr, log->nc );
-
-	MPI_Reduce ( &log->elements_assembled, &sum_i, 1, MPI_INT, MPI_SUM, 0, comm );
-        Journal_PrintfL( self->debug, 1, "  Element stiffness matrices assembled for operator:        %d (total) \n", sum_i );
-	
-	MPI_Reduce ( &log->elements_assembled_for_bc_correction, &sum_i, 1, MPI_INT, MPI_SUM, 0, comm );
-        Journal_PrintfL( self->debug, 1, "  Element stiffness matrices assembled for bc corrections:  %d (total) \n", sum_i );
-
-	Journal_PrintfL( self->debug, 1, "                                               min     /      max      (sec)\n" );	
-
-	StiffMatAssLog_Report_min_max( comm, log->total_TIME, &min, &max );
-        Journal_PrintfL( self->debug, 1, "  Total time:                             %6.6e / %6.6e  (sec)\n", min, max );
-
-	StiffMatAssLog_Report_min_max( comm, log->cumulative_el_stiff_mat_ass_TIME, &min, &max );
-        Journal_PrintfL( self->debug, 1, "  Assembling element stiffness matrices:  %6.6e / %6.6e  (sec)\n", min, max );
-
-	StiffMatAssLog_Report_min_max( comm, log->parallel_assembly_TIME, &min, &max );
-        Journal_PrintfL( self->debug, 1, "  Parallel assembly:                      %6.6e / %6.6e  (sec)\n", min, max );
-
-	StiffMatAssLog_Report_min_max( comm, log->element_insertion_TIME, &min, &max );
-	Journal_PrintfL( self->debug, 1, "  Element insertion:                      %6.6e / %6.6e  (sec)\n", min, max );
-
-
-	/* reset printing rank of stream */
-	Stream_SetPrintingRank( self->debug, init_stream_rank );
-}
-
-void StiffMatAssLog_Report( StiffnessMatrix *self, struct StiffMatAss_Log *log )
-{
-	int size;
-
-	MPI_Comm_size( self->comm, &size );
-	if( size == 1 ) {
-		StiffMatAssLog_Report_sequential( self, log );
-	}
-	else {
-		StiffMatAssLog_Report_parallel( self, log );
-	}
-}
-
-
-void _StiffMatAss( struct StiffMatAss_Log *log, void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context ) {
-
-        StiffnessMatrix*                self = (StiffnessMatrix*)stiffnessMatrix;
-        SystemLinearEquations*          sle = (SystemLinearEquations*)_sle;
-        FeVariable                      *rowVar, *colVar;
-        FeMesh                          *rowMesh, *colMesh;
-        FeEquationNumber                *rowEqNum, *colEqNum;
-        DofLayout                       *rowDofs, *colDofs;
-        unsigned                        nRowEls;
-        unsigned                        nRowNodes, *rowNodes;
-        unsigned                        nColNodes, *colNodes;
-        unsigned                        maxDofs, maxRCDofs, nDofs, nRowDofs, nColDofs;
-        double**                        elStiffMat;
-/*         Mat                             matrix		= ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
-	Mat                             matrix = self->matrix;
-        unsigned                        e_i, n_i;
-
-        int c_dof, r_dof;
-
-        assert( self && Stg_CheckType( self, StiffnessMatrix ) );
-
-	StiffMatAssLog_Init( log, "OPERATOR_ONLY" );
-	StiffMatAssLog_InitTimer_TotalTime( log );
-
-        rowVar = self->rowVariable;
-        colVar = self->columnVariable ? self->columnVariable : rowVar;
-        rowEqNum = rowVar->eqNum;
-        colEqNum = colVar->eqNum;
-        rowMesh = rowVar->feMesh;
-        colMesh = colVar->feMesh;
-        rowDofs = rowVar->dofLayout;
-        colDofs = colVar->dofLayout;
-        nRowEls = FeMesh_GetElementLocalSize( rowMesh );
-        assert( (rowVar == colVar) ? !self->transRHS : 1 );
-
-        //matrix = self->matrix;
-        elStiffMat = NULL;
-        maxDofs = 0;
-
-
-
-	StiffMatAssLog_GetOperatorDimensions( log, matrix );
-       /* Begin assembling each element. */
-        for( e_i = 0; e_i < nRowEls; e_i++ ) {
-                FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc );
-                nRowNodes = IArray_GetSize( self->rowInc );
-                rowNodes = (unsigned*)IArray_GetPtr( self->rowInc );
-                FeMesh_GetElementNodes( colMesh, e_i, self->colInc );
-                nColNodes = IArray_GetSize( self->colInc );
-                colNodes = (unsigned*)IArray_GetPtr( self->colInc );
-
-                /* Do we need more space to assemble this element? */
-                nRowDofs = 0;
-                for( n_i = 0; n_i < nRowNodes; n_i++ ) {
-                        nRowDofs += rowDofs->dofCounts[rowNodes[n_i]];
-                        r_dof = rowDofs->dofCounts[rowNodes[n_i]];
-                }
-                nColDofs = 0;
-                for( n_i = 0; n_i < nColNodes; n_i++ ) {
-                        nColDofs += colDofs->dofCounts[colNodes[n_i]];
-                        c_dof = colDofs->dofCounts[colNodes[n_i]];
-                }
-                nDofs = nRowDofs * nColDofs;
-                self->nRowDofs = nRowDofs;
-                self->nColDofs = nColDofs;
-                if( nDofs > maxDofs ) {
-                        maxRCDofs = (nRowDofs > nColDofs) ? nRowDofs : nColDofs;
-                        elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs );
-
-                        maxDofs = nDofs;
-                        self->elStiffMat = elStiffMat;
-                }
-
-                       
-                /* Assemble the element. */
-                memset( elStiffMat[0], 0, nDofs * sizeof(double) );
-                StiffMatAssLog_InitTimer_ElementAssembly( log );
-		StiffnessMatrix_AssembleElement( self, e_i, sle, (FiniteElementContext*)_context, elStiffMat );
-		StiffMatAssLog_AccumulateTime_ElementAssembly( log );
-
-
-               /* If keeping BCs in, zero corresponding entries in the element stiffness matrix. */
-                if( !rowEqNum->removeBCs || !colEqNum->removeBCs )
-                        Assembler_LoopMatrixElement( self->zeroBCsAsm, e_i );
-
-                /* Add to stiffness matrix. */
-		StiffMatAssLog_InitTimer_ElementInsertion( log );
-                MatSetValues( matrix,
-                              nRowDofs, (PetscInt*)rowEqNum->locationMatrix[e_i][0],
-                              nColDofs, (PetscInt*)colEqNum->locationMatrix[e_i][0],
-                              elStiffMat[0], INSERT_VALUES );
-
-		StiffMatAssLog_AccumulateTime_ElementInsertion( log ); /* update time */
-		StiffMatAssLog_UpdateElementsAssembled( log ); /* update counter */
-        }
-
-        
-        /* If keeping BCs in and rows and columnns use the same variable, put ones in all BC'd diagonals. */
-        if( !colEqNum->removeBCs && rowVar == colVar )
-                Assembler_LoopMatrixDiagonal( self->diagBCsAsm );
-
-        /* Start matrix assembly */
-	StiffMatAssLog_InitTimer_ParallelAssembly( log );
-	MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
-	MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
-	StiffMatAssLog_AccumulateTime_ParallelAssembly( log );
-
-        FreeArray( elStiffMat );
-
-	StiffMatAssLog_AccumulateTime_Total( log );
-
-}
-
-void _StiffMatAss_vector_corrections(  struct StiffMatAss_Log *log, void *stiffnessMatrix, Bool removeBCs, void *_sle, void *_context ) {
-        StiffnessMatrix*                self = (StiffnessMatrix*)stiffnessMatrix;
-        SystemLinearEquations*          sle = (SystemLinearEquations*)_sle;
-        FeVariable                      *rowVar, *colVar;
-        FeMesh                          *rowMesh, *colMesh;
-        FeEquationNumber                *rowEqNum, *colEqNum;
-        DofLayout                       *rowDofs, *colDofs;
-        unsigned                        nRowEls;
-        unsigned                        nRowNodes, *rowNodes;
-        unsigned                        nColNodes, *colNodes;
-        unsigned                        maxDofs, maxRCDofs, nDofs, nRowDofs, nColDofs;
-        double**                        elStiffMat;
-        double*                         bcVals;
-/* 	Mat				matrix		= ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
-	Mat                             matrix = self->matrix;
-	Vec				vector, transVector;
-        unsigned                        e_i, n_i;
-
-        unsigned bc_cnt = 0;
-        int *row_index_to_keep, *col_index_to_keep;
-        int n_rows, n_cols;
-        int same_variables;
-        int c_dof, r_dof;
-        double *rhs;
-	int has_col_bc, has_row_bc;
-	int eq_num;
-
-        assert( self && Stg_CheckType( self, StiffnessMatrix ) );
-
-	StiffMatAssLog_Init( log, "OPERATOR_WITH_BC_CORRECTIONS" );
-	StiffMatAssLog_InitTimer_TotalTime( log );
-
-        rowVar = self->rowVariable;
-        colVar = self->columnVariable ? self->columnVariable : rowVar;
-        rowEqNum = rowVar->eqNum;
-        colEqNum = colVar->eqNum;
-        rowMesh = rowVar->feMesh;
-        colMesh = colVar->feMesh;
-        rowDofs = rowVar->dofLayout;
-        colDofs = colVar->dofLayout;
-        nRowEls = FeMesh_GetElementLocalSize( rowMesh );
-        assert( (rowVar == colVar) ? !self->transRHS : 1 );
-
-        //matrix = self->matrix;
-        vector = self->rhs ? self->rhs->vector : NULL;
-        transVector = self->transRHS ? self->transRHS->vector : NULL;
-        elStiffMat = NULL;
-        bcVals = NULL;
-        maxDofs = 0;
-
-	col_index_to_keep = NULL;
-	row_index_to_keep = NULL;
-	rhs = NULL;
-
-        same_variables = 0;
-        if( rowMesh == colMesh ) {
-                same_variables = 1;
-//                printf("Detected same variables in assembly VECTOR_CORRECTIONS\n");
-        }
-
-	assert( vector ); /* If we are in here then vector must be valid */
-
-
-	bc_cnt = 0;
-
-	StiffMatAssLog_GetOperatorDimensions( log, matrix );
-       /* Begin assembling each element. */
-        for( e_i = 0; e_i < nRowEls; e_i++ ) {
-                FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc );
-                nRowNodes = IArray_GetSize( self->rowInc );
-                rowNodes = (unsigned*)IArray_GetPtr( self->rowInc );
-                FeMesh_GetElementNodes( colMesh, e_i, self->colInc );
-                nColNodes = IArray_GetSize( self->colInc );
-                colNodes = (unsigned*)IArray_GetPtr( self->colInc );
-
-                /* Do we need more space to assemble this element? */
-                nRowDofs = 0;
-                for( n_i = 0; n_i < nRowNodes; n_i++ ) {
-                        nRowDofs += rowDofs->dofCounts[rowNodes[n_i]];
-                        r_dof = rowDofs->dofCounts[rowNodes[n_i]];
-                }
-                nColDofs = 0;
-                for( n_i = 0; n_i < nColNodes; n_i++ ) {
-                        nColDofs += colDofs->dofCounts[colNodes[n_i]];
-                        c_dof = colDofs->dofCounts[colNodes[n_i]];
-                }
-                nDofs = nRowDofs * nColDofs;
-                self->nRowDofs = nRowDofs;
-                self->nColDofs = nColDofs;
-                if( nDofs > maxDofs ) {
-                        maxRCDofs = (nRowDofs > nColDofs) ? nRowDofs : nColDofs;
-                        elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs );
-                        bcVals = ReallocArray( bcVals, double, maxRCDofs );
-                        rhs = ReallocArray( rhs, double, maxRCDofs );
-
-                        col_index_to_keep  = ReallocArray( col_index_to_keep, int, maxRCDofs );
-                        row_index_to_keep  = ReallocArray( row_index_to_keep, int, maxRCDofs );
-
-                        maxDofs = nDofs;
-                        self->elStiffMat = elStiffMat;
-                        self->bcVals = bcVals;
-                }
-
-                /* check for presence of bc's */
-                n_rows = n_cols = 0;
-                has_row_bc = has_col_bc = 0;
-
-                       
-		for( n_i=0; n_i<nColDofs; n_i++ ) {
-			eq_num = colEqNum->locationMatrix[e_i][0][n_i];
-			if( colEqNum->locationMatrix[e_i][0][n_i] < 0 ) {
-				col_index_to_keep[ n_cols ] = n_i;
-				n_cols++;
-				has_col_bc = 1;
-			}
-		}
-		for( n_i=0; n_i<nRowDofs; n_i++ ) {
-			if( rowEqNum->locationMatrix[e_i][0][n_i] >= 0 ) {
-				row_index_to_keep[ n_rows ] = n_i;
-				n_rows++;
-				has_row_bc = 1;
-			}
-		}
-
-		if( has_col_bc == 0 ) continue;
-
-		/* Assemble the element. */
-		memset( elStiffMat[0], 0, nDofs * sizeof(double) );
-		StiffMatAssLog_InitTimer_ElementAssembly( log );
-		
-		StiffnessMatrix_AssembleElement( self, e_i, sle, (FiniteElementContext*)_context, elStiffMat );
-		
-		StiffMatAssLog_AccumulateTime_ElementAssembly( log ); /* update time */
-		StiffMatAssLog_UpdateElementsAssembled( log ); /* update counter */
-
-
-		/* If keeping BCs in, zero corresponding entries in the element stiffness matrix. */
-		if( !rowEqNum->removeBCs || !colEqNum->removeBCs )
-			Assembler_LoopMatrixElement( self->zeroBCsAsm, e_i );
-
-
-		if( (has_col_bc==1) ) {
-			/* int I; */
-			memset( rhs, 0, maxRCDofs * sizeof(double) );
-
-			_get_bc_values( colVar, nColNodes, c_dof, (int*)colNodes, bcVals );
-			_make_dirichlet_corrections_to_rhs( n_rows, row_index_to_keep, n_cols, col_index_to_keep, elStiffMat, -1, bcVals, rhs );
-/*
-			printf("f: e = %d \n", e_i );
-                        
-			for( I=0; I<nRowDofs; I++ ) {
-				printf("  I=%d : %d -- bcval = %f : rhs = %f \n", I, rowEqNum->locationMatrix[e_i][0][I], bcVals[I], rhs[I] );
-			}
-*/
-			VecSetValues( vector, nRowDofs, (PetscInt*)rowEqNum->locationMatrix[e_i][0], rhs, ADD_VALUES );
-			StiffMatAssLog_UpdateElementsAssembledForBC_Corrections( log );
-			bc_cnt++;
-		}
-
-
-		/* Add to stiffness matrix. */
-		/*
-		StiffMatAssLog_InitTimer_ElementInsertion( log );
-                Matrix_AddEntries( matrix,
-                                   nRowDofs, (unsigned*)rowEqNum->locationMatrix[e_i][0],
-                                   nColDofs, (unsigned*)colEqNum->locationMatrix[e_i][0],
-                                   elStiffMat[0] );
-		StiffMatAssLog_AccumulateTime_ElementInsertion( log ); 
-		*/
-        }
-
-	StiffMatAssLog_InitTimer_ParallelAssembly( log );
-        /* Start assembling vectors. */
-	VecAssemblyBegin( vector );
-        
-        /* If keeping BCs in and rows and columnns use the same variable, put ones in all BC'd diagonals. */
-//        if( !colEqNum->removeBCs && rowVar == colVar )
-//                Assembler_LoopMatrixDiagonal( self->diagBCsAsm );
-
-        /* Start matrix assembly */
-        //Matrix_AssemblyBegin( matrix );
-
-        /* Finalise matrix and vector assembly */
-	VecAssemblyEnd( vector );
-        //Matrix_AssemblyEnd( matrix );
-	StiffMatAssLog_AccumulateTime_ParallelAssembly( log );
-
-//        printf("Applied vector modifications using %u of %u elements \n", bc_cnt, nRowEls );
-        FreeArray( elStiffMat );
-        FreeArray( bcVals );
-        FreeArray( row_index_to_keep );
-        FreeArray( col_index_to_keep );
-	FreeArray( rhs );
-
-	StiffMatAssLog_AccumulateTime_Total( log );
-
-/*
-	{
- 		PETScVector*    self = (PETScVector*)vector;
-		printf("f = \n");
-        	VecView( self->petscVec, PETSC_VIEWER_STDOUT_WORLD );
-	}
-*/	
-
-}
-
-
-
-
-void _StiffMatAss_vector_corrections_from_transpose( struct StiffMatAss_Log *log, void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context ) {
-	StiffnessMatrix*                self = (StiffnessMatrix*)stiffnessMatrix;
-	SystemLinearEquations*          sle = (SystemLinearEquations*)_sle;
-	FeVariable                      *rowVar, *colVar;
-	FeMesh                          *rowMesh, *colMesh;
-	FeEquationNumber                *rowEqNum, *colEqNum;
-	DofLayout                       *rowDofs, *colDofs;
-	unsigned                        nRowEls;
-	unsigned                        nRowNodes, *rowNodes;
-	unsigned                        nColNodes, *colNodes;
-	unsigned                        maxDofs, maxRCDofs, nDofs, nRowDofs, nColDofs;
-	double**                        elStiffMat;
-	double*                         bcVals;
-/* 	Mat				matrix		= ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
-	Mat                             matrix = self->matrix;
-	Vec				transVector;
-	unsigned                        e_i, n_i;
-
-	unsigned bc_cnt = 0;
-	int *row_index_to_keep, *col_index_to_keep;
-	int n_rows, n_cols;
-	int same_variables;
-	int c_dof, r_dof;
-	double *rhs;
-	int has_col_bc, has_row_bc;
-	int eq_num;
-
-	assert( self && Stg_CheckType( self, StiffnessMatrix ) );
-	StiffMatAssLog_Init( log, "OPERATOR_WITH_BC_CORRECTIONS_FROM_OP_TRANS" );
-	StiffMatAssLog_InitTimer_TotalTime( log );
-
-	rowVar = self->rowVariable;
-	colVar = self->columnVariable ? self->columnVariable : rowVar;
-	rowEqNum = rowVar->eqNum;
-	colEqNum = colVar->eqNum;
- 	rowMesh = rowVar->feMesh;
-	colMesh = colVar->feMesh;
-	rowDofs = rowVar->dofLayout;
-	colDofs = colVar->dofLayout;
-	nRowEls = FeMesh_GetElementLocalSize( rowMesh );
-	assert( (rowVar == colVar) ? !self->transRHS : 1 );
-
-  	//matrix = self->matrix;
-  	transVector = self->transRHS ? self->transRHS->vector : NULL;
-  	elStiffMat = NULL;
-  	bcVals = NULL;
-  	maxDofs = 0;
-
-	col_index_to_keep = NULL;
-	row_index_to_keep = NULL;
-	rhs = NULL;
-
-
-  	same_variables = 0;
-  	if( rowMesh == colMesh ) {
-  		same_variables = 1;
-		// printf("Detected same variables in assembly VECTOR CORRECTIONS FROM TRANSPOSE \n");
-	}
-	assert( transVector ); /* If we are in this function than transVector must be valid */ 
-
-	bc_cnt = 0;
-
-
-	StiffMatAssLog_GetOperatorDimensions( log, matrix );
-       /* Begin assembling each element. */
-        for( e_i = 0; e_i < nRowEls; e_i++ ) {
-                FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc );
-                nRowNodes = IArray_GetSize( self->rowInc );
-                rowNodes = (unsigned*)IArray_GetPtr( self->rowInc );
-                FeMesh_GetElementNodes( colMesh, e_i, self->colInc );
-                nColNodes = IArray_GetSize( self->colInc );
-                colNodes = (unsigned*)IArray_GetPtr( self->colInc );
-
-                /* Do we need more space to assemble this element? */
-                nRowDofs = 0;
-                for( n_i = 0; n_i < nRowNodes; n_i++ ) {
-                        nRowDofs += rowDofs->dofCounts[rowNodes[n_i]];
-                        r_dof = rowDofs->dofCounts[rowNodes[n_i]];
-                }
-                nColDofs = 0;
-                for( n_i = 0; n_i < nColNodes; n_i++ ) {
-                        nColDofs += colDofs->dofCounts[colNodes[n_i]];
-                        c_dof = colDofs->dofCounts[colNodes[n_i]];
-                }
-                nDofs = nRowDofs * nColDofs;
-                self->nRowDofs = nRowDofs;
-                self->nColDofs = nColDofs;
-                if( nDofs > maxDofs ) {
-                        maxRCDofs = (nRowDofs > nColDofs) ? nRowDofs : nColDofs;
-                        elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs );
-                        bcVals = ReallocArray( bcVals, double, maxRCDofs );
-                        rhs = ReallocArray( rhs, double, maxRCDofs );
-
-                        col_index_to_keep  = ReallocArray( col_index_to_keep, int, maxRCDofs );
-                        row_index_to_keep  = ReallocArray( row_index_to_keep, int, maxRCDofs );
-
-                        maxDofs = nDofs;
-                        self->elStiffMat = elStiffMat;
-                        self->bcVals = bcVals;
-                }
-
-                /* check for presence of bc's */
-                n_rows = n_cols = 0;
-                has_row_bc = has_col_bc = 0;
-
-		/* cause this is the transpose function, we make corrections on the bc's if there are applied to the row variable */
-                for( n_i=0; n_i<nColDofs; n_i++ ) {
-			eq_num = colEqNum->locationMatrix[e_i][0][n_i];
-                        if( colEqNum->locationMatrix[e_i][0][n_i] >= 0 ) {
-				col_index_to_keep[ n_cols ] = n_i;
-                                n_cols++;
-                                has_col_bc = 1;
-                        }
-                }
-        
-                for( n_i=0; n_i<nRowDofs; n_i++ ) {
-                       if( rowEqNum->locationMatrix[e_i][0][n_i] < 0 ) {
-				row_index_to_keep[ n_rows ] = n_i;
-                                n_rows++;
-                                has_row_bc = 1;
-                       }
-                }
-
-
-		if( has_row_bc == 0 ) continue;
-
-
-
-                /* Initialise the element stiffness matrix */
-                memset( elStiffMat[0], 0, nDofs * sizeof(double) );
-		/*
-		for( si=0; si<nRowDofs; si++ )
-		for( sj=0; sj<nColDofs; sj++ )
-			elStiffMat[si][sj] = 0.0;
-		*/
-
-		/* Assemble the element stiffness matrix */	     
-		StiffMatAssLog_InitTimer_ElementAssembly( log );
-
-		StiffnessMatrix_AssembleElement( self, e_i, sle, (FiniteElementContext*)_context, elStiffMat );
-
-		StiffMatAssLog_AccumulateTime_ElementAssembly( log );		
-		StiffMatAssLog_UpdateElementsAssembled( log );
-
-
-		/* If keeping BCs in, zero corresponding entries in the element stiffness matrix. */
-		if( !rowEqNum->removeBCs || !colEqNum->removeBCs )
-			Assembler_LoopMatrixElement( self->zeroBCsAsm, e_i );
-
-		if( (has_row_bc==1) ) {
-			/* int I; */
-			memset( rhs, 0, maxRCDofs * sizeof(double) );
-			/*
-			for( II=0; II<maxRCDofs; II++ ) {
-				bcVals[II] = rhs[II] = 0.0;
-			}
-			*/
-			_get_bc_values( rowVar, nRowNodes, r_dof, (int*)rowNodes, bcVals );
-
-			_make_dirichlet_corrections_to_rhs_transpose( n_cols, col_index_to_keep, n_rows, row_index_to_keep, elStiffMat, -1, bcVals, rhs );
-/*
-  			printf("h: e = %d \n", e_i );
-			for( I=0; I<nColDofs; I++ ) {
-				printf("  I=%d : %d -- bcval = %f : rhs = %f\n", I, colEqNum->locationMatrix[e_i][0][I], bcVals[I], rhs[I] );
-			}
-*/
-
-			VecSetValues( transVector, nColDofs, colEqNum->locationMatrix[e_i][0], rhs, INSERT_VALUES );
-			StiffMatAssLog_UpdateElementsAssembledForBC_Corrections( log );
-			bc_cnt++;
-		}
-
-		/* Add to stiffness matrix. */
-/*
-		StiffMatAssLog_InitTimer_ElementInsertion(log);
-                Matrix_AddEntries( matrix,
-                                   nRowDofs, (unsigned*)rowEqNum->locationMatrix[e_i][0],
-                                   nColDofs, (unsigned*)colEqNum->locationMatrix[e_i][0],
-                                   elStiffMat[0] );
-		StiffMatAssLog_AccumulateTime_ElementInsertion( log ); 
-*/  
-      }
-
-
-	StiffMatAssLog_InitTimer_ParallelAssembly( log );
-        /* Start assembling vectors. */
-	VecAssemblyBegin( transVector );
-
-
-        /* If keeping BCs in and rows and columnns use the same variable, put ones in all BC'd diagonals. */
-//        if( !colEqNum->removeBCs && rowVar == colVar )
-//                Assembler_LoopMatrixDiagonal( self->diagBCsAsm );
-
-        /* Start matrix assembly */
-//        Matrix_AssemblyBegin( matrix );
-
-        /* Finalise matrix and vector assembly */
-	VecAssemblyEnd( transVector );
-//        Matrix_AssemblyEnd( matrix );
-	StiffMatAssLog_AccumulateTime_ParallelAssembly( log );
-
-//        printf("Applied vector modifications using %u of %u elements \n", bc_cnt, nRowEls );
-        FreeArray( elStiffMat );
-        FreeArray( bcVals );
-        FreeArray( row_index_to_keep );
-        FreeArray( col_index_to_keep );
-	FreeArray( rhs );
-
-	StiffMatAssLog_AccumulateTime_Total( log );
-/*
-        {
-                PETScVector*    self = (PETScVector*)transVector;
-		printf("h = \n");
-                VecView( self->petscVec, PETSC_VIEWER_STDOUT_WORLD );
-        }
-*/
-}
-
-
-//void __StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context );
-void StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context ) {
-	StiffnessMatrix	*self = (StiffnessMatrix*)stiffnessMatrix;
-	Vec					vector, transVector;	
-	struct				StiffMatAss_Log *log;
-
-	vector = self->rhs ? self->rhs->vector : NULL;
-	transVector = self->transRHS ? self->transRHS->vector : NULL;
-
-	log = StiffMatAssLog_New();
-
-
-	_StiffMatAss( log, stiffnessMatrix, removeBCs, _sle, (FiniteElementContext*)_context );
-	StiffMatAssLog_Report( self, log );
-
-	if( vector ) {
-		_StiffMatAss_vector_corrections( log, stiffnessMatrix, removeBCs, _sle, (FiniteElementContext*)_context );
-		StiffMatAssLog_Report( self, log );
-	}
-	if( transVector ) {
-		_StiffMatAss_vector_corrections_from_transpose( log, stiffnessMatrix, removeBCs, _sle, (FiniteElementContext*)_context );
-		StiffMatAssLog_Report( self, log );
-	}
-	//	__StiffnessMatrix_NewAssemble( stiffnessMatrix, removeBCs, _sle, _context );
-	StiffMatAssLog_Delete( &log );
-}
-
-#if 0
-void StiffnessMatrix_SetEqsToUnity( StiffnessMatrix* self, const STreeNode* node ) {
-   static const double one = 1.0;
-
-   if( !node ) return;
-   StiffnessMatrix_SetEqsToUnity( self, node->left );
-   Matrix_AddEntries( self->matrix, 1, (int*)node->data, 1, (int*)node->data, (double*)&one );
-   StiffnessMatrix_SetEqsToUnity( self, node->right );
-}
-#endif
-
-
-/* Callback version */
-void __StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context ) {
-   static const double one = 1.0;
-	StiffnessMatrix*		self = (StiffnessMatrix*)stiffnessMatrix;
-	SystemLinearEquations*		sle = (SystemLinearEquations*)_sle;
-	FeVariable			*rowVar, *colVar;
-	FeMesh				*rowMesh, *colMesh;
-	FeEquationNumber		*rowEqNum, *colEqNum;
-	DofLayout			*rowDofs, *colDofs;
-	unsigned			nRowEls;
-	unsigned			nRowNodes, *rowNodes;
-	unsigned			nColNodes, *colNodes;
-	unsigned			maxDofs, maxRCDofs, nDofs, nRowDofs, nColDofs;
-	double**			elStiffMat;
-	double*				bcVals;
-/* 	Mat				matrix		= ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
-	Mat                             matrix = self->matrix;
-	Vec				vector, transVector;
-        int nRowNodeDofs, nColNodeDofs;
-        int rowInd, colInd;
-        double bc;
-	unsigned			e_i, n_i, dof_i, n_j, dof_j;
-
-	assert( self && Stg_CheckType( self, StiffnessMatrix ) );
-
-	rowVar = self->rowVariable;
-	colVar = self->columnVariable ? self->columnVariable : rowVar;
-	rowEqNum = rowVar->eqNum;
-	colEqNum = colVar->eqNum;
-	rowMesh = rowVar->feMesh;
-	colMesh = colVar->feMesh;
-	rowDofs = rowVar->dofLayout;
-	colDofs = colVar->dofLayout;
-	nRowEls = FeMesh_GetElementLocalSize( rowMesh );
-	assert( (rowVar == colVar) ? !self->transRHS : 1 );
-
-	//matrix = self->matrix;
-	vector = self->rhs ? self->rhs->vector : NULL;
-	transVector = self->transRHS ? self->transRHS->vector : NULL;
-	elStiffMat = NULL;
-	bcVals = NULL;
-	maxDofs = 0;
-
-	/* Begin assembling each element. */
-	for( e_i = 0; e_i < nRowEls; e_i++ ) {
-		FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc );
-		nRowNodes = IArray_GetSize( self->rowInc );
-		rowNodes = (unsigned*)IArray_GetPtr( self->rowInc );
-		FeMesh_GetElementNodes( colMesh, e_i, self->colInc );
-		nColNodes = IArray_GetSize( self->colInc );
-		colNodes = (unsigned*)IArray_GetPtr( self->colInc );
-
-		/* Do we need more space to assemble this element? */
-		nRowDofs = 0;
-		for( n_i = 0; n_i < nRowNodes; n_i++ )
-			nRowDofs += rowDofs->dofCounts[rowNodes[n_i]];
-		nColDofs = 0;
-		for( n_i = 0; n_i < nColNodes; n_i++ )
-			nColDofs += colDofs->dofCounts[colNodes[n_i]];
-		nDofs = nRowDofs * nColDofs;
-		self->nRowDofs = nRowDofs;
-		self->nColDofs = nColDofs;
-		if( nDofs > maxDofs ) {
-			maxRCDofs = (nRowDofs > nColDofs) ? nRowDofs : nColDofs;
-			elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs );
-			bcVals = ReallocArray( bcVals, double, maxRCDofs );
-			maxDofs = nDofs;
-			self->elStiffMat = elStiffMat;
-			self->bcVals = bcVals;
-		}
-
-		/* Assemble the element. */
-		memset( elStiffMat[0], 0, nDofs * sizeof(double) );
-		StiffnessMatrix_AssembleElement( self, e_i, sle, (FiniteElementContext*)_context, elStiffMat );
-
-		/* Correct for BCs providing I'm not keeping them in. */
-		if( vector && removeBCs ) {
-			memset( bcVals, 0, nRowDofs * sizeof(double) );
-
-                        rowInd = 0;
-                        for( n_i = 0; n_i < nRowNodes; n_i++ ) {
-                           nRowNodeDofs = rowDofs->dofCounts[rowNodes[n_i]];
-                           for( dof_i = 0; dof_i < nRowNodeDofs; dof_i++ ) {
-                              if( !FeVariable_IsBC( rowVar, rowNodes[n_i], dof_i ) ) {
-                                 colInd = 0;
-                                 for( n_j = 0; n_j < nColNodes; n_j++ ) {
-                                    nColNodeDofs = colDofs->dofCounts[colNodes[n_j]];
-                                    for( dof_j = 0; dof_j < nColNodeDofs; dof_j++ ) {
-                                       if( FeVariable_IsBC( colVar, colNodes[n_j], dof_j ) ) {
-                                          bc = DofLayout_GetValueDouble( colDofs, colNodes[n_j], dof_j );
-                                          bcVals[rowInd] -= bc * elStiffMat[rowInd][colInd];
-                                       }
-                                       colInd++;
-                                    }
-                                 }
-                              }
-                              rowInd++;
-                           }
-                        }
-
-			//Vector_AddEntries( vector, nRowDofs, (unsigned*)rowEqNum->locationMatrix[e_i][0], bcVals );
-			VecSetValues( vector, nRowDofs, rowEqNum->locationMatrix[e_i][0], bcVals, ADD_VALUES );
-		}
-		if( transVector && removeBCs ) {
-			memset( bcVals, 0, nColDofs * sizeof(double) );
-
-                        colInd = 0;
-                        for( n_i = 0; n_i < nColNodes; n_i++ ) {
-                           nColNodeDofs = colDofs->dofCounts[colNodes[n_i]];
-                           for( dof_i = 0; dof_i < nColNodeDofs; dof_i++ ) {
-                              if( !FeVariable_IsBC( colVar, colNodes[n_i], dof_i ) ) {
-                                 rowInd = 0;
-                                 for( n_j = 0; n_j < nRowNodes; n_j++ ) {
-                                    nRowNodeDofs = rowDofs->dofCounts[rowNodes[n_j]];
-                                    for( dof_j = 0; dof_j < nRowNodeDofs; dof_j++ ) {
-                                       if( FeVariable_IsBC( rowVar, rowNodes[n_j], dof_j ) ) {
-                                          bc = DofLayout_GetValueDouble( rowDofs, rowNodes[n_j], dof_j );
-                                          bcVals[colInd] -= bc * elStiffMat[rowInd][colInd];
-                                       }
-                                       rowInd++;
-                                    }
-                                 }
-                              }
-                              colInd++;
-                           }
-                        }
-
-			VecSetValues( transVector, nColDofs, colEqNum->locationMatrix[e_i][0], bcVals, ADD_VALUES );
-		}
-
-		/* If keeping BCs in, zero corresponding entries in the element stiffness matrix. */
-		if( !rowEqNum->removeBCs || !colEqNum->removeBCs ) {
-                   rowInd = 0;
-                   for( n_i = 0; n_i < nRowNodes; n_i++ ) {
-                      nRowNodeDofs = rowDofs->dofCounts[rowNodes[n_i]];
-                      for( dof_i = 0; dof_i < nRowNodeDofs; dof_i++ ) {
-                         if( FeVariable_IsBC( rowVar, rowNodes[n_i], dof_i ) ) {
-                            memset( elStiffMat[rowInd], 0, nColDofs * sizeof(double) );
-                         }
-                         else {
-                            colInd = 0;
-                            for( n_j = 0; n_j < nColNodes; n_j++ ) {
-                               nColNodeDofs = colDofs->dofCounts[colNodes[n_j]];
-                               for( dof_j = 0; dof_j < nColNodeDofs; dof_j++ ) {
-                                  if( FeVariable_IsBC( colVar, colNodes[n_j], dof_j ) )
-                                     elStiffMat[rowInd][colInd] = 0.0;
-                                  colInd++;
-                               }
-                            }
-                         }
-                         rowInd++;
-                      }
-                   }
-                }
-
-		/* Add to stiffness matrix. */
-		MatSetValues( matrix, 
-			      nRowDofs, rowEqNum->locationMatrix[e_i][0], 
-			      nColDofs, colEqNum->locationMatrix[e_i][0], 
-			      elStiffMat[0], ADD_VALUES );
-	}
-
-	FreeArray( elStiffMat );
-	FreeArray( bcVals );
-
-	/* If keeping BCs in and rows and columnns use the same variable, put ones in all BC'd diagonals. */
-	if( !colEqNum->removeBCs && rowVar == colVar ) {
-           for( n_i = 0; n_i < FeMesh_GetNodeLocalSize( colMesh ); n_i++ ) {
-              nColNodeDofs = colDofs->dofCounts[n_i];
-              for( dof_i = 0; dof_i < nColNodeDofs; dof_i++ ) {
-                 if( FeVariable_IsBC( colVar, n_i, dof_i ) ) {
-                    MatSetValues( self->matrix,
-                                       1, colEqNum->destinationArray[n_i] + dof_i,
-                                       1, colEqNum->destinationArray[n_i] + dof_i,
-                                       (double*)&one, ADD_VALUES );
-                 }
-              }
-           }
-
-#if 0
-           StiffnessMatrix_SetEqsToUnity( self, rowEqNum, STree_GetRoot( rowEqNum->ownedMap ) );
-#endif
-        }
-
-	/* Reassemble the matrix and vectors. */
-	MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
-	MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
-	if( vector ) {
-		VecAssemblyBegin( vector );
-		VecAssemblyEnd( vector );
-	}
-	if( transVector) {
-		VecAssemblyBegin( transVector );
-		VecAssemblyEnd( transVector );
-	}
-
-	MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
-	MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
-}
-
-/* void StiffnessMatrix_ShellAssembly( void* stiffnessMatrix, Bool removeBCs, void* data ) { */
-/* 	StiffnessMatrix*	self = (StiffnessMatrix*)stiffnessMatrix; */
-/* 	Vec    			rhs; */
-/* 	FeVariable		*rowVar, *colVar; */
-/* 	FeMesh			*rowMesh, *colMesh; */
-/* 	FeEquationNumber	*rowEqNum, *colEqNum; */
-/* 	DofLayout		*rowDofs, *colDofs; */
-/* 	unsigned		nRowEls; */
-/* 	unsigned		nRowNodes, *rowNodes; */
-/* 	unsigned		nColNodes, *colNodes; */
-/* 	unsigned		maxDofs, nDofs, nRowDofs, nColDofs; */
-/* 	double**		elStiffMat; */
-/* 	double*			values; */
-/* 	unsigned*		indices; */
-/* 	unsigned		curRow, curCol; */
-/* 	unsigned		colEq; */
-/* 	double			bc; */
-/* 	unsigned		e_i, n_i, n_j, dof_i, dof_j; */
-
-/* 	assert( self && Stg_CheckType( self, StiffnessMatrix ) ); */
-
-/* 	/\* The whole point of this routine is to remove the BCs. *\/ */
-/* 	if( !removeBCs ) */
-/* 		return; */
-
-/* 	rhs = self->rhs->vector; */
-/* 	rowVar = self->rowVariable; */
-/* 	colVar = self->columnVariable ? self->columnVariable : rowVar; */
-/* 	if( rowVar != colVar ) { */
-/* 		FeVariable* 	tmp = rowVar; */
-/* 		rowVar = colVar; */
-/* 		colVar = tmp; */
-/* 	} */
-/* 	rowEqNum = rowVar->eqNum; */
-/* 	colEqNum = colVar->eqNum; */
-/* 	rowMesh = rowVar->feMesh; */
-/* 	colMesh = colVar->feMesh; */
-/* 	rowDofs = rowVar->dofLayout; */
-/* 	colDofs = colVar->dofLayout; */
-/* 	nRowEls = FeMesh_GetElementLocalSize( rowMesh ); */
-/* 	elStiffMat = NULL; */
-/* 	values = NULL; */
-/* 	indices = NULL; */
-/* 	maxDofs = 0; */
-
-/* 	for( e_i = 0; e_i < nRowEls; e_i++ ) { */
-/* 		FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc ); */
-/* 		nRowNodes = IArray_GetSize( self->rowInc ); */
-/* 		rowNodes = IArray_GetPtr( self->rowInc ); */
-/* 		FeMesh_GetElementNodes( colMesh, e_i, self->colInc ); */
-/* 		nColNodes = IArray_GetSize( self->colInc ); */
-/* 		colNodes = IArray_GetPtr( self->colInc ); */
-
-/* 		/\* If none of the column equations on this element have BCs then skip it. *\/ */
-/* 		for( n_i = 0; n_i < nRowNodes; n_i++ ) { */
-/* 			for( dof_i = 0; dof_i < rowDofs->dofCounts[rowNodes[n_i]]; dof_i++ ) { */
-/* 				if( rowEqNum->locationMatrix[e_i][n_i][dof_i] == (unsigned)-1 ) */
-/* 					continue; */
-/* 				for( n_j = 0; n_j < nColNodes; n_j++ ) { */
-/* 					for( dof_j = 0; dof_j < colDofs->dofCounts[colNodes[n_j]]; dof_j++ ) { */
-/* 						if( colEqNum->locationMatrix[e_i][n_j][dof_j] == (unsigned)-1 ) */
-/* 							break; */
-/* 					} */
-/* 					if( dof_j < colDofs->dofCounts[colNodes[n_j]] ) */
-/* 						break; */
-/* 				} */
-/* 				if( n_j < nColNodes ) */
-/* 					break; */
-/* 			} */
-/* 			if( dof_i < rowDofs->dofCounts[rowNodes[n_i]] ) */
-/* 				break; */
-/* 		} */
-/* 		if( n_i == nRowNodes ) */
-/* 			continue; */
-
-/* 		/\* Do we need more space to assemble this element? *\/ */
-/* 		nRowDofs = 0; */
-/* 		for( n_i = 0; n_i < nRowNodes; n_i++ ) */
-/* 			nRowDofs += rowDofs->dofCounts[rowNodes[n_i]]; */
-/* 		nColDofs = 0; */
-/* 		for( n_i = 0; n_i < nColNodes; n_i++ ) */
-/* 			nColDofs += colDofs->dofCounts[colNodes[n_i]]; */
-/* 		nDofs = nRowDofs * nColDofs; */
-/* 		if( nDofs > maxDofs ) { */
-/* #if 0 */
-/* 			elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs ); */
-/* #endif */
-/* 			values = ReallocArray( values, double, nDofs ); */
-/* 			indices = ReallocArray( indices, unsigned, nDofs ); */
-/* 			maxDofs = nDofs; */
-/* 		} */
-
-/* #if 0 */
-/* 		/\* Assemble the element. *\/ */
-/* 		memset( &elStiffMat[0][0], 0, nDofs * sizeof(double) ); */
-/* 		StiffnessMatrix_AssembleElement( self, e_i, sle, elStiffMat ); */
-/* #endif */
-
-/* 		elStiffMat = ((PETScShellMatrix*)self->matrix)->elStiffMat;	assert( elStiffMat ); */
-
-/* 		/\* Update the force vector with BCs. *\/ */
-/* 		curRow = 0; */
-/* 		memset( values, 0, nDofs * sizeof(double) ); */
-/* 		for( n_i = 0; n_i < nRowNodes; n_i++ ) { */
-/* 			for( dof_i = 0; dof_i < rowDofs->dofCounts[rowNodes[n_i]]; dof_i++ ) { */
-/* 				indices[curRow] = rowEqNum->locationMatrix[e_i][n_i][dof_i]; */
-/* 				if( indices[curRow] == (unsigned)-1 ) { */
-/* 					curRow++; */
-/* 					continue; */
-/* 				} */
-
-/* 				curCol = 0; */
-/* 				for( n_j = 0; n_j < nColNodes; n_j++ ) { */
-/* 					for( dof_j = 0; dof_j < colDofs->dofCounts[colNodes[n_j]]; dof_j++ ) { */
-/* 						colEq = colEqNum->locationMatrix[e_i][n_j][dof_j]; */
-/* 						if( colEq != (unsigned)-1 ) { */
-/* 							curCol++; */
-/* 							continue; */
-/* 						} */
-
-/* 						bc = DofLayout_GetValueDouble( colDofs, colNodes[n_j], dof_j ); */
-/* 						values[curRow] -= elStiffMat[curRow][curCol] * bc; */
-
-/* 						curCol++; */
-/* 					} */
-/* 				} */
-
-/* 				curRow++; */
-/* 			} */
-/* 		} */
-
-/* 		VecSetValues( rhs, curRow, indices, values, ADD_VALUES ); */
-/* 	} */
-
-/* 	FreeArray( values ); */
-/* 	FreeArray( indices ); */
-
-/* 	VecAssemblyBegin( rhs ); */
-/* 	VecAssemblyEnd( rhs ); */
-/* } */
-
-
-
-/* +++ PRIVATE FUNCTIONS +++ */
-	
-void _StiffnessMatrix_UpdateBC_CorrectionTables(
-	StiffnessMatrix*	self,
-	FeEquationNumber*	eqNum, 
-	DofLayout*		dofLayout,
-	Dof_EquationNumber**	elementLM,
-	Node_ElementLocalIndex	nodeCountThisEl,
-	Element_Nodes		nodeIdsThisEl,
-	Dof_Index*		bcLM_Id,
-	double*			bcValues,
-	int*			nBC_NodalDofPtr )
-{
-	Node_ElementLocalIndex		node_elLocalI = 0;
-	Node_LocalIndex			node_lI = 0;
-	Dof_Index*			dofCounts = dofLayout->dofCounts;
-	Dof_Index			dofCountThisNode=0;
-	Dof_Index			dof_nodeLocalI=0;
-	unsigned			pos = 0;
-
-	for( node_elLocalI = 0; node_elLocalI < nodeCountThisEl; node_elLocalI++ ) {
-		node_lI = nodeIdsThisEl[node_elLocalI];
-		dofCountThisNode = dofCounts[node_lI];
-		
-		for( dof_nodeLocalI = 0; dof_nodeLocalI < dofCountThisNode; dof_nodeLocalI++ ) {
-			Bool	isBC = False;
-
-			/* Can only use 'elementLM' if FeEquationNumber has been told to remove BCs.  Otherwise
-			   we'll need to determine if the VariableCondition has a value specified for this 
-			   node/dof. - Luke */
-			if( elementLM[node_elLocalI][dof_nodeLocalI] != (unsigned)-1 ) {
-				unsigned	lEqNum;
-
-				lEqNum = *(int*)STreeMap_Map( eqNum->ownedMap,
-							      elementLM[node_elLocalI] + dof_nodeLocalI );
-
-				if( eqNum->bcEqNums && STree_Has( eqNum->bcEqNums, &lEqNum ) ) {
-					isBC = True;
-				}
-			}
-			else {
-				isBC = True;
-			}
-
-			if ( isBC ) {
-				/* offset into the elementStiffness matrix */
-				bcLM_Id[ *nBC_NodalDofPtr ] = pos;
-/*
-  bcLM_Id[ *nBC_NodalDofPtr ] = &elementLM[node_elLocalI][dof_nodeLocalI] - &elementLM[0][0];
-*/
-
-/* 				 get bc values from the bc_layout  */
-				bcValues[ *nBC_NodalDofPtr ]  = DofLayout_GetValueDouble( dofLayout, node_lI, dof_nodeLocalI );
-
-				Journal_DPrintfL( self->debug, 3, "bcValues[%d]: at &LM[0][0] + %d=%d, is %f\n",
-						  *nBC_NodalDofPtr, bcLM_Id[ *nBC_NodalDofPtr ],
-						  elementLM[0][ bcLM_Id[ *nBC_NodalDofPtr ] ],
-						  bcValues[ *nBC_NodalDofPtr ] );
-
-				(*nBC_NodalDofPtr)++;
-			}
-
-			/* Move to next element stiffness matrix entry. */
-			pos++;
-		}
-	}
-}	
-
-
-void _StiffnessMatrix_CorrectForceVectorWithOneElementsBoundaryConditions(
-	StiffnessMatrix*	self,
-	Dof_EquationNumber** 	elementLM[MAX_FE_VARS],
-	double*			h2Add,
-	double** 		elStiffMatToAdd,
-	Dof_Index*		totalDofsThisElement[MAX_FE_VARS],
-	Dof_Index*		bcLM_Id[MAX_FE_VARS],
-	double*			bcValues[MAX_FE_VARS],
-	int			nBC_NodalDof_Row, 
-	unsigned		elementInd /* NEW ONE */ )
-{
-#if 0
-	int 		rowEqId;
-	double		bc_value;
-	Dof_Index	colDof_elLocalI;
-#endif
-
-	memset( h2Add, 0, (*totalDofsThisElement[COL_VAR]) * sizeof(double) );
-
-	/*
-	** Something fishy is up with BC corrections, adding this for now.
-	*/
-
-	if( self->rowVariable != self->columnVariable )	{
-		Mesh			*rowMesh, *colMesh;
-		FeEquationNumber	*rowEqNum, *colEqNum;
-		DofLayout		*rowDofs, *colDofs;
-		unsigned		nRowElNodes, *rowElNodes, nColElNodes, *colElNodes;
-		unsigned		nRowDofs, nColDofs;
-		unsigned		dofI, dofJ, elIndI, elIndJ;
-		double			bcValue;
-		unsigned		n_i, n_j, d_i, d_j;
-
-		rowMesh = (Mesh*)self->rowVariable->feMesh;
-		colMesh = (Mesh*)self->columnVariable->feMesh;
-		rowEqNum = self->rowVariable->eqNum;
-		colEqNum = self->columnVariable->eqNum;
-		rowDofs = rowEqNum->dofLayout;
-		colDofs = colEqNum->dofLayout;
-		Mesh_GetIncidence( rowMesh, Mesh_GetDimSize( rowMesh ), elementInd, MT_VERTEX, self->rowInc );
-		nRowElNodes = IArray_GetSize( self->rowInc );
-		rowElNodes = (unsigned*)IArray_GetPtr( self->rowInc );
-		Mesh_GetIncidence( colMesh, Mesh_GetDimSize( colMesh ), elementInd, MT_VERTEX, self->colInc );
-		nColElNodes = IArray_GetSize( self->colInc );
-		colElNodes = (unsigned*)IArray_GetPtr( self->colInc );
-		nRowDofs = rowDofs->dofCounts[0];
-		nColDofs = colDofs->dofCounts[0];
-
-		for( n_i = 0; n_i < nColElNodes; n_i++ ) {
-			for( d_i = 0; d_i < nColDofs; d_i++ ) {
-				dofI = colEqNum->locationMatrix[elementInd][n_i][d_i];
-				if( dofI == -1 )
-					continue;
-
-				elIndI = n_i * nColDofs + d_i;
-				for( n_j = 0; n_j < nRowElNodes; n_j++ ) {
-					for( d_j = 0; d_j < nRowDofs; d_j++ ) {
-						dofJ = rowEqNum->locationMatrix[elementInd][n_j][d_j];
-						if( dofJ != -1 )
-							continue;
-
-						elIndJ = n_j * nRowDofs + d_j;
-						bcValue = DofLayout_GetValueDouble( rowDofs, rowElNodes[n_j], d_j );
-						h2Add[elIndI] -= elStiffMatToAdd[elIndJ][elIndI] * bcValue;
-					}
-				}
-			}
-		}
-	}
-	else {
-		Mesh			*rowMesh, *colMesh;
-		FeEquationNumber	*rowEqNum, *colEqNum;
-		DofLayout		*rowDofs, *colDofs;
-		unsigned		nRowElNodes, *rowElNodes, nColElNodes, *colElNodes;
-		unsigned		nRowDofs, nColDofs;
-		unsigned		dofI, dofJ, elIndI, elIndJ;
-		double			bcValue;
-		unsigned		n_i, n_j, d_i, d_j;
-
-		rowMesh = (Mesh*)self->rowVariable->feMesh;
-		colMesh = (Mesh*)self->columnVariable->feMesh;
-		rowEqNum = self->rowVariable->eqNum;
-		colEqNum = self->columnVariable->eqNum;
-		rowDofs = rowEqNum->dofLayout;
-		colDofs = colEqNum->dofLayout;
-		Mesh_GetIncidence( rowMesh, Mesh_GetDimSize( rowMesh ), elementInd, MT_VERTEX, self->rowInc );
-		nRowElNodes = IArray_GetSize( self->rowInc );
-		rowElNodes = (unsigned*)IArray_GetPtr( self->rowInc );
-		Mesh_GetIncidence( colMesh, Mesh_GetDimSize( colMesh ), elementInd, MT_VERTEX, self->colInc );
-		nColElNodes = IArray_GetSize( self->colInc );
-		colElNodes = (unsigned*)IArray_GetPtr( self->colInc );
-		nRowDofs = rowDofs->dofCounts[0];
-		nColDofs = colDofs->dofCounts[0];
-
-		for( n_i = 0; n_i < nRowElNodes; n_i++ ) {
-			for( d_i = 0; d_i < nRowDofs; d_i++ ) {
-				dofI = rowEqNum->locationMatrix[elementInd][n_i][d_i];
-				if( dofI == -1 )
-					continue;
-
-				elIndI = n_i * nRowDofs + d_i;
-				for( n_j = 0; n_j < nColElNodes; n_j++ ) {
-					for( d_j = 0; d_j < nColDofs; d_j++ ) {
-						dofJ = colEqNum->locationMatrix[elementInd][n_j][d_j];
-						if( dofJ != -1 )
-							continue;
-
-						elIndJ = n_j * nColDofs + d_j;
-						bcValue = DofLayout_GetValueDouble( colDofs, colElNodes[n_j], d_j );
-						h2Add[elIndI] -= elStiffMatToAdd[elIndI][elIndJ] * bcValue;
-					}
-				}
-			}
-		}
-	}
-
-#if 0
-	for( colDof_elLocalI=0; colDof_elLocalI < *totalDofsThisElement[COL_VAR]; colDof_elLocalI++ ) {
-		double		sum = 0.0;
-
-		for( bcDof_I=0; bcDof_I < nBC_NodalDof_Row; bcDof_I++ ) {
-			rowEqId = bcLM_Id[ROW_VAR][bcDof_I];
-			bc_value = bcValues[ROW_VAR][bcDof_I];
-/* 			printf("bc_value = %f \n",bc_value );  */
-			
-			/* this index is gets us to the right */
-			sum = sum - ( elStiffMatToAdd[rowEqId][colDof_elLocalI] * bc_value );
-		}
-		h2Add[colDof_elLocalI] = sum;
-	}
-#endif
-
-	VecSetValues( self->rhs->vector, *totalDofsThisElement[COL_VAR], elementLM[COL_VAR][0], h2Add, ADD_VALUES );
-	
-	/* assume that K is symetric, so corrections are made with KTrans.
-	   this allows us to use this func with G, when we want velocity
-	   corrections from GTrans to appear in H.
-	*/
-
-	/*
-	  for( bcDof_I=0; bcDof_I < nBC_NodalDof_row; bcDof_I++ ) {
-	  rowEqId = bcLM_Id[ROW_VAR][bcDof_I];
-	  bc_value = bcValues[ROW_VAR][bcDof_I];
-	  printf("bc_value = %f \n",bc_value ); 
-		
-	  printf("bc value = %f \n",bc_value );
-	  correct = 0;
-	  for( colDof_elLocalI=0; colDof_elLocalI< *totalDofsThisElement[COL_VAR]; colDof_elLocalI++ ) {
-	  h2Add[correct] = h2Add[correct]
-	  - elStiffMatToAdd[rowEqId* (*totalDofsThisElement[COL_VAR]) + colDof_elLocalI] * bc_value;
-	  hIdx[correct] = elementLM[COL_VAR][0][ colDof_elLocalI ];
-			
-	  correct = correct + 1;
-	  }
-	  }
-	  Vector_AddTo( self->rhs->vector, correct, hIdx, h2Add );
-	*/
-	
-	/* does not work */
-	/*for( rowDof_elLocalI=0; rowDof_elLocalI < *totalDofsThisElement[ROW_VAR]; rowDof_elLocalI++ ) {
-		double sum = 0.0;
-		for( rowDof_elLocalI=0; rowDof_elLocalI<nBC_NodalDof[ROW_VAR]; rowDof_elLocalI++ ) {
-		colEqId = bcLM_Id[COL_VAR][rowDof_elLocalI];
-		bc_value = bcValues[COL_VAR][rowDof_elLocalI];
-			
-		sum = sum + elStiffMatToAdd[ i* (*totalDofsThisElement[COL_VAR]) + colEqId] * bc_value;
-		}
-		h2Add[rowDof_elLocalI] = -sum;
-		}
-		Vector_AddTo( self->rhs->vector, *totalDofsThisElement[ROW_VAR], elementLM[ROW_VAR][0], h2Add ); */
-}
-
-void _StiffnessMatrix_PrintElementStiffnessMatrix(
-	StiffnessMatrix* self,
-	Element_LocalIndex element_lI,
-	Dof_EquationNumber** rowElementLM,
-	Dof_EquationNumber** colElementLM,
-	double** elStiffMatToAdd )
-{
-	FeMesh*			rFeMesh = self->rowVariable->feMesh;
-	FeMesh*			cFeMesh = self->columnVariable->feMesh;
-	Dof_Index		rowDofsPerNode;
-	Dof_Index		colDofsPerNode;
-	Node_LocalIndex		rowNodesThisEl;
-	Node_LocalIndex		colNodesThisEl;
-	Node_LocalIndex		rowNode_I, colNode_I;
-	Dof_Index		rowDof_I, colDof_I;
-	Index			rowIndex, colIndex;
-	unsigned		nRowElInc, *rowElInc;
-	unsigned		nColElInc, *colElInc;
-
-	FeMesh_GetElementNodes( rFeMesh, element_lI, self->rowInc );
-	nRowElInc = IArray_GetSize( self->rowInc );
-	rowElInc = (unsigned*)IArray_GetPtr( self->rowInc );
-	FeMesh_GetElementNodes( cFeMesh, element_lI, self->colInc );
-	nColElInc = IArray_GetSize( self->colInc );
-	colElInc = (unsigned*)IArray_GetPtr( self->colInc );
-
-	rowDofsPerNode = self->rowVariable->dofLayout->dofCounts[rowElInc[0]];
-	colDofsPerNode = self->columnVariable->dofLayout->dofCounts[colElInc[0]];
-	rowNodesThisEl = nRowElInc;
-	colNodesThisEl = nColElInc;
-
-	for ( rowNode_I=0; rowNode_I < rowNodesThisEl; rowNode_I++ ) {
-		for ( rowDof_I = 0; rowDof_I < rowDofsPerNode; rowDof_I++ ) {
-			for ( colNode_I=0; colNode_I < colNodesThisEl; colNode_I++ ) {
-				for ( colDof_I = 0; colDof_I < colDofsPerNode; colDof_I++ ) {
-					rowIndex = rowNode_I*rowDofsPerNode + rowDof_I;
-					colIndex = colNode_I*colDofsPerNode + colDof_I;
-
-					Journal_DPrintf( self->debug, "Row [%d][%d], Col [%d][%d] (LM (%4d,%4d)) = %.3f\n",
-						rowNode_I, rowDof_I,
-						colNode_I, colDof_I,
-						rowElementLM[rowNode_I][rowDof_I],
-						colElementLM[colNode_I][colDof_I],
-						elStiffMatToAdd[rowIndex][colIndex] ); 
-				}			
-			}
-		}
-	}
-}
-
-void StiffnessMatrix_AssembleElement(
-	void* stiffnessMatrix,
-	Element_LocalIndex element_lI,
-	SystemLinearEquations* sle,
-	FiniteElementContext* context,
-	double** elStiffMatToAdd )
-{
-	StiffnessMatrix*        self                      = (StiffnessMatrix*) stiffnessMatrix;
-	Index                   stiffnessMatrixTermCount  = Stg_ObjectList_Count( self->stiffnessMatrixTermList );
-	Index                   stiffnessMatrixTerm_I;
-	StiffnessMatrixTerm*    stiffnessMatrixTerm;
-
-	for ( stiffnessMatrixTerm_I = 0 ; stiffnessMatrixTerm_I < stiffnessMatrixTermCount ; stiffnessMatrixTerm_I++ ) {
-		stiffnessMatrixTerm = (StiffnessMatrixTerm*) Stg_ObjectList_At( self->stiffnessMatrixTermList, stiffnessMatrixTerm_I );
-		StiffnessMatrixTerm_AssembleElement( stiffnessMatrixTerm, self, element_lI, sle, context, elStiffMatToAdd );
-	}
-}
-
-void StiffnessMatrix_CheckElementAssembly( 
-	void* stiffnessMatrix,
-	Element_LocalIndex element_lI,
-	double** elStiffMatToAdd,
-	Index elStiffMatToAddRowSize,
-	Index elStiffMatToAddColSize )
-{
-	StiffnessMatrix*  self = (StiffnessMatrix*)stiffnessMatrix;
-	Bool              atLeastOneNonZeroElementContributionEntry = False;
-	Index             elStiffMat_rowI = 0;
-	Index             elStiffMat_colI = 0;
-	Stream*           errorStream = Journal_Register( Error_Type, (Name)self->type );
-	
-	for ( elStiffMat_colI = 0; elStiffMat_colI < elStiffMatToAddColSize; elStiffMat_colI++ ) {
-		for ( elStiffMat_rowI = 0; elStiffMat_rowI < elStiffMatToAddColSize; elStiffMat_rowI++ ) {
-			if ( elStiffMatToAdd[elStiffMat_rowI][elStiffMat_colI] != 0.0 ) {
-				atLeastOneNonZeroElementContributionEntry = True;
-				break;
-			}	
-		}	
-		if ( atLeastOneNonZeroElementContributionEntry == True  ) {
-			break;
-		}	
-	}
-
-	Journal_Firewall( atLeastOneNonZeroElementContributionEntry == True, errorStream,
-		"Error - in %s(): while assembling matrix \"%s\", for element %u - elStiffMatToAdd assembled at this "
-		"element is all zeros."
-		"Did you register a stiffnessMatrixTerm? Is there at least one integration point in this "
-		"element?\n", __func__, self->name, element_lI  );
-}
-
-void StiffnessMatrix_AddStiffnessMatrixTerm( void* stiffnessMatrix, StiffnessMatrixTerm* stiffnessMatrixTerm ) {
-	StiffnessMatrix* self = (StiffnessMatrix*) stiffnessMatrix;
-
-	stiffnessMatrixTerm = Stg_CheckType( stiffnessMatrixTerm, StiffnessMatrixTerm );
-	Stg_ObjectList_Append( self->stiffnessMatrixTermList, stiffnessMatrixTerm );
-}
-
-void StiffnessMatrix_RefreshMatrix( StiffnessMatrix* self ) {
-	int nProcs;
-	
-	assert( self && Stg_CheckType( self, StiffnessMatrix ) );
-
-	/* Note: I'd like to make this a dereference, just in case there is another class still using 
-	   the old matrix, but that'd require two matrices to exist at one time; i.e. lots of memory. 
-	   Keeping it as a free just means that other classes need to assume they never own the matrix. */
-	/*if( self->useShellMatrix ) { 
- 		PETScShellMatrix_SetComm( self->shellMatrix, self->comm ); 
- 		PETScShellMatrix_SetLocalSize( self->shellMatrix, self->rowLocalSize, self->colLocalSize ); 
- 		PETScShellMatrix_SetNonZeroStructure( self->shellMatrix, self->nonZeroCount, self->diagonalNonZeroIndices, self->offDiagonalNonZeroIndices ); 
-	} 
- 	else { */
-		if( self->matrix != PETSC_NULL )
-			MatDestroy( self->matrix );
-
-		MatCreate( self->comm, &self->matrix );
-		MatSetSizes( self->matrix, self->rowLocalSize, self->colLocalSize, PETSC_DETERMINE, PETSC_DETERMINE );
-		MatSetFromOptions( self->matrix );
-		MPI_Comm_size( self->comm, &nProcs );
-
-		if( self->diagonalNonZeroIndices || self->offDiagonalNonZeroIndices ) {
-			if( nProcs > 1 )
-                          MatMPIAIJSetPreallocation( self->matrix, PETSC_NULL, (PetscInt*)(self->diagonalNonZeroIndices), PETSC_NULL, (PetscInt*)(self->offDiagonalNonZeroIndices) );
-			else
-                          MatSeqAIJSetPreallocation( self->matrix, PETSC_NULL, (PetscInt*)(self->diagonalNonZeroIndices) );
-		}
-		else {
-			if( nProcs > 1 )
-				MatMPIAIJSetPreallocation( self->matrix, self->nonZeroCount, PETSC_NULL, self->nonZeroCount, PETSC_NULL );
-			else
-				MatSeqAIJSetPreallocation( self->matrix, self->nonZeroCount, PETSC_NULL );
-		}
-	/*}*/
-}
-
-void StiffnessMatrix_CalcNonZeros( void* stiffnessMatrix ) {
-	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
-	Stream *stream;
-	FeVariable *rowVar, *colVar;
-	FeMesh *rowMesh, *colMesh;
-	FeEquationNumber *rowEqNum, *colEqNum;
-	DofLayout *rowDofs, *colDofs;
-	int nRowEqs, nColEqs;
-	int nColNodes, *colNodes;
-	int nNodeEls, *nodeEls;
-	int *nDiagNonZeros, *nOffDiagNonZeros;
-	int rowEq, colEq, localRowEq;
-	int netNonZeros;
-	STree *candColEqs;
-	int e_i;
-	int n_i, dof_i;
-	int n_j, dof_j;
-
-	assert( self && Stg_CheckType( self, StiffnessMatrix ) );
-	assert( self->rowVariable );
-
-	stream = Journal_Register( Info_Type, (Name)self->type  );
-	Journal_Printf( stream, "Stiffness matrix: '%s'\n", self->name );
-	Stream_Indent( stream );
-	Journal_Printf( stream, "Calculating number of nonzero entries...\n" );
-	Stream_Indent( stream );
-
-	rowVar = self->rowVariable;
-	colVar = self->columnVariable ? self->columnVariable : rowVar;
-	rowMesh = rowVar->feMesh;
-	colMesh = colVar->feMesh;
-	rowEqNum = rowVar->eqNum;
-	colEqNum = colVar->eqNum;
-	nRowEqs = rowEqNum->localEqNumsOwnedCount;
-	nColEqs = colEqNum->localEqNumsOwnedCount;
-	rowDofs = rowVar->dofLayout;
-	colDofs = colVar->dofLayout;
-
-	candColEqs = STree_New();
-	STree_SetIntCallbacks( candColEqs );
-	STree_SetItemSize( candColEqs, sizeof(int) );
-	nDiagNonZeros = AllocArray( int, nRowEqs );
-	nOffDiagNonZeros = AllocArray( int, nRowEqs );
-	memset( nDiagNonZeros, 0, nRowEqs * sizeof(int) );
-	memset( nOffDiagNonZeros, 0, nRowEqs * sizeof(int) );
-	netNonZeros = 0;
-
-	for( n_i = 0; n_i < FeMesh_GetNodeLocalSize( rowMesh ); n_i++ ) {
-		for( dof_i = 0; dof_i < rowDofs->dofCounts[n_i]; dof_i++ ) {
-			rowEq = rowEqNum->destinationArray[n_i][dof_i];
-
-			if( rowEq == -1 ) continue;
-			if( !STreeMap_HasKey( rowEqNum->ownedMap, &rowEq ) ) continue;
-
-			localRowEq = *(int*)STreeMap_Map( rowEqNum->ownedMap, &rowEq );
-			FeMesh_GetNodeElements( rowMesh, n_i, self->rowInc );
-			nNodeEls = IArray_GetSize( self->rowInc );
-			nodeEls = IArray_GetPtr( self->rowInc );
-			STree_Clear( candColEqs );
-
-			for( e_i = 0; e_i < nNodeEls; e_i++ ) {
-				/* ASSUME: Row and column meshes have one-to-one element overlap. */
-				FeMesh_GetElementNodes( colMesh, nodeEls[e_i], self->colInc );
-				nColNodes = IArray_GetSize( self->colInc );
-				colNodes = IArray_GetPtr( self->colInc );
-
-				for( n_j = 0; n_j < nColNodes; n_j++ ) {
-					for( dof_j = 0; dof_j < colDofs->dofCounts[colNodes[n_j]]; dof_j++ ) {
-						colEq = colEqNum->destinationArray[colNodes[n_j]][dof_j];
-
-						if( colEq == -1 ) continue;
-						if( !STree_Has( candColEqs, &colEq  ) ) {
-							STree_Insert( candColEqs, &colEq );
-							if( STreeMap_HasKey( colEqNum->ownedMap, &colEq ) )
-								nDiagNonZeros[localRowEq]++;
-							else
-								nOffDiagNonZeros[localRowEq]++;
-							netNonZeros++;
-						}
-					}
-				}
-			}
-      }
-   }
-        self->diagonalNonZeroIndices = (Index*)nDiagNonZeros;
-   self->offDiagonalNonZeroIndices = (Index*)nOffDiagNonZeros;
-
-   {
-      int tmp;
-      MPI_Allreduce( &netNonZeros, &tmp, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD );
-      netNonZeros = tmp;
-   }
-   Journal_Printf( stream, "Found %d nonzero entries.\n", netNonZeros );
-   Journal_Printf( stream, "Done.\n" );
-   Stream_UnIndent( stream );
-   Stream_UnIndent( stream );
-}
-
-
-Bool StiffnessMatrix_ZeroBCsAsm_RowR( void* stiffMat, Assembler* assm ) {
-	memset( ((StiffnessMatrix*)stiffMat)->elStiffMat[assm->rowInd], 0, ((StiffnessMatrix*)stiffMat)->nColDofs * sizeof(double) );
-
-	return False;
-}
-
-Bool StiffnessMatrix_ZeroBCsAsm_ColR( void* stiffMat, Assembler* assm ) {
-	((StiffnessMatrix*)stiffMat)->elStiffMat[assm->rowInd][assm->colInd] = 0.0;
-	return True;
-}
-
-Bool StiffnessMatrix_BCAsm_ColR( void* stiffMat, Assembler* assm ) {
-	double	bc;
-
-	bc = DofLayout_GetValueDouble( assm->colVar->dofLayout, assm->colNodeInd, assm->colDofInd );
-	((StiffnessMatrix*)stiffMat)->bcVals[assm->rowInd] -= bc * ((StiffnessMatrix*)stiffMat)->elStiffMat[assm->rowInd][assm->colInd];
-
-	return True;
-}
-
-Bool StiffnessMatrix_TransBCAsm_ColR( void* stiffMat, Assembler* assm ) {
-	double	bc;
-
-	bc = DofLayout_GetValueDouble( assm->colVar->dofLayout, assm->colNodeInd, assm->colDofInd );
-	((StiffnessMatrix*)stiffMat)->bcVals[assm->rowInd] -= bc * ((StiffnessMatrix*)stiffMat)->elStiffMat[assm->colInd][assm->rowInd];
-
-	return True;
-}
-
-Bool StiffnessMatrix_DiagBCsAsm_RowR( void* stiffMat, Assembler* assm ) {
-	static const double	one = 1.0;
-
-	MatSetValues( ((StiffnessMatrix*)stiffMat)->matrix, 1, (PetscInt*)(&assm->rowEq), 1, (PetscInt*)(&assm->rowEq), (double*)&one, ADD_VALUES );
-
-	return True;
-}
-
-void StiffnessMatrix_AddModifyCallback( StiffnessMatrix* self, void* callback, void* object ) {
-   self->nModifyCBs++;
-   self->modifyCBs = ReallocArray( self->modifyCBs, Callback, self->nModifyCBs );
-   self->modifyCBs[self->nModifyCBs - 1].callback = callback;
-   self->modifyCBs[self->nModifyCBs - 1].object = object;
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/StiffnessMatrix.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/StiffnessMatrix.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,2909 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: StiffnessMatrix.c 1210 2008-08-25 01:17:12Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <mpi.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "FiniteElementContext.h"
+#include "StiffnessMatrix.h"
+#include "StiffnessMatrixTerm.h"
+#include "SystemLinearEquations.h"
+#include "EntryPoint.h"
+#include "SolutionVector.h"
+#include "ForceVector.h"
+#include "Assembler.h"
+
+void __StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context );
+void StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context );
+Bool StiffnessMatrix_ZeroBCsAsm_RowR( void* stiffMat, Assembler* assm );
+Bool StiffnessMatrix_ZeroBCsAsm_ColR( void* stiffMat, Assembler* assm );
+Bool StiffnessMatrix_BCAsm_ColR( void* stiffMat, Assembler* assm );
+Bool StiffnessMatrix_TransBCAsm_ColR( void* stiffMat, Assembler* assm );
+Bool StiffnessMatrix_DiagBCsAsm_RowR( void* stiffMat, Assembler* assm );
+
+
+/* Textual name of this class */
+const Type StiffnessMatrix_Type = "StiffnessMatrix";
+
+/** First part of name for build entry point */
+static const char	StiffnessMatrix_assembleStiffnessMatrixStr[] = "assembleStiffnessMatrix";
+
+
+void* StiffnessMatrix_DefaultNew( Name name )
+{
+	/* Variables set in this function */
+	SizeT                                                               _sizeOfSelf = sizeof(StiffnessMatrix);
+	Type                                                                       type = StiffnessMatrix_Type;
+	Stg_Class_DeleteFunction*                                               _delete = _StiffnessMatrix_Delete;
+	Stg_Class_PrintFunction*                                                 _print = _StiffnessMatrix_Print;
+	Stg_Class_CopyFunction*                                                   _copy = _StiffnessMatrix_Copy;
+	Stg_Component_DefaultConstructorFunction*                   _defaultConstructor = StiffnessMatrix_DefaultNew;
+	Stg_Component_ConstructFunction*                                     _construct = _StiffnessMatrix_AssignFromXML;
+	Stg_Component_BuildFunction*                                             _build = _StiffnessMatrix_Build;
+	Stg_Component_InitialiseFunction*                                   _initialise = _StiffnessMatrix_Initialise;
+	Stg_Component_ExecuteFunction*                                         _execute = _StiffnessMatrix_Execute;
+	Stg_Component_DestroyFunction*                                         _destroy = _StiffnessMatrix_Destroy;
+	Bool                                                                   initFlag = False;
+	StiffnessMatrix_CalculateNonZeroEntriesFunction*       _calculateNonZeroEntries = StiffnessMatrix_CalcNonZeros;
+	void*                                                               rowVariable = NULL;
+	void*                                                            columnVariable = NULL;
+	void*                                                                       rhs = NULL;
+	Stg_Component*                                               applicationDepInfo = NULL;
+	Dimension_Index                                                             dim = 0;
+	Bool                                                                isNonLinear = False;
+	Bool                                              allowZeroElementContributions = False;
+	void*                                                       entryPoint_Register = NULL;
+	MPI_Comm                                                                   comm = 0;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _StiffnessMatrix_New(  STIFFNESSMATRIX_PASSARGS  );
+}
+
+
+StiffnessMatrix* StiffnessMatrix_New(
+	Name                                             name,
+	void*                                            rowVariable,
+	void*                                            columnVariable,
+	void*                                            rhs,
+	Stg_Component*                                   applicationDepInfo,
+	Dimension_Index                                  dim,
+	Bool                                             isNonLinear,
+	Bool                                             allowZeroElementContributions,
+	void*                                            entryPoint_Register,
+	MPI_Comm                                         comm )
+{
+	/* Variables set in this function */
+	SizeT                                                          _sizeOfSelf = sizeof(StiffnessMatrix);
+	Type                                                                  type = StiffnessMatrix_Type;
+	Stg_Class_DeleteFunction*                                          _delete = _StiffnessMatrix_Delete;
+	Stg_Class_PrintFunction*                                            _print = _StiffnessMatrix_Print;
+	Stg_Class_CopyFunction*                                              _copy = _StiffnessMatrix_Copy;
+	Stg_Component_DefaultConstructorFunction*              _defaultConstructor = StiffnessMatrix_DefaultNew;
+	Stg_Component_ConstructFunction*                                _construct = _StiffnessMatrix_AssignFromXML;
+	Stg_Component_BuildFunction*                                        _build = _StiffnessMatrix_Build;
+	Stg_Component_InitialiseFunction*                              _initialise = _StiffnessMatrix_Initialise;
+	Stg_Component_ExecuteFunction*                                    _execute = _StiffnessMatrix_Execute;
+	Stg_Component_DestroyFunction*                                    _destroy = _StiffnessMatrix_Destroy;
+	Bool                                                              initFlag = True;
+	StiffnessMatrix_CalculateNonZeroEntriesFunction*  _calculateNonZeroEntries = StiffnessMatrix_CalcNonZeros;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _StiffnessMatrix_New(  STIFFNESSMATRIX_PASSARGS  );
+}
+
+
+StiffnessMatrix* _StiffnessMatrix_New(  STIFFNESSMATRIX_DEFARGS  )
+{
+	StiffnessMatrix*	self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(StiffnessMatrix) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (StiffnessMatrix*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+	
+	/* General info */
+	
+	/* Virtual functions */
+	self->_calculateNonZeroEntries = _calculateNonZeroEntries;
+	
+	if( initFlag ){
+		_StiffnessMatrix_Init( self, rowVariable, columnVariable, rhs, applicationDepInfo, dim,
+				       isNonLinear, allowZeroElementContributions, entryPoint_Register, comm );
+	}
+	
+	return self;
+}
+
+void _StiffnessMatrix_Init(
+	StiffnessMatrix*                                 self,
+	void*                                            rowVariable,
+	void*                                            columnVariable,
+	void*                                            rhs,
+	Stg_Component*                                   applicationDepInfo,
+	Dimension_Index                                  dim,
+	Bool                                             isNonLinear,
+	Bool                                             allowZeroElementContributions,
+	void*                                            entryPoint_Register,
+	MPI_Comm                                         comm )
+{
+	Stream*		error = Journal_Register( ErrorStream_Type, (Name)self->type  );
+	Stream*		stream;
+
+	/* General and Virtual info should already be set */
+	stream = Journal_Register( Info_Type, (Name)self->type  );
+	Stream_SetPrintingRank( stream, 0 );
+	
+	/* StiffnessMatrix info */
+	self->isConstructed = True;
+	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
+	Journal_Firewall( (rowVariable != NULL), error, "Error: NULL row FeVariable provided to \"%s\" %s.\n", self->name, self->type );
+
+	self->rowVariable = (FeVariable*)rowVariable;
+	Journal_Firewall( (columnVariable != NULL), error, "Error: NULL column FeVariable provided to \"%s\" %s.\n", self->name, self->type );
+
+	self->columnVariable = (FeVariable*)columnVariable;
+	Journal_Firewall( (rhs != NULL), error, "Error: NULL rhs ForceVector provided to \"%s\" %s.\n", self->name, self->type );
+
+	self->rhs = (ForceVector*)rhs;
+	self->applicationDepInfo = applicationDepInfo;
+	self->comm = comm;
+	self->dim = dim;
+	self->isNonLinear = isNonLinear;
+	self->allowZeroElementContributions = allowZeroElementContributions;
+	
+	self->rowLocalSize = 0;
+	self->colLocalSize = 0;
+	self->nonZeroCount = 0;
+	self->diagonalNonZeroCount = 0;
+	self->offDiagonalNonZeroCount = 0;
+	self->diagonalNonZeroIndices = NULL;
+	self->offDiagonalNonZeroIndices = NULL;
+	
+	self->entryPoint_Register = (EntryPoint_Register*)entryPoint_Register;
+
+	Stg_asprintf( &self->_assembleStiffnessMatrixEPName, "%s-%s", self->name, StiffnessMatrix_assembleStiffnessMatrixStr );
+	self->assembleStiffnessMatrix = FeEntryPoint_New( self->_assembleStiffnessMatrixEPName, FeEntryPoint_AssembleStiffnessMatrix_CastType );
+
+	EntryPoint_Register_Add( self->entryPoint_Register, self->assembleStiffnessMatrix );
+
+	self->stiffnessMatrixTermList = Stg_ObjectList_New();
+
+	/* Set default function for Global Stiffness Matrix Assembly */
+	EP_ReplaceAll( self->assembleStiffnessMatrix, __StiffnessMatrix_NewAssemble );
+
+	/* We need some assembler contexts. */
+	self->zeroBCsAsm = Assembler_New();
+	self->bcAsm = Assembler_New();
+	self->transBCAsm = Assembler_New();
+
+	if( rowVariable == columnVariable )
+		self->diagBCsAsm = Assembler_New();
+
+	self->elStiffMat = NULL;
+	self->bcVals = NULL;
+	self->nRowDofs = 0;
+	self->nColDofs = 0;
+	self->transRHS = NULL;
+
+	self->rowInc = IArray_New();
+	self->colInc = IArray_New();
+
+	self->nModifyCBs = 0;
+	self->modifyCBs = NULL;
+
+	self->matrix = PETSC_NULL;
+	/* self->shellMatrix = NULL; */
+	/* self->useShellMatrix = False; */
+}
+
+void _StiffnessMatrix_Delete( void* stiffnessMatrix ) {
+	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
+	/* Stg_Class_Delete parent*/
+	_Stg_Component_Delete( self );
+	
+}
+
+void _StiffnessMatrix_Print( void* stiffnessMatrix, Stream* stream ) {
+	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
+	
+	/* Set the Journal for printing informations */
+	Stream* stiffnessMatrixStream = stream;
+	
+	/* General info */
+	Journal_Printf( stiffnessMatrixStream, "StiffnessMatrix (ptr): %p\n", self );
+	
+	/* Print parent */
+	_Stg_Component_Print( self, stiffnessMatrixStream );
+	
+	/* Virtual info */
+	Journal_Printf( stiffnessMatrixStream, "\t_build (func ptr): %p\n", self->_build );
+	
+	Journal_Printf( stiffnessMatrixStream, "\tassembleStiffnessMatrix e.p. (ptr): %p\n", self->assembleStiffnessMatrix );
+	EntryPoint_PrintConcise( self->assembleStiffnessMatrix, stream );
+	
+	/* StiffnessMatrix info */
+	Journal_Printf( stiffnessMatrixStream, "\trowVariable (ptr): %p\n", self->rowVariable );
+	Journal_Printf( stiffnessMatrixStream, "\t\tvariable name: %s\n", self->rowVariable->name );
+	Journal_Printf( stiffnessMatrixStream, "\tcolumnVariable (ptr): %p\n", self->columnVariable );
+	Journal_Printf( stiffnessMatrixStream, "\t\tvariable name: %s\n", self->columnVariable->name );
+	Journal_Printf( stiffnessMatrixStream, "\tMatrix (ptr): %p\n", self->matrix );
+	Journal_Printf( stiffnessMatrixStream, "\tComm: %u\n", self->comm );
+	Journal_Printf( stiffnessMatrixStream, "\trowLocalSize: %u\n", self->rowLocalSize );
+	Journal_Printf( stiffnessMatrixStream, "\tcolLocalSize: %u\n", self->colLocalSize );
+	Journal_Printf( stiffnessMatrixStream, "\tnonZeroCount: %u\n", self->nonZeroCount );
+	Journal_Printf( stiffnessMatrixStream, "\tisNonLinear: %s\n", StG_BoolToStringMap[self->isNonLinear] );
+	Journal_Printf( stiffnessMatrixStream, "\tallowZeroElementContributions: %s\n", StG_BoolToStringMap[self->allowZeroElementContributions] );
+}
+
+void* _StiffnessMatrix_Copy( const void* stiffnessMatrix, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	StiffnessMatrix*	self = (StiffnessMatrix*)stiffnessMatrix;
+	StiffnessMatrix*	newStiffnessMatrix;
+	PtrMap*			map = ptrMap;
+	Bool			ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newStiffnessMatrix = (StiffnessMatrix*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
+	
+	/* Virtual functions */
+	newStiffnessMatrix->_calculateNonZeroEntries = self->_calculateNonZeroEntries;
+	
+	/* TODO: copy matrix */
+	newStiffnessMatrix->matrix = self->matrix;
+/* 	newStiffnessMatrix->shellMatrix = self->shellMatrix; */
+	newStiffnessMatrix->entryPoint_Register = self->entryPoint_Register;
+	newStiffnessMatrix->comm = self->comm;
+	newStiffnessMatrix->rowLocalSize = self->rowLocalSize;
+	newStiffnessMatrix->colLocalSize = self->colLocalSize;
+	newStiffnessMatrix->dim = self->dim;
+	newStiffnessMatrix->nonZeroCount = self->nonZeroCount;
+	newStiffnessMatrix->diagonalNonZeroCount = self->diagonalNonZeroCount;
+	newStiffnessMatrix->offDiagonalNonZeroCount = self->offDiagonalNonZeroCount;
+	
+	if( deep ) {
+		newStiffnessMatrix->debug = (Stream*)Stg_Class_Copy( self->debug, NULL, deep, nameExt, map );
+		newStiffnessMatrix->rowVariable = (FeVariable*)Stg_Class_Copy( self->rowVariable, NULL, deep, nameExt, map );
+		newStiffnessMatrix->columnVariable = (FeVariable*)Stg_Class_Copy( self->columnVariable, NULL, deep, nameExt, map );
+		newStiffnessMatrix->rhs =(ForceVector*)Stg_Class_Copy( self->rhs, NULL, deep, nameExt, map );
+		newStiffnessMatrix->assembleStiffnessMatrix = (FeEntryPoint*)Stg_Class_Copy( self->assembleStiffnessMatrix, NULL, deep, nameExt, map );
+		
+		if( self->_assembleStiffnessMatrixEPName ) {
+			if( nameExt ) {
+				Stg_asprintf( &newStiffnessMatrix->_assembleStiffnessMatrixEPName, "%s%s", 
+					      self->_assembleStiffnessMatrixEPName, nameExt );
+			}
+			else {
+				newStiffnessMatrix->_assembleStiffnessMatrixEPName = StG_Strdup( self->_assembleStiffnessMatrixEPName );
+			}
+		}
+		else {
+			newStiffnessMatrix->_assembleStiffnessMatrixEPName = NULL;
+		}
+		
+		/* Arrays */
+		if( (newStiffnessMatrix->diagonalNonZeroIndices = (Index*)PtrMap_Find( map, self->diagonalNonZeroIndices )) == NULL ) {
+			if( self->diagonalNonZeroIndices ) {
+				newStiffnessMatrix->diagonalNonZeroIndices = Memory_Alloc_Array( Index, 
+												 newStiffnessMatrix->rowLocalSize, "diagonalNonZeroIndices" );
+				memcpy( newStiffnessMatrix->diagonalNonZeroIndices, self->diagonalNonZeroIndices, 
+					newStiffnessMatrix->rowLocalSize * sizeof( Index ) );
+				PtrMap_Append( map, self->diagonalNonZeroIndices, newStiffnessMatrix->diagonalNonZeroIndices );
+			}
+			else {
+				newStiffnessMatrix->diagonalNonZeroIndices = NULL;
+			}
+		}
+		
+		if( (newStiffnessMatrix->offDiagonalNonZeroIndices = (Index*)PtrMap_Find( map, self->offDiagonalNonZeroIndices )) == NULL ) {
+			if( self->offDiagonalNonZeroIndices ) {
+				newStiffnessMatrix->offDiagonalNonZeroIndices = Memory_Alloc_Array( Index, 
+												    newStiffnessMatrix->rowLocalSize, "diagonalNonZeroIndices" );
+				memcpy( newStiffnessMatrix->offDiagonalNonZeroIndices, self->offDiagonalNonZeroIndices, 
+					newStiffnessMatrix->rowLocalSize * sizeof( Index ) );
+				PtrMap_Append( map, self->offDiagonalNonZeroIndices, newStiffnessMatrix->offDiagonalNonZeroIndices );
+			}
+			else {
+				newStiffnessMatrix->offDiagonalNonZeroIndices = NULL;
+			}
+		}
+	}
+	else {
+		newStiffnessMatrix->debug = self->debug;
+		newStiffnessMatrix->rowVariable = self->rowVariable;
+		newStiffnessMatrix->columnVariable = self->columnVariable;
+		newStiffnessMatrix->rhs = self->rhs;
+		newStiffnessMatrix->diagonalNonZeroIndices = self->diagonalNonZeroIndices;
+		newStiffnessMatrix->offDiagonalNonZeroIndices = self->offDiagonalNonZeroIndices;
+	}
+	
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+	
+	return (void*)newStiffnessMatrix;
+}
+
+void _StiffnessMatrix_AssignFromXML( void* stiffnessMatrix, Stg_ComponentFactory* cf, void* data ) {
+	StiffnessMatrix* self               = (StiffnessMatrix*)stiffnessMatrix;
+	Stream*		 stream;
+	FeVariable*      rowVar             = NULL;
+	FeVariable*      colVar             = NULL;
+	ForceVector*     fVector            = NULL;
+	Stg_Component*   applicationDepInfo = NULL;
+	void*            entryPointRegister = NULL;
+	Dimension_Index  dim                = 0;
+	Bool             isNonLinear;
+	Bool             allowZeroElementContributions;
+	
+	self->context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
+	if( !self->context  )
+		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
+
+	rowVar             = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"RowVariable", FeVariable, True, data  );
+	colVar             = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ColumnVariable", FeVariable, True, data  );
+	fVector            = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"RHS", ForceVector, False, data  );
+	applicationDepInfo = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ApplicationDepInfo", Stg_Component, False, data);
+	
+	entryPointRegister = self->context->entryPoint_Register; 
+	assert( entryPointRegister  );
+	
+	dim = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"dim", 0 );
+	assert( dim  );
+
+	isNonLinear = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"isNonLinear", False  );
+
+	/* Default is to allow zero element contributions - to allow backward compatibility */
+	allowZeroElementContributions = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"allowZeroElementContributions", True  );
+
+	_StiffnessMatrix_Init( 
+		self, 
+		rowVar, 
+		colVar, 
+		fVector, 
+		applicationDepInfo, 
+		dim,
+		isNonLinear,
+		allowZeroElementContributions,
+		entryPointRegister, 
+		0 );
+
+	/* Do we need to use the transpose? */
+	self->transRHS = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"transposeRHS", ForceVector, False, data  );
+
+	/* Read the matrix type from the dictionary. */
+/* 	self->shellMatrix = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"matrix", PETScShellMatrix, False, data ); */
+/* 	if( !self->shellMatrix  ) { */
+/* 		self->useShellMatrix = False; */
+/* 	} */
+/* 	else { */
+/* 		EP_ReplaceAll( self->assembleStiffnessMatrix, StiffnessMatrix_ShellAssembly ); */
+
+/* 		self->useShellMatrix = True; */
+/* 	} */
+
+	/* Setup the stream. */
+	stream = Journal_Register( Info_Type, (Name)self->type  );
+	if( Dictionary_GetBool_WithDefault( cf->rootDict, (Dictionary_Entry_Key)"watchAll", False ) == True  )
+		Stream_SetPrintingRank( stream, STREAM_ALL_RANKS );
+	else {
+		unsigned	rankToWatch;
+
+		rankToWatch = Dictionary_GetUnsignedInt_WithDefault( cf->rootDict, "rankToWatch", 0 );
+		Stream_SetPrintingRank( stream, rankToWatch );
+	}
+}
+
+void _StiffnessMatrix_Build( void* stiffnessMatrix, void* data ) {
+	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
+
+	Journal_DPrintf( self->debug, "In %s - for matrix %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	/* ensure variables are built */
+	if( self->rowVariable )
+		Stg_Component_Build( self->rowVariable, data, False );
+
+	/* If we don't have a communicator, grab one off the mesh. */
+	if( !self->comm ) {
+		self->comm = Mesh_GetCommTopology( self->rowVariable->feMesh, MT_VERTEX )->mpiComm;
+		Journal_Firewall( (self->comm != 0), self->debug, "Error: NULL Comm provided to \"%s\" %s.\n",
+				  self->name, self->type );
+	}
+	
+	if( self->columnVariable )
+		Stg_Component_Build( self->columnVariable, data, False );
+
+   /* ensure the rhs vector is built */
+   Stg_Component_Build( self->rhs, data, False );
+
+	
+/* 	if( self->useShellMatrix ) */
+/* 		Stg_Component_Build( self->shellMatrix, data, False ); */
+	
+#if DEBUG
+	if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+		Journal_DPrintf( self->debug, "Row variable(%s) I.D. array calc. as:\n", self->rowVariable->name );
+		FeEquationNumber_PrintDestinationArray( self->rowVariable->eqNum, self->debug );
+		Journal_DPrintf( self->debug, "Column variable(%s) I.D. array calc. as:\n", self->columnVariable->name );
+		FeEquationNumber_PrintDestinationArray( self->columnVariable->eqNum, self->debug );
+	}
+#endif
+	
+	/* update the row and column sizes for the variables */	
+	self->rowLocalSize = self->rowVariable->eqNum->localEqNumsOwnedCount;
+	assert( self->rowLocalSize );
+	self->colLocalSize = self->columnVariable->eqNum->localEqNumsOwnedCount;
+	assert( self->colLocalSize );
+	
+	/* update the number of non zero entries from the finite element variables */
+	StiffnessMatrix_CalcNonZeros( self );
+	
+	Journal_DPrintf( self->debug, "row(%s) localSize = %d : col(%s) localSize = %d \n", self->rowVariable->name,
+		self->rowLocalSize, self->columnVariable->name, self->colLocalSize );
+	
+	/* assert( self->nonZeroCount ); */
+
+	StiffnessMatrix_RefreshMatrix( self );
+
+	Journal_DPrintf( self->debug, "Matrix allocated.\n" );
+
+	Assembler_SetVariables( self->zeroBCsAsm, self->rowVariable, self->columnVariable );
+	Assembler_SetCallbacks( self->zeroBCsAsm, NULL, StiffnessMatrix_ZeroBCsAsm_RowR, NULL, 
+		StiffnessMatrix_ZeroBCsAsm_ColR, NULL, 
+		self );
+	Assembler_SetVariables( self->bcAsm, self->rowVariable, self->columnVariable );
+	Assembler_SetCallbacks( self->bcAsm, 
+		NULL, 
+		NULL, NULL, 
+		StiffnessMatrix_BCAsm_ColR, NULL, 
+		self );
+	Assembler_SetVariables( self->transBCAsm, self->columnVariable, self->rowVariable );
+	Assembler_SetCallbacks( self->transBCAsm, 
+		NULL, 
+		NULL, NULL, 
+		StiffnessMatrix_TransBCAsm_ColR, NULL, 
+		self );
+	if( self->rowVariable == self->columnVariable ) {
+		Assembler_SetVariables( self->diagBCsAsm, self->rowVariable, self->columnVariable );
+		Assembler_SetCallbacks( self->diagBCsAsm, 
+			NULL, 
+			StiffnessMatrix_DiagBCsAsm_RowR, NULL, 
+			NULL, NULL, 
+			self );
+	}
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _StiffnessMatrix_Initialise( void* stiffnessMatrix, void* data ) {
+	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
+	
+	Journal_DPrintf( self->debug, "In %s - for matrix %s\n", __func__, self->name );
+	/* ensure variables are initialised */
+	if( self->rowVariable )
+		Stg_Component_Initialise( self->rowVariable, data, False );
+	
+	if( self->columnVariable )
+		Stg_Component_Initialise( self->columnVariable, data, False );
+
+   /* ensure the rhs vector is built */
+   Stg_Component_Initialise( self->rhs, data, False );
+
+/* 	if( self->useShellMatrix ) */
+/* 		Stg_Component_Initialise( self->shellMatrix, data, False ); */
+}
+
+
+void _StiffnessMatrix_Execute( void* stiffnessMatrix, void* data ) {
+}
+
+void _StiffnessMatrix_Destroy( void* stiffnessMatrix, void* data ) {
+	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
+	
+	Journal_DPrintf( self->debug, "In %s - for matrix %s\n", __func__, self->name );
+	MatDestroy( self->matrix );
+	FreeObject( self->stiffnessMatrixTermList );
+	FreeArray( self->_assembleStiffnessMatrixEPName );
+	FreeArray( self->diagonalNonZeroIndices );
+	FreeArray( self->offDiagonalNonZeroIndices );
+	FreeObject( self->zeroBCsAsm );
+	FreeObject( self->bcAsm );
+	FreeObject( self->transBCAsm );
+	FreeObject( self->diagBCsAsm );
+	/* Don't delete entry points: E.P. register will delete them automatically */
+	NewClass_Delete( self->rowInc );
+	NewClass_Delete( self->colInc );
+
+
+}
+
+void StiffnessMatrix_CalculateNonZeroEntries( void* stiffnessMatrix ) {
+	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
+	
+	self->_calculateNonZeroEntries( self );
+}
+
+void _StiffnessMatrix_CalculateNonZeroEntries( void* stiffnessMatrix ) {
+	StiffnessMatrix*		self = (StiffnessMatrix*)stiffnessMatrix;
+	FeMesh*					rFeMesh = self->rowVariable->feMesh;
+	FeMesh*					cFeMesh = self->columnVariable->feMesh;
+	Dof_EquationNumber	currMatrixRow = 0;
+	Node_LocalIndex		rowNode_lI = 0;
+	Index						activeEqsAtCurrRowNodeCount = 0;
+#ifdef DEBUG
+	unsigned int			totalNonZeroEntries = 0;
+#endif
+
+	Journal_DPrintf( self->debug, "In %s - for matrix %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	assert ( self->rowVariable );
+	assert ( self->columnVariable );
+
+	Journal_DPrintfL( self->debug, 1, "row nodeLocalCount %d\n", FeMesh_GetNodeLocalSize( rFeMesh ) );
+	Journal_DPrintfL( self->debug, 1, "column nodeLocalCount %d\n", FeMesh_GetNodeLocalSize( cFeMesh ) );
+	
+	self->diagonalNonZeroIndices = Memory_Alloc_Array  ( Index, self->rowLocalSize, "diagonalNonZeroIndices" );
+	self->offDiagonalNonZeroIndices = Memory_Alloc_Array  ( Index, self->rowLocalSize, "offDiagonalNonZeroIndices" );
+	for ( rowNode_lI = 0; rowNode_lI < self->rowLocalSize; rowNode_lI++ ) { 
+		self->diagonalNonZeroIndices[rowNode_lI] = 0;
+		self->offDiagonalNonZeroIndices[rowNode_lI] = 0;
+	}
+
+	for( rowNode_lI = 0; rowNode_lI < FeMesh_GetNodeLocalSize( rFeMesh ); rowNode_lI++ ) { 
+		_StiffnessMatrix_CalcAndUpdateNonZeroEntriesAtRowNode( self, rowNode_lI, currMatrixRow, activeEqsAtCurrRowNodeCount );
+	}
+
+#ifdef DEBUG
+	for ( rowNode_lI = 0; rowNode_lI < self->rowLocalSize; rowNode_lI++ ) { 
+		totalNonZeroEntries += self->diagonalNonZeroIndices[rowNode_lI];
+		totalNonZeroEntries += self->offDiagonalNonZeroIndices[rowNode_lI];
+	}	
+
+	Journal_DPrintfL( self->debug, 1, "Calculated %d non-zero entries in Matrix (results in %d bytes storage)\n",
+			  totalNonZeroEntries, totalNonZeroEntries * sizeof(double) );
+#endif	
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _StiffnessMatrix_CalcAndUpdateNonZeroEntriesAtRowNode(
+	StiffnessMatrix*	self,
+	Node_LocalIndex		rowNode_lI,
+	Dof_EquationNumber	currMatrixRow,
+	Index			activeEqsAtCurrRowNode )
+{
+	FeMesh*			rFeMesh = self->rowVariable->feMesh;
+	FeMesh*			cFeMesh = self->columnVariable->feMesh;
+	DofLayout*		colDofLayout = self->columnVariable->dofLayout;
+	FeEquationNumber*	rowEqNum = self->rowVariable->eqNum;
+	FeEquationNumber*	colEqNum = self->columnVariable->eqNum;
+	Element_Index		rowNodeElement_I = 0;
+	Element_DomainIndex	element_dI = 0;
+	Node_DomainIndex	colNode_dI = 0;
+	Dof_Index		colNodeDof_I = 0;
+	Index*			countTableToAdjust = 0;
+	Dof_EquationNumber	currColEqNum = 0;
+	Node_DomainIndex*	uniqueRelatedColNodes = NULL;
+	Node_Index		uniqueRelatedColNodesCount = 0;
+	Node_Index		uniqueRelatedColNodes_AllocCount = 0;
+	Node_Index		uniqueRelatedColNode_I = 0;
+	Dof_Index		currNodeDof_I = 0;
+	Dof_EquationNumber	currDofMatrixRow = 0;
+	unsigned		nNodeInc, *nodeInc;
+
+	Journal_DPrintfL( self->debug, 3, "In %s - for row local node %d\n", __func__, rowNode_lI );
+	Stream_Indent( self->debug );
+
+	FeMesh_GetNodeElements( rFeMesh, rowNode_lI, self->rowInc );
+	nNodeInc = IArray_GetSize( self->rowInc );
+	nodeInc = (unsigned*)IArray_GetPtr( self->rowInc );
+	for ( rowNodeElement_I = 0; rowNodeElement_I < nNodeInc; rowNodeElement_I++ ) {
+		unsigned	nElInc;
+
+		/* note the dI (domain index) - some of these elements may be in shadow space */
+		element_dI = nodeInc[rowNodeElement_I];
+
+		nElInc = FeMesh_GetElementNodeSize( cFeMesh, element_dI );
+		uniqueRelatedColNodes_AllocCount += nElInc;
+	}
+	
+	Journal_DPrintfL( self->debug, 3, "Calculated the max possible number of unique related nodes as %d\n",
+			  uniqueRelatedColNodes_AllocCount );
+	uniqueRelatedColNodes = Memory_Alloc_Array( Node_DomainIndex, uniqueRelatedColNodes_AllocCount, "uniqueRelatedColNodes" );
+
+	_StiffnessMatrix_CalculatedListOfUniqueRelatedColNodes( self, rowNode_lI, uniqueRelatedColNodes, &uniqueRelatedColNodesCount);
+	
+	Journal_DPrintfL( self->debug, 3, "Searching the %d unique related col nodes for active dofs\n",
+			  uniqueRelatedColNodesCount );
+	Stream_Indent( self->debug );
+	for ( uniqueRelatedColNode_I = 0; uniqueRelatedColNode_I < uniqueRelatedColNodesCount; uniqueRelatedColNode_I++ ) {
+		colNode_dI = uniqueRelatedColNodes[uniqueRelatedColNode_I];
+
+		Journal_DPrintfL( self->debug, 3, "col node_dI %d: has %d dofs\n", colNode_dI, colDofLayout->dofCounts[colNode_dI] );
+		Stream_Indent( self->debug );
+		for ( colNodeDof_I = 0; colNodeDof_I < colDofLayout->dofCounts[colNode_dI]; colNodeDof_I++ ) {
+
+			currColEqNum = colEqNum->destinationArray[colNode_dI][colNodeDof_I];
+			Journal_DPrintfL( self->debug, 3, "dof %d: ", colNodeDof_I );
+			if ( currColEqNum == -1 ) {
+				Journal_DPrintfL( self->debug, 3, "is a BC.\n" );
+			}
+			else {
+				if( STreeMap_HasKey( colEqNum->ownedMap, &currColEqNum ) ) {
+					Journal_DPrintfL( self->debug, 3, "is diagonal (eq %d)\n", currColEqNum );
+					countTableToAdjust = self->diagonalNonZeroIndices;
+				}
+				else {
+					Journal_DPrintfL( self->debug, 3, "is off-diagonal (eq %d)\n", currColEqNum );
+					countTableToAdjust = self->offDiagonalNonZeroIndices;
+				}
+
+				for ( currNodeDof_I = 0; currNodeDof_I < self->rowVariable->dofLayout->dofCounts[rowNode_lI]; currNodeDof_I++) {
+					if ( -1 != rowEqNum->destinationArray[rowNode_lI][currNodeDof_I] ) {
+						currDofMatrixRow = *(int*)STreeMap_Map(
+							rowEqNum->ownedMap,
+							rowEqNum->destinationArray[rowNode_lI] + currNodeDof_I );
+
+						/* Because of periodic BCs, the eq num may be lower than the normal
+						 * lowest held on this processor, so we need to check this */
+						if ( currDofMatrixRow >= self->rowLocalSize ) {	
+							Journal_DPrintfL( self->debug, 3, "Found currDofMatRow(=%d) >= self->rowLocalSize(=%d) : for "
+									  "rowNode_lI=%d, currMatRow=%d, colNode_dI=%d, colNodeDof_I = %d, "
+									  "currNodeDof_I = %d\n", currDofMatrixRow,
+									  self->rowLocalSize, rowNode_lI, currMatrixRow,
+									  colNode_dI, colNodeDof_I, currNodeDof_I ); 
+						}		
+						else if ( currDofMatrixRow < 0 ) {	
+							Journal_DPrintfL( self->debug, 3, "Found currDofMatRow(=%d) < 0 : for "
+									  "rowNode_lI=%d, currMatRow=%d, colNode_dI=%d, colNodeDof_I = %d, "
+									  "currNodeDof_I = %d\n", currDofMatrixRow,
+									  rowNode_lI, currMatrixRow,
+									  colNode_dI, colNodeDof_I, currNodeDof_I ); 
+						}		
+						else {	
+							Journal_DPrintfL( self->debug, 3, "(incrementing app. count at row %d)\n",
+									  currDofMatrixRow );
+
+							countTableToAdjust[ currDofMatrixRow ] += 1;
+						}
+					}
+				}
+			}	
+		}	
+		Stream_UnIndent( self->debug );
+	}		
+	Stream_UnIndent( self->debug );
+
+	Journal_DPrintfL( self->debug, 3, "diagonal count\t%d off diagonal count\t%d\n", 
+			  self->diagonalNonZeroIndices[currMatrixRow], self->offDiagonalNonZeroIndices[currMatrixRow]);
+
+	Memory_Free( uniqueRelatedColNodes );
+
+/* 	 TODO: do we need to check that diag is set to at least 1, as the PETSc webpage on MatCreate_MPIAIJ suggests? */
+
+	Stream_UnIndent( self->debug );
+}			
+
+
+void _StiffnessMatrix_CalculatedListOfUniqueRelatedColNodes(
+	StiffnessMatrix*	self,
+	Node_LocalIndex		rowNode_lI,
+	Node_DomainIndex*	uniqueRelatedColNodes,
+	Node_Index*		uniqueRelatedColNodesCountPtr )
+{
+	FeMesh*			rFeMesh = self->rowVariable->feMesh;
+	FeMesh*			cFeMesh = self->columnVariable->feMesh;
+	Element_Index		rowNodeElement_I = 0;
+	Element_DomainIndex	element_dI = 0;
+	Node_Index		colElLocalNode_I = 0;
+	Node_DomainIndex	colNode_dI = 0;
+	Node_Index		uniqueRelatedColNode_I = 0;
+	unsigned		nNodeInc, *nodeInc;
+
+	FeMesh_GetNodeElements( rFeMesh, rowNode_lI, self->rowInc );
+	nNodeInc = IArray_GetSize( self->rowInc );
+	nodeInc = (unsigned*)IArray_GetPtr( self->rowInc );
+	Journal_DPrintfL( self->debug, 3, "Searching the %d elements this node belongs to for unique related col nodes:\n",
+			  nNodeInc );
+	
+	Stream_Indent( self->debug );
+	for ( rowNodeElement_I = 0; rowNodeElement_I < nNodeInc; rowNodeElement_I++ ) {
+		unsigned	nElInc, *elInc;
+
+		/* note the dI (domain index) - some of these elements may be in shadow space */
+		element_dI = nodeInc[rowNodeElement_I];
+
+		Journal_DPrintfL( self->debug, 3, "rowNodeElement_I: ", rowNodeElement_I );
+		Journal_DPrintfL( self->debug, 3, "domain element %d\n", element_dI );
+		
+		Stream_Indent( self->debug );
+		FeMesh_GetElementNodes( cFeMesh, element_dI, self->colInc );
+		nElInc = IArray_GetSize( self->colInc );
+		elInc = (unsigned*)IArray_GetPtr( self->colInc );
+		Journal_DPrintfL( self->debug, 3, "Searching the %d column var nodes in this el:\n", nElInc );
+		for ( colElLocalNode_I =0; colElLocalNode_I < nElInc; colElLocalNode_I++ ) {
+			colNode_dI = elInc[colElLocalNode_I];
+			
+			Journal_DPrintfL( self->debug, 3, "Col domain node %d: ", colNode_dI );
+			for ( uniqueRelatedColNode_I = 0; uniqueRelatedColNode_I < (*uniqueRelatedColNodesCountPtr); uniqueRelatedColNode_I++ )
+			{
+				if ( colNode_dI == uniqueRelatedColNodes[uniqueRelatedColNode_I] ) {
+					Journal_DPrintfL( self->debug, 3, "already in list -> skip to next.\n" );
+					break;
+				}
+			}
+			if ( uniqueRelatedColNode_I == (*uniqueRelatedColNodesCountPtr) ) {
+				Journal_DPrintfL( self->debug, 3, "is unique so far -> add to list.\n" );
+				uniqueRelatedColNodes[uniqueRelatedColNode_I] = colNode_dI;
+				(*uniqueRelatedColNodesCountPtr)++;
+			}
+		}
+		Stream_UnIndent( self->debug );
+	}
+	Stream_UnIndent( self->debug );
+}
+
+
+void StiffnessMatrix_Assemble( void* stiffnessMatrix, Bool bcRemoveQuery, void* _sle, void* _context ) {
+	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
+        int ii;
+
+	StiffnessMatrix_RefreshMatrix( self );
+
+	Journal_DPrintf( self->debug, "In %s - for matrix \"%s\" - calling the \"%s\" E.P.\n", __func__, self->name,
+			 self->assembleStiffnessMatrix->name );
+	/* Call the Entry point directly from the base class */
+	/* Note that it may be empty: this is deliberate. */
+	((FeEntryPoint_AssembleStiffnessMatrix_CallFunction*)EntryPoint_GetRun( self->assembleStiffnessMatrix ))(
+		self->assembleStiffnessMatrix,
+		self,
+		bcRemoveQuery,
+		_sle,
+		_context );
+
+        /* Run all the modify callbacks. */
+        for( ii = 0; ii < self->nModifyCBs; ii++ ) {
+           void* callback = self->modifyCBs[ii].callback;
+           void* object = self->modifyCBs[ii].object;
+           ((void(*)(void*))callback)( object );
+        }
+}
+
+
+void StiffnessMatrix_GlobalAssembly_General( void* stiffnessMatrix, Bool bcRemoveQuery, void* _sle, void* _context )
+{
+	StiffnessMatrix*        self = (StiffnessMatrix*)stiffnessMatrix;
+	SystemLinearEquations*  sle  = (SystemLinearEquations*)_sle;
+	FiniteElementContext*   context  = (FiniteElementContext*)_context;
+	
+	FeVariable*             feVars[MAX_FE_VARS]; /* Set later */
+	Index                   numFeVars = 2;
+	Index                   feVar_I;
+
+	/* Location Matrix for a single element - may be a ptr into full LM array */
+	Dof_EquationNumber**    elementLM[MAX_FE_VARS];
+	/* Number of dofs at an element: required for matrix assembly */
+	Dof_Index*              totalDofsThisElement[MAX_FE_VARS];
+	Dof_Index*              totalDofsPrevElement[MAX_FE_VARS];
+	/* The actual element stiffness matrix values, per element: filled in by this class's entry point */
+	double**                elStiffMatToAdd = NULL;
+
+	/* counts and indices used in building per-element locationMatrix and BC info */
+	Element_LocalIndex      nLocalElements;
+	Element_LocalIndex      element_lI;
+	Node_ElementLocalIndex	nodeCountThisEl;
+	/* Shortcut to node IDs at a particular element */
+	Element_Nodes           nodeIdsThisEl;
+
+	/* related to correction of BCs */
+	Bool                    makeBC_Corrections_row = False;
+	Bool                    modifiedRHS_Vec_cont = False;
+	Dof_Index*              bcLM_Id[ MAX_FE_VARS ] = { NULL, NULL };
+	double*                 bcValues[ MAX_FE_VARS ] = { NULL, NULL };
+	int                     nBC_NodalDof[ MAX_FE_VARS ] = { 0, 0 };
+	double*                 h2Add = NULL;
+	
+	/* For output printing */
+	double                  outputPercentage      = 10;	/* Controls how often to give a status update of assembly progress*/
+	int                     outputInterval;
+	double                  startTime, totalTime;
+	double                  matAddingStart;
+	double                  matAddingTime         = 0;
+	double                  elStiffMatBuildStart;
+	double                  elStiffMatBuildTime   = 0;
+	Bool			updateRHS;
+	MPI_Comm		comm;
+
+/* 	Mat			matrix		      = ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
+	Mat                     matrix = self->matrix;
+
+	/* Do some type checking */
+	assert( !sle || Stg_CheckType( sle, SystemLinearEquations ) );
+	assert( self->rhs || self->transRHS );
+
+	feVars[0] = self->rowVariable;
+	feVars[1] = self->columnVariable;
+
+	/* Get communicator. */
+	comm = Mesh_GetCommTopology( feVars[0]->feMesh, MT_VERTEX )->mpiComm;
+	
+	startTime = MPI_Wtime();
+
+	Journal_DPrintf( self->debug, "In %s - for matrix \"%s\"\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	Journal_Firewall( Stg_ObjectList_Count( self->stiffnessMatrixTermList ) != 0,
+			  Journal_Register( Error_Type, (Name)self->type ),
+			  "Error in func %s for %s '%s' - No StiffnessMatrixTerms registered.\n", 
+			  __func__, self->type, self->name );
+
+	totalDofsThisElement[ROW_VAR] = Memory_Alloc( Dof_Index, "el nodal dofs" );
+	totalDofsPrevElement[ROW_VAR] = Memory_Alloc( Dof_Index, "el nodal dofs (prev element)" );
+	*totalDofsPrevElement[ROW_VAR] = 0;
+	/* check if row variable and col variable are the same */
+	if ( self->rowVariable == self->columnVariable ) {
+		numFeVars = 1;
+		Journal_DPrintfL( self->debug, 2, "Detected both row and column FeVariable to assemble over are \"%s\", "
+				  "so only processing once per element.\n", self->rowVariable->name );
+		/* since Row and Col FeVars are same, set LM_col and totalDofsThisElement to be same as row ones */
+		totalDofsThisElement[COL_VAR] = totalDofsThisElement[ROW_VAR];	
+		totalDofsPrevElement[COL_VAR] = totalDofsPrevElement[ROW_VAR];	
+	}
+	else {
+		Journal_DPrintfL( self->debug, 2, "Since row FeVariable \"%s\" and column FeVariable \"%s\" to assemble over "
+				  "are different, processing both per element.\n", self->rowVariable->name, self->columnVariable->name );
+		totalDofsThisElement[COL_VAR] = Memory_Alloc( Dof_Index, "el nodal dofs (col)" );
+		totalDofsPrevElement[COL_VAR] = Memory_Alloc( Dof_Index, "el nodal dofs (col) (prev element)" );
+		*totalDofsPrevElement[COL_VAR] = 0;
+	}
+	
+	/* Assumes that both row and col variables have same number of variables */
+	nLocalElements = FeMesh_GetElementLocalSize( feVars[ROW_VAR]->feMesh );
+	
+	/* Initialise matrix */
+	MatZeroEntries( matrix );
+
+	outputInterval = (int)( (outputPercentage/100.0)*(double)(nLocalElements) );
+	if( outputInterval == 0 ) { outputInterval = nLocalElements; }
+
+	for( element_lI = 0; element_lI < nLocalElements; element_lI++ ) {  
+		
+		/* This loop is how we handle the possiblity of different row-column variables: if both variables are
+		 * the same, then numFeVars is set to 1 and the loop only progresses through once.
+		 -- PatrickSunter 13 September 2004 */
+		for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
+			FeEquationNumber* 		feEqNum = feVars[feVar_I]->eqNum;
+			DofLayout*			dofLayout = feVars[feVar_I]->dofLayout;
+			Dof_Index			dofCountLastNode;
+			unsigned			nDofsThisEl;
+			unsigned			n_i;
+
+			/* Get the local node ids */
+			FeMesh_GetElementNodes( feVars[feVar_I]->feMesh, element_lI, 
+						self->rowInc );
+			nodeCountThisEl = IArray_GetSize( self->rowInc );
+			nodeIdsThisEl = (unsigned*)IArray_GetPtr( self->rowInc );
+
+			/* Set value of elementLM: will automatically use large one if built */
+			elementLM[feVar_I] = FeEquationNumber_BuildOneElementLocationMatrix( feEqNum, element_lI );
+
+			/* work out number of dofs at the node, based on LM */
+			dofCountLastNode = dofLayout->dofCounts[nodeIdsThisEl[nodeCountThisEl-1]];
+			nDofsThisEl = dofLayout->dofCounts[nodeIdsThisEl[0]];
+			for( n_i = 1; n_i < nodeCountThisEl; n_i++ )
+				nDofsThisEl += dofLayout->dofCounts[nodeIdsThisEl[n_i]];
+			*totalDofsThisElement[feVar_I] = nDofsThisEl;
+/*
+ *totalDofsThisElement[feVar_I] = &elementLM[feVar_I][nodeCountThisEl-1][dofCountLastNode-1]
+ - &elementLM[feVar_I][0][0] + 1;
+*/
+
+			if ( *totalDofsThisElement[feVar_I] > *totalDofsPrevElement[feVar_I] ) {
+				Journal_DPrintfL( self->debug, 2, "Reallocating bcLM_Id and bcValues for fe var \"%s\" "
+						  "to size %d\n", feVars[feVar_I]->name, *totalDofsThisElement[feVar_I] );
+
+				if ( bcLM_Id[feVar_I] ) Memory_Free( bcLM_Id[feVar_I] );
+				bcLM_Id[feVar_I] = Memory_Alloc_Array( Dof_Index, *totalDofsThisElement[feVar_I], "bcLM_Id" );
+
+				if ( bcValues[feVar_I] ) Memory_Free( bcValues[feVar_I] );
+				bcValues[feVar_I] = Memory_Alloc_Array( double, *totalDofsThisElement[feVar_I], "bcValues" );
+			}
+		}
+
+		/* Reallocate el stiff mat and other arrays if necessary */
+		if ( (*totalDofsThisElement[ROW_VAR] != *totalDofsPrevElement[ROW_VAR]) ||
+		     (*totalDofsThisElement[COL_VAR] != *totalDofsPrevElement[COL_VAR]) )
+		{
+			if (h2Add) Memory_Free( h2Add );
+			Journal_DPrintfL( self->debug, 2, "Reallocating h2Add to size %d\n",
+					  *totalDofsThisElement[COL_VAR] ); 
+			h2Add = Memory_Alloc_Array( double, *totalDofsThisElement[COL_VAR], "h2Add" );
+			
+			if (elStiffMatToAdd) Memory_Free( elStiffMatToAdd );
+			Journal_DPrintfL( self->debug, 2, "Reallocating elStiffMatToAdd to size %d*%d\n",
+					  *totalDofsThisElement[ROW_VAR], *totalDofsThisElement[COL_VAR] ); 
+			elStiffMatToAdd = Memory_Alloc_2DArray( double, *totalDofsThisElement[ROW_VAR], *totalDofsThisElement[COL_VAR], (Name)"elStiffMatToAdd"  );
+		}
+
+		/* Initialise the elStiffMat to zero */
+		/* Note we have to dereference the ptr once ... so we don't clobber the ptrs, just the values */
+		memset( elStiffMatToAdd[0], 0, sizeof(double) * *totalDofsThisElement[ROW_VAR] * *totalDofsThisElement[COL_VAR] );
+
+		/* Assemble this element's element stiffness matrix: call the entry point */
+		elStiffMatBuildStart = MPI_Wtime();
+		StiffnessMatrix_AssembleElement( self, element_lI, sle, context, elStiffMatToAdd );
+		elStiffMatBuildTime += MPI_Wtime() - elStiffMatBuildStart;
+		if ( False == self->allowZeroElementContributions ) {
+			StiffnessMatrix_CheckElementAssembly( self, element_lI, elStiffMatToAdd, *totalDofsThisElement[ROW_VAR],
+							      *totalDofsThisElement[COL_VAR] );
+		}	
+
+		/* This loop is how we handle the possiblity of different row-column variables: if both variables are
+		 * the same, then numFeVars is set to 1 and the loop only progresses through once.
+		 -- PatrickSunter 13 September 2004 */
+		for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
+			/* Reset from previous calculation */
+			nBC_NodalDof[feVar_I] = 0;
+			makeBC_Corrections_row = False;
+
+			/* Check if we want to build table of corrected BC info for the matrix */
+			if( bcRemoveQuery == True ) {
+				unsigned	nNodeInc, *nodeInc;
+
+				FeMesh_GetElementNodes( feVars[feVar_I]->feMesh, element_lI, 
+							self->rowInc );
+				nNodeInc = IArray_GetSize( self->rowInc );
+				nodeInc = (unsigned*)IArray_GetPtr( self->rowInc );
+				_StiffnessMatrix_UpdateBC_CorrectionTables(
+					self,
+					feVars[feVar_I]->eqNum, 
+					feVars[feVar_I]->dofLayout,
+					elementLM[feVar_I],
+					nNodeInc, 
+					nodeInc, 
+					bcLM_Id[feVar_I],
+					bcValues[feVar_I],
+					&(nBC_NodalDof[feVar_I]) );
+			}
+		}
+
+		/* If there is only one feVar, use the same LM for both row and col insertion */
+		if ( numFeVars == 1 ) elementLM[COL_VAR] = elementLM[ROW_VAR];
+
+/*
+  #if DEBUG
+  if ( Stream_IsPrintableLevel( self->debug, 3 ) ) {
+  Journal_DPrintf( self->debug, "Handling Element %d:\n", element_lI );
+  for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
+  FeEquationNumber_PrintElementLocationMatrix( feVars[feVar_I]->eqNum,
+  elementLM[feVar_I], element_lI, self->debug );
+				
+  }
+			
+  Journal_DPrintf( self->debug, "El stiff Mat about to be added:\n" );
+  _StiffnessMatrix_PrintElementStiffnessMatrix( self, element_lI, elementLM[ROW_VAR],
+  elementLM[COL_VAR], elStiffMatToAdd );
+  }	
+  #endif
+*/
+
+
+		/*
+		** Need to make corrections to the RHS before filling in the matrix.  This is because we may modify the
+		** element matrix values before they get there.
+		*/
+
+		/* Set flag for making corrcetions to rhs from bc's */
+		if( nBC_NodalDof[ROW_VAR] != 0 ) {
+			makeBC_Corrections_row = True;
+			modifiedRHS_Vec_cont = True;	/* this guy only needs to be toggled once */
+		}
+		
+		if( makeBC_Corrections_row == True && bcRemoveQuery ) {
+			_StiffnessMatrix_CorrectForceVectorWithOneElementsBoundaryConditions(
+				self,
+				elementLM,
+				h2Add,
+				elStiffMatToAdd,
+				totalDofsThisElement,
+				bcLM_Id,
+				bcValues,
+				nBC_NodalDof[ROW_VAR], 
+				element_lI );
+		}
+
+		/*
+		** If not keeping BCs in, we may need to zero some of these element values, or set them to one.
+		*/
+
+		if( (!self->rowVariable || !self->rowVariable->eqNum->removeBCs) && 
+		    (!self->columnVariable || !self->columnVariable->eqNum->removeBCs) )
+		{
+			FeEquationNumber*	rowEqNum = self->rowVariable->eqNum;
+			FeEquationNumber*	colEqNum = self->columnVariable->eqNum;
+			unsigned		nRows = *totalDofsThisElement[ROW_VAR];
+			unsigned		row_i;
+
+			/* Loop over elementLM rows */
+			for( row_i = 0; row_i < nRows; row_i++ ) {
+				unsigned	rowEqInd;
+
+				rowEqInd = *(int*)STreeMap_Map( rowEqNum->ownedMap,
+								elementLM[ROW_VAR][0] + row_i );
+
+				/* If row is bc */
+				if( STree_Has( rowEqNum->bcEqNums, &rowEqInd ) ) {
+					unsigned	nCols = *totalDofsThisElement[COL_VAR];
+					unsigned	col_i;
+
+					/* Loop over elementLM cols */
+					for( col_i = 0; col_i < nCols; col_i++ ) {
+						unsigned	colEqInd;
+
+						colEqInd = *(int*)STreeMap_Map( colEqNum->ownedMap,
+										elementLM[COL_VAR][0] + col_i );
+
+						/* If col is bc */
+						if( STree_Has( colEqNum->bcEqNums, &colEqInd ) ) {
+							elStiffMatToAdd[0][row_i * nCols + col_i] = 0.0;
+						}
+						else {
+							elStiffMatToAdd[0][row_i * nCols + col_i] = 0.0;
+						}
+					}
+				}
+				else {
+					unsigned	nCols = *totalDofsThisElement[COL_VAR];
+					unsigned	col_i;
+
+					for( col_i = 0; col_i < nCols; col_i++ ) {
+						unsigned	colEqInd = elementLM[COL_VAR][0][col_i];
+
+						/* If col is bc */
+						if( STree_Has( colEqNum->bcEqNums, &colEqInd ) ) {
+							elStiffMatToAdd[0][row_i * nCols + col_i] = 0.0;
+						}
+					}
+				}
+			}
+		}
+
+		/* Add to the global matrix. */
+		matAddingStart = MPI_Wtime();
+		MatSetValues( matrix, *totalDofsThisElement[ROW_VAR], elementLM[ROW_VAR][0], *totalDofsThisElement[COL_VAR], 
+				elementLM[COL_VAR][0], elStiffMatToAdd[0], ADD_VALUES );
+		matAddingTime += MPI_Wtime() - matAddingStart;	
+		
+		
+#if DEBUG
+		if( element_lI % outputInterval == 0 ) {
+			Journal_DPrintfL( self->debug, 2, "done %d percent of global element stiffness assembly (general) \n",
+					  (int)(100.0*((double)element_lI/(double)nLocalElements)) );
+		}
+#endif
+
+		for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
+			/* Save the number of dofs in this element */
+			*totalDofsPrevElement[feVar_I] = *totalDofsThisElement[feVar_I];
+			/* If we haven't built the big LM for all elements, free the temporary one */
+			if ( False == feVars[feVar_I]->eqNum->locationMatrixBuilt ) {
+				Memory_Free( elementLM[feVar_I] );
+			}	
+		}	
+	}
+
+/* 	//////////////////////////////////////////////////////// */
+	MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
+	MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
+	
+	MPI_Allreduce( &modifiedRHS_Vec_cont, &updateRHS, 1, MPI_UNSIGNED, MPI_LOR, comm );
+	if( updateRHS == True && bcRemoveQuery ) {
+		/* stuff was submitted to vec (at least once) and needs to be assembled */
+		VecAssemblyBegin( self->rhs->vector );
+		VecAssemblyEnd( self->rhs->vector );
+	}
+/* 	//////////////////////////////////////////////////////// */
+
+	/*
+	** If keeping BCs in, modify the RHS to reflect BCs.
+	*/
+
+	if( (!self->rowVariable || !self->rowVariable->eqNum->removeBCs) && 
+	    (!self->columnVariable || !self->columnVariable->eqNum->removeBCs) )
+	{
+		FeEquationNumber*	colEqNum = self->columnVariable->eqNum;
+		FeMesh*			feMesh = self->columnVariable->feMesh;
+		DofLayout*		dofLayout = self->columnVariable->dofLayout;
+		unsigned		nNodes = FeMesh_GetNodeLocalSize( feMesh );
+		unsigned		node_i;
+
+		/* What to do if they aren't the same? */
+		assert( self->rowVariable == self->columnVariable );
+
+		for( node_i = 0; node_i < nNodes; node_i++ ) {
+			unsigned	nDofs = dofLayout->dofCounts[node_i];
+			unsigned	dof_i;
+
+			for( dof_i = 0; dof_i < nDofs; dof_i++ ) {
+				unsigned	eqInd = colEqNum->destinationArray[node_i][dof_i];
+				int localEq;
+
+				localEq = *(int*)STreeMap_Map( colEqNum->ownedMap, &eqInd );
+				if( STree_Has( colEqNum->bcEqNums, &localEq ) ) {
+					double	bcVal = DofLayout_GetValueDouble( dofLayout, node_i, dof_i );
+					double	one = 1.0;
+
+					VecSetValues( self->rhs->vector, 1, (PetscInt*)(&eqInd), &bcVal, INSERT_VALUES );
+					MatSetValues( matrix, 1, (PetscInt*)(&eqInd), 1, (PetscInt*)(&eqInd), &one, INSERT_VALUES );
+				}
+			}
+		}
+
+		/* Need to reassemble. */
+		MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
+		MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
+		VecAssemblyBegin( self->rhs->vector );
+		VecAssemblyEnd( self->rhs->vector );
+	}
+
+	for ( feVar_I = 0; feVar_I < numFeVars; feVar_I++ ) {
+		Memory_Free( totalDofsThisElement[feVar_I] );
+		Memory_Free( totalDofsPrevElement[feVar_I] );
+		Memory_Free( bcLM_Id[feVar_I] );
+		Memory_Free( bcValues[feVar_I] );
+	}
+	Memory_Free( elStiffMatToAdd );
+	Memory_Free( h2Add );
+
+	totalTime = MPI_Wtime() - startTime;
+	Journal_DPrintfL( self->debug, 2, "Total time used by %s: %.5g s\n", __func__, totalTime );
+	Journal_DPrintfL( self->debug, 2, "Of which %.5g s spend building elStiffMats\n", elStiffMatBuildTime );
+	Journal_DPrintfL( self->debug, 2, "And %.5g s spend adding to global matrix\n", matAddingTime );
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+
+void _make_dirichlet_corrections_to_rhs(
+        int nr, int rows_to_keep[],
+        int nc, int cols_to_keep[],
+        double **ke, int n_cols, double bc_vals[],
+        double rhs[] )
+{
+        int i,j,I,J;
+
+        for( i=0; i<nr; i++ ) {
+                I = rows_to_keep[i];
+                rhs[I] = 0.0;
+
+                for( j=0; j<nc; j++ ) {
+                        J = cols_to_keep[j];
+                        rhs[I] = rhs[I] - ke[I][J] * bc_vals[J];
+                }
+        }
+
+}
+
+void _make_dirichlet_corrections_to_rhs_transpose(
+        int nr, int rows_to_keep[],
+        int nc, int cols_to_keep[],
+        double **ke, int n_cols, 
+	double bc_vals[], double rhs[] )
+{
+        int i,j,I,J;
+
+        for( i=0; i<nr; i++ ) {
+                I = rows_to_keep[i];
+                rhs[I] = 0.0;
+
+                for( j=0; j<nc; j++ ) {
+                        J = cols_to_keep[j];
+
+                        rhs[I] = rhs[I] - ke[J][I] * bc_vals[J];
+                }
+        }
+
+}
+
+#define LEOrder( i,i_d,i_dof ) ( (i)*(i_dof) + (i_d) )
+void _get_bc_values( FeVariable *colVar, int npe, int ndof, int el_nodes[], double bc_vals[] )
+{
+        double bc;
+        int n, d, n_i;
+
+        for( n=0; n<npe; n++ ) {
+		n_i = el_nodes[n];
+                for( d=0; d<ndof; d++ ) {
+			/* query node index to see if it is has a dirichlet boundary condition */
+			if( FeVariable_IsBC( colVar, n_i, d) == True ) {       
+                		bc = DofLayout_GetValueDouble( colVar->dofLayout, n_i,  d );
+				bc_vals[ LEOrder(n,d,ndof) ] = bc;
+			}
+			/* end bc query */
+                }
+        }
+}
+
+struct StiffMatAss_Log {
+	char *ass_type; /* one of { OPERATOR_ONLY, OPERATOR_WITH_BC_CORRECTIONS, OPERATOR_WITH_BC_CORRECTIONS_FROM_OP_TRANS, OP_BC_CORRECTIONS_ONLY, OP_BC_CORRECTIONS_FROM_OP_TRANS_ONLY } */
+	double total_TIME;
+	double cumulative_el_stiff_mat_ass_TIME;
+	double parallel_assembly_TIME;
+	double element_insertion_TIME;
+	int nr, nc;
+	int local_nr, local_nc;
+	int elements_assembled_for_bc_correction;
+	int elements_assembled;
+	
+	/* local timer info */
+	double dt_element_assembly, dt_total, dt_parallel_assembly, dt_el_insert;
+	double t0_element_assembly, t0_total, t0_parallel_assembly, t0_el_insert;
+};
+
+#define StiffMatAssLog_UpdateElementsAssembled( log ) (log)->elements_assembled++
+#define StiffMatAssLog_UpdateElementsAssembledForBC_Corrections( log ) (log)->elements_assembled_for_bc_correction++
+#define StiffMatAssLog_InitTimer_TotalTime( log ) (log)->t0_total = MPI_Wtime()
+#define StiffMatAssLog_InitTimer_ElementAssembly( log ) (log)->t0_element_assembly = MPI_Wtime()
+#define StiffMatAssLog_InitTimer_ParallelAssembly( log ) (log)->t0_parallel_assembly = MPI_Wtime()
+#define StiffMatAssLog_InitTimer_ElementInsertion( log ) (log)->t0_el_insert = MPI_Wtime()
+
+inline void StiffMatAssLog_AccumulateTime_Total( struct StiffMatAss_Log *log )
+{
+	log->dt_total = MPI_Wtime() - log->t0_total;	
+	log->total_TIME = log->total_TIME + log->dt_total;
+}
+
+inline void StiffMatAssLog_AccumulateTime_ElementAssembly( struct StiffMatAss_Log* log )
+{
+	log->dt_element_assembly = MPI_Wtime() - log->t0_element_assembly;	
+	log->cumulative_el_stiff_mat_ass_TIME = log->cumulative_el_stiff_mat_ass_TIME + log->dt_element_assembly;
+}
+
+
+inline void StiffMatAssLog_AccumulateTime_ParallelAssembly( struct StiffMatAss_Log *log )
+{
+	log->dt_parallel_assembly = MPI_Wtime() - log->t0_parallel_assembly;
+	log->parallel_assembly_TIME = log->parallel_assembly_TIME + log->dt_parallel_assembly;
+}
+
+inline void StiffMatAssLog_AccumulateTime_ElementInsertion( struct StiffMatAss_Log *log )
+{
+	log->dt_el_insert = MPI_Wtime() - log->t0_el_insert;
+	log->element_insertion_TIME = log->element_insertion_TIME + log->dt_el_insert;
+}
+
+inline void StiffMatAssLog_GetOperatorDimensions( struct StiffMatAss_Log *log, Mat matrix )
+{
+  MatGetSize( matrix, (PetscInt*)(&log->nr), (PetscInt*)(&log->nc) );
+  MatGetLocalSize( matrix, (PetscInt*)(&log->local_nr), (PetscInt*)(&log->local_nc) );
+}
+
+void StiffMatAssLog_Delete( struct StiffMatAss_Log** _log )
+{
+	struct StiffMatAss_Log *log = *_log;
+
+	if( log->ass_type != NULL ) free( log->ass_type );
+	free( log );
+	log = NULL;
+
+	*_log = log;
+}
+
+void StiffMatAssLog_Init( struct StiffMatAss_Log *log, const char type_name[] )
+{
+	if( log->ass_type != NULL ) free( log->ass_type );
+	asprintf( &log->ass_type, "%s", type_name );
+	
+	/* reset timers and counter */
+	log->total_TIME                           = 0.0;
+	log->cumulative_el_stiff_mat_ass_TIME     = 0.0;
+	log->parallel_assembly_TIME               = 0.0;
+	log->element_insertion_TIME               = 0.0;
+	log->nr           = log->nc               = 0;
+	log->local_nr     = log->local_nc         = 0;
+	log->elements_assembled_for_bc_correction = 0;
+	log->elements_assembled                   = 0;
+}
+
+struct StiffMatAss_Log* StiffMatAssLog_New( void )
+{
+        struct StiffMatAss_Log *log;
+
+        log = (struct StiffMatAss_Log*)malloc( sizeof(struct StiffMatAss_Log) );
+        log->ass_type = NULL;
+
+	StiffMatAssLog_Init( log, "UNINITIALISED" );
+
+        return log;
+}
+
+
+void StiffMatAssLog_Report_min_max( MPI_Comm comm, double local_val, double *min, double *max )
+{
+	MPI_Reduce ( &local_val, min, 1, MPI_DOUBLE, MPI_MIN, 0, comm );
+	MPI_Reduce ( &local_val, max, 1, MPI_DOUBLE, MPI_MAX, 0, comm );
+}
+
+void StiffMatAssLog_Report_sequential( StiffnessMatrix *self, struct StiffMatAss_Log *log )
+{
+	Journal_PrintfL( self->debug, 1, "GlobalStiffnessMatrix Assembly Report: %s \n", self->name );
+	Journal_PrintfL( self->debug, 1, "  Assembly type:            %s \n", log->ass_type );
+	Journal_PrintfL( self->debug, 1, "  Operator dimensions:      %d x %d (global) \n", log->nr, log->nc );
+	Journal_PrintfL( self->debug, 1, "  Total time:                                  %6.6e (sec)\n", log->total_TIME );
+	Journal_PrintfL( self->debug, 1, "  Assembling element stiffness matrices:       %6.6e (sec)\n", log->cumulative_el_stiff_mat_ass_TIME );
+	Journal_PrintfL( self->debug, 1, "  Parallel assembly:                           %6.6e (sec)\n", log->parallel_assembly_TIME ); 
+	Journal_PrintfL( self->debug, 1, "  Element insertion:                           %6.6e (sec)\n", log->element_insertion_TIME );
+	Journal_PrintfL( self->debug, 1, "  Element stiffness matrices assembled for operator:        %d \n", log->elements_assembled );
+	Journal_PrintfL( self->debug, 1, "  Element stiffness matrices assembled for bc corrections:  %d \n", log->elements_assembled_for_bc_correction );
+}	
+
+void StiffMatAssLog_Report_parallel( StiffnessMatrix *self, struct StiffMatAss_Log *log )
+{
+	double min, max;
+	int sum_i;
+	MPI_Comm comm = self->comm;
+	int init_stream_rank;
+
+	/* change stream to only print on rank 0 */
+        init_stream_rank = Stream_GetPrintingRank( self->debug );
+        Stream_SetPrintingRank( self->debug, 0 );
+
+        Journal_PrintfL( self->debug, 1, "GlobalStiffnessMatrix Assembly Report: %s \n", self->name );
+        Journal_PrintfL( self->debug, 1, "  Assembly type:                          %s \n", log->ass_type );
+        Journal_PrintfL( self->debug, 1, "  Operator dimensions:                                      %d x %d (global) \n", log->nr, log->nc );
+
+	MPI_Reduce ( &log->elements_assembled, &sum_i, 1, MPI_INT, MPI_SUM, 0, comm );
+        Journal_PrintfL( self->debug, 1, "  Element stiffness matrices assembled for operator:        %d (total) \n", sum_i );
+	
+	MPI_Reduce ( &log->elements_assembled_for_bc_correction, &sum_i, 1, MPI_INT, MPI_SUM, 0, comm );
+        Journal_PrintfL( self->debug, 1, "  Element stiffness matrices assembled for bc corrections:  %d (total) \n", sum_i );
+
+	Journal_PrintfL( self->debug, 1, "                                               min     /      max      (sec)\n" );	
+
+	StiffMatAssLog_Report_min_max( comm, log->total_TIME, &min, &max );
+        Journal_PrintfL( self->debug, 1, "  Total time:                             %6.6e / %6.6e  (sec)\n", min, max );
+
+	StiffMatAssLog_Report_min_max( comm, log->cumulative_el_stiff_mat_ass_TIME, &min, &max );
+        Journal_PrintfL( self->debug, 1, "  Assembling element stiffness matrices:  %6.6e / %6.6e  (sec)\n", min, max );
+
+	StiffMatAssLog_Report_min_max( comm, log->parallel_assembly_TIME, &min, &max );
+        Journal_PrintfL( self->debug, 1, "  Parallel assembly:                      %6.6e / %6.6e  (sec)\n", min, max );
+
+	StiffMatAssLog_Report_min_max( comm, log->element_insertion_TIME, &min, &max );
+	Journal_PrintfL( self->debug, 1, "  Element insertion:                      %6.6e / %6.6e  (sec)\n", min, max );
+
+
+	/* reset printing rank of stream */
+	Stream_SetPrintingRank( self->debug, init_stream_rank );
+}
+
+void StiffMatAssLog_Report( StiffnessMatrix *self, struct StiffMatAss_Log *log )
+{
+	int size;
+
+	MPI_Comm_size( self->comm, &size );
+	if( size == 1 ) {
+		StiffMatAssLog_Report_sequential( self, log );
+	}
+	else {
+		StiffMatAssLog_Report_parallel( self, log );
+	}
+}
+
+
+void _StiffMatAss( struct StiffMatAss_Log *log, void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context ) {
+
+        StiffnessMatrix*                self = (StiffnessMatrix*)stiffnessMatrix;
+        SystemLinearEquations*          sle = (SystemLinearEquations*)_sle;
+        FeVariable                      *rowVar, *colVar;
+        FeMesh                          *rowMesh, *colMesh;
+        FeEquationNumber                *rowEqNum, *colEqNum;
+        DofLayout                       *rowDofs, *colDofs;
+        unsigned                        nRowEls;
+        unsigned                        nRowNodes, *rowNodes;
+        unsigned                        nColNodes, *colNodes;
+        unsigned                        maxDofs, maxRCDofs, nDofs, nRowDofs, nColDofs;
+        double**                        elStiffMat;
+/*         Mat                             matrix		= ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
+	Mat                             matrix = self->matrix;
+        unsigned                        e_i, n_i;
+
+        int c_dof, r_dof;
+
+        assert( self && Stg_CheckType( self, StiffnessMatrix ) );
+
+	StiffMatAssLog_Init( log, "OPERATOR_ONLY" );
+	StiffMatAssLog_InitTimer_TotalTime( log );
+
+        rowVar = self->rowVariable;
+        colVar = self->columnVariable ? self->columnVariable : rowVar;
+        rowEqNum = rowVar->eqNum;
+        colEqNum = colVar->eqNum;
+        rowMesh = rowVar->feMesh;
+        colMesh = colVar->feMesh;
+        rowDofs = rowVar->dofLayout;
+        colDofs = colVar->dofLayout;
+        nRowEls = FeMesh_GetElementLocalSize( rowMesh );
+        assert( (rowVar == colVar) ? !self->transRHS : 1 );
+
+        //matrix = self->matrix;
+        elStiffMat = NULL;
+        maxDofs = 0;
+
+
+
+	StiffMatAssLog_GetOperatorDimensions( log, matrix );
+       /* Begin assembling each element. */
+        for( e_i = 0; e_i < nRowEls; e_i++ ) {
+                FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc );
+                nRowNodes = IArray_GetSize( self->rowInc );
+                rowNodes = (unsigned*)IArray_GetPtr( self->rowInc );
+                FeMesh_GetElementNodes( colMesh, e_i, self->colInc );
+                nColNodes = IArray_GetSize( self->colInc );
+                colNodes = (unsigned*)IArray_GetPtr( self->colInc );
+
+                /* Do we need more space to assemble this element? */
+                nRowDofs = 0;
+                for( n_i = 0; n_i < nRowNodes; n_i++ ) {
+                        nRowDofs += rowDofs->dofCounts[rowNodes[n_i]];
+                        r_dof = rowDofs->dofCounts[rowNodes[n_i]];
+                }
+                nColDofs = 0;
+                for( n_i = 0; n_i < nColNodes; n_i++ ) {
+                        nColDofs += colDofs->dofCounts[colNodes[n_i]];
+                        c_dof = colDofs->dofCounts[colNodes[n_i]];
+                }
+                nDofs = nRowDofs * nColDofs;
+                self->nRowDofs = nRowDofs;
+                self->nColDofs = nColDofs;
+                if( nDofs > maxDofs ) {
+                        maxRCDofs = (nRowDofs > nColDofs) ? nRowDofs : nColDofs;
+                        elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs );
+
+                        maxDofs = nDofs;
+                        self->elStiffMat = elStiffMat;
+                }
+
+                       
+                /* Assemble the element. */
+                memset( elStiffMat[0], 0, nDofs * sizeof(double) );
+                StiffMatAssLog_InitTimer_ElementAssembly( log );
+		StiffnessMatrix_AssembleElement( self, e_i, sle, (FiniteElementContext*)_context, elStiffMat );
+		StiffMatAssLog_AccumulateTime_ElementAssembly( log );
+
+
+               /* If keeping BCs in, zero corresponding entries in the element stiffness matrix. */
+                if( !rowEqNum->removeBCs || !colEqNum->removeBCs )
+                        Assembler_LoopMatrixElement( self->zeroBCsAsm, e_i );
+
+                /* Add to stiffness matrix. */
+		StiffMatAssLog_InitTimer_ElementInsertion( log );
+                MatSetValues( matrix,
+                              nRowDofs, (PetscInt*)rowEqNum->locationMatrix[e_i][0],
+                              nColDofs, (PetscInt*)colEqNum->locationMatrix[e_i][0],
+                              elStiffMat[0], INSERT_VALUES );
+
+		StiffMatAssLog_AccumulateTime_ElementInsertion( log ); /* update time */
+		StiffMatAssLog_UpdateElementsAssembled( log ); /* update counter */
+        }
+
+        
+        /* If keeping BCs in and rows and columnns use the same variable, put ones in all BC'd diagonals. */
+        if( !colEqNum->removeBCs && rowVar == colVar )
+                Assembler_LoopMatrixDiagonal( self->diagBCsAsm );
+
+        /* Start matrix assembly */
+	StiffMatAssLog_InitTimer_ParallelAssembly( log );
+	MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
+	MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
+	StiffMatAssLog_AccumulateTime_ParallelAssembly( log );
+
+        FreeArray( elStiffMat );
+
+	StiffMatAssLog_AccumulateTime_Total( log );
+
+}
+
+void _StiffMatAss_vector_corrections(  struct StiffMatAss_Log *log, void *stiffnessMatrix, Bool removeBCs, void *_sle, void *_context ) {
+        StiffnessMatrix*                self = (StiffnessMatrix*)stiffnessMatrix;
+        SystemLinearEquations*          sle = (SystemLinearEquations*)_sle;
+        FeVariable                      *rowVar, *colVar;
+        FeMesh                          *rowMesh, *colMesh;
+        FeEquationNumber                *rowEqNum, *colEqNum;
+        DofLayout                       *rowDofs, *colDofs;
+        unsigned                        nRowEls;
+        unsigned                        nRowNodes, *rowNodes;
+        unsigned                        nColNodes, *colNodes;
+        unsigned                        maxDofs, maxRCDofs, nDofs, nRowDofs, nColDofs;
+        double**                        elStiffMat;
+        double*                         bcVals;
+/* 	Mat				matrix		= ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
+	Mat                             matrix = self->matrix;
+	Vec				vector, transVector;
+        unsigned                        e_i, n_i;
+
+        unsigned bc_cnt = 0;
+        int *row_index_to_keep, *col_index_to_keep;
+        int n_rows, n_cols;
+        int same_variables;
+        int c_dof, r_dof;
+        double *rhs;
+	int has_col_bc, has_row_bc;
+	int eq_num;
+
+        assert( self && Stg_CheckType( self, StiffnessMatrix ) );
+
+	StiffMatAssLog_Init( log, "OPERATOR_WITH_BC_CORRECTIONS" );
+	StiffMatAssLog_InitTimer_TotalTime( log );
+
+        rowVar = self->rowVariable;
+        colVar = self->columnVariable ? self->columnVariable : rowVar;
+        rowEqNum = rowVar->eqNum;
+        colEqNum = colVar->eqNum;
+        rowMesh = rowVar->feMesh;
+        colMesh = colVar->feMesh;
+        rowDofs = rowVar->dofLayout;
+        colDofs = colVar->dofLayout;
+        nRowEls = FeMesh_GetElementLocalSize( rowMesh );
+        assert( (rowVar == colVar) ? !self->transRHS : 1 );
+
+        //matrix = self->matrix;
+        vector = self->rhs ? self->rhs->vector : NULL;
+        transVector = self->transRHS ? self->transRHS->vector : NULL;
+        elStiffMat = NULL;
+        bcVals = NULL;
+        maxDofs = 0;
+
+	col_index_to_keep = NULL;
+	row_index_to_keep = NULL;
+	rhs = NULL;
+
+        same_variables = 0;
+        if( rowMesh == colMesh ) {
+                same_variables = 1;
+//                printf("Detected same variables in assembly VECTOR_CORRECTIONS\n");
+        }
+
+	assert( vector ); /* If we are in here then vector must be valid */
+
+
+	bc_cnt = 0;
+
+	StiffMatAssLog_GetOperatorDimensions( log, matrix );
+       /* Begin assembling each element. */
+        for( e_i = 0; e_i < nRowEls; e_i++ ) {
+                FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc );
+                nRowNodes = IArray_GetSize( self->rowInc );
+                rowNodes = (unsigned*)IArray_GetPtr( self->rowInc );
+                FeMesh_GetElementNodes( colMesh, e_i, self->colInc );
+                nColNodes = IArray_GetSize( self->colInc );
+                colNodes = (unsigned*)IArray_GetPtr( self->colInc );
+
+                /* Do we need more space to assemble this element? */
+                nRowDofs = 0;
+                for( n_i = 0; n_i < nRowNodes; n_i++ ) {
+                        nRowDofs += rowDofs->dofCounts[rowNodes[n_i]];
+                        r_dof = rowDofs->dofCounts[rowNodes[n_i]];
+                }
+                nColDofs = 0;
+                for( n_i = 0; n_i < nColNodes; n_i++ ) {
+                        nColDofs += colDofs->dofCounts[colNodes[n_i]];
+                        c_dof = colDofs->dofCounts[colNodes[n_i]];
+                }
+                nDofs = nRowDofs * nColDofs;
+                self->nRowDofs = nRowDofs;
+                self->nColDofs = nColDofs;
+                if( nDofs > maxDofs ) {
+                        maxRCDofs = (nRowDofs > nColDofs) ? nRowDofs : nColDofs;
+                        elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs );
+                        bcVals = ReallocArray( bcVals, double, maxRCDofs );
+                        rhs = ReallocArray( rhs, double, maxRCDofs );
+
+                        col_index_to_keep  = ReallocArray( col_index_to_keep, int, maxRCDofs );
+                        row_index_to_keep  = ReallocArray( row_index_to_keep, int, maxRCDofs );
+
+                        maxDofs = nDofs;
+                        self->elStiffMat = elStiffMat;
+                        self->bcVals = bcVals;
+                }
+
+                /* check for presence of bc's */
+                n_rows = n_cols = 0;
+                has_row_bc = has_col_bc = 0;
+
+                       
+		for( n_i=0; n_i<nColDofs; n_i++ ) {
+			eq_num = colEqNum->locationMatrix[e_i][0][n_i];
+			if( colEqNum->locationMatrix[e_i][0][n_i] < 0 ) {
+				col_index_to_keep[ n_cols ] = n_i;
+				n_cols++;
+				has_col_bc = 1;
+			}
+		}
+		for( n_i=0; n_i<nRowDofs; n_i++ ) {
+			if( rowEqNum->locationMatrix[e_i][0][n_i] >= 0 ) {
+				row_index_to_keep[ n_rows ] = n_i;
+				n_rows++;
+				has_row_bc = 1;
+			}
+		}
+
+		if( has_col_bc == 0 ) continue;
+
+		/* Assemble the element. */
+		memset( elStiffMat[0], 0, nDofs * sizeof(double) );
+		StiffMatAssLog_InitTimer_ElementAssembly( log );
+		
+		StiffnessMatrix_AssembleElement( self, e_i, sle, (FiniteElementContext*)_context, elStiffMat );
+		
+		StiffMatAssLog_AccumulateTime_ElementAssembly( log ); /* update time */
+		StiffMatAssLog_UpdateElementsAssembled( log ); /* update counter */
+
+
+		/* If keeping BCs in, zero corresponding entries in the element stiffness matrix. */
+		if( !rowEqNum->removeBCs || !colEqNum->removeBCs )
+			Assembler_LoopMatrixElement( self->zeroBCsAsm, e_i );
+
+
+		if( (has_col_bc==1) ) {
+			/* int I; */
+			memset( rhs, 0, maxRCDofs * sizeof(double) );
+
+			_get_bc_values( colVar, nColNodes, c_dof, (int*)colNodes, bcVals );
+			_make_dirichlet_corrections_to_rhs( n_rows, row_index_to_keep, n_cols, col_index_to_keep, elStiffMat, -1, bcVals, rhs );
+/*
+			printf("f: e = %d \n", e_i );
+                        
+			for( I=0; I<nRowDofs; I++ ) {
+				printf("  I=%d : %d -- bcval = %f : rhs = %f \n", I, rowEqNum->locationMatrix[e_i][0][I], bcVals[I], rhs[I] );
+			}
+*/
+			VecSetValues( vector, nRowDofs, (PetscInt*)rowEqNum->locationMatrix[e_i][0], rhs, ADD_VALUES );
+			StiffMatAssLog_UpdateElementsAssembledForBC_Corrections( log );
+			bc_cnt++;
+		}
+
+
+		/* Add to stiffness matrix. */
+		/*
+		StiffMatAssLog_InitTimer_ElementInsertion( log );
+                Matrix_AddEntries( matrix,
+                                   nRowDofs, (unsigned*)rowEqNum->locationMatrix[e_i][0],
+                                   nColDofs, (unsigned*)colEqNum->locationMatrix[e_i][0],
+                                   elStiffMat[0] );
+		StiffMatAssLog_AccumulateTime_ElementInsertion( log ); 
+		*/
+        }
+
+	StiffMatAssLog_InitTimer_ParallelAssembly( log );
+        /* Start assembling vectors. */
+	VecAssemblyBegin( vector );
+        
+        /* If keeping BCs in and rows and columnns use the same variable, put ones in all BC'd diagonals. */
+//        if( !colEqNum->removeBCs && rowVar == colVar )
+//                Assembler_LoopMatrixDiagonal( self->diagBCsAsm );
+
+        /* Start matrix assembly */
+        //Matrix_AssemblyBegin( matrix );
+
+        /* Finalise matrix and vector assembly */
+	VecAssemblyEnd( vector );
+        //Matrix_AssemblyEnd( matrix );
+	StiffMatAssLog_AccumulateTime_ParallelAssembly( log );
+
+//        printf("Applied vector modifications using %u of %u elements \n", bc_cnt, nRowEls );
+        FreeArray( elStiffMat );
+        FreeArray( bcVals );
+        FreeArray( row_index_to_keep );
+        FreeArray( col_index_to_keep );
+	FreeArray( rhs );
+
+	StiffMatAssLog_AccumulateTime_Total( log );
+
+/*
+	{
+ 		PETScVector*    self = (PETScVector*)vector;
+		printf("f = \n");
+        	VecView( self->petscVec, PETSC_VIEWER_STDOUT_WORLD );
+	}
+*/	
+
+}
+
+
+
+
+void _StiffMatAss_vector_corrections_from_transpose( struct StiffMatAss_Log *log, void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context ) {
+	StiffnessMatrix*                self = (StiffnessMatrix*)stiffnessMatrix;
+	SystemLinearEquations*          sle = (SystemLinearEquations*)_sle;
+	FeVariable                      *rowVar, *colVar;
+	FeMesh                          *rowMesh, *colMesh;
+	FeEquationNumber                *rowEqNum, *colEqNum;
+	DofLayout                       *rowDofs, *colDofs;
+	unsigned                        nRowEls;
+	unsigned                        nRowNodes, *rowNodes;
+	unsigned                        nColNodes, *colNodes;
+	unsigned                        maxDofs, maxRCDofs, nDofs, nRowDofs, nColDofs;
+	double**                        elStiffMat;
+	double*                         bcVals;
+/* 	Mat				matrix		= ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
+	Mat                             matrix = self->matrix;
+	Vec				transVector;
+	unsigned                        e_i, n_i;
+
+	unsigned bc_cnt = 0;
+	int *row_index_to_keep, *col_index_to_keep;
+	int n_rows, n_cols;
+	int same_variables;
+	int c_dof, r_dof;
+	double *rhs;
+	int has_col_bc, has_row_bc;
+	int eq_num;
+
+	assert( self && Stg_CheckType( self, StiffnessMatrix ) );
+	StiffMatAssLog_Init( log, "OPERATOR_WITH_BC_CORRECTIONS_FROM_OP_TRANS" );
+	StiffMatAssLog_InitTimer_TotalTime( log );
+
+	rowVar = self->rowVariable;
+	colVar = self->columnVariable ? self->columnVariable : rowVar;
+	rowEqNum = rowVar->eqNum;
+	colEqNum = colVar->eqNum;
+ 	rowMesh = rowVar->feMesh;
+	colMesh = colVar->feMesh;
+	rowDofs = rowVar->dofLayout;
+	colDofs = colVar->dofLayout;
+	nRowEls = FeMesh_GetElementLocalSize( rowMesh );
+	assert( (rowVar == colVar) ? !self->transRHS : 1 );
+
+  	//matrix = self->matrix;
+  	transVector = self->transRHS ? self->transRHS->vector : NULL;
+  	elStiffMat = NULL;
+  	bcVals = NULL;
+  	maxDofs = 0;
+
+	col_index_to_keep = NULL;
+	row_index_to_keep = NULL;
+	rhs = NULL;
+
+
+  	same_variables = 0;
+  	if( rowMesh == colMesh ) {
+  		same_variables = 1;
+		// printf("Detected same variables in assembly VECTOR CORRECTIONS FROM TRANSPOSE \n");
+	}
+	assert( transVector ); /* If we are in this function than transVector must be valid */ 
+
+	bc_cnt = 0;
+
+
+	StiffMatAssLog_GetOperatorDimensions( log, matrix );
+       /* Begin assembling each element. */
+        for( e_i = 0; e_i < nRowEls; e_i++ ) {
+                FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc );
+                nRowNodes = IArray_GetSize( self->rowInc );
+                rowNodes = (unsigned*)IArray_GetPtr( self->rowInc );
+                FeMesh_GetElementNodes( colMesh, e_i, self->colInc );
+                nColNodes = IArray_GetSize( self->colInc );
+                colNodes = (unsigned*)IArray_GetPtr( self->colInc );
+
+                /* Do we need more space to assemble this element? */
+                nRowDofs = 0;
+                for( n_i = 0; n_i < nRowNodes; n_i++ ) {
+                        nRowDofs += rowDofs->dofCounts[rowNodes[n_i]];
+                        r_dof = rowDofs->dofCounts[rowNodes[n_i]];
+                }
+                nColDofs = 0;
+                for( n_i = 0; n_i < nColNodes; n_i++ ) {
+                        nColDofs += colDofs->dofCounts[colNodes[n_i]];
+                        c_dof = colDofs->dofCounts[colNodes[n_i]];
+                }
+                nDofs = nRowDofs * nColDofs;
+                self->nRowDofs = nRowDofs;
+                self->nColDofs = nColDofs;
+                if( nDofs > maxDofs ) {
+                        maxRCDofs = (nRowDofs > nColDofs) ? nRowDofs : nColDofs;
+                        elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs );
+                        bcVals = ReallocArray( bcVals, double, maxRCDofs );
+                        rhs = ReallocArray( rhs, double, maxRCDofs );
+
+                        col_index_to_keep  = ReallocArray( col_index_to_keep, int, maxRCDofs );
+                        row_index_to_keep  = ReallocArray( row_index_to_keep, int, maxRCDofs );
+
+                        maxDofs = nDofs;
+                        self->elStiffMat = elStiffMat;
+                        self->bcVals = bcVals;
+                }
+
+                /* check for presence of bc's */
+                n_rows = n_cols = 0;
+                has_row_bc = has_col_bc = 0;
+
+		/* cause this is the transpose function, we make corrections on the bc's if there are applied to the row variable */
+                for( n_i=0; n_i<nColDofs; n_i++ ) {
+			eq_num = colEqNum->locationMatrix[e_i][0][n_i];
+                        if( colEqNum->locationMatrix[e_i][0][n_i] >= 0 ) {
+				col_index_to_keep[ n_cols ] = n_i;
+                                n_cols++;
+                                has_col_bc = 1;
+                        }
+                }
+        
+                for( n_i=0; n_i<nRowDofs; n_i++ ) {
+                       if( rowEqNum->locationMatrix[e_i][0][n_i] < 0 ) {
+				row_index_to_keep[ n_rows ] = n_i;
+                                n_rows++;
+                                has_row_bc = 1;
+                       }
+                }
+
+
+		if( has_row_bc == 0 ) continue;
+
+
+
+                /* Initialise the element stiffness matrix */
+                memset( elStiffMat[0], 0, nDofs * sizeof(double) );
+		/*
+		for( si=0; si<nRowDofs; si++ )
+		for( sj=0; sj<nColDofs; sj++ )
+			elStiffMat[si][sj] = 0.0;
+		*/
+
+		/* Assemble the element stiffness matrix */	     
+		StiffMatAssLog_InitTimer_ElementAssembly( log );
+
+		StiffnessMatrix_AssembleElement( self, e_i, sle, (FiniteElementContext*)_context, elStiffMat );
+
+		StiffMatAssLog_AccumulateTime_ElementAssembly( log );		
+		StiffMatAssLog_UpdateElementsAssembled( log );
+
+
+		/* If keeping BCs in, zero corresponding entries in the element stiffness matrix. */
+		if( !rowEqNum->removeBCs || !colEqNum->removeBCs )
+			Assembler_LoopMatrixElement( self->zeroBCsAsm, e_i );
+
+		if( (has_row_bc==1) ) {
+			/* int I; */
+			memset( rhs, 0, maxRCDofs * sizeof(double) );
+			/*
+			for( II=0; II<maxRCDofs; II++ ) {
+				bcVals[II] = rhs[II] = 0.0;
+			}
+			*/
+			_get_bc_values( rowVar, nRowNodes, r_dof, (int*)rowNodes, bcVals );
+
+			_make_dirichlet_corrections_to_rhs_transpose( n_cols, col_index_to_keep, n_rows, row_index_to_keep, elStiffMat, -1, bcVals, rhs );
+/*
+  			printf("h: e = %d \n", e_i );
+			for( I=0; I<nColDofs; I++ ) {
+				printf("  I=%d : %d -- bcval = %f : rhs = %f\n", I, colEqNum->locationMatrix[e_i][0][I], bcVals[I], rhs[I] );
+			}
+*/
+
+			VecSetValues( transVector, nColDofs, colEqNum->locationMatrix[e_i][0], rhs, INSERT_VALUES );
+			StiffMatAssLog_UpdateElementsAssembledForBC_Corrections( log );
+			bc_cnt++;
+		}
+
+		/* Add to stiffness matrix. */
+/*
+		StiffMatAssLog_InitTimer_ElementInsertion(log);
+                Matrix_AddEntries( matrix,
+                                   nRowDofs, (unsigned*)rowEqNum->locationMatrix[e_i][0],
+                                   nColDofs, (unsigned*)colEqNum->locationMatrix[e_i][0],
+                                   elStiffMat[0] );
+		StiffMatAssLog_AccumulateTime_ElementInsertion( log ); 
+*/  
+      }
+
+
+	StiffMatAssLog_InitTimer_ParallelAssembly( log );
+        /* Start assembling vectors. */
+	VecAssemblyBegin( transVector );
+
+
+        /* If keeping BCs in and rows and columnns use the same variable, put ones in all BC'd diagonals. */
+//        if( !colEqNum->removeBCs && rowVar == colVar )
+//                Assembler_LoopMatrixDiagonal( self->diagBCsAsm );
+
+        /* Start matrix assembly */
+//        Matrix_AssemblyBegin( matrix );
+
+        /* Finalise matrix and vector assembly */
+	VecAssemblyEnd( transVector );
+//        Matrix_AssemblyEnd( matrix );
+	StiffMatAssLog_AccumulateTime_ParallelAssembly( log );
+
+//        printf("Applied vector modifications using %u of %u elements \n", bc_cnt, nRowEls );
+        FreeArray( elStiffMat );
+        FreeArray( bcVals );
+        FreeArray( row_index_to_keep );
+        FreeArray( col_index_to_keep );
+	FreeArray( rhs );
+
+	StiffMatAssLog_AccumulateTime_Total( log );
+/*
+        {
+                PETScVector*    self = (PETScVector*)transVector;
+		printf("h = \n");
+                VecView( self->petscVec, PETSC_VIEWER_STDOUT_WORLD );
+        }
+*/
+}
+
+
+//void __StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context );
+void StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context ) {
+	StiffnessMatrix	*self = (StiffnessMatrix*)stiffnessMatrix;
+	Vec					vector, transVector;	
+	struct				StiffMatAss_Log *log;
+
+	vector = self->rhs ? self->rhs->vector : NULL;
+	transVector = self->transRHS ? self->transRHS->vector : NULL;
+
+	log = StiffMatAssLog_New();
+
+
+	_StiffMatAss( log, stiffnessMatrix, removeBCs, _sle, (FiniteElementContext*)_context );
+	StiffMatAssLog_Report( self, log );
+
+	if( vector ) {
+		_StiffMatAss_vector_corrections( log, stiffnessMatrix, removeBCs, _sle, (FiniteElementContext*)_context );
+		StiffMatAssLog_Report( self, log );
+	}
+	if( transVector ) {
+		_StiffMatAss_vector_corrections_from_transpose( log, stiffnessMatrix, removeBCs, _sle, (FiniteElementContext*)_context );
+		StiffMatAssLog_Report( self, log );
+	}
+	//	__StiffnessMatrix_NewAssemble( stiffnessMatrix, removeBCs, _sle, _context );
+	StiffMatAssLog_Delete( &log );
+}
+
+#if 0
+void StiffnessMatrix_SetEqsToUnity( StiffnessMatrix* self, const STreeNode* node ) {
+   static const double one = 1.0;
+
+   if( !node ) return;
+   StiffnessMatrix_SetEqsToUnity( self, node->left );
+   Matrix_AddEntries( self->matrix, 1, (int*)node->data, 1, (int*)node->data, (double*)&one );
+   StiffnessMatrix_SetEqsToUnity( self, node->right );
+}
+#endif
+
+
+/* Callback version */
+void __StiffnessMatrix_NewAssemble( void* stiffnessMatrix, Bool removeBCs, void* _sle, void* _context ) {
+   static const double one = 1.0;
+	StiffnessMatrix*		self = (StiffnessMatrix*)stiffnessMatrix;
+	SystemLinearEquations*		sle = (SystemLinearEquations*)_sle;
+	FeVariable			*rowVar, *colVar;
+	FeMesh				*rowMesh, *colMesh;
+	FeEquationNumber		*rowEqNum, *colEqNum;
+	DofLayout			*rowDofs, *colDofs;
+	unsigned			nRowEls;
+	unsigned			nRowNodes, *rowNodes;
+	unsigned			nColNodes, *colNodes;
+	unsigned			maxDofs, maxRCDofs, nDofs, nRowDofs, nColDofs;
+	double**			elStiffMat;
+	double*				bcVals;
+/* 	Mat				matrix		= ( self->useShellMatrix ) ? self->shellMatrix->matrix : self->matrix; */
+	Mat                             matrix = self->matrix;
+	Vec				vector, transVector;
+        int nRowNodeDofs, nColNodeDofs;
+        int rowInd, colInd;
+        double bc;
+	unsigned			e_i, n_i, dof_i, n_j, dof_j;
+
+	assert( self && Stg_CheckType( self, StiffnessMatrix ) );
+
+	rowVar = self->rowVariable;
+	colVar = self->columnVariable ? self->columnVariable : rowVar;
+	rowEqNum = rowVar->eqNum;
+	colEqNum = colVar->eqNum;
+	rowMesh = rowVar->feMesh;
+	colMesh = colVar->feMesh;
+	rowDofs = rowVar->dofLayout;
+	colDofs = colVar->dofLayout;
+	nRowEls = FeMesh_GetElementLocalSize( rowMesh );
+	assert( (rowVar == colVar) ? !self->transRHS : 1 );
+
+	//matrix = self->matrix;
+	vector = self->rhs ? self->rhs->vector : NULL;
+	transVector = self->transRHS ? self->transRHS->vector : NULL;
+	elStiffMat = NULL;
+	bcVals = NULL;
+	maxDofs = 0;
+
+	/* Begin assembling each element. */
+	for( e_i = 0; e_i < nRowEls; e_i++ ) {
+		FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc );
+		nRowNodes = IArray_GetSize( self->rowInc );
+		rowNodes = (unsigned*)IArray_GetPtr( self->rowInc );
+		FeMesh_GetElementNodes( colMesh, e_i, self->colInc );
+		nColNodes = IArray_GetSize( self->colInc );
+		colNodes = (unsigned*)IArray_GetPtr( self->colInc );
+
+		/* Do we need more space to assemble this element? */
+		nRowDofs = 0;
+		for( n_i = 0; n_i < nRowNodes; n_i++ )
+			nRowDofs += rowDofs->dofCounts[rowNodes[n_i]];
+		nColDofs = 0;
+		for( n_i = 0; n_i < nColNodes; n_i++ )
+			nColDofs += colDofs->dofCounts[colNodes[n_i]];
+		nDofs = nRowDofs * nColDofs;
+		self->nRowDofs = nRowDofs;
+		self->nColDofs = nColDofs;
+		if( nDofs > maxDofs ) {
+			maxRCDofs = (nRowDofs > nColDofs) ? nRowDofs : nColDofs;
+			elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs );
+			bcVals = ReallocArray( bcVals, double, maxRCDofs );
+			maxDofs = nDofs;
+			self->elStiffMat = elStiffMat;
+			self->bcVals = bcVals;
+		}
+
+		/* Assemble the element. */
+		memset( elStiffMat[0], 0, nDofs * sizeof(double) );
+		StiffnessMatrix_AssembleElement( self, e_i, sle, (FiniteElementContext*)_context, elStiffMat );
+
+		/* Correct for BCs providing I'm not keeping them in. */
+		if( vector && removeBCs ) {
+			memset( bcVals, 0, nRowDofs * sizeof(double) );
+
+                        rowInd = 0;
+                        for( n_i = 0; n_i < nRowNodes; n_i++ ) {
+                           nRowNodeDofs = rowDofs->dofCounts[rowNodes[n_i]];
+                           for( dof_i = 0; dof_i < nRowNodeDofs; dof_i++ ) {
+                              if( !FeVariable_IsBC( rowVar, rowNodes[n_i], dof_i ) ) {
+                                 colInd = 0;
+                                 for( n_j = 0; n_j < nColNodes; n_j++ ) {
+                                    nColNodeDofs = colDofs->dofCounts[colNodes[n_j]];
+                                    for( dof_j = 0; dof_j < nColNodeDofs; dof_j++ ) {
+                                       if( FeVariable_IsBC( colVar, colNodes[n_j], dof_j ) ) {
+                                          bc = DofLayout_GetValueDouble( colDofs, colNodes[n_j], dof_j );
+                                          bcVals[rowInd] -= bc * elStiffMat[rowInd][colInd];
+                                       }
+                                       colInd++;
+                                    }
+                                 }
+                              }
+                              rowInd++;
+                           }
+                        }
+
+			//Vector_AddEntries( vector, nRowDofs, (unsigned*)rowEqNum->locationMatrix[e_i][0], bcVals );
+			VecSetValues( vector, nRowDofs, rowEqNum->locationMatrix[e_i][0], bcVals, ADD_VALUES );
+		}
+		if( transVector && removeBCs ) {
+			memset( bcVals, 0, nColDofs * sizeof(double) );
+
+                        colInd = 0;
+                        for( n_i = 0; n_i < nColNodes; n_i++ ) {
+                           nColNodeDofs = colDofs->dofCounts[colNodes[n_i]];
+                           for( dof_i = 0; dof_i < nColNodeDofs; dof_i++ ) {
+                              if( !FeVariable_IsBC( colVar, colNodes[n_i], dof_i ) ) {
+                                 rowInd = 0;
+                                 for( n_j = 0; n_j < nRowNodes; n_j++ ) {
+                                    nRowNodeDofs = rowDofs->dofCounts[rowNodes[n_j]];
+                                    for( dof_j = 0; dof_j < nRowNodeDofs; dof_j++ ) {
+                                       if( FeVariable_IsBC( rowVar, rowNodes[n_j], dof_j ) ) {
+                                          bc = DofLayout_GetValueDouble( rowDofs, rowNodes[n_j], dof_j );
+                                          bcVals[colInd] -= bc * elStiffMat[rowInd][colInd];
+                                       }
+                                       rowInd++;
+                                    }
+                                 }
+                              }
+                              colInd++;
+                           }
+                        }
+
+			VecSetValues( transVector, nColDofs, colEqNum->locationMatrix[e_i][0], bcVals, ADD_VALUES );
+		}
+
+		/* If keeping BCs in, zero corresponding entries in the element stiffness matrix. */
+		if( !rowEqNum->removeBCs || !colEqNum->removeBCs ) {
+                   rowInd = 0;
+                   for( n_i = 0; n_i < nRowNodes; n_i++ ) {
+                      nRowNodeDofs = rowDofs->dofCounts[rowNodes[n_i]];
+                      for( dof_i = 0; dof_i < nRowNodeDofs; dof_i++ ) {
+                         if( FeVariable_IsBC( rowVar, rowNodes[n_i], dof_i ) ) {
+                            memset( elStiffMat[rowInd], 0, nColDofs * sizeof(double) );
+                         }
+                         else {
+                            colInd = 0;
+                            for( n_j = 0; n_j < nColNodes; n_j++ ) {
+                               nColNodeDofs = colDofs->dofCounts[colNodes[n_j]];
+                               for( dof_j = 0; dof_j < nColNodeDofs; dof_j++ ) {
+                                  if( FeVariable_IsBC( colVar, colNodes[n_j], dof_j ) )
+                                     elStiffMat[rowInd][colInd] = 0.0;
+                                  colInd++;
+                               }
+                            }
+                         }
+                         rowInd++;
+                      }
+                   }
+                }
+
+		/* Add to stiffness matrix. */
+		MatSetValues( matrix, 
+			      nRowDofs, rowEqNum->locationMatrix[e_i][0], 
+			      nColDofs, colEqNum->locationMatrix[e_i][0], 
+			      elStiffMat[0], ADD_VALUES );
+	}
+
+	FreeArray( elStiffMat );
+	FreeArray( bcVals );
+
+	/* If keeping BCs in and rows and columnns use the same variable, put ones in all BC'd diagonals. */
+	if( !colEqNum->removeBCs && rowVar == colVar ) {
+           for( n_i = 0; n_i < FeMesh_GetNodeLocalSize( colMesh ); n_i++ ) {
+              nColNodeDofs = colDofs->dofCounts[n_i];
+              for( dof_i = 0; dof_i < nColNodeDofs; dof_i++ ) {
+                 if( FeVariable_IsBC( colVar, n_i, dof_i ) ) {
+                    MatSetValues( self->matrix,
+                                       1, colEqNum->destinationArray[n_i] + dof_i,
+                                       1, colEqNum->destinationArray[n_i] + dof_i,
+                                       (double*)&one, ADD_VALUES );
+                 }
+              }
+           }
+
+#if 0
+           StiffnessMatrix_SetEqsToUnity( self, rowEqNum, STree_GetRoot( rowEqNum->ownedMap ) );
+#endif
+        }
+
+	/* Reassemble the matrix and vectors. */
+	MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
+	MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
+	if( vector ) {
+		VecAssemblyBegin( vector );
+		VecAssemblyEnd( vector );
+	}
+	if( transVector) {
+		VecAssemblyBegin( transVector );
+		VecAssemblyEnd( transVector );
+	}
+
+	MatAssemblyBegin( matrix, MAT_FINAL_ASSEMBLY );
+	MatAssemblyEnd( matrix, MAT_FINAL_ASSEMBLY );
+}
+
+/* void StiffnessMatrix_ShellAssembly( void* stiffnessMatrix, Bool removeBCs, void* data ) { */
+/* 	StiffnessMatrix*	self = (StiffnessMatrix*)stiffnessMatrix; */
+/* 	Vec    			rhs; */
+/* 	FeVariable		*rowVar, *colVar; */
+/* 	FeMesh			*rowMesh, *colMesh; */
+/* 	FeEquationNumber	*rowEqNum, *colEqNum; */
+/* 	DofLayout		*rowDofs, *colDofs; */
+/* 	unsigned		nRowEls; */
+/* 	unsigned		nRowNodes, *rowNodes; */
+/* 	unsigned		nColNodes, *colNodes; */
+/* 	unsigned		maxDofs, nDofs, nRowDofs, nColDofs; */
+/* 	double**		elStiffMat; */
+/* 	double*			values; */
+/* 	unsigned*		indices; */
+/* 	unsigned		curRow, curCol; */
+/* 	unsigned		colEq; */
+/* 	double			bc; */
+/* 	unsigned		e_i, n_i, n_j, dof_i, dof_j; */
+
+/* 	assert( self && Stg_CheckType( self, StiffnessMatrix ) ); */
+
+/* 	/\* The whole point of this routine is to remove the BCs. *\/ */
+/* 	if( !removeBCs ) */
+/* 		return; */
+
+/* 	rhs = self->rhs->vector; */
+/* 	rowVar = self->rowVariable; */
+/* 	colVar = self->columnVariable ? self->columnVariable : rowVar; */
+/* 	if( rowVar != colVar ) { */
+/* 		FeVariable* 	tmp = rowVar; */
+/* 		rowVar = colVar; */
+/* 		colVar = tmp; */
+/* 	} */
+/* 	rowEqNum = rowVar->eqNum; */
+/* 	colEqNum = colVar->eqNum; */
+/* 	rowMesh = rowVar->feMesh; */
+/* 	colMesh = colVar->feMesh; */
+/* 	rowDofs = rowVar->dofLayout; */
+/* 	colDofs = colVar->dofLayout; */
+/* 	nRowEls = FeMesh_GetElementLocalSize( rowMesh ); */
+/* 	elStiffMat = NULL; */
+/* 	values = NULL; */
+/* 	indices = NULL; */
+/* 	maxDofs = 0; */
+
+/* 	for( e_i = 0; e_i < nRowEls; e_i++ ) { */
+/* 		FeMesh_GetElementNodes( rowMesh, e_i, self->rowInc ); */
+/* 		nRowNodes = IArray_GetSize( self->rowInc ); */
+/* 		rowNodes = IArray_GetPtr( self->rowInc ); */
+/* 		FeMesh_GetElementNodes( colMesh, e_i, self->colInc ); */
+/* 		nColNodes = IArray_GetSize( self->colInc ); */
+/* 		colNodes = IArray_GetPtr( self->colInc ); */
+
+/* 		/\* If none of the column equations on this element have BCs then skip it. *\/ */
+/* 		for( n_i = 0; n_i < nRowNodes; n_i++ ) { */
+/* 			for( dof_i = 0; dof_i < rowDofs->dofCounts[rowNodes[n_i]]; dof_i++ ) { */
+/* 				if( rowEqNum->locationMatrix[e_i][n_i][dof_i] == (unsigned)-1 ) */
+/* 					continue; */
+/* 				for( n_j = 0; n_j < nColNodes; n_j++ ) { */
+/* 					for( dof_j = 0; dof_j < colDofs->dofCounts[colNodes[n_j]]; dof_j++ ) { */
+/* 						if( colEqNum->locationMatrix[e_i][n_j][dof_j] == (unsigned)-1 ) */
+/* 							break; */
+/* 					} */
+/* 					if( dof_j < colDofs->dofCounts[colNodes[n_j]] ) */
+/* 						break; */
+/* 				} */
+/* 				if( n_j < nColNodes ) */
+/* 					break; */
+/* 			} */
+/* 			if( dof_i < rowDofs->dofCounts[rowNodes[n_i]] ) */
+/* 				break; */
+/* 		} */
+/* 		if( n_i == nRowNodes ) */
+/* 			continue; */
+
+/* 		/\* Do we need more space to assemble this element? *\/ */
+/* 		nRowDofs = 0; */
+/* 		for( n_i = 0; n_i < nRowNodes; n_i++ ) */
+/* 			nRowDofs += rowDofs->dofCounts[rowNodes[n_i]]; */
+/* 		nColDofs = 0; */
+/* 		for( n_i = 0; n_i < nColNodes; n_i++ ) */
+/* 			nColDofs += colDofs->dofCounts[colNodes[n_i]]; */
+/* 		nDofs = nRowDofs * nColDofs; */
+/* 		if( nDofs > maxDofs ) { */
+/* #if 0 */
+/* 			elStiffMat = ReallocArray2D( elStiffMat, double, nRowDofs, nColDofs ); */
+/* #endif */
+/* 			values = ReallocArray( values, double, nDofs ); */
+/* 			indices = ReallocArray( indices, unsigned, nDofs ); */
+/* 			maxDofs = nDofs; */
+/* 		} */
+
+/* #if 0 */
+/* 		/\* Assemble the element. *\/ */
+/* 		memset( &elStiffMat[0][0], 0, nDofs * sizeof(double) ); */
+/* 		StiffnessMatrix_AssembleElement( self, e_i, sle, elStiffMat ); */
+/* #endif */
+
+/* 		elStiffMat = ((PETScShellMatrix*)self->matrix)->elStiffMat;	assert( elStiffMat ); */
+
+/* 		/\* Update the force vector with BCs. *\/ */
+/* 		curRow = 0; */
+/* 		memset( values, 0, nDofs * sizeof(double) ); */
+/* 		for( n_i = 0; n_i < nRowNodes; n_i++ ) { */
+/* 			for( dof_i = 0; dof_i < rowDofs->dofCounts[rowNodes[n_i]]; dof_i++ ) { */
+/* 				indices[curRow] = rowEqNum->locationMatrix[e_i][n_i][dof_i]; */
+/* 				if( indices[curRow] == (unsigned)-1 ) { */
+/* 					curRow++; */
+/* 					continue; */
+/* 				} */
+
+/* 				curCol = 0; */
+/* 				for( n_j = 0; n_j < nColNodes; n_j++ ) { */
+/* 					for( dof_j = 0; dof_j < colDofs->dofCounts[colNodes[n_j]]; dof_j++ ) { */
+/* 						colEq = colEqNum->locationMatrix[e_i][n_j][dof_j]; */
+/* 						if( colEq != (unsigned)-1 ) { */
+/* 							curCol++; */
+/* 							continue; */
+/* 						} */
+
+/* 						bc = DofLayout_GetValueDouble( colDofs, colNodes[n_j], dof_j ); */
+/* 						values[curRow] -= elStiffMat[curRow][curCol] * bc; */
+
+/* 						curCol++; */
+/* 					} */
+/* 				} */
+
+/* 				curRow++; */
+/* 			} */
+/* 		} */
+
+/* 		VecSetValues( rhs, curRow, indices, values, ADD_VALUES ); */
+/* 	} */
+
+/* 	FreeArray( values ); */
+/* 	FreeArray( indices ); */
+
+/* 	VecAssemblyBegin( rhs ); */
+/* 	VecAssemblyEnd( rhs ); */
+/* } */
+
+
+
+/* +++ PRIVATE FUNCTIONS +++ */
+	
+void _StiffnessMatrix_UpdateBC_CorrectionTables(
+	StiffnessMatrix*	self,
+	FeEquationNumber*	eqNum, 
+	DofLayout*		dofLayout,
+	Dof_EquationNumber**	elementLM,
+	Node_ElementLocalIndex	nodeCountThisEl,
+	Element_Nodes		nodeIdsThisEl,
+	Dof_Index*		bcLM_Id,
+	double*			bcValues,
+	int*			nBC_NodalDofPtr )
+{
+	Node_ElementLocalIndex		node_elLocalI = 0;
+	Node_LocalIndex			node_lI = 0;
+	Dof_Index*			dofCounts = dofLayout->dofCounts;
+	Dof_Index			dofCountThisNode=0;
+	Dof_Index			dof_nodeLocalI=0;
+	unsigned			pos = 0;
+
+	for( node_elLocalI = 0; node_elLocalI < nodeCountThisEl; node_elLocalI++ ) {
+		node_lI = nodeIdsThisEl[node_elLocalI];
+		dofCountThisNode = dofCounts[node_lI];
+		
+		for( dof_nodeLocalI = 0; dof_nodeLocalI < dofCountThisNode; dof_nodeLocalI++ ) {
+			Bool	isBC = False;
+
+			/* Can only use 'elementLM' if FeEquationNumber has been told to remove BCs.  Otherwise
+			   we'll need to determine if the VariableCondition has a value specified for this 
+			   node/dof. - Luke */
+			if( elementLM[node_elLocalI][dof_nodeLocalI] != (unsigned)-1 ) {
+				unsigned	lEqNum;
+
+				lEqNum = *(int*)STreeMap_Map( eqNum->ownedMap,
+							      elementLM[node_elLocalI] + dof_nodeLocalI );
+
+				if( eqNum->bcEqNums && STree_Has( eqNum->bcEqNums, &lEqNum ) ) {
+					isBC = True;
+				}
+			}
+			else {
+				isBC = True;
+			}
+
+			if ( isBC ) {
+				/* offset into the elementStiffness matrix */
+				bcLM_Id[ *nBC_NodalDofPtr ] = pos;
+/*
+  bcLM_Id[ *nBC_NodalDofPtr ] = &elementLM[node_elLocalI][dof_nodeLocalI] - &elementLM[0][0];
+*/
+
+/* 				 get bc values from the bc_layout  */
+				bcValues[ *nBC_NodalDofPtr ]  = DofLayout_GetValueDouble( dofLayout, node_lI, dof_nodeLocalI );
+
+				Journal_DPrintfL( self->debug, 3, "bcValues[%d]: at &LM[0][0] + %d=%d, is %f\n",
+						  *nBC_NodalDofPtr, bcLM_Id[ *nBC_NodalDofPtr ],
+						  elementLM[0][ bcLM_Id[ *nBC_NodalDofPtr ] ],
+						  bcValues[ *nBC_NodalDofPtr ] );
+
+				(*nBC_NodalDofPtr)++;
+			}
+
+			/* Move to next element stiffness matrix entry. */
+			pos++;
+		}
+	}
+}	
+
+
+void _StiffnessMatrix_CorrectForceVectorWithOneElementsBoundaryConditions(
+	StiffnessMatrix*	self,
+	Dof_EquationNumber** 	elementLM[MAX_FE_VARS],
+	double*			h2Add,
+	double** 		elStiffMatToAdd,
+	Dof_Index*		totalDofsThisElement[MAX_FE_VARS],
+	Dof_Index*		bcLM_Id[MAX_FE_VARS],
+	double*			bcValues[MAX_FE_VARS],
+	int			nBC_NodalDof_Row, 
+	unsigned		elementInd /* NEW ONE */ )
+{
+#if 0
+	int 		rowEqId;
+	double		bc_value;
+	Dof_Index	colDof_elLocalI;
+#endif
+
+	memset( h2Add, 0, (*totalDofsThisElement[COL_VAR]) * sizeof(double) );
+
+	/*
+	** Something fishy is up with BC corrections, adding this for now.
+	*/
+
+	if( self->rowVariable != self->columnVariable )	{
+		Mesh			*rowMesh, *colMesh;
+		FeEquationNumber	*rowEqNum, *colEqNum;
+		DofLayout		*rowDofs, *colDofs;
+		unsigned		nRowElNodes, *rowElNodes, nColElNodes, *colElNodes;
+		unsigned		nRowDofs, nColDofs;
+		unsigned		dofI, dofJ, elIndI, elIndJ;
+		double			bcValue;
+		unsigned		n_i, n_j, d_i, d_j;
+
+		rowMesh = (Mesh*)self->rowVariable->feMesh;
+		colMesh = (Mesh*)self->columnVariable->feMesh;
+		rowEqNum = self->rowVariable->eqNum;
+		colEqNum = self->columnVariable->eqNum;
+		rowDofs = rowEqNum->dofLayout;
+		colDofs = colEqNum->dofLayout;
+		Mesh_GetIncidence( rowMesh, Mesh_GetDimSize( rowMesh ), elementInd, MT_VERTEX, self->rowInc );
+		nRowElNodes = IArray_GetSize( self->rowInc );
+		rowElNodes = (unsigned*)IArray_GetPtr( self->rowInc );
+		Mesh_GetIncidence( colMesh, Mesh_GetDimSize( colMesh ), elementInd, MT_VERTEX, self->colInc );
+		nColElNodes = IArray_GetSize( self->colInc );
+		colElNodes = (unsigned*)IArray_GetPtr( self->colInc );
+		nRowDofs = rowDofs->dofCounts[0];
+		nColDofs = colDofs->dofCounts[0];
+
+		for( n_i = 0; n_i < nColElNodes; n_i++ ) {
+			for( d_i = 0; d_i < nColDofs; d_i++ ) {
+				dofI = colEqNum->locationMatrix[elementInd][n_i][d_i];
+				if( dofI == -1 )
+					continue;
+
+				elIndI = n_i * nColDofs + d_i;
+				for( n_j = 0; n_j < nRowElNodes; n_j++ ) {
+					for( d_j = 0; d_j < nRowDofs; d_j++ ) {
+						dofJ = rowEqNum->locationMatrix[elementInd][n_j][d_j];
+						if( dofJ != -1 )
+							continue;
+
+						elIndJ = n_j * nRowDofs + d_j;
+						bcValue = DofLayout_GetValueDouble( rowDofs, rowElNodes[n_j], d_j );
+						h2Add[elIndI] -= elStiffMatToAdd[elIndJ][elIndI] * bcValue;
+					}
+				}
+			}
+		}
+	}
+	else {
+		Mesh			*rowMesh, *colMesh;
+		FeEquationNumber	*rowEqNum, *colEqNum;
+		DofLayout		*rowDofs, *colDofs;
+		unsigned		nRowElNodes, *rowElNodes, nColElNodes, *colElNodes;
+		unsigned		nRowDofs, nColDofs;
+		unsigned		dofI, dofJ, elIndI, elIndJ;
+		double			bcValue;
+		unsigned		n_i, n_j, d_i, d_j;
+
+		rowMesh = (Mesh*)self->rowVariable->feMesh;
+		colMesh = (Mesh*)self->columnVariable->feMesh;
+		rowEqNum = self->rowVariable->eqNum;
+		colEqNum = self->columnVariable->eqNum;
+		rowDofs = rowEqNum->dofLayout;
+		colDofs = colEqNum->dofLayout;
+		Mesh_GetIncidence( rowMesh, Mesh_GetDimSize( rowMesh ), elementInd, MT_VERTEX, self->rowInc );
+		nRowElNodes = IArray_GetSize( self->rowInc );
+		rowElNodes = (unsigned*)IArray_GetPtr( self->rowInc );
+		Mesh_GetIncidence( colMesh, Mesh_GetDimSize( colMesh ), elementInd, MT_VERTEX, self->colInc );
+		nColElNodes = IArray_GetSize( self->colInc );
+		colElNodes = (unsigned*)IArray_GetPtr( self->colInc );
+		nRowDofs = rowDofs->dofCounts[0];
+		nColDofs = colDofs->dofCounts[0];
+
+		for( n_i = 0; n_i < nRowElNodes; n_i++ ) {
+			for( d_i = 0; d_i < nRowDofs; d_i++ ) {
+				dofI = rowEqNum->locationMatrix[elementInd][n_i][d_i];
+				if( dofI == -1 )
+					continue;
+
+				elIndI = n_i * nRowDofs + d_i;
+				for( n_j = 0; n_j < nColElNodes; n_j++ ) {
+					for( d_j = 0; d_j < nColDofs; d_j++ ) {
+						dofJ = colEqNum->locationMatrix[elementInd][n_j][d_j];
+						if( dofJ != -1 )
+							continue;
+
+						elIndJ = n_j * nColDofs + d_j;
+						bcValue = DofLayout_GetValueDouble( colDofs, colElNodes[n_j], d_j );
+						h2Add[elIndI] -= elStiffMatToAdd[elIndI][elIndJ] * bcValue;
+					}
+				}
+			}
+		}
+	}
+
+#if 0
+	for( colDof_elLocalI=0; colDof_elLocalI < *totalDofsThisElement[COL_VAR]; colDof_elLocalI++ ) {
+		double		sum = 0.0;
+
+		for( bcDof_I=0; bcDof_I < nBC_NodalDof_Row; bcDof_I++ ) {
+			rowEqId = bcLM_Id[ROW_VAR][bcDof_I];
+			bc_value = bcValues[ROW_VAR][bcDof_I];
+/* 			printf("bc_value = %f \n",bc_value );  */
+			
+			/* this index is gets us to the right */
+			sum = sum - ( elStiffMatToAdd[rowEqId][colDof_elLocalI] * bc_value );
+		}
+		h2Add[colDof_elLocalI] = sum;
+	}
+#endif
+
+	VecSetValues( self->rhs->vector, *totalDofsThisElement[COL_VAR], elementLM[COL_VAR][0], h2Add, ADD_VALUES );
+	
+	/* assume that K is symetric, so corrections are made with KTrans.
+	   this allows us to use this func with G, when we want velocity
+	   corrections from GTrans to appear in H.
+	*/
+
+	/*
+	  for( bcDof_I=0; bcDof_I < nBC_NodalDof_row; bcDof_I++ ) {
+	  rowEqId = bcLM_Id[ROW_VAR][bcDof_I];
+	  bc_value = bcValues[ROW_VAR][bcDof_I];
+	  printf("bc_value = %f \n",bc_value ); 
+		
+	  printf("bc value = %f \n",bc_value );
+	  correct = 0;
+	  for( colDof_elLocalI=0; colDof_elLocalI< *totalDofsThisElement[COL_VAR]; colDof_elLocalI++ ) {
+	  h2Add[correct] = h2Add[correct]
+	  - elStiffMatToAdd[rowEqId* (*totalDofsThisElement[COL_VAR]) + colDof_elLocalI] * bc_value;
+	  hIdx[correct] = elementLM[COL_VAR][0][ colDof_elLocalI ];
+			
+	  correct = correct + 1;
+	  }
+	  }
+	  Vector_AddTo( self->rhs->vector, correct, hIdx, h2Add );
+	*/
+	
+	/* does not work */
+	/*for( rowDof_elLocalI=0; rowDof_elLocalI < *totalDofsThisElement[ROW_VAR]; rowDof_elLocalI++ ) {
+		double sum = 0.0;
+		for( rowDof_elLocalI=0; rowDof_elLocalI<nBC_NodalDof[ROW_VAR]; rowDof_elLocalI++ ) {
+		colEqId = bcLM_Id[COL_VAR][rowDof_elLocalI];
+		bc_value = bcValues[COL_VAR][rowDof_elLocalI];
+			
+		sum = sum + elStiffMatToAdd[ i* (*totalDofsThisElement[COL_VAR]) + colEqId] * bc_value;
+		}
+		h2Add[rowDof_elLocalI] = -sum;
+		}
+		Vector_AddTo( self->rhs->vector, *totalDofsThisElement[ROW_VAR], elementLM[ROW_VAR][0], h2Add ); */
+}
+
+void _StiffnessMatrix_PrintElementStiffnessMatrix(
+	StiffnessMatrix* self,
+	Element_LocalIndex element_lI,
+	Dof_EquationNumber** rowElementLM,
+	Dof_EquationNumber** colElementLM,
+	double** elStiffMatToAdd )
+{
+	FeMesh*			rFeMesh = self->rowVariable->feMesh;
+	FeMesh*			cFeMesh = self->columnVariable->feMesh;
+	Dof_Index		rowDofsPerNode;
+	Dof_Index		colDofsPerNode;
+	Node_LocalIndex		rowNodesThisEl;
+	Node_LocalIndex		colNodesThisEl;
+	Node_LocalIndex		rowNode_I, colNode_I;
+	Dof_Index		rowDof_I, colDof_I;
+	Index			rowIndex, colIndex;
+	unsigned		nRowElInc, *rowElInc;
+	unsigned		nColElInc, *colElInc;
+
+	FeMesh_GetElementNodes( rFeMesh, element_lI, self->rowInc );
+	nRowElInc = IArray_GetSize( self->rowInc );
+	rowElInc = (unsigned*)IArray_GetPtr( self->rowInc );
+	FeMesh_GetElementNodes( cFeMesh, element_lI, self->colInc );
+	nColElInc = IArray_GetSize( self->colInc );
+	colElInc = (unsigned*)IArray_GetPtr( self->colInc );
+
+	rowDofsPerNode = self->rowVariable->dofLayout->dofCounts[rowElInc[0]];
+	colDofsPerNode = self->columnVariable->dofLayout->dofCounts[colElInc[0]];
+	rowNodesThisEl = nRowElInc;
+	colNodesThisEl = nColElInc;
+
+	for ( rowNode_I=0; rowNode_I < rowNodesThisEl; rowNode_I++ ) {
+		for ( rowDof_I = 0; rowDof_I < rowDofsPerNode; rowDof_I++ ) {
+			for ( colNode_I=0; colNode_I < colNodesThisEl; colNode_I++ ) {
+				for ( colDof_I = 0; colDof_I < colDofsPerNode; colDof_I++ ) {
+					rowIndex = rowNode_I*rowDofsPerNode + rowDof_I;
+					colIndex = colNode_I*colDofsPerNode + colDof_I;
+
+					Journal_DPrintf( self->debug, "Row [%d][%d], Col [%d][%d] (LM (%4d,%4d)) = %.3f\n",
+						rowNode_I, rowDof_I,
+						colNode_I, colDof_I,
+						rowElementLM[rowNode_I][rowDof_I],
+						colElementLM[colNode_I][colDof_I],
+						elStiffMatToAdd[rowIndex][colIndex] ); 
+				}			
+			}
+		}
+	}
+}
+
+void StiffnessMatrix_AssembleElement(
+	void* stiffnessMatrix,
+	Element_LocalIndex element_lI,
+	SystemLinearEquations* sle,
+	FiniteElementContext* context,
+	double** elStiffMatToAdd )
+{
+	StiffnessMatrix*        self                      = (StiffnessMatrix*) stiffnessMatrix;
+	Index                   stiffnessMatrixTermCount  = Stg_ObjectList_Count( self->stiffnessMatrixTermList );
+	Index                   stiffnessMatrixTerm_I;
+	StiffnessMatrixTerm*    stiffnessMatrixTerm;
+
+	for ( stiffnessMatrixTerm_I = 0 ; stiffnessMatrixTerm_I < stiffnessMatrixTermCount ; stiffnessMatrixTerm_I++ ) {
+		stiffnessMatrixTerm = (StiffnessMatrixTerm*) Stg_ObjectList_At( self->stiffnessMatrixTermList, stiffnessMatrixTerm_I );
+		StiffnessMatrixTerm_AssembleElement( stiffnessMatrixTerm, self, element_lI, sle, context, elStiffMatToAdd );
+	}
+}
+
+void StiffnessMatrix_CheckElementAssembly( 
+	void* stiffnessMatrix,
+	Element_LocalIndex element_lI,
+	double** elStiffMatToAdd,
+	Index elStiffMatToAddRowSize,
+	Index elStiffMatToAddColSize )
+{
+	StiffnessMatrix*  self = (StiffnessMatrix*)stiffnessMatrix;
+	Bool              atLeastOneNonZeroElementContributionEntry = False;
+	Index             elStiffMat_rowI = 0;
+	Index             elStiffMat_colI = 0;
+	Stream*           errorStream = Journal_Register( Error_Type, (Name)self->type );
+	
+	for ( elStiffMat_colI = 0; elStiffMat_colI < elStiffMatToAddColSize; elStiffMat_colI++ ) {
+		for ( elStiffMat_rowI = 0; elStiffMat_rowI < elStiffMatToAddColSize; elStiffMat_rowI++ ) {
+			if ( elStiffMatToAdd[elStiffMat_rowI][elStiffMat_colI] != 0.0 ) {
+				atLeastOneNonZeroElementContributionEntry = True;
+				break;
+			}	
+		}	
+		if ( atLeastOneNonZeroElementContributionEntry == True  ) {
+			break;
+		}	
+	}
+
+	Journal_Firewall( atLeastOneNonZeroElementContributionEntry == True, errorStream,
+		"Error - in %s(): while assembling matrix \"%s\", for element %u - elStiffMatToAdd assembled at this "
+		"element is all zeros."
+		"Did you register a stiffnessMatrixTerm? Is there at least one integration point in this "
+		"element?\n", __func__, self->name, element_lI  );
+}
+
+void StiffnessMatrix_AddStiffnessMatrixTerm( void* stiffnessMatrix, StiffnessMatrixTerm* stiffnessMatrixTerm ) {
+	StiffnessMatrix* self = (StiffnessMatrix*) stiffnessMatrix;
+
+	stiffnessMatrixTerm = Stg_CheckType( stiffnessMatrixTerm, StiffnessMatrixTerm );
+	Stg_ObjectList_Append( self->stiffnessMatrixTermList, stiffnessMatrixTerm );
+}
+
+void StiffnessMatrix_RefreshMatrix( StiffnessMatrix* self ) {
+	int nProcs;
+	
+	assert( self && Stg_CheckType( self, StiffnessMatrix ) );
+
+	/* Note: I'd like to make this a dereference, just in case there is another class still using 
+	   the old matrix, but that'd require two matrices to exist at one time; i.e. lots of memory. 
+	   Keeping it as a free just means that other classes need to assume they never own the matrix. */
+	/*if( self->useShellMatrix ) { 
+ 		PETScShellMatrix_SetComm( self->shellMatrix, self->comm ); 
+ 		PETScShellMatrix_SetLocalSize( self->shellMatrix, self->rowLocalSize, self->colLocalSize ); 
+ 		PETScShellMatrix_SetNonZeroStructure( self->shellMatrix, self->nonZeroCount, self->diagonalNonZeroIndices, self->offDiagonalNonZeroIndices ); 
+	} 
+ 	else { */
+		if( self->matrix != PETSC_NULL )
+			MatDestroy( self->matrix );
+
+		MatCreate( self->comm, &self->matrix );
+		MatSetSizes( self->matrix, self->rowLocalSize, self->colLocalSize, PETSC_DETERMINE, PETSC_DETERMINE );
+		MatSetFromOptions( self->matrix );
+		MPI_Comm_size( self->comm, &nProcs );
+
+		if( self->diagonalNonZeroIndices || self->offDiagonalNonZeroIndices ) {
+			if( nProcs > 1 )
+                          MatMPIAIJSetPreallocation( self->matrix, PETSC_NULL, (PetscInt*)(self->diagonalNonZeroIndices), PETSC_NULL, (PetscInt*)(self->offDiagonalNonZeroIndices) );
+			else
+                          MatSeqAIJSetPreallocation( self->matrix, PETSC_NULL, (PetscInt*)(self->diagonalNonZeroIndices) );
+		}
+		else {
+			if( nProcs > 1 )
+				MatMPIAIJSetPreallocation( self->matrix, self->nonZeroCount, PETSC_NULL, self->nonZeroCount, PETSC_NULL );
+			else
+				MatSeqAIJSetPreallocation( self->matrix, self->nonZeroCount, PETSC_NULL );
+		}
+	/*}*/
+}
+
+void StiffnessMatrix_CalcNonZeros( void* stiffnessMatrix ) {
+	StiffnessMatrix* self = (StiffnessMatrix*)stiffnessMatrix;
+	Stream *stream;
+	FeVariable *rowVar, *colVar;
+	FeMesh *rowMesh, *colMesh;
+	FeEquationNumber *rowEqNum, *colEqNum;
+	DofLayout *rowDofs, *colDofs;
+	int nRowEqs, nColEqs;
+	int nColNodes, *colNodes;
+	int nNodeEls, *nodeEls;
+	int *nDiagNonZeros, *nOffDiagNonZeros;
+	int rowEq, colEq, localRowEq;
+	int netNonZeros;
+	STree *candColEqs;
+	int e_i;
+	int n_i, dof_i;
+	int n_j, dof_j;
+
+	assert( self && Stg_CheckType( self, StiffnessMatrix ) );
+	assert( self->rowVariable );
+
+	stream = Journal_Register( Info_Type, (Name)self->type  );
+	Journal_Printf( stream, "Stiffness matrix: '%s'\n", self->name );
+	Stream_Indent( stream );
+	Journal_Printf( stream, "Calculating number of nonzero entries...\n" );
+	Stream_Indent( stream );
+
+	rowVar = self->rowVariable;
+	colVar = self->columnVariable ? self->columnVariable : rowVar;
+	rowMesh = rowVar->feMesh;
+	colMesh = colVar->feMesh;
+	rowEqNum = rowVar->eqNum;
+	colEqNum = colVar->eqNum;
+	nRowEqs = rowEqNum->localEqNumsOwnedCount;
+	nColEqs = colEqNum->localEqNumsOwnedCount;
+	rowDofs = rowVar->dofLayout;
+	colDofs = colVar->dofLayout;
+
+	candColEqs = STree_New();
+	STree_SetIntCallbacks( candColEqs );
+	STree_SetItemSize( candColEqs, sizeof(int) );
+	nDiagNonZeros = AllocArray( int, nRowEqs );
+	nOffDiagNonZeros = AllocArray( int, nRowEqs );
+	memset( nDiagNonZeros, 0, nRowEqs * sizeof(int) );
+	memset( nOffDiagNonZeros, 0, nRowEqs * sizeof(int) );
+	netNonZeros = 0;
+
+	for( n_i = 0; n_i < FeMesh_GetNodeLocalSize( rowMesh ); n_i++ ) {
+		for( dof_i = 0; dof_i < rowDofs->dofCounts[n_i]; dof_i++ ) {
+			rowEq = rowEqNum->destinationArray[n_i][dof_i];
+
+			if( rowEq == -1 ) continue;
+			if( !STreeMap_HasKey( rowEqNum->ownedMap, &rowEq ) ) continue;
+
+			localRowEq = *(int*)STreeMap_Map( rowEqNum->ownedMap, &rowEq );
+			FeMesh_GetNodeElements( rowMesh, n_i, self->rowInc );
+			nNodeEls = IArray_GetSize( self->rowInc );
+			nodeEls = IArray_GetPtr( self->rowInc );
+			STree_Clear( candColEqs );
+
+			for( e_i = 0; e_i < nNodeEls; e_i++ ) {
+				/* ASSUME: Row and column meshes have one-to-one element overlap. */
+				FeMesh_GetElementNodes( colMesh, nodeEls[e_i], self->colInc );
+				nColNodes = IArray_GetSize( self->colInc );
+				colNodes = IArray_GetPtr( self->colInc );
+
+				for( n_j = 0; n_j < nColNodes; n_j++ ) {
+					for( dof_j = 0; dof_j < colDofs->dofCounts[colNodes[n_j]]; dof_j++ ) {
+						colEq = colEqNum->destinationArray[colNodes[n_j]][dof_j];
+
+						if( colEq == -1 ) continue;
+						if( !STree_Has( candColEqs, &colEq  ) ) {
+							STree_Insert( candColEqs, &colEq );
+							if( STreeMap_HasKey( colEqNum->ownedMap, &colEq ) )
+								nDiagNonZeros[localRowEq]++;
+							else
+								nOffDiagNonZeros[localRowEq]++;
+							netNonZeros++;
+						}
+					}
+				}
+			}
+      }
+   }
+        self->diagonalNonZeroIndices = (Index*)nDiagNonZeros;
+   self->offDiagonalNonZeroIndices = (Index*)nOffDiagNonZeros;
+
+   {
+      int tmp;
+      MPI_Allreduce( &netNonZeros, &tmp, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD );
+      netNonZeros = tmp;
+   }
+   Journal_Printf( stream, "Found %d nonzero entries.\n", netNonZeros );
+   Journal_Printf( stream, "Done.\n" );
+   Stream_UnIndent( stream );
+   Stream_UnIndent( stream );
+}
+
+
+Bool StiffnessMatrix_ZeroBCsAsm_RowR( void* stiffMat, Assembler* assm ) {
+	memset( ((StiffnessMatrix*)stiffMat)->elStiffMat[assm->rowInd], 0, ((StiffnessMatrix*)stiffMat)->nColDofs * sizeof(double) );
+
+	return False;
+}
+
+Bool StiffnessMatrix_ZeroBCsAsm_ColR( void* stiffMat, Assembler* assm ) {
+	((StiffnessMatrix*)stiffMat)->elStiffMat[assm->rowInd][assm->colInd] = 0.0;
+	return True;
+}
+
+Bool StiffnessMatrix_BCAsm_ColR( void* stiffMat, Assembler* assm ) {
+	double	bc;
+
+	bc = DofLayout_GetValueDouble( assm->colVar->dofLayout, assm->colNodeInd, assm->colDofInd );
+	((StiffnessMatrix*)stiffMat)->bcVals[assm->rowInd] -= bc * ((StiffnessMatrix*)stiffMat)->elStiffMat[assm->rowInd][assm->colInd];
+
+	return True;
+}
+
+Bool StiffnessMatrix_TransBCAsm_ColR( void* stiffMat, Assembler* assm ) {
+	double	bc;
+
+	bc = DofLayout_GetValueDouble( assm->colVar->dofLayout, assm->colNodeInd, assm->colDofInd );
+	((StiffnessMatrix*)stiffMat)->bcVals[assm->rowInd] -= bc * ((StiffnessMatrix*)stiffMat)->elStiffMat[assm->colInd][assm->rowInd];
+
+	return True;
+}
+
+Bool StiffnessMatrix_DiagBCsAsm_RowR( void* stiffMat, Assembler* assm ) {
+	static const double	one = 1.0;
+
+	MatSetValues( ((StiffnessMatrix*)stiffMat)->matrix, 1, (PetscInt*)(&assm->rowEq), 1, (PetscInt*)(&assm->rowEq), (double*)&one, ADD_VALUES );
+
+	return True;
+}
+
+void StiffnessMatrix_AddModifyCallback( StiffnessMatrix* self, void* callback, void* object ) {
+   self->nModifyCBs++;
+   self->modifyCBs = ReallocArray( self->modifyCBs, Callback, self->nModifyCBs );
+   self->modifyCBs[self->nModifyCBs - 1].callback = callback;
+   self->modifyCBs[self->nModifyCBs - 1].object = object;
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/StiffnessMatrixTerm.c
--- a/SLE/SystemSetup/src/StiffnessMatrixTerm.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: StiffnessMatrixTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "FiniteElementContext.h"
-#include "StiffnessMatrixTerm.h"
-#include "SolutionVector.h"
-#include "StiffnessMatrix.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-#include "EntryPoint.h"
-
-/* Textual name of this class */
-const Type StiffnessMatrixTerm_Type = "StiffnessMatrixTerm";
-
-StiffnessMatrixTerm* StiffnessMatrixTerm_New(
-		Name                                                 name,
-		FiniteElementContext*                                context,
-		StiffnessMatrix*                                     stiffnessMatrix,
-		Swarm*                                               integrationSwarm,
-		Stg_Component*                                       extraInfo )		
-{
-	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*) _StiffnessMatrixTerm_DefaultNew( name );
-
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, extraInfo );
-
-	return self;
-}
-
-StiffnessMatrixTerm* _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_DEFARGS  )
-{
-	StiffnessMatrixTerm*		self;
-	
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(StiffnessMatrixTerm) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (StiffnessMatrixTerm*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-
-	self->_assembleElement = _assembleElement;
-	
-	return self;
-}
-
-
-void _StiffnessMatrixTerm_Init(
-		void*                                                stiffnessMatrixTerm,
-		FiniteElementContext*				                    context,
-		StiffnessMatrix*                                     stiffnessMatrix,
-		Swarm*                                               integrationSwarm,
-		Stg_Component*                                       extraInfo )
-{
-	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)  stiffnessMatrixTerm;
-	
-	self->isConstructed		= True;
-	self->context				= context;
-	self->debug					= Journal_MyStream( Debug_Type, self );
-	self->extraInfo			= extraInfo;	
-	self->integrationSwarm	= integrationSwarm;	
-	self->stiffnessMatrix	= stiffnessMatrix;
-	self->max_nElNodes		= 0; /* initialise to zero, in assembly routine it will change value */
-	self->GNx					= NULL;
-
-	StiffnessMatrix_AddStiffnessMatrixTerm( stiffnessMatrix, self );
-}
-
-void _StiffnessMatrixTerm_Delete( void* stiffnessMatrixTerm ) {
-	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-
-	/* Stg_Class_Delete parent*/
-	_Stg_Component_Delete( self );
-}
-
-
-void _StiffnessMatrixTerm_Print( void* stiffnessMatrixTerm, Stream* stream ) {
-	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-
-	/* General info */
-	Journal_Printf( stream, "StiffnessMatrixTerm (ptr): %p\n", self );
-	
-	/* Print parent */
-	_Stg_Component_Print( self, stream );
-	
-	/* StiffnessMatrixTerm info */
-	Journal_Printf( stream, "\tintegrationSwarm (ptr): %p\n", self->integrationSwarm );
-	Journal_Printf( stream, "\textraInfo (ptr): %p\n", self->extraInfo );
-}
-
-
-void* _StiffnessMatrixTerm_Copy( const void* stiffnessMatrixTerm, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	StiffnessMatrixTerm*	self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-	StiffnessMatrixTerm*	newStiffnessMatrixTerm;
-	PtrMap*		map = ptrMap;
-	Bool		ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newStiffnessMatrixTerm = (StiffnessMatrixTerm*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
-	
-	newStiffnessMatrixTerm->extraInfo = self->extraInfo;
-	if( deep ) {
-		newStiffnessMatrixTerm->integrationSwarm = (Swarm*)Stg_Class_Copy( self->integrationSwarm, NULL, deep, nameExt, map );
-	}
-	else {
-		newStiffnessMatrixTerm->integrationSwarm = self->integrationSwarm;
-	}
-	
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-	
-	return (void*)newStiffnessMatrixTerm;
-}
-
-void* _StiffnessMatrixTerm_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                 _sizeOfSelf = sizeof(StiffnessMatrixTerm);
-	Type                                                         type = StiffnessMatrixTerm_Type;
-	Stg_Class_DeleteFunction*                                 _delete = _StiffnessMatrixTerm_Delete;
-	Stg_Class_PrintFunction*                                   _print = _StiffnessMatrixTerm_Print;
-	Stg_Class_CopyFunction*                                     _copy = _StiffnessMatrixTerm_Copy;
-	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _StiffnessMatrixTerm_DefaultNew;
-	Stg_Component_ConstructFunction*                       _construct = _StiffnessMatrixTerm_AssignFromXML;
-	Stg_Component_BuildFunction*                               _build = _StiffnessMatrixTerm_Build;
-	Stg_Component_InitialiseFunction*                     _initialise = _StiffnessMatrixTerm_Initialise;
-	Stg_Component_ExecuteFunction*                           _execute = _StiffnessMatrixTerm_Execute;
-	Stg_Component_DestroyFunction*                           _destroy = _StiffnessMatrixTerm_Destroy;
-	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _StiffnessMatrixTerm_AssembleElement;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
-}
-
-void _StiffnessMatrixTerm_AssignFromXML( void* stiffnessMatrixTerm, Stg_ComponentFactory* cf, void* data ) {
-	StiffnessMatrixTerm*       self               = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-	Swarm*                     swarm              = NULL;
-	Stg_Component*             extraInfo;
-	StiffnessMatrix*           stiffnessMatrix;
-   FiniteElementContext*      context;
-   
-	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
-	if( !context  )
-		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
-
-	stiffnessMatrix = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"StiffnessMatrix", StiffnessMatrix, True, data  ) ;
-	swarm           = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Swarm", Swarm, True, data  ) ;
-	extraInfo       = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ExtraInfo", Stg_Component, False, data  );
-
-	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, swarm, extraInfo );
-}
-
-void _StiffnessMatrixTerm_Build( void* stiffnessMatrixTerm, void* data ) {
-	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-	
-	/* ensure integrationSwarm is built */
-	Stg_Component_Build( self->integrationSwarm, data, False );
-
-	if ( self->extraInfo ) 
-		Stg_Component_Build( self->extraInfo, data, False );
-		
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _StiffnessMatrixTerm_Initialise( void* stiffnessMatrixTerm, void* data ) {
-	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-	
-	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	Stg_Component_Initialise( self->integrationSwarm, data, False );
-	if ( self->extraInfo ) 
-		Stg_Component_Initialise( self->extraInfo, data, False );
-	
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _StiffnessMatrixTerm_Execute( void* stiffnessMatrixTerm, void* data ) {
-}
-
-void _StiffnessMatrixTerm_Destroy( void* stiffnessMatrixTerm, void* data ) {
-	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-	/* free GNx memory */
-	if( self->GNx ) Memory_Free( self->GNx );
-}
-
-void StiffnessMatrixTerm_AssembleElement( 
-			void*                             stiffnessMatrixTerm, 
-			StiffnessMatrix*                  stiffnessMatrix, 
-			Element_LocalIndex                lElement_I,
-			SystemLinearEquations*            sle,
-			FiniteElementContext*             context,
-			double**                          elStiffMatToAdd ) 
-{
-	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-
-	self->_assembleElement( self, stiffnessMatrix, lElement_I, sle, context, elStiffMatToAdd );
-}
-	
-void _StiffnessMatrixTerm_AssembleElement( 
-			void*                             stiffnessMatrixTerm, 
-			StiffnessMatrix*                  stiffnessMatrix, 
-			Element_LocalIndex                lElement_I,
-			SystemLinearEquations*            sle,
-			FiniteElementContext*             context,
-			double**                          elStiffMatToAdd ) 
-{
-	StiffnessMatrixTerm* self        = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-	Stream*    errorStream = Journal_Register( Error_Type, (Name)self->type  );
-
-	Journal_Printf( errorStream, "Error in func %s for %s '%s' - "
-			"This function is the default function which should never be called - "
-			"Please set this virtual function with appropriate application dependent function.\n",
-			__func__, self->type, self->name );
-	abort();
-}	
-
-void StiffnessMatrixTerm_SetAssembleElementFunction( void* stiffnessMatrixTerm, StiffnessMatrixTerm_AssembleElementFunction* assembleElementFunction ) {
-	StiffnessMatrixTerm* self        = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
-
-	self->_assembleElement = assembleElementFunction;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/StiffnessMatrixTerm.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/StiffnessMatrixTerm.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,285 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: StiffnessMatrixTerm.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "FiniteElementContext.h"
+#include "StiffnessMatrixTerm.h"
+#include "SolutionVector.h"
+#include "StiffnessMatrix.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "EntryPoint.h"
+
+/* Textual name of this class */
+const Type StiffnessMatrixTerm_Type = "StiffnessMatrixTerm";
+
+StiffnessMatrixTerm* StiffnessMatrixTerm_New(
+		Name                                                 name,
+		FiniteElementContext*                                context,
+		StiffnessMatrix*                                     stiffnessMatrix,
+		Swarm*                                               integrationSwarm,
+		Stg_Component*                                       extraInfo )		
+{
+	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*) _StiffnessMatrixTerm_DefaultNew( name );
+
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, integrationSwarm, extraInfo );
+
+	return self;
+}
+
+StiffnessMatrixTerm* _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_DEFARGS  )
+{
+	StiffnessMatrixTerm*		self;
+	
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(StiffnessMatrixTerm) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (StiffnessMatrixTerm*)_Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+
+	self->_assembleElement = _assembleElement;
+	
+	return self;
+}
+
+
+void _StiffnessMatrixTerm_Init(
+		void*                                                stiffnessMatrixTerm,
+		FiniteElementContext*				                    context,
+		StiffnessMatrix*                                     stiffnessMatrix,
+		Swarm*                                               integrationSwarm,
+		Stg_Component*                                       extraInfo )
+{
+	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)  stiffnessMatrixTerm;
+	
+	self->isConstructed		= True;
+	self->context				= context;
+	self->debug					= Journal_MyStream( Debug_Type, self );
+	self->extraInfo			= extraInfo;	
+	self->integrationSwarm	= integrationSwarm;	
+	self->stiffnessMatrix	= stiffnessMatrix;
+	self->max_nElNodes		= 0; /* initialise to zero, in assembly routine it will change value */
+	self->GNx					= NULL;
+
+	StiffnessMatrix_AddStiffnessMatrixTerm( stiffnessMatrix, self );
+}
+
+void _StiffnessMatrixTerm_Delete( void* stiffnessMatrixTerm ) {
+	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+
+	/* Stg_Class_Delete parent*/
+	_Stg_Component_Delete( self );
+}
+
+
+void _StiffnessMatrixTerm_Print( void* stiffnessMatrixTerm, Stream* stream ) {
+	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+
+	/* General info */
+	Journal_Printf( stream, "StiffnessMatrixTerm (ptr): %p\n", self );
+	
+	/* Print parent */
+	_Stg_Component_Print( self, stream );
+	
+	/* StiffnessMatrixTerm info */
+	Journal_Printf( stream, "\tintegrationSwarm (ptr): %p\n", self->integrationSwarm );
+	Journal_Printf( stream, "\textraInfo (ptr): %p\n", self->extraInfo );
+}
+
+
+void* _StiffnessMatrixTerm_Copy( const void* stiffnessMatrixTerm, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	StiffnessMatrixTerm*	self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+	StiffnessMatrixTerm*	newStiffnessMatrixTerm;
+	PtrMap*		map = ptrMap;
+	Bool		ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newStiffnessMatrixTerm = (StiffnessMatrixTerm*)_Stg_Component_Copy( self, dest, deep, nameExt, map );
+	
+	newStiffnessMatrixTerm->extraInfo = self->extraInfo;
+	if( deep ) {
+		newStiffnessMatrixTerm->integrationSwarm = (Swarm*)Stg_Class_Copy( self->integrationSwarm, NULL, deep, nameExt, map );
+	}
+	else {
+		newStiffnessMatrixTerm->integrationSwarm = self->integrationSwarm;
+	}
+	
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+	
+	return (void*)newStiffnessMatrixTerm;
+}
+
+void* _StiffnessMatrixTerm_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                 _sizeOfSelf = sizeof(StiffnessMatrixTerm);
+	Type                                                         type = StiffnessMatrixTerm_Type;
+	Stg_Class_DeleteFunction*                                 _delete = _StiffnessMatrixTerm_Delete;
+	Stg_Class_PrintFunction*                                   _print = _StiffnessMatrixTerm_Print;
+	Stg_Class_CopyFunction*                                     _copy = _StiffnessMatrixTerm_Copy;
+	Stg_Component_DefaultConstructorFunction*     _defaultConstructor = _StiffnessMatrixTerm_DefaultNew;
+	Stg_Component_ConstructFunction*                       _construct = _StiffnessMatrixTerm_AssignFromXML;
+	Stg_Component_BuildFunction*                               _build = _StiffnessMatrixTerm_Build;
+	Stg_Component_InitialiseFunction*                     _initialise = _StiffnessMatrixTerm_Initialise;
+	Stg_Component_ExecuteFunction*                           _execute = _StiffnessMatrixTerm_Execute;
+	Stg_Component_DestroyFunction*                           _destroy = _StiffnessMatrixTerm_Destroy;
+	StiffnessMatrixTerm_AssembleElementFunction*     _assembleElement = _StiffnessMatrixTerm_AssembleElement;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _StiffnessMatrixTerm_New(  STIFFNESSMATRIXTERM_PASSARGS  );
+}
+
+void _StiffnessMatrixTerm_AssignFromXML( void* stiffnessMatrixTerm, Stg_ComponentFactory* cf, void* data ) {
+	StiffnessMatrixTerm*       self               = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+	Swarm*                     swarm              = NULL;
+	Stg_Component*             extraInfo;
+	StiffnessMatrix*           stiffnessMatrix;
+   FiniteElementContext*      context;
+   
+	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
+	if( !context  )
+		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  );
+
+	stiffnessMatrix = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"StiffnessMatrix", StiffnessMatrix, True, data  ) ;
+	swarm           = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Swarm", Swarm, True, data  ) ;
+	extraInfo       = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"ExtraInfo", Stg_Component, False, data  );
+
+	_StiffnessMatrixTerm_Init( self, context, stiffnessMatrix, swarm, extraInfo );
+}
+
+void _StiffnessMatrixTerm_Build( void* stiffnessMatrixTerm, void* data ) {
+	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+	
+	/* ensure integrationSwarm is built */
+	Stg_Component_Build( self->integrationSwarm, data, False );
+
+	if ( self->extraInfo ) 
+		Stg_Component_Build( self->extraInfo, data, False );
+		
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _StiffnessMatrixTerm_Initialise( void* stiffnessMatrixTerm, void* data ) {
+	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+	
+	Journal_DPrintf( self->debug, "In %s - for %s\n", __func__, self->name );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	Stg_Component_Initialise( self->integrationSwarm, data, False );
+	if ( self->extraInfo ) 
+		Stg_Component_Initialise( self->extraInfo, data, False );
+	
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _StiffnessMatrixTerm_Execute( void* stiffnessMatrixTerm, void* data ) {
+}
+
+void _StiffnessMatrixTerm_Destroy( void* stiffnessMatrixTerm, void* data ) {
+	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+	/* free GNx memory */
+	if( self->GNx ) Memory_Free( self->GNx );
+}
+
+void StiffnessMatrixTerm_AssembleElement( 
+			void*                             stiffnessMatrixTerm, 
+			StiffnessMatrix*                  stiffnessMatrix, 
+			Element_LocalIndex                lElement_I,
+			SystemLinearEquations*            sle,
+			FiniteElementContext*             context,
+			double**                          elStiffMatToAdd ) 
+{
+	StiffnessMatrixTerm* self = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+
+	self->_assembleElement( self, stiffnessMatrix, lElement_I, sle, context, elStiffMatToAdd );
+}
+	
+void _StiffnessMatrixTerm_AssembleElement( 
+			void*                             stiffnessMatrixTerm, 
+			StiffnessMatrix*                  stiffnessMatrix, 
+			Element_LocalIndex                lElement_I,
+			SystemLinearEquations*            sle,
+			FiniteElementContext*             context,
+			double**                          elStiffMatToAdd ) 
+{
+	StiffnessMatrixTerm* self        = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+	Stream*    errorStream = Journal_Register( Error_Type, (Name)self->type  );
+
+	Journal_Printf( errorStream, "Error in func %s for %s '%s' - "
+			"This function is the default function which should never be called - "
+			"Please set this virtual function with appropriate application dependent function.\n",
+			__func__, self->type, self->name );
+	abort();
+}	
+
+void StiffnessMatrixTerm_SetAssembleElementFunction( void* stiffnessMatrixTerm, StiffnessMatrixTerm_AssembleElementFunction* assembleElementFunction ) {
+	StiffnessMatrixTerm* self        = (StiffnessMatrixTerm*)stiffnessMatrixTerm;
+
+	self->_assembleElement = assembleElementFunction;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/SystemLinearEquations.c
--- a/SLE/SystemSetup/src/SystemLinearEquations.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1408 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student Monash University, VPAC. (davidm at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: SystemLinearEquations.c 1230 2008-09-15 01:44:43Z DavidLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <petsc.h>
-#include <petscvec.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "units.h"
-#include "types.h"
-#include "shortcuts.h"
-#include "SystemLinearEquations.h"
-#include "SLE_Solver.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <string.h>
-
-#include "StiffnessMatrix.h"
-#include "SolutionVector.h"
-#include "ForceVector.h"
-#include "FiniteElementContext.h"
-
-
-/* Textual name of this class */
-const Type SystemLinearEquations_Type = "SystemLinearEquations";
-
-/** Constructor */
-SystemLinearEquations* SystemLinearEquations_New(
-	Name							name,
-	SLE_Solver*					solver,
-	void*							nlSolver,
-	FiniteElementContext*	context,
-	Bool							isNonLinear,
-	double						nonLinearTolerance,
-	Iteration_Index			nonLinearMaxIterations,
-	Bool							killNonConvergent,		
-	EntryPoint_Register*		entryPoint_Register,
-	MPI_Comm						comm )
-{
-  SystemLinearEquations* self = (SystemLinearEquations*)_SystemLinearEquations_DefaultNew( name );
-
-	self->isConstructed = True;
-	_SystemLinearEquations_Init(
-		self,
-		solver,
-		nlSolver,
-		context,
-		False, /* TODO: A hack put in place for setting the convergence stream to 'off' if the SLE class is created from within the code, not via an xml */
-		isNonLinear,
-		nonLinearTolerance,
-		nonLinearMaxIterations,
-		killNonConvergent,
-		1, /* TODO : hack for setting the minimum number of iterations to 1- same hack as above */
-		"",
-		"",
-		entryPoint_Register,
-		comm );
-
-	return self;
-}
-
-/* Creation implementation / Virtual constructor */
-SystemLinearEquations* _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_DEFARGS  ) 
-{
-	SystemLinearEquations* self;
-
-	/* Allocate memory */
-	assert( _sizeOfSelf >= sizeof(SystemLinearEquations) );
-	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
-	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
-	   and so should be set to ZERO in any children of this class. */
-	nameAllocationType = NON_GLOBAL;
-
-	self = (SystemLinearEquations*) _Stg_Component_New(  STG_COMPONENT_PASSARGS  );
-	
-	/* Virtual info */
-	self->_LM_Setup = _LM_Setup;
-	self->_matrixSetup = _matrixSetup;
-	self->_vectorSetup = _vectorSetup;
-	self->_updateSolutionOntoNodes = _updateSolutionOntoNodes;
-	self->_mgSelectStiffMats = _mgSelectStiffMats;
-
-	self->_sleFormFunction = NULL;
-	
-	return self;
-}
-
-void _SystemLinearEquations_Init( 
-	void*							sle, 
-	SLE_Solver*					solver, 
-	void*							nlSolver,
-	FiniteElementContext*	context, 
-	Bool							makeConvergenceFile,  
-	Bool							isNonLinear,
-	double						nonLinearTolerance,
-	Iteration_Index			nonLinearMaxIterations,
-	Bool							killNonConvergent,
-	Iteration_Index			nonLinearMinIterations,
-	Name							nonLinearSolutionType,
-	Name							optionsPrefix,
-	EntryPoint_Register*		entryPoint_Register,
-	MPI_Comm						comm ) 
-{
-	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
-	char*							filename;
-	char*							optionsName;
-
-	self->extensionManager = ExtensionManager_New_OfExistingObject( self->name, self );
-	
-	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
-	self->info =  Journal_MyStream( Info_Type, self );
-    /* Note: currently we're sending self->info to the master proc only so there's not too much
-	   identical timing info printed. May want to fine-tune later so that some info does get 
-       printed on all procs. */	
-	Stream_SetPrintingRank( self->info, 0 );
-
-	self->makeConvergenceFile = makeConvergenceFile;
-	if ( self->makeConvergenceFile ) {
-		self->convergenceStream = Journal_Register( InfoStream_Type, (Name)"Convergence Info"  );
-		Stg_asprintf( &filename, "Convergence.dat" );
-		Stream_RedirectFile_WithPrependedPath( self->convergenceStream, context->outputPath, filename );
-		Stream_SetPrintingRank( self->convergenceStream, 0 );
-		Memory_Free( filename );
-		Journal_Printf( self->convergenceStream , "Timestep\tIteration\tResidual\tTolerance\n" );
-	}
-	
-	self->comm = comm;
-	self->solver = solver;
-	self->nlSolver = (SNES)nlSolver;
-	self->stiffnessMatrices = Stg_ObjectList_New();
-	self->forceVectors = Stg_ObjectList_New();
-	self->solutionVectors = Stg_ObjectList_New();
-	self->bcRemoveQuery = True;
-	self->context = context;
-
-	/* Init NonLinear Stuff */
-	self->nonLinearSolutionType = nonLinearSolutionType; /* This will never got propogated through to _Initialise->SetToNonLinear if we keep it in the loop */
-	if ( isNonLinear ) {
-		self->nonLinearSolutionType	= nonLinearSolutionType;
-		SystemLinearEquations_SetToNonLinear( self );
-	}
-	self->nonLinearTolerance        = nonLinearTolerance;
-	self->nonLinearMaxIterations    = nonLinearMaxIterations;
-	self->killNonConvergent         = killNonConvergent;
-	self->nonLinearMinIterations    = nonLinearMinIterations;    
-	self->curResidual               = 0.0;
-	self->curSolveTime              = 0.0;
-									     /* _  /0 */
-	optionsName = Memory_Alloc_Array_Unnamed( char, strlen(optionsPrefix) + 1 + 1 );
-	sprintf( optionsName, "%s_", optionsPrefix );
-	self->optionsPrefix = optionsName;
-
-	/* BEGIN LUKE'S FRICTIONAL BCS BIT */
-	Stg_asprintf( &self->nlSetupEPName, "%s-nlSetupEP", self->name );
-	self->nlSetupEP = EntryPoint_New( self->nlSetupEPName, EntryPoint_2VoidPtr_CastType );
-	Stg_asprintf( &self->nlEPName, "%s-nlEP", self->name );
-	self->nlEP = EntryPoint_New( self->nlEPName, EntryPoint_2VoidPtr_CastType );
-	Stg_asprintf( &self->nlEPName, "%s-postNlEP", self->name );
-	self->postNlEP = EntryPoint_New( self->postNlEPName, EntryPoint_2VoidPtr_CastType );
-	Stg_asprintf( &self->nlConvergedEPName, "%s-nlConvergedEP", self->name );
-	self->nlConvergedEP = EntryPoint_New( self->nlConvergedEPName, EntryPoint_2VoidPtr_CastType );
-	/* END LUKE'S FRICTIONAL BCS BIT */
-	self->nlFormJacobian = False;
-	self->nlCurIterate = PETSC_NULL;
-	
-	/* Initialise MG stuff. */
-	self->mgEnabled = False;
-	self->mgUpdate = True;
-	self->nMGHandles = 0;
-	self->mgHandles = NULL;
-	
-	/* Create Execute Entry Point */
-	Stg_asprintf( &self->executeEPName, "%s-execute", self->name );
-	self->executeEP = EntryPoint_New( self->executeEPName, EntryPoint_2VoidPtr_CastType );
-
-	/* Add default hooks to Execute E.P. */
-	EntryPoint_Append( self->executeEP, "BC_Setup", (void*)SystemLinearEquations_BC_Setup, self->type);
-	EntryPoint_Append( self->executeEP, "LM_Setup", (void*)SystemLinearEquations_LM_Setup, self->type);
-	EntryPoint_Append( self->executeEP, "IntegrationSetup", (void*)SystemLinearEquations_IntegrationSetup, self->type );
-	EntryPoint_Append( self->executeEP, "ZeroAllVectors", (void*)SystemLinearEquations_ZeroAllVectors, self->type);
-	EntryPoint_Append( self->executeEP, "MatrixSetup", (void*)SystemLinearEquations_MatrixSetup, self->type);
-	EntryPoint_Append( self->executeEP, "VectorSetup", (void*)SystemLinearEquations_VectorSetup, self->type);
-	EntryPoint_Append( self->executeEP, "ExecuteSolver", (void*)SystemLinearEquations_ExecuteSolver, self->type);
-	EntryPoint_Append( self->executeEP, "UpdateSolutionOntoNodes",(void*)SystemLinearEquations_UpdateSolutionOntoNodes,self->type);
-
-	/* Create Integration Setup EP */
-	Stg_asprintf( &self->integrationSetupEPName, "%s-integrationSetup", self->name );
-	self->integrationSetupEP = EntryPoint_New( self->integrationSetupEPName, EntryPoint_Class_VoidPtr_CastType );
-	
-	if ( entryPoint_Register )
-		EntryPoint_Register_Add( entryPoint_Register, self->executeEP );
-	self->entryPoint_Register = entryPoint_Register;
-
-	/* Add SLE to Context */
-	if ( context )
-		FiniteElementContext_AddSLE( context, self );
-}
-
-void _SystemLinearEquations_Delete( void* sle ) {
-	SystemLinearEquations* self = (SystemLinearEquations*)sle;
-	
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-	
-	/* delete parent */
-	_Stg_Component_Delete( self );
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void _SystemLinearEquations_Print( void* sle, Stream* stream ) {
-	SystemLinearEquations*		self = (SystemLinearEquations*)sle;
-	
-	/* General info */
-	Journal_Printf( stream, "SystemLinearEquations (ptr): %p\n", self );
-	_Stg_Component_Print( self, stream );
-	
-	/* Virtual info */
-	Stg_Class_Print( self->stiffnessMatrices, stream );
-	Stg_Class_Print( self->forceVectors, stream );
-	Stg_Class_Print( self->solutionVectors, stream );
-
-	/* other info */
-	Journal_PrintPointer( stream, self->extensionManager );
-	Journal_Printf( stream, "\tcomm: %u\n", self->comm );
-	Journal_Printf( stream, "\tsolver (ptr): %p\n", self->solver );
-	Stg_Class_Print( self->solver, stream );
-}
-
-void* _SystemLinearEquations_Copy( const void* sle, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
-	SystemLinearEquations*	newSLE;
-	PtrMap*			map = ptrMap;
-	Bool			ownMap = False;
-	
-	if( !map ) {
-		map = PtrMap_New( 10 );
-		ownMap = True;
-	}
-	
-	newSLE = (SystemLinearEquations*)_Stg_Component_Copy( sle, dest, deep, nameExt, map );
-	
-	/* Virtual methods */
-	newSLE->_LM_Setup = self->_LM_Setup;
-	newSLE->_matrixSetup = self->_matrixSetup;
-	newSLE->_vectorSetup = self->_vectorSetup;
-	newSLE->_mgSelectStiffMats = self->_mgSelectStiffMats;
-	
-	newSLE->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, newSLE->type );
-	newSLE->comm = self->comm;
-	
-	if( deep ) {
-		newSLE->solver = (SLE_Solver*)Stg_Class_Copy( self->solver, NULL, deep, nameExt, map );
-		newSLE->stiffnessMatrices = (StiffnessMatrixList*)Stg_Class_Copy( self->stiffnessMatrices, NULL, deep, nameExt, map );
-		newSLE->forceVectors = (ForceVectorList*)Stg_Class_Copy( self->forceVectors, NULL, deep, nameExt, map );
-		newSLE->solutionVectors = (SolutionVectorList*)Stg_Class_Copy( self->solutionVectors, NULL, deep, nameExt, map );
-		if( (newSLE->extensionManager = (ExtensionManager*)PtrMap_Find( map, self->extensionManager )) == NULL ) {
-                  newSLE->extensionManager = (ExtensionManager*)Stg_Class_Copy( self->extensionManager, NULL, deep, nameExt, map );
-			PtrMap_Append( map, self->extensionManager, newSLE->extensionManager );
-		}
-	}
-	else {
-		newSLE->solver = self->solver;
-		newSLE->stiffnessMatrices = self->stiffnessMatrices;
-		newSLE->forceVectors = self->forceVectors;
-		newSLE->solutionVectors = self->solutionVectors;
-	}
-	
-	if( ownMap ) {
-		Stg_Class_Delete( map );
-	}
-	
-	return newSLE;
-}
-
-void* _SystemLinearEquations_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                                            _sizeOfSelf = sizeof(SystemLinearEquations);
-	Type                                                                    type = SystemLinearEquations_Type;
-	Stg_Class_DeleteFunction*                                            _delete = _SystemLinearEquations_Delete;
-	Stg_Class_PrintFunction*                                              _print = _SystemLinearEquations_Print;
-	Stg_Class_CopyFunction*                                                _copy = _SystemLinearEquations_Copy;
-	Stg_Component_DefaultConstructorFunction*                _defaultConstructor = _SystemLinearEquations_DefaultNew;
-	Stg_Component_ConstructFunction*                                  _construct = _SystemLinearEquations_AssignFromXML;
-	Stg_Component_BuildFunction*                                          _build = _SystemLinearEquations_Build;
-	Stg_Component_InitialiseFunction*                                _initialise = _SystemLinearEquations_Initialise;
-	Stg_Component_ExecuteFunction*                                      _execute = _SystemLinearEquations_Execute;
-	Stg_Component_DestroyFunction*                                      _destroy = _SystemLinearEquations_Destroy;
-	SystemLinearEquations_LM_SetupFunction*                            _LM_Setup = _SystemLinearEquations_LM_Setup;
-	SystemLinearEquations_MatrixSetupFunction*                      _matrixSetup = _SystemLinearEquations_MatrixSetup;
-	SystemLinearEquations_VectorSetupFunction*                      _vectorSetup = _SystemLinearEquations_VectorSetup;
-	SystemLinearEquations_UpdateSolutionOntoNodesFunc*  _updateSolutionOntoNodes = _SystemLinearEquations_UpdateSolutionOntoNodes;
-	SystemLinearEquations_MG_SelectStiffMatsFunc*             _mgSelectStiffMats = _SystemLinearEquations_MG_SelectStiffMats;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_PASSARGS  );
-}
-
-void _SystemLinearEquations_AssignFromXML( void* sle, Stg_ComponentFactory* cf, void* data ){
-	SystemLinearEquations*  self = (SystemLinearEquations*)sle;
-	SLE_Solver*             solver = NULL;
-	void*                   entryPointRegister = NULL;
-	FiniteElementContext*   context = NULL;
-	double                  nonLinearTolerance;
-	Iteration_Index         nonLinearMaxIterations;
-	Bool                    isNonLinear;
-	Bool                    killNonConvergent;
-	Bool                    makeConvergenceFile;
-	Iteration_Index         nonLinearMinIterations;                     
-	Name							nonLinearSolutionType;
-	SNES                    nlSolver = NULL;
-	Name							optionsPrefix;
-	
-	solver = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)SLE_Solver_Type, SLE_Solver, False, data  ) ;
-
-	makeConvergenceFile		= Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"makeConvergenceFile", False  );
-	isNonLinear					= Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"isNonLinear", False  );
-	nonLinearTolerance		= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"nonLinearTolerance", 0.01  );
-	nonLinearMaxIterations	= Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"nonLinearMaxIterations", 500  );
-	killNonConvergent			= Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"killNonConvergent", True  );
-	nonLinearMinIterations 	= Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"nonLinearMinIterations", 1  );
-	nonLinearSolutionType	= Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"nonLinearSolutionType", "default"  );
-	optionsPrefix				= Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"optionsPrefix", ""  );
-
-	/* Read some value for Picard */
-	self->picard_form_function_type = Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"picard_FormFunctionType", "PicardFormFunction_KSPResidual"  );
-
-	self->alpha				= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"picard_alpha", 1.0  );
-	self->rtol				= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"picard_rtol", 1.0e-8  );
-	self->abstol			= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"picard_atol", 1.0e-50  );        
-	self->xtol				= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"picard_xtol", 1.0e-8  );
-	self->picard_monitor	= Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"picard_ActivateMonitor", False  );
-	
-	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
-	if( !context  )
-		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data );
-
-	entryPointRegister = context->entryPoint_Register;
-	assert( entryPointRegister );
-
-	if( isNonLinear  ) {
-		SNESCreate( context->communicator, &nlSolver );
-		self->linearSolveInitGuess = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"linearSolveInitialGuess", False  );
-	}
-	
-	_SystemLinearEquations_Init( 
-		self,
-		solver,
-		nlSolver,
-		context,
-		makeConvergenceFile,
-		isNonLinear,
-		nonLinearTolerance, 
-		nonLinearMaxIterations,
-		killNonConvergent, 
-		nonLinearMinIterations,
-		nonLinearSolutionType,
-		optionsPrefix,
-		(EntryPoint_Register*)entryPointRegister,
-		MPI_COMM_WORLD );
-
-	VecCreate( self->comm, &self->X );
-	VecCreate( self->comm, &self->F );
-	MatCreate( self->comm, &self->A );
-	MatCreate( self->comm, &self->J );
-}
-
-/* Build */
-void _SystemLinearEquations_Build( void* sle, void* _context ) {
-	SystemLinearEquations*		self = (SystemLinearEquations*)sle;
-	Index				index;
-	
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	/* build the matrices */
-	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
-		/* Update rowSize and colSize if boundary conditions have been applied */		
-		Stg_Component_Build( self->stiffnessMatrices->data[index], _context, False );
-	}	
-	
-	/* and the vectors */
-	for ( index = 0; index < self->forceVectors->count; index++ ) {
-		/* Build the force vectors - includes updateing matrix size based on Dofs */
-		Stg_Component_Build( self->forceVectors->data[index], _context, False );
-	}
-	
-	/* and the solutions */
-	for ( index = 0; index < self->solutionVectors->count; index++ ) {
-		/* Build the force vectors - includes updateing matrix size based on Dofs */
-		Stg_Component_Build( self->solutionVectors->data[index], _context, False );
-	}
-	
-	/* lastly, the solver - if required */
-	if( self->solver )
-		Stg_Component_Build( self->solver, self, False );
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _SystemLinearEquations_Initialise( void* sle, void* _context ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	Index						index;
-	
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	/* initialise the matrices */
-	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
-		/* Update rowSize and colSize if boundary conditions have been applied */		
-		Stg_Component_Initialise( self->stiffnessMatrices->data[index], _context, False );
-	}	
-	
-	/* and the vectors */
-	for ( index = 0; index < self->forceVectors->count; index++ ) {
-		/* Initialise the force vectors - includes updateing matrix size based on Dofs */
-		Stg_Component_Initialise( self->forceVectors->data[index], _context, False );
-	}
-	
-	/* and the solutions */
-	for ( index = 0; index < self->solutionVectors->count; index++ ) {
-		/* Initialise the force vectors - includes updateing matrix size based on Dofs */
-		Stg_Component_Initialise( self->solutionVectors->data[index], _context, False );
-	}
-
-	/* Check to see if any of the components need to make the SLE non-linear */
-	SystemLinearEquations_CheckIfNonLinear( self );
-	
-	/* Setup Location Matrix */
-	SystemLinearEquations_LM_Setup( self, _context );
-
-	/* lastly, the solver, if required */
-	if( self->solver )
-		Stg_Component_Initialise( self->solver, self, False );
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void _SystemLinearEquations_Execute( void* sle, void* _context ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
-	
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-
-	_EntryPoint_Run_2VoidPtr( self->executeEP, sle, _context );
-	
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void SystemLinearEquations_ExecuteSolver( void* sle, void* _context ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
-	double wallTime;
-	/* Actually run the solver to get the new values into the SolutionVectors */
-	
-	Journal_Printf(self->info,"Linear solver (%s) \n",self->executeEPName);
-		
-	wallTime = MPI_Wtime();
-	if( self->solver )	
-		Stg_Component_Execute( self->solver, self, True );
-	
-	self->curSolveTime = MPI_Wtime() - wallTime;
-	Journal_Printf(self->info,"Linear solver (%s), solution time %6.6e (secs)\n",self->executeEPName, self->curSolveTime);
-		
-}
-
-void _SystemLinearEquations_Destroy( void* sle, void* _context ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
-	
-	/* BEGIN LUKE'S FRICTIONAL BCS BIT */
-	Memory_Free( self->nlSetupEPName );
-	Memory_Free( self->nlEPName );
-	Memory_Free( self->postNlEPName );
-	Memory_Free( self->nlConvergedEPName );
-	/* END LUKE'S FRICTIONAL BCS BIT */
-	Memory_Free( self->executeEPName );
-	
-	Stg_Class_Delete( self->extensionManager );
-
-	Stg_Class_Delete( self->stiffnessMatrices ); 
-	Stg_Class_Delete( self->forceVectors ); 
-	Stg_Class_Delete( self->solutionVectors ); 
-
-	Memory_Free( self->optionsPrefix );
-
-	VecDestroy( self->X );
-	VecDestroy( self->F );
-	MatDestroy( self->A );
-	MatDestroy( self->J );
-
-	/* Free the the MG handles. */
-	FreeArray( self->mgHandles );
-}
-
-void SystemLinearEquations_BC_Setup( void* sle, void* _context ) {
-	SystemLinearEquations*				self = (SystemLinearEquations*)sle;
-	Index						index;
-	
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	for ( index = 0; index < self->solutionVectors->count; index++ ) {
-		SolutionVector_ApplyBCsToVariables( self->solutionVectors->data[index], _context );
-	}
-}
-
-
-void SystemLinearEquations_LM_Setup( void* sle, void* _context ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	self->_LM_Setup( self, _context );
-}
-
-void SystemLinearEquations_IntegrationSetup( void* sle, void* _context ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	_EntryPoint_Run_Class_VoidPtr( self->integrationSetupEP, _context );
-}
-
-void _SystemLinearEquations_LM_Setup( void* sle, void* _context ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	Index						index;
-
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-	/* For each feVariable of each stiffness matrix, build the LM  */
-	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
-		StiffnessMatrix*				sm = (StiffnessMatrix*)self->stiffnessMatrices->data[index];
-		
-		FeEquationNumber_BuildLocationMatrix( sm->rowVariable->eqNum );
-		FeEquationNumber_BuildLocationMatrix( sm->columnVariable->eqNum );
-	}
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-void SystemLinearEquations_MatrixSetup( void* sle, void* _context ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	self->_matrixSetup( self, _context );
-}
-
-void _SystemLinearEquations_MatrixSetup( void* sle, void* _context ) {
-	SystemLinearEquations*				self = (SystemLinearEquations*)sle;
-	FiniteElementContext*				context = (FiniteElementContext*)_context;
-	Index						index;
-	
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
-		StiffnessMatrix_Assemble( self->stiffnessMatrices->data[index], self->bcRemoveQuery, self, context );
-	}
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void SystemLinearEquations_VectorSetup( void* sle, void* _context ) {
-	SystemLinearEquations*				self = (SystemLinearEquations*)sle;
-	
-	self->_vectorSetup( self, _context );
-}
-
-void _SystemLinearEquations_VectorSetup( void* sle, void* _context ) {
-	SystemLinearEquations*				self = (SystemLinearEquations*)sle;
-	Index						index;
-	
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-	for ( index = 0; index < self->forceVectors->count; index++ ) {
-		ForceVector_Assemble( self->forceVectors->data[index] );
-	}
-	Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-Index _SystemLinearEquations_AddStiffnessMatrix( void* sle, StiffnessMatrix* stiffnessMatrix ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	return SystemLinearEquations_AddStiffnessMatrix( self, stiffnessMatrix );
-}
-
-StiffnessMatrix* _SystemLinearEquations_GetStiffnessMatrix( void* sle, Name stiffnessMatrixName ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	return SystemLinearEquations_GetStiffnessMatrix( self, stiffnessMatrixName );
-}
-
-Index _SystemLinearEquations_AddForceVector( void* sle, ForceVector* forceVector ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	return SystemLinearEquations_AddForceVector( self, forceVector );
-}
-
-ForceVector* _SystemLinearEquations_GetForceVector( void* sle, Name forceVectorName ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	return SystemLinearEquations_GetForceVector( self, forceVectorName );
-}
-
-Index _SystemLinearEquations_AddSolutionVector( void* sle, SolutionVector* solutionVector ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	return SystemLinearEquations_AddSolutionVector( self, solutionVector );
-}
-
-SolutionVector* _SystemLinearEquations_GetSolutionVector( void* sle, Name solutionVectorName ) {
-	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
-	
-	return SystemLinearEquations_GetSolutionVector( self, solutionVectorName );
-}
-
-void SystemLinearEquations_UpdateSolutionOntoNodes( void* sle, void* _context ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
-
-	self->_updateSolutionOntoNodes( self, _context );
-}
-
-void _SystemLinearEquations_UpdateSolutionOntoNodes( void* sle, void* _context ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
-	SolutionVector_Index	solnVec_I;
-	SolutionVector*		currentSolnVec;
-
-	for ( solnVec_I=0; solnVec_I < self->solutionVectors->count; solnVec_I++ ) {
-		currentSolnVec = (SolutionVector*)self->solutionVectors->data[solnVec_I];
-		SolutionVector_UpdateSolutionOntoNodes( currentSolnVec );
-	}	
-}
-
-void SystemLinearEquations_ZeroAllVectors( void* sle, void* _context ) {
-	SystemLinearEquations*      self = (SystemLinearEquations*)sle;
-	Index                       index;
-	ForceVector*                forceVector;
-	
-	Journal_DPrintf( self->debug, "In %s\n", __func__ );
-	for ( index = 0; index < self->forceVectors->count; index++ ) {
-		forceVector = (ForceVector*) self->forceVectors->data[index];
-		
-		VecSet( forceVector->vector, 0.0 );
-	}
-}
-
-/* need to do this before the SLE specific function to set up the 
-pre conditioners is called (beginning of solve) */
-void SystemLinearEquations_NewtonInitialise( void* _context, void* data ) {
-	FiniteElementContext*	context = (FiniteElementContext*)_context;
-	SystemLinearEquations*	sle = (SystemLinearEquations*)context->slEquations->data[0];
-	SNES							snes;
-	SNES							oldSnes = sle->nlSolver;
-
-	/* don't assume that a snes is being used for initial guess, check for this!!! */
-	if( oldSnes && context->timeStep == 1 && !sle->linearSolveInitGuess )
-		SNESDestroy( oldSnes );
-
-	SNESCreate( sle->comm, &snes );
-
-	sle->nlSolver = snes;
-	sle->_setFFunc( &sle->F, context );
-
-	SNESSetJacobian( snes, sle->J, sle->P, sle->_buildJ, sle->buildJContext );
-	SNESSetFunction( snes, sle->F, sle->_buildF, sle->buildFContext );
-
-	/* configure the KSP */
-	sle->_configureNLSolverFunc( snes, context );
-}
-
-/* do this after the pre conditoiners have been set up in the problem specific SLE */
-void SystemLinearEquations_NewtonExecute( void* sle, void* _context ) {
-	SystemLinearEquations*	self            = (SystemLinearEquations*) sle;
-	SNES			snes		= self->nlSolver;
-
-	SNESSetOptionsPrefix( snes, self->optionsPrefix );
-	SNESSetFromOptions( snes );
-	SNESSolve( snes, PETSC_NULL, self->X );
-}
-
-/* do this at end of solve step */
-void SystemLinearEquations_NewtonFinalise( void* _context, void* data ) {
-	FiniteElementContext*	context		= (FiniteElementContext*)_context;
-	SystemLinearEquations*	sle             = (SystemLinearEquations*)context->slEquations->data[0];
-	SNES			snes		= sle->nlSolver;
-
-	sle->_updateOldFields( &sle->X, context );
-	
-	SNESDestroy( snes );	
-}
-
-void SystemLinearEquations_NewtonMFFDExecute( void* sle, void* _context ) {
-	SystemLinearEquations*	self            = (SystemLinearEquations*) sle;
-	Vec    			F;
-
-	VecDuplicate( SystemLinearEquations_GetSolutionVectorAt( self, 0 )->vector, &F );
-
-	/* creates the nonlinear solver */
-	if( self->nlSolver != PETSC_NULL )
-		SNESDestroy( self->nlSolver );
-	SNESCreate( self->comm, &self->nlSolver );
-	SNESSetFunction( self->nlSolver, F, self->_buildF, _context );
-
-	// set J (jacobian)
-	
-	// set F (residual vector)
-	
-	// call non linear solver func (SNES wrapper)
-}
-
-void SystemLinearEquations_NonLinearExecute( void* sle, void* _context ) {
-	SystemLinearEquations*	self            = (SystemLinearEquations*) sle;
-	Vec                     previousVector;
-	Vec                     currentVector;
-	double                  residual;
-	double                  tolerance       = self->nonLinearTolerance;
-	Iteration_Index         maxIterations   = self->nonLinearMaxIterations;
-	Bool                    converged;
-	Stream*                 errorStream     = Journal_Register( Error_Type, (Name)self->type  );
-	double					wallTime;
-	Iteration_Index         minIterations   = self->nonLinearMinIterations;
-        SLE_Solver*             solver;
-
-	PetscScalar		currVecNorm, prevVecNorm;
-
-	Journal_Printf( self->info, "In %s\n", __func__ );
-	Stream_IndentBranch( StgFEM_Debug );
-		
-	wallTime = MPI_Wtime();		
-
-	/* First Solve */
-	/* setting the nonlinear stuff */
-	//START OF NONLINEAR ITERATION!!!!!
-	/* first get current timestep */
-        solver = self->solver;
-	solver->currenttimestep = self->context->timeStep;
-	/* if current timestep is not the same as previous timestep, then reset all variables back to zero and update previous timestep */
-	if(solver->currenttimestep != solver->previoustimestep){
-		//update prev timestep
-		solver->previoustimestep = solver->currenttimestep;
-		solver->nonlinearitsinitialtime = 0; 
-		solver->nonlinearitsendtime = 0; 
-		solver->totalnonlinearitstime = 0; 
-		solver->totalnumnonlinearits = 0; 
-		solver->avgtimenonlinearits = 0; 	
-		solver->inneritsinitialtime = 0; 
-		solver->outeritsinitialtime = 0; 
-		solver->inneritsendtime = 0; 
-		solver->outeritsendtime = 0; 
-		solver->totalinneritstime = 0; 
-		solver->totalouteritstime = 0; 
-		solver->totalnuminnerits = 0; 
-		solver->totalnumouterits = 0; 
-		solver->avgnuminnerits = 0; 
-		solver->avgnumouterits = 0; 
-		solver->avgtimeinnerits = 0; 
-		solver->avgtimeouterits = 0;	
-	}
-
-	self->nonLinearIteration_I = 0;
-	Journal_Printf(self->info,"\nNon linear solver - iteration %d\n", self->nonLinearIteration_I);
-
-        /* More of Luke's stuff. I need an entry point for a non-linear setup operation. */
-        _EntryPoint_Run_2VoidPtr( self->nlSetupEP, sle, _context );
-
-	/*Don't know if we should include this but the timing of the outer and inner iterations starts here so it makes sense to count this one? */		
-	solver->nonlinearitsinitialtime = MPI_Wtime();
-
-	self->linearExecute( self, _context );
-	self->hasExecuted = True;
-
-	solver->nonlinearitsendtime = MPI_Wtime();
-	solver->totalnonlinearitstime = solver->totalnonlinearitstime + (-solver->nonlinearitsinitialtime + solver->nonlinearitsendtime);
-	/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
-	solver->nonlinearitsinitialtime = 0;
-	solver->nonlinearitsendtime = 0;
-	/*
-	** Include an entry point to do some kind of post-non-linear-iteration operation. */
-	_EntryPoint_Run_2VoidPtr( self->postNlEP, sle, _context );
-
-	/* TODO - Give option which solution vector to test */
-	currentVector   = SystemLinearEquations_GetSolutionVectorAt( self, 0 )->vector; 
-	VecDuplicate( currentVector, &previousVector );
-	
-	for ( self->nonLinearIteration_I = 1 ; self->nonLinearIteration_I < maxIterations ; self->nonLinearIteration_I++ ) {
-		/* get initial wall time for nonlinear loop */
-		solver->nonlinearitsinitialtime = MPI_Wtime();
-		
-		/*
-		** BEGIN LUKE'S FRICTIONAL BCS BIT
-		**
-		** Adding an interface for allowing other components to add some form of non-linearity to the system.
-		** This is with a focus on frictional BCs, where we want to examine the stress field and modify
-		** traction BCs to enforce friction rules. - Luke 18/07/2007
-		*/
-
-		_EntryPoint_Run_2VoidPtr( self->nlEP, sle, _context );
-		
-		/*
-		** END LUKE'S FRICTIONAL BCS BIT
-		*/
-
-
-		//Vector_CopyEntries( currentVector, previousVector );
-		VecCopy( currentVector, previousVector );
-	
-		Journal_Printf(self->info,"Non linear solver - iteration %d\n", self->nonLinearIteration_I);
-			
-		self->linearExecute( self, _context );
-//		PetscPrintf( PETSC_COMM_WORLD, "|Xn+1| = %12.12e \n", Vector_L2Norm(SystemLinearEquations_GetSolutionVectorAt(self,1)->vector) );
-
-		/* Calculate Residual */
-		VecAXPY( previousVector, -1.0, currentVector );
-		VecNorm( previousVector, NORM_2, &prevVecNorm );
-		VecNorm( currentVector, NORM_2, &currVecNorm );
-		residual = ((double)prevVecNorm) / ((double)currVecNorm);
-		
-		self->curResidual = residual;
-
-                /*
-                ** Include an entry point to do some kind of post-non-linear-iteration operation. */
-		_EntryPoint_Run_2VoidPtr( self->postNlEP, sle, _context );
-
-		Journal_Printf( self->info, "In func %s: Iteration %u of %u - Residual %.5g - Tolerance = %.5g\n", 
-				__func__, self->nonLinearIteration_I, maxIterations, residual, tolerance );
-		if ( self->makeConvergenceFile ) {
-			Journal_Printf( self->convergenceStream, "%d\t\t%d\t\t%.5g\t\t%.5g\n", 
-							 self->context->timeStep, self->nonLinearIteration_I, residual, tolerance );
-		}
-			
-		/* Check if residual is below tolerance */
-		converged = (residual < tolerance) ? True : False;
-		
-		Journal_Printf(self->info,"Non linear solver - Residual %.8e; Tolerance %.4e%s%s - %6.6e (secs)\n\n", residual, tolerance, 
-			(converged) ? " - Converged" : " - Not converged",
-			(self->nonLinearIteration_I < maxIterations) ? "" : " - Reached iteration limit",
-			MPI_Wtime() - wallTime );
-			//END OF NONLINEAR ITERATION LOOP!!!
-			
-			/* add the outer loop iterations to the total outer iterations */
-			solver->totalnumnonlinearits = solver->totalnumnonlinearits++;
-			/*get wall time for end of outer loop*/
-			solver->nonlinearitsendtime = MPI_Wtime();
-			/* add time to total time inner its: */
-			solver->totalnonlinearitstime = solver->totalnonlinearitstime + (-solver->nonlinearitsinitialtime + solver->nonlinearitsendtime);
-			//printf("totalnumnonlinearits before converging is %d totalnonlinearitstime is %g, totalouteritstime is %g and totalinneritstime is %g\n",solver->totalnumnonlinearits,solver->totalnonlinearitstime,solver->totalouteritstime,solver->totalinneritstime);
-
-			/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
-			solver->nonlinearitsinitialtime = 0;
-			solver->nonlinearitsendtime = 0;        
-		if ( (converged) && (self->nonLinearIteration_I>=minIterations) ) {
-		   int result;
-
-		   /* Adding in another entry point so we can insert out own custom
-		      convergeance checks. For example, with frictional boundary
-		      conditions we need to ensure envery node was gone from the
-		      original searching state to a fixed slipping or sticking state. */
-		   _EntryPoint_Run_2VoidPtr( self->nlConvergedEP, _context, &converged );
-		   MPI_Allreduce( &converged, &result, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD );
-		   if( result )
-		      break;
-		}
-	}
-
-	/* Print Info */
-	if ( converged ) {
-		Journal_Printf( self->info, "In func %s: Converged after %u iterations.\n",
-				__func__, self->nonLinearIteration_I );
-	}
-	else {
-		Journal_Printf( errorStream, "In func %s: Failed to converge after %u iterations.\n", 
-				__func__, self->nonLinearIteration_I);
-		if ( self->killNonConvergent ) {
-			abort();
-		}
-	}
-
-	Stream_UnIndentBranch( StgFEM_Debug );
-
-	VecDestroy( previousVector );
-	
-	/*Set all the printout variables */
-        if( solver->totalnumnonlinearits ) {
-           solver->avgtimenonlinearits = (solver->totalnonlinearitstime - solver->totalouteritstime)/solver->totalnumnonlinearits;
-           solver->avgnumouterits = solver->totalnumouterits/solver->totalnumnonlinearits;
-        }
-        if( solver->totalnumouterits ) {
-           solver->avgnuminnerits = solver->totalnuminnerits/solver->totalnumouterits;
-           solver->avgtimeouterits = (solver->totalouteritstime - solver->totalinneritstime)/solver->totalnumouterits;
-        }
-        if( solver->totalnuminnerits )
-           solver->avgtimeinnerits = solver->totalinneritstime/solver->totalnuminnerits;
-	//printf("totalnumnonlinearits = %d, avgnumouterits %d, avgnuminnerits %d\n",solver->totalnumnonlinearits, solver->avgnumouterits, solver->avgnuminnerits); 
-
-}
-
-void SystemLinearEquations_AddNonLinearSetupEP( void* sle, Name name, EntryPoint_2VoidPtr_Cast func ) {
-	SystemLinearEquations* self = (SystemLinearEquations*)sle;
-
-	SystemLinearEquations_SetToNonLinear( self );
-	EntryPoint_Append( self->nlSetupEP, (char*)name, (void*)func, self->type );
-}
-
-void SystemLinearEquations_AddPostNonLinearEP( void* sle, Name name, EntryPoint_2VoidPtr_Cast func ) {
-	SystemLinearEquations* self = (SystemLinearEquations*)sle;
-
-	EntryPoint_Append( self->postNlEP, (char*)name, (void*)func, self->type );
-}
-
-void SystemLinearEquations_AddNonLinearConvergedEP( void* sle,
-						    Name name,
-						    EntryPoint_2VoidPtr_Cast func )
-{
-	SystemLinearEquations* self = (SystemLinearEquations*)sle;
-
-	SystemLinearEquations_SetToNonLinear( self );
-	EntryPoint_Append( self->nlConvergedEP, (char*)name, (void*)func, self->type );
-}
-
-/*
-Computes
-  F1 := A(x) x -b  = -r,
-  where r = b - A(x) x
-*/
-//void SystemLinearEquations_SNESPicardFormalResidual( void *someSLE, Vector *stg_X, Vector *stg_F, void *_context )
-void SystemLinearEquations_SNESPicardFormalResidual( void *someSLE, Vec X, Vec F, void *_context )
-{
-	SystemLinearEquations *sle = (SystemLinearEquations*)someSLE;
-    	SLE_Solver            *solver = (SLE_Solver*)sle->solver;
-	Stream*                 errorStream     = Journal_Register( Error_Type, (Name)sle->type  );
-
-	Journal_Printf( errorStream, "    **** SystemLinearEquations_SNESPicardFormalResidual: This option is un-tested and does not yet function correctly. \n");
-	Journal_Printf( errorStream, "    **** Use the default form function or specify --components.XXX.picard_FormFunctionType=PicardFormFunction_KSPResidual instead. \n");
-	Journal_Printf( errorStream, "    ****     [Dave May - 12 May, 2008] \n");
-	abort();
-
-	solver->_formResidual( (void*)sle,  (void*)solver, F );
-}
-
-/*
-Computes
-  F2 := x - A(x)^{-1} b
-*/
-#if 0
-void SystemLinearEquations_SNESPicardKSPResidual( void *someSLE, Vector *stg_X, Vector *stg_F, void *_context )
-{
-        SystemLinearEquations *sle = (SystemLinearEquations*)someSLE;
-        SLE_Solver            *solver = (SLE_Solver*)sle->solver;
-        Vec                   F,X,Xcopy;
-        PetscReal norm;
-
-        F = StgVectorGetPetscVec( stg_F );
-        X = StgVectorGetPetscVec( stg_X );
-
-        VecDuplicate( X, &Xcopy );
-        VecCopy( X, Xcopy );
-
-        VecCopy( X, F );                        /* F <- X */
-//      VecNorm( X, NORM_2, &norm );
-//      PetscPrintf(PETSC_COMM_WORLD,"  |X|_pre = %5.5e \n", norm );
-        sle->linearExecute( sle, _context );    /* X = A^{-1} b */
-        X = StgVectorGetPetscVec( stg_X );
-//      VecNorm( X, NORM_2, &norm );
-//      PetscPrintf(PETSC_COMM_WORLD,"  |X|_post = %5.5e \n", norm );
-
-        VecAXPY( F, -1.0, X );                  /* F <- X - F */
-//      VecNorm( F, NORM_2, &norm );
-//      PetscPrintf(PETSC_COMM_WORLD,"  |F|_post = %5.5e \n", norm );
-
-        VecCopy( Xcopy, X );
-        VecDestroy( Xcopy );
-}
-#endif
-
-/*
-stg_X must not get modified by this function !!
-*/
-void SystemLinearEquations_SNESPicardKSPResidual( void *someSLE, Vec X, Vec F, void *_context )
-{
-        SystemLinearEquations *sle = (SystemLinearEquations*)someSLE;
-        SLE_Solver            *solver = (SLE_Solver*)sle->solver;
-	Vec			Xstar;
-	PetscReal norm,norms;
-
-	solver->_getSolution( sle, solver, &Xstar );
-
-	/* Map most current solution into stg object, vec->mesh  */
-	VecCopy( X, Xstar );  /* X* <- X */
-	/* Map onto nodes */
-	SystemLinearEquations_UpdateSolutionOntoNodes( someSLE, _context );
-
-	VecNorm( X, NORM_2, &norm );
-	VecNorm( Xstar, NORM_2, &norms );
-//	PetscPrintf(PETSC_COMM_WORLD,"  |X| = %12.12e : |x*| = %12.12e <pre>\n", norm, norms );
-
-	sle->linearExecute( sle, _context );    /* X* = A^{-1} b */
-
-	VecNorm( X, NORM_2, &norm );
-	VecNorm( Xstar, NORM_2, &norms );
-//	PetscPrintf(PETSC_COMM_WORLD,"  |X| = %12.12e : |x*| = %12.12e <post> \n", norm, norms );
-
-	VecWAXPY( F, -1.0, Xstar, X ); /* F = -X* + X  */
-}
-
-void SLEComputeFunction( void *someSLE, Vec X, Vec F, void *_context )
-{
-        SystemLinearEquations *sle = (SystemLinearEquations*)someSLE;	
-
-	if (sle->_sleFormFunction!=NULL) {
-		sle->_sleFormFunction( sle, X, F, _context );
-	}
-	else {
-		SETERRABORT( sle->comm, PETSC_ERR_SUP, "SLEComputeFunction in not valid" );
-	}
-}
-
-void SLE_SNESMonitor( void *sle, PetscInt iter, PetscReal fnorm )
-{
-  PetscPrintf( PETSC_COMM_WORLD, "  %.4d SLE_NS Function norm %12.12e    --------------------------------------------------------------------------------\n", iter, fnorm );
-}
-
-void SLE_SNESMonitor2( void *sle, PetscInt iter, PetscReal fnorm0, PetscReal fnorm, PetscReal dX, PetscReal X1 )
-{
-  if(iter==0) {
-    PetscPrintf( PETSC_COMM_WORLD, "  SLE_NS  it       |F|              |F|/|F0|          |X1-X0|        |X1-X0|/|X1| \n" );
-  }
-  PetscPrintf( PETSC_COMM_WORLD,   "  SLE_NS  %1.4d     %2.4e      %2.4e       %2.4e     %2.4e \n", iter, fnorm, fnorm/fnorm0, dX, dX/X1 );
-}
-
-void _monitor_progress( PetscReal initial, PetscReal target, PetscReal current, PetscReal *p )
-{
-  PetscReal p0;
-
-  p0 = log10(initial) - log10(target);
-  *p = 100.0 * ( 1.0 - (log10(current)-log10(target)) / p0 );
-}
-
-void SLE_SNESMonitorProgress( void *sle, 
-  PetscInt iter, 
-  PetscReal fnorm0, PetscReal fnorm, PetscReal dX, PetscReal X1, 
-  PetscReal fatol, PetscReal frtol, PetscReal xtol )
-{
-  PetscReal f_abs_s, f_abs_e, v1, p1;
-  PetscReal f_rel_s, f_rel_e, v2, p2;
-  PetscReal x_del_s, x_del_e, v3, p3;
-
-  if(iter==0) {
-    PetscPrintf( PETSC_COMM_WORLD, "  SLE_NS  it       |F|                 |F|/|F0|             |X1-X0|/|X1| \n" );
-  }
-
-  f_abs_s = fnorm0;
-  f_abs_e = fatol;
-  v1 = fnorm;
-  _monitor_progress( f_abs_s, f_abs_e, v1, &p1 );
-
-  f_rel_s = fnorm0;
-  f_rel_e = fnorm0 * frtol;
-  v2 = fnorm;
-  _monitor_progress( f_rel_s, f_rel_e, v2, &p2 );
-
-  x_del_s = 1.0;
-  x_del_e = xtol;
-  v3 = dX/X1;
-  _monitor_progress( x_del_s, x_del_e, v3, &p3 );
-
-  PetscPrintf( PETSC_COMM_WORLD,   "  SLE_NS  %1.4d     %2.4e [%2.0f%%]     %2.4e [%2.0f%%]      %2.4e [%2.0f%%] \n", iter, fnorm,p1, fnorm/fnorm0,p2,  dX/X1,p3 );
-}
-
-
-void SLE_SNESConverged(
-	PetscReal snes_abstol, PetscReal snes_rtol, PetscReal snes_ttol, PetscReal snes_xtol,
-	PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason )
-{
-  /* PetscErrorCode ierr; */
-
-  *reason = SNES_CONVERGED_ITERATING;
-
-  if (!it) {
-    /* set parameter for default relative tolerance convergence test */
-    snes_ttol = fnorm*snes_rtol;
-  }
-  if (fnorm != fnorm) {
-//    ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRV(ierr);
-    *reason = SNES_DIVERGED_FNORM_NAN;
-  } else if (fnorm < snes_abstol) {
-//    ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes_abstol);CHKERRV(ierr);
-    *reason = SNES_CONVERGED_FNORM_ABS;
-  }
-//  } else if (snes->nfuncs >= snes->max_funcs) {
-//    ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRV(ierr);
-//    *reason = SNES_DIVERGED_FUNCTION_COUNT;
-//  }
-
-  if (it && !*reason) {
-    if (fnorm <= snes_ttol) {
-//      ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes_ttol);CHKERRV(ierr);
-      *reason = SNES_CONVERGED_FNORM_RELATIVE;
-    } else if (pnorm < snes_xtol*xnorm) {
-//      ierr = PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes_xtol,xnorm);CHKERRV(ierr);
-      *reason = SNES_CONVERGED_PNORM_RELATIVE;
-    }
-  }
-}
-
-
-#if defined(PETSC_HAVE_ISINF) && defined(PETSC_HAVE_ISNAN)
-#define PetscIsInfOrNanScalar(a) (isinf(PetscAbsScalar(a)) || isnan(PetscAbsScalar(a)))
-#define PetscIsInfOrNanReal(a) (isinf(a) || isnan(a))
-#elif defined(PETSC_HAVE__FINITE) && defined(PETSC_HAVE__ISNAN)
-#if defined(PETSC_HAVE_FLOAT_H)
-#include "float.h"  /* windows defines _finite() in float.h */ 
-#endif
-#define PetscIsInfOrNanScalar(a) (!_finite(PetscAbsScalar(a)) || _isnan(PetscAbsScalar(a)))
-#define PetscIsInfOrNanReal(a) (!_finite(a) || _isnan(a))
-#else
-#define PetscIsInfOrNanScalar(a) ((a - a) != 0.0)
-#define PetscIsInfOrNanReal(a) ((a - a) != 0.0)
-#endif
-
-/*
-This will be replaced by SNESPicard in petsc 2.4.0.
-*/
-
-void SystemLinearEquations_PicardExecute( void *sle, void *_context )
-{
-  SystemLinearEquations *self = (SystemLinearEquations*)sle;
-  SLE_Solver            *solver = (SLE_Solver*)self->solver;
-
-  Vec            X, Y, F, Xstar,delta_X;
-  PetscReal      alpha = 1.0;
-  PetscReal      fnorm,norm_X,pnorm,fnorm0;
-  PetscInt       i;
-  PetscErrorCode ierr;
-  SNESConvergedReason snes_reason;
- 
-  PetscReal snes_norm;
-  PetscInt snes_iter;
-
-  PetscReal snes_ttol, snes_rtol, snes_abstol, snes_xtol;
-  PetscInt  snes_maxits;
-
-  PetscTruth monitor_flg;
-
-  /* setup temporary some vectors */
-  solver->_getSolution( self, solver, &Xstar );
-
-  VecDuplicate( Xstar, &X );
-  VecDuplicate( X, &F );
-  VecDuplicate( F, &Y );
-  VecDuplicate( F, &delta_X );
-
-  /* Get some values from dictionary */
-  snes_maxits =  (PetscInt)self->nonLinearMaxIterations;
-  snes_ttol   = 0.0;
-  snes_rtol   = (PetscReal)self->rtol;
-  snes_abstol = (PetscReal)self->abstol;
-  snes_xtol   = (PetscReal)self->xtol;
-  monitor_flg = PETSC_FALSE;
-  if (self->picard_monitor==True) { monitor_flg = PETSC_TRUE; }
-  alpha       = (PetscReal)self->alpha;
-
-  snes_reason = SNES_CONVERGED_ITERATING;
-
-  /* Map X <- X* */
-  VecCopy( Xstar, X );  // Vector_CopyEntries( currentVector, previousVector );
-
-  /* Get an initial guess if |X| ~ 0, by solving the linear problem  */
-  VecNorm( X, NORM_2, &norm_X );
-  if (norm_X <1.0e-20) {
-    if (monitor_flg==PETSC_TRUE)
-      PetscPrintf( PETSC_COMM_WORLD, "SLE_Picard: Computing an initial guess for X from the linear problem\n");
-
-    self->linearExecute( sle, _context );    /* X* = A^{-1} b */
-    self->hasExecuted = True;
-
-    /* Map X <- X* */
-    VecCopy( Xstar, X ); 
-    VecNorm( X, NORM_2, &norm_X );
-  }
-
-
-  snes_iter = 0;
-  snes_norm = 0;
-  //SLEComputeFunction( sle, stg_X, stg_F, _context );
-  SLEComputeFunction( sle, X, F, _context );
-  ierr = VecNorm(F, NORM_2, &fnorm);CHKERRV(ierr); /* fnorm <- ||F||  */
-  fnorm0 = fnorm;
-  if( PetscIsInfOrNanReal(fnorm) ) SETERRABORT( self->comm,PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
-
-  snes_norm = fnorm;
-  if(monitor_flg==PETSC_TRUE) {
-  /*  SLE_SNESMonitor(sle,0,fnorm); */
-  /*  SLE_SNESMonitor2(sle,0,fnorm0,fnorm, norm_X, norm_X ); */
-    SLE_SNESMonitorProgress( sle, snes_iter,  fnorm0, fnorm, norm_X, norm_X, snes_abstol, snes_rtol, snes_xtol );
-  }
-
-  /* set parameter for default relative tolerance convergence test */
-  snes_ttol = fnorm*snes_rtol;
-  /* test convergence */
-  SLE_SNESConverged( snes_abstol,snes_rtol,snes_ttol,snes_xtol , 0,norm_X,0.0,fnorm,&snes_reason);
-  if (snes_reason) return;
-
-  for(i = 0; i < snes_maxits; i++) {
-    /* Update guess Y = X^n - F(X^n) */
-    ierr = VecWAXPY(Y, -1.0, F, X);CHKERRV(ierr);
-
-    VecCopy( X, delta_X );  /* delta_X <- X */
-
-    /* X^{n+1} = (1 - \alpha) X^n + alpha Y */
-    ierr = VecAXPBY(X, alpha, 1 - alpha, Y);CHKERRV(ierr);
-    VecNorm( X, NORM_2, &norm_X ); 
-/*    PetscPrintf( PETSC_COMM_WORLD, "  Xn+1 = %12.12e \n", norm_X ); */
-
-    VecAYPX( delta_X, -1.0, X );   /* delta_X <- Xn+1 - delta_X */
-    VecNorm( delta_X, NORM_2, &pnorm );
-
-    /* Compute F(X^{new}) */
-    SLEComputeFunction( sle, X, F, _context );
-    ierr = VecNorm(F, NORM_2, &fnorm);CHKERRV(ierr);
-    if( PetscIsInfOrNanReal(fnorm) ) SETERRABORT( self->comm,PETSC_ERR_FP,"Infinite or not-a-number generated norm");
-
-    /* Monitor convergence */
-    snes_iter = i+1;
-    snes_norm = fnorm;
-    if (monitor_flg==PETSC_TRUE) {
-    /*  SLE_SNESMonitor(sle,snes_iter,snes_norm); */
-    /*  SLE_SNESMonitor2(sle,snes_iter,fnorm0,fnorm, pnorm, norm_X ); */
-      SLE_SNESMonitorProgress( sle, snes_iter,  fnorm0, fnorm, pnorm, norm_X, snes_abstol, snes_rtol, snes_xtol );
-    }
-
-    /* Test for convergence */
-    SLE_SNESConverged( snes_abstol,snes_rtol,snes_ttol,snes_xtol , snes_iter,norm_X,pnorm,fnorm,&snes_reason);
-    if (snes_reason) break;
-  }
-  if (i == snes_maxits) {
-//    ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRV(ierr);
-    if (!snes_reason) snes_reason = SNES_DIVERGED_MAX_IT;
-  }
-
-  /* If monitoring, report reason converged */
-  if (monitor_flg==PETSC_TRUE)
-    PetscPrintf( PETSC_COMM_WORLD, "Nonlinear solve converged due to %s \n", SNESConvergedReasons[snes_reason] );
-
-  VecDestroy( X );
-  VecDestroy( F );
-  VecDestroy( Y );
-  VecDestroy( delta_X );
-
-}
-
-
-///////////////
-
-void SystemLinearEquations_AddNonLinearEP( void* sle, Name name, EntryPoint_2VoidPtr_Cast func ) {
-	SystemLinearEquations* self = (SystemLinearEquations*)sle;
-
-	SystemLinearEquations_SetToNonLinear( self );
-	EntryPoint_Append( self->nlEP, (char*)name, (void*)func, self->type );
-}
-
-
-
-void SystemLinearEquations_SetToNonLinear( void* sle ) {
-	SystemLinearEquations*	self            	= (SystemLinearEquations*) sle;
-	Hook*			nonLinearInitHook	= NULL;
-	Hook*			nonLinearFinaliseHook	= NULL;
-	FiniteElementContext*	context			= NULL;
-
-	assert( self );
-	if ( self->isNonLinear )
-		return;
-
-	self->isNonLinear = True;
-
-	self->linearExecute = self->_execute;
-	self->_execute = SystemLinearEquations_NonLinearExecute;
-
-	if( self->nonLinearSolutionType ) {
-		if( !strcmp( self->nonLinearSolutionType, "default" ) ) {
-			self->_execute = SystemLinearEquations_NonLinearExecute;
-		}		
-
-		if( !strcmp( self->nonLinearSolutionType, "MatrixFreeNewton" ) )
-			self->_execute = SystemLinearEquations_NewtonMFFDExecute;
-
-		if( !strcmp( self->nonLinearSolutionType, "Newton" ) ) {
-			context = self->context;
-
-			nonLinearInitHook = Hook_New( "NewtonInitialise", 
-						(void*)SystemLinearEquations_NewtonInitialise, self->name );
-			_EntryPoint_PrependHook_AlwaysFirst( Context_GetEntryPoint( context, AbstractContext_EP_Solve ), 
-								nonLinearInitHook );
-			nonLinearFinaliseHook = Hook_New( "NewtonFinalise",
-						(void*)SystemLinearEquations_NewtonFinalise, self->name );
-			_EntryPoint_AppendHook_AlwaysLast( Context_GetEntryPoint( context, AbstractContext_EP_Solve ), 
-						nonLinearFinaliseHook );
-			self->_execute = SystemLinearEquations_NewtonExecute;
-		}
-		
-		if (!strcmp( self->nonLinearSolutionType, "Picard") ) {
-			/* set function pointer for execute */
-			self->_execute = SystemLinearEquations_PicardExecute;
-
-			/* set form function */
-			if (!strcmp(self->picard_form_function_type,"PicardFormFunction_KSPResidual") ) {
-				self->_sleFormFunction = SystemLinearEquations_SNESPicardKSPResidual;
-			}
-			else if (!strcmp(self->picard_form_function_type,"PicardFormFunction_FormalResidual") ) {
-				self->_sleFormFunction = SystemLinearEquations_SNESPicardFormalResidual;
-			}
-			else {
-				 Stream *errorStream = Journal_Register( Error_Type, (Name)self->type  );
-
-		                Journal_Printf( errorStream, "Unknown the Picard FormFunction type %s is unrecognised. .\n", self->picard_form_function_type );
-				Journal_Printf( errorStream, "Supported types include <PicardFormFunction_FormalResidual, PicardFormFunction_KSPResidual> \n" );
-                        	abort();
-
-			}
-		}
-	}
-}
-
-void SystemLinearEquations_CheckIfNonLinear( void* sle ) {
-	SystemLinearEquations*	self            = (SystemLinearEquations*) sle;
-	Index                   index;
-	
-	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
-		StiffnessMatrix* stiffnessMatrix = SystemLinearEquations_GetStiffnessMatrixAt( self, index );
-		
-		if ( stiffnessMatrix->isNonLinear )
-			SystemLinearEquations_SetToNonLinear( self );
-
-		/* TODO CHECK FOR FORCE VECTORS */
-	}	
-}
-
-/*
-** All the MG functions and their general implementations.
-*/
-
-void SystemLinearEquations_MG_Enable( void* _sle ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)_sle;
-	
-	if( !self->isBuilt ) {
-		Journal_Printf(self->info, "Warning: SLE has not been built, can't enable multi-grid.\n" );
-		return;
-	}
-	
-	self->mgEnabled = True;
-}
-
-
-void SystemLinearEquations_MG_SelectStiffMats( void* _sle, unsigned* nSMs, StiffnessMatrix*** sms ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)_sle;
-	
-	assert( self->_mgSelectStiffMats );
-	self->_mgSelectStiffMats( self, nSMs, sms );
-}
-
-
-void _SystemLinearEquations_MG_SelectStiffMats( void* _sle, unsigned* nSMs, StiffnessMatrix*** sms ) {
-	SystemLinearEquations*	self = (SystemLinearEquations*)_sle;
-	
-	/*
-	** As we have nothing else to go on, attempt to apply MG to all stiffness matrices in the list.
-	*/
-	
-	{
-		unsigned	sm_i;
-		
-		*nSMs = 0;
-		for( sm_i = 0; sm_i < self->stiffnessMatrices->count; sm_i++ ) {
-			StiffnessMatrix*	sm = ((StiffnessMatrix**)self->stiffnessMatrices->data)[sm_i];
-			
-			/* Add this one to the list. */
-			*sms = Memory_Realloc_Array( *sms, StiffnessMatrix*, (*nSMs) + 1 );
-			(*sms)[*nSMs] = sm;
-			(*nSMs)++;
-		}
-	}
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/src/SystemLinearEquations.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/src/SystemLinearEquations.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,1408 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student Monash University, VPAC. (davidm at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: SystemLinearEquations.c 1230 2008-09-15 01:44:43Z DavidLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <petsc.h>
+#include <petscvec.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "units.h"
+#include "types.h"
+#include "shortcuts.h"
+#include "SystemLinearEquations.h"
+#include "SLE_Solver.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "StiffnessMatrix.h"
+#include "SolutionVector.h"
+#include "ForceVector.h"
+#include "FiniteElementContext.h"
+
+
+/* Textual name of this class */
+const Type SystemLinearEquations_Type = "SystemLinearEquations";
+
+/** Constructor */
+SystemLinearEquations* SystemLinearEquations_New(
+	Name							name,
+	SLE_Solver*					solver,
+	void*							nlSolver,
+	FiniteElementContext*	context,
+	Bool							isNonLinear,
+	double						nonLinearTolerance,
+	Iteration_Index			nonLinearMaxIterations,
+	Bool							killNonConvergent,		
+	EntryPoint_Register*		entryPoint_Register,
+	MPI_Comm						comm )
+{
+  SystemLinearEquations* self = (SystemLinearEquations*)_SystemLinearEquations_DefaultNew( name );
+
+	self->isConstructed = True;
+	_SystemLinearEquations_Init(
+		self,
+		solver,
+		nlSolver,
+		context,
+		False, /* TODO: A hack put in place for setting the convergence stream to 'off' if the SLE class is created from within the code, not via an xml */
+		isNonLinear,
+		nonLinearTolerance,
+		nonLinearMaxIterations,
+		killNonConvergent,
+		1, /* TODO : hack for setting the minimum number of iterations to 1- same hack as above */
+		"",
+		"",
+		entryPoint_Register,
+		comm );
+
+	return self;
+}
+
+/* Creation implementation / Virtual constructor */
+SystemLinearEquations* _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_DEFARGS  ) 
+{
+	SystemLinearEquations* self;
+
+	/* Allocate memory */
+	assert( _sizeOfSelf >= sizeof(SystemLinearEquations) );
+	/* The following terms are parameters that have been passed into this function but are being set before being passed onto the parent */
+	/* This means that any values of these parameters that are passed into this function are not passed onto the parent function
+	   and so should be set to ZERO in any children of this class. */
+	nameAllocationType = NON_GLOBAL;
+
+	self = (SystemLinearEquations*) _Stg_Component_New(  STG_COMPONENT_PASSARGS  );
+	
+	/* Virtual info */
+	self->_LM_Setup = _LM_Setup;
+	self->_matrixSetup = _matrixSetup;
+	self->_vectorSetup = _vectorSetup;
+	self->_updateSolutionOntoNodes = _updateSolutionOntoNodes;
+	self->_mgSelectStiffMats = _mgSelectStiffMats;
+
+	self->_sleFormFunction = NULL;
+	
+	return self;
+}
+
+void _SystemLinearEquations_Init( 
+	void*							sle, 
+	SLE_Solver*					solver, 
+	void*							nlSolver,
+	FiniteElementContext*	context, 
+	Bool							makeConvergenceFile,  
+	Bool							isNonLinear,
+	double						nonLinearTolerance,
+	Iteration_Index			nonLinearMaxIterations,
+	Bool							killNonConvergent,
+	Iteration_Index			nonLinearMinIterations,
+	Name							nonLinearSolutionType,
+	Name							optionsPrefix,
+	EntryPoint_Register*		entryPoint_Register,
+	MPI_Comm						comm ) 
+{
+	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
+	char*							filename;
+	char*							optionsName;
+
+	self->extensionManager = ExtensionManager_New_OfExistingObject( self->name, self );
+	
+	self->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, self->type );
+	self->info =  Journal_MyStream( Info_Type, self );
+    /* Note: currently we're sending self->info to the master proc only so there's not too much
+	   identical timing info printed. May want to fine-tune later so that some info does get 
+       printed on all procs. */	
+	Stream_SetPrintingRank( self->info, 0 );
+
+	self->makeConvergenceFile = makeConvergenceFile;
+	if ( self->makeConvergenceFile ) {
+		self->convergenceStream = Journal_Register( InfoStream_Type, (Name)"Convergence Info"  );
+		Stg_asprintf( &filename, "Convergence.dat" );
+		Stream_RedirectFile_WithPrependedPath( self->convergenceStream, context->outputPath, filename );
+		Stream_SetPrintingRank( self->convergenceStream, 0 );
+		Memory_Free( filename );
+		Journal_Printf( self->convergenceStream , "Timestep\tIteration\tResidual\tTolerance\n" );
+	}
+	
+	self->comm = comm;
+	self->solver = solver;
+	self->nlSolver = (SNES)nlSolver;
+	self->stiffnessMatrices = Stg_ObjectList_New();
+	self->forceVectors = Stg_ObjectList_New();
+	self->solutionVectors = Stg_ObjectList_New();
+	self->bcRemoveQuery = True;
+	self->context = context;
+
+	/* Init NonLinear Stuff */
+	self->nonLinearSolutionType = nonLinearSolutionType; /* This will never got propogated through to _Initialise->SetToNonLinear if we keep it in the loop */
+	if ( isNonLinear ) {
+		self->nonLinearSolutionType	= nonLinearSolutionType;
+		SystemLinearEquations_SetToNonLinear( self );
+	}
+	self->nonLinearTolerance        = nonLinearTolerance;
+	self->nonLinearMaxIterations    = nonLinearMaxIterations;
+	self->killNonConvergent         = killNonConvergent;
+	self->nonLinearMinIterations    = nonLinearMinIterations;    
+	self->curResidual               = 0.0;
+	self->curSolveTime              = 0.0;
+									     /* _  /0 */
+	optionsName = Memory_Alloc_Array_Unnamed( char, strlen(optionsPrefix) + 1 + 1 );
+	sprintf( optionsName, "%s_", optionsPrefix );
+	self->optionsPrefix = optionsName;
+
+	/* BEGIN LUKE'S FRICTIONAL BCS BIT */
+	Stg_asprintf( &self->nlSetupEPName, "%s-nlSetupEP", self->name );
+	self->nlSetupEP = EntryPoint_New( self->nlSetupEPName, EntryPoint_2VoidPtr_CastType );
+	Stg_asprintf( &self->nlEPName, "%s-nlEP", self->name );
+	self->nlEP = EntryPoint_New( self->nlEPName, EntryPoint_2VoidPtr_CastType );
+	Stg_asprintf( &self->nlEPName, "%s-postNlEP", self->name );
+	self->postNlEP = EntryPoint_New( self->postNlEPName, EntryPoint_2VoidPtr_CastType );
+	Stg_asprintf( &self->nlConvergedEPName, "%s-nlConvergedEP", self->name );
+	self->nlConvergedEP = EntryPoint_New( self->nlConvergedEPName, EntryPoint_2VoidPtr_CastType );
+	/* END LUKE'S FRICTIONAL BCS BIT */
+	self->nlFormJacobian = False;
+	self->nlCurIterate = PETSC_NULL;
+	
+	/* Initialise MG stuff. */
+	self->mgEnabled = False;
+	self->mgUpdate = True;
+	self->nMGHandles = 0;
+	self->mgHandles = NULL;
+	
+	/* Create Execute Entry Point */
+	Stg_asprintf( &self->executeEPName, "%s-execute", self->name );
+	self->executeEP = EntryPoint_New( self->executeEPName, EntryPoint_2VoidPtr_CastType );
+
+	/* Add default hooks to Execute E.P. */
+	EntryPoint_Append( self->executeEP, "BC_Setup", (void*)SystemLinearEquations_BC_Setup, self->type);
+	EntryPoint_Append( self->executeEP, "LM_Setup", (void*)SystemLinearEquations_LM_Setup, self->type);
+	EntryPoint_Append( self->executeEP, "IntegrationSetup", (void*)SystemLinearEquations_IntegrationSetup, self->type );
+	EntryPoint_Append( self->executeEP, "ZeroAllVectors", (void*)SystemLinearEquations_ZeroAllVectors, self->type);
+	EntryPoint_Append( self->executeEP, "MatrixSetup", (void*)SystemLinearEquations_MatrixSetup, self->type);
+	EntryPoint_Append( self->executeEP, "VectorSetup", (void*)SystemLinearEquations_VectorSetup, self->type);
+	EntryPoint_Append( self->executeEP, "ExecuteSolver", (void*)SystemLinearEquations_ExecuteSolver, self->type);
+	EntryPoint_Append( self->executeEP, "UpdateSolutionOntoNodes",(void*)SystemLinearEquations_UpdateSolutionOntoNodes,self->type);
+
+	/* Create Integration Setup EP */
+	Stg_asprintf( &self->integrationSetupEPName, "%s-integrationSetup", self->name );
+	self->integrationSetupEP = EntryPoint_New( self->integrationSetupEPName, EntryPoint_Class_VoidPtr_CastType );
+	
+	if ( entryPoint_Register )
+		EntryPoint_Register_Add( entryPoint_Register, self->executeEP );
+	self->entryPoint_Register = entryPoint_Register;
+
+	/* Add SLE to Context */
+	if ( context )
+		FiniteElementContext_AddSLE( context, self );
+}
+
+void _SystemLinearEquations_Delete( void* sle ) {
+	SystemLinearEquations* self = (SystemLinearEquations*)sle;
+	
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+	
+	/* delete parent */
+	_Stg_Component_Delete( self );
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void _SystemLinearEquations_Print( void* sle, Stream* stream ) {
+	SystemLinearEquations*		self = (SystemLinearEquations*)sle;
+	
+	/* General info */
+	Journal_Printf( stream, "SystemLinearEquations (ptr): %p\n", self );
+	_Stg_Component_Print( self, stream );
+	
+	/* Virtual info */
+	Stg_Class_Print( self->stiffnessMatrices, stream );
+	Stg_Class_Print( self->forceVectors, stream );
+	Stg_Class_Print( self->solutionVectors, stream );
+
+	/* other info */
+	Journal_PrintPointer( stream, self->extensionManager );
+	Journal_Printf( stream, "\tcomm: %u\n", self->comm );
+	Journal_Printf( stream, "\tsolver (ptr): %p\n", self->solver );
+	Stg_Class_Print( self->solver, stream );
+}
+
+void* _SystemLinearEquations_Copy( const void* sle, void* dest, Bool deep, Name nameExt, PtrMap* ptrMap ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
+	SystemLinearEquations*	newSLE;
+	PtrMap*			map = ptrMap;
+	Bool			ownMap = False;
+	
+	if( !map ) {
+		map = PtrMap_New( 10 );
+		ownMap = True;
+	}
+	
+	newSLE = (SystemLinearEquations*)_Stg_Component_Copy( sle, dest, deep, nameExt, map );
+	
+	/* Virtual methods */
+	newSLE->_LM_Setup = self->_LM_Setup;
+	newSLE->_matrixSetup = self->_matrixSetup;
+	newSLE->_vectorSetup = self->_vectorSetup;
+	newSLE->_mgSelectStiffMats = self->_mgSelectStiffMats;
+	
+	newSLE->debug = Stream_RegisterChild( StgFEM_SLE_SystemSetup_Debug, newSLE->type );
+	newSLE->comm = self->comm;
+	
+	if( deep ) {
+		newSLE->solver = (SLE_Solver*)Stg_Class_Copy( self->solver, NULL, deep, nameExt, map );
+		newSLE->stiffnessMatrices = (StiffnessMatrixList*)Stg_Class_Copy( self->stiffnessMatrices, NULL, deep, nameExt, map );
+		newSLE->forceVectors = (ForceVectorList*)Stg_Class_Copy( self->forceVectors, NULL, deep, nameExt, map );
+		newSLE->solutionVectors = (SolutionVectorList*)Stg_Class_Copy( self->solutionVectors, NULL, deep, nameExt, map );
+		if( (newSLE->extensionManager = (ExtensionManager*)PtrMap_Find( map, self->extensionManager )) == NULL ) {
+                  newSLE->extensionManager = (ExtensionManager*)Stg_Class_Copy( self->extensionManager, NULL, deep, nameExt, map );
+			PtrMap_Append( map, self->extensionManager, newSLE->extensionManager );
+		}
+	}
+	else {
+		newSLE->solver = self->solver;
+		newSLE->stiffnessMatrices = self->stiffnessMatrices;
+		newSLE->forceVectors = self->forceVectors;
+		newSLE->solutionVectors = self->solutionVectors;
+	}
+	
+	if( ownMap ) {
+		Stg_Class_Delete( map );
+	}
+	
+	return newSLE;
+}
+
+void* _SystemLinearEquations_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                                            _sizeOfSelf = sizeof(SystemLinearEquations);
+	Type                                                                    type = SystemLinearEquations_Type;
+	Stg_Class_DeleteFunction*                                            _delete = _SystemLinearEquations_Delete;
+	Stg_Class_PrintFunction*                                              _print = _SystemLinearEquations_Print;
+	Stg_Class_CopyFunction*                                                _copy = _SystemLinearEquations_Copy;
+	Stg_Component_DefaultConstructorFunction*                _defaultConstructor = _SystemLinearEquations_DefaultNew;
+	Stg_Component_ConstructFunction*                                  _construct = _SystemLinearEquations_AssignFromXML;
+	Stg_Component_BuildFunction*                                          _build = _SystemLinearEquations_Build;
+	Stg_Component_InitialiseFunction*                                _initialise = _SystemLinearEquations_Initialise;
+	Stg_Component_ExecuteFunction*                                      _execute = _SystemLinearEquations_Execute;
+	Stg_Component_DestroyFunction*                                      _destroy = _SystemLinearEquations_Destroy;
+	SystemLinearEquations_LM_SetupFunction*                            _LM_Setup = _SystemLinearEquations_LM_Setup;
+	SystemLinearEquations_MatrixSetupFunction*                      _matrixSetup = _SystemLinearEquations_MatrixSetup;
+	SystemLinearEquations_VectorSetupFunction*                      _vectorSetup = _SystemLinearEquations_VectorSetup;
+	SystemLinearEquations_UpdateSolutionOntoNodesFunc*  _updateSolutionOntoNodes = _SystemLinearEquations_UpdateSolutionOntoNodes;
+	SystemLinearEquations_MG_SelectStiffMatsFunc*             _mgSelectStiffMats = _SystemLinearEquations_MG_SelectStiffMats;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _SystemLinearEquations_New(  SYSTEMLINEAREQUATIONS_PASSARGS  );
+}
+
+void _SystemLinearEquations_AssignFromXML( void* sle, Stg_ComponentFactory* cf, void* data ){
+	SystemLinearEquations*  self = (SystemLinearEquations*)sle;
+	SLE_Solver*             solver = NULL;
+	void*                   entryPointRegister = NULL;
+	FiniteElementContext*   context = NULL;
+	double                  nonLinearTolerance;
+	Iteration_Index         nonLinearMaxIterations;
+	Bool                    isNonLinear;
+	Bool                    killNonConvergent;
+	Bool                    makeConvergenceFile;
+	Iteration_Index         nonLinearMinIterations;                     
+	Name							nonLinearSolutionType;
+	SNES                    nlSolver = NULL;
+	Name							optionsPrefix;
+	
+	solver = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)SLE_Solver_Type, SLE_Solver, False, data  ) ;
+
+	makeConvergenceFile		= Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"makeConvergenceFile", False  );
+	isNonLinear					= Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"isNonLinear", False  );
+	nonLinearTolerance		= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"nonLinearTolerance", 0.01  );
+	nonLinearMaxIterations	= Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"nonLinearMaxIterations", 500  );
+	killNonConvergent			= Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"killNonConvergent", True  );
+	nonLinearMinIterations 	= Stg_ComponentFactory_GetUnsignedInt( cf, self->name, (Dictionary_Entry_Key)"nonLinearMinIterations", 1  );
+	nonLinearSolutionType	= Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"nonLinearSolutionType", "default"  );
+	optionsPrefix				= Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"optionsPrefix", ""  );
+
+	/* Read some value for Picard */
+	self->picard_form_function_type = Stg_ComponentFactory_GetString( cf, self->name, (Dictionary_Entry_Key)"picard_FormFunctionType", "PicardFormFunction_KSPResidual"  );
+
+	self->alpha				= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"picard_alpha", 1.0  );
+	self->rtol				= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"picard_rtol", 1.0e-8  );
+	self->abstol			= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"picard_atol", 1.0e-50  );        
+	self->xtol				= Stg_ComponentFactory_GetDouble( cf, self->name, (Dictionary_Entry_Key)"picard_xtol", 1.0e-8  );
+	self->picard_monitor	= Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"picard_ActivateMonitor", False  );
+	
+	context = Stg_ComponentFactory_ConstructByKey( cf, self->name, (Dictionary_Entry_Key)"Context", FiniteElementContext, False, data );
+	if( !context  )
+		context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data );
+
+	entryPointRegister = context->entryPoint_Register;
+	assert( entryPointRegister );
+
+	if( isNonLinear  ) {
+		SNESCreate( context->communicator, &nlSolver );
+		self->linearSolveInitGuess = Stg_ComponentFactory_GetBool( cf, self->name, (Dictionary_Entry_Key)"linearSolveInitialGuess", False  );
+	}
+	
+	_SystemLinearEquations_Init( 
+		self,
+		solver,
+		nlSolver,
+		context,
+		makeConvergenceFile,
+		isNonLinear,
+		nonLinearTolerance, 
+		nonLinearMaxIterations,
+		killNonConvergent, 
+		nonLinearMinIterations,
+		nonLinearSolutionType,
+		optionsPrefix,
+		(EntryPoint_Register*)entryPointRegister,
+		MPI_COMM_WORLD );
+
+	VecCreate( self->comm, &self->X );
+	VecCreate( self->comm, &self->F );
+	MatCreate( self->comm, &self->A );
+	MatCreate( self->comm, &self->J );
+}
+
+/* Build */
+void _SystemLinearEquations_Build( void* sle, void* _context ) {
+	SystemLinearEquations*		self = (SystemLinearEquations*)sle;
+	Index				index;
+	
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	/* build the matrices */
+	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
+		/* Update rowSize and colSize if boundary conditions have been applied */		
+		Stg_Component_Build( self->stiffnessMatrices->data[index], _context, False );
+	}	
+	
+	/* and the vectors */
+	for ( index = 0; index < self->forceVectors->count; index++ ) {
+		/* Build the force vectors - includes updateing matrix size based on Dofs */
+		Stg_Component_Build( self->forceVectors->data[index], _context, False );
+	}
+	
+	/* and the solutions */
+	for ( index = 0; index < self->solutionVectors->count; index++ ) {
+		/* Build the force vectors - includes updateing matrix size based on Dofs */
+		Stg_Component_Build( self->solutionVectors->data[index], _context, False );
+	}
+	
+	/* lastly, the solver - if required */
+	if( self->solver )
+		Stg_Component_Build( self->solver, self, False );
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _SystemLinearEquations_Initialise( void* sle, void* _context ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	Index						index;
+	
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	/* initialise the matrices */
+	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
+		/* Update rowSize and colSize if boundary conditions have been applied */		
+		Stg_Component_Initialise( self->stiffnessMatrices->data[index], _context, False );
+	}	
+	
+	/* and the vectors */
+	for ( index = 0; index < self->forceVectors->count; index++ ) {
+		/* Initialise the force vectors - includes updateing matrix size based on Dofs */
+		Stg_Component_Initialise( self->forceVectors->data[index], _context, False );
+	}
+	
+	/* and the solutions */
+	for ( index = 0; index < self->solutionVectors->count; index++ ) {
+		/* Initialise the force vectors - includes updateing matrix size based on Dofs */
+		Stg_Component_Initialise( self->solutionVectors->data[index], _context, False );
+	}
+
+	/* Check to see if any of the components need to make the SLE non-linear */
+	SystemLinearEquations_CheckIfNonLinear( self );
+	
+	/* Setup Location Matrix */
+	SystemLinearEquations_LM_Setup( self, _context );
+
+	/* lastly, the solver, if required */
+	if( self->solver )
+		Stg_Component_Initialise( self->solver, self, False );
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void _SystemLinearEquations_Execute( void* sle, void* _context ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
+	
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+
+	_EntryPoint_Run_2VoidPtr( self->executeEP, sle, _context );
+	
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void SystemLinearEquations_ExecuteSolver( void* sle, void* _context ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
+	double wallTime;
+	/* Actually run the solver to get the new values into the SolutionVectors */
+	
+	Journal_Printf(self->info,"Linear solver (%s) \n",self->executeEPName);
+		
+	wallTime = MPI_Wtime();
+	if( self->solver )	
+		Stg_Component_Execute( self->solver, self, True );
+	
+	self->curSolveTime = MPI_Wtime() - wallTime;
+	Journal_Printf(self->info,"Linear solver (%s), solution time %6.6e (secs)\n",self->executeEPName, self->curSolveTime);
+		
+}
+
+void _SystemLinearEquations_Destroy( void* sle, void* _context ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
+	
+	/* BEGIN LUKE'S FRICTIONAL BCS BIT */
+	Memory_Free( self->nlSetupEPName );
+	Memory_Free( self->nlEPName );
+	Memory_Free( self->postNlEPName );
+	Memory_Free( self->nlConvergedEPName );
+	/* END LUKE'S FRICTIONAL BCS BIT */
+	Memory_Free( self->executeEPName );
+	
+	Stg_Class_Delete( self->extensionManager );
+
+	Stg_Class_Delete( self->stiffnessMatrices ); 
+	Stg_Class_Delete( self->forceVectors ); 
+	Stg_Class_Delete( self->solutionVectors ); 
+
+	Memory_Free( self->optionsPrefix );
+
+	VecDestroy( self->X );
+	VecDestroy( self->F );
+	MatDestroy( self->A );
+	MatDestroy( self->J );
+
+	/* Free the the MG handles. */
+	FreeArray( self->mgHandles );
+}
+
+void SystemLinearEquations_BC_Setup( void* sle, void* _context ) {
+	SystemLinearEquations*				self = (SystemLinearEquations*)sle;
+	Index						index;
+	
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	for ( index = 0; index < self->solutionVectors->count; index++ ) {
+		SolutionVector_ApplyBCsToVariables( self->solutionVectors->data[index], _context );
+	}
+}
+
+
+void SystemLinearEquations_LM_Setup( void* sle, void* _context ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	self->_LM_Setup( self, _context );
+}
+
+void SystemLinearEquations_IntegrationSetup( void* sle, void* _context ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	_EntryPoint_Run_Class_VoidPtr( self->integrationSetupEP, _context );
+}
+
+void _SystemLinearEquations_LM_Setup( void* sle, void* _context ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	Index						index;
+
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+	/* For each feVariable of each stiffness matrix, build the LM  */
+	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
+		StiffnessMatrix*				sm = (StiffnessMatrix*)self->stiffnessMatrices->data[index];
+		
+		FeEquationNumber_BuildLocationMatrix( sm->rowVariable->eqNum );
+		FeEquationNumber_BuildLocationMatrix( sm->columnVariable->eqNum );
+	}
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+void SystemLinearEquations_MatrixSetup( void* sle, void* _context ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	self->_matrixSetup( self, _context );
+}
+
+void _SystemLinearEquations_MatrixSetup( void* sle, void* _context ) {
+	SystemLinearEquations*				self = (SystemLinearEquations*)sle;
+	FiniteElementContext*				context = (FiniteElementContext*)_context;
+	Index						index;
+	
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
+		StiffnessMatrix_Assemble( self->stiffnessMatrices->data[index], self->bcRemoveQuery, self, context );
+	}
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void SystemLinearEquations_VectorSetup( void* sle, void* _context ) {
+	SystemLinearEquations*				self = (SystemLinearEquations*)sle;
+	
+	self->_vectorSetup( self, _context );
+}
+
+void _SystemLinearEquations_VectorSetup( void* sle, void* _context ) {
+	SystemLinearEquations*				self = (SystemLinearEquations*)sle;
+	Index						index;
+	
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+	for ( index = 0; index < self->forceVectors->count; index++ ) {
+		ForceVector_Assemble( self->forceVectors->data[index] );
+	}
+	Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+Index _SystemLinearEquations_AddStiffnessMatrix( void* sle, StiffnessMatrix* stiffnessMatrix ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	return SystemLinearEquations_AddStiffnessMatrix( self, stiffnessMatrix );
+}
+
+StiffnessMatrix* _SystemLinearEquations_GetStiffnessMatrix( void* sle, Name stiffnessMatrixName ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	return SystemLinearEquations_GetStiffnessMatrix( self, stiffnessMatrixName );
+}
+
+Index _SystemLinearEquations_AddForceVector( void* sle, ForceVector* forceVector ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	return SystemLinearEquations_AddForceVector( self, forceVector );
+}
+
+ForceVector* _SystemLinearEquations_GetForceVector( void* sle, Name forceVectorName ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	return SystemLinearEquations_GetForceVector( self, forceVectorName );
+}
+
+Index _SystemLinearEquations_AddSolutionVector( void* sle, SolutionVector* solutionVector ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	return SystemLinearEquations_AddSolutionVector( self, solutionVector );
+}
+
+SolutionVector* _SystemLinearEquations_GetSolutionVector( void* sle, Name solutionVectorName ) {
+	SystemLinearEquations*					self = (SystemLinearEquations*)sle;
+	
+	return SystemLinearEquations_GetSolutionVector( self, solutionVectorName );
+}
+
+void SystemLinearEquations_UpdateSolutionOntoNodes( void* sle, void* _context ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
+
+	self->_updateSolutionOntoNodes( self, _context );
+}
+
+void _SystemLinearEquations_UpdateSolutionOntoNodes( void* sle, void* _context ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)sle;
+	SolutionVector_Index	solnVec_I;
+	SolutionVector*		currentSolnVec;
+
+	for ( solnVec_I=0; solnVec_I < self->solutionVectors->count; solnVec_I++ ) {
+		currentSolnVec = (SolutionVector*)self->solutionVectors->data[solnVec_I];
+		SolutionVector_UpdateSolutionOntoNodes( currentSolnVec );
+	}	
+}
+
+void SystemLinearEquations_ZeroAllVectors( void* sle, void* _context ) {
+	SystemLinearEquations*      self = (SystemLinearEquations*)sle;
+	Index                       index;
+	ForceVector*                forceVector;
+	
+	Journal_DPrintf( self->debug, "In %s\n", __func__ );
+	for ( index = 0; index < self->forceVectors->count; index++ ) {
+		forceVector = (ForceVector*) self->forceVectors->data[index];
+		
+		VecSet( forceVector->vector, 0.0 );
+	}
+}
+
+/* need to do this before the SLE specific function to set up the 
+pre conditioners is called (beginning of solve) */
+void SystemLinearEquations_NewtonInitialise( void* _context, void* data ) {
+	FiniteElementContext*	context = (FiniteElementContext*)_context;
+	SystemLinearEquations*	sle = (SystemLinearEquations*)context->slEquations->data[0];
+	SNES							snes;
+	SNES							oldSnes = sle->nlSolver;
+
+	/* don't assume that a snes is being used for initial guess, check for this!!! */
+	if( oldSnes && context->timeStep == 1 && !sle->linearSolveInitGuess )
+		SNESDestroy( oldSnes );
+
+	SNESCreate( sle->comm, &snes );
+
+	sle->nlSolver = snes;
+	sle->_setFFunc( &sle->F, context );
+
+	SNESSetJacobian( snes, sle->J, sle->P, sle->_buildJ, sle->buildJContext );
+	SNESSetFunction( snes, sle->F, sle->_buildF, sle->buildFContext );
+
+	/* configure the KSP */
+	sle->_configureNLSolverFunc( snes, context );
+}
+
+/* do this after the pre conditoiners have been set up in the problem specific SLE */
+void SystemLinearEquations_NewtonExecute( void* sle, void* _context ) {
+	SystemLinearEquations*	self            = (SystemLinearEquations*) sle;
+	SNES			snes		= self->nlSolver;
+
+	SNESSetOptionsPrefix( snes, self->optionsPrefix );
+	SNESSetFromOptions( snes );
+	SNESSolve( snes, PETSC_NULL, self->X );
+}
+
+/* do this at end of solve step */
+void SystemLinearEquations_NewtonFinalise( void* _context, void* data ) {
+	FiniteElementContext*	context		= (FiniteElementContext*)_context;
+	SystemLinearEquations*	sle             = (SystemLinearEquations*)context->slEquations->data[0];
+	SNES			snes		= sle->nlSolver;
+
+	sle->_updateOldFields( &sle->X, context );
+	
+	SNESDestroy( snes );	
+}
+
+void SystemLinearEquations_NewtonMFFDExecute( void* sle, void* _context ) {
+	SystemLinearEquations*	self            = (SystemLinearEquations*) sle;
+	Vec    			F;
+
+	VecDuplicate( SystemLinearEquations_GetSolutionVectorAt( self, 0 )->vector, &F );
+
+	/* creates the nonlinear solver */
+	if( self->nlSolver != PETSC_NULL )
+		SNESDestroy( self->nlSolver );
+	SNESCreate( self->comm, &self->nlSolver );
+	SNESSetFunction( self->nlSolver, F, self->_buildF, _context );
+
+	// set J (jacobian)
+	
+	// set F (residual vector)
+	
+	// call non linear solver func (SNES wrapper)
+}
+
+void SystemLinearEquations_NonLinearExecute( void* sle, void* _context ) {
+	SystemLinearEquations*	self            = (SystemLinearEquations*) sle;
+	Vec                     previousVector;
+	Vec                     currentVector;
+	double                  residual;
+	double                  tolerance       = self->nonLinearTolerance;
+	Iteration_Index         maxIterations   = self->nonLinearMaxIterations;
+	Bool                    converged;
+	Stream*                 errorStream     = Journal_Register( Error_Type, (Name)self->type  );
+	double					wallTime;
+	Iteration_Index         minIterations   = self->nonLinearMinIterations;
+        SLE_Solver*             solver;
+
+	PetscScalar		currVecNorm, prevVecNorm;
+
+	Journal_Printf( self->info, "In %s\n", __func__ );
+	Stream_IndentBranch( StgFEM_Debug );
+		
+	wallTime = MPI_Wtime();		
+
+	/* First Solve */
+	/* setting the nonlinear stuff */
+	//START OF NONLINEAR ITERATION!!!!!
+	/* first get current timestep */
+        solver = self->solver;
+	solver->currenttimestep = self->context->timeStep;
+	/* if current timestep is not the same as previous timestep, then reset all variables back to zero and update previous timestep */
+	if(solver->currenttimestep != solver->previoustimestep){
+		//update prev timestep
+		solver->previoustimestep = solver->currenttimestep;
+		solver->nonlinearitsinitialtime = 0; 
+		solver->nonlinearitsendtime = 0; 
+		solver->totalnonlinearitstime = 0; 
+		solver->totalnumnonlinearits = 0; 
+		solver->avgtimenonlinearits = 0; 	
+		solver->inneritsinitialtime = 0; 
+		solver->outeritsinitialtime = 0; 
+		solver->inneritsendtime = 0; 
+		solver->outeritsendtime = 0; 
+		solver->totalinneritstime = 0; 
+		solver->totalouteritstime = 0; 
+		solver->totalnuminnerits = 0; 
+		solver->totalnumouterits = 0; 
+		solver->avgnuminnerits = 0; 
+		solver->avgnumouterits = 0; 
+		solver->avgtimeinnerits = 0; 
+		solver->avgtimeouterits = 0;	
+	}
+
+	self->nonLinearIteration_I = 0;
+	Journal_Printf(self->info,"\nNon linear solver - iteration %d\n", self->nonLinearIteration_I);
+
+        /* More of Luke's stuff. I need an entry point for a non-linear setup operation. */
+        _EntryPoint_Run_2VoidPtr( self->nlSetupEP, sle, _context );
+
+	/*Don't know if we should include this but the timing of the outer and inner iterations starts here so it makes sense to count this one? */		
+	solver->nonlinearitsinitialtime = MPI_Wtime();
+
+	self->linearExecute( self, _context );
+	self->hasExecuted = True;
+
+	solver->nonlinearitsendtime = MPI_Wtime();
+	solver->totalnonlinearitstime = solver->totalnonlinearitstime + (-solver->nonlinearitsinitialtime + solver->nonlinearitsendtime);
+	/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
+	solver->nonlinearitsinitialtime = 0;
+	solver->nonlinearitsendtime = 0;
+	/*
+	** Include an entry point to do some kind of post-non-linear-iteration operation. */
+	_EntryPoint_Run_2VoidPtr( self->postNlEP, sle, _context );
+
+	/* TODO - Give option which solution vector to test */
+	currentVector   = SystemLinearEquations_GetSolutionVectorAt( self, 0 )->vector; 
+	VecDuplicate( currentVector, &previousVector );
+	
+	for ( self->nonLinearIteration_I = 1 ; self->nonLinearIteration_I < maxIterations ; self->nonLinearIteration_I++ ) {
+		/* get initial wall time for nonlinear loop */
+		solver->nonlinearitsinitialtime = MPI_Wtime();
+		
+		/*
+		** BEGIN LUKE'S FRICTIONAL BCS BIT
+		**
+		** Adding an interface for allowing other components to add some form of non-linearity to the system.
+		** This is with a focus on frictional BCs, where we want to examine the stress field and modify
+		** traction BCs to enforce friction rules. - Luke 18/07/2007
+		*/
+
+		_EntryPoint_Run_2VoidPtr( self->nlEP, sle, _context );
+		
+		/*
+		** END LUKE'S FRICTIONAL BCS BIT
+		*/
+
+
+		//Vector_CopyEntries( currentVector, previousVector );
+		VecCopy( currentVector, previousVector );
+	
+		Journal_Printf(self->info,"Non linear solver - iteration %d\n", self->nonLinearIteration_I);
+			
+		self->linearExecute( self, _context );
+//		PetscPrintf( PETSC_COMM_WORLD, "|Xn+1| = %12.12e \n", Vector_L2Norm(SystemLinearEquations_GetSolutionVectorAt(self,1)->vector) );
+
+		/* Calculate Residual */
+		VecAXPY( previousVector, -1.0, currentVector );
+		VecNorm( previousVector, NORM_2, &prevVecNorm );
+		VecNorm( currentVector, NORM_2, &currVecNorm );
+		residual = ((double)prevVecNorm) / ((double)currVecNorm);
+		
+		self->curResidual = residual;
+
+                /*
+                ** Include an entry point to do some kind of post-non-linear-iteration operation. */
+		_EntryPoint_Run_2VoidPtr( self->postNlEP, sle, _context );
+
+		Journal_Printf( self->info, "In func %s: Iteration %u of %u - Residual %.5g - Tolerance = %.5g\n", 
+				__func__, self->nonLinearIteration_I, maxIterations, residual, tolerance );
+		if ( self->makeConvergenceFile ) {
+			Journal_Printf( self->convergenceStream, "%d\t\t%d\t\t%.5g\t\t%.5g\n", 
+							 self->context->timeStep, self->nonLinearIteration_I, residual, tolerance );
+		}
+			
+		/* Check if residual is below tolerance */
+		converged = (residual < tolerance) ? True : False;
+		
+		Journal_Printf(self->info,"Non linear solver - Residual %.8e; Tolerance %.4e%s%s - %6.6e (secs)\n\n", residual, tolerance, 
+			(converged) ? " - Converged" : " - Not converged",
+			(self->nonLinearIteration_I < maxIterations) ? "" : " - Reached iteration limit",
+			MPI_Wtime() - wallTime );
+			//END OF NONLINEAR ITERATION LOOP!!!
+			
+			/* add the outer loop iterations to the total outer iterations */
+			solver->totalnumnonlinearits = solver->totalnumnonlinearits++;
+			/*get wall time for end of outer loop*/
+			solver->nonlinearitsendtime = MPI_Wtime();
+			/* add time to total time inner its: */
+			solver->totalnonlinearitstime = solver->totalnonlinearitstime + (-solver->nonlinearitsinitialtime + solver->nonlinearitsendtime);
+			//printf("totalnumnonlinearits before converging is %d totalnonlinearitstime is %g, totalouteritstime is %g and totalinneritstime is %g\n",solver->totalnumnonlinearits,solver->totalnonlinearitstime,solver->totalouteritstime,solver->totalinneritstime);
+
+			/* reset initial time and end time for inner its back to 0 - probs don't need to do this but just in case */
+			solver->nonlinearitsinitialtime = 0;
+			solver->nonlinearitsendtime = 0;        
+		if ( (converged) && (self->nonLinearIteration_I>=minIterations) ) {
+		   int result;
+
+		   /* Adding in another entry point so we can insert out own custom
+		      convergeance checks. For example, with frictional boundary
+		      conditions we need to ensure envery node was gone from the
+		      original searching state to a fixed slipping or sticking state. */
+		   _EntryPoint_Run_2VoidPtr( self->nlConvergedEP, _context, &converged );
+		   MPI_Allreduce( &converged, &result, 1, MPI_INT, MPI_LOR, MPI_COMM_WORLD );
+		   if( result )
+		      break;
+		}
+	}
+
+	/* Print Info */
+	if ( converged ) {
+		Journal_Printf( self->info, "In func %s: Converged after %u iterations.\n",
+				__func__, self->nonLinearIteration_I );
+	}
+	else {
+		Journal_Printf( errorStream, "In func %s: Failed to converge after %u iterations.\n", 
+				__func__, self->nonLinearIteration_I);
+		if ( self->killNonConvergent ) {
+			abort();
+		}
+	}
+
+	Stream_UnIndentBranch( StgFEM_Debug );
+
+	VecDestroy( previousVector );
+	
+	/*Set all the printout variables */
+        if( solver->totalnumnonlinearits ) {
+           solver->avgtimenonlinearits = (solver->totalnonlinearitstime - solver->totalouteritstime)/solver->totalnumnonlinearits;
+           solver->avgnumouterits = solver->totalnumouterits/solver->totalnumnonlinearits;
+        }
+        if( solver->totalnumouterits ) {
+           solver->avgnuminnerits = solver->totalnuminnerits/solver->totalnumouterits;
+           solver->avgtimeouterits = (solver->totalouteritstime - solver->totalinneritstime)/solver->totalnumouterits;
+        }
+        if( solver->totalnuminnerits )
+           solver->avgtimeinnerits = solver->totalinneritstime/solver->totalnuminnerits;
+	//printf("totalnumnonlinearits = %d, avgnumouterits %d, avgnuminnerits %d\n",solver->totalnumnonlinearits, solver->avgnumouterits, solver->avgnuminnerits); 
+
+}
+
+void SystemLinearEquations_AddNonLinearSetupEP( void* sle, Name name, EntryPoint_2VoidPtr_Cast func ) {
+	SystemLinearEquations* self = (SystemLinearEquations*)sle;
+
+	SystemLinearEquations_SetToNonLinear( self );
+	EntryPoint_Append( self->nlSetupEP, (char*)name, (void*)func, self->type );
+}
+
+void SystemLinearEquations_AddPostNonLinearEP( void* sle, Name name, EntryPoint_2VoidPtr_Cast func ) {
+	SystemLinearEquations* self = (SystemLinearEquations*)sle;
+
+	EntryPoint_Append( self->postNlEP, (char*)name, (void*)func, self->type );
+}
+
+void SystemLinearEquations_AddNonLinearConvergedEP( void* sle,
+						    Name name,
+						    EntryPoint_2VoidPtr_Cast func )
+{
+	SystemLinearEquations* self = (SystemLinearEquations*)sle;
+
+	SystemLinearEquations_SetToNonLinear( self );
+	EntryPoint_Append( self->nlConvergedEP, (char*)name, (void*)func, self->type );
+}
+
+/*
+Computes
+  F1 := A(x) x -b  = -r,
+  where r = b - A(x) x
+*/
+//void SystemLinearEquations_SNESPicardFormalResidual( void *someSLE, Vector *stg_X, Vector *stg_F, void *_context )
+void SystemLinearEquations_SNESPicardFormalResidual( void *someSLE, Vec X, Vec F, void *_context )
+{
+	SystemLinearEquations *sle = (SystemLinearEquations*)someSLE;
+    	SLE_Solver            *solver = (SLE_Solver*)sle->solver;
+	Stream*                 errorStream     = Journal_Register( Error_Type, (Name)sle->type  );
+
+	Journal_Printf( errorStream, "    **** SystemLinearEquations_SNESPicardFormalResidual: This option is un-tested and does not yet function correctly. \n");
+	Journal_Printf( errorStream, "    **** Use the default form function or specify --components.XXX.picard_FormFunctionType=PicardFormFunction_KSPResidual instead. \n");
+	Journal_Printf( errorStream, "    ****     [Dave May - 12 May, 2008] \n");
+	abort();
+
+	solver->_formResidual( (void*)sle,  (void*)solver, F );
+}
+
+/*
+Computes
+  F2 := x - A(x)^{-1} b
+*/
+#if 0
+void SystemLinearEquations_SNESPicardKSPResidual( void *someSLE, Vector *stg_X, Vector *stg_F, void *_context )
+{
+        SystemLinearEquations *sle = (SystemLinearEquations*)someSLE;
+        SLE_Solver            *solver = (SLE_Solver*)sle->solver;
+        Vec                   F,X,Xcopy;
+        PetscReal norm;
+
+        F = StgVectorGetPetscVec( stg_F );
+        X = StgVectorGetPetscVec( stg_X );
+
+        VecDuplicate( X, &Xcopy );
+        VecCopy( X, Xcopy );
+
+        VecCopy( X, F );                        /* F <- X */
+//      VecNorm( X, NORM_2, &norm );
+//      PetscPrintf(PETSC_COMM_WORLD,"  |X|_pre = %5.5e \n", norm );
+        sle->linearExecute( sle, _context );    /* X = A^{-1} b */
+        X = StgVectorGetPetscVec( stg_X );
+//      VecNorm( X, NORM_2, &norm );
+//      PetscPrintf(PETSC_COMM_WORLD,"  |X|_post = %5.5e \n", norm );
+
+        VecAXPY( F, -1.0, X );                  /* F <- X - F */
+//      VecNorm( F, NORM_2, &norm );
+//      PetscPrintf(PETSC_COMM_WORLD,"  |F|_post = %5.5e \n", norm );
+
+        VecCopy( Xcopy, X );
+        VecDestroy( Xcopy );
+}
+#endif
+
+/*
+stg_X must not get modified by this function !!
+*/
+void SystemLinearEquations_SNESPicardKSPResidual( void *someSLE, Vec X, Vec F, void *_context )
+{
+        SystemLinearEquations *sle = (SystemLinearEquations*)someSLE;
+        SLE_Solver            *solver = (SLE_Solver*)sle->solver;
+	Vec			Xstar;
+	PetscReal norm,norms;
+
+	solver->_getSolution( sle, solver, &Xstar );
+
+	/* Map most current solution into stg object, vec->mesh  */
+	VecCopy( X, Xstar );  /* X* <- X */
+	/* Map onto nodes */
+	SystemLinearEquations_UpdateSolutionOntoNodes( someSLE, _context );
+
+	VecNorm( X, NORM_2, &norm );
+	VecNorm( Xstar, NORM_2, &norms );
+//	PetscPrintf(PETSC_COMM_WORLD,"  |X| = %12.12e : |x*| = %12.12e <pre>\n", norm, norms );
+
+	sle->linearExecute( sle, _context );    /* X* = A^{-1} b */
+
+	VecNorm( X, NORM_2, &norm );
+	VecNorm( Xstar, NORM_2, &norms );
+//	PetscPrintf(PETSC_COMM_WORLD,"  |X| = %12.12e : |x*| = %12.12e <post> \n", norm, norms );
+
+	VecWAXPY( F, -1.0, Xstar, X ); /* F = -X* + X  */
+}
+
+void SLEComputeFunction( void *someSLE, Vec X, Vec F, void *_context )
+{
+        SystemLinearEquations *sle = (SystemLinearEquations*)someSLE;	
+
+	if (sle->_sleFormFunction!=NULL) {
+		sle->_sleFormFunction( sle, X, F, _context );
+	}
+	else {
+		SETERRABORT( sle->comm, PETSC_ERR_SUP, "SLEComputeFunction in not valid" );
+	}
+}
+
+void SLE_SNESMonitor( void *sle, PetscInt iter, PetscReal fnorm )
+{
+  PetscPrintf( PETSC_COMM_WORLD, "  %.4d SLE_NS Function norm %12.12e    --------------------------------------------------------------------------------\n", iter, fnorm );
+}
+
+void SLE_SNESMonitor2( void *sle, PetscInt iter, PetscReal fnorm0, PetscReal fnorm, PetscReal dX, PetscReal X1 )
+{
+  if(iter==0) {
+    PetscPrintf( PETSC_COMM_WORLD, "  SLE_NS  it       |F|              |F|/|F0|          |X1-X0|        |X1-X0|/|X1| \n" );
+  }
+  PetscPrintf( PETSC_COMM_WORLD,   "  SLE_NS  %1.4d     %2.4e      %2.4e       %2.4e     %2.4e \n", iter, fnorm, fnorm/fnorm0, dX, dX/X1 );
+}
+
+void _monitor_progress( PetscReal initial, PetscReal target, PetscReal current, PetscReal *p )
+{
+  PetscReal p0;
+
+  p0 = log10(initial) - log10(target);
+  *p = 100.0 * ( 1.0 - (log10(current)-log10(target)) / p0 );
+}
+
+void SLE_SNESMonitorProgress( void *sle, 
+  PetscInt iter, 
+  PetscReal fnorm0, PetscReal fnorm, PetscReal dX, PetscReal X1, 
+  PetscReal fatol, PetscReal frtol, PetscReal xtol )
+{
+  PetscReal f_abs_s, f_abs_e, v1, p1;
+  PetscReal f_rel_s, f_rel_e, v2, p2;
+  PetscReal x_del_s, x_del_e, v3, p3;
+
+  if(iter==0) {
+    PetscPrintf( PETSC_COMM_WORLD, "  SLE_NS  it       |F|                 |F|/|F0|             |X1-X0|/|X1| \n" );
+  }
+
+  f_abs_s = fnorm0;
+  f_abs_e = fatol;
+  v1 = fnorm;
+  _monitor_progress( f_abs_s, f_abs_e, v1, &p1 );
+
+  f_rel_s = fnorm0;
+  f_rel_e = fnorm0 * frtol;
+  v2 = fnorm;
+  _monitor_progress( f_rel_s, f_rel_e, v2, &p2 );
+
+  x_del_s = 1.0;
+  x_del_e = xtol;
+  v3 = dX/X1;
+  _monitor_progress( x_del_s, x_del_e, v3, &p3 );
+
+  PetscPrintf( PETSC_COMM_WORLD,   "  SLE_NS  %1.4d     %2.4e [%2.0f%%]     %2.4e [%2.0f%%]      %2.4e [%2.0f%%] \n", iter, fnorm,p1, fnorm/fnorm0,p2,  dX/X1,p3 );
+}
+
+
+void SLE_SNESConverged(
+	PetscReal snes_abstol, PetscReal snes_rtol, PetscReal snes_ttol, PetscReal snes_xtol,
+	PetscInt it,PetscReal xnorm,PetscReal pnorm,PetscReal fnorm,SNESConvergedReason *reason )
+{
+  /* PetscErrorCode ierr; */
+
+  *reason = SNES_CONVERGED_ITERATING;
+
+  if (!it) {
+    /* set parameter for default relative tolerance convergence test */
+    snes_ttol = fnorm*snes_rtol;
+  }
+  if (fnorm != fnorm) {
+//    ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRV(ierr);
+    *reason = SNES_DIVERGED_FNORM_NAN;
+  } else if (fnorm < snes_abstol) {
+//    ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes_abstol);CHKERRV(ierr);
+    *reason = SNES_CONVERGED_FNORM_ABS;
+  }
+//  } else if (snes->nfuncs >= snes->max_funcs) {
+//    ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRV(ierr);
+//    *reason = SNES_DIVERGED_FUNCTION_COUNT;
+//  }
+
+  if (it && !*reason) {
+    if (fnorm <= snes_ttol) {
+//      ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes_ttol);CHKERRV(ierr);
+      *reason = SNES_CONVERGED_FNORM_RELATIVE;
+    } else if (pnorm < snes_xtol*xnorm) {
+//      ierr = PetscInfo3(snes,"Converged due to small update length: %G < %G * %G\n",pnorm,snes_xtol,xnorm);CHKERRV(ierr);
+      *reason = SNES_CONVERGED_PNORM_RELATIVE;
+    }
+  }
+}
+
+
+#if defined(PETSC_HAVE_ISINF) && defined(PETSC_HAVE_ISNAN)
+#define PetscIsInfOrNanScalar(a) (isinf(PetscAbsScalar(a)) || isnan(PetscAbsScalar(a)))
+#define PetscIsInfOrNanReal(a) (isinf(a) || isnan(a))
+#elif defined(PETSC_HAVE__FINITE) && defined(PETSC_HAVE__ISNAN)
+#if defined(PETSC_HAVE_FLOAT_H)
+#include "float.h"  /* windows defines _finite() in float.h */ 
+#endif
+#define PetscIsInfOrNanScalar(a) (!_finite(PetscAbsScalar(a)) || _isnan(PetscAbsScalar(a)))
+#define PetscIsInfOrNanReal(a) (!_finite(a) || _isnan(a))
+#else
+#define PetscIsInfOrNanScalar(a) ((a - a) != 0.0)
+#define PetscIsInfOrNanReal(a) ((a - a) != 0.0)
+#endif
+
+/*
+This will be replaced by SNESPicard in petsc 2.4.0.
+*/
+
+void SystemLinearEquations_PicardExecute( void *sle, void *_context )
+{
+  SystemLinearEquations *self = (SystemLinearEquations*)sle;
+  SLE_Solver            *solver = (SLE_Solver*)self->solver;
+
+  Vec            X, Y, F, Xstar,delta_X;
+  PetscReal      alpha = 1.0;
+  PetscReal      fnorm,norm_X,pnorm,fnorm0;
+  PetscInt       i;
+  PetscErrorCode ierr;
+  SNESConvergedReason snes_reason;
+ 
+  PetscReal snes_norm;
+  PetscInt snes_iter;
+
+  PetscReal snes_ttol, snes_rtol, snes_abstol, snes_xtol;
+  PetscInt  snes_maxits;
+
+  PetscTruth monitor_flg;
+
+  /* setup temporary some vectors */
+  solver->_getSolution( self, solver, &Xstar );
+
+  VecDuplicate( Xstar, &X );
+  VecDuplicate( X, &F );
+  VecDuplicate( F, &Y );
+  VecDuplicate( F, &delta_X );
+
+  /* Get some values from dictionary */
+  snes_maxits =  (PetscInt)self->nonLinearMaxIterations;
+  snes_ttol   = 0.0;
+  snes_rtol   = (PetscReal)self->rtol;
+  snes_abstol = (PetscReal)self->abstol;
+  snes_xtol   = (PetscReal)self->xtol;
+  monitor_flg = PETSC_FALSE;
+  if (self->picard_monitor==True) { monitor_flg = PETSC_TRUE; }
+  alpha       = (PetscReal)self->alpha;
+
+  snes_reason = SNES_CONVERGED_ITERATING;
+
+  /* Map X <- X* */
+  VecCopy( Xstar, X );  // Vector_CopyEntries( currentVector, previousVector );
+
+  /* Get an initial guess if |X| ~ 0, by solving the linear problem  */
+  VecNorm( X, NORM_2, &norm_X );
+  if (norm_X <1.0e-20) {
+    if (monitor_flg==PETSC_TRUE)
+      PetscPrintf( PETSC_COMM_WORLD, "SLE_Picard: Computing an initial guess for X from the linear problem\n");
+
+    self->linearExecute( sle, _context );    /* X* = A^{-1} b */
+    self->hasExecuted = True;
+
+    /* Map X <- X* */
+    VecCopy( Xstar, X ); 
+    VecNorm( X, NORM_2, &norm_X );
+  }
+
+
+  snes_iter = 0;
+  snes_norm = 0;
+  //SLEComputeFunction( sle, stg_X, stg_F, _context );
+  SLEComputeFunction( sle, X, F, _context );
+  ierr = VecNorm(F, NORM_2, &fnorm);CHKERRV(ierr); /* fnorm <- ||F||  */
+  fnorm0 = fnorm;
+  if( PetscIsInfOrNanReal(fnorm) ) SETERRABORT( self->comm,PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
+
+  snes_norm = fnorm;
+  if(monitor_flg==PETSC_TRUE) {
+  /*  SLE_SNESMonitor(sle,0,fnorm); */
+  /*  SLE_SNESMonitor2(sle,0,fnorm0,fnorm, norm_X, norm_X ); */
+    SLE_SNESMonitorProgress( sle, snes_iter,  fnorm0, fnorm, norm_X, norm_X, snes_abstol, snes_rtol, snes_xtol );
+  }
+
+  /* set parameter for default relative tolerance convergence test */
+  snes_ttol = fnorm*snes_rtol;
+  /* test convergence */
+  SLE_SNESConverged( snes_abstol,snes_rtol,snes_ttol,snes_xtol , 0,norm_X,0.0,fnorm,&snes_reason);
+  if (snes_reason) return;
+
+  for(i = 0; i < snes_maxits; i++) {
+    /* Update guess Y = X^n - F(X^n) */
+    ierr = VecWAXPY(Y, -1.0, F, X);CHKERRV(ierr);
+
+    VecCopy( X, delta_X );  /* delta_X <- X */
+
+    /* X^{n+1} = (1 - \alpha) X^n + alpha Y */
+    ierr = VecAXPBY(X, alpha, 1 - alpha, Y);CHKERRV(ierr);
+    VecNorm( X, NORM_2, &norm_X ); 
+/*    PetscPrintf( PETSC_COMM_WORLD, "  Xn+1 = %12.12e \n", norm_X ); */
+
+    VecAYPX( delta_X, -1.0, X );   /* delta_X <- Xn+1 - delta_X */
+    VecNorm( delta_X, NORM_2, &pnorm );
+
+    /* Compute F(X^{new}) */
+    SLEComputeFunction( sle, X, F, _context );
+    ierr = VecNorm(F, NORM_2, &fnorm);CHKERRV(ierr);
+    if( PetscIsInfOrNanReal(fnorm) ) SETERRABORT( self->comm,PETSC_ERR_FP,"Infinite or not-a-number generated norm");
+
+    /* Monitor convergence */
+    snes_iter = i+1;
+    snes_norm = fnorm;
+    if (monitor_flg==PETSC_TRUE) {
+    /*  SLE_SNESMonitor(sle,snes_iter,snes_norm); */
+    /*  SLE_SNESMonitor2(sle,snes_iter,fnorm0,fnorm, pnorm, norm_X ); */
+      SLE_SNESMonitorProgress( sle, snes_iter,  fnorm0, fnorm, pnorm, norm_X, snes_abstol, snes_rtol, snes_xtol );
+    }
+
+    /* Test for convergence */
+    SLE_SNESConverged( snes_abstol,snes_rtol,snes_ttol,snes_xtol , snes_iter,norm_X,pnorm,fnorm,&snes_reason);
+    if (snes_reason) break;
+  }
+  if (i == snes_maxits) {
+//    ierr = PetscInfo1(snes, "Maximum number of iterations has been reached: %D\n", maxits);CHKERRV(ierr);
+    if (!snes_reason) snes_reason = SNES_DIVERGED_MAX_IT;
+  }
+
+  /* If monitoring, report reason converged */
+  if (monitor_flg==PETSC_TRUE)
+    PetscPrintf( PETSC_COMM_WORLD, "Nonlinear solve converged due to %s \n", SNESConvergedReasons[snes_reason] );
+
+  VecDestroy( X );
+  VecDestroy( F );
+  VecDestroy( Y );
+  VecDestroy( delta_X );
+
+}
+
+
+///////////////
+
+void SystemLinearEquations_AddNonLinearEP( void* sle, Name name, EntryPoint_2VoidPtr_Cast func ) {
+	SystemLinearEquations* self = (SystemLinearEquations*)sle;
+
+	SystemLinearEquations_SetToNonLinear( self );
+	EntryPoint_Append( self->nlEP, (char*)name, (void*)func, self->type );
+}
+
+
+
+void SystemLinearEquations_SetToNonLinear( void* sle ) {
+	SystemLinearEquations*	self            	= (SystemLinearEquations*) sle;
+	Hook*			nonLinearInitHook	= NULL;
+	Hook*			nonLinearFinaliseHook	= NULL;
+	FiniteElementContext*	context			= NULL;
+
+	assert( self );
+	if ( self->isNonLinear )
+		return;
+
+	self->isNonLinear = True;
+
+	self->linearExecute = self->_execute;
+	self->_execute = SystemLinearEquations_NonLinearExecute;
+
+	if( self->nonLinearSolutionType ) {
+		if( !strcmp( self->nonLinearSolutionType, "default" ) ) {
+			self->_execute = SystemLinearEquations_NonLinearExecute;
+		}		
+
+		if( !strcmp( self->nonLinearSolutionType, "MatrixFreeNewton" ) )
+			self->_execute = SystemLinearEquations_NewtonMFFDExecute;
+
+		if( !strcmp( self->nonLinearSolutionType, "Newton" ) ) {
+			context = self->context;
+
+			nonLinearInitHook = Hook_New( "NewtonInitialise", 
+						(void*)SystemLinearEquations_NewtonInitialise, self->name );
+			_EntryPoint_PrependHook_AlwaysFirst( Context_GetEntryPoint( context, AbstractContext_EP_Solve ), 
+								nonLinearInitHook );
+			nonLinearFinaliseHook = Hook_New( "NewtonFinalise",
+						(void*)SystemLinearEquations_NewtonFinalise, self->name );
+			_EntryPoint_AppendHook_AlwaysLast( Context_GetEntryPoint( context, AbstractContext_EP_Solve ), 
+						nonLinearFinaliseHook );
+			self->_execute = SystemLinearEquations_NewtonExecute;
+		}
+		
+		if (!strcmp( self->nonLinearSolutionType, "Picard") ) {
+			/* set function pointer for execute */
+			self->_execute = SystemLinearEquations_PicardExecute;
+
+			/* set form function */
+			if (!strcmp(self->picard_form_function_type,"PicardFormFunction_KSPResidual") ) {
+				self->_sleFormFunction = SystemLinearEquations_SNESPicardKSPResidual;
+			}
+			else if (!strcmp(self->picard_form_function_type,"PicardFormFunction_FormalResidual") ) {
+				self->_sleFormFunction = SystemLinearEquations_SNESPicardFormalResidual;
+			}
+			else {
+				 Stream *errorStream = Journal_Register( Error_Type, (Name)self->type  );
+
+		                Journal_Printf( errorStream, "Unknown the Picard FormFunction type %s is unrecognised. .\n", self->picard_form_function_type );
+				Journal_Printf( errorStream, "Supported types include <PicardFormFunction_FormalResidual, PicardFormFunction_KSPResidual> \n" );
+                        	abort();
+
+			}
+		}
+	}
+}
+
+void SystemLinearEquations_CheckIfNonLinear( void* sle ) {
+	SystemLinearEquations*	self            = (SystemLinearEquations*) sle;
+	Index                   index;
+	
+	for ( index = 0; index < self->stiffnessMatrices->count; index++ ) {
+		StiffnessMatrix* stiffnessMatrix = SystemLinearEquations_GetStiffnessMatrixAt( self, index );
+		
+		if ( stiffnessMatrix->isNonLinear )
+			SystemLinearEquations_SetToNonLinear( self );
+
+		/* TODO CHECK FOR FORCE VECTORS */
+	}	
+}
+
+/*
+** All the MG functions and their general implementations.
+*/
+
+void SystemLinearEquations_MG_Enable( void* _sle ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)_sle;
+	
+	if( !self->isBuilt ) {
+		Journal_Printf(self->info, "Warning: SLE has not been built, can't enable multi-grid.\n" );
+		return;
+	}
+	
+	self->mgEnabled = True;
+}
+
+
+void SystemLinearEquations_MG_SelectStiffMats( void* _sle, unsigned* nSMs, StiffnessMatrix*** sms ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)_sle;
+	
+	assert( self->_mgSelectStiffMats );
+	self->_mgSelectStiffMats( self, nSMs, sms );
+}
+
+
+void _SystemLinearEquations_MG_SelectStiffMats( void* _sle, unsigned* nSMs, StiffnessMatrix*** sms ) {
+	SystemLinearEquations*	self = (SystemLinearEquations*)_sle;
+	
+	/*
+	** As we have nothing else to go on, attempt to apply MG to all stiffness matrices in the list.
+	*/
+	
+	{
+		unsigned	sm_i;
+		
+		*nSMs = 0;
+		for( sm_i = 0; sm_i < self->stiffnessMatrices->count; sm_i++ ) {
+			StiffnessMatrix*	sm = ((StiffnessMatrix**)self->stiffnessMatrices->data)[sm_i];
+			
+			/* Add this one to the list. */
+			*sms = Memory_Realloc_Array( *sms, StiffnessMatrix*, (*nSMs) + 1 );
+			(*sms)[*nSMs] = sm;
+			(*nSMs)++;
+		}
+	}
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/tests/ContextSuite.c
--- a/SLE/SystemSetup/tests/ContextSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-
-typedef struct {
-	FiniteElementContext* context;
-} ContextSuiteData;
-
-void ContextSuite_Setup( ContextSuiteData* data ) {
-	Journal_Enable_AllTypedStream( False );
-}
-
-void ContextSuite_Teardown( ContextSuiteData* data ) {
-	Journal_Enable_AllTypedStream( True );
-}
-
-double ContextSuite_CalcDtFunc( FiniteElementContext* context) {
-	if ( context->timeStep == 1 ) {
-		return 1.0;
-	}
-	else {
-		return context->dt * 1.5; 
-	}
-}
-
-void ContextSuite_TestContext( ContextSuiteData* data ) {
-	/** Test Definition: */
-	char							expected_file[PCU_PATH_MAX];
-	Stg_ComponentFactory*	cf;
-	Dictionary*					dictionary;
-	Name							outputPath;
-	Stream*						stream; 
-	char							xml_input[PCU_PATH_MAX];
-
-	/* read in the xml input file */
-	pcu_filename_input( "testContext.xml", xml_input );
-	
-	cf = stgMainInitFromXML( xml_input, MPI_COMM_WORLD, NULL );
-	data->context = (FiniteElementContext*)LiveComponentRegister_Get( cf->LCRegister, (Name)"context" ); 
-	stgMainBuildAndInitialise(cf );
-
-	dictionary = data->context->dictionary;
-	outputPath = Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"outputPath"  );
-
-	/* Run the test  ----------------------------------------------------------------------------------------------------*/
-	/* This is where we'd normally construct components if it was real main.
-	* instead, we'll just set the dt function so we can test it */
-	EP_AppendClassHook( data->context->calcDtEP, ContextSuite_CalcDtFunc, data->context );
-
-	if( data->context->rank == 0 ) 
-		Context_PrintConcise( data->context, data->context->verbose );
-
-	if ( True == Dictionary_GetBool_WithDefault( dictionary, (Dictionary_Entry_Key)"showJournalStatus", False ) ) {
-		Journal_PrintConcise( );	
-	}	
-
-	/* Building phase ---------------------------------------------------------------------------------------------------*/
-	Stg_Component_Build( data->context, 0 /* dummy */, False );
-    
-	/* Initialisaton phase ----------------------------------------------------------------------------------------------*/
-	Stg_Component_Initialise( data->context, 0 /* dummy */, False );
-    
-	/* Run (Solve) phase ------------------------------------------------------------------------------------------------*/
-	data->context->maxTimeSteps = 10;
-	data->context->dtFactor = 1.0;
-
-	Journal_Enable_TypedStream( InfoStream_Type, True );
-	stream = Journal_Register( Info_Type, (Name)"testContext.xml" ); 
-	data->context->info = stream;  /* Redirect output to test data stream */
-	Stream_RedirectFile_WithPrependedPath( stream, outputPath, "test.dat" );
-
-	Journal_Printf( stream, "Running with no timestep braking, using  " "dt that increases 50%% each step:\n" );
-
-	Stg_Component_Execute( data->context, 0 /* dummy */, False );
-	data->context->currentTime=0;
-	data->context->dt = 0;
-
-	Journal_Printf( stream, "\nTurning on timestep braking, at default " "level, running again:\n" );
-	data->context->limitTimeStepIncreaseRate = True;
-	Stg_Component_Execute( data->context, 0 /* dummy */, True );
-	data->context->currentTime=0;
-	data->context->dt = 0;
-
-	Journal_Printf( stream, "\nTurning on timestep braking, at 80%% " "level, running again - expect same as original:\n" );
-	data->context->maxTimeStepIncreasePercentage = 80;
-	Stg_Component_Execute( data->context, 0 /* dummy */, True );
-
-	Stream_CloseAndFreeFile( stream );
-
-	/* Compare results to expected */
-	pcu_filename_expected( "testContext.expected", expected_file );
-	pcu_check_fileEq( "output/test.dat", expected_file );
-	remove("output/test.dat");
-}
-
-void ContextSuite( pcu_suite_t* suite ) {
-	pcu_suite_setData( suite, ContextSuiteData );
-	pcu_suite_setFixtures( suite, ContextSuite_Setup, ContextSuite_Teardown );
-	pcu_suite_addTest( suite, ContextSuite_TestContext );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/tests/ContextSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/tests/ContextSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,108 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+
+typedef struct {
+	FiniteElementContext* context;
+} ContextSuiteData;
+
+void ContextSuite_Setup( ContextSuiteData* data ) {
+	Journal_Enable_AllTypedStream( False );
+}
+
+void ContextSuite_Teardown( ContextSuiteData* data ) {
+	Journal_Enable_AllTypedStream( True );
+}
+
+double ContextSuite_CalcDtFunc( FiniteElementContext* context) {
+	if ( context->timeStep == 1 ) {
+		return 1.0;
+	}
+	else {
+		return context->dt * 1.5; 
+	}
+}
+
+void ContextSuite_TestContext( ContextSuiteData* data ) {
+	/** Test Definition: */
+	char							expected_file[PCU_PATH_MAX];
+	Stg_ComponentFactory*	cf;
+	Dictionary*					dictionary;
+	Name							outputPath;
+	Stream*						stream; 
+	char							xml_input[PCU_PATH_MAX];
+
+	/* read in the xml input file */
+	pcu_filename_input( "testContext.xml", xml_input );
+	
+	cf = stgMainInitFromXML( xml_input, MPI_COMM_WORLD, NULL );
+	data->context = (FiniteElementContext*)LiveComponentRegister_Get( cf->LCRegister, (Name)"context" ); 
+	stgMainBuildAndInitialise(cf );
+
+	dictionary = data->context->dictionary;
+	outputPath = Dictionary_GetString( dictionary, (Dictionary_Entry_Key)"outputPath"  );
+
+	/* Run the test  ----------------------------------------------------------------------------------------------------*/
+	/* This is where we'd normally construct components if it was real main.
+	* instead, we'll just set the dt function so we can test it */
+	EP_AppendClassHook( data->context->calcDtEP, ContextSuite_CalcDtFunc, data->context );
+
+	if( data->context->rank == 0 ) 
+		Context_PrintConcise( data->context, data->context->verbose );
+
+	if ( True == Dictionary_GetBool_WithDefault( dictionary, (Dictionary_Entry_Key)"showJournalStatus", False ) ) {
+		Journal_PrintConcise( );	
+	}	
+
+	/* Building phase ---------------------------------------------------------------------------------------------------*/
+	Stg_Component_Build( data->context, 0 /* dummy */, False );
+    
+	/* Initialisaton phase ----------------------------------------------------------------------------------------------*/
+	Stg_Component_Initialise( data->context, 0 /* dummy */, False );
+    
+	/* Run (Solve) phase ------------------------------------------------------------------------------------------------*/
+	data->context->maxTimeSteps = 10;
+	data->context->dtFactor = 1.0;
+
+	Journal_Enable_TypedStream( InfoStream_Type, True );
+	stream = Journal_Register( Info_Type, (Name)"testContext.xml" ); 
+	data->context->info = stream;  /* Redirect output to test data stream */
+	Stream_RedirectFile_WithPrependedPath( stream, outputPath, "test.dat" );
+
+	Journal_Printf( stream, "Running with no timestep braking, using  " "dt that increases 50%% each step:\n" );
+
+	Stg_Component_Execute( data->context, 0 /* dummy */, False );
+	data->context->currentTime=0;
+	data->context->dt = 0;
+
+	Journal_Printf( stream, "\nTurning on timestep braking, at default " "level, running again:\n" );
+	data->context->limitTimeStepIncreaseRate = True;
+	Stg_Component_Execute( data->context, 0 /* dummy */, True );
+	data->context->currentTime=0;
+	data->context->dt = 0;
+
+	Journal_Printf( stream, "\nTurning on timestep braking, at 80%% " "level, running again - expect same as original:\n" );
+	data->context->maxTimeStepIncreasePercentage = 80;
+	Stg_Component_Execute( data->context, 0 /* dummy */, True );
+
+	Stream_CloseAndFreeFile( stream );
+
+	/* Compare results to expected */
+	pcu_filename_expected( "testContext.expected", expected_file );
+	pcu_check_fileEq( "output/test.dat", expected_file );
+	remove("output/test.dat");
+}
+
+void ContextSuite( pcu_suite_t* suite ) {
+	pcu_suite_setData( suite, ContextSuiteData );
+	pcu_suite_setFixtures( suite, ContextSuite_Setup, ContextSuite_Teardown );
+	pcu_suite_addTest( suite, ContextSuite_TestContext );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/tests/SolutionVectorSuite.c
--- a/SLE/SystemSetup/tests/SolutionVectorSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,187 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-
-typedef struct {
-} SolutionVectorSuiteData;
-
-void SolutionVectorSuite_Setup( SolutionVectorSuiteData* data ) { }
-
-void SolutionVectorSuite_Teardown( SolutionVectorSuiteData* data ) {}
-
-
-FeVariable* SolutionVectorSuite_buildFeVar() {
-   CartesianGenerator*				gen;
-   FeMesh*								feMesh;
-   DofLayout*							dofs;
-   FeEquationNumber*					eqNum;
-   Variable_Register*				varReg;
-   int									maxDecomp[3] = {0, 1, 1};
-   int									sizes[3];
-   double								minCrd[3];
-   double								maxCrd[3];
-   static int							arraySize;
-   static double*						arrayPtrs[2];
-   int									nRanks;
-   Variable*							var;
-   VariableCondition*				bcs;
-   ConditionFunction_Register*	cfReg;
-   Dictionary*							dict;
-   XML_IO_Handler*					ioHandler;
-   FieldVariable_Register*			fieldReg;
-   FeVariable*							feVar;
-   int									n_i;
-	char									xml_input[PCU_PATH_MAX];
-
-	pcu_filename_input( "testSolutionVector.xml", xml_input );
-
-   MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
-   sizes[0] = nRanks * 2;
-   sizes[1] = sizes[2] = 2;
-   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
-   maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
-
-   gen = CartesianGenerator_New( "", NULL );
-   CartesianGenerator_SetDimSize( gen, 2 );
-   CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
-   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-   CartesianGenerator_SetShadowDepth( gen, 0 );
-
-   feMesh = FeMesh_New( "", NULL );
-   Mesh_SetGenerator( feMesh, gen );
-   FeMesh_SetElementFamily( feMesh, "linear" );
-   Stg_Component_Build( feMesh, NULL, False );
-
-   varReg = Variable_Register_New();
-   cfReg = ConditionFunction_Register_New();
-
-   arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-   arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize * 2 );
-/*
-   arrayPtrs[1] = Memory_Alloc_Array_Unnamed( double, arraySize );
-*/
-   var = Variable_NewVector( "velocity", NULL, Variable_DataType_Double, 2, (unsigned*)&arraySize, NULL, 
-		(void**)arrayPtrs, varReg, 
-		"vx", "vy" );
-   Variable_Register_BuildAll( varReg );
-
-   dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
-   dofs->nBaseVariables = 2;
-   dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 2 );
-   dofs->baseVariables[0] = var->components[0];
-   dofs->baseVariables[1] = var->components[1];
-   Stg_Component_Build( dofs, NULL, False );
-   Stg_Component_Initialise( dofs, NULL, False );
-
-   ioHandler = XML_IO_Handler_New();
-   dict = Dictionary_New();
-   IO_Handler_ReadAllFromFile( ioHandler, xml_input, dict );
-   bcs = (VariableCondition*)WallVC_New( "", NULL, "wallVC", varReg, cfReg, dict, feMesh );
-   Stg_Component_Build( bcs, NULL, False );
-   Stg_Component_Initialise( bcs, NULL, False );
-
-   eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, bcs, NULL );
-   Stg_Component_Build( eqNum, NULL, False );
-   Stg_Component_Initialise( eqNum, NULL, False );
-
-   fieldReg = FieldVariable_Register_New();
-   feVar = FeVariable_New( "velocity", NULL, feMesh, NULL, dofs, bcs, NULL, NULL, 2, True, 
-		False, False, fieldReg );
-
-   for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ); n_i++ ) {
-      /*const double pi=acos(-1.0);*/
-      double* pos = Mesh_GetVertex( feMesh, n_i );
-
-      Variable_SetValue( var, n_i, pos );
-		/*
-      arrayPtrs[0][n_i] = (1.0 - pos[1]) + 0.1 * cos( pi * pos[0] ) * sin(  pi * pos[1]  );
-      arrayPtrs[1][n_i] = (1.0 - pos[1]) + 0.1 * cos( pi * pos[0] ) * sin(  pi * pos[1]  );
-		*/
-   }
-
-   /* Build and initialise system */
-   Stg_Component_Build( bcs, 0, False );
-   Stg_Component_Build( feVar, 0, False );
-   Stg_Component_Initialise( feVar, 0, False );
-
-   return feVar;
-}
-
-
-void SolutionVectorSuite_TestSolutionVector( SolutionVectorSuiteData* data ) {
-	FeVariable*				feVar;
-	FeMesh*					mesh;
-	int						nEls, nVerts, nDims;
-	const int				*verts;
-	double*					vert;
-	double					val[3];
-	InterpolationResult	ret;
-	SolutionVector*		sol;
-	int						lSize;
-	double*					array;
-	IArray*					incArray;
-	int						e_i, v_i, d_i, a_i;
-
-	feVar = SolutionVectorSuite_buildFeVar();
-	FeVariable_SyncShadowValues( feVar );
-	sol = SolutionVector_New( "velocity", NULL, MPI_COMM_WORLD, feVar );
-	/* Check solution vector created */
-	pcu_check_true(sol);
-	Stg_Component_Build( sol, NULL, False );
-
-	SolutionVector_LoadCurrentFeVariableValuesOntoVector( sol );
-	VecGetLocalSize( sol->vector, &lSize );
-	VecGetArray( sol->vector, &array );
-
-	for( a_i = 0; a_i < lSize; a_i++ )
-		array[a_i] += 1.0;
-	VecRestoreArray( sol->vector, &array );
-	SolutionVector_UpdateSolutionOntoNodes( sol );
-
-	mesh = feVar->feMesh;
-	nDims = Mesh_GetDimSize( mesh );
-	nEls = Mesh_GetDomainSize( mesh, (MeshTopology_Dim)nDims );
-	incArray = IArray_New();
-
-	for( e_i = 0; e_i < nEls; e_i++ ) {
-		Mesh_GetIncidence( mesh, (MeshTopology_Dim)nDims, e_i, (MeshTopology_Dim)0, incArray );
-		nVerts = IArray_GetSize( incArray );
-		verts = IArray_GetPtr( incArray );
-		for( v_i = 0; v_i < nVerts; v_i++ ) {
-			vert = Mesh_GetVertex( mesh, verts[v_i] );
-			ret = FieldVariable_InterpolateValueAt( feVar, vert, val );
-			if( ret != LOCAL && ret != SHADOW )
-				continue;
-			for( d_i = 0; d_i < nDims; d_i++ ) {
-				if( !Num_Approx( vert[d_i] + 1.0, val[d_i] ) )
-					break;
-			}
-			if( d_i < nDims )
-				break;
-		}
-		if( v_i < nVerts )
-			break;
-	}
-
-	/* Check all elements processed */
-	pcu_check_true(e_i == nEls);
-
-	NewClass_Delete( incArray );
-
-	FreeObject( feVar );
-	FreeObject( sol );
-}
-
-void SolutionVectorSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, SolutionVectorSuiteData );
-   pcu_suite_setFixtures( suite, SolutionVectorSuite_Setup, SolutionVectorSuite_Teardown );
-   pcu_suite_addTest( suite, SolutionVectorSuite_TestSolutionVector );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/tests/SolutionVectorSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/tests/SolutionVectorSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,187 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+
+typedef struct {
+} SolutionVectorSuiteData;
+
+void SolutionVectorSuite_Setup( SolutionVectorSuiteData* data ) { }
+
+void SolutionVectorSuite_Teardown( SolutionVectorSuiteData* data ) {}
+
+
+FeVariable* SolutionVectorSuite_buildFeVar() {
+   CartesianGenerator*				gen;
+   FeMesh*								feMesh;
+   DofLayout*							dofs;
+   FeEquationNumber*					eqNum;
+   Variable_Register*				varReg;
+   int									maxDecomp[3] = {0, 1, 1};
+   int									sizes[3];
+   double								minCrd[3];
+   double								maxCrd[3];
+   static int							arraySize;
+   static double*						arrayPtrs[2];
+   int									nRanks;
+   Variable*							var;
+   VariableCondition*				bcs;
+   ConditionFunction_Register*	cfReg;
+   Dictionary*							dict;
+   XML_IO_Handler*					ioHandler;
+   FieldVariable_Register*			fieldReg;
+   FeVariable*							feVar;
+   int									n_i;
+	char									xml_input[PCU_PATH_MAX];
+
+	pcu_filename_input( "testSolutionVector.xml", xml_input );
+
+   MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
+   sizes[0] = nRanks * 2;
+   sizes[1] = sizes[2] = 2;
+   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
+   maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
+
+   gen = CartesianGenerator_New( "", NULL );
+   CartesianGenerator_SetDimSize( gen, 2 );
+   CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
+   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+   CartesianGenerator_SetShadowDepth( gen, 0 );
+
+   feMesh = FeMesh_New( "", NULL );
+   Mesh_SetGenerator( feMesh, gen );
+   FeMesh_SetElementFamily( feMesh, "linear" );
+   Stg_Component_Build( feMesh, NULL, False );
+
+   varReg = Variable_Register_New();
+   cfReg = ConditionFunction_Register_New();
+
+   arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+   arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize * 2 );
+/*
+   arrayPtrs[1] = Memory_Alloc_Array_Unnamed( double, arraySize );
+*/
+   var = Variable_NewVector( "velocity", NULL, Variable_DataType_Double, 2, (unsigned*)&arraySize, NULL, 
+		(void**)arrayPtrs, varReg, 
+		"vx", "vy" );
+   Variable_Register_BuildAll( varReg );
+
+   dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
+   dofs->nBaseVariables = 2;
+   dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 2 );
+   dofs->baseVariables[0] = var->components[0];
+   dofs->baseVariables[1] = var->components[1];
+   Stg_Component_Build( dofs, NULL, False );
+   Stg_Component_Initialise( dofs, NULL, False );
+
+   ioHandler = XML_IO_Handler_New();
+   dict = Dictionary_New();
+   IO_Handler_ReadAllFromFile( ioHandler, xml_input, dict );
+   bcs = (VariableCondition*)WallVC_New( "", NULL, "wallVC", varReg, cfReg, dict, feMesh );
+   Stg_Component_Build( bcs, NULL, False );
+   Stg_Component_Initialise( bcs, NULL, False );
+
+   eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, bcs, NULL );
+   Stg_Component_Build( eqNum, NULL, False );
+   Stg_Component_Initialise( eqNum, NULL, False );
+
+   fieldReg = FieldVariable_Register_New();
+   feVar = FeVariable_New( "velocity", NULL, feMesh, NULL, dofs, bcs, NULL, NULL, 2, True, 
+		False, False, fieldReg );
+
+   for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ); n_i++ ) {
+      /*const double pi=acos(-1.0);*/
+      double* pos = Mesh_GetVertex( feMesh, n_i );
+
+      Variable_SetValue( var, n_i, pos );
+		/*
+      arrayPtrs[0][n_i] = (1.0 - pos[1]) + 0.1 * cos( pi * pos[0] ) * sin(  pi * pos[1]  );
+      arrayPtrs[1][n_i] = (1.0 - pos[1]) + 0.1 * cos( pi * pos[0] ) * sin(  pi * pos[1]  );
+		*/
+   }
+
+   /* Build and initialise system */
+   Stg_Component_Build( bcs, 0, False );
+   Stg_Component_Build( feVar, 0, False );
+   Stg_Component_Initialise( feVar, 0, False );
+
+   return feVar;
+}
+
+
+void SolutionVectorSuite_TestSolutionVector( SolutionVectorSuiteData* data ) {
+	FeVariable*				feVar;
+	FeMesh*					mesh;
+	int						nEls, nVerts, nDims;
+	const int				*verts;
+	double*					vert;
+	double					val[3];
+	InterpolationResult	ret;
+	SolutionVector*		sol;
+	int						lSize;
+	double*					array;
+	IArray*					incArray;
+	int						e_i, v_i, d_i, a_i;
+
+	feVar = SolutionVectorSuite_buildFeVar();
+	FeVariable_SyncShadowValues( feVar );
+	sol = SolutionVector_New( "velocity", NULL, MPI_COMM_WORLD, feVar );
+	/* Check solution vector created */
+	pcu_check_true(sol);
+	Stg_Component_Build( sol, NULL, False );
+
+	SolutionVector_LoadCurrentFeVariableValuesOntoVector( sol );
+	VecGetLocalSize( sol->vector, &lSize );
+	VecGetArray( sol->vector, &array );
+
+	for( a_i = 0; a_i < lSize; a_i++ )
+		array[a_i] += 1.0;
+	VecRestoreArray( sol->vector, &array );
+	SolutionVector_UpdateSolutionOntoNodes( sol );
+
+	mesh = feVar->feMesh;
+	nDims = Mesh_GetDimSize( mesh );
+	nEls = Mesh_GetDomainSize( mesh, (MeshTopology_Dim)nDims );
+	incArray = IArray_New();
+
+	for( e_i = 0; e_i < nEls; e_i++ ) {
+		Mesh_GetIncidence( mesh, (MeshTopology_Dim)nDims, e_i, (MeshTopology_Dim)0, incArray );
+		nVerts = IArray_GetSize( incArray );
+		verts = IArray_GetPtr( incArray );
+		for( v_i = 0; v_i < nVerts; v_i++ ) {
+			vert = Mesh_GetVertex( mesh, verts[v_i] );
+			ret = FieldVariable_InterpolateValueAt( feVar, vert, val );
+			if( ret != LOCAL && ret != SHADOW )
+				continue;
+			for( d_i = 0; d_i < nDims; d_i++ ) {
+				if( !Num_Approx( vert[d_i] + 1.0, val[d_i] ) )
+					break;
+			}
+			if( d_i < nDims )
+				break;
+		}
+		if( v_i < nVerts )
+			break;
+	}
+
+	/* Check all elements processed */
+	pcu_check_true(e_i == nEls);
+
+	NewClass_Delete( incArray );
+
+	FreeObject( feVar );
+	FreeObject( sol );
+}
+
+void SolutionVectorSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, SolutionVectorSuiteData );
+   pcu_suite_setFixtures( suite, SolutionVectorSuite_Setup, SolutionVectorSuite_Teardown );
+   pcu_suite_addTest( suite, SolutionVectorSuite_TestSolutionVector );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/tests/StiffnessMatrixSuite.c
--- a/SLE/SystemSetup/tests/StiffnessMatrixSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-
-typedef struct {
-} StiffnessMatrixSuiteData;
-
-void StiffnessMatrixSuite_Setup( StiffnessMatrixSuiteData* data ) { 
-	Journal_Enable_AllTypedStream( False );
-}
-
-void StiffnessMatrixSuite_Teardown( StiffnessMatrixSuiteData* data ) {
-	Journal_Enable_AllTypedStream( True );
-}
-
-FeVariable* buildFeVar() {
-   CartesianGenerator*				gen;
-   FeMesh*								feMesh;
-   DofLayout*							dofs;
-   FeEquationNumber*					eqNum;
-   Variable_Register*				varReg;
-   int									maxDecomp[3] = {0, 1, 1};
-   int									sizes[3];
-   double								minCrd[3];
-   double								maxCrd[3];
-   char									xml_input[PCU_PATH_MAX];
-   static int							arraySize;
-   static double*						arrayPtrs[2];
-   int									nRanks;
-   Variable*							var;
-   VariableCondition*				bcs;
-   ConditionFunction_Register*	cfReg;
-   Dictionary*							dict;
-   XML_IO_Handler*					ioHandler;
-   FieldVariable_Register*			fieldReg;
-   FeVariable*							feVar;
-   int									n_i;
-
-   MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
-   sizes[0] = nRanks * 2;
-   sizes[1] = sizes[2] = 2;
-   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
-   maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
-
-   gen = CartesianGenerator_New( "", NULL );
-   CartesianGenerator_SetDimSize( gen, 2 );
-   CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
-   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
-   CartesianGenerator_SetShadowDepth( gen, 0 );
-
-   feMesh = FeMesh_New( "", NULL );
-   Mesh_SetGenerator( feMesh, gen );
-   FeMesh_SetElementFamily( feMesh, "linear" );
-   Stg_Component_Build( feMesh, NULL, False );
-
-   varReg = Variable_Register_New();
-   cfReg = ConditionFunction_Register_New();
-
-   arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
-   arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize * 2 );
-   var = Variable_NewVector( "velocity", NULL, Variable_DataType_Double, 2, (unsigned*)&arraySize, NULL, 
-		(void**)arrayPtrs, varReg, "vx", "vy" );
-   Variable_Register_BuildAll( varReg );
-
-   dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
-   dofs->nBaseVariables = 2;
-   dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 2 );
-   dofs->baseVariables[0] = var->components[0];
-   dofs->baseVariables[1] = var->components[1];
-   Stg_Component_Build( dofs, NULL, False );
-   Stg_Component_Initialise( dofs, NULL, False );
-
-   ioHandler = XML_IO_Handler_New();
-   dict = Dictionary_New();
-   pcu_filename_input( "velWallVC.xml", xml_input );
-   IO_Handler_ReadAllFromFile( ioHandler, xml_input, dict );
-   bcs = (VariableCondition*)WallVC_New( "", NULL, "wallVC", varReg, cfReg, dict, feMesh );
-   Stg_Component_Build( bcs, NULL, False );
-   Stg_Component_Initialise( bcs, NULL, False );
-
-   eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, bcs, NULL );
-   Stg_Component_Build( eqNum, NULL, False );
-   Stg_Component_Initialise( eqNum, NULL, False );
-
-   fieldReg = FieldVariable_Register_New();
-   feVar = FeVariable_New( "velocity", NULL, feMesh, NULL, dofs, bcs, NULL, NULL, 2, True, 
-		False, False, fieldReg );
-
-   for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ); n_i++ ) {
-      /*const double pi=acos(-1.0);*/
-      double* pos = Mesh_GetVertex( feMesh, n_i );
-
-      /* assign the position vector as the nodes vector */
-      Variable_SetValue( var, n_i, pos );
-   }
-
-   /* Build and initialise system */
-   Stg_Component_Build( bcs, 0, False );
-   Stg_Component_Build( feVar, 0, False );
-   Stg_Component_Initialise( feVar, 0, False );
-
-   return feVar;
-}
-
-
-void StiffnessMatrixSuite_TestStiffnessMatrix( StiffnessMatrixSuiteData* data ) {
-  FeVariable*				feVar;
-  FeMesh*					mesh;
-  EntryPoint_Register*	ep_reg;
-  StiffnessMatrix*		mat;
-  ForceVector*				vec;
-  MPI_Comm					comm;
-
-  pcu_docstring( "This test just creates a Stiffness matrix data structure, builds, itialises, refreshes and then destroys it.\n" );
-
-  /* we need an EP register here for the construction of the ForceVector and StiffnessMatrix */
-  ep_reg = EntryPoint_Register_New();
-
-  /* here we build a feVar with the position vector stored on the nodes */
-  feVar = buildFeVar();
-  mesh = feVar->feMesh;
-  FeVariable_SyncShadowValues( feVar );
-
-  /* create SiffnessMatrix, it requires a ForceVector */
-  comm = Comm_GetMPIComm( Mesh_GetCommTopology( mesh, MT_VERTEX ) );
-  vec = ForceVector_New( "testVector", NULL, feVar, 2, ep_reg, comm );
-  mat = StiffnessMatrix_New( "testMatrix", feVar, feVar, vec, NULL, 2, False, False, ep_reg, comm);
-
-  /* build & initialise the mat, this should build and initialise the vec */
-  Stg_Component_Build( mat, NULL, False );
-  Stg_Component_Initialise( mat, NULL, False );
-
-  StiffnessMatrix_RefreshMatrix( mat );
-
-  pcu_check_true( mat->matrix != NULL );
-
-  Stg_Component_Destroy( feVar, NULL, True );
-  Stg_Component_Destroy( vec, NULL, True );
-  Stg_Component_Destroy( mat, NULL, True );
-  _Stg_Component_Delete( feVar );
-  _Stg_Component_Delete( vec );
-  /*_Stg_Component_Delete( mat );*/
-  Stg_Class_Delete( ep_reg );
-}
-
-void StiffnessMatrixSuite( pcu_suite_t* suite ) {
-   pcu_suite_setData( suite, StiffnessMatrixSuiteData );
-   pcu_suite_setFixtures( suite, StiffnessMatrixSuite_Setup, StiffnessMatrixSuite_Teardown );
-   pcu_suite_addTest( suite, StiffnessMatrixSuite_TestStiffnessMatrix );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/SystemSetup/tests/StiffnessMatrixSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/SystemSetup/tests/StiffnessMatrixSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,158 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+
+typedef struct {
+} StiffnessMatrixSuiteData;
+
+void StiffnessMatrixSuite_Setup( StiffnessMatrixSuiteData* data ) { 
+	Journal_Enable_AllTypedStream( False );
+}
+
+void StiffnessMatrixSuite_Teardown( StiffnessMatrixSuiteData* data ) {
+	Journal_Enable_AllTypedStream( True );
+}
+
+FeVariable* buildFeVar() {
+   CartesianGenerator*				gen;
+   FeMesh*								feMesh;
+   DofLayout*							dofs;
+   FeEquationNumber*					eqNum;
+   Variable_Register*				varReg;
+   int									maxDecomp[3] = {0, 1, 1};
+   int									sizes[3];
+   double								minCrd[3];
+   double								maxCrd[3];
+   char									xml_input[PCU_PATH_MAX];
+   static int							arraySize;
+   static double*						arrayPtrs[2];
+   int									nRanks;
+   Variable*							var;
+   VariableCondition*				bcs;
+   ConditionFunction_Register*	cfReg;
+   Dictionary*							dict;
+   XML_IO_Handler*					ioHandler;
+   FieldVariable_Register*			fieldReg;
+   FeVariable*							feVar;
+   int									n_i;
+
+   MPI_Comm_size( MPI_COMM_WORLD, &nRanks );
+   sizes[0] = nRanks * 2;
+   sizes[1] = sizes[2] = 2;
+   minCrd[0] = minCrd[1] = minCrd[2] = 0.0;
+   maxCrd[0] = maxCrd[1] = maxCrd[2] = (double)nRanks;
+
+   gen = CartesianGenerator_New( "", NULL );
+   CartesianGenerator_SetDimSize( gen, 2 );
+   CartesianGenerator_SetTopologyParams( gen, (unsigned*)sizes, 0, NULL, (unsigned*)maxDecomp );
+   CartesianGenerator_SetGeometryParams( gen, minCrd, maxCrd );
+   CartesianGenerator_SetShadowDepth( gen, 0 );
+
+   feMesh = FeMesh_New( "", NULL );
+   Mesh_SetGenerator( feMesh, gen );
+   FeMesh_SetElementFamily( feMesh, "linear" );
+   Stg_Component_Build( feMesh, NULL, False );
+
+   varReg = Variable_Register_New();
+   cfReg = ConditionFunction_Register_New();
+
+   arraySize = Mesh_GetDomainSize( feMesh, MT_VERTEX );
+   arrayPtrs[0] = Memory_Alloc_Array_Unnamed( double, arraySize * 2 );
+   var = Variable_NewVector( "velocity", NULL, Variable_DataType_Double, 2, (unsigned*)&arraySize, NULL, 
+		(void**)arrayPtrs, varReg, "vx", "vy" );
+   Variable_Register_BuildAll( varReg );
+
+   dofs = DofLayout_New( "", NULL, varReg, 0, feMesh );
+   dofs->nBaseVariables = 2;
+   dofs->baseVariables = Memory_Alloc_Array_Unnamed( Variable*, 2 );
+   dofs->baseVariables[0] = var->components[0];
+   dofs->baseVariables[1] = var->components[1];
+   Stg_Component_Build( dofs, NULL, False );
+   Stg_Component_Initialise( dofs, NULL, False );
+
+   ioHandler = XML_IO_Handler_New();
+   dict = Dictionary_New();
+   pcu_filename_input( "velWallVC.xml", xml_input );
+   IO_Handler_ReadAllFromFile( ioHandler, xml_input, dict );
+   bcs = (VariableCondition*)WallVC_New( "", NULL, "wallVC", varReg, cfReg, dict, feMesh );
+   Stg_Component_Build( bcs, NULL, False );
+   Stg_Component_Initialise( bcs, NULL, False );
+
+   eqNum = FeEquationNumber_New( "", NULL, feMesh, dofs, bcs, NULL );
+   Stg_Component_Build( eqNum, NULL, False );
+   Stg_Component_Initialise( eqNum, NULL, False );
+
+   fieldReg = FieldVariable_Register_New();
+   feVar = FeVariable_New( "velocity", NULL, feMesh, NULL, dofs, bcs, NULL, NULL, 2, True, 
+		False, False, fieldReg );
+
+   for( n_i = 0; n_i < Mesh_GetLocalSize( feMesh, (MeshTopology_Dim)0 ); n_i++ ) {
+      /*const double pi=acos(-1.0);*/
+      double* pos = Mesh_GetVertex( feMesh, n_i );
+
+      /* assign the position vector as the nodes vector */
+      Variable_SetValue( var, n_i, pos );
+   }
+
+   /* Build and initialise system */
+   Stg_Component_Build( bcs, 0, False );
+   Stg_Component_Build( feVar, 0, False );
+   Stg_Component_Initialise( feVar, 0, False );
+
+   return feVar;
+}
+
+
+void StiffnessMatrixSuite_TestStiffnessMatrix( StiffnessMatrixSuiteData* data ) {
+  FeVariable*				feVar;
+  FeMesh*					mesh;
+  EntryPoint_Register*	ep_reg;
+  StiffnessMatrix*		mat;
+  ForceVector*				vec;
+  MPI_Comm					comm;
+
+  pcu_docstring( "This test just creates a Stiffness matrix data structure, builds, itialises, refreshes and then destroys it.\n" );
+
+  /* we need an EP register here for the construction of the ForceVector and StiffnessMatrix */
+  ep_reg = EntryPoint_Register_New();
+
+  /* here we build a feVar with the position vector stored on the nodes */
+  feVar = buildFeVar();
+  mesh = feVar->feMesh;
+  FeVariable_SyncShadowValues( feVar );
+
+  /* create SiffnessMatrix, it requires a ForceVector */
+  comm = Comm_GetMPIComm( Mesh_GetCommTopology( mesh, MT_VERTEX ) );
+  vec = ForceVector_New( "testVector", NULL, feVar, 2, ep_reg, comm );
+  mat = StiffnessMatrix_New( "testMatrix", feVar, feVar, vec, NULL, 2, False, False, ep_reg, comm);
+
+  /* build & initialise the mat, this should build and initialise the vec */
+  Stg_Component_Build( mat, NULL, False );
+  Stg_Component_Initialise( mat, NULL, False );
+
+  StiffnessMatrix_RefreshMatrix( mat );
+
+  pcu_check_true( mat->matrix != NULL );
+
+  Stg_Component_Destroy( feVar, NULL, True );
+  Stg_Component_Destroy( vec, NULL, True );
+  Stg_Component_Destroy( mat, NULL, True );
+  _Stg_Component_Delete( feVar );
+  _Stg_Component_Delete( vec );
+  /*_Stg_Component_Delete( mat );*/
+  Stg_Class_Delete( ep_reg );
+}
+
+void StiffnessMatrixSuite( pcu_suite_t* suite ) {
+   pcu_suite_setData( suite, StiffnessMatrixSuiteData );
+   pcu_suite_setFixtures( suite, StiffnessMatrixSuite_Setup, StiffnessMatrixSuite_Teardown );
+   pcu_suite_addTest( suite, StiffnessMatrixSuite_TestStiffnessMatrix );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/src/Finalise.c
--- a/SLE/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "StgFEM/SLE/ProvidedSystems/ProvidedSystems.h"
-#include "Finalise.h"
-
-#include <stdio.h>
-
-Bool StgFEM_SLE_Finalise( void ) {
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	
-	//StgFEM_SLE_LinearAlgebra_Finalise();
-	StgFEM_SLE_SystemSetup_Finalise();
-	StgFEM_SLE_ProvidedSystems_Finalise();
-
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,62 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "StgFEM/SLE/ProvidedSystems/ProvidedSystems.h"
+#include "Finalise.h"
+
+#include <stdio.h>
+
+Bool StgFEM_SLE_Finalise( void ) {
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	
+	//StgFEM_SLE_LinearAlgebra_Finalise();
+	StgFEM_SLE_SystemSetup_Finalise();
+	StgFEM_SLE_ProvidedSystems_Finalise();
+
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/src/Init.c
--- a/SLE/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
-#include "StgFEM/SLE/ProvidedSystems/ProvidedSystems.h"
-
-#include "types.h"
-#include "Init.h"
-
-#include <stdio.h>
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_SLE_Init( int* argc, char** argv[] ) {
-	int tmp;
-	
-	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-	tmp = Stream_GetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context" )  );
-	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), 0 );
-	Journal_Printf( /* DO NOT CHANGE OR REMOVE */
-		Journal_Register( InfoStream_Type, (Name)"Context"  ), 
-		"StGermain SLE Library revision %s. Copyright (C) 2003-2005 VPAC.\n", VERSION );
-	Stream_Flush( Journal_Register( InfoStream_Type, (Name)"Context" )  );
-	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), tmp );
-	
-	//StgFEM_SLE_LinearAlgebra_Init( argc, argv );
-	StgFEM_SLE_SystemSetup_Init( argc, argv );
-	StgFEM_SLE_ProvidedSystems_Init( argc, argv );
-
-	return True;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SLE/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SLE/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,75 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SystemSetup/SystemSetup.h"
+#include "StgFEM/SLE/ProvidedSystems/ProvidedSystems.h"
+
+#include "types.h"
+#include "Init.h"
+
+#include <stdio.h>
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_SLE_Init( int* argc, char** argv[] ) {
+	int tmp;
+	
+	Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+	tmp = Stream_GetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context" )  );
+	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), 0 );
+	Journal_Printf( /* DO NOT CHANGE OR REMOVE */
+		Journal_Register( InfoStream_Type, (Name)"Context"  ), 
+		"StGermain SLE Library revision %s. Copyright (C) 2003-2005 VPAC.\n", VERSION );
+	Stream_Flush( Journal_Register( InfoStream_Type, (Name)"Context" )  );
+	Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), tmp );
+	
+	//StgFEM_SLE_LinearAlgebra_Init( argc, argv );
+	StgFEM_SLE_SystemSetup_Init( argc, argv );
+	StgFEM_SLE_ProvidedSystems_Init( argc, argv );
+
+	return True;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/AdvDiffSteadyState1D/AdvDiffSteadyState1D.c
--- a/SysTest/AnalyticPlugins/AdvDiffSteadyState1D/AdvDiffSteadyState1D.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: AdvDiffSteadyState1D.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-/* This analytic solutions is just the advection of a diffusing temperature for one time step.
- *  The advection is in the direction of one of the i,j,k axis 
- *  */
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include <string.h>
-
-const Type AdvDiffSteadyState1D_Type = "AdvDiffSteadyState1D";
-
-typedef struct { 
-	__FieldTest
-	AdvDiffResidualForceTerm* residual;
-	/* Velocity in this analyticSolution is constant */
-	double                    velocity;
-	Axis                      velocityDirection;
-	double                    A;
-	double                    B;
-	double                    c;
-	FeVariable*		  temperatureField;
-} AdvDiffSteadyState1D;
-
-void AdvDiffSteadyState1D_TemperatureFunction( void* analyticSolution, double* coord, double* temperature ) {
-	AdvDiffSteadyState1D* self = (AdvDiffSteadyState1D*)analyticSolution;
-	double                exponent;
-	double                kappa = self->residual->defaultDiffusivity;
-
-	exponent = self->velocity / kappa * ( coord[ self->velocityDirection ] - self->c );
-	*temperature = self->A * exp( exponent ) + self->B;
-}
-
-void AdvDiffSteadyState1D_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* temperature ){
-	DomainContext*	context    = (DomainContext*)_context;
-	AdvDiffSteadyState1D*   self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)AdvDiffSteadyState1D_Type, AdvDiffSteadyState1D, True, 0 /* dummy */ );
-	FeVariable*             feVariable = NULL;
-	FeMesh*     mesh       = NULL;
-	double*                 coord;
-	
-	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	mesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( mesh, node_lI );
-
-	AdvDiffSteadyState1D_TemperatureFunction( self, coord, (double*)temperature );
-}
-
-
-void _AdvDiffSteadyState1D_Build( void* analyticSolution, void* data ) {
-	AdvDiffSteadyState1D* self = (AdvDiffSteadyState1D*)analyticSolution;
-	FeVariable*           velocityField = Stg_CheckType( self->residual->velocityField, FeVariable );
-	CompositeVC*          velocityICs   = Stg_CheckType( velocityField->ics, CompositeVC );
-	Stream*               errorStream   = Journal_MyStream( Error_Type, self );
-	AllNodesVC*           allNodesVC;
-	AllNodesVC_Entry*     vcEntry;
-
-	_FieldTest_Build( self, data );
-
-	/* here we assign the memory and the func ptr for analytic sols */
-	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 1 );
-	/* this order MUST be consistent with the xml file definition */
-	self->_analyticSolutionList[0] = AdvDiffSteadyState1D_TemperatureFunction;
-
-	/* Get AllNodes Variable Condition */
-	Stg_Component_Build( velocityICs, data, False );
-	Journal_Firewall( velocityICs->itemCount == 1, errorStream, 
-			"Velocity Field needs to have one and only one Boundary Condition.\n"
-			"Currently it has %d types of VariableConditions.\n", velocityICs->itemCount );
-	allNodesVC    = Stg_CheckType( velocityICs->itemTbl[ 0 ], AllNodesVC );
-
-	/* Get Variable Condition entry */
-	Journal_Firewall( allNodesVC->_entryCount == 1, errorStream, 
-			"Velocity Field has more than one Boundary Condition.\n"
-			"Currently it has %d VariableCondition entries.\n", allNodesVC->_entryCount );
-	vcEntry       = &allNodesVC->_entryTbl[0];
-
-	/* Get Velocity Direction from Variable Condition */
-	if ( strcmp( vcEntry->varName, "vx" ) == 0 ) {
-		self->velocityDirection = I_AXIS;
-	}
-	else if ( strcmp( vcEntry->varName, "vy" ) == 0 ) {
-		self->velocityDirection = J_AXIS;
-	}
-	else if ( strcmp( vcEntry->varName, "vz" ) == 0 ) {
-		self->velocityDirection = K_AXIS;
-	}
-	else {
-		Journal_Firewall( False, errorStream, "Cannot recognise Boundary Condition: %s.\n", vcEntry->varName );
-	}
-}
-
-void _AdvDiffSteadyState1D_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	AdvDiffSteadyState1D*  self = (AdvDiffSteadyState1D*)analyticSolution;
-	ConditionFunction*     condFunc;
-
-	_FieldTest_AssignFromXML( self, cf, data );
-
-	self->residual = Stg_ComponentFactory_ConstructByName( cf, (Name)"defaultResidualForceTerm", AdvDiffResidualForceTerm, True, data  );
-
-	self->velocity = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"velocity", 1.0  );
-	self->A        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"A", 1.0  );
-	self->B        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"B", 0.0  );
-	self->c        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"c", 0.0  );
-	
-	condFunc = ConditionFunction_New( AdvDiffSteadyState1D_TemperatureBC, (Name)"AnalyticSolutionFunction"  );
-	ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-}
-
-void* _AdvDiffSteadyState1D_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(AdvDiffSteadyState1D);
-	Type                                                      type = AdvDiffSteadyState1D_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _AdvDiffSteadyState1D_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _AdvDiffSteadyState1D_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _AdvDiffSteadyState1D_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_AdvDiffSteadyState1D_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, AdvDiffSteadyState1D_Type, (Name)"0", _AdvDiffSteadyState1D_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/AdvDiffSteadyState1D/AdvDiffSteadyState1D.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SysTest/AnalyticPlugins/AdvDiffSteadyState1D/AdvDiffSteadyState1D.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,177 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: AdvDiffSteadyState1D.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/* This analytic solutions is just the advection of a diffusing temperature for one time step.
+ *  The advection is in the direction of one of the i,j,k axis 
+ *  */
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include <string.h>
+
+const Type AdvDiffSteadyState1D_Type = "AdvDiffSteadyState1D";
+
+typedef struct { 
+	__FieldTest
+	AdvDiffResidualForceTerm* residual;
+	/* Velocity in this analyticSolution is constant */
+	double                    velocity;
+	Axis                      velocityDirection;
+	double                    A;
+	double                    B;
+	double                    c;
+	FeVariable*		  temperatureField;
+} AdvDiffSteadyState1D;
+
+void AdvDiffSteadyState1D_TemperatureFunction( void* analyticSolution, double* coord, double* temperature ) {
+	AdvDiffSteadyState1D* self = (AdvDiffSteadyState1D*)analyticSolution;
+	double                exponent;
+	double                kappa = self->residual->defaultDiffusivity;
+
+	exponent = self->velocity / kappa * ( coord[ self->velocityDirection ] - self->c );
+	*temperature = self->A * exp( exponent ) + self->B;
+}
+
+void AdvDiffSteadyState1D_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* temperature ){
+	DomainContext*	context    = (DomainContext*)_context;
+	AdvDiffSteadyState1D*   self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)AdvDiffSteadyState1D_Type, AdvDiffSteadyState1D, True, 0 /* dummy */ );
+	FeVariable*             feVariable = NULL;
+	FeMesh*     mesh       = NULL;
+	double*                 coord;
+	
+	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	mesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( mesh, node_lI );
+
+	AdvDiffSteadyState1D_TemperatureFunction( self, coord, (double*)temperature );
+}
+
+
+void _AdvDiffSteadyState1D_Build( void* analyticSolution, void* data ) {
+	AdvDiffSteadyState1D* self = (AdvDiffSteadyState1D*)analyticSolution;
+	FeVariable*           velocityField = Stg_CheckType( self->residual->velocityField, FeVariable );
+	CompositeVC*          velocityICs   = Stg_CheckType( velocityField->ics, CompositeVC );
+	Stream*               errorStream   = Journal_MyStream( Error_Type, self );
+	AllNodesVC*           allNodesVC;
+	AllNodesVC_Entry*     vcEntry;
+
+	_FieldTest_Build( self, data );
+
+	/* here we assign the memory and the func ptr for analytic sols */
+	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 1 );
+	/* this order MUST be consistent with the xml file definition */
+	self->_analyticSolutionList[0] = AdvDiffSteadyState1D_TemperatureFunction;
+
+	/* Get AllNodes Variable Condition */
+	Stg_Component_Build( velocityICs, data, False );
+	Journal_Firewall( velocityICs->itemCount == 1, errorStream, 
+			"Velocity Field needs to have one and only one Boundary Condition.\n"
+			"Currently it has %d types of VariableConditions.\n", velocityICs->itemCount );
+	allNodesVC    = Stg_CheckType( velocityICs->itemTbl[ 0 ], AllNodesVC );
+
+	/* Get Variable Condition entry */
+	Journal_Firewall( allNodesVC->_entryCount == 1, errorStream, 
+			"Velocity Field has more than one Boundary Condition.\n"
+			"Currently it has %d VariableCondition entries.\n", allNodesVC->_entryCount );
+	vcEntry       = &allNodesVC->_entryTbl[0];
+
+	/* Get Velocity Direction from Variable Condition */
+	if ( strcmp( vcEntry->varName, "vx" ) == 0 ) {
+		self->velocityDirection = I_AXIS;
+	}
+	else if ( strcmp( vcEntry->varName, "vy" ) == 0 ) {
+		self->velocityDirection = J_AXIS;
+	}
+	else if ( strcmp( vcEntry->varName, "vz" ) == 0 ) {
+		self->velocityDirection = K_AXIS;
+	}
+	else {
+		Journal_Firewall( False, errorStream, "Cannot recognise Boundary Condition: %s.\n", vcEntry->varName );
+	}
+}
+
+void _AdvDiffSteadyState1D_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	AdvDiffSteadyState1D*  self = (AdvDiffSteadyState1D*)analyticSolution;
+	ConditionFunction*     condFunc;
+
+	_FieldTest_AssignFromXML( self, cf, data );
+
+	self->residual = Stg_ComponentFactory_ConstructByName( cf, (Name)"defaultResidualForceTerm", AdvDiffResidualForceTerm, True, data  );
+
+	self->velocity = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"velocity", 1.0  );
+	self->A        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"A", 1.0  );
+	self->B        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"B", 0.0  );
+	self->c        = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"c", 0.0  );
+	
+	condFunc = ConditionFunction_New( AdvDiffSteadyState1D_TemperatureBC, (Name)"AnalyticSolutionFunction"  );
+	ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+}
+
+void* _AdvDiffSteadyState1D_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(AdvDiffSteadyState1D);
+	Type                                                      type = AdvDiffSteadyState1D_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _AdvDiffSteadyState1D_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _AdvDiffSteadyState1D_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _AdvDiffSteadyState1D_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_AdvDiffSteadyState1D_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, AdvDiffSteadyState1D_Type, (Name)"0", _AdvDiffSteadyState1D_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/CosineHillRotate/CosineHillRotate.c
--- a/SysTest/AnalyticPlugins/CosineHillRotate/CosineHillRotate.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: CosineHillRotate.c 968 2007-10-23 07:53:39Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-const Type CosineHillRotate_Type = "CosineHillRotate";
-
-typedef struct { 
-	__FieldTest
-	FeVariable* temperatureField;
-	double      hillHeight;
-	double      hillDiameter;
-	Coord       rotationCentre;
-} CosineHillRotate;
-
-void CosineHillRotate_TemperatureFunction( void* analyticSolution, double* coord, double* temperature ) {
-	CosineHillRotate *self = (CosineHillRotate*)analyticSolution;
-	double distanceFromCentre = StGermain_DistanceBetweenPoints( self->rotationCentre, coord, 2 );
-	
-	if (distanceFromCentre < self->hillDiameter ) 
-		*temperature = self->hillHeight * (0.5 + 0.5 * cos( 2.0 * M_PI/self->hillDiameter * distanceFromCentre + M_PI ) );
-	else
-		*temperature = 0.0;
-}
-
-void CosineHillRotate_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context    = (DomainContext*)_context;
-	CosineHillRotate*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)CosineHillRotate_Type, CosineHillRotate, True, 0 );
-	FeVariable*             feVariable = NULL;
-	FeMesh*			mesh       = NULL;
-	double*                 result     = (double*) _result;
-	double*                 coord;
-	
-	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	mesh       = feVariable->feMesh;
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	CosineHillRotate_TemperatureFunction( self, coord, result );
-}
-
-void _CosineHillRotate_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	CosineHillRotate* self = (CosineHillRotate*)analyticSolution;
-	ConditionFunction*     condFunc;
-
-	_FieldTest_AssignFromXML( self, cf, data );
-
-	/* Read values from dictionary */
-	self->hillHeight       = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"CosineHillHeight"  , 1.0  );
-	self->hillDiameter     = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"CosineHillDiameter", 1.0  );
-	self->rotationCentre[ I_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreX" , 0.0  );
-	self->rotationCentre[ J_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreY" , 0.0  );
-	self->rotationCentre[ K_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ" , 0.0  );
-
-	/* Create Condition Functions */
-	condFunc = ConditionFunction_New( CosineHillRotate_TemperatureBC, (Name)"Temperature_CosineHill"  );
-	ConditionFunction_Register_Add( condFunc_Register, condFunc );
-}
-
-void _CosineHillRotate_Build( void* analyticSolution, void* data ) {
-	CosineHillRotate* self = (CosineHillRotate*)analyticSolution;	
-
-	_FieldTest_Build( self, data );
-
-	/* here we assign the memory and the func ptr for analytic sols */
-	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 1 );
-	/* this order MUST be consistent with the xml file definition */
-	self->_analyticSolutionList[0] = CosineHillRotate_TemperatureFunction;
-}
-
-void* _CosineHillRotate_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(CosineHillRotate);
-	Type                                                      type = CosineHillRotate_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _CosineHillRotate_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _CosineHillRotate_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _CosineHillRotate_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_CosineHillRotate_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, CosineHillRotate_Type, (Name)"0", _CosineHillRotate_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/CosineHillRotate/CosineHillRotate.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SysTest/AnalyticPlugins/CosineHillRotate/CosineHillRotate.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,137 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: CosineHillRotate.c 968 2007-10-23 07:53:39Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+const Type CosineHillRotate_Type = "CosineHillRotate";
+
+typedef struct { 
+	__FieldTest
+	FeVariable* temperatureField;
+	double      hillHeight;
+	double      hillDiameter;
+	Coord       rotationCentre;
+} CosineHillRotate;
+
+void CosineHillRotate_TemperatureFunction( void* analyticSolution, double* coord, double* temperature ) {
+	CosineHillRotate *self = (CosineHillRotate*)analyticSolution;
+	double distanceFromCentre = StGermain_DistanceBetweenPoints( self->rotationCentre, coord, 2 );
+	
+	if (distanceFromCentre < self->hillDiameter ) 
+		*temperature = self->hillHeight * (0.5 + 0.5 * cos( 2.0 * M_PI/self->hillDiameter * distanceFromCentre + M_PI ) );
+	else
+		*temperature = 0.0;
+}
+
+void CosineHillRotate_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context    = (DomainContext*)_context;
+	CosineHillRotate*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)CosineHillRotate_Type, CosineHillRotate, True, 0 );
+	FeVariable*             feVariable = NULL;
+	FeMesh*			mesh       = NULL;
+	double*                 result     = (double*) _result;
+	double*                 coord;
+	
+	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	mesh       = feVariable->feMesh;
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	CosineHillRotate_TemperatureFunction( self, coord, result );
+}
+
+void _CosineHillRotate_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	CosineHillRotate* self = (CosineHillRotate*)analyticSolution;
+	ConditionFunction*     condFunc;
+
+	_FieldTest_AssignFromXML( self, cf, data );
+
+	/* Read values from dictionary */
+	self->hillHeight       = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"CosineHillHeight"  , 1.0  );
+	self->hillDiameter     = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"CosineHillDiameter", 1.0  );
+	self->rotationCentre[ I_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreX" , 0.0  );
+	self->rotationCentre[ J_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreY" , 0.0  );
+	self->rotationCentre[ K_AXIS ] = Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ" , 0.0  );
+
+	/* Create Condition Functions */
+	condFunc = ConditionFunction_New( CosineHillRotate_TemperatureBC, (Name)"Temperature_CosineHill"  );
+	ConditionFunction_Register_Add( condFunc_Register, condFunc );
+}
+
+void _CosineHillRotate_Build( void* analyticSolution, void* data ) {
+	CosineHillRotate* self = (CosineHillRotate*)analyticSolution;	
+
+	_FieldTest_Build( self, data );
+
+	/* here we assign the memory and the func ptr for analytic sols */
+	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 1 );
+	/* this order MUST be consistent with the xml file definition */
+	self->_analyticSolutionList[0] = CosineHillRotate_TemperatureFunction;
+}
+
+void* _CosineHillRotate_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(CosineHillRotate);
+	Type                                                      type = CosineHillRotate_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _CosineHillRotate_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _CosineHillRotate_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _CosineHillRotate_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_CosineHillRotate_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, CosineHillRotate_Type, (Name)"0", _CosineHillRotate_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/HomogeneousNaturalBCs/HomogeneousNaturalBCs.c
--- a/SysTest/AnalyticPlugins/HomogeneousNaturalBCs/HomogeneousNaturalBCs.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: HomogeneousNaturalBCs.c 967 2007-10-23 05:27:09Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-const Type HomogeneousNaturalBCs_Type = "HomogeneousNaturalBCs";
-
-typedef struct { 
-	__FieldTest
-	double angle;
-	FeVariable* temperatureField;
-} HomogeneousNaturalBCs;
-
-
-void HomogeneousNaturalBCs_Velocity_SkewToMesh( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	HomogeneousNaturalBCs*  self    = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousNaturalBCs_Type, HomogeneousNaturalBCs, True, 0 );
-	double*                 result  = (double*) _result;
-	
-	result[ I_AXIS ] =  cos( self->angle );
-	result[ J_AXIS ] =  sin( self->angle  );
-}
-
-
-void HomogeneousNaturalBCs_TemperatureFunction( void* analyticSolution, double* coord, double* temperature ) {
-	HomogeneousNaturalBCs *self = (HomogeneousNaturalBCs*)analyticSolution;
-
-	if ( coord[ J_AXIS ] < tan( self->angle ) * coord[ I_AXIS ] + 0.25 )
-		*temperature = 1.0;
-	else 
-		*temperature = 0.0;
-}
-	
-void HomogeneousNaturalBCs_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context    = (DomainContext*)_context;
-	HomogeneousNaturalBCs*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousNaturalBCs_Type, HomogeneousNaturalBCs, True, 0 );
-	FeVariable*             feVariable = NULL;
-	FeMesh*			mesh       = NULL;
-	double*                 result     = (double*) _result;
-	double*                 coord;
-	
-	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	mesh       = feVariable->feMesh;
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	HomogeneousNaturalBCs_TemperatureFunction( self, coord, result );
-}
-
-void _HomogeneousNaturalBCs_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	HomogeneousNaturalBCs* self = (HomogeneousNaturalBCs*)analyticSolution;
-	ConditionFunction*     condFunc;
-
-	_FieldTest_AssignFromXML( self, cf, data );
-
-	self->angle = StGermain_DegreeToRadian (Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"VelocitySkewAngle", 45.0 )  );
-
-	/* Create Condition Functions */
-/*
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
-*/
-	condFunc = ConditionFunction_New( HomogeneousNaturalBCs_Velocity_SkewToMesh, (Name)"Velocity_SkewToMesh"  );
-	ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	condFunc = ConditionFunction_New( HomogeneousNaturalBCs_TemperatureBC, (Name)"Temperature_StepFunction"  );
-	ConditionFunction_Register_Add( condFunc_Register, condFunc );
-}
-
-void _HomogeneousNaturalBCs_Build( void* analyticSolution, void* data ) {
-	HomogeneousNaturalBCs* self = (HomogeneousNaturalBCs*)analyticSolution;	
-
-	_FieldTest_Build( self, data );
-
-	/* here we assign the memory and the func ptr for analytic sols */
-	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 1 );
-	/* this order MUST be consistent with the xml file definition */
-	self->_analyticSolutionList[0] = HomogeneousNaturalBCs_TemperatureFunction;
-}
-
-void* _HomogeneousNaturalBCs_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(HomogeneousNaturalBCs);
-	Type                                                      type = HomogeneousNaturalBCs_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _HomogeneousNaturalBCs_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _HomogeneousNaturalBCs_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _HomogeneousNaturalBCs_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_HomogeneousNaturalBCs_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, HomogeneousNaturalBCs_Type, (Name)"0", _HomogeneousNaturalBCs_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/HomogeneousNaturalBCs/HomogeneousNaturalBCs.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SysTest/AnalyticPlugins/HomogeneousNaturalBCs/HomogeneousNaturalBCs.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,145 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: HomogeneousNaturalBCs.c 967 2007-10-23 05:27:09Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+const Type HomogeneousNaturalBCs_Type = "HomogeneousNaturalBCs";
+
+typedef struct { 
+	__FieldTest
+	double angle;
+	FeVariable* temperatureField;
+} HomogeneousNaturalBCs;
+
+
+void HomogeneousNaturalBCs_Velocity_SkewToMesh( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	HomogeneousNaturalBCs*  self    = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousNaturalBCs_Type, HomogeneousNaturalBCs, True, 0 );
+	double*                 result  = (double*) _result;
+	
+	result[ I_AXIS ] =  cos( self->angle );
+	result[ J_AXIS ] =  sin( self->angle  );
+}
+
+
+void HomogeneousNaturalBCs_TemperatureFunction( void* analyticSolution, double* coord, double* temperature ) {
+	HomogeneousNaturalBCs *self = (HomogeneousNaturalBCs*)analyticSolution;
+
+	if ( coord[ J_AXIS ] < tan( self->angle ) * coord[ I_AXIS ] + 0.25 )
+		*temperature = 1.0;
+	else 
+		*temperature = 0.0;
+}
+	
+void HomogeneousNaturalBCs_TemperatureBC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context    = (DomainContext*)_context;
+	HomogeneousNaturalBCs*  self       = Stg_ComponentFactory_ConstructByName( context->CF, (Name)HomogeneousNaturalBCs_Type, HomogeneousNaturalBCs, True, 0 );
+	FeVariable*             feVariable = NULL;
+	FeMesh*			mesh       = NULL;
+	double*                 result     = (double*) _result;
+	double*                 coord;
+	
+	feVariable = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	mesh       = feVariable->feMesh;
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	HomogeneousNaturalBCs_TemperatureFunction( self, coord, result );
+}
+
+void _HomogeneousNaturalBCs_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	HomogeneousNaturalBCs* self = (HomogeneousNaturalBCs*)analyticSolution;
+	ConditionFunction*     condFunc;
+
+	_FieldTest_AssignFromXML( self, cf, data );
+
+	self->angle = StGermain_DegreeToRadian (Stg_ComponentFactory_GetRootDictDouble( cf, (Dictionary_Entry_Key)"VelocitySkewAngle", 45.0 )  );
+
+	/* Create Condition Functions */
+/*
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
+*/
+	condFunc = ConditionFunction_New( HomogeneousNaturalBCs_Velocity_SkewToMesh, (Name)"Velocity_SkewToMesh"  );
+	ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	condFunc = ConditionFunction_New( HomogeneousNaturalBCs_TemperatureBC, (Name)"Temperature_StepFunction"  );
+	ConditionFunction_Register_Add( condFunc_Register, condFunc );
+}
+
+void _HomogeneousNaturalBCs_Build( void* analyticSolution, void* data ) {
+	HomogeneousNaturalBCs* self = (HomogeneousNaturalBCs*)analyticSolution;	
+
+	_FieldTest_Build( self, data );
+
+	/* here we assign the memory and the func ptr for analytic sols */
+	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 1 );
+	/* this order MUST be consistent with the xml file definition */
+	self->_analyticSolutionList[0] = HomogeneousNaturalBCs_TemperatureFunction;
+}
+
+void* _HomogeneousNaturalBCs_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(HomogeneousNaturalBCs);
+	Type                                                      type = HomogeneousNaturalBCs_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _HomogeneousNaturalBCs_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _HomogeneousNaturalBCs_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _HomogeneousNaturalBCs_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_HomogeneousNaturalBCs_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, HomogeneousNaturalBCs_Type, (Name)"0", _HomogeneousNaturalBCs_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.c
--- a/SysTest/AnalyticPlugins/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LidDrivenIsoviscousAnalytic.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-/* This is taken from Mirko Velic's Analytic Stokes Flow solution */
-
-const Type LidDrivenIsoviscousAnalytic_Type = "LidDrivenIsoviscousAnalytic";
-
-typedef struct { 
-	__FieldTest 
-	unsigned int wavenumber;
-	double A, B, C, D;
-	FeVariable* velocityField;
-	FeVariable* pressureField;
-} LidDrivenIsoviscousAnalytic;
-
-
-void LidDrivenIsoviscousAnalytic_CalculateConstants( LidDrivenIsoviscousAnalytic *self ) {
-	double                  E;
-	double                  e_nPI;
-	double                  e_2nPI;
-	double                  e_4nPI;
-	double                  n;
-
-	n = (double) self->wavenumber;
-
-	e_nPI = exp( n * M_PI );
-	e_2nPI = e_nPI * e_nPI;
-	e_4nPI = e_2nPI * e_2nPI;
-
-	E = (4.0 * n * n * M_PI * M_PI + 2.0 ) * e_2nPI - e_4nPI - 1.0;
-
-	self->A = ( e_2nPI - 1.0 )* e_nPI / E;
-	self->B = - self->A;
-
-	self->C =   ( 2.0 * n * M_PI - e_2nPI + 1.0 ) * e_nPI / E;
-	self->D = - ( 2.0 * n * M_PI * e_2nPI - e_2nPI + 1.0 ) * e_nPI / E;
-}
-
-void LidDrivenIsoviscousAnalytic_VelocityFunction( void* analyticSolution, double* coord, double* velocity ) {
-	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)analyticSolution;
-	double x,y;
-	double n;
-	double A, B, C, D;
-
-	/* Get local copy of constants */
-	n = (double) self->wavenumber;
-	A = self->A;
-	B = self->B;
-	C = self->C;
-	D = self->D;
-
-	/* get copy of coords */
-	x = coord[I_AXIS];
-	y = coord[J_AXIS];
-	
-	velocity[ I_AXIS ] = sin( n * M_PI * x ) * 
-		( ( A * n * M_PI + C + C * n * M_PI * y) *exp( n * M_PI * y ) 
-		- ( B * n * M_PI - D + D * n * M_PI * y ) * exp( - n * M_PI * y ) );
-	velocity[ J_AXIS ] = - n * M_PI * cos( n * M_PI * x ) * 
-		( ( A + C * y ) * exp( n * M_PI * y ) 
-		+ ( B + D * y ) * exp( - n * M_PI * y ) );
-}
-
-
-void LidDrivenIsoviscousAnalytic_PressureFunction( void* analyticSolution, double* coord, double* pressure ) {
-	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)analyticSolution;
-	double x,y;
-	double n;
-	double A, B, C, D;
-
-	/* Get local copy of constants */
-	n = (double) self->wavenumber;
-	A = self->A;
-	B = self->B;
-	C = self->C;
-	D = self->D;
-
-	/* get copy of coords */
-	x = coord[I_AXIS];
-	y = coord[J_AXIS];
-	
-	*pressure = - 2.0 * n * M_PI * cos( n * M_PI * x ) * ( C * exp( n * M_PI * y ) + D * exp( - n * M_PI * y ) );
-}
-
-void _LidDrivenIsoviscousAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)analyticSolution;
-
-	_FieldTest_AssignFromXML( self, cf, data );
-
-	/* Set constants */
-	self->wavenumber = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"sinusoidalLidWavenumber", 1 );
-	LidDrivenIsoviscousAnalytic_CalculateConstants( self  );
-}
-
-void _LidDrivenIsoviscousAnalytic_Build( void* analyticSolution, void* data ) {
-	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)analyticSolution;
-
-	_FieldTest_Build( self, data );
-
-	/* here we assign the memory and the func ptr for analytic sols */
-	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 2 );
-	/* this order MUST be consistent with the xml file definition */
-	self->_analyticSolutionList[0] = LidDrivenIsoviscousAnalytic_VelocityFunction;
-	self->_analyticSolutionList[1] = LidDrivenIsoviscousAnalytic_PressureFunction;
-}
-
-void* _LidDrivenIsoviscousAnalytic_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(LidDrivenIsoviscousAnalytic);
-	Type                                                      type = LidDrivenIsoviscousAnalytic_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LidDrivenIsoviscousAnalytic_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _LidDrivenIsoviscousAnalytic_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _LidDrivenIsoviscousAnalytic_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_LidDrivenIsoviscousAnalytic_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, LidDrivenIsoviscousAnalytic_Type, (Name)"0", _LidDrivenIsoviscousAnalytic_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SysTest/AnalyticPlugins/LidDrivenIsoviscousAnalytic/LidDrivenIsoviscousAnalytic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,175 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LidDrivenIsoviscousAnalytic.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+/* This is taken from Mirko Velic's Analytic Stokes Flow solution */
+
+const Type LidDrivenIsoviscousAnalytic_Type = "LidDrivenIsoviscousAnalytic";
+
+typedef struct { 
+	__FieldTest 
+	unsigned int wavenumber;
+	double A, B, C, D;
+	FeVariable* velocityField;
+	FeVariable* pressureField;
+} LidDrivenIsoviscousAnalytic;
+
+
+void LidDrivenIsoviscousAnalytic_CalculateConstants( LidDrivenIsoviscousAnalytic *self ) {
+	double                  E;
+	double                  e_nPI;
+	double                  e_2nPI;
+	double                  e_4nPI;
+	double                  n;
+
+	n = (double) self->wavenumber;
+
+	e_nPI = exp( n * M_PI );
+	e_2nPI = e_nPI * e_nPI;
+	e_4nPI = e_2nPI * e_2nPI;
+
+	E = (4.0 * n * n * M_PI * M_PI + 2.0 ) * e_2nPI - e_4nPI - 1.0;
+
+	self->A = ( e_2nPI - 1.0 )* e_nPI / E;
+	self->B = - self->A;
+
+	self->C =   ( 2.0 * n * M_PI - e_2nPI + 1.0 ) * e_nPI / E;
+	self->D = - ( 2.0 * n * M_PI * e_2nPI - e_2nPI + 1.0 ) * e_nPI / E;
+}
+
+void LidDrivenIsoviscousAnalytic_VelocityFunction( void* analyticSolution, double* coord, double* velocity ) {
+	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)analyticSolution;
+	double x,y;
+	double n;
+	double A, B, C, D;
+
+	/* Get local copy of constants */
+	n = (double) self->wavenumber;
+	A = self->A;
+	B = self->B;
+	C = self->C;
+	D = self->D;
+
+	/* get copy of coords */
+	x = coord[I_AXIS];
+	y = coord[J_AXIS];
+	
+	velocity[ I_AXIS ] = sin( n * M_PI * x ) * 
+		( ( A * n * M_PI + C + C * n * M_PI * y) *exp( n * M_PI * y ) 
+		- ( B * n * M_PI - D + D * n * M_PI * y ) * exp( - n * M_PI * y ) );
+	velocity[ J_AXIS ] = - n * M_PI * cos( n * M_PI * x ) * 
+		( ( A + C * y ) * exp( n * M_PI * y ) 
+		+ ( B + D * y ) * exp( - n * M_PI * y ) );
+}
+
+
+void LidDrivenIsoviscousAnalytic_PressureFunction( void* analyticSolution, double* coord, double* pressure ) {
+	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)analyticSolution;
+	double x,y;
+	double n;
+	double A, B, C, D;
+
+	/* Get local copy of constants */
+	n = (double) self->wavenumber;
+	A = self->A;
+	B = self->B;
+	C = self->C;
+	D = self->D;
+
+	/* get copy of coords */
+	x = coord[I_AXIS];
+	y = coord[J_AXIS];
+	
+	*pressure = - 2.0 * n * M_PI * cos( n * M_PI * x ) * ( C * exp( n * M_PI * y ) + D * exp( - n * M_PI * y ) );
+}
+
+void _LidDrivenIsoviscousAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)analyticSolution;
+
+	_FieldTest_AssignFromXML( self, cf, data );
+
+	/* Set constants */
+	self->wavenumber = Stg_ComponentFactory_GetRootDictUnsignedInt( cf, (Dictionary_Entry_Key)"sinusoidalLidWavenumber", 1 );
+	LidDrivenIsoviscousAnalytic_CalculateConstants( self  );
+}
+
+void _LidDrivenIsoviscousAnalytic_Build( void* analyticSolution, void* data ) {
+	LidDrivenIsoviscousAnalytic *self = (LidDrivenIsoviscousAnalytic*)analyticSolution;
+
+	_FieldTest_Build( self, data );
+
+	/* here we assign the memory and the func ptr for analytic sols */
+	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 2 );
+	/* this order MUST be consistent with the xml file definition */
+	self->_analyticSolutionList[0] = LidDrivenIsoviscousAnalytic_VelocityFunction;
+	self->_analyticSolutionList[1] = LidDrivenIsoviscousAnalytic_PressureFunction;
+}
+
+void* _LidDrivenIsoviscousAnalytic_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(LidDrivenIsoviscousAnalytic);
+	Type                                                      type = LidDrivenIsoviscousAnalytic_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LidDrivenIsoviscousAnalytic_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _LidDrivenIsoviscousAnalytic_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _LidDrivenIsoviscousAnalytic_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_LidDrivenIsoviscousAnalytic_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, LidDrivenIsoviscousAnalytic_Type, (Name)"0", _LidDrivenIsoviscousAnalytic_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/LinearTemperatureField/LinearTemperatureField.c
--- a/SysTest/AnalyticPlugins/LinearTemperatureField/LinearTemperatureField.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,104 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LinearTemperatureField.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-/** Pretty simple.
- * One time step with the diffusion coefficiants K = 1
- * TempBCs Bottom BC = 1, top BC = 0, sides = 0
- */
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-const Type LinearTemperatureField_Type = "LinearTemperatureField";
-
-typedef struct { __FieldTest FeVariable* temperatureField; } LinearTemperatureField;
-
-void LinearTemperatureField_TemperatureFunction( void* analyticSolution, double* coord, double* value ) {
-	*value = 1.0 - coord[ J_AXIS ];
-}
-
-
-void _LinearTemperatureField_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	LinearTemperatureField *self = (LinearTemperatureField*)analyticSolution;
-
-	_FieldTest_AssignFromXML( self, cf, data );
-
-	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
-}
-
-void _LinearTemperatureField_Build( void* analyticSolution, void* data ) {
-	LinearTemperatureField *self = (LinearTemperatureField*)analyticSolution;
-
-	_FieldTest_Build( self, data );
-
-	/* here we assign the memory and the func ptr for analytic sols */
-	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 1 );
-	/* this order MUST be consistent with the xml file definition */
-	self->_analyticSolutionList[0] = LinearTemperatureField_TemperatureFunction;
-}
-
-void* _LinearTemperatureField_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(LinearTemperatureField);
-	Type                                                      type = LinearTemperatureField_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinearTemperatureField_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _LinearTemperatureField_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _LinearTemperatureField_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_LinearTemperatureField_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, LinearTemperatureField_Type, (Name)"0", _LinearTemperatureField_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/LinearTemperatureField/LinearTemperatureField.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SysTest/AnalyticPlugins/LinearTemperatureField/LinearTemperatureField.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,104 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LinearTemperatureField.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+/** Pretty simple.
+ * One time step with the diffusion coefficiants K = 1
+ * TempBCs Bottom BC = 1, top BC = 0, sides = 0
+ */
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+const Type LinearTemperatureField_Type = "LinearTemperatureField";
+
+typedef struct { __FieldTest FeVariable* temperatureField; } LinearTemperatureField;
+
+void LinearTemperatureField_TemperatureFunction( void* analyticSolution, double* coord, double* value ) {
+	*value = 1.0 - coord[ J_AXIS ];
+}
+
+
+void _LinearTemperatureField_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	LinearTemperatureField *self = (LinearTemperatureField*)analyticSolution;
+
+	_FieldTest_AssignFromXML( self, cf, data );
+
+	self->temperatureField = Stg_ComponentFactory_ConstructByName( cf, (Name)"TemperatureField", FeVariable, True, data  ); 
+}
+
+void _LinearTemperatureField_Build( void* analyticSolution, void* data ) {
+	LinearTemperatureField *self = (LinearTemperatureField*)analyticSolution;
+
+	_FieldTest_Build( self, data );
+
+	/* here we assign the memory and the func ptr for analytic sols */
+	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 1 );
+	/* this order MUST be consistent with the xml file definition */
+	self->_analyticSolutionList[0] = LinearTemperatureField_TemperatureFunction;
+}
+
+void* _LinearTemperatureField_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(LinearTemperatureField);
+	Type                                                      type = LinearTemperatureField_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinearTemperatureField_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _LinearTemperatureField_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _LinearTemperatureField_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FieldTest_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_LinearTemperatureField_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, LinearTemperatureField_Type, (Name)"0", _LinearTemperatureField_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/LinearVelocityAnalytic/LinearVelocityAnalytic.c
--- a/SysTest/AnalyticPlugins/LinearVelocityAnalytic/LinearVelocityAnalytic.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,379 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: LinearVelocityAnalytic.c 1111 2008-04-23 04:12:36Z RobertTurnbull $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include <string.h>
-
-const Type LinearVelocityAnalytic_Type = "LinearVelocityAnalytic";
-
-typedef struct { 
-	__FieldTest
-	FeVariable* velocityField;
-	double  nodeVelocity[8][3];
-	double  nodeCoords[8][3];
-	int    cornerNodeCount;
-} LinearVelocityAnalytic;
-
-Index Grid_ProjectIJK( Grid* grid, Index i, Index j, Index k ) {
-	IJK ijk = {0,0,0};
-	
-	ijk[0] = i;
-	ijk[1] = j;
-	ijk[2] = k;
-
-	return Grid_Project( grid, ijk );
-}
-Index Grid_ProjectIJK_MinMax( Grid* grid, Bool iIsMax, Bool jIsMax, Bool kIsMax ) {
-	IJK ijk = {0,0,0};
-	
-	if ( iIsMax )
-		ijk[0] = grid->sizes[0] - 1;
-	if ( jIsMax )
-		ijk[1] = grid->sizes[1] - 1;
-	if ( kIsMax )
-		ijk[2] = grid->sizes[2] - 1;
-
-	return Grid_Project( grid, ijk );
-}
-
-void LinearVelocityAnalytic_GetCornerNodeVelocities(void* analyticSolution) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	Grid*                   vertGrid;
-	Node_GlobalIndex        nodeMapper[8];
-	FeVariable*             velocityField = self->velocityField;
-	FeMesh*                 mesh = velocityField->feMesh;
-	Dimension_Index         dim = velocityField->dim;
-	Node_Index              globalNode_I;
-	Node_Index              ii;
-	
-	vertGrid = *(Grid**)ExtensionManager_Get( mesh->info, mesh, ExtensionManager_GetHandle( mesh->info, (Name)"vertexGrid" )  );
-
-	/* Find global indicies of nodes */
-	self->cornerNodeCount = 4;
-	nodeMapper[0] = Grid_ProjectIJK_MinMax( vertGrid, False, False, False );
-	nodeMapper[1] = Grid_ProjectIJK_MinMax( vertGrid, True, False, False );
-	nodeMapper[2] = Grid_ProjectIJK_MinMax( vertGrid, False, True, False );
-	nodeMapper[3] = Grid_ProjectIJK_MinMax( vertGrid, True, True, False );
-	if ( dim == 3 ) {
-		self->cornerNodeCount = 8;
-		nodeMapper[4] = Grid_ProjectIJK_MinMax( vertGrid, False, False, True );
-		nodeMapper[5] = Grid_ProjectIJK_MinMax( vertGrid, True, False, True );
-		nodeMapper[6] = Grid_ProjectIJK_MinMax( vertGrid, False, True, True );
-		nodeMapper[7] = Grid_ProjectIJK_MinMax( vertGrid, True, True, True );
-	}
-
-	/* Loop over corner nodes */
-	for ( ii = 0 ; ii < self->cornerNodeCount ; ii++ ) {
-		globalNode_I = nodeMapper[ ii ];
-		FeVariable_GetValueAtNodeGlobal( velocityField, globalNode_I, self->nodeVelocity[ii] );
-		FeVariable_GetCoordAtNodeGlobal( velocityField, globalNode_I, self->nodeCoords[ii] );
-	}
-}
-
-void GetLocalCoords( LinearVelocityAnalytic* self, double* coord, double* xi ) {
-	FeVariable*             velocityField = self->velocityField;
-	XYZ                     min;
-	XYZ                     max;
-	Dimension_Index         dim = velocityField->dim;
-	Dimension_Index         dim_I;
-
-	_FeVariable_GetMinAndMaxGlobalCoords( velocityField, min, max );
-	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
-		xi[ dim_I ] = 2.0 * (coord[ dim_I ] - min[ dim_I ])/(max[dim_I] - min[dim_I]) - 1;
-	}	
-}	
-
-/* Do a normal linear interpolation as if the box were a FEM element */
-void LinearVelocityAnalytic_VelocityFunction( void* analyticSolution, double* coord, double* velocity ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	FeVariable*             velocityField = self->velocityField;
-	FeMesh*                 mesh = velocityField->feMesh;
-	Dimension_Index         dim = velocityField->dim;
-	Dimension_Index         dim_I;
-	XYZ                     xi;
-	double                  Ni[8];
-	Node_Index              ii;
-	ElementType*            elementType;
-
-	/* Transform the coordinate into a master coordinate system */
-	GetLocalCoords( self, coord, xi );
-
-	/* Get Shape Functions */
-	elementType = FeMesh_GetElementType( mesh, 0 );
-	ElementType_EvaluateShapeFunctionsAt( elementType, xi, Ni );
-
-	/* Do interpolation */
-	/* Loop over corner nodes */
-	memset( velocity, 0, dim*sizeof(double) );
-	for ( ii = 0 ; ii < self->cornerNodeCount ; ii++ ) {
-		for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
-			velocity[ dim_I ] += Ni[ ii ] * self->nodeVelocity[ii][ dim_I ];
-		}
-	}
-}
-void LinearVelocityAnalytic_PressureFunction( void* analyticSolution, double* coord, double* pressure ) {
-	*pressure = 0.0;
-}
-
-void LinearVelocityAnalytic_VelocityGradientsFunction( void* analyticSolution, double* coord, double* velocityGradients ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	FeVariable*             velocityField = self->velocityField;
-	FeMesh*                 mesh = velocityField->feMesh;
-	ElementType*            elementType;
-	XYZ                     xi;
-	double                  jac[3][3];
-	double                  cof[3][3];	/* cofactors */
-	double                  detJac;
-	Node_Index              node_I;
-	double**                GNi; 
-	double**                GNx; 
-	double*                 nodeCoord;
-	double                  nodeValue;
-	Dimension_Index         dim = velocityField->dim;
-	Dimension_Index         i, j, dx, dxi;
-	Dimension_Index         dim_I;
-	
-	/* Transform the coordinate into a master coordinate system */
-	GetLocalCoords( self, coord, xi );
-
-	GNi = Memory_Alloc_2DArray( double, dim, self->cornerNodeCount, (Name)"GNi"  );
-	GNx = Memory_Alloc_2DArray( double, dim, self->cornerNodeCount, (Name)"GNx"  );
-
-	/* Get Shape Functions */
-	elementType = FeMesh_GetElementType( mesh, 0 );
-	elementType->_evaluateShapeFunctionLocalDerivsAt( elementType, xi, GNi );
-
-	/* build the jacobian matrix */
-	/*
-	jac = 	\sum_i d/d\xi( N_i ) x_i 		\sum_i d/d\xi( N_i ) y_i
-			\sum_i d/d\eta( N_i ) x_i 		\sum_i d/d\eta( N_i ) y_i
-	*/
-	if( dim == 2 ) {
-		jac[0][0] = jac[0][1] = jac[1][0] = jac[1][1] = 0.0;
-		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
-			nodeCoord = self->nodeCoords[ node_I ];
-			jac[0][0] = jac[0][0] + GNi[0][node_I] * nodeCoord[0];
-			jac[0][1] = jac[0][1] + GNi[0][node_I] * nodeCoord[1];
-			
-			jac[1][0] = jac[1][0] + GNi[1][node_I] * nodeCoord[0];
-			jac[1][1] = jac[1][1] + GNi[1][node_I] * nodeCoord[1];
-		}
-	}
-	
-	if( dim == 3 ) {
-		jac[0][0] = jac[0][1] = jac[0][2] = 0.0;
-		jac[1][0] = jac[1][1] = jac[1][2] = 0.0;
-		jac[2][0] = jac[2][1] = jac[2][2] = 0.0;
-		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
-			nodeCoord = self->nodeCoords[ node_I ];
-			jac[0][0] = jac[0][0] + GNi[0][node_I] * nodeCoord[0];
-			jac[0][1] = jac[0][1] + GNi[0][node_I] * nodeCoord[1];
-			jac[0][2] = jac[0][2] + GNi[0][node_I] * nodeCoord[2];
-			
-			jac[1][0] = jac[1][0] + GNi[1][node_I] * nodeCoord[0];
-			jac[1][1] = jac[1][1] + GNi[1][node_I] * nodeCoord[1];
-			jac[1][2] = jac[1][2] + GNi[1][node_I] * nodeCoord[2];
-			
-			jac[2][0] = jac[2][0] + GNi[2][node_I] * nodeCoord[0];
-			jac[2][1] = jac[2][1] + GNi[2][node_I] * nodeCoord[1];
-			jac[2][2] = jac[2][2] + GNi[2][node_I] * nodeCoord[2];
-		}
-	}
-	
-	/* get determinant of the jacobian matrix */
-	if( dim == 2 ) {
-		detJac = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0]; 
-	}		
-	if( dim == 3 ) {
-		detJac = jac[0][0]*( jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1] ) 
-				  - jac[0][1]*( jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0] ) 
-				  + jac[0][2]*( jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0] );
-	}
-	
-	/* invert the jacobian matrix A^-1 = adj(A)/det(A) */
-	if( dim == 2 ) {
-		double tmp = jac[0][0];
-		jac[0][0] = jac[1][1]/detJac;
-		jac[1][1] = tmp/detJac;
-		jac[0][1] = -jac[0][1]/detJac;
-		jac[1][0] = -jac[1][0]/detJac;		
-	}
-	if( dim == 3 ) {
-		/*
-		00 01 02
-		10 11 12
-		20 21 22		
-		*/		
-		cof[0][0] = jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1];
-		cof[1][0] = -(jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0]);
-		cof[2][0] = jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0];
-		
-		cof[0][1] = -(jac[0][1]*jac[2][2] - jac[0][2]*jac[2][1]);
-		cof[1][1] = jac[0][0]*jac[2][2] - jac[0][2]*jac[2][0];
-		cof[2][1] = -(jac[0][0]*jac[2][1] - jac[0][1]*jac[2][0]);
-		
-		cof[0][2] = jac[0][1]*jac[1][2] - jac[0][2]*jac[1][1];
-		cof[1][2] = -(jac[0][0]*jac[1][2] - jac[0][2]*jac[1][0]);
-		cof[2][2] = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0];
-		
-		for( i=0; i<dim; i++ ) {
-			for( j=0; j<dim; j++ ) {
-				jac[i][j] = cof[i][j]/detJac;
-			}
-		}
-		
-		
-	}
-	
-	/* get global derivs Ni_x, Ni_y and Ni_z if dim == 3 */
-	for( dx=0; dx<dim; dx++ ) {
-		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
-			double globalSF_DerivVal = 0.0;
-			for(dxi=0; dxi<dim; dxi++) {
-				globalSF_DerivVal = globalSF_DerivVal + GNi[dxi][node_I] * jac[dx][dxi];
-			}
-			
-			GNx[dx][node_I] = globalSF_DerivVal;
-		}
-	}
-	
-	/* Initialise velocity gradients */
-	memset( velocityGradients, 0, sizeof( double ) * dim * dim );
-	
-	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
-		/* Interpolate derivative from nodes */
-		for( node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
-			nodeValue    = self->nodeVelocity[ node_I ][ dim_I ];
-			
-			velocityGradients[dim_I*dim + 0] += GNx[0][node_I] * nodeValue;
-			velocityGradients[dim_I*dim + 1] += GNx[1][node_I] * nodeValue;
-			if( dim == 3 ) 
-				velocityGradients[dim_I*dim + 2] += GNx[2][node_I] * nodeValue;	
-		}
-	}
-	Memory_Free( GNi );
-	Memory_Free( GNx );
-}
-
-void LinearVelocityAnalytic_StrainRateFunction( void* analyticSolution, double* coord, double* strainRate ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	Dimension_Index         dim = self->velocityField->dim;
-	TensorArray             velocityGradients;
-
-	/* Get Velocity Gradients */
-	LinearVelocityAnalytic_VelocityGradientsFunction( self, coord, velocityGradients );
-	
-	/* Get Strain Rate */
-	TensorArray_GetSymmetricPart( velocityGradients, dim, strainRate );
-}
-
-void LinearVelocityAnalytic_StrainRateInvFunction( void* analyticSolution, double* coord, double* strainRateInv ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	Dimension_Index         dim = self->velocityField->dim;
-	SymmetricTensor         strainRate;
-
-	/* Get Strain Rate */
-	LinearVelocityAnalytic_StrainRateFunction( self, coord, strainRate );
-	
-	/* Get Invariant */
-	*strainRateInv = SymmetricTensor_2ndInvariant( strainRate, dim );
-}
-
-void _LinearVelocityAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-
-	_FieldTest_AssignFromXML( self, cf, data );
-
-	self->velocityField = Stg_ComponentFactory_ConstructByName( cf, (Name)"VelocityField", FeVariable, True, data  ); 
-}
-
-void _LinearVelocityAnalytic_Build( void* analyticSolution, void* data ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	
-	_FieldTest_Build( self, data );
-
-	/* here we assign the memory and the func ptr for analytic sols */
-	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 4 );
-	/* this order MUST be consistent with the xml file definition */
-	self->_analyticSolutionList[0] = LinearVelocityAnalytic_VelocityFunction;
-	self->_analyticSolutionList[1] = LinearVelocityAnalytic_PressureFunction;
-	self->_analyticSolutionList[2] = LinearVelocityAnalytic_StrainRateFunction;
-	self->_analyticSolutionList[3] = LinearVelocityAnalytic_StrainRateInvFunction;
-}
-
-void _LinearVelocityAnalytic_Initialise( void* analyticSolution, void* data ) {
-	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
-	
-	Stg_Component_Initialise( self->velocityField, data,  False );
-	LinearVelocityAnalytic_GetCornerNodeVelocities( self );
-
-	_FieldTest_Initialise( self, data );
-}
-
-void* _LinearVelocityAnalytic_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(LinearVelocityAnalytic);
-	Type                                                      type = LinearVelocityAnalytic_Type;
-	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
-	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
-	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinearVelocityAnalytic_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _LinearVelocityAnalytic_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _LinearVelocityAnalytic_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _LinearVelocityAnalytic_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_LinearVelocityAnalytic_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, LinearVelocityAnalytic_Type, (Name)"0", _LinearVelocityAnalytic_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 SysTest/AnalyticPlugins/LinearVelocityAnalytic/LinearVelocityAnalytic.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SysTest/AnalyticPlugins/LinearVelocityAnalytic/LinearVelocityAnalytic.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,379 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: LinearVelocityAnalytic.c 1111 2008-04-23 04:12:36Z RobertTurnbull $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include <string.h>
+
+const Type LinearVelocityAnalytic_Type = "LinearVelocityAnalytic";
+
+typedef struct { 
+	__FieldTest
+	FeVariable* velocityField;
+	double  nodeVelocity[8][3];
+	double  nodeCoords[8][3];
+	int    cornerNodeCount;
+} LinearVelocityAnalytic;
+
+Index Grid_ProjectIJK( Grid* grid, Index i, Index j, Index k ) {
+	IJK ijk = {0,0,0};
+	
+	ijk[0] = i;
+	ijk[1] = j;
+	ijk[2] = k;
+
+	return Grid_Project( grid, ijk );
+}
+Index Grid_ProjectIJK_MinMax( Grid* grid, Bool iIsMax, Bool jIsMax, Bool kIsMax ) {
+	IJK ijk = {0,0,0};
+	
+	if ( iIsMax )
+		ijk[0] = grid->sizes[0] - 1;
+	if ( jIsMax )
+		ijk[1] = grid->sizes[1] - 1;
+	if ( kIsMax )
+		ijk[2] = grid->sizes[2] - 1;
+
+	return Grid_Project( grid, ijk );
+}
+
+void LinearVelocityAnalytic_GetCornerNodeVelocities(void* analyticSolution) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	Grid*                   vertGrid;
+	Node_GlobalIndex        nodeMapper[8];
+	FeVariable*             velocityField = self->velocityField;
+	FeMesh*                 mesh = velocityField->feMesh;
+	Dimension_Index         dim = velocityField->dim;
+	Node_Index              globalNode_I;
+	Node_Index              ii;
+	
+	vertGrid = *(Grid**)ExtensionManager_Get( mesh->info, mesh, ExtensionManager_GetHandle( mesh->info, (Name)"vertexGrid" )  );
+
+	/* Find global indicies of nodes */
+	self->cornerNodeCount = 4;
+	nodeMapper[0] = Grid_ProjectIJK_MinMax( vertGrid, False, False, False );
+	nodeMapper[1] = Grid_ProjectIJK_MinMax( vertGrid, True, False, False );
+	nodeMapper[2] = Grid_ProjectIJK_MinMax( vertGrid, False, True, False );
+	nodeMapper[3] = Grid_ProjectIJK_MinMax( vertGrid, True, True, False );
+	if ( dim == 3 ) {
+		self->cornerNodeCount = 8;
+		nodeMapper[4] = Grid_ProjectIJK_MinMax( vertGrid, False, False, True );
+		nodeMapper[5] = Grid_ProjectIJK_MinMax( vertGrid, True, False, True );
+		nodeMapper[6] = Grid_ProjectIJK_MinMax( vertGrid, False, True, True );
+		nodeMapper[7] = Grid_ProjectIJK_MinMax( vertGrid, True, True, True );
+	}
+
+	/* Loop over corner nodes */
+	for ( ii = 0 ; ii < self->cornerNodeCount ; ii++ ) {
+		globalNode_I = nodeMapper[ ii ];
+		FeVariable_GetValueAtNodeGlobal( velocityField, globalNode_I, self->nodeVelocity[ii] );
+		FeVariable_GetCoordAtNodeGlobal( velocityField, globalNode_I, self->nodeCoords[ii] );
+	}
+}
+
+void GetLocalCoords( LinearVelocityAnalytic* self, double* coord, double* xi ) {
+	FeVariable*             velocityField = self->velocityField;
+	XYZ                     min;
+	XYZ                     max;
+	Dimension_Index         dim = velocityField->dim;
+	Dimension_Index         dim_I;
+
+	_FeVariable_GetMinAndMaxGlobalCoords( velocityField, min, max );
+	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
+		xi[ dim_I ] = 2.0 * (coord[ dim_I ] - min[ dim_I ])/(max[dim_I] - min[dim_I]) - 1;
+	}	
+}	
+
+/* Do a normal linear interpolation as if the box were a FEM element */
+void LinearVelocityAnalytic_VelocityFunction( void* analyticSolution, double* coord, double* velocity ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	FeVariable*             velocityField = self->velocityField;
+	FeMesh*                 mesh = velocityField->feMesh;
+	Dimension_Index         dim = velocityField->dim;
+	Dimension_Index         dim_I;
+	XYZ                     xi;
+	double                  Ni[8];
+	Node_Index              ii;
+	ElementType*            elementType;
+
+	/* Transform the coordinate into a master coordinate system */
+	GetLocalCoords( self, coord, xi );
+
+	/* Get Shape Functions */
+	elementType = FeMesh_GetElementType( mesh, 0 );
+	ElementType_EvaluateShapeFunctionsAt( elementType, xi, Ni );
+
+	/* Do interpolation */
+	/* Loop over corner nodes */
+	memset( velocity, 0, dim*sizeof(double) );
+	for ( ii = 0 ; ii < self->cornerNodeCount ; ii++ ) {
+		for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
+			velocity[ dim_I ] += Ni[ ii ] * self->nodeVelocity[ii][ dim_I ];
+		}
+	}
+}
+void LinearVelocityAnalytic_PressureFunction( void* analyticSolution, double* coord, double* pressure ) {
+	*pressure = 0.0;
+}
+
+void LinearVelocityAnalytic_VelocityGradientsFunction( void* analyticSolution, double* coord, double* velocityGradients ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	FeVariable*             velocityField = self->velocityField;
+	FeMesh*                 mesh = velocityField->feMesh;
+	ElementType*            elementType;
+	XYZ                     xi;
+	double                  jac[3][3];
+	double                  cof[3][3];	/* cofactors */
+	double                  detJac;
+	Node_Index              node_I;
+	double**                GNi; 
+	double**                GNx; 
+	double*                 nodeCoord;
+	double                  nodeValue;
+	Dimension_Index         dim = velocityField->dim;
+	Dimension_Index         i, j, dx, dxi;
+	Dimension_Index         dim_I;
+	
+	/* Transform the coordinate into a master coordinate system */
+	GetLocalCoords( self, coord, xi );
+
+	GNi = Memory_Alloc_2DArray( double, dim, self->cornerNodeCount, (Name)"GNi"  );
+	GNx = Memory_Alloc_2DArray( double, dim, self->cornerNodeCount, (Name)"GNx"  );
+
+	/* Get Shape Functions */
+	elementType = FeMesh_GetElementType( mesh, 0 );
+	elementType->_evaluateShapeFunctionLocalDerivsAt( elementType, xi, GNi );
+
+	/* build the jacobian matrix */
+	/*
+	jac = 	\sum_i d/d\xi( N_i ) x_i 		\sum_i d/d\xi( N_i ) y_i
+			\sum_i d/d\eta( N_i ) x_i 		\sum_i d/d\eta( N_i ) y_i
+	*/
+	if( dim == 2 ) {
+		jac[0][0] = jac[0][1] = jac[1][0] = jac[1][1] = 0.0;
+		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
+			nodeCoord = self->nodeCoords[ node_I ];
+			jac[0][0] = jac[0][0] + GNi[0][node_I] * nodeCoord[0];
+			jac[0][1] = jac[0][1] + GNi[0][node_I] * nodeCoord[1];
+			
+			jac[1][0] = jac[1][0] + GNi[1][node_I] * nodeCoord[0];
+			jac[1][1] = jac[1][1] + GNi[1][node_I] * nodeCoord[1];
+		}
+	}
+	
+	if( dim == 3 ) {
+		jac[0][0] = jac[0][1] = jac[0][2] = 0.0;
+		jac[1][0] = jac[1][1] = jac[1][2] = 0.0;
+		jac[2][0] = jac[2][1] = jac[2][2] = 0.0;
+		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
+			nodeCoord = self->nodeCoords[ node_I ];
+			jac[0][0] = jac[0][0] + GNi[0][node_I] * nodeCoord[0];
+			jac[0][1] = jac[0][1] + GNi[0][node_I] * nodeCoord[1];
+			jac[0][2] = jac[0][2] + GNi[0][node_I] * nodeCoord[2];
+			
+			jac[1][0] = jac[1][0] + GNi[1][node_I] * nodeCoord[0];
+			jac[1][1] = jac[1][1] + GNi[1][node_I] * nodeCoord[1];
+			jac[1][2] = jac[1][2] + GNi[1][node_I] * nodeCoord[2];
+			
+			jac[2][0] = jac[2][0] + GNi[2][node_I] * nodeCoord[0];
+			jac[2][1] = jac[2][1] + GNi[2][node_I] * nodeCoord[1];
+			jac[2][2] = jac[2][2] + GNi[2][node_I] * nodeCoord[2];
+		}
+	}
+	
+	/* get determinant of the jacobian matrix */
+	if( dim == 2 ) {
+		detJac = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0]; 
+	}		
+	if( dim == 3 ) {
+		detJac = jac[0][0]*( jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1] ) 
+				  - jac[0][1]*( jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0] ) 
+				  + jac[0][2]*( jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0] );
+	}
+	
+	/* invert the jacobian matrix A^-1 = adj(A)/det(A) */
+	if( dim == 2 ) {
+		double tmp = jac[0][0];
+		jac[0][0] = jac[1][1]/detJac;
+		jac[1][1] = tmp/detJac;
+		jac[0][1] = -jac[0][1]/detJac;
+		jac[1][0] = -jac[1][0]/detJac;		
+	}
+	if( dim == 3 ) {
+		/*
+		00 01 02
+		10 11 12
+		20 21 22		
+		*/		
+		cof[0][0] = jac[1][1]*jac[2][2] - jac[1][2]*jac[2][1];
+		cof[1][0] = -(jac[1][0]*jac[2][2] - jac[1][2]*jac[2][0]);
+		cof[2][0] = jac[1][0]*jac[2][1] - jac[1][1]*jac[2][0];
+		
+		cof[0][1] = -(jac[0][1]*jac[2][2] - jac[0][2]*jac[2][1]);
+		cof[1][1] = jac[0][0]*jac[2][2] - jac[0][2]*jac[2][0];
+		cof[2][1] = -(jac[0][0]*jac[2][1] - jac[0][1]*jac[2][0]);
+		
+		cof[0][2] = jac[0][1]*jac[1][2] - jac[0][2]*jac[1][1];
+		cof[1][2] = -(jac[0][0]*jac[1][2] - jac[0][2]*jac[1][0]);
+		cof[2][2] = jac[0][0]*jac[1][1] - jac[0][1]*jac[1][0];
+		
+		for( i=0; i<dim; i++ ) {
+			for( j=0; j<dim; j++ ) {
+				jac[i][j] = cof[i][j]/detJac;
+			}
+		}
+		
+		
+	}
+	
+	/* get global derivs Ni_x, Ni_y and Ni_z if dim == 3 */
+	for( dx=0; dx<dim; dx++ ) {
+		for(  node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
+			double globalSF_DerivVal = 0.0;
+			for(dxi=0; dxi<dim; dxi++) {
+				globalSF_DerivVal = globalSF_DerivVal + GNi[dxi][node_I] * jac[dx][dxi];
+			}
+			
+			GNx[dx][node_I] = globalSF_DerivVal;
+		}
+	}
+	
+	/* Initialise velocity gradients */
+	memset( velocityGradients, 0, sizeof( double ) * dim * dim );
+	
+	for ( dim_I = 0 ; dim_I < dim ; dim_I++ ) {
+		/* Interpolate derivative from nodes */
+		for( node_I =0;  node_I < self->cornerNodeCount ;  node_I ++){	
+			nodeValue    = self->nodeVelocity[ node_I ][ dim_I ];
+			
+			velocityGradients[dim_I*dim + 0] += GNx[0][node_I] * nodeValue;
+			velocityGradients[dim_I*dim + 1] += GNx[1][node_I] * nodeValue;
+			if( dim == 3 ) 
+				velocityGradients[dim_I*dim + 2] += GNx[2][node_I] * nodeValue;	
+		}
+	}
+	Memory_Free( GNi );
+	Memory_Free( GNx );
+}
+
+void LinearVelocityAnalytic_StrainRateFunction( void* analyticSolution, double* coord, double* strainRate ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	Dimension_Index         dim = self->velocityField->dim;
+	TensorArray             velocityGradients;
+
+	/* Get Velocity Gradients */
+	LinearVelocityAnalytic_VelocityGradientsFunction( self, coord, velocityGradients );
+	
+	/* Get Strain Rate */
+	TensorArray_GetSymmetricPart( velocityGradients, dim, strainRate );
+}
+
+void LinearVelocityAnalytic_StrainRateInvFunction( void* analyticSolution, double* coord, double* strainRateInv ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	Dimension_Index         dim = self->velocityField->dim;
+	SymmetricTensor         strainRate;
+
+	/* Get Strain Rate */
+	LinearVelocityAnalytic_StrainRateFunction( self, coord, strainRate );
+	
+	/* Get Invariant */
+	*strainRateInv = SymmetricTensor_2ndInvariant( strainRate, dim );
+}
+
+void _LinearVelocityAnalytic_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+
+	_FieldTest_AssignFromXML( self, cf, data );
+
+	self->velocityField = Stg_ComponentFactory_ConstructByName( cf, (Name)"VelocityField", FeVariable, True, data  ); 
+}
+
+void _LinearVelocityAnalytic_Build( void* analyticSolution, void* data ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	
+	_FieldTest_Build( self, data );
+
+	/* here we assign the memory and the func ptr for analytic sols */
+	self->_analyticSolutionList = Memory_Alloc_Array_Unnamed( FieldTest_AnalyticSolutionFunc*, 4 );
+	/* this order MUST be consistent with the xml file definition */
+	self->_analyticSolutionList[0] = LinearVelocityAnalytic_VelocityFunction;
+	self->_analyticSolutionList[1] = LinearVelocityAnalytic_PressureFunction;
+	self->_analyticSolutionList[2] = LinearVelocityAnalytic_StrainRateFunction;
+	self->_analyticSolutionList[3] = LinearVelocityAnalytic_StrainRateInvFunction;
+}
+
+void _LinearVelocityAnalytic_Initialise( void* analyticSolution, void* data ) {
+	LinearVelocityAnalytic *self = (LinearVelocityAnalytic*)analyticSolution;
+	
+	Stg_Component_Initialise( self->velocityField, data,  False );
+	LinearVelocityAnalytic_GetCornerNodeVelocities( self );
+
+	_FieldTest_Initialise( self, data );
+}
+
+void* _LinearVelocityAnalytic_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(LinearVelocityAnalytic);
+	Type                                                      type = LinearVelocityAnalytic_Type;
+	Stg_Class_DeleteFunction*                              _delete = _FieldTest_Delete;
+	Stg_Class_PrintFunction*                                _print = _FieldTest_Print;
+	Stg_Class_CopyFunction*                                  _copy = _FieldTest_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _LinearVelocityAnalytic_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _LinearVelocityAnalytic_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _LinearVelocityAnalytic_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _LinearVelocityAnalytic_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _FieldTest_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _FieldTest_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _FieldTest_New(  FIELDTEST_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_LinearVelocityAnalytic_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, LinearVelocityAnalytic_Type, (Name)"0", _LinearVelocityAnalytic_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/Toolbox/Toolbox.c
--- a/libStgFEM/Toolbox/Toolbox.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**	Kent Humphries, Software Engineer, VPAC. (kenth at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: StandardConditionFunctions.c 532 2006-04-04 00:21:59Z PatrickSunter $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include "Toolbox.h"
-
-const Type StgFEM_Toolbox_Type = "StgFEM_Toolbox";
-
-void _StgFEM_Toolbox_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data )  {
-}
-
-void* _StgFEM_Toolbox_DefaultNew( Name name ) {
-	return Codelet_New(
-			StgFEM_Toolbox_Type,
-			_StgFEM_Toolbox_DefaultNew,
-			_StgFEM_Toolbox_AssignFromXML,
-			_Codelet_Build,
-			_Codelet_Initialise,
-			_Codelet_Execute,
-			_Codelet_Destroy,
-			name );
-}
-
-void StgFEM_Toolbox_Initialise( PluginsManager* pluginsManager, int* argc, char*** argv ) {
-	StgFEM_Init( argc, argv );
-}
-
-void StgFEM_Toolbox_Finalise( PluginsManager* pluginsManager ) {
-	StgFEM_Finalise();
-	
-	Journal_RPrintf( Journal_Register( DebugStream_Type, (Name)StgFEM_Toolbox_Type  ), "Finalised: StGermain FEM Toolbox.\n" );
-}
-
-Index StgFEM_Toolbox_Register( PluginsManager* pluginsManager ) {
-	return PluginsManager_Submit( pluginsManager, StgFEM_Toolbox_Type, (Name)"0", _StgFEM_Toolbox_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/Toolbox/Toolbox.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libStgFEM/Toolbox/Toolbox.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,81 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**	Kent Humphries, Software Engineer, VPAC. (kenth at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: StandardConditionFunctions.c 532 2006-04-04 00:21:59Z PatrickSunter $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include "Toolbox.h"
+
+const Type StgFEM_Toolbox_Type = "StgFEM_Toolbox";
+
+void _StgFEM_Toolbox_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data )  {
+}
+
+void* _StgFEM_Toolbox_DefaultNew( Name name ) {
+	return Codelet_New(
+			StgFEM_Toolbox_Type,
+			_StgFEM_Toolbox_DefaultNew,
+			_StgFEM_Toolbox_AssignFromXML,
+			_Codelet_Build,
+			_Codelet_Initialise,
+			_Codelet_Execute,
+			_Codelet_Destroy,
+			name );
+}
+
+void StgFEM_Toolbox_Initialise( PluginsManager* pluginsManager, int* argc, char*** argv ) {
+	StgFEM_Init( argc, argv );
+}
+
+void StgFEM_Toolbox_Finalise( PluginsManager* pluginsManager ) {
+	StgFEM_Finalise();
+	
+	Journal_RPrintf( Journal_Register( DebugStream_Type, (Name)StgFEM_Toolbox_Type  ), "Finalised: StGermain FEM Toolbox.\n" );
+}
+
+Index StgFEM_Toolbox_Register( PluginsManager* pluginsManager ) {
+	return PluginsManager_Submit( pluginsManager, StgFEM_Toolbox_Type, (Name)"0", _StgFEM_Toolbox_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/src/Finalise.c
--- a/libStgFEM/src/Finalise.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SLE.h"
-#include "StgFEM/Assembly/Assembly.h"
-#include "Finalise.h"
-
-#include <stdio.h>
-
-Bool StgFEM_Finalise( void ) {
-	if( ToolboxesManager_IsInitialised( stgToolboxesManager, "StgFEM" ) ) {
-		Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-		
-		Stream_IndentBranch( StgFEM_Debug );
-		StgFEM_Discretisation_Finalise();
-		StgFEM_SLE_Finalise();
-		StgFEM_Assembly_Finalise();
-		Stream_UnIndentBranch( StgFEM_Debug );
-		return True;
-	} else {
-		return False;
-	}
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/src/Finalise.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libStgFEM/src/Finalise.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,67 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Finalise.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SLE.h"
+#include "StgFEM/Assembly/Assembly.h"
+#include "Finalise.h"
+
+#include <stdio.h>
+
+Bool StgFEM_Finalise( void ) {
+	if( ToolboxesManager_IsInitialised( stgToolboxesManager, "StgFEM" ) ) {
+		Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+		
+		Stream_IndentBranch( StgFEM_Debug );
+		StgFEM_Discretisation_Finalise();
+		StgFEM_SLE_Finalise();
+		StgFEM_Assembly_Finalise();
+		Stream_UnIndentBranch( StgFEM_Debug );
+		return True;
+	} else {
+		return False;
+	}
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/src/Init.c
--- a/libStgFEM/src/Init.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "StgFEM/SLE/SLE.h"
-#include "StgFEM/Assembly/Assembly.h"
-#include "Init.h"
-
-#include <stdio.h>
-
-/** Initialises the Linear Algebra package, then any init for this package
-such as streams etc */
-Bool StgFEM_StandardConditionFunctions_Init( int * argc, char ** argv[] );
-Bool StgFEM_Init( int* argc, char** argv[] ) {
-	/* This init function tells StGermain of all the component types, etc this module contributes. Because it can be linked at compile
-	   time or linked in by a toolbox at runtime, we need to make sure it isn't run twice (compiled in and loaded through a toolbox.*/
-	if( !ToolboxesManager_IsInitialised( stgToolboxesManager, "StgFEM" ) ) {
-		int tmp;
-		char* directory;
-
-		Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
-		tmp = Stream_GetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context" )  );
-		Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), 0 );
-		Journal_Printf( /* DO NOT CHANGE OR REMOVE */
-			Journal_Register( InfoStream_Type, (Name)"Context"  ), 
-			"StGermain Finite Element Framework revision %s. Copyright (C) 2003-2005 VPAC.\n", VERSION );
-		Stream_Flush( Journal_Register( InfoStream_Type, (Name)"Context" )  );
-		Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), tmp );
-	
-		StgFEM_Discretisation_Init( argc, argv );
-		StgFEM_SLE_Init( argc, argv );
-		StgFEM_Assembly_Init( argc, argv );
-                StgFEM_StandardConditionFunctions_Init( argc, argv );
-
-		/* Add the StgFEM path to the global xml path dictionary */
-		directory = Memory_Alloc_Array( char, 200, "xmlDirectory" ) ;
-		sprintf(directory, "%s%s", LIB_DIR, "/StGermain" );
-		XML_IO_Handler_AddDirectory("StgFEM", directory );
-		Memory_Free(directory);
-	
-		/* Add the plugin path to the global plugin list */
-		ModulesManager_AddDirectory( "StgFEM", LIB_DIR );
-
-		return True;
-	}
-	return False;
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/src/Init.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libStgFEM/src/Init.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,90 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Init.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "StgFEM/SLE/SLE.h"
+#include "StgFEM/Assembly/Assembly.h"
+#include "Init.h"
+
+#include <stdio.h>
+
+/** Initialises the Linear Algebra package, then any init for this package
+such as streams etc */
+Bool StgFEM_StandardConditionFunctions_Init( int * argc, char ** argv[] );
+Bool StgFEM_Init( int* argc, char** argv[] ) {
+	/* This init function tells StGermain of all the component types, etc this module contributes. Because it can be linked at compile
+	   time or linked in by a toolbox at runtime, we need to make sure it isn't run twice (compiled in and loaded through a toolbox.*/
+	if( !ToolboxesManager_IsInitialised( stgToolboxesManager, "StgFEM" ) ) {
+		int tmp;
+		char* directory;
+
+		Journal_Printf( Journal_Register( DebugStream_Type, (Name)"Context"  ), "In: %s\n", __func__ ); /* DO NOT CHANGE OR REMOVE */
+		tmp = Stream_GetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context" )  );
+		Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), 0 );
+		Journal_Printf( /* DO NOT CHANGE OR REMOVE */
+			Journal_Register( InfoStream_Type, (Name)"Context"  ), 
+			"StGermain Finite Element Framework revision %s. Copyright (C) 2003-2005 VPAC.\n", VERSION );
+		Stream_Flush( Journal_Register( InfoStream_Type, (Name)"Context" )  );
+		Stream_SetPrintingRank( Journal_Register( InfoStream_Type, (Name)"Context"  ), tmp );
+	
+		StgFEM_Discretisation_Init( argc, argv );
+		StgFEM_SLE_Init( argc, argv );
+		StgFEM_Assembly_Init( argc, argv );
+                StgFEM_StandardConditionFunctions_Init( argc, argv );
+
+		/* Add the StgFEM path to the global xml path dictionary */
+		directory = Memory_Alloc_Array( char, 200, "xmlDirectory" ) ;
+		sprintf(directory, "%s%s", LIB_DIR, "/StGermain" );
+		XML_IO_Handler_AddDirectory("StgFEM", directory );
+		Memory_Free(directory);
+	
+		/* Add the plugin path to the global plugin list */
+		ModulesManager_AddDirectory( "StgFEM", LIB_DIR );
+
+		return True;
+	}
+	return False;
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/tests/LibStgFEMSuite.c
--- a/libStgFEM/tests/LibStgFEMSuite.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-#include <mpi.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "pcu/pcu.h"
-#include <StGermain/StGermain.h>
-
-#include "StgDomain/StgDomain.h"
-#include "StgFEM/StgFEM.h"
-
-#include "LibStgFEMSuite.h"
-
-typedef struct {
-} LibStgFEMSuiteData;
-
-void LibStgFEMSuite_Setup( LibStgFEMSuiteData* data ) {
-}
-
-void LibStgFEMSuite_Teardown( LibStgFEMSuiteData* data ) {
-}
-
-void LibStgFEMSuite_DirectoryStGermain( LibStgFEMSuiteData* data ) {
-    Stg_Object* testDirectoryStGermain;
-    testDirectoryStGermain = (Stg_Object*)Stg_ObjectList_Get( Project_XMLSearchPaths, (Name)"StGermain" );
-    pcu_check_true( testDirectoryStGermain != NULL );
-}
-
-void LibStgFEMSuite_DirectoryStgFEM( LibStgFEMSuiteData * data  ) {
-    Stg_Object* testDirectoryStGermain;
-    Stg_Object* testDirectoryStgFEM;
-
-    testDirectoryStGermain = (Stg_Object*)Stg_ObjectList_Get( Project_XMLSearchPaths, (Name)"StGermain"  );
-    testDirectoryStgFEM= (Stg_Object*)Stg_ObjectList_Get( Project_XMLSearchPaths, (Name)"StgFEM" );
-
-    pcu_check_true( ( strcmp((char* )LIB_DIR, (char*)testDirectoryStGermain) ) || ( testDirectoryStgFEM != NULL ) );
-}
-
-void LibStgFEMSuite( pcu_suite_t* suite ) {
-
-    pcu_suite_setData( suite, LibStgFEMSuiteData );
-    pcu_suite_setFixtures( suite, LibStgFEMSuite_Setup, LibStgFEMSuite_Teardown);
-
-    pcu_suite_addTest( suite, LibStgFEMSuite_DirectoryStGermain );
-    pcu_suite_addTest( suite, LibStgFEMSuite_DirectoryStgFEM);
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/tests/LibStgFEMSuite.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libStgFEM/tests/LibStgFEMSuite.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,49 @@
+#include <mpi.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcu/pcu.h"
+#include <StGermain/StGermain.h>
+
+#include "StgDomain/StgDomain.h"
+#include "StgFEM/StgFEM.h"
+
+#include "LibStgFEMSuite.h"
+
+typedef struct {
+} LibStgFEMSuiteData;
+
+void LibStgFEMSuite_Setup( LibStgFEMSuiteData* data ) {
+}
+
+void LibStgFEMSuite_Teardown( LibStgFEMSuiteData* data ) {
+}
+
+void LibStgFEMSuite_DirectoryStGermain( LibStgFEMSuiteData* data ) {
+    Stg_Object* testDirectoryStGermain;
+    testDirectoryStGermain = (Stg_Object*)Stg_ObjectList_Get( Project_XMLSearchPaths, (Name)"StGermain" );
+    pcu_check_true( testDirectoryStGermain != NULL );
+}
+
+void LibStgFEMSuite_DirectoryStgFEM( LibStgFEMSuiteData * data  ) {
+    Stg_Object* testDirectoryStGermain;
+    Stg_Object* testDirectoryStgFEM;
+
+    testDirectoryStGermain = (Stg_Object*)Stg_ObjectList_Get( Project_XMLSearchPaths, (Name)"StGermain"  );
+    testDirectoryStgFEM= (Stg_Object*)Stg_ObjectList_Get( Project_XMLSearchPaths, (Name)"StgFEM" );
+
+    pcu_check_true( ( strcmp((char* )LIB_DIR, (char*)testDirectoryStGermain) ) || ( testDirectoryStgFEM != NULL ) );
+}
+
+void LibStgFEMSuite( pcu_suite_t* suite ) {
+
+    pcu_suite_setData( suite, LibStgFEMSuiteData );
+    pcu_suite_setFixtures( suite, LibStgFEMSuite_Setup, LibStgFEMSuite_Teardown);
+
+    pcu_suite_addTest( suite, LibStgFEMSuite_DirectoryStGermain );
+    pcu_suite_addTest( suite, LibStgFEMSuite_DirectoryStgFEM);
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/tests/testLibStgFEM.c
--- a/libStgFEM/tests/testLibStgFEM.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: testLibStgFEM.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-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 );
-	/* Read input */
-
-	if( !StGermain_Init( &argc, &argv ) || !StgDomain_Init( &argc, &argv ) ) {
-		fprintf( stderr, "Error initialising StGermain, exiting.\n" );
-		exit( EXIT_FAILURE );
-	}
-	StgFEM_Init( &argc, &argv );
-	MPI_Barrier( CommWorld ); /* Ensures copyright info always come first in output */
-
-	if( argc >= 2 ) {
-		procToWatch = atoi( argv[1] );
-	}
-	else {
-		procToWatch = 0;
-	}
-	if( rank == procToWatch ) {
-		Stg_Object* testDirectory;
-		printf( "Watching rank: %i\n", rank );
-		/* Testing entries in xmlDictionary */
-		testDirectory = Stg_ObjectList_Get( xmlSearchPaths, (Name)"StGermain" );
-		if (testDirectory != NULL) {
-			printf("StGermain XML library Path found.\n");
-		}
-		else {
-			printf("StGermain XML library Path not found.\n"); 
-		}
-		/* For build in the same build directory */
-		if (strcmp((char* )LIB_DIR, (char*)testDirectory)) {
-			printf("StgFEM XML library Path found.\n");
-		}
-		/* For build in separate directories */
-		else{
-			testDirectory = Stg_ObjectList_Get( xmlSearchPaths, (Name)"StgFEM" );
-			if (testDirectory != NULL) {
-				printf("StgFEM XML library Path found.\n");
-			}
-			else {
-				printf("StgFEM XML library Path not found.\n"); 
-			}
-		}
-	
-	}
-	 
-	StgFEM_Finalise();
-	StGermain_Finalise();
-	
-	/* Close off MPI */
-	MPI_Finalize( );
-
-	return 0; /* success */
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 libStgFEM/tests/testLibStgFEM.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libStgFEM/tests/testLibStgFEM.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,114 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: testLibStgFEM.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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 );
+	/* Read input */
+
+	if( !StGermain_Init( &argc, &argv ) || !StgDomain_Init( &argc, &argv ) ) {
+		fprintf( stderr, "Error initialising StGermain, exiting.\n" );
+		exit( EXIT_FAILURE );
+	}
+	StgFEM_Init( &argc, &argv );
+	MPI_Barrier( CommWorld ); /* Ensures copyright info always come first in output */
+
+	if( argc >= 2 ) {
+		procToWatch = atoi( argv[1] );
+	}
+	else {
+		procToWatch = 0;
+	}
+	if( rank == procToWatch ) {
+		Stg_Object* testDirectory;
+		printf( "Watching rank: %i\n", rank );
+		/* Testing entries in xmlDictionary */
+		testDirectory = Stg_ObjectList_Get( xmlSearchPaths, (Name)"StGermain" );
+		if (testDirectory != NULL) {
+			printf("StGermain XML library Path found.\n");
+		}
+		else {
+			printf("StGermain XML library Path not found.\n"); 
+		}
+		/* For build in the same build directory */
+		if (strcmp((char* )LIB_DIR, (char*)testDirectory)) {
+			printf("StgFEM XML library Path found.\n");
+		}
+		/* For build in separate directories */
+		else{
+			testDirectory = Stg_ObjectList_Get( xmlSearchPaths, (Name)"StgFEM" );
+			if (testDirectory != NULL) {
+				printf("StgFEM XML library Path found.\n");
+			}
+			else {
+				printf("StgFEM XML library Path not found.\n"); 
+			}
+		}
+	
+	}
+	 
+	StgFEM_Finalise();
+	StGermain_Finalise();
+	
+	/* Close off MPI */
+	MPI_Finalize( );
+
+	return 0; /* success */
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/CompareFeVariableAgainstReferenceSolution/CompareFeVariableAgainstReferenceSolution.c
--- a/plugins/CompareFeVariableAgainstReferenceSolution/CompareFeVariableAgainstReferenceSolution.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,541 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-** Copyright (c) 2005, Monash Cluster Computing 
-** All rights reserved.
-** Redistribution and use in source and binary forms, with or without modification,
-** are permitted provided that the following conditions are met:
-**
-** 		* Redistributions of source code must retain the above copyright notice, 
-** 			this list of conditions and the following disclaimer.
-** 		* Redistributions in binary form must reproduce the above copyright 
-**			notice, this list of conditions and the following disclaimer in the 
-**			documentation and/or other materials provided with the distribution.
-** 		* Neither the name of the Monash University nor the names of its contributors 
-**			may be used to endorse or promote products derived from this software 
-**			without specific prior written permission.
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
-** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
-** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
-** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
-** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
-** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
-** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
-** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**
-**
-** Contact:
-*%		Louis Moresi - Louis.Moresi at sci.monash.edu.au
-*%
-** Contributors:
-*+		Mirko Velic
-*+		Julian Giordani
-*+		Robert Turnbull
-*+		Vincent Lemiale
-*+		Louis Moresi
-*+		David May
-*+		David Stegman
-*+		Patrick Sunter
-** $Id: solA.c 567 2006-05-25 02:10:57Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-#include <string.h>
-
-const Type CompareFeVariableAgainstReferenceSolution_Type = "StgFEM_CompareFeVariableAgainstReferenceSolution";
-
-void CompareFeVariableAgainstReferenceSolution_TestAll( void* compareFeVariable, void* data );
-void CompareFeVariableAgainstReferenceSolution_TestVariable( void* compareFeVariable, FeVariable* feVarToTest, double tolerance, Bool relativeErrorMeasure );
-void _CompareFeVariableAgainstReferenceSolution_Delete( void* compareFeVariable );
-
-typedef struct {
-	__Codelet
-	Stg_ComponentFactory*    cf;
-
-	char*                    referencePath;
-	Swarm*                   integrationSwarm;
-	
-	Stg_ObjectList*          variables;
-	Stg_ObjectList*          tolerances;
-	Stg_ObjectList*          relativeErrorMeasure;
-
-	Index                    timeStepToCompare;
-
-	char*                    importFormatType;
-	char*                    exportFormatType;
-
-	char*                    referenceFeVariableSuffix;
-	Bool                     alwaysOutputErrors;
-} CompareFeVariableAgainstReferenceSolution;
-
-
-void _CompareFeVariableAgainstReferenceSolution_AssignFromXML( void* compareFeVariable, Stg_ComponentFactory* cf, void* data ) {
-	CompareFeVariableAgainstReferenceSolution* self = (CompareFeVariableAgainstReferenceSolution*) compareFeVariable;
-
-	AbstractContext*         context;
-
-	Dictionary*              dictionary;
-	char*                    referencePath;
-	char*                    integrationSwarmName;
-	
-	char*                    varName;
-	Dictionary_Entry_Value*  varList;
-
-	FeVariable*              feVarToTest;
-	Index                    var_I;
-	double                   tolerance;
-	Bool                     relativeErrorMeasure;
-
-	char*                    tmpName;
-
-	Stream*                  myStream;
-
-	context = (AbstractContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
-	self->context = context;
-	self->cf = cf;
-
-	EP_AppendClassHook( 
-			Context_GetEntryPoint( context, AbstractContext_EP_DumpClass ),
-			CompareFeVariableAgainstReferenceSolution_TestAll, 
-			self );
-
-	self->alwaysOutputErrors = Dictionary_GetBool_WithDefault( cf->rootDict, (Dictionary_Entry_Key)"alwaysOutputErrors", False  );
-
-	dictionary = Dictionary_GetDictionary( cf->rootDict, self->name );
-	Journal_Firewall(
-		dictionary != NULL,
-		Journal_MyStream( Error_Type, self ),
-		"In func %s - Specify FeVariables to compare in struct %s\n", __func__, self->name );
-
-	referencePath = Dictionary_GetString_WithDefault( dictionary, "referencePath", "./" );
-	Journal_Printf(
-		Journal_MyStream( Info_Type, self ),
-		"%s: Using reference path %s\n", self->name, referencePath );
-	if ( referencePath[ strlen(referencePath) ] == (int)'/' ) {
-		self->referencePath = StG_Strdup( referencePath );
-	} 
-	else {	
-		Stg_asprintf( &self->referencePath, "%s/", referencePath );
-	}
-	
-	integrationSwarmName = Dictionary_GetString_WithDefault( dictionary, "integrationSwarm", "gaussSwarm" );
-	Journal_Printf(
-		Journal_MyStream( Info_Type, self ),
-		"%s: Using integration swarm %s\n", self->name, integrationSwarmName );
-	self->integrationSwarm = Stg_ComponentFactory_ConstructByName( cf, (Name)integrationSwarmName, Swarm, True, data ); 
-
-	self->variables            = Stg_ObjectList_New();
-	self->tolerances           = Stg_ObjectList_New();
-	self->relativeErrorMeasure = Stg_ObjectList_New( );
-
-	varList = Dictionary_Get( dictionary, (Dictionary_Entry_Key)"variables" );
-	Journal_Firewall(
-		varList != NULL && Dictionary_Entry_Value_GetCount( varList  ) > 0,
-		Journal_MyStream( Error_Type, self ),
-		"In func %s - Specify FeVariables to compare in list \"variables\" for %s\n", __func__, self->name );
-
-	for ( var_I = 0; var_I < Dictionary_Entry_Value_GetCount( varList ); ++var_I ) {
-		varName = Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( varList, var_I ) );
-		feVarToTest = Stg_ComponentFactory_ConstructByName( cf, (Name)varName, FeVariable, True, data  );
-		Journal_Printf(
-			Journal_MyStream( Info_Type, self ),
-			"%s: Comparing FeVariable %s\n", self->name, varName );
-
-		tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"tolerance"  );
-		tolerance = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)tmpName, 0.005  );
-
-		tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"useRelativeErrorMeasure"  );
-		relativeErrorMeasure = Dictionary_GetBool_WithDefault( dictionary, (Dictionary_Entry_Key)tmpName, False  );
-		
-		Stg_ObjectList_Append( self->variables, feVarToTest );
-		Stg_ObjectList_Append( self->tolerances, Stg_PrimitiveObject_New_Double( tolerance, (Name)varName )  );
-		Stg_ObjectList_Append( self->relativeErrorMeasure, Stg_PrimitiveObject_New_Int( (relativeErrorMeasure)?1:0, (Name)varName )  );
-	}
-
-	/* Default is zero which means every time step */
-	self->timeStepToCompare = Dictionary_GetUnsignedInt_WithDefault( dictionary, "timeStepToCompare", 0 );
-	if ( self->timeStepToCompare == 0 ) {
-		Journal_Printf(
-			Journal_MyStream( Info_Type, self ),
-			"%s: timeStepToCompare is 0 - All time steps will be compared\n",
-			self->type );
-	}
-
-	self->referenceFeVariableSuffix = StG_Strdup( Dictionary_GetString_WithDefault( dictionary, "referenceFeVariableSuffix", 
-		"Reference" ) );
-		
-
-	myStream = Journal_MyStream( Info_Type, self );
-	Stg_asprintf( &tmpName, "%s.dat", self->name );
-        Stream_RedirectFile_WithPrependedPath( myStream, self->context->outputPath, tmpName );
-	Memory_Free( tmpName );
-}
-
-
-void* _CompareFeVariableAgainstReferenceSolution_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(CompareFeVariableAgainstReferenceSolution);
-	Type                                                      type = CompareFeVariableAgainstReferenceSolution_Type;
-	Stg_Class_DeleteFunction*                              _delete = _CompareFeVariableAgainstReferenceSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _CompareFeVariableAgainstReferenceSolution_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _CompareFeVariableAgainstReferenceSolution_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Codelet_New(  CODELET_PASSARGS  );
-}
-
-
-Index StgFEM_CompareFeVariableAgainstReferenceSolution_Register( PluginsManager* pluginsManager ) {
-	return PluginsManager_Submit( pluginsManager, CompareFeVariableAgainstReferenceSolution_Type, (Name)"0", _CompareFeVariableAgainstReferenceSolution_DefaultNew  );
-}
-
-
-void CompareFeVariableAgainstReferenceSolution_TestAll( void* compareFeVariable, void* data ) {
-	CompareFeVariableAgainstReferenceSolution* self = (CompareFeVariableAgainstReferenceSolution*) compareFeVariable;
-
-	FeVariable*     feVarToTest;
-	double          tolerance;
-	int             relativeErrorMeasure;
-
-	Index           var_I;
-
-	/* No need to test initial conditions */
-	if ( self->context->timeStep < 1 ) {
-		return;
-	}
-
-	if ( self->timeStepToCompare != 0 && self->context->timeStep != self->timeStepToCompare ) {
-		/* Only compare timesteps that has been selected iff timeStepToCompare is non-zero */
-		return;
-	}
-
-	for ( var_I = 0; var_I < self->variables->count; ++var_I ) {
-		feVarToTest = (FeVariable*)Stg_ObjectList_At( self->variables, var_I );
-		tolerance = ((Stg_PrimitiveObject*)Stg_ObjectList_At( self->tolerances, var_I ))->value.asDouble;
-		relativeErrorMeasure = ((Stg_PrimitiveObject*)Stg_ObjectList_At( self->relativeErrorMeasure, var_I ))->value.asInt;
-		CompareFeVariableAgainstReferenceSolution_TestVariable( self, feVarToTest, tolerance, relativeErrorMeasure ? True : False );
-	}
-}
-
-
-void CompareFeVariableAgainstReferenceSolution_TestVariable( void* compareFeVariable, FeVariable* feVarToTest, double tolerance, Bool relativeErrorMeasure ) {
-	CompareFeVariableAgainstReferenceSolution* self = (CompareFeVariableAgainstReferenceSolution*) compareFeVariable;
-	Variable_Register*       variable_Register;
-	Variable*                referenceDataVariable;
-	Variable*                roundedDataVariable;
-	char*                    referenceVariableName[9];
-	char*                    roundedVariableName[9];
-	Variable_Index           variable_I;
-	DofLayout*               referenceDofLayout;
-	DofLayout*               roundedDofLayout;
-	Node_DomainIndex         dNode_I;
-	Dof_Index                dofCountAtNode;
-	Dof_Index                dofCountAtPrevNode = 0;
-	Dof_Index                dof_I;
-	double*                  nodalValues = NULL;
-
-	FeVariable*              referenceFeVar;
-	OperatorFeVariable*      refMagnitudeField;
-	FeVariable*              roundedFeVar;
-	OperatorFeVariable*      errorField;
-	OperatorFeVariable*      errorMagnitudeField, *relativeErrorMagnitudeField;
-	OperatorFeVariable*      feVarOutput;
-
-	char*                    tmpName;
-	char*                    tmpName2;
-	char*                    filename;
-	Bool                     scalar;
-	Dof_Index                componentsCount;
-	/* TODO: hardcode for now - should be read in constructor, or read from the reference */
-	/* feVar type, or file reader or something */
-	unsigned int             numSigFigsInReferenceFeVar = 15;
-	char*                    refName = NULL;
-	double                   result;
-	
-	variable_Register = self->context->variable_Register;
-
-	componentsCount = feVarToTest->fieldComponentCount;
-	scalar = (componentsCount == 1) ? True : False;
-
-	/* Ok:- here, we know that the reference, or benchmark, FeVariable that we are
-	comparing against may have been rounded off already, and we don't want to give
-	a spurious error result just because the solution just calculated has accuracy
-	beyond what the rounded benchmark is giving. Thus, we truncate the result to the
-	level of the reference FeVariable */
-
-	/* Create a DataVariable for the Reference. This serves as the memory object is is linked to */
-	/* Likewise, for the rounded-off version of the "live" FeVar we are testing */
-	assert( Class_IsSuper( feVarToTest->feMesh->topo, IGraph ) );
-	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"Reference-DataVariable"  );
-	tmpName2 = Stg_Object_AppendSuffix( feVarToTest, (Name)"Rounded-DataVariable" );
-	if ( scalar == 1  ) {
-		referenceDataVariable = Variable_NewScalar( tmpName, self->context, Variable_DataType_Double, (Index*)&((IGraph*)feVarToTest->feMesh->topo)->remotes[MT_VERTEX]->nDomains, NULL, (void**)NULL, variable_Register  );
-		roundedDataVariable = Variable_NewScalar( tmpName2, self->context, Variable_DataType_Double, (Index*)&((IGraph*)feVarToTest->feMesh->topo)->remotes[MT_VERTEX]->nDomains, NULL, (void**)NULL, variable_Register  );
-	}
-	else {
-		Journal_Firewall( 
-			componentsCount <= 9,
-			Journal_MyStream( Error_Type, self ),
-			"In func %s - Cannot create a variable with more than 9 components (%s)\n",
-			__func__,
-			feVarToTest->name );
-		for ( variable_I = 0 ; variable_I < componentsCount; variable_I++ ) {
-			Stg_asprintf( 
-				&referenceVariableName[ variable_I ], 
-				"%s-Reference-ComponentVariable%d", 
-				feVarToTest->name, 
-				variable_I );
-			Stg_asprintf( 
-				&roundedVariableName[ variable_I ], 
-				"%s-Rounded-ComponentVariable%d", 
-				feVarToTest->name, 
-				variable_I );
-		}
-		referenceDataVariable = Variable_NewVector(
-				tmpName,
-				self->context,
-				Variable_DataType_Double,
-				componentsCount,
-				(Index*)(&((IGraph*)feVarToTest->feMesh->topo)->remotes[MT_VERTEX]->nDomains), 
-				NULL,
-				(void**)NULL,
-				variable_Register,
-				referenceVariableName[0],
-				referenceVariableName[1],
-				referenceVariableName[2],
-				referenceVariableName[3],
-				referenceVariableName[4],
-				referenceVariableName[5],
-				referenceVariableName[6],
-				referenceVariableName[7],
-				referenceVariableName[8] );
-
-		roundedDataVariable = Variable_NewVector(
-				tmpName2,
-				self->context,
-				Variable_DataType_Double,
-				componentsCount,
-				(Index*)(&((IGraph*)feVarToTest->feMesh->topo)->remotes[MT_VERTEX]->nDomains), 
-				NULL,
-				(void**)NULL,
-				variable_Register,
-				roundedVariableName[0],
-				roundedVariableName[1],
-				roundedVariableName[2],
-				roundedVariableName[3],
-				roundedVariableName[4],
-				roundedVariableName[5],
-				roundedVariableName[6],
-				roundedVariableName[7],
-				roundedVariableName[8] );
-	}
-	Memory_Free( tmpName );
-	Memory_Free( tmpName2 );
-	
-	referenceDataVariable->allocateSelf = True;
-	roundedDataVariable->allocateSelf = True;
-
-	Stg_Component_Build( referenceDataVariable, NULL, False );
-	Stg_Component_Initialise( referenceDataVariable, NULL, False );
-	Stg_Component_Build( roundedDataVariable, NULL, False );
-	Stg_Component_Initialise( roundedDataVariable, NULL, False );
-
-	/* Create Dof layout for this variable based on its own DataVariable */
-	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"Reference-DofLayout"  );
-	tmpName2 = Stg_Object_AppendSuffix( feVarToTest, (Name)"Rounded-DofLayout"  );
-	referenceDofLayout = DofLayout_New( tmpName, (DomainContext*)self->context, variable_Register, Mesh_GetDomainSize( feVarToTest->feMesh, MT_VERTEX ), NULL );
-	roundedDofLayout = DofLayout_New( tmpName2, (DomainContext*)self->context, variable_Register, Mesh_GetDomainSize( feVarToTest->feMesh, MT_VERTEX ), NULL );
-
-	if ( scalar ) {
-		DofLayout_AddAllFromVariableArray( referenceDofLayout, 1, &referenceDataVariable );
-		DofLayout_AddAllFromVariableArray( roundedDofLayout, 1, &roundedDataVariable );
-	}
-	else {
-		for ( variable_I = 0 ; variable_I < componentsCount ; variable_I++ ) {
-			/* Assign variable to each node */
-			for( dNode_I = 0; dNode_I < Mesh_GetDomainSize( feVarToTest->feMesh, MT_VERTEX ); dNode_I++ ) {
-				DofLayout_AddDof_ByVarName( referenceDofLayout, referenceVariableName[variable_I], dNode_I );
-				DofLayout_AddDof_ByVarName( roundedDofLayout, roundedVariableName[variable_I], dNode_I );
-			}
-			/* Free Name */
-			Memory_Free( referenceVariableName[ variable_I ] );
-			Memory_Free( roundedVariableName[ variable_I ] );
-		}
-	}
-	Memory_Free( tmpName );
-	Memory_Free( tmpName2 );
-	
-	Stg_Component_Build( referenceDofLayout, NULL, False );
-	Stg_Component_Initialise( referenceDofLayout, NULL, False );
-	Stg_Component_Build( roundedDofLayout, NULL, False );
-	Stg_Component_Initialise( roundedDofLayout, NULL, False );
-
-	if ( strlen( self->referenceFeVariableSuffix ) > 0 ) {
-		refName = Stg_Object_AppendSuffix( feVarToTest, (Name)self->referenceFeVariableSuffix  );
-	}
-	else {
-		/* refName = Stg_Object_AppendSuffix( feVarToTest, (Name)"Reference"  ); */
-		/* We actually need the referenceFeVar initially to be called the same as feVarToTest,
-		 * so it reads the correct values - PatrickSunter, 9 Jun 2007 */ 
-		refName = StG_Strdup( feVarToTest->name );
-	}
-
-	referenceFeVar = FeVariable_New_FromTemplate( 
-		refName, 
-		(DomainContext*)self->context,
-		feVarToTest,
-		referenceDofLayout, 
-		NULL, 
-		True,  /* isReference = True */
-		False, /* Don't set the "test every timestep var", since we re-create this guy each timestep anyway*/
-		feVarToTest->fieldVariable_Register );
-
-	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"Rounded"  );
-	roundedFeVar = FeVariable_New_FromTemplate( 
-		tmpName, 
-		(DomainContext*)self->context,
-		feVarToTest, 
-		roundedDofLayout, 
-		NULL, 
-		False,
-		False,
-		feVarToTest->fieldVariable_Register );
-
-	Memory_Free( tmpName );
-
-	Stg_Component_Build( referenceFeVar, self->context, False );
-	Stg_Component_Build( roundedFeVar, self->context, False );
-	/* Note we _don't_ pass in the context to the vars below to disable checkpoint-restart,
-	 * since we want manual control over loading these 2 */
-	Stg_Component_Initialise( referenceFeVar, NULL, False );
-	Stg_Component_Initialise( roundedFeVar, NULL, False );
-
-	filename = Memory_Alloc_Array_Unnamed( char, strlen(self->referencePath) + strlen(self->name) + 1 + 5 + 1 + 3 + 1 );
-#ifdef READ_HDF5
-		sprintf( filename, "%s/%s.%.5u.h5", self->referencePath, self->name, self->context->timeStep );
-#else
-		sprintf( filename, "%s/%s.%.5u.h5", self->referencePath, self->name, self->context->timeStep );
-#endif
-	FeVariable_ReadFromFile( referenceFeVar, filename );
-
-	/* Note this is a bit inelegant, but kind of necessary unless we rewrite the FeVariable
-	 * checkpointing-reading code again to be more general - see my comment above when
-	 * refName is allocated */
-	if ( 0 == strcmp( feVarToTest->name, referenceFeVar->name ) ) {
-		Memory_Free( referenceFeVar->name );
-		referenceFeVar->name = Stg_Object_AppendSuffix( feVarToTest, (Name)"Reference"  );
-	}
-	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"MagnitudeField"  );
-	refMagnitudeField = OperatorFeVariable_NewUnary( tmpName, (DomainContext*)self->context, referenceFeVar, "Magnitude" );
-	Memory_Free( tmpName );
-
-	/* now we need to round off the feVar we are testing, and copy the result to the roundedFeVar */
-	for( dNode_I = 0; dNode_I < Mesh_GetDomainSize( feVarToTest->feMesh, MT_VERTEX ); dNode_I++ ) {
-		dofCountAtNode = feVarToTest->dofLayout->dofCounts[dNode_I];
-		
-		if ( dofCountAtNode != dofCountAtPrevNode ) {
-			nodalValues = Memory_Realloc_Array( nodalValues, double, dofCountAtNode ); 
-		}
-		FeVariable_GetValueAtNode( feVarToTest, dNode_I, nodalValues );
-
-		for ( dof_I=0; dof_I < dofCountAtNode; dof_I++ ) {
-			nodalValues[dof_I] = StG_RoundDoubleToNSigFigs( nodalValues[dof_I], numSigFigsInReferenceFeVar );
-		}
-		FeVariable_SetValueAtNode( roundedFeVar, dNode_I, nodalValues );
-		dofCountAtPrevNode = dofCountAtNode;
-	}
-	Memory_Free( nodalValues );
-
-	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"ErrorField"  );
-	errorField = OperatorFeVariable_NewBinary( tmpName, (DomainContext*)self->context, roundedFeVar, referenceFeVar, "Subtraction" );
-	Memory_Free( tmpName );
-
-	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"ErrorMagnitudeField"  );
-	errorMagnitudeField = OperatorFeVariable_NewUnary( tmpName, (DomainContext*)self->context, errorField, "Magnitude" );
-	Memory_Free( tmpName );
-
-	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"RelativeErrorMagnitudeField"  );
-	relativeErrorMagnitudeField = OperatorFeVariable_NewBinary( tmpName, (DomainContext*)self->context, errorMagnitudeField, refMagnitudeField, "ScalarDivision" );
-	Memory_Free( tmpName );
-
-	/* Build and Initialise the newly-created OperatorFeVariables - else we can't use them */
-	Stg_Component_Build( errorField, self->context, False );
-	Stg_Component_Build( errorMagnitudeField, self->context, False );
-	Stg_Component_Build( refMagnitudeField, self->context, False );
-	Stg_Component_Build( relativeErrorMagnitudeField, self->context, False );
-	Stg_Component_Initialise( errorField, self->context, False );
-	Stg_Component_Initialise( errorMagnitudeField, self->context, False );
-	Stg_Component_Initialise( refMagnitudeField, self->context, False );
-	Stg_Component_Initialise( relativeErrorMagnitudeField, self->context, False );
-
-	/* If the relativeErrorMeasure flag was used, then change the calculations and output to be relative */
-	if( relativeErrorMeasure ) 
-		feVarOutput = relativeErrorMagnitudeField;
-	else
-		feVarOutput = errorMagnitudeField;
-
-        result = FeVariable_Integrate( feVarOutput, self->integrationSwarm );
-
-	Journal_Printf( 
-		Journal_MyStream( Info_Type, self ), 
-		"Timestep %u: Total integrated value of '%s' is %s a tolerance %.5g.\n",
-		self->context->timeStep, 
-		feVarOutput->name, 
-		result <= tolerance ? "within" : "outside", 
-		tolerance );
-
-	if ( ( result > tolerance ) || (True == self->alwaysOutputErrors) ) {
-		if( relativeErrorMeasure ) {
-			Journal_Printf( 
-				Journal_MyStream( Info_Type, self ), 
-				"\t(Integrated total relative error was %g)\n",
-				result );
-		}
-		else {
-			Journal_Printf( 
-				Journal_MyStream( Info_Type, self ), 
-				"\t(Integrated total absolute error was %g)\n",
-				result );
-		}
-	}	
-
-	/* TODO: The lines below were commented out. Why? This is actually a bad memory leak! PatrickSunter, 9 Jul 2007 */
-	/*
-	Stg_Class_Delete( referenceDataVariable );
-	Stg_Class_Delete( referenceDofLayout );
-	Stg_Class_Delete( referenceFeVar );
-	Stg_Class_Delete( roundedDataVariable );
-	Stg_Class_Delete( roundedDofLayout );
-	Stg_Class_Delete( roundedFeVar );
-	Stg_Class_Delete( errorField );
-	Stg_Class_Delete( errorMagnitudeField );
-	Stg_Class_Delete( relativeErrorMagnitudeField );
-	*/
-
-	Memory_Free( refName );
-}
-	
-void _CompareFeVariableAgainstReferenceSolution_Delete( void* compareFeVariable ) {
-	CompareFeVariableAgainstReferenceSolution* self = (CompareFeVariableAgainstReferenceSolution*) compareFeVariable;
-
-	Memory_Free( self->referencePath );
-	Memory_Free( self->referenceFeVariableSuffix );
-	Memory_Free( self->importFormatType );
-	Memory_Free( self->exportFormatType );
-}	
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/CompareFeVariableAgainstReferenceSolution/CompareFeVariableAgainstReferenceSolution.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/CompareFeVariableAgainstReferenceSolution/CompareFeVariableAgainstReferenceSolution.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,541 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+** Copyright (c) 2005, Monash Cluster Computing 
+** All rights reserved.
+** Redistribution and use in source and binary forms, with or without modification,
+** are permitted provided that the following conditions are met:
+**
+** 		* Redistributions of source code must retain the above copyright notice, 
+** 			this list of conditions and the following disclaimer.
+** 		* Redistributions in binary form must reproduce the above copyright 
+**			notice, this list of conditions and the following disclaimer in the 
+**			documentation and/or other materials provided with the distribution.
+** 		* Neither the name of the Monash University nor the names of its contributors 
+**			may be used to endorse or promote products derived from this software 
+**			without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
+** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 
+** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
+** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+**
+** Contact:
+*%		Louis Moresi - Louis.Moresi at sci.monash.edu.au
+*%
+** Contributors:
+*+		Mirko Velic
+*+		Julian Giordani
+*+		Robert Turnbull
+*+		Vincent Lemiale
+*+		Louis Moresi
+*+		David May
+*+		David Stegman
+*+		Patrick Sunter
+** $Id: solA.c 567 2006-05-25 02:10:57Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+#include <string.h>
+
+const Type CompareFeVariableAgainstReferenceSolution_Type = "StgFEM_CompareFeVariableAgainstReferenceSolution";
+
+void CompareFeVariableAgainstReferenceSolution_TestAll( void* compareFeVariable, void* data );
+void CompareFeVariableAgainstReferenceSolution_TestVariable( void* compareFeVariable, FeVariable* feVarToTest, double tolerance, Bool relativeErrorMeasure );
+void _CompareFeVariableAgainstReferenceSolution_Delete( void* compareFeVariable );
+
+typedef struct {
+	__Codelet
+	Stg_ComponentFactory*    cf;
+
+	char*                    referencePath;
+	Swarm*                   integrationSwarm;
+	
+	Stg_ObjectList*          variables;
+	Stg_ObjectList*          tolerances;
+	Stg_ObjectList*          relativeErrorMeasure;
+
+	Index                    timeStepToCompare;
+
+	char*                    importFormatType;
+	char*                    exportFormatType;
+
+	char*                    referenceFeVariableSuffix;
+	Bool                     alwaysOutputErrors;
+} CompareFeVariableAgainstReferenceSolution;
+
+
+void _CompareFeVariableAgainstReferenceSolution_AssignFromXML( void* compareFeVariable, Stg_ComponentFactory* cf, void* data ) {
+	CompareFeVariableAgainstReferenceSolution* self = (CompareFeVariableAgainstReferenceSolution*) compareFeVariable;
+
+	AbstractContext*         context;
+
+	Dictionary*              dictionary;
+	char*                    referencePath;
+	char*                    integrationSwarmName;
+	
+	char*                    varName;
+	Dictionary_Entry_Value*  varList;
+
+	FeVariable*              feVarToTest;
+	Index                    var_I;
+	double                   tolerance;
+	Bool                     relativeErrorMeasure;
+
+	char*                    tmpName;
+
+	Stream*                  myStream;
+
+	context = (AbstractContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
+	self->context = context;
+	self->cf = cf;
+
+	EP_AppendClassHook( 
+			Context_GetEntryPoint( context, AbstractContext_EP_DumpClass ),
+			CompareFeVariableAgainstReferenceSolution_TestAll, 
+			self );
+
+	self->alwaysOutputErrors = Dictionary_GetBool_WithDefault( cf->rootDict, (Dictionary_Entry_Key)"alwaysOutputErrors", False  );
+
+	dictionary = Dictionary_GetDictionary( cf->rootDict, self->name );
+	Journal_Firewall(
+		dictionary != NULL,
+		Journal_MyStream( Error_Type, self ),
+		"In func %s - Specify FeVariables to compare in struct %s\n", __func__, self->name );
+
+	referencePath = Dictionary_GetString_WithDefault( dictionary, "referencePath", "./" );
+	Journal_Printf(
+		Journal_MyStream( Info_Type, self ),
+		"%s: Using reference path %s\n", self->name, referencePath );
+	if ( referencePath[ strlen(referencePath) ] == (int)'/' ) {
+		self->referencePath = StG_Strdup( referencePath );
+	} 
+	else {	
+		Stg_asprintf( &self->referencePath, "%s/", referencePath );
+	}
+	
+	integrationSwarmName = Dictionary_GetString_WithDefault( dictionary, "integrationSwarm", "gaussSwarm" );
+	Journal_Printf(
+		Journal_MyStream( Info_Type, self ),
+		"%s: Using integration swarm %s\n", self->name, integrationSwarmName );
+	self->integrationSwarm = Stg_ComponentFactory_ConstructByName( cf, (Name)integrationSwarmName, Swarm, True, data ); 
+
+	self->variables            = Stg_ObjectList_New();
+	self->tolerances           = Stg_ObjectList_New();
+	self->relativeErrorMeasure = Stg_ObjectList_New( );
+
+	varList = Dictionary_Get( dictionary, (Dictionary_Entry_Key)"variables" );
+	Journal_Firewall(
+		varList != NULL && Dictionary_Entry_Value_GetCount( varList  ) > 0,
+		Journal_MyStream( Error_Type, self ),
+		"In func %s - Specify FeVariables to compare in list \"variables\" for %s\n", __func__, self->name );
+
+	for ( var_I = 0; var_I < Dictionary_Entry_Value_GetCount( varList ); ++var_I ) {
+		varName = Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( varList, var_I ) );
+		feVarToTest = Stg_ComponentFactory_ConstructByName( cf, (Name)varName, FeVariable, True, data  );
+		Journal_Printf(
+			Journal_MyStream( Info_Type, self ),
+			"%s: Comparing FeVariable %s\n", self->name, varName );
+
+		tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"tolerance"  );
+		tolerance = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)tmpName, 0.005  );
+
+		tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"useRelativeErrorMeasure"  );
+		relativeErrorMeasure = Dictionary_GetBool_WithDefault( dictionary, (Dictionary_Entry_Key)tmpName, False  );
+		
+		Stg_ObjectList_Append( self->variables, feVarToTest );
+		Stg_ObjectList_Append( self->tolerances, Stg_PrimitiveObject_New_Double( tolerance, (Name)varName )  );
+		Stg_ObjectList_Append( self->relativeErrorMeasure, Stg_PrimitiveObject_New_Int( (relativeErrorMeasure)?1:0, (Name)varName )  );
+	}
+
+	/* Default is zero which means every time step */
+	self->timeStepToCompare = Dictionary_GetUnsignedInt_WithDefault( dictionary, "timeStepToCompare", 0 );
+	if ( self->timeStepToCompare == 0 ) {
+		Journal_Printf(
+			Journal_MyStream( Info_Type, self ),
+			"%s: timeStepToCompare is 0 - All time steps will be compared\n",
+			self->type );
+	}
+
+	self->referenceFeVariableSuffix = StG_Strdup( Dictionary_GetString_WithDefault( dictionary, "referenceFeVariableSuffix", 
+		"Reference" ) );
+		
+
+	myStream = Journal_MyStream( Info_Type, self );
+	Stg_asprintf( &tmpName, "%s.dat", self->name );
+        Stream_RedirectFile_WithPrependedPath( myStream, self->context->outputPath, tmpName );
+	Memory_Free( tmpName );
+}
+
+
+void* _CompareFeVariableAgainstReferenceSolution_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(CompareFeVariableAgainstReferenceSolution);
+	Type                                                      type = CompareFeVariableAgainstReferenceSolution_Type;
+	Stg_Class_DeleteFunction*                              _delete = _CompareFeVariableAgainstReferenceSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _CompareFeVariableAgainstReferenceSolution_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _CompareFeVariableAgainstReferenceSolution_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Codelet_New(  CODELET_PASSARGS  );
+}
+
+
+Index StgFEM_CompareFeVariableAgainstReferenceSolution_Register( PluginsManager* pluginsManager ) {
+	return PluginsManager_Submit( pluginsManager, CompareFeVariableAgainstReferenceSolution_Type, (Name)"0", _CompareFeVariableAgainstReferenceSolution_DefaultNew  );
+}
+
+
+void CompareFeVariableAgainstReferenceSolution_TestAll( void* compareFeVariable, void* data ) {
+	CompareFeVariableAgainstReferenceSolution* self = (CompareFeVariableAgainstReferenceSolution*) compareFeVariable;
+
+	FeVariable*     feVarToTest;
+	double          tolerance;
+	int             relativeErrorMeasure;
+
+	Index           var_I;
+
+	/* No need to test initial conditions */
+	if ( self->context->timeStep < 1 ) {
+		return;
+	}
+
+	if ( self->timeStepToCompare != 0 && self->context->timeStep != self->timeStepToCompare ) {
+		/* Only compare timesteps that has been selected iff timeStepToCompare is non-zero */
+		return;
+	}
+
+	for ( var_I = 0; var_I < self->variables->count; ++var_I ) {
+		feVarToTest = (FeVariable*)Stg_ObjectList_At( self->variables, var_I );
+		tolerance = ((Stg_PrimitiveObject*)Stg_ObjectList_At( self->tolerances, var_I ))->value.asDouble;
+		relativeErrorMeasure = ((Stg_PrimitiveObject*)Stg_ObjectList_At( self->relativeErrorMeasure, var_I ))->value.asInt;
+		CompareFeVariableAgainstReferenceSolution_TestVariable( self, feVarToTest, tolerance, relativeErrorMeasure ? True : False );
+	}
+}
+
+
+void CompareFeVariableAgainstReferenceSolution_TestVariable( void* compareFeVariable, FeVariable* feVarToTest, double tolerance, Bool relativeErrorMeasure ) {
+	CompareFeVariableAgainstReferenceSolution* self = (CompareFeVariableAgainstReferenceSolution*) compareFeVariable;
+	Variable_Register*       variable_Register;
+	Variable*                referenceDataVariable;
+	Variable*                roundedDataVariable;
+	char*                    referenceVariableName[9];
+	char*                    roundedVariableName[9];
+	Variable_Index           variable_I;
+	DofLayout*               referenceDofLayout;
+	DofLayout*               roundedDofLayout;
+	Node_DomainIndex         dNode_I;
+	Dof_Index                dofCountAtNode;
+	Dof_Index                dofCountAtPrevNode = 0;
+	Dof_Index                dof_I;
+	double*                  nodalValues = NULL;
+
+	FeVariable*              referenceFeVar;
+	OperatorFeVariable*      refMagnitudeField;
+	FeVariable*              roundedFeVar;
+	OperatorFeVariable*      errorField;
+	OperatorFeVariable*      errorMagnitudeField, *relativeErrorMagnitudeField;
+	OperatorFeVariable*      feVarOutput;
+
+	char*                    tmpName;
+	char*                    tmpName2;
+	char*                    filename;
+	Bool                     scalar;
+	Dof_Index                componentsCount;
+	/* TODO: hardcode for now - should be read in constructor, or read from the reference */
+	/* feVar type, or file reader or something */
+	unsigned int             numSigFigsInReferenceFeVar = 15;
+	char*                    refName = NULL;
+	double                   result;
+	
+	variable_Register = self->context->variable_Register;
+
+	componentsCount = feVarToTest->fieldComponentCount;
+	scalar = (componentsCount == 1) ? True : False;
+
+	/* Ok:- here, we know that the reference, or benchmark, FeVariable that we are
+	comparing against may have been rounded off already, and we don't want to give
+	a spurious error result just because the solution just calculated has accuracy
+	beyond what the rounded benchmark is giving. Thus, we truncate the result to the
+	level of the reference FeVariable */
+
+	/* Create a DataVariable for the Reference. This serves as the memory object is is linked to */
+	/* Likewise, for the rounded-off version of the "live" FeVar we are testing */
+	assert( Class_IsSuper( feVarToTest->feMesh->topo, IGraph ) );
+	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"Reference-DataVariable"  );
+	tmpName2 = Stg_Object_AppendSuffix( feVarToTest, (Name)"Rounded-DataVariable" );
+	if ( scalar == 1  ) {
+		referenceDataVariable = Variable_NewScalar( tmpName, self->context, Variable_DataType_Double, (Index*)&((IGraph*)feVarToTest->feMesh->topo)->remotes[MT_VERTEX]->nDomains, NULL, (void**)NULL, variable_Register  );
+		roundedDataVariable = Variable_NewScalar( tmpName2, self->context, Variable_DataType_Double, (Index*)&((IGraph*)feVarToTest->feMesh->topo)->remotes[MT_VERTEX]->nDomains, NULL, (void**)NULL, variable_Register  );
+	}
+	else {
+		Journal_Firewall( 
+			componentsCount <= 9,
+			Journal_MyStream( Error_Type, self ),
+			"In func %s - Cannot create a variable with more than 9 components (%s)\n",
+			__func__,
+			feVarToTest->name );
+		for ( variable_I = 0 ; variable_I < componentsCount; variable_I++ ) {
+			Stg_asprintf( 
+				&referenceVariableName[ variable_I ], 
+				"%s-Reference-ComponentVariable%d", 
+				feVarToTest->name, 
+				variable_I );
+			Stg_asprintf( 
+				&roundedVariableName[ variable_I ], 
+				"%s-Rounded-ComponentVariable%d", 
+				feVarToTest->name, 
+				variable_I );
+		}
+		referenceDataVariable = Variable_NewVector(
+				tmpName,
+				self->context,
+				Variable_DataType_Double,
+				componentsCount,
+				(Index*)(&((IGraph*)feVarToTest->feMesh->topo)->remotes[MT_VERTEX]->nDomains), 
+				NULL,
+				(void**)NULL,
+				variable_Register,
+				referenceVariableName[0],
+				referenceVariableName[1],
+				referenceVariableName[2],
+				referenceVariableName[3],
+				referenceVariableName[4],
+				referenceVariableName[5],
+				referenceVariableName[6],
+				referenceVariableName[7],
+				referenceVariableName[8] );
+
+		roundedDataVariable = Variable_NewVector(
+				tmpName2,
+				self->context,
+				Variable_DataType_Double,
+				componentsCount,
+				(Index*)(&((IGraph*)feVarToTest->feMesh->topo)->remotes[MT_VERTEX]->nDomains), 
+				NULL,
+				(void**)NULL,
+				variable_Register,
+				roundedVariableName[0],
+				roundedVariableName[1],
+				roundedVariableName[2],
+				roundedVariableName[3],
+				roundedVariableName[4],
+				roundedVariableName[5],
+				roundedVariableName[6],
+				roundedVariableName[7],
+				roundedVariableName[8] );
+	}
+	Memory_Free( tmpName );
+	Memory_Free( tmpName2 );
+	
+	referenceDataVariable->allocateSelf = True;
+	roundedDataVariable->allocateSelf = True;
+
+	Stg_Component_Build( referenceDataVariable, NULL, False );
+	Stg_Component_Initialise( referenceDataVariable, NULL, False );
+	Stg_Component_Build( roundedDataVariable, NULL, False );
+	Stg_Component_Initialise( roundedDataVariable, NULL, False );
+
+	/* Create Dof layout for this variable based on its own DataVariable */
+	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"Reference-DofLayout"  );
+	tmpName2 = Stg_Object_AppendSuffix( feVarToTest, (Name)"Rounded-DofLayout"  );
+	referenceDofLayout = DofLayout_New( tmpName, (DomainContext*)self->context, variable_Register, Mesh_GetDomainSize( feVarToTest->feMesh, MT_VERTEX ), NULL );
+	roundedDofLayout = DofLayout_New( tmpName2, (DomainContext*)self->context, variable_Register, Mesh_GetDomainSize( feVarToTest->feMesh, MT_VERTEX ), NULL );
+
+	if ( scalar ) {
+		DofLayout_AddAllFromVariableArray( referenceDofLayout, 1, &referenceDataVariable );
+		DofLayout_AddAllFromVariableArray( roundedDofLayout, 1, &roundedDataVariable );
+	}
+	else {
+		for ( variable_I = 0 ; variable_I < componentsCount ; variable_I++ ) {
+			/* Assign variable to each node */
+			for( dNode_I = 0; dNode_I < Mesh_GetDomainSize( feVarToTest->feMesh, MT_VERTEX ); dNode_I++ ) {
+				DofLayout_AddDof_ByVarName( referenceDofLayout, referenceVariableName[variable_I], dNode_I );
+				DofLayout_AddDof_ByVarName( roundedDofLayout, roundedVariableName[variable_I], dNode_I );
+			}
+			/* Free Name */
+			Memory_Free( referenceVariableName[ variable_I ] );
+			Memory_Free( roundedVariableName[ variable_I ] );
+		}
+	}
+	Memory_Free( tmpName );
+	Memory_Free( tmpName2 );
+	
+	Stg_Component_Build( referenceDofLayout, NULL, False );
+	Stg_Component_Initialise( referenceDofLayout, NULL, False );
+	Stg_Component_Build( roundedDofLayout, NULL, False );
+	Stg_Component_Initialise( roundedDofLayout, NULL, False );
+
+	if ( strlen( self->referenceFeVariableSuffix ) > 0 ) {
+		refName = Stg_Object_AppendSuffix( feVarToTest, (Name)self->referenceFeVariableSuffix  );
+	}
+	else {
+		/* refName = Stg_Object_AppendSuffix( feVarToTest, (Name)"Reference"  ); */
+		/* We actually need the referenceFeVar initially to be called the same as feVarToTest,
+		 * so it reads the correct values - PatrickSunter, 9 Jun 2007 */ 
+		refName = StG_Strdup( feVarToTest->name );
+	}
+
+	referenceFeVar = FeVariable_New_FromTemplate( 
+		refName, 
+		(DomainContext*)self->context,
+		feVarToTest,
+		referenceDofLayout, 
+		NULL, 
+		True,  /* isReference = True */
+		False, /* Don't set the "test every timestep var", since we re-create this guy each timestep anyway*/
+		feVarToTest->fieldVariable_Register );
+
+	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"Rounded"  );
+	roundedFeVar = FeVariable_New_FromTemplate( 
+		tmpName, 
+		(DomainContext*)self->context,
+		feVarToTest, 
+		roundedDofLayout, 
+		NULL, 
+		False,
+		False,
+		feVarToTest->fieldVariable_Register );
+
+	Memory_Free( tmpName );
+
+	Stg_Component_Build( referenceFeVar, self->context, False );
+	Stg_Component_Build( roundedFeVar, self->context, False );
+	/* Note we _don't_ pass in the context to the vars below to disable checkpoint-restart,
+	 * since we want manual control over loading these 2 */
+	Stg_Component_Initialise( referenceFeVar, NULL, False );
+	Stg_Component_Initialise( roundedFeVar, NULL, False );
+
+	filename = Memory_Alloc_Array_Unnamed( char, strlen(self->referencePath) + strlen(self->name) + 1 + 5 + 1 + 3 + 1 );
+#ifdef READ_HDF5
+		sprintf( filename, "%s/%s.%.5u.h5", self->referencePath, self->name, self->context->timeStep );
+#else
+		sprintf( filename, "%s/%s.%.5u.h5", self->referencePath, self->name, self->context->timeStep );
+#endif
+	FeVariable_ReadFromFile( referenceFeVar, filename );
+
+	/* Note this is a bit inelegant, but kind of necessary unless we rewrite the FeVariable
+	 * checkpointing-reading code again to be more general - see my comment above when
+	 * refName is allocated */
+	if ( 0 == strcmp( feVarToTest->name, referenceFeVar->name ) ) {
+		Memory_Free( referenceFeVar->name );
+		referenceFeVar->name = Stg_Object_AppendSuffix( feVarToTest, (Name)"Reference"  );
+	}
+	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"MagnitudeField"  );
+	refMagnitudeField = OperatorFeVariable_NewUnary( tmpName, (DomainContext*)self->context, referenceFeVar, "Magnitude" );
+	Memory_Free( tmpName );
+
+	/* now we need to round off the feVar we are testing, and copy the result to the roundedFeVar */
+	for( dNode_I = 0; dNode_I < Mesh_GetDomainSize( feVarToTest->feMesh, MT_VERTEX ); dNode_I++ ) {
+		dofCountAtNode = feVarToTest->dofLayout->dofCounts[dNode_I];
+		
+		if ( dofCountAtNode != dofCountAtPrevNode ) {
+			nodalValues = Memory_Realloc_Array( nodalValues, double, dofCountAtNode ); 
+		}
+		FeVariable_GetValueAtNode( feVarToTest, dNode_I, nodalValues );
+
+		for ( dof_I=0; dof_I < dofCountAtNode; dof_I++ ) {
+			nodalValues[dof_I] = StG_RoundDoubleToNSigFigs( nodalValues[dof_I], numSigFigsInReferenceFeVar );
+		}
+		FeVariable_SetValueAtNode( roundedFeVar, dNode_I, nodalValues );
+		dofCountAtPrevNode = dofCountAtNode;
+	}
+	Memory_Free( nodalValues );
+
+	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"ErrorField"  );
+	errorField = OperatorFeVariable_NewBinary( tmpName, (DomainContext*)self->context, roundedFeVar, referenceFeVar, "Subtraction" );
+	Memory_Free( tmpName );
+
+	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"ErrorMagnitudeField"  );
+	errorMagnitudeField = OperatorFeVariable_NewUnary( tmpName, (DomainContext*)self->context, errorField, "Magnitude" );
+	Memory_Free( tmpName );
+
+	tmpName = Stg_Object_AppendSuffix( feVarToTest, (Name)"RelativeErrorMagnitudeField"  );
+	relativeErrorMagnitudeField = OperatorFeVariable_NewBinary( tmpName, (DomainContext*)self->context, errorMagnitudeField, refMagnitudeField, "ScalarDivision" );
+	Memory_Free( tmpName );
+
+	/* Build and Initialise the newly-created OperatorFeVariables - else we can't use them */
+	Stg_Component_Build( errorField, self->context, False );
+	Stg_Component_Build( errorMagnitudeField, self->context, False );
+	Stg_Component_Build( refMagnitudeField, self->context, False );
+	Stg_Component_Build( relativeErrorMagnitudeField, self->context, False );
+	Stg_Component_Initialise( errorField, self->context, False );
+	Stg_Component_Initialise( errorMagnitudeField, self->context, False );
+	Stg_Component_Initialise( refMagnitudeField, self->context, False );
+	Stg_Component_Initialise( relativeErrorMagnitudeField, self->context, False );
+
+	/* If the relativeErrorMeasure flag was used, then change the calculations and output to be relative */
+	if( relativeErrorMeasure ) 
+		feVarOutput = relativeErrorMagnitudeField;
+	else
+		feVarOutput = errorMagnitudeField;
+
+        result = FeVariable_Integrate( feVarOutput, self->integrationSwarm );
+
+	Journal_Printf( 
+		Journal_MyStream( Info_Type, self ), 
+		"Timestep %u: Total integrated value of '%s' is %s a tolerance %.5g.\n",
+		self->context->timeStep, 
+		feVarOutput->name, 
+		result <= tolerance ? "within" : "outside", 
+		tolerance );
+
+	if ( ( result > tolerance ) || (True == self->alwaysOutputErrors) ) {
+		if( relativeErrorMeasure ) {
+			Journal_Printf( 
+				Journal_MyStream( Info_Type, self ), 
+				"\t(Integrated total relative error was %g)\n",
+				result );
+		}
+		else {
+			Journal_Printf( 
+				Journal_MyStream( Info_Type, self ), 
+				"\t(Integrated total absolute error was %g)\n",
+				result );
+		}
+	}	
+
+	/* TODO: The lines below were commented out. Why? This is actually a bad memory leak! PatrickSunter, 9 Jul 2007 */
+	/*
+	Stg_Class_Delete( referenceDataVariable );
+	Stg_Class_Delete( referenceDofLayout );
+	Stg_Class_Delete( referenceFeVar );
+	Stg_Class_Delete( roundedDataVariable );
+	Stg_Class_Delete( roundedDofLayout );
+	Stg_Class_Delete( roundedFeVar );
+	Stg_Class_Delete( errorField );
+	Stg_Class_Delete( errorMagnitudeField );
+	Stg_Class_Delete( relativeErrorMagnitudeField );
+	*/
+
+	Memory_Free( refName );
+}
+	
+void _CompareFeVariableAgainstReferenceSolution_Delete( void* compareFeVariable ) {
+	CompareFeVariableAgainstReferenceSolution* self = (CompareFeVariableAgainstReferenceSolution*) compareFeVariable;
+
+	Memory_Free( self->referencePath );
+	Memory_Free( self->referenceFeVariableSuffix );
+	Memory_Free( self->importFormatType );
+	Memory_Free( self->exportFormatType );
+}	
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/FeVariableImportExporters/FeVariable_ImportExport_ABAQUS/FeVariable_ImportExport_ABAQUS.c
--- a/plugins/FeVariableImportExporters/FeVariable_ImportExport_ABAQUS/FeVariable_ImportExport_ABAQUS.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FeVariable_ImportExport_ABAQUS.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-#include <string.h>
-
-const Type   StgFEM_FeVariable_ImportExport_ABAQUS_Type = "StgFEM_FeVariable_ImportExport_ABAQUS";
-Name  ABAQUS_ImportExportType = "ABAQUS";
-
-
-void FeVariable_ReadNodalValuesFromFile_ABAQUS( void* _feVariable, Name prefixStr, unsigned int timeStep ) {
-	FeVariable*        feVariable = (FeVariable*)_feVariable;
-	char*              filename;
-	Node_LocalIndex    lNode_I = 0;
-	Node_GlobalIndex   gNode_I = 0;
-	Node_GlobalIndex   gNodeCount_I = 0;
-	Dof_Index          dof_I;
-	Dof_Index          dofAtEachNodeCount;
-	FILE*              inputFile;
-	double             variableVal;
-	char               lineString[1000];
-	const unsigned int MAX_LINE_LENGTH = 1000;
-	Processor_Index    proc_I=0;
-	Dimension_Index    dim_I=0;
-	char*              matchString;
-	Index              currentFileLine = 0;
-	Coord              localGeometryMin;
-	Coord              localGeometryMax;
-	Stream*            debugStream = Journal_Register( Debug_Type, (Name)StgFEM_FeVariable_ImportExport_ABAQUS_Type  );
-	FeMesh*		mesh = feVariable->feMesh;
-	MPI_Comm	comm;
-	unsigned	rank, nProcs;
-	double		min[3], max[3];
-	unsigned	nDims;
-	
-	Journal_DPrintf( debugStream, "In %s(): for FeVariable \"%s\"\n", __func__, feVariable->name );
-	Stream_Indent( debugStream );
-
-	nDims = Mesh_GetDimSize( mesh );
-	comm = Comm_GetMPIComm( Mesh_GetCommTopology( mesh, MT_VERTEX ) );
-	MPI_Comm_rank( comm, (int*)&rank );
-	MPI_Comm_size( comm, (int*)&nProcs );
-	
-	/*                                                prefix            feVariable->name        . 00000 .  dat \0 */
-	filename = Memory_Alloc_Array_Unnamed( char, strlen(prefixStr) + strlen(feVariable->name) + 1 + 5 + 1 + 3 + 1 );
-	sprintf( filename, "%s%s.%.5u.rpt", prefixStr, feVariable->name, timeStep );
-
-	/* TODO May need/want to change to MPI file stuff */
-	
-	/* This loop used to stop 2 processors trying to open the file at the same time, which
-	  * seems to cause problems */
-	for ( proc_I = 0; proc_I < nProcs; proc_I++ ) {
-		MPI_Barrier( comm );
-		if ( proc_I == rank ) {	
-			inputFile = fopen( filename, "r" );
-		}
-	}
-
-	if ( NULL==inputFile ) {
-		Stream*    errorStr = Journal_Register( Error_Type, (Name)feVariable->type  );
-		Journal_Printf( errorStr, "Error- in %s(), for feVariable \"%s\": Couldn't find checkpoint file with "
-			"prefix \"%s\", timestep %d - thus full filename \"%s\" - aborting.\n", __func__, feVariable->name,
-			prefixStr, timeStep, filename );
-		exit(EXIT_FAILURE);	
-	}
-
-	/* This is where we skip over the ABAQUS header stuff */
-	while ( !feof(inputFile) ) {
-		currentFileLine++;
-		fgets( lineString, MAX_LINE_LENGTH, inputFile );
-		matchString = strstr( lineString, "            Node" );
-		if ( matchString != NULL ) {
-			/* Grab the "Label" and the "----" lines */ 
-			fgets( lineString, MAX_LINE_LENGTH, inputFile );
-			fgets( lineString, MAX_LINE_LENGTH, inputFile );
-			currentFileLine += 2;
-			/* Ok, now we're ready to start reading the actual field values */
-			break;
-		}
-	}	
-	Journal_DPrintf( debugStream, "Skipped %u lines of ABAQUS header info...\n", currentFileLine );
-
-	dofAtEachNodeCount = feVariable->fieldComponentCount;
-
-	/* Need to re-set the geometry here, in case we're loading from a checkpoint that had compression/squashing BCs,
-		and hence ended up with a smaller mesh than the original */
-	for ( dim_I = 0; dim_I < 3; dim_I++ ) {
-		localGeometryMin[dim_I] = HUGE_VAL;
-		localGeometryMax[dim_I] = -HUGE_VAL;
-	}
-
-	Journal_DPrintf( debugStream, "Processing Nodal Data...\n", currentFileLine );
-	Stream_Indent( debugStream );
-	/* Note: in ABAQUS, the number of lines of nodal values from hereon is always == the number of global nodes */
-	for ( gNodeCount_I = 0; gNodeCount_I < Mesh_GetGlobalSize( mesh, MT_VERTEX ); gNodeCount_I++ ) {
-		fscanf( inputFile, "%u ", &gNode_I );
-		/* Note: ABAQUS has same layout of global node indices as StgFEM, except it indexes starting from 1 - thus we
-		 * need to subtract 1 here */
-		gNode_I -= 1;
-		
-		if ( Mesh_GlobalToDomain( feVariable->feMesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
-			Journal_DPrintfL( debugStream, 3, "Found info for global node %u, local node %u:\n", gNode_I, lNode_I );
-			Stream_Indent( debugStream );
-
-			/* Note: until we have proper mesh geometry, topology etc checkpointing, we re-load the 
-			node co-ords from the feVariable file - and also update the geometry */
-			fscanf( inputFile, "%lg %lg ", Mesh_GetVertex( mesh, lNode_I ), 
-				Mesh_GetVertex( mesh, lNode_I ) + 1 );
-			if ( feVariable->fieldComponentCount == 3 ) {
-				fscanf( inputFile, "%lg", Mesh_GetVertex( mesh, lNode_I ) + 2 );
-			}
-
-			Journal_DPrintfL( debugStream, 3, "read coord (%.3f, %.3f, %.3f)\n", 
-					  Mesh_GetVertex( mesh, lNode_I )[0],
-					  Mesh_GetVertex( mesh, lNode_I )[1],
-					  (nDims == 3) ? Mesh_GetVertex( mesh, lNode_I )[2] : 0.0 );
-
-			for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
-				fscanf( inputFile, "%lg ", &variableVal );
-				DofLayout_SetValueDouble( feVariable->dofLayout, lNode_I, dof_I, variableVal );
-				Journal_DPrintfL( debugStream, 3, "read dof %u: %g\n", dof_I, variableVal ); 
-				/* TODO: Hack for now - ABAQUS only uses initial coords, so assume this is displacement and add */
-				Mesh_GetVertex( mesh, lNode_I )[dof_I] += variableVal;
-				Journal_DPrintfL( debugStream, 3, "TODO: using HACK assumption of disp.:- updating nodeCoord[%u] to %.3f\n",
-						  dof_I, Mesh_GetVertex( mesh, lNode_I )[dof_I] );
-			}
-
-			for ( dim_I = 0; dim_I < 3; dim_I++ ) {
-				if ( Mesh_GetVertex( mesh, lNode_I )[dim_I] < localGeometryMin[dim_I] ) {
-					localGeometryMin[dim_I] = Mesh_GetVertex( mesh, lNode_I )[dim_I];
-				}
-				else if ( Mesh_GetVertex( mesh, lNode_I )[dim_I] > localGeometryMax[dim_I] ) {
-					localGeometryMax[dim_I] = Mesh_GetVertex( mesh, lNode_I )[dim_I];
-				}
-			}
-			
-		}
-		else {
-			Journal_DPrintfL( debugStream, 3, "not on current proc -> skipping\n" );
-			fgets( lineString, MAX_LINE_LENGTH, inputFile );
-		}
-		Stream_UnIndent( debugStream );
-		currentFileLine++;
-	}			
-	fclose( inputFile );
-	Stream_UnIndent( debugStream );
-
-	/* Resync the mesh and update deformation members. */
-	Mesh_Sync( mesh );
-	Mesh_DeformationUpdate( mesh );
-
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	Journal_DPrintf( debugStream, "Recalculated global field min coord as (%.3f, %.3f, %.3f)\n",
-			 min[0], min[1], (nDims == 3) ? min[2] : 0.0 );
-	Journal_DPrintf( debugStream, "Recalculated global field max coord as (%.3f, %.3f, %.3f)\n",
-			 max[0], max[1], (nDims == 3) ? max[2] : 0.0 );
-
-	Stream_UnIndent( debugStream );
-}			
-
-
-void FeVariable_SaveNodalValuesToFile_ABAQUS( void* _feVariable, Name prefixStr, unsigned int timeStep ) {
-	FeVariable*      feVariable = (FeVariable*)_feVariable;
-	Stream*          errorStream = Journal_Register( Error_Type, (Name)StgFEM_FeVariable_ImportExport_ABAQUS_Type  );
-
-	Journal_Firewall( 0, errorStream, "Error - in %s(), for FeVariable \"%s\": function not implemented yet.\n",
-		__func__, feVariable->name );
-}
-
-
-void _StgFEM_FeVariable_ImportExport_ABAQUS_AssignFromXML( void* componment, Stg_ComponentFactory* cf, void* data ) {
-	AbstractContext* context;
-
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data );
-	
-}
-
-void* _StgFEM_FeVariable_ImportExport_ABAQUS_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof( Codelet );
-	Type                                                      type = StgFEM_FeVariable_ImportExport_ABAQUS_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_FeVariable_ImportExport_ABAQUS_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _StgFEM_FeVariable_ImportExport_ABAQUS_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Codelet_New(  CODELET_PASSARGS  );
-}
-   
-Index StgFEM_FeVariable_ImportExport_ABAQUS_Register( PluginsManager* pluginsManager  ) {
-	return PluginsManager_Submit( pluginsManager, StgFEM_FeVariable_ImportExport_ABAQUS_Type, (Name)"0", _StgFEM_FeVariable_ImportExport_ABAQUS_DefaultNew  );
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/FeVariableImportExporters/FeVariable_ImportExport_ABAQUS/FeVariable_ImportExport_ABAQUS.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/FeVariableImportExporters/FeVariable_ImportExport_ABAQUS/FeVariable_ImportExport_ABAQUS.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,246 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FeVariable_ImportExport_ABAQUS.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+#include <string.h>
+
+const Type   StgFEM_FeVariable_ImportExport_ABAQUS_Type = "StgFEM_FeVariable_ImportExport_ABAQUS";
+Name  ABAQUS_ImportExportType = "ABAQUS";
+
+
+void FeVariable_ReadNodalValuesFromFile_ABAQUS( void* _feVariable, Name prefixStr, unsigned int timeStep ) {
+	FeVariable*        feVariable = (FeVariable*)_feVariable;
+	char*              filename;
+	Node_LocalIndex    lNode_I = 0;
+	Node_GlobalIndex   gNode_I = 0;
+	Node_GlobalIndex   gNodeCount_I = 0;
+	Dof_Index          dof_I;
+	Dof_Index          dofAtEachNodeCount;
+	FILE*              inputFile;
+	double             variableVal;
+	char               lineString[1000];
+	const unsigned int MAX_LINE_LENGTH = 1000;
+	Processor_Index    proc_I=0;
+	Dimension_Index    dim_I=0;
+	char*              matchString;
+	Index              currentFileLine = 0;
+	Coord              localGeometryMin;
+	Coord              localGeometryMax;
+	Stream*            debugStream = Journal_Register( Debug_Type, (Name)StgFEM_FeVariable_ImportExport_ABAQUS_Type  );
+	FeMesh*		mesh = feVariable->feMesh;
+	MPI_Comm	comm;
+	unsigned	rank, nProcs;
+	double		min[3], max[3];
+	unsigned	nDims;
+	
+	Journal_DPrintf( debugStream, "In %s(): for FeVariable \"%s\"\n", __func__, feVariable->name );
+	Stream_Indent( debugStream );
+
+	nDims = Mesh_GetDimSize( mesh );
+	comm = Comm_GetMPIComm( Mesh_GetCommTopology( mesh, MT_VERTEX ) );
+	MPI_Comm_rank( comm, (int*)&rank );
+	MPI_Comm_size( comm, (int*)&nProcs );
+	
+	/*                                                prefix            feVariable->name        . 00000 .  dat \0 */
+	filename = Memory_Alloc_Array_Unnamed( char, strlen(prefixStr) + strlen(feVariable->name) + 1 + 5 + 1 + 3 + 1 );
+	sprintf( filename, "%s%s.%.5u.rpt", prefixStr, feVariable->name, timeStep );
+
+	/* TODO May need/want to change to MPI file stuff */
+	
+	/* This loop used to stop 2 processors trying to open the file at the same time, which
+	  * seems to cause problems */
+	for ( proc_I = 0; proc_I < nProcs; proc_I++ ) {
+		MPI_Barrier( comm );
+		if ( proc_I == rank ) {	
+			inputFile = fopen( filename, "r" );
+		}
+	}
+
+	if ( NULL==inputFile ) {
+		Stream*    errorStr = Journal_Register( Error_Type, (Name)feVariable->type  );
+		Journal_Printf( errorStr, "Error- in %s(), for feVariable \"%s\": Couldn't find checkpoint file with "
+			"prefix \"%s\", timestep %d - thus full filename \"%s\" - aborting.\n", __func__, feVariable->name,
+			prefixStr, timeStep, filename );
+		exit(EXIT_FAILURE);	
+	}
+
+	/* This is where we skip over the ABAQUS header stuff */
+	while ( !feof(inputFile) ) {
+		currentFileLine++;
+		fgets( lineString, MAX_LINE_LENGTH, inputFile );
+		matchString = strstr( lineString, "            Node" );
+		if ( matchString != NULL ) {
+			/* Grab the "Label" and the "----" lines */ 
+			fgets( lineString, MAX_LINE_LENGTH, inputFile );
+			fgets( lineString, MAX_LINE_LENGTH, inputFile );
+			currentFileLine += 2;
+			/* Ok, now we're ready to start reading the actual field values */
+			break;
+		}
+	}	
+	Journal_DPrintf( debugStream, "Skipped %u lines of ABAQUS header info...\n", currentFileLine );
+
+	dofAtEachNodeCount = feVariable->fieldComponentCount;
+
+	/* Need to re-set the geometry here, in case we're loading from a checkpoint that had compression/squashing BCs,
+		and hence ended up with a smaller mesh than the original */
+	for ( dim_I = 0; dim_I < 3; dim_I++ ) {
+		localGeometryMin[dim_I] = HUGE_VAL;
+		localGeometryMax[dim_I] = -HUGE_VAL;
+	}
+
+	Journal_DPrintf( debugStream, "Processing Nodal Data...\n", currentFileLine );
+	Stream_Indent( debugStream );
+	/* Note: in ABAQUS, the number of lines of nodal values from hereon is always == the number of global nodes */
+	for ( gNodeCount_I = 0; gNodeCount_I < Mesh_GetGlobalSize( mesh, MT_VERTEX ); gNodeCount_I++ ) {
+		fscanf( inputFile, "%u ", &gNode_I );
+		/* Note: ABAQUS has same layout of global node indices as StgFEM, except it indexes starting from 1 - thus we
+		 * need to subtract 1 here */
+		gNode_I -= 1;
+		
+		if ( Mesh_GlobalToDomain( feVariable->feMesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
+			Journal_DPrintfL( debugStream, 3, "Found info for global node %u, local node %u:\n", gNode_I, lNode_I );
+			Stream_Indent( debugStream );
+
+			/* Note: until we have proper mesh geometry, topology etc checkpointing, we re-load the 
+			node co-ords from the feVariable file - and also update the geometry */
+			fscanf( inputFile, "%lg %lg ", Mesh_GetVertex( mesh, lNode_I ), 
+				Mesh_GetVertex( mesh, lNode_I ) + 1 );
+			if ( feVariable->fieldComponentCount == 3 ) {
+				fscanf( inputFile, "%lg", Mesh_GetVertex( mesh, lNode_I ) + 2 );
+			}
+
+			Journal_DPrintfL( debugStream, 3, "read coord (%.3f, %.3f, %.3f)\n", 
+					  Mesh_GetVertex( mesh, lNode_I )[0],
+					  Mesh_GetVertex( mesh, lNode_I )[1],
+					  (nDims == 3) ? Mesh_GetVertex( mesh, lNode_I )[2] : 0.0 );
+
+			for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
+				fscanf( inputFile, "%lg ", &variableVal );
+				DofLayout_SetValueDouble( feVariable->dofLayout, lNode_I, dof_I, variableVal );
+				Journal_DPrintfL( debugStream, 3, "read dof %u: %g\n", dof_I, variableVal ); 
+				/* TODO: Hack for now - ABAQUS only uses initial coords, so assume this is displacement and add */
+				Mesh_GetVertex( mesh, lNode_I )[dof_I] += variableVal;
+				Journal_DPrintfL( debugStream, 3, "TODO: using HACK assumption of disp.:- updating nodeCoord[%u] to %.3f\n",
+						  dof_I, Mesh_GetVertex( mesh, lNode_I )[dof_I] );
+			}
+
+			for ( dim_I = 0; dim_I < 3; dim_I++ ) {
+				if ( Mesh_GetVertex( mesh, lNode_I )[dim_I] < localGeometryMin[dim_I] ) {
+					localGeometryMin[dim_I] = Mesh_GetVertex( mesh, lNode_I )[dim_I];
+				}
+				else if ( Mesh_GetVertex( mesh, lNode_I )[dim_I] > localGeometryMax[dim_I] ) {
+					localGeometryMax[dim_I] = Mesh_GetVertex( mesh, lNode_I )[dim_I];
+				}
+			}
+			
+		}
+		else {
+			Journal_DPrintfL( debugStream, 3, "not on current proc -> skipping\n" );
+			fgets( lineString, MAX_LINE_LENGTH, inputFile );
+		}
+		Stream_UnIndent( debugStream );
+		currentFileLine++;
+	}			
+	fclose( inputFile );
+	Stream_UnIndent( debugStream );
+
+	/* Resync the mesh and update deformation members. */
+	Mesh_Sync( mesh );
+	Mesh_DeformationUpdate( mesh );
+
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	Journal_DPrintf( debugStream, "Recalculated global field min coord as (%.3f, %.3f, %.3f)\n",
+			 min[0], min[1], (nDims == 3) ? min[2] : 0.0 );
+	Journal_DPrintf( debugStream, "Recalculated global field max coord as (%.3f, %.3f, %.3f)\n",
+			 max[0], max[1], (nDims == 3) ? max[2] : 0.0 );
+
+	Stream_UnIndent( debugStream );
+}			
+
+
+void FeVariable_SaveNodalValuesToFile_ABAQUS( void* _feVariable, Name prefixStr, unsigned int timeStep ) {
+	FeVariable*      feVariable = (FeVariable*)_feVariable;
+	Stream*          errorStream = Journal_Register( Error_Type, (Name)StgFEM_FeVariable_ImportExport_ABAQUS_Type  );
+
+	Journal_Firewall( 0, errorStream, "Error - in %s(), for FeVariable \"%s\": function not implemented yet.\n",
+		__func__, feVariable->name );
+}
+
+
+void _StgFEM_FeVariable_ImportExport_ABAQUS_AssignFromXML( void* componment, Stg_ComponentFactory* cf, void* data ) {
+	AbstractContext* context;
+
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data );
+	
+}
+
+void* _StgFEM_FeVariable_ImportExport_ABAQUS_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof( Codelet );
+	Type                                                      type = StgFEM_FeVariable_ImportExport_ABAQUS_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_FeVariable_ImportExport_ABAQUS_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _StgFEM_FeVariable_ImportExport_ABAQUS_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Codelet_New(  CODELET_PASSARGS  );
+}
+   
+Index StgFEM_FeVariable_ImportExport_ABAQUS_Register( PluginsManager* pluginsManager  ) {
+	return PluginsManager_Submit( pluginsManager, StgFEM_FeVariable_ImportExport_ABAQUS_Type, (Name)"0", _StgFEM_FeVariable_ImportExport_ABAQUS_DefaultNew  );
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/FeVariableImportExporters/FeVariable_ImportExport_SpecRidge2D/FeVariable_ImportExport_SpecRidge2D.c
--- a/plugins/FeVariableImportExporters/FeVariable_ImportExport_SpecRidge2D/FeVariable_ImportExport_SpecRidge2D.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FeVariable_ImportExport_SpecRidge2D.c 835 2007-05-16 02:54:29Z DaveLee $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-#include <string.h>
-
-const Type   StgFEM_FeVariable_ImportExport_SpecRidge2D_Type = "StgFEM_FeVariable_ImportExport_SpecRidge2D";
-Name  SpecRidge2D_ImportExportType = "SpecRidge2D";
-
-
-void FeVariable_ReadNodalValuesFromFile_SpecRidge2D( void* _feVariable, Name prefixStr, unsigned int timeStep ) {
-	FeVariable*        feVariable = (FeVariable*)_feVariable;
-	char*              filename;
-	Node_LocalIndex    lNode_I = 0;
-	Node_GlobalIndex   gNode_I = 0;
-	Dof_Index          dof_I;
-	Dof_Index          dofAtEachNodeCount;
-	FILE*              inputFile;
-	double             variableVal;
-	char               lineString[1000];
-	const unsigned int MAX_LINE_LENGTH = 1000;
-	Processor_Index    proc_I=0;
-	Dimension_Index    dim_I=0;
-	/* char*              matchString; */
-	Index              currentFileLine = 0;
-	Coord              localGeometryMin;
-	Coord              localGeometryMax;
-	Stream*            debugStream = Journal_Register( Debug_Type, (Name)StgFEM_FeVariable_ImportExport_SpecRidge2D_Type  );
-	FeMesh*		mesh = feVariable->feMesh;
-	MPI_Comm	comm;
-	unsigned	rank, nProcs;
-	double		min[3], max[3];
-	unsigned	nDims;
-
-	Journal_DPrintf( debugStream, "In %s(): for FeVariable \"%s\"\n", __func__, feVariable->name );
-	Stream_Indent( debugStream );
-
-	nDims = Mesh_GetDimSize( mesh );
-	comm = Comm_GetMPIComm( Mesh_GetCommTopology( mesh, MT_VERTEX ) );
-	MPI_Comm_rank( comm, (int*)&rank );
-	MPI_Comm_size( comm, (int*)&nProcs );
-
-	/*                                                prefix            feVariable->name        . 00000 .  dat \0 */
-	filename = Memory_Alloc_Array_Unnamed( char, strlen(prefixStr) + strlen(feVariable->name) + 1 + 5 + 1 + 3 + 1 );
-	sprintf( filename, "%s%s.%.5u.rpt", prefixStr, feVariable->name, timeStep );
-
-	/* TODO May need/want to change to MPI file stuff */
-	
-	/* This loop used to stop 2 processors trying to open the file at the same time, which
-	  * seems to cause problems */
-	for ( proc_I = 0; proc_I < nProcs; proc_I++ ) {
-		MPI_Barrier( comm );
-		if ( proc_I == rank ) {	
-			inputFile = fopen( filename, "r" );
-		}
-	}
-
-	if ( NULL == inputFile ) {
-		Stream*    errorStr = Journal_Register( Error_Type, (Name)feVariable->type  );
-		Journal_Printf( errorStr, "Error- in %s(), for feVariable \"%s\": Couldn't find checkpoint file with "
-			"prefix \"%s\", timestep %d - thus full filename \"%s\" - aborting.\n", __func__, feVariable->name,
-			prefixStr, timeStep, filename );
-		exit(EXIT_FAILURE);	
-	}
-
-	/* This is where we skip over the file header stuff */
-	/*while ( !feof(inputFile) ) {
-		currentFileLine++;
-		fgets( lineString, MAX_LINE_LENGTH, inputFile );
-		matchString = strstr( lineString, "            Node" );
-		if ( matchString != NULL ) {*/
-			/* Grab the "Label" and the "----" lines */ 
-			/*fgets( lineString, MAX_LINE_LENGTH, inputFile );
-			fgets( lineString, MAX_LINE_LENGTH, inputFile );
-			currentFileLine += 2;*/
-			/* Ok, now we're ready to start reading the actual field values */
-			/*break;
-		}
-	}	
-	Journal_DPrintf( debugStream, "Skipped %u lines of SpecRidge2D header info...\n", currentFileLine );
-*/
-	dofAtEachNodeCount = feVariable->fieldComponentCount;
-
-	/* Need to re-set the geometry here, in case we're loading from a checkpoint that had compression/squashing BCs,
-		and hence ended up with a smaller mesh than the original */
-	for ( dim_I = 0; dim_I < 3; dim_I++ ) {
-		localGeometryMin[dim_I] = HUGE_VAL;
-		localGeometryMax[dim_I] = -HUGE_VAL;
-	}
-
-	Journal_DPrintf( debugStream, "Processing Nodal Data...\n", currentFileLine );
-	Stream_Indent( debugStream );
-	/* TODO: add error checking to make sure number of lines in file == number of global nodes */
-	/* Note: in ABAQUS, the number of lines of nodal values from hereon is always == the number of global nodes */
-	for ( gNode_I = 0; gNode_I < Mesh_GetGlobalSize( mesh, MT_VERTEX ); gNode_I++ ) {
-		/*fscanf( inputFile, "%u ", &gNode_I );*/
-		/* Note: ABAQUS has same layout of global node indices as StgFEM, except it indexes starting from 1 - thus we
-		 * need to subtract 1 here */
-		/*gNode_I -= 1;*/
-		
-		if ( Mesh_GlobalToDomain( feVariable->feMesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
-			Journal_DPrintfL( debugStream, 3, "Found info for global node %u, local node %u:\n", gNode_I, lNode_I );
-			Stream_Indent( debugStream );
-
-			fscanf( inputFile, "%lg %lg ", Mesh_GetVertex( mesh, lNode_I ), 
-				Mesh_GetVertex( mesh, lNode_I ) + 1 );
-			if ( feVariable->fieldComponentCount == 3 ) {
-				fscanf( inputFile, "%lg", Mesh_GetVertex( mesh, lNode_I ) + 2 );
-			}
-		
-			Journal_DPrintfL( debugStream, 3, "read coord (%.3f, %.3f, %.3f)\n", 
-					  Mesh_GetVertex( mesh, lNode_I )[0],
-					  Mesh_GetVertex( mesh, lNode_I )[1],
-					  (nDims == 3) ? Mesh_GetVertex( mesh, lNode_I )[2] : 0.0 );
-			
-			for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
-				fscanf( inputFile, " %lg ", &variableVal );
-
-				DofLayout_SetValueDouble( feVariable->dofLayout, lNode_I, dof_I, variableVal );
-				Journal_DPrintfL( debugStream, 3, "read dof %u: %g\n", dof_I, variableVal ); 
-				/* TODO: Hack for now - ABAQUS only uses initial coords, so assume this is displacement and add */
-				/*Mesh_GetVertex( mesh, lNode_I )[dof_I] += variableVal;*/
-				/*Journal_DPrintfL( debugStream, 3, "TODO: using HACK assumption of disp.:- updating nodeCoord[%u] to %.3f\n",
-						  dof_I, Mesh_GetVertex( mesh, lNode_I )[dof_I] );*/
-				/*printf("value %d: %f  ", dof_I, variableVal);*/
-
-			}
-
-			for ( dim_I = 0; dim_I < 3; dim_I++ ) {
-				if ( Mesh_GetVertex( mesh, lNode_I )[dim_I] < localGeometryMin[dim_I] ) {
-					localGeometryMin[dim_I] = Mesh_GetVertex( mesh, lNode_I )[dim_I];
-				}
-				else if ( Mesh_GetVertex( mesh, lNode_I )[dim_I] > localGeometryMax[dim_I] ) {
-					localGeometryMax[dim_I] = Mesh_GetVertex( mesh, lNode_I )[dim_I];
-				}
-			}
-			
-		}
-		else {
-			Journal_DPrintfL( debugStream, 3, "not on current proc -> skipping\n" );
-			fgets( lineString, MAX_LINE_LENGTH, inputFile );
-		}
-		Stream_UnIndent( debugStream );
-		currentFileLine++;
-	}			
-	fclose( inputFile );
-	Stream_UnIndent( debugStream );
-
-	/* Resync the mesh and update deformation members. */
-	Mesh_Sync( mesh );
-	Mesh_DeformationUpdate( mesh );
-
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	Journal_DPrintf( debugStream, "Recalculated global field min coord as (%.3f, %.3f, %.3f)\n",
-			 min[0], min[1], (nDims == 3) ? min[2] : 0.0 );
-	Journal_DPrintf( debugStream, "Recalculated global field max coord as (%.3f, %.3f, %.3f)\n",
-			 max[0], max[1], (nDims == 3) ? max[2] : 0.0 );
-
-	Stream_UnIndent( debugStream );
-
-
-}			
-
-
-void FeVariable_SaveNodalValuesToFile_SpecRidge2D( void* _feVariable, Name prefixStr, unsigned int timeStep ) {
-	FeVariable*      feVariable = (FeVariable*)_feVariable;
-	Stream*          errorStream = Journal_Register( Error_Type, (Name)StgFEM_FeVariable_ImportExport_SpecRidge2D_Type  );
-
-	Journal_Firewall( 0, errorStream, "Error - in %s(), for FeVariable \"%s\": function not implemented yet.\n",
-		__func__, feVariable->name );
-}
-
-
-void _StgFEM_FeVariable_ImportExport_SpecRidge2D_AssignFromXML( void* componment, Stg_ComponentFactory* cf, void* data ) {
-	AbstractContext* context;
-
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data );
-	
-}
-
-void* _StgFEM_FeVariable_ImportExport_SpecRidge2D_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof( Codelet );
-	Type                                                      type = StgFEM_FeVariable_ImportExport_SpecRidge2D_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_FeVariable_ImportExport_SpecRidge2D_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _StgFEM_FeVariable_ImportExport_SpecRidge2D_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Codelet_New(  CODELET_PASSARGS  );
-}
-   
-Index StgFEM_FeVariable_ImportExport_SpecRidge2D_Register( PluginsManager* pluginsManager  ) {
-	return PluginsManager_Submit( pluginsManager, StgFEM_FeVariable_ImportExport_SpecRidge2D_Type, (Name)"0", _StgFEM_FeVariable_ImportExport_SpecRidge2D_DefaultNew  );
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/FeVariableImportExporters/FeVariable_ImportExport_SpecRidge2D/FeVariable_ImportExport_SpecRidge2D.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/FeVariableImportExporters/FeVariable_ImportExport_SpecRidge2D/FeVariable_ImportExport_SpecRidge2D.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,249 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FeVariable_ImportExport_SpecRidge2D.c 835 2007-05-16 02:54:29Z DaveLee $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+#include <string.h>
+
+const Type   StgFEM_FeVariable_ImportExport_SpecRidge2D_Type = "StgFEM_FeVariable_ImportExport_SpecRidge2D";
+Name  SpecRidge2D_ImportExportType = "SpecRidge2D";
+
+
+void FeVariable_ReadNodalValuesFromFile_SpecRidge2D( void* _feVariable, Name prefixStr, unsigned int timeStep ) {
+	FeVariable*        feVariable = (FeVariable*)_feVariable;
+	char*              filename;
+	Node_LocalIndex    lNode_I = 0;
+	Node_GlobalIndex   gNode_I = 0;
+	Dof_Index          dof_I;
+	Dof_Index          dofAtEachNodeCount;
+	FILE*              inputFile;
+	double             variableVal;
+	char               lineString[1000];
+	const unsigned int MAX_LINE_LENGTH = 1000;
+	Processor_Index    proc_I=0;
+	Dimension_Index    dim_I=0;
+	/* char*              matchString; */
+	Index              currentFileLine = 0;
+	Coord              localGeometryMin;
+	Coord              localGeometryMax;
+	Stream*            debugStream = Journal_Register( Debug_Type, (Name)StgFEM_FeVariable_ImportExport_SpecRidge2D_Type  );
+	FeMesh*		mesh = feVariable->feMesh;
+	MPI_Comm	comm;
+	unsigned	rank, nProcs;
+	double		min[3], max[3];
+	unsigned	nDims;
+
+	Journal_DPrintf( debugStream, "In %s(): for FeVariable \"%s\"\n", __func__, feVariable->name );
+	Stream_Indent( debugStream );
+
+	nDims = Mesh_GetDimSize( mesh );
+	comm = Comm_GetMPIComm( Mesh_GetCommTopology( mesh, MT_VERTEX ) );
+	MPI_Comm_rank( comm, (int*)&rank );
+	MPI_Comm_size( comm, (int*)&nProcs );
+
+	/*                                                prefix            feVariable->name        . 00000 .  dat \0 */
+	filename = Memory_Alloc_Array_Unnamed( char, strlen(prefixStr) + strlen(feVariable->name) + 1 + 5 + 1 + 3 + 1 );
+	sprintf( filename, "%s%s.%.5u.rpt", prefixStr, feVariable->name, timeStep );
+
+	/* TODO May need/want to change to MPI file stuff */
+	
+	/* This loop used to stop 2 processors trying to open the file at the same time, which
+	  * seems to cause problems */
+	for ( proc_I = 0; proc_I < nProcs; proc_I++ ) {
+		MPI_Barrier( comm );
+		if ( proc_I == rank ) {	
+			inputFile = fopen( filename, "r" );
+		}
+	}
+
+	if ( NULL == inputFile ) {
+		Stream*    errorStr = Journal_Register( Error_Type, (Name)feVariable->type  );
+		Journal_Printf( errorStr, "Error- in %s(), for feVariable \"%s\": Couldn't find checkpoint file with "
+			"prefix \"%s\", timestep %d - thus full filename \"%s\" - aborting.\n", __func__, feVariable->name,
+			prefixStr, timeStep, filename );
+		exit(EXIT_FAILURE);	
+	}
+
+	/* This is where we skip over the file header stuff */
+	/*while ( !feof(inputFile) ) {
+		currentFileLine++;
+		fgets( lineString, MAX_LINE_LENGTH, inputFile );
+		matchString = strstr( lineString, "            Node" );
+		if ( matchString != NULL ) {*/
+			/* Grab the "Label" and the "----" lines */ 
+			/*fgets( lineString, MAX_LINE_LENGTH, inputFile );
+			fgets( lineString, MAX_LINE_LENGTH, inputFile );
+			currentFileLine += 2;*/
+			/* Ok, now we're ready to start reading the actual field values */
+			/*break;
+		}
+	}	
+	Journal_DPrintf( debugStream, "Skipped %u lines of SpecRidge2D header info...\n", currentFileLine );
+*/
+	dofAtEachNodeCount = feVariable->fieldComponentCount;
+
+	/* Need to re-set the geometry here, in case we're loading from a checkpoint that had compression/squashing BCs,
+		and hence ended up with a smaller mesh than the original */
+	for ( dim_I = 0; dim_I < 3; dim_I++ ) {
+		localGeometryMin[dim_I] = HUGE_VAL;
+		localGeometryMax[dim_I] = -HUGE_VAL;
+	}
+
+	Journal_DPrintf( debugStream, "Processing Nodal Data...\n", currentFileLine );
+	Stream_Indent( debugStream );
+	/* TODO: add error checking to make sure number of lines in file == number of global nodes */
+	/* Note: in ABAQUS, the number of lines of nodal values from hereon is always == the number of global nodes */
+	for ( gNode_I = 0; gNode_I < Mesh_GetGlobalSize( mesh, MT_VERTEX ); gNode_I++ ) {
+		/*fscanf( inputFile, "%u ", &gNode_I );*/
+		/* Note: ABAQUS has same layout of global node indices as StgFEM, except it indexes starting from 1 - thus we
+		 * need to subtract 1 here */
+		/*gNode_I -= 1;*/
+		
+		if ( Mesh_GlobalToDomain( feVariable->feMesh, MT_VERTEX, gNode_I, &lNode_I ) ) {
+			Journal_DPrintfL( debugStream, 3, "Found info for global node %u, local node %u:\n", gNode_I, lNode_I );
+			Stream_Indent( debugStream );
+
+			fscanf( inputFile, "%lg %lg ", Mesh_GetVertex( mesh, lNode_I ), 
+				Mesh_GetVertex( mesh, lNode_I ) + 1 );
+			if ( feVariable->fieldComponentCount == 3 ) {
+				fscanf( inputFile, "%lg", Mesh_GetVertex( mesh, lNode_I ) + 2 );
+			}
+		
+			Journal_DPrintfL( debugStream, 3, "read coord (%.3f, %.3f, %.3f)\n", 
+					  Mesh_GetVertex( mesh, lNode_I )[0],
+					  Mesh_GetVertex( mesh, lNode_I )[1],
+					  (nDims == 3) ? Mesh_GetVertex( mesh, lNode_I )[2] : 0.0 );
+			
+			for ( dof_I = 0; dof_I < dofAtEachNodeCount; dof_I++ ) {
+				fscanf( inputFile, " %lg ", &variableVal );
+
+				DofLayout_SetValueDouble( feVariable->dofLayout, lNode_I, dof_I, variableVal );
+				Journal_DPrintfL( debugStream, 3, "read dof %u: %g\n", dof_I, variableVal ); 
+				/* TODO: Hack for now - ABAQUS only uses initial coords, so assume this is displacement and add */
+				/*Mesh_GetVertex( mesh, lNode_I )[dof_I] += variableVal;*/
+				/*Journal_DPrintfL( debugStream, 3, "TODO: using HACK assumption of disp.:- updating nodeCoord[%u] to %.3f\n",
+						  dof_I, Mesh_GetVertex( mesh, lNode_I )[dof_I] );*/
+				/*printf("value %d: %f  ", dof_I, variableVal);*/
+
+			}
+
+			for ( dim_I = 0; dim_I < 3; dim_I++ ) {
+				if ( Mesh_GetVertex( mesh, lNode_I )[dim_I] < localGeometryMin[dim_I] ) {
+					localGeometryMin[dim_I] = Mesh_GetVertex( mesh, lNode_I )[dim_I];
+				}
+				else if ( Mesh_GetVertex( mesh, lNode_I )[dim_I] > localGeometryMax[dim_I] ) {
+					localGeometryMax[dim_I] = Mesh_GetVertex( mesh, lNode_I )[dim_I];
+				}
+			}
+			
+		}
+		else {
+			Journal_DPrintfL( debugStream, 3, "not on current proc -> skipping\n" );
+			fgets( lineString, MAX_LINE_LENGTH, inputFile );
+		}
+		Stream_UnIndent( debugStream );
+		currentFileLine++;
+	}			
+	fclose( inputFile );
+	Stream_UnIndent( debugStream );
+
+	/* Resync the mesh and update deformation members. */
+	Mesh_Sync( mesh );
+	Mesh_DeformationUpdate( mesh );
+
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	Journal_DPrintf( debugStream, "Recalculated global field min coord as (%.3f, %.3f, %.3f)\n",
+			 min[0], min[1], (nDims == 3) ? min[2] : 0.0 );
+	Journal_DPrintf( debugStream, "Recalculated global field max coord as (%.3f, %.3f, %.3f)\n",
+			 max[0], max[1], (nDims == 3) ? max[2] : 0.0 );
+
+	Stream_UnIndent( debugStream );
+
+
+}			
+
+
+void FeVariable_SaveNodalValuesToFile_SpecRidge2D( void* _feVariable, Name prefixStr, unsigned int timeStep ) {
+	FeVariable*      feVariable = (FeVariable*)_feVariable;
+	Stream*          errorStream = Journal_Register( Error_Type, (Name)StgFEM_FeVariable_ImportExport_SpecRidge2D_Type  );
+
+	Journal_Firewall( 0, errorStream, "Error - in %s(), for FeVariable \"%s\": function not implemented yet.\n",
+		__func__, feVariable->name );
+}
+
+
+void _StgFEM_FeVariable_ImportExport_SpecRidge2D_AssignFromXML( void* componment, Stg_ComponentFactory* cf, void* data ) {
+	AbstractContext* context;
+
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data );
+	
+}
+
+void* _StgFEM_FeVariable_ImportExport_SpecRidge2D_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof( Codelet );
+	Type                                                      type = StgFEM_FeVariable_ImportExport_SpecRidge2D_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_FeVariable_ImportExport_SpecRidge2D_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _StgFEM_FeVariable_ImportExport_SpecRidge2D_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Codelet_New(  CODELET_PASSARGS  );
+}
+   
+Index StgFEM_FeVariable_ImportExport_SpecRidge2D_Register( PluginsManager* pluginsManager  ) {
+	return PluginsManager_Submit( pluginsManager, StgFEM_FeVariable_ImportExport_SpecRidge2D_Type, (Name)"0", _StgFEM_FeVariable_ImportExport_SpecRidge2D_DefaultNew  );
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/FileAnalyticSolution/FileAnalyticSolution.c
--- a/plugins/FileAnalyticSolution/FileAnalyticSolution.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FileAnalyticSolution.c 989 2007-12-18 13:57:56Z JulianGiordani $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-/* This is taken from Mirko Velic's Analytic Stokes Flow solution */
-
-const Type FileAnalyticSolution_Type = "FileAnalyticSolution";
-
-typedef struct { 
-	__AnalyticSolution 
-	char* referencePath;
-} FileAnalyticSolution;
-
-void FileAnalyticSolution_DummyFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* value ) {
-	abort();
-}
-
-
-
-void _FileAnalyticSolution_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
-	FileAnalyticSolution *   self = (FileAnalyticSolution*)analyticSolution;
-	Dictionary_Entry_Value*  varList;
-	Index                    var_I;
-	char*                    varName;
-	FeVariable*              feVarToTest;
-
-	_AnalyticSolution_AssignFromXML( self, cf, data );
-	varList = Dictionary_Get( cf->rootDict, (Dictionary_Entry_Key)self->name  );
-	Journal_Firewall( varList != NULL, Journal_Register( Error_Type, (Name)self->type  ), 
-		"Error- in %s(): Can't find list in XML '%s'\n", __func__, self->name );
-
-	for ( var_I = 0; var_I < Dictionary_Entry_Value_GetCount( varList ); ++var_I ) {
-		varName = Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( varList, var_I ) );
-		feVarToTest = Stg_ComponentFactory_ConstructByName( cf, (Name)varName, FeVariable, True, data  );
-	
-		AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, feVarToTest, FileAnalyticSolution_DummyFunction );
-	}
-
-
-	/* Get reference path */
-	self->referencePath = Dictionary_GetString_WithDefault( cf->rootDict, "referencePath", "./expected/" );
-}
-
-void _FileAnalyticSolution_Initialise( void* analyticSolution, void* data ) {
-	FileAnalyticSolution *self = (FileAnalyticSolution*)analyticSolution;
-	FeVariable*           analyticFeVariable;
-	Index                 analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
-	Index                 analyticFeVariable_I;
-
-
-	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
-
-	/* Assign values to all analytic fields */
-	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
-		Stg_Component_Initialise( Stg_ObjectList_At( self->feVariableList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Initialise( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Initialise( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
-		Stg_Component_Initialise( Stg_ObjectList_At( self->relativeErrorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
-
-		/* Initialise values from file */
-		analyticFeVariable = (FeVariable*) Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I );
-		FeVariable_ReadFromFile( analyticFeVariable, self->referencePath, 0 );
-	}
-}
-
-void* _FileAnalyticSolution_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(FileAnalyticSolution);
-	Type                                                      type = FileAnalyticSolution_Type;
-	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
-	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
-	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _FileAnalyticSolution_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _FileAnalyticSolution_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _AnalyticSolution_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _FileAnalyticSolution_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
-}
-
-/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
-Index StgFEM_FileAnalyticSolution_Register( PluginsManager* pluginsManager ) {
-	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
-	return PluginsManager_Submit( pluginsManager, FileAnalyticSolution_Type, (Name)"0", _FileAnalyticSolution_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/FileAnalyticSolution/FileAnalyticSolution.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/FileAnalyticSolution/FileAnalyticSolution.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,133 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FileAnalyticSolution.c 989 2007-12-18 13:57:56Z JulianGiordani $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+/* This is taken from Mirko Velic's Analytic Stokes Flow solution */
+
+const Type FileAnalyticSolution_Type = "FileAnalyticSolution";
+
+typedef struct { 
+	__AnalyticSolution 
+	char* referencePath;
+} FileAnalyticSolution;
+
+void FileAnalyticSolution_DummyFunction( void* analyticSolution, FeVariable* analyticFeVariable, double* coord, double* value ) {
+	abort();
+}
+
+
+
+void _FileAnalyticSolution_AssignFromXML( void* analyticSolution, Stg_ComponentFactory* cf, void* data ) {
+	FileAnalyticSolution *   self = (FileAnalyticSolution*)analyticSolution;
+	Dictionary_Entry_Value*  varList;
+	Index                    var_I;
+	char*                    varName;
+	FeVariable*              feVarToTest;
+
+	_AnalyticSolution_AssignFromXML( self, cf, data );
+	varList = Dictionary_Get( cf->rootDict, (Dictionary_Entry_Key)self->name  );
+	Journal_Firewall( varList != NULL, Journal_Register( Error_Type, (Name)self->type  ), 
+		"Error- in %s(): Can't find list in XML '%s'\n", __func__, self->name );
+
+	for ( var_I = 0; var_I < Dictionary_Entry_Value_GetCount( varList ); ++var_I ) {
+		varName = Dictionary_Entry_Value_AsString( Dictionary_Entry_Value_GetElement( varList, var_I ) );
+		feVarToTest = Stg_ComponentFactory_ConstructByName( cf, (Name)varName, FeVariable, True, data  );
+	
+		AnalyticSolution_RegisterFeVariableWithAnalyticFunction( self, feVarToTest, FileAnalyticSolution_DummyFunction );
+	}
+
+
+	/* Get reference path */
+	self->referencePath = Dictionary_GetString_WithDefault( cf->rootDict, "referencePath", "./expected/" );
+}
+
+void _FileAnalyticSolution_Initialise( void* analyticSolution, void* data ) {
+	FileAnalyticSolution *self = (FileAnalyticSolution*)analyticSolution;
+	FeVariable*           analyticFeVariable;
+	Index                 analyticFeVariableCount = Stg_ObjectList_Count( self->analyticFeVariableList );
+	Index                 analyticFeVariable_I;
+
+
+	assert( analyticFeVariableCount == Stg_ObjectList_Count( self->analyticFeVariableFuncList ) );
+
+	/* Assign values to all analytic fields */
+	for ( analyticFeVariable_I = 0 ; analyticFeVariable_I < analyticFeVariableCount ; analyticFeVariable_I++ ) {
+		Stg_Component_Initialise( Stg_ObjectList_At( self->feVariableList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Initialise( Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Initialise( Stg_ObjectList_At( self->errorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
+		Stg_Component_Initialise( Stg_ObjectList_At( self->relativeErrorMagnitudeFieldList, analyticFeVariable_I ), data, False ) ;
+
+		/* Initialise values from file */
+		analyticFeVariable = (FeVariable*) Stg_ObjectList_At( self->analyticFeVariableList, analyticFeVariable_I );
+		FeVariable_ReadFromFile( analyticFeVariable, self->referencePath, 0 );
+	}
+}
+
+void* _FileAnalyticSolution_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(FileAnalyticSolution);
+	Type                                                      type = FileAnalyticSolution_Type;
+	Stg_Class_DeleteFunction*                              _delete = _AnalyticSolution_Delete;
+	Stg_Class_PrintFunction*                                _print = _AnalyticSolution_Print;
+	Stg_Class_CopyFunction*                                  _copy = _AnalyticSolution_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _FileAnalyticSolution_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _FileAnalyticSolution_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _AnalyticSolution_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _FileAnalyticSolution_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _AnalyticSolution_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _AnalyticSolution_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return (void*) _AnalyticSolution_New(  ANALYTICSOLUTION_PASSARGS  );
+}
+
+/* This function is automatically run by StGermain when this plugin is loaded. The name must be "<plugin-name>_Register". */
+Index StgFEM_FileAnalyticSolution_Register( PluginsManager* pluginsManager ) {
+	/* A plugin is only properly registered once it returns the handle provided when submitting a codelet to StGermain. */
+	return PluginsManager_Submit( pluginsManager, FileAnalyticSolution_Type, (Name)"0", _FileAnalyticSolution_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Multigrid/Multigrid.c
--- a/plugins/Multigrid/Multigrid.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd,
-** 110 Victoria Street, Melbourne, 3053, Australia.
-**
-** Authors:
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Multigrid.c 2192 2004-10-15 02:45:38Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <mpi.h>
-#include <petsc.h>
-#include <petscvec.h>
-#include <petscmat.h>
-#include <petscksp.h>
-#include <petscsnes.h>
-
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-
-#include "Multigrid.h"
-
-
-const Type StgFEM_Multigrid_Type = "StgFEM_Multigrid";
-StgFEM_Multigrid* StgFEM_Multigrid_selfPointer = NULL;
-
-
-void StgFEM_Multigrid_SolverSetup( void* _solver, void* _stokesSLE ) {
-    StgFEM_Multigrid* self = StgFEM_Multigrid_selfPointer;
-    Stokes_SLE_UzawaSolver* solver = (Stokes_SLE_UzawaSolver*)_solver;
-    Stokes_SLE* sle = (Stokes_SLE*)_stokesSLE;
-	
-    Journal_DPrintf( solver->debug, "In %s:\n", __func__ );
-    Stream_IndentBranch( StgFEM_Debug );
-
-    Journal_DPrintfL( solver->debug, 1, "Setting up MatrixSolver for the velocity eqn.\n" );
-    self->mgSolver->mgData->matrixChanged = True;
-    //MatrixSolver_SetMatrix( self->velSolver, sle->kStiffMat->matrix );
-    //KSPSetOperators( self->velSolver, ((PETScMatrix*)sle->kStiffMat->matrix)->petscMat, 
-    //		((PETScMatrix*)sle->kStiffMat->matrix)->petscMat, DIFFERENT_NONZERO_PATTERN );
-
-    self->mgSolver->mgData->matrix = sle->kStiffMat->matrix;
-    PETScMGSolver_Setup( self->mgSolver, NULL, NULL );
-    solver->velSolver = self->mgSolver->mgData->ksp;
-    KSPSetOperators( solver->velSolver, sle->kStiffMat->matrix, sle->kStiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
-/*
-  KSPSetOperators( solver->velSolver, sle->kStiffMat->matrix, sle->kStiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
-  KSPSetFromOptions( solver->velSolver );
-*/
-
-    if( solver->pcSolver ) {
-        Journal_DPrintfL( solver->debug, 1, "Setting up MatrixSolver for the Preconditioner.\n" );
-        //MatrixSolver_SetMatrix( self->pcSolver, self->preconditioner->matrix );
-        //KSPSetOperators( self->pcSolver, ((PETScMatrix*)self->preconditioner->matrix)->petscMat, 
-        //		((PETScMatrix*)self->preconditioner->matrix)->petscMat, DIFFERENT_NONZERO_PATTERN );
-        KSPSetOperators( solver->pcSolver, solver->preconditioner->matrix, solver->preconditioner->matrix, DIFFERENT_NONZERO_PATTERN );
-        KSPSetFromOptions( solver->pcSolver );
-    }
-
-    Stream_UnIndentBranch( StgFEM_Debug );
-}
-
-
-void StgFEM_Multigrid_AssignFromXML( void* _self, Stg_ComponentFactory* cf, void* data ) {
-    StgFEM_Multigrid* self = (StgFEM_Multigrid*)_self;
-
-    StgFEM_Multigrid_selfPointer = self;
-
-    self->sle = Stg_ComponentFactory_ConstructByName( cf, (Name)"stokesEqn", Stokes_SLE, True, data  );
-    self->mgSolver = Stg_ComponentFactory_ConstructByName( cf, (Name)"mgSolver", PETScMGSolver, True, data  );
-
-    /* Replace the setup routine... hacky. */
-    self->sle->solver->_solverSetup = StgFEM_Multigrid_SolverSetup;   
-   
-}
-
-void StgFEM_Multigrid_Build( void* _self, void* data ) {
-    StgFEM_Multigrid* self = (StgFEM_Multigrid*)_self;
-
-    Stg_Component_Build( self->mgSolver, data, False );
-    Stg_Component_Build( self->sle, data, False );
-}
-
-void StgFEM_Multigrid_Initialise( void* _self, void* data ) {
-    StgFEM_Multigrid* self = (StgFEM_Multigrid*)_self;
-
-    Stg_Component_Initialise( self->mgSolver, data, False );
-    Stg_Component_Initialise( self->sle, data, False );
-
-    /* Setup the MG solver. */
-    PETScMGSolver_SetComm( self->mgSolver, MPI_COMM_WORLD );
-}
-
-void* StgFEM_Multigrid_New( Name name ) {
-    /* Variables set in this function */
-    SizeT                                              _sizeOfSelf = sizeof(StgFEM_Multigrid);
-    Type                                                      type = StgFEM_Multigrid_Type;
-    Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-    Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-    Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-    Stg_Component_DefaultConstructorFunction*  _defaultConstructor = StgFEM_Multigrid_New;
-    Stg_Component_ConstructFunction*                    _construct = StgFEM_Multigrid_AssignFromXML;
-    Stg_Component_BuildFunction*                            _build = StgFEM_Multigrid_Build;
-    Stg_Component_InitialiseFunction*                  _initialise = StgFEM_Multigrid_Initialise;
-    Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-    Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-    /* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-    AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-    return _Codelet_New(  CODELET_PASSARGS  );
-}
-
-Index StgFEM_Multigrid_Register( PluginsManager* mgr ) {
-    return PluginsManager_Submit( mgr, StgFEM_Multigrid_Type, (Name)"0", StgFEM_Multigrid_New  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Multigrid/Multigrid.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Multigrid/Multigrid.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,143 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003, Victorian Partnership for Advanced Computing (VPAC) Ltd,
+** 110 Victoria Street, Melbourne, 3053, Australia.
+**
+** Authors:
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Siew-Ching Tan, Software Engineer, VPAC. (siew at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Multigrid.c 2192 2004-10-15 02:45:38Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <mpi.h>
+#include <petsc.h>
+#include <petscvec.h>
+#include <petscmat.h>
+#include <petscksp.h>
+#include <petscsnes.h>
+
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+
+#include "Multigrid.h"
+
+
+const Type StgFEM_Multigrid_Type = "StgFEM_Multigrid";
+StgFEM_Multigrid* StgFEM_Multigrid_selfPointer = NULL;
+
+
+void StgFEM_Multigrid_SolverSetup( void* _solver, void* _stokesSLE ) {
+    StgFEM_Multigrid* self = StgFEM_Multigrid_selfPointer;
+    Stokes_SLE_UzawaSolver* solver = (Stokes_SLE_UzawaSolver*)_solver;
+    Stokes_SLE* sle = (Stokes_SLE*)_stokesSLE;
+	
+    Journal_DPrintf( solver->debug, "In %s:\n", __func__ );
+    Stream_IndentBranch( StgFEM_Debug );
+
+    Journal_DPrintfL( solver->debug, 1, "Setting up MatrixSolver for the velocity eqn.\n" );
+    self->mgSolver->mgData->matrixChanged = True;
+    //MatrixSolver_SetMatrix( self->velSolver, sle->kStiffMat->matrix );
+    //KSPSetOperators( self->velSolver, ((PETScMatrix*)sle->kStiffMat->matrix)->petscMat, 
+    //		((PETScMatrix*)sle->kStiffMat->matrix)->petscMat, DIFFERENT_NONZERO_PATTERN );
+
+    self->mgSolver->mgData->matrix = sle->kStiffMat->matrix;
+    PETScMGSolver_Setup( self->mgSolver, NULL, NULL );
+    solver->velSolver = self->mgSolver->mgData->ksp;
+    KSPSetOperators( solver->velSolver, sle->kStiffMat->matrix, sle->kStiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
+/*
+  KSPSetOperators( solver->velSolver, sle->kStiffMat->matrix, sle->kStiffMat->matrix, DIFFERENT_NONZERO_PATTERN );
+  KSPSetFromOptions( solver->velSolver );
+*/
+
+    if( solver->pcSolver ) {
+        Journal_DPrintfL( solver->debug, 1, "Setting up MatrixSolver for the Preconditioner.\n" );
+        //MatrixSolver_SetMatrix( self->pcSolver, self->preconditioner->matrix );
+        //KSPSetOperators( self->pcSolver, ((PETScMatrix*)self->preconditioner->matrix)->petscMat, 
+        //		((PETScMatrix*)self->preconditioner->matrix)->petscMat, DIFFERENT_NONZERO_PATTERN );
+        KSPSetOperators( solver->pcSolver, solver->preconditioner->matrix, solver->preconditioner->matrix, DIFFERENT_NONZERO_PATTERN );
+        KSPSetFromOptions( solver->pcSolver );
+    }
+
+    Stream_UnIndentBranch( StgFEM_Debug );
+}
+
+
+void StgFEM_Multigrid_AssignFromXML( void* _self, Stg_ComponentFactory* cf, void* data ) {
+    StgFEM_Multigrid* self = (StgFEM_Multigrid*)_self;
+
+    StgFEM_Multigrid_selfPointer = self;
+
+    self->sle = Stg_ComponentFactory_ConstructByName( cf, (Name)"stokesEqn", Stokes_SLE, True, data  );
+    self->mgSolver = Stg_ComponentFactory_ConstructByName( cf, (Name)"mgSolver", PETScMGSolver, True, data  );
+
+    /* Replace the setup routine... hacky. */
+    self->sle->solver->_solverSetup = StgFEM_Multigrid_SolverSetup;   
+   
+}
+
+void StgFEM_Multigrid_Build( void* _self, void* data ) {
+    StgFEM_Multigrid* self = (StgFEM_Multigrid*)_self;
+
+    Stg_Component_Build( self->mgSolver, data, False );
+    Stg_Component_Build( self->sle, data, False );
+}
+
+void StgFEM_Multigrid_Initialise( void* _self, void* data ) {
+    StgFEM_Multigrid* self = (StgFEM_Multigrid*)_self;
+
+    Stg_Component_Initialise( self->mgSolver, data, False );
+    Stg_Component_Initialise( self->sle, data, False );
+
+    /* Setup the MG solver. */
+    PETScMGSolver_SetComm( self->mgSolver, MPI_COMM_WORLD );
+}
+
+void* StgFEM_Multigrid_New( Name name ) {
+    /* Variables set in this function */
+    SizeT                                              _sizeOfSelf = sizeof(StgFEM_Multigrid);
+    Type                                                      type = StgFEM_Multigrid_Type;
+    Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+    Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+    Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+    Stg_Component_DefaultConstructorFunction*  _defaultConstructor = StgFEM_Multigrid_New;
+    Stg_Component_ConstructFunction*                    _construct = StgFEM_Multigrid_AssignFromXML;
+    Stg_Component_BuildFunction*                            _build = StgFEM_Multigrid_Build;
+    Stg_Component_InitialiseFunction*                  _initialise = StgFEM_Multigrid_Initialise;
+    Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+    Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+    /* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+    AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+    return _Codelet_New(  CODELET_PASSARGS  );
+}
+
+Index StgFEM_Multigrid_Register( PluginsManager* mgr ) {
+    return PluginsManager_Submit( mgr, StgFEM_Multigrid_Type, (Name)"0", StgFEM_Multigrid_New  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/CPUTime/CPUTime.c
--- a/plugins/Output/CPUTime/CPUTime.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: CPUTime.c 1107 2008-04-16 01:54:15Z BelindaMay $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/FrequentOutput/FrequentOutput.h>
-
-#include "CPUTime.h"
-  
-const Type StgFEM_CPUTime_Type = "StgFEM_CPUTime";
-
-void StgFEM_CPUTime_PrintTimeInfo( AbstractContext* context ) {
-	StgFEM_CPUTime* self = (StgFEM_CPUTime*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_CPUTime_Type  );
-
-	/* Print Current Time Taken */
-	StgFEM_FrequentOutput_PrintValue( context, MPI_Wtime() - self->initialTime );
-}
-
-void _StgFEM_CPUTime_AssignFromXML( void* componment, Stg_ComponentFactory* cf, void* data ) {
-	StgFEM_CPUTime* self 		= (StgFEM_CPUTime*)componment;
-	Dictionary*	pluginDict	= Codelet_GetPluginDictionary( self, cf->rootDict );
-
-	self->context = Stg_ComponentFactory_ConstructByName( cf, Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"Context"  ), AbstractContext, True, data );
-	if( !self->context )
-		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data ); 
-	
-	/* Initialise Timer */
-	self->initialTime = MPI_Wtime( );
-
-	/* Print Header to file */
-	StgFEM_FrequentOutput_PrintString( self->context, "CPU_Time" );
-	
-	ContextEP_Append( self->context, AbstractContext_EP_FrequentOutput ,StgFEM_CPUTime_PrintTimeInfo );
-}
-
-void* _StgFEM_CPUTime_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof( StgFEM_CPUTime );
-	Type                                                      type = StgFEM_CPUTime_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_CPUTime_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _StgFEM_CPUTime_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Codelet_New(  CODELET_PASSARGS  );
-}
-   
-Index StgFEM_CPUTime_Register( PluginsManager* pluginsManager ) {
-	return PluginsManager_Submit( pluginsManager, StgFEM_CPUTime_Type, (Name)"0", _StgFEM_CPUTime_DefaultNew  );
-}
-
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/CPUTime/CPUTime.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Output/CPUTime/CPUTime.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,101 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: CPUTime.c 1107 2008-04-16 01:54:15Z BelindaMay $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/FrequentOutput/FrequentOutput.h>
+
+#include "CPUTime.h"
+  
+const Type StgFEM_CPUTime_Type = "StgFEM_CPUTime";
+
+void StgFEM_CPUTime_PrintTimeInfo( AbstractContext* context ) {
+	StgFEM_CPUTime* self = (StgFEM_CPUTime*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_CPUTime_Type  );
+
+	/* Print Current Time Taken */
+	StgFEM_FrequentOutput_PrintValue( context, MPI_Wtime() - self->initialTime );
+}
+
+void _StgFEM_CPUTime_AssignFromXML( void* componment, Stg_ComponentFactory* cf, void* data ) {
+	StgFEM_CPUTime* self 		= (StgFEM_CPUTime*)componment;
+	Dictionary*	pluginDict	= Codelet_GetPluginDictionary( self, cf->rootDict );
+
+	self->context = Stg_ComponentFactory_ConstructByName( cf, Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"Context"  ), AbstractContext, True, data );
+	if( !self->context )
+		self->context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data ); 
+	
+	/* Initialise Timer */
+	self->initialTime = MPI_Wtime( );
+
+	/* Print Header to file */
+	StgFEM_FrequentOutput_PrintString( self->context, "CPU_Time" );
+	
+	ContextEP_Append( self->context, AbstractContext_EP_FrequentOutput ,StgFEM_CPUTime_PrintTimeInfo );
+}
+
+void* _StgFEM_CPUTime_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof( StgFEM_CPUTime );
+	Type                                                      type = StgFEM_CPUTime_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_CPUTime_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _StgFEM_CPUTime_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Codelet_New(  CODELET_PASSARGS  );
+}
+   
+Index StgFEM_CPUTime_Register( PluginsManager* pluginsManager ) {
+	return PluginsManager_Submit( pluginsManager, StgFEM_CPUTime_Type, (Name)"0", _StgFEM_CPUTime_DefaultNew  );
+}
+
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.c
--- a/plugins/Output/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.c 1107 2008-04-16 01:54:15Z BelindaMay $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/FrequentOutput/FrequentOutput.h>
-#include "CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.h"
-#include "StgFEM/Discretisation/Discretisation.h"
-#include "../../../SLE/SystemSetup/src/SystemSetup.h"
-#include "../../../SLE/ProvidedSystems/StokesFlow/src/StokesFlow.h"
-//#include "../../../SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_UzawaSolve.h"
-
-  
-const Type StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Type = "StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve";
-
-void StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_PrintTimeInfo( AbstractContext* context ) {
-	StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve*	self;
-	Stokes_SLE*	sle  = (Stokes_SLE*) LiveComponentRegister_Get( context->CF->LCRegister, (Name)"stokesEqn");
-	SLE_Solver*	solver = (SLE_Solver* ) LiveComponentRegister_Get( context->CF->LCRegister, (Name)"uzawa");
-
-	self = (StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve* )LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Type  );
-	
-	/* Print Current Average InnerIteration Time Taken */
-	StgFEM_FrequentOutput_PrintValue( context, solver->avgtimeinnerits);
-	/* Print Current Average OuterIteration Time Taken */
-	StgFEM_FrequentOutput_PrintValue( context, solver->avgtimeouterits);
-	/* Print Current Average NonLinearIteration Time Taken */
-	if(sle->isNonLinear == True){
-		StgFEM_FrequentOutput_PrintValue( context, solver->avgtimenonlinearits);
-	}	
-	/* Print Average Number of Inner Iterations*/
-	StgFEM_FrequentOutput_PrintValue( context, solver->avgnuminnerits);
-	/* Print Number of Outer Iterations */
-	StgFEM_FrequentOutput_PrintValue( context, solver->avgnumouterits);
-	/* Print Number of NonLinear Iterations*/
-	if(sle->isNonLinear == True){
-		StgFEM_FrequentOutput_PrintValue( context, solver->totalnumnonlinearits);
-	}
-}
-
-void _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
-	StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve* self = (StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve*)component;
-	AbstractContext* context;
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
-	self->context = context;
-		
-	ContextEP_Append( context, AbstractContext_EP_FrequentOutput ,StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_PrintTimeInfo );
-}
-
-void _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Initialise( void* component, void* data ) {
-	StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve* self = (StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve*)component;
-	Stokes_SLE*  sle  = (Stokes_SLE*) LiveComponentRegister_Get( self->context->CF->LCRegister, (Name)"stokesEqn" );
-		
-	/*this isn't set to true before the initialise phase*/
-	
-	/* Print Header to file */
-	StgFEM_FrequentOutput_PrintString( self->context, "AvgCPUInner" );
-	StgFEM_FrequentOutput_PrintString( self->context, "AvgCPUOuter" );
-	if(sle->isNonLinear == True){
-		StgFEM_FrequentOutput_PrintString( self->context, "AvgCPUNonLin" );
-	}
-	StgFEM_FrequentOutput_PrintString( self->context, "AvgInIts" );
-	StgFEM_FrequentOutput_PrintString( self->context, "AvgOutIts" );
-	if(sle->isNonLinear == True){
-		StgFEM_FrequentOutput_PrintString( self->context, "NonLinIts" );
-	}
-}
-
-void* _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_DefaultNew( Name name ) {
-	SizeT                                              _sizeOfSelf = sizeof( StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve );
-	Type                                                      type = StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Codelet_New( CODELET_PASSARGS );
-}
-   
-Index StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Register( PluginsManager* pluginsManager ) {
-	return PluginsManager_Submit( pluginsManager, StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Type, (Name)"0", _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_DefaultNew  );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Output/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve/CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,129 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.c 1107 2008-04-16 01:54:15Z BelindaMay $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/FrequentOutput/FrequentOutput.h>
+#include "CPUTimeAndNumberOfIterationsForInnerAndOuterSolve.h"
+#include "StgFEM/Discretisation/Discretisation.h"
+#include "../../../SLE/SystemSetup/src/SystemSetup.h"
+#include "../../../SLE/ProvidedSystems/StokesFlow/src/StokesFlow.h"
+//#include "../../../SLE/ProvidedSystems/StokesFlow/src/Stokes_SLE_UzawaSolve.h"
+
+  
+const Type StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Type = "StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve";
+
+void StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_PrintTimeInfo( AbstractContext* context ) {
+	StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve*	self;
+	Stokes_SLE*	sle  = (Stokes_SLE*) LiveComponentRegister_Get( context->CF->LCRegister, (Name)"stokesEqn");
+	SLE_Solver*	solver = (SLE_Solver* ) LiveComponentRegister_Get( context->CF->LCRegister, (Name)"uzawa");
+
+	self = (StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve* )LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Type  );
+	
+	/* Print Current Average InnerIteration Time Taken */
+	StgFEM_FrequentOutput_PrintValue( context, solver->avgtimeinnerits);
+	/* Print Current Average OuterIteration Time Taken */
+	StgFEM_FrequentOutput_PrintValue( context, solver->avgtimeouterits);
+	/* Print Current Average NonLinearIteration Time Taken */
+	if(sle->isNonLinear == True){
+		StgFEM_FrequentOutput_PrintValue( context, solver->avgtimenonlinearits);
+	}	
+	/* Print Average Number of Inner Iterations*/
+	StgFEM_FrequentOutput_PrintValue( context, solver->avgnuminnerits);
+	/* Print Number of Outer Iterations */
+	StgFEM_FrequentOutput_PrintValue( context, solver->avgnumouterits);
+	/* Print Number of NonLinear Iterations*/
+	if(sle->isNonLinear == True){
+		StgFEM_FrequentOutput_PrintValue( context, solver->totalnumnonlinearits);
+	}
+}
+
+void _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
+	StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve* self = (StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve*)component;
+	AbstractContext* context;
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  ); 
+	self->context = context;
+		
+	ContextEP_Append( context, AbstractContext_EP_FrequentOutput ,StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_PrintTimeInfo );
+}
+
+void _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Initialise( void* component, void* data ) {
+	StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve* self = (StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve*)component;
+	Stokes_SLE*  sle  = (Stokes_SLE*) LiveComponentRegister_Get( self->context->CF->LCRegister, (Name)"stokesEqn" );
+		
+	/*this isn't set to true before the initialise phase*/
+	
+	/* Print Header to file */
+	StgFEM_FrequentOutput_PrintString( self->context, "AvgCPUInner" );
+	StgFEM_FrequentOutput_PrintString( self->context, "AvgCPUOuter" );
+	if(sle->isNonLinear == True){
+		StgFEM_FrequentOutput_PrintString( self->context, "AvgCPUNonLin" );
+	}
+	StgFEM_FrequentOutput_PrintString( self->context, "AvgInIts" );
+	StgFEM_FrequentOutput_PrintString( self->context, "AvgOutIts" );
+	if(sle->isNonLinear == True){
+		StgFEM_FrequentOutput_PrintString( self->context, "NonLinIts" );
+	}
+}
+
+void* _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_DefaultNew( Name name ) {
+	SizeT                                              _sizeOfSelf = sizeof( StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve );
+	Type                                                      type = StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Codelet_New( CODELET_PASSARGS );
+}
+   
+Index StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Register( PluginsManager* pluginsManager ) {
+	return PluginsManager_Submit( pluginsManager, StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_Type, (Name)"0", _StgFEM_CPUTimeAndNumberOfIterationsForInnerAndOuterSolve_DefaultNew  );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/FeVariableList/FeVariableList.c
--- a/plugins/Output/FeVariableList/FeVariableList.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**      Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**      Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**      Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**      Monash Cluster Computing - http://www.mcc.monash.edu.au
-**      Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**      Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**      Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**      Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**      David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**      Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**      Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**      Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**      Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**      Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**      Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "FeVariableList.h"
-
-#ifndef MASTER
-        #define MASTER 0
-#endif
-
-const Type StgFEM_FeVariableList_Type = "StgFEM_FeVariableList";
-
-void _StgFEM_FeVariableList_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
-   StgFEM_FeVariableList*          self = (StgFEM_FeVariableList*) component;
-   AbstractContext*                context;
-   Dictionary*                     dictionary;
-   Stream*                         stream;
-   Name                            fevariableListFilename;
-   Bool                            fileOpened;
-   Bool                            PrintToFile;
-   
-   self->context = context = (AbstractContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  );
-   dictionary  = context->dictionary;
-      
-   /* Create Stream */
-   stream = self->stream = Journal_Register( InfoStream_Type, (Name)"FeVariableList"  );
-   
-   /* Set auto flush on stream */
-   Stream_SetAutoFlush( stream, True );
-   
-   /* Print to screen or to file? */
-   PrintToFile = Dictionary_GetBool_WithDefault( dictionary, (Dictionary_Entry_Key)"FeVariableListPrintToFile", True );
-   if(PrintToFile ){
-          /* Get name of fevariable list file */
-          fevariableListFilename = Dictionary_GetString_WithDefault( dictionary, "FeVariableListFilename", "FeVariables.list" );
-          /* Open New File */
-          if ( context->rank == MASTER ) {
-                  Stream* errorStream = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
-                  fileOpened          = Stream_RedirectFile_WithPrependedPath( stream, context->outputPath, fevariableListFilename );
-                  Journal_Firewall( fileOpened, errorStream,
-                                  "Could not open file %s/%s. Possibly directory %s does not exist or is not writable.\n"
-                                  "Check 'outputPath' in input file.\n", context->outputPath, fevariableListFilename, context->outputPath );
-          }
-          /* Set it so only master processor can print to stream */
-          Stream_SetPrintingRank( stream, MASTER );
-   }
-}
-
-void* _StgFEM_FeVariableList_DefaultNew( Name name ) {
-   /* Variables set in this function */
-   SizeT                                              _sizeOfSelf = sizeof(StgFEM_FeVariableList);
-   Type                                                      type = StgFEM_FeVariableList_Type;
-   Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-   Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-   Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-   Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_FeVariableList_DefaultNew;
-   Stg_Component_ConstructFunction*                    _construct = _StgFEM_FeVariableList_AssignFromXML;
-   Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-   Stg_Component_InitialiseFunction*                  _initialise = StgFEM_FeVariableList_PrintVariables;
-   Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-   Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-   /* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-   AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-   return _Codelet_New(  CODELET_PASSARGS  );
-}
-
-Index StgFEM_FeVariableList_Register( PluginsManager* pluginsManager ) {
-   return PluginsManager_Submit( pluginsManager, StgFEM_FeVariableList_Type, (Name)"0", _StgFEM_FeVariableList_DefaultNew  );
-}
-
-void StgFEM_FeVariableList_PrintVariables( void* _self, void* data ){
-   StgFEM_FeVariableList*  self    = (StgFEM_FeVariableList*) _self;
-   DomainContext*          context = (DomainContext*)self->context;
-   Stream*                 stream  = self->stream;;
-   FieldVariable_Register* fV_Register;
-   Index                   variablecount;
-   Index                   countindex;
-   Index                   columnWidth1     = 70;
-   Index                   columnWidth2     = 30;
-   
-   /* Get FeVariable Register*/
-   fV_Register                     = context->fieldVariable_Register;
-   variablecount                   = (Index) fV_Register->objects->count;
-   
-   /* Print header material */
-   Journal_Printf( stream, "\n");
-   Journal_PrintString_WithLength( stream, "FeVariable", columnWidth1 );
-   Journal_PrintString_WithLength( stream, "FeVariableType", columnWidth2 );
-   Journal_Printf( stream, "\n");
-   Journal_PrintString_WithLength( stream, "------------------------", columnWidth1 );
-   Journal_PrintString_WithLength( stream, "------------------------", columnWidth2 );
-   Journal_Printf( stream, "\n");
-   
-   /* Print Variables */
-   for(countindex = 1; countindex <= variablecount; ++countindex){
-          Journal_PrintString_WithLength( stream, fV_Register->objects->data[ countindex - 1 ]->name, columnWidth1 );
-          Journal_PrintString_WithLength( stream, fV_Register->objects->data[ countindex - 1 ]->type, columnWidth2 );
-          Journal_Printf( stream, "\n");
-   }
-   Journal_Printf( stream, "\n");
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/FeVariableList/FeVariableList.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Output/FeVariableList/FeVariableList.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,145 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**      Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**      Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**      Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**      Monash Cluster Computing - http://www.mcc.monash.edu.au
+**      Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**      Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**      Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**      Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**      David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**      Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**      Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**      Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**      Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**      Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**      Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "FeVariableList.h"
+
+#ifndef MASTER
+        #define MASTER 0
+#endif
+
+const Type StgFEM_FeVariableList_Type = "StgFEM_FeVariableList";
+
+void _StgFEM_FeVariableList_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
+   StgFEM_FeVariableList*          self = (StgFEM_FeVariableList*) component;
+   AbstractContext*                context;
+   Dictionary*                     dictionary;
+   Stream*                         stream;
+   Name                            fevariableListFilename;
+   Bool                            fileOpened;
+   Bool                            PrintToFile;
+   
+   self->context = context = (AbstractContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data  );
+   dictionary  = context->dictionary;
+      
+   /* Create Stream */
+   stream = self->stream = Journal_Register( InfoStream_Type, (Name)"FeVariableList"  );
+   
+   /* Set auto flush on stream */
+   Stream_SetAutoFlush( stream, True );
+   
+   /* Print to screen or to file? */
+   PrintToFile = Dictionary_GetBool_WithDefault( dictionary, (Dictionary_Entry_Key)"FeVariableListPrintToFile", True );
+   if(PrintToFile ){
+          /* Get name of fevariable list file */
+          fevariableListFilename = Dictionary_GetString_WithDefault( dictionary, "FeVariableListFilename", "FeVariables.list" );
+          /* Open New File */
+          if ( context->rank == MASTER ) {
+                  Stream* errorStream = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
+                  fileOpened          = Stream_RedirectFile_WithPrependedPath( stream, context->outputPath, fevariableListFilename );
+                  Journal_Firewall( fileOpened, errorStream,
+                                  "Could not open file %s/%s. Possibly directory %s does not exist or is not writable.\n"
+                                  "Check 'outputPath' in input file.\n", context->outputPath, fevariableListFilename, context->outputPath );
+          }
+          /* Set it so only master processor can print to stream */
+          Stream_SetPrintingRank( stream, MASTER );
+   }
+}
+
+void* _StgFEM_FeVariableList_DefaultNew( Name name ) {
+   /* Variables set in this function */
+   SizeT                                              _sizeOfSelf = sizeof(StgFEM_FeVariableList);
+   Type                                                      type = StgFEM_FeVariableList_Type;
+   Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+   Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+   Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+   Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_FeVariableList_DefaultNew;
+   Stg_Component_ConstructFunction*                    _construct = _StgFEM_FeVariableList_AssignFromXML;
+   Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+   Stg_Component_InitialiseFunction*                  _initialise = StgFEM_FeVariableList_PrintVariables;
+   Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+   Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+   /* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+   AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+   return _Codelet_New(  CODELET_PASSARGS  );
+}
+
+Index StgFEM_FeVariableList_Register( PluginsManager* pluginsManager ) {
+   return PluginsManager_Submit( pluginsManager, StgFEM_FeVariableList_Type, (Name)"0", _StgFEM_FeVariableList_DefaultNew  );
+}
+
+void StgFEM_FeVariableList_PrintVariables( void* _self, void* data ){
+   StgFEM_FeVariableList*  self    = (StgFEM_FeVariableList*) _self;
+   DomainContext*          context = (DomainContext*)self->context;
+   Stream*                 stream  = self->stream;;
+   FieldVariable_Register* fV_Register;
+   Index                   variablecount;
+   Index                   countindex;
+   Index                   columnWidth1     = 70;
+   Index                   columnWidth2     = 30;
+   
+   /* Get FeVariable Register*/
+   fV_Register                     = context->fieldVariable_Register;
+   variablecount                   = (Index) fV_Register->objects->count;
+   
+   /* Print header material */
+   Journal_Printf( stream, "\n");
+   Journal_PrintString_WithLength( stream, "FeVariable", columnWidth1 );
+   Journal_PrintString_WithLength( stream, "FeVariableType", columnWidth2 );
+   Journal_Printf( stream, "\n");
+   Journal_PrintString_WithLength( stream, "------------------------", columnWidth1 );
+   Journal_PrintString_WithLength( stream, "------------------------", columnWidth2 );
+   Journal_Printf( stream, "\n");
+   
+   /* Print Variables */
+   for(countindex = 1; countindex <= variablecount; ++countindex){
+          Journal_PrintString_WithLength( stream, fV_Register->objects->data[ countindex - 1 ]->name, columnWidth1 );
+          Journal_PrintString_WithLength( stream, fV_Register->objects->data[ countindex - 1 ]->type, columnWidth2 );
+          Journal_Printf( stream, "\n");
+   }
+   Journal_Printf( stream, "\n");
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/FrequentOutput/FrequentOutput.c
--- a/plugins/Output/FrequentOutput/FrequentOutput.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: FrequentOutput.c 1219 2008-09-04 23:09:02Z JohnMansour $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "FrequentOutput.h"
-
-#ifndef MASTER
-	#define MASTER 0
-#endif
-
-const Type StgFEM_FrequentOutput_Type = "StgFEM_FrequentOutput";
-
-void _StgFEM_FrequentOutput_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
-	StgFEM_FrequentOutput*            self         = (StgFEM_FrequentOutput*) component;
-	AbstractContext*                   context;
-	Dictionary*                        dictionary;
-	Stream*                            stream;
-	Name                               frequentOutputFilename;
-	Bool                               fileOpened;
-	Stream*                            errorStream  = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
-	Dictionary*			   pluginDict	= Codelet_GetPluginDictionary( self, cf->rootDict );
-
-	context = Stg_ComponentFactory_ConstructByName( cf, Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"Context"  ), AbstractContext, True, data );
-	self->context = context;
-	dictionary = context->dictionary;
-	
-	ContextEP_Append( context, AbstractContext_EP_Initialise, StgFEM_FrequentOutput_PrintNewLine );
-	ContextEP_Prepend_AlwaysFirst( context, AbstractContext_EP_FrequentOutput, StgFEM_FrequentOutput_PrintTime );
-	ContextEP_Append_AlwaysLast(   context, AbstractContext_EP_FrequentOutput, StgFEM_FrequentOutput_PrintNewLine );
-	
-	/* Create Stream */
-	stream = self->stream = Journal_Register( InfoStream_Type, (Name)"FrequentOutputFile"  );
-
-	/* Set auto flush on stream */
-	Stream_SetAutoFlush( stream, True );
-
-	/* Get name of frequent output file */
-	frequentOutputFilename = Dictionary_GetString_WithDefault( dictionary, "FrequentOutputFilename", "FrequentOutput.dat" );
-
-	/* Open File */
-	if ( context->rank == MASTER ) {
-		if ( (context->loadFromCheckPoint == False) && (Dictionary_GetBool_WithDefault( context->dictionary, (Dictionary_Entry_Key)"visualOnly", False ) == False )  ) {
-			/* Always overwrite the file if starting a new run */
-			fileOpened = Stream_RedirectFile_WithPrependedPath( stream, context->outputPath, frequentOutputFilename );
-		}
-		else {
-			/* Just append to the file if doing a restart from checkpoint */
-			fileOpened = Stream_AppendFile_WithPrependedPath( stream, context->outputPath, frequentOutputFilename );
-		}
-		Journal_Firewall( fileOpened, errorStream, 
-				"Could not open file %s/%s. Possibly directory %s does not exist or is not writable.\n"
-				"Check 'outputPath' in input file.\n", context->outputPath, frequentOutputFilename, context->outputPath );
-	}
-	
-	/* Set it so only master processor can print to stream */
-	Stream_SetPrintingRank( stream, MASTER );
-
-	/* Read in values from dictionary */
-	self->columnWidth   = Dictionary_GetUnsignedInt_WithDefault( dictionary, "FrequentOutputColumnWidth",  12 );
-	self->decimalLength = Dictionary_GetUnsignedInt_WithDefault( dictionary, "FrequentOutputDecimalLength", 6 );
-	self->borderString  = Dictionary_GetString_WithDefault( dictionary, "FrequentOutputBorderString", "    " );
-
-	StgFEM_FrequentOutput_PrintHeader( context );
-}
-
-void* _StgFEM_FrequentOutput_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof(StgFEM_FrequentOutput);
-	Type                                                      type = StgFEM_FrequentOutput_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_FrequentOutput_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _StgFEM_FrequentOutput_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Codelet_New(  CODELET_PASSARGS  );
-}
-
-Index StgFEM_FrequentOutput_Register( PluginsManager* pluginsManager ) {
-	return PluginsManager_Submit( pluginsManager, StgFEM_FrequentOutput_Type, (Name)"0", _StgFEM_FrequentOutput_DefaultNew  );
-}
-
-void StgFEM_FrequentOutput_PrintString( void* _context, char* string ) {
-	AbstractContext*                   context = (AbstractContext*) _context;
-	Stream*                            stream;
-
-	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type  );
-	stream     = self->stream;
-
-	/* Print some empty space at start */
-	Journal_Printf( stream, self->borderString );
-
-	/* Print String - Truncated if nessesary */
-	Journal_PrintString_WithLength( stream, string, self->columnWidth );
-}
-
-void StgFEM_FrequentOutput_PrintDouble( void* _context, double value ) {
-	AbstractContext*                   context = (AbstractContext*) _context;
-	char*                              formatString;
-	Stream*                            stream;
-
-	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type  );
-
-	stream     = self->stream;
-
-	/* Create format String */
-	Stg_asprintf( &formatString, "%%%d.%dg", self->columnWidth, self->decimalLength );
-
-	Journal_Printf( self->stream, self->borderString );
-	Journal_Printf( self->stream, formatString, value );
-
-	Memory_Free( formatString );
-}
-
-void StgFEM_FrequentOutput_PrintHeader( void* _context ) {
-	AbstractContext*                   context = (AbstractContext*) _context;
-	char*                              firstBorderString;
-	Stream*                            stream;
-
-	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type );
-	
-	stream     = self->stream;
-
-	/* Print First Boarder with '#' in the front */
-	firstBorderString = StG_Strdup( self->borderString  );
-	firstBorderString[0] = '#';
-	Journal_Printf( stream, firstBorderString );
-	Memory_Free( firstBorderString );
-
-	Journal_PrintString_WithLength( stream, "Timestep", self->columnWidth );
-
-	StgFEM_FrequentOutput_PrintString( context, "Time" );
-}
-
-void StgFEM_FrequentOutput_PrintTime( void* _context ) {
-	AbstractContext* context = (AbstractContext*) _context;
-
-	StgFEM_FrequentOutput_PrintValue( context, context->timeStep );
-	StgFEM_FrequentOutput_PrintValue( context, context->currentTime );
-}
-
-void StgFEM_FrequentOutput_PrintNewLine( void* _context ) {
-	AbstractContext*                   context = (AbstractContext*) _context;
-	Stream*                            stream;
-
-	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type  );
-	
-	stream     = self->stream;
-
-	Journal_Printf( stream, "\n" );
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/FrequentOutput/FrequentOutput.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Output/FrequentOutput/FrequentOutput.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,201 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: FrequentOutput.c 1219 2008-09-04 23:09:02Z JohnMansour $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "FrequentOutput.h"
+
+#ifndef MASTER
+	#define MASTER 0
+#endif
+
+const Type StgFEM_FrequentOutput_Type = "StgFEM_FrequentOutput";
+
+void _StgFEM_FrequentOutput_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
+	StgFEM_FrequentOutput*            self         = (StgFEM_FrequentOutput*) component;
+	AbstractContext*                   context;
+	Dictionary*                        dictionary;
+	Stream*                            stream;
+	Name                               frequentOutputFilename;
+	Bool                               fileOpened;
+	Stream*                            errorStream  = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
+	Dictionary*			   pluginDict	= Codelet_GetPluginDictionary( self, cf->rootDict );
+
+	context = Stg_ComponentFactory_ConstructByName( cf, Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"Context"  ), AbstractContext, True, data );
+	self->context = context;
+	dictionary = context->dictionary;
+	
+	ContextEP_Append( context, AbstractContext_EP_Initialise, StgFEM_FrequentOutput_PrintNewLine );
+	ContextEP_Prepend_AlwaysFirst( context, AbstractContext_EP_FrequentOutput, StgFEM_FrequentOutput_PrintTime );
+	ContextEP_Append_AlwaysLast(   context, AbstractContext_EP_FrequentOutput, StgFEM_FrequentOutput_PrintNewLine );
+	
+	/* Create Stream */
+	stream = self->stream = Journal_Register( InfoStream_Type, (Name)"FrequentOutputFile"  );
+
+	/* Set auto flush on stream */
+	Stream_SetAutoFlush( stream, True );
+
+	/* Get name of frequent output file */
+	frequentOutputFilename = Dictionary_GetString_WithDefault( dictionary, "FrequentOutputFilename", "FrequentOutput.dat" );
+
+	/* Open File */
+	if ( context->rank == MASTER ) {
+		if ( (context->loadFromCheckPoint == False) && (Dictionary_GetBool_WithDefault( context->dictionary, (Dictionary_Entry_Key)"visualOnly", False ) == False )  ) {
+			/* Always overwrite the file if starting a new run */
+			fileOpened = Stream_RedirectFile_WithPrependedPath( stream, context->outputPath, frequentOutputFilename );
+		}
+		else {
+			/* Just append to the file if doing a restart from checkpoint */
+			fileOpened = Stream_AppendFile_WithPrependedPath( stream, context->outputPath, frequentOutputFilename );
+		}
+		Journal_Firewall( fileOpened, errorStream, 
+				"Could not open file %s/%s. Possibly directory %s does not exist or is not writable.\n"
+				"Check 'outputPath' in input file.\n", context->outputPath, frequentOutputFilename, context->outputPath );
+	}
+	
+	/* Set it so only master processor can print to stream */
+	Stream_SetPrintingRank( stream, MASTER );
+
+	/* Read in values from dictionary */
+	self->columnWidth   = Dictionary_GetUnsignedInt_WithDefault( dictionary, "FrequentOutputColumnWidth",  12 );
+	self->decimalLength = Dictionary_GetUnsignedInt_WithDefault( dictionary, "FrequentOutputDecimalLength", 6 );
+	self->borderString  = Dictionary_GetString_WithDefault( dictionary, "FrequentOutputBorderString", "    " );
+
+	StgFEM_FrequentOutput_PrintHeader( context );
+}
+
+void* _StgFEM_FrequentOutput_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof(StgFEM_FrequentOutput);
+	Type                                                      type = StgFEM_FrequentOutput_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_FrequentOutput_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _StgFEM_FrequentOutput_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Codelet_New(  CODELET_PASSARGS  );
+}
+
+Index StgFEM_FrequentOutput_Register( PluginsManager* pluginsManager ) {
+	return PluginsManager_Submit( pluginsManager, StgFEM_FrequentOutput_Type, (Name)"0", _StgFEM_FrequentOutput_DefaultNew  );
+}
+
+void StgFEM_FrequentOutput_PrintString( void* _context, char* string ) {
+	AbstractContext*                   context = (AbstractContext*) _context;
+	Stream*                            stream;
+
+	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type  );
+	stream     = self->stream;
+
+	/* Print some empty space at start */
+	Journal_Printf( stream, self->borderString );
+
+	/* Print String - Truncated if nessesary */
+	Journal_PrintString_WithLength( stream, string, self->columnWidth );
+}
+
+void StgFEM_FrequentOutput_PrintDouble( void* _context, double value ) {
+	AbstractContext*                   context = (AbstractContext*) _context;
+	char*                              formatString;
+	Stream*                            stream;
+
+	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type  );
+
+	stream     = self->stream;
+
+	/* Create format String */
+	Stg_asprintf( &formatString, "%%%d.%dg", self->columnWidth, self->decimalLength );
+
+	Journal_Printf( self->stream, self->borderString );
+	Journal_Printf( self->stream, formatString, value );
+
+	Memory_Free( formatString );
+}
+
+void StgFEM_FrequentOutput_PrintHeader( void* _context ) {
+	AbstractContext*                   context = (AbstractContext*) _context;
+	char*                              firstBorderString;
+	Stream*                            stream;
+
+	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type );
+	
+	stream     = self->stream;
+
+	/* Print First Boarder with '#' in the front */
+	firstBorderString = StG_Strdup( self->borderString  );
+	firstBorderString[0] = '#';
+	Journal_Printf( stream, firstBorderString );
+	Memory_Free( firstBorderString );
+
+	Journal_PrintString_WithLength( stream, "Timestep", self->columnWidth );
+
+	StgFEM_FrequentOutput_PrintString( context, "Time" );
+}
+
+void StgFEM_FrequentOutput_PrintTime( void* _context ) {
+	AbstractContext* context = (AbstractContext*) _context;
+
+	StgFEM_FrequentOutput_PrintValue( context, context->timeStep );
+	StgFEM_FrequentOutput_PrintValue( context, context->currentTime );
+}
+
+void StgFEM_FrequentOutput_PrintNewLine( void* _context ) {
+	AbstractContext*                   context = (AbstractContext*) _context;
+	Stream*                            stream;
+
+	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput*)LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type  );
+	
+	stream     = self->stream;
+
+	Journal_Printf( stream, "\n" );
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/PeakMemory/PeakMemory.c
--- a/plugins/Output/PeakMemory/PeakMemory.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id:  $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/Discretisation/Discretisation.h>
-#include <StgFEM/FrequentOutput/FrequentOutput.h>
-
-#include "PeakMemory.h"
-  
-const Type StgFEM_PeakMemory_Type = "StgFEM_PeakMemory";
-
-void StgFEM_PeakMemory_PrintMemoryInfo( AbstractContext* context ) {
-	PetscLogDouble stgPeak, totalMem, petscMem, ave;
-	
-	stgPeak = (PetscLogDouble)stgMemory->stgPeakMemory;
-	MPI_Allreduce( &stgPeak, &ave, 1, MPI_DOUBLE, MPI_SUM, context->communicator );
-	ave /= 1024 * 1024;
-	StgFEM_FrequentOutput_PrintValue( context, ave );
-
-	PetscMallocGetMaximumUsage( &petscMem );
-	MPI_Allreduce( &petscMem, &ave, 1, MPI_DOUBLE, MPI_SUM, context->communicator );
-	ave /= 1024 * 1024;
-	StgFEM_FrequentOutput_PrintValue( context, ave );
-
-	PetscMemoryGetMaximumUsage( &totalMem );
-	MPI_Allreduce( &totalMem, &ave, 1, MPI_DOUBLE, MPI_SUM, context->communicator );
-	ave /= 1024 * 1024;
-	StgFEM_FrequentOutput_PrintValue( context, ave );
-}
-
-void _StgFEM_PeakMemory_AssignFromXML( void* componment, Stg_ComponentFactory* cf, void* data ) {
-	AbstractContext* context;
-
-	/* Turn on the magical petsc logging */
-	PetscMemorySetGetMaximumUsage();
-
-	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data ); 
-	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput* )LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type  );
-
-	/* set the stupid stream column width so I don't get "..." behaviour */
-	self->columnWidth = 15;
-	
-	/* Print Header to file */
-	StgFEM_FrequentOutput_PrintString( context, "StgPeakMem(Mb)" );
-	StgFEM_FrequentOutput_PrintString( context, "PetscMem(Mb)" );
-	StgFEM_FrequentOutput_PrintString( context, "ProgMem(Mb)" );
-	
-	ContextEP_Append( context, AbstractContext_EP_FrequentOutput ,StgFEM_PeakMemory_PrintMemoryInfo );
-}
-
-void* _StgFEM_PeakMemory_DefaultNew( Name name ) {
-	/* Variables set in this function */
-	SizeT                                              _sizeOfSelf = sizeof( Codelet );
-	Type                                                      type = StgFEM_PeakMemory_Type;
-	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_PeakMemory_DefaultNew;
-	Stg_Component_ConstructFunction*                    _construct = _StgFEM_PeakMemory_AssignFromXML;
-	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
-	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-	return _Codelet_New(  CODELET_PASSARGS  );
-}
-   
-Index StgFEM_PeakMemory_Register( PluginsManager* pluginsManager ) {
-	return PluginsManager_Submit( pluginsManager, StgFEM_PeakMemory_Type, (Name)"0", _StgFEM_PeakMemory_DefaultNew  );
-}
-
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/PeakMemory/PeakMemory.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Output/PeakMemory/PeakMemory.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,116 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id:  $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/Discretisation/Discretisation.h>
+#include <StgFEM/FrequentOutput/FrequentOutput.h>
+
+#include "PeakMemory.h"
+  
+const Type StgFEM_PeakMemory_Type = "StgFEM_PeakMemory";
+
+void StgFEM_PeakMemory_PrintMemoryInfo( AbstractContext* context ) {
+	PetscLogDouble stgPeak, totalMem, petscMem, ave;
+	
+	stgPeak = (PetscLogDouble)stgMemory->stgPeakMemory;
+	MPI_Allreduce( &stgPeak, &ave, 1, MPI_DOUBLE, MPI_SUM, context->communicator );
+	ave /= 1024 * 1024;
+	StgFEM_FrequentOutput_PrintValue( context, ave );
+
+	PetscMallocGetMaximumUsage( &petscMem );
+	MPI_Allreduce( &petscMem, &ave, 1, MPI_DOUBLE, MPI_SUM, context->communicator );
+	ave /= 1024 * 1024;
+	StgFEM_FrequentOutput_PrintValue( context, ave );
+
+	PetscMemoryGetMaximumUsage( &totalMem );
+	MPI_Allreduce( &totalMem, &ave, 1, MPI_DOUBLE, MPI_SUM, context->communicator );
+	ave /= 1024 * 1024;
+	StgFEM_FrequentOutput_PrintValue( context, ave );
+}
+
+void _StgFEM_PeakMemory_AssignFromXML( void* componment, Stg_ComponentFactory* cf, void* data ) {
+	AbstractContext* context;
+
+	/* Turn on the magical petsc logging */
+	PetscMemorySetGetMaximumUsage();
+
+	context = Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data ); 
+	StgFEM_FrequentOutput* self = (StgFEM_FrequentOutput* )LiveComponentRegister_Get( context->CF->LCRegister, (Name)StgFEM_FrequentOutput_Type  );
+
+	/* set the stupid stream column width so I don't get "..." behaviour */
+	self->columnWidth = 15;
+	
+	/* Print Header to file */
+	StgFEM_FrequentOutput_PrintString( context, "StgPeakMem(Mb)" );
+	StgFEM_FrequentOutput_PrintString( context, "PetscMem(Mb)" );
+	StgFEM_FrequentOutput_PrintString( context, "ProgMem(Mb)" );
+	
+	ContextEP_Append( context, AbstractContext_EP_FrequentOutput ,StgFEM_PeakMemory_PrintMemoryInfo );
+}
+
+void* _StgFEM_PeakMemory_DefaultNew( Name name ) {
+	/* Variables set in this function */
+	SizeT                                              _sizeOfSelf = sizeof( Codelet );
+	Type                                                      type = StgFEM_PeakMemory_Type;
+	Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+	Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+	Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+	Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_PeakMemory_DefaultNew;
+	Stg_Component_ConstructFunction*                    _construct = _StgFEM_PeakMemory_AssignFromXML;
+	Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+	Stg_Component_InitialiseFunction*                  _initialise = _Codelet_Initialise;
+	Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+	Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+	/* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+	AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+	return _Codelet_New(  CODELET_PASSARGS  );
+}
+   
+Index StgFEM_PeakMemory_Register( PluginsManager* pluginsManager ) {
+	return PluginsManager_Submit( pluginsManager, StgFEM_PeakMemory_Type, (Name)"0", _StgFEM_PeakMemory_DefaultNew  );
+}
+
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/PrintFeVariableDiscreteValues/Plugin.c
--- a/plugins/Output/PrintFeVariableDiscreteValues/Plugin.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Plugin.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include "Plugin.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-const Type StgFEM_PrintFeVariableDiscreteValues_Type = "StgFEM_PrintFeVariableDiscreteValues";
-
-Name PRINT_FE_VARIABLE_DISCRETE_VALUES_TAG = "PrintFeVariableDiscreteValues";
-
-void _StgFEM_PrintFeVariableDiscreteValues_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
-	FiniteElementContext* context;
-
-	context = (FiniteElementContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  ); 
-	
-	ContextEP_Append( context, AbstractContext_EP_Dump, PrintFeVariableDiscreteValues );
-}
-
-void* _StgFEM_PrintFeVariableDiscreteValues_DefaultNew( Name name ) {
-	return Codelet_New(
-			StgFEM_PrintFeVariableDiscreteValues_Type,
-			_StgFEM_PrintFeVariableDiscreteValues_DefaultNew,
-			_StgFEM_PrintFeVariableDiscreteValues_AssignFromXML,
-			_Codelet_Build,
-			_Codelet_Initialise,
-			_Codelet_Execute,
-			_Codelet_Destroy,
-			name );
-}
-
-Index StgFEM_PrintFeVariableDiscreteValues_Register( PluginsManager* pluginsManager ) {
-	Journal_DPrintf( StgFEM_Debug, "In: %s( void* )\n", __func__ );
-	
-	return PluginsManager_Submit( pluginsManager, StgFEM_PrintFeVariableDiscreteValues_Type, (Name)"0", _StgFEM_PrintFeVariableDiscreteValues_DefaultNew );
-}
-
-
-void PrintFeVariableDiscreteValues( void* _context ) {
-	FiniteElementContext*			context = (FiniteElementContext* )_context;
-	FeVariable*				currFeVar;
-	Stream*					stream;
-	Name					currFeVarName;
-	Dictionary_Entry_Value*			feVarList=NULL;
-	Dictionary_Entry_Value*			currFvParam=NULL;
-	Index					feVar_I=0;
-	Index					numFeVarsToPrint=0;
-	Stream*					warningStr = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
-	
-	stream = Journal_Register( Info_Type, (Name)CURR_MODULE_NAME  );
-
-	feVarList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)(char*)PRINT_FE_VARIABLE_DISCRETE_VALUES_TAG );
-	if ( NULL == feVarList  ) {
-		Journal_Printf( warningStr, "Warning - in %s: Plugin \"%s\" loaded, but no \"%s\" tag found "
-			"in dictionary. Not printing any FE vars.\n", __func__, CURR_MODULE_NAME, PRINT_FE_VARIABLE_DISCRETE_VALUES_TAG );
-		return;
-	}
-
-	numFeVarsToPrint = Dictionary_Entry_Value_GetCount( feVarList );
-	if ( 0 == numFeVarsToPrint ) {
-		Journal_Printf( warningStr, "Warning - in %s: Plugin \"%s\" loaded, \"%s\" list found, "
-			"but list has 0 entries.\n",
-			__func__, CURR_MODULE_NAME, PRINT_FE_VARIABLE_DISCRETE_VALUES_TAG );
-		return;
-	}
-
-
-	for ( feVar_I=0; feVar_I < numFeVarsToPrint; feVar_I++ ) {
-		currFvParam = Dictionary_Entry_Value_GetElement( feVarList, feVar_I );
-		currFeVarName = Dictionary_Entry_Value_AsString( currFvParam );
-		currFeVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, currFeVarName );
-		if ( NULL == currFeVar ) {
-			Journal_Printf( warningStr, "Warning - in %s: You requested printing the values of feVariable "
-				"\"%s\", but it doesn't exist in the context's field variable register. Skipping.\n",
-				__func__, currFeVarName );
-			Journal_Printf( warningStr, "(Field Vars currently registered are: " );	
-			Stg_ObjectList_PrintAllEntryNames( context->fieldVariable_Register->objects, warningStr );
-			Journal_Printf( warningStr, ")\n" );	
-			continue;
-		}
-		Journal_Printf( stream, "%s Values (at end of timestep %d):\n", currFeVarName, context->timeStep );
-		FeVariable_PrintLocalDiscreteValues( currFeVar, stream );
-		Journal_Printf( stream, "\n" );
-	}
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/PrintFeVariableDiscreteValues/Plugin.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Output/PrintFeVariableDiscreteValues/Plugin.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,130 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Plugin.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include "Plugin.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+const Type StgFEM_PrintFeVariableDiscreteValues_Type = "StgFEM_PrintFeVariableDiscreteValues";
+
+Name PRINT_FE_VARIABLE_DISCRETE_VALUES_TAG = "PrintFeVariableDiscreteValues";
+
+void _StgFEM_PrintFeVariableDiscreteValues_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
+	FiniteElementContext* context;
+
+	context = (FiniteElementContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  ); 
+	
+	ContextEP_Append( context, AbstractContext_EP_Dump, PrintFeVariableDiscreteValues );
+}
+
+void* _StgFEM_PrintFeVariableDiscreteValues_DefaultNew( Name name ) {
+	return Codelet_New(
+			StgFEM_PrintFeVariableDiscreteValues_Type,
+			_StgFEM_PrintFeVariableDiscreteValues_DefaultNew,
+			_StgFEM_PrintFeVariableDiscreteValues_AssignFromXML,
+			_Codelet_Build,
+			_Codelet_Initialise,
+			_Codelet_Execute,
+			_Codelet_Destroy,
+			name );
+}
+
+Index StgFEM_PrintFeVariableDiscreteValues_Register( PluginsManager* pluginsManager ) {
+	Journal_DPrintf( StgFEM_Debug, "In: %s( void* )\n", __func__ );
+	
+	return PluginsManager_Submit( pluginsManager, StgFEM_PrintFeVariableDiscreteValues_Type, (Name)"0", _StgFEM_PrintFeVariableDiscreteValues_DefaultNew );
+}
+
+
+void PrintFeVariableDiscreteValues( void* _context ) {
+	FiniteElementContext*			context = (FiniteElementContext* )_context;
+	FeVariable*				currFeVar;
+	Stream*					stream;
+	Name					currFeVarName;
+	Dictionary_Entry_Value*			feVarList=NULL;
+	Dictionary_Entry_Value*			currFvParam=NULL;
+	Index					feVar_I=0;
+	Index					numFeVarsToPrint=0;
+	Stream*					warningStr = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
+	
+	stream = Journal_Register( Info_Type, (Name)CURR_MODULE_NAME  );
+
+	feVarList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)(char*)PRINT_FE_VARIABLE_DISCRETE_VALUES_TAG );
+	if ( NULL == feVarList  ) {
+		Journal_Printf( warningStr, "Warning - in %s: Plugin \"%s\" loaded, but no \"%s\" tag found "
+			"in dictionary. Not printing any FE vars.\n", __func__, CURR_MODULE_NAME, PRINT_FE_VARIABLE_DISCRETE_VALUES_TAG );
+		return;
+	}
+
+	numFeVarsToPrint = Dictionary_Entry_Value_GetCount( feVarList );
+	if ( 0 == numFeVarsToPrint ) {
+		Journal_Printf( warningStr, "Warning - in %s: Plugin \"%s\" loaded, \"%s\" list found, "
+			"but list has 0 entries.\n",
+			__func__, CURR_MODULE_NAME, PRINT_FE_VARIABLE_DISCRETE_VALUES_TAG );
+		return;
+	}
+
+
+	for ( feVar_I=0; feVar_I < numFeVarsToPrint; feVar_I++ ) {
+		currFvParam = Dictionary_Entry_Value_GetElement( feVarList, feVar_I );
+		currFeVarName = Dictionary_Entry_Value_AsString( currFvParam );
+		currFeVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, currFeVarName );
+		if ( NULL == currFeVar ) {
+			Journal_Printf( warningStr, "Warning - in %s: You requested printing the values of feVariable "
+				"\"%s\", but it doesn't exist in the context's field variable register. Skipping.\n",
+				__func__, currFeVarName );
+			Journal_Printf( warningStr, "(Field Vars currently registered are: " );	
+			Stg_ObjectList_PrintAllEntryNames( context->fieldVariable_Register->objects, warningStr );
+			Journal_Printf( warningStr, ")\n" );	
+			continue;
+		}
+		Journal_Printf( stream, "%s Values (at end of timestep %d):\n", currFeVarName, context->timeStep );
+		FeVariable_PrintLocalDiscreteValues( currFeVar, stream );
+		Journal_Printf( stream, "\n" );
+	}
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/PrintFeVariableDiscreteValues_2dBox/Plugin.c
--- a/plugins/Output/PrintFeVariableDiscreteValues_2dBox/Plugin.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: Plugin.c 964 2007-10-11 08:03:06Z SteveQuenette $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include "Plugin.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-const Type StgFEM_PrintFeVariableDiscreteValues_2dBox_Type = "StgFEM_PrintFeVariableDiscreteValues_2dBox";
-
-Name PRINT_FE_VARIABLE_DISCRETE_VALUES_2D_BOX_TAG = "PrintFeVariableDiscreteValues_2dBox";
-
-void _StgFEM_PrintFeVariableDiscreteValues_2dBox_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
-	FiniteElementContext* context;
-
-	context = (FiniteElementContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  ); 
-	/* Add extensions to nodes, elements and the context */
-
-	/* Add extensions to functionality (entry points) */ 
-	ContextEP_Append( context, AbstractContext_EP_Dump, PrintFeVariableDiscreteValues_2dBox );
-}
-
-void* _StgFEM_PrintFeVariableDiscreteValues_2dBox_DefaultNew( Name name ) {
-	return Codelet_New(
-			StgFEM_PrintFeVariableDiscreteValues_2dBox_Type,
-			_StgFEM_PrintFeVariableDiscreteValues_2dBox_DefaultNew,
-			_StgFEM_PrintFeVariableDiscreteValues_2dBox_AssignFromXML,
-			_Codelet_Build,
-			_Codelet_Initialise,
-			_Codelet_Execute,
-			_Codelet_Destroy,
-			name );
-}
-
-Index StgFEM_PrintFeVariableDiscreteValues_2dBox_Register( PluginsManager* pluginsManager ) {
-	Journal_DPrintf( StgFEM_Debug, "In: %s( void* )\n", __func__ );
-
-	return PluginsManager_Submit( pluginsManager, StgFEM_PrintFeVariableDiscreteValues_2dBox_Type, (Name)"0", _StgFEM_PrintFeVariableDiscreteValues_2dBox_DefaultNew );
-}
-
-
-void PrintFeVariableDiscreteValues_2dBox( void* _context ) {
-	FiniteElementContext*			context = (FiniteElementContext* )_context;
-	FeVariable*				currFeVar;
-	Stream*					stream;
-	Name					currFeVarName;
-	Dictionary_Entry_Value*			feVarList=NULL;
-	Dictionary_Entry_Value*			currFvParam=NULL;
-	Index					feVar_I=0;
-	Index					numFeVarsToPrint=0;
-	Stream*					warningStr = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
-	
-	stream = Journal_Register( Info_Type, (Name)CURR_MODULE_NAME  );
-
-	feVarList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)(char*)PRINT_FE_VARIABLE_DISCRETE_VALUES_2D_BOX_TAG );
-	if ( NULL == feVarList  ) {
-		Journal_Printf( warningStr, "Warning - in %s: Plugin \"%s\" loaded, but no \"%s\" tag found "
-			"in dictionary. Not printing any FE vars.\n", __func__, CURR_MODULE_NAME, PRINT_FE_VARIABLE_DISCRETE_VALUES_2D_BOX_TAG );
-		return;
-	}
-
-	numFeVarsToPrint = Dictionary_Entry_Value_GetCount( feVarList );
-	if ( 0 == numFeVarsToPrint ) {
-		Journal_Printf( warningStr, "Warning - in %s: Plugin \"%s\" loaded, \"%s\" list found, "
-			"but list has 0 entries.\n",
-			__func__, CURR_MODULE_NAME, PRINT_FE_VARIABLE_DISCRETE_VALUES_2D_BOX_TAG );
-		return;
-	}
-
-
-	for ( feVar_I=0; feVar_I < numFeVarsToPrint; feVar_I++ ) {
-		currFvParam = Dictionary_Entry_Value_GetElement( feVarList, feVar_I );
-		currFeVarName = Dictionary_Entry_Value_AsString( currFvParam );
-		currFeVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, currFeVarName );
-		if ( NULL == currFeVar ) {
-			Journal_Printf( warningStr, "Warning - in %s: You requested printing the values of feVariable "
-				"\"%s\", but it doesn't exist in the context's field variable register. Skipping.\n",
-				__func__, currFeVarName );
-			Journal_Printf( warningStr, "(Field Vars currently registered are: " );	
-			Stg_ObjectList_PrintAllEntryNames( context->fieldVariable_Register->objects, warningStr );
-			Journal_Printf( warningStr, ")\n" );	
-			continue;
-		}
-		Journal_Printf( stream, "%s Values (at end of timestep %d):\n", currFeVarName, context->timeStep );
-		FeVariable_PrintLocalDiscreteValues_2dBox( currFeVar, stream );
-		Journal_Printf( stream, "\n" );
-	}
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/PrintFeVariableDiscreteValues_2dBox/Plugin.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Output/PrintFeVariableDiscreteValues_2dBox/Plugin.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,132 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: Plugin.c 964 2007-10-11 08:03:06Z SteveQuenette $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include "Plugin.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+const Type StgFEM_PrintFeVariableDiscreteValues_2dBox_Type = "StgFEM_PrintFeVariableDiscreteValues_2dBox";
+
+Name PRINT_FE_VARIABLE_DISCRETE_VALUES_2D_BOX_TAG = "PrintFeVariableDiscreteValues_2dBox";
+
+void _StgFEM_PrintFeVariableDiscreteValues_2dBox_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
+	FiniteElementContext* context;
+
+	context = (FiniteElementContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", FiniteElementContext, True, data  ); 
+	/* Add extensions to nodes, elements and the context */
+
+	/* Add extensions to functionality (entry points) */ 
+	ContextEP_Append( context, AbstractContext_EP_Dump, PrintFeVariableDiscreteValues_2dBox );
+}
+
+void* _StgFEM_PrintFeVariableDiscreteValues_2dBox_DefaultNew( Name name ) {
+	return Codelet_New(
+			StgFEM_PrintFeVariableDiscreteValues_2dBox_Type,
+			_StgFEM_PrintFeVariableDiscreteValues_2dBox_DefaultNew,
+			_StgFEM_PrintFeVariableDiscreteValues_2dBox_AssignFromXML,
+			_Codelet_Build,
+			_Codelet_Initialise,
+			_Codelet_Execute,
+			_Codelet_Destroy,
+			name );
+}
+
+Index StgFEM_PrintFeVariableDiscreteValues_2dBox_Register( PluginsManager* pluginsManager ) {
+	Journal_DPrintf( StgFEM_Debug, "In: %s( void* )\n", __func__ );
+
+	return PluginsManager_Submit( pluginsManager, StgFEM_PrintFeVariableDiscreteValues_2dBox_Type, (Name)"0", _StgFEM_PrintFeVariableDiscreteValues_2dBox_DefaultNew );
+}
+
+
+void PrintFeVariableDiscreteValues_2dBox( void* _context ) {
+	FiniteElementContext*			context = (FiniteElementContext* )_context;
+	FeVariable*				currFeVar;
+	Stream*					stream;
+	Name					currFeVarName;
+	Dictionary_Entry_Value*			feVarList=NULL;
+	Dictionary_Entry_Value*			currFvParam=NULL;
+	Index					feVar_I=0;
+	Index					numFeVarsToPrint=0;
+	Stream*					warningStr = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
+	
+	stream = Journal_Register( Info_Type, (Name)CURR_MODULE_NAME  );
+
+	feVarList = Dictionary_Get( context->dictionary, (Dictionary_Entry_Key)(char*)PRINT_FE_VARIABLE_DISCRETE_VALUES_2D_BOX_TAG );
+	if ( NULL == feVarList  ) {
+		Journal_Printf( warningStr, "Warning - in %s: Plugin \"%s\" loaded, but no \"%s\" tag found "
+			"in dictionary. Not printing any FE vars.\n", __func__, CURR_MODULE_NAME, PRINT_FE_VARIABLE_DISCRETE_VALUES_2D_BOX_TAG );
+		return;
+	}
+
+	numFeVarsToPrint = Dictionary_Entry_Value_GetCount( feVarList );
+	if ( 0 == numFeVarsToPrint ) {
+		Journal_Printf( warningStr, "Warning - in %s: Plugin \"%s\" loaded, \"%s\" list found, "
+			"but list has 0 entries.\n",
+			__func__, CURR_MODULE_NAME, PRINT_FE_VARIABLE_DISCRETE_VALUES_2D_BOX_TAG );
+		return;
+	}
+
+
+	for ( feVar_I=0; feVar_I < numFeVarsToPrint; feVar_I++ ) {
+		currFvParam = Dictionary_Entry_Value_GetElement( feVarList, feVar_I );
+		currFeVarName = Dictionary_Entry_Value_AsString( currFvParam );
+		currFeVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, currFeVarName );
+		if ( NULL == currFeVar ) {
+			Journal_Printf( warningStr, "Warning - in %s: You requested printing the values of feVariable "
+				"\"%s\", but it doesn't exist in the context's field variable register. Skipping.\n",
+				__func__, currFeVarName );
+			Journal_Printf( warningStr, "(Field Vars currently registered are: " );	
+			Stg_ObjectList_PrintAllEntryNames( context->fieldVariable_Register->objects, warningStr );
+			Journal_Printf( warningStr, ")\n" );	
+			continue;
+		}
+		Journal_Printf( stream, "%s Values (at end of timestep %d):\n", currFeVarName, context->timeStep );
+		FeVariable_PrintLocalDiscreteValues_2dBox( currFeVar, stream );
+		Journal_Printf( stream, "\n" );
+	}
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/SwarmVariableList/SwarmVariableList.c
--- a/plugins/Output/SwarmVariableList/SwarmVariableList.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**      Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**      Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**      Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**      Monash Cluster Computing - http://www.mcc.monash.edu.au
-**      Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**      Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**      Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**      Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**      David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**      Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**      Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**      Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**      Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**      Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**      Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-
-#include "SwarmVariableList.h"
-
-#ifndef MASTER
-        #define MASTER 0
-#endif
-
-const Type StgFEM_SwarmVariableList_Type = "StgFEM_SwarmVariableList";
-
-void _StgFEM_SwarmVariableList_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
-        StgFEM_SwarmVariableList* self         = (StgFEM_SwarmVariableList*) component;
-        AbstractContext*                context;
-        Dictionary*                     dictionary;
-        Stream*                         stream;
-        Name                            swarmVariableListFilename;
-        Bool                            fileOpened;
-        Bool                            PrintToFile;
-
-        self->context       = context = (AbstractContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data );
-        dictionary          = context->dictionary;
-        self->swarmRegister = Swarm_Register_GetSwarm_Register( );
-
-        /** create stream **/
-        stream = self->stream = Journal_Register( InfoStream_Type, (Name)"SwarmVariableList"  );
-
-        /** set auto flush on stream **/
-        Stream_SetAutoFlush( stream, True );
-
-        /** print to screen or to file? **/
-        PrintToFile = Dictionary_GetBool_WithDefault( dictionary, (Dictionary_Entry_Key)"SwarmVariableListPrintToFile", True );
-        if(PrintToFile ){
-                /** get name of SwarmVariable list file **/
-                swarmVariableListFilename = Dictionary_GetString_WithDefault( dictionary, "SwarmVariableListFilename", "SwarmVariables.list" );
-                /** open new file **/
-                if ( context->rank == MASTER ) {
-                        Stream* errorStream = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
-                        fileOpened          = Stream_RedirectFile_WithPrependedPath( stream, context->outputPath, swarmVariableListFilename );
-                        Journal_Firewall( fileOpened, errorStream,
-                                        "Could not open file %s/%s. Possibly directory %s does not exist or is not writable.\n"
-                                        "Check 'outputPath' in input file.\n", context->outputPath, swarmVariableListFilename, context->outputPath );
-                }
-                /** set it so only master processor can print to stream **/
-                Stream_SetPrintingRank( stream, MASTER );
-        }
-}
-
-void* _StgFEM_SwarmVariableList_DefaultNew( Name name ) {
-   /* Variables set in this function */
-   SizeT                                              _sizeOfSelf = sizeof(StgFEM_SwarmVariableList);
-   Type                                                      type = StgFEM_SwarmVariableList_Type;
-   Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
-   Stg_Class_PrintFunction*                                _print = _Codelet_Print;
-   Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
-   Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_SwarmVariableList_DefaultNew;
-   Stg_Component_ConstructFunction*                    _construct = _StgFEM_SwarmVariableList_AssignFromXML;
-   Stg_Component_BuildFunction*                            _build = _Codelet_Build;
-   Stg_Component_InitialiseFunction*                  _initialise = StgFEM_SwarmVariableList_PrintVariables;
-   Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
-   Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
-
-   /* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
-   AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
-
-        return _Codelet_New(  CODELET_PASSARGS  );
-}
-
-Index StgFEM_SwarmVariableList_Register( PluginsManager* pluginsManager ) {
-        return PluginsManager_Submit( pluginsManager, StgFEM_SwarmVariableList_Type, (Name)"0", _StgFEM_SwarmVariableList_DefaultNew  );
-}
-
-void StgFEM_SwarmVariableList_PrintVariables( void* _self, void* data ){
-   StgFEM_SwarmVariableList* self    = (StgFEM_SwarmVariableList*)_self;
-   AbstractContext*          context = self->context;
-   Stream*                   stream  = self->stream;;
-   Index                     swarmCount;
-   Index                     variablecount;
-   Index                     countindex;
-   Index                     swarmcountindex;
-   Index                     columnWidth     = 40;
-   Swarm*                    currentSwarm;
-   
-   /** print header material **/
-   Journal_Printf( stream, "\n");
-   Journal_PrintString_WithLength( stream, "SwarmVariable", columnWidth );
-   Journal_PrintString_WithLength( stream, "Swarm", columnWidth );
-   Journal_Printf( stream, "\n");
-   Journal_PrintString_WithLength( stream, "------------------------", columnWidth );
-   Journal_PrintString_WithLength( stream, "------------------------", columnWidth );
-   Journal_Printf( stream, "\n");
-   
-   /** get total number of different swarms **/
-   swarmCount  = self->swarmRegister->swarmList->count;
-   
-   /** print swarm variables **/
-   for(swarmcountindex = 0; swarmcountindex < swarmCount; ++swarmcountindex){
-          currentSwarm = (Swarm*)Stg_ComponentFactory_ConstructByName( context->CF, (Name)self->swarmRegister->swarmList->data[swarmcountindex]->name, Swarm, True, NULL );
-          variablecount = currentSwarm->swarmVariable_Register->objects->count;
-          for(countindex = 0; countindex < variablecount; ++countindex ){
-                  Journal_PrintString_WithLength( stream, currentSwarm->swarmVariable_Register->objects->data[ countindex ]->name, columnWidth );
-                  Journal_PrintString_WithLength( stream, self->swarmRegister->swarmList->data[swarmcountindex]->name, columnWidth );
-                  Journal_Printf( stream, "\n");
-          }
-   }
-   Journal_Printf( stream, "\n");
-}
-
-
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/Output/SwarmVariableList/SwarmVariableList.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/Output/SwarmVariableList/SwarmVariableList.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,152 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**      Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**      Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**      Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**      Monash Cluster Computing - http://www.mcc.monash.edu.au
+**      Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**      Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**      Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**      Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**      David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**      Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**      Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**      Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**      Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**      Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**      Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+
+#include "SwarmVariableList.h"
+
+#ifndef MASTER
+        #define MASTER 0
+#endif
+
+const Type StgFEM_SwarmVariableList_Type = "StgFEM_SwarmVariableList";
+
+void _StgFEM_SwarmVariableList_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
+        StgFEM_SwarmVariableList* self         = (StgFEM_SwarmVariableList*) component;
+        AbstractContext*                context;
+        Dictionary*                     dictionary;
+        Stream*                         stream;
+        Name                            swarmVariableListFilename;
+        Bool                            fileOpened;
+        Bool                            PrintToFile;
+
+        self->context       = context = (AbstractContext*)Stg_ComponentFactory_ConstructByName( cf, (Name)"context", AbstractContext, True, data );
+        dictionary          = context->dictionary;
+        self->swarmRegister = Swarm_Register_GetSwarm_Register( );
+
+        /** create stream **/
+        stream = self->stream = Journal_Register( InfoStream_Type, (Name)"SwarmVariableList"  );
+
+        /** set auto flush on stream **/
+        Stream_SetAutoFlush( stream, True );
+
+        /** print to screen or to file? **/
+        PrintToFile = Dictionary_GetBool_WithDefault( dictionary, (Dictionary_Entry_Key)"SwarmVariableListPrintToFile", True );
+        if(PrintToFile ){
+                /** get name of SwarmVariable list file **/
+                swarmVariableListFilename = Dictionary_GetString_WithDefault( dictionary, "SwarmVariableListFilename", "SwarmVariables.list" );
+                /** open new file **/
+                if ( context->rank == MASTER ) {
+                        Stream* errorStream = Journal_Register( Error_Type, (Name)CURR_MODULE_NAME  );
+                        fileOpened          = Stream_RedirectFile_WithPrependedPath( stream, context->outputPath, swarmVariableListFilename );
+                        Journal_Firewall( fileOpened, errorStream,
+                                        "Could not open file %s/%s. Possibly directory %s does not exist or is not writable.\n"
+                                        "Check 'outputPath' in input file.\n", context->outputPath, swarmVariableListFilename, context->outputPath );
+                }
+                /** set it so only master processor can print to stream **/
+                Stream_SetPrintingRank( stream, MASTER );
+        }
+}
+
+void* _StgFEM_SwarmVariableList_DefaultNew( Name name ) {
+   /* Variables set in this function */
+   SizeT                                              _sizeOfSelf = sizeof(StgFEM_SwarmVariableList);
+   Type                                                      type = StgFEM_SwarmVariableList_Type;
+   Stg_Class_DeleteFunction*                              _delete = _Codelet_Delete;
+   Stg_Class_PrintFunction*                                _print = _Codelet_Print;
+   Stg_Class_CopyFunction*                                  _copy = _Codelet_Copy;
+   Stg_Component_DefaultConstructorFunction*  _defaultConstructor = _StgFEM_SwarmVariableList_DefaultNew;
+   Stg_Component_ConstructFunction*                    _construct = _StgFEM_SwarmVariableList_AssignFromXML;
+   Stg_Component_BuildFunction*                            _build = _Codelet_Build;
+   Stg_Component_InitialiseFunction*                  _initialise = StgFEM_SwarmVariableList_PrintVariables;
+   Stg_Component_ExecuteFunction*                        _execute = _Codelet_Execute;
+   Stg_Component_DestroyFunction*                        _destroy = _Codelet_Destroy;
+
+   /* Variables that are set to ZERO are variables that will be set either by the current _New function or another parent _New function further up the hierachy */
+   AllocationType  nameAllocationType = NON_GLOBAL /* default value NON_GLOBAL */;
+
+        return _Codelet_New(  CODELET_PASSARGS  );
+}
+
+Index StgFEM_SwarmVariableList_Register( PluginsManager* pluginsManager ) {
+        return PluginsManager_Submit( pluginsManager, StgFEM_SwarmVariableList_Type, (Name)"0", _StgFEM_SwarmVariableList_DefaultNew  );
+}
+
+void StgFEM_SwarmVariableList_PrintVariables( void* _self, void* data ){
+   StgFEM_SwarmVariableList* self    = (StgFEM_SwarmVariableList*)_self;
+   AbstractContext*          context = self->context;
+   Stream*                   stream  = self->stream;;
+   Index                     swarmCount;
+   Index                     variablecount;
+   Index                     countindex;
+   Index                     swarmcountindex;
+   Index                     columnWidth     = 40;
+   Swarm*                    currentSwarm;
+   
+   /** print header material **/
+   Journal_Printf( stream, "\n");
+   Journal_PrintString_WithLength( stream, "SwarmVariable", columnWidth );
+   Journal_PrintString_WithLength( stream, "Swarm", columnWidth );
+   Journal_Printf( stream, "\n");
+   Journal_PrintString_WithLength( stream, "------------------------", columnWidth );
+   Journal_PrintString_WithLength( stream, "------------------------", columnWidth );
+   Journal_Printf( stream, "\n");
+   
+   /** get total number of different swarms **/
+   swarmCount  = self->swarmRegister->swarmList->count;
+   
+   /** print swarm variables **/
+   for(swarmcountindex = 0; swarmcountindex < swarmCount; ++swarmcountindex){
+          currentSwarm = (Swarm*)Stg_ComponentFactory_ConstructByName( context->CF, (Name)self->swarmRegister->swarmList->data[swarmcountindex]->name, Swarm, True, NULL );
+          variablecount = currentSwarm->swarmVariable_Register->objects->count;
+          for(countindex = 0; countindex < variablecount; ++countindex ){
+                  Journal_PrintString_WithLength( stream, currentSwarm->swarmVariable_Register->objects->data[ countindex ]->name, columnWidth );
+                  Journal_PrintString_WithLength( stream, self->swarmRegister->swarmList->data[swarmcountindex]->name, columnWidth );
+                  Journal_Printf( stream, "\n");
+          }
+   }
+   Journal_Printf( stream, "\n");
+}
+
+
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/StandardConditionFunctions/StandardConditionFunctions.c
--- a/plugins/StandardConditionFunctions/StandardConditionFunctions.c	Wed May 11 14:43:33 2011 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2841 +0,0 @@
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-**
-** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
-**	Melbourne, 3053, Australia.
-**
-** Primary Contributing Organisations:
-**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
-**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
-**	Monash Cluster Computing - http://www.mcc.monash.edu.au
-**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
-**
-** Contributors:
-**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
-**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
-**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
-**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
-**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
-**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
-**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
-**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
-**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
-**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
-**
-**  This library is free software; you can redistribute it and/or
-**  modify it under the terms of the GNU Lesser General Public
-**  License as published by the Free Software Foundation; either
-**  version 2.1 of the License, or (at your option) any later version.
-**
-**  This library is distributed in the hope that it will be useful,
-**  but WITHOUT ANY WARRANTY; without even the implied warranty of
-**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-**  Lesser General Public License for more details.
-**
-**  You should have received a copy of the GNU Lesser General Public
-**  License along with this library; if not, write to the Free Software
-**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-**
-** $Id: StandardConditionFunctions.c 1196 2008-08-04 16:29:30Z LukeHodkinson $
-**
-**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-#include <string.h>
-#include <mpi.h>
-#include <StGermain/StGermain.h>
-#include <StgDomain/StgDomain.h>
-#include <StgFEM/StgFEM.h>
-#include <assert.h>
-#include "StandardConditionFunctions.h"
-#include "muParser.h"
-
-const Type StgFEM_StandardConditionFunctions_Type = "StgFEM_StandardConditionFunctions";
-
-void _StgFEM_StandardConditionFunctions_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
-  Codelet*		self		= (Codelet*)component;
-  AbstractContext*        context;
-  ConditionFunction*      condFunc;
-  Dictionary*		pluginDict	= Codelet_GetPluginDictionary( component, cf->rootDict );
-
-  context = (AbstractContext*)Stg_ComponentFactory_ConstructByName( cf, Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"Context"  ), AbstractContext, True, data );
-  self->context = context;
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SolidBodyRotation, "Velocity_SolidBodyRotation"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_PartialRotationX, "Velocity_PartialRotationX"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-		
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_PartialRotationY, "Velocity_PartialRotationY"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_TaperedRotationX, "TaperedRotationX" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-		
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_TaperedRotationY, "TaperedRotationY" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SimpleShear, "Velocity_SimpleShear" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SimpleShearInverted, "Velocity_SimpleShearInverted" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ShearZ, "ShearZ" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_Extension, "Velocity_Extension" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_PartialLid_TopLayer, "Velocity_PartialLid_TopLayer"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_Trigonometry, "Temperature_Trigonometry"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_LinearInterpolationLid, "Velocity_LinearInterpolationLid"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_Lid_RampWithCentralMax, "Velocity_Lid_RampWithCentralMax"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_LinearVelocityLeftWall, "LinearVelocityLeftWall"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_LinearVelocityRightWall, "LinearVelocityRightWall"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SinusoidalLid, "Velocity_SinusoidalLid"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_CornerOnly, "Velocity_Lid_CornerOnly"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_TemperatureCosineHill, "Temperature_CosineHill"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ConvectionBenchmark, "Temperature_ConvectionBenchmark"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_LinearWithSinusoidalPerturbation, "LinearWithSinusoidalPerturbation"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_EdgeDriveConvectionIC, "EdgeDriveConvectionIC"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ThermalEdgeDriveConvectionIC, "ThermalEdgeDriveConvectionIC"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_AnalyticalTemperatureIC, "AnalyticalTemperatureIC"  );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New( Stg_FEM_VelicTemperatureIC, "VelicTemperatureIC" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New( Stg_FEM_VelicTemperatureIC_SolB, "VelicTemperatureIC_SolB" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-	
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SinusoidalExtension, "SinusoidalExtension" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_StepFunction, "StepFunction" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_StepFunctionProduct1, "StepFunctionProduct1");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_StepFunctionProduct2, "StepFunctionProduct2");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_StepFunctionProduct3, "StepFunctionProduct3");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_StepFunctionProduct4, "StepFunctionProduct4");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_TemperatureProfile, "TemperatureProfile");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_Gaussian, "Gaussian");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_ERF,
-                                   (char*)"ERF");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_ERFC,
-                                   (char*)"ERFC");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_RubberSheet,
-                                   (char*)"RubberSheet");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_MovingStepFunction, "MovingStepFunction");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpecRidge3D, "SpecRidge3D" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralBCX, "SpectralBCX" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralBCY, "SpectralBCY" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralBCZ, "SpectralBCZ" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralPressureBCX, "SpectralPressureBCX" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralPressureBCY, "SpectralPressureBCY" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ErrorFunc, "ErrorFunc" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ConstantVector, "ConstantVector" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_GaussianDistribution, "GaussianDistribution" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_1DGaussianDistribution, "1DGaussianDistribution" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_HalfContainer, "HalfContainer" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ConstantValue, "ConstantValue" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_DiagonalLine, "DiagonalLine" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_DeltaFunction, "DeltaFunction" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_InflowBottom, "InflowBottom" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_GaussianTube, "GaussianTube" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_GravitationalPotential, "GravitationalPotential" );
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_WarsTemperature,
-                                   "WarsTemperature");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_Quadratic,
-                                   "Quadratic");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File1,
-                                   "File1");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File2,
-                                   "File2");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File3,
-                                   "File3");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File4,
-                                   "File4");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File5,
-                                   "File5");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File6,
-                                   "File6");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File7,
-                                   "File7");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File8,
-                                   "File8");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File9,
-                                   "File9");
-  ConditionFunction_Register_Add( condFunc_Register, condFunc );
-  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File10,
-                                   "File10");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation1,
-                                 "Equation1");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation2,
-                                 "Equation2");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation3,
-                                 "Equation3");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation4,
-                                 "Equation4");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation5,
-                                 "Equation5");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation6,
-                                 "Equation6");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation7,
-                                 "Equation7");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation8,
-                                 "Equation8");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation9,
-                                 "Equation9");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation10,
-                                 "Equation10");
-  ConditionFunction_Register_Add(condFunc_Register,condFunc);
-}
-
-void _StgFEM_StandardConditionFunctions_Destroy( void* _self, void* data ) {
-   /* This function will totally clean the condFunc_Register
-    *
-    * This could be trouble some if other code adds or deletes condition functions on this register
-    */
-
-   unsigned *refCount = &(condFunc_Register->count);
-
-   /* first check if there are things still on the condFunc_Register, if so .... */
-   if( *refCount != 0 ) {
-      while( *refCount != 0 ) {
-
-         _ConditionFunction_Delete( condFunc_Register->_cf[ *refCount-1 ] );
-         condFunc_Register->_cf[ *refCount-1 ] = NULL;
-
-         *refCount = *refCount - 1;
-      }
-   }
-   _Codelet_Destroy( _self, data );
-}
-void* _StgFEM_StandardConditionFunctions_DefaultNew( Name name ) {
-	return Codelet_New(
-		StgFEM_StandardConditionFunctions_Type,
-		_StgFEM_StandardConditionFunctions_DefaultNew,
-		_StgFEM_StandardConditionFunctions_AssignFromXML,
-		_Codelet_Build,
-		_Codelet_Initialise,
-		_Codelet_Execute,
-		_StgFEM_StandardConditionFunctions_Destroy,
-		name );
-}
-
-Index StgFEM_StandardConditionFunctions_Register( PluginsManager* pluginsManager ) {
-	Journal_DPrintf( StgFEM_Debug, "In: %s( void* )\n", __func__ );
-
-	return PluginsManager_Submit( pluginsManager, StgFEM_StandardConditionFunctions_Type, (Name)"0", _StgFEM_StandardConditionFunctions_DefaultNew  );
-}
-
-Bool StgFEM_StandardConditionFunctions_Init( int* argc, char** argv[] ) {
-  Stg_ComponentRegister* componentsRegister = Stg_ComponentRegister_Get_ComponentRegister();
-  Stg_ComponentRegister_Add(componentsRegister,
-                            StgFEM_StandardConditionFunctions_Type, (Name)"0",
-                            _StgFEM_StandardConditionFunctions_DefaultNew );
-  RegisterParent( StgFEM_StandardConditionFunctions_Type, Stg_Component_Type );
-  return True;
-}
-
-#ifdef NO_ERF
-
-/* Copied from the OpenBSD iplementation of erf.c
-   (src/lib/libm/src/erf.c and src/lib/libm/src/math_private.h).
-   Modified to only work on 32 bit little endian machines.
-   This is just a hack for Windows machines. */
-
-/* @(#)s_erf.c 5.1 93/09/24 */
-/*
- * ====================================================
- * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
- *
- * Developed at SunPro, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice 
- * is preserved.
- * ====================================================
- */
-
-/* double erf(double x)
- * double erfc(double x)
- *                           x
- *                    2      |\
- *     erf(x)  =  ---------  | exp(-t*t)dt
- *                  sqrt(pi) \| 
- *                           0
- *
- *     erfc(x) =  1-erf(x)
- *  Note that 
- *              erf(-x) = -erf(x)
- *              erfc(-x) = 2 - erfc(x)
- *
- * Method:
- *      1. For |x| in [0, 0.84375]
- *          erf(x)  = x + x*R(x^2)
- *          erfc(x) = 1 - erf(x)           if x in [-.84375,0.25]
- *                  = 0.5 + ((0.5-x)-x*R)  if x in [0.25,0.84375]
- *         where R = P/Q where P is an odd poly of degree 8 and
- *         Q is an odd poly of degree 10.
- *                                               -57.90
- *                      | R - (erf(x)-x)/x | <= 2
- *      
- *
- *         Remark. The formula is derived by noting
- *          erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
- *         and that
- *          2/sqrt(pi) = 1.128379167095512573896158903121545171688
- *         is close to one. The interval is chosen because the fix
- *         point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
- *         near 0.6174), and by some experiment, 0.84375 is chosen to
- *         guarantee the error is less than one ulp for erf.
- *
- *      2. For |x| in [0.84375,1.25], let s = |x| - 1, and
- *         c = 0.84506291151 rounded to single (24 bits)
- *              erf(x)  = sign(x) * (c  + P1(s)/Q1(s))
- *              erfc(x) = (1-c)  - P1(s)/Q1(s) if x > 0
- *                        1+(c+P1(s)/Q1(s))    if x < 0
- *              |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
- *         Remark: here we use the taylor series expansion at x=1.
- *              erf(1+s) = erf(1) + s*Poly(s)
- *                       = 0.845.. + P1(s)/Q1(s)
- *         That is, we use rational approximation to approximate
- *                      erf(1+s) - (c = (single)0.84506291151)
- *         Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
- *         where 
- *              P1(s) = degree 6 poly in s
- *              Q1(s) = degree 6 poly in s
- *
- *      3. For x in [1.25,1/0.35(~2.857143)], 
- *              erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
- *              erf(x)  = 1 - erfc(x)
- *         where 
- *              R1(z) = degree 7 poly in z, (z=1/x^2)
- *              S1(z) = degree 8 poly in z
- *
- *      4. For x in [1/0.35,28]
- *              erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
- *                      = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
- *                      = 2.0 - tiny                (if x <= -6)
- *              erf(x)  = sign(x)*(1.0 - erfc(x)) if x < 6, else
- *              erf(x)  = sign(x)*(1.0 - tiny)
- *         where
- *              R2(z) = degree 6 poly in z, (z=1/x^2)
- *              S2(z) = degree 7 poly in z
- *
- *      Note1:
- *         To compute exp(-x*x-0.5625+R/S), let s be a single
- *         precision number and s := x; then
- *              -x*x = -s*s + (s-x)*(s+x)
- *              exp(-x*x-0.5626+R/S) = 
- *                      exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
- *      Note2:
- *         Here 4 and 5 make use of the asymptotic series
- *                        exp(-x*x)
- *              erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
- *                        x*sqrt(pi)
- *         We use rational approximation to approximate
- *              g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
- *         Here is the error bound for R1/S1 and R2/S2
- *              |R1/S1 - f(x)|  < 2**(-62.57)
- *              |R2/S2 - f(x)|  < 2**(-61.52)
- *
- *      5. For inf > x >= 28
- *              erf(x)  = sign(x) *(1 - tiny)  (raise inexact)
- *              erfc(x) = tiny*tiny (raise underflow) if x > 0
- *                      = 2 - tiny if x<0
- *
- *      7. Special case:
- *              erf(0)  = 0, erf(inf)  = 1, erf(-inf) = -1,
- *              erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, 
- *                 erfc/erf(NaN) is NaN
- */
-
-/*  Assume little endian, 32 bit machines  */
-
-typedef int int32_t;
-typedef unsigned int u_int32_t;
-
-typedef union
-{
-  double value;
-  struct
-  {
-    u_int32_t lsw;
-    u_int32_t msw;
-  } parts;
-} ieee_double_shape_type;
-
-/* Get the more significant 32 bit int from a double.  */
-
-#define GET_HIGH_WORD(i,d)                                      \
-do {                                                            \
-  ieee_double_shape_type gh_u;                                  \
-  gh_u.value = (d);                                             \
-  (i) = gh_u.parts.msw;                                         \
-} while (0)
-
-/* Set the less significant 32 bits of a double from an int.  */
-
-#define SET_LOW_WORD(d,v)                                       \
-do {                                                            \
-  ieee_double_shape_type sl_u;                                  \
-  sl_u.value = (d);                                             \
-  sl_u.parts.lsw = (v);                                         \
-  (d) = sl_u.value;                                             \
-} while (0)
-
-
-static const double
-tiny        = 1e-300,
-half=  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
-one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
-two =  2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
-        /* c = (float)0.84506291151 */
-erx =  8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */
-/*
- * Coefficients for approximation to  erf on [0,0.84375]
- */
-efx =  1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */
-efx8=  1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */
-pp0  =  1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */
-pp1  = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */
-pp2  = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */
-pp3  = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */
-pp4  = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */
-qq1  =  3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */
-qq2  =  6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */
-qq3  =  5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */
-qq4  =  1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */
-qq5  = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */
-/*
- * Coefficients for approximation to  erf  in [0.84375,1.25] 
- */
-pa0  = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */
-pa1  =  4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */
-pa2  = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */
-pa3  =  3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */
-pa4  = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */
-pa5  =  3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */
-pa6  = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */
-qa1  =  1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */
-qa2  =  5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */
-qa3  =  7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */
-qa4  =  1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */
-qa5  =  1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */
-qa6  =  1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */
-/*
- * Coefficients for approximation to  erfc in [1.25,1/0.35]
- */
-ra0  = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */
-ra1  = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */
-ra2  = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */
-ra3  = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */
-ra4  = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */
-ra5  = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */
-ra6  = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */
-ra7  = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */
-sa1  =  1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */
-sa2  =  1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */
-sa3  =  4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */
-sa4  =  6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */
-sa5  =  4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */
-sa6  =  1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */
-sa7  =  6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */
-sa8  = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */
-/*
- * Coefficients for approximation to  erfc in [1/.35,28]
- */
-rb0  = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */
-rb1  = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */
-rb2  = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */
-rb3  = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */
-rb4  = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */
-rb5  = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */
-rb6  = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */
-sb1  =  3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */
-sb2  =  3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */
-sb3  =  1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */
-sb4  =  3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */
-sb5  =  2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */
-sb6  =  4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */
-sb7  = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */
-
-double
-erf(double x) 
-{
-        int32_t hx,ix,i;
-        double R,S,P,Q,s,y,z,r;
-        GET_HIGH_WORD(hx,x);
-        ix = hx&0x7fffffff;
-        if(ix>=0x7ff00000) {                /* erf(nan)=nan */
-            i = ((u_int32_t)hx>>31)<<1;
-            return (double)(1-i)+one/x;        /* erf(+-inf)=+-1 */
-        }
-
-        if(ix < 0x3feb0000) {                /* |x|<0.84375 */
-            if(ix < 0x3e300000) {         /* |x|<2**-28 */
-                if (ix < 0x00800000) 
-                    return 0.125*(8.0*x+efx8*x);  /*avoid underflow */
-                return x + efx*x;
-            }
-            z = x*x;
-            r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
-            s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
-            y = r/s;
-            return x + x*y;
-        }
-        if(ix < 0x3ff40000) {                /* 0.84375 <= |x| < 1.25 */
-            s = fabs(x)-one;
-            P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
-            Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
-            if(hx>=0) return erx + P/Q; else return -erx - P/Q;
-        }
-        if (ix >= 0x40180000) {                /* inf>|x|>=6 */
-            if(hx>=0) return one-tiny; else return tiny-one;
-        }
-        x = fabs(x);
-        s = one/(x*x);
-        if(ix< 0x4006DB6E) {        /* |x| < 1/0.35 */
-            R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
-                                ra5+s*(ra6+s*ra7))))));
-            S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
-                                sa5+s*(sa6+s*(sa7+s*sa8)))))));
-        } else {        /* |x| >= 1/0.35 */
-            R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
-                                rb5+s*rb6)))));
-            S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
-                                sb5+s*(sb6+s*sb7))))));
-        }
-        z  = x;  
-        SET_LOW_WORD(z,0);
-        r  =  exp(-z*z-0.5625)*exp((z-x)*(z+x)+R/S);
-        if(hx>=0) return one-r/x; else return  r/x-one;
-}
-
-double
-erfc(double x) 
-{
-        int32_t hx,ix;
-        double R,S,P,Q,s,y,z,r;
-        GET_HIGH_WORD(hx,x);
-        ix = hx&0x7fffffff;
-        if(ix>=0x7ff00000) {                        /* erfc(nan)=nan */
-                                                /* erfc(+-inf)=0,2 */
-            return (double)(((u_int32_t)hx>>31)<<1)+one/x;
-        }
-
-        if(ix < 0x3feb0000) {                /* |x|<0.84375 */
-            if(ix < 0x3c700000)          /* |x|<2**-56 */
-                return one-x;
-            z = x*x;
-            r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
-            s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
-            y = r/s;
-            if(hx < 0x3fd00000) {          /* x<1/4 */
-                return one-(x+x*y);
-            } else {
-                r = x*y;
-                r += (x-half);
-                return half - r ;
-            }
-        }
-        if(ix < 0x3ff40000) {                /* 0.84375 <= |x| < 1.25 */
-            s = fabs(x)-one;
-            P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
-            Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
-            if(hx>=0) {
-                z  = one-erx; return z - P/Q; 
-            } else {
-                z = erx+P/Q; return one+z;
-            }
-        }
-        if (ix < 0x403c0000) {                /* |x|<28 */
-            x = fabs(x);
-            s = one/(x*x);
-            if(ix< 0x4006DB6D) {        /* |x| < 1/.35 ~ 2.857143*/
-                R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
-                                ra5+s*(ra6+s*ra7))))));
-                S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
-                                sa5+s*(sa6+s*(sa7+s*sa8)))))));
-            } else {                        /* |x| >= 1/.35 ~ 2.857143 */
-                if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */
-                R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
-                                rb5+s*rb6)))));
-                S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
-                                sb5+s*(sb6+s*sb7))))));
-            }
-            z  = x;
-            SET_LOW_WORD(z,0);
-            r  =  exp(-z*z-0.5625)*
-                        exp((z-x)*(z+x)+R/S);
-            if(hx>0) return r/x; else return two-r/x;
-        } else {
-            if(hx>0) return tiny*tiny; else return two-tiny;
-        }
-}
-
-#endif
-
-
-void StgFEM_StandardConditionFunctions_SolidBodyRotation( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	Coord                   centre;
-	Coord                   vector;
-	double                  omega;
-	
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-
-	/* Find Centre of Solid Body Rotation */
-	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreX", 0.0  );
-	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreY", 0.0  );
-	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ", 0.0  );
-	omega            = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationOmega", 1.0  );
-
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	/* Find vector from centre to node */
-	StGermain_VectorSubtraction( vector, coord, centre, 2 );
-
-	result[ I_AXIS ] = -omega * vector[ J_AXIS ];
-	result[ J_AXIS ] =  omega * vector[ I_AXIS ];
-}
-
-
-void StgFEM_StandardConditionFunctions_PartialRotationX( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	Coord                   centre;
-	Coord                   vector;
-	double                  omega;
-	double			size;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-
-	/* Find Centre of Solid Body Rotation */
-	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreX", 0.0  );
-	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreY", 0.0  );
-	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ", 0.0  );
-	size             = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"RadiusCylinder", 0.0  );
-	omega            = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationOmega", 1.0  );
-
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	/* Find vector from centre to node */
-	StGermain_VectorSubtraction( vector, coord, centre, 2 );
-
-	/*if (context->currentTime > 1.33e-6)
-	  omega=0.0;*/
-	
-	if ((vector[ I_AXIS ]*vector[ I_AXIS ]+vector[ J_AXIS ]*vector[ J_AXIS ])<=size*size)
-		*result = -omega * vector[ J_AXIS ];
-	else
-		*result = 0.0;
-}
-
-void StgFEM_StandardConditionFunctions_PartialRotationY( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	Coord                   centre;
-	Coord                   vector;
-	double                  omega;
-	double			size;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-
-	/* Find Centre of Solid Body Rotation */
-	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreX", 0.0  );
-	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreY", 0.0  );
-	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ", 0.0  );
-	size             = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"RadiusCylinder", 0.0  );
-	omega            = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationOmega", 1.0  );
-
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	/* Find vector from centre to node */
-	StGermain_VectorSubtraction( vector, coord, centre, 2 );
-	
-	if ((vector[ I_AXIS ]*vector[ I_AXIS ]+vector[ J_AXIS ]*vector[ J_AXIS ])<=size*size)
-		*result =  omega * vector[ I_AXIS ];
-	else 
-		*result = 0.0;
-}
-
-
-void StgFEM_StandardConditionFunctions_TaperedRotationX( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	Coord                   centre;
-	Coord                   vector;
-	double                  omega;
-	double			size, r, taper;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-
-	/* Find Centre of Solid Body Rotation */
-	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreX", 0.0 );
-	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreY", 0.0 );
-	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreZ", 0.0 );
-	size             = Dictionary_GetDouble_WithDefault( dictionary, "RadiusCylinder", 0.0 );
-	omega            = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationOmega",   1.0 );
-
-	taper            = Dictionary_GetDouble_WithDefault( dictionary, "TaperedRadius",   0.0 );
-
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	/* Find vector from centre to node */
-	StGermain_VectorSubtraction( vector, coord, centre, 2 );
-
-        r=sqrt(vector[ I_AXIS ]*vector[ I_AXIS ]
-               +vector[ J_AXIS ]*vector[ J_AXIS ]);
-	if (r<=size)
-          *result = -omega * vector[ J_AXIS ];
-	else if(r<=taper)
-          *result = -omega * vector[ J_AXIS ]*(taper-r)/(taper-size);
-        else
-          *result = 0;
-}
-
-void StgFEM_StandardConditionFunctions_TaperedRotationY( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	Coord                   centre;
-	Coord                   vector;
-	double                  omega;
-	double			size, r, taper;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-
-	/* Find Centre of Solid Body Rotation */
-	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreX", 0.0 );
-	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreY", 0.0 );
-	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreZ", 0.0 );
-	size             = Dictionary_GetDouble_WithDefault( dictionary, "RadiusCylinder", 0.0 );
-	omega            = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationOmega",   1.0 );
-
-	taper            = Dictionary_GetDouble_WithDefault( dictionary, "TaperedRadius",   0.0 );
-
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	/* Find vector from centre to node */
-	StGermain_VectorSubtraction( vector, coord, centre, 2 );
-
-
-        r=sqrt(vector[ I_AXIS ]*vector[ I_AXIS ]
-               +vector[ J_AXIS ]*vector[ J_AXIS ]);
-	if (r<=size)
-          *result = omega * vector[ I_AXIS ];
-	else if(r<=taper)
-          *result = omega * vector[ I_AXIS ]*(taper-r)/(taper-size);
-        else
-          *result = 0;
-}
-
-
-
-
-void StgFEM_StandardConditionFunctions_SimpleShear( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	double                  centre;
-	double                  factor;
-	
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-
-	/* Find Centre of Solid Body Rotation */
-	centre = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SimpleShearCentreY", 0.0  );
-	factor = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SimpleShearFactor", 1.0  );
-
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	*result = factor * (coord[ J_AXIS ] - centre);
-}
-
-void StgFEM_StandardConditionFunctions_ShearZ( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	double                  centre;
-	double                  factor;
-	
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-
-	/* Find Centre of Solid Body Rotation */
-	centre = Dictionary_GetDouble_WithDefault( dictionary, "ShearZCentre", 0.0 );
-	factor = Dictionary_GetDouble_WithDefault( dictionary, "ShearZFactor", 1.0 );
-
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	*result = factor * (coord[ K_AXIS ] - centre);
-}
-
-void StgFEM_StandardConditionFunctions_SimpleShearInverted( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-        DomainContext*  context            = (DomainContext*)_context;
-        Dictionary*             dictionary         = context->dictionary;
-        FeVariable*             feVariable         = NULL;
-        FeMesh*                 mesh               = NULL;
-        double*                 result             = (double*) _result;
-        double*                 coord;
-        double                  centre;
-        double                  factor;
-        double                  yAxisInvert;
-
-        feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-        mesh       = feVariable->feMesh;
-
-        /* Find Centre of Solid Body Rotation */
-        centre = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SimpleShearCentreY", 0.0  );
-        factor = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SimpleShearFactor", 1.0  );
-
-        /* Find coordinate of node */
-        coord = Mesh_GetVertex( mesh, node_lI );
-
-        yAxisInvert = coord[ J_AXIS ] * -1.0 - 1.0;
-
-        *result = factor * ( 1.0 - coord[ J_AXIS ] ) ;
-}
-
-
-void StgFEM_StandardConditionFunctions_Extension( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	double                  centre;
-	double                  factor;
-	
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-
-	/* Find Centre of Solid Body Rotation */
-	centre = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ExtensionCentreX", 0.0  );
-	factor = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ExtensionFactor", 1.0  );
-
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( mesh, node_lI );
-
-	*result = factor * (coord[ I_AXIS ] - centre);
-}
-
-
-void StgFEM_StandardConditionFunctions_PartialLid_TopLayer( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	FeVariable*             velVar = NULL;
-	FeMesh*			mesh = NULL;
-	double*			velResult = (double*)result;
-	double                  margin = 0;
-	double			min[3], max[3];
-	
-	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh = velVar->feMesh;
-
-	Mesh_GetMinimumSeparation( mesh, &margin, NULL );
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	margin *= 1.1;
-	if( (Mesh_GetVertex( mesh, node_lI )[I_AXIS] < (max[I_AXIS] - margin )) && 
-	    (Mesh_GetVertex( mesh, node_lI )[I_AXIS] > (min[I_AXIS] + margin )))
-	{
-		(*velResult) = 1;
-	}
-	else {
-		(*velResult) = 0;
-	}
-}
-
-void StgFEM_StandardConditionFunctions_LinearInterpolationLid( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	FeVariable*             velVar = NULL;
-	FeMesh*			mesh = NULL;
-	double*			velResult = (double*)result;
-	double			boxLength = 0;
-	double			leftHandSideValue = 0;
-	double			rightHandSideValue = 0;
-	double			gradient = 0;
-	double			min[3], max[3];
-	
-	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh = velVar->feMesh;
-
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	boxLength = max[I_AXIS] - min[I_AXIS];
-	leftHandSideValue = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"bcLeftHandSideValue", 0.0  );
-	rightHandSideValue = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"bcRightHandSideValue", 1.0 );
-	gradient = (rightHandSideValue - leftHandSideValue) / boxLength;
-	(*velResult ) = leftHandSideValue + gradient * (Mesh_GetVertex( mesh, node_lI )[I_AXIS] - min[I_AXIS] );
-}
-
-
-void StgFEM_StandardConditionFunctions_Lid_RampWithCentralMax( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	FeVariable*             velVar = NULL;
-	FeMesh*			mesh = NULL;
-	double*			velResult = (double*)result;
-	double			boxLength = 0;
-	double			xPosRelativeToTopLeft = 0;
-	double			min[3], max[3];
-	
-	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh = velVar->feMesh;
-
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	xPosRelativeToTopLeft = Mesh_GetVertex( mesh, node_lI )[I_AXIS] - min[I_AXIS];
-	boxLength = max[I_AXIS] - min[I_AXIS];
-	if ( xPosRelativeToTopLeft < boxLength / 2 ) {
-		(*velResult) =  2 * xPosRelativeToTopLeft / boxLength;
-	}
-	else {
-		(*velResult) = 1 - 2 * ( xPosRelativeToTopLeft - (boxLength/2) );
-	}
-}
-void StgFEM_StandardConditionFunctions_LinearVelocityLeftWall( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	FeVariable*             velVar = NULL;
-	FeMesh*			mesh = NULL;
-	double*			velResult = (double*)result;
-	Dictionary*             dictionary         = context->dictionary;
-	double			min[3], max[3];
-	double			gradient, maxvel;
-	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh = velVar->feMesh;
-
-	maxvel = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"MaximumVelocity_Left", 0.0  );
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	gradient = maxvel/(min[1] - max[1]);
-	
-	(*velResult)   = gradient*Mesh_GetVertex( mesh, node_lI )[J_AXIS];
-	 //printf("Left velResult is %g\n",(*velResult));
-	 
-}
-void StgFEM_StandardConditionFunctions_LinearVelocityRightWall( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	FeVariable*             velVar = NULL;
-	FeMesh*			mesh = NULL;
-	double*			velResult = (double*)result;
-	Dictionary*             dictionary         = context->dictionary;
-	double			min[3], max[3];
-	double			gradient, maxvel;
-	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh = velVar->feMesh;
-
-	maxvel = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"MaximumVelocity_Right", 0.0  );
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	gradient = maxvel/(max[1] - min[1]);
-	 
-	(*velResult)   = maxvel - gradient*Mesh_GetVertex( mesh, node_lI )[J_AXIS];
-	//printf("Right velResult is %g\n",(*velResult));
-}
-
-
-void StgFEM_StandardConditionFunctions_SinusoidalLid( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	FeVariable*             velVar = NULL;
-	FeMesh*			mesh = NULL;
-	double*			velResult = (double*)result;
-	double			boxLength = 0;
-	double			linearInterp = 0;
-	double          	wavenumber;
-	double			min[3], max[3];
-
-	wavenumber = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"sinusoidalLidWavenumber", 1 );
-	
-	velVar = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh = velVar->feMesh;
-
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	boxLength = max[I_AXIS] - min[I_AXIS];
-	linearInterp = (Mesh_GetVertex( mesh, node_lI )[I_AXIS] - min[I_AXIS] ) / boxLength;
-	(*velResult) = sin( linearInterp * M_PI * wavenumber );
-}
-
-
-void StgFEM_StandardConditionFunctions_CornerOnly( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	FeVariable*             velVar = NULL;
-	FeMesh*			feMesh = NULL;
-	double*			velResult = (double*)result;
-	Node_GlobalIndex	node_gI = 0;
-	unsigned		inds[3];
-	Grid*			elGrid;
-
-	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	feMesh = velVar->feMesh;
-	elGrid = *(Grid**)ExtensionManager_Get( feMesh->info, feMesh, 
-						ExtensionManager_GetHandle( feMesh->info, (Name)"elGrid" )  );
-
-	node_gI = Mesh_DomainToGlobal( feMesh, MT_VERTEX, node_lI );
-	RegularMeshUtils_Node_1DTo3D( feMesh, node_gI, inds );
-	
-	if ( inds[0] == elGrid->sizes[I_AXIS] ) {
-		(*velResult) = 1;
-	}
-	else {
-		(*velResult) = 0;
-	}
-}
-
-double StGermain_CosineHillValue( double* centre, double* position, double height, double diameterAtBase, Dimension_Index dim ) {
-	double distanceFromCentre = StGermain_DistanceBetweenPoints( centre, position, dim );
-	
-	if (distanceFromCentre < diameterAtBase * 0.5 ) 
-		return height * (0.5 + 0.5 * cos( 2.0 * M_PI/diameterAtBase * distanceFromCentre ) );
-	else
-		return 0.0;
-}
-
-void StgFEM_StandardConditionFunctions_TemperatureCosineHill( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			feMesh               = NULL;
-	double*                 result             = (double*) _result;
-	Coord                   centre;
-	Coord                   rotationCentre;
-	double                  omega;
-	double                  hillHeight;
-	double                  hillDiameter;
-	
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	feMesh       = feVariable->feMesh;
-
-	/* Read values from dictionary */
-	hillHeight       = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillHeight"  , 1.0  );
-	hillDiameter     = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillDiameter", 1.0  );
-	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillCentreX" , 0.0  );
-	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillCentreY" , 0.0  );
-	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillCentreZ" , 0.0  );
-
-	if ( Dictionary_GetBool( dictionary, "RotateCosineHill" ) ) {
-		/* Assume solid body rotation */
-		rotationCentre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreX", 0.0  );
-		rotationCentre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreY", 0.0  );
-		rotationCentre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ", 0.0  );
-		omega                    = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationOmega", 1.0  );
-
-		StGermain_VectorSubtraction( centre, rotationCentre, centre, context->dim );
-		StGermain_RotateCoordinateAxis( centre, centre, K_AXIS, omega * context->currentTime );
-		StGermain_VectorAddition( centre, centre, rotationCentre, context->dim );
-	}
-
-	*result = StGermain_CosineHillValue( centre, Mesh_GetVertex( feMesh, node_lI ), hillHeight, hillDiameter, context->dim );
-}
-
-
-void StgFEM_StandardConditionFunctions_LinearWithSinusoidalPerturbation( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	FeVariable*             feVariable = NULL;
-	FeMesh*			feMesh = NULL;
-	unsigned		nDims;
-	double*                 result = (double*) _result;
-	double                  topLayerBC;
-	double                  bottomLayerBC;
-	double                  perturbationAmplitude;
-	double                  horizontalWaveNumber;
-	double                  verticalWaveNumber;
-	double                  scaleFactor;
-	double*                 coord;
-	Coord                   relScaledCoord; 
-	double			min[3], max[3], topLayerCoord, bottomLayerCoord;
-	
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	feMesh       = feVariable->feMesh;
-
-	nDims = Mesh_GetDimSize( feMesh );
-	Mesh_GetGlobalCoordRange( feMesh, min, max );
-
-	topLayerCoord = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_TopLayerCoord", max[J_AXIS]  );
-	bottomLayerCoord = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_BottomLayerCoord", min[J_AXIS]  );
-
-	topLayerBC = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_TopLayerBC", 0.0  );
-	bottomLayerBC = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_BottomLayerBC", 1.0  );
-	scaleFactor = bottomLayerBC - topLayerBC;
-	perturbationAmplitude = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_PerturbationAmplitude", 0.1  );
-	/* Note: these are both multiplied by pi, so wavenumber = 1 means the perturbation goes from 0 to pi, which is
-	 * half a full sin or cos cycle. Wavenumber = 3 means the range is 0 -> 3pi, or 1 and a half full cycles. */
-	horizontalWaveNumber = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_HorizontalWaveNumber", 1.0  );
-	verticalWaveNumber = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_VerticalWaveNumber", 1.0  );
-
-	coord = Mesh_GetVertex( feMesh, node_lI );
-
-	/* if node is outside IC shape set to 0 temperature */
-	if( coord[J_AXIS] > topLayerCoord || coord[J_AXIS] < bottomLayerCoord ) {
-		*result = 0; return ;
-	}
-
-	/* make coord relative to box bottom left corner, then scale from 0 to 1 between box min & max */
-	relScaledCoord[I_AXIS] = (coord[0] - min[0]) / (max[0] - min[0]);
-	relScaledCoord[J_AXIS] = (coord[1] - bottomLayerCoord) / (topLayerCoord - bottomLayerCoord);
-
-
-	/* Note: ok to use the 1.0 below since we've already scaled the coord to somewhere between 0 to 1 */
-	*result = topLayerBC + scaleFactor * ( 1.0 - relScaledCoord[ J_AXIS ] )
-		+ perturbationAmplitude * ( cos( horizontalWaveNumber * M_PI * coord[ I_AXIS ] )
-					    * sin( verticalWaveNumber * M_PI * relScaledCoord[ J_AXIS ] ) );
-}
-
-void StgFEM_StandardConditionFunctions_Trigonometry( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			feMesh               = NULL;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	double                  height, width;
-	double			min[3], max[3];
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	feMesh       = feVariable->feMesh;
-
-	Mesh_GetGlobalCoordRange( feMesh, min, max );
-	coord = Mesh_GetVertex( feMesh, node_lI );
-
-	/* Get Aspect Ratio */
-	height = max[ J_AXIS ] - min[ J_AXIS ];
-	width  = max[ I_AXIS ] - min[ I_AXIS ];
-	
-	*result = 1.0 - 0.5 * M_PI * coord[ J_AXIS ] * sin( M_PI * coord[ I_AXIS ]/width );
-}
-
-#define SMALL 1.0e-5
-void Stg_FEM_VelicTemperatureIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*  context            = (DomainContext*)_context;
-	FeVariable*             temperatureField   = (FeVariable*) FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	FeMesh*			feMesh               = temperatureField->feMesh;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	double                  x; 
-	double                  y;
-	double                  kx;
-	double                  ky;
-	int                     wavenumberX;
-	double                  wavenumberY;
-	double                  sigma;
-	double                  Lx;
-	double			min[3], max[3];
-	
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( feMesh, node_lI );
-	Mesh_GetGlobalCoordRange( feMesh, min, max );
-
-	/* Make sure that the box has right dimensions */
-	assert( ( max[ J_AXIS ] - min[ J_AXIS ] - 1.0 ) < SMALL );
-	Lx = max[ I_AXIS ] - min[ I_AXIS ];
-
-	x = coord[ I_AXIS ] - min[ I_AXIS ];
-	y = coord[ J_AXIS ] - min[ J_AXIS ];
-
-	wavenumberX = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberX", 1  );
-	wavenumberY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberY", 1.0  );
-	sigma = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"sigma", 1.0 );
-	
-	assert( sigma > 0.0 );
-	assert( wavenumberY > 0.0 );
-	assert( wavenumberX > 0.0 );
-	
-	kx = (double)wavenumberX * M_PI / Lx;
-	ky = (double)wavenumberY * M_PI;
-
-	*result = sigma * sin( ky * y ) * cos( kx * x  );
-}
-
-/* IC from Mirko Velic. This is the IC temperature for his solB, from his Analytic Suite. Added 22-May-2006 */
-void Stg_FEM_VelicTemperatureIC_SolB( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*  context            = (DomainContext*)_context;
-	FeVariable*             temperatureField   = (FeVariable*) FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	FeMesh*			feMesh               = temperatureField->feMesh;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	double                  x; 
-	double                  y;
-	double                  km; /*  for y-direction */
-	double                  kn; /*  for x-direction */
-	double                  wavenumberX;
-	double                  wavenumberY;
-	double                  L;
-	double                  sigma;
-	double			min[3], max[3];
-	
-	/* Find coordinate of node */
-	coord = Mesh_GetVertex( feMesh, node_lI );
-	Mesh_GetGlobalCoordRange( feMesh, min, max );
-
-	/* Make sure that the box has right dimensions */
-	assert( (max[ J_AXIS ] - min[ J_AXIS ] - 1.0 ) < SMALL );
-	L = max[ I_AXIS ] - min[ I_AXIS ];
-
-	x = coord[ I_AXIS ] - min[ I_AXIS ];
-	y = coord[ J_AXIS ] - min[ J_AXIS ];
-
-	wavenumberX = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberX", 1  );
-	wavenumberY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberY", 2.0 );
-	assert( wavenumberX != wavenumberY  );
-	sigma = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"sigma", 1.0 );
-
-	kn = wavenumberX * M_PI / L;
-/* 	 TODO: Re-write Mirko's code and/or Documentation so the input parameters for these ICs are less confusing */
-	km = wavenumberY / L;
-
-	*result = sigma * sinh( km * y ) * cos( kn * x  );
-}
-
-
-/* Initial Condition derived from Boundary Layer theory -
-   taken from P. E. van Keken, S. D. King, U. R. Schmeling, U. R. Christensen, D. Neumeister, and M.-P. Doin. A comparison of methods for the modeling of thermochemical convection. Journal of Geophysical Research, 102(B10):22477-22496, october 1997. */
-void StgFEM_StandardConditionFunctions_AnalyticalTemperatureIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			feMesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	double*                 coord;
-	double                  u0, v0, Q;
-	double                  x, y;
-	double                  RaT;
-	double                  lambda, height, width;
-	double                  Tu, Tl, Tr, Ts;
-	double			min[3], max[3];
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	feMesh       = feVariable->feMesh;
-
-	coord      = Mesh_GetVertex( feMesh, node_lI );
-	Mesh_GetGlobalCoordRange( feMesh, min, max );
-
-	/* Get Aspect Ratio */
-	height = max[ J_AXIS ] - min[ J_AXIS ];
-	width  = max[ I_AXIS ] - min[ I_AXIS ];
-	lambda = width/height;
-	
-	x = coord[ I_AXIS ] - min[ I_AXIS ];
-	y = coord[ J_AXIS ] - min[ J_AXIS ];
-	
-	/* Get thermal Rayleigh Number from Dictionary */
-	RaT = Dictionary_GetDouble( dictionary, "RaT" );
-	
-	/* Horizontal fluid velocity at upper boundary & lower boundary - Equation A3 */
-	u0 = pow( lambda , 7.0/3.0 )/ pow(1 + lambda*lambda*lambda*lambda, 2.0/3.0) * pow(0.5*RaT/sqrt(M_PI) , 2.0/3.0);
-
-	/* Vertical velocity of the upwelling and downwellings - Modified from Van Keken to match Turcotte and Shubert */
-	v0 = u0; /*lambda; */
-	
-	/* Total rate of heat flow out of the top of the cell per unit distance along the axis of the roll - Equation A3 */
-	Q = 2.0 * sqrt(M_1_PI * lambda/u0);
-	Tu = 0.5 * erf( 0.5 * ( 1 - y ) * sqrt(u0/x) );                                                      /* Equation A2a */
-	Tl = 1.0 - 0.5 * erf(0.5 * y * sqrt(u0/(lambda-x)));                                                 /* Equation A2b */
-	Tr = 0.5 + 0.5*Q/sqrt(M_PI) * sqrt(v0/(y+1)) * exp( -x*x*v0/(4*y+4) );                               /* Equation A2c */
-	Ts = 0.5 - 0.5*Q/sqrt(M_PI) * sqrt(v0/(2-y)) * exp( -(lambda - x) * (lambda - x) * v0 / (8 - 4*y) ); /* Equation A2d */
-
-	/* Equation A1 */
-	*result = Tu + Tl + Tr + Ts - 1.5;
-
-	/* Crop result */
-	if ( *result > 1.0 ) 
-		*result = 1.0;
-	else if ( *result < 0.0 ) 
-		*result = 0.0;
-	
-}
-
-void StgFEM_StandardConditionFunctions_EdgeDriveConvectionIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{        
-	DomainContext*  context = (DomainContext*)_context;        
-	Dictionary*             dictionary         = context->dictionary;        
-	FeVariable*             feVariable = NULL;        
-	FeMesh*			mesh = NULL;        
-	double*                 result = (double*) _result;        
-	double                  perturbationAmplitude;        
-	double                  thermalAnomalyOffset;        
-	double*                 coord;        
-	
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );        
-	mesh       = feVariable->feMesh;        
-	perturbationAmplitude = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_PerturbationAmplitude", 0.1  );        
-	thermalAnomalyOffset = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"thermalAnomalyOffset", 0.0  );        
-	coord = Mesh_GetVertex( mesh, node_lI );
-	
-	/* eqn 1 from S.D.King & D.L. Anderson, "Edge-drive convection", EPSL 160 (1998) 289-296 */        
-	
-	*result = 1.0 + perturbationAmplitude * sin( M_PI * coord[ J_AXIS ] ) * cos( 0.5 * M_PI * ( coord[ I_AXIS ] + thermalAnomalyOffset ) );
-}
-
-void StgFEM_StandardConditionFunctions_ThermalEdgeDriveConvectionIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result )
-{
-        DomainContext*  context = (DomainContext*)_context;
-        Dictionary*             dictionary         = context->dictionary;
-        FeVariable*             feVariable = NULL;
-        FeMesh*                 mesh = NULL;
-        double*                 result = (double*) _result;
-        double*                 coord;
-        int                     dim;
-        double                  contStartX, contEndX;
-        double                  contStartY, contEndY;
-        double                  contStartZ, contEndZ;
-        double                  minY, maxY, interiorTemp;
-
-        feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-        mesh       = feVariable->feMesh;
-        coord = Mesh_GetVertex( mesh, node_lI );
-        
-	dim = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"dim", 0.0  );
-        contStartX = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contStartX", 0.0  );
-        contEndX = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contEndX", 0.0  );
-        contStartY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contStartY", 0.0  );
-        contEndY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contEndY", 0.0  );
-        minY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"minY", 0.0  );
-        maxY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"maxY", 0.0  );
-	interiorTemp = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"interiorTemp", 1.0 );
-        if ( dim == 3  ) {
-                contStartZ = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contStartZ", 0.0  );
-                contEndZ = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contEndZ", 0.0 );
-        }
-
-        if(( coord[I_AXIS] >= contStartX && coord[ I_AXIS ] <= contEndX ) && ( coord[J_AXIS] >= contStartY && coord[ J_AXIS ] <= contEndY )) {
-                if ( dim == 3 ) {
-                        if ( coord[K_AXIS] >= contStartZ && coord[ K_AXIS ] <= contEndZ  )
-                                        *result = 0.0;
-                        else
-                                        *result = interiorTemp;
-                }
-        }
-        else
-                        *result = interiorTemp;
-}
-
-void StgFEM_StandardConditionFunctions_SinusoidalExtension( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	double                  frequency;
-	double                  vel0;
-	double                  amplitude;
-	double                  phaseShift;
-
-	frequency  = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalExtensionFrequency", 1.0  );
-	vel0       = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalExtensionVelocity", 0.0  );
-	amplitude  = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalExtensionAmplitude", 0.0  );
-	phaseShift = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalExtensionPhaseShift", 0.0 );
-
-
-	*result = vel0 + amplitude * cos( 2.0 * M_PI * frequency * (context->currentTime + context->dt - phaseShift )  );
-}
-
-
-void StgFEM_StandardConditionFunctions_StepFunction( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			feMesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double                  lower_offset, upper_offset;
-	double                  value, lower_value, upper_value;
-	unsigned		dim;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	feMesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( feMesh, node_lI );
-
-	lower_offset = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionLowerOffset", 0.0 );
-	upper_offset = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionUpperOffset", lower_offset );
-	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionValue", 0.0 );
-	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionDim", 0 );
-
-        lower_value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionLowerValue", 0.0 );
-        upper_value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionUpperValue", value );
-
-        if(dim==3)
-          {
-            dim=0;
-            coord=&(context->currentTime);
-          }
-
-        if(coord[dim] < lower_offset) {
-          *result=lower_value;
-        } else if(coord[dim] < upper_offset) {
-          *result=lower_value + 
-            (upper_value-lower_value)
-            *(coord[dim] - lower_offset)/(upper_offset-lower_offset);
-        } else {
-          *result=upper_value;
-        }
-}
-
-
-void StG_FEM_StandardConditionFunctions_StepFunctionProduct1( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*     mesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double                  start, end;
-	double                  value;
-	unsigned		dim;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( mesh, node_lI );
-
-	start = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct1Start", 0.0 );
-	end = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct1End", 0.0 );
-	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct1Value", 0.0 );
-	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionProduct1Dim", 0 );
-
-        if( coord[dim] > start && coord[dim] < end ) {
-          *result = value;
-        }
-        else {
-          *result = 0;
-        }
-}
-
-void StG_FEM_StandardConditionFunctions_StepFunctionProduct2( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*     mesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double                  start, end;
-	double                  value;
-	unsigned		dim;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( mesh, node_lI );
-
-	start = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct2Start", 0.0 );
-	end = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct2End", 0.0 );
-	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct2Value", 0.0 );
-	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionProduct2Dim", 0 );
-
-        if( coord[dim] > start && coord[dim] < end ) {
-          *result = value;
-        }
-        else {
-          *result = 0;
-        }
-}
-
-
-void StG_FEM_StandardConditionFunctions_StepFunctionProduct3( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*     mesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double                  start, end;
-	double                  value;
-	unsigned		dim;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( mesh, node_lI );
-
-	start = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct3Start", 0.0 );
-	end = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct3End", 0.0 );
-	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct3Value", 0.0 );
-	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionProduct3Dim", 1 );
-
-        if( coord[dim] > start && coord[dim] < end ) {
-          *result = value;
-        }
-        else {
-          *result = 0;
-        }
-}
-
-void StG_FEM_StandardConditionFunctions_StepFunctionProduct4( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*     mesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double                  start, end;
-	double                  value;
-	unsigned		dim;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( mesh, node_lI );
-
-	start = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct4Start", 0.0 );
-	end = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct4End", 0.0 );
-	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct4Value", 0.0 );
-	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionProduct4Dim", 1 );
-
-        if( coord[dim] > start && coord[dim] < end ) {
-          *result = value;
-        }
-        else {
-          *result = 0;
-        }
-}
-
-/* A Gaussian GaussianHeight*exp(-((GaussianCenter-x)/GaussianWidth)^2) */
-
-void StG_FEM_StandardConditionFunctions_Gaussian
-( Node_LocalIndex node_lI, Variable_Index var_I, void* _context,
-  void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*     mesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double                  center, width, height;
-	unsigned		dim;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( mesh, node_lI );
-
-        center = Dictionary_GetDouble_WithDefault( dictionary,
-                                                   "GaussianCenter", 0.0 );
-	width = Dictionary_GetDouble_WithDefault( dictionary,
-                                                  "GaussianWidth", 1.0 );
-	height = Dictionary_GetDouble_WithDefault( dictionary,
-                                                   "GaussianHeight", 1.0 );
-	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary,
-                                                     "GaussianDim", 0 );
-
-        *result=height*exp(-(center-coord[dim])*(center-coord[dim])
-                           /(width*width));
-}
-
-void StgFEM_StandardConditionFunctions_MovingStepFunction( Node_LocalIndex nodeInd, Variable_Index varInd, void* _ctx, void* _result ) {
-   FiniteElementContext* ctx = (FiniteElementContext*)_ctx;
-   FeVariable* velField;
-   FeMesh* mesh;
-   Dictionary* dict = ctx->dictionary;
-   double* result = (double*)_result;
-   double* coord, offsetLower, offsetUpper, left, right;
-   double *wallCrd, pos;
-   int dim, wallDepth;
-   unsigned ijk[3];
-   char* movingWall;
-   Grid* grid;
-
-   /*
-   ** Get the velocity field. */
-   velField = (FeVariable*)FieldVariable_Register_GetByName(
-      ctx->fieldVariable_Register, "VelocityField" );
-
-   /*
-   ** Get the mesh and the coordinate of the node. */
-   mesh = velField->feMesh;
-   coord = Mesh_GetVertex( mesh, nodeInd );
-
-   /*
-   ** Extract all the parameters we need from the dictionary. */
-   offsetLower = Dictionary_GetDouble_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionOffsetLower", 0.0  );
-   offsetUpper = Dictionary_GetDouble_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionOffsetUpper", 0.0  );
-   dim = Dictionary_GetUnsignedInt_WithDefault( dict, "MovingStepFunctionDim", 0 );
-   left = Dictionary_GetDouble_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionLeftSide", 0.0  );
-   right = Dictionary_GetDouble_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionRightSide", 0.0  );
-   movingWall = Dictionary_GetString_WithDefault( dict, "MovingStepFunctionMovingWall", "lower" );
-   wallDepth = Dictionary_GetInt_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionWallDepth", 0  );
-
-   /*
-   ** Because we're dealing with a moving step function, we need to calculate
-   ** from where the offset should be applied. */
-   grid = *(Grid**)Mesh_GetExtension( mesh, Grid**, "vertexGrid" );
-   assert( grid );
-   memset( ijk, 0, 3 * sizeof(unsigned) );
-   if( !strcmp( movingWall, "lower" ) ) {
-      ijk[dim] = wallDepth;
-      wallCrd = Mesh_GetVertex( mesh, Grid_Project( grid, ijk ) );
-      offsetLower += wallCrd[dim];
-      offsetUpper += wallCrd[dim];
-   }
-   else {
-      ijk[dim] = grid->sizes[dim] - wallDepth - 1;
-      wallCrd = Mesh_GetVertex( mesh, Grid_Project( grid, ijk ) );
-      offsetLower += wallCrd[dim];
-      offsetUpper += wallCrd[dim];
-   }
-
-   /*
-   ** Apply the set of parameters to this node. */
-   pos = coord[dim];
-   if( pos <= offsetLower )
-      *result = left;
-   else if( pos >= offsetUpper )
-      *result = right;
-   else {
-      *result = left + ((pos - offsetLower) / (offsetUpper - offsetLower)) * (right - left);
-   }
-}
-
-void StgFEM_StandardConditionFunctions_ConvectionBenchmark( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	/* This IC is for the 2D ConvectionBenchmark defined in
-	 * http://www.mcc.monash.edu.au/twiki/view/Research/ConvectionBenchmarks
-	 */
-	
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			mesh;
-	double*                 result             = (double*) _result;
-	double			min[3], max[3];
-        double*                 coord;
-	double                  x,y;
-	double                  Lx, Ly;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-	mesh       = (FeMesh*)feVariable->feMesh;
-
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	
-	Lx = max[ I_AXIS ] - min[ I_AXIS ];
-	Ly = max[ J_AXIS ] - min[ J_AXIS ];
-	
-	coord      = Mesh_GetVertex( mesh, node_lI );
-
-	x = ( coord[0] - min[ I_AXIS ] ) / Lx;
-	y = ( coord[1] - min[ J_AXIS ] ) / Ly;
-
-
-	*result = ( 1 - y ) + ( cos( M_PI * x ) * sin( M_PI * y ) ) / 100 ;
-}
-
-void StgFEM_StandardConditionFunctions_ConstantVector( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*		context            = (DomainContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	
-	result[0] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ConstantValueX", 0.0  );
-	result[1] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ConstantValueY", 0.0 );
-  if (context->dim == 3  ) 
-    result[2] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ConstantValueZ", 0.0 );
-}
-
-/* 3D spec ridge top BC (for milestone 1 of magma project ) 
- * to be applied to the top x-z plane of the domain */
-void StgFEM_StandardConditionFunctions_SpecRidge3D( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			feMesh             = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-
-	double			leftVal;
-	double			rightVal;
-	double			xOffset1;
-	double			xOffset2;
-	double			yOffset1, yOffset2;
-	double			xBegin, xEnd;
-	double			zBegin, zEnd;
-
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	feMesh     = feVariable->feMesh;
-	coord      = Mesh_GetVertex( feMesh, node_lI );
-
-	leftVal = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DLeftSide", 0.0  );
-	rightVal = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DRightSide", 0.0  );
-	xOffset1 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DXOffset1", 0.0  );
-	xOffset2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DXOffset2", 0.0  );
-	yOffset1 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DZOffset1", 0.0  );
-	yOffset2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DZOffset2", 0.0  );
-	xBegin = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DXBegin", 0.0  );
-	xEnd = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DXEnd", 0.0  );
-	zBegin = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DZBegin", 0.0  );
-	zEnd = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DZEnd", 0.0 );
-
-	if( coord[0] < xBegin || coord[0] > xEnd ||
-	    coord[2] < zBegin || coord[2] > zEnd )
-	{
-		*result = 0.0;
-	}
-	else if( coord[0] < xOffset1 )
-		*result = leftVal;
-	else if( coord[0] < xOffset2 && coord[2] > yOffset1 && coord[2] < yOffset2  )
-		*result = leftVal;
-	else
-		*result = rightVal;
-}
-
-void StgFEM_StandardConditionFunctions_TemperatureProfile( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-  FiniteElementContext *	context            = (FiniteElementContext*)_context;
-  FeVariable*             feVariable         = NULL;
-  FeMesh*     mesh               = NULL;
-  Dictionary*             dictionary         = context->dictionary;
-  double*                 result             = (double*) _result;
-  double*                 coord;
-  double                  T_0, H_0, dH, H, H_m, A, B, C, x_min, x_max, y_max, T_m, xc, dum;
-  /* G.Ito 10/08 added variables x_min, x_max, T_m, Xc, to do variation in x
-     and limit maximum T */
-  
-  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-  mesh       = feVariable->feMesh;
-  coord      = Mesh_GetVertex( mesh, node_lI );
-  
-  T_0 = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileTop", 0.0 );
-  T_m = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileMax", 10000.0 );
-  H_0 = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileH0", -1.0 );
-  H_m = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileHm", 1.0e+8 );
-  dH = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfiledH", 0.0 );     
-  A = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileLinearCoefficient", 0.0 );
-  B = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileExponentialCoefficient1", 0.0 );
-  C = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileExponentialCoefficient2", 0.0 );
-  y_max = Dictionary_GetDouble_WithDefault( dictionary, "maxY", 0.0 );
-  x_max = Dictionary_GetDouble_WithDefault( dictionary, "maxX", 0.0 );
-  x_min = Dictionary_GetDouble_WithDefault( dictionary, "minX", 0.0 );
-  xc = Dictionary_GetDouble_WithDefault( dictionary, "ExtensionCentreX", 0.0 );
-  
-  if (H_0<0.0)
-    {
-      if(coord[1]>y_max)
-        {
-          *result=T_0;
-        }
-      else
-        {
-          *result=T_0 + A*(y_max-coord[1]) + B*(1-exp(-C*(y_max-coord[1])));
-        }
-    }
-  else
-    {
-      if(coord[1]>=y_max)
-        {
-          *result=T_0;
-        }
-      else
-        {
-          H=H_0 + 2*fabs(coord[0]-xc)/(x_max-x_min)*dH;
-          if (H>H_m) H=H_m;
-          
-          dum=T_0 + ((T_m-T_0)/H)*(y_max-coord[1])
-            + B*(1-exp(-C*(y_max-coord[1])));
-          if (dum>T_m) dum=T_m;
-          *result=dum;
-        }
-    }
-
-}
-
-void StgFEM_StandardConditionFunctions_ERF( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			feMesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double                  width, scale, dilate, offset, constant;
-	unsigned		dim;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	feMesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( feMesh, node_lI );
-
-	width = Dictionary_GetDouble_WithDefault( dictionary, "ERFWidth", 0.0 );
-	offset= Dictionary_GetDouble_WithDefault(dictionary, "ERFOffset",0.0 );
-	constant=Dictionary_GetDouble_WithDefault(dictionary,"ERFConstant",0.0);
-        scale = Dictionary_GetDouble_WithDefault( dictionary, "ERFScale", 1.0 );
-	dilate = Dictionary_GetDouble_WithDefault( dictionary,"ERFDilate",1.0 );
-	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "ERFDim", 0 );
-
-        if(dim==3)
-          {
-            dim=0;
-            coord=&(context->currentTime);
-          }
-
-        if(coord[dim]+offset < -width && width!=0)
-          *result=constant-scale;
-        else if(coord[dim]+offset > width && width!=0)
-          *result=constant+scale;
-        else
-          *result=constant+scale*erf((coord[dim]+offset)/dilate);
-}
-
-void StgFEM_StandardConditionFunctions_ERFC(Node_LocalIndex node_lI,
-                                            Variable_Index var_I,
-                                            void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			feMesh               = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double                  width, scale, dilate, offset, constant;
-	unsigned		dim;
-
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName
-          ( context->fieldVariable_Register, "VelocityField" );
-	feMesh       = feVariable->feMesh;
-	coord      = Mesh_GetVertex( feMesh, node_lI );
-
-	width = Dictionary_GetDouble_WithDefault(dictionary, "ERFCWidth", 0.0 );
-	offset= Dictionary_GetDouble_WithDefault(dictionary, "ERFCOffset",0.0 );
-	constant=Dictionary_GetDouble_WithDefault(dictionary,"ERFCConstant",0.0);
-        scale = Dictionary_GetDouble_WithDefault(dictionary, "ERFCScale", 1.0 );
-	dilate = Dictionary_GetDouble_WithDefault(dictionary,"ERFCDilate",1.0 );
-	dim = Dictionary_GetUnsignedInt_WithDefault(dictionary, "ERFCDim", 0 );
-
-        if(dim==3)
-          {
-            dim=0;
-            coord=&(context->currentTime);
-          }
-
-        if(coord[dim]+offset < -width && width!=0)
-          *result=constant-scale;
-        else if(coord[dim]+offset > width && width!=0)
-          *result=constant+scale;
-        else
-          *result=constant+scale*erfc((coord[dim]+offset)/dilate);
-}
-
-void StgFEM_StandardConditionFunctions_RubberSheet( Node_LocalIndex node_lI,
-                                                    Variable_Index var_I,
-                                                    void* _context,
-                                                    void* _result )
-{
-  FiniteElementContext *	context            = (FiniteElementContext*)_context;
-  FeVariable*             feVariable         = NULL;
-  FeMesh*			feMesh               = NULL;
-  Dictionary*             dictionary         = context->dictionary;
-  double*                 result             = (double*) _result;
-  double*                 coord;
-  double                  lower_offset, upper_offset;
-  double                  lower_value, upper_value, time;
-  unsigned		dim;
-
-  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-  feMesh       = feVariable->feMesh;
-  coord      = Mesh_GetVertex( feMesh, node_lI );
-
-  lower_offset = Dictionary_GetDouble_WithDefault( dictionary,
-                                                   "RubberSheetLowerOffset",
-                                                   0.0 );
-  upper_offset = Dictionary_GetDouble_WithDefault( dictionary,
-                                                   "RubberSheetUpperOffset",
-                                                   lower_offset );
-  dim = Dictionary_GetUnsignedInt_WithDefault( dictionary,
-                                               "RubberSheetDim", 0 );
-
-  lower_value = Dictionary_GetDouble_WithDefault( dictionary,
-                                                  "RubberSheetLowerValue",
-                                                  0.0 );
-  upper_value = Dictionary_GetDouble_WithDefault( dictionary,
-                                                  "RubberSheetUpperValue",
-                                                  0.0 );
-
-  time=context->currentTime;
-
-  if(coord[dim] < lower_offset + lower_value*time)
-    {
-      *result=lower_value;
-    }
-  else if(coord[dim] < upper_offset + upper_value*time)
-    {
-      double min[3], max[3];
-      Mesh_GetGlobalCoordRange( feMesh, min, max );
-      *result=lower_value + 
-        (upper_value-lower_value)
-        *(coord[dim] - min[dim])/(max[dim]-min[dim]);
-    }
-  else
-    {
-      *result=upper_value;
-    }
-}
-
-/* get the BC's from the analytic solution as stored on the relevant FeVariable */
-void StgFEM_StandardConditionFunctions_SpectralBCX( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             analyticFeVarX     = NULL;
-	FeVariable*             numericFeVar       = NULL;
-	double*                 result             = (double*) _result;
-	/*FeMesh*			feMesh             = NULL;
-        double*                 coord;
-	Node_LocalIndex		analyticNodeI;
-	Element_DomainIndex	analyticElement_I;
-	double			analyticLocalElementCoord[3];
-	FeMesh*			analyticFeMesh;
-	*/
-	analyticFeVarX = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralVelocityXField" );
-	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	//feMesh         = numericFeVar->feMesh;
-	//coord          = Mesh_GetVertex( feMesh, node_lI );
-
-	//analyticFeMesh = analyticFeVarX->feMesh;
-	//if( Mesh_SearchElements( analyticFeMesh, coord, &analyticElement_I ) ) {
-	//	FeMesh_CoordGlobalToLocal( analyticFeMesh, analyticElement_I, coord, analyticLocalElementCoord );
-	//	FeVariable_InterpolateWithinElement( analyticFeVarX, analyticElement_I, analyticLocalElementCoord, result );
-	//}
-	//else {	/* numerical solution node outside analytic mesh - just find closest point & use that */
-	//	analyticNodeI  = Mesh_NearestVertex( analyticFeMesh, coord );
-	//	FeVariable_GetValueAtNode( analyticFeVarX, analyticNodeI, result );
-	//}
-	
-	FeVariable_GetValueAtNode( analyticFeVarX, node_lI, result );
-}
-
-void StgFEM_StandardConditionFunctions_SpectralBCY( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             analyticFeVarY     = NULL;
-	FeVariable*             numericFeVar       = NULL;
-	double*                 result             = (double*) _result;
-	/*FeMesh*			feMesh             = NULL;
-        double*                 coord;
-	Node_LocalIndex		analyticNodeI;
-	Element_DomainIndex	analyticElement_I;
-	double			analyticLocalElementCoord[3];
-	FeMesh*			analyticFeMesh;
-	*/
-	analyticFeVarY = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralVelocityYField" );
-	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	//feMesh         = numericFeVar->feMesh;
-	//coord          = Mesh_GetVertex( feMesh, node_lI );
-
-	//analyticFeMesh = analyticFeVarY->feMesh;
-	//if( Mesh_SearchElements( analyticFeMesh, coord, &analyticElement_I ) ) {
-	//	FeMesh_CoordGlobalToLocal( analyticFeMesh, analyticElement_I, coord, analyticLocalElementCoord );
-	//	FeVariable_InterpolateWithinElement( analyticFeVarY, analyticElement_I, analyticLocalElementCoord, result );
-	//}
-	//else {
-	//	analyticNodeI  = Mesh_NearestVertex( analyticFeMesh, coord );
-	//	FeVariable_GetValueAtNode( analyticFeVarY, analyticNodeI, result );
-	//}
-	
-	FeVariable_GetValueAtNode( analyticFeVarY, node_lI, result );
-}
-
-void StgFEM_StandardConditionFunctions_SpectralBCZ( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             analyticFeVarZ     = NULL;
-	FeVariable*             numericFeVar       = NULL;
-	double*                 result             = (double*) _result;
-	/*
-	FeMesh*			feMesh             = NULL;
-        double*                 coord;
-	Node_LocalIndex		analyticNodeI;
-	Element_DomainIndex	analyticElement_I;
-	double			analyticLocalElementCoord[3];
-	FeMesh*			analyticFeMesh;
-	*/
-	analyticFeVarZ = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralVelocityZField" );
-	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	//feMesh         = numericFeVar->feMesh;
-	//coord          = Mesh_GetVertex( feMesh, node_lI );
-
-	//analyticFeMesh = analyticFeVarZ->feMesh;
-	//if( Mesh_SearchElements( analyticFeMesh, coord, &analyticElement_I ) ) {
-	//	FeMesh_CoordGlobalToLocal( analyticFeMesh, analyticElement_I, coord, analyticLocalElementCoord );
-	//	FeVariable_InterpolateWithinElement( analyticFeVarZ, analyticElement_I, analyticLocalElementCoord, result );
-	//}
-	//else {
-	//	analyticNodeI  = Mesh_NearestVertex( analyticFeMesh, coord );
-	//	FeVariable_GetValueAtNode( analyticFeVarZ, analyticNodeI, result );
-	//}
-	
-	FeVariable_GetValueAtNode( analyticFeVarZ, node_lI, result );
-}
-
-void StgFEM_StandardConditionFunctions_SpectralPressureBCX( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             analyticFeVarX     = NULL;
-	FeVariable*             numericFeVar       = NULL;
-	FeMesh*			feMesh             = NULL;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-
-	analyticFeVarX = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralPressureField" );
-	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "PressureField" );
-	feMesh         = numericFeVar->feMesh;
-	coord          = Mesh_GetVertex( feMesh, node_lI );
-
-	FeVariable_GetValueAtNode( analyticFeVarX, node_lI, result );
-}
-
-void StgFEM_StandardConditionFunctions_SpectralPressureBCY( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             analyticFeVarY     = NULL;
-	FeVariable*             numericFeVar       = NULL;
-	FeMesh*			feMesh             = NULL;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-
-	analyticFeVarY = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralPressureField" );
-	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "PressureField" );
-	feMesh         = numericFeVar->feMesh;
-	coord          = Mesh_GetVertex( feMesh, node_lI );
-
-	FeVariable_GetValueAtNode( analyticFeVarY, node_lI, result );
-}
-
-/* error function for use in 3D spec ridge top BC */
-double errorFunction( double z, int n ) {
-	double		pi	= 3.1415926535;
-	double 		a;
-	double 		erf 	= 0.0;
-	int		denom;
-	int		i, j;
-
-	a = 2.0/sqrt( pi );
-
-	for( i=0 ; i<n ; i++ ) {
-		denom = 1;
-		for( j=1 ; j<=2*i+1 ; j+=2 ) 
-			denom *= j; 
-		
-		erf += pow( 2, i )*pow( z, 2*i+1 )/denom;
-	}
-
-	return erf *= a*exp( -1.0*z*z );
-}
-
-
-
-void StgFEM_StandardConditionFunctions_ErrorFunc( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	FeMesh*			feMesh             = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-        double*                 coord;
-	double			dilate;
-	double			width; 
-
-	feVariable  = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	feMesh      = feVariable->feMesh;
-	coord       = Mesh_GetVertex( feMesh, node_lI );
-
-	dilate      = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ErrorFuncDilate", 0.0  );
-	width       = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ErrorFuncWidth", 0.0 );
-
-	if( coord[0] < -1.0*width ) {
-		*result = -1.0;
-	}
-	else if( coord[0] > width  ) {
-		*result = 1.0;
-	}
-	else {
-		*result     = errorFunction( coord[0]/dilate, 5 );	
-	}
-}
-
-void StgFEM_StandardConditionFunctions_GaussianDistribution( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	Name			variableName;
-	double*			coord;
-	unsigned		nDims              = context->dim;
-	unsigned		dim_I;
-	double			orig[3];
-	double			sigma              = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"sigma", 1.0  );
-	double			gaussianScale      = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianScale", 1.0  );
-	double			background         = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"backgroundValue", 1.0  );
-	double			distsq             = 0.0;
-
-	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
-	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
-
-	orig[0] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"x0", 0.0  );
-	orig[1] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"y0", 0.0  );
-	orig[2] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"z0", 0.0 );
-
-	for( dim_I = 0; dim_I < nDims; dim_I++ )
-		distsq += ( coord[dim_I] - orig[dim_I] ) * ( coord[dim_I] - orig[dim_I] );
-
-	*result = gaussianScale * exp( -distsq / ( 2.0 * sigma * sigma )  ) + background;
-}
-
-void StgFEM_StandardConditionFunctions_GravitationalPotential( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	Name			variableName;
-	double*			coord;
-
-	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
-	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
-
-	*result = -1.0 * coord[J_AXIS];
-}
-
-void StgFEM_StandardConditionFunctions_1DGaussianDistribution( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	Name			variableName;
-	double*			coord;
-	double			orig[3];
-	double			sigma              = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"sigma", 1.0  );
-	double			gaussianScale      = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianScale", 1.0  );
-	double			background         = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"backgroundValue", 1.0  );
-	double			distsq             = 0.0;
-
-	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
-	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
-
-	orig[0] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"x0", 0.0  );
-	orig[1] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"y0", 0.0  );
-	orig[2] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"z0", 0.0 );
-
-	distsq = ( coord[J_AXIS] - orig[J_AXIS] ) * ( coord[J_AXIS] - orig[J_AXIS] );
-
-	*result = gaussianScale * exp( -distsq / ( 2.0 * sigma * sigma )  ) + background;
-}
-
-void StgFEM_StandardConditionFunctions_HalfContainer( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	FeVariable*             feVariable         = NULL;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	Name			variableName;
-	double*			coord;
-	double			halfPoint          = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"halfPoint", 0.0  );
-
-	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
-	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
-
-	if( coord[1] < halfPoint )
-		*result = 1;
-	else
-		*result = 0;	
-}
-
-void StgFEM_StandardConditionFunctions_ConstantValue( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	double			value              = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"constantValue", 1.0  );
-
-	*result = value;
-}
-
-void StgFEM_StandardConditionFunctions_DiagonalLine( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	double			width              = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"lineWidth", 1.0  );
-	double*			coord;
-	Name			variableName;
-	FeVariable*             feVariable         = NULL;
-
-	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
-	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
-
-	if( fabs( coord[0] - coord[1] ) < width )
-		*result = 1.0;
-	else
-		*result = 0.0;
-}
-
-void StgFEM_StandardConditionFunctions_DeltaFunction( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	FiniteElementContext *	context            = (FiniteElementContext*)_context;
-	Dictionary*             dictionary         = context->dictionary;
-	double*                 result             = (double*) _result;
-	double			epsilon		   = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"deltaFunctionEpsilon", 0.001  );
-	unsigned		dim		   = Dictionary_GetUnsignedInt_WithDefault( dictionary, "deltaFunctionDim", 0 );
-	double			centre		   = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"deltaFunctionCentre", 0.5  );
-	double			value		   = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"deltaFunctionValue", 1.0  );
-	double*			coord;
-	Name			variableName	   = Dictionary_GetString_WithDefault( dictionary, "DeltaFunctionFeVariable", "" );
-	FeVariable*		feVariable	   = (FeVariable*) FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
-
-	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
-	
-	*result = (fabs( coord[dim] - centre ) < epsilon) ? value : 0.0;
-}
-
-void StgFEM_StandardConditionFunctions_InflowBottom( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
-	DomainContext*	context            = (DomainContext*)_context;
-	FeVariable* feVariable;
-	Dictionary*             dictionary         = context->dictionary;
-	FeMesh*			mesh               = NULL;
-	double*                 result             = (double*) _result;
-	double sideLength, wallLength, sideV;
-	double min[3], max[3];
-	
-	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-	mesh       = feVariable->feMesh;
-	Mesh_GetGlobalCoordRange( mesh, min, max );
-	sideLength = max[1] - min[1];
-	wallLength = max[0] - min[0];
-	sideV = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"InflowSideVelocity", 1.0  );
-
-	*result = 2.0 * sideV * sideLength / wallLength;
-}
-
-void StgFEM_StandardConditionFunctions_GaussianTube( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-        DomainContext*  context = (DomainContext*)_context;
-        Dictionary*             dictionary         = context->dictionary;
-        FeVariable*             feVariable = NULL;
-        FeMesh*                 feMesh = NULL;
-        unsigned                nDims;
-        double*                 result = (double*) _result;
-        double                  a1,b1,c1, a2,b2,c2, x,y,z,r_y,r_yz;
-        double*                 coord;
-        double                  min[3], max[3];
-	double                  y_shift, z_shift;
-
-        feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
-        feMesh       = feVariable->feMesh;
-
-        nDims = Mesh_GetDimSize( feMesh );
-        Mesh_GetGlobalCoordRange( feMesh, min, max );
-
- 	a1 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_a1", 1.0  ); /* Scales the magnitude of the perturbation. */
-	c1 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_c1", 0.1  ); /* Controls the smoothing length. Smaller values produce less smoothing. */
-
-        a2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_a2", 0.05  ); /* Controls ampltude of oscillations */
-        b2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_b2", 6.28318530718  ); /* Controls frequency of oscillations */
-	c2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_c2", 1.570796326795  ); /* Shifts oscillations */
-
-	y_shift = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_y_origin", 0.0  );
-	z_shift = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_z_origin", 0.0  );
-
-        coord = Mesh_GetVertex( feMesh, node_lI );
-
-	x = coord[ I_AXIS ];
-	y = coord[ J_AXIS ];
-
-	y = y - y_shift;
-	if (nDims==2) {
-		b1 = a2 * sin( b2*x - c2 );
-		r_y = sqrt( (y-b1)*(y-b1) );
-		*result = a1 * exp( -(r_y * r_y) / (2.0*c1*c1) );
-	}
-	if (nDims==3) {
-		z = coord[ K_AXIS ];
-		z = z - z_shift;
-
-		b1 = a2 * sin( b2*x - c2 );
-		r_yz = sqrt( (y-b1)*(y-b1) + z*z );
-		*result = a1 * exp( -(r_yz * r_yz) / (2.0*c1*c1) );
-	}
-
-
-}
-
-
-void StgFEM_StandardConditionFunctions_WarsTemperature( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  FiniteElementContext *	context            = (FiniteElementContext*)_context;
-  FeVariable*             feVariable         = NULL;
-  FeMesh*     mesh               = NULL;
-  Dictionary*             dictionary         = context->dictionary;
-  double*                 result             = (double*) _result;
-  double*                 coord;
-  double                  EAEnd, WarsStart, WarsHeight, WarsTTop,
-    WarsTBottom, h, maxY;
-  
-  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-  mesh       = feVariable->feMesh;
-  coord      = Mesh_GetVertex( mesh, node_lI );
-  
-  EAEnd = Dictionary_GetDouble( dictionary, "EAEnd");
-  WarsStart = Dictionary_GetDouble( dictionary, "WarsStart");
-  WarsHeight = Dictionary_GetDouble( dictionary, "WarsHeight");
-  WarsTTop = Dictionary_GetDouble( dictionary, "WarsTTop");
-  WarsTBottom = Dictionary_GetDouble( dictionary, "WarsTBottom");     
-  maxY=Dictionary_GetDouble( dictionary, "maxY");
-
-
-  h=WarsHeight*(coord[0]-EAEnd)/(WarsStart-EAEnd);
-  if(coord[0]<EAEnd)
-    h=0;
-  if(coord[0]>WarsStart)
-    h=WarsHeight;
-  *result=WarsTBottom + ((coord[1]-h)/(maxY-h))*(WarsTTop-WarsTBottom);
-}
-
-void StgFEM_StandardConditionFunctions_Quadratic( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  FiniteElementContext *	context            = (FiniteElementContext*)_context;
-  FeVariable*             feVariable         = NULL;
-  FeMesh*     mesh               = NULL;
-  Dictionary*             dictionary         = context->dictionary;
-  double*                 result             = (double*) _result;
-  double*                 coord;
-  int                     dim;
-  double                  a, b, c;
-  
-  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-  mesh       = feVariable->feMesh;
-  coord      = Mesh_GetVertex( mesh, node_lI );
-  
-  dim = Dictionary_GetInt( dictionary, "Quadratic_Dim");
-  a = Dictionary_GetDouble( dictionary, "Quadratic_Constant");
-  b = Dictionary_GetDouble( dictionary, "Quadratic_Linear");
-  c = Dictionary_GetDouble( dictionary, "Quadratic_Quadratic");
-
-  *result= a + coord[dim]*(b + c*coord[dim]);
-}
-
-int Binary_Search(double *data, int s, int e, double value);
-
-void StgFEM_StandardConditionFunctions_FileN( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result, int file_num, double **coords, double **data);
-
-void StgFEM_StandardConditionFunctions_File1( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,1,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File2( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,2,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File3( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,3,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File4( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,4,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File5( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,5,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File6( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,6,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File7( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,7,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File8( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,8,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File9( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,9,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_File10( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
-{
-  static double *coords=NULL;
-  static double *data=NULL;
-  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,10,
-                                          &coords,&data);
-}
-
-void StgFEM_StandardConditionFunctions_FileN( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result, int file_num, double **coords, double **data)
-{
-  FiniteElementContext *	context            = (FiniteElementContext*)_context;
-  FeVariable*             feVariable         = NULL;
-  FeMesh*     mesh               = NULL;
-  Dictionary*             dictionary         = context->dictionary;
-  double*                 result             = (double*) _result;
-  double*                 coord;
-  int                     dim, dim2, dim3, i, j, k;
-  char *filename;
-  int N, N2, N3, ndims;
-  int result_index, result_index2, result_index3;
-  double factor, factor2, factor3;
-  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
-  mesh       = feVariable->feMesh;
-  coord      = Mesh_GetVertex( mesh, node_lI );
-  
-  char fileN_number[10], fileN_dim[15], fileN_dim2[15], fileN_dim3[15],
-    fileN_name[128], fileN_N[15], fileN_N2[15], fileN_N3[15];
-  sprintf(fileN_number,"File%d",file_num);
-  sprintf(fileN_dim,"File%d_Dim",file_num);
-  sprintf(fileN_dim2,"File%d_Dim2",file_num);
-  sprintf(fileN_dim3,"File%d_Dim3",file_num);
-  sprintf(fileN_name,"File%d_Name",file_num);
-  sprintf(fileN_N,"File%d_N",file_num);
-  sprintf(fileN_N2,"File%d_N2",file_num);
-  sprintf(fileN_N3,"File%d_N3",file_num);
-
-  filename = Dictionary_GetString( dictionary, fileN_name);
-  N = Dictionary_GetInt( dictionary, fileN_N);
-  dim = Dictionary_GetInt( dictionary, fileN_dim);
-  N2 = Dictionary_GetInt_WithDefault( dictionary, fileN_N2,-1);
-  N3 = Dictionary_GetInt_WithDefault( dictionary, fileN_N3,-1);
-
-  if(N2==-1)
-    ndims=1;
-  else if(N3==-1)
-    ndims=2;
-  else
-    ndims=3;
-
-  if(ndims>1)
-    {
-      dim2 = Dictionary_GetInt( dictionary, fileN_dim2);
-      if(ndims>2)
-        dim3 = Dictionary_GetInt( dictionary, fileN_dim3);
-    }
-
-  Journal_Firewall(dim>=0 && dim<3,
-                   Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
-                   "%s must be either 0, 1, or 2, but was set to %d\n",
-                   fileN_dim,dim);
-  Journal_Firewall(N>0,
-                   Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
-                   "%s must be greater than zero, but was set to %d.\n",
-                   fileN_N,N);
-  if(*data==NULL)
-    {
-      FILE *fp=fopen(filename,"r");
-      Journal_Firewall(fp!=NULL,
-                       Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
-                       "Bad filename for %s.  Could not open %s\n",
-                       fileN_name,filename);
-
-      /* In 1D, data and coords are simple 1D arrays.  In 2D, data is
-         a 2D arrays, and coord is still a 1D array, with the first N
-         elements being the coordinates in the Dim direction, and the
-         next N2 elements being the coordinates in the Dim2
-         dirction.  Similarly in 3D.  */
-      if(ndims==1)
-        {
-          *data=(double *)malloc(N*sizeof(double));
-          *coords=(double *)malloc(N*sizeof(double));
-        }
-      else if(ndims==2)
-        {
-          *data=(double *)malloc(N*N2*sizeof(double));
-          *coords=(double *)malloc((N+N2)*sizeof(double));
-        }
-      else
-        {
-          *data=(double *)malloc(N*N2*N3*sizeof(double));
-          *coords=(double *)malloc((N+N2+N3)*sizeof(double));
-        }
-
-      Journal_Firewall(*data!=NULL && *coords!=NULL,
-                       Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
-                       "Could not allocate enough memory for %s\n",file_num);
-      if(ndims==1)
-        {
-          for(i=0;i<N;++i)
-            fscanf(fp,"%lf %lf",*coords+i,*data+i);
-        }
-      else if(ndims==2)
-        {
-          for(i=0;i<N;++i)
-            for(j=0;j<N2;++j)
-              {
-                fscanf(fp,"%lf %lf %lf",*coords+i,*coords+N+j,*data+i+N*j);
-              }
-        }
-      else if(ndims==3)
-        {
-          for(i=0;i<N;++i)
-            for(j=0;j<N2;++j)
-              for(k=0;k<N3;++k)
-                fscanf(fp,"%lf %lf %lf %lf",*coords+i,*coords+N+j,*coords+N+N2+k,
-                       *data+i+N*(j+N2*k));
-        }
-      fclose(fp);
-    }
-
-  Journal_Firewall(!(coord[dim]<(*coords)[0] || coord[dim]>(*coords)[N-1]),
-                   Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
-                   "The range in the file '%s' does not cover this value %g\nIt only covers %g to %g in the %d direction.\n",
-                   filename,coord[dim],(*coords)[0],(*coords)[N-1],dim);
-  if(ndims>1)
-    Journal_Firewall(!(coord[dim2]<(*coords)[N] || coord[dim2]>(*coords)[N+N2-1]),
-                     Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
-                     "The range in the file '%s' does not cover this value %g\nIt only covers %g to %g in the %d direction.\n",
-                     filename,coord[dim2],(*coords)[N],(*coords)[N+N2-1],dim2);
-  if(ndims>2)
-    Journal_Firewall(!(coord[dim3]<(*coords)[N+N2] || coord[dim3]>(*coords)[N+N2+N3-1]),
-                     Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
-                     "The range in the file '%s' does not cover this value %g\nIt only covers %g to %g in the %d direction.\n",
-                     filename,coord[dim3],(*coords)[N+N2],(*coords)[N+N2+N3-1],dim2);
-
-  i=Binary_Search(*coords,0,N-1,coord[dim]);
-  factor=((*coords)[i+1]-coord[dim])/((*coords)[i+1]-(*coords)[i]);
-    
-  if(ndims>1)
-    {
-      j=Binary_Search(*coords,N,N+N2-1,coord[dim2]);
-      factor2=((*coords)[j+1]-coord[dim2])/((*coords)[j+1]-(*coords)[j]);
-      j=j-N;
-      if(ndims>2)
-        {
-          k=Binary_Search(*coords,N,N+N2+N3-1,coord[dim3]);
-          factor3=((*coords)[k+1]-coord[dim3])/((*coords)[k+1]-(*coords)[k]);
-          k=k-N-N2;
-        }
-    }
-
-  switch(ndims)
-    {
-    case 1:
-      *result=(*data)[i]*factor + (*data)[i+1]*(1-factor);
-      break;
-    case 2:
-      *result=factor*(factor2*(*data)[i+N*j] + (1-factor2)*(*data)[i+N*(j+1)])
-        + (1-factor)*(factor2*(*data)[i+1+N*j] + (1-factor2)*(*data)[i+1+N*(j+1)]);
-      break;
-    case 3:
-      *result=factor*(factor2*(factor3*(*data)[i+N*(j+N2*k)]
-                               + (1-factor3)*(*data)[i+N*(j+N2*(k+1))])
-                      + (1-factor2)*(factor3*(*data)[i+N*((j+1)+N2*k)]
-                                     + (1-factor3)*(*data)[i+N*((j+1)+N2*(k+1))]))
-        + (1-factor)*(factor2*(factor3*(*data)[i+1+N*(j+N2*k)]
-                               + (1-factor3)*(*data)[i+1+N*(j+N2*(k+1))])
-                      + (1-factor2)*(factor3*(*data)[i+1+N*((j+1)+N2*k)]
-                                     + (1-factor3)*(*data)[i+1+N*((j+1)+N2*(k+1))]));
-      break;
-    }
-}
-    
-
-int Binary_Search(double *data, int s, int e, const double value)
-{
-  int start, end, midpoint;
-
-  start=s;
-  end=e;
-  midpoint=(end-start)/2 + start;
-  while(start!=midpoint)
-    {
-      if(data[midpoint]>=value)
-        end=midpoint;
-      else
-        start=midpoint;
-      midpoint=(end-start)/2 + start;
-    }
-  return start;
-}
-
-void StgFEM_StandardConditionFunctions_EquationN(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result,
-                                                 std::string equation_string,
-                                                 const int equation_number);
-
-void StgFEM_StandardConditionFunctions_Equation1(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,1);
-}
-
-void StgFEM_StandardConditionFunctions_Equation2(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,2);
-}
-
-void StgFEM_StandardConditionFunctions_Equation3(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,3);
-}
-
-void StgFEM_StandardConditionFunctions_Equation4(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,4);
-}
-
-void StgFEM_StandardConditionFunctions_Equation5(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,5);
-}
-
-void StgFEM_StandardConditionFunctions_Equation6(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,6);
-}
-
-void StgFEM_StandardConditionFunctions_Equation7(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,7);
-}
-
-void StgFEM_StandardConditionFunctions_Equation8(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,8);
-}
-
-void StgFEM_StandardConditionFunctions_Equation9(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,9);
-}
-
-void StgFEM_StandardConditionFunctions_Equation10(Node_LocalIndex node_lI,
-                                                  Variable_Index var_I,
-                                                  void* _context,
-                                                  void* _result)
-{
-  static std::string equation_string;
-  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
-                                              equation_string,10);
-}
-
-void StgFEM_StandardConditionFunctions_EquationN(Node_LocalIndex node_lI,
-                                                 Variable_Index var_I,
-                                                 void* _context,
-                                                 void* _result,
-                                                 std::string equation_string,
-                                                 const int equation_number) 
-{
-  FiniteElementContext *context=(FiniteElementContext*)_context;
-  FeVariable *feVariable=(FeVariable*)FieldVariable_Register_GetByName
-    (context->fieldVariable_Register, "VelocityField");
-  FeMesh *mesh(feVariable->feMesh);
-  Dictionary *dictionary=context->dictionary;
-  double *coord=Mesh_GetVertex(mesh,node_lI);
-  double *result=(double*)_result;
-
-  if(equation_string.empty())
-    {
-      std::stringstream ss;
-      ss << "Equation" << equation_number;
-      equation_string=std::string(Dictionary_GetString(dictionary,
-                                                       ss.str().c_str()));
-      Journal_Firewall(!equation_string.empty(),
-                       Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_EquationN"),
-                       "The equation given for %s is empty.",
-                       ss.str().c_str());
-    }
-  try
-    {
-      mu::Parser p;
-      p.DefineVar("x", coord); 
-      p.DefineVar("y", coord+1); 
-      p.DefineVar("z", coord+2); 
-      p.DefineVar("t", &(context->currentTime));
-      p.SetExpr(equation_string);
-
-      *result=p.Eval();
-    }
-  catch (mu::Parser::exception_type &e)
-    {
-      Journal_Firewall(false,
-                       Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_Equation"),
-                       "Error when parsing equation: %s\n",e.GetMsg().c_str());
-    }
-}
diff -r bd633e2a3a35 -r 46408d74ad35 plugins/StandardConditionFunctions/StandardConditionFunctions.cxx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/StandardConditionFunctions/StandardConditionFunctions.cxx	Thu May 12 11:19:05 2011 -0700
@@ -0,0 +1,2841 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+**
+** Copyright (C), 2003-2006, Victorian Partnership for Advanced Computing (VPAC) Ltd, 110 Victoria Street,
+**	Melbourne, 3053, Australia.
+**
+** Primary Contributing Organisations:
+**	Victorian Partnership for Advanced Computing Ltd, Computational Software Development - http://csd.vpac.org
+**	Australian Computational Earth Systems Simulator - http://www.access.edu.au
+**	Monash Cluster Computing - http://www.mcc.monash.edu.au
+**	Computational Infrastructure for Geodynamics - http://www.geodynamics.org
+**
+** Contributors:
+**	Patrick D. Sunter, Software Engineer, VPAC. (pds at vpac.org)
+**	Robert Turnbull, Research Assistant, Monash University. (robert.turnbull at sci.monash.edu.au)
+**	Stevan M. Quenette, Senior Software Engineer, VPAC. (steve at vpac.org)
+**	David May, PhD Student, Monash University (david.may at sci.monash.edu.au)
+**	Louis Moresi, Associate Professor, Monash University. (louis.moresi at sci.monash.edu.au)
+**	Luke J. Hodkinson, Computational Engineer, VPAC. (lhodkins at vpac.org)
+**	Alan H. Lo, Computational Engineer, VPAC. (alan at vpac.org)
+**	Raquibul Hassan, Computational Engineer, VPAC. (raq at vpac.org)
+**	Julian Giordani, Research Assistant, Monash University. (julian.giordani at sci.monash.edu.au)
+**	Vincent Lemiale, Postdoctoral Fellow, Monash University. (vincent.lemiale at sci.monash.edu.au)
+**
+**  This library is free software; you can redistribute it and/or
+**  modify it under the terms of the GNU Lesser General Public
+**  License as published by the Free Software Foundation; either
+**  version 2.1 of the License, or (at your option) any later version.
+**
+**  This library is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+**  Lesser General Public License for more details.
+**
+**  You should have received a copy of the GNU Lesser General Public
+**  License along with this library; if not, write to the Free Software
+**  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+**
+** $Id: StandardConditionFunctions.c 1196 2008-08-04 16:29:30Z LukeHodkinson $
+**
+**~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+#include <string.h>
+#include <mpi.h>
+#include <StGermain/StGermain.h>
+#include <StgDomain/StgDomain.h>
+#include <StgFEM/StgFEM.h>
+#include <assert.h>
+#include "StandardConditionFunctions.h"
+#include "muParser.h"
+
+const Type StgFEM_StandardConditionFunctions_Type = "StgFEM_StandardConditionFunctions";
+
+void _StgFEM_StandardConditionFunctions_AssignFromXML( void* component, Stg_ComponentFactory* cf, void* data ) {
+  Codelet*		self		= (Codelet*)component;
+  AbstractContext*        context;
+  ConditionFunction*      condFunc;
+  Dictionary*		pluginDict	= Codelet_GetPluginDictionary( component, cf->rootDict );
+
+  context = (AbstractContext*)Stg_ComponentFactory_ConstructByName( cf, Dictionary_GetString( pluginDict, (Dictionary_Entry_Key)"Context"  ), AbstractContext, True, data );
+  self->context = context;
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SolidBodyRotation, "Velocity_SolidBodyRotation"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_PartialRotationX, "Velocity_PartialRotationX"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+		
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_PartialRotationY, "Velocity_PartialRotationY"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_TaperedRotationX, "TaperedRotationX" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+		
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_TaperedRotationY, "TaperedRotationY" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SimpleShear, "Velocity_SimpleShear" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SimpleShearInverted, "Velocity_SimpleShearInverted" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ShearZ, "ShearZ" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_Extension, "Velocity_Extension" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_PartialLid_TopLayer, "Velocity_PartialLid_TopLayer"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_Trigonometry, "Temperature_Trigonometry"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_LinearInterpolationLid, "Velocity_LinearInterpolationLid"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_Lid_RampWithCentralMax, "Velocity_Lid_RampWithCentralMax"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_LinearVelocityLeftWall, "LinearVelocityLeftWall"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_LinearVelocityRightWall, "LinearVelocityRightWall"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SinusoidalLid, "Velocity_SinusoidalLid"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_CornerOnly, "Velocity_Lid_CornerOnly"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_TemperatureCosineHill, "Temperature_CosineHill"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ConvectionBenchmark, "Temperature_ConvectionBenchmark"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_LinearWithSinusoidalPerturbation, "LinearWithSinusoidalPerturbation"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_EdgeDriveConvectionIC, "EdgeDriveConvectionIC"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ThermalEdgeDriveConvectionIC, "ThermalEdgeDriveConvectionIC"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_AnalyticalTemperatureIC, "AnalyticalTemperatureIC"  );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New( Stg_FEM_VelicTemperatureIC, "VelicTemperatureIC" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New( Stg_FEM_VelicTemperatureIC_SolB, "VelicTemperatureIC_SolB" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+	
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SinusoidalExtension, "SinusoidalExtension" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_StepFunction, "StepFunction" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_StepFunctionProduct1, "StepFunctionProduct1");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_StepFunctionProduct2, "StepFunctionProduct2");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_StepFunctionProduct3, "StepFunctionProduct3");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_StepFunctionProduct4, "StepFunctionProduct4");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_TemperatureProfile, "TemperatureProfile");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StG_FEM_StandardConditionFunctions_Gaussian, "Gaussian");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_ERF,
+                                   (char*)"ERF");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_ERFC,
+                                   (char*)"ERFC");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_RubberSheet,
+                                   (char*)"RubberSheet");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_MovingStepFunction, "MovingStepFunction");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpecRidge3D, "SpecRidge3D" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralBCX, "SpectralBCX" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralBCY, "SpectralBCY" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralBCZ, "SpectralBCZ" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralPressureBCX, "SpectralPressureBCX" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_SpectralPressureBCY, "SpectralPressureBCY" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ErrorFunc, "ErrorFunc" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ConstantVector, "ConstantVector" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_GaussianDistribution, "GaussianDistribution" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_1DGaussianDistribution, "1DGaussianDistribution" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_HalfContainer, "HalfContainer" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_ConstantValue, "ConstantValue" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_DiagonalLine, "DiagonalLine" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_DeltaFunction, "DeltaFunction" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_InflowBottom, "InflowBottom" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_GaussianTube, "GaussianTube" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New( StgFEM_StandardConditionFunctions_GravitationalPotential, "GravitationalPotential" );
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_WarsTemperature,
+                                   "WarsTemperature");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_Quadratic,
+                                   "Quadratic");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File1,
+                                   "File1");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File2,
+                                   "File2");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File3,
+                                   "File3");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File4,
+                                   "File4");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File5,
+                                   "File5");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File6,
+                                   "File6");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File7,
+                                   "File7");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File8,
+                                   "File8");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File9,
+                                   "File9");
+  ConditionFunction_Register_Add( condFunc_Register, condFunc );
+  condFunc = ConditionFunction_New(StgFEM_StandardConditionFunctions_File10,
+                                   "File10");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation1,
+                                 "Equation1");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation2,
+                                 "Equation2");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation3,
+                                 "Equation3");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation4,
+                                 "Equation4");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation5,
+                                 "Equation5");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation6,
+                                 "Equation6");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation7,
+                                 "Equation7");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation8,
+                                 "Equation8");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation9,
+                                 "Equation9");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+  condFunc=ConditionFunction_New(StgFEM_StandardConditionFunctions_Equation10,
+                                 "Equation10");
+  ConditionFunction_Register_Add(condFunc_Register,condFunc);
+}
+
+void _StgFEM_StandardConditionFunctions_Destroy( void* _self, void* data ) {
+   /* This function will totally clean the condFunc_Register
+    *
+    * This could be trouble some if other code adds or deletes condition functions on this register
+    */
+
+   unsigned *refCount = &(condFunc_Register->count);
+
+   /* first check if there are things still on the condFunc_Register, if so .... */
+   if( *refCount != 0 ) {
+      while( *refCount != 0 ) {
+
+         _ConditionFunction_Delete( condFunc_Register->_cf[ *refCount-1 ] );
+         condFunc_Register->_cf[ *refCount-1 ] = NULL;
+
+         *refCount = *refCount - 1;
+      }
+   }
+   _Codelet_Destroy( _self, data );
+}
+void* _StgFEM_StandardConditionFunctions_DefaultNew( Name name ) {
+	return Codelet_New(
+		StgFEM_StandardConditionFunctions_Type,
+		_StgFEM_StandardConditionFunctions_DefaultNew,
+		_StgFEM_StandardConditionFunctions_AssignFromXML,
+		_Codelet_Build,
+		_Codelet_Initialise,
+		_Codelet_Execute,
+		_StgFEM_StandardConditionFunctions_Destroy,
+		name );
+}
+
+Index StgFEM_StandardConditionFunctions_Register( PluginsManager* pluginsManager ) {
+	Journal_DPrintf( StgFEM_Debug, "In: %s( void* )\n", __func__ );
+
+	return PluginsManager_Submit( pluginsManager, StgFEM_StandardConditionFunctions_Type, (Name)"0", _StgFEM_StandardConditionFunctions_DefaultNew  );
+}
+
+Bool StgFEM_StandardConditionFunctions_Init( int* argc, char** argv[] ) {
+  Stg_ComponentRegister* componentsRegister = Stg_ComponentRegister_Get_ComponentRegister();
+  Stg_ComponentRegister_Add(componentsRegister,
+                            StgFEM_StandardConditionFunctions_Type, (Name)"0",
+                            _StgFEM_StandardConditionFunctions_DefaultNew );
+  RegisterParent( StgFEM_StandardConditionFunctions_Type, Stg_Component_Type );
+  return True;
+}
+
+#ifdef NO_ERF
+
+/* Copied from the OpenBSD iplementation of erf.c
+   (src/lib/libm/src/erf.c and src/lib/libm/src/math_private.h).
+   Modified to only work on 32 bit little endian machines.
+   This is just a hack for Windows machines. */
+
+/* @(#)s_erf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice 
+ * is preserved.
+ * ====================================================
+ */
+
+/* double erf(double x)
+ * double erfc(double x)
+ *                           x
+ *                    2      |\
+ *     erf(x)  =  ---------  | exp(-t*t)dt
+ *                  sqrt(pi) \| 
+ *                           0
+ *
+ *     erfc(x) =  1-erf(x)
+ *  Note that 
+ *              erf(-x) = -erf(x)
+ *              erfc(-x) = 2 - erfc(x)
+ *
+ * Method:
+ *      1. For |x| in [0, 0.84375]
+ *          erf(x)  = x + x*R(x^2)
+ *          erfc(x) = 1 - erf(x)           if x in [-.84375,0.25]
+ *                  = 0.5 + ((0.5-x)-x*R)  if x in [0.25,0.84375]
+ *         where R = P/Q where P is an odd poly of degree 8 and
+ *         Q is an odd poly of degree 10.
+ *                                               -57.90
+ *                      | R - (erf(x)-x)/x | <= 2
+ *      
+ *
+ *         Remark. The formula is derived by noting
+ *          erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
+ *         and that
+ *          2/sqrt(pi) = 1.128379167095512573896158903121545171688
+ *         is close to one. The interval is chosen because the fix
+ *         point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
+ *         near 0.6174), and by some experiment, 0.84375 is chosen to
+ *         guarantee the error is less than one ulp for erf.
+ *
+ *      2. For |x| in [0.84375,1.25], let s = |x| - 1, and
+ *         c = 0.84506291151 rounded to single (24 bits)
+ *              erf(x)  = sign(x) * (c  + P1(s)/Q1(s))
+ *              erfc(x) = (1-c)  - P1(s)/Q1(s) if x > 0
+ *                        1+(c+P1(s)/Q1(s))    if x < 0
+ *              |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
+ *         Remark: here we use the taylor series expansion at x=1.
+ *              erf(1+s) = erf(1) + s*Poly(s)
+ *                       = 0.845.. + P1(s)/Q1(s)
+ *         That is, we use rational approximation to approximate
+ *                      erf(1+s) - (c = (single)0.84506291151)
+ *         Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
+ *         where 
+ *              P1(s) = degree 6 poly in s
+ *              Q1(s) = degree 6 poly in s
+ *
+ *      3. For x in [1.25,1/0.35(~2.857143)], 
+ *              erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
+ *              erf(x)  = 1 - erfc(x)
+ *         where 
+ *              R1(z) = degree 7 poly in z, (z=1/x^2)
+ *              S1(z) = degree 8 poly in z
+ *
+ *      4. For x in [1/0.35,28]
+ *              erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
+ *                      = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
+ *                      = 2.0 - tiny                (if x <= -6)
+ *              erf(x)  = sign(x)*(1.0 - erfc(x)) if x < 6, else
+ *              erf(x)  = sign(x)*(1.0 - tiny)
+ *         where
+ *              R2(z) = degree 6 poly in z, (z=1/x^2)
+ *              S2(z) = degree 7 poly in z
+ *
+ *      Note1:
+ *         To compute exp(-x*x-0.5625+R/S), let s be a single
+ *         precision number and s := x; then
+ *              -x*x = -s*s + (s-x)*(s+x)
+ *              exp(-x*x-0.5626+R/S) = 
+ *                      exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
+ *      Note2:
+ *         Here 4 and 5 make use of the asymptotic series
+ *                        exp(-x*x)
+ *              erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
+ *                        x*sqrt(pi)
+ *         We use rational approximation to approximate
+ *              g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
+ *         Here is the error bound for R1/S1 and R2/S2
+ *              |R1/S1 - f(x)|  < 2**(-62.57)
+ *              |R2/S2 - f(x)|  < 2**(-61.52)
+ *
+ *      5. For inf > x >= 28
+ *              erf(x)  = sign(x) *(1 - tiny)  (raise inexact)
+ *              erfc(x) = tiny*tiny (raise underflow) if x > 0
+ *                      = 2 - tiny if x<0
+ *
+ *      7. Special case:
+ *              erf(0)  = 0, erf(inf)  = 1, erf(-inf) = -1,
+ *              erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, 
+ *                 erfc/erf(NaN) is NaN
+ */
+
+/*  Assume little endian, 32 bit machines  */
+
+typedef int int32_t;
+typedef unsigned int u_int32_t;
+
+typedef union
+{
+  double value;
+  struct
+  {
+    u_int32_t lsw;
+    u_int32_t msw;
+  } parts;
+} ieee_double_shape_type;
+
+/* Get the more significant 32 bit int from a double.  */
+
+#define GET_HIGH_WORD(i,d)                                      \
+do {                                                            \
+  ieee_double_shape_type gh_u;                                  \
+  gh_u.value = (d);                                             \
+  (i) = gh_u.parts.msw;                                         \
+} while (0)
+
+/* Set the less significant 32 bits of a double from an int.  */
+
+#define SET_LOW_WORD(d,v)                                       \
+do {                                                            \
+  ieee_double_shape_type sl_u;                                  \
+  sl_u.value = (d);                                             \
+  sl_u.parts.lsw = (v);                                         \
+  (d) = sl_u.value;                                             \
+} while (0)
+
+
+static const double
+tiny        = 1e-300,
+half=  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
+one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
+two =  2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
+        /* c = (float)0.84506291151 */
+erx =  8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */
+/*
+ * Coefficients for approximation to  erf on [0,0.84375]
+ */
+efx =  1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */
+efx8=  1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */
+pp0  =  1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */
+pp1  = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */
+pp2  = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */
+pp3  = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */
+pp4  = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */
+qq1  =  3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */
+qq2  =  6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */
+qq3  =  5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */
+qq4  =  1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */
+qq5  = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */
+/*
+ * Coefficients for approximation to  erf  in [0.84375,1.25] 
+ */
+pa0  = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */
+pa1  =  4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */
+pa2  = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */
+pa3  =  3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */
+pa4  = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */
+pa5  =  3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */
+pa6  = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */
+qa1  =  1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */
+qa2  =  5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */
+qa3  =  7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */
+qa4  =  1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */
+qa5  =  1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */
+qa6  =  1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */
+/*
+ * Coefficients for approximation to  erfc in [1.25,1/0.35]
+ */
+ra0  = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */
+ra1  = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */
+ra2  = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */
+ra3  = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */
+ra4  = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */
+ra5  = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */
+ra6  = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */
+ra7  = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */
+sa1  =  1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */
+sa2  =  1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */
+sa3  =  4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */
+sa4  =  6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */
+sa5  =  4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */
+sa6  =  1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */
+sa7  =  6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */
+sa8  = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */
+/*
+ * Coefficients for approximation to  erfc in [1/.35,28]
+ */
+rb0  = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */
+rb1  = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */
+rb2  = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */
+rb3  = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */
+rb4  = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */
+rb5  = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */
+rb6  = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */
+sb1  =  3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */
+sb2  =  3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */
+sb3  =  1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */
+sb4  =  3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */
+sb5  =  2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */
+sb6  =  4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */
+sb7  = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */
+
+double
+erf(double x) 
+{
+        int32_t hx,ix,i;
+        double R,S,P,Q,s,y,z,r;
+        GET_HIGH_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x7ff00000) {                /* erf(nan)=nan */
+            i = ((u_int32_t)hx>>31)<<1;
+            return (double)(1-i)+one/x;        /* erf(+-inf)=+-1 */
+        }
+
+        if(ix < 0x3feb0000) {                /* |x|<0.84375 */
+            if(ix < 0x3e300000) {         /* |x|<2**-28 */
+                if (ix < 0x00800000) 
+                    return 0.125*(8.0*x+efx8*x);  /*avoid underflow */
+                return x + efx*x;
+            }
+            z = x*x;
+            r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+            s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+            y = r/s;
+            return x + x*y;
+        }
+        if(ix < 0x3ff40000) {                /* 0.84375 <= |x| < 1.25 */
+            s = fabs(x)-one;
+            P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+            Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+            if(hx>=0) return erx + P/Q; else return -erx - P/Q;
+        }
+        if (ix >= 0x40180000) {                /* inf>|x|>=6 */
+            if(hx>=0) return one-tiny; else return tiny-one;
+        }
+        x = fabs(x);
+        s = one/(x*x);
+        if(ix< 0x4006DB6E) {        /* |x| < 1/0.35 */
+            R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+                                ra5+s*(ra6+s*ra7))))));
+            S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+                                sa5+s*(sa6+s*(sa7+s*sa8)))))));
+        } else {        /* |x| >= 1/0.35 */
+            R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+                                rb5+s*rb6)))));
+            S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+                                sb5+s*(sb6+s*sb7))))));
+        }
+        z  = x;  
+        SET_LOW_WORD(z,0);
+        r  =  exp(-z*z-0.5625)*exp((z-x)*(z+x)+R/S);
+        if(hx>=0) return one-r/x; else return  r/x-one;
+}
+
+double
+erfc(double x) 
+{
+        int32_t hx,ix;
+        double R,S,P,Q,s,y,z,r;
+        GET_HIGH_WORD(hx,x);
+        ix = hx&0x7fffffff;
+        if(ix>=0x7ff00000) {                        /* erfc(nan)=nan */
+                                                /* erfc(+-inf)=0,2 */
+            return (double)(((u_int32_t)hx>>31)<<1)+one/x;
+        }
+
+        if(ix < 0x3feb0000) {                /* |x|<0.84375 */
+            if(ix < 0x3c700000)          /* |x|<2**-56 */
+                return one-x;
+            z = x*x;
+            r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
+            s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+            y = r/s;
+            if(hx < 0x3fd00000) {          /* x<1/4 */
+                return one-(x+x*y);
+            } else {
+                r = x*y;
+                r += (x-half);
+                return half - r ;
+            }
+        }
+        if(ix < 0x3ff40000) {                /* 0.84375 <= |x| < 1.25 */
+            s = fabs(x)-one;
+            P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
+            Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
+            if(hx>=0) {
+                z  = one-erx; return z - P/Q; 
+            } else {
+                z = erx+P/Q; return one+z;
+            }
+        }
+        if (ix < 0x403c0000) {                /* |x|<28 */
+            x = fabs(x);
+            s = one/(x*x);
+            if(ix< 0x4006DB6D) {        /* |x| < 1/.35 ~ 2.857143*/
+                R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
+                                ra5+s*(ra6+s*ra7))))));
+                S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
+                                sa5+s*(sa6+s*(sa7+s*sa8)))))));
+            } else {                        /* |x| >= 1/.35 ~ 2.857143 */
+                if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */
+                R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
+                                rb5+s*rb6)))));
+                S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
+                                sb5+s*(sb6+s*sb7))))));
+            }
+            z  = x;
+            SET_LOW_WORD(z,0);
+            r  =  exp(-z*z-0.5625)*
+                        exp((z-x)*(z+x)+R/S);
+            if(hx>0) return r/x; else return two-r/x;
+        } else {
+            if(hx>0) return tiny*tiny; else return two-tiny;
+        }
+}
+
+#endif
+
+
+void StgFEM_StandardConditionFunctions_SolidBodyRotation( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	Coord                   centre;
+	Coord                   vector;
+	double                  omega;
+	
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+
+	/* Find Centre of Solid Body Rotation */
+	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreX", 0.0  );
+	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreY", 0.0  );
+	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ", 0.0  );
+	omega            = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationOmega", 1.0  );
+
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	/* Find vector from centre to node */
+	StGermain_VectorSubtraction( vector, coord, centre, 2 );
+
+	result[ I_AXIS ] = -omega * vector[ J_AXIS ];
+	result[ J_AXIS ] =  omega * vector[ I_AXIS ];
+}
+
+
+void StgFEM_StandardConditionFunctions_PartialRotationX( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	Coord                   centre;
+	Coord                   vector;
+	double                  omega;
+	double			size;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+
+	/* Find Centre of Solid Body Rotation */
+	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreX", 0.0  );
+	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreY", 0.0  );
+	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ", 0.0  );
+	size             = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"RadiusCylinder", 0.0  );
+	omega            = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationOmega", 1.0  );
+
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	/* Find vector from centre to node */
+	StGermain_VectorSubtraction( vector, coord, centre, 2 );
+
+	/*if (context->currentTime > 1.33e-6)
+	  omega=0.0;*/
+	
+	if ((vector[ I_AXIS ]*vector[ I_AXIS ]+vector[ J_AXIS ]*vector[ J_AXIS ])<=size*size)
+		*result = -omega * vector[ J_AXIS ];
+	else
+		*result = 0.0;
+}
+
+void StgFEM_StandardConditionFunctions_PartialRotationY( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	Coord                   centre;
+	Coord                   vector;
+	double                  omega;
+	double			size;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+
+	/* Find Centre of Solid Body Rotation */
+	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreX", 0.0  );
+	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreY", 0.0  );
+	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ", 0.0  );
+	size             = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"RadiusCylinder", 0.0  );
+	omega            = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationOmega", 1.0  );
+
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	/* Find vector from centre to node */
+	StGermain_VectorSubtraction( vector, coord, centre, 2 );
+	
+	if ((vector[ I_AXIS ]*vector[ I_AXIS ]+vector[ J_AXIS ]*vector[ J_AXIS ])<=size*size)
+		*result =  omega * vector[ I_AXIS ];
+	else 
+		*result = 0.0;
+}
+
+
+void StgFEM_StandardConditionFunctions_TaperedRotationX( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	Coord                   centre;
+	Coord                   vector;
+	double                  omega;
+	double			size, r, taper;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+
+	/* Find Centre of Solid Body Rotation */
+	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreX", 0.0 );
+	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreY", 0.0 );
+	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreZ", 0.0 );
+	size             = Dictionary_GetDouble_WithDefault( dictionary, "RadiusCylinder", 0.0 );
+	omega            = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationOmega",   1.0 );
+
+	taper            = Dictionary_GetDouble_WithDefault( dictionary, "TaperedRadius",   0.0 );
+
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	/* Find vector from centre to node */
+	StGermain_VectorSubtraction( vector, coord, centre, 2 );
+
+        r=sqrt(vector[ I_AXIS ]*vector[ I_AXIS ]
+               +vector[ J_AXIS ]*vector[ J_AXIS ]);
+	if (r<=size)
+          *result = -omega * vector[ J_AXIS ];
+	else if(r<=taper)
+          *result = -omega * vector[ J_AXIS ]*(taper-r)/(taper-size);
+        else
+          *result = 0;
+}
+
+void StgFEM_StandardConditionFunctions_TaperedRotationY( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	Coord                   centre;
+	Coord                   vector;
+	double                  omega;
+	double			size, r, taper;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+
+	/* Find Centre of Solid Body Rotation */
+	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreX", 0.0 );
+	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreY", 0.0 );
+	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationCentreZ", 0.0 );
+	size             = Dictionary_GetDouble_WithDefault( dictionary, "RadiusCylinder", 0.0 );
+	omega            = Dictionary_GetDouble_WithDefault( dictionary, "SolidBodyRotationOmega",   1.0 );
+
+	taper            = Dictionary_GetDouble_WithDefault( dictionary, "TaperedRadius",   0.0 );
+
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	/* Find vector from centre to node */
+	StGermain_VectorSubtraction( vector, coord, centre, 2 );
+
+
+        r=sqrt(vector[ I_AXIS ]*vector[ I_AXIS ]
+               +vector[ J_AXIS ]*vector[ J_AXIS ]);
+	if (r<=size)
+          *result = omega * vector[ I_AXIS ];
+	else if(r<=taper)
+          *result = omega * vector[ I_AXIS ]*(taper-r)/(taper-size);
+        else
+          *result = 0;
+}
+
+
+
+
+void StgFEM_StandardConditionFunctions_SimpleShear( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	double                  centre;
+	double                  factor;
+	
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+
+	/* Find Centre of Solid Body Rotation */
+	centre = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SimpleShearCentreY", 0.0  );
+	factor = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SimpleShearFactor", 1.0  );
+
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	*result = factor * (coord[ J_AXIS ] - centre);
+}
+
+void StgFEM_StandardConditionFunctions_ShearZ( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	double                  centre;
+	double                  factor;
+	
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+
+	/* Find Centre of Solid Body Rotation */
+	centre = Dictionary_GetDouble_WithDefault( dictionary, "ShearZCentre", 0.0 );
+	factor = Dictionary_GetDouble_WithDefault( dictionary, "ShearZFactor", 1.0 );
+
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	*result = factor * (coord[ K_AXIS ] - centre);
+}
+
+void StgFEM_StandardConditionFunctions_SimpleShearInverted( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+        DomainContext*  context            = (DomainContext*)_context;
+        Dictionary*             dictionary         = context->dictionary;
+        FeVariable*             feVariable         = NULL;
+        FeMesh*                 mesh               = NULL;
+        double*                 result             = (double*) _result;
+        double*                 coord;
+        double                  centre;
+        double                  factor;
+        double                  yAxisInvert;
+
+        feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+        mesh       = feVariable->feMesh;
+
+        /* Find Centre of Solid Body Rotation */
+        centre = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SimpleShearCentreY", 0.0  );
+        factor = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SimpleShearFactor", 1.0  );
+
+        /* Find coordinate of node */
+        coord = Mesh_GetVertex( mesh, node_lI );
+
+        yAxisInvert = coord[ J_AXIS ] * -1.0 - 1.0;
+
+        *result = factor * ( 1.0 - coord[ J_AXIS ] ) ;
+}
+
+
+void StgFEM_StandardConditionFunctions_Extension( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	double                  centre;
+	double                  factor;
+	
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+
+	/* Find Centre of Solid Body Rotation */
+	centre = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ExtensionCentreX", 0.0  );
+	factor = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ExtensionFactor", 1.0  );
+
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( mesh, node_lI );
+
+	*result = factor * (coord[ I_AXIS ] - centre);
+}
+
+
+void StgFEM_StandardConditionFunctions_PartialLid_TopLayer( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	FeVariable*             velVar = NULL;
+	FeMesh*			mesh = NULL;
+	double*			velResult = (double*)result;
+	double                  margin = 0;
+	double			min[3], max[3];
+	
+	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh = velVar->feMesh;
+
+	Mesh_GetMinimumSeparation( mesh, &margin, NULL );
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	margin *= 1.1;
+	if( (Mesh_GetVertex( mesh, node_lI )[I_AXIS] < (max[I_AXIS] - margin )) && 
+	    (Mesh_GetVertex( mesh, node_lI )[I_AXIS] > (min[I_AXIS] + margin )))
+	{
+		(*velResult) = 1;
+	}
+	else {
+		(*velResult) = 0;
+	}
+}
+
+void StgFEM_StandardConditionFunctions_LinearInterpolationLid( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	FeVariable*             velVar = NULL;
+	FeMesh*			mesh = NULL;
+	double*			velResult = (double*)result;
+	double			boxLength = 0;
+	double			leftHandSideValue = 0;
+	double			rightHandSideValue = 0;
+	double			gradient = 0;
+	double			min[3], max[3];
+	
+	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh = velVar->feMesh;
+
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	boxLength = max[I_AXIS] - min[I_AXIS];
+	leftHandSideValue = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"bcLeftHandSideValue", 0.0  );
+	rightHandSideValue = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"bcRightHandSideValue", 1.0 );
+	gradient = (rightHandSideValue - leftHandSideValue) / boxLength;
+	(*velResult ) = leftHandSideValue + gradient * (Mesh_GetVertex( mesh, node_lI )[I_AXIS] - min[I_AXIS] );
+}
+
+
+void StgFEM_StandardConditionFunctions_Lid_RampWithCentralMax( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	FeVariable*             velVar = NULL;
+	FeMesh*			mesh = NULL;
+	double*			velResult = (double*)result;
+	double			boxLength = 0;
+	double			xPosRelativeToTopLeft = 0;
+	double			min[3], max[3];
+	
+	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh = velVar->feMesh;
+
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	xPosRelativeToTopLeft = Mesh_GetVertex( mesh, node_lI )[I_AXIS] - min[I_AXIS];
+	boxLength = max[I_AXIS] - min[I_AXIS];
+	if ( xPosRelativeToTopLeft < boxLength / 2 ) {
+		(*velResult) =  2 * xPosRelativeToTopLeft / boxLength;
+	}
+	else {
+		(*velResult) = 1 - 2 * ( xPosRelativeToTopLeft - (boxLength/2) );
+	}
+}
+void StgFEM_StandardConditionFunctions_LinearVelocityLeftWall( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	FeVariable*             velVar = NULL;
+	FeMesh*			mesh = NULL;
+	double*			velResult = (double*)result;
+	Dictionary*             dictionary         = context->dictionary;
+	double			min[3], max[3];
+	double			gradient, maxvel;
+	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh = velVar->feMesh;
+
+	maxvel = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"MaximumVelocity_Left", 0.0  );
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	gradient = maxvel/(min[1] - max[1]);
+	
+	(*velResult)   = gradient*Mesh_GetVertex( mesh, node_lI )[J_AXIS];
+	 //printf("Left velResult is %g\n",(*velResult));
+	 
+}
+void StgFEM_StandardConditionFunctions_LinearVelocityRightWall( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	FeVariable*             velVar = NULL;
+	FeMesh*			mesh = NULL;
+	double*			velResult = (double*)result;
+	Dictionary*             dictionary         = context->dictionary;
+	double			min[3], max[3];
+	double			gradient, maxvel;
+	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh = velVar->feMesh;
+
+	maxvel = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"MaximumVelocity_Right", 0.0  );
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	gradient = maxvel/(max[1] - min[1]);
+	 
+	(*velResult)   = maxvel - gradient*Mesh_GetVertex( mesh, node_lI )[J_AXIS];
+	//printf("Right velResult is %g\n",(*velResult));
+}
+
+
+void StgFEM_StandardConditionFunctions_SinusoidalLid( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	FeVariable*             velVar = NULL;
+	FeMesh*			mesh = NULL;
+	double*			velResult = (double*)result;
+	double			boxLength = 0;
+	double			linearInterp = 0;
+	double          	wavenumber;
+	double			min[3], max[3];
+
+	wavenumber = Dictionary_GetDouble_WithDefault( context->dictionary, (Dictionary_Entry_Key)"sinusoidalLidWavenumber", 1 );
+	
+	velVar = (FeVariable* )FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh = velVar->feMesh;
+
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	boxLength = max[I_AXIS] - min[I_AXIS];
+	linearInterp = (Mesh_GetVertex( mesh, node_lI )[I_AXIS] - min[I_AXIS] ) / boxLength;
+	(*velResult) = sin( linearInterp * M_PI * wavenumber );
+}
+
+
+void StgFEM_StandardConditionFunctions_CornerOnly( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	FeVariable*             velVar = NULL;
+	FeMesh*			feMesh = NULL;
+	double*			velResult = (double*)result;
+	Node_GlobalIndex	node_gI = 0;
+	unsigned		inds[3];
+	Grid*			elGrid;
+
+	velVar = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	feMesh = velVar->feMesh;
+	elGrid = *(Grid**)ExtensionManager_Get( feMesh->info, feMesh, 
+						ExtensionManager_GetHandle( feMesh->info, (Name)"elGrid" )  );
+
+	node_gI = Mesh_DomainToGlobal( feMesh, MT_VERTEX, node_lI );
+	RegularMeshUtils_Node_1DTo3D( feMesh, node_gI, inds );
+	
+	if ( inds[0] == elGrid->sizes[I_AXIS] ) {
+		(*velResult) = 1;
+	}
+	else {
+		(*velResult) = 0;
+	}
+}
+
+double StGermain_CosineHillValue( double* centre, double* position, double height, double diameterAtBase, Dimension_Index dim ) {
+	double distanceFromCentre = StGermain_DistanceBetweenPoints( centre, position, dim );
+	
+	if (distanceFromCentre < diameterAtBase * 0.5 ) 
+		return height * (0.5 + 0.5 * cos( 2.0 * M_PI/diameterAtBase * distanceFromCentre ) );
+	else
+		return 0.0;
+}
+
+void StgFEM_StandardConditionFunctions_TemperatureCosineHill( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			feMesh               = NULL;
+	double*                 result             = (double*) _result;
+	Coord                   centre;
+	Coord                   rotationCentre;
+	double                  omega;
+	double                  hillHeight;
+	double                  hillDiameter;
+	
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	feMesh       = feVariable->feMesh;
+
+	/* Read values from dictionary */
+	hillHeight       = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillHeight"  , 1.0  );
+	hillDiameter     = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillDiameter", 1.0  );
+	centre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillCentreX" , 0.0  );
+	centre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillCentreY" , 0.0  );
+	centre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"CosineHillCentreZ" , 0.0  );
+
+	if ( Dictionary_GetBool( dictionary, "RotateCosineHill" ) ) {
+		/* Assume solid body rotation */
+		rotationCentre[ I_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreX", 0.0  );
+		rotationCentre[ J_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreY", 0.0  );
+		rotationCentre[ K_AXIS ] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationCentreZ", 0.0  );
+		omega                    = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SolidBodyRotationOmega", 1.0  );
+
+		StGermain_VectorSubtraction( centre, rotationCentre, centre, context->dim );
+		StGermain_RotateCoordinateAxis( centre, centre, K_AXIS, omega * context->currentTime );
+		StGermain_VectorAddition( centre, centre, rotationCentre, context->dim );
+	}
+
+	*result = StGermain_CosineHillValue( centre, Mesh_GetVertex( feMesh, node_lI ), hillHeight, hillDiameter, context->dim );
+}
+
+
+void StgFEM_StandardConditionFunctions_LinearWithSinusoidalPerturbation( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	FeVariable*             feVariable = NULL;
+	FeMesh*			feMesh = NULL;
+	unsigned		nDims;
+	double*                 result = (double*) _result;
+	double                  topLayerBC;
+	double                  bottomLayerBC;
+	double                  perturbationAmplitude;
+	double                  horizontalWaveNumber;
+	double                  verticalWaveNumber;
+	double                  scaleFactor;
+	double*                 coord;
+	Coord                   relScaledCoord; 
+	double			min[3], max[3], topLayerCoord, bottomLayerCoord;
+	
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	feMesh       = feVariable->feMesh;
+
+	nDims = Mesh_GetDimSize( feMesh );
+	Mesh_GetGlobalCoordRange( feMesh, min, max );
+
+	topLayerCoord = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_TopLayerCoord", max[J_AXIS]  );
+	bottomLayerCoord = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_BottomLayerCoord", min[J_AXIS]  );
+
+	topLayerBC = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_TopLayerBC", 0.0  );
+	bottomLayerBC = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_BottomLayerBC", 1.0  );
+	scaleFactor = bottomLayerBC - topLayerBC;
+	perturbationAmplitude = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_PerturbationAmplitude", 0.1  );
+	/* Note: these are both multiplied by pi, so wavenumber = 1 means the perturbation goes from 0 to pi, which is
+	 * half a full sin or cos cycle. Wavenumber = 3 means the range is 0 -> 3pi, or 1 and a half full cycles. */
+	horizontalWaveNumber = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_HorizontalWaveNumber", 1.0  );
+	verticalWaveNumber = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_VerticalWaveNumber", 1.0  );
+
+	coord = Mesh_GetVertex( feMesh, node_lI );
+
+	/* if node is outside IC shape set to 0 temperature */
+	if( coord[J_AXIS] > topLayerCoord || coord[J_AXIS] < bottomLayerCoord ) {
+		*result = 0; return ;
+	}
+
+	/* make coord relative to box bottom left corner, then scale from 0 to 1 between box min & max */
+	relScaledCoord[I_AXIS] = (coord[0] - min[0]) / (max[0] - min[0]);
+	relScaledCoord[J_AXIS] = (coord[1] - bottomLayerCoord) / (topLayerCoord - bottomLayerCoord);
+
+
+	/* Note: ok to use the 1.0 below since we've already scaled the coord to somewhere between 0 to 1 */
+	*result = topLayerBC + scaleFactor * ( 1.0 - relScaledCoord[ J_AXIS ] )
+		+ perturbationAmplitude * ( cos( horizontalWaveNumber * M_PI * coord[ I_AXIS ] )
+					    * sin( verticalWaveNumber * M_PI * relScaledCoord[ J_AXIS ] ) );
+}
+
+void StgFEM_StandardConditionFunctions_Trigonometry( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			feMesh               = NULL;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	double                  height, width;
+	double			min[3], max[3];
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	feMesh       = feVariable->feMesh;
+
+	Mesh_GetGlobalCoordRange( feMesh, min, max );
+	coord = Mesh_GetVertex( feMesh, node_lI );
+
+	/* Get Aspect Ratio */
+	height = max[ J_AXIS ] - min[ J_AXIS ];
+	width  = max[ I_AXIS ] - min[ I_AXIS ];
+	
+	*result = 1.0 - 0.5 * M_PI * coord[ J_AXIS ] * sin( M_PI * coord[ I_AXIS ]/width );
+}
+
+#define SMALL 1.0e-5
+void Stg_FEM_VelicTemperatureIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*  context            = (DomainContext*)_context;
+	FeVariable*             temperatureField   = (FeVariable*) FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	FeMesh*			feMesh               = temperatureField->feMesh;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	double                  x; 
+	double                  y;
+	double                  kx;
+	double                  ky;
+	int                     wavenumberX;
+	double                  wavenumberY;
+	double                  sigma;
+	double                  Lx;
+	double			min[3], max[3];
+	
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( feMesh, node_lI );
+	Mesh_GetGlobalCoordRange( feMesh, min, max );
+
+	/* Make sure that the box has right dimensions */
+	assert( ( max[ J_AXIS ] - min[ J_AXIS ] - 1.0 ) < SMALL );
+	Lx = max[ I_AXIS ] - min[ I_AXIS ];
+
+	x = coord[ I_AXIS ] - min[ I_AXIS ];
+	y = coord[ J_AXIS ] - min[ J_AXIS ];
+
+	wavenumberX = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberX", 1  );
+	wavenumberY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberY", 1.0  );
+	sigma = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"sigma", 1.0 );
+	
+	assert( sigma > 0.0 );
+	assert( wavenumberY > 0.0 );
+	assert( wavenumberX > 0.0 );
+	
+	kx = (double)wavenumberX * M_PI / Lx;
+	ky = (double)wavenumberY * M_PI;
+
+	*result = sigma * sin( ky * y ) * cos( kx * x  );
+}
+
+/* IC from Mirko Velic. This is the IC temperature for his solB, from his Analytic Suite. Added 22-May-2006 */
+void Stg_FEM_VelicTemperatureIC_SolB( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*  context            = (DomainContext*)_context;
+	FeVariable*             temperatureField   = (FeVariable*) FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	FeMesh*			feMesh               = temperatureField->feMesh;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	double                  x; 
+	double                  y;
+	double                  km; /*  for y-direction */
+	double                  kn; /*  for x-direction */
+	double                  wavenumberX;
+	double                  wavenumberY;
+	double                  L;
+	double                  sigma;
+	double			min[3], max[3];
+	
+	/* Find coordinate of node */
+	coord = Mesh_GetVertex( feMesh, node_lI );
+	Mesh_GetGlobalCoordRange( feMesh, min, max );
+
+	/* Make sure that the box has right dimensions */
+	assert( (max[ J_AXIS ] - min[ J_AXIS ] - 1.0 ) < SMALL );
+	L = max[ I_AXIS ] - min[ I_AXIS ];
+
+	x = coord[ I_AXIS ] - min[ I_AXIS ];
+	y = coord[ J_AXIS ] - min[ J_AXIS ];
+
+	wavenumberX = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberX", 1  );
+	wavenumberY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"wavenumberY", 2.0 );
+	assert( wavenumberX != wavenumberY  );
+	sigma = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"sigma", 1.0 );
+
+	kn = wavenumberX * M_PI / L;
+/* 	 TODO: Re-write Mirko's code and/or Documentation so the input parameters for these ICs are less confusing */
+	km = wavenumberY / L;
+
+	*result = sigma * sinh( km * y ) * cos( kn * x  );
+}
+
+
+/* Initial Condition derived from Boundary Layer theory -
+   taken from P. E. van Keken, S. D. King, U. R. Schmeling, U. R. Christensen, D. Neumeister, and M.-P. Doin. A comparison of methods for the modeling of thermochemical convection. Journal of Geophysical Research, 102(B10):22477-22496, october 1997. */
+void StgFEM_StandardConditionFunctions_AnalyticalTemperatureIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			feMesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	double*                 coord;
+	double                  u0, v0, Q;
+	double                  x, y;
+	double                  RaT;
+	double                  lambda, height, width;
+	double                  Tu, Tl, Tr, Ts;
+	double			min[3], max[3];
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	feMesh       = feVariable->feMesh;
+
+	coord      = Mesh_GetVertex( feMesh, node_lI );
+	Mesh_GetGlobalCoordRange( feMesh, min, max );
+
+	/* Get Aspect Ratio */
+	height = max[ J_AXIS ] - min[ J_AXIS ];
+	width  = max[ I_AXIS ] - min[ I_AXIS ];
+	lambda = width/height;
+	
+	x = coord[ I_AXIS ] - min[ I_AXIS ];
+	y = coord[ J_AXIS ] - min[ J_AXIS ];
+	
+	/* Get thermal Rayleigh Number from Dictionary */
+	RaT = Dictionary_GetDouble( dictionary, "RaT" );
+	
+	/* Horizontal fluid velocity at upper boundary & lower boundary - Equation A3 */
+	u0 = pow( lambda , 7.0/3.0 )/ pow(1 + lambda*lambda*lambda*lambda, 2.0/3.0) * pow(0.5*RaT/sqrt(M_PI) , 2.0/3.0);
+
+	/* Vertical velocity of the upwelling and downwellings - Modified from Van Keken to match Turcotte and Shubert */
+	v0 = u0; /*lambda; */
+	
+	/* Total rate of heat flow out of the top of the cell per unit distance along the axis of the roll - Equation A3 */
+	Q = 2.0 * sqrt(M_1_PI * lambda/u0);
+	Tu = 0.5 * erf( 0.5 * ( 1 - y ) * sqrt(u0/x) );                                                      /* Equation A2a */
+	Tl = 1.0 - 0.5 * erf(0.5 * y * sqrt(u0/(lambda-x)));                                                 /* Equation A2b */
+	Tr = 0.5 + 0.5*Q/sqrt(M_PI) * sqrt(v0/(y+1)) * exp( -x*x*v0/(4*y+4) );                               /* Equation A2c */
+	Ts = 0.5 - 0.5*Q/sqrt(M_PI) * sqrt(v0/(2-y)) * exp( -(lambda - x) * (lambda - x) * v0 / (8 - 4*y) ); /* Equation A2d */
+
+	/* Equation A1 */
+	*result = Tu + Tl + Tr + Ts - 1.5;
+
+	/* Crop result */
+	if ( *result > 1.0 ) 
+		*result = 1.0;
+	else if ( *result < 0.0 ) 
+		*result = 0.0;
+	
+}
+
+void StgFEM_StandardConditionFunctions_EdgeDriveConvectionIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{        
+	DomainContext*  context = (DomainContext*)_context;        
+	Dictionary*             dictionary         = context->dictionary;        
+	FeVariable*             feVariable = NULL;        
+	FeMesh*			mesh = NULL;        
+	double*                 result = (double*) _result;        
+	double                  perturbationAmplitude;        
+	double                  thermalAnomalyOffset;        
+	double*                 coord;        
+	
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );        
+	mesh       = feVariable->feMesh;        
+	perturbationAmplitude = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalTempIC_PerturbationAmplitude", 0.1  );        
+	thermalAnomalyOffset = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"thermalAnomalyOffset", 0.0  );        
+	coord = Mesh_GetVertex( mesh, node_lI );
+	
+	/* eqn 1 from S.D.King & D.L. Anderson, "Edge-drive convection", EPSL 160 (1998) 289-296 */        
+	
+	*result = 1.0 + perturbationAmplitude * sin( M_PI * coord[ J_AXIS ] ) * cos( 0.5 * M_PI * ( coord[ I_AXIS ] + thermalAnomalyOffset ) );
+}
+
+void StgFEM_StandardConditionFunctions_ThermalEdgeDriveConvectionIC( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result )
+{
+        DomainContext*  context = (DomainContext*)_context;
+        Dictionary*             dictionary         = context->dictionary;
+        FeVariable*             feVariable = NULL;
+        FeMesh*                 mesh = NULL;
+        double*                 result = (double*) _result;
+        double*                 coord;
+        int                     dim;
+        double                  contStartX, contEndX;
+        double                  contStartY, contEndY;
+        double                  contStartZ, contEndZ;
+        double                  minY, maxY, interiorTemp;
+
+        feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+        mesh       = feVariable->feMesh;
+        coord = Mesh_GetVertex( mesh, node_lI );
+        
+	dim = Dictionary_GetInt_WithDefault( dictionary, (Dictionary_Entry_Key)"dim", 0.0  );
+        contStartX = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contStartX", 0.0  );
+        contEndX = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contEndX", 0.0  );
+        contStartY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contStartY", 0.0  );
+        contEndY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contEndY", 0.0  );
+        minY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"minY", 0.0  );
+        maxY = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"maxY", 0.0  );
+	interiorTemp = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"interiorTemp", 1.0 );
+        if ( dim == 3  ) {
+                contStartZ = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contStartZ", 0.0  );
+                contEndZ = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"contEndZ", 0.0 );
+        }
+
+        if(( coord[I_AXIS] >= contStartX && coord[ I_AXIS ] <= contEndX ) && ( coord[J_AXIS] >= contStartY && coord[ J_AXIS ] <= contEndY )) {
+                if ( dim == 3 ) {
+                        if ( coord[K_AXIS] >= contStartZ && coord[ K_AXIS ] <= contEndZ  )
+                                        *result = 0.0;
+                        else
+                                        *result = interiorTemp;
+                }
+        }
+        else
+                        *result = interiorTemp;
+}
+
+void StgFEM_StandardConditionFunctions_SinusoidalExtension( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	double                  frequency;
+	double                  vel0;
+	double                  amplitude;
+	double                  phaseShift;
+
+	frequency  = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalExtensionFrequency", 1.0  );
+	vel0       = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalExtensionVelocity", 0.0  );
+	amplitude  = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalExtensionAmplitude", 0.0  );
+	phaseShift = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SinusoidalExtensionPhaseShift", 0.0 );
+
+
+	*result = vel0 + amplitude * cos( 2.0 * M_PI * frequency * (context->currentTime + context->dt - phaseShift )  );
+}
+
+
+void StgFEM_StandardConditionFunctions_StepFunction( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			feMesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double                  lower_offset, upper_offset;
+	double                  value, lower_value, upper_value;
+	unsigned		dim;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	feMesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( feMesh, node_lI );
+
+	lower_offset = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionLowerOffset", 0.0 );
+	upper_offset = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionUpperOffset", lower_offset );
+	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionValue", 0.0 );
+	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionDim", 0 );
+
+        lower_value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionLowerValue", 0.0 );
+        upper_value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionUpperValue", value );
+
+        if(dim==3)
+          {
+            dim=0;
+            coord=&(context->currentTime);
+          }
+
+        if(coord[dim] < lower_offset) {
+          *result=lower_value;
+        } else if(coord[dim] < upper_offset) {
+          *result=lower_value + 
+            (upper_value-lower_value)
+            *(coord[dim] - lower_offset)/(upper_offset-lower_offset);
+        } else {
+          *result=upper_value;
+        }
+}
+
+
+void StG_FEM_StandardConditionFunctions_StepFunctionProduct1( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*     mesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double                  start, end;
+	double                  value;
+	unsigned		dim;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( mesh, node_lI );
+
+	start = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct1Start", 0.0 );
+	end = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct1End", 0.0 );
+	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct1Value", 0.0 );
+	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionProduct1Dim", 0 );
+
+        if( coord[dim] > start && coord[dim] < end ) {
+          *result = value;
+        }
+        else {
+          *result = 0;
+        }
+}
+
+void StG_FEM_StandardConditionFunctions_StepFunctionProduct2( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*     mesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double                  start, end;
+	double                  value;
+	unsigned		dim;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( mesh, node_lI );
+
+	start = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct2Start", 0.0 );
+	end = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct2End", 0.0 );
+	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct2Value", 0.0 );
+	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionProduct2Dim", 0 );
+
+        if( coord[dim] > start && coord[dim] < end ) {
+          *result = value;
+        }
+        else {
+          *result = 0;
+        }
+}
+
+
+void StG_FEM_StandardConditionFunctions_StepFunctionProduct3( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*     mesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double                  start, end;
+	double                  value;
+	unsigned		dim;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( mesh, node_lI );
+
+	start = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct3Start", 0.0 );
+	end = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct3End", 0.0 );
+	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct3Value", 0.0 );
+	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionProduct3Dim", 1 );
+
+        if( coord[dim] > start && coord[dim] < end ) {
+          *result = value;
+        }
+        else {
+          *result = 0;
+        }
+}
+
+void StG_FEM_StandardConditionFunctions_StepFunctionProduct4( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*     mesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double                  start, end;
+	double                  value;
+	unsigned		dim;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( mesh, node_lI );
+
+	start = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct4Start", 0.0 );
+	end = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct4End", 0.0 );
+	value = Dictionary_GetDouble_WithDefault( dictionary, "StepFunctionProduct4Value", 0.0 );
+	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "StepFunctionProduct4Dim", 1 );
+
+        if( coord[dim] > start && coord[dim] < end ) {
+          *result = value;
+        }
+        else {
+          *result = 0;
+        }
+}
+
+/* A Gaussian GaussianHeight*exp(-((GaussianCenter-x)/GaussianWidth)^2) */
+
+void StG_FEM_StandardConditionFunctions_Gaussian
+( Node_LocalIndex node_lI, Variable_Index var_I, void* _context,
+  void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*     mesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double                  center, width, height;
+	unsigned		dim;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( mesh, node_lI );
+
+        center = Dictionary_GetDouble_WithDefault( dictionary,
+                                                   "GaussianCenter", 0.0 );
+	width = Dictionary_GetDouble_WithDefault( dictionary,
+                                                  "GaussianWidth", 1.0 );
+	height = Dictionary_GetDouble_WithDefault( dictionary,
+                                                   "GaussianHeight", 1.0 );
+	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary,
+                                                     "GaussianDim", 0 );
+
+        *result=height*exp(-(center-coord[dim])*(center-coord[dim])
+                           /(width*width));
+}
+
+void StgFEM_StandardConditionFunctions_MovingStepFunction( Node_LocalIndex nodeInd, Variable_Index varInd, void* _ctx, void* _result ) {
+   FiniteElementContext* ctx = (FiniteElementContext*)_ctx;
+   FeVariable* velField;
+   FeMesh* mesh;
+   Dictionary* dict = ctx->dictionary;
+   double* result = (double*)_result;
+   double* coord, offsetLower, offsetUpper, left, right;
+   double *wallCrd, pos;
+   int dim, wallDepth;
+   unsigned ijk[3];
+   char* movingWall;
+   Grid* grid;
+
+   /*
+   ** Get the velocity field. */
+   velField = (FeVariable*)FieldVariable_Register_GetByName(
+      ctx->fieldVariable_Register, "VelocityField" );
+
+   /*
+   ** Get the mesh and the coordinate of the node. */
+   mesh = velField->feMesh;
+   coord = Mesh_GetVertex( mesh, nodeInd );
+
+   /*
+   ** Extract all the parameters we need from the dictionary. */
+   offsetLower = Dictionary_GetDouble_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionOffsetLower", 0.0  );
+   offsetUpper = Dictionary_GetDouble_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionOffsetUpper", 0.0  );
+   dim = Dictionary_GetUnsignedInt_WithDefault( dict, "MovingStepFunctionDim", 0 );
+   left = Dictionary_GetDouble_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionLeftSide", 0.0  );
+   right = Dictionary_GetDouble_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionRightSide", 0.0  );
+   movingWall = Dictionary_GetString_WithDefault( dict, "MovingStepFunctionMovingWall", "lower" );
+   wallDepth = Dictionary_GetInt_WithDefault( dict, (Dictionary_Entry_Key)"MovingStepFunctionWallDepth", 0  );
+
+   /*
+   ** Because we're dealing with a moving step function, we need to calculate
+   ** from where the offset should be applied. */
+   grid = *(Grid**)Mesh_GetExtension( mesh, Grid**, "vertexGrid" );
+   assert( grid );
+   memset( ijk, 0, 3 * sizeof(unsigned) );
+   if( !strcmp( movingWall, "lower" ) ) {
+      ijk[dim] = wallDepth;
+      wallCrd = Mesh_GetVertex( mesh, Grid_Project( grid, ijk ) );
+      offsetLower += wallCrd[dim];
+      offsetUpper += wallCrd[dim];
+   }
+   else {
+      ijk[dim] = grid->sizes[dim] - wallDepth - 1;
+      wallCrd = Mesh_GetVertex( mesh, Grid_Project( grid, ijk ) );
+      offsetLower += wallCrd[dim];
+      offsetUpper += wallCrd[dim];
+   }
+
+   /*
+   ** Apply the set of parameters to this node. */
+   pos = coord[dim];
+   if( pos <= offsetLower )
+      *result = left;
+   else if( pos >= offsetUpper )
+      *result = right;
+   else {
+      *result = left + ((pos - offsetLower) / (offsetUpper - offsetLower)) * (right - left);
+   }
+}
+
+void StgFEM_StandardConditionFunctions_ConvectionBenchmark( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	/* This IC is for the 2D ConvectionBenchmark defined in
+	 * http://www.mcc.monash.edu.au/twiki/view/Research/ConvectionBenchmarks
+	 */
+	
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			mesh;
+	double*                 result             = (double*) _result;
+	double			min[3], max[3];
+        double*                 coord;
+	double                  x,y;
+	double                  Lx, Ly;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+	mesh       = (FeMesh*)feVariable->feMesh;
+
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	
+	Lx = max[ I_AXIS ] - min[ I_AXIS ];
+	Ly = max[ J_AXIS ] - min[ J_AXIS ];
+	
+	coord      = Mesh_GetVertex( mesh, node_lI );
+
+	x = ( coord[0] - min[ I_AXIS ] ) / Lx;
+	y = ( coord[1] - min[ J_AXIS ] ) / Ly;
+
+
+	*result = ( 1 - y ) + ( cos( M_PI * x ) * sin( M_PI * y ) ) / 100 ;
+}
+
+void StgFEM_StandardConditionFunctions_ConstantVector( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*		context            = (DomainContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	
+	result[0] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ConstantValueX", 0.0  );
+	result[1] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ConstantValueY", 0.0 );
+  if (context->dim == 3  ) 
+    result[2] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ConstantValueZ", 0.0 );
+}
+
+/* 3D spec ridge top BC (for milestone 1 of magma project ) 
+ * to be applied to the top x-z plane of the domain */
+void StgFEM_StandardConditionFunctions_SpecRidge3D( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			feMesh             = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+
+	double			leftVal;
+	double			rightVal;
+	double			xOffset1;
+	double			xOffset2;
+	double			yOffset1, yOffset2;
+	double			xBegin, xEnd;
+	double			zBegin, zEnd;
+
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	feMesh     = feVariable->feMesh;
+	coord      = Mesh_GetVertex( feMesh, node_lI );
+
+	leftVal = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DLeftSide", 0.0  );
+	rightVal = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DRightSide", 0.0  );
+	xOffset1 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DXOffset1", 0.0  );
+	xOffset2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DXOffset2", 0.0  );
+	yOffset1 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DZOffset1", 0.0  );
+	yOffset2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DZOffset2", 0.0  );
+	xBegin = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DXBegin", 0.0  );
+	xEnd = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DXEnd", 0.0  );
+	zBegin = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DZBegin", 0.0  );
+	zEnd = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"SpecRidge3DZEnd", 0.0 );
+
+	if( coord[0] < xBegin || coord[0] > xEnd ||
+	    coord[2] < zBegin || coord[2] > zEnd )
+	{
+		*result = 0.0;
+	}
+	else if( coord[0] < xOffset1 )
+		*result = leftVal;
+	else if( coord[0] < xOffset2 && coord[2] > yOffset1 && coord[2] < yOffset2  )
+		*result = leftVal;
+	else
+		*result = rightVal;
+}
+
+void StgFEM_StandardConditionFunctions_TemperatureProfile( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+  FiniteElementContext *	context            = (FiniteElementContext*)_context;
+  FeVariable*             feVariable         = NULL;
+  FeMesh*     mesh               = NULL;
+  Dictionary*             dictionary         = context->dictionary;
+  double*                 result             = (double*) _result;
+  double*                 coord;
+  double                  T_0, H_0, dH, H, H_m, A, B, C, x_min, x_max, y_max, T_m, xc, dum;
+  /* G.Ito 10/08 added variables x_min, x_max, T_m, Xc, to do variation in x
+     and limit maximum T */
+  
+  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+  mesh       = feVariable->feMesh;
+  coord      = Mesh_GetVertex( mesh, node_lI );
+  
+  T_0 = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileTop", 0.0 );
+  T_m = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileMax", 10000.0 );
+  H_0 = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileH0", -1.0 );
+  H_m = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileHm", 1.0e+8 );
+  dH = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfiledH", 0.0 );     
+  A = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileLinearCoefficient", 0.0 );
+  B = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileExponentialCoefficient1", 0.0 );
+  C = Dictionary_GetDouble_WithDefault( dictionary, "TemperatureProfileExponentialCoefficient2", 0.0 );
+  y_max = Dictionary_GetDouble_WithDefault( dictionary, "maxY", 0.0 );
+  x_max = Dictionary_GetDouble_WithDefault( dictionary, "maxX", 0.0 );
+  x_min = Dictionary_GetDouble_WithDefault( dictionary, "minX", 0.0 );
+  xc = Dictionary_GetDouble_WithDefault( dictionary, "ExtensionCentreX", 0.0 );
+  
+  if (H_0<0.0)
+    {
+      if(coord[1]>y_max)
+        {
+          *result=T_0;
+        }
+      else
+        {
+          *result=T_0 + A*(y_max-coord[1]) + B*(1-exp(-C*(y_max-coord[1])));
+        }
+    }
+  else
+    {
+      if(coord[1]>=y_max)
+        {
+          *result=T_0;
+        }
+      else
+        {
+          H=H_0 + 2*fabs(coord[0]-xc)/(x_max-x_min)*dH;
+          if (H>H_m) H=H_m;
+          
+          dum=T_0 + ((T_m-T_0)/H)*(y_max-coord[1])
+            + B*(1-exp(-C*(y_max-coord[1])));
+          if (dum>T_m) dum=T_m;
+          *result=dum;
+        }
+    }
+
+}
+
+void StgFEM_StandardConditionFunctions_ERF( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			feMesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double                  width, scale, dilate, offset, constant;
+	unsigned		dim;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	feMesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( feMesh, node_lI );
+
+	width = Dictionary_GetDouble_WithDefault( dictionary, "ERFWidth", 0.0 );
+	offset= Dictionary_GetDouble_WithDefault(dictionary, "ERFOffset",0.0 );
+	constant=Dictionary_GetDouble_WithDefault(dictionary,"ERFConstant",0.0);
+        scale = Dictionary_GetDouble_WithDefault( dictionary, "ERFScale", 1.0 );
+	dilate = Dictionary_GetDouble_WithDefault( dictionary,"ERFDilate",1.0 );
+	dim = Dictionary_GetUnsignedInt_WithDefault( dictionary, "ERFDim", 0 );
+
+        if(dim==3)
+          {
+            dim=0;
+            coord=&(context->currentTime);
+          }
+
+        if(coord[dim]+offset < -width && width!=0)
+          *result=constant-scale;
+        else if(coord[dim]+offset > width && width!=0)
+          *result=constant+scale;
+        else
+          *result=constant+scale*erf((coord[dim]+offset)/dilate);
+}
+
+void StgFEM_StandardConditionFunctions_ERFC(Node_LocalIndex node_lI,
+                                            Variable_Index var_I,
+                                            void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			feMesh               = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double                  width, scale, dilate, offset, constant;
+	unsigned		dim;
+
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName
+          ( context->fieldVariable_Register, "VelocityField" );
+	feMesh       = feVariable->feMesh;
+	coord      = Mesh_GetVertex( feMesh, node_lI );
+
+	width = Dictionary_GetDouble_WithDefault(dictionary, "ERFCWidth", 0.0 );
+	offset= Dictionary_GetDouble_WithDefault(dictionary, "ERFCOffset",0.0 );
+	constant=Dictionary_GetDouble_WithDefault(dictionary,"ERFCConstant",0.0);
+        scale = Dictionary_GetDouble_WithDefault(dictionary, "ERFCScale", 1.0 );
+	dilate = Dictionary_GetDouble_WithDefault(dictionary,"ERFCDilate",1.0 );
+	dim = Dictionary_GetUnsignedInt_WithDefault(dictionary, "ERFCDim", 0 );
+
+        if(dim==3)
+          {
+            dim=0;
+            coord=&(context->currentTime);
+          }
+
+        if(coord[dim]+offset < -width && width!=0)
+          *result=constant-scale;
+        else if(coord[dim]+offset > width && width!=0)
+          *result=constant+scale;
+        else
+          *result=constant+scale*erfc((coord[dim]+offset)/dilate);
+}
+
+void StgFEM_StandardConditionFunctions_RubberSheet( Node_LocalIndex node_lI,
+                                                    Variable_Index var_I,
+                                                    void* _context,
+                                                    void* _result )
+{
+  FiniteElementContext *	context            = (FiniteElementContext*)_context;
+  FeVariable*             feVariable         = NULL;
+  FeMesh*			feMesh               = NULL;
+  Dictionary*             dictionary         = context->dictionary;
+  double*                 result             = (double*) _result;
+  double*                 coord;
+  double                  lower_offset, upper_offset;
+  double                  lower_value, upper_value, time;
+  unsigned		dim;
+
+  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+  feMesh       = feVariable->feMesh;
+  coord      = Mesh_GetVertex( feMesh, node_lI );
+
+  lower_offset = Dictionary_GetDouble_WithDefault( dictionary,
+                                                   "RubberSheetLowerOffset",
+                                                   0.0 );
+  upper_offset = Dictionary_GetDouble_WithDefault( dictionary,
+                                                   "RubberSheetUpperOffset",
+                                                   lower_offset );
+  dim = Dictionary_GetUnsignedInt_WithDefault( dictionary,
+                                               "RubberSheetDim", 0 );
+
+  lower_value = Dictionary_GetDouble_WithDefault( dictionary,
+                                                  "RubberSheetLowerValue",
+                                                  0.0 );
+  upper_value = Dictionary_GetDouble_WithDefault( dictionary,
+                                                  "RubberSheetUpperValue",
+                                                  0.0 );
+
+  time=context->currentTime;
+
+  if(coord[dim] < lower_offset + lower_value*time)
+    {
+      *result=lower_value;
+    }
+  else if(coord[dim] < upper_offset + upper_value*time)
+    {
+      double min[3], max[3];
+      Mesh_GetGlobalCoordRange( feMesh, min, max );
+      *result=lower_value + 
+        (upper_value-lower_value)
+        *(coord[dim] - min[dim])/(max[dim]-min[dim]);
+    }
+  else
+    {
+      *result=upper_value;
+    }
+}
+
+/* get the BC's from the analytic solution as stored on the relevant FeVariable */
+void StgFEM_StandardConditionFunctions_SpectralBCX( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             analyticFeVarX     = NULL;
+	FeVariable*             numericFeVar       = NULL;
+	double*                 result             = (double*) _result;
+	/*FeMesh*			feMesh             = NULL;
+        double*                 coord;
+	Node_LocalIndex		analyticNodeI;
+	Element_DomainIndex	analyticElement_I;
+	double			analyticLocalElementCoord[3];
+	FeMesh*			analyticFeMesh;
+	*/
+	analyticFeVarX = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralVelocityXField" );
+	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	//feMesh         = numericFeVar->feMesh;
+	//coord          = Mesh_GetVertex( feMesh, node_lI );
+
+	//analyticFeMesh = analyticFeVarX->feMesh;
+	//if( Mesh_SearchElements( analyticFeMesh, coord, &analyticElement_I ) ) {
+	//	FeMesh_CoordGlobalToLocal( analyticFeMesh, analyticElement_I, coord, analyticLocalElementCoord );
+	//	FeVariable_InterpolateWithinElement( analyticFeVarX, analyticElement_I, analyticLocalElementCoord, result );
+	//}
+	//else {	/* numerical solution node outside analytic mesh - just find closest point & use that */
+	//	analyticNodeI  = Mesh_NearestVertex( analyticFeMesh, coord );
+	//	FeVariable_GetValueAtNode( analyticFeVarX, analyticNodeI, result );
+	//}
+	
+	FeVariable_GetValueAtNode( analyticFeVarX, node_lI, result );
+}
+
+void StgFEM_StandardConditionFunctions_SpectralBCY( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             analyticFeVarY     = NULL;
+	FeVariable*             numericFeVar       = NULL;
+	double*                 result             = (double*) _result;
+	/*FeMesh*			feMesh             = NULL;
+        double*                 coord;
+	Node_LocalIndex		analyticNodeI;
+	Element_DomainIndex	analyticElement_I;
+	double			analyticLocalElementCoord[3];
+	FeMesh*			analyticFeMesh;
+	*/
+	analyticFeVarY = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralVelocityYField" );
+	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	//feMesh         = numericFeVar->feMesh;
+	//coord          = Mesh_GetVertex( feMesh, node_lI );
+
+	//analyticFeMesh = analyticFeVarY->feMesh;
+	//if( Mesh_SearchElements( analyticFeMesh, coord, &analyticElement_I ) ) {
+	//	FeMesh_CoordGlobalToLocal( analyticFeMesh, analyticElement_I, coord, analyticLocalElementCoord );
+	//	FeVariable_InterpolateWithinElement( analyticFeVarY, analyticElement_I, analyticLocalElementCoord, result );
+	//}
+	//else {
+	//	analyticNodeI  = Mesh_NearestVertex( analyticFeMesh, coord );
+	//	FeVariable_GetValueAtNode( analyticFeVarY, analyticNodeI, result );
+	//}
+	
+	FeVariable_GetValueAtNode( analyticFeVarY, node_lI, result );
+}
+
+void StgFEM_StandardConditionFunctions_SpectralBCZ( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             analyticFeVarZ     = NULL;
+	FeVariable*             numericFeVar       = NULL;
+	double*                 result             = (double*) _result;
+	/*
+	FeMesh*			feMesh             = NULL;
+        double*                 coord;
+	Node_LocalIndex		analyticNodeI;
+	Element_DomainIndex	analyticElement_I;
+	double			analyticLocalElementCoord[3];
+	FeMesh*			analyticFeMesh;
+	*/
+	analyticFeVarZ = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralVelocityZField" );
+	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	//feMesh         = numericFeVar->feMesh;
+	//coord          = Mesh_GetVertex( feMesh, node_lI );
+
+	//analyticFeMesh = analyticFeVarZ->feMesh;
+	//if( Mesh_SearchElements( analyticFeMesh, coord, &analyticElement_I ) ) {
+	//	FeMesh_CoordGlobalToLocal( analyticFeMesh, analyticElement_I, coord, analyticLocalElementCoord );
+	//	FeVariable_InterpolateWithinElement( analyticFeVarZ, analyticElement_I, analyticLocalElementCoord, result );
+	//}
+	//else {
+	//	analyticNodeI  = Mesh_NearestVertex( analyticFeMesh, coord );
+	//	FeVariable_GetValueAtNode( analyticFeVarZ, analyticNodeI, result );
+	//}
+	
+	FeVariable_GetValueAtNode( analyticFeVarZ, node_lI, result );
+}
+
+void StgFEM_StandardConditionFunctions_SpectralPressureBCX( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             analyticFeVarX     = NULL;
+	FeVariable*             numericFeVar       = NULL;
+	FeMesh*			feMesh             = NULL;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+
+	analyticFeVarX = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralPressureField" );
+	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "PressureField" );
+	feMesh         = numericFeVar->feMesh;
+	coord          = Mesh_GetVertex( feMesh, node_lI );
+
+	FeVariable_GetValueAtNode( analyticFeVarX, node_lI, result );
+}
+
+void StgFEM_StandardConditionFunctions_SpectralPressureBCY( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             analyticFeVarY     = NULL;
+	FeVariable*             numericFeVar       = NULL;
+	FeMesh*			feMesh             = NULL;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+
+	analyticFeVarY = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "SpectralPressureField" );
+	numericFeVar   = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "PressureField" );
+	feMesh         = numericFeVar->feMesh;
+	coord          = Mesh_GetVertex( feMesh, node_lI );
+
+	FeVariable_GetValueAtNode( analyticFeVarY, node_lI, result );
+}
+
+/* error function for use in 3D spec ridge top BC */
+double errorFunction( double z, int n ) {
+	double		pi	= 3.1415926535;
+	double 		a;
+	double 		erf 	= 0.0;
+	int		denom;
+	int		i, j;
+
+	a = 2.0/sqrt( pi );
+
+	for( i=0 ; i<n ; i++ ) {
+		denom = 1;
+		for( j=1 ; j<=2*i+1 ; j+=2 ) 
+			denom *= j; 
+		
+		erf += pow( 2, i )*pow( z, 2*i+1 )/denom;
+	}
+
+	return erf *= a*exp( -1.0*z*z );
+}
+
+
+
+void StgFEM_StandardConditionFunctions_ErrorFunc( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	FeMesh*			feMesh             = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+        double*                 coord;
+	double			dilate;
+	double			width; 
+
+	feVariable  = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	feMesh      = feVariable->feMesh;
+	coord       = Mesh_GetVertex( feMesh, node_lI );
+
+	dilate      = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ErrorFuncDilate", 0.0  );
+	width       = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"ErrorFuncWidth", 0.0 );
+
+	if( coord[0] < -1.0*width ) {
+		*result = -1.0;
+	}
+	else if( coord[0] > width  ) {
+		*result = 1.0;
+	}
+	else {
+		*result     = errorFunction( coord[0]/dilate, 5 );	
+	}
+}
+
+void StgFEM_StandardConditionFunctions_GaussianDistribution( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	Name			variableName;
+	double*			coord;
+	unsigned		nDims              = context->dim;
+	unsigned		dim_I;
+	double			orig[3];
+	double			sigma              = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"sigma", 1.0  );
+	double			gaussianScale      = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianScale", 1.0  );
+	double			background         = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"backgroundValue", 1.0  );
+	double			distsq             = 0.0;
+
+	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
+	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
+
+	orig[0] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"x0", 0.0  );
+	orig[1] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"y0", 0.0  );
+	orig[2] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"z0", 0.0 );
+
+	for( dim_I = 0; dim_I < nDims; dim_I++ )
+		distsq += ( coord[dim_I] - orig[dim_I] ) * ( coord[dim_I] - orig[dim_I] );
+
+	*result = gaussianScale * exp( -distsq / ( 2.0 * sigma * sigma )  ) + background;
+}
+
+void StgFEM_StandardConditionFunctions_GravitationalPotential( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	Name			variableName;
+	double*			coord;
+
+	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
+	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
+
+	*result = -1.0 * coord[J_AXIS];
+}
+
+void StgFEM_StandardConditionFunctions_1DGaussianDistribution( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	Name			variableName;
+	double*			coord;
+	double			orig[3];
+	double			sigma              = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"sigma", 1.0  );
+	double			gaussianScale      = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianScale", 1.0  );
+	double			background         = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"backgroundValue", 1.0  );
+	double			distsq             = 0.0;
+
+	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
+	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
+
+	orig[0] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"x0", 0.0  );
+	orig[1] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"y0", 0.0  );
+	orig[2] = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"z0", 0.0 );
+
+	distsq = ( coord[J_AXIS] - orig[J_AXIS] ) * ( coord[J_AXIS] - orig[J_AXIS] );
+
+	*result = gaussianScale * exp( -distsq / ( 2.0 * sigma * sigma )  ) + background;
+}
+
+void StgFEM_StandardConditionFunctions_HalfContainer( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	FeVariable*             feVariable         = NULL;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	Name			variableName;
+	double*			coord;
+	double			halfPoint          = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"halfPoint", 0.0  );
+
+	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
+	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
+
+	if( coord[1] < halfPoint )
+		*result = 1;
+	else
+		*result = 0;	
+}
+
+void StgFEM_StandardConditionFunctions_ConstantValue( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	double			value              = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"constantValue", 1.0  );
+
+	*result = value;
+}
+
+void StgFEM_StandardConditionFunctions_DiagonalLine( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	double			width              = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"lineWidth", 1.0  );
+	double*			coord;
+	Name			variableName;
+	FeVariable*             feVariable         = NULL;
+
+	variableName = Dictionary_GetString_WithDefault( dictionary, "FieldVariable", "" );
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
+	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
+
+	if( fabs( coord[0] - coord[1] ) < width )
+		*result = 1.0;
+	else
+		*result = 0.0;
+}
+
+void StgFEM_StandardConditionFunctions_DeltaFunction( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	FiniteElementContext *	context            = (FiniteElementContext*)_context;
+	Dictionary*             dictionary         = context->dictionary;
+	double*                 result             = (double*) _result;
+	double			epsilon		   = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"deltaFunctionEpsilon", 0.001  );
+	unsigned		dim		   = Dictionary_GetUnsignedInt_WithDefault( dictionary, "deltaFunctionDim", 0 );
+	double			centre		   = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"deltaFunctionCentre", 0.5  );
+	double			value		   = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"deltaFunctionValue", 1.0  );
+	double*			coord;
+	Name			variableName	   = Dictionary_GetString_WithDefault( dictionary, "DeltaFunctionFeVariable", "" );
+	FeVariable*		feVariable	   = (FeVariable*) FieldVariable_Register_GetByName( context->fieldVariable_Register, variableName );
+
+	coord = Mesh_GetVertex( feVariable->feMesh, node_lI );
+	
+	*result = (fabs( coord[dim] - centre ) < epsilon) ? value : 0.0;
+}
+
+void StgFEM_StandardConditionFunctions_InflowBottom( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) {
+	DomainContext*	context            = (DomainContext*)_context;
+	FeVariable* feVariable;
+	Dictionary*             dictionary         = context->dictionary;
+	FeMesh*			mesh               = NULL;
+	double*                 result             = (double*) _result;
+	double sideLength, wallLength, sideV;
+	double min[3], max[3];
+	
+	feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+	mesh       = feVariable->feMesh;
+	Mesh_GetGlobalCoordRange( mesh, min, max );
+	sideLength = max[1] - min[1];
+	wallLength = max[0] - min[0];
+	sideV = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"InflowSideVelocity", 1.0  );
+
+	*result = 2.0 * sideV * sideLength / wallLength;
+}
+
+void StgFEM_StandardConditionFunctions_GaussianTube( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+        DomainContext*  context = (DomainContext*)_context;
+        Dictionary*             dictionary         = context->dictionary;
+        FeVariable*             feVariable = NULL;
+        FeMesh*                 feMesh = NULL;
+        unsigned                nDims;
+        double*                 result = (double*) _result;
+        double                  a1,b1,c1, a2,b2,c2, x,y,z,r_y,r_yz;
+        double*                 coord;
+        double                  min[3], max[3];
+	double                  y_shift, z_shift;
+
+        feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "TemperatureField" );
+        feMesh       = feVariable->feMesh;
+
+        nDims = Mesh_GetDimSize( feMesh );
+        Mesh_GetGlobalCoordRange( feMesh, min, max );
+
+ 	a1 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_a1", 1.0  ); /* Scales the magnitude of the perturbation. */
+	c1 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_c1", 0.1  ); /* Controls the smoothing length. Smaller values produce less smoothing. */
+
+        a2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_a2", 0.05  ); /* Controls ampltude of oscillations */
+        b2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_b2", 6.28318530718  ); /* Controls frequency of oscillations */
+	c2 = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_c2", 1.570796326795  ); /* Shifts oscillations */
+
+	y_shift = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_y_origin", 0.0  );
+	z_shift = Dictionary_GetDouble_WithDefault( dictionary, (Dictionary_Entry_Key)"GaussianTube_z_origin", 0.0  );
+
+        coord = Mesh_GetVertex( feMesh, node_lI );
+
+	x = coord[ I_AXIS ];
+	y = coord[ J_AXIS ];
+
+	y = y - y_shift;
+	if (nDims==2) {
+		b1 = a2 * sin( b2*x - c2 );
+		r_y = sqrt( (y-b1)*(y-b1) );
+		*result = a1 * exp( -(r_y * r_y) / (2.0*c1*c1) );
+	}
+	if (nDims==3) {
+		z = coord[ K_AXIS ];
+		z = z - z_shift;
+
+		b1 = a2 * sin( b2*x - c2 );
+		r_yz = sqrt( (y-b1)*(y-b1) + z*z );
+		*result = a1 * exp( -(r_yz * r_yz) / (2.0*c1*c1) );
+	}
+
+
+}
+
+
+void StgFEM_StandardConditionFunctions_WarsTemperature( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  FiniteElementContext *	context            = (FiniteElementContext*)_context;
+  FeVariable*             feVariable         = NULL;
+  FeMesh*     mesh               = NULL;
+  Dictionary*             dictionary         = context->dictionary;
+  double*                 result             = (double*) _result;
+  double*                 coord;
+  double                  EAEnd, WarsStart, WarsHeight, WarsTTop,
+    WarsTBottom, h, maxY;
+  
+  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+  mesh       = feVariable->feMesh;
+  coord      = Mesh_GetVertex( mesh, node_lI );
+  
+  EAEnd = Dictionary_GetDouble( dictionary, "EAEnd");
+  WarsStart = Dictionary_GetDouble( dictionary, "WarsStart");
+  WarsHeight = Dictionary_GetDouble( dictionary, "WarsHeight");
+  WarsTTop = Dictionary_GetDouble( dictionary, "WarsTTop");
+  WarsTBottom = Dictionary_GetDouble( dictionary, "WarsTBottom");     
+  maxY=Dictionary_GetDouble( dictionary, "maxY");
+
+
+  h=WarsHeight*(coord[0]-EAEnd)/(WarsStart-EAEnd);
+  if(coord[0]<EAEnd)
+    h=0;
+  if(coord[0]>WarsStart)
+    h=WarsHeight;
+  *result=WarsTBottom + ((coord[1]-h)/(maxY-h))*(WarsTTop-WarsTBottom);
+}
+
+void StgFEM_StandardConditionFunctions_Quadratic( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  FiniteElementContext *	context            = (FiniteElementContext*)_context;
+  FeVariable*             feVariable         = NULL;
+  FeMesh*     mesh               = NULL;
+  Dictionary*             dictionary         = context->dictionary;
+  double*                 result             = (double*) _result;
+  double*                 coord;
+  int                     dim;
+  double                  a, b, c;
+  
+  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+  mesh       = feVariable->feMesh;
+  coord      = Mesh_GetVertex( mesh, node_lI );
+  
+  dim = Dictionary_GetInt( dictionary, "Quadratic_Dim");
+  a = Dictionary_GetDouble( dictionary, "Quadratic_Constant");
+  b = Dictionary_GetDouble( dictionary, "Quadratic_Linear");
+  c = Dictionary_GetDouble( dictionary, "Quadratic_Quadratic");
+
+  *result= a + coord[dim]*(b + c*coord[dim]);
+}
+
+int Binary_Search(double *data, int s, int e, double value);
+
+void StgFEM_StandardConditionFunctions_FileN( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result, int file_num, double **coords, double **data);
+
+void StgFEM_StandardConditionFunctions_File1( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,1,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File2( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,2,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File3( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,3,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File4( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,4,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File5( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,5,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File6( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,6,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File7( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,7,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File8( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,8,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File9( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,9,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_File10( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result ) 
+{
+  static double *coords=NULL;
+  static double *data=NULL;
+  StgFEM_StandardConditionFunctions_FileN(node_lI,var_I,_context,_result,10,
+                                          &coords,&data);
+}
+
+void StgFEM_StandardConditionFunctions_FileN( Node_LocalIndex node_lI, Variable_Index var_I, void* _context, void* _result, int file_num, double **coords, double **data)
+{
+  FiniteElementContext *	context            = (FiniteElementContext*)_context;
+  FeVariable*             feVariable         = NULL;
+  FeMesh*     mesh               = NULL;
+  Dictionary*             dictionary         = context->dictionary;
+  double*                 result             = (double*) _result;
+  double*                 coord;
+  int                     dim, dim2, dim3, i, j, k;
+  char *filename;
+  int N, N2, N3, ndims;
+  int result_index, result_index2, result_index3;
+  double factor, factor2, factor3;
+  feVariable = (FeVariable*)FieldVariable_Register_GetByName( context->fieldVariable_Register, "VelocityField" );
+  mesh       = feVariable->feMesh;
+  coord      = Mesh_GetVertex( mesh, node_lI );
+  
+  char fileN_number[10], fileN_dim[15], fileN_dim2[15], fileN_dim3[15],
+    fileN_name[128], fileN_N[15], fileN_N2[15], fileN_N3[15];
+  sprintf(fileN_number,"File%d",file_num);
+  sprintf(fileN_dim,"File%d_Dim",file_num);
+  sprintf(fileN_dim2,"File%d_Dim2",file_num);
+  sprintf(fileN_dim3,"File%d_Dim3",file_num);
+  sprintf(fileN_name,"File%d_Name",file_num);
+  sprintf(fileN_N,"File%d_N",file_num);
+  sprintf(fileN_N2,"File%d_N2",file_num);
+  sprintf(fileN_N3,"File%d_N3",file_num);
+
+  filename = Dictionary_GetString( dictionary, fileN_name);
+  N = Dictionary_GetInt( dictionary, fileN_N);
+  dim = Dictionary_GetInt( dictionary, fileN_dim);
+  N2 = Dictionary_GetInt_WithDefault( dictionary, fileN_N2,-1);
+  N3 = Dictionary_GetInt_WithDefault( dictionary, fileN_N3,-1);
+
+  if(N2==-1)
+    ndims=1;
+  else if(N3==-1)
+    ndims=2;
+  else
+    ndims=3;
+
+  if(ndims>1)
+    {
+      dim2 = Dictionary_GetInt( dictionary, fileN_dim2);
+      if(ndims>2)
+        dim3 = Dictionary_GetInt( dictionary, fileN_dim3);
+    }
+
+  Journal_Firewall(dim>=0 && dim<3,
+                   Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
+                   "%s must be either 0, 1, or 2, but was set to %d\n",
+                   fileN_dim,dim);
+  Journal_Firewall(N>0,
+                   Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
+                   "%s must be greater than zero, but was set to %d.\n",
+                   fileN_N,N);
+  if(*data==NULL)
+    {
+      FILE *fp=fopen(filename,"r");
+      Journal_Firewall(fp!=NULL,
+                       Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
+                       "Bad filename for %s.  Could not open %s\n",
+                       fileN_name,filename);
+
+      /* In 1D, data and coords are simple 1D arrays.  In 2D, data is
+         a 2D arrays, and coord is still a 1D array, with the first N
+         elements being the coordinates in the Dim direction, and the
+         next N2 elements being the coordinates in the Dim2
+         dirction.  Similarly in 3D.  */
+      if(ndims==1)
+        {
+          *data=(double *)malloc(N*sizeof(double));
+          *coords=(double *)malloc(N*sizeof(double));
+        }
+      else if(ndims==2)
+        {
+          *data=(double *)malloc(N*N2*sizeof(double));
+          *coords=(double *)malloc((N+N2)*sizeof(double));
+        }
+      else
+        {
+          *data=(double *)malloc(N*N2*N3*sizeof(double));
+          *coords=(double *)malloc((N+N2+N3)*sizeof(double));
+        }
+
+      Journal_Firewall(*data!=NULL && *coords!=NULL,
+                       Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
+                       "Could not allocate enough memory for %s\n",file_num);
+      if(ndims==1)
+        {
+          for(i=0;i<N;++i)
+            fscanf(fp,"%lf %lf",*coords+i,*data+i);
+        }
+      else if(ndims==2)
+        {
+          for(i=0;i<N;++i)
+            for(j=0;j<N2;++j)
+              {
+                fscanf(fp,"%lf %lf %lf",*coords+i,*coords+N+j,*data+i+N*j);
+              }
+        }
+      else if(ndims==3)
+        {
+          for(i=0;i<N;++i)
+            for(j=0;j<N2;++j)
+              for(k=0;k<N3;++k)
+                fscanf(fp,"%lf %lf %lf %lf",*coords+i,*coords+N+j,*coords+N+N2+k,
+                       *data+i+N*(j+N2*k));
+        }
+      fclose(fp);
+    }
+
+  Journal_Firewall(!(coord[dim]<(*coords)[0] || coord[dim]>(*coords)[N-1]),
+                   Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
+                   "The range in the file '%s' does not cover this value %g\nIt only covers %g to %g in the %d direction.\n",
+                   filename,coord[dim],(*coords)[0],(*coords)[N-1],dim);
+  if(ndims>1)
+    Journal_Firewall(!(coord[dim2]<(*coords)[N] || coord[dim2]>(*coords)[N+N2-1]),
+                     Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
+                     "The range in the file '%s' does not cover this value %g\nIt only covers %g to %g in the %d direction.\n",
+                     filename,coord[dim2],(*coords)[N],(*coords)[N+N2-1],dim2);
+  if(ndims>2)
+    Journal_Firewall(!(coord[dim3]<(*coords)[N+N2] || coord[dim3]>(*coords)[N+N2+N3-1]),
+                     Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_FileN"),
+                     "The range in the file '%s' does not cover this value %g\nIt only covers %g to %g in the %d direction.\n",
+                     filename,coord[dim3],(*coords)[N+N2],(*coords)[N+N2+N3-1],dim2);
+
+  i=Binary_Search(*coords,0,N-1,coord[dim]);
+  factor=((*coords)[i+1]-coord[dim])/((*coords)[i+1]-(*coords)[i]);
+    
+  if(ndims>1)
+    {
+      j=Binary_Search(*coords,N,N+N2-1,coord[dim2]);
+      factor2=((*coords)[j+1]-coord[dim2])/((*coords)[j+1]-(*coords)[j]);
+      j=j-N;
+      if(ndims>2)
+        {
+          k=Binary_Search(*coords,N,N+N2+N3-1,coord[dim3]);
+          factor3=((*coords)[k+1]-coord[dim3])/((*coords)[k+1]-(*coords)[k]);
+          k=k-N-N2;
+        }
+    }
+
+  switch(ndims)
+    {
+    case 1:
+      *result=(*data)[i]*factor + (*data)[i+1]*(1-factor);
+      break;
+    case 2:
+      *result=factor*(factor2*(*data)[i+N*j] + (1-factor2)*(*data)[i+N*(j+1)])
+        + (1-factor)*(factor2*(*data)[i+1+N*j] + (1-factor2)*(*data)[i+1+N*(j+1)]);
+      break;
+    case 3:
+      *result=factor*(factor2*(factor3*(*data)[i+N*(j+N2*k)]
+                               + (1-factor3)*(*data)[i+N*(j+N2*(k+1))])
+                      + (1-factor2)*(factor3*(*data)[i+N*((j+1)+N2*k)]
+                                     + (1-factor3)*(*data)[i+N*((j+1)+N2*(k+1))]))
+        + (1-factor)*(factor2*(factor3*(*data)[i+1+N*(j+N2*k)]
+                               + (1-factor3)*(*data)[i+1+N*(j+N2*(k+1))])
+                      + (1-factor2)*(factor3*(*data)[i+1+N*((j+1)+N2*k)]
+                                     + (1-factor3)*(*data)[i+1+N*((j+1)+N2*(k+1))]));
+      break;
+    }
+}
+    
+
+int Binary_Search(double *data, int s, int e, const double value)
+{
+  int start, end, midpoint;
+
+  start=s;
+  end=e;
+  midpoint=(end-start)/2 + start;
+  while(start!=midpoint)
+    {
+      if(data[midpoint]>=value)
+        end=midpoint;
+      else
+        start=midpoint;
+      midpoint=(end-start)/2 + start;
+    }
+  return start;
+}
+
+void StgFEM_StandardConditionFunctions_EquationN(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result,
+                                                 std::string equation_string,
+                                                 const int equation_number);
+
+void StgFEM_StandardConditionFunctions_Equation1(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,1);
+}
+
+void StgFEM_StandardConditionFunctions_Equation2(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,2);
+}
+
+void StgFEM_StandardConditionFunctions_Equation3(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,3);
+}
+
+void StgFEM_StandardConditionFunctions_Equation4(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,4);
+}
+
+void StgFEM_StandardConditionFunctions_Equation5(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,5);
+}
+
+void StgFEM_StandardConditionFunctions_Equation6(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,6);
+}
+
+void StgFEM_StandardConditionFunctions_Equation7(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,7);
+}
+
+void StgFEM_StandardConditionFunctions_Equation8(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,8);
+}
+
+void StgFEM_StandardConditionFunctions_Equation9(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,9);
+}
+
+void StgFEM_StandardConditionFunctions_Equation10(Node_LocalIndex node_lI,
+                                                  Variable_Index var_I,
+                                                  void* _context,
+                                                  void* _result)
+{
+  static std::string equation_string;
+  StgFEM_StandardConditionFunctions_EquationN(node_lI,var_I,_context,_result,
+                                              equation_string,10);
+}
+
+void StgFEM_StandardConditionFunctions_EquationN(Node_LocalIndex node_lI,
+                                                 Variable_Index var_I,
+                                                 void* _context,
+                                                 void* _result,
+                                                 std::string equation_string,
+                                                 const int equation_number) 
+{
+  FiniteElementContext *context=(FiniteElementContext*)_context;
+  FeVariable *feVariable=(FeVariable*)FieldVariable_Register_GetByName
+    (context->fieldVariable_Register, "VelocityField");
+  FeMesh *mesh(feVariable->feMesh);
+  Dictionary *dictionary=context->dictionary;
+  double *coord=Mesh_GetVertex(mesh,node_lI);
+  double *result=(double*)_result;
+
+  if(equation_string.empty())
+    {
+      std::stringstream ss;
+      ss << "Equation" << equation_number;
+      equation_string=std::string(Dictionary_GetString(dictionary,
+                                                       ss.str().c_str()));
+      Journal_Firewall(!equation_string.empty(),
+                       Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_EquationN"),
+                       "The equation given for %s is empty.",
+                       ss.str().c_str());
+    }
+  try
+    {
+      mu::Parser p;
+      p.DefineVar("x", coord); 
+      p.DefineVar("y", coord+1); 
+      p.DefineVar("z", coord+2); 
+      p.DefineVar("t", &(context->currentTime));
+      p.SetExpr(equation_string);
+
+      *result=p.Eval();
+    }
+  catch (mu::Parser::exception_type &e)
+    {
+      Journal_Firewall(false,
+                       Journal_Register( Error_Type,"StgFEM_StandardConditionFunctions_Equation"),
+                       "Error when parsing equation: %s\n",e.GetMsg().c_str());
+    }
+}



More information about the CIG-COMMITS mailing list