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(); }
//======================= // Navier Stokes equation //======================= #region nse /// <summary> /// /// </summary> /// <param name="XOp"></param> /// <param name="d"></param> /// <param name="D"></param> /// <param name="spcName"></param> /// <param name="spcId"></param> /// <param name="BcMap"></param> /// <param name="config"></param> /// <param name="LsTrk"></param> /// <param name="U0meanrequired"></param> public static void AddSpeciesNSE_component(XSpatialOperatorMk2 XOp, INSE_Configuration config, int d, int D, string spcName, SpeciesId spcId, IncompressibleMultiphaseBoundaryCondMap BcMap, LevelSetTracker LsTrk, out bool U0meanrequired) { // check input if (XOp.IsCommited) { throw new InvalidOperationException("Spatial Operator is already committed. 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; DoNotTouchParameters dntParams = config.getDntParams; // 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 operator // =================== U0meanrequired = false; if (physParams.IncludeConvection && config.isTransport) { var conv = new Operator.Convection.ConvectionInSpeciesBulk_LLF(D, BcMap, spcName, spcId, d, rhoSpc, LFFSpc, LsTrk); comps.Add(conv); U0meanrequired = true; } // pressure gradient // ================= if (config.isPressureGradient) { var pres = new Operator.Pressure.PressureInSpeciesBulk(d, BcMap, spcName, spcId); comps.Add(pres); //problably necessary for LDG Simulation. Only one species parameter reynoldsA!!!!!! //var presStab = new PressureStabilizationInBulk(dntParams.PresPenalty2, physParams.reynolds_A, spcName, spcId); //comps.Add(presStab); } // viscous operator // ================ if (config.isViscous && !(muSpc == 0.0)) { double penalty = dntParams.PenaltySafety; switch (dntParams.ViscosityMode) { case ViscosityMode.Standard: case ViscosityMode.TransposeTermMissing: { // Bulk operator: var Visc1 = new Operator.Viscosity.ViscosityInSpeciesBulk_GradUTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, spcName, spcId, d, D, physParams.mu_A, physParams.mu_B); comps.Add(Visc1); if (dntParams.UseGhostPenalties) { var Visc1Penalty = new Operator.Viscosity.ViscosityInSpeciesBulk_GradUTerm( penalty, 0.0, BcMap, spcName, spcId, d, D, physParams.mu_A, physParams.mu_B); XOp.GhostEdgesOperator.EquationComponents[CodName].Add(Visc1Penalty); } break; } case ViscosityMode.FullySymmetric: { // Bulk operator var Visc1 = new Operator.Viscosity.ViscosityInSpeciesBulk_GradUTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, spcName, spcId, d, D, physParams.mu_A, physParams.mu_B); comps.Add(Visc1); var Visc2 = new Operator.Viscosity.ViscosityInSpeciesBulk_GradUtranspTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, spcName, spcId, d, D, physParams.mu_A, physParams.mu_B); comps.Add(Visc2); if (dntParams.UseGhostPenalties) { var Visc1Penalty = new Operator.Viscosity.ViscosityInSpeciesBulk_GradUTerm( penalty, 0.0, BcMap, spcName, spcId, d, D, physParams.mu_A, physParams.mu_B); var Visc2Penalty = new Operator.Viscosity.ViscosityInSpeciesBulk_GradUtranspTerm( penalty, 0.0, BcMap, spcName, spcId, d, D, physParams.mu_A, physParams.mu_B); XOp.GhostEdgesOperator.EquationComponents[CodName].Add(Visc1Penalty); XOp.GhostEdgesOperator.EquationComponents[CodName].Add(Visc2Penalty); } break; } case ViscosityMode.Viscoelastic: { //set species arguments double ReSpc, betaSpc; switch (spcName) { case "A": { ReSpc = physParams.reynolds_A; betaSpc = physParams.beta_a; break; } case "B": { ReSpc = physParams.reynolds_B; betaSpc = physParams.beta_b; break; } default: throw new ArgumentException("Unknown species."); } // Bulk operator: var Visc1 = new Operator.Viscosity.DimensionlessViscosityInSpeciesBulk_GradUTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, spcName, spcId, d, D, physParams.reynolds_A / physParams.beta_a, physParams.reynolds_B / physParams.beta_b); comps.Add(Visc1); var Visc2 = new Operator.Viscosity.DimensionlessViscosityInSpeciesBulk_GradUtranspTerm( dntParams.UseGhostPenalties ? 0.0 : penalty, 1.0, BcMap, spcName, spcId, d, D, physParams.reynolds_A / physParams.beta_a, physParams.reynolds_B / physParams.beta_b); comps.Add(Visc2); var div = new StressDivergenceInBulk(d, BcMap, ReSpc, dntParams.Penalty1, dntParams.Penalty2, spcName, spcId); comps.Add(div); break; } default: throw new NotImplementedException(); } } }