/// <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()); }
public static void MapConsistencyTest( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder ) { //if no selection is chosen mapping should be the same as of origin //assume: indexing is right 'cause of other tests Utils.TestInit((int)UseXdg, DGOrder); Console.WriteLine("MapConsistencyTest({0},{1})", UseXdg, DGOrder); //Arrange MultigridOperator MGOp = Utils.CreateTestMGOperator(UseXdg, DGOrder); var sbs = new SubBlockSelector(MGOp.Mapping); var mask = new BlockMask(sbs); var stw = new Stopwatch(); stw.Restart(); //Act --- Create Mapping from mask stw.Start(); var submatrix = mask.GetSubBlockMatrix(MGOp.OperatorMatrix); stw.Stop(); var rowpart = submatrix._RowPartitioning; var colpart = submatrix._ColPartitioning; //Assert --- Equal Partition of mask and origin Assert.AreEqual(rowpart, colpart); Assert.IsTrue(rowpart.IsLocallyEqual(MGOp.Mapping)); }
private static void MgConsistencyTestRec(MultigridOperator mgOp, double[] mgSolVec, double[] mgRhsVec) { double[] mgResidual = mgRhsVec.CloneAs(); mgOp.OperatorMatrix.SpMV(1.0, mgSolVec, -1.0, mgResidual); double scale = 1.0 / (mgRhsVec.L2Norm() + mgSolVec.L2Norm()); int DOFs = mgOp.Mapping.TotalLength; Debug.Assert(DOFs == mgOp.OperatorMatrix.NoOfRows); Debug.Assert(DOFs == mgOp.OperatorMatrix.NoOfCols); double mgResidual_l2Norm = mgResidual.L2Norm(); Console.WriteLine("Multigrid Residual norm, level {0}: {1} ({2} DOFs)", mgOp.LevelIndex, mgResidual_l2Norm, DOFs); Assert.LessOrEqual(scale * mgResidual_l2Norm, 1.0e-8); if (mgOp.CoarserLevel != null) { double[] mgCoarseSolVec = new double[mgOp.CoarserLevel.Mapping.LocalLength]; double[] mgCoarseRhsVec = new double[mgOp.CoarserLevel.Mapping.LocalLength]; mgOp.CoarserLevel.Restrict(mgSolVec, mgCoarseSolVec); mgOp.CoarserLevel.Restrict(mgRhsVec, mgCoarseRhsVec); MgConsistencyTestRec(mgOp.CoarserLevel, mgCoarseSolVec, mgCoarseRhsVec); } }
/// <summary> /// Restricts some solution vector down to a certain multigrid level and prolongates it back. /// </summary> /// <param name="i"> /// Multigrid level index; usually 0 at start of recursion. /// </param> /// <param name="iEnd"> /// End level index. /// </param> /// <param name="mgOp"></param> /// <param name="FineIn"> /// Input; solution vector which will be restricted down to level <paramref name="iEnd"/>. /// </param> /// <param name="FineOut"> /// Output; vector <paramref name="FineIn"/> restricted to level <paramref name="iEnd"/>, and prolongated back to level <paramref name="i"/>. /// </param> static void XDG_Recursive(int i, int iEnd, MultigridOperator mgOp, double[] FineIn, double[] FineOut) { MultigridMapping mgMap = mgOp.Mapping; int Lfin = mgMap.LocalLength; int Lcrs = mgOp.CoarserLevel.Mapping.LocalLength; Assert.IsTrue(FineIn.Length == Lfin); Assert.IsTrue(FineOut.Length == Lfin); double[] Coarse1 = new double[Lcrs]; double[] Coarse2 = new double[Lcrs]; mgOp.CoarserLevel.Restrict(FineIn, Coarse1); if (i == iEnd) { Coarse2.SetV(Coarse1); } else { XDG_Recursive(i + 1, iEnd, mgOp.CoarserLevel, Coarse1, Coarse2); } mgOp.CoarserLevel.Prolongate(1.0, FineOut, 0.0, Coarse2); }
public static void GetExternalRowsTest( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(4)] int Res) { //Matlabaufruf --> gesamte Matrix nach Matlab schreiben //Teilmatritzen gemäß Globalid extrahieren //Mit ExternalRows vergleichen //Die große Frage: funktioniert der batchmode connector parallel? Beim rausschreiben beachten Utils.TestInit((int)UseXdg, DGOrder); Console.WriteLine("GetExternalRowsTest({0},{1})", UseXdg, DGOrder); //Arrange --- setup mgo and mask MultigridOperator mgo = Utils.CreateTestMGOperator(UseXdg, DGOrder, MatrixShape.laplace, Res); MultigridMapping map = mgo.Mapping; BlockMsrMatrix M = mgo.OperatorMatrix; //Delete this plz ... //M.SaveToTextFileSparse("M"); //int[] A = Utils.GimmeAllBlocksWithSpec(map, 9); //int[] B = Utils.GimmeAllBlocksWithSpec(map, 18); //if (map.MpiRank == 0) { // A.SaveToTextFileDebug("ACells"); // B.SaveToTextFileDebug("BCells"); //} var selector = new SubBlockSelector(map); var dummy = new BlockMsrMatrix(map); // we are only interested in getting indices, so a dummy is sufficient var mask = new BlockMask(selector, dummy); //Arrange --- get stuff to put into matlab int[] GlobalIdx_ext = Utils.GetAllExtCellIdc(map); double[] GlobIdx = GlobalIdx_ext.Length.ForLoop(i => (double)GlobalIdx_ext[i] + 1.0); //Arrange --- get external rows by mask BlockMsrMatrix extrows = BlockMask.GetAllExternalRows(mgo.Mapping, mgo.OperatorMatrix); //Assert --- idc and rows of extrows have to be the same Assert.IsTrue(GlobIdx.Length == extrows._RowPartitioning.LocalLength); //Arrange --- get external rows by matlab var infNorm = MultidimensionalArray.Create(1, 1); using (BatchmodeConnector matlab = new BatchmodeConnector()) { //note: BatchmodeCon maybe working on proc0 but savetotxt file, etc. (I/O) is full mpi parallel //so concider this as full mpi-parallel matlab.PutSparseMatrix(M, "M"); matlab.PutSparseMatrix(extrows, "M_test"); matlab.PutVector(GlobIdx, "Idx"); matlab.Cmd(String.Format("M_ext = M(Idx, :);")); matlab.Cmd("n=norm(M_test-M_ext,inf)"); matlab.GetMatrix(infNorm, "n"); matlab.Execute(); } //Assert --- test if we actually got the right Matrix corresponding to Index Assert.IsTrue(infNorm[0, 0] == 0.0); }
public static void SubSelection( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(MatrixShape.full_var_spec, MatrixShape.full_spec, MatrixShape.full_var, MatrixShape.full)] MatrixShape MShape, [Values(4)] int Res) { Utils.TestInit((int)UseXdg, DGOrder, (int)MShape, Res); Console.WriteLine("SubSelection({0},{1},{2},{3})", UseXdg, DGOrder, MShape, Res); //Arrange --- create test matrix, MG mapping MultigridOperator mgo = Utils.CreateTestMGOperator(UseXdg, DGOrder, MShape, Res); MultigridMapping map = mgo.Mapping; BlockMsrMatrix M = mgo.OperatorMatrix; //Arrange --- get mask int[] cells = Utils.GetCellsOfOverlappingTestBlock(map); Array.Sort(cells); var sbs = new SubBlockSelector(map); sbs.CellSelector(cells, false); BlockMsrMatrix M_ext = BlockMask.GetAllExternalRows(map, M); var mask = new BlockMask(sbs, M_ext); //Arrange --- get GlobalIdxList int[] idc = Utils.GetIdcOfSubBlock(map, cells); bool[] coup = Utils.SetCoupling(MShape); var M_sub = mask.GetSubBlockMatrix(M, false, coup[0], coup[1]); var infNorm = MultidimensionalArray.Create(4, 1); int rank = map.MpiRank; using (BatchmodeConnector matlab = new BatchmodeConnector()) { double[] GlobIdx = idc.Count().ForLoop(i => (double)idc[i] + 1.0); Assert.IsTrue(GlobIdx.Length == M_sub.NoOfRows); matlab.PutSparseMatrix(M, "M"); // note: M_sub lives on Comm_Self, therefore we have to distinguish between procs ... matlab.PutSparseMatrixRankExclusive(M_sub, "M_sub"); matlab.PutVectorRankExclusive(GlobIdx, "Idx"); matlab.Cmd("M_0 = full(M(Idx_0, Idx_0));"); matlab.Cmd("M_1 = full(M(Idx_1, Idx_1));"); matlab.Cmd("M_2 = full(M(Idx_2, Idx_2));"); matlab.Cmd("M_3 = full(M(Idx_3, Idx_3));"); matlab.Cmd("n=[0; 0; 0; 0];"); matlab.Cmd("n(1,1)=norm(M_0-M_sub_0,inf);"); matlab.Cmd("n(2,1)=norm(M_1-M_sub_1,inf);"); matlab.Cmd("n(3,1)=norm(M_2-M_sub_2,inf);"); matlab.Cmd("n(4,1)=norm(M_3-M_sub_3,inf);"); matlab.GetMatrix(infNorm, "n"); matlab.Execute(); } Assert.IsTrue(infNorm[rank, 0] == 0.0); }
private static List <ChangeOfBasisConfig[]> MgDescend(MultigridOperator mgo, List <ChangeOfBasisConfig[]> cobc) { cobc.Add(mgo.Config); if (mgo.CoarserLevel != null) { return(MgDescend(mgo.CoarserLevel, cobc)); } else { return(cobc); } }
public void Init(MultigridOperator op) { this.m_MgOp = op; int D = this.LsTrk.GridDat.SpatialDimension; int[] VelVarIdx = D.ForLoop(d => d); this.USubMatrixIdx_Row = this.m_MgOp.Mapping.GetSubvectorIndices(VelVarIdx); this.PSubMatrixIdx_Row = this.m_MgOp.Mapping.GetSubvectorIndices(new int[] { D }); this.ExtractMatrices(); }
private static List <AggregationGridBasis[]> MgDescend(MultigridOperator mgo, List <AggregationGridBasis[]> agggb) { agggb.Add(mgo.Mapping.AggBasis); if (mgo.CoarserLevel != null) { return(MgDescend(mgo.CoarserLevel, agggb)); } else { return(agggb); } }
public static void VectorSplitOperation( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(MatrixShape.full_var_spec, MatrixShape.full_spec, MatrixShape.full)] MatrixShape MShape, [Values(4)] int Res) { Utils.TestInit((int)UseXdg, DGOrder, (int)MShape, Res); Console.WriteLine("VectorSplitOperation({0},{1},{2},{3})", UseXdg, DGOrder, MShape, Res); //Arrange --- create test matrix, MG mapping MultigridOperator mgo = Utils.CreateTestMGOperator(UseXdg, DGOrder, MShape, Res); MultigridMapping map = mgo.Mapping; BlockMsrMatrix M = mgo.OperatorMatrix; BlockMsrMatrix M_ext = BlockMask.GetAllExternalRows(map, M); double[] Vec = Utils.GetRandomVector(M_ext.RowPartitioning.LocalLength); //Arrange --- setup masking SubBlockSelector sbsA = new SubBlockSelector(map); sbsA.SetDefaultSplitSelection(MShape, true, false); BlockMask maskA = new BlockMask(sbsA, M_ext); SubBlockSelector sbsB = new SubBlockSelector(map); sbsB.SetDefaultSplitSelection(MShape, false, false); BlockMask maskB = new BlockMask(sbsB, M_ext); double[] VecAB = new double[Vec.Length]; //Arrange --- some time measurement Stopwatch stw = new Stopwatch(); stw.Reset(); //Act --- stw.Start(); var VecA = maskA.GetSubVec(Vec, new double[0]); var VecB = maskB.GetSubVec(Vec, new double[0]); maskA.AccSubVec(VecA, VecAB, new double[0]); maskB.AccSubVec(VecB, VecAB, new double[0]); stw.Stop(); Debug.Assert(Vec.L2Norm() != 0); double fac = ((MShape == MatrixShape.full_var || MShape == MatrixShape.diagonal_var) && UseXdg == XDGusage.none) ? -2.0 : -1.0; VecAB.AccV(fac, Vec); //Assert --- are extracted blocks and Assert.IsTrue(VecAB.L2Norm() == 0.0, String.Format("L2Norm neq 0!")); }
private ConvergenceObserver ActivateCObserver(MultigridOperator mop, BlockMsrMatrix Massmatrix, SolverFactory SF, List <Action <int, double[], double[], MultigridOperator> > Callback) { Console.WriteLine("===Convergence Observer activated==="); //string AnalyseOutputpath = String.Join(@"\",this.Control.DbPath, this.CurrentSessionInfo.ID); string AnalyseOutputpath = System.IO.Directory.GetCurrentDirectory(); var CO = new ConvergenceObserver(mop, Massmatrix, uEx.CoordinateVector.ToArray(), SF); //CO.TecplotOut = String.Concat(AnalyseOutputpath, @"\Xdg_conv"); Callback.Add(CO.IterationCallback); Console.WriteLine("Analysis output will be written to: {0}", AnalyseOutputpath); Console.WriteLine("===================="); return(CO); }
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); }
public static void SubMatrixExtractionWithCoupling( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(MatrixShape.diagonal, MatrixShape.diagonal_var, MatrixShape.full_spec, MatrixShape.full_var_spec)] MatrixShape MShape ) { Utils.TestInit((int)UseXdg, DGOrder, (int)MShape); Console.WriteLine("ExtractSubMatrixAndIgnoreCoupling({0},{1},{2})", UseXdg, DGOrder, MShape); //Arrange --- get multigridoperator MultigridOperator MGOp = Utils.CreateTestMGOperator(UseXdg, DGOrder, MShape); BlockMsrMatrix M = MGOp.OperatorMatrix; MultigridMapping map = MGOp.Mapping; //Arrange --- setup masking SubBlockSelector SBS = new SubBlockSelector(map); BlockMask mask = new BlockMask(SBS, null); bool[] coup = Utils.SetCoupling(MShape); //Arrange --- some time measurement Stopwatch stw = new Stopwatch(); stw.Reset(); //Act --- establish submatrix stw.Start(); //var Ones = M.CloneAs(); //Ones.Clear(); //Ones.SetAll(1); //var extractOnes = mask.GetSubBlockMatrix(Ones, false, coup[0], coup[1]); var Mext = mask.GetSubBlockMatrix(M, false, coup[0], coup[1]); stw.Stop(); var Mquad = M.ConvertToQuadraticBMsr(mask.GlobalIList_Internal.ToArray(), true); Mext.Acc(-1.0, Mquad); //Assert --- Mext conains only diagonal blocks of M Assert.IsTrue(Mext.InfNorm() == 0); }
public void Init(MultigridOperator op) { this.m_MgOp = op; int D = this.LsTrk.GridDat.SpatialDimension; int[] VelVarIdx = D.ForLoop(d => d); this.USubMatrixIdx_Row = this.m_MgOp.Mapping.GetSubvectorIndices(VelVarIdx); this.PSubMatrixIdx_Row = this.m_MgOp.Mapping.GetSubvectorIndices(new int[] { D }); this.USpcSubMatrix_Row = new int[this.LsTrk.SpeciesIdS.Count][]; this.PSpcSubMatrix_Row = new int[this.LsTrk.SpeciesIdS.Count][]; for (int iSpc = 0; iSpc < this.LsTrk.SpeciesIdS.Count; iSpc++) { this.USpcSubMatrix_Row[iSpc] = this.m_MgOp.Mapping.GetSubvectorIndices(this.LsTrk.SpeciesIdS[iSpc], VelVarIdx); this.PSpcSubMatrix_Row[iSpc] = this.m_MgOp.Mapping.GetSubvectorIndices(this.LsTrk.SpeciesIdS[iSpc], D); } this.ExtractMatrices(); this.ApproximationMatrix(); }
public static void ExternalIndexTest( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(4)] int Res ) { Utils.TestInit((int)UseXdg, DGOrder); Console.WriteLine("ExternalIndexTest({0},{1})", UseXdg, DGOrder); //Arrange --- Get global index by mapping MultigridOperator MGOp = Utils.CreateTestMGOperator(UseXdg, DGOrder, MatrixShape.laplace, Res); var map = MGOp.Mapping; int[] GlobalIdxMap_ext = Utils.GetAllExtCellIdc(map); //Arrange --- Prepare stuff for mask var selector = new SubBlockSelector(map); var dummy = new BlockMsrMatrix(map); // we are only interested in getting indices, so a dummy is sufficient var stw = new Stopwatch(); stw.Reset(); //Act --- do the masking to get index lists stw.Start(); var mask = new BlockMask(selector, dummy); stw.Stop(); int[] GlobalIdxMask_ext = mask.GlobalIList_External.ToArray(); //Assert --- Idx lists are of same length Assert.IsTrue(GlobalIdxMap_ext.Length == GlobalIdxMask_ext.Length); //Assert --- Compare map and mask indices for (int iLoc = 0; iLoc < GlobalIdxMask_ext.Length; iLoc++) { Assert.IsTrue(GlobalIdxMask_ext[iLoc] == GlobalIdxMap_ext[iLoc]); } }
public static BlockMsrMatrix GetCellCompMatrix(SelectionType SType, MultigridOperator mop, int iB) { int rank = mop.Mapping.MpiRank; int iBlock = mop.Mapping.AggGrid.CellPartitioning.i0 + iB; int i0 = mop.Mapping.GetBlockI0(iBlock); //int jBlock = i0 + jB; int R = mop.Mapping.GetBlockLen(iBlock); //int C = mop.Mapping.GetBlockLen(jBlock); bool ZwoSpecR = Math.Max(mop.Mapping.GetSubblkLen(0)[0], mop.Mapping.GetSubblkLen(1)[0]) == R; //bool ZwoSpecC = (mop.Mapping.AggBasis[0].GetMaximalLength(DGdegree) + mop.Mapping.AggBasis[0].GetMaximalLength(DGdegree - 1)) == C; SpeciesId A = ((XdgAggregationBasis)mop.Mapping.AggBasis[0]).UsedSpecies[0]; int Specpos = ((XdgAggregationBasis)mop.Mapping.AggBasis[0]).GetSpeciesIndex(iB, A); int[] SubIdcR = GetSubIndices(SType, ZwoSpecR, Specpos); //int[] SubIdcC = GetSubIndices(SType, ZwoSpecC); for (int i = 0; i < SubIdcR.Length; i++) { Debug.Assert(SubIdcR[i] < R); SubIdcR[i] += i0; } //for (int i = 0; i < SubIdcC.Length; i++) { // Debug.Assert(SubIdcC[i] < C); // SubIdcC[i] += i0; //} //return mop.OperatorMatrix.GetSubMatrix(SubIdcR, SubIdcC); var part = new BlockPartitioning(SubIdcR.Length, new int[] { 0 }, new int[] { SubIdcR.Length }, csMPI.Raw._COMM.SELF); BlockMsrMatrix sub = new BlockMsrMatrix(part); mop.OperatorMatrix.WriteSubMatrixTo(sub, SubIdcR, default(int[]), SubIdcR, default(int[])); return(sub); //return mop.OperatorMatrix.GetSubMatrix(SubIdcR, SubIdcR); }
public static void LocalIndexTest( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder) { Utils.TestInit((int)UseXdg, DGOrder); Console.WriteLine("LocalLIndexTest({0},{1})", UseXdg, DGOrder); //Arrange --- Get global index by mapping MultigridOperator MGOp = Utils.CreateTestMGOperator(UseXdg, DGOrder); var map = MGOp.Mapping; int[] fields = map.NoOfVariables.ForLoop(i => i); int[] GlobalIdxMap_loc = map.GetSubvectorIndices(fields); //Arrange --- Prepare stuff for mask var selector = new SubBlockSelector(map); var stw = new Stopwatch(); stw.Reset(); //Act --- do the masking to get index lists stw.Start(); var mask = new BlockMask(selector, null); stw.Stop(); int[] GlobalIdxMask_loc = mask.GlobalIList_Internal.ToArray(); //Assert --- Idx lists are of same length Assert.IsTrue(GlobalIdxMap_loc.Length == GlobalIdxMask_loc.Length); //Assert --- Compare map and mask indices for (int iLoc = 0; iLoc < GlobalIdxMask_loc.Length; iLoc++) { Assert.True(GlobalIdxMap_loc[iLoc] == GlobalIdxMask_loc[iLoc]); } }
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 } } }); }
/// <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."); // } //} } } }
/// <summary> /// Logging of residuals (provisional). /// </summary> virtual protected void LogResis(int iterIndex, double[] currentSol, double[] currentRes, MultigridOperator Mgop) { if (m_ResLogger != null) { int NF = this.CurrentStateMapping.Fields.Count; m_ResLogger.IterationCounter = iterIndex; if (m_TransformedResi) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // transform current solution and residual back to the DG domain // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ var R = this.Residuals; R.Clear(); Mgop.TransformRhsFrom(R, currentRes); //Mgop.TransformSolFrom(X, currentSol); //this.m_Agglomerator.Extrapolate(X, X.Mapping); this.m_CurrentAgglomeration.Extrapolate(R.Mapping); /* * CoordinateVector Solution = new CoordinateVector(this.Residuals.Fields.Select(delegate (DGField f) { * DGField r = f.CloneAs(); * r.Identification = "Sol_" + r.Identification; * return r; * })); * Mgop.TransformSolFrom(Solution, currentSol); * Tecplot.Tecplot.PlotFields(Solution.Fields.Cat(this.Residuals.Fields), "DuringNewton-" + iterIndex, iterIndex, 3); */ for (int i = 0; i < NF; i++) { double L2Res = R.Mapping.Fields[i].L2Norm(); m_ResLogger.CustomValue(L2Res, m_ResidualNames[i]); } } else { // +++++++++++++++++++++++ // un-transformed residual // +++++++++++++++++++++++ var VarIdx = NF.ForLoop(i => Mgop.Mapping.GetSubvectorIndices(i)); for (int i = 0; i < VarIdx.Length; i++) { double L2Res = 0.0; foreach (int idx in VarIdx[i]) { L2Res += currentRes[idx - Mgop.Mapping.i0].Pow2(); } L2Res = L2Res.MPISum().Sqrt(); // would be better to do the MPISum for all L2Res together, // but this implementation is anyway inefficient.... m_ResLogger.CustomValue(L2Res, m_ResidualNames[i]); } } if (Config_LevelSetHandling == LevelSetHandling.Coupled_Iterative) { m_ResLogger.CustomValue(m_LastLevelSetResidual, "LevelSet"); } m_ResLogger.NextIteration(true); } }
private void RKstageImplicit(double PhysTime, double dt, double[][] k, int s, BlockMsrMatrix[] Mass, CoordinateVector u0, double ActualLevSetRelTime, double[] RK_as, double RelTime) { Debug.Assert(s < m_RKscheme.Stages); Debug.Assert(m_RKscheme.c[s] > 0); Debug.Assert(RK_as[s] != 0); int Ndof = m_CurrentState.Count; // ========= // RHS setup // ========= m_ImplStParams = new ImplicitStage_AssiParams() { m_CurrentDt = dt, m_CurrentPhystime = PhysTime, m_IterationCounter = 0, m_ActualLevSetRelTime = ActualLevSetRelTime, m_RelTime = RelTime, m_k = k, m_u0 = u0, m_Mass = Mass, m_RK_as = RK_as, m_s = s }; // ================ // solve the system // ================ NonlinearSolver nonlinSolver; ISolverSmootherTemplate linearSolver; GetSolver(out nonlinSolver, out linearSolver); if (RequiresNonlinearSolver) { // Nonlinear Solver (Navier-Stokes) // -------------------------------- nonlinSolver.SolverDriver(m_CurrentState, default(double[])); // Note: the RHS is passed as the affine part via 'this.SolverCallback' } else { // Linear Solver (Stokes) // ---------------------- // build the saddle-point matrix BlockMsrMatrix System, MaMa; double[] RHS; this.AssembleMatrixCallback(out System, out RHS, out MaMa, CurrentStateMapping.Fields.ToArray(), true); RHS.ScaleV(-1); // update the multigrid operator MultigridOperator mgOperator = new MultigridOperator(this.MultigridBasis, CurrentStateMapping, System, MaMa, this.Config_MultigridOperator); // init linear solver linearSolver.Init(mgOperator); // try to solve the saddle-point system. mgOperator.UseSolver(linearSolver, m_CurrentState, RHS); // 'revert' agglomeration m_CurrentAgglomeration.Extrapolate(CurrentStateMapping); } // ================ // reset // ================ m_ImplStParams = null; }
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); * * } */ }
protected void CustomItCallback(int iterIndex, double[] currentSol, double[] currentRes, MultigridOperator Mgop) { //currentSol.SaveToTextFile("X_"+ iterIndex); //currentRes.SaveToTextFile("Res_" + iterIndex); MaxMlevel = Mgop.LevelIndex; }
protected void CustomItCallback(int iterIndex, double[] currentSol, double[] currentRes, MultigridOperator Mgop) { //noch nix ... MaxMlevel = Mgop.LevelIndex; }
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> /// 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> /// /// </summary> ISolverSmootherTemplate KcycleMultiSchwarz(MultigridOperator op) { var solver = new OrthonormalizationScheme() { MaxIter = 500, Tolerance = 1.0e-10, }; // my tests show that the ideal block size may be around 10'000 int DirectKickIn = base.Control.TargetBlockSize; MultigridOperator Current = op; var PrecondChain = new List<ISolverSmootherTemplate>(); for (int iLevel = 0; iLevel < base.MultigridSequence.Length; iLevel++) { int SysSize = Current.Mapping.TotalLength; int NoOfBlocks = (int)Math.Ceiling(((double)SysSize) / ((double)DirectKickIn)); bool useDirect = false; useDirect |= (SysSize < DirectKickIn); useDirect |= iLevel == base.MultigridSequence.Length - 1; useDirect |= NoOfBlocks.MPISum() <= 1; ISolverSmootherTemplate levelSolver; if (useDirect) { levelSolver = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.PARDISO, TestSolution = false }; } else { Schwarz swz1 = new Schwarz() { m_MaxIterations = 1, CoarseSolver = null, m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { NoOfPartsPerProcess = NoOfBlocks }, Overlap = 2 // overlap seems to help }; SoftPCG pcg1 = new SoftPCG() { m_MinIterations = 5, m_MaxIterations = 5 }; //*/ var pre = new SolverSquence() { SolverChain = new ISolverSmootherTemplate[] { swz1, pcg1 } }; levelSolver = swz1; } if (iLevel > 0) { GenericRestriction[] R = new GenericRestriction[iLevel]; for (int ir = 0; ir < R.Length; ir++) { R[ir] = new GenericRestriction(); if (ir >= 1) R[ir - 1].CoarserLevelSolver = R[ir]; } R[iLevel - 1].CoarserLevelSolver = levelSolver; PrecondChain.Add(R[0]); } else { PrecondChain.Add(levelSolver); } if (useDirect) { Console.WriteLine("Kswz: using {0} levels, lowest level DOF is {1}, target size is {2}.", iLevel + 1, SysSize, DirectKickIn); break; } Current = Current.CoarserLevel; } if (PrecondChain.Count > 1) { /* // construct a V-cycle for (int i = PrecondChain.Count - 2; i>= 0; i--) { PrecondChain.Add(PrecondChain[i]); } */ var tmp = PrecondChain.ToArray(); for (int i = 0; i < PrecondChain.Count; i++) { PrecondChain[i] = tmp[PrecondChain.Count - 1 - i]; } } solver.PrecondS = PrecondChain.ToArray(); solver.MaxKrylovDim = solver.PrecondS.Length * 4; return solver; }
protected void CustomItCallback(int iterIndex, double[] currentSol, double[] currentRes, MultigridOperator Mgop) { MaxMlevel = Mgop.LevelIndex; //currentRes.SaveToTextFileDebug(String.Format("Res_{0}_proc",iterIndex)); //currentSol.SaveToTextFileDebug(String.Format("Sol_{0}_proc",iterIndex)); //Console.WriteLine("Callback executed {0} times",iterIndex); }
/// <summary> /// Ganz ok. /// </summary> ISolverSmootherTemplate MultilevelSchwarz(MultigridOperator op) { var solver = new SoftPCG() { m_MaxIterations = 500, m_Tolerance = 1.0e-12 }; //var solver = new OrthonormalizationScheme() { // MaxIter = 500, // Tolerance = 1.0e-10, //}; //var solver = new SoftGMRES() { // m_MaxIterations = 500, // m_Tolerance = 1.0e-10, //}; // my tests show that the ideal block size may be around 10'000 int DirectKickIn = base.Control.TargetBlockSize; MultigridOperator Current = op; ISolverSmootherTemplate[] MultigridChain = new ISolverSmootherTemplate[base.MultigridSequence.Length]; for (int iLevel = 0; iLevel < base.MultigridSequence.Length; iLevel++) { int SysSize = Current.Mapping.TotalLength; int NoOfBlocks = (int)Math.Ceiling(((double)SysSize) / ((double)DirectKickIn)); bool useDirect = false; useDirect |= (SysSize < DirectKickIn); useDirect |= iLevel == base.MultigridSequence.Length - 1; useDirect |= NoOfBlocks.MPISum() <= 1; if (useDirect) { MultigridChain[iLevel] = new DirectSolver() { WhichSolver = DirectSolver._whichSolver.PARDISO, TestSolution = false }; } else { ClassicMultigrid MgLevel = new ClassicMultigrid() { m_MaxIterations = 1, m_Tolerance = 0.0 // termination controlled by top level PCG }; MultigridChain[iLevel] = MgLevel; ISolverSmootherTemplate pre, pst; if (iLevel > 0) { Schwarz swz1 = new Schwarz() { m_MaxIterations = 1, CoarseSolver = null, m_BlockingStrategy = new Schwarz.METISBlockingStrategy() { NoOfPartsPerProcess = NoOfBlocks }, Overlap = 0 // overlap does **NOT** seem to help }; SoftPCG pcg1 = new SoftPCG() { m_MinIterations = 5, m_MaxIterations = 5 }; SoftPCG pcg2 = new SoftPCG() { m_MinIterations = 5, m_MaxIterations = 5 }; var preChain = new ISolverSmootherTemplate[] { swz1, pcg1 }; var pstChain = new ISolverSmootherTemplate[] { swz1, pcg2 }; pre = new SolverSquence() { SolverChain = preChain }; pst = new SolverSquence() { SolverChain = pstChain }; } else { // +++++++++++++++++++++++++++++++++++++++++++++++++++ // top level - use only iterative (non-direct) solvers // +++++++++++++++++++++++++++++++++++++++++++++++++++ pre = new BlockJacobi() { NoOfIterations = 3, omega = 0.5 }; pst = new BlockJacobi() { NoOfIterations = 3, omega = 0.5 }; //preChain = new ISolverSmootherTemplate[] { pcg1 }; //pstChain = new ISolverSmootherTemplate[] { pcg2 }; } //if (iLevel > 0) { // MgLevel.PreSmoother = pre; // MgLevel.PostSmoother = pst; //} else { // //MgLevel.PreSmoother = pcg1; // ganz schlechte Idee, konvergiert gegen FALSCHE lösung // //MgLevel.PostSmoother = pcg2; // ganz schlechte Idee, konvergiert gegen FALSCHE lösung // MgLevel.PreSmoother = pre; // MgLevel.PostSmoother = pst; //} MgLevel.PreSmoother = pre; MgLevel.PostSmoother = pst; } if (iLevel > 0) { ((ClassicMultigrid)(MultigridChain[iLevel - 1])).CoarserLevelSolver = MultigridChain[iLevel]; } if (useDirect) { Console.WriteLine("MG: using {0} levels, lowest level DOF is {1}, target size is {2}.", iLevel + 1, SysSize, DirectKickIn); break; } Current = Current.CoarserLevel; } // end of level loop solver.Precond = MultigridChain[0]; //solver.PrecondS = new[] { MultigridChain[0] }; return solver; }
protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { LsUpdate(phystime); // operator-matrix assemblieren OperatorMatrix = new BlockMsrMatrix(MG_Mapping.ProblemMapping); AltOperatorMatrix = new MsrMatrix(MG_Mapping.ProblemMapping); double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength]; MultiphaseCellAgglomerator Agg; Agg = LsTrk.GetAgglomerator(this.LsTrk.SpeciesIdS.ToArray(), m_quadOrder, __AgglomerationTreshold: this.THRESHOLD); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, MG_Mapping.ProblemMapping, null, MG_Mapping.ProblemMapping); mtxBuilder.time = 0.0; mtxBuilder.ComputeMatrix(OperatorMatrix, Affine); Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, MG_Mapping.ProblemMapping, MG_Mapping.ProblemMapping); foreach (var S in this.LsTrk.SpeciesNames) { Console.WriteLine(" Species {0}: no of agglomerated cells: {1}", S, Agg.GetAgglomerator(this.LsTrk.GetSpeciesId(S)).AggInfo.SourceCells.NoOfItemsLocally); } MGOp = new MultigridOperator(XAggB, map, OperatorMatrix, this.massFact.GetMassMatrix(map, false), OpConfig, null); Debug.Assert(MGOp.OperatorMatrix != null); Debug.Assert(MGOp.Mapping != null); someVec = GetRHS(Affine, OperatorMatrix); mtxBuilder.ComputeMatrix(AltOperatorMatrix, Affine); Agg.ManipulateMatrixAndRHS(AltOperatorMatrix, Affine, MG_Mapping.ProblemMapping, MG_Mapping.ProblemMapping); //LsTrk.GetSpeciesName(((XdgAggregationBasis)MGOp.Mapping.AggBasis[0]).UsedSpecies[1]); //LsTrk.GetSpeciesName(((XdgAggregationBasis)MGOp.Mapping.AggBasis[0]).UsedSpecies[0]); int nnz = this.OperatorMatrix.GetTotalNoOfNonZeros(); Console.WriteLine("Number of non-zeros in matrix: " + nnz); int nnz2 = this.AltOperatorMatrix.GetTotalNoOfNonZeros(); Assert.IsTrue(nnz == nnz2, "Number of non-zeros in matrix different for " + OperatorMatrix.GetType() + " and " + AltOperatorMatrix.GetType()); Console.WriteLine("Number of non-zeros in matrix (reference): " + nnz2); MsrMatrix Comp = AltOperatorMatrix.CloneAs(); Comp.Acc(-1.0, OperatorMatrix); double CompErr = Comp.InfNorm(); double Denom = Math.Max(AltOperatorMatrix.InfNorm(), OperatorMatrix.InfNorm()); double CompErrRel = Denom > Math.Sqrt(double.Epsilon) ? CompErr / Denom : CompErr; Console.WriteLine("Comparison: " + CompErrRel); Assert.LessOrEqual(CompErrRel, 1.0e-7, "Huge difference between MsrMatrix and BlockMsrMatrix."); base.TerminationKey = true; return(0.0); }