/// <summary>
        /// Fluid cells are "0", void cells are "1"
        /// </summary>
        /// <param name="program"></param>
        /// <returns></returns>
        public (int noOfClasses, int[] cellToPerformanceClassMap) ClassifyCells(IProgram <CNSControl> program)
        {
            ImmersedSpeciesMap speciesMap = program.SpeciesMap as ImmersedSpeciesMap;
            IBMControl         ibmControl = program.Control as IBMControl;

            if (speciesMap == null || ibmControl == null)
            {
                throw new Exception("IBM classifier only valid for IBM runs");
            }

            // Fluid and cut cells are "0"
            int J = program.GridData.iLogicalCells.NoOfLocalUpdatedCells;

            int[] cellToPerformanceClassMap = new int[J];

            // Void cells are "1"
            foreach (int j in speciesMap.Tracker.Regions.GetSpeciesMask(ibmControl.VoidSpeciesName).ItemEnum)
            {
                cellToPerformanceClassMap[j] = 1;
            }

            int noOfClasses = 2;

            return(noOfClasses, cellToPerformanceClassMap);
        }
        public static void TestRebalancingForDG2WithLTS1AndAV_IBM_AggOn()
        {
            int             dgDegree       = 2;
            ExplicitSchemes explicitScheme = ExplicitSchemes.LTS;
            int             explicitOrder  = 1;

            IBMControl control = ShockTubeToro1WithIBMAndAVTemplate(
                dgDegree: dgDegree,
                explicitScheme: explicitScheme,
                explicitOrder: explicitOrder);

            control.AgglomerationThreshold = 0.9;
            control.Endtime = 0.005;
            //control.Endtime = 0.002;

            //control.DbPath = @"c:\bosss_db\";
            //control.savetodb = true;

            // MUST be the same as rebalancing period since LTS scheme MUST
            // recluster after rebalancing (at least, it makes life much easier)
            control.ReclusteringInterval = REBALANCING_PERIOD;

            control.NumberOfSubGrids = 2;
            control.FluxCorrection   = false;
            control.maxNumOfSubSteps = 10;

            control.forceReclustering = true;

            Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
            CheckRunsProduceSameResults(control, hilbert: false);
        }
        public static void TestRebalancingForDG2WithRK1AndAV_IBM_AggOff()
        {
            int             dgDegree       = 2;
            ExplicitSchemes explicitScheme = ExplicitSchemes.RungeKutta;
            int             explicitOrder  = 1;

            IBMControl control = ShockTubeToro1WithIBMAndAVTemplate(
                dgDegree: dgDegree,
                explicitScheme: explicitScheme,
                explicitOrder: explicitOrder);

            control.AgglomerationThreshold = 0.1;

            // MUST be the same as rebalancing period since LTS scheme MUST
            // recluster after rebalancing (at least, it makes life much easier)
            //control.ReclusteringInterval = REBALANCING_PERIOD;

            //control.NumberOfSubGrids = 3;
            //control.maxNumOfSubSteps = 10;
            //control.FluxCorrection = false;

            Console.WriteLine("TestRebalancingForDG2WithRK1AndAV_IBM_AggOff");
            // Threshold is set to 2e1-3, since METIS results for density are worse compared to Hilbert
            // Could be influenced by the handling of cut-cells along processor boundaries, communication plays
            // a more important role for non-agglomerated cut-cells in the IBM-case as for non-IBM simulations, etc.
            // Anyway, this does not seem to be a real problem.
            CheckRunsProduceSameResults(control, differenceThreshold: 2e-13, hilbert: true);
        }
示例#4
0
        /// <summary>
        /// Standard cells are "0", cut cells are "1", void cells are "2"
        /// </summary>
        /// <param name="program"></param>
        /// <returns></returns>
        public (int noOfClasses, int[] cellToPerformanceClassMap) ClassifyCells(IProgram <CNSControl> program)
        {
            ImmersedSpeciesMap speciesMap = program.SpeciesMap as ImmersedSpeciesMap;
            IBMControl         ibmControl = program.Control as IBMControl;

            if (speciesMap == null || ibmControl == null)
            {
                throw new Exception("IBM classifier only valid for IBM runs");
            }

            // Pure fluid cells are "0"
            int[] cellToPerformanceClassMap = new int[program.Grid.NoOfUpdateCells];

            // Cut cells are "1"
            foreach (int j in speciesMap.Tracker.Regions.GetCutCellMask().ItemEnum)
            {
                cellToPerformanceClassMap[j] = 1;
            }

            // Void cells are "2"
            foreach (int j in speciesMap.Tracker.Regions.GetSpeciesMask(ibmControl.VoidSpeciesName).ItemEnum)
            {
                cellToPerformanceClassMap[j] = 2;
            }

            int noOfClasses = 3;

            return(noOfClasses, cellToPerformanceClassMap);
        }
        /// <summary>
        /// There is an problem for AV and IBMSplitRungeKutta.
        /// This test currently fails because of some unknown reason.
        /// - IBMSplitRungeKutta should work, as it is used, e.g. in <see cref="TestRebalancingForDG0WithRK1_IBM_AggOff"/>
        /// - RaiseOnBeforeComputeChangeRate should be called in all IBM Runge-Kutta time steppers
        /// </summary>
        //[Test]
        public static void TestRebalancingForDG2WithRK1AndAV_IBM_AggOn()
        {
            int             dgDegree       = 2;
            ExplicitSchemes explicitScheme = ExplicitSchemes.RungeKutta;
            int             explicitOrder  = 1;

            IBMControl control = ShockTubeToro1WithIBMAndAVTemplate(
                dgDegree: dgDegree,
                explicitScheme: explicitScheme,
                explicitOrder: explicitOrder);

            control.AgglomerationThreshold = 0.9;
            control.Endtime = 0.0005;

            Console.WriteLine(System.Reflection.MethodBase.GetCurrentMethod().Name);
            CheckRunsProduceSameResults(control);
        }
示例#6
0
        public static IBMControl[] IBMNACA0012Study(int noOfGridLevels, int maxDgDegree, double CFL, double agglomeration, double alpha, int minDgDegree = 0)
        {
            IBMControl[] controls = new IBMControl[noOfGridLevels * ((maxDgDegree - minDgDegree) + 1)];

            for (int i = minDgDegree; i <= maxDgDegree; i++)
            {
                for (int j = 0; j < noOfGridLevels; j++)
                {
                    int noOfCells = (int)Math.Pow(2, 3 + j);
                    controls[(i - minDgDegree) * noOfGridLevels + j] = IBMNACA0012(noOfCells, i, CFL, agglomeration, alpha);
                    controls[(i - minDgDegree) * noOfGridLevels + j].Paramstudy_ContinueOnError    = true;
                    controls[(i - minDgDegree) * noOfGridLevels + j].Paramstudy_CaseIdentification = new Tuple <string, object>[] {
                        new Tuple <string, object>("refinement+dgDegree", i * 100 + noOfCells)
                    };
                }
            }

            return(controls);
        }
        public static void TestRebalancingForDG2WithRK1AndAV_IBM_AggOn()
        {
            int             dgDegree       = 2;
            ExplicitSchemes explicitScheme = ExplicitSchemes.RungeKutta;
            int             explicitOrder  = 1;

            IBMControl control = ShockTubeToro1WithIBMAndAVTemplate(
                dgDegree: dgDegree,
                explicitScheme: explicitScheme,
                explicitOrder: explicitOrder);

            control.AgglomerationThreshold = 0.9;

            // MUST be the same as rebalancing period since LTS scheme MUST
            // recluster after rebalancing (at least, it makes life much easier)
            //control.ReclusteringInterval = REBALANCING_PERIOD;

            //control.NumberOfSubGrids = 3;
            //control.maxNumOfSubSteps = 10;
            //control.FluxCorrection = false;

            Console.WriteLine("TestRebalancingForDG2WithRK1AndAV_IBM_AggOn");
            CheckRunsProduceSameResults(control, hilbert: true);
        }
示例#8
0
        /// <summary>
        /// Creates the appropriate time-stepper for a given
        /// <paramref name="timeStepperType"/>
        /// </summary>
        /// <param name="timeStepperType">
        /// The type of the time-stepper (e.g., Runge-Kutta) to be created
        /// </param>
        /// <param name="control">
        /// Configuration options
        /// </param>
        /// <param name="equationSystem">
        /// The equation system to be solved
        /// </param>
        /// <param name="fieldSet">
        /// Fields affected by the time-stepper
        /// </param>
        /// <param name="parameterMap">
        /// Fields serving as parameter for the time-stepper.
        /// </param>
        /// <param name="speciesMap">
        /// Mapping of different species inside the domain
        /// </param>
        /// <param name="program"></param>
        /// <returns>
        /// Depending on <paramref name="timeStepperType"/>, an appropriate
        /// implementation of <see cref="ITimeStepper"/>.
        /// </returns>
        /// <remarks>
        /// Currently limiting is not supported for Adams-Bashforth methods
        /// </remarks>
        public static ITimeStepper Instantiate <T>(
            this ExplicitSchemes timeStepperType,
            CNSControl control,
            OperatorFactory equationSystem,
            CNSFieldSet fieldSet,
            CoordinateMapping parameterMap,
            ISpeciesMap speciesMap,
            IProgram <T> program)
            where T : CNSControl, new()
        {
            CoordinateMapping variableMap = new CoordinateMapping(fieldSet.ConservativeVariables);

            IBMControl         ibmControl = control as IBMControl;
            IBMOperatorFactory ibmFactory = equationSystem as IBMOperatorFactory;

            if (control.DomainType != DomainTypes.Standard &&
                (ibmFactory == null || ibmControl == null))
            {
                throw new Exception();
            }

            ITimeStepper timeStepper;

            switch (timeStepperType)
            {
            case ExplicitSchemes.RungeKutta when control.DomainType == DomainTypes.Standard:
                timeStepper = new RungeKutta(
                    RungeKutta.GetDefaultScheme(control.ExplicitOrder),
                    equationSystem.GetJoinedOperator().ToSpatialOperator(fieldSet),
                    variableMap,
                    parameterMap,
                    equationSystem.GetJoinedOperator().CFLConstraints);
                break;

            case ExplicitSchemes.RungeKutta:
                timeStepper = ibmControl.TimesteppingStrategy.CreateRungeKuttaTimeStepper(
                    ibmControl,
                    equationSystem,
                    fieldSet,
                    parameterMap,
                    speciesMap,
                    equationSystem.GetJoinedOperator().CFLConstraints);
                break;

            case ExplicitSchemes.AdamsBashforth when control.DomainType == DomainTypes.Standard:
                timeStepper = new AdamsBashforth(
                    equationSystem.GetJoinedOperator().ToSpatialOperator(fieldSet),
                    variableMap,
                    parameterMap,
                    control.ExplicitOrder,
                    equationSystem.GetJoinedOperator().CFLConstraints);
                break;

            case ExplicitSchemes.AdamsBashforth:
                timeStepper = new IBMAdamsBashforth(
                    ibmFactory.GetJoinedOperator().ToSpatialOperator(fieldSet),
                    ibmFactory.GetImmersedBoundaryOperator().ToSpatialOperator(fieldSet),
                    variableMap,
                    parameterMap,
                    speciesMap,
                    ibmControl,
                    equationSystem.GetJoinedOperator().CFLConstraints);
                break;

            case ExplicitSchemes.LTS when control.DomainType == DomainTypes.Standard:
                timeStepper = new AdamsBashforthLTS(
                    equationSystem.GetJoinedOperator().ToSpatialOperator(fieldSet),
                    variableMap,
                    parameterMap,
                    control.ExplicitOrder,
                    control.NumberOfSubGrids,
                    equationSystem.GetJoinedOperator().CFLConstraints,
                    reclusteringInterval: control.ReclusteringInterval,
                    fluxCorrection: control.FluxCorrection,
                    saveToDBCallback: program.SaveToDatabase,
                    maxNumOfSubSteps: control.maxNumOfSubSteps,
                    forceReclustering: control.forceReclustering,
                    logging: control.WriteLTSLog,
                    consoleOutput: control.WriteLTSConsoleOutput);
                break;

            case ExplicitSchemes.LTS:
                timeStepper = new IBMAdamsBashforthLTS(
                    equationSystem.GetJoinedOperator().ToSpatialOperator(fieldSet),
                    ibmFactory.GetImmersedBoundaryOperator().ToSpatialOperator(fieldSet),
                    variableMap,
                    parameterMap,
                    speciesMap,
                    ibmControl,
                    equationSystem.GetJoinedOperator().CFLConstraints,
                    reclusteringInterval: control.ReclusteringInterval,
                    fluxCorrection: control.FluxCorrection,
                    maxNumOfSubSteps: control.maxNumOfSubSteps,
                    forceReclustering: control.forceReclustering,
                    logging: control.WriteLTSLog,
                    consoleOutput: control.WriteLTSConsoleOutput);
                break;

            case ExplicitSchemes.Rock4 when control.DomainType == DomainTypes.Standard:
                timeStepper = new ROCK4(equationSystem.GetJoinedOperator().ToSpatialOperator(fieldSet), new CoordinateVector(variableMap), null);
                break;

            case ExplicitSchemes.SSP54 when control.DomainType == DomainTypes.Standard:
                timeStepper = new RungeKutta(
                    RungeKuttaScheme.SSP54,
                    equationSystem.GetJoinedOperator().ToSpatialOperator(fieldSet),
                    variableMap,
                    parameterMap,
                    equationSystem.GetJoinedOperator().CFLConstraints);
                break;

            case ExplicitSchemes.RKC84 when control.DomainType == DomainTypes.Standard:
                timeStepper = new RungeKutta(
                    RungeKuttaScheme.RKC84,
                    equationSystem.GetJoinedOperator().ToSpatialOperator(fieldSet),
                    variableMap,
                    parameterMap,
                    equationSystem.GetJoinedOperator().CFLConstraints);
                break;

            case ExplicitSchemes.None:
                throw new System.ArgumentException("Cannot instantiate empty scheme");

            default:
                throw new NotImplementedException(String.Format(
                                                      "Explicit time stepper type '{0}' not implemented for domain type '{1}'",
                                                      timeStepperType,
                                                      control.DomainType));
            }

            // Make sure shock sensor is updated before every flux evaluation
            if (control.CNSShockSensor != null)
            {
                ExplicitEuler explicitEulerBasedTimestepper = timeStepper as ExplicitEuler;
                if (explicitEulerBasedTimestepper == null)
                {
                    throw new Exception(String.Format(
                                            "Shock-capturing currently not implemented for time-steppers of type '{0}'",
                                            timeStepperType));
                }

                explicitEulerBasedTimestepper.OnBeforeComputeChangeRate += delegate(double absTime, double relTime) {
                    // Note: Only shock sensor is updated, _NOT_ the corresponding variable
                    program.Control.CNSShockSensor.UpdateSensorValues(
                        program.WorkingSet.AllFields,
                        program.SpeciesMap,
                        explicitEulerBasedTimestepper.SubGrid.VolumeMask);
                    // Note: When being called, artificial viscosity is updated in the _ENTIRE_ (fluid) domain
                    var avField = program.WorkingSet.DerivedFields[CNSVariables.ArtificialViscosity];
                    CNSVariables.ArtificialViscosity.UpdateFunction(avField, program.SpeciesMap.SubGrid.VolumeMask, program);

                    // Test
                    //double sensorNorm = program.WorkingSet.DerivedFields[CNSVariables.ShockSensor].L2Norm();
                    //double avNorm = program.WorkingSet.DerivedFields[CNSVariables.ArtificialViscosity].L2Norm();
                    //Console.WriteLine("\r\nThis is OnBeforeComputeChangeRate");
                    //Console.WriteLine("SensorNeu: {0}", sensorNorm);
                    //Console.WriteLine("AVNeu: {0}", avNorm);
                };
            }

            // Make sure limiter is applied after each modification of conservative variables
            if (control.Limiter != null)
            {
                ExplicitEuler explicitEulerBasedTimestepper = timeStepper as ExplicitEuler;
                if (explicitEulerBasedTimestepper == null)
                {
                    throw new Exception(String.Format(
                                            "Limiting currently not implemented for time-steppers of type '{0}~",
                                            timeStepperType));
                }

                explicitEulerBasedTimestepper.OnAfterFieldUpdate +=
                    (t, f) => control.Limiter.LimitFieldValues(program.WorkingSet.ConservativeVariables, program.WorkingSet.DerivedFields.Values);
            }

            return(timeStepper);
        }
示例#9
0
        public static IBMControl IBMNACA0012(int MeshPara, int dgDegree, double CFL, double agglomeration, double alpha)
        {
            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 = 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.savetodb           = false;
            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;
            c.MachNumber      = 1.0 / Math.Sqrt(c.EquationOfState.HeatCapacityRatio);

            // Primary CNSVariables
            c.AddVariable(CompressibleVariables.Density, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.xComponent, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.yComponent, dgDegree);
            c.AddVariable(CompressibleVariables.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.EdgeTagNames.Add(2, "AdiabaticSlipWall");
                grid.DefineEdgeTags((Vector 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(CompressibleVariables.Density, X => rho(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.xComponent, X => u0(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.yComponent, X => u1(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Pressure, X => pressure(X, 0.0));

            //BoundaryConditions
            c.AddBoundaryValue("AdiabaticSlipWall");
            c.AddBoundaryValue("supersonicInlet", CompressibleVariables.Density, rho);
            c.AddBoundaryValue("supersonicInlet", CNSVariables.Velocity.xComponent, u0);
            c.AddBoundaryValue("supersonicInlet", CNSVariables.Velocity.yComponent, u1);
            c.AddBoundaryValue("supersonicInlet", CNSVariables.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, bool AV = true)
        {
            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;

            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 = CompressibleVariables.Density;
                c.CNSShockSensor = new PerssonSensor(sensorVariable, sensorLimit);
                c.AddVariable(CNSVariables.ShockSensor, 0);
                c.ArtificialViscosityLaw = new SmoothedHeavisideArtificialViscosityLaw(c.CNSShockSensor, 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(CompressibleVariables.Density, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.xComponent, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.yComponent, dgDegree);
            c.AddVariable(CompressibleVariables.Energy, dgDegree);
            c.AddVariable(CNSVariables.Velocity.xComponent, dgDegree);
            c.AddVariable(CNSVariables.Velocity.yComponent, dgDegree);
            c.AddVariable(CNSVariables.Pressure, dgDegree);
            c.AddVariable(CNSVariables.Rank, 0);

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

            if (c.ExplicitScheme.Equals(ExplicitSchemes.LTS))
            {
                c.AddVariable(CNSVariables.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.AddBoundaryValue("AdiabaticSlipWall");

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

            // Direction vector of initial shock
            Vector r = new Vector(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(CNSVariables.Pressure, X => pressureLeft - SmoothJump(DistanceFromPointToLine(X, p, r)) * (pressureLeft - pressureRight));
            c.InitialValues_Evaluators.Add(CompressibleVariables.Density, X => densityLeft - Jump(X[0]) * (densityLeft - densityRight));
            c.InitialValues_Evaluators.Add(CNSVariables.Pressure, X => pressureLeft - Jump(X[0]) * (pressureLeft - pressureRight));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.xComponent, X => 0.0);
            c.InitialValues_Evaluators.Add(CNSVariables.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, agg={3}, s0={4:0.0E-00}, CFLFrac={5}, ALTS {6}/{7}/{8}({9}), Part={10}/{11}({12})", dgDegree, noOfCellsX, noOfCellsY, c.AgglomerationThreshold, sensorLimit, c.CFLFraction, c.ExplicitOrder, c.NumberOfSubGrids, c.ReclusteringInterval, c.maxNumOfSubSteps, c.GridPartType.ToString(), c.DynamicLoadBalancing_Period, c.DynamicLoadBalancing_ImbalanceThreshold);

            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(CompressibleVariables.Density, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.xComponent, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.yComponent, dgDegree);
            c.AddVariable(CompressibleVariables.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((Vector 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(CompressibleVariables.Density, X => rho(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.xComponent, X => u(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.yComponent, X => v(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.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 Vector(0.0, 10.0 * amplitude * Math.Cos(10.0 * t));

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

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

            return(c);
        }
示例#12
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 CNSVariables
            c.AddVariable(CompressibleVariables.Density, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.xComponent, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.yComponent, dgDegree);
            c.AddVariable(CompressibleVariables.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(CompressibleVariables.Density, X => rho(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.xComponent, X => u0(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.yComponent, X => u1(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.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.AddBoundaryValue("adiabaticSlipWall");
            c.AddBoundaryValue("supersonicInlet", CompressibleVariables.Density, rho);
            c.AddBoundaryValue("supersonicInlet", CNSVariables.Velocity.xComponent, u0);
            c.AddBoundaryValue("supersonicInlet", CNSVariables.Velocity.yComponent, u1);
            c.AddBoundaryValue("supersonicInlet", CNSVariables.Pressure, pressure);


            // Queries

            c.Queries.Add("L2ErrorEntropy", IBMQueries.L2Error(state => state.Entropy, (X, t) => 2.8571428571428));
            return(c);
        }
示例#13
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 CNSVariables
            c.AddVariable(CompressibleVariables.Density, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.xComponent, dgDegree);
            c.AddVariable(CompressibleVariables.Momentum.yComponent, dgDegree);
            c.AddVariable(CompressibleVariables.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(CompressibleVariables.Density, X => rho(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.xComponent, X => u0(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Velocity.yComponent, X => u1(X, 0.0));
            c.InitialValues_Evaluators.Add(CNSVariables.Pressure, X => pressure(X, 0.0));

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

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


            // Queries

            c.Queries.Add("L2ErrorEntropy", IBMQueries.L2Error(state => state.Entropy, (X, t) => 2.8571428571428));
            return(c);
        }