private static void CheckRunsProduceSameResults(CNSControl refControl, double differenceThreshold = 1e-16)
        {
            Debug.Assert(refControl.DynamicLoadBalancing_Period <= 0);
            Debug.Assert(refControl.DynamicLoadBalancing_CellCostEstimatorFactories.Count == 0);

            CNSControl loadBalControl = refControl.CloneAs();

            loadBalControl.DynamicLoadBalancing_Period         = REBALANCING_PERIOD;
            loadBalControl.DynamicLoadBalancing_CellClassifier = new RandomCellClassifier(2);
            loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.Add((p, i) => new StaticCellCostEstimator(new[] { 1, 10 }));
            loadBalControl.DynamicLoadBalancing_ImbalanceThreshold = 0.01;


            //// TEST ONLY SUCCEEDS IF THESE LINES ARE IN
            //loadBalControl.DynamicLoadBalancing_CellClassifier = new IndifferentCellClassifier();
            //loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.Clear();
            //loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.Add(CellCostEstimatorLibrary.AllCellsAreEqual);


            Debug.Assert(loadBalControl.DynamicLoadBalancing_Period > 0);
            Debug.Assert(loadBalControl.DynamicLoadBalancing_CellClassifier != null);
            Debug.Assert(loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.Count > 0);

            Console.WriteLine("Run WITHOUT load balancing");
            var refSolver = new ShockTubeLoadBalancingTests();

            refSolver.Init(refControl, commandLineOptions);
            refSolver.RunSolverMode();

            Console.WriteLine("Run WITH load balancing");
            var loadBalSolver = new ShockTubeLoadBalancingTests();

            loadBalSolver.Init(loadBalControl, commandLineOptions);
            loadBalSolver.RunSolverMode();

            // To be able to compare errors without using the databse, we to
            // agree on a single grid partitioning in the end -> use ref
            Console.WriteLine("Transfering load balancing data to reference grid");
            var refPartitioning = new int[loadBalSolver.GridData.Cells.NoOfLocalUpdatedCells];

            for (int i = 0; i < refSolver.GridData.CellPartitioning.TotalLength; i++)
            {
                int localIndex = loadBalSolver.GridData.CellPartitioning.TransformIndexToLocal(i);
                if (localIndex >= 0 && localIndex < loadBalSolver.GridData.Cells.NoOfLocalUpdatedCells)
                {
                    refPartitioning[localIndex] = refSolver.GridData.CellPartitioning.FindProcess(i);
                }
            }
            loadBalSolver.MpiRedistributeAndMeshAdapt(
                int.MinValue,
                double.MinValue,
                refPartitioning,
                refSolver.GridData.CurrentGlobalIdPermutation);

            CompareErrors(refSolver.WorkingSet, loadBalSolver.WorkingSet, differenceThreshold);
        }
        private static void CheckRunsProduceSameResults(CNSControl refControl, double differenceThreshold = 1e-13, bool hilbert = true)
        {
            Debug.Assert(refControl.DynamicLoadBalancing_Period <= 0);
            Debug.Assert(refControl.DynamicLoadBalancing_CellCostEstimatorFactories.Count == 0);

            CNSControl loadBalControl = refControl.CloneAs();

            loadBalControl.DynamicLoadBalancing_On                 = true;
            loadBalControl.DynamicLoadBalancing_Period             = REBALANCING_PERIOD;
            loadBalControl.DynamicLoadBalancing_ImbalanceThreshold = 0.01;

            //if (loadBalControl.ExplicitScheme is ExplicitSchemes.LTS) {
            //    loadBalControl.DynamicLoadBalancing_CellClassifier = new LTSCellClassifier();
            //    loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.AddRange(LTSCellCostEstimator.Factory(loadBalControl.NumberOfSubGrids));
            //} else {
            loadBalControl.DynamicLoadBalancing_CellClassifier = new RandomCellClassifier(2);
            loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.Add((p, i) => new StaticCellCostEstimator(new[] { 1, 10 }));
            //}

            //// TEST ONLY SUCCEEDS IF THESE LINES ARE IN
            //loadBalControl.DynamicLoadBalancing_CellClassifier = new IndifferentCellClassifier();
            //loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.Clear();
            //loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.Add(CellCostEstimatorLibrary.AllCellsAreEqual);

            Debug.Assert(loadBalControl.DynamicLoadBalancing_On == true);
            Debug.Assert(loadBalControl.DynamicLoadBalancing_Period > 0);
            Debug.Assert(loadBalControl.DynamicLoadBalancing_CellClassifier != null);
            Debug.Assert(loadBalControl.DynamicLoadBalancing_CellCostEstimatorFactories.Count > 0);

            ShockTubeLoadBalancingTests   hilbertSolver  = null;
            List <IProgram <CNSControl> > loadBalSolvers = new List <IProgram <CNSControl> >();

            if (hilbert)
            {
                CNSControl hilbertControl = loadBalControl.CloneAs();
                hilbertControl.GridPartType = GridPartType.Hilbert;

                Console.WriteLine("\nRun WITH load balancing (clusterHilbert)");
                hilbertSolver = new ShockTubeLoadBalancingTests();
                hilbertSolver.Init(hilbertControl);
                hilbertSolver.RunSolverMode();
                loadBalSolvers.Add(hilbertSolver);
            }

            Console.WriteLine("Run WITHOUT load balancing");
            var refSolver = new ShockTubeLoadBalancingTests();

            refSolver.Init(refControl);
            refSolver.RunSolverMode();

            Console.WriteLine("\nRun WITH load balancing");
            var metisSolver = new ShockTubeLoadBalancingTests();

            metisSolver.Init(loadBalControl);
            metisSolver.RunSolverMode();
            loadBalSolvers.Add(metisSolver);

            // To be able to compare errors without using the database, we need to
            // agree on a single grid partitioning in the end -> use ref
            //Console.WriteLine("Transfering load balancing data to reference grid");
            //var refPartitioning = new int[loadBalSolver.GridData.Cells.NoOfLocalUpdatedCells];
            //for (int i = 0; i < refSolver.GridData.CellPartitioning.TotalLength; i++) {
            //    int localIndex = loadBalSolver.GridData.CellPartitioning.TransformIndexToLocal(i);
            //    if (localIndex >= 0 && localIndex < loadBalSolver.GridData.Cells.NoOfLocalUpdatedCells) {
            //        refPartitioning[localIndex] = refSolver.GridData.CellPartitioning.FindProcess(i);
            //    }
            //}
            //loadBalSolver.MpiRedistributeAndMeshAdapt(
            //    int.MinValue,
            //    double.MinValue,
            //    refPartitioning,
            //    refSolver.GridData.CurrentGlobalIdPermutation);

            //if (!twoD) {
            //    CompareErrors(refSolver.WorkingSet, loadBalSolver.WorkingSet, differenceThreshold);
            //}
            CompareNorms(refSolver, loadBalSolvers, differenceThreshold);

            try {
                refSolver.Dispose();
            } catch (Exception) { }
            foreach (var s in loadBalSolvers)
            {
                try {
                    s.Dispose();
                } catch (Exception) { }
            }
        }