/// <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); }