/// <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
        }
Example #2
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);
            }
        }
Example #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);
        }
        /// <summary>
        /// <see cref="ResidualLogger"/>
        /// </summary>
        /// <param name="program"></param>
        /// <param name="residualInterval">
        /// <see cref="ResidualLogger"/>
        /// </param>
        /// <param name="differentialOperator">
        /// The spatial differential operator defining (the spatial part of)
        /// the system of equations that are solved.
        /// </param>
        public RigorousResidualLogger(Program <T> program, int residualInterval, SpatialOperator differentialOperator)
            : base(program.ResLogger, program.CurrentSessionInfo, program.WorkingSet, residualInterval)
        {
            DGField[]                   primalFields    = program.WorkingSet.ConservativeVariables;
            CoordinateMapping           domainMapping   = new CoordinateMapping(primalFields);
            UnsetteledCoordinateMapping codomainMapping = new UnsetteledCoordinateMapping(
                primalFields.Select((field) => field.Basis).ToArray());

            evaluator = differentialOperator.GetEvaluatorEx(
                domainMapping,
                program.ParameterMapping,
                codomainMapping);
        }
        /// <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);
        }
        /// <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);
        }
        /// <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
        }
Example #8
0
        void PerformRKstep(double dt, int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi, SpatialOperator.Evaluator Evaluator)
        {
            int N   = this.LevelSetBasis.GetLength(jCell);
            int i0G = this.LevelSetMapping.GlobalUniqueCoordinateIndex(0, jCell, 0);
            int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0);

            double[][] k = new double[RKsch.Stages][];
            for (int i = 0; i < RKsch.Stages; i++)
            {
                k[i] = new double[N];
            }

            double[] y0 = Phi.Coordinates.GetRow(jCell);
            Debug.Assert(y0.Length == N);

            ComputeChangeRate(k[0], jCell, AcceptedMask, Phi, gradPhi, Evaluator);

            for (int s = 1; s < RKsch.Stages; s++)
            {
                Phi.Coordinates.SetRow(jCell, y0);
                for (int r = 0; r < s; r++)
                {
                    if (RKsch.a[s, r] != 0.0)
                    {
                        Phi.Coordinates.AccRow(jCell, -dt * RKsch.a[s, r], k[r]);
                    }
                }

                ComputeChangeRate(k[s], jCell, AcceptedMask, Phi, gradPhi, Evaluator);
            }

            // next timestep
            for (int s = 0; s < RKsch.Stages; s++)
            {
                if (RKsch.b[s] != 0.0)
                {
                    y0.AccV(-RKsch.b[s] * dt, k[s]);
                }
            }
            Phi.Coordinates.SetRow(jCell, y0);
        }
Example #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];
            }
        }