Esempio n. 1
0
        /// <summary>
        /// Auto-tuning
        /// </summary>
        public void PerformanceVsCachesize()
        {
            double[] dummy = new double[this.u.CoordinateVector.Count];

            SpatialOperator.Evaluator eval = diffOp.GetEvaluatorEx(new DGField[] { this.u }, this.Velocity.ToArray(), this.u.Mapping,
                                                                   edgeQrCtx: new EdgeQuadratureScheme(false, EdgeMask.GetEmptyMask(this.GridData)),
                                                                   volQrCtx: new CellQuadratureScheme(true, null));

            Stopwatch stw      = new Stopwatch();
            int       NoOfRuns = 10;

            Console.WriteLine("BlkSz\tNoChks\tRunTime");
            foreach (int bulkSize in new int[] { 1, 2, 4, 8, 16, 32, 64, 256, 512, 1024, 2048, 8192, 16384, 16384 * 2, 16384 * 4 })
            {
                Quadrature_Bulksize.CHUNK_DATA_LIMIT = bulkSize;

                stw.Reset();
                stw.Start();
                for (int i = 0; i < NoOfRuns; i++)
                {
                    eval.Evaluate(1.0, 0.0, dummy);
                }
                stw.Stop();

                double runTime = stw.Elapsed.TotalSeconds;
                Console.WriteLine("{0}\t{2}\t{1}", bulkSize, runTime.ToStringDot("0.####E-00"), this.GridData.Cells.NoOfLocalUpdatedCells / bulkSize);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// accumulates the projection of some vector field to this field, i.e.
        /// \f[
        ///   this = this + \alpha \cdot \| \vec{vec} \|.
        /// \f]
        /// </summary>
        /// <param name="alpha">factor \f$ \alpha \f$ </param>
        /// <param name="vec">vector field \f$ \vec{vec} \f$ </param>
        /// <param name="em">
        /// An optional restriction to the domain in which the projection is computed (it may, e.g.
        /// be only required in boundary cells, so a computation over the whole domain
        /// would be a waste of computation power. If null, the computation is carried out in the whole domain;
        /// </param>
        virtual public void ProjectAbs(double alpha, CellMask em, params DGField[] vec)
        {
            int K = vec.Length;

            string[] args = new string[K];
            for (int k = 0; k < K; k++)
            {
                args[k] = "_" + k;
            }

            SpatialOperator powOp = new SpatialOperator(args, new string[] { "res" }, QuadOrderFunc.SumOfMaxDegrees());

            powOp.EquationComponents["res"].Add(new AbsSource(args));
            powOp.Commit();

            CoordinateVector coDom = new CoordinateVector(this);

            SpatialOperator.Evaluator ev = powOp.GetEvaluatorEx(
                new CoordinateMapping(vec),
                null,
                coDom.Mapping,
                edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)),
                volQrCtx: new CellQuadratureScheme(true, em));

            ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom); // only sources, no edge integrals required
        }
Esempio n. 3
0
        /// <summary>
        /// accumulates the derivative of DG field <paramref name="f"/>
        /// (along the <paramref name="d"/>-th axis) times <paramref name="alpha"/>
        /// to this field, i.e. <br/>
        /// this = this + <paramref name="alpha"/>* \f$ \frac{\partial}{\partial x_d} \f$ <paramref name="f"/>;
        /// </summary>
        /// <param name="f"></param>
        /// <param name="d">
        /// 0 for the x-derivative, 1 for the y-derivative, 2 for the
        /// z-derivative
        /// </param>
        /// <param name="alpha">
        /// scaling of <paramref name="f"/>;
        /// </param>
        /// <param name="optionalSubGrid">
        /// An optional restriction to the domain in which the derivative is
        /// computed (it may, e.g. be only required in boundary cells, so a
        /// computation over the whole domain would be a waste of computational
        /// power. A proper execution mask would be see e.g.
        /// <see cref="GridData.BoundaryCells"/>.)
        /// <br/>
        /// if null, the computation is carried out in the whole domain.
        /// </param>
        /// <param name="bndMode">
        /// if a sub-grid is provided, this determines how the sub-grid
        /// boundary should be treated.
        /// </param>
        /// <remarks>
        /// The derivative is calculated using Riemann flux functions
        /// (central difference);<br/>
        /// In comparison to
        /// <see cref="Derivative(double, DGField, int, CellMask)"/>, this method
        /// should be slower, but produce more sane results, especially for
        /// fields of low polynomial degree (0 or 1);
        /// </remarks>
        virtual public void DerivativeByFlux(double alpha, DGField f, int d, SubGrid optionalSubGrid = null, SpatialOperator.SubGridBoundaryModes bndMode = SpatialOperator.SubGridBoundaryModes.OpenBoundary)
        {
            int D = this.Basis.GridDat.SpatialDimension;

            if (d < 0 || d >= D)
            {
                throw new ArgumentException("spatial dimension out of range.", "d");
            }
            MPICollectiveWatchDog.Watch(csMPI.Raw._COMM.WORLD);

            SpatialOperator d_dx = new SpatialOperator(1, 1, QuadOrderFunc.Linear(), "in", "out");
            var             flux = CreateDerivativeFlux(d, f.Identification);

            d_dx.EquationComponents["out"].Add(flux);
            d_dx.Commit();

            EdgeMask emEdge = (optionalSubGrid != null) ? optionalSubGrid.AllEdgesMask : null;
            CellMask emVol  = (optionalSubGrid != null) ? optionalSubGrid.VolumeMask : null;

            SpatialOperator.Evaluator ev = d_dx.GetEvaluatorEx(
                new CoordinateMapping(f), null, this.Mapping,
                edgeQrCtx: new Quadrature.EdgeQuadratureScheme(true, emEdge),
                volQrCtx: new Quadrature.CellQuadratureScheme(true, emVol),
                sgrd: optionalSubGrid, subGridBoundaryTreatment: bndMode);

            ev.Evaluate <CoordinateVector>(alpha, 1.0, this.CoordinateVector);
        }
Esempio n. 4
0
        /// <summary>
        /// computes the change rate for the time evolution problem;
        /// </summary>
        /// <param name="k">
        /// the "change rate" is <b>accumulated</b> here;<br/>
        /// Indices into this array can be computed by <see cref="Mapping"/>;
        /// </param>
        /// <param name="AbsTime">
        /// absolute time at which the change rate will be evaluated
        /// </param>
        /// <param name="RelTime">
        /// time, relative to the point of time at which the initial value holds.
        /// </param>
        /// <remarks>
        /// Assume an ODE
        /// <br/>
        /// d/dt u = f(u)
        /// <br/>
        /// which is discretized by an explicit Euler scheme
        /// <br/>
        /// (u_1 - u_0)/delta_t = f(u_0).
        /// <br/>
        /// Here, f(u) denotes the discretization of the spatial operator by the DG method.
        /// The purpose of this method is to evaluate f(u_0).<br/>
        /// It does so by calling <see cref="SpatialOperator.Evaluator.Evaluate{Tout}"/>
        /// of <see cref="Evaluator"/>.<br/>
        /// Override this method e.g. for the implementation of (some types of) limiters.
        /// </remarks>
        virtual internal protected void ComputeChangeRate(double[] k, double AbsTime, double RelTime, double[] edgeFluxes = null)
        {
            using (var tr = new ilPSP.Tracing.FuncTrace()) {
                RaiseOnBeforeComputechangeRate(AbsTime, RelTime);

                // k += F(u0)
                Evaluator.Evaluate <double[]>(1.0, 1.0, k, AbsTime, outputBndEdge: edgeFluxes);
            }
        }
        /// <summary>
        /// For a system
        /// \f$
        /// \frac{\partial U}{dt} + F(U) = 0,
        /// \f$
        /// evaluates
        /// \f$
        /// || \frac{U_1 - U_0}{\Delta t} + F(U_1) ||
        /// \f$
        /// in the associated relative residuals in L2 and the Linf norm.
        /// </summary>
        /// <param name="timeStepNumber"></param>
        /// <param name="dt"></param>
        /// <param name="phystime">not used</param>
        public override IDictionary <string, double> LogTimeStep(int timeStepNumber, double dt, double phystime)
        {
            Dictionary <string, double> result = new Dictionary <string, double>();

            if (residualInterval < 1)
            {
                return(result);
            }

            if (this.ShouldLog(timeStepNumber, residualInterval))
            {
                double beta;
                if (dt == 0.0)
                {
                    // r = F(u1)
                    beta = 0.0;
                    PreviousState.Clear();
                }
                else
                {
                    // r = (u1-u0)/dt + F(u1)
                    beta = -1.0 / dt;
                    for (int i = 0; i < CurrentState.Dim; i++)
                    {
                        PreviousState[i].Acc(-1.0, CurrentState[i]);
                    }
                }

                CoordinateVector resultVector = new CoordinateVector(
                    new CoordinateMapping(PreviousState.ToArray()));
                evaluator.Evaluate(1.0, beta, resultVector);

                for (int i = 0; i < CurrentState.Dim; i++)
                {
                    double abs = PreviousState[i].L2Norm();
                    double rel = abs / CurrentState[i].L2Norm();

                    result.Add("rigorous_L2_abs_" + CurrentState[i].Identification, abs);

                    baseLogger.CustomValue(abs, "residual_abs_" + CurrentState[i].Identification);
                    baseLogger.CustomValue(rel, "residual_rel_" + CurrentState[i].Identification);
                }
            }

            // If residuals will be calculated in next time-step
            if ((timeStepNumber + 1) % residualInterval == 0 &&
                dt != 0.0)
            {
                PreviousState = CurrentState.CloneAs();
            }

            return(result);
        }
Esempio n. 6
0
        /// <summary>
        /// Calculates the DG-projection (with respect to the DG-basis
        /// of this field, <see cref="Basis"/>) of
        /// <paramref name="alpha"/>*<paramref name="a"/>/<paramref name="b"/>
        /// and, depending on the value of <paramref name="accumulateResult"/>,
        /// either adds or assigns it to this field.
        /// </summary>
        /// <param name="a">1st multiplicand</param>
        /// <param name="b">2nd multiplicand</param>
        /// <param name="alpha">scaling for <paramref name="a"/>*<paramref name="b"/></param>
        /// <param name="accumulateResult">
        /// Tells this method whether to accumulate (true) or not (false)
        /// </param>
        /// <param name="cm">
        /// optional restriction to computational domain
        /// </param>
        virtual public void ProjectQuotient(
            double alpha, DGField a, DGField b, CellMask cm, bool accumulateResult)
        {
            if (!object.ReferenceEquals(a.Basis.GridDat, this.Basis.GridDat))
            {
                throw new ArgumentException("field is associated to another grid.", "a");
            }
            if (!object.ReferenceEquals(b.Basis.GridDat, this.Basis.GridDat))
            {
                throw new ArgumentException("field is associated to another grid.", "b");
            }

            if (!accumulateResult)
            {
                if (a == this)
                {
                    a = (DGField)a.Clone();

                    if (b == this)
                    {
                        b = a;
                    }
                }
                else if (b == this)
                {
                    b = (DGField)b.Clone();
                }

                this.Clear();
            }

            SpatialOperator fracOp = new SpatialOperator(new string[] { "a", "b" },
                                                         new string[] { "res" },
                                                         QuadOrderFunc.Linear());

            fracOp.EquationComponents["res"].Add(new QuotientSource());
            fracOp.Commit();

            CoordinateVector coDom = this.CoordinateVector;

            SpatialOperator.Evaluator ev = fracOp.GetEvaluatorEx(
                new CoordinateMapping(a, b), null, coDom.Mapping,
                edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)),
                volQrCtx: new CellQuadratureScheme(true, cm));

            ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom);
        }
Esempio n. 7
0
        /// <summary>
        /// assembles the right-hand-side (DG coordinates of <paramref name="rhsIn"/> minus the affine offset <see cref="m_AffineOffset"/>
        /// of the operator, which usually carries the boundary conditions)
        /// </summary>
        /// <param name="rhsIn">input</param>
        /// <param name="TotalRhs">output</param>
        void GetTotalRHS(IList <double> rhsIn, out double[] TotalRhs)
        {
            int n = m_Mapping.LocalLength;

            // check
            if (rhsIn != null)
            {
                if (rhsIn.Count < m_Mapping.LocalLength)
                {
                    throw new ArgumentOutOfRangeException("right hand side vector to short.");
                }
            }

            // clone or allocate memory
            if (rhsIn == null)
            {
                TotalRhs = new double[m_AffineOffset.Length];
            }
            else
            {
                TotalRhs = rhsIn as double[];
                if (TotalRhs == null)
                {
                    TotalRhs = rhsIn.ToArray();
                }
            }
            rhsIn = null;
            //Console.WriteLine("Affine offset norm = " + BLAS.dnrm2(m_AffineOffset.Length,m_AffineOffset,1));

            // call evaluator
            if (m_rhsEvaluator != null)
            {
                m_rhsEvaluator.Evaluate <double[]>(1.0, 1.0, TotalRhs);
            }

            // notify
            if (RHSEvaluated != null)
            {
                RHSEvaluated(TotalRhs);
            }


            // substract affine part
            BLAS.daxpy(n, -1.0, m_AffineOffset, 1, TotalRhs, 1);
        }
Esempio n. 8
0
        /// <summary>
        /// accumulates
        /// <paramref name="alpha"/>*<paramref name="f"/>(<paramref name="U"/>)
        /// to this field;
        /// </summary>
        /// <param name="alpha">scaling</param>
        /// <param name="f">some function</param>
        /// <param name="cqs">
        /// cell quadrature scheme: domain and quadrature rule
        /// </param>
        /// <param name="U">
        /// arguments for <paramref name="f"/>
        /// </param>
        public void ProjectFunction(double alpha, Func f, CellQuadratureScheme cqs, params DGField[] U)
        {
            string[] Dom = new string[U.Length];
            for (int i = 0; i < Dom.Length; i++)
            {
                Dom[i] = "_" + i;
            }

            string[] Cod = new string[] { "res" };

            SpatialOperator src = new SpatialOperator(Dom, Cod, QuadOrderFunc.NonLinear(3));

            src.EquationComponents[Cod[0]].Add(new ProjectFunctionSource(Dom, f));
            src.Commit();

            SpatialOperator.Evaluator ev = src.GetEvaluatorEx(
                new CoordinateMapping(U), null, this.Mapping,
                edgeQrCtx: new EdgeQuadratureScheme(false, EdgeMask.GetEmptyMask(this.Basis.GridDat)),
                volQrCtx: cqs);

            ev.Evaluate(alpha, 1.0, this.CoordinateVector);
        }
Esempio n. 9
0
        void ComputeChangeRate(double[] k, int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi, SpatialOperator.Evaluator Evaluator)
        {
            int N   = this.LevelSetBasis.GetLength(jCell);
            int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0);

            Debug.Assert(k.Length == N);

            if (temp == null)
            {
                temp = new double[this.LevelSetMapping.LocalLength];
            }

            gm.GradientUpdate(jCell, AcceptedMask, Phi, gradPhi);

            for (int n = 0; n < N; n++)
            {
                temp[n + i0L] = 0;
            }
#if DEBUG
            double[] oldtemp = temp.CloneAs();
#endif

            Evaluator.Evaluate <double[]>(1.0, 1.0, temp, 0.0, MPIexchange: false);

#if DEBUG
            for (int i = 0; i < oldtemp.Length; i++)
            {
                if (i < i0L && i >= (i0L + N))
                {
                    Debug.Assert(oldtemp[i] == temp[i]); // check that the locality of the operator is implemented correctly
                }
            }
#endif

            for (int n = 0; n < N; n++)
            {
                k[n] = temp[n + i0L];
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Accumulates the DG-projection (with respect to the DG-basis
        /// of this field, <see cref="Basis"/>) of
        /// <paramref name="alpha"/>*<paramref name="f"/>^<paramref name="pow"/> to this field;
        /// </summary>
        /// <param name="alpha">scaling for accumulation</param>
        /// <param name="f">operand</param>
        /// <param name="pow">exponent</param>
        /// <param name="em">
        /// An optional restriction to the domain in which the projection is
        /// computed (it may, e.g. be only required in boundary cells, so a
        /// computation over the whole domain would be a waste of computation
        /// power. A proper execution mask would be see e.g.
        /// <see cref="GridData.BoundaryCells"/>.)
        /// if null, the computation is carried out in the whole domain;
        /// </param>
        virtual public void ProjectPow(double alpha, DGField f, double pow, CellMask em)
        {
            if (!object.ReferenceEquals(f.Basis.GridDat, this.Basis.GridDat))
            {
                throw new ArgumentException("field is associated to another context.", "a");
            }

            SpatialOperator powOp = new SpatialOperator(new string[] { "f" },
                                                        new string[] { "res" },
                                                        QuadOrderFunc.SumOfMaxDegrees());

            powOp.EquationComponents["res"].Add(new PowSource(pow));
            powOp.Commit();

            CoordinateVector coDom = this.CoordinateVector;

            SpatialOperator.Evaluator ev = powOp.GetEvaluatorEx(
                new CoordinateMapping(f), null, coDom.Mapping,
                edgeQrCtx: new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(this.Basis.GridDat)),
                volQrCtx: new CellQuadratureScheme(true, em));

            ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom); // only sources, no edge integrals required
        }