protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { using (new FuncTrace()) { base.NoOfTimesteps = int.MaxValue; base.EndTime = endTime; // Set time step size if (dt <= 0) { dt = dtFixed; } Console.Write("Timestep " + TimestepNo + " ..."); if (phystime >= ChangeMetricTime) { CustomTimestepConstraint.FirstMetricActive = false; } timeStepper.UpdateTimeInfo(new TimeInformation(TimestepNo, phystime, dt)); timeStepper.Perform(dt); Console.WriteLine("finished"); // Print L2 Norm at the end of the simulation run if (EndTime - phystime - dt < 1E-10) { energyNorm = c.L2Norm(); Console.WriteLine("Energy norm = {0:0.000000000000000E-00}", energyNorm); } return(dt); } }
static private bool TestingReclusteringIndependency() { //TestCase: 5x4 grid, AV=false, dgdegree=0, Timestepping=LTS&RK CNSControl ctrRepON = ShockTube_PartTest_Dynamic(5, 4, int.MaxValue, 2, true, 5); CNSControl ctrRepOFF = ShockTube_PartTest_Dynamic(5, 4, int.MaxValue, 2, false, 5); using (var solverRepON = new HilbertTest()) using (var solverRepOFF = new HilbertTest()) { solverRepON.Init(ctrRepON); solverRepON.RunSolverMode(); solverRepOFF.Init(ctrRepOFF); solverRepOFF.RunSolverMode(); bool result = true; string[] varname = { "Desity", "x-Momentum", "y-Momentum", "Energy" }; for (int i = 0; i < 4; i++) { List <DGField> listOfDGFields_RepON = (List <DGField>)solverRepON.IOFields; DGField variableRepON = listOfDGFields_RepON[i]; double L2NormRepON = variableRepON.L2Norm(); List <DGField> listOfDGFields_RepOFF = (List <DGField>)solverRepOFF.IOFields; DGField vriableRepOFF = listOfDGFields_RepOFF[i]; double L2NormRepOFF = vriableRepOFF.L2Norm(); Console.WriteLine("{0}-L2Norm Rep ON: {1}", varname[i], L2NormRepON); Console.WriteLine("{0}-L2Norm Rep OFF: {1}", varname[i], L2NormRepOFF); bool normequal = (Math.Abs(L2NormRepON - L2NormRepOFF) <= 1e-14); result &= normequal; Console.WriteLine("{0}-L2Norm equal: {1}", varname[i], normequal); } return(result); } }
/// <summary> /// Can be used independent on the grid and the grid partitioning /// in constrast to <see cref="CompareErrors(CNSFieldSet, CNSFieldSet, double)"/> /// </summary> /// <param name="loadBalSolver"></param> /// <param name="refSolver"></param> /// <param name="differenceThreshold"></param> private static void CompareNorms(IProgram <CNSControl> refSolver, IList <IProgram <CNSControl> > loadBalSolvers, double differenceThreshold) { List <Action> assertions = new List <Action>(); string[] varName = { "Density", "x-Momentum", "Energy" }; for (int i = 0; i < varName.Length; i++) { List <DGField> listOfDGFields_RepOFF = (List <DGField>)refSolver.IOFields; DGField variableRepOFF = listOfDGFields_RepOFF[i]; double L2NormRepOFF = variableRepOFF.L2Norm(); for (int j = 0; j < loadBalSolvers.Count; j++) { List <DGField> listOfDGFields_RepON = (List <DGField>)loadBalSolvers[j].IOFields; DGField variableRepON = listOfDGFields_RepON[i]; double L2NormRepON = variableRepON.L2Norm(); double difference = Math.Abs(L2NormRepON - L2NormRepOFF); string message = String.Format("{0}: Difference in {1} norm is {2} (Threshold is {3})", loadBalSolvers[j].Control.GridPartType.ToString(), varName[i], difference, differenceThreshold); Console.WriteLine(message); assertions.Add(() => Assert.IsTrue(difference < differenceThreshold, message)); } } assertions.ForEach(a => a()); }
/// <summary> /// Computes the L2 error of field <paramref name="fieldName"/> with /// respect to the given <paramref name="referenceField"/> in the /// domain defined by <paramref name="maskFactory"/>. /// </summary> /// <param name="fieldName"> /// The name of the field to be evaluated /// </param> /// <param name="referenceField"> /// A DG field containing the exact solution. /// </param> /// <param name="maskFactory"> /// A function that returns the domain of integration in terms of cells /// to be evaluated. If null, the full computational domain will be /// considered. /// </param> /// <returns> /// The error of <paramref name="fieldName"/> in the L2 norm. /// </returns> public static Query L2Error(string fieldName, DGField referenceField, Func <GridData, CellMask> maskFactory = null) { return(delegate(IApplication <AppControl> app, double time) { DGField differenceField = referenceField - GetField(app.IOFields, fieldName); return differenceField.L2Norm(GetMaskOrNull(maskFactory, app.GridData)); }); }
/// <summary> /// L2Norm of given Field <paramref name="f"/>. /// </summary> /// <param name="f"></param> /// <param name="ResidualKey"> /// Optional parameter for key of residual. /// If null, the name of <paramref name="f"/> will be used as key. /// </param> public void ComputeL2Norm(DGField f, string ResidualKey = null) { string key = GetDictionaryKey(Residualtype.L2Norm, f.Identification, ResidualKey); double L2Norm = f.L2Norm(); m_Residuals[key] = L2Norm; }
/// <summary> /// Can be used independent on the grid and the grid partitioning /// in constrast to <see cref="CompareErrors(CNSFieldSet, CNSFieldSet, double)"/> /// </summary> /// <param name="loadBalSolver"></param> /// <param name="refSolver"></param> /// <param name="differenceThreshold"></param> private static void CompareNorms(IProgram <CNSControl> loadBalSolver, IProgram <CNSControl> refSolver, double differenceThreshold, IProgram <CNSControl> hilbertSolver = null) { List <Action> assertions = new List <Action>(); string[] varName = { "Density", "x-Momentum", "Energy" }; for (int i = 0; i < 3; i++) { List <DGField> listOfDGFields_RepON = (List <DGField>)loadBalSolver.IOFields; DGField variableRepON = listOfDGFields_RepON[i]; double L2NormRepON = variableRepON.L2Norm(); List <DGField> listOfDGFields_RepOFF = (List <DGField>)refSolver.IOFields; DGField variableRepOFF = listOfDGFields_RepOFF[i]; double L2NormRepOFF = variableRepOFF.L2Norm(); double difference = Math.Abs(L2NormRepON - L2NormRepOFF); //Console.WriteLine("{0}-L2Norm Rep ON: {1}", varName[i], L2NormRepON); //Console.WriteLine("{0}-L2Norm Rep OFF: {1}", varName[i], L2NormRepOFF); string message = String.Format("METIS: Difference in {0} norm is {1} (Threshold is {2})", varName[i], difference, differenceThreshold); Console.WriteLine(message); assertions.Add(() => Assert.IsTrue(difference < differenceThreshold, message)); // Duplicated code... double differenceHilbert; if (hilbertSolver != null) { List <DGField> listOfDGFields_Hilbert = (List <DGField>)hilbertSolver.IOFields; DGField variableHilbert = listOfDGFields_Hilbert[i]; double L2NormHilbert = variableHilbert.L2Norm(); differenceHilbert = Math.Abs(L2NormHilbert - L2NormRepOFF); string messageHilbert = String.Format("Hilbert: Difference in {0} norm is {1} (Threshold is {2})", varName[i], differenceHilbert, differenceThreshold); Console.WriteLine(messageHilbert); assertions.Add(() => Assert.IsTrue(differenceHilbert < differenceThreshold, messageHilbert)); } } assertions.ForEach(a => a()); }
/// <summary> /// Computes L2 norms between DG fields on different grid resolutions, i.e. for a /// convergence study, where the solution on the finest grid is assumed to be exact. /// </summary> /// <param name="FieldsToCompare"> /// Identification (<see cref="DGField.Identification"/>) of the fields which should be compared. /// </param> /// <param name="timestepS"> /// A collection of solutions on different grid resolutions. /// </param> /// <param name="GridRes"> /// On exit, the resolution of the different grids. /// </param> /// <param name="L2Errors"> /// On exit, the L2 error /// (for each field specified in <paramref name="FieldsToCompare"/>) /// in comparison to the solution on the finest grid. /// </param> /// <param name="__DOFs"> /// On exit, the number of degrees-of-freedom /// (for each field specified in <paramref name="FieldsToCompare"/>). /// </param> /// <param name="timestepIds"> /// on exit, the timestep id which correlate with the resolutions <paramref name="GridRes"/> /// (remarks: <paramref name="timestepIds"/> may be re-sorted internally according to grid resolution). /// </param> public static void ComputeErrors(IEnumerable <string> FieldsToCompare, IEnumerable <ITimestepInfo> timestepS, out double[] GridRes, out Dictionary <string, int[]> __DOFs, out Dictionary <string, double[]> L2Errors, out Guid[] timestepIds) { // load the DG-Fields List <IEnumerable <DGField> > fields = new List <IEnumerable <DGField> >(); int i = 1; foreach (var timestep in timestepS) { Console.WriteLine("Loading timestep {0} of {1}, ({2})...", i, timestepS.Count(), timestep.ID); fields.Add(timestep.Fields); i++; Console.WriteLine("done (Grid has {0} cells).", fields.Last().First().GridDat.CellPartitioning.TotalLength); } // sort according to grid resolution { var s = fields.OrderBy(f => f.First().GridDat.CellPartitioning.TotalLength).ToArray(); timestepIds = new Guid[s.Length]; for (int z = 0; z < timestepIds.Length; z++) { int idx = fields.IndexOf(s[z], (f1, f2) => object.ReferenceEquals(f1, f2)); timestepIds[z] = timestepS.ElementAt(idx).ID; } fields.Clear(); fields.AddRange(s); } // Grids and coarse-to-fine -- mappings. GridData[] gDataS = fields.Select(fc => (GridData)(fc.First().GridDat)).ToArray(); int[][] Fine2CoarseMapS = new int[gDataS.Length - 1][]; // 1st index: level; 2n index: cell index on finest level for (int iLevel = 0; iLevel < Fine2CoarseMapS.Length; iLevel++) { ComputeFine2CoarseMap(gDataS.Last(), gDataS[iLevel], out Fine2CoarseMapS[iLevel]); } // extrapolate to fine grid Dictionary <string, List <DGField> > injectedFields = new Dictionary <string, List <DGField> >(); Dictionary <string, List <int> > DOFs = new Dictionary <string, List <int> >(); foreach (string Identification in FieldsToCompare) { List <DGField> fields_Identification = new List <DGField>(); // fields for different resolutions List <int> dofs_Idenitification = new List <int>(); DGField finestSolution = fields.Last().Single(f => f.Identification == Identification); for (int iLevel = 0; iLevel < gDataS.Length - 1; iLevel++) { Console.WriteLine("Injecting '{0}' from level {1} to finest grid...", Identification, iLevel); DGField coarseSolution = fields[iLevel].Single(f => f.Identification == Identification); if (finestSolution.GetType() != coarseSolution.GetType()) { throw new NotSupportedException(); } if (coarseSolution.Basis.Degree != finestSolution.Basis.Degree) { throw new NotSupportedException(); } if (finestSolution is XDGField) { XDGField _coarseSolution = (XDGField)coarseSolution; XDGField _finestSolution = (XDGField)finestSolution; XDGField injectedSolution = new XDGField(_finestSolution.Basis, Identification + "-inj-" + iLevel); InjectXDGField(Fine2CoarseMapS[iLevel], injectedSolution, _coarseSolution); fields_Identification.Add(injectedSolution); dofs_Idenitification.Add(coarseSolution.Mapping.GetTotalNoOfDOFs()); } else if (finestSolution is SinglePhaseField) { SinglePhaseField _coarseSolution = (SinglePhaseField)coarseSolution; SinglePhaseField _finestSolution = (SinglePhaseField)finestSolution; SinglePhaseField injectedSolution = new SinglePhaseField(_finestSolution.Basis, Identification + "-inj-" + iLevel); InjectDGField(Fine2CoarseMapS[iLevel], injectedSolution, _coarseSolution); fields_Identification.Add(injectedSolution); dofs_Idenitification.Add(coarseSolution.Mapping.GetTotalNoOfDOFs()); } else { throw new NotSupportedException("DG field type '" + finestSolution.GetType().FullName + "' not supported, Identification is '" + finestSolution.Identification + "'"); } Console.WriteLine("done."); } fields_Identification.Add(finestSolution); injectedFields.Add(Identification, fields_Identification); DOFs.Add(Identification, dofs_Idenitification); } __DOFs = new Dictionary <string, int[]>(); foreach (var kv in DOFs) { __DOFs.Add(kv.Key, kv.Value.ToArray()); } // compute the errors L2Errors = new Dictionary <string, double[]>(); foreach (string Identification in FieldsToCompare) { double[] L2Error = new double[gDataS.Length - 1]; for (int iLevel = 0; iLevel < gDataS.Length - 1; iLevel++) { Console.WriteLine("Computing L2 error of '{0}' on level {1} ...", Identification, iLevel); DGField Error = injectedFields[Identification].Last().CloneAs(); DGField injSol = injectedFields[Identification].ElementAt(iLevel); Error.Acc(-1.0, injSol); L2Error[iLevel] = Error.L2Norm(); Console.WriteLine("done (Error is {0:0.####E-00}).", L2Error[iLevel]); } L2Errors.Add(Identification, L2Error); } GridRes = gDataS.Take(gDataS.Length - 1).Select(gd => gd.Cells.h_minGlobal).ToArray(); }
/// <summary> /// Computes L2 norms between DG fields on different grid resolutions, i.e. for a /// convergence study, where the solution on the finest grid is assumed to be exact. /// </summary> /// <param name="FieldsToCompare"> /// Identification (<see cref="DGField.Identification"/>) of the fields which should be compared. /// </param> /// <param name="timestepS"> /// A collection of solutions on different grid resolutions. /// </param> /// <param name="GridRes"> /// On exit, the resolution of the different grids. /// </param> /// <param name="L2Errors"> /// On exit, the L2 error /// (for each field specified in <paramref name="FieldsToCompare"/>) /// in comparison to the solution on the finest grid. /// </param> public static void ComputeErrors(string[] FieldsToCompare, ITimestepInfo[] timestepS, out double[] GridRes, out Dictionary <string, double[]> L2Errors) { // load the DG-Fields List <IEnumerable <DGField> > fields = new List <IEnumerable <DGField> >(); int i = 1; foreach (var timestep in timestepS) { Console.WriteLine("Loading timestep {0} of {1}, ({2})...", i, timestepS.Length, timestep.ID); fields.Add(timestep.Fields); i++; Console.WriteLine("done (Grid has {0} cells).", fields.Last().First().GridDat.CellPartitioning.TotalLength); } { var s = fields.OrderBy(f => f.First().GridDat.CellPartitioning.TotalLength).ToArray(); fields.Clear(); fields.AddRange(s); } // Grids and coarse-to-fine -- mappings. GridData[] gDataS = fields.Select(fc => (GridData)(fc.First().GridDat)).ToArray(); int[][] Fine2CoarseMapS = new int[gDataS.Length - 1][]; for (int iLevel = 0; iLevel < Fine2CoarseMapS.Length; iLevel++) { ComputeFine2CoarseMap(gDataS.Last(), gDataS[iLevel], out Fine2CoarseMapS[iLevel]); } // extrapolate to fine grid Dictionary <string, List <DGField> > injectedFields = new Dictionary <string, List <DGField> >(); foreach (string Identification in FieldsToCompare) { List <DGField> blabla = new List <DGField>(); DGField finestSolution = fields.Last().Single(f => f.Identification == Identification); for (int iLevel = 0; iLevel < gDataS.Length - 1; iLevel++) { Console.WriteLine("Injecting '{0}' from level {1} to finest grid...", Identification, iLevel); DGField coarseSolution = fields[iLevel].Single(f => f.Identification == Identification); if (finestSolution.GetType() != coarseSolution.GetType()) { throw new NotSupportedException(); } if (coarseSolution.Basis.Degree != finestSolution.Basis.Degree) { throw new NotSupportedException(); } if (finestSolution is XDGField) { XDGField _coarseSolution = (XDGField)coarseSolution; XDGField _finestSolution = (XDGField)finestSolution; XDGField injectedSolution = new XDGField(_finestSolution.Basis, Identification + "-inj-" + iLevel); InjectXDGField(Fine2CoarseMapS[iLevel], injectedSolution, _coarseSolution); blabla.Add(injectedSolution); } else if (finestSolution is SinglePhaseField) { SinglePhaseField _coarseSolution = (SinglePhaseField)coarseSolution; SinglePhaseField _finestSolution = (SinglePhaseField)finestSolution; SinglePhaseField injectedSolution = new SinglePhaseField(_finestSolution.Basis, Identification + "-inj-" + iLevel); InjectDGField(Fine2CoarseMapS[iLevel], injectedSolution, _coarseSolution); blabla.Add(injectedSolution); } else { throw new NotSupportedException("DG field type '" + finestSolution.GetType().FullName + "' not supported, Identification is '" + finestSolution.Identification + "'"); } Console.WriteLine("done."); } blabla.Add(finestSolution); injectedFields.Add(Identification, blabla); } // compute the errors L2Errors = new Dictionary <string, double[]>(); foreach (string Identification in FieldsToCompare) { double[] L2Error = new double[gDataS.Length - 1]; for (int iLevel = 0; iLevel < gDataS.Length - 1; iLevel++) { Console.WriteLine("Computing L2 error of '{0}' on level {1} ...", Identification, iLevel); DGField Error = injectedFields[Identification].Last().CloneAs(); DGField injSol = injectedFields[Identification].ElementAt(iLevel); Error.Acc(-1.0, injSol); L2Error[iLevel] = Error.L2Norm(); Console.WriteLine("done (Error is {0:0.####E-00}).", L2Error[iLevel]); } L2Errors.Add(Identification, L2Error); } GridRes = gDataS.Take(gDataS.Length - 1).Select(gd => gd.Cells.h_minGlobal).ToArray(); // convert to table /* * MultidimensionalArray RES = MultidimensionalArray.Create(GridRes.Length, FieldsToCompare.Length + 1); * RES.SetColumn(0, GridRes); * for(int ii = 0; ii < FieldsToCompare.Length; ii++) { * RES.SetColumn(ii + 1, L2Errors[FieldsToCompare[ii]]); * } * * * using(var fs = new FileStream("res.csv", FileMode.Append)) { * var stw = new StreamWriter(fs); * stw.Write("GridRes "); * for(int ii = 0; ii < FieldsToCompare.Length; ii++) { * stw.Write(FieldsToCompare[ii]); * if(ii + 1 < FieldsToCompare.Length) * stw.Write(" "); * } * * stw.Flush(); * * RES.WriteToStream(fs); * * } */ }