Esempio n. 1
0
        public static IBMControl IBMNACA0012(int MeshPara, int dgDegree, double CFL, double agglomeration, double alpha)
        {
            IBMControl c = new IBMControl();

            c.savetodb = true;

            // Solver Settings
            c.dtMin         = 0.0;
            c.dtMax         = 1.0;
            c.Endtime       = 1000.0;
            c.CFLFraction   = CFL;
            c.NoOfTimesteps = 200000;

            c.PrintInterval      = 10;
            c.ResidualInterval   = 100;
            c.ResidualLoggerType = ResidualLoggerTypes.ChangeRate | ResidualLoggerTypes.Query;
            c.ResidualBasedTerminationCriteria.Add("changeRate_L2_abs_rhoE", 1E-8);

            //IBM Settings
            c.LevelSetBoundaryTag     = "adiabaticSlipWall";
            c.LevelSetQuadratureOrder = 2 * dgDegree + 2;
            c.AgglomerationThreshold  = agglomeration;

            // NEXT STEP: SET THIS BOOL TO FALSE AND JUST USE IN POSITIVE SUB_VOLUME;
            // THEN TRY BOUNDING BOX APPROACH?
            // WHY THE HELL DOES THIS CONFIGURATION FAIL!??!?!?!?
            c.CutCellQuadratureType             = XQuadFactoryHelper.MomentFittingVariants.Classic;
            c.SurfaceHMF_ProjectNodesToLevelSet = false;
            c.SurfaceHMF_RestrictNodes          = true;
            c.SurfaceHMF_UseGaussNodes          = false;
            c.VolumeHMF_NodeCountSafetyFactor   = 3.0;
            c.VolumeHMF_RestrictNodes           = true;
            c.VolumeHMF_UseGaussNodes           = false;

            //Guid restart = new Guid("cd061fe3-3215-483a-8790-f6fd686d6676");
            //c.RestartInfo = new Tuple<Guid, BoSSS.Foundation.IO.TimestepNumber>(restart, -1);

            // Session Settings
            c.DbPath = @"\\fdyprime\userspace\kraemer-eis\FDY-Cluster\dbe_NACA\";
            //c.DbPath = @"C:\bosss_dbv2\NACA0012";
            c.savetodb           = true;
            c.saveperiod         = 10000;
            c.ProjectName        = "MeshPara:" + MeshPara + "_CFL=" + c.CFLFraction + "_p=" + dgDegree + "_agg=" + c.AgglomerationThreshold + "_alpha=" + alpha + "_HMF=" + c.CutCellQuadratureType;
            c.ProjectDescription = "NACA0012 Steady Test with Ma=0.5";
            c.Tags.Add("NACA0012");
            c.Tags.Add("IBM Test");
            c.Tags.Add("steady");

            // Solver Type
            c.DomainType         = DomainTypes.StaticImmersedBoundary;
            c.ActiveOperators    = Operators.Convection;
            c.ConvectiveFluxType = ConvectiveFluxTypes.OptimizedHLLC;

            // Time-Stepping Settings
            c.ExplicitScheme = ExplicitSchemes.RungeKutta;
            c.ExplicitOrder  = 1;

            //Material Settings
            c.EquationOfState = IdealGas.Air;



            // Primary Variables
            c.AddVariable(Variables.Density, dgDegree);
            c.AddVariable(Variables.Momentum.xComponent, dgDegree);
            c.AddVariable(Variables.Momentum.yComponent, dgDegree);
            c.AddVariable(Variables.Energy, dgDegree);

            c.AddVariable(IBMVariables.LevelSet, 8);

            // Refined Region
            double xBegin = -0.012;
            double xEnd   = 1.01;

            c.GridFunc = delegate
            {
                int chords = 100;

                int xleft   = -chords;
                int xRight  = chords;
                int yBottom = -chords;
                int yTop    = chords;

                double spacingFactor = 3.95;

                double[] xnodes1 = Grid1D.TanhSpacing(xleft, xBegin, MeshPara + 1, spacingFactor, false);
                double[] xnodes2 = Grid1D.TanhSpacing_DoubleSided(xBegin, xEnd, MeshPara + 1, 2.0);
                double[] xnodes3 = Grid1D.TanhSpacing(xEnd, xRight, MeshPara + 1, spacingFactor, true);

                double[] xComplete = new double[xnodes1.Length + xnodes2.Length + xnodes3.Length - 2];
                for (int i = 0; i < xnodes1.Length; i++)
                {
                    xComplete[i] = xnodes1[i];
                }
                for (int i = 1; i < xnodes2.Length; i++)
                {
                    xComplete[i + xnodes1.Length - 1] = xnodes2[i];
                }
                for (int i = 1; i < xnodes3.Length; i++)
                {
                    xComplete[i + xnodes1.Length + xnodes2.Length - 2] = xnodes3[i];
                }

                double yrefinedTop    = 0.2;
                double yrefinedBottom = -0.2;

                double[] ynodes1 = Grid1D.TanhSpacing(yBottom, yrefinedBottom, MeshPara + 1, spacingFactor, false);
                double[] ynodes2 = GenericBlas.Linspace(yrefinedBottom, yrefinedTop, (int)(0.75 * MeshPara) + 1);
                double[] ynodes3 = Grid1D.TanhSpacing(yrefinedTop, yTop, MeshPara + 1, spacingFactor, true);

                double[] yComplete = new double[ynodes1.Length + ynodes2.Length + ynodes3.Length - 2];
                for (int i = 0; i < ynodes1.Length; i++)
                {
                    yComplete[i] = ynodes1[i];
                }
                for (int i = 1; i < ynodes2.Length; i++)
                {
                    yComplete[i + ynodes1.Length - 1] = ynodes2[i];
                }
                for (int i = 1; i < ynodes3.Length; i++)
                {
                    yComplete[i + ynodes1.Length + ynodes2.Length - 2] = ynodes3[i];
                }


                int numOfCellsX = (xRight - xleft) * MeshPara;
                int numOfCellsY = (yTop - yBottom) * MeshPara;

                GridCommons grid = Grid2D.Cartesian2DGrid(
                    xComplete,
                    yComplete
                    );

                grid.EdgeTagNames.Add(1, "supersonicinlet");
                grid.DefineEdgeTags(x => 1);
                grid.Name = "[" + xleft + "," + xRight + "]x[" + yBottom + "," + yTop + "]_Cells:(" + (xComplete.Length - 1) + "x" + (yComplete.Length - 1) + ")";

                return(grid);
            };



            // Functions
            Func <double[], double, double> rho      = (X, t) => 1.0;
            Func <double[], double, double> u0       = (X, t) => 1.0;
            Func <double[], double, double> u1       = (X, t) => 0.0;
            Func <double[], double, double> pressure = (X, t) => 2.8571428571428;

            Func <double[], double> test = X => 1 - 0.05 * 0.4 / 1.4 * Math.Pow(Math.Exp(1 - X[0] * X[0] - X[1] * X[1]), (1 / 0.4));

            Func <double[], double, double> levelSet = delegate(double[] X, double t) {
                double value = 0.0;

                double radian = alpha * Math.PI / 180;

                double xRotated = 1 + Math.Cos(radian) * (X[0] - 1) - Math.Sin(radian) * (X[1]);
                double yRotated = Math.Sin(radian) * (X[0] - 1) + Math.Cos(radian) * (X[1]);

                double a = 0.6;
                //double b = 0.2969;
                double c1 = 0.126;
                double d  = 0.3516;
                double e  = 0.2843;
                double f  = 0.1036;


                if (yRotated >= 0.0 || (X[0] > 0.562875 && X[1] > 0))
                {
                    //if (yRotated >= 0.0 ){
                    value = Math.Pow((yRotated + a * (c1 * xRotated + d * Math.Pow(xRotated, 2) - e * Math.Pow(xRotated, 3) + f * Math.Pow(xRotated, 4))), 2) - 0.0317338596 * xRotated;
                }
                else
                {
                    value = Math.Pow((-yRotated + a * (c1 * xRotated + d * Math.Pow(xRotated, 2) - e * Math.Pow(xRotated, 3) + f * Math.Pow(xRotated, 4))), 2) - 0.0317338596 * xRotated;
                }

                //value = yRotated - Math.Tan(radian)*xRotated;

                return(value);
            };

            c.LevelSetFunction = levelSet;

            //Initial Values
            c.InitialValues_Evaluators.Add(Variables.Density, X => rho(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Velocity.xComponent, X => u0(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Velocity.yComponent, X => u1(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Pressure, X => pressure(X, 0.0));

            //BoundaryConditions
            c.AddBoundaryCondition("adiabaticSlipWall");
            c.AddBoundaryCondition("supersonicInlet", Variables.Density, rho);
            c.AddBoundaryCondition("supersonicInlet", Variables.Velocity.xComponent, u0);
            c.AddBoundaryCondition("supersonicInlet", Variables.Velocity.yComponent, u1);
            c.AddBoundaryCondition("supersonicInlet", Variables.Pressure, pressure);


            // Queries

            c.Queries.Add("L2ErrorEntropy", IBMQueries.L2Error(state => state.Entropy, (X, t) => 2.8571428571428));
            c.Queries.Add("IBMDragForce", IBMQueries.IBMDragForce());
            c.Queries.Add("IBMLiftForce", IBMQueries.IBMLiftForce());
            return(c);
        }
        private static IBMControl ShockTubeToro1WithIBMAndAVTemplate(int dgDegree, ExplicitSchemes explicitScheme, int explicitOrder, int noOfCellsX = 50, int noOfCellsY = 10)
        {
            IBMControl c = new IBMControl();

            c.DbPath = null;
            //c.DbPath = @"c:\bosss_db\";
            c.savetodb = false;

            c.saveperiod    = 1;
            c.PrintInterval = 1;

            double xMin = 0;
            double xMax = 1;
            double yMin = 0;
            double yMax = 1;

            bool AV = true;

            c.DomainType       = DomainTypes.StaticImmersedBoundary;
            c.LevelSetFunction = delegate(double[] X, double t) {
                return(X[1] - 0.16);
            };
            c.LevelSetBoundaryTag     = "AdiabaticSlipWall";
            c.CutCellQuadratureType   = XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes;
            c.LevelSetQuadratureOrder = 6;
            c.AgglomerationThreshold  = 0.3;
            c.AddVariable(IBMVariables.LevelSet, 1);

            //c.AddVariable(IBMVariables.FluidCells, 1);
            //c.AddVariable(IBMVariables.FluidCellsWithoutSourceCells, 1);
            //c.AddVariable(IBMVariables.CutCells, 1);
            //c.AddVariable(IBMVariables.CutCellsWithoutSourceCells, 1);
            //c.AddVariable(IBMVariables.SourceCells, 1);

            if (AV)
            {
                c.ActiveOperators = Operators.Convection | Operators.ArtificialViscosity;
            }
            else
            {
                c.ActiveOperators = Operators.Convection;
            }
            c.ConvectiveFluxType = ConvectiveFluxTypes.OptimizedHLLC;

            // Shock-capturing
            double sensorLimit = 1e-3;
            double epsilon0    = 1.0;
            double kappa       = 0.5;

            if (AV)
            {
                Variable sensorVariable = Variables.Density;
                c.ShockSensor = new PerssonSensor(sensorVariable, sensorLimit);
                c.AddVariable(Variables.ShockSensor, 0);
                c.ArtificialViscosityLaw = new SmoothedHeavisideArtificialViscosityLaw(c.ShockSensor, dgDegree, sensorLimit, epsilon0, kappa, lambdaMax: 2);
            }

            c.ExplicitScheme = explicitScheme;
            c.ExplicitOrder  = explicitOrder;

            c.EquationOfState = IdealGas.Air;

            c.MachNumber     = 1.0 / Math.Sqrt(c.EquationOfState.HeatCapacityRatio);
            c.ReynoldsNumber = 1.0;
            c.PrandtlNumber  = 0.71;

            c.AddVariable(Variables.Density, dgDegree);
            c.AddVariable(Variables.Momentum.xComponent, dgDegree);
            c.AddVariable(Variables.Momentum.yComponent, dgDegree);
            c.AddVariable(Variables.Energy, dgDegree);
            c.AddVariable(Variables.Velocity.xComponent, dgDegree);
            c.AddVariable(Variables.Velocity.yComponent, dgDegree);
            c.AddVariable(Variables.Pressure, dgDegree);
            c.AddVariable(Variables.Rank, 0);

            if (AV)
            {
                c.AddVariable(Variables.ArtificialViscosity, 2);
                c.AddVariable(Variables.CFLArtificialViscosity, 0);
            }
            c.AddVariable(Variables.CFL, 0);
            c.AddVariable(Variables.CFLConvective, 0);

            if (c.ExplicitScheme.Equals(ExplicitSchemes.LTS))
            {
                c.AddVariable(Variables.LTSClusters, 0);
            }

            c.GridFunc = delegate {
                double[] xNodes = GenericBlas.Linspace(xMin, xMax, noOfCellsX + 1);
                double[] yNodes = GenericBlas.Linspace(yMin, yMax, noOfCellsY + 1);
                var      grid   = Grid2D.Cartesian2DGrid(xNodes, yNodes, periodicX: false, periodicY: false);
                // Boundary conditions
                grid.EdgeTagNames.Add(1, "AdiabaticSlipWall");

                grid.DefineEdgeTags(delegate(double[] _X) {
                    return(1);
                });
                return(grid);
            };

            c.AddBoundaryCondition("AdiabaticSlipWall");

            // Normal vector of initial shock
            Vector2D normalVector = new Vector2D(1, 0);

            // Direction vector of initial shock
            Vector2D r = new Vector2D(normalVector.y, -normalVector.x);

            r.Normalize();

            // Distance from a point X to the initial shock
            double[] p = new double[] { 0.5, 0.0 };

            double cellSize = Math.Min((xMax - xMin) / noOfCellsX, (yMax - yMin) / noOfCellsY);

            Func <double, double> SmoothJump = delegate(double distance) {
                // smoothing should be in the range of h/p
                double maxDistance = 4.0 * cellSize / Math.Max(dgDegree, 1);

                return((Math.Tanh(distance / maxDistance) + 1.0) * 0.5);
            };

            Func <double, double> Jump = (x => x <= 0.5 ? 0 : 1);

            // Initial conditions
            double densityLeft   = 1.0;
            double densityRight  = 0.125;
            double pressureLeft  = 1.0;
            double pressureRight = 0.1;

            //c.InitialValues_Evaluators.Add(Variables.Density, X => densityLeft - SmoothJump(DistanceFromPointToLine(X, p, r)) * (densityLeft - densityRight));
            //c.InitialValues_Evaluators.Add(Variables.Pressure, X => pressureLeft - SmoothJump(DistanceFromPointToLine(X, p, r)) * (pressureLeft - pressureRight));
            c.InitialValues_Evaluators.Add(Variables.Density, X => densityLeft - Jump(X[0]) * (densityLeft - densityRight));
            c.InitialValues_Evaluators.Add(Variables.Pressure, X => pressureLeft - Jump(X[0]) * (pressureLeft - pressureRight));
            c.InitialValues_Evaluators.Add(Variables.Velocity.xComponent, X => 0.0);
            c.InitialValues_Evaluators.Add(Variables.Velocity.yComponent, X => 0.0);

            // Time config
            c.dtMin         = 0.0;
            c.dtMax         = 1.0;
            c.CFLFraction   = 0.1;
            c.Endtime       = 0.001;
            c.NoOfTimesteps = int.MaxValue;

            c.ProjectName = "Shock tube";
            c.SessionName = String.Format("IBM shock tube, p={0}, {1}x{2} cells, aggloThresh={3}, s0={4:0.0E-00}, CFLFrac={5}, ALTS {6}/{7}/{8}({9})", dgDegree, noOfCellsX, noOfCellsY, c.AgglomerationThreshold, sensorLimit, c.CFLFraction, c.ExplicitOrder, c.NumberOfSubGrids, c.ReclusteringInterval, c.maxNumOfSubSteps);

            return(c);
        }
Esempio n. 3
0
        public static IBMControl IBMBumpTest(int noOfCells, int dgDegree, int lsDegree, double CFL)
        {
            IBMControl c = new IBMControl();

            // Solver Settings
            c.dtMin         = 0.0;
            c.dtMax         = 1.0;
            c.Endtime       = 1000.0;
            c.CFLFraction   = CFL;
            c.NoOfTimesteps = 250000;

            c.PrintInterval      = 100;
            c.ResidualInterval   = 100;
            c.ResidualLoggerType = ResidualLoggerTypes.ChangeRate | ResidualLoggerTypes.Query;
            c.ResidualBasedTerminationCriteria.Add("changeRate_L2_abs_rhoE", 1E-8);

            //Guid restart = new Guid(" 60688cbc-707d-4777-98e6-d237796ec14c");
            //c.RestartInfo = new Tuple<Guid, BoSSS.Foundation.IO.TimestepNumber>(restart, -1);

            // Session Settings
            c.DbPath = @"C:\bosss_dbv2\GaussianBump_hhlr";
            //c.DbPath = @"\\fdyprime\userspace\kraemer-eis\FDY-Cluster\dbe_bump\";
            //c.DbPath = @"/home/kraemer/GaussianBump/dbev2/";
            c.savetodb           = true;
            c.saveperiod         = 100;
            c.ProjectName        = "TestsCutCells_(" + 2 * noOfCells + "x" + noOfCells + ")_CFL=" + c.CFLFraction + "_ls=" + lsDegree + "_p=" + dgDegree + "_agg=" + 0.53;
            c.ProjectDescription = "GaussianBump with Ma=0.5";
            c.Tags.Add("Gaussian Bump");
            c.Tags.Add("IBM Test");

            // Solver Type
            c.DomainType         = DomainTypes.StaticImmersedBoundary;
            c.ActiveOperators    = Operators.Convection;
            c.ConvectiveFluxType = ConvectiveFluxTypes.OptimizedHLLC;

            // Time-Stepping Settings
            c.ExplicitScheme = ExplicitSchemes.RungeKutta;
            c.ExplicitOrder  = 1;

            //Material Settings
            c.EquationOfState = IdealGas.Air;

            //IBM Settings
            c.LevelSetBoundaryTag     = "adiabaticSlipWall";
            c.LevelSetQuadratureOrder = 2 * lsDegree;
            c.CutCellQuadratureType   = XQuadFactoryHelper.MomentFittingVariants.Classic;
            c.AgglomerationThreshold  = 0.3;

            // Primary Variables
            c.AddVariable(Variables.Density, dgDegree);
            c.AddVariable(Variables.Momentum.xComponent, dgDegree);
            c.AddVariable(Variables.Momentum.yComponent, dgDegree);
            c.AddVariable(Variables.Energy, dgDegree);

            c.AddVariable(IBMVariables.LevelSet, lsDegree);

            c.GridFunc = delegate {
                double xBoundary = 2.0625;
                double yBoundary = 2.0525;
                double yBottom   = -0.01;

                double[] xnodes = GenericBlas.Linspace(-xBoundary, xBoundary, 2 * noOfCells + 1);
                double[] ynodes = GenericBlas.Linspace(yBottom, yBoundary, noOfCells + 1);

                GridCommons grid = Grid2D.Cartesian2DGrid(
                    xnodes,
                    ynodes
                    );

                grid.EdgeTagNames.Add(1, "supersonicinlet");
                grid.EdgeTagNames.Add(2, "adiabaticSlipWall");

                Func <double[], byte> func = delegate(double[] x) {
                    if (Math.Abs(x[0] + xBoundary) < 1e-5)   // Inflow
                    {
                        return(1);
                    }
                    else if (Math.Abs(x[0] - xBoundary) < 1e-5)     // Outflow
                    {
                        return(1);
                    }
                    else if (Math.Abs(x[1] - yBoundary) < 1e-5)     // Top
                    {
                        return(1);
                    }
                    else     // Bottom
                    {
                        return(2);
                    }
                };
                grid.DefineEdgeTags(func);
                grid.Name = "IBM-[" + -xBoundary + "," + xBoundary + "]x[" + yBottom + "," + yBoundary + "]_Cells:(" + 2 * noOfCells + "x" + noOfCells + ")";
                return(grid);
            };

            // Functions
            Func <double[], double, double> rho      = (X, t) => 1.0;
            Func <double[], double, double> u0       = (X, t) => 1.0;
            Func <double[], double, double> u1       = (X, t) => 0.0;
            Func <double[], double, double> pressure = (X, t) => 2.8571428571428;

            //Initial Values
            c.InitialValues_Evaluators.Add(Variables.Density, X => rho(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Velocity.xComponent, X => u0(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Velocity.yComponent, X => u1(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Pressure, X => pressure(X, 0.0));

            c.LevelSetFunction = (X, t) => X[1] - 0.3939 * Math.Exp(-0.5 * X[0] * X[0]);

            //BoundaryConditions
            c.AddBoundaryCondition("adiabaticSlipWall");
            c.AddBoundaryCondition("supersonicInlet", Variables.Density, rho);
            c.AddBoundaryCondition("supersonicInlet", Variables.Velocity.xComponent, u0);
            c.AddBoundaryCondition("supersonicInlet", Variables.Velocity.yComponent, u1);
            c.AddBoundaryCondition("supersonicInlet", Variables.Pressure, pressure);


            // Queries

            c.Queries.Add("L2ErrorEntropy", IBMQueries.L2Error(state => state.Entropy, (X, t) => 2.8571428571428));
            return(c);
        }
Esempio n. 4
0
        public static IBMControl IBMBump(int noOfCells, int dgDegree, int lsDegree, double CFL, double epsilonX = 0.0, double epsilonY = 0.0)
        {
            IBMControl c = new IBMControl();

            // Solver Settings
            c.dtMin         = 0.0;
            c.dtMax         = 1.0;
            c.Endtime       = 1000.0;
            c.CFLFraction   = CFL;
            c.NoOfTimesteps = 200000;

            c.PrintInterval      = 100;
            c.ResidualInterval   = 100;
            c.ResidualLoggerType = ResidualLoggerTypes.ChangeRate | ResidualLoggerTypes.Query;
            c.ResidualBasedTerminationCriteria.Add("changeRate_L2_abs_rhoE", 1E-8);

            //IBM Settings
            c.LevelSetBoundaryTag     = "adiabaticSlipWall";
            c.LevelSetQuadratureOrder = 2 * dgDegree;
            c.AgglomerationThreshold  = 0.3;

            // NEXT STEP: SET THIS BOOL TO FALSE AND JUST USE IN POSITIVE SUB_VOLUME;
            // THEN TRY BOUNDING BOX APPROACH?
            // WHY THE HELL DOES THIS CONFIGURATION FAIL!??!?!?!?
            c.CutCellQuadratureType             = XQuadFactoryHelper.MomentFittingVariants.Classic;
            c.SurfaceHMF_ProjectNodesToLevelSet = false;
            c.SurfaceHMF_RestrictNodes          = true;
            c.SurfaceHMF_UseGaussNodes          = false;
            c.VolumeHMF_NodeCountSafetyFactor   = 3.0;
            c.VolumeHMF_RestrictNodes           = true;
            c.VolumeHMF_UseGaussNodes           = false;

            //Guid restart = new Guid(" 60688cbc-707d-4777-98e6-d237796ec14c");
            //c.RestartInfo = new Tuple<Guid, BoSSS.Foundation.IO.TimestepNumber>(restart, -1);

            // Session Settings
            c.DbPath = @"\\fdyprime\userspace\kraemer-eis\FDY-Cluster\dbe_bump\";
            //c.DbPath = @"/home/kraemer/GaussianBump/dbev2/";
            c.savetodb           = true;
            c.saveperiod         = 20000;
            c.ProjectName        = "BoxHMF=" + c.CutCellQuadratureType + "_Ma=0.5_(" + 2 * noOfCells + "x" + noOfCells + ")_CFL=" + c.CFLFraction + "_lsQuadOrder=" + c.LevelSetQuadratureOrder + "_p=" + dgDegree + "_agg=" + c.AgglomerationThreshold + "_epsX=" + epsilonX + "_epsY=" + epsilonY;
            c.ProjectDescription = "GaussianBump with Ma=0.5";
            c.Tags.Add("Gaussian Bump");
            c.Tags.Add("IBM Test");

            // Solver Type
            c.DomainType         = DomainTypes.StaticImmersedBoundary;
            c.ActiveOperators    = Operators.Convection;
            c.ConvectiveFluxType = ConvectiveFluxTypes.OptimizedHLLC;

            // Time-Stepping Settings
            c.ExplicitScheme = ExplicitSchemes.RungeKutta;
            c.ExplicitOrder  = 1;

            //Material Settings
            c.EquationOfState = IdealGas.Air;



            // Primary Variables
            c.AddVariable(Variables.Density, dgDegree);
            c.AddVariable(Variables.Momentum.xComponent, dgDegree);
            c.AddVariable(Variables.Momentum.yComponent, dgDegree);
            c.AddVariable(Variables.Energy, dgDegree);

            c.AddVariable(IBMVariables.LevelSet, lsDegree);



            // Grid

            //switch (noOfCells) {
            //    case 8:
            //        c.GridGuid = new Guid("7337e273-542f-4b97-b592-895ac3422621");
            //        break;
            //    case 16:
            //        c.GridGuid = new Guid("32e5a779-2aef-4ea2-bdef-b158ae785f01");
            //        break;
            //    case 32:
            //        c.GridGuid = new Guid("e96c9f83-3486-4e45-aa3b-9a436445a059");
            //        break;
            //    case 64:
            //        c.GridGuid = new Guid("a86f1b67-4fa3-48ed-b6df-dcea370eb2c0");
            //        break;
            //    default:
            //        throw new ArgumentException("Wrong Grid Input");
            //}



            c.GridFunc = delegate {
                double xBoundary = 12.0;
                double yBoundary = 12.0;
                double yBottom   = 0.0;

                double[] xnodes = GenericBlas.Linspace(-xBoundary, xBoundary, 2 * noOfCells + 1);

                //double ySplit = 6.0;
                //int ySplitNoOfCells = (int) (0.5*noOfCells);
                //double[] ynodes1 = GenericBlas.Linspace(yBottom, ySplit, ySplitNoOfCells + 1);
                //double[] ynodes2 = GenericBlas.Linspace(ySplit, yBoundary, noOfCells-ySplitNoOfCells + 1);
                //ynodes1 = ynodes1.GetSubVector(0, ynodes1.Length - 1);
                //double[] ynodes = ArrayTools.Cat(ynodes1, ynodes2);

                double[] ynodes = GenericBlas.Linspace(yBottom, yBoundary, noOfCells + 1);

                GridCommons grid = Grid2D.Cartesian2DGrid(
                    xnodes,
                    ynodes
                    );

                grid.EdgeTagNames.Add(1, "supersonicinlet");
                grid.EdgeTagNames.Add(2, "adiabaticSlipWall");

                Func <double[], byte> func = delegate(double[] x) {
                    if (Math.Abs(x[0] + xBoundary) < 1e-5)   // Inflow
                    {
                        return(1);
                    }
                    else if (Math.Abs(x[0] - xBoundary) < 1e-5)     // Outflow
                    {
                        return(1);
                    }
                    else if (Math.Abs(x[1] - yBoundary) < 1e-5)     // Top
                    {
                        return(1);
                    }
                    else     // Bottom
                    {
                        return(2);
                    }
                };
                grid.DefineEdgeTags(func);
                grid.Name = "IBM-[" + -xBoundary + "," + xBoundary + "]x[" + yBottom + "," + yBoundary + "]_Cells:(" + 2 * noOfCells + "x" + noOfCells + ")";
                return(grid);
            };

            // Functions
            Func <double[], double, double> rho      = (X, t) => 1.0;
            Func <double[], double, double> u0       = (X, t) => 1.0;
            Func <double[], double, double> u1       = (X, t) => 0.0;
            Func <double[], double, double> pressure = (X, t) => 2.8571428571428;

            //Initial Values
            c.InitialValues_Evaluators.Add(Variables.Density, X => rho(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Velocity.xComponent, X => u0(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Velocity.yComponent, X => u1(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Pressure, X => pressure(X, 0.0));

            c.LevelSetFunction = (X, t) => X[1] - epsilonY - 0.01 - 0.3939 * Math.Exp(-0.5 * (X[0] - epsilonX) * (X[0] - epsilonX));

            //BoundaryConditions
            c.AddBoundaryCondition("adiabaticSlipWall");
            c.AddBoundaryCondition("supersonicInlet", Variables.Density, rho);
            c.AddBoundaryCondition("supersonicInlet", Variables.Velocity.xComponent, u0);
            c.AddBoundaryCondition("supersonicInlet", Variables.Velocity.yComponent, u1);
            c.AddBoundaryCondition("supersonicInlet", Variables.Pressure, pressure);


            // Queries

            c.Queries.Add("L2ErrorEntropy", IBMQueries.L2Error(state => state.Entropy, (X, t) => 2.8571428571428));
            return(c);
        }
        public static IBMControl MovingFrameIBMIsentropicVortex(string dbPath = null, int dgDegree = 3, int noOfCellsPerDirection = 20, double initialLevelSetPosition = -0.9, double agglomerationThreshold = 0.2)
        {
            IBMControl c = new IBMControl();

            double advectionVelocity = 1.0;

            c.DbPath     = dbPath;
            c.savetodb   = dbPath != null;
            c.saveperiod = 1;

            c.ProjectName = "Moving IBM Isentropic vortex";
            c.Tags.Add("Isentropic vortex");
            c.Tags.Add("Moving IBM");

            c.DomainType         = DomainTypes.MovingImmersedBoundary;
            c.ActiveOperators    = Operators.Convection;
            c.ConvectiveFluxType = ConvectiveFluxTypes.MovingFrameRusanov;
            c.EquationOfState    = IdealGas.Air;
            c.MachNumber         = 1.0 / Math.Sqrt(c.EquationOfState.HeatCapacityRatio);

            c.TimesteppingStrategy = TimesteppingStrategies.MovingFrameFlux;
            c.ExplicitScheme       = ExplicitSchemes.RungeKutta;
            c.ExplicitOrder        = 1;

            c.AddVariable(Variables.Density, dgDegree);
            c.AddVariable(Variables.Momentum.xComponent, dgDegree);
            c.AddVariable(Variables.Momentum.yComponent, dgDegree);
            c.AddVariable(Variables.Energy, dgDegree);
            c.AddVariable(IBMVariables.LevelSet, 1);

            c.GridFunc = delegate {
                double[] nodes = GenericBlas.Linspace(-10.0, 10.0, noOfCellsPerDirection + 1);
                var      grid  = Grid2D.Cartesian2DGrid(nodes, nodes, periodicX: true, periodicY: false);
                grid.EdgeTagNames.Add(1, "adiabaticSlipWall");
                grid.DefineEdgeTags(X => 1);
                return(grid);
            };

            c.CutCellQuadratureType             = XQuadFactoryHelper.MomentFittingVariants.Classic;
            c.SurfaceHMF_ProjectNodesToLevelSet = false;
            c.SurfaceHMF_RestrictNodes          = true;
            c.SurfaceHMF_UseGaussNodes          = false;
            c.VolumeHMF_NodeCountSafetyFactor   = 3.0;
            c.VolumeHMF_RestrictNodes           = true;
            c.VolumeHMF_UseGaussNodes           = false;
            c.LevelSetQuadratureOrder           = 10;
            c.LevelSetBoundaryTag = "supersonicInlet";

            c.AgglomerationThreshold = agglomerationThreshold;
            c.SaveAgglomerationPairs = true;

            double gamma = c.EquationOfState.HeatCapacityRatio;
            Func <double[], double, double> x   = (X, t) => X[0] - advectionVelocity * t;
            Func <double[], double, double> r   = (X, t) => Math.Sqrt(x(X, t) * x(X, t) + X[1] * X[1]);
            Func <double[], double, double> phi = (X, t) => Math.Atan2(X[1], x(X, t));
            Func <double[], double, double> rho = (X, t) => Math.Pow(
                1.0 - 0.5 * (gamma - 1.0) / gamma * Math.Exp(1.0 - r(X, t) * r(X, t)),
                1.0 / (gamma - 1.0));
            Func <double[], double, double> p    = (X, t) => Math.Pow(rho(X, t), gamma);
            Func <double[], double, double> uAbs = (X, t) => r(X, t) * Math.Exp(0.5 * (1.0 - r(X, t) * r(X, t)));
            Func <double[], double, double> u    = (X, t) => advectionVelocity - Math.Sin(phi(X, t)) * uAbs(X, t);
            Func <double[], double, double> v    = (X, t) => Math.Cos(phi(X, t)) * uAbs(X, t);

            c.InitialValues_Evaluators.Add(Variables.Density, X => rho(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Velocity.xComponent, X => u(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Velocity.yComponent, X => v(X, 0.0));
            c.InitialValues_Evaluators.Add(Variables.Pressure, X => p(X, 0.0));

            double amplitude = 0.3;

            c.LevelSetFunction = delegate(double[] X, double time) {
                double newLevelSetPosition = initialLevelSetPosition + amplitude * Math.Sin(10.0 * time);
                return(X[1] - newLevelSetPosition);
            };
            c.LevelSetVelocity = (X, t) => new Vector3D(
                0.0,
                10.0 * amplitude * Math.Cos(10.0 * t),
                0.0);

            c.AddBoundaryCondition("adiabaticSlipWall");
            c.AddBoundaryCondition("supersonicInlet", Variables.Density, rho);
            c.AddBoundaryCondition("supersonicInlet", Variables.Velocity[0], u);
            c.AddBoundaryCondition("supersonicInlet", Variables.Velocity[1], v);
            c.AddBoundaryCondition("supersonicInlet", Variables.Pressure, p);

            c.dtMin         = 0.0;
            c.dtMax         = 1.0;
            c.CFLFraction   = 0.1;
            c.Endtime       = 10;
            c.NoOfTimesteps = 1000;

            return(c);
        }