/// <summary> /// Adds an XDG field. /// </summary> public static void AddDGField(this TestingIO t, XDGField f) { var trk = f.Basis.Tracker; foreach (string spc in trk.SpeciesNames) { var fs = f.GetSpeciesShadowField(spc); SinglePhaseField fsFatClone = new SinglePhaseField(fs.Basis, fs.Identification); CellMask msk = trk.Regions.GetSpeciesMask(spc); fsFatClone.Acc(1.0, fs, msk); t.AddDGField(fsFatClone); } }
/// <summary> /// Mainly, comparison of single-core vs MPI-parallel run /// </summary> void TestLengthScales(int quadOrder, int TimestepNo) { string name_disc = $"t{TimestepNo}-alpha{this.THRESHOLD}-p{this.DEGREE}-q{MomentFittingVariant}"; var spcA = LsTrk.GetSpeciesId("A"); var spcB = LsTrk.GetSpeciesId("B"); var species = new[] { spcA, spcB }; //MultiphaseCellAgglomerator.CheckFile = $"InsideMpagg-{name_disc}.csv"; MultiphaseCellAgglomerator Agg = LsTrk.GetAgglomerator(species, quadOrder, this.THRESHOLD); int RefMPIsize = 1; // check level-set coordinates // =========================== { var LsChecker = new TestingIO(this.GridData, $"LevelSets-{name_disc}.csv", RefMPIsize); LsChecker.AddDGField(this.Phi0); LsChecker.AddDGField(this.Phi1); LsChecker.DoIOnow(); Assert.Less(LsChecker.AbsError(this.Phi0), 1.0e-8, "Mismatch in level-set 0 between single-core and parallel run."); Assert.Less(LsChecker.AbsError(this.Phi1), 1.0e-8, "Mismatch in level-set 1 between single-core and parallel run."); } // check equality of agglomeration // =============================== // Note: agglomeration in parallel and serial mode is not necessarily equal - but very often it is. // Therefore, we need to check whether the agglomeration is equal or not, // in order to know whether agglomerated length scales should be compared or not. bool[] equalAggAsinReferenceRun; { var aggoCheck = new TestingIO(this.GridData, $"Agglom-{name_disc}.csv", RefMPIsize); long[] GiDs = GridData.CurrentGlobalIdPermutation.Values; int J = GridData.iLogicalCells.NoOfLocalUpdatedCells; long[] extGiDs = GridData.iParallel.GlobalIndicesExternalCells; for (int iSpc = 0; iSpc < species.Length; iSpc++) { var spc = species[iSpc]; var spcN = LsTrk.GetSpeciesName(spc); var ai = Agg.GetAgglomerator(spc).AggInfo; var srcMask = ai.SourceCells.GetBitMask(); var aggPairs = ai.AgglomerationPairs; aggoCheck.AddColumn($"SourceCells{spcN}", delegate(double[] X, int j, int jG) { if (srcMask[j]) { var pair = aggPairs.Single(cap => cap.jCellSource == j); if (pair.jCellTarget < J) { return((double)GiDs[pair.jCellTarget]); } else { return((double)extGiDs[pair.jCellTarget - J]); } } return(0.0); }); } aggoCheck.DoIOnow(); equalAggAsinReferenceRun = new bool[species.Length]; for (int iSpc = 0; iSpc < species.Length; iSpc++) { var spc = species[iSpc]; var spcN = LsTrk.GetSpeciesName(spc); equalAggAsinReferenceRun[iSpc] = aggoCheck.AbsError($"SourceCells{spcN}") < 0.1; if (equalAggAsinReferenceRun[iSpc] == false) { Console.WriteLine("Different agglomeration between single-core and parallel run for species " + spcN + "."); } } //Agg.PlotAgglomerationPairs($"-aggPairs-{name_disc}-MPI{MPIRank + 1}of{MPISize}"); } // compare length scales // ===================== csMPI.Raw.Comm_Rank(csMPI.Raw._COMM.WORLD, out int rank); foreach (ICutCellMetrics ccm in new ICutCellMetrics[] { Agg.NonAgglomeratedMetrics, Agg }) // loop over non-agglom and agglomerated metrics { string name; bool Agglom; if (object.ReferenceEquals(ccm, Agg)) { name = "Agglomerated"; Agglom = true; } else { name = "Nonagglom"; Agglom = false; } MultidimensionalArray CellSurfaceA = ccm.CellSurface[spcA]; MultidimensionalArray CellVolumeA = ccm.CutCellVolumes[spcA]; MultidimensionalArray CellSurfaceB = ccm.CellSurface[spcB]; MultidimensionalArray CellVolumeB = ccm.CutCellVolumes[spcB]; string FileName = $"{name}LengthScales-{name_disc}.csv"; var Checker = new TestingIO(this.GridData, FileName, RefMPIsize); Checker.AddColumn("CellSurfA", (double[] X, int j, int jG) => CellSurfaceA[j]); Checker.AddColumn("CellVolA", (double[] X, int j, int jG) => CellVolumeA[j]); Checker.AddColumn("CellSurfB", (double[] X, int j, int jG) => CellSurfaceB[j]); Checker.AddColumn("CellVolB", (double[] X, int j, int jG) => CellVolumeB[j]); Checker.DoIOnow(); if (this.MPISize == 1) { var Checker2 = new TestingIO(this.GridData, FileName, int.MaxValue); Checker2.AddColumn("CellSurfA", (double[] X, int j, int jG) => CellSurfaceA[j]); Checker2.AddColumn("CellVolA", (double[] X, int j, int jG) => CellVolumeA[j]); Checker2.AddColumn("CellSurfB", (double[] X, int j, int jG) => CellSurfaceB[j]); Checker2.AddColumn("CellVolB", (double[] X, int j, int jG) => CellVolumeB[j]); Checker2.DoIOnow(); foreach (string s in Checker2.ColumnNames) { Assert.Less(Checker2.RelError(s), 1.0e-10, "'TestingUtils.Compare' itself is f****d up."); } } double srfA = Checker.RelError("CellSurfA") * ((!Agglom || equalAggAsinReferenceRun[0]) ? 1.0 : 0.0); double volA = Checker.RelError("CellVolA") * ((!Agglom || equalAggAsinReferenceRun[0]) ? 1.0 : 0.0); double srfB = Checker.RelError("CellSurfB") * ((!Agglom || equalAggAsinReferenceRun[1]) ? 1.0 : 0.0); double volB = Checker.RelError("CellVolB") * ((!Agglom || equalAggAsinReferenceRun[1]) ? 1.0 : 0.0); if (srfA + volA + srfB + volB > 0.001) { Console.WriteLine($"Mismatch in {name} cell surface for species A between single-core and parallel run: {srfA}."); Console.WriteLine($"Mismatch in {name} cell volume for species A between single-core and parallel run: {volA}."); Console.WriteLine($"Mismatch in {name} cell surface for species B between single-core and parallel run: {srfB}."); Console.WriteLine($"Mismatch in {name} cell volume for species B between single-core and parallel run: {volB}."); } Assert.Less(srfA, BLAS.MachineEps.Sqrt(), $"Mismatch in {name} cell surface for species A between single-core and parallel run."); Assert.Less(volA, BLAS.MachineEps.Sqrt(), $"Mismatch in {name} cell volume for species A between single-core and parallel run."); Assert.Less(srfB, BLAS.MachineEps.Sqrt(), $"Mismatch in {name} cell surface for species B between single-core and parallel run."); Assert.Less(volB, BLAS.MachineEps.Sqrt(), $"Mismatch in {name} cell volume for species B between single-core and parallel run."); } }