/// <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); * * } */ }