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