//TO BE CHANGED!!!!! public void GradientNorm(out SinglePhaseField norm, CellMask cm) { Basis basisForNorm = new Basis(this.GridDat, this.Basis.Degree * 2); norm = new SinglePhaseField(basisForNorm); Func <Basis, string, SinglePhaseField> fac = (Basis b, string id) => new SinglePhaseField(b, id); VectorField <SinglePhaseField> Gradient = new VectorField <SinglePhaseField>(GridDat.SpatialDimension, Basis, fac); for (int i = 0; i < GridDat.SpatialDimension; i++) { Gradient[i].Derivative(1.0, this, i, cm); } norm.ProjectAbs <SinglePhaseField>(1.0, Gradient); }
/// <summary> /// Assigns the normalized gradient of the level set to the Output /// vector /// </summary> /// <param name="Output">Normal vector</param> /// <param name="optionalSubGrid"> /// Restriction of the computations to a an optional subgrid /// </param> /// <param name="bndMode"></param> public void ComputeNormalByFlux(VectorField <SinglePhaseField> Output, SubGrid optionalSubGrid = null, SpatialOperator.SubGridBoundaryModes bndMode = SpatialOperator.SubGridBoundaryModes.OpenBoundary) { if (this.m_Basis.Degree < 1) { throw new ArgumentException("For correct computation of these level set quantities, the level set has to be at least of degree 1!"); } SinglePhaseField absval = new SinglePhaseField(Output[0].Basis); //Output.Clear(); for (int i = 0; i < Output.Dim; i++) { Output[i].DerivativeByFlux(1.0, this, i, optionalSubGrid, bndMode); } absval.ProjectAbs(1.0, Output); for (int i = 0; i < Output.Dim; i++) { Output[i].ProjectQuotient(1.0, Output[i], absval, null, false); } }
/// <summary> /// Assigns the normalized gradient of the level set to the Output /// vector /// </summary> /// <param name="Output">Normal Vector</param> /// <param name="optionalCellMask"> /// Cell mask used when computing the derivatives /// </param> public void ComputeNormal(VectorField <SinglePhaseField> Output, CellMask optionalCellMask) { if (this.m_Basis.Degree < 1) { throw new ArgumentException("For correct computation of these level set quantities, the level set has to be at least of degree 1!"); } SinglePhaseField absval = new SinglePhaseField(Output[0].Basis); Output.Clear(); for (int i = 0; i < Output.Dim; i++) { Output[i].Derivative(1.0, this, i, optionalCellMask); } absval.ProjectAbs(1.0, Output); for (int i = 0; i < Output.Dim; i++) { Output[i].ProjectQuotient(1.0, Output[i], absval, null, false); } }
/// <summary> /// Obtaining the time integrated spatial discretization of the reinitialization equation in a narrow band around the zero level set, based on a Godunov's numerical Hamiltonian calculation /// </summary> /// <param name="LS"> The level set function </param> /// <param name="Restriction"> The narrow band around the zero level set </param> /// <param name="NumberOfTimesteps"> /// maximum number of pseudo-timesteps /// </param> /// <param name="thickness"> /// The smoothing width of the signum function. /// This is the main stabilization parameter for re-initialization. /// It should be set to approximately 3 cells. /// </param> /// <param name="TimestepSize"> /// size of the pseudo-timestep /// </param> public void ReInitialize(LevelSet LS, SubGrid Restriction, double thickness, double TimestepSize, int NumberOfTimesteps) { using (var tr = new FuncTrace()) { // log parameters: tr.Info("thickness: " + thickness.ToString(NumberFormatInfo.InvariantInfo)); tr.Info("TimestepSize: " + TimestepSize.ToString(NumberFormatInfo.InvariantInfo)); tr.Info("NumberOfTimesteps: " + NumberOfTimesteps); ExplicitEuler TimeIntegrator; SpatialOperator SO; Func <int[], int[], int[], int> QuadratureOrder = QuadOrderFunc.NonLinear(3); if (m_ctx.SpatialDimension == 2) { SO = new SpatialOperator(1, 5, 1, QuadratureOrder, new string[] { "LS", "LSCGV", "LSDG[0]", "LSUG[0]", "LSDG[1]", "LSUG[1]", "Result" }); SO.EquationComponents["Result"].Add(new GodunovHamiltonian(m_ctx, thickness)); SO.Commit(); TimeIntegrator = new RungeKutta(m_Scheme, SO, new CoordinateMapping(LS), new CoordinateMapping(LSCGV, LSDG[0], LSUG[0], LSDG[1], LSUG[1]), sgrd: Restriction); } else { SO = new SpatialOperator(1, 7, 1, QuadratureOrder, new string[] { "LS", "LSCGV", "LSDG[0]", "LSUG[0]", "LSDG[1]", "LSUG[1]", "LSDG[2]", "LSUG[2]", "Result" }); SO.EquationComponents["Result"].Add(new GodunovHamiltonian(m_ctx, thickness)); SO.Commit(); TimeIntegrator = new RungeKutta(m_Scheme, SO, new CoordinateMapping(LS), new CoordinateMapping(LSCGV, LSDG[0], LSUG[0], LSDG[1], LSUG[1], LSDG[2], LSUG[2]), sgrd: Restriction); } // Calculating the gradients in each sub-stage of a Runge-Kutta integration procedure ExplicitEuler.ChangeRateCallback EvalGradients = delegate(double t1, double t2) { LSUG.Clear(); CalculateLevelSetGradient(LS, LSUG, "Upwind", Restriction); LSDG.Clear(); CalculateLevelSetGradient(LS, LSDG, "Downwind", Restriction); LSCG.Clear(); CalculateLevelSetGradient(LS, LSCG, "Central", Restriction); LSCGV.Clear(); var VolMask = (Restriction != null) ? Restriction.VolumeMask : null; LSCGV.ProjectAbs(1.0, VolMask, LSCG.ToArray()); }; TimeIntegrator.OnBeforeComputeChangeRate += EvalGradients; { EvalGradients(0, 0); var GodunovResi = new SinglePhaseField(LS.Basis, "Residual"); SO.Evaluate(1.0, 0.0, LS.Mapping, TimeIntegrator.ParameterMapping.Fields, GodunovResi.Mapping, Restriction); //Tecplot.Tecplot.PlotFields(ArrayTools.Cat<DGField>( LSUG, LSDG, LS, GodunovResi), "Residual", 0, 3); } // pseudo-timestepping // =================== double factor = 1.0; double time = 0; LevelSet prevLevSet = new LevelSet(LS.Basis, "prevLevSet"); CellMask RestrictionMask = (Restriction == null) ? null : Restriction.VolumeMask; for (int i = 0; (i < NumberOfTimesteps); i++) { tr.Info("Level set reinitialization pseudo-timestepping, timestep " + i); // backup old Levelset // ------------------- prevLevSet.Clear(); prevLevSet.Acc(1.0, LS, RestrictionMask); // time integration // ---------------- double dt = TimestepSize * factor; tr.Info("dt = " + dt.ToString(NumberFormatInfo.InvariantInfo) + " (factor = " + factor.ToString(NumberFormatInfo.InvariantInfo) + ")"); TimeIntegrator.Perform(dt); time += dt; // change norm // ------ prevLevSet.Acc(-1.0, LS, RestrictionMask); double ChangeNorm = prevLevSet.L2Norm(RestrictionMask); Console.WriteLine("Reinit: PseudoTime: {0} - Changenorm: {1}", i, ChangeNorm); //Tecplot.Tecplot.PlotFields(new SinglePhaseField[] { LS }, m_ctx, "Reinit-" + i, "Reinit-" + i, i, 3); } //*/ } }
/// <summary> /// In this method, the vector normal to the surface as well as certain derivatives /// of it that we intend to use are set up /// </summary> protected void NormalVec(double deltax) { wx = new SinglePhaseField(m_gradBasis, "wx"); wy = new SinglePhaseField(m_gradBasis, "wy"); if (m_Context.Grid.SpatialDimension == 2) { m_Gradw = new VectorField <SinglePhaseField>(wx, wy); } else if (m_Context.Grid.SpatialDimension == 3) { wz = new SinglePhaseField(m_gradBasis, "wz"); m_Gradw = new VectorField <SinglePhaseField>(wx, wy, wz); } else { throw new NotSupportedException("only spatial dimension 2 and 3 are supported."); } SinglePhaseField absval = new SinglePhaseField(m_gradBasis); m_Gradw[0].Derivative(1.0, m_Field, 0); m_Gradw[1].Derivative(1.0, m_Field, 1); if (m_Context.Grid.SpatialDimension == 3) { m_Gradw[2].Derivative(1.0, m_Field, 2); } /* * Normalization of the gradient vector * Might be better implemented using a * Function */ absval.ProjectAbs(1.0, m_Gradw); m_Gradw[0].ProjectQuotient(1.0, m_Gradw[0], absval, null, false); m_Gradw[1].ProjectQuotient(1.0, m_Gradw[1], absval, null, false); if (m_Context.Grid.SpatialDimension == 3) { m_Gradw[2].ProjectQuotient(1.0, m_Gradw[2], absval, null, false); } SinglePhaseField n1x = new SinglePhaseField(m_derivsBasis, "n1x"); SinglePhaseField n2x = new SinglePhaseField(m_derivsBasis, "n2x"); SinglePhaseField n1y = new SinglePhaseField(m_derivsBasis, "n1y"); SinglePhaseField n2y = new SinglePhaseField(m_derivsBasis, "n2y"); if (m_Context.Grid.SpatialDimension == 3) { SinglePhaseField n3x = new SinglePhaseField(m_derivsBasis, "n3x"); SinglePhaseField n3y = new SinglePhaseField(m_derivsBasis, "n3y"); SinglePhaseField n1z = new SinglePhaseField(m_derivsBasis, "n1z"); SinglePhaseField n2z = new SinglePhaseField(m_derivsBasis, "n2z"); SinglePhaseField n3z = new SinglePhaseField(m_derivsBasis, "n3z"); m_normderivs = new VectorField <SinglePhaseField>(n1x, n2x, n3x, n1y, n2y, n3y, n1z, n2z, n3z); /* Partial derivatives of the normal vector. * These quantities are used in the product rule applied to the surface projection * and to compute the mean curvature */ m_normderivs[0].Derivative(1.0, m_Gradw[0], 0); m_normderivs[1].Derivative(1.0, m_Gradw[1], 0); m_normderivs[2].Derivative(1.0, m_Gradw[2], 0); m_normderivs[3].Derivative(1.0, m_Gradw[0], 1); m_normderivs[4].Derivative(1.0, m_Gradw[1], 1); m_normderivs[5].Derivative(1.0, m_Gradw[2], 1); m_normderivs[6].Derivative(1.0, m_Gradw[0], 2); m_normderivs[7].Derivative(1.0, m_Gradw[1], 2); m_normderivs[8].Derivative(1.0, m_Gradw[2], 2); } else { m_normderivs = new VectorField <SinglePhaseField>(n1x, n2x, n1y, n2y); /* Partial derivatives of the normal vector. * These quantities are used in the product rule applied to the surface projection * and to compute the mean curvature */ m_normderivs[0].Derivative(1.0, m_Gradw[0], 0); m_normderivs[1].Derivative(1.0, m_Gradw[1], 0); m_normderivs[2].Derivative(1.0, m_Gradw[0], 1); m_normderivs[3].Derivative(1.0, m_Gradw[1], 1); } /* * Divergence of the surface normal vector yields the total curvature * which is twice the mean curvature * ATTENTION: here with inverse sign!!!!! */ m_Curvature = new SinglePhaseField(m_derivsBasis); m_Curvature.Acc(1.0, m_normderivs[0]); m_Curvature.Acc(1.0, m_normderivs[4]); if (m_Context.Grid.SpatialDimension == 3) { m_Curvature.Acc(1.0, m_normderivs[8]); } m_sign = new SinglePhaseField(m_Basis, "sign"); SinglePhaseField quot = new SinglePhaseField(m_Basis, "quot"); SinglePhaseField sqrt = new SinglePhaseField(m_Basis, "sqrt"); sqrt.ProjectProduct(1.0, m_Field, m_Field); sqrt.AccConstant(0.01); quot.ProjectPow(1.0, sqrt, deltax * deltax); m_sign.ProjectQuotient(1.0, m_Field, quot); }