public static void XDG_MatrixPolynomialRestAndPrlgTest_2( [Values(0, 1, 2, 3)] int p, [Values(0.0, 0.3)] double AggregationThreshold, [Values(0, 1)] int TrackerWidth, [Values(MultigridOperator.Mode.Eye, MultigridOperator.Mode.IdMass)] MultigridOperator.Mode mode) { if (AggregationThreshold < 0.1 && p >= 3 && mode == MultigridOperator.Mode.IdMass) { // this test combination is not supposed to work: // without agglomeration, for high p, the mass matrix may be indefinite in small cut-cells // => Cholesky decomposition on mass matrix fails, i.e. 'mode == IdMass' cannot succseed. return; } XQuadFactoryHelper.MomentFittingVariants variant = XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes; var xt = new XDGTestSetup(p, AggregationThreshold, TrackerWidth, mode, variant); // Restriction & prolongation together with orthonormalization // ----------------------------------------------------------- for (var mgop = xt.MultigridOp; mgop != null; mgop = mgop.CoarserLevel) { var Itself = mgop.Mapping.FromOtherLevelMatrix(mgop.Mapping); Itself.AccEyeSp(-1.0); double Itslef_Norm = Itself.InfNorm(); //Console.WriteLine("Level {0}, Restriction onto itself {1}", mgm.LevelIndex, Itslef_Norm); Assert.LessOrEqual(Itslef_Norm, 1.0e-8); } { // test change of basis on top level XDGField uTestRnd = new XDGField(xt.XB); Random rnd = new Random(); for (int i = 0; i < uTestRnd.CoordinateVector.Count; i++) { uTestRnd.CoordinateVector[i] = rnd.NextDouble(); } xt.agg.ClearAgglomerated(uTestRnd.CoordinateVector, uTestRnd.Mapping); // perform change of basis on top level ... int Ltop = xt.MultigridOp.Mapping.LocalLength; double[] uTest_Fine = new double[Ltop]; xt.MultigridOp.TransformSolInto(uTestRnd.CoordinateVector, uTest_Fine); // .. and back XDGField uError2 = uTestRnd.CloneAs(); uError2.Clear(); xt.MultigridOp.TransformSolFrom(uError2.CoordinateVector, uTest_Fine); // compare: uError2.Acc(-1.0, uTestRnd); double NORM_uError = uError2.L2Norm(); // output Console.WriteLine("Top level change of basis error: {0}", NORM_uError); Assert.LessOrEqual(NORM_uError, 1.0e-8); } { // perform change of basis on top level int Ltop = xt.MultigridOp.Mapping.LocalLength; double[] uTest_Fine = new double[Ltop]; xt.MultigridOp.TransformSolInto(xt.uTest.CoordinateVector, uTest_Fine); // check for each level of the multigrid operator... for (int iLevel = 0; iLevel < MgSeq.Count() - 1; iLevel++) { double[] uTest_Prolonged = new double[Ltop]; XDG_Recursive(0, iLevel, xt.MultigridOp, uTest_Fine, uTest_Prolonged); XDGField uError = xt.uTest.CloneAs(); uError.Clear(); xt.MultigridOp.TransformSolFrom(uError.CoordinateVector, uTest_Prolonged); xt.agg.Extrapolate(uError.Mapping); uError.Acc(-1.0, xt.uTest); double NORM_uError = uError.L2Norm(); Console.WriteLine("Rest/Prlg error, level {0}: {1}", iLevel, NORM_uError); Assert.LessOrEqual(NORM_uError, 1.0e-8); } } }
public static void XDG_MatrixPolynomialRestAndPrlgTest( [Values(0, 1, 2, 3)] int p, [Values(0.0, 0.3)] double AggregationThreshold, [Values(0, 1)] int TrackerWidth) { XQuadFactoryHelper.MomentFittingVariants variant = XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes; var xt = new XDGTestSetup(p, AggregationThreshold, TrackerWidth, MultigridOperator.Mode.Eye, variant); // test matrix version of the restriction operator // ----------------------------------------------- List <MultigridMapping> MultigridMaps = new List <MultigridMapping>(); for (var mgop = xt.XdgMultigridOp; mgop != null; mgop = mgop.CoarserLevel) { MultigridMaps.Add(mgop.Mapping); } for (int iLevel = 0; iLevel < MgSeq.Length; iLevel++) { MultigridMapping mgMap = MultigridMaps[iLevel]; var XAggBasis = mgMap.AggBasis[0]; // set the test field: XDGField Test = new XDGField(xt.XB, "Test"); Random rand = new Random(); for (int i = 0; i < Test.CoordinateVector.Count; i++) { Test.CoordinateVector[i] = rand.NextDouble(); } xt.agg.ClearAgglomerated(Test.CoordinateVector, Test.Mapping); // do restriction/prolongation (Reference) double[] RestVecRef = new double[XAggBasis.LocalDim]; XAggBasis.RestictFromFullGrid(Test.CoordinateVector, RestVecRef); // and now with the matrix: BlockMsrMatrix RestMtx = new BlockMsrMatrix(mgMap, mgMap.ProblemMapping); XAggBasis.GetRestrictionMatrix(RestMtx, mgMap, 0); double[] RestVec = new double[mgMap.LocalLength]; RestMtx.SpMV(1.0, Test.CoordinateVector, 0.0, RestVec); double[] X1 = new double[xt.XdgMultigridOp.Mapping.LocalLength]; XDGField X2 = new XDGField(Test.Basis); xt.XdgMultigridOp.TransformSolInto(Test.CoordinateVector, X1); xt.XdgMultigridOp.TransformSolFrom(X2.CoordinateVector, X1); //xt.agg.Extrapolate(X2.CoordinatesAsVector, X2.Mapping); var ERR2 = Test.CloneAs(); ERR2.Acc(-1.0, X2); double ERR2Norm = ERR2.L2Norm(); //Console.WriteLine("MultigridOperator TranformInto/FransformFrom mismatch: " + ERR2Norm); Assert.LessOrEqual(ERR2Norm, 1.0e-8); // compare double ERR = 0.0; int Nmax = XAggBasis.MaximalLength; for (int jAgg = 0; jAgg < mgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; jAgg++) { int i0Ref = jAgg * Nmax; int i0Tst = mgMap.LocalUniqueIndex(0, jAgg, 0); int N = mgMap.GetLength(jAgg); for (int n = 0; n < N; n++) { double dist = RestVecRef[i0Ref + n] - RestVec[i0Tst + n]; ERR += dist.Pow2(); } } Console.WriteLine("Restriction matrix test (iLevel = {0}): {1}", iLevel, ERR); Assert.LessOrEqual(ERR, 1.0e-8); // double[] PrlgVecA = new double[XAggBasis.LocalDim]; double[] PrlgVecB = new double[mgMap.LocalLength]; for (int jAgg = 0; jAgg < mgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; jAgg++) { int i0Ref = jAgg * Nmax; int i0Tst = mgMap.LocalUniqueIndex(0, jAgg, 0); int N = mgMap.GetLength(jAgg); for (int n = 0; n < N; n++) { double rndVal = rand.NextDouble(); PrlgVecA[i0Ref + n] = rndVal; PrlgVecB[i0Tst + n] = rndVal; } } XDGField QA = new XDGField(Test.Basis); XDGField QB = new XDGField(Test.Basis); XAggBasis.ProlongateToFullGrid(QA.CoordinateVector, PrlgVecA); var PrlgMtx = RestMtx.Transpose(); PrlgMtx.SpMV(1.0, PrlgVecB, 0.0, QB.CoordinateVector); XDGField ERR5 = QA.CloneAs(); ERR5.Acc(-1.0, QB); double ERR5_Norm = ERR5.L2Norm(); Console.WriteLine("Prolongation matrix test (iLevel = {0}): {1}", iLevel, ERR5_Norm); Assert.LessOrEqual(ERR5_Norm, 1.0e-8); } }
private void ExperimentalSolver(out double mintime, out double maxtime, out bool Converged, out int NoOfIter, out int DOFs) { using (var tr = new FuncTrace()) { mintime = double.MaxValue; maxtime = 0; Converged = false; NoOfIter = int.MaxValue; DOFs = 0; AggregationGridBasis[][] XAggB; using (new BlockTrace("Aggregation_basis_init", tr)) { XAggB = AggregationGridBasis.CreateSequence(base.MultigridSequence, u.Mapping.BasisS); } XAggB.UpdateXdgAggregationBasis(this.Op_Agglomeration); var MassMatrix = this.Op_mass.GetMassMatrix(this.u.Mapping, new double[] { 1.0 }, false, this.LsTrk.SpeciesIdS.ToArray()); double[] _RHSvec = this.GetRHS(); Stopwatch stw = new Stopwatch(); stw.Reset(); stw.Start(); Console.WriteLine("Setting up multigrid operator..."); int p = this.u.Basis.Degree; var MultigridOp = new MultigridOperator(XAggB, this.u.Mapping, this.Op_Matrix, this.Op_mass.GetMassMatrix(new UnsetteledCoordinateMapping(this.u.Basis), false), OpConfig); Assert.True(MultigridOp != null); int L = MultigridOp.Mapping.LocalLength; DOFs = MultigridOp.Mapping.TotalLength; double[] RHSvec = new double[L]; MultigridOp.TransformRhsInto(_RHSvec, RHSvec); ISolverSmootherTemplate exsolver; SolverFactory SF = new SolverFactory(this.Control.NonLinearSolver, this.Control.LinearSolver); List <Action <int, double[], double[], MultigridOperator> > Callbacks = new List <Action <int, double[], double[], MultigridOperator> >(); Callbacks.Add(CustomItCallback); SF.GenerateLinear(out exsolver, MultigridSequence, OpConfig, Callbacks); using (new BlockTrace("Solver_Init", tr)) { exsolver.Init(MultigridOp); } /* * string filename = "XdgPoisson" + this.Grid.SpatialDimension + "p" + this.u.Basis.Degree + "R" + this.Grid.CellPartitioning.TotalLength; * MultigridOp.OperatorMatrix.SaveToTextFileSparse(filename + ".txt"); * RHSvec.SaveToTextFile(filename + "_rhs.txt"); * * var uEx = this.u.CloneAs(); * Op_Agglomeration.ClearAgglomerated(uEx.Mapping); * var CO = new ConvergenceObserver(MultigridOp, MassMatrix, uEx.CoordinateVector.ToArray()); * uEx = null; * CO.TecplotOut = "PoissonConvergence"; * //CO.PlotDecomposition(this.u.CoordinateVector.ToArray()); * * if (exsolver is ISolverWithCallback) { * ((ISolverWithCallback)exsolver).IterationCallback = CO.IterationCallback; * } * //*/ XDGField u2 = u.CloneAs(); using (new BlockTrace("Solver_Run", tr)) { // use solver (on XDG-field 'u2'). u2.Clear(); MultigridOp.UseSolver(exsolver, u2.CoordinateVector, _RHSvec); Console.WriteLine("Solver: {0}, converged? {1}, {2} iterations.", exsolver.GetType().Name, exsolver.Converged, exsolver.ThisLevelIterations); this.Op_Agglomeration.Extrapolate(u2.Mapping); Assert.IsTrue(exsolver.Converged, "Iterative solver did not converge."); } stw.Stop(); mintime = Math.Min(stw.Elapsed.TotalSeconds, mintime); maxtime = Math.Max(stw.Elapsed.TotalSeconds, maxtime); Converged = exsolver.Converged; NoOfIter = exsolver.ThisLevelIterations; // compute error between reference solution and multigrid solver XDGField ErrField = u2.CloneAs(); ErrField.Acc(-1.0, u); double ERR = ErrField.L2Norm(); double RelERR = ERR / u.L2Norm(); Assert.LessOrEqual(RelERR, 1.0e-6, "Result from iterative solver above threshold."); } }