public static void Init() { //GridCommons grd = Grid2D.Cartesian2DGrid(RandomSpacing(), RandomSpacing()); //grid = new GridData(Grid2D.Cartesian2DGrid(GenericBlas.Linspace(-7, 7, 8), GenericBlas.Linspace(-1, 1, 2))); //grid = new GridData(Grid2D.Cartesian2DGrid(new double[] { -6, -4, -2, 2, 4, 6 }, GenericBlas.Linspace(-1, 1, 2))); //if (curved) //{ // grid = Grid2D.CurvedSquareGrid(GenericBlas.Linspace(1, 2, 5), GenericBlas.Linspace(0, 1, 17), CellType.Square_9, true).GridData; //} //else //{ // grid = (Grid2D.Cartesian2DGrid(GenericBlas.Linspace(-1.5, 1.5, 17), GenericBlas.Linspace(-1.5, 1.5, 17))).GridData; //} grid = (Grid2D.Cartesian2DGrid(GenericBlas.Linspace(-1.5, 1.5, 17), GenericBlas.Linspace(-1.5, 1.5, 17))).GridData; MgSeq = CoarseningAlgorithms.CreateSequence(grid); for (int p = 0; p <= 3; p++) // loop over polynomial degrees... { var uMapping = new UnsetteledCoordinateMapping(new Basis(grid, p)); var MgMapSeq = new MultigridMapping[MgSeq.Length]; var BasisSeq = AggregationGridBasis.CreateSequence(MgSeq, uMapping.BasisS); for (int iLevel = 0; iLevel < MgSeq.Length; iLevel++) { MgMapSeq[iLevel] = new MultigridMapping(uMapping, BasisSeq[iLevel], new int[] { p }); } MultigrigMap.Add(p, MgMapSeq); } }
public static void Init() { bool dummy; ilPSP.Environment.Bootstrap( new string[0], BoSSS.Solution.Application.GetBoSSSInstallDir(), out dummy); //GridCommons grd = Grid2D.Cartesian2DGrid(RandomSpacing(), RandomSpacing()); //grid = new GridData(Grid2D.Cartesian2DGrid(GenericBlas.Linspace(-7, 7, 8), GenericBlas.Linspace(-1, 1, 2))); //grid = new GridData(Grid2D.Cartesian2DGrid(new double[] { -6, -4, -2, 2, 4, 6 }, GenericBlas.Linspace(-1, 1, 2))); grid = new GridData(Grid2D.Cartesian2DGrid(GenericBlas.Linspace(-1.5, 1.5, 17), GenericBlas.Linspace(-1.5, 1.5, 17))); MgSeq = CoarseningAlgorithms.CreateSequence(grid); for (int p = 0; p <= 3; p++) // loop over polynomial degrees... { var uMapping = new UnsetteledCoordinateMapping(new Basis(grid, p)); var MgMapSeq = new MultigridMapping[MgSeq.Length]; var BasisSeq = AggregationGridBasis.CreateSequence(MgSeq, uMapping.BasisS); for (int iLevel = 0; iLevel < MgSeq.Length; iLevel++) { MgMapSeq[iLevel] = new MultigridMapping(uMapping, BasisSeq[iLevel], new int[] { p }); } MultigrigMap.Add(p, MgMapSeq); } }
/// <summary> /// Constructor for XDG solvers /// </summary> public OpAnalysisBase(LevelSetTracker LsTrk, BlockMsrMatrix Mtx, double[] RHS, UnsetteledCoordinateMapping Mapping, MultiphaseCellAgglomerator CurrentAgglomeration, BlockMsrMatrix _mass, IEnumerable <MultigridOperator.ChangeOfBasisConfig[]> OpConfig, ISpatialOperator abstractOperator) { int RHSlen = Mapping.TotalLength; m_map = Mapping; // mapping VarGroup = Mapping.BasisS.Count.ForLoop(i => i); //default: all dependent variables are included in operator matrix m_LsTrk = LsTrk; m_OpMtx = Mtx.CloneAs(); localRHS = RHS.CloneAs(); // create the Dummy XDG aggregation basis var baseGrid = Mapping.GridDat; var mgSeq = Foundation.Grid.Aggregation.CoarseningAlgorithms.CreateSequence(baseGrid, 1); AggregationGridBasis[][] XAggB = AggregationGridBasis.CreateSequence(mgSeq, Mapping.BasisS); // XAggB.UpdateXdgAggregationBasis(CurrentAgglomeration); // create multigrid operator m_MultigridOp = new MultigridOperator(XAggB, Mapping, m_OpMtx, _mass, OpConfig, abstractOperator.DomainVar.Select(varName => abstractOperator.FreeMeanValue[varName]).ToArray()); }
private static int[] ConvertRowIndices( int jCell, AggregationGridBasis basis, int[] Degrees, ChangeOfBasisConfig conf, int E, int[] _i0s, int[] LocIdx) { int NN = conf.VarIndex.Sum(iVar => basis.GetLength(jCell, Degrees[iVar])); int[] Loc2glob = new int[NN]; int i0Rowloc = 0; for (int eRow = 0; eRow < E; eRow++) // loop over variables in configuration { int i0Row = _i0s[eRow]; int iVarRow = conf.VarIndex[eRow]; int NRow = basis.GetLength(jCell, Degrees[iVarRow]); for (int n_row = 0; n_row < NRow; n_row++) // row loop... //n_row = LocIdx[k]; { int iRowLoc = n_row + i0Rowloc; int iRowGlb = n_row + i0Row; Loc2glob[iRowLoc] = iRowGlb; } i0Rowloc += NRow; } return(LocIdx.Select(i => Loc2glob[i]).ToArray()); }
static void RestictionMatrixTestRec(int p, IEnumerable <MultigridMapping> MgMapSeq) { var currentLevelMap = MgMapSeq.First(); AggregationGridBasis AggBasis = currentLevelMap.AggBasis[0]; var map = new UnsetteledCoordinateMapping(new Basis(grid, p)); Random rnd = new Random(); double[] OrigVec = map.LocalLength.ForLoop(i => rnd.NextDouble()); double[] RestVec = new double[AggBasis.LocalDim]; double[] PrlgVec = new double[OrigVec.Length]; double[] RestVec2 = new double[RestVec.Length]; double[] PrlgVec2 = new double[OrigVec.Length]; AggBasis.RestictFromFullGrid(OrigVec, RestVec); AggBasis.ProlongateToFullGrid(PrlgVec, RestVec); BlockMsrMatrix RestOp = new BlockMsrMatrix(MgMapSeq.First(), MgMapSeq.First().ProblemMapping); AggBasis.GetRestrictionMatrix(RestOp, MgMapSeq.First(), 0); RestOp.SpMV(1.0, OrigVec, 0.0, RestVec2); BlockMsrMatrix PrlgOp = RestOp.Transpose(); PrlgOp.SpMV(1.0, RestVec2, 0.0, PrlgVec2); double RestErrNorm = GenericBlas.L2Dist(RestVec2, RestVec); double PrlgErrNorm = GenericBlas.L2Dist(PrlgVec2, PrlgVec); double LostInfNorm = GenericBlas.L2Dist(OrigVec, PrlgVec2); //Console.WriteLine("Rest. matrix test: {0}, Prolong. matrix test {1}, Lost info {2}", RestErrNorm, PrlgErrNorm, LostInfNorm); Assert.IsTrue(RestErrNorm < 1.0e-10); Assert.IsTrue(PrlgErrNorm < 1.0e-10); // restriction onto level itself BlockMsrMatrix RestMtx = currentLevelMap.FromOtherLevelMatrix(currentLevelMap); BlockMsrMatrix ShldBeEye = BlockMsrMatrix.Multiply(RestMtx, RestMtx.Transpose()); ShldBeEye.AccEyeSp(-1.0); double errNorm = ShldBeEye.InfNorm(); Console.WriteLine("Id norm {0} \t (level {1})", errNorm, currentLevelMap.AggGrid.MgLevel); Assert.IsTrue(errNorm < 1.0e-8); // recursion if (MgMapSeq.Count() > 1) { RestictionMatrixTestRec(p, MgMapSeq.Skip(1)); } }
private void OperatorAnalysis() { AggregationGridBasis[][] XAggB = AggregationGridBasis.CreateSequence(base.MultigridSequence, u.Mapping.BasisS); XAggB.UpdateXdgAggregationBasis(this.Op_Agglomeration); var MultigridOp = new MultigridOperator(XAggB, this.u.Mapping, this.Op_Matrix, this.Op_mass.GetMassMatrix(new UnsetteledCoordinateMapping(this.u.Basis), false), OpConfig); var PcOpMatrix = MultigridOp.OperatorMatrix; //PcOpMatrix.SaveToTextFileSparse("C:\\temp\\Xpoisson.txt"); MultidimensionalArray ret = MultidimensionalArray.Create(1, 4); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(PcOpMatrix, "OpMtx"); bmc.Cmd("OpMtxSym = 0.5*(OpMtx + OpMtx');"); bmc.Cmd("condNo = condest(OpMtxSym);"); bmc.Cmd("eigMaxi = eigs(OpMtxSym,1,'lm')"); bmc.Cmd("eigMini = eigs(OpMtxSym,1,'sm')"); bmc.Cmd("lasterr"); bmc.Cmd("[V,r]=chol(OpMtxSym);"); bmc.Cmd("ret = [condNo, eigMaxi, eigMini, r]"); bmc.GetMatrix(ret, "ret"); bmc.Execute(false); } double condNo = ret[0, 0]; double eigMaxi = ret[0, 1]; double eigMini = ret[0, 2]; double posDef = ret[0, 3] == 0 ? 1 : 0; Console.WriteLine("Condition number: {0:0.####E-00}", condNo); if (posDef == 0.0) { Console.WriteLine("WARNING: Operator matrix is not positive definite."); } base.QueryHandler.ValueQuery("condNo", condNo, false); base.QueryHandler.ValueQuery("eigMaxi", eigMaxi, false); base.QueryHandler.ValueQuery("eigMini", eigMini, false); base.QueryHandler.ValueQuery("posDef", posDef, false); }
/// <summary> /// Initialization of the solver/preconditioner. /// </summary> protected void InitMultigrid(DGField[] Fields, bool useX) { Basis[] bs; if (useX) { bs = new Basis[Fields.Length]; for (int i = 0; i < bs.Length; i++) { bs[i] = new XDGBasis(m_LsTrk, Fields[i].Basis.Degree); } } else { bs = Fields.Select(f => f.Basis).ToArray(); } this.MultigridBasis = AggregationGridBasis.CreateSequence(this.MultigridSequence, bs); }
public static void Init() { grid = Grid2D.CurvedSquareGrid(GenericBlas.Linspace(1, 2, 17), GenericBlas.Linspace(0, 1, 17), CellType.Square_9, true).GridData; MgSeq = CoarseningAlgorithms.CreateSequence(grid); for (int p = 0; p <= 3; p++) { // loop over polynomial degrees... var uMapping = new UnsetteledCoordinateMapping(new Basis(grid, p)); var MgMapSeq = new MultigridMapping[MgSeq.Length]; var BasisSeq = AggregationGridBasis.CreateSequence(MgSeq, uMapping.BasisS); for (int iLevel = 0; iLevel < MgSeq.Length; iLevel++) { MgMapSeq[iLevel] = new MultigridMapping(uMapping, BasisSeq[iLevel], new int[] { p }); } MultigrigMap.Add(p, MgMapSeq); } }
private void Setup() { MgSeq = CoarseningAlgorithms.CreateSequence(m_grid.iGridData); int p = m_DGorder; var uMapping = new UnsetteledCoordinateMapping(u1.Basis, u2.Basis); //var uMapping = new UnsetteledCoordinateMapping(u1.Basis); //var uMapping = new UnsetteledCoordinateMapping(new Basis(m_grid.iGridData, p)); XAggB = AggregationGridBasis.CreateSequence(MgSeq, uMapping.BasisS); var bla = LsTrk.SpeciesIdS.ToArray(); var agg = LsTrk.GetAgglomerator(bla, m_quadOrder, THRESHOLD, AgglomerateNewborn: false, AgglomerateDecased: false, ExceptionOnFailedAgglomeration: true); XAggB.UpdateXdgAggregationBasis(agg); var VarDegrees = uMapping.BasisS.Count.ForLoop(i => uMapping.BasisS[i].Degree); MG_Mapping = new MultigridMapping(uMapping, XAggB[0], VarDegrees); map = uMapping; }
static void RestictionMatrixTestRec(int p, IEnumerable <MultigridMapping> MgMapSeq) { AggregationGridBasis AggBasis = MgMapSeq.First().AggBasis[0]; var map = new UnsetteledCoordinateMapping(new Basis(grid, p)); Random rnd = new Random(); double[] OrigVec = map.LocalLength.ForLoop(i => rnd.NextDouble()); double[] RestVec = new double[AggBasis.LocalDim]; double[] PrlgVec = new double[OrigVec.Length]; double[] RestVec2 = new double[RestVec.Length]; double[] PrlgVec2 = new double[OrigVec.Length]; AggBasis.RestictFromFullGrid(OrigVec, RestVec); AggBasis.ProlongateToFullGrid(PrlgVec, RestVec); BlockMsrMatrix RestOp = new BlockMsrMatrix(MgMapSeq.First(), MgMapSeq.First().ProblemMapping); AggBasis.GetRestrictionMatrix(RestOp, MgMapSeq.First(), 0); RestOp.SpMV(1.0, OrigVec, 0.0, RestVec2); BlockMsrMatrix PrlgOp = RestOp.Transpose(); PrlgOp.SpMV(1.0, RestVec2, 0.0, PrlgVec2); double RestErrNorm = GenericBlas.L2Dist(RestVec2, RestVec); double PrlgErrNorm = GenericBlas.L2Dist(PrlgVec2, PrlgVec); double LostInfNorm = GenericBlas.L2Dist(OrigVec, PrlgVec2); //Console.WriteLine("Rest. matrix test: {0}, Prolong. matrix test {1}, Lost info {2}", RestErrNorm, PrlgErrNorm, LostInfNorm); Debug.Assert(RestErrNorm < 1.0e-10); Debug.Assert(PrlgErrNorm < 1.0e-10); if (MgMapSeq.Count() > 1) { RestictionMatrixTestRec(p, MgMapSeq.Skip(1)); } }
public static void RestrictionOfSystemOpTest() { Basis B1 = new Basis(grid, 0), B2 = new Basis(grid, 2); var Map = new UnsetteledCoordinateMapping(B1, B2); var Lev0Basis = new AggregationGridBasis(B2, TestProgram.MgSeq[0]); var Lev1Basis = new AggregationGridBasis(B2, TestProgram.MgSeq[1]); var Lev0 = new MultigridMapping(Map, new AggregationGridBasis[] { Lev0Basis, Lev0Basis }, new int[] { B1.Degree, B2.Degree }); var Lev1 = new MultigridMapping(Map, new AggregationGridBasis[] { Lev1Basis, Lev1Basis }, new int[] { B1.Degree, B2.Degree }); int[] I0col = Lev0.GetSubvectorIndices(new int[] { 0 }); int[] I1col = Lev0.GetSubvectorIndices(new int[] { 1 }); int[] I0row = Lev1.GetSubvectorIndices(new int[] { 0 }); int[] I1row = Lev1.GetSubvectorIndices(new int[] { 1 }); var RestMtx = Lev1.FromOtherLevelMatrix(Lev0); MsrMatrix Rest00 = new MsrMatrix(I0row.Length, I0col.Length, 1, 1); RestMtx.WriteSubMatrixTo(Rest00, I0row, default(int[]), I0col, default(int[])); MsrMatrix Rest01 = new MsrMatrix(I0row.Length, I1col.Length, 1, 1); RestMtx.WriteSubMatrixTo(Rest01, I0row, default(int[]), I1col, default(int[])); MsrMatrix Rest10 = new MsrMatrix(I1row.Length, I0col.Length, 1, 1); RestMtx.WriteSubMatrixTo(Rest10, I1row, default(int[]), I0col, default(int[])); MsrMatrix Rest11 = new MsrMatrix(I1row.Length, I1col.Length, 1, 1); RestMtx.WriteSubMatrixTo(Rest11, I1row, default(int[]), I1col, default(int[])); Debug.Assert(Rest10.InfNorm() == 0.0); Debug.Assert(Rest01.InfNorm() == 0.0); Debug.Assert(Rest00.InfNorm() != 0.0); Debug.Assert(Rest11.InfNorm() != 0.0); }
public static void RestrictionOfSystemOpTest() { Basis B1 = new Basis(grid, 0), B2 = new Basis(grid, 2); var Map = new UnsetteledCoordinateMapping(B1, B2); AggregationGridBasis[][] aB = AggregationGridBasis.CreateSequence(TestProgram.MgSeq.Take(2), new Basis[] { B1, B2 }); var Lev0 = new MultigridMapping(Map, aB[0], new int[] { B1.Degree, B2.Degree }); var Lev1 = new MultigridMapping(Map, aB[1], new int[] { B1.Degree, B2.Degree }); int[] I0col = Lev0.GetSubvectorIndices(new int[] { 0 }); int[] I1col = Lev0.GetSubvectorIndices(new int[] { 1 }); int[] I0row = Lev1.GetSubvectorIndices(new int[] { 0 }); int[] I1row = Lev1.GetSubvectorIndices(new int[] { 1 }); var RestMtx = Lev1.FromOtherLevelMatrix(Lev0); MsrMatrix Rest00 = new MsrMatrix(I0row.Length, I0col.Length, 1, 1); RestMtx.WriteSubMatrixTo(Rest00, I0row, default(int[]), I0col, default(int[])); MsrMatrix Rest01 = new MsrMatrix(I0row.Length, I1col.Length, 1, 1); RestMtx.WriteSubMatrixTo(Rest01, I0row, default(int[]), I1col, default(int[])); MsrMatrix Rest10 = new MsrMatrix(I1row.Length, I0col.Length, 1, 1); RestMtx.WriteSubMatrixTo(Rest10, I1row, default(int[]), I0col, default(int[])); MsrMatrix Rest11 = new MsrMatrix(I1row.Length, I1col.Length, 1, 1); RestMtx.WriteSubMatrixTo(Rest11, I1row, default(int[]), I1col, default(int[])); Assert.IsTrue(Rest10.InfNorm() == 0.0); Assert.IsTrue(Rest01.InfNorm() == 0.0); Assert.IsTrue(Rest00.InfNorm() != 0.0); Assert.IsTrue(Rest11.InfNorm() != 0.0); }
/// <summary> /// Solution of the system /// <see cref="LaplaceMtx"/>*<see cref="T"/> + <see cref="LaplaceAffine"/> = <see cref="RHS"/> /// using the modular solver framework. /// </summary> private void ExperimentalSolve(out double mintime, out double maxtime, out bool Converged, out int NoOfIter) { using (var tr = new FuncTrace()) { int p = this.T.Basis.Degree; var MgSeq = this.MultigridSequence; mintime = double.MaxValue; maxtime = 0; Converged = false; NoOfIter = int.MaxValue; Console.WriteLine("Construction of Multigrid basis..."); Stopwatch mgBasis = new Stopwatch(); mgBasis.Start(); AggregationGridBasis[][] AggBasis; using (new BlockTrace("Aggregation_basis_init", tr)) { AggBasis = AggregationGridBasis.CreateSequence(MgSeq, new Basis[] { this.T.Basis }); } mgBasis.Stop(); Console.WriteLine("done. (" + mgBasis.Elapsed.TotalSeconds + " sec)"); //foreach (int sz in new int[] { 1000, 2000, 5000, 10000, 20000 }) { // base.Control.TargetBlockSize = sz; for (int irun = 0; irun < base.Control.NoOfSolverRuns; irun++) { Stopwatch stw = new Stopwatch(); stw.Reset(); stw.Start(); Console.WriteLine("Setting up multigrid operator..."); var mgsetup = new Stopwatch(); mgsetup.Start(); var MultigridOp = new MultigridOperator(AggBasis, this.T.Mapping, this.LaplaceMtx, null, MgConfig); mgsetup.Stop(); Console.WriteLine("done. (" + mgsetup.Elapsed.TotalSeconds + " sec)"); Console.WriteLine("Setting up solver..."); var solverSetup = new Stopwatch(); solverSetup.Start(); ISolverSmootherTemplate solver; switch (base.Control.solver_name) { case SolverCodes.exp_direct: solver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.PARDISO }; break; case SolverCodes.exp_direct_lapack: solver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.Lapack }; break; case SolverCodes.exp_softpcg_schwarz_directcoarse: { double LL = this.LaplaceMtx._RowPartitioning.LocalLength; int NoOfBlocks = (int)Math.Max(1, Math.Round(LL / (double)this.Control.TargetBlockSize)); Console.WriteLine("Additive Schwarz w. direct coarse, No of blocks: " + NoOfBlocks.MPISum()); solver = new SoftPCG() { m_MaxIterations = 50000, m_Tolerance = 1.0e-10, Precond = new Schwarz() { m_MaxIterations = 1, //CoarseSolver = new GenericRestriction() { // CoarserLevelSolver = new GenericRestriction() { CoarseSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.PARDISO // } //} }, m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { NoOfPartsPerProcess = NoOfBlocks }, Overlap = 1, } }; break; } case SolverCodes.exp_softpcg_schwarz: { double LL = this.LaplaceMtx._RowPartitioning.LocalLength; int NoOfBlocks = (int)Math.Max(1, Math.Round(LL / (double)this.Control.TargetBlockSize)); Console.WriteLine("Additive Schwarz, No of blocks: " + NoOfBlocks.MPISum()); solver = new SoftPCG() { m_MaxIterations = 50000, m_Tolerance = 1.0e-10, Precond = new Schwarz() { m_MaxIterations = 1, CoarseSolver = null, m_BlockingStrategy = new Schwarz.METISBlockingStrategy { NoOfPartsPerProcess = NoOfBlocks }, Overlap = 1 } }; break; } case SolverCodes.exp_softpcg_mg: solver = MultilevelSchwarz(MultigridOp); break; case SolverCodes.exp_Kcycle_schwarz: solver = KcycleMultiSchwarz(MultigridOp); break; default: throw new ApplicationException("unknown solver: " + this.Control.solver_name); } T.Clear(); T.AccLaidBack(1.0, Tex); ConvergenceObserver CO = null; //CO = new ConvergenceObserver(MultigridOp, null, T.CoordinateVector.ToArray()); //CO.TecplotOut = "oasch"; if (solver is ISolverWithCallback) { if (CO == null) { ((ISolverWithCallback)solver).IterationCallback = delegate (int iter, double[] xI, double[] rI, MultigridOperator mgOp) { double l2_RES = rI.L2NormPow2().MPISum().Sqrt(); double[] xRef = new double[xI.Length]; MultigridOp.TransformSolInto(T.CoordinateVector, xRef); double l2_ERR = GenericBlas.L2DistPow2(xI, xRef).MPISum().Sqrt(); Console.WriteLine("Iter: {0}\tRes: {1:0.##E-00}\tErr: {2:0.##E-00}\tRunt: {3:0.##E-00}", iter, l2_RES, l2_ERR, stw.Elapsed.TotalSeconds); //Tjac.CoordinatesAsVector.SetV(xI); //Residual.CoordinatesAsVector.SetV(rI); //PlotCurrentState(iter, new TimestepNumber(iter), 3); }; } else { ((ISolverWithCallback)solver).IterationCallback = CO.IterationCallback; } } using (new BlockTrace("Solver_Init", tr)) { solver.Init(MultigridOp); } solverSetup.Stop(); Console.WriteLine("done. (" + solverSetup.Elapsed.TotalSeconds + " sec)"); Console.WriteLine("Running solver..."); var solverIteration = new Stopwatch(); solverIteration.Start(); double[] T2 = this.T.CoordinateVector.ToArray(); using (new BlockTrace("Solver_Run", tr)) { solver.ResetStat(); T2.Clear(); var RHSvec = RHS.CoordinateVector.ToArray(); BLAS.daxpy(RHSvec.Length, -1.0, this.LaplaceAffine, 1, RHSvec, 1); MultigridOp.UseSolver(solver, T2, RHSvec); T.CoordinateVector.SetV(T2); } solverIteration.Stop(); Console.WriteLine("done. (" + solverIteration.Elapsed.TotalSeconds + " sec)"); Console.WriteLine("Pardiso phase 11: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_11.Elapsed.TotalSeconds); Console.WriteLine("Pardiso phase 22: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_22.Elapsed.TotalSeconds); Console.WriteLine("Pardiso phase 33: " + ilPSP.LinSolvers.PARDISO.PARDISOSolver.Phase_33.Elapsed.TotalSeconds); // time measurement, statistics stw.Stop(); mintime = Math.Min(stw.Elapsed.TotalSeconds, mintime); maxtime = Math.Max(stw.Elapsed.TotalSeconds, maxtime); Converged = solver.Converged; NoOfIter = solver.ThisLevelIterations; if (CO != null) CO.PlotTrend(true, true, true); } } }
/// <summary> /// applies the pre-conditioning to the operator matrix /// (passed in the constructor) /// and returns the pre-conditioned matrix /// </summary> /// <param name="LeftPreCond"> /// left pre-conditioning matrix /// </param> /// <param name="RightPreCond"> /// right pre-conditioning matrix /// </param> /// <param name="RightPreCondInv"> /// the inverse of <paramref name="RightPreCond"/> -- usually required to transform an initial guess. /// </param> /// <param name="LeftPreCondInv"></param> /// <param name="MassMatrix"> /// on entry the mass matrix w.r.t. the XDG basis /// </param> /// <param name="OpMatrix"> /// </param> /// <returns> /// List of indefinite row indices. /// </returns> int[] ComputeChangeOfBasis(BlockMsrMatrix OpMatrix, BlockMsrMatrix MassMatrix, out BlockMsrMatrix LeftPreCond, out BlockMsrMatrix RightPreCond, out BlockMsrMatrix LeftPreCondInv, out BlockMsrMatrix RightPreCondInv) { using (var tr = new FuncTrace()) { // test arguments // ============== VerifyConfig(); Debug.Assert(OpMatrix.RowPartitioning.LocalLength == this.Mapping.LocalLength); Debug.Assert(OpMatrix.ColPartition.LocalLength == this.Mapping.LocalLength); Debug.Assert(MassMatrix == null || (MassMatrix.RowPartitioning.LocalLength == this.Mapping.LocalLength)); Debug.Assert(MassMatrix == null || (MassMatrix.ColPartition.LocalLength == this.Mapping.LocalLength)); AggregationGridBasis[] basisS = this.Mapping.AggBasis; int[] Degrees = this.Mapping.DgDegree; List <int> IndefRows = new List <int>(); // compute preconditioner matrices // =============================== using (var bt = new BlockTrace("compute-pc", tr)) { Stopwatch stw_Data = new Stopwatch(); stw_Data.Reset(); Stopwatch stw_Comp = new Stopwatch(); stw_Comp.Reset(); LeftPreCond = new BlockMsrMatrix(OpMatrix._RowPartitioning, OpMatrix._ColPartitioning); RightPreCond = new BlockMsrMatrix(OpMatrix._RowPartitioning, OpMatrix._ColPartitioning); RightPreCondInv = new BlockMsrMatrix(OpMatrix._RowPartitioning, OpMatrix._ColPartitioning); LeftPreCondInv = new BlockMsrMatrix(OpMatrix._RowPartitioning, OpMatrix._ColPartitioning); LeftPreCond.AccEyeSp(1.0); RightPreCond.AccEyeSp(1.0); LeftPreCondInv.AccEyeSp(1.0); RightPreCondInv.AccEyeSp(1.0); int LL = this.m_Config.Length; MultidimensionalArray[] MassBlock = new MultidimensionalArray[LL]; MultidimensionalArray[] OperatorBlock = new MultidimensionalArray[LL]; MultidimensionalArray[] PCleftBlock = new MultidimensionalArray[LL]; MultidimensionalArray[] work = new MultidimensionalArray[LL]; MultidimensionalArray[] PCrightBlock_inv = new MultidimensionalArray[LL]; MultidimensionalArray[] PCleftBlock_inv = new MultidimensionalArray[LL]; MultidimensionalArray[] PCrightBlock = new MultidimensionalArray[LL]; int[][] __i0s = new int[LL][]; for (int i = 0; i < LL; i++) { var conf = m_Config[i]; __i0s[i] = new int[conf.VarIndex.Length]; } int J = this.Mapping.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; int i0 = this.Mapping.Partitioning.i0; for (int jCell = 0; jCell < J; jCell++) // loop over cells... //ReducedRegionCode rrc; //int NoOfSpc = LsTrk.GetNoOfSpecies(jCell, out rrc); //if (this.Mapping.GetLength(jCell) == 0) // // void cell // continue; { for (int i = 0; i < LL; i++) // for each configuration item... { var conf = m_Config[i]; int E = conf.VarIndex.Length; int[] _i0s = __i0s[i]; AggregationGridBasis basis = null; int DOF = 0; bool AnyZeroLength = false; for (int e1 = 0; e1 < E; e1++) { int dof_var = this.Mapping.GetLengthForVar(jCell, conf.VarIndex[e1]); DOF += dof_var; AnyZeroLength |= (dof_var == 0); } if (AnyZeroLength && DOF > 0) { throw new ApplicationException(); } if (DOF == 0) { // void cell continue; } for (int e = 0; e < E; e++) { _i0s[e] = this.Mapping.LocalUniqueIndex(conf.VarIndex[e], jCell, 0) + i0; if (e == 0) { basis = basisS[conf.VarIndex[e]]; } else { if (!object.ReferenceEquals(basis, basisS[conf.VarIndex[e]])) { throw new NotSupportedException("All variables in a configuration item must share the same basis."); } } } // extract blocks from operator and mass matrix // -------------------------------------------- stw_Data.Start(); ExtractBlock(jCell, basis, Degrees, conf, E, _i0s, true, MassMatrix, ref MassBlock[i]); ExtractBlock(jCell, basis, Degrees, conf, E, _i0s, true, OpMatrix, ref OperatorBlock[i]); stw_Data.Stop(); double MassBlkNrm = MassBlock[i].InfNorm(); double OperatorBlkNrm = OperatorBlock[i].InfNorm(); int NN = MassBlock[i].NoOfRows; if (MassBlkNrm == 0) { //throw new ArithmeticException("absolute zero Mass block in cell " + jCell + "."); //Console.WriteLine("absolute zero Mass block in cell " + jCell + "."); if (conf.mode == Mode.IdMass_DropIndefinite || conf.mode == Mode.SymPart_DiagBlockEquilib_DropIndefinite) { // we can deal with this ... } else { throw new ArithmeticException("absolute zero Mass block in cell " + jCell + "."); } } //if(OperatorBlkNrm == 0) { // throw new ArithmeticException("absolute zero Operator block in cell " + jCell + "."); //} // mem alloc // --------- if (PCleftBlock[i] == null || PCleftBlock[i].NoOfRows != NN) { PCleftBlock[i] = MultidimensionalArray.Create(NN, NN); } if (PCrightBlock[i] == null || PCrightBlock[i].NoOfRows != NN) { PCrightBlock[i] = MultidimensionalArray.Create(NN, NN); } if (work[i] == null || work[i].NoOfRows != NN) { work[i] = MultidimensionalArray.Create(NN, NN); } // compute precond // --------------- stw_Comp.Start(); int Rank; PCleftBlock[i].Clear(); PCrightBlock[i].Clear(); int[] idr = ComputeChangeOfBasisBlock(MassBlock[i], OperatorBlock[i], PCleftBlock[i], PCrightBlock[i], conf.mode, out Rank, work[i]); if (Rank != NN) { IndefRows.AddRange(ConvertRowIndices(jCell, basis, Degrees, conf, E, _i0s, idr)); } else { Debug.Assert(idr == null); } stw_Comp.Stop(); // write block back // ---------------- stw_Data.Start(); ExtractBlock(jCell, basis, Degrees, conf, E, _i0s, false, LeftPreCond, ref PCleftBlock[i]); ExtractBlock(jCell, basis, Degrees, conf, E, _i0s, false, RightPreCond, ref PCrightBlock[i]); // inverse precond-matrix // ---------------------- // right-inverse: (required for transforming solution guess) if (PCrightBlock_inv[i] == null || PCrightBlock_inv[i].NoOfRows != NN) { PCrightBlock_inv[i] = MultidimensionalArray.Create(NN, NN); } if (Rank == NN) { PCrightBlock[i].InvertTo(PCrightBlock_inv[i]); } else { RankDefInvert(PCrightBlock[i], PCrightBlock_inv[i]); } ExtractBlock(jCell, basis, Degrees, conf, E, _i0s, false, RightPreCondInv, ref PCrightBlock_inv[i]); // left-inverse: (required for analysis purposes, to transform residuals back onto original grid) if (PCleftBlock_inv[i] == null || PCleftBlock_inv[i].NoOfRows != NN) { PCleftBlock_inv[i] = MultidimensionalArray.Create(NN, NN); } if (Rank == NN) { PCleftBlock[i].InvertTo(PCleftBlock_inv[i]); } else { RankDefInvert(PCleftBlock[i], PCleftBlock_inv[i]); } ExtractBlock(jCell, basis, Degrees, conf, E, _i0s, false, LeftPreCondInv, ref PCleftBlock_inv[i]); stw_Data.Stop(); } } bt.LogDummyblock(stw_Data.Elapsed.Ticks, "Change_of_Basis_data_copy"); bt.LogDummyblock(stw_Comp.Elapsed.Ticks, "Change_of_Basis_compute"); } return(IndefRows.ToArray()); } }
/// <summary> /// /// </summary> /// <param name="ProblemMapping"></param> /// <param name="MultigridSequence"></param> /// <param name="useX"> /// Create an XDG aggregation basis even if <paramref name="ProblemMapping"/> only contains DG basis. /// </param> /// <returns></returns> public static AggregationGridBasis[][] CreateAggregationGridBasis(UnsetteledCoordinateMapping ProblemMapping, LevelSetTracker _LsTrk, AggregationGrid[] MultigridSequence, bool useX) { Debug.Assert(object.ReferenceEquals(_LsTrk.GridDat, ProblemMapping.GridDat)); Basis[] BasisS = ProblemMapping.BasisS.ToArray(); Debug.Assert(BasisS.Where(b => !object.ReferenceEquals(b.GridDat, _LsTrk.GridDat)).Count() == 0); AggregationGridBasis[][] MultigridBasis = new AggregationGridBasis[MultigridSequence.Length][]; XDGBasis maxXDGbasis = null; Basis maxDGbasis = null; foreach (var b in BasisS) { if (b is XDGBasis) { XDGBasis xb = (XDGBasis)b; if (maxXDGbasis == null || maxXDGbasis.Degree < xb.Degree) { maxXDGbasis = xb; } } else { if (maxDGbasis == null || maxDGbasis.Degree < b.Degree) { maxDGbasis = b; } } } if (useX) { if (maxDGbasis != null) { if (maxXDGbasis == null || maxXDGbasis.Degree < maxDGbasis.Degree) { maxXDGbasis = new XDGBasis(_LsTrk, maxDGbasis.Degree); } } } XdgAggregationBasis[] mgXdgB; if (maxXDGbasis != null) { mgXdgB = MultigridSequence.Select(aggGrd => new XdgAggregationBasis(maxXDGbasis, aggGrd)).ToArray(); } else { mgXdgB = null; } AggregationGridBasis[] mgDgB; if (maxDGbasis != null) { mgDgB = MultigridSequence.Select(aggGrd => new AggregationGridBasis(maxDGbasis, aggGrd)).ToArray(); } else { mgDgB = null; } for (int iLevel = 0; iLevel < MultigridSequence.Length; iLevel++) { MultigridBasis[iLevel] = new AggregationGridBasis[BasisS.Length]; for (int r = 0; r < BasisS.Length; r++) { if (BasisS[r] is XDGBasis || useX) { MultigridBasis[iLevel][r] = mgXdgB[iLevel]; } else { MultigridBasis[iLevel][r] = mgDgB[iLevel]; } } } return(MultigridBasis); }
/// <summary> /// Spatial operator matrix analysis method /// </summary> public void SpatialOperatorMatrixAnalysis(bool CheckAssertions, int AnalysisLevel) { using (var solver = new Rheology()) { int D = solver.Grid.SpatialDimension; if (AnalysisLevel < 0 || AnalysisLevel > 2) { throw new ArgumentException(); } BlockMsrMatrix OpMatrix; double[] OpAffine; solver.AssembleMatrix(out OpMatrix, out OpAffine, solver.CurrentSolution.Mapping.ToArray(), true); // ============================= // AnalysisLevel 0 // ============================= { var OpMatrixT = OpMatrix.Transpose(); CoordinateVector TestVec = new CoordinateVector(solver.CurrentSolution.Mapping.Fields.Select(f => f.CloneAs()).ToArray()); double testsumPos = 0.0; double testsumNeg = 0.0; for (int rnd_seed = 0; rnd_seed < 20; rnd_seed++) { // fill the pressure components of the test vector TestVec.Clear(); Random rnd = new Random(rnd_seed); DGField Pressack = TestVec.Mapping.Fields[D] as DGField; int J = solver.GridData.iLogicalCells.NoOfLocalUpdatedCells; for (int j = 0; j < J; j++) { int N = Pressack.Basis.GetLength(j); for (int n = 0; n < N; n++) { Pressack.Coordinates[j, n] = rnd.NextDouble(); } } // Gradient times P: double[] R1 = new double[TestVec.Count]; OpMatrix.SpMV(1.0, TestVec, 0.0, R1); // R1 = Grad * P //Console.WriteLine("L2 of 'Grad * P': " + R1.L2Norm()); // transpose of Divergence times P: double[] R2 = new double[TestVec.Count]; OpMatrix.SpMV(1.0, TestVec, 0.0, R2); // R2 = divT * P //Console.WriteLine("L2 of 'divT * P': " + R2.L2Norm()); TestVec.Clear(); TestVec.Acc(1.0, R1); TestVec.Acc(1.0, R2); // analyze! testsumNeg += GenericBlas.L2Dist(R1, R2); R2.ScaleV(-1.0); testsumPos += GenericBlas.L2Dist(R1, R2); } Console.WriteLine("Pressure/Divergence Symmetry error in all tests (+): " + testsumPos); Console.WriteLine("Pressure/Divergence Symmetry error in all tests (-): " + testsumNeg); if (CheckAssertions) { Assert.LessOrEqual(Math.Abs(testsumNeg), testsumPos * 1.0e-13); } } // ============================= // AnalysisLevel 1 and 2 // ============================= if (AnalysisLevel > 0) { AggregationGridBasis[][] MgBasis = AggregationGridBasis.CreateSequence(solver.MultigridSequence, solver.CurrentSolution.Mapping.BasisS); MultigridOperator mgOp = new MultigridOperator(MgBasis, solver.CurrentSolution.Mapping, OpMatrix, null, solver.MultigridOperatorConfig); // extract //////////// MsrMatrix FullMatrix = mgOp.OperatorMatrix.ToMsrMatrix(); MsrMatrix DiffMatrix; { int[] VelVarIdx = D.ForLoop(d => d); int[] USubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(VelVarIdx); int[] USubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(VelVarIdx); int L = USubMatrixIdx_Row.Length; DiffMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(DiffMatrix, USubMatrixIdx_Row, default(int[]), USubMatrixIdx_Col, default(int[])); double DiffMatrix_sd = DiffMatrix.SymmetryDeviation(); Console.WriteLine("Diffusion assymetry:" + DiffMatrix_sd); } MsrMatrix SaddlePointMatrix; { int[] VelPVarIdx = new int[] { 0, 1, 2 }; int[] VelPSubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(VelPVarIdx); int[] VelPSubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(VelPVarIdx); int L = VelPSubMatrixIdx_Row.Length; SaddlePointMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(SaddlePointMatrix, VelPSubMatrixIdx_Row, default(int[]), VelPSubMatrixIdx_Col, default(int[])); } //SaddlePointMatrix.SaveToTextFileSparse("C:\\Users\\kikker\\Documents\\MATLAB\\spm.txt"); MsrMatrix ConstitutiveMatrix; { int[] StressVarIdx = new int[] { 3, 4, 5 }; int[] StressSubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(StressVarIdx); int[] StressSubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(StressVarIdx); int L = StressSubMatrixIdx_Row.Length; ConstitutiveMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(ConstitutiveMatrix, StressSubMatrixIdx_Row, default(int[]), StressSubMatrixIdx_Col, default(int[])); } // operator analysis ////////////////////// bool posDef; if (AnalysisLevel > 1) { // +++++++++++++++++++++++++++++++ // check condition number, etc // +++++++++++++++++++++++++++++++ MultidimensionalArray ret = MultidimensionalArray.Create(1, 5); Console.WriteLine("Calling MATLAB/Octave..."); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(FullMatrix, "FullMatrix"); bmc.PutSparseMatrix(SaddlePointMatrix, "SaddlePointMatrix"); bmc.PutSparseMatrix(ConstitutiveMatrix, "ConstitutiveMatrix"); bmc.PutSparseMatrix(DiffMatrix, "DiffMatrix"); bmc.Cmd("DiffMatrix = 0.5*(DiffMatrix + DiffMatrix');"); bmc.Cmd("condNoFullMatrix = condest(FullMatrix);"); bmc.Cmd("condNoSaddlePointMatrix = condest(SaddlePointMatrix);"); bmc.Cmd("condNoConstitutiveMatrix = condest(ConstitutiveMatrix);"); bmc.Cmd("condNoDiffMatrix = condest(DiffMatrix);"); //bmc.Cmd("eigiMaxiSaddle = 1.0; % eigs(SaddlePointMatrix,1,'lm')"); //bmc.Cmd("eigiMiniSaddle = 1.0; % eigs(SaddlePointMatrix,1,'sm')"); //bmc.Cmd("eigiMaxiConst = 1.0; % eigs(ConstitutiveMatrix,1,'lm')"); //bmc.Cmd("eigiMiniConst = 1.0; % eigs(ConstitutiveMatrix,1,'sm')"); //bmc.Cmd("eigiMaxiDiff = 1.0; % eigs(DiffMatrix,1,'lm')"); //bmc.Cmd("eigiMiniDiff = 1.0; % eigs(DiffMatrix,1,'sm')"); bmc.Cmd("lasterr"); bmc.Cmd("[V,r]=chol(SaddlePointMatrix);"); bmc.Cmd("[V,r]=chol(ConstitutiveMatrix);"); bmc.Cmd("ret = [condNoFullMatrix, condNoSaddlePointMatrix, condNoConstitutiveMatrix, condNoDiffMatrix, r]"); //eigiMaxiSaddle, eigiMiniSaddle, eigiMaxiConst, eigiMiniConst, eigiMaxiDiff, eigiMiniDiff, bmc.GetMatrix(ret, "ret"); bmc.Execute(false); } double condNoFullMatrix = ret[0, 0]; double condNoSaddlePMatrix = ret[0, 1]; double condNoConstitutiveMatrix = ret[0, 2]; double condNoDiffMatrix = ret[0, 3]; //double eigiMaxiSaddle = ret[0, 4]; //double eigiMiniSaddle = ret[0, 5]; //double eigiMaxiConst = ret[0, 6]; //double eigiMiniConst = ret[0, 7]; //double eigiMaxiDiff = ret[0, 8]; //double eigiMiniDiff = ret[0, 9]; posDef = ret[0, 4] == 0; //Console.WriteLine("Eigenvalue range of saddle point matrix: {0} to {1}", eigiMiniSaddle, eigiMaxiSaddle); //Console.WriteLine("Eigenvalue range of constitutive matrix: {0} to {1}", eigiMiniConst, eigiMaxiConst); //Console.WriteLine("Eigenvalue range of diffusion matrix: {0} to {1}", eigiMiniDiff, eigiMaxiDiff); Console.WriteLine("Condition number full operator: {0:0.####E-00}", condNoFullMatrix); Console.WriteLine("Condition number saddle point operator: {0:0.####E-00}", condNoSaddlePMatrix); Console.WriteLine("Condition number constitutive operator: {0:0.####E-00}", condNoConstitutiveMatrix); Console.WriteLine("Condition number diffusion operator: {0:0.####E-00}", condNoDiffMatrix); //base.QueryHandler.ValueQuery("ConditionNumber", condNoFullMatrix); } else { // +++++++++++++++++++++++++++++++++++++++ // test only for positive definiteness // +++++++++++++++++++++++++++++++++++++++ var SaddlePMatrixFull = SaddlePointMatrix.ToFullMatrixOnProc0(); var ConstMatrixFull = ConstitutiveMatrix.ToFullMatrixOnProc0(); posDef = true; try { SaddlePMatrixFull.Cholesky(); } catch (ArithmeticException) { posDef = false; } posDef = true; try { ConstMatrixFull.Cholesky(); } catch (ArithmeticException) { posDef = false; } } double SaddlePSymm = SaddlePointMatrix.SymmetryDeviation(); Console.WriteLine("Symmetry deviation of saddle point matrix: " + SaddlePSymm); if (posDef) { Console.WriteLine("Good news: Saddle point operator matrix seems to be positive definite."); } else { Console.WriteLine("WARNING: Saddle point operator matrix is not positive definite."); } double ConstSymm = ConstitutiveMatrix.SymmetryDeviation(); Console.WriteLine("Symmetry deviation of constitutive matrix: " + ConstSymm); if (posDef) { Console.WriteLine("Good news: constitutive operator matrix seems to be positive definite."); } else { Console.WriteLine("WARNING: constitutive operator matrix is not positive definite."); } //if (CheckAssertions) { // if (Control.AdvancedDiscretizationOptions.ViscosityMode == ViscosityMode.FullySymmetric && Control.PhysicalParameters.IncludeConvection == false) { // Assert.IsTrue(posDef, "Positive definiteness test failed."); // double compVal = DiffMatrix.InfNorm() * 1e-13; // Assert.LessOrEqual(DiffSymm, compVal, "Diffusion matrix seems to be non-symmetric."); // } //} } } }
public XDGTestSetup( int p, double AggregationThreshold, int TrackerWidth, MultigridOperator.Mode mumo, XQuadFactoryHelper.MomentFittingVariants momentFittingVariant, ScalarFunction LevSetFunc = null) { // Level set, tracker and XDG basis // ================================ if (LevSetFunc == null) { LevSetFunc = ((_2D)((x, y) => 0.8 * 0.8 - x * x - y * y)).Vectorize(); } LevSet = new LevelSet(new Basis(grid, 2), "LevelSet"); LevSet.Clear(); LevSet.ProjectField(LevSetFunc); LsTrk = new LevelSetTracker(grid, XQuadFactoryHelper.MomentFittingVariants.Classic, TrackerWidth, new string[] { "A", "B" }, LevSet); LsTrk.UpdateTracker(); XB = new XDGBasis(LsTrk, p); XSpatialOperator Dummy = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "C1", "u"); //Dummy.EquationComponents["c1"].Add(new Dummy.Commit(); //Tecplot.PlotFields(new DGField[] { LevSet }, "agglo", 0.0, 3); // operator // ======== Debug.Assert(p <= 4); XDGBasis opXB = new XDGBasis(LsTrk, 4); // we want to have a very precise quad rule var map = new UnsetteledCoordinateMapping(opXB); int quadOrder = Dummy.QuadOrderFunction(map.BasisS.Select(bs => bs.Degree).ToArray(), new int[0], map.BasisS.Select(bs => bs.Degree).ToArray()); //agg = new MultiphaseCellAgglomerator(new CutCellMetrics(momentFittingVariant, quadOrder, LsTrk, LsTrk.SpeciesIdS.ToArray()), AggregationThreshold, false); agg = LsTrk.GetAgglomerator(LsTrk.SpeciesIdS.ToArray(), quadOrder, __AgglomerationTreshold: AggregationThreshold); foreach (var S in LsTrk.SpeciesIdS) { Console.WriteLine("Species {0}, no. of agglomerated cells {1} ", LsTrk.GetSpeciesName(S), agg.GetAgglomerator(S).AggInfo.SourceCells.Count()); } // mass matrix factory // =================== // Basis maxB = map.BasisS.ElementAtMax(b => b.Degree); //MassFact = new MassMatrixFactory(maxB, agg); MassFact = LsTrk.GetXDGSpaceMetrics(LsTrk.SpeciesIdS.ToArray(), quadOrder, 1).MassMatrixFactory; // Test field // ========== // set the test field: this is a polynomial function, // but different for each species; On this field, restriction followed by prolongation should be the identity this.Xdg_uTest = new XDGField(this.XB, "uTest"); Dictionary <SpeciesId, double> dumia = new Dictionary <SpeciesId, double>(); int i = 2; foreach (var Spc in LsTrk.SpeciesIdS) { dumia.Add(Spc, i); i -= 1; } SetTestValue(Xdg_uTest, dumia); // dummy operator matrix which fits polynomial degree p // ==================================================== Xdg_opMtx = new BlockMsrMatrix(Xdg_uTest.Mapping, Xdg_uTest.Mapping); Xdg_opMtx.AccEyeSp(120.0); // XDG Aggregation BasiseS // ======================= //XAggB = MgSeq.Select(agGrd => new XdgAggregationBasis[] { new XdgAggregationBasis(uTest.Basis, agGrd) }).ToArray(); XAggB = new XdgAggregationBasis[MgSeq.Length][]; var _XAggB = AggregationGridBasis.CreateSequence(MgSeq, Xdg_uTest.Mapping.BasisS); for (int iLevel = 0; iLevel < XAggB.Length; iLevel++) { XAggB[iLevel] = new[] { (XdgAggregationBasis)(_XAggB[iLevel][0]) }; XAggB[iLevel][0].Update(agg); } // Multigrid Operator // ================== Xdg_opMtx = new BlockMsrMatrix(Xdg_uTest.Mapping, Xdg_uTest.Mapping); Xdg_opMtx.AccEyeSp(120.0); XdgMultigridOp = new MultigridOperator(XAggB, Xdg_uTest.Mapping, Xdg_opMtx, MassFact.GetMassMatrix(Xdg_uTest.Mapping, false), new MultigridOperator.ChangeOfBasisConfig[][] { new MultigridOperator.ChangeOfBasisConfig[] { new MultigridOperator.ChangeOfBasisConfig() { VarIndex = new int[] { 0 }, mode = mumo, Degree = p } } }); }
private void ConsistencyTest() { // consistency test on the original matrix // ----------------------------------------------------- this.residual.Clear(); double[] RHSvec = this.GetRHS(); this.residual.CoordinateVector.SetV(RHSvec, 1.0); this.Op_Matrix.SpMV(-1.0, this.u.CoordinateVector, 1.0, residual.CoordinateVector); double residual_L2Norm = this.residual.L2Norm(); Console.WriteLine("Residual norm: " + residual_L2Norm); Assert.LessOrEqual(residual_L2Norm, 1.0e-8); // consistency test on the multigrid // -------------------------------------------------------------------- AggregationGridBasis[][] XAggB = AggregationGridBasis.CreateSequence(base.MultigridSequence, u.Mapping.BasisS); XAggB.UpdateXdgAggregationBasis(this.Op_Agglomeration); 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), new MultigridOperator.ChangeOfBasisConfig[][] { new MultigridOperator.ChangeOfBasisConfig[] { new MultigridOperator.ChangeOfBasisConfig() { VarIndex = new int[] { 0 }, mode = MultigridOperator.Mode.Eye, Degree = u.Basis.Degree } } }); double[] mgSolVec = new double[MultigridOp.Mapping.LocalLength]; double[] mgRhsVec = new double[MultigridOp.Mapping.LocalLength]; MultigridOp.TransformSolInto(this.u.CoordinateVector, mgSolVec); MultigridOp.TransformRhsInto(RHSvec, mgRhsVec); MgConsistencyTestRec(MultigridOp, mgSolVec, mgRhsVec); // /* * { * int Jagg1 = MgSeq[1].NoOfAggregateCells; * MultigridOperator MgOp0 = MultigridOp; * MultigridOperator MgOp1 = MultigridOp.CoarserLevel; * MultigridMapping Map0 = MgOp0.Mapping; * MultigridMapping Map1 = MgOp1.Mapping; * * * double[] V0 = new double[MgOp0.Mapping.LocalLength]; * double[] V1 = new double[MgOp1.Mapping.LocalLength]; * * for(int j = 0; j < Jagg1; j++) { * int idx = Map1.LocalUniqueIndex(0, j, 0); * V1[idx] = j; * } * * MgOp1.Prolongate(1.0, V0, 0.0, V1); * * XDGField Marker = new XDGField(this.u.Basis, "Tracker"); * * MgOp0.TransformSolFrom(Marker.CoordinatesAsVector, V0); * this.Op_Agglomeration.Extrapolate(Marker.CoordinatesAsVector, Marker.Mapping); * * Tecplot.PlotFields(new DGField[] { Marker }, "Tracker", "Tracker", 0.0, 5); * * } */ }
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."); } }
/// <summary> /// Prolongation/Injection operator to finer grid level. /// </summary> public BlockMsrMatrix GetProlongationOperator(MultigridMapping finerLevel) { using (new FuncTrace()) { // Argument checking // ================= if (!object.ReferenceEquals(finerLevel.AggGrid, this.AggGrid.ParentGrid)) { throw new ArgumentException("Only prolongation/injection to next level is supported."); } if (finerLevel.AggBasis.Length != this.AggBasis.Length) { throw new ArgumentException(""); } int NoOfVar = this.AggBasis.Length; MultidimensionalArray[][] InjOp = new MultidimensionalArray[NoOfVar][]; AggregationGridBasis[] B = new AggregationGridBasis[NoOfVar]; bool[] useX = new bool[NoOfVar]; int[] DegreeS = new int[NoOfVar]; int[] DegreeSfine = new int[NoOfVar]; for (int iVar = 0; iVar < NoOfVar; iVar++) { InjOp[iVar] = this.AggBasis[iVar].InjectionOperator; B[iVar] = AggBasis[iVar]; DegreeS[iVar] = this.DgDegree[iVar]; DegreeSfine[iVar] = finerLevel.DgDegree[iVar]; if (DegreeSfine[iVar] < DegreeS[iVar]) { throw new ArgumentException("Lower DG degree on finer grid is not supported by this method "); } useX[iVar] = this.AggBasis[iVar] is XdgAggregationBasis; if (useX[iVar] != (finerLevel.AggBasis[iVar] is XdgAggregationBasis)) { throw new ArgumentException("XDG / DG mismatch between this and finer level for " + iVar + "-th variable."); } } XdgAggregationBasis XB = null; XdgAggregationBasis XBf = null; int[][,] spcIdxMap = null; SpeciesId[][] spc = null; //SpeciesId[][] spcf = null; for (int iVar = 0; iVar < NoOfVar; iVar++) { if (useX[iVar]) { XB = (XdgAggregationBasis)(B[iVar]); XBf = (XdgAggregationBasis)(finerLevel.AggBasis[iVar]); spcIdxMap = XB.SpeciesIndexMapping; spc = XB.AggCellsSpecies; //spcf = XBf.AggCellsSpecies; break; } } int[] Np = this.AggBasis[0].GetNp(); int[] Np_fine = finerLevel.AggBasis[0].GetNp(); // create matrix // ============= // init retval var PrlgMtx = new BlockMsrMatrix(finerLevel, this); int[][] C2F = this.AggGrid.jCellCoarse2jCellFine; int JCoarse = this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; //Debug.Assert((JCoarse == C2F.Length) || ()); for (int jc = 0; jc < JCoarse; jc++) // loop over coarse cells... { int[] AggCell = C2F[jc]; int I = AggCell.Length; for (int iVar = 0; iVar < NoOfVar; iVar++) { int DgDeg = DegreeS[iVar]; int DgDegF = DegreeSfine[iVar]; MultidimensionalArray Inj_iVar_jc = InjOp[iVar][jc]; Debug.Assert(Inj_iVar_jc.GetLength(0) == I); bool useX_iVar = false; if (useX[iVar]) { if (spcIdxMap[jc] != null) { useX_iVar = true; } } if (useX_iVar) { //throw new NotImplementedException("todo"); int NoOfSpc = XB.GetNoOfSpecies(jc); int Np_col = Np[DgDeg]; Debug.Assert(Np_col * NoOfSpc == B[iVar].GetLength(jc, DgDeg)); for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) // loop over species { SpeciesId spc_jc_i = spc[jc][iSpc]; int Col0 = this.GlobalUniqueIndex(iVar, jc, Np_col * iSpc); for (int i = 0; i < I; i++) // loop over finer cells { int jf = AggCell[i]; int iSpc_Row = XBf.GetSpeciesIndex(jf, spc_jc_i); if (iSpc_Row < 0) { // nothing to do continue; } int Np_row = Np_fine[DgDegF]; Debug.Assert(Np_row * XBf.GetNoOfSpecies(jf) == finerLevel.AggBasis[iVar].GetLength(jf, DgDegF)); int Row0 = finerLevel.GlobalUniqueIndex(iVar, jf, Np_row * iSpc_Row); //if(Row0 <= 12 && 12 < Row0 + Np_row) { // if(Col0 <= 3 && 3 < Col0 + Np_col) { // Debugger.Break(); // } //} PrlgMtx.AccBlock(Row0, Col0, 1.0, Inj_iVar_jc.ExtractSubArrayShallow(new[] { i, 0, 0 }, new[] { i - 1, Np_row - 1, Np_col - 1 })); } } } else { // ++++++++++++++++++ // standard DG branch // ++++++++++++++++++ int Np_col = Np[DgDeg]; Debug.Assert(Np_col == B[iVar].GetLength(jc, DgDeg)); int Col0 = this.GlobalUniqueIndex(iVar, jc, 0); for (int i = 0; i < I; i++) // loop over finer cells { int jf = AggCell[i]; int Np_row = Np_fine[DgDegF]; Debug.Assert(Np_row == finerLevel.AggBasis[iVar].GetLength(jf, DgDegF)); int Row0 = finerLevel.GlobalUniqueIndex(iVar, jf, 0); PrlgMtx.AccBlock(Row0, Col0, 1.0, Inj_iVar_jc.ExtractSubArrayShallow(new[] { i, 0, 0 }, new[] { i - 1, Np_row - 1, Np_col - 1 })); //if(Row0 <= 12 && 12 < Row0 + Np_row) { // if(Col0 <= 3 && 3 < Col0 + Np_col) { // Debugger.Break(); // } // } } } } } // return // ====== return(PrlgMtx); } }
private static void ExtractBlock(int jCell, AggregationGridBasis basis, int[] Degrees, ChangeOfBasisConfig conf, int E, int[] _i0s, bool Sp2Full, BlockMsrMatrix MtxSp, ref MultidimensionalArray MtxFl) { int NN = conf.VarIndex.Sum(iVar => basis.GetLength(jCell, Degrees[iVar])); if (MtxFl == null || MtxFl.NoOfRows != NN) { Debug.Assert(Sp2Full == true); MtxFl = MultidimensionalArray.Create(NN, NN); } else { if (Sp2Full) { MtxFl.Clear(); } } if (!Sp2Full) { Debug.Assert(MtxSp != null); } int i0Rowloc = 0; for (int eRow = 0; eRow < E; eRow++) // loop over variables in configuration { int i0Row = _i0s[eRow]; int iVarRow = conf.VarIndex[eRow]; int NRow = basis.GetLength(jCell, Degrees[iVarRow]); int i0Colloc = 0; for (int eCol = 0; eCol < E; eCol++) // loop over variables in configuration { int i0Col = _i0s[eCol]; int iVarCol = conf.VarIndex[eCol]; int NCol = basis.GetLength(jCell, Degrees[iVarCol]); MultidimensionalArray MtxFl_blk; if (i0Rowloc == 0 && NRow == MtxFl.GetLength(0) && i0Colloc == 0 && NCol == MtxFl.GetLength(1)) { MtxFl_blk = MtxFl; } else { MtxFl_blk = MtxFl.ExtractSubArrayShallow(new[] { i0Rowloc, i0Colloc }, new[] { i0Rowloc + NRow - 1, i0Colloc + NCol - 1 }); } /* * for(int n_row = 0; n_row < NRow; n_row++) { // row loop... * for(int n_col = 0; n_col < NCol; n_col++) { // column loop... * if(Sp2Full) { * // copy from sparse to full * MtxFl[n_row + i0Rowloc, n_col + i0Colloc] = (MtxSp != null) ? ( MtxSp[n_row + i0Row, n_col + i0Col]) : (n_col == n_row ? 1.0 : 0.0); * } else { * // the other way around. * MtxSp[n_row + i0Row, n_col + i0Col] = MtxFl[n_row + i0Rowloc, n_col + i0Colloc]; * } * } * } */ if (Sp2Full) { if (MtxSp != null) { MtxSp.ReadBlock(i0Row, i0Col, MtxFl_blk); } else { MtxFl_blk.AccEye(1.0); } } else { #if DEBUG Debug.Assert(MtxSp != null); //for (int n_row = 0; n_row < NRow; n_row++) { // row loop... // for (int n_col = 0; n_col < NCol; n_col++) { // column loop... // Debug.Assert(MtxSp[n_row + i0Row, n_col + i0Col] == 0.0); // } //} #endif MtxSp.AccBlock(i0Row, i0Col, 1.0, MtxFl_blk, 0.0); } #if DEBUG for (int n_row = 0; n_row < NRow; n_row++) // row loop... { for (int n_col = 0; n_col < NCol; n_col++) // column loop... { Debug.Assert(MtxFl[n_row + i0Rowloc, n_col + i0Colloc] == ((MtxSp != null) ? (MtxSp[n_row + i0Row, n_col + i0Col]) : (n_col == n_row ? 1.0 : 0.0))); } } #endif i0Colloc += NCol; } i0Rowloc += NRow; } }