/// <summary> /// Sets fields an their exact derivatives. /// </summary> protected override void SetInitial() { if (this.GridData.SpatialDimension == 3) { f1.ProjectField((x, y, z) => (3 * x + z)); f1Gradient_Analytical[0].ProjectField((x, y, z) => 3.0); f1Gradient_Analytical[1].ProjectField((x, y, z) => 0.0); f1Gradient_Analytical[2].ProjectField((x, y, z) => 1.0); f2.ProjectField((x, y, z) => z + 2 * y); f2Gradient_Analytical[0].ProjectField((x, y, z) => 0.0); f2Gradient_Analytical[1].ProjectField((x, y, z) => 2.0); f2Gradient_Analytical[2].ProjectField((x, y, z) => 1.0); Laplace_f1_Analytical.ProjectField((x, y, z) => 0.0); Laplace_f2_Analytical.ProjectField((x, y, z) => 0.0); } else if (this.GridData.SpatialDimension == 2) { if (AltRefSol == false) { f1.ProjectField((x, y) => (3 * x)); f1Gradient_Analytical[0].ProjectField((x, y) => 3); f1Gradient_Analytical[1].ProjectField((x, y) => 0); f2.ProjectField((x, y) => x + 2 * y); f2Gradient_Analytical[0].ProjectField((x, y) => 1.0); f2Gradient_Analytical[1].ProjectField((x, y) => 2.0); Laplace_f1_Analytical.ProjectField((x, y) => 0.0); Laplace_f2_Analytical.ProjectField((x, y) => 0.0); } else { f1.ProjectField((x, y) => Math.Sin(Math.Atan(y / x) * 4.0)); f1Gradient_Analytical[0].ProjectField((x, y) => (-4 * Math.Cos(4 * Math.Atan(y / x)) * y / (x * x) / (1 + (y * y) / (x * x)))); f1Gradient_Analytical[1].ProjectField((x, y) => (4 * Math.Cos(4 * Math.Atan(y / x)) / x / (1 + (y * y) / (x * x)))); } } else if (this.GridData.SpatialDimension == 1) { f1.ProjectField((x) => (3 * x)); f1Gradient_Analytical[0].ProjectField((_1D)((x) => 3)); f2.ProjectField((x) => x * x); f2Gradient_Analytical[0].ProjectField((_1D)((x) => 2 * x)); Laplace_f1_Analytical.ProjectField((_1D)((x) => 0.0)); Laplace_f2_Analytical.ProjectField((_1D)((x) => 2.0)); } else { throw new NotImplementedException(); } }
/// <summary> /// Calculate A Level-Set field from the Explicit description /// </summary> /// <param name="LevelSet">Target Field</param> /// <param name="LsTrk"></param> public void ProjectToDGLevelSet(SinglePhaseField LevelSet, LevelSetTracker LsTrk = null) { CellMask VolMask; if (LsTrk == null) { VolMask = CellMask.GetFullMask(LevelSet.Basis.GridDat); } else { // set values in positive and negative FAR region to +1 and -1 CellMask Near = LsTrk.Regions.GetNearMask4LevSet(0, 1); CellMask PosFar = LsTrk.Regions.GetLevelSetWing(0, +1).VolumeMask.Except(Near); CellMask NegFar = LsTrk.Regions.GetLevelSetWing(0, -1).VolumeMask.Except(Near); LevelSet.Clear(PosFar); LevelSet.AccConstant(1, PosFar); LevelSet.Clear(NegFar); LevelSet.AccConstant(-1, NegFar); // project Fourier levelSet to DGfield on near field VolMask = Near; } LevelSet.Clear(VolMask); // scalar function is already vectorized for parallel execution // nodes in global coordinates LevelSet.ProjectField(1.0, PhiEvaluation(mode), new Foundation.Quadrature.CellQuadratureScheme(true, VolMask)); // check the projection error projErr_phiDG = LevelSet.L2Error( PhiEvaluation(mode), new Foundation.Quadrature.CellQuadratureScheme(true, VolMask)); //if (projErr_phiDG >= 1e-5) // Console.WriteLine("WARNING: LevelSet projection error onto PhiDG = {0}", projErr_phiDG); // project on higher degree field and take the difference //SinglePhaseField higherLevSet = new SinglePhaseField(new Basis(LevelSet.GridDat, LevelSet.Basis.Degree * 2), "higherLevSet"); //higherLevSet.ProjectField(1.0, PhiEvaluator(), new Foundation.Quadrature.CellQuadratureScheme(true, VolMask)); //double higherProjErr = higherLevSet.L2Error( // PhiEvaluator(), // new Foundation.Quadrature.CellQuadratureScheme(true, VolMask)); //Console.WriteLine("LevelSet projection error onto higherPhiDG = {0}", higherProjErr.ToString()); // check the projection from current sample points on the DGfield //MultidimensionalArray interP = MultidimensionalArray.Create(current_interfaceP.Lengths); //if (this is PolarFourierLevSet) { // interP = ((PolarFourierLevSet)this).interfaceP_cartesian; //} else { // interP = current_interfaceP; //} //projErr_interface = InterfaceProjectionError(LevelSet, current_interfaceP); //if (projErr_interface >= 1e-3) // Console.WriteLine("WARNING: Interface projection Error onto PhiDG = {0}", projErr_interface); }
/// <summary> /// Sets level-set and solution at time (<paramref name="time"/> + <paramref name="dt"/>). /// </summary> double DelUpdateLevelset(DGField[] CurrentState, double time, double dt, double UnderRelax, bool _incremental) { // new time double t = time + dt; // project new level-set double s = 1.0; LevSet.ProjectField((x, y) => - (x - s * t).Pow2() - y.Pow2() + (2.4).Pow2()); LsTrk.UpdateTracker(incremental: _incremental); LsTrk.PushStacks(); // exact solution for new timestep uXEx.GetSpeciesShadowField("A").ProjectField((x, y) => x + alpha_A * t); uXEx.GetSpeciesShadowField("B").ProjectField((x, y) => x + alpha_B * t); // uX.Clear(); //uX.Acc(1.0, uXEx); // single-phase-properties u.Clear(); u.ProjectField(NonVectorizedScalarFunction.Vectorize(uEx, t)); Grad_u.Clear(); Grad_u.Gradient(1.0, u); MagGrad_u.Clear(); MagGrad_u.ProjectFunction(1.0, (double[] X, double[] U, int jCell) => Math.Sqrt(U[0].Pow2() + U[1].Pow2()), new Foundation.Quadrature.CellQuadratureScheme(), Grad_u.ToArray()); // return level-set residual return(0.0); }
private SinglePhaseField ComputeDistanceField() { SinglePhaseField phiDist = new SinglePhaseField(phi.Basis); GridData GridDat = (GridData)(phi.GridDat); // calculate distance field phiDist = 0.5 * log(Max(1+phi, eps)/Max(1-phi, eps)) * sqrt(2) * Cahn // =================== phiDist.ProjectField( (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NS, MultidimensionalArray result) { // ScalarFunction2 Debug.Assert(result.Dimension == 2); Debug.Assert(Len == result.GetLength(0)); int K = result.GetLength(1); // number of nodes // evaluate Phi // ----------------------------- phi.Evaluate(j0, Len, NS, result); // compute the pointwise values of the new level set // ----------------------------- result.ApplyAll(x => 0.5 * Math.Log(Math.Max(1 + x, 1e-10) / Math.Max(1 - x, 1e-10)) * Math.Sqrt(2) * this.Control.cahn); } ); return(phiDist); }
private double SetUpConfiguration() { testCase.UpdateLevelSet(levelSet); levelSetTracker.UpdateTracker(__NearRegionWith: 0, incremental: false, __LevSetAllowedMovement: 2); XDGField.Clear(); XDGField.GetSpeciesShadowField("A").ProjectField( 1.0, testCase.JumpingFieldSpeciesAInitialValue, default(CellQuadratureScheme)); XDGField.GetSpeciesShadowField("B").ProjectField( 1.0, testCase.JumpingFieldSpeciesBInitialValue, default(CellQuadratureScheme)); SinglePhaseField.Clear(); SinglePhaseField.ProjectField(testCase.ContinuousFieldInitialValue); double referenceValue = testCase.Solution; if (testCase is IVolumeTestCase) { QuadRule standardRule = Grid.RefElements[0].GetQuadratureRule(2 * XDGField.Basis.Degree + 1); ScalarFieldQuadrature uncutQuadrature = new ScalarFieldQuadrature( GridData, XDGField, new CellQuadratureScheme( new FixedRuleFactory <QuadRule>(standardRule), levelSetTracker.Regions.GetCutCellSubGrid().Complement().VolumeMask), standardRule.OrderOfPrecision); uncutQuadrature.Execute(); referenceValue -= uncutQuadrature.Result; } return(referenceValue); }
protected override void SetInitial() { this.LsUpdate(0.0); u.ProjectField((x, y) => x); du_dx_Exact.ProjectField((x, y) => 1.0); }
void TestAgglomeration_Extraploation(MultiphaseCellAgglomerator Agg) { _2D SomePolynomial; if (this.u.Basis.Degree == 0) { SomePolynomial = (x, y) => 3.2; } else if (this.u.Basis.Degree == 1) { SomePolynomial = (x, y) => 3.2 + x - 2.4 * y; } else { SomePolynomial = (x, y) => x * x + y * y; } // ======================================================== // extrapolate polynomial function for species B of a XDG-field // ======================================================== var Bmask = LsTrk.Regions.GetSpeciesMask("B"); XDGField xt = new XDGField(new XDGBasis(this.LsTrk, this.u.Basis.Degree), "XDG-test"); xt.GetSpeciesShadowField("B").ProjectField(1.0, SomePolynomial.Vectorize(), new CellQuadratureScheme(true, Bmask)); double[] bkupVec = xt.CoordinateVector.ToArray(); Agg.ClearAgglomerated(xt.Mapping); Agg.Extrapolate(xt.Mapping); double Err = GenericBlas.L2DistPow2(bkupVec, xt.CoordinateVector).MPISum().Sqrt(); Console.WriteLine("Agglom: extrapolation error: " + Err); Assert.LessOrEqual(Err, 1.0e-10); // ======================================================== // extrapolate polynomial function for a single-phase-field // ======================================================== SinglePhaseField xt2 = new SinglePhaseField(this.u.Basis, "DG-test"); xt2.ProjectField(SomePolynomial); double[] bkupVec2 = xt2.CoordinateVector.ToArray(); Agg.ClearAgglomerated(xt2.Mapping); Agg.Extrapolate(xt2.Mapping); double Err2 = GenericBlas.L2DistPow2(bkupVec, xt.CoordinateVector).MPISum().Sqrt(); Console.WriteLine("Agglom: extrapolation error: " + Err2); Assert.LessOrEqual(Err2, 1.0e-10); }
void PlotAnalyticSolution(Func <double[], double> AnalyticSolution, Basis PlotBasis, string Identification) { if (AnalyticSolution != null) { SinglePhaseField tmp = new SinglePhaseField(PlotBasis, Identification); tmp.ProjectField(AnalyticSolution); m_IOFields.Add(tmp); } }
/// <summary> /// sets some initial value for field <see cref="u"/>; /// </summary> protected override void SetInitial() { switch (GridData.SpatialDimension) { case 2: u.ProjectField((_2D)(delegate(double x, double y) { //double r = Math.Sqrt(x*x + y*y); //return Math.Exp(-r * r); return(x); })); Velocity[0].ProjectField((_2D)((x, y) => 1.0)); Velocity[1].ProjectField((_2D)((x, y) => 0.0)); break; case 3: u.ProjectField((x, y, z) => ((Math.Abs(x) <= 3.0 && Math.Abs(y) <= 3.0 && Math.Abs(z) <= 3.0) ? 1 : 0)); Velocity[0].ProjectField((_3D)((x, y, z) => 1)); Velocity[1].ProjectField((_3D)((x, y, z) => 0)); Velocity[2].ProjectField((_3D)((x, y, z) => 0)); break; default: throw new NotImplementedException(); } double rank = GridData.MpiRank; int J = GridData.iLogicalCells.NoOfLocalUpdatedCells; for (int j = 0; j < J; j++) { mpi_rank.SetMeanValue(j, rank); } }
/// <summary> /// Setting initial value. /// </summary> protected override void SetInitial() { TestData.ProjectField(TestDataFunc); DelUpdateLevelset(new DGField[] { uX }, 0.0, 0.0, 1.0, false); uX.ProjectField((x, y) => 1.0); // check error double L2err = TestData.L2Error(TestDataFunc); Console.WriteLine("Projection error from old to new grid: " + L2err); Assert.LessOrEqual(L2err, 1.0e-8, "Projection error of test field to high."); }
/// <summary> /// Setting initial value. /// </summary> protected override void SetInitial() { TestData.ProjectField(TestDataFunc); DelUpdateLevelset(new DGField[] { uX }, 0.0, 0.0, 1.0, false); uX.ProjectField((x, y) => 1.0); /* * RefinedGrid = this.GridData; * Refined_u = this.u; * Refined_TestData = new SinglePhaseField(this.u.Basis, "TestData"); * Refined_Grad_u = this.Grad_u; * Refined_MagGrad_u = this.MagGrad_u; */ }
/// <summary> /// Projects every basis polynomial for the quadrature rule of the /// given order onto a single cell grid supplied by the sub-class and /// approximates the LInfinity error of the projection. /// </summary> /// <remarks> /// The DG projection uses a quadrature rule of 2*n+1 for a basis of /// order n. Thus, make sure <paramref name="order"/> that a quadrature /// rule of order 2*order+1 exists before calling this method</remarks> /// <param name="order">The <b>requested</b> order</param> /// <param name="polynomials">The orthonormal polynomials</param> /// <param name="rule">The tested quadrature rule</param> private void TestProjectionError(int order, PolynomialList polynomials, QuadRule rule) { Basis basis = new Basis(context, order); for (int i = 0; i < polynomials.Count; i++) { if (2 * polynomials[i].AbsoluteDegree + 1 > order) { // Not integrable _exactly_ with this rule continue; } DGField field = new SinglePhaseField(basis); ScalarFunction function = delegate(MultidimensionalArray input, MultidimensionalArray output) { polynomials[i].Evaluate(output, new NodeSet(rule.RefElement, input)); }; field.ProjectField(function); double LInfError = 0; for (int j = 0; j < rule.NoOfNodes; j++) { MultidimensionalArray result = MultidimensionalArray.Create(1, 1); NodeSet point = new NodeSet(context.iGeomCells.GetRefElement(0), 1, rule.SpatialDim); for (int k = 0; k < rule.SpatialDim; k++) { point[0, k] = rule.Nodes[j, k]; } point.LockForever(); //Evaluate pointwise because we don't want the accumulated //result field.Evaluate(0, 1, point, result, 0.0); MultidimensionalArray exactResult = MultidimensionalArray.Create(1); polynomials[i].Evaluate(exactResult, point); LInfError = Math.Max(Math.Abs(result[0, 0] - exactResult[0]), LInfError); } //Console.WriteLine("ProjectionError: {0}", LInfError); Assert.IsTrue( LInfError <= 1e-13, String.Format( "Projection error too high for polynomial {0}. Error: {1:e}", i, LInfError)); } }
// Reinitialize Phasefield with changed interface thickness private void ReInit(double cahn_old, double cahn) { Console.WriteLine($"Reprojecting Phasefield:\n" + $" old thickness: {cahn_old}\n" + $" new thickness: {cahn}"); // we assume the current phasefield is close to the equilibrium tangenshyperbolicus form SinglePhaseField phiNew = new SinglePhaseField(phi.Basis); GridData GridDat = (GridData)(phi.GridDat); // compute and project // step one calculate distance field phiDist = 0.5 * log(Max(1+phi, eps)/Max(1-phi, eps)) * sqrt(2) * Cahn_old // step two project the new phasefield phiNew = tanh(phiDist/(sqrt(2) * Cahn_new)) // here done in one step, with default quadscheme // =================== phiNew.ProjectField( (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NS, MultidimensionalArray result) { // ScalarFunction2 Debug.Assert(result.Dimension == 2); Debug.Assert(Len == result.GetLength(0)); int K = result.GetLength(1); // number of nodes // evaluate Phi // ----------------------------- phi.Evaluate(j0, Len, NS, result); // compute the pointwise values of the new level set // ----------------------------- result.ApplyAll(x => Math.Tanh(0.5 * Math.Log(Math.Max(1 + x, 1e-10) / Math.Max(1 - x, 1e-10)) * (cahn_old / cahn))); } ); phi.Clear(); phi.Acc(1.0, phiNew); CorrectionLevSet.Clear(); CorrectionLevSet.Acc(1.0, phi); this.CorrectionLsTrk.UpdateTracker(0.0); // update DG LevelSet DGLevSet.Clear(); DGLevSet.Acc(1.0, phi); reinit++; PlotCurrentState(0.0, reinit); }
/// <summary> /// Returns thermodynamic pressure as function of inital mass and temperature. /// </summary> /// <param name="InitialMass"></param> /// <param name="Temperature"></param> /// <returns></returns> public override double GetMassDeterminedThermodynamicPressure(double InitialMass, SinglePhaseField Temperature) { SinglePhaseField omega = new SinglePhaseField(Temperature.Basis); omega.ProjectField(1.0, delegate(int j0, int Len, NodeSet NS, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray temp = MultidimensionalArray.Create(Len, K); Temperature.Evaluate(j0, Len, NS, temp); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { result[j, k] = 1 / temp[j, k]; } } }, new Foundation.Quadrature.CellQuadratureScheme(true, null)); return(InitialMass / omega.IntegralOver(null)); }
/// <summary> /// calculate the curvature corresponding to the Level-Set /// </summary> /// <param name="Curvature"></param> /// <param name="LevSetGradient"></param> /// <param name="VolMask"></param> public void ProjectToDGCurvature(SinglePhaseField Curvature, out VectorField <SinglePhaseField> LevSetGradient, CellMask VolMask = null) { if (VolMask == null) { VolMask = CellMask.GetFullMask(Curvature.Basis.GridDat); } Curvature.Clear(); Curvature.ProjectField(1.0, CurvEvaluation(mode), new Foundation.Quadrature.CellQuadratureScheme(true, VolMask)); // check the projection error projErr_curv = Curvature.L2Error( CurvEvaluation(mode), new Foundation.Quadrature.CellQuadratureScheme(true, VolMask)); //if (projErr_curv >= 1e-5) // Console.WriteLine("WARNING: Curvature projection error onto PhiDG = {0}", projErr_curv); LevSetGradient = null; }
#pragma warning restore 649 /// <summary> /// creates heat equation related fields /// </summary> public void CreateHeatFields() { int D = this.GridData.SpatialDimension; this.Temperature = new XDGField(new XDGBasis(this.LsTrk, this.Control.FieldOptions[VariableNames.Temperature].Degree), VariableNames.Temperature); base.RegisterField(this.Temperature); this.ResidualHeat = new XDGField(this.Temperature.Basis, "ResidualHeat"); base.RegisterField(this.ResidualHeat); this.HeatFlux = new VectorField <XDGField>(D.ForLoop(d => new XDGField(new XDGBasis(this.LsTrk, this.Control.FieldOptions[VariableNames.HeatFluxVectorComponent(d)].Degree), VariableNames.HeatFluxVectorComponent(d)))); base.RegisterField(this.HeatFlux); if (this.Control.conductMode != ConductivityInSpeciesBulk.ConductivityMode.SIP) { this.ResidualAuxHeatFlux = new VectorField <XDGField>(D.ForLoop(d => new XDGField(new XDGBasis(this.LsTrk, this.Control.FieldOptions[VariableNames.HeatFluxVectorComponent(d)].Degree), VariableNames.ResidualAuxHeatFluxVectorComponent(d)))); base.RegisterField(this.ResidualAuxHeatFlux); } this.DisjoiningPressure = new SinglePhaseField(new Basis(this.GridData, this.Control.FieldOptions[VariableNames.Pressure].Degree), "DisjoiningPressure"); if (this.Control.DisjoiningPressureFunc != null) { DisjoiningPressure.ProjectField(this.Control.DisjoiningPressureFunc); } base.RegisterField(this.DisjoiningPressure); }
/// <summary> /// Reconstructs a <see cref="BoSSS.Foundation.XDG.LevelSet"/> from a given set of points on a given DG field /// </summary> /// <param name="field">The DG field to work with</param> /// <param name="points"> <see cref="MultidimensionalArray"/> /// Lengths --> [0]: numOfPoints, [1]: 2 /// [1] --> [0]: x, [1]: y /// </param> public static SinglePhaseField ReconstructLevelSetField(SinglePhaseField field, MultidimensionalArray points) { // Init IGridData gridData = field.GridDat; // Evaluate gradient SinglePhaseField gradientX = new SinglePhaseField(field.Basis, "gradientX"); SinglePhaseField gradientY = new SinglePhaseField(field.Basis, "gradientY"); gradientX.DerivativeByFlux(1.0, field, d: 0); gradientY.DerivativeByFlux(1.0, field, d: 1); //gradientX = PatchRecovery(gradientX); //gradientY = PatchRecovery(gradientY); FieldEvaluation ev = new FieldEvaluation((GridData)gridData); MultidimensionalArray GradVals = MultidimensionalArray.Create(points.GetLength(0), 2); ev.Evaluate(1.0, new DGField[] { gradientX, gradientY }, points, 0.0, GradVals); // Level set reconstruction Console.WriteLine("Reconstruction of field levelSet started..."); int count = 0; Func <double[], double> func = delegate(double[] X) { double minDistSigned = double.MaxValue; int iMin = int.MaxValue; double closestPointOnInterfaceX = double.MaxValue; double closestPointOnInterfaceY = double.MaxValue; double x = X[0]; double y = X[1]; for (int i = 0; i < points.Lengths[0]; i++) { double currentPointX = points[i, 0]; double currentPointY = points[i, 1]; double deltaX = x - currentPointX; double deltaY = y - currentPointY; double dist = Math.Sqrt(deltaX * deltaX + deltaY * deltaY); if (dist <= minDistSigned) { iMin = i; minDistSigned = dist; closestPointOnInterfaceX = currentPointX; closestPointOnInterfaceY = currentPointY; } } //// Compute global cell index of quadrature node //gridData.LocatePoint(X, out long GlobalId, out long GlobalIndex, out bool IsInside, out bool OnThisProcess); //// Compute local node set //NodeSet nodeSet = GetLocalNodeSet(gridData, X, (int)GlobalIndex); //// Evaluate gradient //// Get local cell index of quadrature node //int j0Grd = gridData.CellPartitioning.i0; //int j0 = (int)(GlobalIndex - j0Grd); //int Len = 1; //MultidimensionalArray resultGradX = MultidimensionalArray.Create(1, 1); //MultidimensionalArray resultGradY = MultidimensionalArray.Create(1, 1); //gradientX.Evaluate(j0, Len, nodeSet, resultGradX); //gradientY.Evaluate(j0, Len, nodeSet, resultGradY); int sign = Math.Sign((x - closestPointOnInterfaceX) * GradVals[iMin, 0] + (y - closestPointOnInterfaceY) * GradVals[iMin, 1]); minDistSigned *= sign; //Console.WriteLine(String.Format("Quadrature point #{0}: ({1}, {2}), interface point: ({3}, {4})", count, X[0], X[1], closestPointOnInterfaceX, closestPointOnInterfaceY)); count++; return(minDistSigned); }; // DG level set field SinglePhaseField DGLevelSet = new SinglePhaseField(field.Basis, "levelSet_recon"); DGLevelSet.ProjectField(func.Vectorize()); Console.WriteLine("finished"); return(DGLevelSet); }
void TestAgglomeration_Projection(int quadOrder, MultiphaseCellAgglomerator Agg) { var Bmask = LsTrk.Regions.GetSpeciesMask("B"); var BbitMask = Bmask.GetBitMask(); var XDGmetrics = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, quadOrder, 1); int degree = Math.Max(0, this.u.Basis.Degree - 1); _2D SomePolynomial; if (degree == 0) { SomePolynomial = (x, y) => 3.2; } else if (degree == 1) { SomePolynomial = (x, y) => 3.2 + x - 2.4 * y; } else { SomePolynomial = (x, y) => x * x + y * y; } // ------------------------------------------------ // project the polynomial onto a single-phase field // ------------------------------------------------ SinglePhaseField NonAgglom = new SinglePhaseField(new Basis(this.GridData, degree), "NonAgglom"); NonAgglom.ProjectField(1.0, SomePolynomial.Vectorize(), new CellQuadratureScheme(true, Bmask)); // ------------------------------------------------ // project the polynomial onto the aggomerated XDG-field // ------------------------------------------------ var qsh = XDGmetrics.XQuadSchemeHelper; // Compute the inner product of 'SomePolynomial' with the cut-cell-basis, ... SinglePhaseField xt = new SinglePhaseField(NonAgglom.Basis, "test"); xt.ProjectField(1.0, SomePolynomial.Vectorize(), qsh.GetVolumeQuadScheme(this.LsTrk.GetSpeciesId("B")).Compile(this.GridData, Agg.CutCellQuadratureOrder)); CoordinateMapping map = xt.Mapping; // ... change to the cut-cell-basis, ... double[] xVec = xt.CoordinateVector.ToArray(); Agg.ManipulateMatrixAndRHS(default(MsrMatrix), xVec, map, null); { double[] xVec2 = xVec.CloneAs(); Agg.ClearAgglomerated(xVec2, map); // clearing should have no effect now. double Err3 = GenericBlas.L2DistPow2(xVec, xVec2).MPISum().Sqrt(); Assert.LessOrEqual(Err3, 0.0); } // ... multiply with the inverse mass-matrix, ... var Mfact = XDGmetrics.MassMatrixFactory; BlockMsrMatrix MassMtx = Mfact.GetMassMatrix(map, false); Agg.ManipulateMatrixAndRHS(MassMtx, default(double[]), map, map); var InvMassMtx = MassMtx.InvertBlocks(OnlyDiagonal: true, Subblocks: true, ignoreEmptyBlocks: true, SymmetricalInversion: true); double[] xAggVec = new double[xVec.Length]; InvMassMtx.SpMV(1.0, xVec, 0.0, xAggVec); // ... and extrapolate. // Since we projected a polynomial, the projection is exact and after extrapolation, must be equal // to the polynomial. xt.CoordinateVector.SetV(xAggVec); Agg.Extrapolate(xt.Mapping); // ------------------------------------------------ // check the error // ------------------------------------------------ //double Err2 = xt.L2Error(SomePolynomial.Vectorize(), new CellQuadratureScheme(domain: Bmask)); double Err2 = NonAgglom.L2Error(xt); Console.WriteLine("Agglom: projection and extrapolation error: " + Err2); Assert.LessOrEqual(Err2, 1.0e-10); }
protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { origin.ProjectField((x, y) => (Math.Sin(x) + Math.Cos(x) + x - (Math.Cos(y) + 1))); // 2D //origin.ProjectField((x, y, z) => (Math.Sin(x) + Math.Cos(x) + x - (y + 1) + Math.Sin(z))); // 3D //origin.ProjectField((x, y, z) => Math.Sqrt(x.Pow2() + y.Pow2() + z.Pow2()) - 1); //origin.ProjectField((x, y) => x * x + y * y * y - x * y); //origin.ProjectField((x,y) => x + y); //origin.ProjectField((x, y) => Math.Sin(2 * Math.PI * (x / 3.0))); CellMask msk2D = CellMask.GetCellMask((BoSSS.Foundation.Grid.Classic.GridData)(this.GridData), X => (X[0] > 0.0 && X[0] < 4.0 && X[1] > 0.0 && X[1] < 1.0)); //|| (X[0] > 1.0 && X[0] < 3.0 && X[1] > 1.0 && X[1] < 2.0) //|| (X[0] > 2.0 && X[0] < 4.0 && X[1] > 2.0 && X[1] < 3.0) //|| (X[0] > 3.0 && X[0] < 4.0 && X[1] > 3.0 && X[1] < 4.0)); //CellMask msk3D = CellMask.GetCellMask(this.GridData, X => (X[0] > 0.0 && X[0] < 3.0 && X[1] > 0.0 && X[1] < 3.0 && X[2] > 0.0 && X[2] < 1.5) //|| (X[0] > 0.0 && X[0] < 1.5 && X[1] > 0.0 && X[1] < 3.0 && X[2] > 0.0 && X[2] < 3.0) //|| (X[0] > 0.0 && X[0] < 3.0 && X[1] > 0.0 && X[1] < 1.5 && X[2] > 0.0 && X[2] < 3.0)); CellMask test = null; cdgField.ProjectDGField(1.0, origin, test); cdgField.AccToDGField(1.0, result); //specField.ProjectDGField(1.0, origin, test); //specField.AccToDGField(1.0, specFieldDG); //MultidimensionalArray n4 = MultidimensionalArray.Create(3, 2); //n4[0, 0] = 0.3; //n4[0, 1] = -1; //n4[1, 0] = 0.6; //n4[1, 1] = -1; //n4[2, 0] = 0.9; //n4[2, 1] = -1; //MultidimensionalArray n11 = MultidimensionalArray.Create(3, 2); //n11[0, 0] = -0.4; //n11[0, 1] = 1; //n11[1, 0] = 0.2; //n11[1, 1] = 1; //n11[2, 0] = 0.8; //n11[2, 1] = 1; //NodeSet ns4 = new NodeSet(Grid.GetRefElement(0), n4); //NodeSet ns11 = new NodeSet(Grid.GetRefElement(0), n11); //MultidimensionalArray res4 = MultidimensionalArray.Create(1, 3); //MultidimensionalArray res11 = MultidimensionalArray.Create(1, 3); //result.Evaluate(4,1,ns4, res4); //result.Evaluate(11, 1, ns11, res11); PlotCurrentState(0.0, 0, 4); //var err = origin.CloneAs(); //err.Acc(-1.0, result); double L2err = 0.0; //err.L2Norm(); double L2jump = JumpNorm(result, test); Console.WriteLine(""); //double L2jump_specFEM = JumpNorm(specFieldDG, test); //Console.WriteLine("L2 error = " + L2err); Console.WriteLine("L2 Norm of [[u]] = " + L2jump); //Console.WriteLine("L2 Norm of [[u]] = " + L2jump_specFEM); if (L2err < 1.0e-10 && L2jump < 1.0e-12) { Console.WriteLine("Test PASSED"); passed = true; } else { Console.WriteLine("Test FAILED"); passed = false; } base.TerminationKey = true; return(0.0); }
/// <summary> /// Computation of mean curvature according to Bonnet's formula. /// </summary> /// <param name="scale"></param> /// <param name="Output"> /// output. /// </param> /// <param name="quadScheme"></param> /// <param name="UseCenDiffUpTo"> /// Either 0, 1, or 2: /// If 0, all derivatives are computed locally (broken derivative); /// if 1, the first order derivatives are computed by central /// differences, while the second order ones are computed locally, /// based on the first order ones; /// if 2, all derivatives are computed by central differences. /// </param> /// <param name="_1stDerivDegree"> /// Relative DG polynomial degree for the 1st order derivatives, i.e. /// degree is <paramref name="_1stDerivDegree"/>+<em>p</em>, where /// <em>p</em> is the degree of this field. /// Only active if <paramref name="UseCenDiffUpTo"/> is greater than 0. /// </param> /// <param name="_2ndDerivDegree"> /// Relative DG polynomial degree for the 2nd order derivatives, i.e. /// degree is <paramref name="_2ndDerivDegree"/>+<em>p</em>, where /// <em>p</em> is the degree of this field. Only active if /// <paramref name="UseCenDiffUpTo"/> is greater than 1. /// </param> /// <remarks> /// using central differences causes memory allocation: <em>D</em> /// fields for <paramref name="UseCenDiffUpTo"/>=1, and /// <em>D</em>*(<em>D</em>+1) for <paramref name="UseCenDiffUpTo"/>=2, /// where <em>D</em> notates the spatial dimension. /// </remarks> public void ProjectTotalcurvature2( double scale, SinglePhaseField Output, int UseCenDiffUpTo, int _1stDerivDegree = 0, int _2ndDerivDegree = 0, CellQuadratureScheme quadScheme = null) { using (new FuncTrace()) { if (UseCenDiffUpTo < 0 || UseCenDiffUpTo > 2) { throw new ArgumentOutOfRangeException(); } //int M = Output.Basis.Length; //int N = this.Basis.Length; int D = this.GridDat.SpatialDimension; //var NSC = m_context.NSC; SubGrid sgrd = null; SpatialOperator.SubGridBoundaryModes bndMode = SpatialOperator.SubGridBoundaryModes.InnerEdge; if (UseCenDiffUpTo >= 1 && quadScheme != null && quadScheme.Domain != null) { sgrd = new SubGrid(quadScheme.Domain); bndMode = SpatialOperator.SubGridBoundaryModes.OpenBoundary; } // compute 1st order derivatives by central differences, if desired // ================================================================ Basis B2 = new Basis(this.GridDat, this.Basis.Degree + _1stDerivDegree); SinglePhaseField[] GradientVector = null; if (UseCenDiffUpTo >= 1) { GradientVector = new SinglePhaseField[D]; for (int d = 0; d < D; d++) { GradientVector[d] = new SinglePhaseField(B2); GradientVector[d].DerivativeByFlux(1.0, this, d, sgrd, bndMode); } } // compute 2nd order derivatives by central differences, if desired // =============================================================== Basis B3 = new Basis(this.GridDat, this.Basis.Degree + _2ndDerivDegree); SinglePhaseField[,] HessianTensor = null; if (UseCenDiffUpTo >= 2) { HessianTensor = new SinglePhaseField[D, D]; for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { HessianTensor[d1, d2] = new SinglePhaseField(B3); HessianTensor[d1, d2].DerivativeByFlux(1.0, GradientVector[d1], d2, sgrd, bndMode); } } } // compute and project // =================== // buffers: MultidimensionalArray Phi = new MultidimensionalArray(2); MultidimensionalArray GradPhi = new MultidimensionalArray(3); MultidimensionalArray HessPhi = new MultidimensionalArray(4); MultidimensionalArray ooNormGrad = new MultidimensionalArray(2); MultidimensionalArray Laplace = new MultidimensionalArray(2); MultidimensionalArray Q = new MultidimensionalArray(3); // evaluate/project: //double Erracc = 0; Output.ProjectField(scale, (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result) { // ScalarFunction2 Debug.Assert(result.Dimension == 2); Debug.Assert(Len == result.GetLength(0)); int K = result.GetLength(1); // number of nodes // alloc buffers // ------------- if (Phi.GetLength(0) != Len || Phi.GetLength(1) != K) { Phi.Allocate(Len, K); GradPhi.Allocate(Len, K, D); HessPhi.Allocate(Len, K, D, D); ooNormGrad.Allocate(Len, K); Laplace.Allocate(Len, K); Q.Allocate(Len, K, D); } else { Phi.Clear(); GradPhi.Clear(); HessPhi.Clear(); ooNormGrad.Clear(); Laplace.Clear(); Q.Clear(); } // evaluate Gradient and Hessian // ----------------------------- if (UseCenDiffUpTo >= 1) { for (int d = 0; d < D; d++) { GradientVector[d].Evaluate(j0, Len, NodeSet, GradPhi.ExtractSubArrayShallow(-1, -1, d)); } } else { this.EvaluateGradient(j0, Len, NodeSet, GradPhi); } if (UseCenDiffUpTo == 2) { for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { HessianTensor[d1, d2].Evaluate(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d1, d2)); } } } else if (UseCenDiffUpTo == 1) { for (int d = 0; d < D; d++) { var GradientVector_d = GradientVector[d]; GradientVector_d.EvaluateGradient(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d, -1), 0, 0.0); } } else if (UseCenDiffUpTo == 0) { this.EvaluateHessian(j0, Len, NodeSet, HessPhi); } else { Debug.Assert(false); } // compute the monstrous formula // ----------------------------- // norm of Gradient: for (int d = 0; d < D; d++) { var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d); ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik"); } ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x)); // laplacian of phi: for (int d = 0; d < D; d++) { var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d); Laplace.Acc(1.0, HessPhi_d_d); } // result = Laplacian(phi)/|Grad phi| result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik"); // result = Grad(1/|Grad(phi)|) for (int d1 = 0; d1 < D; d1++) { var Qd = Q.ExtractSubArrayShallow(-1, -1, d1); for (int d2 = 0; d2 < D; d2++) { var Grad_d2 = GradPhi.ExtractSubArrayShallow(-1, -1, d2); var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1); Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik"); } } ooNormGrad.ApplyAll(x => x * x * x); result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik"); //for (int i = 0; i < Len; i++) { // for (int k = 0; k < K; k++) { // double acc = 0; // for (int d = 0; d < D; d++) { // acc += GradPhi[i,k,d]*Q[i,k,d]*ooNormGrad[i,k]; // } // Erracc += (acc - result[i,k]).Abs(); // } //} }, quadScheme.SaveCompile(this.GridDat, (Output.Basis.Degree + this.m_Basis.Degree * (this.m_Basis.Degree - 1) * D) * 2) ); } }
/// <summary> /// Single run of the solver /// </summary> protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { using (new FuncTrace()) { if (Control.ExactSolution_provided) { Tex.Clear(); Tex.ProjectField(this.Control.InitialValues_Evaluators["Tex"]); RHS.Clear(); RHS.ProjectField(this.Control.InitialValues_Evaluators["RHS"]); } if (Control.AdaptiveMeshRefinement == false) { base.NoOfTimesteps = -1; if (TimestepNo > 1) { throw new ApplicationException("steady-state-equation."); } base.TerminationKey = true; } // Update matrices // --------------- UpdateMatrices(); // call solver // ----------- double mintime, maxtime; bool converged; int NoOfIterations; ClassicSolve(out mintime, out maxtime, out converged, out NoOfIterations); Console.WriteLine("finished; " + NoOfIterations + " iterations."); Console.WriteLine("converged? " + converged); Console.WriteLine("Timespan: " + mintime + " to " + maxtime + " seconds"); base.QueryHandler.ValueQuery("minSolRunT", mintime, true); base.QueryHandler.ValueQuery("maxSolRunT", maxtime, true); base.QueryHandler.ValueQuery("Conv", converged ? 1.0 : 0.0, true); base.QueryHandler.ValueQuery("NoIter", NoOfIterations, true); base.QueryHandler.ValueQuery("NoOfCells", this.GridData.CellPartitioning.TotalLength, true); base.QueryHandler.ValueQuery("DOFs", T.Mapping.TotalLength, true); base.QueryHandler.ValueQuery("BlockSize", T.Basis.Length, true); if (base.Control.ExactSolution_provided) { Error.Clear(); Error.AccLaidBack(1.0, Tex); Error.AccLaidBack(-1.0, T); double L2_ERR = Error.L2Norm(); Console.WriteLine("\t\tL2 error on " + this.Grid.NumberOfCells + ": " + L2_ERR); base.QueryHandler.ValueQuery("SolL2err", L2_ERR, true); } // evaluate residual // ================= { this.ResiualKP1.Clear(); if (this.Control.InitialValues_Evaluators.ContainsKey("RHS")) { this.ResiualKP1.ProjectField(this.Control.InitialValues_Evaluators["RHS"]); } var ev = this.LapaceIp.GetEvaluator(T.Mapping, ResiualKP1.Mapping); ev.Evaluate(-1.0, 1.0, ResiualKP1.CoordinateVector); } // return // ====== return(0.0); } }
/// <summary> /// /// </summary> /// <param name="output">output</param> /// <param name="cm">mask on which the filtering should be performed</param> /// <param name="input">input</param> /// <param name="mode"></param> public static void FilterStencilProjection(SinglePhaseField output, CellMask cm, SinglePhaseField input, PatchRecoveryMode mode) { var GridDat = input.GridDat; if (!object.ReferenceEquals(output.GridDat, GridDat)) { throw new ArgumentException(); } if (!object.ReferenceEquals(input.GridDat, GridDat)) { throw new ArgumentException(); } if (cm == null) { cm = CellMask.GetFullMask(GridDat); } switch (mode) { case PatchRecoveryMode.L2_unrestrictedDom: case PatchRecoveryMode.L2_restrictedDom: { var Mask = cm.GetBitMaskWithExternal(); bool RestrictToCellMask = mode == PatchRecoveryMode.L2_restrictedDom; foreach (int jCell in cm.ItemEnum) { int[] NeighCells, dummy; GridDat.GetCellNeighbours(jCell, GetCellNeighbours_Mode.ViaVertices, out NeighCells, out dummy); if (RestrictToCellMask == true) { NeighCells = NeighCells.Where(j => Mask[j]).ToArray(); } FilterStencilProjection(output, jCell, NeighCells, input); } return; } case PatchRecoveryMode.ChebychevInteroplation: { int P = input.Basis.Degree * 3; double[] ChebyNodes = ChebyshevNodes(P); NodeSet Nds = new NodeSet(GridDat.iGeomCells.RefElements[0], P, 1); Nds.SetColumn(0, ChebyNodes); Nds.LockForever(); Polynomial[] Polynomials = GetNodalPolynomials(ChebyNodes); MultidimensionalArray PolyVals = MultidimensionalArray.Create(P, P); for (int p = 0; p < P; p++) { Polynomials[p].Evaluate(PolyVals.ExtractSubArrayShallow(p, -1), Nds); for (int i = 0; i < P; i++) { Debug.Assert(Math.Abs(((i == p) ? 1.0 : 0.0) - PolyVals[p, i]) <= 1.0e-8); } } foreach (int jCell in cm.ItemEnum) { AffineTrafo T; var NodalValues = NodalPatchRecovery(jCell, ChebyNodes, input, out T); /* * MultidimensionalArray Nodes2D = MultidimensionalArray.Create(P, P, 2); * for (int i = 0; i < P; i++) { * for (int j = 0; j < P; j++) { * Nodes2D[i, j, 0] = ChebyNodes[i]; * Nodes2D[i, j, 1] = ChebyNodes[j]; * } * } * var _Nodes2D = Nodes2D.ResizeShallow(P*P, 2); * var xNodes = _Nodes2D.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { P*P - 1, 0 }); * var yNodes = _Nodes2D.ExtractSubArrayShallow(new int[] { 0, 1 }, new int[] { P*P - 1, 1 }); * int K = P*P; * * MultidimensionalArray xPolyVals = MultidimensionalArray.Create(P, K); * MultidimensionalArray yPolyVals = MultidimensionalArray.Create(P, K); * * for (int p = 0; p < P; p++) { * Polynomials[p].Evaluate(yPolyVals.ExtractSubArrayShallow(p, -1), yNodes); * Polynomials[p].Evaluate(xPolyVals.ExtractSubArrayShallow(p, -1), xNodes); * * } * * * double ERR = 0; * for (int k = 0; k < K; k++) { * * double x = xNodes[k, 0]; * double y = yNodes[k, 0]; * * double acc = 0; * double BasisHits = 0.0; * for (int i = 0; i < P; i++) { * for (int j = 0; j < P; j++) { * * bool isNode = (Math.Abs(x - ChebyNodes[i]) < 1.0e-8) && (Math.Abs(y - ChebyNodes[j]) < 1.0e-8); * double BasisSoll = isNode ? 1.0 : 0.0; * if (isNode) * Console.WriteLine(); * * double Basis_ij = xPolyVals[i, k]*yPolyVals[j, k]; * * Debug.Assert((Basis_ij - BasisSoll).Abs() < 1.0e-8); * * BasisHits += Math.Abs(Basis_ij); * * acc += Basis_ij*NodalValues[i, j]; * } * } * Debug.Assert(Math.Abs(BasisHits - 1.0) < 1.0e-8); * * * * * double soll = yNodes[k,0]; * Debug.Assert((soll - acc).Pow2() < 1.0e-7); * ERR = (soll - acc).Pow2(); * } * Console.WriteLine(ERR); */ output.ProjectField(1.0, delegate(int j0, int Len, NodeSet Nodes, MultidimensionalArray result) { var K = Nodes.NoOfNodes; MultidimensionalArray NT = T.Transform(Nodes); var xNodes = new NodeSet(null, NT.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { K - 1, 0 })); var yNodes = new NodeSet(null, NT.ExtractSubArrayShallow(new int[] { 0, 1 }, new int[] { K - 1, 1 })); MultidimensionalArray xPolyVals = MultidimensionalArray.Create(P, K); MultidimensionalArray yPolyVals = MultidimensionalArray.Create(P, K); for (int p = 0; p < P; p++) { Polynomials[p].Evaluate(yPolyVals.ExtractSubArrayShallow(p, -1), yNodes); Polynomials[p].Evaluate(xPolyVals.ExtractSubArrayShallow(p, -1), xNodes); } for (int k = 0; k < K; k++) { double acc = 0; for (int i = 0; i < P; i++) { for (int j = 0; j < P; j++) { acc += xPolyVals[i, k] * yPolyVals[j, k] * NodalValues[i, j]; } } result[0, k] = acc; } }, new CellQuadratureScheme(true, new CellMask(input.GridDat, Chunk.GetSingleElementChunk(jCell)))); } return; } } }
private void MassCorrection() { double[] Qnts_old = ComputeBenchmarkQuantities(); CorrectionLevSet.Clear(); CorrectionLevSet.Acc(1.0, phi); this.CorrectionLsTrk.UpdateTracker(0.0); double[] Qnts = ComputeBenchmarkQuantities(); double massDiff = Qnts_old[0] - Qnts[0]; // we assume the current phasefield is close to the equilibrium tangenshyperbolicus form SinglePhaseField phiNew = new SinglePhaseField(phi.Basis); GridData GridDat = (GridData)(phi.GridDat); double mass_uc = Qnts[0]; int i = 0; while (massDiff.Abs() > 1e-6) { // calculated for a cone, one could include the shape e.g. by using the circularity // correction guess double correction = Math.Sign(massDiff) * 1e-10;//-Qnts[1] / (4 * Qnts[0] * Math.PI) * massDiff * 1e-5; // take the correction guess and calculate a forward difference to approximate the derivative phiNew.ProjectField( (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NS, MultidimensionalArray result) { // ScalarFunction2 Debug.Assert(result.Dimension == 2); Debug.Assert(Len == result.GetLength(0)); int K = result.GetLength(1); // number of nodes // evaluate Phi // ----------------------------- phi.Evaluate(j0, Len, NS, result); // compute the pointwise values of the new level set // ----------------------------- result.ApplyAll(x => 0.5 * Math.Log(Math.Max(1 + x, 1e-10) / Math.Max(1 - x, 1e-10)) * Math.Sqrt(2) * this.Control.cahn); result.ApplyAll(x => Math.Tanh((x + correction) / (Math.Sqrt(2) * this.Control.cahn))); } ); // update LsTracker CorrectionLevSet.Clear(); CorrectionLevSet.Acc(1.0, phiNew); this.CorrectionLsTrk.UpdateTracker(0.0); Qnts = ComputeBenchmarkQuantities(); correction = -(massDiff) / ((Qnts_old[0] - Qnts[0] - massDiff) / (correction)); double initial = massDiff; bool finished = false; int k = 0; //while (massDiff.Abs() - initial.Abs() >= 0.0 && step > 1e-12) while (!finished) { double step = Math.Pow(0.5, k); // compute and project // step one calculate distance field phiDist = 0.5 * log(Max(1+c, eps)/Max(1-c, eps)) * sqrt(2) * Cahn // step two project the new phasefield phiNew = tanh((cDist + correction)/(sqrt(2) * Cahn)) // =================== phiNew.ProjectField( (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NS, MultidimensionalArray result) { // ScalarFunction2 Debug.Assert(result.Dimension == 2); Debug.Assert(Len == result.GetLength(0)); int K = result.GetLength(1); // number of nodes // evaluate Phi // ----------------------------- phi.Evaluate(j0, Len, NS, result); // compute the pointwise values of the new level set // ----------------------------- result.ApplyAll(x => 0.5 * Math.Log(Math.Max(1 + x, 1e-10) / Math.Max(1 - x, 1e-10)) * Math.Sqrt(2) * this.Control.cahn); result.ApplyAll(x => Math.Tanh((x + correction * step) / (Math.Sqrt(2) * this.Control.cahn))); } ); // update LsTracker CorrectionLevSet.Clear(); CorrectionLevSet.Acc(1.0, phiNew); this.CorrectionLsTrk.UpdateTracker(0.0); Qnts = ComputeBenchmarkQuantities(); massDiff = Qnts_old[0] - Qnts[0]; if (massDiff.Abs() < (1 - 1e-4 * step) * initial.Abs()) { finished = true; // update field phi.Clear(); phi.Acc(1.0, phiNew); // update LsTracker CorrectionLevSet.Clear(); CorrectionLevSet.Acc(1.0, phi); this.CorrectionLsTrk.UpdateTracker(0.0); Console.WriteLine($"" + $"converged with stepsize: {step}, correction: {correction}\n" + $" dM: {massDiff}"); if (k > 0) { Console.WriteLine($"Finished Linesearch in {k} iterations"); } } else if (Math.Abs(correction * step) < 1e-15) { // reset LsTracker CorrectionLevSet.Clear(); CorrectionLevSet.Acc(1.0, phi); this.CorrectionLsTrk.UpdateTracker(0.0); Qnts = ComputeBenchmarkQuantities(); massDiff = Qnts_old[0] - Qnts[0]; Console.WriteLine($" Linesearch failed after {k} iterations"); goto Failed; } else { k++; } } i++; } Failed: Console.WriteLine($"Performed Mass Correction in {i} iteratins: \n" + $"\told mass: {Qnts_old[0]:N4}\n" + $"\tuncorrected mass: {mass_uc:N4}\n" + $"\tcorrected mass: {Qnts[0]:N4}"); }
protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { //origin.ProjectField((x, y) => 1-x*x); origin.ProjectField((x, y) => x * x + y * y * y - x * y); specField.ProjectDGFieldCheaply(1.0, origin); //specField.ProjectDGField(1.0, origin); /* * if (this.MPIRank >= 0) { * // specField.Coordinates[46] = 1; * // specField.Coordinates[48] = -1; * ilPSP.Environment.StdoutOnlyOnRank0 = false; * * Random R = new Random(); * * for (int t = 1; t <= 2; t++) { * int i0 = spec_basis.GetLocalOwnedNodesOffset(t); * int L = spec_basis.GetNoOfOwnedNodes(t); * * * for (int l = 0; l < L; l++) { * double x = specField.Basis.GlobalNodes[i0 + l, 0]; * double y = specField.Basis.GlobalNodes[i0 + l, 1]; * * specField.Coordinates[i0 + l] = R.NextDouble(); * * //if (Math.Abs(x - (+2.0)) < 1.0e-8) { * // Console.WriteLine("Hi! R" + this.MPIRank + ", " + (l + i0) + " (" + x + "," + y + ")"); * // specField.Coordinates[i0 + l] = y; * //} * * } * } * * //ilPSP.Environment.StdoutOnlyOnRank0 = true; * * }*/ using (var m_transciever = new Foundation.SpecFEM.Transceiver(spec_basis)) { m_transciever.Scatter(specField.Coordinates); } specField.AccToDGField(1.0, Result); var ERR = origin.CloneAs(); ERR.Acc(-1.0, Result); double L2Err = ERR.L2Norm(); double L2Jump = JumpNorm(Result); Console.WriteLine("L2 Error: " + L2Err); Console.WriteLine("L2 Norm of [[u]]: " + L2Jump); if ((L2Err < 1.0e-10 || this.Grid.PeriodicTrafo.Count > 0) && L2Jump < 1.0e-10) { Console.WriteLine("Test PASSED"); Passed = true; } else { Console.WriteLine("Test FAILED"); Passed = false; } Passed = true; base.TerminationKey = true; return(0.0); }