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(); }
static string[] BndFunctions(IGridData g) { int D = g.SpatialDimension; return(ArrayTools.Cat(VariableNames.VelocityVector(D), VariableNames.Temperature, "HeatFlux")); }
protected override void CreateEquationsAndSolvers(GridUpdateDataVaultBase L) { using (FuncTrace tr = new FuncTrace()) { this.BcMap = new IncompressibleBoundaryCondMap(this.GridData, grid.GetBoundaryConfig(), PhysicsMode.Incompressible); // assemble system, create matrix // ------------------------------ int D = GridData.SpatialDimension; //double penalty_base = ((double)((U[0].Basis.Degree + 1) * (U[0].Basis.Degree + D))) / ((double)D); double penalty_base = 1.0; double penalty_factor = 1.2; // equation assembly // ----------------- string[] CodNames = D.ForLoop(i => "C" + i); Operator = new SpatialOperator(VariableNames.VelocityVector(D), new string[] { VariableNames.ViscosityMolecular }, CodNames, QuadOrderFunc.Linear()); for (int d = 0; d < D; d++) { if ((this.whichTerms & Terms.T1) != 0) { var flx1 = new swipViscosity_Term1(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity); flx1.g_Diri_Override = this.solution.U; flx1.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx1); } if ((this.whichTerms & Terms.T2) != 0) { var flx2 = new swipViscosity_Term2(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity); flx2.g_Diri_Override = this.solution.U; flx2.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx2); } if ((this.whichTerms & Terms.T3) != 0) { var flx3 = new swipViscosity_Term3(penalty_base * penalty_factor, d, D, BcMap, ViscosityOption.VariableViscosity); flx3.g_Diri_Override = this.solution.U; flx3.g_Neu_Override = this.solution.dU; Operator.EquationComponents[CodNames[d]].Add(flx3); } } // */ Operator.Commit(); var map = this.U.Mapping; OperatorMtx = new MsrMatrix(map, map); Operator.ComputeMatrixEx(map, new DGField[] { this.mu }, map, OperatorMtx, this.bnd.CoordinateVector, volQuadScheme: null, edgeQuadScheme: null); // test for matrix symmetry // ======================== if (base.MPISize == 1) { double MatrixAssymmetry = OperatorMtx.SymmetryDeviation(); Console.WriteLine("Matrix asymmetry: " + MatrixAssymmetry); Assert.LessOrEqual(Math.Abs(MatrixAssymmetry), 1.0e-10); } } }
protected override SpatialOperator GetOperatorInstance(int D) { // create operator // =============== { double _D = D; double penalty_base = (phi.Basis.Degree + 1) * (phi.Basis.Degree + _D) / _D; // Get this from where? double penalty_factor = this.Control.penalty_poisson * penalty_base; //BoundaryCondMap<BoundaryType> PoissonBcMap = new BoundaryCondMap<BoundaryType>(this.GridData, this.Control.BoundaryValues, "T"); MultidimensionalArray LengthScales; if (this.GridData is GridData) { LengthScales = ((GridData)this.GridData).Cells.cj; } else if (this.GridData is AggregationGridData) { LengthScales = ((AggregationGridData)this.GridData).AncestorGrid.Cells.cj; } else { throw new NotImplementedException(); } m_bcMap = new BoundaryCondMap <BoundaryType>(this.GridData, BoundaryTranslator(ParentControl.BoundaryValues), "phi"); #region variables //create Parameter and Variablelists string[] paramVar = VariableNames.VelocityVector(D).Cat("phi0"); string[] domainVar = new string[] { "phi" }; string[] codomainVar = new string[] { "Res_phi" }; switch (this.Control.ModTyp) { case PhasefieldControl.ModelType.modelA: break; case PhasefieldControl.ModelType.modelB: domainVar = domainVar.Cat("mu"); codomainVar = codomainVar.Cat("Res_mu"); break; case PhasefieldControl.ModelType.modelC: default: throw new NotImplementedException(); break; } switch (this.Control.CurvatureCorrectionType) { case PhasefieldControl.CurvatureCorrection.FullyCoupled: domainVar = domainVar.Cat(VariableNames.Curvature); codomainVar = codomainVar.Cat("Res_" + VariableNames.Curvature); break; case PhasefieldControl.CurvatureCorrection.DirectCoupledIterative: case PhasefieldControl.CurvatureCorrection.DirectCoupledOnce: domainVar = domainVar.Cat(VariableNames.Curvature); codomainVar = codomainVar.Cat("Res_" + VariableNames.Curvature); paramVar = paramVar.Cat("D" + VariableNames.Curvature); break; case PhasefieldControl.CurvatureCorrection.None: default: break; } #endregion CHOp = new SpatialOperator( domainVar, paramVar, codomainVar, (DomainVariableDegrees, ParameterDegrees, CodomainVariableDegrees) => 4 * DomainVariableDegrees[0] //QuadOrderFunc.NonLinear(3) ); CHOp.ParameterUpdates.Add(CompleteParameterUpdate); CHOp.ParameterFactories.Add(AllocateParameters); #region equation components // convection term CHOp.EquationComponents["Res_phi"].Add( new phi_Flux(D, m_bcMap) ); switch (this.Control.ModTyp) { case PhasefieldControl.ModelType.modelA: CHOp.EquationComponents["Res_phi"].Add( new phi_Source(this.Control.diff) ); CHOp.EquationComponents["Res_phi"].Add( new mu_Diffusion(D, penalty_factor, LengthScales, this.Control.cahn * this.Control.diff.Sqrt(), m_bcMap) ); switch (this.Control.CurvatureCorrectionType) { case PhasefieldControl.CurvatureCorrection.FullyCoupled: CHOp.EquationComponents["Res_phi"].Add( new phi_CurvatureCorrection(D, this.Control.cahn * this.Control.diff.Sqrt()) ); CHOp.EquationComponents["Res_" + VariableNames.Curvature].Add( new curvature_Source(D) ); CHOp.EquationComponents["Res_" + VariableNames.Curvature].Add( new curvature_Divergence(D, penalty_factor, 0.001 / this.Control.cahn, LengthScales) ); break; case PhasefieldControl.CurvatureCorrection.DirectCoupledIterative: case PhasefieldControl.CurvatureCorrection.DirectCoupledOnce: CHOp.EquationComponents["Res_phi"].Add( new phi_CurvatureCorrection(D, this.Control.cahn * this.Control.diff.Sqrt()) ); CHOp.EquationComponents["Res_" + VariableNames.Curvature].Add( new curvature_Direct(D) ); break; case PhasefieldControl.CurvatureCorrection.None: default: break; } break; case PhasefieldControl.ModelType.modelB: CHOp.EquationComponents["Res_phi"].Add( new phi_Diffusion(D, penalty_factor, LengthScales, this.Control.diff, this.Control.lambda, m_bcMap) ); CHOp.EquationComponents["Res_mu"].Add( new mu_Diffusion(D, penalty_factor, LengthScales, this.Control.cahn, m_bcMap) ); CHOp.EquationComponents["Res_mu"].Add( new mu_Source() ); switch (this.Control.CurvatureCorrectionType) { case PhasefieldControl.CurvatureCorrection.FullyCoupled: CHOp.EquationComponents["Res_mu"].Add( new phi_CurvatureCorrection(D, this.Control.cahn) ); CHOp.EquationComponents["Res_" + VariableNames.Curvature].Add( new curvature_Source(D) ); CHOp.EquationComponents["Res_" + VariableNames.Curvature].Add( new curvature_Divergence(D, penalty_factor, 0.001 / this.Control.cahn, LengthScales) ); break; case PhasefieldControl.CurvatureCorrection.DirectCoupledIterative: case PhasefieldControl.CurvatureCorrection.DirectCoupledOnce: CHOp.EquationComponents["Res_mu"].Add( new phi_CurvatureCorrection(D, this.Control.cahn) ); CHOp.EquationComponents["Res_" + VariableNames.Curvature].Add( new curvature_Direct(D) ); break; case PhasefieldControl.CurvatureCorrection.None: default: break; } break; case PhasefieldControl.ModelType.modelC: throw new NotImplementedException(); break; default: throw new ArgumentOutOfRangeException(); break; } #endregion // temporal derivative double[] MassScales = new double[domainVar.Length]; MassScales[0] = 1.0; CHOp.TemporalOperator = new ConstantTemporalOperator(CHOp, MassScales); CHOp.LinearizationHint = LinearizationHint.GetJacobiOperator; CHOp.Commit(); return(CHOp); } }
/// <summary> /// ctor for the operator factory, where the equation compnents are set /// </summary> /// <param name="config"></param> /// <param name="_LsTrk"></param> /// <param name="_HMFdegree"></param> /// <param name="BcMap"></param> /// <param name="degU"></param> public XNSE_OperatorFactory(IXNSE_Configuration config, LevelSetTracker _LsTrk, int _HMFdegree, IncompressibleMultiphaseBoundaryCondMap BcMap, int degU) { this.LsTrk = _LsTrk; this.D = _LsTrk.GridDat.SpatialDimension; this.HMFDegree = _HMFdegree; this.physParams = config.getPhysParams; this.dntParams = config.getDntParams; // test input // ========== { if (config.getDomBlocks.GetLength(0) != 2 || config.getCodBlocks.GetLength(0) != 2) { throw new ArgumentException(); } if ((config.getPhysParams.mu_A <= 0) && (config.getPhysParams.mu_B <= 0)) { config.isViscous = false; } else { if ((config.getPhysParams.mu_A <= 0) || (config.getPhysParams.mu_B <= 0)) { throw new ArgumentException(); } } if ((config.getPhysParams.rho_A <= 0) || (config.getPhysParams.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 = ArrayTools.Cat(EquationNames.MomentumEquations(D), EquationNames.ContinuityEquation); Params = ArrayTools.Cat( VariableNames.Velocity0Vector(D), VariableNames.Velocity0MeanVector(D), VariableNames.NormalVector(D), VariableNames.Curvature, VariableNames.SurfaceForceVector(D) ); DomName = ArrayTools.Cat(VariableNames.VelocityVector(D), VariableNames.Pressure); // selected part: if (config.getCodBlocks[0]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(0, D)); } if (config.getCodBlocks[1]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(D, 1)); } if (config.getDomBlocks[0]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(0, D)); } if (config.getDomBlocks[1]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(D, 1)); } // create Operator // =============== m_XOp = new XSpatialOperatorMk2(DomNameSelected, Params, CodNameSelected, (A, B, C) => _HMFdegree, this.LsTrk.SpeciesIdS.ToArray()); // add components // ============== // species bulk components for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { // Navier Stokes equations XOperatorComponentsFactory.AddSpeciesNSE(m_XOp, config, D, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], BcMap, LsTrk, out U0meanrequired); // continuity equation if (config.isContinuity) { XOperatorComponentsFactory.AddSpeciesContinuityEq(m_XOp, config, D, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], BcMap); } } // interface components XOperatorComponentsFactory.AddInterfaceNSE(m_XOp, config, D, BcMap, LsTrk); // surface stress tensor XOperatorComponentsFactory.AddSurfaceTensionForce(m_XOp, config, D, BcMap, LsTrk, degU, out NormalsRequired, out CurvatureRequired); // surface tension force if (config.isContinuity) { XOperatorComponentsFactory.AddInterfaceContinuityEq(m_XOp, config, D, LsTrk); // continuity equation } m_XOp.Commit(); }
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 for the operator factory, where the equation compnents are set /// </summary> /// <param name="_config"></param> /// <param name="_LsTrk"></param> /// <param name="_HMFdegree"></param> /// <param name="BcMap"></param> /// <param name="thermBcMap"></param> /// <param name="degU"></param> public XNSFE_OperatorFactory(XNSFE_OperatorConfiguration _config, LevelSetTracker _LsTrk, int _HMFdegree, IncompressibleMultiphaseBoundaryCondMap BcMap, ThermalMultiphaseBoundaryCondMap thermBcMap, int degU, IDictionary <SpeciesId, IEnumerable <double> > MassScale) { this.config = _config; this.LsTrk = _LsTrk; this.D = _LsTrk.GridDat.SpatialDimension; this.HMFDegree = _HMFdegree; this.physParams = config.getPhysParams; this.thermParams = config.getThermParams; this.dntParams = config.getDntParams; // test input // ========== { if ((config.getPhysParams.mu_A <= 0) && (config.getPhysParams.mu_B <= 0)) { config.isViscous = false; } else { if ((config.getPhysParams.mu_A <= 0) || (config.getPhysParams.mu_B <= 0)) { throw new ArgumentException(); } } if ((config.getPhysParams.rho_A <= 0) || (config.getPhysParams.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 = ArrayTools.Cat(EquationNames.MomentumEquations(D), EquationNames.ContinuityEquation); Params = ArrayTools.Cat( VariableNames.Velocity0Vector(D), VariableNames.Velocity0MeanVector(D), VariableNames.NormalVector(D), VariableNames.Curvature, VariableNames.SurfaceForceVector(D) ); DomName = ArrayTools.Cat(VariableNames.VelocityVector(D), VariableNames.Pressure); if (config.solveEnergy) { CodName = ArrayTools.Cat(CodName, EquationNames.KineticEnergyEquation); Params = ArrayTools.Cat(Params, VariableNames.VelocityX_GradientVector(), VariableNames.VelocityY_GradientVector(), new string[] { "VelocityXGradX_GradientX", "VelocityXGradX_GradientY" }, new string[] { "VelocityXGradY_GradientX", "VelocityXGradY_GradientY" }, new string[] { "VelocityYGradX_GradientX", "VelocityYGradX_GradientY" }, new string[] { "VelocityYGradY_GradientX", "VelocityYGradY_GradientY" }, VariableNames.Pressure0, VariableNames.PressureGradient(D), VariableNames.GravityVector(D) ); DomName = ArrayTools.Cat(DomName, VariableNames.KineticEnergy); } if (config.solveHeat) { Params = ArrayTools.Cat(Params, VariableNames.Temperature0, VariableNames.HeatFlux0Vector(D), VariableNames.DisjoiningPressure ); if (config.conductMode == ConductivityInSpeciesBulk.ConductivityMode.SIP) { CodName = ArrayTools.Cat(CodName, EquationNames.HeatEquation); DomName = ArrayTools.Cat(DomName, VariableNames.Temperature); } else { CodName = ArrayTools.Cat(CodName, EquationNames.HeatEquation, EquationNames.AuxHeatFlux(D)); DomName = ArrayTools.Cat(DomName, VariableNames.Temperature, VariableNames.HeatFluxVector(D)); } } storedParams = new DGField[Params.Length]; // selected part: if (config.getCodBlocks[0]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(0, D)); } if (config.getCodBlocks[1]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(D, 1)); } if (config.getDomBlocks[0]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(0, D)); } if (config.getDomBlocks[1]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(D, 1)); } int nBlocks = 2; if (config.solveEnergy) { nBlocks = 3; if (config.getCodBlocks[2]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(D + 1, 1)); } if (config.getDomBlocks[2]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(D + 1, 1)); } } if (config.solveHeat) { if (config.getCodBlocks[nBlocks]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(nBlocks + (D - 1) + 1, 1)); } if (config.getDomBlocks[nBlocks]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(nBlocks + (D - 1) + 1, 1)); } if (config.conductMode != ConductivityInSpeciesBulk.ConductivityMode.SIP) { if (config.getCodBlocks[nBlocks + 1]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(nBlocks + (D - 1) + 2, D)); } if (config.getDomBlocks[nBlocks + 1]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(nBlocks + (D - 1) + 2, D)); } } } // create Operator // =============== m_XOp = new XSpatialOperatorMk2(DomNameSelected, Params, CodNameSelected, (A, B, C) => _HMFdegree, this.LsTrk.SpeciesNames); // add Navier-Stokes components // ============================ // species bulk components for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { // Navier Stokes equations Solution.XNSECommon.XOperatorComponentsFactory.AddSpeciesNSE(m_XOp, config, D, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], BcMap, LsTrk, out U0meanrequired); // continuity equation if (config.isContinuity) { Solution.XNSECommon.XOperatorComponentsFactory.AddSpeciesContinuityEq(m_XOp, config, D, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], BcMap); } } // interface components Solution.XNSECommon.XOperatorComponentsFactory.AddInterfaceNSE(m_XOp, config, D, BcMap, LsTrk); // surface stress tensor Solution.XNSECommon.XOperatorComponentsFactory.AddSurfaceTensionForce(m_XOp, config, D, BcMap, LsTrk, degU, out NormalsRequired, out CurvatureRequired); // surface tension force if (config.isContinuity) { Solution.XNSECommon.XOperatorComponentsFactory.AddInterfaceContinuityEq(m_XOp, config, D, LsTrk); // continuity equation } // add kinetic energy equation components // ====================================== if (config.solveEnergy) { // species bulk components for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { Solution.EnergyCommon.XOperatorComponentsFactory.AddSpeciesKineticEnergyEquation(m_XOp, config, D, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], BcMap, LsTrk); } // interface components Solution.EnergyCommon.XOperatorComponentsFactory.AddInterfaceKineticEnergyEquation(m_XOp, config, D, BcMap, LsTrk, degU); CurvatureRequired = true; } // add Heat equation components // ============================ if (config.solveHeat) { // species bulk components for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { Solution.XheatCommon.XOperatorComponentsFactory.AddSpeciesHeatEq(m_XOp, config, D, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], thermBcMap, LsTrk); } // interface components Solution.XheatCommon.XOperatorComponentsFactory.AddInterfaceHeatEq(m_XOp, config, D, thermBcMap, LsTrk); } // add Evaporation interface components // ==================================== if (config.isEvaporation) { XOperatorComponentsFactory.AddInterfaceNSE_withEvaporation(m_XOp, config, D, LsTrk); if (config.isContinuity) { XOperatorComponentsFactory.AddInterfaceContinuityEq_withEvaporation(m_XOp, config, D, LsTrk); } } // create temporal operator // ======================== var TempOp = new ConstantXTemporalOperator(m_XOp, 0.0); m_XOp.TemporalOperator = TempOp; foreach (var kv in MassScale) { TempOp.DiagonalScale[LsTrk.GetSpeciesName(kv.Key)].SetV(kv.Value.ToArray()); } // Finalize // ======== m_XOp.Commit(); }
/// <summary> /// ctor for the operator factory, where the equation compnents are set /// </summary> /// <param name="config"></param> /// <param name="_LsTrk"></param> /// <param name="_HMFdegree"></param> /// <param name="BcMap"></param> /// <param name="degU"></param> public XRheology_OperatorFactory(XRheology_OperatorConfiguration config, LevelSetTracker _LsTrk, int _HMFdegree, IncompressibleMultiphaseBoundaryCondMap BcMap, int _stressDegree, int degU) { this.LsTrk = _LsTrk; this.D = _LsTrk.GridDat.SpatialDimension; this.HMFDegree = _HMFdegree; this.physParams = config.getPhysParams; this.dntParams = config.getDntParams; this.useJacobianForOperatorMatrix = config.isUseJacobian; this.useArtificialDiffusion = config.isUseArtificialDiffusion; // test input // ========== { if (config.getDomBlocks.GetLength(0) != 3 || config.getCodBlocks.GetLength(0) != 3) { throw new ArgumentException(); } //if ((config.getPhysParams.Weissenberg_a <= 0) && (config.getPhysParams.Weissenberg_a <= 0)) { // config.isOldroydB = false; //} else { // if ((config.getPhysParams.mu_A <= 0) || (config.getPhysParams.mu_B <= 0)) // throw new ArgumentException(); //} //if ((config.getPhysParams.reynolds_A <= 0) && (config.getPhysParams.reynolds_B <= 0)) { // config.isViscous = false; //} else { // if ((config.getPhysParams.reynolds_A <= 0) || (config.getPhysParams.reynolds_B <= 0)) // throw new ArgumentException(); //if ((config.getPhysParams.rho_A <= 0) || (config.getPhysParams.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 = ArrayTools.Cat(EquationNames.MomentumEquations(this.D), EquationNames.ContinuityEquation, EquationNames.Constitutive(this.D)); Params = ArrayTools.Cat( VariableNames.Velocity0Vector(this.D), VariableNames.Velocity0MeanVector(this.D), VariableNames.VelocityX_GradientVector(), VariableNames.VelocityY_GradientVector(), VariableNames.StressXXP, VariableNames.StressXYP, VariableNames.StressYYP, // "artificialViscosity", VariableNames.NormalVector(this.D), VariableNames.Curvature, VariableNames.SurfaceForceVector(this.D) ); DomName = ArrayTools.Cat(VariableNames.VelocityVector(this.D), VariableNames.Pressure, VariableNames.StressXX, VariableNames.StressXY, VariableNames.StressYY); // selected part: if (config.getCodBlocks[0]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(0, this.D)); } if (config.getCodBlocks[1]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(this.D, 1)); } if (config.getCodBlocks[2]) { CodNameSelected = ArrayTools.Cat(CodNameSelected, CodName.GetSubVector(this.D + 1, 3)); } if (config.getDomBlocks[0]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(0, this.D)); } if (config.getDomBlocks[1]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(this.D, 1)); } if (config.getDomBlocks[2]) { DomNameSelected = ArrayTools.Cat(DomNameSelected, DomName.GetSubVector(this.D + 1, 3)); } // create Operator // =============== m_XOp = new XSpatialOperatorMk2(DomNameSelected, Params, CodNameSelected, (A, B, C) => _HMFdegree, this.LsTrk.SpeciesIdS.ToArray()); // add components // ============================ // species bulk components for (int spc = 0; spc < LsTrk.TotalNoOfSpecies; spc++) { // Navier Stokes equations XOperatorComponentsFactory.AddSpeciesNSE(m_XOp, config, this.D, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], BcMap, LsTrk, out U0meanrequired); // continuity equation if (config.isContinuity) { XOperatorComponentsFactory.AddSpeciesContinuityEq(m_XOp, config, this.D, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], BcMap); } // constitutive equation XConstitutiveOperatorComponentsFactory.AddSpeciesConstitutive(m_XOp, config, this.D, stressDegree, LsTrk.SpeciesNames[spc], LsTrk.SpeciesIdS[spc], BcMap, LsTrk, out U0meanrequired); } // interface components XOperatorComponentsFactory.AddInterfaceNSE(m_XOp, config, this.D, BcMap, LsTrk); // surface stress tensor XOperatorComponentsFactory.AddSurfaceTensionForce(m_XOp, config, this.D, BcMap, LsTrk, degU, out NormalsRequired, out CurvatureRequired); // surface tension force XConstitutiveOperatorComponentsFactory.AddInterfaceConstitutive(m_XOp, config, this.D, BcMap, LsTrk); //viscosity of stresses at constitutive if (config.isContinuity) { XOperatorComponentsFactory.AddInterfaceContinuityEq(m_XOp, config, this.D, LsTrk); // continuity equation } m_XOp.Commit(); }
public void Init(MultigridOperator op) { int D = op.GridData.SpatialDimension; CodName = (new string[] { "mom0", "mom1" }); Params = ArrayTools.Cat( VariableNames.Velocity0Vector(D)); DomName = ArrayTools.Cat(VariableNames.VelocityVector(D)); LocalOp = new SpatialOperator(DomName, Params, CodName, (A, B, C) => 4); for (int d = 0; d < D; d++) { LocalOp.EquationComponents["mom" + d].Add(new LocalDiffusiveFlux() { m_component = d, dt = m_dt, muA = m_muA }); } LocalOp.Commit(); //LocalMatrix = op.MassMatrix.CloneAs().ToMsrMatrix(); //LocalMatrix.Clear(); //var U0 = new VectorField<SinglePhaseField>(op.BaseGridProblemMapping Take(D).Select(F => (SinglePhaseField)F).ToArray()); UnsetteledCoordinateMapping test = new UnsetteledCoordinateMapping(op.BaseGridProblemMapping.BasisS.GetSubVector(0, D)); var U0 = ((BoSSS.Foundation.CoordinateMapping)op.Mapping.ProblemMapping).Fields.GetSubVector(0, 2); var empty = new SinglePhaseField[D]; LocalMatrix = LocalOp.ComputeMatrix(test, empty, test, time: m_dt); Uidx = op.Mapping.ProblemMapping.GetSubvectorIndices(true, D.ForLoop(i => i)); Pidx = op.Mapping.ProblemMapping.GetSubvectorIndices(true, D); int Upart = Uidx.Length; int Ppart = Pidx.Length; ConvDiff = null; // new BlockMsrMatrix(Upart, Upart, 1, 1); pGrad = null; // new BlockMsrMatrix(Upart, Ppart, 1, 1); divVel = null; // new BlockMsrMatrix(Ppart, Upart, 1, 1); BlockMsrMatrix VelocityMass = null; // new BlockMsrMatrix(Upart, Upart, 1, 1); BlockMsrMatrix leftChangeBasesVel = null; // new BlockMsrMatrix(Upart, Upart, 1, 1); BlockMsrMatrix rightChangeBasesVel = null; // new BlockMsrMatrix(Upart, Upart, 1, 1); op.MassMatrix.AccSubMatrixTo(1.0, VelocityMass, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); op.LeftChangeOfBasis.AccSubMatrixTo(1.0, leftChangeBasesVel, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); op.RightChangeOfBasis.AccSubMatrixTo(1.0, rightChangeBasesVel, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); var temp = BlockMsrMatrix.Multiply(leftChangeBasesVel, LocalMatrix); LocalMatrix = BlockMsrMatrix.Multiply(temp, rightChangeBasesVel); var M = op.OperatorMatrix; M.AccSubMatrixTo(1.0, ConvDiff, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); M.AccSubMatrixTo(1.0, pGrad, Uidx, default(int[]), Pidx, default(int[]), default(int[]), default(int[])); M.AccSubMatrixTo(1.0, divVel, Pidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); //LocalMatrix.SaveToTextFileSparse("LocalConvDiffMatrix"); //ConvDiff.SaveToTextFileSparse("ConvDiff"); //op.MassMatrix.SaveToTextFileSparse("MassMatrix"); //VelocityMass.SaveToTextFileSparse("VelocityMass"); }
/// <summary> /// Declaration of the spatial operator /// </summary> protected override SpatialOperator GetOperatorInstance(int D) { // instantiate boundary condition mapping // ====================================== boundaryCondMap = new IncompressibleBoundaryCondMap(this.GridData, this.Control.BoundaryValues, PhysicsMode.Incompressible); // instantiate operator // ==================== string[] CodName = (new[] { "ResidualMomentumX", "ResidualMomentumY", "ResidualMomentumZ" }).GetSubVector(0, D).Cat("ResidualConti"); var op = new SpatialOperator( __DomainVar: VariableNames.VelocityVector(D).Cat(VariableNames.Pressure), __ParameterVar: VariableNames.GravityVector(D), __CoDomainVar: CodName, QuadOrderFunc: QuadOrderFunc.NonLinear(2)); op.LinearizationHint = LinearizationHint.GetJacobiOperator; // Temporal Operator // ================= var TempOp = new ConstantTemporalOperator(op, 0.0); // init with entire diagonal set to 0.0 op.TemporalOperator = TempOp; for (int d = 0; d < D; d++) { TempOp.SetDiagonal(CodName[d], Control.Density); // set momentum equation entries to density } // Pressure Reference // ================== // if there is no Dirichlet boundary condition, // the mean value of the pressure is free: op.FreeMeanValue[VariableNames.Pressure] = !boundaryCondMap.DirichletPressureBoundary; // Momentum Equation // ================= // convective part: { for (int d = 0; d < D; d++) { var comps = op.EquationComponents[CodName[d]]; var ConvBulk = new LocalLaxFriedrichsConvection(D, boundaryCondMap, d, Control.Density); comps.Add(ConvBulk); // bulk component } } // pressure part: { for (int d = 0; d < D; d++) { var comps = op.EquationComponents[CodName[d]]; var pres = new PressureGradientLin_d(d, boundaryCondMap); comps.Add(pres); // bulk component } } // viscous part: { for (int d = 0; d < D; d++) { var comps = op.EquationComponents[CodName[d]]; double penalty_bulk = this.Control.PenaltySafety; var Visc = new swipViscosity_Term1(penalty_bulk, d, D, boundaryCondMap, ViscosityOption.ConstantViscosity, constantViscosityValue: Control.Viscosity); comps.Add(Visc); // bulk component GradUTerm } } // Continuity equation // =================== { for (int d = 0; d < D; d++) { var src = new Divergence_DerivativeSource(d, D); var flx = new Divergence_DerivativeSource_Flux(d, boundaryCondMap); op.EquationComponents[CodName[D]].Add(src); op.EquationComponents[CodName[D]].Add(flx); } //IBM_Op.EquationComponents["div"].Add(new PressureStabilization(1, 1.0 / this.Control.PhysicalParameters.mu_A)); } // Gravity parameter // ================= op.ParameterFactories.Add(delegate(IReadOnlyDictionary <string, DGField> DomainVarFields) { return(D.ForLoop(d => (VariableNames.Gravity_d(d), this.Gravity[d] as DGField))); }); // commit & return // =============== op.Commit(); return(op); }