Esempio n. 1
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, SubGridBoundaryModes bndMode = 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);

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

            SpatialOperator d_dx = new SpatialOperator(1, 1, QuadOrderFunc.Linear(), "in", "out");

            d_dx.EdgeQuadraturSchemeProvider   = g => new Quadrature.EdgeQuadratureScheme(true, emEdge);
            d_dx.VolumeQuadraturSchemeProvider = g => new Quadrature.CellQuadratureScheme(true, emVol);
            var flux = CreateDerivativeFlux(d, f.Identification);

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


            var ev = d_dx.GetEvaluatorEx(
                new CoordinateMapping(f), null, this.Mapping);

            if (optionalSubGrid != null)
            {
                ev.ActivateSubgridBoundary(optionalSubGrid.VolumeMask, bndMode);
            }

            ev.Evaluate <CoordinateVector>(alpha, 1.0, this.CoordinateVector);
        }
        /// <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());

            //QuadOrderFunc.NonLinear(2));
            fracOp.EdgeQuadraturSchemeProvider   = g => new EdgeQuadratureScheme(true, EdgeMask.GetEmptyMask(g));
            fracOp.VolumeQuadraturSchemeProvider = g => new CellQuadratureScheme(true, cm);
            fracOp.EquationComponents["res"].Add(new QuotientSource());
            fracOp.Commit();

            CoordinateVector coDom = this.CoordinateVector;

            var ev = fracOp.GetEvaluatorEx(
                new CoordinateMapping(a, b), null, coDom.Mapping);

            ev.Evaluate <CoordinateVector>(alpha, 1.0, coDom);
        }