/// <summary> /// Legacy interface, preserved as static function. /// </summary> public static void ComputeMatrixEx <M, V>( this XSpatialOperator xOp, LevelSetTracker lsTrk, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, M Matrix, V AffineOffset, bool OnlyAffine, double time, bool ParameterMPIExchange, IDictionary <SpeciesId, MultidimensionalArray> CellLengthScales, IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengthScales, MultidimensionalArray SlipLengths, SubGrid SubGrid, params SpeciesId[] whichSpc) where M : IMutableMatrixEx where V : IList <double> // { var SpeciesDictionary = new Dictionary <SpeciesId, XSpatialOperator.QrSchemPair>(); foreach (var sp in whichSpc) { SpeciesDictionary.Add(sp, new XSpatialOperator.QrSchemPair()); } ComputeMatrixEx <M, V>( xOp, lsTrk, DomainMap, Parameters, CodomainMap, Matrix, AffineOffset, OnlyAffine, time, ParameterMPIExchange, SpeciesDictionary, CellLengthScales, InterfaceLengthScales, SlipLengths, //agg, out mass, SubGrid); }
/// <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. /// </summary> /// <param name="LSTrck"></param> /// <param name="bcmap">Boundary Conditions for the LevelSet Equations</param> /// <param name="Control">various parameters <paramref name="EllipticReinitControl"/></param> public Extender(SinglePhaseField Extension, LevelSetTracker LSTrck, ILevelSetComponent InterfaceFlux, List <DGField> InterfaceParams, VectorField <SinglePhaseField> LevelSetGradient, EllipticExtVelAlgoControl Control) { if (InterfaceFlux.ParameterOrdering.Count != InterfaceParams.Count) { throw new ArgumentException("Missmatch in Number of Parameters and expected amount in the given flux."); } this.InterfaceParams = InterfaceParams; this.Control = Control; int D = LSTrck.GridDat.SpatialDimension; //this.InterfaceValue = InterfaceValue; //InterfaceValue.Identification = "InterfaceValue"; this.Extension = Extension; this.LevelSetTracker = LSTrck; Phi = LevelSetTracker.LevelSets[0] as LevelSet; this.LevelSetGradient = LevelSetGradient; switch (Control.FluxVariant) { case FluxVariant.GradientBased: // Flux Direction based on Mean Level Set Gradient MeanLevelSetGradient = new VectorField <SinglePhaseField>( D.ForLoop( d => new SinglePhaseField( new Basis(LSTrck.GridDat, 0), VariableNames.MeanLevelSetGradientComponent(d) ) ) ); BulkParams = new List <DGField> { }; BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray()); break; case FluxVariant.ValueBased: // Flux Direction Based on Cell-Averaged Level-Set Value MeanLevelSet = new SinglePhaseField(new Basis(LSTrck.GridDat, 0), "MeanLevelSet"); BulkParams = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet); break; case FluxVariant.SWIP: BulkParams = LevelSetGradient.ToArray(); break; default: throw new NotImplementedException(); } this.D = LevelSetTracker.GridDat.SpatialDimension; double PenaltyBase = Control.PenaltyMultiplierFlux * ((double)((Phi.Basis.Degree + 1) * (Phi.Basis.Degree + D))) / ((double)D); DefineBulkOperator(LSTrck, InterfaceFlux, D, PenaltyBase); Operator_interface = InterfaceFlux.XOperator(QuadOrderFunc.FixedOrder(2 * Extension.Basis.Degree + 2)); }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { Op = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "u", "c1"); Op.EquationComponents["c1"].Add(new DxFlux()); // Flux in Bulk Phase; Op.EquationComponents["c1"].Add(new LevSetFlx_phi0(this.LsTrk)); // flux am lev-set 0 Op.EquationComponents["c1"].Add(new LevSetFlx_phi1(this.LsTrk)); // flux am lev-set 1 Op.Commit(); }
/// <summary> /// creates the spatial operator that consists only of component <paramref name="c"/> /// </summary> public static XSpatialOperator XOperator(this IEquationComponent c) { string[] Codomain = new string[] { "v1" }; string[] Domain = c.ArgumentOrdering.ToArray(); string[] Param = (c.ParameterOrdering != null) ? c.ParameterOrdering.ToArray() : new string[0]; XSpatialOperator ret = new XSpatialOperator(Domain, Param, Codomain); ret.EquationComponents[Codomain[0]].Add(c); ret.Commit(); return(ret); }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { m_quadOrder = u1.Basis.Degree * 2; Op = new XSpatialOperator(2, 0, 2, (A, B, c) => m_quadOrder, "u1", "u2", "c1", "c2"); Op.EquationComponents["c1"].Add(new DxFlux("u1", -3.0)); // Flux in Bulk Phase; Op.EquationComponents["c1"].Add(new LevSetFlx(this.LsTrk, "u1", -3.0)); Op.EquationComponents["c2"].Add(new DxFlux("u1", +3.0)); // Flux in Bulk Phase; Op.EquationComponents["c2"].Add(new LevSetFlx(this.LsTrk, "u1", +3.0)); Op.EquationComponents["c2"].Add(new DxFlux("u2", 77.7)); // Flux in Bulk Phase; Op.EquationComponents["c2"].Add(new LevSetFlx(this.LsTrk, "u2", 77.7)); Op.Commit(); }
/// <summary> /// Legacy interface, preserved as static function. /// </summary> static public void ComputeMatrixEx <M, V>( this XSpatialOperator xOp, LevelSetTracker lsTrk, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, M Matrix, V AffineOffset, bool OnlyAffine, double time, bool MPIParameterExchange, params SpeciesId[] whichSpc) where M : IMutableMatrixEx where V : IList <double> // { ComputeMatrixEx <M, V>( xOp, lsTrk, DomainMap, Parameters, CodomainMap, Matrix, AffineOffset, OnlyAffine, time, MPIParameterExchange, subGrid: null, whichSpc: whichSpc ); }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { int quadorder = this.u.Basis.Degree * 2 + 1; Op = new XSpatialOperator(1, 0, 1, (A, B, C) => quadorder, "u", "c1"); var blkFlux = new DxFlux(this.LsTrk, alpha_A, alpha_B); Op.EquationComponents["c1"].Add(blkFlux); // Flux in Bulk Phase; Op.EquationComponents["c1"].Add(new LevSetFlx(this.LsTrk, alpha_A, alpha_B)); // flux am lev-set 0 Op.Commit(); if (L == null) { TimeIntegration = new XdgBDFTimestepping( new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk, true, DelComputeOperatorMatrix, null, DelUpdateLevelset, 3, // BDF3 //-1, // Crank-Nicolson //0, // Explicit Euler LevelSetHandling.LieSplitting, MassMatrixShapeandDependence.IsTimeDependent, SpatialOperatorType.LinearTimeDependent, MassScale, MultigridOperatorConfig, this.MultigridSequence, this.LsTrk.SpeciesIdS.ToArray(), quadorder, this.THRESHOLD, true, this.Control.NonLinearSolver, this.Control.LinearSolver); } else { Debug.Assert(object.ReferenceEquals(this.MultigridSequence[0].ParentGrid, this.GridData)); TimeIntegration.DataRestoreAfterBalancing(L, new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk, this.MultigridSequence); } }
/// <summary> /// Legacy interface, preserved as static function. /// </summary> static public void ComputeMatrixEx <M, V>( this XSpatialOperator xOp, LevelSetTracker lsTrk, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, M Matrix, V AffineOffset, bool OnlyAffine, double time, bool ParameterMPIExchange, IDictionary <SpeciesId, MultidimensionalArray> CellLengthScales, IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengthScales, MultidimensionalArray SlipLengths, params SpeciesId[] whichSpc) where M : IMutableMatrixEx where V : IList <double> // { ComputeMatrixEx <M, V>( xOp, lsTrk, DomainMap, Parameters, CodomainMap, Matrix, AffineOffset, OnlyAffine, time, ParameterMPIExchange, CellLengthScales, InterfaceLengthScales, SlipLengths, null, whichSpc); }
/// <summary> /// Legacy interface, preserved as static function. /// </summary> static public void ComputeMatrixEx <M, V>( this XSpatialOperator xOp, LevelSetTracker lsTrk, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, M Matrix, V AffineOffset, bool OnlyAffine, double time, bool MPIParameterExchange, SubGrid subGrid, params SpeciesId[] whichSpc) where M : IMutableMatrixEx where V : IList <double> // { Console.WriteLine("Warning: Legacy interface!"); Console.WriteLine(" Usage of XDG without an agglomerated penalty!"); int order = xOp.GetOrderFromQuadOrderFunction(DomainMap, Parameters, CodomainMap); MultiphaseCellAgglomerator dummy = lsTrk.GetAgglomerator(lsTrk.SpeciesIdS.ToArray(), order, 0.0); Dictionary <SpeciesId, MultidimensionalArray> Idummy = dummy.XDGSpaceMetrics.CutCellMetrics.InterfaceArea; var bla = new Dictionary <SpeciesId, XSpatialOperator.QrSchemPair>(); foreach (var sp in whichSpc) { bla.Add(sp, new XSpatialOperator.QrSchemPair()); } ComputeMatrixEx <M, V>( xOp, lsTrk, DomainMap, Parameters, CodomainMap, Matrix, AffineOffset, OnlyAffine, time, MPIParameterExchange, bla, dummy.CellLengthScales, Idummy, SubGrid: subGrid); Debug.Assert(dummy.TotalNumberOfAgglomerations <= 0, "internal error"); }
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); } }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { if (Operator != null) { return; } // create operator // --------------- Func <double[], double, double> S; switch (this.Control.InterfaceMode) { case InterfaceMode.MovingInterface: S = this.Control.S; break; case InterfaceMode.Splitting: S = (X, t) => 0.0; break; default: throw new NotImplementedException(); } int quadOrder; if (this.Control.Eq == Equation.ScalarTransport) { quadOrder = this.LinearQuadratureDegree; Func <double[], double, double>[] uBnd = new Func <double[], double, double> [this.Grid.EdgeTagNames.Keys.Max() + 1]; for (int iEdgeTag = 1; iEdgeTag < uBnd.Length; iEdgeTag++) { string nameEdgeTag; if (this.Grid.EdgeTagNames.TryGetValue((byte)iEdgeTag, out nameEdgeTag)) { if (!this.Control.BoundaryValues[nameEdgeTag].Evaluators.TryGetValue("u", out uBnd[iEdgeTag])) { uBnd[iEdgeTag] = (X, t) => 0.0; } } } Operator = new XSpatialOperator(1, 2, 1, (A, B, C) => quadOrder, "u", "Vx", "Vy", "Cod1"); Operator.EquationComponents["Cod1"].Add(new TranportFlux_Bulk() { Inflow = uBnd }); Operator.EquationComponents["Cod1"].Add(new TransportFlux_Interface(this.LsTrk, S)); Operator.Commit(); } else if (this.Control.Eq == Equation.HeatEq) { quadOrder = this.LinearQuadratureDegree; Operator = new XSpatialOperator(1, 0, 1, (A, B, C) => quadOrder, "u", "Cod1"); var bulkFlx = new HeatFlux_Bulk() { m_muA = this.Control.muA, m_muB = this.Control.muB, m_rhsA = this.Control.rhsA, m_rhsB = this.Control.rhsB }; var intfFlx = new HeatFlux_Interface(this.LsTrk, S) { m_muA = this.Control.muA, m_muB = this.Control.muB }; Operator.EquationComponents["Cod1"].Add(bulkFlx); Operator.EquationComponents["Cod1"].Add(intfFlx); Operator.Commit(); } else if (this.Control.Eq == Equation.Burgers) { quadOrder = this.NonlinearQuadratureDegree; Operator = new XSpatialOperator(1, 1, 1, (A, B, C) => quadOrder, "u", "u0", "Cod1"); Operator.EquationComponents["Cod1"].Add(new BurgersFlux_Bulk() { Direction = this.Control.BurgersDirection, Inflow = this.Control.u_Ex }); Operator.EquationComponents["Cod1"].Add(new BurgersFlux_Interface(this.LsTrk, S, this.Control.BurgersDirection)); Operator.Commit(); } else { throw new NotImplementedException(); } // create timestepper // ------------------ LevelSetHandling lsh; switch (this.Control.InterfaceMode) { case InterfaceMode.MovingInterface: lsh = LevelSetHandling.Coupled_Once; break; case InterfaceMode.Splitting: lsh = LevelSetHandling.LieSplitting; break; default: throw new NotImplementedException(); } RungeKuttaScheme rksch = null; int bdfOrder = -1000; if (this.Control.TimeSteppingScheme == TimeSteppingScheme.CrankNicolson) { bdfOrder = -1; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.ExplicitEuler) { bdfOrder = 0; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.ImplicitEuler) { bdfOrder = 1; } else if (this.Control.TimeSteppingScheme.ToString().StartsWith("BDF")) { bdfOrder = Convert.ToInt32(this.Control.TimeSteppingScheme.ToString().Substring(3)); } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK1) { rksch = RungeKuttaScheme.ExplicitEuler; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK1u1) { rksch = RungeKuttaScheme.ExplicitEuler2; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK2) { rksch = RungeKuttaScheme.Heun2; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK3) { rksch = RungeKuttaScheme.TVD3; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK4) { rksch = RungeKuttaScheme.RungeKutta1901; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK_ImplicitEuler) { rksch = RungeKuttaScheme.ImplicitEuler; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK_CrankNic) { rksch = RungeKuttaScheme.CrankNicolson; } else if (this.Control.TimeSteppingScheme == TimeSteppingScheme.RK_IMEX3) { rksch = RungeKuttaScheme.IMEX3; } else { throw new NotImplementedException(); } if (bdfOrder > -1000) { m_BDF_Timestepper = new XdgBDFTimestepping(new DGField[] { this.u }, new DGField[] { this.Residual }, LsTrk, true, DelComputeOperatorMatrix, DelUpdateLevelset, bdfOrder, lsh, MassMatrixShapeandDependence.IsTimeDependent, SpatialOperatorType.LinearTimeDependent, MassScale, null, base.MultigridSequence, this.LsTrk.SpeciesIdS.ToArray(), quadOrder, this.Control.AgglomerationThreshold, false); } else { m_RK_Timestepper = new XdgRKTimestepping(new DGField[] { this.u }, new DGField[] { this.Residual }, LsTrk, DelComputeOperatorMatrix, DelUpdateLevelset, rksch, lsh, MassMatrixShapeandDependence.IsTimeDependent, SpatialOperatorType.LinearTimeDependent, MassScale, null, base.MultigridSequence, this.LsTrk.SpeciesIdS.ToArray(), quadOrder, this.Control.AgglomerationThreshold, false); } }
private void AssembleMatrix(double MU_A, double MU_B, out BlockMsrMatrix M, out double[] b, out MultiphaseCellAgglomerator agg, out MassMatrixFactory massFact) { using (var tr = new FuncTrace()) { // create operator // =============== if (this.Control.SetDefaultDiriBndCnd) { this.Control.xLaplaceBCs.g_Diri = ((CommonParamsBnd inp) => 0.0); this.Control.xLaplaceBCs.IsDirichlet = (inp => true); } double D = this.GridData.SpatialDimension; int p = u.Basis.Degree; double penalty_base = (p + 1) * (p + D) / D; double penalty_multiplyer = base.Control.penalty_multiplyer; XQuadFactoryHelper.MomentFittingVariants momentFittingVariant; if (D == 3) { momentFittingVariant = XQuadFactoryHelper.MomentFittingVariants.Classic; } momentFittingVariant = this.Control.CutCellQuadratureType; int order = this.u.Basis.Degree * 2; XSpatialOperator Op = new XSpatialOperator(1, 1, (A, B, C) => order, "u", "c1"); var lengthScales = ((BoSSS.Foundation.Grid.Classic.GridData)GridData).Cells.PenaltyLengthScales; var lap = new XLaplace_Bulk(this.LsTrk, penalty_multiplyer * penalty_base, "u", this.Control.xLaplaceBCs, 1.0, MU_A, MU_B, lengthScales, this.Control.ViscosityMode); Op.EquationComponents["c1"].Add(lap); // Bulk form Op.EquationComponents["c1"].Add(new XLaplace_Interface(this.LsTrk, MU_A, MU_B, penalty_base * 2, this.Control.ViscosityMode)); // coupling form Op.Commit(); // create agglomeration // ==================== var map = new UnsetteledCoordinateMapping(u.Basis); //agg = new MultiphaseCellAgglomerator( // new CutCellMetrics(momentFittingVariant, // QuadOrderFunc.SumOfMaxDegrees(RoundUp: true)(map.BasisS.Select(bs => bs.Degree).ToArray(), new int[0], map.BasisS.Select(bs => bs.Degree).ToArray()), // //this.HMFDegree, // LsTrk, this.LsTrk.SpeciesIdS.ToArray()), // this.Control.AgglomerationThreshold, false); agg = LsTrk.GetAgglomerator(this.LsTrk.SpeciesIdS.ToArray(), order, this.Control.AgglomerationThreshold); // compute matrix // ============= using (new BlockTrace("XdgMatrixAssembly", tr)) { M = new BlockMsrMatrix(map, map); b = new double[M.RowPartitioning.LocalLength]; Op.ComputeMatrixEx(LsTrk, map, null, map, M, b, false, 0.0, true, agg.CellLengthScales, null, null, //out massFact, this.LsTrk.SpeciesIdS.ToArray()); } // compare with linear evaluation // ============================== DGField[] testDomainFieldS = map.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray(); CoordinateVector test = new CoordinateVector(testDomainFieldS); DGField[] errFieldS = map.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray(); CoordinateVector Err = new CoordinateVector(errFieldS); var eval = Op.GetEvaluatorEx(LsTrk, testDomainFieldS, null, map); foreach (var s in this.LsTrk.SpeciesIdS) { eval.SpeciesOperatorCoefficients[s].CellLengthScales = agg.CellLengthScales[s]; } eval.time = 0.0; int L = test.Count; Random r = new Random(); for (int i = 0; i < L; i++) { test[i] = r.NextDouble(); } double[] R1 = new double[L]; double[] R2 = new double[L]; eval.Evaluate(1.0, 1.0, R1); R2.AccV(1.0, b); M.SpMV(1.0, test, 1.0, R2); Err.AccV(+1.0, R1); Err.AccV(-1.0, R2); double ErrDist = GenericBlas.L2DistPow2(R1, R2).MPISum().Sqrt(); double Ref = test.L2NormPow2().MPISum().Sqrt(); Assert.LessOrEqual(ErrDist, Ref * 1.0e-5, "Mismatch between explicit evaluation of XDG operator and matrix."); // agglomeration wahnsinn // ====================== agg.ManipulateMatrixAndRHS(M, b, map, map); foreach (var S in this.LsTrk.SpeciesNames) { Console.WriteLine(" Species {0}: no of agglomerated cells: {1}", S, agg.GetAgglomerator(this.LsTrk.GetSpeciesId(S)).AggInfo.SourceCells.NoOfItemsLocally); } // mass matrix factory // =================== Basis maxB = map.BasisS.ElementAtMax(bss => bss.Degree); //massFact = new MassMatrixFactory(maxB, agg); massFact = LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), order).MassMatrixFactory; } }
public OperatorFactory( OperatorConfiguration config, LevelSetTracker _LsTrk, int _HMFdegree, int degU, IncompressibleMultiphaseBoundaryCondMap BcMap, bool _movingmesh, bool _evaporation, bool _staticInt) { // variable names // ============== D = _LsTrk.GridDat.SpatialDimension; this.LsTrk = _LsTrk; //this.momentFittingVariant = momentFittingVariant; this.HMFDegree = _HMFdegree; this.dntParams = config.dntParams.CloneAs(); this.physParams = config.physParams.CloneAs(); this.UseExtendedVelocity = config.UseXDG4Velocity; this.movingmesh = _movingmesh; this.evaporation = _evaporation; // test input // ========== { if (config.DomBlocks.GetLength(0) != 2 || config.CodBlocks.GetLength(0) != 2) { throw new ArgumentException(); } if (config.physParams.mu_A == 0.0 && config.physParams.mu_B == 0.0) { muIs0 = true; } else { if (config.physParams.mu_A <= 0) { throw new ArgumentException(); } if (config.physParams.mu_B <= 0) { throw new ArgumentException(); } } if (config.physParams.rho_A <= 0) { throw new ArgumentException(); } if (config.physParams.rho_B <= 0) { throw new ArgumentException(); } if (_LsTrk.SpeciesNames.Count != 2) { throw new ArgumentException(); } if (!(_LsTrk.SpeciesNames.Contains("A") && _LsTrk.SpeciesNames.Contains("B"))) { throw new ArgumentException(); } } // full operator: CodName = ((new string[] { "momX", "momY", "momZ" }).GetSubVector(0, D)).Cat("div"); Params = ArrayTools.Cat( VariableNames.Velocity0Vector(D), VariableNames.Velocity0MeanVector(D), "Curvature", (new string[] { "surfForceX", "surfForceY", "surfForceZ" }).GetSubVector(0, D), (new string[] { "NX", "NY", "NZ" }).GetSubVector(0, D), (new string[] { "GradTempX", "GradTempY", "GradTempZ" }.GetSubVector(0, D)), VariableNames.Temperature, "DisjoiningPressure"); DomName = ArrayTools.Cat(VariableNames.VelocityVector(D), VariableNames.Pressure); // selected part: if (config.CodBlocks[0]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(0, D)); } if (config.CodBlocks[1]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(D, 1)); } if (config.DomBlocks[0]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(0, D)); } if (config.DomBlocks[1]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(D, 1)); } muA = config.physParams.mu_A; muB = config.physParams.mu_B; rhoA = config.physParams.rho_A; rhoB = config.physParams.rho_B; sigma = config.physParams.Sigma; MatInt = !evaporation; double kA = 0.0; double kB = 0.0; double hVapA = 0.0; double hVapB = 0.0; double Tsat = 0.0; double R_int = 0.0; double p_c = 0.0; if (evaporation) { kA = config.thermParams.k_A; kB = config.thermParams.k_B; hVapA = config.thermParams.hVap_A; hVapB = config.thermParams.hVap_B; Tsat = config.thermParams.T_sat; p_c = config.thermParams.pc; //double T_intMin = 0.0; double f = config.thermParams.fc; double R = config.thermParams.Rc; //double pc = config.thermParams.pc; if (config.thermParams.hVap_A > 0 && config.thermParams.hVap_B < 0) { R_int = ((2.0 - f) / (2 * f)) * Tsat * Math.Sqrt(2 * Math.PI * R * Tsat) / (rhoB * hVapA.Pow2()); //T_intMin = Tsat * (1 + (pc / (rhoA * hVapA.Pow2()))); } else if (config.thermParams.hVap_A < 0 && config.thermParams.hVap_B > 0) { R_int = ((2.0 - f) / (2 * f)) * Tsat * Math.Sqrt(2 * Math.PI * R * Tsat) / (rhoA * hVapB.Pow2()); //T_intMin = Tsat * (1 + (pc / (rhoB * hVapB.Pow2()))); } this.CurvatureRequired = true; } //if (!MatInt) // throw new NotSupportedException("Non-Material interface is NOT tested!"); // create Operator // =============== m_OP = new XSpatialOperator(DomNameSelected, Params, CodNameSelected, (A, B, C) => _HMFdegree); // build the operator // ================== { // Momentum equation // ================= if (config.physParams.IncludeConvection && config.Transport) { for (int d = 0; d < D; d++) { var comps = m_OP.EquationComponents[CodName[d]]; // convective part: // variante 1: double LFFA = config.dntParams.LFFA; double LFFB = config.dntParams.LFFB; var conv = new Operator.Convection.ConvectionInBulk_LLF(D, BcMap, d, rhoA, rhoB, LFFA, LFFB, LsTrk); comps.Add(conv); // Bulk component comps.Add(new Operator.Convection.ConvectionAtLevelSet_LLF(d, D, LsTrk, rhoA, rhoB, LFFA, LFFB, config.physParams.Material, BcMap, movingmesh)); // LevelSet component //comps.Add(new Operator.Convection.ConvectionAtLevelSet_weightedLLF(d, D, LsTrk, rhoA, rhoB, LFFA, LFFB, BcMap, movingmesh)); // LevelSet component if (evaporation) { //comps.Add(new Operator.Convection.ConvectionAtLevelSet_Divergence(d, D, LsTrk, rhoA, rhoB, config.dntParams.ContiSign, config.dntParams.RescaleConti, kA, kB, hVapA, R_int, Tsat, sigma, p_c)); //comps.Add(new Operator.Convection.ConvectionAtLevelSet_nonMaterialLLF(d, D, LsTrk, rhoA, rhoB, kA, kB, hVapA, R_int, Tsat, sigma, p_c)); //comps.Add(new Operator.Convection.ConvectionAtLevelSet_nonMaterial(d, D, LsTrk, rhoA, rhoB, kA, kB, hVapA, R_int, Tsat, sigma, p_c)); } // variante 3: //var convA = new LocalConvection(D, d, rhoA, rhoB, this.config.varMode, LsTrk); //XOP.OnIntegratingBulk += convA.SetParameter; //comps.Add(convA); //////var convB = new LocalConvection2(D, d, rhoA, rhoB, varMode, LsTrk); // macht Bum-Bum! ////XOP.OnIntegratingBulk += convB.SetParameter; ////comps.Add(convB); } this.U0meanrequired = true; } // pressure gradient // ================= if (config.PressureGradient) { for (int d = 0; d < D; d++) { var comps = m_OP.EquationComponents[CodName[d]]; var pres = new Operator.Pressure.PressureInBulk(d, BcMap); comps.Add(pres); //if (!MatInt) // throw new NotSupportedException("New Style pressure coupling does not support non-material interface."); var presLs = new Operator.Pressure.PressureFormAtLevelSet(d, D, LsTrk); //, dntParams.UseWeightedAverages, muA, muB); comps.Add(presLs); //if (evaporation) { // var presLSGen = new Operator.Pressure.GeneralizedPressureFormAtLevelSet(d, D, LsTrk, config.thermParams.p_sat, hVapA); // comps.Add(presLSGen); //} } } // viscous operator // ================ if (config.Viscous && !muIs0) { for (int d = 0; d < D; d++) { var comps = m_OP.EquationComponents[CodName[d]]; // viscous part: //double _D = D; //double penalty_mul = dntParams.PenaltySafety; //double _p = degU; //double penalty_base = (_p + 1) * (_p + _D) / _D; //double penalty = penalty_base * penalty_mul; double penalty = dntParams.PenaltySafety; switch (dntParams.ViscosityMode) { case ViscosityMode.Standard: { // Bulk operator: var Visc = new Operator.Viscosity.ViscosityInBulk_GradUTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, d, D, muA, muB); // , _betaA: this.physParams.betaS_A, _betaB: this.physParams.betaS_B); comps.Add(Visc); if (dntParams.UseGhostPenalties) { var ViscPenalty = new Operator.Viscosity.ViscosityInBulk_GradUTerm(penalty * 1.0, 0.0, BcMap, d, D, muA, muB); m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(ViscPenalty); } // Level-Set operator: comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_Standard(LsTrk, muA, muB, penalty * 1.0, d, true)); break; } case ViscosityMode.TransposeTermMissing: { // Bulk operator: var Visc = new Operator.Viscosity.ViscosityInBulk_GradUTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, d, D, muA, muB); comps.Add(Visc); if (dntParams.UseGhostPenalties) { var ViscPenalty = new Operator.Viscosity.ViscosityInBulk_GradUTerm(penalty * 1.0, 0.0, BcMap, d, D, muA, muB); m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(ViscPenalty); } // Level-Set operator: comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_Standard(LsTrk, muA, muB, penalty * 1.0, d, false)); break; } case ViscosityMode.ExplicitTransformation: { // Bulk operator var Visc = new Operator.Viscosity.ViscosityInBulk_GradUTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, d, D, muA, muB); comps.Add(Visc); if (dntParams.UseGhostPenalties) { var ViscPenalty = new Operator.Viscosity.ViscosityInBulk_GradUTerm(penalty * 1.0, 0.0, BcMap, d, D, muA, muB); m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(ViscPenalty); } //Level-Set operator: //comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_Explicit(d, D, LsTrk, penalty, muA, muB)); throw new NotSupportedException("Beim refact rausgeflogen, braucht eh kein Mensch. fk, 08jan16."); //break; } case ViscosityMode.FullySymmetric: { // Bulk operator var Visc1 = new Operator.Viscosity.ViscosityInBulk_GradUTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, d, D, muA, muB, _betaA: this.physParams.betaS_A, _betaB: this.physParams.betaS_B); var Visc2 = new Operator.Viscosity.ViscosityInBulk_GradUtranspTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, d, D, muA, muB, _betaA: this.physParams.betaS_A, _betaB: this.physParams.betaS_B); //var Visc3 = new Operator.Viscosity.ViscosityInBulk_divTerm(dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, d, D, muA, muB); comps.Add(Visc1); comps.Add(Visc2); //comps.Add(Visc3); if (dntParams.UseGhostPenalties) { var Visc1Penalty = new Operator.Viscosity.ViscosityInBulk_GradUTerm( penalty, 0.0, BcMap, d, D, muA, muB); var Visc2Penalty = new Operator.Viscosity.ViscosityInBulk_GradUtranspTerm( penalty, 0.0, BcMap, d, D, muA, muB); //var Visc3Penalty = new Operator.Viscosity.ViscosityInBulk_divTerm( // penalty, 0.0, // BcMap, d, D, muA, muB); //m_OP.OnIntegratingBulk += Visc3Penalty.SetParameter; m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(Visc1Penalty); m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(Visc2Penalty); //m_OP.AndresHint.EquationComponents[CodName[d]].Add(Visc3Penalty); } // Level-Set operator comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_FullySymmetric(LsTrk, muA, muB, penalty, d, _staticInt, dntParams.UseWeightedAverages)); if (this.evaporation) { comps.Add(new Operator.Viscosity.GeneralizedViscosityAtLevelSet_FullySymmetric(LsTrk, muA, muB, penalty, d, rhoA, rhoB, kA, kB, hVapA, R_int, Tsat, sigma, p_c)); } break; } default: throw new NotImplementedException(); } } } // Continuum equation // ================== if (config.continuity) { for (int d = 0; d < D; d++) { var src = new Operator.Continuity.DivergenceInBulk_Volume(d, D, rhoA, rhoB, config.dntParams.ContiSign, config.dntParams.RescaleConti); var flx = new Operator.Continuity.DivergenceInBulk_Edge(d, BcMap, rhoA, rhoB, config.dntParams.ContiSign, config.dntParams.RescaleConti); m_OP.EquationComponents["div"].Add(flx); m_OP.EquationComponents["div"].Add(src); } var divPen = new Operator.Continuity.DivergenceAtLevelSet(D, LsTrk, rhoA, rhoB, MatInt, config.dntParams.ContiSign, config.dntParams.RescaleConti, _staticInt); //, dntParams.UseWeightedAverages, muA, muB); m_OP.EquationComponents["div"].Add(divPen); if (evaporation) { var divPenGen = new Operator.Continuity.GeneralizedDivergenceAtLevelSet(D, LsTrk, rhoA, rhoB, config.dntParams.ContiSign, config.dntParams.RescaleConti, kA, kB, hVapA, R_int, Tsat, sigma, p_c); m_OP.EquationComponents["div"].Add(divPenGen); } //// pressure stabilization //if (this.config.PressureStab) { // Console.WriteLine("Pressure Stabilization active."); //var pStabi = new PressureStabilization(0.0001, 0.0001); // m_OP.OnIntegratingBulk += pStabi.SetParameter; // m_OP.EquationComponents["div"].Add(pStabi); ////var pStabiLS = new PressureStabilizationAtLevelSet(D, LsTrk, rhoA, muA, rhoB, muB, sigma, this.config.varMode, MatInt); // //XOP.EquationComponents["div"].Add(pStabiLS); //} else { // Console.WriteLine("Pressure Stabilization INACTIVE."); //} } // surface tension // =============== if (config.PressureGradient && config.physParams.Sigma != 0.0) { // isotropic part of the surface stress tensor if (config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_Flux || config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_Local || config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_ContactLine) { for (int d = 0; d < D; d++) { if (config.dntParams.SST_isotropicMode != SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_ContactLine) { IEquationComponent G = new SurfaceTension_LaplaceBeltrami_Surface(d, config.physParams.Sigma * 0.5); IEquationComponent H = new SurfaceTension_LaplaceBeltrami_BndLine(d, config.physParams.Sigma * 0.5, config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.LaplaceBeltrami_Flux); m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(G); m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(H); } else { //G = new SurfaceTension_LaplaceBeltrami2_Surface(d, config.physParams.Sigma * 0.5); //H = new SurfaceTension_LaplaceBeltrami2_BndLine(d, config.physParams.Sigma * 0.5, config.physParams.Theta_e, config.physParams.betaL); IEquationComponent isoSurfT = new IsotropicSurfaceTension_LaplaceBeltrami(d, D, config.physParams.Sigma * 0.5, BcMap.EdgeTag2Type, BcMap, config.physParams.theta_e, config.physParams.betaL, _staticInt); m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(isoSurfT); } } this.NormalsRequired = true; } else if (config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_Projected || config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_ClosestPoint || config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_LaplaceBeltramiMean || config.dntParams.SST_isotropicMode == SurfaceStressTensor_IsotropicMode.Curvature_Fourier) { for (int d = 0; d < D; d++) { m_OP.EquationComponents[CodName[d]].Add(new CurvatureBasedSurfaceTension(d, D, LsTrk, config.physParams.Sigma)); } this.CurvatureRequired = true; /* * Console.WriteLine("REM: hack in Operator factory"); * for(int d = 0; d < D; d++) { * //var G = new SurfaceTension_LaplaceBeltrami_Surface(d, config.physParams.Sigma * 0.5); * var H = new SurfaceTension_LaplaceBeltrami_BndLine(d, config.physParams.Sigma * 0.5, config.dntParams.surfTensionMode == SurfaceTensionMode.LaplaceBeltrami_Flux); * * //m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(G); * m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(H); * } * * this.NormalsRequired = true; */ } else { throw new NotImplementedException("Not implemented."); } // dynamic part if (config.dntParams.SurfStressTensor != SurfaceSressTensor.Isotropic) { double muI = config.physParams.mu_I; double lamI = config.physParams.lambda_I; double penalty_base = (degU + 1) * (degU + D) / D; double penalty = penalty_base * dntParams.PenaltySafety; // surface shear viscosity if (config.dntParams.SurfStressTensor == SurfaceSressTensor.SurfaceRateOfDeformation || config.dntParams.SurfStressTensor == SurfaceSressTensor.SemiImplicit || config.dntParams.SurfStressTensor == SurfaceSressTensor.FullBoussinesqScriven) { for (int d = 0; d < D; d++) { var surfDeformRate = new BoussinesqScriven_SurfaceDeformationRate_GradU(d, muI * 0.5, penalty); m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(surfDeformRate); //m_OP.OnIntegratingSurfaceElement += surfDeformRate.SetParameter; if (config.dntParams.SurfStressTensor != SurfaceSressTensor.SemiImplicit) { var surfDeformRateT = new BoussinesqScriven_SurfaceDeformationRate_GradUTranspose(d, muI * 0.5, penalty); m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(surfDeformRateT); //m_OP.OnIntegratingSurfaceElement += surfDeformRateT.SetParameter; } } } // surface dilatational viscosity if (config.dntParams.SurfStressTensor == SurfaceSressTensor.SurfaceVelocityDivergence || config.dntParams.SurfStressTensor == SurfaceSressTensor.FullBoussinesqScriven) { for (int d = 0; d < D; d++) { var surfVelocDiv = new BoussinesqScriven_SurfaceVelocityDivergence(d, muI * 0.5, lamI * 0.5, penalty, BcMap.EdgeTag2Type); m_OP.SurfaceElementOperator.EquationComponents[CodName[d]].Add(surfVelocDiv); //m_OP.OnIntegratingSurfaceElement += surfVelocDiv.SetParameter; } } } // stabilization if (config.dntParams.UseLevelSetStabilization) { for (int d = 0; d < D; d++) { m_OP.EquationComponents[CodName[d]].Add(new LevelSetStabilization(d, D, LsTrk)); } } } // surface force term // ================== if (config.PressureGradient && config.physParams.useArtificialSurfaceForce) { for (int d = 0; d < D; d++) { m_OP.EquationComponents[CodName[d]].Add(new SurfaceTension_ArfForceSrc(d, D, LsTrk)); } } // evaporation (mass flux) // ======================= if (evaporation) { for (int d = 0; d < D; d++) { m_OP.EquationComponents[CodName[d]].Add(new Operator.DynamicInterfaceConditions.MassFluxAtInterface(d, D, LsTrk, rhoA, rhoB, kA, kB, hVapA, R_int, Tsat, sigma, p_c)); } } } // Finalize // ======== m_OP.Commit(); }
/// <summary> /// ctor. /// </summary> internal LECQuadratureLevelSet(IGridData context, XSpatialOperator DiffOp, M Matrix, V OffsetVec, UnsetteledCoordinateMapping RowMap, IList <DGField> ParamsMap, UnsetteledCoordinateMapping ColMap, LevelSetTracker lsTrk, int _iLevSet, ICollection <SpeciesId> SpeciesPair, ICompositeQuadRule <QuadRule> domAndRule, IDictionary <SpeciesId, MultidimensionalArray> __LenScales) // : base(new int[] { RowMap.MaxTotalNoOfCoordinatesPerCell, 1 + ((Matrix == null) ? 0 : ColMap.MaxTotalNoOfCoordinatesPerCell) }, context, domAndRule) // { // ------------------ // init custom timers // ------------------ base.CustomTimers = new Stopwatch[] { new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch() }; base.CustomTimers_Names = new string[] { "Flux-Eval", "Basis-Eval", "Loops", "ParametersAndNormals" }; base.CustomTimers_RootPointer = new int[4]; ArrayTools.SetAll(base.CustomTimers_RootPointer, -1); // ----------------------------------- // set members / check ctor parameters // ----------------------------------- m_RowMap = RowMap; m_ColMap = ColMap; m_Parameters = (ParamsMap != null) ? ParamsMap.ToArray() : new DGField[0]; m_LenScales = __LenScales; if (m_RowMap.BasisS.Count != DiffOp.CodomainVar.Count) { throw new ArgumentException("mismatch between number of codomain variables in spatial operator and row mapping"); } if (m_ColMap.BasisS.Count != DiffOp.DomainVar.Count) { throw new ArgumentException("mismatch between number of domain variables in spatial operator and column mapping"); } if (m_Parameters.Length != DiffOp.ParameterVar.Count) { throw new ArgumentException("mismatch between number of parameter variables in spatial operator and given parameters"); } int Gamma = m_RowMap.BasisS.Count; m_lsTrk = lsTrk; if (Matrix != null && (Matrix.RowPartitioning.LocalLength != RowMap.LocalLength)) { throw new ArgumentException("mismatch between matrix number of rows and row mapping."); } if (Matrix != null && (Matrix.ColPartition.LocalLength != ColMap.LocalLength)) { throw new ArgumentException("mismatch between matrix number of columns and column mapping."); } this.m_LevSetIdx = _iLevSet; this.OperatorMatrix = Matrix; this.OperatorAffine = OffsetVec; this.m_SpeciesPair = SpeciesPair; // ------------------------ // sort equation components // ------------------------ //m_BiLinForms = DiffOp.GetArgMapping<IBilinearForm>(true, Compfilter<IBilinearForm>); //m_2ndDerivFlux = DiffOp.GetArgMapping<ILinear2ndDerivativeCouplingFlux>(true, Compfilter<ILinear2ndDerivativeCouplingFlux>); m_LsForm_UxV = DiffOp.GetArgMapping <ILinearLevelSetComponent_UxV>(true, eq => ((eq.LevelSetTerms & TermActivationFlags.UxV) != 0) && Compfilter(eq), eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null); m_LsForm_GradUxV = DiffOp.GetArgMapping <ILinearLevelSetComponent_GradUxV>(true, eq => ((eq.LevelSetTerms & TermActivationFlags.GradUxV) != 0) && Compfilter(eq), eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null); m_LsForm_UxGradV = DiffOp.GetArgMapping <ILinearLevelSetComponent_UxGradV>(true, eq => ((eq.LevelSetTerms & TermActivationFlags.UxGradV) != 0) && Compfilter(eq), eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null); m_LsForm_GradUxGradV = DiffOp.GetArgMapping <ILinearLevelSetComponent_GradUxGradV>(true, eq => ((eq.LevelSetTerms & TermActivationFlags.GradUxGradV) != 0) && Compfilter(eq), eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null); m_LsForm_V = DiffOp.GetArgMapping <ILinearLevelSetComponent_V>(true, eq => ((eq.LevelSetTerms & TermActivationFlags.V) != 0 && Compfilter(eq)), eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null); m_LsForm_GradV = DiffOp.GetArgMapping <ILinearLevelSetComponent_GradV>(true, eq => ((eq.LevelSetTerms & TermActivationFlags.GradV) != 0) && Compfilter(eq), eq => (eq is ILevelSetComponent) ? new LinearLevelSetComponentVectorizer(lsTrk, (ILevelSetComponent)eq) : null); // ----- // alloc // ----- AllocEmpty(m_LsForm_UxV, out Koeff_UxV, out Sum_Koeff_UxV, 5, false); AllocEmpty(m_LsForm_GradUxV, out Koeff_NablaUxV, out Sum_Koeff_NablaUxV, 6, false); AllocEmpty(m_LsForm_UxGradV, out Koeff_UxNablaV, out Sum_Koeff_UxNablaV, 6, false); AllocEmpty(m_LsForm_GradUxGradV, out Koeff_NablaUxNablaV, out Sum_Koeff_NablaUxNablaV, 7, false); AllocEmpty(m_LsForm_V, out Koeff_V, out Sum_Koeff_V, 3, true); AllocEmpty(m_LsForm_GradV, out Koeff_NablaV, out Sum_Koeff_NablaV, 4, true); }
/// <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(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(); }
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> /// Legacy interface, preserved as static function. /// </summary> static public void ComputeMatrixEx <M, V>( this XSpatialOperator xOp, LevelSetTracker lsTrk, UnsetteledCoordinateMapping DomainMap, IList <DGField> Parameters, UnsetteledCoordinateMapping CodomainMap, M Matrix, V AffineOffset, bool OnlyAffine, double time, bool MPIParameterExchange, IDictionary <SpeciesId, XSpatialOperator.QrSchemPair> SpeciesSchemes, IDictionary <SpeciesId, MultidimensionalArray> CellLengthScales, IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengthScales, MultidimensionalArray SlipLengths = null, SubGrid SubGrid = null) where M : IMutableMatrixEx where V : IList <double> // { CellMask SubGridCellMask = null; EdgeMask SubGridEdgeMask = null; if (SubGrid != null) { SubGridCellMask = SubGrid.VolumeMask; /// I don't know why, but this seems to work: SubGridEdgeMask = SubGrid.AllEdgesMask; /// And this does not: //SubGridEdgeMask = SubGrid.InnerEdgesMask; } SpeciesId[] ReqSpecies = SpeciesSchemes.Keys.ToArray(); //int order = xOp.GetOrderFromQuadOrderFunction(DomainMap, Parameters, CodomainMap); //var SchemeHelper = lsTrk.GetXDGSpaceMetrics(ReqSpecies, order, 1).XQuadSchemeHelper; //var SpeciesSchemes_out = new Dictionary<SpeciesId, XSpatialOperator.QrSchemPair>(); //foreach(var SpeciesId in SpeciesSchemes.Keys) { // EdgeQuadratureScheme edgeScheme; // CellQuadratureScheme cellScheme; // var qrSchemes = SpeciesSchemes[SpeciesId]; // bool AssembleOnFullGrid = (SubGrid == null); // if(qrSchemes.EdgeScheme == null) { // edgeScheme = SchemeHelper.GetEdgeQuadScheme(SpeciesId, AssembleOnFullGrid, SubGridEdgeMask); // } else { // //edgeScheme = qrSchemes.EdgeScheme; // //throw new ArgumentException(); // } // if(qrSchemes.CellScheme == null) { // cellScheme = SchemeHelper.GetVolumeQuadScheme(SpeciesId, AssembleOnFullGrid, SubGridCellMask); // } else { // //cellScheme = qrSchemes.CellScheme; // throw new ArgumentException(); // } // SpeciesSchemes_out.Add(SpeciesId, // new XSpatialOperator.QrSchemPair() { // CellScheme = cellScheme, // EdgeScheme = edgeScheme // }); //} var ev = xOp.GetMatrixBuilder(lsTrk, DomainMap, Parameters, CodomainMap, SpeciesSchemes); ev.time = time; ev.MPITtransceive = MPIParameterExchange; foreach (var s in CellLengthScales.Keys) { if (ev.SpeciesOperatorCoefficients.ContainsKey(s)) { ev.SpeciesOperatorCoefficients[s].CellLengthScales = CellLengthScales[s]; } else { ev.SpeciesOperatorCoefficients.Add(s, new CoefficientSet() { CellLengthScales = CellLengthScales[s], GrdDat = lsTrk.GridDat }); } if (InterfaceLengthScales != null) { ev.SpeciesOperatorCoefficients[s].UserDefinedValues["InterfaceLengths"] = InterfaceLengthScales[s]; } if (SlipLengths != null) { ev.SpeciesOperatorCoefficients[s].UserDefinedValues["SlipLengths"] = SlipLengths; } } if (OnlyAffine) { ev.ComputeAffine(AffineOffset); } else { ev.ComputeMatrix(Matrix, AffineOffset); } }
/// <summary> /// ctor. /// </summary> internal NECQuadratureLevelSet(IGridData context, XSpatialOperator DiffOp, V __ResultVector, IList <DGField> __DomainFields, IList <DGField> __Parameters, UnsetteledCoordinateMapping CodomainMap, LevelSetTracker lsTrk, int _iLevSet, Tuple <SpeciesId, SpeciesId> SpeciesPair, ICompositeQuadRule <QuadRule> domAndRule) // : base(new int[] { CodomainMap.MaxTotalNoOfCoordinatesPerCell }, context, domAndRule) // { // ----------------------------------- // set members / check ctor parameters // ----------------------------------- m_lsTrk = lsTrk; this.m_LevSetIdx = _iLevSet; this.m_SpeciesPair = SpeciesPair; this.ResultVector = __ResultVector; m_CodomainMap = CodomainMap; var _Parameters = (__Parameters != null) ? __Parameters.ToArray() : new DGField[0]; if (__DomainFields.Count != DiffOp.DomainVar.Count) { throw new ArgumentException("mismatch between number of domain variables in spatial operator and given domain variables"); } if (_Parameters.Length != DiffOp.ParameterVar.Count) { throw new ArgumentException("mismatch between number of parameter variables in spatial operator and given parameters"); } if (m_CodomainMap.NoOfVariables != DiffOp.CodomainVar.Count) { throw new ArgumentException("mismatch between number of codomain variables in spatial operator and given codomain mapping"); } m_DomainAndParamFields = ArrayTools.Cat(__DomainFields, _Parameters); this.DELTA = __DomainFields.Count; // ------------------------ // sort equation components // ------------------------ int Gamma = m_CodomainMap.NoOfVariables; m_NonlinLsForm_V = DiffOp.GetArgMapping <INonlinLevelSetForm_V>(true, eq => ((eq.LevelSetTerms & (TermActivationFlags.V | TermActivationFlags.UxV | TermActivationFlags.GradUxV)) != 0) && Compfilter(eq), eq => (eq is ILevelSetForm) ? new NonlinearLevelSetFormVectorizer((ILevelSetForm)eq) : null); m_NonlinLsForm_GradV = DiffOp.GetArgMapping <INonlinLevelSetForm_GradV>(true, eq => ((eq.LevelSetTerms & (TermActivationFlags.GradV | TermActivationFlags.UxGradV | TermActivationFlags.GradUxGradV)) != 0) && Compfilter(eq), eq => (eq is ILevelSetForm) ? new NonlinearLevelSetFormVectorizer((ILevelSetForm)eq) : null); m_ValueRequired = new bool[m_DomainAndParamFields.Length]; m_GradientRequired = new bool[m_DomainAndParamFields.Length]; m_NonlinLsForm_V.DetermineReqFields(m_GradientRequired, comp => ((comp.LevelSetTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.GradUxV)) != 0)); m_NonlinLsForm_GradV.DetermineReqFields(m_GradientRequired, comp => ((comp.LevelSetTerms & (TermActivationFlags.GradUxGradV | TermActivationFlags.GradUxV)) != 0)); m_NonlinLsForm_V.DetermineReqFields(m_ValueRequired, comp => ((comp.LevelSetTerms & (TermActivationFlags.UxGradV | TermActivationFlags.UxV)) != 0)); m_NonlinLsForm_GradV.DetermineReqFields(m_ValueRequired, comp => ((comp.LevelSetTerms & (TermActivationFlags.UxGradV | TermActivationFlags.UxV)) != 0)); for (int i = __DomainFields.Count; i < m_DomainAndParamFields.Length; i++) { m_ValueRequired[i] = true; // parameters are always required! } // ----- // alloc // ----- Koeff_V = new MultidimensionalArray[Gamma]; Koeff_GradV = new MultidimensionalArray[Gamma]; for (int gamma = 0; gamma < Gamma; gamma++) { Koeff_V[gamma] = new MultidimensionalArray(3); Koeff_GradV[gamma] = new MultidimensionalArray(4); } int L = m_DomainAndParamFields.Length; m_FieldValuesPos = new MultidimensionalArray[L]; m_FieldValuesNeg = new MultidimensionalArray[L]; m_FieldGradientValuesPos = new MultidimensionalArray[L]; m_FieldGradientValuesNeg = new MultidimensionalArray[L]; for (int l = 0; l < L; l++) { if (m_ValueRequired[l]) { m_FieldValuesPos[l] = new MultidimensionalArray(2); m_FieldValuesNeg[l] = new MultidimensionalArray(2); } if (m_GradientRequired[l]) { m_FieldGradientValuesPos[l] = new MultidimensionalArray(3); m_FieldGradientValuesNeg[l] = new MultidimensionalArray(3); } } // ------------------ // init custom timers // ------------------ base.CustomTimers = new Stopwatch[] { new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch(), new Stopwatch() }; base.CustomTimers_Names = new string[] { "Flux-Eval", "Basis-Eval", "Loops", "ParametersAndNormals", "Field-Eval" }; base.CustomTimers_RootPointer = new int[5]; ArrayTools.SetAll(base.CustomTimers_RootPointer, -1); this.m_NonlinLsForm_V_Watches = this.m_NonlinLsForm_V.InitStopWatches(0, this); this.m_NonlinLsForm_GradV_Watches = this.m_NonlinLsForm_GradV.InitStopWatches(0, this); Flux_Eval = base.CustomTimers[0]; Basis_Eval = base.CustomTimers[1]; Loops = base.CustomTimers[2]; ParametersAndNormals = base.CustomTimers[3]; Field_Eval = base.CustomTimers[4]; }