SpatialOperator CreateAdvectionSpatialOperator(IncompressibleBoundaryCondMap bcMap) { Func <int[], int[], int[], int> QuadOrderFunction = QuadOrderFunc.SumOfMaxDegrees(); string[] parameterList; parameterList = ArrayTools.Cat( VariableNames.Velocity0Vector(D), VariableNames.Velocity0MeanVector(D), "div(U)"); SpatialOperator SO = new SpatialOperator(new string[] { "LevelSet" }, parameterList, new string[] { "Phi-Evo" }, QuadOrderFunc.NonLinear(2)); //div(u*phi) SO.EquationComponents["Phi-Evo"].Add(new LevelSetLLFFlux(GridDat, bcMap)); //-phi*div(u) SO.EquationComponents["Phi-Evo"].Add(new FextSource()); SO.Commit(); return(SO); }
/// <summary> /// Creating the time integrated DG-FEM discretization of the level set advection equation /// </summary> /// <param name="LevelSet"></param> /// <param name="ExtensionVelocity"></param> /// <param name="e"></param> void CreateAdvectionSpatialOperator(SinglePhaseField LevelSet, SinglePhaseField ExtensionVelocity, ExplicitEuler.ChangeRateCallback e, SubGrid subGrid) { SpatialOperator SO; Func <int[], int[], int[], int> QuadOrderFunction = QuadOrderFunc.Linear(); int D = LevelSet.GridDat.SpatialDimension; //FieldFactory<SinglePhaseField> fac = new FieldFactory<SinglePhaseField>(SinglePhaseField.Factory); //VectorField<SinglePhaseField> LevelSetGradient = new VectorField<SinglePhaseField>(D, // LevelSet.Basis,fac); SO = new SpatialOperator(1, 1, 1, QuadOrderFunction, new string[] { "LS", "S", "Result" }); double PenaltyBase = ((double)((LevelSet.Basis.Degree + 1) * (LevelSet.Basis.Degree + D))) / ((double)D); SO.EquationComponents["Result"].Add(new ScalarVelocityAdvectionFlux(GridDat, PenaltyBase)); SO.Commit(); this.TimeIntegrator = new RungeKutta(RungeKuttaScheme.ExplicitEuler, SO, new CoordinateMapping(LevelSet), new CoordinateMapping(ExtensionVelocity), subGrid); // Performing the task e if (e != null) { this.TimeIntegrator.OnBeforeComputeChangeRate += e; } }
unsafe public static void Laplacian(ref int GridRef, ref int DgDegree, out int ierr) { try { // grid, etc // ========= GridData grd = null;// (GridData)(Infrastructure.GetObject(GridRef)); var b = new Basis(grd, DgDegree); var map = new UnsetteledCoordinateMapping(b); var L = new Laplace(1.3, grd.Cells.cj); var op = new SpatialOperator(1, 0, 1, QuadOrderFunc.Linear(), "T", "c1"); op.EquationComponents["c1"].Add(L); op.Commit(); // evaluate operator // ================= var Mtx = new BlockMsrMatrix(map, map); double[] B = new double[map.LocalLength]; var eval = op.GetMatrixBuilder(map, null, map); eval.ComputeMatrix(Mtx, B); // return data // =========== throw new NotImplementedException("todo"); } catch (Exception e) { ierr = Infrastructure.ErrorHandler(e); } ierr = 0; }
/// <summary> /// Includes assembly of the matrix. /// </summary> /// <param name="L"></param> protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { using (FuncTrace tr = new FuncTrace()) { // create operator // =============== { double D = this.GridData.SpatialDimension; double penalty_base = (T.Basis.Degree + 1) * (T.Basis.Degree + D) / D; double penalty_factor = base.Control.penalty_poisson; BoundaryCondMap <BoundaryType> PoissonBcMap = new BoundaryCondMap <BoundaryType>(this.GridData, this.Control.BoundaryValues, "T"); LapaceIp = new SpatialOperator(1, 1, QuadOrderFunc.SumOfMaxDegrees(), "T", "T"); MultidimensionalArray LengthScales; if (this.GridData is GridData) { LengthScales = ((GridData)GridData).Cells.cj; } else if (this.GridData is AggregationGridData) { LengthScales = ((AggregationGridData)GridData).AncestorGrid.Cells.cj; } else { throw new NotImplementedException(); } var flux = new ipFlux(penalty_base * base.Control.penalty_poisson, LengthScales, PoissonBcMap); LapaceIp.EquationComponents["T"].Add(flux); LapaceIp.Commit(); } } }
protected override void CreateEquationsAndSolvers(LoadbalData L) { Op = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "u", "c1"); var blkFlux = new DxFlux(this.LsTrk, Control.alpha_A, Control.alpha_B); Op.EquationComponents["c1"].Add(blkFlux); // Flux in Bulk Phase; Op.EquationComponents["c1"].Add(new LevSetFlx(this.LsTrk, Control.alpha_A, Control.alpha_B)); // flux am lev-set 0 Op.OnIntegratingBulk += blkFlux.NowIntegratingBulk; Op.Commit(); if (L == null) { TimeIntegration = new XdgBDFTimestepping( new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk, true, DelComputeOperatorMatrix, DelUpdateLevelset, DelUpdateCutCellMetrics, 3, // BDF3 //-1, // Crank-Nicolson //0, // Explicit Euler LevelSetHandling.LieSplitting, MassMatrixShapeandDependence.IsTimeDependent, SpatialOperatorType.LinearTimeDependent, MassScale, MultigridOperatorConfig, this.MultigridSequence, this.THRESHOLD, true); } else { Debug.Assert(object.ReferenceEquals(this.MultigridSequence[0].ParentGrid, this.GridData)); TimeIntegration.DataRestoreAfterBalancing(L, new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk, this.MultigridSequence); } }
public static SpatialOperator BuildEulerOperator(IGridData gridData, CompressibleControl control) { // Boundary condition map Material material = control.GetMaterial(); IBoundaryConditionMap boundaryMap = new CompressibleBoundaryCondMap(gridData, control, material); // Initialize operator SpatialOperator EulerOperator = new SpatialOperator( new string[] { CompressibleVariables.Density, CompressibleVariables.Momentum.xComponent, CompressibleVariables.Momentum.yComponent, CompressibleVariables.Energy }, new string[] { }, new string[] { CompressibleVariables.Density, CompressibleVariables.Momentum.xComponent, CompressibleVariables.Momentum.yComponent, CompressibleVariables.Energy }, QuadOrderFunc.NonLinearWithoutParameters(2) ); // Map fluxes EulerOperator.EquationComponents[CompressibleVariables.Density].Add(new OptimizedHLLCDensityFlux(boundaryMap, material)); EulerOperator.EquationComponents[CompressibleVariables.Momentum.xComponent].Add(new OptimizedHLLCMomentumFlux(boundaryMap, 0, material)); EulerOperator.EquationComponents[CompressibleVariables.Momentum.yComponent].Add(new OptimizedHLLCMomentumFlux(boundaryMap, 1, material)); EulerOperator.EquationComponents[CompressibleVariables.Energy].Add(new OptimizedHLLCEnergyFlux(boundaryMap, material)); EulerOperator.Commit(); return(EulerOperator); }
/// <summary> /// Based on the Ideas by /// C. Basting and D. Kuzmin, /// “A minimization-based finite element formulation for interface-preserving level set reinitialization”, /// Computing, vol. 95, no. 1, pp. 13–25, Dec. 2012. /// Create Spatial Operators and build the corresponding Matrices /// For the Left-Hand Side of the ReInitProblem /// RHS is computed on the fly in <see cref="ReInitSingleStep"/> /// The Bulk component is constant unless the grid changes, thus it is computed in <see cref="BuildOperators(CellQuadratureScheme)"/>. /// The Interface component changes with its motion. /// This component is calculated in <see cref="UpdateOperators(CellQuadratureScheme)"/>. /// </summary> /// <param name="LSTrck"></param> /// <param name="Control">various parameters <paramref name="EllipticReinitControl"/></param> /// <param name="HMFOrder">order of tghe interface quadrature</param> public EllipticReInit(LevelSetTracker LSTrck, EllipticReInitAlgoControl Control, SinglePhaseField LevelSetForReInit = null) { this.Control = Control; this.LevelSetTracker = LSTrck; if (LevelSetForReInit == null) { Phi = LevelSetTracker.LevelSets[0] as SinglePhaseField; } else { Phi = LevelSetForReInit; } this.underrelaxation = Control.underrelaxation; Residual = new SinglePhaseField(Phi.Basis); OldPhi = new SinglePhaseField(Phi.Basis); NewPhi = new SinglePhaseField(Phi.Basis); foreach (SinglePhaseField f in new List <SinglePhaseField> { Residual, OldPhi, NewPhi }) { f.Clear(); f.Acc(1.0, Phi); } this.D = LevelSetTracker.GridDat.SpatialDimension; this.ConvergenceCriterion = Control.ConvergenceCriterion; this.MaxIteration = Control.MaxIt; double PenaltyBase = ((double)((Phi.Basis.Degree + 1) * (Phi.Basis.Degree + D))) / ((double)D); // Choose Forms according to Upwinding or Central Fluxes string[] paramNames; int noOfParamFields; IEquationComponent BulkForm; RHSForm myRHSForm; LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, "LevelSetGradient", SinglePhaseField.Factory); MeanLevelSetGradient = new VectorField <SinglePhaseField>(D, new Basis(Phi.GridDat, 0), "MeanLevelSetGradient", SinglePhaseField.Factory); if (Control.Upwinding) { paramNames = new string[] { "OldLevelSet", "MeanLevelSetGradient[0]", "MeanLevelSetGradient[1]" }; noOfParamFields = D; LevelSetGradient.Clear(); LevelSetGradient.Gradient(1.0, Phi); //LevelSetGradient.GradientByFlux(1.0, Phi); MeanLevelSetGradient.Clear(); MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient); parameterFields = ArrayTools.Cat(new SinglePhaseField[] { OldPhi }, MeanLevelSetGradient.ToArray()); //throw new NotImplementedException("ToDO"); BulkForm = new EllipticReInitUpwindForm_Laplace(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck); myRHSForm = new EllipticReInitUpwindForm_RHS(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck); OldDirection = new double[MeanLevelSetGradient.CoordinateVector.ToArray().Length]; for (int i = 0; i < MeanLevelSetGradient.CoordinateVector.Length; i++) { OldDirection[i] = Math.Sign(MeanLevelSetGradient.CoordinateVector[i]); } NewDirection = OldDirection.CloneAs(); } else { paramNames = new string[] { }; noOfParamFields = 0; parameterFields = new SinglePhaseField[] { }; BulkForm = new CentralDifferencesLHSForm(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck.GridDat.Cells.cj); myRHSForm = new CentralDifferencesRHSForm(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck); } // SIP for the bulk Phase //this.Operator_bulk = new SpatialOperator(1, noOfParamFields, 1, QuadOrderFunc.SumOfMaxDegrees(1, RoundUp: false), variableNames); this.Operator_bulk = BulkForm.Operator(); // Zero at the Interface // Calculate Quadrature Order Func <int[], int[], int[], int> InterfaceQuadOrder; InterfaceQuadOrder = QuadOrderFunc.FixedOrder(Phi.Basis.Degree * 2 + 2); // Generate Interface Operator this.Operator_interface = (new EllipticReInitInterfaceForm(Control.PenaltyMultiplierInterface * PenaltyBase, LSTrck)).XOperator(new[] { "A" }, InterfaceQuadOrder); // Nonlinear Part on the RHS // switch for the potential functions switch (Control.Potential) { case ReInitPotential.BastingDoubleWell: { myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.DoubleWell(d, b)); break; }; case ReInitPotential.BastingSingleWell: { myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWell(d, b)); break; }; case ReInitPotential.SingleWellNear: { myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWellNear(d, b)); break; }; case ReInitPotential.P4DoubleWell: { Console.WriteLine("Warning - This Option for Elliptic ReInit does not work well"); myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.DoubleWellAlternative(d, b)); break; }; case ReInitPotential.SingleWellOnCutDoubleWellElse: { myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWellOnCutDoubleWellElse(d, b)); break; } } Operator_RHS = myRHSForm.Operator(QuadOrderFunc.SumOfMaxDegrees(2, RoundUp: true)); // The result of the nonlinear part on the rhs is projected on a single-phase field RHSField = new SinglePhaseField(Phi.Basis, "RHS"); OpMatrix = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping); OpAffine = new double[OpMatrix.RowPartitioning.LocalLength]; // Matrix and RHS for the Bulk component OpMatrix_bulk = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping); OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength]; // Matrix and RHS for the Interface Penalty OpMatrix_interface = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping); OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength]; // Init Parameter Fields OldPhi.Clear(); OldPhi.Acc(1.0, Phi); // Compute Matrices UpdateBulkMatrix(); }
/// <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> /// /// </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> /// Declaration of the spatial operator /// </summary> protected override SpatialOperator GetOperatorInstance(int D) { // instantiate boundary condition mapping // ====================================== boundaryCondMap = new IncompressibleBoundaryCondMap(this.GridData, this.Control.BoundaryValues, PhysicsMode.Incompressible); // instantiate operator // ==================== string[] CodName = (new[] { "ResidualMomentumX", "ResidualMomentumY", "ResidualMomentumZ" }).GetSubVector(0, D).Cat("ResidualConti"); var op = new SpatialOperator( __DomainVar: VariableNames.VelocityVector(D).Cat(VariableNames.Pressure), __ParameterVar: VariableNames.GravityVector(D), __CoDomainVar: CodName, QuadOrderFunc: QuadOrderFunc.NonLinear(2)); op.LinearizationHint = LinearizationHint.GetJacobiOperator; // Temporal Operator // ================= var TempOp = new ConstantTemporalOperator(op, 0.0); // init with entire diagonal set to 0.0 op.TemporalOperator = TempOp; for (int d = 0; d < D; d++) { TempOp.SetDiagonal(CodName[d], Control.Density); // set momentum equation entries to density } // Pressure Reference // ================== // if there is no Dirichlet boundary condition, // the mean value of the pressure is free: op.FreeMeanValue[VariableNames.Pressure] = !boundaryCondMap.DirichletPressureBoundary; // Momentum Equation // ================= // convective part: { for (int d = 0; d < D; d++) { var comps = op.EquationComponents[CodName[d]]; var ConvBulk = new LocalLaxFriedrichsConvection(D, boundaryCondMap, d, Control.Density); comps.Add(ConvBulk); // bulk component } } // pressure part: { for (int d = 0; d < D; d++) { var comps = op.EquationComponents[CodName[d]]; var pres = new PressureGradientLin_d(d, boundaryCondMap); comps.Add(pres); // bulk component } } // viscous part: { for (int d = 0; d < D; d++) { var comps = op.EquationComponents[CodName[d]]; double penalty_bulk = this.Control.PenaltySafety; var Visc = new swipViscosity_Term1(penalty_bulk, d, D, boundaryCondMap, ViscosityOption.ConstantViscosity, constantViscosityValue: Control.Viscosity); comps.Add(Visc); // bulk component GradUTerm } } // Continuity equation // =================== { for (int d = 0; d < D; d++) { var src = new Divergence_DerivativeSource(d, D); var flx = new Divergence_DerivativeSource_Flux(d, boundaryCondMap); op.EquationComponents[CodName[D]].Add(src); op.EquationComponents[CodName[D]].Add(flx); } //IBM_Op.EquationComponents["div"].Add(new PressureStabilization(1, 1.0 / this.Control.PhysicalParameters.mu_A)); } // Gravity parameter // ================= op.ParameterFactories.Add(delegate(IReadOnlyDictionary <string, DGField> DomainVarFields) { return(D.ForLoop(d => (VariableNames.Gravity_d(d), this.Gravity[d] as DGField))); }); // commit & return // =============== op.Commit(); return(op); }
protected override SpatialOperator GetSpatialOperator(SolverConfiguration SolverConf, int SpatialComponent, int SpatialDirection) { SpatialOperator DivergenceOp = new SpatialOperator(new string[] { VariableNames.Velocity_d(SpatialComponent) }, new string[] { "div_d" }, QuadOrderFunc.Linear()); DivergenceOp.EquationComponents["div_d"].Add(new Divergence_DerivativeSource(SpatialComponent, SolverConf.SpatialDimension)); DivergenceOp.EquationComponents["div_d"].Add(new Divergence_DerivativeSource_Flux(SpatialComponent, SolverConf.BcMap)); DivergenceOp.Commit(); return(DivergenceOp); }
protected override SpatialOperator GetSpatialOperator(SolverConfiguration SolverConf, int SpatialComponent, int SpatialDirection) { SpatialOperator PressureOp = new SpatialOperator(new string[] { VariableNames.Pressure }, new string[] { "p1" }, QuadOrderFunc.Linear()); PressureOp.EquationComponents["p1"].Add(new PressureGradientLin_d(SpatialDirection, SolverConf.BcMap)); if (SolverConf.Control.PressureGradientSource != null) { PressureOp.EquationComponents["p1"].Add( new SrcPressureGradientLin_d(SolverConf.Control.PressureGradientSource[SpatialDirection])); } PressureOp.Commit(); return(PressureOp); }
/// <summary> /// creates the spatial operator that consists only of component <paramref name="c"/> /// </summary> public static XSpatialOperatorMk2 XOperator(this IEquationComponent c, int DegreeOfNonlinearity = 1) { return(XOperator(c, QuadOrderFunc.NonLinear(DegreeOfNonlinearity))); }
/// <summary> /// creates the spatial operator that consists only of component <paramref name="c"/> /// </summary> public static XSpatialOperatorMk2 XOperator(this IEquationComponent c, IEnumerable <string> species, int DegreeOfNonlinearity = 1) { return(XOperator(c, species, QuadOrderFunc.NonLinear(DegreeOfNonlinearity))); }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { using (FuncTrace tr = new FuncTrace()) { this.BcMap = new IncompressibleBoundaryCondMap(this.GridData, grid.GetBoundaryConfig(), PhysicsMode.Incompressible); // assemble system, create matrix // ------------------------------ int D = GridData.SpatialDimension; //double penalty_base = ((double)((U[0].Basis.Degree + 1) * (U[0].Basis.Degree + D))) / ((double)D); double penalty_base = 1.0; double penalty_factor = 1.2; // equation assembly // ----------------- string[] CodNames = D.ForLoop(i => "C" + i); Operator = new SpatialOperator(VariableNames.VelocityVector(D), new string[] { VariableNames.ViscosityMolecular }, CodNames, QuadOrderFunc.Linear()); for (int d = 0; d < D; d++) { if ((this.whichTerms & Terms.T1) != 0) { var flx1 = new swipViscosity_Term1(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity); flx1.g_Diri_Override = this.solution.U; flx1.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx1); } if ((this.whichTerms & Terms.T2) != 0) { var flx2 = new swipViscosity_Term2(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity); flx2.g_Diri_Override = this.solution.U; flx2.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx2); } if ((this.whichTerms & Terms.T3) != 0) { var flx3 = new swipViscosity_Term3(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity); flx3.g_Diri_Override = this.solution.U; flx3.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx3); } } // */ Operator.Commit(); var map = this.U.Mapping; OperatorMtx = new MsrMatrix(map, map); Operator.ComputeMatrixEx(map, new DGField[] { this.mu }, map, OperatorMtx, this.bnd.CoordinateVector, volQuadScheme: null, edgeQuadScheme: null); // test for matrix symmetry // ======================== if (base.MPISize == 1) { double MatrixAssymmetry = OperatorMtx.SymmetryDeviation(); Console.WriteLine("Matrix asymmetry: " + MatrixAssymmetry); Assert.LessOrEqual(Math.Abs(MatrixAssymmetry), 1.0e-10); } } }
public XDGTestSetup( int p, double AggregationThreshold, int TrackerWidth, MultigridOperator.Mode mumo, XQuadFactoryHelper.MomentFittingVariants momentFittingVariant, ScalarFunction LevSetFunc = null) { // Level set, tracker and XDG basis // ================================ if (LevSetFunc == null) { LevSetFunc = ((_2D)((x, y) => 0.8 * 0.8 - x * x - y * y)).Vectorize(); } LevSet = new LevelSet(new Basis(grid, 2), "LevelSet"); LevSet.Clear(); LevSet.ProjectField(LevSetFunc); LsTrk = new LevelSetTracker(grid, XQuadFactoryHelper.MomentFittingVariants.Classic, TrackerWidth, new string[] { "A", "B" }, LevSet); LsTrk.UpdateTracker(); XB = new XDGBasis(LsTrk, p); XSpatialOperator Dummy = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "C1", "u"); //Dummy.EquationComponents["c1"].Add(new Dummy.Commit(); //Tecplot.PlotFields(new DGField[] { LevSet }, "agglo", 0.0, 3); // operator // ======== Debug.Assert(p <= 4); XDGBasis opXB = new XDGBasis(LsTrk, 4); // we want to have a very precise quad rule var map = new UnsetteledCoordinateMapping(opXB); int quadOrder = Dummy.QuadOrderFunction(map.BasisS.Select(bs => bs.Degree).ToArray(), new int[0], map.BasisS.Select(bs => bs.Degree).ToArray()); //agg = new MultiphaseCellAgglomerator(new CutCellMetrics(momentFittingVariant, quadOrder, LsTrk, LsTrk.SpeciesIdS.ToArray()), AggregationThreshold, false); agg = LsTrk.GetAgglomerator(LsTrk.SpeciesIdS.ToArray(), quadOrder, __AgglomerationTreshold: AggregationThreshold); foreach (var S in LsTrk.SpeciesIdS) { Console.WriteLine("Species {0}, no. of agglomerated cells {1} ", LsTrk.GetSpeciesName(S), agg.GetAgglomerator(S).AggInfo.SourceCells.Count()); } // mass matrix factory // =================== // Basis maxB = map.BasisS.ElementAtMax(b => b.Degree); //MassFact = new MassMatrixFactory(maxB, agg); MassFact = LsTrk.GetXDGSpaceMetrics(LsTrk.SpeciesIdS.ToArray(), quadOrder, 1).MassMatrixFactory; // Test field // ========== // set the test field: this is a polynomial function, // but different for each species; On this field, restriction followed by prolongation should be the identity this.Xdg_uTest = new XDGField(this.XB, "uTest"); Dictionary <SpeciesId, double> dumia = new Dictionary <SpeciesId, double>(); int i = 2; foreach (var Spc in LsTrk.SpeciesIdS) { dumia.Add(Spc, i); i -= 1; } SetTestValue(Xdg_uTest, dumia); // dummy operator matrix which fits polynomial degree p // ==================================================== Xdg_opMtx = new BlockMsrMatrix(Xdg_uTest.Mapping, Xdg_uTest.Mapping); Xdg_opMtx.AccEyeSp(120.0); // XDG Aggregation BasiseS // ======================= //XAggB = MgSeq.Select(agGrd => new XdgAggregationBasis[] { new XdgAggregationBasis(uTest.Basis, agGrd) }).ToArray(); XAggB = new XdgAggregationBasis[MgSeq.Length][]; var _XAggB = AggregationGridBasis.CreateSequence(MgSeq, Xdg_uTest.Mapping.BasisS); for (int iLevel = 0; iLevel < XAggB.Length; iLevel++) { XAggB[iLevel] = new[] { (XdgAggregationBasis)(_XAggB[iLevel][0]) }; XAggB[iLevel][0].Update(agg); } // Multigrid Operator // ================== Xdg_opMtx = new BlockMsrMatrix(Xdg_uTest.Mapping, Xdg_uTest.Mapping); Xdg_opMtx.AccEyeSp(120.0); XdgMultigridOp = new MultigridOperator(XAggB, Xdg_uTest.Mapping, Xdg_opMtx, MassFact.GetMassMatrix(Xdg_uTest.Mapping, false), new MultigridOperator.ChangeOfBasisConfig[][] { new MultigridOperator.ChangeOfBasisConfig[] { new MultigridOperator.ChangeOfBasisConfig() { VarIndex = new int[] { 0 }, mode = mumo, Degree = p } } }); }
/// <summary> /// Includes assembly of the matrix. /// </summary> /// <param name="L"></param> protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { using (FuncTrace tr = new FuncTrace()) { // create operator // =============== SpatialOperator LapaceIp; { double D = this.GridData.SpatialDimension; double penalty_base = (T.Basis.Degree + 1) * (T.Basis.Degree + D) / D; double penalty_factor = base.Control.penalty_poisson; BoundaryCondMap <BoundaryType> PoissonBcMap = new BoundaryCondMap <BoundaryType>(this.GridData, this.Control.BoundaryValues, "T"); LapaceIp = new SpatialOperator(1, 1, QuadOrderFunc.SumOfMaxDegrees(), "T", "T"); var flux = new ipFlux(penalty_base * base.Control.penalty_poisson, this.GridData.Cells.cj, PoissonBcMap); LapaceIp.EquationComponents["T"].Add(flux); LapaceIp.Commit(); } // Create Matrices // =============== { // time measurement for matrix assembly Stopwatch stw = new Stopwatch(); stw.Start(); // console Console.WriteLine("creating sparse system for {0} DOF's ...", T.Mapping.Ntotal); // quadrature domain var volQrSch = new CellQuadratureScheme(true, CellMask.GetFullMask(this.GridData)); var edgQrSch = new EdgeQuadratureScheme(true, EdgeMask.GetFullMask(this.GridData)); #if DEBUG // in DEBUG mode, we compare 'MsrMatrix' (old, reference implementation) and 'BlockMsrMatrix' (new standard) var RefLaplaceMtx = new MsrMatrix(T.Mapping); #endif using (new BlockTrace("SipMatrixAssembly", tr)) { LaplaceMtx = new BlockMsrMatrix(T.Mapping); LaplaceAffine = new double[T.Mapping.LocalLength]; LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping, LaplaceMtx, LaplaceAffine, volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch); } #if DEBUG LaplaceAffine.ClearEntries(); LapaceIp.ComputeMatrixEx(T.Mapping, null, T.Mapping, RefLaplaceMtx, LaplaceAffine, volQuadScheme: volQrSch, edgeQuadScheme: edgQrSch); MsrMatrix ErrMtx = RefLaplaceMtx.CloneAs(); ErrMtx.Acc(-1.0, LaplaceMtx); double err = ErrMtx.InfNorm(); double infNrm = LaplaceMtx.InfNorm(); Console.WriteLine("Matrix comparison error: " + err + ", matrix norm is: " + infNrm); Assert.Less(err, infNrm * 1e-10, "MsrMatrix2 comparison failed."); #endif stw.Stop(); Console.WriteLine("done {0} sec.", stw.Elapsed.TotalSeconds); } //double condNo = LaplaceMtx.condest(BatchmodeConnector.Flavor.Octave); //Console.WriteLine("condition number: {0:0.####E-00} ",condNo); } }