/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="D"></param> /// <param name="LsTrk"></param> public static void AddInterfaceContinuityEq_withEvaporation(XSpatialOperatorMk2 XOp, XNSFE_OperatorConfiguration config, int D, LevelSetTracker LsTrk) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.ContinuityEquation; if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } ThermalParameters thermParams = config.getThermParams; DoNotTouchParameters dntParams = config.getDntParams; // set components var comps = XOp.EquationComponents[CodName]; var divEvap = new DivergenceAtLevelSet_withEvaporation(D, LsTrk, dntParams.ContiSign, dntParams.RescaleConti, thermParams, config.getPhysParams.Sigma); comps.Add(divEvap); }
/// <summary> /// Ctor /// </summary> /// <param name="__owner"></param> /// <param name="diagonal"> /// For each species, the temporal operator/mass matrix diagonal (per variable), /// i.e. if <paramref name="__owner"/> has 4 domain and 4 codomain variables, /// this must have 4 entries per species too, providing a single factor for the temporal derivative of each equation. /// </param> public ConstantXTemporalOperator(XSpatialOperatorMk2 __owner, params ValueTuple <string, double[]>[] diagonal) { owner = __owner; if (owner.DomainVar.Count != owner.CodomainVar.Count) { throw new NotSupportedException("Expecting a square operator."); } int NoOfVar = owner.DomainVar.Count; m_DiagonalScale = new Dictionary <string, double[]>(); foreach (string spc in __owner.Species) { m_DiagonalScale.Add(spc, new double[NoOfVar]); } foreach (var tt in diagonal) { string spc = tt.Item1; if (!m_DiagonalScale.ContainsKey(spc)) { throw new ArgumentException($"Got species {spc} which is not contained in the spatial operator."); } double[] vals = tt.Item2.CloneAs(); if (vals.Length != NoOfVar) { throw new ArgumentException($"wrong number of entries for species {spc}"); } m_DiagonalScale[spc].SetV(vals, 1.0); } }
/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="CodName"></param> /// <param name="_D"></param> /// <param name="BcMap"></param> /// <param name="config"></param> /// <param name="LsTrk"></param> public static void AddInterfaceContinuityEq(XSpatialOperatorMk2 XOp, IXNSE_Configuration config, int D, LevelSetTracker LsTrk) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.ContinuityEquation; if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } PhysicalParameters physParams = config.getPhysParams; DoNotTouchParameters dntParams = config.getDntParams; // set species arguments double rhoA = physParams.rho_A; double rhoB = physParams.rho_B; // set components var comps = XOp.EquationComponents[CodName]; var divPen = new Operator.Continuity.DivergenceAtLevelSet(D, LsTrk, rhoA, rhoB, config.isMatInt, dntParams.ContiSign, dntParams.RescaleConti); comps.Add(divPen); //var stabint = new PressureStabilizationAtLevelSet(LsTrk, dntParams.PresPenalty2, physParams.reynolds_A, physParams.reynolds_B); //comps.Add(stabint); }
/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="D"></param> /// <param name="LsTrk"></param> public static void AddInterfaceNSE_withEvaporation(XSpatialOperatorMk2 XOp, XNSFE_OperatorConfiguration config, int D, LevelSetTracker LsTrk) { for (int d = 0; d < D; d++) { AddInterfaceNSE_withEvaporation_component(XOp, config, d, D, LsTrk); } }
/// <summary> /// Ctor /// </summary> /// <param name="__owner"></param> public DependentXTemporalOperator(XSpatialOperatorMk2 __owner) { owner = __owner; InternalRepresentation = new XSpatialOperatorMk2(__owner.DomainVar, __owner.ParameterVar, __owner.CodomainVar, __owner.QuadOrderFunction, __owner.Species.ToArray()); InternalRepresentation.LinearizationHint = LinearizationHint.AdHoc; InternalRepresentation.m_UserDefinedValues = __owner.m_UserDefinedValues; }
XSpatialOperatorMk2 GetJacobiXdgOperator() { if (m_JacobiXdgOperator == null) { m_JacobiXdgOperator = XdgOperator.GetJacobiOperator(GridDat.SpatialDimension) as XSpatialOperatorMk2; } return(m_JacobiXdgOperator); }
/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="BcMap"></param> /// <param name="LsTrk"></param> public static void AddInterfaceNSE(XSpatialOperatorMk2 XOp, IXNSE_Configuration config, int D, IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk) { for (int d = 0; d < D; d++) { AddInterfaceNSE_component(XOp, config, d, D, BcMap, LsTrk); } }
/// <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, ILevelSetForm 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(new[] { "A" }, QuadOrderFunc.FixedOrder(2 * Extension.Basis.Degree + 2)); }
/// <summary> /// Ctor, the same factor in the temporal derivative for all /// </summary> /// <param name="__owner"></param> /// <param name="diagonalValue"></param> public ConstantXTemporalOperator(XSpatialOperatorMk2 __owner, double diagonalValue = 1.0) : this(__owner, Diag(__owner, diagonalValue)) { owner = __owner; if (owner.DomainVar.Count != owner.CodomainVar.Count) { throw new NotSupportedException("Expecting a square operator."); } }
//XdgBDFTimestepping AltTimeIntegration; protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { int quadorder = this.u.Basis.Degree * 2 + 1; Op = new XSpatialOperatorMk2(1, 0, 1, (A, B, C) => quadorder, LsTrk.SpeciesNames, "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.LinearizationHint = LinearizationHint.AdHoc; Op.TemporalOperator = new ConstantXTemporalOperator(Op, 1.0); Op.Commit(); if (L == null) { /* * AltTimeIntegration = new XdgBDFTimestepping( * new DGField[] { u }, new DGField[0], new DGField[] { uResidual }, base.LsTrk, * true, * DelComputeOperatorMatrix, Op.TemporalOperator, DelUpdateLevelset, * 3, // BDF3 * //-1, // Crank-Nicolson * //0, // Explicit Euler * LevelSetHandling.LieSplitting, * MassMatrixShapeandDependence.IsTimeDependent, * SpatialOperatorType.LinearTimeDependent, * MultigridOperatorConfig, * this.MultigridSequence, * this.LsTrk.SpeciesIdS.ToArray(), * quadorder, * this.THRESHOLD, * true, * this.Control.NonLinearSolver, * this.Control.LinearSolver); */ TimeIntegration = new XdgTimestepping( Op, new DGField[] { u }, new DGField[] { uResidual }, TimeSteppingScheme.BDF3, this.DelUpdateLevelset, LevelSetHandling.LieSplitting, MultigridOperatorConfig, MultigridSequence, _AgglomerationThreshold: this.THRESHOLD, LinearSolver: this.Control.LinearSolver, NonLinearSolver: this.Control.NonLinearSolver); } else { Debug.Assert(object.ReferenceEquals(this.MultigridSequence[0].ParentGrid, this.GridData)); TimeIntegration.DataRestoreAfterBalancing(L, new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk, this.MultigridSequence); //AltTimeIntegration.DataRestoreAfterBalancing(L, new DGField[] { u }, new DGField[] { uResidual }, base.LsTrk, this.MultigridSequence); } }
/// <summary> /// Computation of mass matrix, makes use of <see cref="MassMatrixFactory"/> /// </summary> public void ComputeMatrix <M, V>(M MassMatrix, V AffineOffset, double oodt = 1.0) where M : IMutableMatrixEx where V : IList <double> { if (!MassMatrix.RowPartitioning.EqualsPartition(this.CodomainMapping)) { throw new ArgumentException("Mismatch between matrix columns and domain variable mapping."); } if (!MassMatrix.ColPartition.EqualsPartition(this.DomainMapping)) { throw new ArgumentException("Mismatch between matrix columns and domain variable mapping."); } if (DomainMapping.NoOfVariables != CodomainMapping.NoOfVariables) { throw new NotSupportedException($"Mismatch between number of variables in domain ({DomainMapping.NoOfVariables}) and codomain ({CodomainMapping.NoOfVariables})."); } int QuadratureOrder = m_Owner.owner.GetOrderFromQuadOrderFunction(DomainMapping.BasisS, XSpatialOperatorMk2.GetBasisS(Parameters), CodomainMapping.BasisS); LevelSetTracker _LsTrk; if (m_Owner.m_lstrk != null) { _LsTrk = m_Owner.m_lstrk; } else { _LsTrk = XSpatialOperatorMk2.GetTracker(DomainMapping.BasisS, XSpatialOperatorMk2.GetBasisS(Parameters), CodomainMapping.BasisS); } SpeciesId[] _SpeciesToCompute = m_Owner.owner.Species.Select(spcName => _LsTrk.GetSpeciesId(spcName)).ToArray(); Dictionary <SpeciesId, IEnumerable <double> > MassScale = new Dictionary <SpeciesId, IEnumerable <double> >(); foreach (var spc in _SpeciesToCompute) { double[] diag = m_Owner.m_DiagonalScale[_LsTrk.GetSpeciesName(spc)].CloneAs(); diag.ScaleV(oodt); MassScale.Add(spc, diag); } //double MaxTime = _LsTrk.RegionsHistory.AvailabelIndices.Max((int iHist) => _LsTrk.RegionsHistory[iHist].Time.Abs()); double[] AvailableTimes = _LsTrk.TimeLevelsInStack; int ii = AvailableTimes.IndexOfMin((double t) => Math.Abs(t - this.time)); int BestTimeIdx = _LsTrk.RegionsHistory.AvailabelIndices[ii]; if (Math.Abs(Math.Abs(time - _LsTrk.RegionsHistory[BestTimeIdx].Time)) >= time * 1e-10 + 1e-10) { Console.WriteLine("unknown time level"); } //BestTimeIdx = 1; MassMatrixFactory MassFact = _LsTrk.GetXDGSpaceMetrics(_SpeciesToCompute, QuadratureOrder, HistoryIndex: BestTimeIdx).MassMatrixFactory; MassFact.AccMassMatrix(MassMatrix, DomainMapping, MassScale); }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { Op = new XSpatialOperatorMk2(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), new SpeciesId[] { LsTrk.GetSpeciesId("B") }, "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> /// /// </summary> /// <param name = "XOp" ></ param > /// < param name="config"></param> /// <param name = "BcMap" ></ param > /// < param name="LsTrk"></param> /// <param name="U0meanrequired"></param> public static void AddInterfaceConstitutive(XSpatialOperatorMk2 XOp, IRheology_Configuration config, int D, IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk, out bool U0meanrequired) { U0meanrequired = false; for (int d = 0; d < 3; d++) { AddInterfaceConstitutive_component(XOp, config, d, D, BcMap, LsTrk, out U0meanrequired); } }
/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="spcName"></param> /// <param name="spcId"></param> /// <param name="BcMap"></param> /// <param name="LsTrk"></param> /// <param name="U0meanrequired"></param> public static void AddSpeciesNSE(XSpatialOperatorMk2 XOp, INSE_Configuration config, int D, string spcName, SpeciesId spcId, IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk, out bool U0meanrequired) { U0meanrequired = false; for (int d = 0; d < D; d++) { AddSpeciesNSE_component(XOp, config, d, D, spcName, spcId, BcMap, LsTrk, out U0meanrequired); } }
/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="D"></param> /// <param name="LsTrk"></param> public static void AddInterfaceContinuityEq_withEvaporation(XSpatialOperatorMk2 XOp, XNSFE_OperatorConfiguration config, int D, LevelSetTracker LsTrk) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.ContinuityEquation; if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } PhysicalParameters physParams = config.getPhysParams; ThermalParameters thermParams = config.getThermParams; DoNotTouchParameters dntParams = config.getDntParams; // set species arguments double rhoA = physParams.rho_A; double rhoB = physParams.rho_B; double sigma = physParams.Sigma; // compute further arguments double hVapA = thermParams.hVap_A; double hVapB = thermParams.hVap_B; double Tsat = thermParams.T_sat; double f = config.thermParams.fc; double R = config.thermParams.Rc; double R_int = 0.0; 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()))); } //double prescrbM = config.prescribedMassflux; // set components var comps = XOp.EquationComponents[CodName]; var divEvap = new DivergenceAtLevelSet_withEvaporation(D, LsTrk, rhoA, rhoB, dntParams.ContiSign, dntParams.RescaleConti, thermParams, R_int, sigma); comps.Add(divEvap); }
/// <summary> /// Constructor for an XDG operator /// </summary> public XdgTimestepping( XSpatialOperatorMk2 op, IEnumerable <DGField> Fields, IEnumerable <DGField> IterationResiduals, TimeSteppingScheme __Scheme, DelUpdateLevelset _UpdateLevelset = null, LevelSetHandling _LevelSetHandling = LevelSetHandling.None, MultigridOperator.ChangeOfBasisConfig[][] _MultigridOperatorConfig = null, AggregationGridData[] _MultigridSequence = null, double _AgglomerationThreshold = 0.1, LinearSolverConfig LinearSolver = null, NonLinearSolverConfig NonLinearSolver = null) // { this.Scheme = __Scheme; this.XdgOperator = op; this.Parameters = op.InvokeParameterFactory(Fields); foreach (var f in Fields.Cat(IterationResiduals).Cat(Parameters)) { if (f != null && f is XDGField xf) { if (LsTrk == null) { LsTrk = xf.Basis.Tracker; } else { if (!object.ReferenceEquals(LsTrk, xf.Basis.Tracker)) { throw new ArgumentException(); } } } } if (LsTrk == null) { throw new ArgumentException("unable to get Level Set Tracker reference"); } bool UseX = Fields.Any(f => f is XDGField) || IterationResiduals.Any(f => f is XDGField); SpeciesId[] spcToCompute = op.Species.Select(spcName => LsTrk.GetSpeciesId(spcName)).ToArray(); ConstructorCommon(op, UseX, Fields, this.Parameters, IterationResiduals, spcToCompute, _UpdateLevelset, _LevelSetHandling, _MultigridOperatorConfig, _MultigridSequence, _AgglomerationThreshold, LinearSolver, NonLinearSolver); }
/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="BcMap"></param> /// <param name="LsTrk"></param> /// <param name="degU"></param> /// <param name="NormalsRequired"></param> /// <param name="CurvatureRequired"></param> public static void AddSurfaceTensionForce(XSpatialOperatorMk2 XOp, IXNSE_Configuration config, int D, IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk, int degU, out bool NormalsRequired, out bool CurvatureRequired) { NormalsRequired = false; CurvatureRequired = false; for (int d = 0; d < D; d++) { AddSurfaceTensionForce_component(XOp, config, d, D, BcMap, LsTrk, degU, out NormalsRequired, out CurvatureRequired); } }
/// <summary> /// creates the spatial operator that consists only of component <paramref name="c"/> /// </summary> public static XSpatialOperatorMk2 XOperator(this IEquationComponent c, Func <int[], int[], int[], int> quadOrderFunc) { string[] Codomain = new string[] { "v1" }; string[] Domain = c.ArgumentOrdering.ToArray(); string[] Param = (c.ParameterOrdering != null) ? c.ParameterOrdering.ToArray() : new string[0]; XSpatialOperatorMk2 ret = new XSpatialOperatorMk2(Domain, Param, Codomain, quadOrderFunc, null); ret.EquationComponents[Codomain[0]].Add(c); ret.Commit(); return(ret); }
protected override XSpatialOperatorMk2 GetOperatorInstance(int D) { // 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(); } if (this.Control.Eq == Equation.ScalarTransport) { 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; } } } var Operator = new XSpatialOperatorMk2(1, 2, 1, (A, B, C) => this.LinearQuadratureDegree, LsTrk.SpeciesNames, "u", "Vx", "Vy", "Cod1"); Operator.EquationComponents["Cod1"].Add(new TranportFlux_Bulk() { Inflow = uBnd }); Operator.EquationComponents["Cod1"].Add(new TransportFlux_Interface(this.LsTrk, S)); //delegate (string ParameterName, DGField ParamField)[] DelParameterFactory(IReadOnlyDictionary<string, DGField> DomainVarFields) Operator.ParameterFactories.Add(delegate(IReadOnlyDictionary <string, DGField> DomainVarFields) { return(new ValueTuple <string, DGField>[] { ("Vx", this.V[0] as DGField), ("Vy", this.V[1] as DGField) }); });
/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="spcName"></param> /// <param name="spcId"></param> /// <param name="BcMap"></param> /// <param name="LsTrk"></param> /// <param name="U0meanrequired"></param> public static void AddSpeciesConstitutive(XSpatialOperatorMk2 XOp, IRheology_Configuration config, int D, int stressDegree, string spcName, SpeciesId spcId, IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk, out bool U0meanrequired) { if (D > 2) { throw new NotSupportedException("Viscoelastic solver does not support 3D calculation. Only implemented for 2D cases!"); } U0meanrequired = false; for (int d = 0; d < 3; d++) { AddSpeciesConstitutive_component(XOp, config, d, D, stressDegree, spcName, spcId, BcMap, LsTrk, out U0meanrequired); } }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { m_quadOrder = u1.Basis.Degree * 2; Op = new XSpatialOperatorMk2(2, 0, 2, (A, B, c) => m_quadOrder, LsTrk.SpeciesIdS.ToArray(), "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(); }
//============================================================== // additional interface components for NSFE interface components //============================================================== /// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="d"></param> /// <param name="D"></param> /// <param name="LsTrk"></param> public static void AddInterfaceNSE_withEvaporation_component(XSpatialOperatorMk2 XOp, XNSFE_OperatorConfiguration config, int d, int D, LevelSetTracker LsTrk) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.MomentumEquationComponent(d); if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } PhysicalParameters physParams = config.getPhysParams; ThermalParameters thermParams = config.getThermParams; DoNotTouchParameters dntParams = config.getDntParams; double sigma = physParams.Sigma; // set components var comps = XOp.EquationComponents[CodName]; if (config.isTransport) { comps.Add(new ConvectionAtLevelSet_nonMaterialLLF(d, D, LsTrk, thermParams, sigma)); comps.Add(new ConvectionAtLevelSet_Consistency(d, D, LsTrk, dntParams.ContiSign, dntParams.RescaleConti, thermParams, sigma)); } if (config.isMovingMesh) { comps.Add(new ConvectionAtLevelSet_MovingMesh(d, D, LsTrk, thermParams, sigma)); } if (config.isViscous) { comps.Add(new ViscosityAtLevelSet_FullySymmetric_withEvap(LsTrk, physParams.mu_A, physParams.mu_B, dntParams.PenaltySafety, d, thermParams, sigma)); } comps.Add(new MassFluxAtInterface(d, D, LsTrk, thermParams, sigma)); }
//==================== // Continuity equation //==================== #region conti /// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="D"></param> /// <param name="spcName"></param> /// <param name="spcId"></param> /// <param name="BcMap"></param> public static void AddSpeciesContinuityEq(XSpatialOperatorMk2 XOp, INSE_Configuration config, int D, string spcName, SpeciesId spcId, IncompressibleMultiphaseBoundaryCondMap BcMap) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.ContinuityEquation; if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } PhysicalParameters physParams = config.getPhysParams; DoNotTouchParameters dntParams = config.getDntParams; // set species arguments double rhoSpc; switch (spcName) { case "A": { rhoSpc = physParams.rho_A; break; } case "B": { rhoSpc = physParams.rho_B; break; } default: throw new ArgumentException("Unknown species."); } // set components var comps = XOp.EquationComponents[CodName]; for (int d = 0; d < D; d++) { var src = new Operator.Continuity.DivergenceInSpeciesBulk_Volume(d, D, spcName, rhoSpc, dntParams.ContiSign, dntParams.RescaleConti); comps.Add(src); var flx = new Operator.Continuity.DivergenceInSpeciesBulk_Edge(d, BcMap, spcName, spcId, rhoSpc, dntParams.ContiSign, dntParams.RescaleConti); comps.Add(flx); //var stab = new PressureStabilizationInBulk(dntParams.PresPenalty2, physParams.reynolds_A, physParams.reynolds_B, spcName, spcId); //comps.Add(stab); } }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { int quadorder = this.u.Basis.Degree * 2 + 1; Op = new XSpatialOperatorMk2(1, 0, 1, (A, B, C) => quadorder, LsTrk.SpeciesIdS.ToArray(), "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); } }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { Op = new XSpatialOperatorMk2(1, 0, 1, QuadOrderFunc: (int[] DomDegs, int[] ParamDegs, int[] CoDomDegs) => QuadOrder, __Species: new [] { "B" }, __varnames: new[] { "u", "c1" }); Op.EquationComponents["c1"].Add(new DxFlux()); // Flux in Bulk Phase; if (usePhi0) { Op.EquationComponents["c1"].Add(new LevSetFlx_phi0(this.LsTrk)); // flux am lev-set 0 } if (usePhi1) { Op.EquationComponents["c1"].Add(new LevSetFlx_phi1(this.LsTrk)); // flux am lev-set 1 } //Op.EquationComponents["c1"].Add(new DxBroken()); Op.Commit(); }
//============================================================== // additional interface components for NSFE interface components //============================================================== /// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="d"></param> /// <param name="D"></param> /// <param name="LsTrk"></param> public static void AddInterfaceNSE_withEvaporation_component(XSpatialOperatorMk2 XOp, XNSFE_OperatorConfiguration config, int d, int D, LevelSetTracker LsTrk) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.MomentumEquationComponent(d); if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } PhysicalParameters physParams = config.getPhysParams; ThermalParameters thermParams = config.getThermParams; DoNotTouchParameters dntParams = config.getDntParams; // set species arguments double rhoA = physParams.rho_A; double rhoB = physParams.rho_B; double muA = physParams.mu_A; double muB = physParams.mu_B; double sigma = physParams.Sigma; // compute further arguments double hVapA = thermParams.hVap_A; double hVapB = thermParams.hVap_B; double Tsat = thermParams.T_sat; double f = config.thermParams.fc; double R = config.thermParams.Rc; double R_int = 0.0; 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()))); } //double prescrbM = config.prescribedMassflux; // set components var comps = XOp.EquationComponents[CodName]; if (config.isTransport) { comps.Add(new ConvectionAtLevelSet_nonMaterialLLF(d, D, LsTrk, rhoA, rhoB, thermParams, R_int, sigma)); comps.Add(new ConvectionAtLevelSet_Consistency(d, D, LsTrk, rhoA, rhoB, dntParams.ContiSign, dntParams.RescaleConti, thermParams, R_int, sigma)); } //if (config.isPInterfaceSet) { // comps.Add(new GeneralizedPressureFormAtLevelSet(d, LsTrk, thermParams.p_sat, thermParams.hVap_A)); //} if (config.isViscous) { comps.Add(new ViscosityAtLevelSet_FullySymmetric_withEvap(LsTrk, muA, muB, dntParams.PenaltySafety, d, rhoA, rhoB, thermParams, R_int, sigma)); } comps.Add(new MassFluxAtInterface(d, D, LsTrk, rhoA, rhoB, thermParams, R_int, sigma)); }
/// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="config"></param> /// <param name="D"></param> /// <param name="LsTrk"></param> public static void AddInterfaceHeatEq_withEvaporation(XSpatialOperatorMk2 XOp, XNSFE_OperatorConfiguration config, int D, LevelSetTracker LsTrk) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.HeatEquation; if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } if (config.getConductMode != ConductivityInSpeciesBulk.ConductivityMode.SIP) { foreach (string cn in EquationNames.AuxHeatFlux(D)) { if (!XOp.CodomainVar.Contains(cn)) { throw new ArgumentException("CoDomain variable \"" + cn + "\" is not defined in Spatial Operator"); } } } PhysicalParameters physParams = config.getPhysParams; ThermalParameters thermParams = config.getThermParams; // set species arguments double rhoA = physParams.rho_A; double rhoB = physParams.rho_B; double sigma = physParams.Sigma; // compute further arguments double hVapA = thermParams.hVap_A; double hVapB = thermParams.hVap_B; double Tsat = thermParams.T_sat; double f = config.thermParams.fc; double R = config.thermParams.Rc; double rho_l = 0.0; double R_int = 0.0; if (config.thermParams.hVap_A > 0 && config.thermParams.hVap_B < 0) { rho_l = rhoA; 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) { rho_l = rhoB; 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()))); } // set components var comps = XOp.EquationComponents[CodName]; // mass flux at interface // ====================== //if (!config.isSeparated) { // comps.Add(new HeatFluxAtLevelSet(LsTrk, rho_l, thermParams, R_int, sigma)); //} // convective part // ================ if (thermParams.IncludeConvection) { comps.Add(new HeatConvectionAtLevelSet_Divergence(D, LsTrk, rhoA, rhoB, thermParams, R_int, sigma)); } }
public OperatorFactoryMk2( OperatorConfigurationMk2 config, LevelSetTracker _LsTrk, int _HMFdegree, int degU, IncompressibleMultiphaseBoundaryCondMap BcMap, bool _movingmesh, bool _evaporation) { // variable names // ============== D = _LsTrk.GridDat.SpatialDimension; this.LsTrk = _LsTrk; 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 = config.thermParams.k_A; double kB = config.thermParams.k_B; double hVapA = config.thermParams.hVap_A; double hVapB = config.thermParams.hVap_B; double Tsat = config.thermParams.T_sat; double R_int = 0.0; //double T_intMin = 0.0; if (evaporation) { 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; } double p_c = config.thermParams.pc; // create Operator // =============== m_OP = new XSpatialOperatorMk2(DomNameSelected, Params, CodNameSelected, (A, B, C) => _HMFdegree, this.LsTrk.SpeciesIdS.ToArray()); // 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]]; 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 for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { double rhoSpc = 0.0; double LFFSpc = 0.0; switch (LsTrk.SpeciesNames[spc]) { case "A": rhoSpc = rhoA; LFFSpc = LFFA; break; case "B": rhoSpc = rhoB; LFFSpc = LFFB; break; default: throw new ArgumentException("Unknown species."); } var conv = new Operator.Convection.ConvectionInSpeciesBulk_LLF(D, BcMap, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], d, rhoSpc, LFFSpc, 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 if (evaporation) { comps.Add(new Operator.Convection.GeneralizedConvectionAtLevelSet_DissipativePart(d, D, LsTrk, rhoA, rhoB, LFFA, LFFB, BcMap, kA, kB, hVapA, hVapB, R_int, Tsat, sigma, p_c)); } } 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); for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { var pres = new Operator.Pressure.PressureInSpeciesBulk(d, BcMap, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc]); comps.Add(pres); } var presLs = new Operator.Pressure.PressureFormAtLevelSet(d, D, LsTrk); //, dntParams.UseWeightedAverages, muA, muB); comps.Add(presLs); } } // viscous operator // ================ if (config.Viscous && !muIs0) { for (int d = 0; d < D; d++) { var comps = m_OP.EquationComponents[CodName[d]]; 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.FullySymmetric: { // Bulk operator for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { var Visc1 = new Operator.Viscosity.ViscosityInSpeciesBulk_GradUTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], d, D, muA, muB); comps.Add(Visc1); var Visc2 = new Operator.Viscosity.ViscosityInSpeciesBulk_GradUtranspTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], d, D, muA, muB); comps.Add(Visc2); } 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); m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(Visc1Penalty); m_OP.GhostEdgesOperator.EquationComponents[CodName[d]].Add(Visc2Penalty); } // Level-Set operator comps.Add(new Operator.Viscosity.ViscosityAtLevelSet_FullySymmetric(LsTrk, muA, muB, penalty, d, 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); for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { double rhoSpc = 0.0; switch (LsTrk.SpeciesNames[spc]) { case "A": rhoSpc = rhoA; break; case "B": rhoSpc = rhoB; break; default: throw new ArgumentException("Unknown species."); } var src = new Operator.Continuity.DivergenceInSpeciesBulk_Volume(d, D, LsTrk.SpeciesIdS[spc], rhoSpc, config.dntParams.ContiSign, config.dntParams.RescaleConti); var flx = new Operator.Continuity.DivergenceInSpeciesBulk_Edge(d, BcMap, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], rhoSpc, 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); //, 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); } } // 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 { IEquationComponent isoSurfT = new IsotropicSurfaceTension_LaplaceBeltrami(d, D, config.physParams.Sigma * 0.5, BcMap.EdgeTag2Type, config.physParams.theta_e, config.physParams.betaL); 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; } 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); 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); } } } // 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); } } } // 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(); }
//======================== // Kinetic energy equation //======================== #region energy public static void AddSpeciesKineticEnergyEquation(XSpatialOperatorMk2 XOp, IEnergy_Configuration config, int D, string spcName, SpeciesId spcId, IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.KineticEnergyEquation; if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } PhysicalParameters physParams = config.getPhysParams; DoNotTouchParameters dntParams = config.getDntParams; bool laplaceKinE = (config.getKinEviscousDiscretization == KineticEnergyViscousSourceTerms.laplaceKinE); bool divergenceP = (config.getKinEpressureDiscretization == KineticEnergyPressureSourceTerms.divergence); // set species arguments double rhoSpc, LFFSpc, muSpc; switch (spcName) { case "A": { rhoSpc = physParams.rho_A; LFFSpc = dntParams.LFFA; muSpc = physParams.mu_A; break; } case "B": { rhoSpc = physParams.rho_B; LFFSpc = dntParams.LFFB; muSpc = physParams.mu_B; break; } default: throw new ArgumentException("Unknown species."); } // set components var comps = XOp.EquationComponents[CodName]; // convective part // ================ if (config.isTransport) { var convK = new KineticEnergyConvectionInSpeciesBulk(D, BcMap, spcName, spcId, rhoSpc, LFFSpc, LsTrk); //var convK = new KineticEnergyConvectionInSpeciesBulk_Upwind(D, BcMap, spcName, spcId, rhoSpc); comps.Add(convK); } // viscous terms // ============= if (config.isViscous && !(muSpc == 0.0)) { double penalty = dntParams.PenaltySafety; // Laplace of kinetic energy // ========================= if (laplaceKinE) { var kELap = new KineticEnergyLaplaceInSpeciesBulk( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, spcName, spcId, D, physParams.mu_A, physParams.mu_B); comps.Add(kELap); if (dntParams.UseGhostPenalties) { var kELapPenalty = new KineticEnergyLaplaceInSpeciesBulk( penalty, 0.0, BcMap, spcName, spcId, D, physParams.mu_A, physParams.mu_B); XOp.GhostEdgesOperator.EquationComponents[CodName].Add(kELapPenalty); } } // Divergence of stress tensor // =========================== { if (config.getKinEviscousDiscretization == KineticEnergyViscousSourceTerms.fluxFormulation) { comps.Add(new StressDivergenceInSpeciesBulk(D, BcMap, spcName, spcId, muSpc, transposed: !laplaceKinE)); } if (config.getKinEviscousDiscretization == KineticEnergyViscousSourceTerms.local) { comps.Add(new StressDivergence_Local(D, muSpc, spcName, spcId, transposed: !laplaceKinE)); } } // Dissipation // =========== { comps.Add(new Dissipation(D, muSpc, spcName, spcId, _withPressure: config.withPressureDissipation)); } } // pressure term // ============= if (config.isPressureGradient) { if (divergenceP) { comps.Add(new DivergencePressureEnergyInSpeciesBulk(D, BcMap, spcName, spcId)); //comps.Add(new ConvectivePressureTerm_LLF(D, BcMap, spcName, spcId, LFFSpc, LsTrk)); } else { comps.Add(new PressureGradientConvection(D, spcName, spcId)); } } // gravity (volume forces) // ======================= { comps.Add(new PowerofGravity(D, spcName, spcId, rhoSpc)); } }
public static void AddInterfaceKineticEnergyEquation(XSpatialOperatorMk2 XOp, IEnergy_Configuration config, int D, IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk, int degU) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already comitted. Adding of new components is not allowed"); } string CodName = EquationNames.KineticEnergyEquation; if (!XOp.CodomainVar.Contains(CodName)) { throw new ArgumentException("CoDomain variable \"" + CodName + "\" is not defined in Spatial Operator"); } PhysicalParameters physParams = config.getPhysParams; DoNotTouchParameters dntParams = config.getDntParams; bool laplaceKinE = (config.getKinEviscousDiscretization == KineticEnergyViscousSourceTerms.laplaceKinE); bool divergenceP = (config.getKinEpressureDiscretization == KineticEnergyPressureSourceTerms.divergence); // set species arguments double rhoA = physParams.rho_A; double rhoB = physParams.rho_B; double LFFA = dntParams.LFFA; double LFFB = dntParams.LFFB; double muA = physParams.mu_A; double muB = physParams.mu_B; double sigma = physParams.Sigma; double penalty_base = (degU + 1) * (degU + D) / D; double penalty = penalty_base * dntParams.PenaltySafety; // set components var comps = XOp.EquationComponents[CodName]; // convective part // ================ if (config.isTransport) { comps.Add(new KineticEnergyConvectionAtLevelSet(D, LsTrk, rhoA, rhoB, LFFA, LFFB, physParams.Material, BcMap, config.isMovingMesh)); } // viscous terms // ============= if (config.isViscous && (!(muA == 0.0) && !(muB == 0.0))) { if (laplaceKinE) { comps.Add(new KineticEnergyLaplaceAtInterface(LsTrk, muA, muB, penalty * 1.0)); } if (config.getKinEviscousDiscretization == KineticEnergyViscousSourceTerms.fluxFormulation) { comps.Add(new StressDivergenceAtLevelSet(LsTrk, muA, muB, transposed: !laplaceKinE)); } } // pressure term // ============= if (config.isPressureGradient) { if (divergenceP) { comps.Add(new DivergencePressureEnergyAtLevelSet(LsTrk)); //comps.Add(new ConvectivePressureTermAtLevelSet_LLF(D, LsTrk, LFFA, LFFB, physParams.Material, BcMap, config.isMovingMesh)); } } // surface energy // ============== { comps.Add(new SurfaceEnergy(D, LsTrk, sigma, rhoA, rhoB)); } }