Esempio n. 1
0
        /// <summary>
        /// Calculate A Level-Set field from the Explicit description
        /// </summary>
        /// <param name="LevelSet">Target Field</param>
        /// <param name="LsTrk"></param>
        public void ProjectToDGLevelSet(SinglePhaseField LevelSet, LevelSetTracker LsTrk = null)
        {
            CellMask VolMask;

            if (LsTrk == null)
            {
                VolMask = CellMask.GetFullMask(LevelSet.Basis.GridDat);
            }
            else
            {
                // set values in positive and negative FAR region to +1 and -1
                CellMask Near   = LsTrk.Regions.GetNearMask4LevSet(0, 1);
                CellMask PosFar = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask.Except(Near);
                CellMask NegFar = LsTrk.Regions.GetLevelSetWing(0, -1).VolumeMask.Except(Near);

                LevelSet.Clear(PosFar);
                LevelSet.AccConstant(1, PosFar);
                LevelSet.Clear(NegFar);
                LevelSet.AccConstant(-1, NegFar);

                // project Fourier levelSet to DGfield on near field
                VolMask = Near;
            }

            LevelSet.Clear(VolMask);
            // scalar function is already vectorized for parallel execution
            // nodes in global coordinates
            LevelSet.ProjectField(1.0,
                                  PhiEvaluation(mode),
                                  new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));

            // check the projection error
            projErr_phiDG = LevelSet.L2Error(
                PhiEvaluation(mode),
                new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));
            //if (projErr_phiDG >= 1e-5)
            //    Console.WriteLine("WARNING: LevelSet projection error onto PhiDG = {0}", projErr_phiDG);


            // project on higher degree field and take the difference
            //SinglePhaseField higherLevSet = new SinglePhaseField(new Basis(LevelSet.GridDat, LevelSet.Basis.Degree * 2), "higherLevSet");
            //higherLevSet.ProjectField(1.0, PhiEvaluator(), new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));
            //double higherProjErr = higherLevSet.L2Error(
            //    PhiEvaluator(),
            //    new Foundation.Quadrature.CellQuadratureScheme(true, VolMask));
            //Console.WriteLine("LevelSet projection error onto higherPhiDG = {0}", higherProjErr.ToString());


            // check the projection from current sample points on the DGfield
            //MultidimensionalArray interP = MultidimensionalArray.Create(current_interfaceP.Lengths);
            //if (this is PolarFourierLevSet) {
            //    interP = ((PolarFourierLevSet)this).interfaceP_cartesian;
            //} else {
            //    interP = current_interfaceP;
            //}

            //projErr_interface = InterfaceProjectionError(LevelSet, current_interfaceP);
            //if (projErr_interface >= 1e-3)
            //    Console.WriteLine("WARNING: Interface projection Error onto PhiDG = {0}", projErr_interface);
        }
Esempio n. 2
0
        /// <summary>
        /// Sets the positive Far-field of the level-set to +1 and the negative side to -1
        /// </summary>
        /// <param name="LevelSet"></param>
        /// <param name="Domain"></param>
        /// <param name="PosMask"></param>
        public void SetFarField(SinglePhaseField LevelSet, CellMask Domain, CellMask PosMask)
        {
            // set cells outside narrow band to +/- 1
            var Pos = PosMask.Except(Domain);
            var Neg = PosMask.Complement().Except(Domain);

            LevelSet.Clear(Pos);
            LevelSet.AccConstant(1, Pos);

            LevelSet.Clear(Neg);
            LevelSet.AccConstant(-1, Neg);
        }
Esempio n. 3
0
        /// <summary>
        /// Sets level-set and solution at time (<paramref name="time"/> + <paramref name="dt"/>).
        /// </summary>
        double DelUpdateLevelset(DGField[] CurrentState, double time, double dt, double UnderRelax, bool _incremental)
        {
            // new time
            double t = time + dt;

            // project new level-set
            double s = 1.0;

            LevSet.ProjectField((x, y) => - (x - s * t).Pow2() - y.Pow2() + (2.4).Pow2());
            LsTrk.UpdateTracker(incremental: _incremental);

            // exact solution for new timestep
            uEx.GetSpeciesShadowField("A").ProjectField((x, y) => x + alpha_A * t);
            uEx.GetSpeciesShadowField("B").ProjectField((x, y) => x + alpha_B * t);

            u.Clear();
            u.Acc(1.0, uEx);

            // markieren, wo ueberhaupt A und B sind
            Amarker.Clear();
            Bmarker.Clear();
            Amarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("A").VolumeMask);
            Bmarker.AccConstant(1.0, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);

            // MPI rank
            MPICellRank.Clear();
            MPICellRank.AccConstant(base.MPIRank);

            // return level-set residual
            return(0.0);
        }
Esempio n. 4
0
        /// <summary>
        /// Sets level-set and solution at time (<paramref name="time"/> + <paramref name="dt"/>).
        /// </summary>
        double DelUpdateLevelset(DGField[] CurrentState, double time, double dt, double UnderRelax, bool _incremental)
        {
            // new time
            double t = time + dt;

            // project new level-set
            LevSet.ProjectField(this.Control.LevelSet.Vectorize(t));
            LsTrk.UpdateTracker(incremental: _incremental);

            // exact solution for new timestep
            uEx.GetSpeciesShadowField("A").ProjectField(NonVectorizedScalarFunction.Vectorize(this.Control.uEx_A, t));
            uEx.GetSpeciesShadowField("B").ProjectField(NonVectorizedScalarFunction.Vectorize(this.Control.uEx_B, t));

            u.Clear();
            u.Acc(1.0, uEx);

            // markieren, wo ueberhaupt A und B sind
            Amarker.Clear();
            Bmarker.Clear();
            Amarker.AccConstant(+1.0, LsTrk._Regions.GetSpeciesSubGrid("A").VolumeMask);
            Bmarker.AccConstant(1.0, LsTrk._Regions.GetSpeciesSubGrid("B").VolumeMask);

            // MPI rank
            MPICellRank.Clear();
            MPICellRank.AccConstant(base.MPIRank);

            // return level-set residual
            return(0.0);
        }
Esempio n. 5
0
            /// <summary>
            /// Outputs a piecewise constant field which is 0 outside the narrow band
            /// 1+width on cut cells and decreasing on the near-cells
            /// </summary>
            public SinglePhaseField ToDGField()
            {
                SinglePhaseField TrackerField = new SinglePhaseField(new Basis(m_owner.GridDat, 0));

                // decrement loop:
                for (int width = 0; width <= m_owner.NearRegionWidth; width++)
                {
                    TrackerField.AccConstant(1, this.GetNearFieldMask(width));
                }
                return(TrackerField);
            }
Esempio n. 6
0
        /// <summary>
        /// Approximation of the signum function of the level set field
        /// </summary>
        /// <param name="Output"></param>
        /// <param name="gridParameter"></param>
        /// <param name="optionalCellMask"></param>
        public void ApproximateSignFunction(
            SinglePhaseField Output, double gridParameter, CellMask optionalCellMask)
        {
            SinglePhaseField quot = new SinglePhaseField(m_Basis, "quot");
            SinglePhaseField sqrt = new SinglePhaseField(m_Basis, "sqrt");

            sqrt.ProjectProduct(1.0, this, this, optionalCellMask);
            sqrt.AccConstant(gridParameter * gridParameter, optionalCellMask);

            quot.ProjectPow(1.0, sqrt, 0.5, optionalCellMask);
            //Output.ProjectQuotient (1.0, this, quot,false);
            Output.ProjectQuotient(1.0, this, quot, optionalCellMask, false);
        }
Esempio n. 7
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            Console.WriteLine("    Timestep # " + TimestepNo + ", phystime = " + phystime);

            //phystime = 1.8;
            LsUpdate(phystime);


            // operator-matrix assemblieren
            MsrMatrix OperatorMatrix = new MsrMatrix(u.Mapping, u.Mapping);

            double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength];
            MultiphaseCellAgglomerator Agg;
            MassMatrixFactory          Mfact;

            // Agglomerator setup
            int quadOrder = Op.QuadOrderFunction(new int[] { u.Basis.Degree }, new int[0], new int[] { u.Basis.Degree });

            //Agg = new MultiphaseCellAgglomerator(new CutCellMetrics(MomentFittingVariant, quadOrder, LsTrk, ), this.THRESHOLD, false);
            Agg = LsTrk.GetAgglomerator(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, quadOrder, this.THRESHOLD);

            Console.WriteLine("Inter-Process agglomeration? " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.InterProcessAgglomeration);
            if (this.THRESHOLD > 0.01)
            {
                TestAgglomeration_Extraploation(Agg);
                TestAgglomeration_Projection(quadOrder, Agg);
            }

            // operator matrix assembly
            Op.ComputeMatrixEx(LsTrk,
                               u.Mapping, null, u.Mapping,
                               OperatorMatrix, Affine, false, 0.0, true,
                               Agg.CellLengthScales,
                               LsTrk.GetSpeciesId("B"));
            Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, u.Mapping, u.Mapping);

            // mass matrix factory
            Mfact = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, quadOrder, 1).MassMatrixFactory;// new MassMatrixFactory(u.Basis, Agg);

            // Mass matrix/Inverse Mass matrix
            //var MassInv = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, true, LsTrk.GetSpeciesId("B"));
            var Mass = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, false, LsTrk.GetSpeciesId("B"));

            Agg.ManipulateMatrixAndRHS(Mass, default(double[]), u.Mapping, u.Mapping);
            var MassInv = Mass.InvertBlocks(OnlyDiagonal: true, Subblocks: true, ignoreEmptyBlocks: true, SymmetricalInversion: false);


            // test that operator depends only on B-species values
            double DepTest = LsTrk.Regions.GetSpeciesSubGrid("B").TestMatrixDependency(OperatorMatrix, u.Mapping, u.Mapping);

            Console.WriteLine("Matrix dependency test: " + DepTest);
            Assert.LessOrEqual(DepTest, 0.0);

            // diagnostic output
            Console.WriteLine("Number of Agglomerations (all species): " + Agg.TotalNumberOfAgglomerations);
            Console.WriteLine("Number of Agglomerations (species 'B'): " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.SourceCells.NoOfItemsLocally.MPISum());

            // operator auswerten:
            double[] x = new double[Affine.Length];
            BLAS.daxpy(x.Length, 1.0, Affine, 1, x, 1);
            OperatorMatrix.SpMVpara(1.0, u.CoordinateVector, 1.0, x);
            MassInv.SpMV(1.0, x, 0.0, du_dx.CoordinateVector);
            Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).Extrapolate(du_dx.Mapping);


            // markieren, wo ueberhaupt A und B sind
            Bmarker.AccConstant(1.0, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            Amarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("A").VolumeMask);
            Xmarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("X").VolumeMask);

            // compute error
            ERR.Clear();
            ERR.Acc(1.0, du_dx_Exact, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            ERR.Acc(-1.0, du_dx, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            double L2Err = ERR.L2Norm(LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);

            Console.WriteLine("L2 Error: " + L2Err);

            XERR.Clear();
            XERR.GetSpeciesShadowField("B").Acc(1.0, ERR, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            double xL2Err = XERR.L2Norm();

            Console.WriteLine("L2 Error (in XDG space): " + xL2Err);



            // check error
            if (this.THRESHOLD > 0.01)
            {
                // without agglomeration, the error in very tiny cut-cells may be large over the whole cell
                // However, the error in the XDG-space should be small under all circumstances
                Assert.LessOrEqual(L2Err, 1.0e-6);
            }
            Assert.LessOrEqual(xL2Err, 1.0e-6);

            bool IsPassed = ((L2Err <= 1.0e-6 || this.THRESHOLD <= 0.01) && xL2Err <= 1.0e-7);

            if (IsPassed)
            {
                Console.WriteLine("Test PASSED");
            }
            else
            {
                Console.WriteLine("Test FAILED: check errors.");
            }

            // return/Ende
            base.NoOfTimesteps = 17;
            //base.NoOfTimesteps = 2;
            dt = 0.3;
            return(dt);
        }
Esempio n. 8
0
        /// <summary>
        /// Reinit on un-cut cells.
        /// </summary>
        /// <param name="Phi">The level set</param>
        /// <param name="ReInitSpecies">Cell mask wich is to be reinitialized</param>
        /// <param name="sign">Sign of the level set for this <paramref name="ReInitSpecies"/></param>
        /// <param name="_Accepted">CellMask which is taken as boundray values</param>
        /// <param name="GradPhi">LEvel Set gradient</param>
        /// <param name="callBack">A delegate, which might be called after the execution of the reinitialization</param>
        public void Reinitialize(SinglePhaseField Phi, CellMask ReInitSpecies, double sign,
                                 CellMask _Accepted,
                                                                                                //ConventionalDGField[] ExtProperty, double[][] ExtPropertyMin, double[][] ExtPropertyMax,
                                 VectorField <SinglePhaseField> GradPhi, Action <int> callBack) //
        {
            using (new FuncTrace()) {
                Tracer.InstrumentationSwitch = false; // lots of tracing on calls acting on singe cells causes massive overhead (up to 5x slower).
                Stpw_total.Start();

                SinglePhaseField DiffusionCoeff = new SinglePhaseField(new Basis(this.GridDat, 1), "DiffusionCoeff");


                // check args and init
                // ===================

                /*
                 * ExtVelSolver extVelSlv = null;
                 * if(ExtProperty != null) {
                 *  if(ExtProperty.Length != ExtPropertyMin.Length)
                 *      throw new ArgumentException();
                 *  if(ExtProperty.Length != ExtPropertyMax.Length)
                 *      throw new ArgumentException();
                 *
                 *  extVelSlv = new ExtVelSolver(ExtProperty[0].Basis);
                 * }
                 */

                BitArray Acceped_Mutuable   = _Accepted.GetBitMask().CloneAs();
                BitArray Trial_Mutuable     = ((_Accepted.AllNeighbourCells().Intersect(ReInitSpecies)).Except(_Accepted)).GetBitMask().CloneAs();
                BitArray Recalc_Mutuable    = Trial_Mutuable.CloneAs();
                BitArray PosSpecies_Bitmask = ReInitSpecies.GetBitMask();

                int J = this.GridDat.Cells.NoOfCells;
                int D = this.GridDat.SpatialDimension;
                int N = this.LevelSetBasis.Length;

                double   _sign  = sign >= 0 ? 1.0 : -1.0;
                double[] PhiAvg = m_PhiAvg;
                if (PhiAvg == null)
                {
                    throw new ApplicationException();
                }

                foreach (int jCell in _Accepted.ItemEnum)
                {
                    PhiAvg[jCell] = Phi.GetMeanValue(jCell);
                }

                int NoOfNew;
                {
                    var Neu = ReInitSpecies.Except(_Accepted);
                    NoOfNew = Neu.NoOfItemsLocally;
                    Phi.Clear(Neu);
                    Phi.AccConstant(_sign, Neu);

                    foreach (int jCell in Neu.ItemEnum)
                    {
                        PhiAvg[jCell] = 1.0e10;
                    }
                }

                if (this.GridDat.MpiSize > 1)
                {
                    throw new NotSupportedException("Currently not MPI parallel.");
                }


                for (int d = 0; d < this.GridDat.SpatialDimension; d++)
                {
                    if (!GradPhi[d].Basis.Equals(Phi.Basis))
                    {
                        throw new ArgumentException("Level-set and level-set gradient field should have the same DG basis."); // ein grad niedriger wrürde auch genügen...
                    }
                }



                // perform marching...
                // ===================

                // update gradient for cut-cells
                GradPhi.Clear(_Accepted);
                GradPhi.Gradient(1.0, Phi, _Accepted);

                // marching loop../
                int cnt = 0;
                while (true)
                {
                    cnt++;



                    CellMask Recalc   = new CellMask(this.GridDat, Recalc_Mutuable);
                    CellMask Accepted = new CellMask(this.GridDat, Acceped_Mutuable);
                    CellMask Trial    = new CellMask(this.GridDat, Trial_Mutuable);

                    int NoOfTrial = Trial.NoOfItemsLocally;
                    int NoOfAccpt = Accepted.NoOfItemsLocally;
                    int NoOfRcalc = Recalc.NoOfItemsLocally;

                    if (Trial.NoOfItemsLocally <= 0)
                    {
                        //Ploti(Recalc, Accepted, Trial, Phi, Phi_gradient, optEikonalOut, cnt);
                        break;
                    }

                    // Local solver for all 'Recalc'-cells
                    // --------------------------------------


                    if (Recalc.NoOfItemsLocally > 0)
                    {
                        this.LocalSolve(Accepted, Recalc, Phi, GradPhi, _sign, DiffusionCoeff);
                    }

                    // find the next cell to accept
                    // ----------------------------

                    // get mean value in all cells
                    foreach (int jCell in Recalc.ItemEnum)
                    {
                        PhiAvg[jCell]          = Phi.GetMeanValue(jCell);
                        Recalc_Mutuable[jCell] = false;
                    }

                    //Ploti(Recalc, Accepted, Trial, Phi, Phi_gradient, optEikonalOut, cnt);

                    // find trial-cell with minimum average value
                    // this should be done with heap-sort (see fast-marching algorithm)
                    int    jCellAccpt = int.MaxValue;
                    double TrialMin   = double.MaxValue;
                    foreach (int jCell in Trial.ItemEnum)
                    {
                        if (PhiAvg[jCell] * _sign < TrialMin)
                        {
                            TrialMin   = PhiAvg[jCell] * _sign;
                            jCellAccpt = jCell;
                        }
                    }

                    if (callBack != null)
                    {
                        callBack(cnt);
                    }

                    /*
                     * // update the gradient
                     * // -------------------
                     *
                     * this.Stpw_gradientEval.Start();
                     * gradModule.GradientUpdate(jCellAccpt, Acceped_Mutuable, Phi, GradPhi);
                     * this.Stpw_gradientEval.Stop();
                     *
                     * /*
                     * // solve for the extension properties
                     * // ----------------------------------
                     *
                     * if(ExtProperty != null) {
                     *  int[] Neight, dummy33;
                     *  GridDat.Cells.GetCellNeighbours(jCellAccpt, GridData.CellData.GetCellNeighbours_Mode.ViaEdges, out Neight, out dummy33);
                     *
                     *  for(int iComp = 0; iComp < ExtProperty.Length; iComp++) {
                     *
                     *      ExtPropertyMax[iComp][jCellAccpt] = -double.MaxValue;
                     *      ExtPropertyMin[iComp][jCellAccpt] = double.MaxValue;
                     *
                     *      foreach(int jNeig in Neight) {
                     *          if(Acceped_Mutuable[jNeig]) {
                     *              ExtPropertyMax[iComp][jCellAccpt] = Math.Max(ExtPropertyMax[iComp][jCellAccpt], ExtPropertyMax[iComp][jNeig]);
                     *              ExtPropertyMin[iComp][jCellAccpt] = Math.Min(ExtPropertyMin[iComp][jCellAccpt], ExtPropertyMin[iComp][jNeig]);
                     *          }
                     *      }
                     *
                     *      this.Stpw_extVelSolver.Start();
                     *      extVelSlv.ExtVelSolve_Far(Phi, GradPhi, ExtProperty[iComp], ref ExtPropertyMin[iComp][jCellAccpt], ref ExtPropertyMax[iComp][jCellAccpt], jCellAccpt, Accepted, _sign);
                     *      this.Stpw_extVelSolver.Stop();
                     *  }
                     * }
                     * /*
                     * {
                     *  int[] Neight, dummy33;
                     *  GridDat.Cells.GetCellNeighbours(jCellAccpt, GridData.CellData.GetCellNeighbours_Mode.ViaEdges, out Neight, out dummy33);
                     *  foreach(int jNeig in Neight) {
                     *      if(Acceped_Mutuable[jNeig]) {
                     *          plotDependencyArrow(cnt, jCellAccpt, jNeig);
                     *      }
                     *  }
                     * }
                     */

                    // the mimium is moved to accepted
                    // -------------------------------
                    Acceped_Mutuable[jCellAccpt] = true;
                    Trial_Mutuable[jCellAccpt]   = false;
                    Recalc_Mutuable[jCellAccpt]  = false;
                    NoOfNew--;

                    // recalc on all neighbours
                    // ------------------------
                    int[] Neighs, dummy;
                    this.GridDat.GetCellNeighbours(jCellAccpt, GetCellNeighbours_Mode.ViaEdges, out Neighs, out dummy);
                    foreach (int jNeig in Neighs)
                    {
                        if (!Acceped_Mutuable[jNeig] && PosSpecies_Bitmask[jNeig])
                        {
                            Trial_Mutuable[jNeig]  = true;
                            Recalc_Mutuable[jNeig] = true;
                        }
                    }
                }

                if (NoOfNew > 0)
                {
                    throw new ArithmeticException("Unable to perform reinitialization for all requested cells - maybe they are not reachable from the initialy 'accepted' domain?");
                }

                //PlottAlot("dependencies.csv");

                Tracer.InstrumentationSwitch = true;
                Stpw_total.Stop();
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Update scalar field variables after solving scalar equation.
        /// </summary>
        /// <param name="SolverConf"></param>
        /// <param name="ModeRelaxScalar"></param>
        /// <param name="relax_scalar"></param>
        /// <param name="Scalar"></param>
        /// <param name="ScalarRes"></param>
        /// <param name="ScalarMean"></param>
        /// <param name="Rho"></param>
        /// <param name="Eta"></param>
        /// <param name="RhoMatrix"></param>
        /// <param name="EoS"></param>
        /// <param name="ThermodynamicPressure">Null for multiphase flows.</param>
        public static void UpdateScalarFieldVariables(SIMPLEControl SolverConf, RelaxationTypes ModeRelaxScalar, double relax_scalar,
                                                      ScalarFieldHistory <SinglePhaseField> Scalar, SinglePhaseField ScalarRes, SinglePhaseField ScalarMean,
                                                      SinglePhaseField Rho, SinglePhaseField Eta, QuadratureMatrix RhoMatrix, MaterialLaw EoS,
                                                      SinglePhaseField ThermodynamicPressure, bool UpdateRhoVisc = true)
        {
            using (new FuncTrace()) {
                // Explicit Under-Relaxation of scalar variable
                // ============================================

                if (ModeRelaxScalar == RelaxationTypes.Explicit)
                {
                    // phi = alpha * phi_new + (1-alpha) * phi_old
                    Scalar.Current.Scale(relax_scalar);
                    Scalar.Current.Acc((1.0 - relax_scalar), ScalarRes);
                }

                // Scalar residual
                // ===============

                ScalarRes.Scale(-1.0);
                ScalarRes.Acc(1.0, Scalar.Current);

                // ScalarMean
                // ==========

                ScalarMean.Clear();
                ScalarMean.AccLaidBack(1.0, Scalar.Current);

                // Thermodynamic pressure - only for Low-Mach number flows
                // =======================================================

                switch (SolverConf.PhysicsMode)
                {
                case PhysicsMode.LowMach:
                    LowMachSIMPLEControl lowMachConf = SolverConf as LowMachSIMPLEControl;
                    if (lowMachConf.ThermodynamicPressureMode == ThermodynamicPressureMode.MassDetermined)
                    {
                        ThermodynamicPressure.Clear();
                        ThermodynamicPressure.AccConstant(((MaterialLawLowMach)EoS).GetMassDeterminedThermodynamicPressure(lowMachConf.InitialMass.Value, Scalar.Current));
                    }
                    break;

                case PhysicsMode.Multiphase:
                    break;

                default:
                    throw new ApplicationException();
                }

                if (UpdateRhoVisc)
                {
                    // Density
                    // =======

                    Rho.Clear();
                    Rho.ProjectFunction(1.0, EoS.GetDensity, null, Scalar.Current);
                    RhoMatrix.Update();

                    // Viscosity
                    // =========

                    Eta.Clear();
                    Eta.ProjectFunction(1.0, EoS.GetViscosity, null, Scalar.Current);
                }
            }
        }
Esempio n. 10
0
        protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt)
        {
            Console.WriteLine("    Timestep # " + TimestepNo + ", phystime = " + phystime);

            //phystime = 1.8;
            LsUpdate(phystime);


            // operator-matrix assemblieren
            MsrMatrix OperatorMatrix = new MsrMatrix(u.Mapping, u.Mapping);

            double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength];

            // Agglomerator setup
            MultiphaseCellAgglomerator Agg = LsTrk.GetAgglomerator(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, QuadOrder, this.THRESHOLD);

            // plausibility of cell length scales
            if (SER_PAR_COMPARISON)
            {
                TestLengthScales(QuadOrder, TimestepNo);
            }

            Console.WriteLine("Inter-Process agglomeration? " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.InterProcessAgglomeration);
            if (this.THRESHOLD > 0.01)
            {
                TestAgglomeration_Extraploation(Agg);
                TestAgglomeration_Projection(QuadOrder, Agg);
            }
            CheckExchange(true);
            CheckExchange(false);

            // operator matrix assembly
            XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, u.Mapping, null, u.Mapping);
            mtxBuilder.time = 0.0;
            mtxBuilder.ComputeMatrix(OperatorMatrix, Affine);
            Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, u.Mapping, u.Mapping);

            // mass matrix factory
            var Mfact = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, QuadOrder, 1).MassMatrixFactory;// new MassMatrixFactory(u.Basis, Agg);

            // Mass matrix/Inverse Mass matrix
            //var MassInv = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, true, LsTrk.GetSpeciesId("B"));
            var Mass = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, false, LsTrk.GetSpeciesId("B"));

            Agg.ManipulateMatrixAndRHS(Mass, default(double[]), u.Mapping, u.Mapping);
            var MassInv = Mass.InvertBlocks(OnlyDiagonal: true, Subblocks: true, ignoreEmptyBlocks: true, SymmetricalInversion: false);


            // test that operator depends only on B-species values
            double DepTest = LsTrk.Regions.GetSpeciesSubGrid("B").TestMatrixDependency(OperatorMatrix, u.Mapping, u.Mapping);

            Console.WriteLine("Matrix dependency test: " + DepTest);
            Assert.LessOrEqual(DepTest, 0.0);

            // diagnostic output
            Console.WriteLine("Number of Agglomerations (all species): " + Agg.TotalNumberOfAgglomerations);
            Console.WriteLine("Number of Agglomerations (species 'B'): " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.SourceCells.NoOfItemsLocally.MPISum());

            // operator auswerten:
            double[] x = new double[Affine.Length];
            BLAS.daxpy(x.Length, 1.0, Affine, 1, x, 1);
            OperatorMatrix.SpMVpara(1.0, u.CoordinateVector, 1.0, x);
            MassInv.SpMV(1.0, x, 0.0, du_dx.CoordinateVector);
            Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).Extrapolate(du_dx.Mapping);

            // markieren, wo ueberhaupt A und B sind
            Bmarker.AccConstant(1.0, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            Amarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("A").VolumeMask);
            if (usePhi0 && usePhi1)
            {
                Xmarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("X").VolumeMask);
            }

            // compute error
            ERR.Clear();
            ERR.Acc(1.0, du_dx_Exact, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            ERR.Acc(-1.0, du_dx, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            double L2Err = ERR.L2Norm(LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);

            Console.WriteLine("L2 Error: " + L2Err);

            XERR.Clear();
            XERR.GetSpeciesShadowField("B").Acc(1.0, ERR, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask);
            double xL2Err = XERR.L2Norm();

            Console.WriteLine("L2 Error (in XDG space): " + xL2Err);



            // check error
            double ErrorThreshold = 1.0e-1;

            if (this.MomentFittingVariant == XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes)
            {
                ErrorThreshold = 1.0e-6; // HMF is designed for such integrands and should perform close to machine accuracy; on general integrands, the precision is different.
            }
            bool IsPassed = ((L2Err <= ErrorThreshold || this.THRESHOLD <= ErrorThreshold) && xL2Err <= ErrorThreshold);

            if (IsPassed)
            {
                Console.WriteLine("Test PASSED");
            }
            else
            {
                Console.WriteLine("Test FAILED: check errors.");
                //PlotCurrentState(phystime, TimestepNo, 3);
            }

            if (TimestepNo > 1)
            {
                if (this.THRESHOLD > ErrorThreshold)
                {
                    // without agglomeration, the error in very tiny cut-cells may be large over the whole cell
                    // However, the error in the XDG-space should be small under all circumstances
                    Assert.LessOrEqual(L2Err, ErrorThreshold, "DG L2 error of computing du_dx");
                }
                Assert.LessOrEqual(xL2Err, ErrorThreshold, "XDG L2 error of computing du_dx");
            }



            // return/Ende
            base.NoOfTimesteps = 17;
            //base.NoOfTimesteps = 2;
            dt = 0.3;
            return(dt);
        }
Esempio n. 11
0
        /// <summary>
        ///  In this method, the vector normal to the surface as well as certain derivatives
        /// of it that we intend to use are set up
        /// </summary>

        protected void NormalVec(double deltax)
        {
            wx = new SinglePhaseField(m_gradBasis, "wx");
            wy = new SinglePhaseField(m_gradBasis, "wy");

            if (m_Context.Grid.SpatialDimension == 2)
            {
                m_Gradw = new VectorField <SinglePhaseField>(wx, wy);
            }
            else if (m_Context.Grid.SpatialDimension == 3)
            {
                wz      = new SinglePhaseField(m_gradBasis, "wz");
                m_Gradw = new VectorField <SinglePhaseField>(wx, wy, wz);
            }
            else
            {
                throw new NotSupportedException("only spatial dimension 2 and 3 are supported.");
            }
            SinglePhaseField absval = new SinglePhaseField(m_gradBasis);

            m_Gradw[0].Derivative(1.0, m_Field, 0);
            m_Gradw[1].Derivative(1.0, m_Field, 1);

            if (m_Context.Grid.SpatialDimension == 3)
            {
                m_Gradw[2].Derivative(1.0, m_Field, 2);
            }

            /*
             * Normalization of the gradient vector
             * Might be better implemented using a
             * Function
             */

            absval.ProjectAbs(1.0, m_Gradw);
            m_Gradw[0].ProjectQuotient(1.0, m_Gradw[0], absval, null, false);
            m_Gradw[1].ProjectQuotient(1.0, m_Gradw[1], absval, null, false);

            if (m_Context.Grid.SpatialDimension == 3)
            {
                m_Gradw[2].ProjectQuotient(1.0, m_Gradw[2], absval, null, false);
            }
            SinglePhaseField n1x = new SinglePhaseField(m_derivsBasis, "n1x");
            SinglePhaseField n2x = new SinglePhaseField(m_derivsBasis, "n2x");
            SinglePhaseField n1y = new SinglePhaseField(m_derivsBasis, "n1y");
            SinglePhaseField n2y = new SinglePhaseField(m_derivsBasis, "n2y");

            if (m_Context.Grid.SpatialDimension == 3)
            {
                SinglePhaseField n3x = new SinglePhaseField(m_derivsBasis, "n3x");
                SinglePhaseField n3y = new SinglePhaseField(m_derivsBasis, "n3y");
                SinglePhaseField n1z = new SinglePhaseField(m_derivsBasis, "n1z");
                SinglePhaseField n2z = new SinglePhaseField(m_derivsBasis, "n2z");
                SinglePhaseField n3z = new SinglePhaseField(m_derivsBasis, "n3z");

                m_normderivs = new VectorField <SinglePhaseField>(n1x, n2x, n3x, n1y, n2y, n3y, n1z, n2z, n3z);

                /* Partial derivatives of the normal vector.
                 * These quantities are used in the product rule applied to the surface projection
                 * and to compute the mean curvature
                 */

                m_normderivs[0].Derivative(1.0, m_Gradw[0], 0);
                m_normderivs[1].Derivative(1.0, m_Gradw[1], 0);
                m_normderivs[2].Derivative(1.0, m_Gradw[2], 0);
                m_normderivs[3].Derivative(1.0, m_Gradw[0], 1);
                m_normderivs[4].Derivative(1.0, m_Gradw[1], 1);
                m_normderivs[5].Derivative(1.0, m_Gradw[2], 1);
                m_normderivs[6].Derivative(1.0, m_Gradw[0], 2);
                m_normderivs[7].Derivative(1.0, m_Gradw[1], 2);
                m_normderivs[8].Derivative(1.0, m_Gradw[2], 2);
            }
            else
            {
                m_normderivs = new VectorField <SinglePhaseField>(n1x, n2x, n1y, n2y);

                /* Partial derivatives of the normal vector.
                 * These quantities are used in the product rule applied to the surface projection
                 * and to compute the mean curvature
                 */

                m_normderivs[0].Derivative(1.0, m_Gradw[0], 0);
                m_normderivs[1].Derivative(1.0, m_Gradw[1], 0);
                m_normderivs[2].Derivative(1.0, m_Gradw[0], 1);
                m_normderivs[3].Derivative(1.0, m_Gradw[1], 1);
            }

            /*
             * Divergence of the surface normal vector yields the total curvature
             * which is twice the mean curvature
             * ATTENTION: here with inverse sign!!!!!
             */
            m_Curvature = new SinglePhaseField(m_derivsBasis);
            m_Curvature.Acc(1.0, m_normderivs[0]);
            m_Curvature.Acc(1.0, m_normderivs[4]);
            if (m_Context.Grid.SpatialDimension == 3)
            {
                m_Curvature.Acc(1.0, m_normderivs[8]);
            }

            m_sign = new SinglePhaseField(m_Basis, "sign");
            SinglePhaseField quot = new SinglePhaseField(m_Basis, "quot");
            SinglePhaseField sqrt = new SinglePhaseField(m_Basis, "sqrt");

            sqrt.ProjectProduct(1.0, m_Field, m_Field);
            sqrt.AccConstant(0.01);

            quot.ProjectPow(1.0, sqrt, deltax * deltax);
            m_sign.ProjectQuotient(1.0, m_Field, quot);
        }