コード例 #1
0
        /// <summary>
        /// another legacy interface
        /// </summary>
        static public void ComputeAffine <V>(
            this SpatialOperator op,
            UnsetteledCoordinateMapping DomainMap,
            IList <DGField> Parameters,
            UnsetteledCoordinateMapping CodomainMap,
            V AffineOffset,
            bool OnlyBoundaryEdges      = true, double time = 0.0,
            EdgeQuadratureScheme edgeQr = null, CellQuadratureScheme volQr = null)
            where V : IList <double>
        {
            var GridDat = CodomainMap.GridDat;

            if (Parameters != null)
            {
                foreach (var prm in Parameters)
                {
                    if (!object.ReferenceEquals(prm.GridDat, GridDat))
                    {
                        throw new ArgumentException(string.Format("parameter field {0} is assigned to a different grid.", prm.Identification));
                    }
                }
            }

            //Using order zero for DomainMap will lead to inconsistent (and possibly insufficient) quadrature order!!!
            //UnsetteledCoordinateMapping DomainMap;
            //Basis b = new Basis(GridDat, 0);
            //Basis[] B = new Basis[this.DomainVar.Count];
            //B.SetAll(b);
            //DomainMap = new UnsetteledCoordinateMapping(B);


            if (OnlyBoundaryEdges)
            {
                if (edgeQr != null)
                {
                    throw new ArgumentException("If 'OnlyBoundaryEdges == true', 'edgeQr' must be null!", "edgeQr");
                }
                if (volQr != null)
                {
                    throw new ArgumentException("If 'OnlyBoundaryEdges == true', 'volQr' must be null!", "volQr");
                }

                volQr  = new CellQuadratureScheme(true, CellMask.GetEmptyMask(GridDat));
                edgeQr = new EdgeQuadratureScheme(true, GridDat.GetBoundaryEdgeMask());
            }

            op.ComputeMatrixEx(
                DomainMap, Parameters, CodomainMap,
                default(MsrMatrix), AffineOffset,
                OnlyAffine: true, time: time,
                volQuadScheme: volQr, edgeQuadScheme: edgeQr);
        }
コード例 #2
0
        private MsrMatrix PenaltyMatrix(EdgeMask em, Basis LevSetBasis, Basis JumpBasis)
        {
            var OpA = new SpatialOperator(1, 0, 1, QuadOrderFunc.Linear(), "Phi", "c1");

            OpA.EquationComponents["c1"].Add(new JumpForm());
            //OpA.EquationComponents["c1"].Add(new GradientJumpForm() { ATerm = true, BTerm = true });
            OpA.EquationComponents["c1"].Add(new GradientJumpForm2());
            OpA.Commit();

            //var OpB = new SpatialOperator(1, 0, 1, "Phi", "c1");
            //Op.EquationComponents["c1"].Add(new JumpForm());
            //OpB.EquationComponents["c1"].Add(new GradientJumpForm() { BTerm = true });
            //Op.EquationComponents["c1"].Add(new GradientJumpForm2());
            //OpB.Commit();

            var inp_LevSet_Mapping  = new UnsetteledCoordinateMapping(LevSetBasis);
            var outp_Result_Mapping = new UnsetteledCoordinateMapping(JumpBasis);

            MsrMatrix MatrixA;

            MatrixA = new MsrMatrix(outp_Result_Mapping, inp_LevSet_Mapping);
            double[] AffineA = new double[inp_LevSet_Mapping.LocalLength];
            OpA.ComputeMatrixEx(inp_LevSet_Mapping, null, outp_Result_Mapping,
                                MatrixA, AffineA, OnlyAffine: false,
                                edgeQuadScheme: new EdgeQuadratureScheme(true, em),
                                volQuadScheme: new CellQuadratureScheme(true, CellMask.GetEmptyMask(em.GridData)));
            MatrixA.CheckForNanOrInfM();

            //MsrMatrix MatrixB;
            //MatrixB = new MsrMatrix(outp_Result_Mapping, inp_LevSet_Mapping);
            //double[] AffineB = new double[inp_LevSet_Mapping.LocalLength];
            //OpB.ComputeMatrixEx(inp_LevSet_Mapping, null, outp_Result_Mapping,
            //    MatrixB, AffineB, OnlyAffine: false
            //    );//,
            //    //edgeQrCtx: new EdgeQuadratureScheme(true, em),
            //    //volQrCtx: new CellQuadratureScheme(true, CellMask.GetEmptyMask(em.GridData)));

            //Debug.Assert(AffineB.L2Norm() == 0);

            //var Err = MatrixA.Transpose();
            //Err.Acc(-1.0, MatrixB);

            //double errnorm = Err.InfNorm();
            //Debug.Assert(errnorm < 1.0e-10);
            ////Console.WriteLine("Errnorm:" + errnorm);


            return(MatrixA);
        }
コード例 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="jCell"></param>
        /// <param name="AcceptedMask"></param>
        /// <param name="Phi"></param>
        /// <param name="gradPhi"></param>
        /// <param name="__DiffusionCoeff">Output: if artificial diffusion is turned</param>
        /// <param name="MaxAllowedPhi">Input: upper threshold for the values of <paramref name="Phi"/> in cell <see cref="jCell"/>.</param>
        /// <param name="MinAllowedPhi">Input: lower threshold for the values of <paramref name="Phi"/> in cell <see cref="jCell"/>.</param>
        /// <returns></returns>
        public bool LocalSolve_Iterative(int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi, SinglePhaseField __DiffusionCoeff, double MaxAllowedPhi, double MinAllowedPhi)
        {
            //this.LocalSolve_Geometric(jCell, AcceptedMask, Phi, +1, out MinAllowedPhi, out MaxAllowedPhi);) {
            int N   = this.LevelSetBasis.GetLength(jCell);
            int i0G = this.LevelSetMapping.GlobalUniqueCoordinateIndex(0, jCell, 0);
            int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0);

            SinglePhaseField __AcceptedMask = new SinglePhaseField(new Basis(this.GridDat, 0), "accepted");

            for (int j = 0; j < AcceptedMask.Length; j++)
            {
                __AcceptedMask.SetMeanValue(j, AcceptedMask[j] ? 1.0 : 0.0);
            }


            // subgrid on which we are working, consisting only of one cell
            SubGrid jCellGrid = new SubGrid(new CellMask(this.GridDat, Chunk.GetSingleElementChunk(jCell)));

            // create spatial operator
            IEvaluatorNonLin evo;
            {
                SpatialOperator op = new SpatialOperator(1, 2, 1, QuadOrderFunc.NonLinear(2), "Phi", "dPhi_dx0", "dPhi_dx1", "cod1");
                op.EquationComponents["cod1"].Add(new ReinitOperator());
                op.EdgeQuadraturSchemeProvider   = g => (new EdgeQuadratureScheme(domain: EdgeMask.GetEmptyMask(g)));
                op.VolumeQuadraturSchemeProvider = g => (new CellQuadratureScheme(domain: jCellGrid.VolumeMask));
                op.Commit();

                evo = op.GetEvaluatorEx(Phi.Mapping.Fields, gradPhi.Mapping.Fields, Phi.Mapping);
                evo.ActivateSubgridBoundary(jCellGrid.VolumeMask, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdge);
            }

            // create artificial diffusion operator
            MultidimensionalArray DiffMtx;

            double[]        DiffRhs;
            SpatialOperator dop;
            {
                double penaltyBase = this.LevelSetBasis.Degree + 2;
                penaltyBase = penaltyBase.Pow2();

                dop = (new ArtificialViscosity(AcceptedMask, penaltyBase, GridDat.Cells.h_min, jCell, -1.0)).Operator(1);

                MsrMatrix _DiffMtx = new MsrMatrix(this.LevelSetMapping, this.LevelSetMapping);
                double[]  _DiffRhs = new double[this.LevelSetMapping.LocalLength];

                dop.ComputeMatrixEx(this.LevelSetMapping, new DGField[] { Phi, null, null }, this.LevelSetMapping,
                                    _DiffMtx, _DiffRhs, OnlyAffine: false,
                                    edgeQuadScheme: (new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask)),
                                    volQuadScheme: (new CellQuadratureScheme(domain: jCellGrid.VolumeMask)));

                // extract matrix for 'jCell'
                DiffMtx = MultidimensionalArray.Create(N, N);
                DiffRhs = new double[N];
                for (int n = 0; n < N; n++)
                {
#if DEBUG
                    int      Lr;
                    int[]    row_cols = null;
                    double[] row_vals = null;
                    Lr = _DiffMtx.GetRow(i0G + n, ref row_cols, ref row_vals);
                    for (int lr = 0; lr < Lr; lr++)
                    {
                        int    ColIndex = row_cols[lr];
                        double Value    = row_vals[lr];
                        Debug.Assert((ColIndex >= i0G && ColIndex < i0G + N) || (Value == 0.0), "Matrix is expected to be block-diagonal.");
                    }
#endif
                    for (int m = 0; m < N; m++)
                    {
                        DiffMtx[n, m] = _DiffMtx[i0G + n, i0G + m];
                    }
                    DiffRhs[n] = _DiffRhs[i0L + n];
                }

#if DEBUG
                var Test = DiffMtx.Transpose();
                Test.Acc(-1.0, DiffMtx);
                Debug.Assert(Test.InfNorm() <= 1.0e-8);
#endif
            }

            // find 'good' initial value by geometric solve AND
            // thresholds for the maximum an minimal value of Phi
            double Range = MaxAllowedPhi - MinAllowedPhi;
            MinAllowedPhi -= 0.1 * Range;
            MaxAllowedPhi += 0.1 * Range;


            // timestep for pseudo-timestepping
            double dt = 0.5 * this.GridDat.Cells.h_min[jCell] / (((double)(this.LevelSetBasis.Degree)).Pow2());


            DGField[] PlotFields = new DGField[] { Phi, gradPhi[0], gradPhi[1], __DiffusionCoeff, __AcceptedMask };
            //Tecplot.Tecplot.PlotFields(Params, "itt_0", "EllipicReinit", 0, 3);

            double[] PrevVal = new double[N];
            double[] NextVal = new double[N];
            Phi.Coordinates.GetRow(jCell, PrevVal);

            // pseudo-timestepping
            //if(jCell == 80)
            //    Tecplot.Tecplot.PlotFields(PlotFields, "itt_0", "EllipicReinit", 0, 3);
            //Console.Write("  Local solve cell " + jCell + " ... ");

            bool   converged      = false;
            double DiffusionCoeff = 0;
            int    IterGrowCount  = 0; // number of iterations in which the residual grew
            double LastResi       = double.NaN;
            for (int iIter = 0; iIter < 1000; iIter++)
            {
                //Console.Write("  Local solve iteration " + iIter + " ... ");
                PerformRKstep(dt, jCell, AcceptedMask, Phi, gradPhi, evo);

                __DiffusionCoeff.SetMeanValue(jCell, DiffusionCoeff);

                if (jCell == 80)
                {
                    DiffusionCoeff = 0.1;
                }
                if (DiffusionCoeff > 0)
                {
                    //Console.WriteLine(" Diffusion on.");


                    double[] _DiffRhs = new double[this.LevelSetMapping.LocalLength];


                    dop.ComputeMatrixEx(this.LevelSetMapping, new DGField[] { Phi, gradPhi[0], gradPhi[1] }, this.LevelSetMapping,
                                        default(MsrMatrix), _DiffRhs, OnlyAffine: true,
                                        edgeQuadScheme: (new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask)),
                                        volQuadScheme: (new CellQuadratureScheme(domain: CellMask.GetEmptyMask(this.GridDat))));

                    // extract matrix for 'jCell'
                    for (int n = 0; n < N; n++)
                    {
                        DiffRhs[n] = _DiffRhs[i0L + n];
                    }

                    PerformArtificialDiffusion(dt * DiffusionCoeff, jCell, Phi, DiffMtx, DiffRhs);
                }
                Phi.Coordinates.GetRow(jCell, NextVal);
                double   resi = Math.Sqrt(GenericBlas.L2DistPow2(NextVal, PrevVal) / GenericBlas.L2NormPow2(PrevVal));
                double[] A    = NextVal;
                NextVal = PrevVal;
                PrevVal = A;
                if (iIter > 0 && resi > LastResi)
                {
                    IterGrowCount++;
                }
                else
                {
                    IterGrowCount = 0;
                }
                LastResi = resi;


                if (resi < 1.0e-10)
                {
                    converged = true;
                    break;
                }

                double maxPhi, minPhi;
                Phi.GetExtremalValuesInCell(out minPhi, out maxPhi, jCell);

                bool MinAlarm  = minPhi < MinAllowedPhi;
                bool Maxalarm  = maxPhi > MaxAllowedPhi;
                bool GrowAlarm = IterGrowCount > 4;
                bool IterAlarm = iIter >= 50;

                if (MinAlarm || Maxalarm || GrowAlarm)
                {
                    // Diffusion coefficient should be increased
                    if (DiffusionCoeff == 0)
                    {
                        DiffusionCoeff = 1.0e-2;
                    }
                    else
                    {
                        if (DiffusionCoeff < 1.0e3)
                        {
                            DiffusionCoeff *= 2;
                        }
                    }
                    //Console.WriteLine("   increasing Diffusion: {0}, Alarms : {1}{2}{3}{4}", DiffusionCoeff, MinAlarm ? 1 : 0, Maxalarm ? 1 : 0, GrowAlarm ? 1 : 0, IterAlarm ? 1 : 0);
                }


                //if(jCell == 80 && iIter < 100)
                //    Tecplot.Tecplot.PlotFields(PlotFields, "itt_" + (iIter + 1), "EllipicReinit", iIter + 1, 3);
            }


            return(converged);
        }
コード例 #4
0
        /// <summary>
        /// Various condition numbers, organized in a dictionary to create a regression over multiple meshes
        /// </summary>
        public IDictionary <string, double> GetNamedProperties()
        {
            using (new FuncTrace()) {
                var Ret = new Dictionary <string, double>();

                var grd = m_map.GridDat;

                // global condition numbers
                // ========================
                //double CondNo = this.CondNumMUMPS();
                double CondNo = this.CondNumMatlab(); // matlab seems to be more reliable
                Ret.Add("TotCondNo-" + VarNames, CondNo);

                // block-wise condition numbers
                // ============================
                double[] bcn = this.StencilCondNumbers();

                CellMask innerUncut, innerCut, bndyUncut, bndyCut;
                if (m_LsTrk != null)
                {
                    // +++++++++
                    // using XDG
                    // +++++++++
                    innerUncut = grd.GetBoundaryCells().Complement().Except(m_LsTrk.Regions.GetCutCellMask());
                    innerCut   = m_LsTrk.Regions.GetCutCellMask().Except(grd.GetBoundaryCells());

                    bndyUncut = grd.GetBoundaryCells().Except(m_LsTrk.Regions.GetCutCellMask());
                    bndyCut   = grd.GetBoundaryCells().Intersect(m_LsTrk.Regions.GetCutCellMask());
                }
                else
                {
                    // ++++++++
                    // using DG
                    // ++++++++
                    innerUncut = grd.GetBoundaryCells().Complement();
                    innerCut   = CellMask.GetEmptyMask(grd);

                    bndyUncut = grd.GetBoundaryCells();
                    bndyCut   = CellMask.GetEmptyMask(grd);
                }
                double innerUncut_MaxCondNo = innerUncut.NoOfItemsLocally > 0 ? innerUncut.ItemEnum.Max(jCell => bcn[jCell]) : 1.0;
                double innerCut_MaxCondNo   = innerCut.NoOfItemsLocally > 0 ? innerCut.ItemEnum.Max(jCell => bcn[jCell]) : 1.0;
                double bndyUncut_MaxCondNo  = bndyUncut.NoOfItemsLocally > 0 ? bndyUncut.ItemEnum.Max(jCell => bcn[jCell]) : 1.0;
                double bndyCut_MaxCondNo    = bndyCut.NoOfItemsLocally > 0 ? bndyCut.ItemEnum.Max(jCell => bcn[jCell]) : 1.0;

                innerUncut_MaxCondNo = innerUncut_MaxCondNo.MPIMax();
                innerCut_MaxCondNo   = innerCut_MaxCondNo.MPIMax();
                bndyUncut_MaxCondNo  = bndyUncut_MaxCondNo.MPIMax();
                bndyCut_MaxCondNo    = bndyCut_MaxCondNo.MPIMax();

                Ret.Add("StencilCondNo-innerUncut-" + VarNames, innerUncut_MaxCondNo);
                Ret.Add("StencilCondNo-bndyUncut-" + VarNames, bndyUncut_MaxCondNo);

                if (m_LsTrk != null)
                {
                    Ret.Add("StencilCondNo-innerCut-" + VarNames, innerCut_MaxCondNo);
                    Ret.Add("StencilCondNo-bndyCut-" + VarNames, bndyCut_MaxCondNo);
                }
                return(Ret);
            }
        }