/// <summary> /// Updating the <see cref="CurrentLin"/> -- operator; /// </summary> /// <param name="CurrentState">linearization point</param> protected void UpdateLinearization(IEnumerable <DGField> CurrentState) { if (!(this.ProblemMapping.BasisS.Count == CurrentState.Count())) { throw new ArgumentException("mismatch in number of fields."); } BlockMsrMatrix OpMtxRaw, MassMtxRaw; double[] OpAffineRaw; this.m_AssembleMatrix(out OpMtxRaw, out OpAffineRaw, out MassMtxRaw, CurrentState.ToArray(), true); CurrentLin = new MultigridOperator(this.m_AggBasisSeq, this.ProblemMapping, OpMtxRaw.CloneAs(), MassMtxRaw, this.m_MultigridOperatorConfig); OpAffineRaw = OpAffineRaw.CloneAs(); if (this.RHSRaw != null) { OpAffineRaw.AccV(-1.0, this.RHSRaw); } if (LinearizationRHS == null || LinearizationRHS.Length != this.CurrentLin.Mapping.LocalLength) { LinearizationRHS = new double[this.CurrentLin.Mapping.LocalLength]; } else { LinearizationRHS.ClearEntries(); } CurrentLin.TransformRhsInto(OpAffineRaw, this.LinearizationRHS); this.LinearizationRHS.ScaleV(-1.0); }
/// <summary> /// Updating the <see cref="CurrentLin"/> -- operator; /// </summary> /// <param name="CurrentState">linearization point</param> /// <param name="HomotopyValue"> /// <see cref="ISpatialOperator.CurrentHomotopyValue"/> /// </param> protected void UpdateLinearization(IEnumerable <DGField> CurrentState, double HomotopyValue) { if (!(this.ProblemMapping.BasisS.Count == CurrentState.Count())) { throw new ArgumentException("mismatch in number of fields."); } SetHomotopyValue(HomotopyValue); // the real call: this.m_AssembleMatrix(out BlockMsrMatrix OpMtxRaw, out double[] OpAffineRaw, out BlockMsrMatrix MassMtxRaw, CurrentState.ToArray(), true, out ISpatialOperator abstractOperator); AbstractOperator = abstractOperator; // blabla: CurrentLin = new MultigridOperator(this.m_AggBasisSeq, this.ProblemMapping, OpMtxRaw.CloneAs(), MassMtxRaw, this.m_MultigridOperatorConfig, AbstractOperator.DomainVar.Select(varName => AbstractOperator.FreeMeanValue[varName]).ToArray()); OpAffineRaw = OpAffineRaw.CloneAs(); if (this.RHSRaw != null) { OpAffineRaw.AccV(-1.0, this.RHSRaw); } if (LinearizationRHS == null || LinearizationRHS.Length != this.CurrentLin.Mapping.LocalLength) { LinearizationRHS = new double[this.CurrentLin.Mapping.LocalLength]; } else { LinearizationRHS.ClearEntries(); } CurrentLin.TransformRhsInto(OpAffineRaw, this.LinearizationRHS, true); this.LinearizationRHS.ScaleV(-1.0); }
/// <summary> /// Evaluation of the nonlinear operator. /// </summary> /// <param name="alpha"></param> /// <param name="CurrentState"> /// Current state of DG fields /// </param> /// <param name="beta"> /// Pre-scaling of <paramref name="Output"/>. /// </param> /// <param name="Output"></param> protected void EvaluateOperator(double alpha, IEnumerable <DGField> CurrentState, double[] Output) { BlockMsrMatrix OpMtxRaw, MassMtxRaw; double[] OpAffineRaw; this.m_AssembleMatrix(out OpMtxRaw, out OpAffineRaw, out MassMtxRaw, CurrentState.ToArray(), false); Debug.Assert(OpMtxRaw == null); CurrentLin.TransformRhsInto(OpAffineRaw, Output); }
/// <summary> /// Evaluation of the nonlinear operator. /// </summary> /// <param name="alpha"></param> /// <param name="CurrentState"> /// Current state of DG fields /// </param> /// <param name="beta"> /// Pre-scaling of <paramref name="Output"/>. /// </param> /// <param name="Output"></param> /// <param name="HomotopyValue"> /// <see cref="ISpatialOperator.CurrentHomotopyValue"/> /// </param> protected void EvaluateOperator(double alpha, IEnumerable <DGField> CurrentState, double[] Output, double HomotopyValue) { if (alpha != 1.0) { throw new NotSupportedException("some moron has removed this"); } SetHomotopyValue(HomotopyValue); // the real call: this.m_AssembleMatrix(out BlockMsrMatrix OpMtxRaw, out double[] OpAffineRaw, out BlockMsrMatrix MassMtxRaw, CurrentState.ToArray(), false, out var Dummy); if (OpMtxRaw != null) { // only evaluation ==> OpMatrix must be null throw new ApplicationException($"The provided {typeof(OperatorEvalOrLin).Name} is not correctly implemented."); } this.AbstractOperator = Dummy; CurrentLin.TransformRhsInto(OpAffineRaw, Output, false); }
/// <summary> /// Callback routine, see <see cref="ISolverWithCallback.IterationCallback"/> or <see cref="NonlinearSolver.IterationCallback"/>. /// </summary> public void IterationCallback(int iter, double[] xI, double[] rI, MultigridOperator mgOp) { if (xI.Length != SolverOperator.Mapping.LocalLength) { throw new ArgumentException(); } if (rI.Length != SolverOperator.Mapping.LocalLength) { throw new ArgumentException(); } int Lorg = SolverOperator.BaseGridProblemMapping.LocalLength; // transform residual and solution back onto the orignal grid // ========================================================== double[] Res_Org = new double[Lorg]; double[] Sol_Org = new double[Lorg]; SolverOperator.TransformRhsFrom(Res_Org, rI); SolverOperator.TransformSolFrom(Sol_Org, xI); double[] Err_Org = Sol_Org.CloneAs(); Err_Org.AccV(-1.0, this.ExactSolution); if (TecplotOut != null) { var ErrVec = InitProblemDGFields("Err"); var ResVec = InitProblemDGFields("Res"); var SolVec = InitProblemDGFields("Sol"); ErrVec.SetV(Err_Org); ResVec.SetV(Res_Org); SolVec.SetV(Sol_Org); List <DGField> ErrResSol = new List <DGField>(); ErrResSol.AddRange(ErrVec.Mapping.Fields); ErrResSol.AddRange(ResVec.Mapping.Fields); ErrResSol.AddRange(SolVec.Mapping.Fields); Tecplot.Tecplot.PlotFields(ErrResSol, TecplotOut + "." + iter, iter, 4); PlotDecomposition(xI, TecplotOut + "-sol-decomp." + iter); PlotDecomposition(rI, TecplotOut + "-res-decomp." + iter); } // Console out // =========== double l2_RES = rI.L2NormPow2().MPISum().Sqrt(); double l2_ERR = Err_Org.L2NormPow2().MPISum().Sqrt(); Console.WriteLine("Iter: {0}\tRes: {1:0.##E-00}\tErr: {2:0.##E-00}", iter, l2_RES, l2_ERR); // decompose error and residual into orthonormal vectors // ===================================================== int L0 = DecompositionOperator.Mapping.LocalLength; double[] Err_0 = new double[L0], Res_0 = new double[L0]; DecompositionOperator.TransformSolInto(Err_Org, Err_0); DecompositionOperator.TransformRhsInto(Res_Org, Res_0); IList <double[]> Err_OrthoLevels = OrthonormalMultigridDecomposition(Err_0); IList <double[]> Res_OrthoLevels = OrthonormalMultigridDecomposition(Res_0); // compute L2 norms on each level // ============================== for (var mgop = this.DecompositionOperator; mgop != null; mgop = mgop.CoarserLevel) { int[] _Degrees = mgop.Mapping.DgDegree; double[] Resi = Res_OrthoLevels[mgop.LevelIndex]; double[] Errr = Err_OrthoLevels[mgop.LevelIndex]; int JAGG = mgop.Mapping.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; for (int iVar = 0; iVar < _Degrees.Length; iVar++) { for (int p = 0; p <= _Degrees[iVar]; p++) { List <double> ResNorm = this.ResNormTrend[new Tuple <int, int, int>(mgop.LevelIndex, iVar, p)]; List <double> ErrNorm = this.ErrNormTrend[new Tuple <int, int, int>(mgop.LevelIndex, iVar, p)]; double ResNormAcc = 0.0; double ErrNormAcc = 0.0; for (int jagg = 0; jagg < JAGG; jagg++) { int[] NN = mgop.Mapping.AggBasis[iVar].ModeIndexForDegree(jagg, p, _Degrees[iVar]); foreach (int n in NN) { int idx = mgop.Mapping.LocalUniqueIndex(iVar, jagg, n); ResNormAcc += Resi[idx].Pow2(); ErrNormAcc += Errr[idx].Pow2(); } } ResNorm.Add(ResNormAcc.Sqrt()); ErrNorm.Add(ErrNormAcc.Sqrt()); } } } }