/// <summary> /// another legacy interface /// </summary> static public void ComputeAffine <V>( this SpatialOperator op, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, V AffineOffset, bool OnlyBoundaryEdges = true, double time = 0.0, EdgeQuadratureScheme edgeQr = null, CellQuadratureScheme volQr = null) where V : IList <double> { var GridDat = CodomainMap.GridDat; if (Parameters != null) { foreach (var prm in Parameters) { if (!object.ReferenceEquals(prm.GridDat, GridDat)) { throw new ArgumentException(string.Format("parameter field {0} is assigned to a different grid.", prm.Identification)); } } } //Using order zero for DomainMap will lead to inconsistent (and possibly insufficient) quadrature order!!! //UnsetteledCoordinateMapping DomainMap; //Basis b = new Basis(GridDat, 0); //Basis[] B = new Basis[this.DomainVar.Count]; //B.SetAll(b); //DomainMap = new UnsetteledCoordinateMapping(B); if (OnlyBoundaryEdges) { if (edgeQr != null) { throw new ArgumentException("If 'OnlyBoundaryEdges == true', 'edgeQr' must be null!", "edgeQr"); } if (volQr != null) { throw new ArgumentException("If 'OnlyBoundaryEdges == true', 'volQr' must be null!", "volQr"); } volQr = new CellQuadratureScheme(true, CellMask.GetEmptyMask(GridDat)); edgeQr = new EdgeQuadratureScheme(true, GridDat.GetBoundaryEdgeMask()); } op.ComputeMatrixEx( DomainMap, Parameters, CodomainMap, default(MsrMatrix), AffineOffset, OnlyAffine: true, time: time, volQuadScheme: volQr, edgeQuadScheme: edgeQr); }
private MsrMatrix PenaltyMatrix(EdgeMask em, Basis LevSetBasis, Basis JumpBasis) { var OpA = new SpatialOperator(1, 0, 1, QuadOrderFunc.Linear(), "Phi", "c1"); OpA.EquationComponents["c1"].Add(new JumpForm()); //OpA.EquationComponents["c1"].Add(new GradientJumpForm() { ATerm = true, BTerm = true }); OpA.EquationComponents["c1"].Add(new GradientJumpForm2()); OpA.Commit(); //var OpB = new SpatialOperator(1, 0, 1, "Phi", "c1"); //Op.EquationComponents["c1"].Add(new JumpForm()); //OpB.EquationComponents["c1"].Add(new GradientJumpForm() { BTerm = true }); //Op.EquationComponents["c1"].Add(new GradientJumpForm2()); //OpB.Commit(); var inp_LevSet_Mapping = new UnsetteledCoordinateMapping(LevSetBasis); var outp_Result_Mapping = new UnsetteledCoordinateMapping(JumpBasis); MsrMatrix MatrixA; MatrixA = new MsrMatrix(outp_Result_Mapping, inp_LevSet_Mapping); double[] AffineA = new double[inp_LevSet_Mapping.LocalLength]; OpA.ComputeMatrixEx(inp_LevSet_Mapping, null, outp_Result_Mapping, MatrixA, AffineA, OnlyAffine: false, edgeQuadScheme: new EdgeQuadratureScheme(true, em), volQuadScheme: new CellQuadratureScheme(true, CellMask.GetEmptyMask(em.GridData))); MatrixA.CheckForNanOrInfM(); //MsrMatrix MatrixB; //MatrixB = new MsrMatrix(outp_Result_Mapping, inp_LevSet_Mapping); //double[] AffineB = new double[inp_LevSet_Mapping.LocalLength]; //OpB.ComputeMatrixEx(inp_LevSet_Mapping, null, outp_Result_Mapping, // MatrixB, AffineB, OnlyAffine: false // );//, // //edgeQrCtx: new EdgeQuadratureScheme(true, em), // //volQrCtx: new CellQuadratureScheme(true, CellMask.GetEmptyMask(em.GridData))); //Debug.Assert(AffineB.L2Norm() == 0); //var Err = MatrixA.Transpose(); //Err.Acc(-1.0, MatrixB); //double errnorm = Err.InfNorm(); //Debug.Assert(errnorm < 1.0e-10); ////Console.WriteLine("Errnorm:" + errnorm); return(MatrixA); }
/// <summary> /// /// </summary> /// <param name="jCell"></param> /// <param name="AcceptedMask"></param> /// <param name="Phi"></param> /// <param name="gradPhi"></param> /// <param name="__DiffusionCoeff">Output: if artificial diffusion is turned</param> /// <param name="MaxAllowedPhi">Input: upper threshold for the values of <paramref name="Phi"/> in cell <see cref="jCell"/>.</param> /// <param name="MinAllowedPhi">Input: lower threshold for the values of <paramref name="Phi"/> in cell <see cref="jCell"/>.</param> /// <returns></returns> public bool LocalSolve_Iterative(int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi, SinglePhaseField __DiffusionCoeff, double MaxAllowedPhi, double MinAllowedPhi) { //this.LocalSolve_Geometric(jCell, AcceptedMask, Phi, +1, out MinAllowedPhi, out MaxAllowedPhi);) { int N = this.LevelSetBasis.GetLength(jCell); int i0G = this.LevelSetMapping.GlobalUniqueCoordinateIndex(0, jCell, 0); int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0); SinglePhaseField __AcceptedMask = new SinglePhaseField(new Basis(this.GridDat, 0), "accepted"); for (int j = 0; j < AcceptedMask.Length; j++) { __AcceptedMask.SetMeanValue(j, AcceptedMask[j] ? 1.0 : 0.0); } // subgrid on which we are working, consisting only of one cell SubGrid jCellGrid = new SubGrid(new CellMask(this.GridDat, Chunk.GetSingleElementChunk(jCell))); // create spatial operator IEvaluatorNonLin evo; { SpatialOperator op = new SpatialOperator(1, 2, 1, QuadOrderFunc.NonLinear(2), "Phi", "dPhi_dx0", "dPhi_dx1", "cod1"); op.EquationComponents["cod1"].Add(new ReinitOperator()); op.EdgeQuadraturSchemeProvider = g => (new EdgeQuadratureScheme(domain: EdgeMask.GetEmptyMask(g))); op.VolumeQuadraturSchemeProvider = g => (new CellQuadratureScheme(domain: jCellGrid.VolumeMask)); op.Commit(); evo = op.GetEvaluatorEx(Phi.Mapping.Fields, gradPhi.Mapping.Fields, Phi.Mapping); evo.ActivateSubgridBoundary(jCellGrid.VolumeMask, subGridBoundaryTreatment: SubGridBoundaryModes.InnerEdge); } // create artificial diffusion operator MultidimensionalArray DiffMtx; double[] DiffRhs; SpatialOperator dop; { double penaltyBase = this.LevelSetBasis.Degree + 2; penaltyBase = penaltyBase.Pow2(); dop = (new ArtificialViscosity(AcceptedMask, penaltyBase, GridDat.Cells.h_min, jCell, -1.0)).Operator(1); MsrMatrix _DiffMtx = new MsrMatrix(this.LevelSetMapping, this.LevelSetMapping); double[] _DiffRhs = new double[this.LevelSetMapping.LocalLength]; dop.ComputeMatrixEx(this.LevelSetMapping, new DGField[] { Phi, null, null }, this.LevelSetMapping, _DiffMtx, _DiffRhs, OnlyAffine: false, edgeQuadScheme: (new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask)), volQuadScheme: (new CellQuadratureScheme(domain: jCellGrid.VolumeMask))); // extract matrix for 'jCell' DiffMtx = MultidimensionalArray.Create(N, N); DiffRhs = new double[N]; for (int n = 0; n < N; n++) { #if DEBUG int Lr; int[] row_cols = null; double[] row_vals = null; Lr = _DiffMtx.GetRow(i0G + n, ref row_cols, ref row_vals); for (int lr = 0; lr < Lr; lr++) { int ColIndex = row_cols[lr]; double Value = row_vals[lr]; Debug.Assert((ColIndex >= i0G && ColIndex < i0G + N) || (Value == 0.0), "Matrix is expected to be block-diagonal."); } #endif for (int m = 0; m < N; m++) { DiffMtx[n, m] = _DiffMtx[i0G + n, i0G + m]; } DiffRhs[n] = _DiffRhs[i0L + n]; } #if DEBUG var Test = DiffMtx.Transpose(); Test.Acc(-1.0, DiffMtx); Debug.Assert(Test.InfNorm() <= 1.0e-8); #endif } // find 'good' initial value by geometric solve AND // thresholds for the maximum an minimal value of Phi double Range = MaxAllowedPhi - MinAllowedPhi; MinAllowedPhi -= 0.1 * Range; MaxAllowedPhi += 0.1 * Range; // timestep for pseudo-timestepping double dt = 0.5 * this.GridDat.Cells.h_min[jCell] / (((double)(this.LevelSetBasis.Degree)).Pow2()); DGField[] PlotFields = new DGField[] { Phi, gradPhi[0], gradPhi[1], __DiffusionCoeff, __AcceptedMask }; //Tecplot.Tecplot.PlotFields(Params, "itt_0", "EllipicReinit", 0, 3); double[] PrevVal = new double[N]; double[] NextVal = new double[N]; Phi.Coordinates.GetRow(jCell, PrevVal); // pseudo-timestepping //if(jCell == 80) // Tecplot.Tecplot.PlotFields(PlotFields, "itt_0", "EllipicReinit", 0, 3); //Console.Write(" Local solve cell " + jCell + " ... "); bool converged = false; double DiffusionCoeff = 0; int IterGrowCount = 0; // number of iterations in which the residual grew double LastResi = double.NaN; for (int iIter = 0; iIter < 1000; iIter++) { //Console.Write(" Local solve iteration " + iIter + " ... "); PerformRKstep(dt, jCell, AcceptedMask, Phi, gradPhi, evo); __DiffusionCoeff.SetMeanValue(jCell, DiffusionCoeff); if (jCell == 80) { DiffusionCoeff = 0.1; } if (DiffusionCoeff > 0) { //Console.WriteLine(" Diffusion on."); double[] _DiffRhs = new double[this.LevelSetMapping.LocalLength]; dop.ComputeMatrixEx(this.LevelSetMapping, new DGField[] { Phi, gradPhi[0], gradPhi[1] }, this.LevelSetMapping, default(MsrMatrix), _DiffRhs, OnlyAffine: true, edgeQuadScheme: (new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask)), volQuadScheme: (new CellQuadratureScheme(domain: CellMask.GetEmptyMask(this.GridDat)))); // extract matrix for 'jCell' for (int n = 0; n < N; n++) { DiffRhs[n] = _DiffRhs[i0L + n]; } PerformArtificialDiffusion(dt * DiffusionCoeff, jCell, Phi, DiffMtx, DiffRhs); } Phi.Coordinates.GetRow(jCell, NextVal); double resi = Math.Sqrt(GenericBlas.L2DistPow2(NextVal, PrevVal) / GenericBlas.L2NormPow2(PrevVal)); double[] A = NextVal; NextVal = PrevVal; PrevVal = A; if (iIter > 0 && resi > LastResi) { IterGrowCount++; } else { IterGrowCount = 0; } LastResi = resi; if (resi < 1.0e-10) { converged = true; break; } double maxPhi, minPhi; Phi.GetExtremalValuesInCell(out minPhi, out maxPhi, jCell); bool MinAlarm = minPhi < MinAllowedPhi; bool Maxalarm = maxPhi > MaxAllowedPhi; bool GrowAlarm = IterGrowCount > 4; bool IterAlarm = iIter >= 50; if (MinAlarm || Maxalarm || GrowAlarm) { // Diffusion coefficient should be increased if (DiffusionCoeff == 0) { DiffusionCoeff = 1.0e-2; } else { if (DiffusionCoeff < 1.0e3) { DiffusionCoeff *= 2; } } //Console.WriteLine(" increasing Diffusion: {0}, Alarms : {1}{2}{3}{4}", DiffusionCoeff, MinAlarm ? 1 : 0, Maxalarm ? 1 : 0, GrowAlarm ? 1 : 0, IterAlarm ? 1 : 0); } //if(jCell == 80 && iIter < 100) // Tecplot.Tecplot.PlotFields(PlotFields, "itt_" + (iIter + 1), "EllipicReinit", iIter + 1, 3); } return(converged); }
/// <summary> /// Various condition numbers, organized in a dictionary to create a regression over multiple meshes /// </summary> public IDictionary <string, double> GetNamedProperties() { using (new FuncTrace()) { var Ret = new Dictionary <string, double>(); var grd = m_map.GridDat; // global condition numbers // ======================== //double CondNo = this.CondNumMUMPS(); double CondNo = this.CondNumMatlab(); // matlab seems to be more reliable Ret.Add("TotCondNo-" + VarNames, CondNo); // block-wise condition numbers // ============================ double[] bcn = this.StencilCondNumbers(); CellMask innerUncut, innerCut, bndyUncut, bndyCut; if (m_LsTrk != null) { // +++++++++ // using XDG // +++++++++ innerUncut = grd.GetBoundaryCells().Complement().Except(m_LsTrk.Regions.GetCutCellMask()); innerCut = m_LsTrk.Regions.GetCutCellMask().Except(grd.GetBoundaryCells()); bndyUncut = grd.GetBoundaryCells().Except(m_LsTrk.Regions.GetCutCellMask()); bndyCut = grd.GetBoundaryCells().Intersect(m_LsTrk.Regions.GetCutCellMask()); } else { // ++++++++ // using DG // ++++++++ innerUncut = grd.GetBoundaryCells().Complement(); innerCut = CellMask.GetEmptyMask(grd); bndyUncut = grd.GetBoundaryCells(); bndyCut = CellMask.GetEmptyMask(grd); } double innerUncut_MaxCondNo = innerUncut.NoOfItemsLocally > 0 ? innerUncut.ItemEnum.Max(jCell => bcn[jCell]) : 1.0; double innerCut_MaxCondNo = innerCut.NoOfItemsLocally > 0 ? innerCut.ItemEnum.Max(jCell => bcn[jCell]) : 1.0; double bndyUncut_MaxCondNo = bndyUncut.NoOfItemsLocally > 0 ? bndyUncut.ItemEnum.Max(jCell => bcn[jCell]) : 1.0; double bndyCut_MaxCondNo = bndyCut.NoOfItemsLocally > 0 ? bndyCut.ItemEnum.Max(jCell => bcn[jCell]) : 1.0; innerUncut_MaxCondNo = innerUncut_MaxCondNo.MPIMax(); innerCut_MaxCondNo = innerCut_MaxCondNo.MPIMax(); bndyUncut_MaxCondNo = bndyUncut_MaxCondNo.MPIMax(); bndyCut_MaxCondNo = bndyCut_MaxCondNo.MPIMax(); Ret.Add("StencilCondNo-innerUncut-" + VarNames, innerUncut_MaxCondNo); Ret.Add("StencilCondNo-bndyUncut-" + VarNames, bndyUncut_MaxCondNo); if (m_LsTrk != null) { Ret.Add("StencilCondNo-innerCut-" + VarNames, innerCut_MaxCondNo); Ret.Add("StencilCondNo-bndyCut-" + VarNames, bndyCut_MaxCondNo); } return(Ret); } }