public XOptimizedLaplacianArtificialViscosityFlux(BoundaryCondMap <XDGHeatBcType> boundaryCondMap, LevelSetTracker levelSetTracker, string ArgumentVarName, double penaltySafetyFactor, double penaltyFactor, Dictionary <SpeciesId, MultidimensionalArray> inverseLengthScales) { this.GridData = levelSetTracker.GridDat; this.ArgumentName = ArgumentVarName; this.boundaryCondMap = boundaryCondMap; // Calculate penalties CellMask cutCells = levelSetTracker.Regions.GetCutCellMask(); CellMask speciesAWithOutCutCells = levelSetTracker.Regions.GetSpeciesMask("A").Except(cutCells); CellMask speciesBWithOutCutCells = levelSetTracker.Regions.GetSpeciesMask("B").Except(cutCells); double[] lengthScales_A = inverseLengthScales[levelSetTracker.GetSpeciesId("A")].To1DArray(); double[] lengthScales_B = inverseLengthScales[levelSetTracker.GetSpeciesId("B")].To1DArray(); this.penalties = new double[lengthScales_A.Length]; foreach (int cell in speciesAWithOutCutCells.ItemEnum) { this.penalties[cell] = penaltySafetyFactor * penaltyFactor * lengthScales_A[cell]; } foreach (int cell in speciesBWithOutCutCells.ItemEnum) { this.penalties[cell] = penaltySafetyFactor * penaltyFactor * lengthScales_B[cell]; } foreach (int cell in cutCells.ItemEnum) { this.penalties[cell] = double.NaN; } }
/// <summary> /// Ctor for XDG usage /// </summary> public OptimizedLaplacianArtificialViscosityFlux(LevelSetTracker levelSetTracker, string ArgumentVarName, double penaltySafetyFactor, double penaltyFactor, Dictionary <SpeciesId, MultidimensionalArray> cellLengthScales) { this.gridData = levelSetTracker.GridDat; this.ArgumentName = ArgumentVarName; // Combine length scales from species A and B CellMask cutCells = levelSetTracker.Regions.GetCutCellMask(); CellMask speciesAWithOutCutCells = levelSetTracker.Regions.GetSpeciesMask("A").Except(cutCells); CellMask speciesBWithOutCutCells = levelSetTracker.Regions.GetSpeciesMask("B").Except(cutCells); double[] cellLengthScales_A = cellLengthScales[levelSetTracker.GetSpeciesId("A")].To1DArray(); double[] cellLengthScales_B = cellLengthScales[levelSetTracker.GetSpeciesId("B")].To1DArray(); this.Penalties = new double[cellLengthScales_A.Length]; foreach (int cell in speciesAWithOutCutCells.ItemEnum) { this.Penalties[cell] = penaltySafetyFactor * penaltyFactor / cellLengthScales_A[cell]; } foreach (int cell in speciesBWithOutCutCells.ItemEnum) { this.Penalties[cell] = penaltySafetyFactor * penaltyFactor / cellLengthScales_B[cell]; } foreach (int cell in cutCells.ItemEnum) { this.Penalties[cell] = penaltySafetyFactor * penaltyFactor / Math.Min(cellLengthScales_A[cell], cellLengthScales_B[cell]); } #if DEBUG Penalties.ForEach(s => Debug.Assert(s >= 0.0, "Penalty is smaller than zero")); Penalties.ForEach(s => Debug.Assert(!double.IsNaN(s), "Penalty is NaN")); Penalties.ForEach(s => Debug.Assert(!double.IsInfinity(s), "Penalty is infinite")); #endif }
public LevSetFlx(LevelSetTracker _LsTrk, double _alpha_A, double _alpha_B) { alpha_A = _alpha_A; alpha_B = _alpha_B; this.PositiveSpecies = _LsTrk.GetSpeciesId("B"); this.NegativeSpecies = _LsTrk.GetSpeciesId("A"); }
public HeatConvectionAtEvapLevelSet(int _D, LevelSetTracker LsTrk, double _capA, double _capB, double _LFFA, double _LFFB, ThermalMultiphaseBoundaryCondMap _bcmap, double _hVapA, double _Rint, double _Tsat, double _rho, double _sigma, double _pc, double _kA, double _kB, bool _movingmesh) { m_D = _D; capA = _capA; capB = _capB; m_LsTrk = LsTrk; //MaterialInterface = _MaterialInterface; movingmesh = _movingmesh; NegFlux = new HeatConvectionInBulk(_D, _bcmap, _capA, _capB, _LFFA, double.NaN, LsTrk); NegFlux.SetParameter("A", LsTrk.GetSpeciesId("A")); PosFlux = new HeatConvectionInBulk(_D, _bcmap, _capA, _capB, double.NaN, _LFFB, LsTrk); PosFlux.SetParameter("B", LsTrk.GetSpeciesId("B")); this.hVapA = _hVapA; this.Rint = _Rint; this.Tsat = _Tsat; this.rho = _rho; this.sigma = _sigma; this.pc = _pc; this.kA = _kA; this.kB = _kB; }
public ConvectivePressureTermAtLevelSet_LLF(int _D, LevelSetTracker LsTrk, double _LFFA, double _LFFB, bool _MaterialInterface, IncompressibleMultiphaseBoundaryCondMap _bcmap, bool _movingmesh) { m_D = _D; m_LsTrk = LsTrk; MaterialInterface = _MaterialInterface; movingmesh = _movingmesh; NegFlux = new ConvectivePressureTerm_LLF(_D, _bcmap, "A", LsTrk.GetSpeciesId("A"), _LFFA, LsTrk); PosFlux = new ConvectivePressureTerm_LLF(_D, _bcmap, "B", LsTrk.GetSpeciesId("B"), _LFFB, LsTrk); }
public KineticEnergyConvectionAtLevelSet(int _D, LevelSetTracker LsTrk, double _rhoA, double _rhoB, double _LFFA, double _LFFB, bool _MaterialInterface, IncompressibleMultiphaseBoundaryCondMap _bcmap, bool _movingmesh) { m_D = _D; m_LsTrk = LsTrk; MaterialInterface = _MaterialInterface; movingmesh = _movingmesh; NegFlux = new KineticEnergyConvectionInSpeciesBulk(_D, _bcmap, "A", LsTrk.GetSpeciesId("A"), _rhoA, _LFFA, LsTrk); //NegFlux.SetParameter("A", LsTrk.GetSpeciesId("A")); PosFlux = new KineticEnergyConvectionInSpeciesBulk(_D, _bcmap, "B", LsTrk.GetSpeciesId("B"), _rhoB, _LFFB, LsTrk); //PosFlux.SetParameter("B", LsTrk.GetSpeciesId("B")); }
public static double EnergyBalanceNormAtInterface(XDGField P, VectorField <XDGField> U, ConventionalDGField[] Umean, SinglePhaseField C, double muA, double muB, double sigma, int momentFittingOrder) { LevelSetTracker LsTrk = P.Basis.Tracker; double energyBal_Norm = 0.0; ScalarFunctionEx energyBalFunc = GetEnergyBalanceFunc(P, U, Umean, C, muA, muB, sigma, true); var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingOrder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, momentFittingOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { energyBalFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { energyBal_Norm += ResultsOfIntegration[i, 0]; } } ).Execute(); return(energyBal_Norm.Sqrt()); }
public static double EnergyJumpAtInterface(LevelSetTracker LsTrk, VectorField <XDGField> Velocity, XDGField Pressure, double muA, double muB, bool Norm, int momentFittingorder) { double EnergyJump = 0.0; ScalarFunctionEx EnergyJumpFunc = GetEnergyJumpFunc(LsTrk, Velocity, Pressure, muA, muB, Norm); var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingorder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, momentFittingorder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { EnergyJumpFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { EnergyJump += ResultsOfIntegration[i, 0]; } } ).Execute(); if (Norm) { EnergyJump.Sqrt(); } return(EnergyJump); }
public static double SurfaceEnergyChangerate(LevelSetTracker LsTrk, ConventionalDGField[] uI, double sigma, bool Norm, int momentFittingorder) { double Changerate_Surface = 0.0; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingorder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); ScalarFunctionEx SurfaceChangerate = GetInterfaceDivergenceFunc(LsTrk, uI, Norm); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, momentFittingorder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { SurfaceChangerate(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { Changerate_Surface += ResultsOfIntegration[i, 0]; } } ).Execute(); double Changerate_Esurf; if (Norm) { Changerate_Esurf = sigma * Changerate_Surface.Sqrt(); } else { Changerate_Esurf = sigma * Changerate_Surface; } return(Changerate_Esurf); }
public static double CurvatureEnergy(LevelSetTracker LsTrk, SinglePhaseField Curvature, double sigma, ConventionalDGField[] uI, bool ExtVel, bool Norm, int momentFittingorder) { double EnergyCurv = 0.0; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingorder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); ScalarFunctionEx CurvEnergyFunc = GetCurvatureEnergyFunc(LsTrk, Curvature, sigma, uI, ExtVel, Norm); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, momentFittingorder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { CurvEnergyFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { EnergyCurv += ResultsOfIntegration[i, 0]; } } ).Execute(); if (Norm) { EnergyCurv.Sqrt(); } return(EnergyCurv); }
public HeatConvectionAtLevelSet(int _D, LevelSetTracker LsTrk, double _capA, double _capB, double _LFFA, double _LFFB, ThermalMultiphaseBoundaryCondMap _bcmap, bool _movingmesh) { m_D = _D; capA = _capA; capB = _capB; m_LsTrk = LsTrk; //MaterialInterface = _MaterialInterface; movingmesh = _movingmesh; NegFlux = new HeatConvectionInBulk(_D, _bcmap, _capA, _capB, _LFFA, double.NaN, LsTrk); NegFlux.SetParameter("A", LsTrk.GetSpeciesId("A")); PosFlux = new HeatConvectionInBulk(_D, _bcmap, _capA, _capB, double.NaN, _LFFB, LsTrk); PosFlux.SetParameter("B", LsTrk.GetSpeciesId("B")); }
public ConvectionAtLevelSet_LLF(int _d, int _D, LevelSetTracker LsTrk, double _rhoA, double _rhoB, double _LFFA, double _LFFB, bool _MaterialInterface, IncompressibleMultiphaseBoundaryCondMap _bcmap, bool _movingmesh) { m_D = _D; m_d = _d; rhoA = _rhoA; rhoB = _rhoB; m_LsTrk = LsTrk; //varMode = _varMode; MaterialInterface = _MaterialInterface; movingmesh = _movingmesh; NegFlux = new ConvectionInBulk_LLF(_D, _bcmap, _d, _rhoA, _rhoB, _LFFA, double.NaN, LsTrk); NegFlux.SetParameter("A", LsTrk.GetSpeciesId("A"), null); PosFlux = new ConvectionInBulk_LLF(_D, _bcmap, _d, _rhoA, _rhoB, double.NaN, _LFFB, LsTrk); PosFlux.SetParameter("B", LsTrk.GetSpeciesId("B"), null); }
/// <summary> /// Update of all coloured cells. /// </summary> internal int[] UpdateColoring(LevelSetTracker LsTrk) { int[] coloredCells = LsTrk.Regions.ColorMap4Spc[LsTrk.GetSpeciesId("B")]; int[] coloredCellsExchange = coloredCells.CloneAs(); coloredCellsExchange.MPIExchange(GridData); ColorNeighborCells(coloredCells, coloredCellsExchange); RecolorCellsOfNeighborParticles(coloredCells, (GridData)GridData); return(coloredCells); }
private SpeciesId CreateDummyTracker(IEnumerable <DGField> Fields) { var gDat = Fields.First().GridDat as GridData; var DummyLevSet = new LevelSet(new Basis(gDat, 1), "DummyPhi"); DummyLevSet.AccConstant(-1.0); LsTrk = new LevelSetTracker(gDat, XQuadFactoryHelper.MomentFittingVariants.Saye, 1, new[] { "A", "B" }, DummyLevSet); LsTrk.UpdateTracker(0.0, __NearRegionWith: 0); var spcA = LsTrk.GetSpeciesId("A"); Debug.Assert(LsTrk.Regions.GetSpeciesMask(spcA).NoOfItemsLocally == gDat.Cells.NoOfLocalUpdatedCells); return(spcA); }
/// <summary> /// Calculate Forces acting from fluid onto the particle /// </summary> internal double[] Forces(out List <double[]>[] stressToPrintOut, CellMask cutCells) { double[] tempForces = new double[m_SpatialDim]; double[] IntegrationForces = tempForces.CloneAs(); List <double[]>[] stressToPrint = new List <double[]> [m_SpatialDim]; stressToPrint[0] = new List <double[]>(); stressToPrint[1] = new List <double[]>(); for (int d = 0; d < m_SpatialDim; d++) { void ErrFunc(int CurrentCellID, int Length, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Length, K, m_SpatialDim, m_SpatialDim); MultidimensionalArray pARes = MultidimensionalArray.Create(Length, K); MultidimensionalArray Normals = m_LevelSetTracker.DataHistories[0].Current.GetLevelSetNormals(Ns, CurrentCellID, Length); for (int i = 0; i < m_SpatialDim; i++) { m_U[i].EvaluateGradient(CurrentCellID, Length, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } m_P.Evaluate(CurrentCellID, Length, Ns, pARes); for (int j = 0; j < Length; j++) { for (int k = 0; k < K; k++) { result[j, k] = StressTensor(Grad_UARes, pARes, Normals, m_FluidViscosity, k, j, m_SpatialDim, d); double t = Math.PI * (1 - Math.Sign(Normals[j, k, 1])) / 2 + Math.Acos(Normals[j, k, 0]); stressToPrint[d].Add(new double[] { t, result[j, k] }); } } } int[] noOfIntegrals = new int[] { 1 }; XQuadSchemeHelper SchemeHelper = m_LevelSetTracker.GetXDGSpaceMetrics(new[] { m_LevelSetTracker.GetSpeciesId("A") }, m_RequiredOrder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, cutCells); ICompositeQuadRule <QuadRule> surfaceRule = cqs.Compile(m_LevelSetTracker.GridDat, m_RequiredOrder); CellQuadrature.GetQuadrature(noOfIntegrals, m_GridData, surfaceRule, delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { IntegrationForces[d] = ForceTorqueSummationWithNeumaierArray(IntegrationForces[d], ResultsOfIntegration, Length); } ).Execute(); } stressToPrintOut = stressToPrint.CloneAs(); return(tempForces = IntegrationForces.CloneAs()); }
/// <summary> /// Computes the energy stored in the fluid interface of a two-phase flow. /// </summary> /// <param name="LsTrk"></param> /// <param name="sigma"></param> public static double GetSurfaceEnergy(LevelSetTracker LsTrk, double sigma) { using (new FuncTrace()) { if (LsTrk.LevelSets.Count != 1) { throw new NotImplementedException(); } double totSurface = 0; int order = 0; if (LsTrk.GetCachedOrders().Count > 0) { order = LsTrk.GetCachedOrders().Max(); } else { order = 1; } var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, order, 1).XQuadSchemeHelper; //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, LsTrk.GetSpeciesId("A")); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, order), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { EvalResult.SetAll(1.0); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { totSurface += ResultsOfIntegration[i, 0]; } } ).Execute(); return(totSurface * sigma); } }
public static double GetInterfaceShearViscosityEnergyCR(LevelSetTracker LsTrk, ConventionalDGField[] uI, double muI, int momentFittingOrder) { double shearViscEnergy = 0.0; ScalarFunctionEx shearViscEnergyFunc = GetInterfaceShearViscosityEnergyCRFunc(LsTrk, uI, false); var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, momentFittingOrder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, momentFittingOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { shearViscEnergyFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { shearViscEnergy += ResultsOfIntegration[i, 0]; } } ).Execute(); return(muI * shearViscEnergy); }
/// <summary> /// Update Forces and Torque acting from fluid onto the particle /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="LsTrk"></param> /// <param name="muA"></param> public void UpdateForcesAndTorque(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double dt, double fluidDensity, bool NotFullyCoupled) { if (skipForceIntegration) { skipForceIntegration = false; return; } HydrodynamicForces[0][0] = 0; HydrodynamicForces[0][1] = 0; HydrodynamicTorque[0] = 0; int RequiredOrder = U[0].Basis.Degree * 3 + 2; Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); double[] Forces = new double[SpatialDim]; SinglePhaseField[] UA = U.ToArray(); ConventionalDGField pA = null; pA = P; if (IncludeTranslation) { for (int d = 0; d < SpatialDim; d++) { void ErrFunc(int CurrentCellID, int Length, NodeSet Ns, MultidimensionalArray result) { int NumberOfNodes = result.GetLength(1); MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Length, NumberOfNodes, SpatialDim, SpatialDim); MultidimensionalArray pARes = MultidimensionalArray.Create(Length, NumberOfNodes); var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, CurrentCellID, Length); for (int i = 0; i < SpatialDim; i++) { UA[i].EvaluateGradient(CurrentCellID, Length, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } pA.Evaluate(CurrentCellID, Length, Ns, pARes); for (int j = 0; j < Length; j++) { for (int k = 0; k < NumberOfNodes; k++) { result[j, k] = ForceIntegration.CalculateStressTensor(Grad_UARes, pARes, Normals, muA, k, j, this.SpatialDim, d); } } } var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, CutCells_P(LsTrk)); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, RequiredOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { Forces[d] = ParticleAuxillary.ForceTorqueSummationWithNeumaierArray(Forces[d], ResultsOfIntegration, Length); } ).Execute(); } } double Torque = 0; if (IncludeRotation) { void ErrFunc2(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, SpatialDim, SpatialDim);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < SpatialDim; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } pA.Evaluate(j0, Len, Ns, pARes); for (int j = 0; j < Len; j++) { MultidimensionalArray tempArray = Ns.CloneAs(); LsTrk.GridDat.TransformLocal2Global(Ns, tempArray, j0 + j); for (int k = 0; k < K; k++) { result[j, k] = ForceIntegration.CalculateTorqueFromStressTensor2D(Grad_UARes, pARes, Normals, tempArray, muA, k, j, Position[0]); } } } var SchemeHelper2 = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs2 = SchemeHelper2.GetLevelSetquadScheme(0, CutCells_P(LsTrk)); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs2.Compile(LsTrk.GridDat, RequiredOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc2(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { Torque = ParticleAuxillary.ForceTorqueSummationWithNeumaierArray(Torque, ResultsOfIntegration, Length); } ).Execute(); } // add gravity { Forces[1] += (particleDensity - fluidDensity) * Area_P * GravityVertical; } // Sum forces and moments over all MPI processors // ============================================== { int NoOfVars = 1 + SpatialDim; double[] StateBuffer = new double[NoOfVars]; StateBuffer[0] = Torque; for (int d = 0; d < SpatialDim; d++) { StateBuffer[1 + d] = Forces[d]; } double[] GlobalStateBuffer = StateBuffer.MPISum(); Torque = GlobalStateBuffer[0]; for (int d = 0; d < SpatialDim; d++) { Forces[d] = GlobalStateBuffer[1 + d]; } } if (neglectAddedDamping == false) { double fest = Forces[0]; Forces[0] = Forces[0] + AddedDampingCoefficient * dt * (AddedDampingTensor[0, 0] * TranslationalAcceleration[0][0] + AddedDampingTensor[1, 0] * TranslationalAcceleration[0][1] + AddedDampingTensor[0, 2] * RotationalAcceleration[0]); Forces[1] = Forces[1] + AddedDampingCoefficient * dt * (AddedDampingTensor[0, 1] * TranslationalAcceleration[0][0] + AddedDampingTensor[1, 1] * TranslationalAcceleration[0][1] + AddedDampingTensor[1, 2] * RotationalAcceleration[0]); Torque += AddedDampingCoefficient * dt * (AddedDampingTensor[2, 0] * TranslationalAcceleration[0][0] + AddedDampingTensor[2, 1] * TranslationalAcceleration[0][1] + AddedDampingTensor[2, 2] * RotationalAcceleration[0]); } if (iteration_counter_P == -1 || NotFullyCoupled || iteration_counter_P == 250 || stupidcounter == 0) { Console.WriteLine(); if (iteration_counter_P == 1) { Console.WriteLine("First iteration of the current timestep, all relaxation factors are set to 1"); } if (iteration_counter_P == 250) { Console.WriteLine("250 iterations, I'm trying to jump closer to the real solution"); } for (int d = 0; d < SpatialDim; d++) { HydrodynamicForces[0][d] = 0; if (Math.Abs(Forces[d]) < ForceAndTorque_convergence * 1e-2 && ClearSmallValues == true) { Forces[d] = 0; } HydrodynamicForces[0][d] = Forces[d]; } HydrodynamicTorque[0] = 0; if (Math.Abs(Torque) < ForceAndTorque_convergence * 1e-2 && ClearSmallValues == true) { Torque = 0; } HydrodynamicTorque[0] = Torque; stupidcounter = 1; } else { double[] RelaxatedForceAndTorque = Underrelaxation.RelaxatedForcesAndTorque(Forces, Torque, ForcesPrevIteration, TorquePrevIteration, ForceAndTorque_convergence, underrelaxation_factor, ClearSmallValues, AddaptiveUnderrelaxation, AverageDistance, iteration_counter_P); for (int d = 0; d < SpatialDim; d++) { HydrodynamicForces[0][d] = RelaxatedForceAndTorque[d]; } HydrodynamicTorque[0] = RelaxatedForceAndTorque[SpatialDim]; } //for (int d = 0; d < SpatialDim; d++)// changes sign depending on the sign of Forces[d], should increase the convergence rate. (testing needed) //{ // if (Math.Abs(HydrodynamicForces[0][d] - Forces[0]) > Math.Abs(Forces[d])) // { // HydrodynamicForces[0][d] *= -1; // } //} if (double.IsNaN(HydrodynamicForces[0][0]) || double.IsInfinity(HydrodynamicForces[0][0])) { throw new ArithmeticException("Error trying to calculate hydrodynamic forces (x). Value: " + HydrodynamicForces[0][0]); } if (double.IsNaN(HydrodynamicForces[0][1]) || double.IsInfinity(HydrodynamicForces[0][1])) { throw new ArithmeticException("Error trying to calculate hydrodynamic forces (y). Value: " + HydrodynamicForces[0][1]); } if (double.IsNaN(HydrodynamicTorque[0]) || double.IsInfinity(HydrodynamicTorque[0])) { throw new ArithmeticException("Error trying to calculate hydrodynamic torque. Value: " + HydrodynamicTorque[0]); } }
/// <summary> /// Calculates the added damping tensor by integrating over the level set of the particle. /// </summary> /// <param name="particle"> /// The current particle. /// </param> /// <param name="levelSetTracker"> /// The level set tracker. /// </param> /// <param name="fluidViscosity"></param> /// <param name="fluidDensity"></param> /// <param name="dt"></param> /// <param name="currentPosition"></param> /// <returns></returns> internal double[,] IntegrationOverLevelSet(Particle particle, LevelSetTracker levelSetTracker, double fluidViscosity, double fluidDensity, double dt, double[] currentPosition) { double[,] addedDampingTensor = new double[6, 6]; double alpha = 0.5; int RequiredOrder = 2; for (int DampingTensorID = 0; DampingTensorID < 4; DampingTensorID++) { for (int d1 = 0; d1 < 3; d1++) { for (int d2 = 0; d2 < 3; d2++) { void evalfD(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); MultidimensionalArray Normals = levelSetTracker.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); MultidimensionalArray NodeSetGlobal = Ns.CloneAs(); if (levelSetTracker.GridDat.SpatialDimension == 2) { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { levelSetTracker.GridDat.TransformLocal2Global(Ns, NodeSetGlobal, j0 + j); double dh = CalculateNormalMeshSpacing(levelSetTracker, Ns, Normals, j, k); double delta = dh * Math.Sqrt(fluidDensity) / (Math.Sqrt(alpha * fluidViscosity * dt)); double dn = dh / (1 - Math.Exp(-delta)); double[] R = new double[3]; R[0] = NodeSetGlobal[k, 0] - currentPosition[0]; R[1] = NodeSetGlobal[k, 1] - currentPosition[1]; R[2] = 0; double[] NormalComponent = new double[3]; double test = NodeSetGlobal[k, 0]; double test2 = NodeSetGlobal[k, 1]; NormalComponent[0] = Normals[j, k, 0]; NormalComponent[1] = Normals[j, k, 1]; NormalComponent[2] = 0; switch (DampingTensorID) { case 0: //D^{vv} result[j, k] = d1 == d2 ? (1 - NormalComponent[d1] * NormalComponent[d2]) * fluidViscosity / dn : -NormalComponent[d1] * NormalComponent[d2] * fluidViscosity / dn; break; case 1: //D^{vw} if (d1 == 2 && d2 != 2) { result[j, k] = R[1 - d2] * Math.Pow(-1, d2) * fluidViscosity / dn; } else if (d1 != 2 && d2 == 2) { result[j, k] = ((1 - NormalComponent[d1] * NormalComponent[d1]) * (-R[1 - d1]) - NormalComponent[d1] * NormalComponent[1 - d1] * R[d1]) * Math.Pow(-1, d1) * fluidViscosity / dn; } else { result[j, k] = 0; } break; case 2: //D^{wv} if (d2 == 2 && d1 != 2) { result[j, k] = R[1 - d1] * Math.Pow(-1, d1) * fluidViscosity / dn; } else if (d2 != 2 && d1 == 2) { result[j, k] = ((1 - NormalComponent[d2] * NormalComponent[d2]) * (-R[1 - d2]) - NormalComponent[d2] * NormalComponent[1 - d2] * R[d2]) * Math.Pow(-1, d2) * fluidViscosity / dn; } else { result[j, k] = 0; } break; case 3: //D^{ww} if (d1 == d2 && d1 != 2) { result[j, k] = R[1 - d1].Pow2() * fluidViscosity / dn; } else if (d1 != d2 && d1 != 2 && d2 != 2) { result[j, k] = -R[0] * R[1] * fluidViscosity / dn; } else if (d1 == 2 && d2 == 2) { result[j, k] = (((1 - NormalComponent[0] * NormalComponent[0]) * R[1] + NormalComponent[0] * NormalComponent[1] * R[0]) * R[1] + ((1 - NormalComponent[1] * NormalComponent[1]) * R[0] + NormalComponent[0] * NormalComponent[1] * R[1]) * R[0]) * fluidViscosity / dn; } else { result[j, k] = 0; } break; } } } } else { throw new NotImplementedException("Currently the calculation of the Damping tensors is only available for 2D"); } } var SchemeHelper = levelSetTracker.GetXDGSpaceMetrics(new[] { levelSetTracker.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, particle.CutCells_P(levelSetTracker)); CellQuadrature.GetQuadrature(new int[] { 1 }, levelSetTracker.GridDat, cqs.Compile(levelSetTracker.GridDat, RequiredOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { evalfD(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int l = 0; l < Length; l++) { switch (DampingTensorID) { case 0: addedDampingTensor[d1, d2] += ResultsOfIntegration[l, 0]; break; case 1: addedDampingTensor[d1, d2 + 3] += ResultsOfIntegration[l, 0]; break; case 2: addedDampingTensor[d1 + 3, d2] += ResultsOfIntegration[l, 0]; break; case 3: addedDampingTensor[d1 + 3, d2 + 3] += ResultsOfIntegration[l, 0]; break; } } } ).Execute(); } } } if (levelSetTracker.GridDat.SpatialDimension == 2) { return(ModifyDampingTensor2D(addedDampingTensor)); } else { throw new NotImplementedException("Currently the calculation of the Damping tensors is only available for 2D"); } }
/// <summary> /// Update forces and torque acting from fluid onto the particle /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="LsTrk"></param> /// <param name="muA"></param> public void UpdateForcesAndTorque(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA) { if (skipForceIntegration) { skipForceIntegration = false; return; } int D = LsTrk.GridDat.SpatialDimension; // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); var UA = U.ToArray(); int RequiredOrder = U[0].Basis.Degree * 3 + 2; //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max(); //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder); //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); ConventionalDGField pA = null; //pA = P.GetSpeciesShadowField("A"); pA = P; #region Force double[] forces = new double[D]; for (int d = 0; d < D; d++) { ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } pA.Evaluate(j0, Len, Ns, pARes); if (LsTrk.GridDat.SpatialDimension == 2) { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += (pARes[j, k]) * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; break; case 1: acc += (pARes[j, k]) * Normals[j, k, 1]; acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } } else { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2]; break; case 2: acc += pARes[j, k] * Normals[j, k, 2]; acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, ); //CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, this.cutCells_P(LsTrk)); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, RequiredOrder), // agg.HMForder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { forces[d] += ResultsOfIntegration[i, 0]; } } ).Execute(); } #endregion #region Torque double torque = 0; ScalarFunctionEx ErrFunc2 = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } //var trafo = LsTrk.GridDat.Edges.Edge2CellTrafos; //var trafoIdx = LsTrk.GridDat.TransformLocal2Global(Ns) //var transFormed = trafo[trafoIdx].Transform(Nodes); //var newVertices = transFormed.CloneAs(); //GridData.TransformLocal2Global(transFormed, newVertices, jCell); MultidimensionalArray tempArray = Ns.CloneAs(); LsTrk.GridDat.TransformLocal2Global(Ns, tempArray, j0); pA.Evaluate(j0, Len, Ns, pARes); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; double acc2 = 0.0; // Calculate the torque around a circular particle with a given radius (Paper Wan and Turek 2005) acc += (pARes[j, k] * Normals[j, k, 0]); acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; //acc *= -Normals[j, k, 1] * this.radius_P; acc *= -Normals[j, k, 1] * (this.currentPos_P[0][1] - tempArray[k, 1]).Abs(); acc2 += pARes[j, k] * Normals[j, k, 1]; acc2 -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; //acc2 *= Normals[j, k, 0] * this.radius_P; acc2 *= Normals[j, k, 0] * (this.currentPos_P[0][0] - tempArray[k, 0]).Abs(); result[j, k] = acc + acc2; } } }; var SchemeHelper2 = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, ); //CellQuadratureScheme cqs2 = SchemeHelper2.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadratureScheme cqs2 = SchemeHelper2.GetLevelSetquadScheme(0, this.cutCells_P(LsTrk)); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs2.Compile(LsTrk.GridDat, RequiredOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc2(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { torque += ResultsOfIntegration[i, 0]; } } ).Execute(); double underrelaxationFT = 1.0; double[] temp_underR = new double[D + 1]; for (int k = 0; k < D + 1; k++) { temp_underR[k] = underrelaxation_factor; } if (iteration_counter_P == 0) { underrelaxationFT = 1; } else if (underrelaxationFT_constant == true) { underrelaxationFT = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent); } else if (underrelaxationFT_constant == false) { //double[] temp_underR = new double[D + 1]; bool underrelaxation_ok = false; underrelaxationFT_exponent = 1; for (int j = 0; j < D; j++) { underrelaxation_ok = false; temp_underR[j] = underrelaxation_factor; for (int i = 0; underrelaxation_ok == false; i++) { if (Math.Abs(temp_underR[j] * forces[j]) > Math.Abs(forces_P[0][j])) { underrelaxationFT_exponent -= 1; temp_underR[j] = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent); } else { underrelaxation_ok = true; if (underrelaxationFT_exponent > -0) { underrelaxationFT_exponent = -0; temp_underR[j] = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent); } } } } underrelaxation_ok = false; temp_underR[D] = underrelaxation_factor; for (int i = 0; underrelaxation_ok == false; i++) { if (Math.Abs(temp_underR[D] * torque) > Math.Abs(torque_P[0])) { underrelaxationFT_exponent -= 1; temp_underR[D] = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent); } else { underrelaxation_ok = true; if (underrelaxationFT_exponent > -0) { underrelaxationFT_exponent = -0; temp_underR[D] = underrelaxation_factor * Math.Pow(10, underrelaxationFT_exponent); } } } } double[] forces_underR = new double[D]; for (int i = 0; i < D; i++) { forces_underR[i] = temp_underR[i] * forces[i] + (1 - temp_underR[i]) * forces_P[0][i]; } double torque_underR = temp_underR[D] * torque + (1 - temp_underR[D]) * torque_P[0]; this.forces_P.Insert(0, forces_underR); forces_P.Remove(forces_P.Last()); this.torque_P.Remove(torque_P.Last()); this.torque_P.Insert(0, torque_underR); #endregion }
/// <summary> /// Create Spatial Operators and build the corresponding Matrices /// </summary> public void ComputeMatrices(IList <DGField> InterfaceParams, bool nearfield) { OpMatrix = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine = new double[OpMatrix.RowPartitioning.LocalLength]; OpMatrix_bulk = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength]; OpMatrix_interface = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength]; //LevelSetTracker.GetLevelSetGradients(0,); // bulk part of the matrix //Operator_bulk.ComputeMatrix( // Extension.Mapping, // LevelSetGradient.ToArray(), // Extension.Mapping, // OpMatrix_bulk, OpAffine_bulk, // OnlyAffine: false, sgrd: null); switch (Control.FluxVariant) { case FluxVariant.GradientBased: // Flux Direction based on Mean Level Set Gradient BulkParams = new List <DGField> { }; // Hack, to make ArrayTools.Cat produce a List of DGFields // second Hack: Does only work, when InterfaceParams is according to a single component flux, // else, we will have to change the boundary edge flux BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray()); MeanLevelSetGradient.Clear(); MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient); break; case FluxVariant.ValueBased: // Flux Direction Based on Cell-Averaged Level-Set Value BulkParams = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet); MeanLevelSet.Clear(); MeanLevelSet.AccLaidBack(1.0, Phi); break; case FluxVariant.SWIP: BulkParams = LevelSetGradient.ToArray(); break; default: throw new Exception(); } // Build Operator Operator_bulk.ComputeMatrixEx(Extension.Mapping, BulkParams, Extension.Mapping, OpMatrix_bulk, OpAffine_bulk, OnlyAffine: false, time: 0.0, edgeQuadScheme: new EdgeQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).InnerEdgesMask : null), volQuadScheme: new CellQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).VolumeMask : null) ); Operator_interface.ComputeMatrixEx( LevelSetTracker, Extension.Mapping, InterfaceParams, Extension.Mapping, OpMatrix_interface, OpAffine_interface, OnlyAffine: false, time: 0, MPIParameterExchange: false, whichSpc: LevelSetTracker.GetSpeciesId("A") ); #if DEBUG OpMatrix_bulk.CheckForNanOrInfM(); OpAffine_bulk.CheckForNanOrInfV(); OpMatrix_interface.CheckForNanOrInfM(); OpAffine_interface.CheckForNanOrInfV(); #endif //Only for Debugging purposes //OpMatrix.SaveToTextFileSparse("C:\\tmp\\EllipticReInit.txt"); Debug.Assert(OpMatrix_interface.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of InterfaceOperator is 0"); Debug.Assert(OpMatrix_bulk.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of BulkOperator is 0"); #if DEBUG //Console.WriteLine( "L2-Norm of Diagonal of InterfaceOperator is {0}", OpMatrix_interface.GetDiagVector().L2Norm() ); #endif OpMatrix.Clear(); OpMatrix.Acc(1.0, OpMatrix_bulk); OpMatrix.Acc(1.0, OpMatrix_interface); //Console.WriteLine("Op-Matrix Symmetry-Deviation: {0}", OpMatrix.SymmetryDeviation()); OpMatrix.AssumeSymmetric = false; OpAffine.Clear(); OpAffine.AccV(1.0, OpAffine_bulk); OpAffine.AccV(1.0, OpAffine_interface); #if DEBUG //Console.WriteLine("Condition Number of Extension Operator {0}", OpMatrix.condest()); #endif }
/// <summary> /// Create Spatial Operators and build the corresponding Matrices /// </summary> public void ComputeMatrices(IList <DGField> InterfaceParams, bool nearfield) { OpMatrix = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine = new double[OpMatrix.RowPartitioning.LocalLength]; OpMatrix_bulk = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength]; OpMatrix_interface = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength]; //LevelSetTracker.GetLevelSetGradients(0,); // bulk part of the matrix //Operator_bulk.ComputeMatrix( // Extension.Mapping, // LevelSetGradient.ToArray(), // Extension.Mapping, // OpMatrix_bulk, OpAffine_bulk, // OnlyAffine: false, sgrd: null); switch (Control.FluxVariant) { case FluxVariant.GradientBased: // Flux Direction based on Mean Level Set Gradient BulkParams = new List <DGField> { }; // Hack, to make ArrayTools.Cat produce a List of DGFields // second Hack: Does only work, when InterfaceParams is according to a single component flux, // else, we will have to change the boundary edge flux BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray()); MeanLevelSetGradient.Clear(); MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient); break; case FluxVariant.ValueBased: // Flux Direction Based on Cell-Averaged Level-Set Value BulkParams = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet); MeanLevelSet.Clear(); MeanLevelSet.AccLaidBack(1.0, Phi); break; case FluxVariant.SWIP: BulkParams = LevelSetGradient.ToArray(); break; default: throw new Exception(); } // Build Operator Operator_bulk.ComputeMatrixEx(Extension.Mapping, BulkParams, Extension.Mapping, OpMatrix_bulk, OpAffine_bulk, OnlyAffine: false, time: 0.0, edgeQuadScheme: new EdgeQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).InnerEdgesMask : null), volQuadScheme: new CellQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).VolumeMask : null) ); //Operator_interface.ComputeMatrixEx( // LevelSetTracker, // Extension.Mapping, // InterfaceParams, // Extension.Mapping, // OpMatrix_interface, // OpAffine_interface, // OnlyAffine: false, // time: 0, // MPIParameterExchange: false, // whichSpc: LevelSetTracker.GetSpeciesId("A") // ); Operator_interface.OperatorCoefficientsProvider = delegate(LevelSetTracker lstrk, SpeciesId spc, int quadOrder, int TrackerHistoryIdx, double time) { var r = new CoefficientSet() { }; //throw new NotImplementedException("todo"); return(r); }; XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker, Extension.Mapping, InterfaceParams, Extension.Mapping); MultiphaseCellAgglomerator dummy = LevelSetTracker.GetAgglomerator(LevelSetTracker.SpeciesIdS.ToArray(), 2 * Extension.Basis.Degree + 2, 0.0); mtxBuilder.CellLengthScales.Add(LevelSetTracker.GetSpeciesId("A"), dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]); mtxBuilder.time = 0; mtxBuilder.MPITtransceive = false; mtxBuilder.ComputeMatrix(OpMatrix_interface, OpAffine_interface); #if DEBUG OpMatrix_bulk.CheckForNanOrInfM(); OpAffine_bulk.CheckForNanOrInfV(); OpMatrix_interface.CheckForNanOrInfM(); OpAffine_interface.CheckForNanOrInfV(); #endif //Only for Debugging purposes Debug.Assert(OpMatrix_interface.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of InterfaceOperator is 0"); Debug.Assert(OpMatrix_bulk.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of BulkOperator is 0"); #if DEBUG //Console.WriteLine( "L2-Norm of Diagonal of InterfaceOperator is {0}", OpMatrix_interface.GetDiagVector().L2Norm() ); #endif OpMatrix.Clear(); OpMatrix.Acc(1.0, OpMatrix_bulk); OpMatrix.Acc(1.0, OpMatrix_interface); //Console.WriteLine("Op-Matrix Symmetry-Deviation: {0}", OpMatrix.SymmetryDeviation()); OpMatrix.AssumeSymmetric = false; OpAffine.Clear(); OpAffine.AccV(1.0, OpAffine_bulk); OpAffine.AccV(1.0, OpAffine_interface); #if DEBUG //Console.WriteLine("Condition Number of Extension Operator {0}", OpMatrix.condest()); #endif }
static public double[] GetParticleForces(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA) { int D = LsTrk.GridDat.SpatialDimension; // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); var UA = U.ToArray(); int RequiredOrder = U[0].Basis.Degree * 3 + 2; //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max(); //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder); //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); ConventionalDGField pA = null; //pA = P.GetSpeciesShadowField("A"); pA = P; double[] forces = new double[D]; for (int d = 0; d < D; d++) { ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } pA.Evaluate(j0, Len, Ns, pARes); if (LsTrk.GridDat.SpatialDimension == 2) { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } } else { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2]; break; case 2: acc += pARes[j, k] * Normals[j, k, 2]; acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, ); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, RequiredOrder), // agg.HMForder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { forces[d] += ResultsOfIntegration[i, 0]; } } ).Execute(); } for (int i = 0; i < D; i++) { forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]); } return(forces); }
/// <summary> /// Calculates the Torque around the center of mass /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="muA"></param> /// <param name="particleRadius"></param> /// <returns></returns> static public double GetTorque(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double particleRadius) { var _LsTrk = LsTrk; int D = _LsTrk.GridDat.SpatialDimension; var UA = U.ToArray(); //if (D > 2) throw new NotImplementedException("Currently only 2D cases supported"); int RequiredOrder = U[0].Basis.Degree * 3; //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Torque coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); ConventionalDGField pA = null; double force = new double(); pA = P; ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = _LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } pA.Evaluate(j0, Len, Ns, pARes); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; double acc2 = 0.0; // Calculate the torque around a circular particle with a given radius (Paper Wan and Turek 2005) acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; acc *= -Normals[j, k, 1] * particleRadius; acc2 += pARes[j, k] * Normals[j, k, 1]; acc2 -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; acc2 *= Normals[j, k, 0] * particleRadius; result[j, k] = acc + acc2; } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //var SchemeHelper = new XQuadSchemeHelper(_LsTrk, momentFittingVariant, _LsTrk.GetSpeciesId("A")); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, _LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, _LsTrk.GridDat, cqs.Compile(_LsTrk.GridDat, RequiredOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { force += ResultsOfIntegration[i, 0]; } } ).Execute(); return(force); }
void SpecialProjection(LevelSetTracker LsTrk, int order, DGField[] Uin, VectorField <SinglePhaseField> Uout) { var CC = LsTrk.Regions.GetCutCellMask(); var gDat = LsTrk.GridDat; // get quadrature rules // ==================== //XQuadSchemeHelper H = new XQuadSchemeHelper(LsTrk, MomentFittingVariant); var H = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, order, 1).XQuadSchemeHelper; CellQuadratureScheme cqs = H.GetLevelSetquadScheme(0, CC); ICompositeQuadRule <QuadRule> surfRule = cqs.Compile(gDat, order); ICompositeQuadRule <CellBoundaryQuadRule> bndyRule = (new CellBoundaryQuadratureScheme(true, CC)).Compile(gDat, order); // Compute Mass matrix and RHS for the 'strange' projection // ======================================================== int L = CC.NoOfItemsLocally; var Q = new QuadratureKernels(Uin, L); Q.BlockCnt = 0; CellQuadrature.GetQuadrature( new int[] { Q.Nnx + Q.D, Q.Nnx }, gDat, surfRule, Q.Evaluate, Q.SaveIntegrationResults_surf).Execute(); Debug.Assert(Q.BlockCnt == L); Q.BlockCnt = 0; CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature( new int[] { Q.Nnx + Q.D, Q.Nnx }, gDat, bndyRule, Q.Evaluate, Q.SaveIntegrationResults_bndy).Execute(); Debug.Assert(Q.BlockCnt == L); // solve the non-diagonal mass matrix systems // ========================================== int BlkCnt = 0; foreach (int jCell in CC.ItemEnum) { var MassMatrix = Q.MassMatrix.ExtractSubArrayShallow(BlkCnt, -1, -1); var RHS = Q.RHS.ExtractSubArrayShallow(BlkCnt, -1, -1); // Die "Massenmatrix" muss nicht unbedingt invbar sein, daher: Least-Squares solve MassMatrix.LeastSquareSolve(RHS); for (int d = 0; d < Q.D; d++) { for (int n = 0; n < Q.Nnx; n++) { Uout[d].Coordinates[jCell, n] = RHS[n, d]; } } BlkCnt++; } }
/// <summary> /// Calculates the drag (x-component) and lift (y-component) forces acting on a wall of a boundary fitted grid /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="muA"></param> /// <returns></returns> static public double[] GetForces_BoundaryFitted(VectorField <SinglePhaseField> GradU, VectorField <SinglePhaseField> GradV, SinglePhaseField StressXX, SinglePhaseField StressXY, SinglePhaseField StressYY, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double beta) { int D = LsTrk.GridDat.SpatialDimension; if (D > 2) { throw new ArgumentException("Method GetForces_BoundaryFitted only implemented for 2D (viscoelastic)!"); } // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); //var UA = U.ToArray(); MultidimensionalArray Grad_U = new MultidimensionalArray(D); var _GradU = GradU.ToArray(); var _GradV = GradV.ToArray(); int RequiredOrder = _GradU[0].Basis.Degree * 3 + 2; //int RequiredOrder = U[0].Basis.Degree * 3 + 2; //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max(); //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder); //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); SinglePhaseField _StressXX = StressXX; SinglePhaseField _StressXY = StressXY; SinglePhaseField _StressYY = StressYY; SinglePhaseField pA = null; //pA = P.GetSpeciesShadowField("A"); pA = P; double[] forces = new double[D]; for (int d = 0; d < D; d++) { ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_URes = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray Grad_VRes = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressXXRes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressXYRes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressYYRes = MultidimensionalArray.Create(Len, K); var Normals = LsTrk.GridDat.Edges.NormalsCache.GetNormals_Edge(Ns, j0, Len); //var Normals = MultidimensionalArray.Create(1, Ns.Length, 1); //var Normals = LsTrk.GridDat.Edges.NormalsForAffine; for (int i = 0; i < D; i++) { _GradU[i].EvaluateEdge(j0, Len, Ns, Grad_URes.ExtractSubArrayShallow(-1, -1, i), Grad_URes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1); _GradV[i].EvaluateEdge(j0, Len, Ns, Grad_VRes.ExtractSubArrayShallow(-1, -1, i), Grad_VRes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1); //UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } //pA.Evaluate(j0, Len, Ns, pARes); pA.EvaluateEdge(j0, Len, Ns, pARes, pARes, ResultIndexOffset: 0, ResultPreScale: 1); _StressXX.EvaluateEdge(j0, Len, Ns, StressXXRes, StressXXRes, ResultIndexOffset: 0, ResultPreScale: 1); _StressXY.EvaluateEdge(j0, Len, Ns, StressXYRes, StressXYRes, ResultIndexOffset: 0, ResultPreScale: 1); _StressYY.EvaluateEdge(j0, Len, Ns, StressYYRes, StressYYRes, ResultIndexOffset: 0, ResultPreScale: 1); //if (LsTrk.GridDat.SpatialDimension == 2) //{ for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA * beta) * Grad_URes[j, k, 0] * Normals[j, k, 0]; acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 1]; acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 1]; acc -= (muA * (1 - beta)) * StressXXRes[j, k] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 1]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA * beta) * Grad_VRes[j, k, 1] * Normals[j, k, 1]; acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 0]; acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressXYRes[j, k] * Normals[j, k, 0]; acc -= (muA * (1 - beta)) * StressYYRes[j, k] * Normals[j, k, 1]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } //} //else //{ // for (int j = 0; j < Len; j++) // { // for (int k = 0; k < K; k++) // { // double acc = 0.0; // // pressure // switch (d) // { // case 0: // acc += pARes[j, k] * Normals[j, k, 0]; // acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2]; // break; // case 1: // acc += pARes[j, k] * Normals[j, k, 1]; // acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2]; // break; // case 2: // acc += pARes[j, k] * Normals[j, k, 2]; // acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2]; // acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1]; // acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0]; // acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1]; // break; // default: // throw new NotImplementedException(); // } // result[j, k] = acc; //} //} //} }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; EdgeMask Mask = new EdgeMask(LsTrk.GridDat, "Wall_cylinder"); EdgeQuadratureScheme eqs = SchemeHelper.GetEdgeQuadScheme(LsTrk.GetSpeciesId("A"), IntegrationDomain: Mask); EdgeQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, eqs.Compile(LsTrk.GridDat, RequiredOrder), // agg.HMForder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { forces[d] += ResultsOfIntegration[i, 0]; } } ).Execute(); } //for (int i = 0; i < D; i++) // forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]); return(forces); }
// Local Variables for Iteration // <summary> // Counter for Iteration Steps // </summary> //double OldResidual = double.MaxValue; //int divergencecounter = 0; ///// <summary> ///// Checks for Reaching Max. Number of Iterations and Divergence of Algorithm ///// </summary> ///// <param name="Residual">Change Rate of the Algorithm</param> ///// <returns>Reaching Max Iterations, Aborts when diverged</returns> //public bool CheckAbortCriteria(double Residual, int IterationCounter) { // if (Residual <= ConvergenceCriterion) { // Console.WriteLine("EllipticReInit converged after {0} Iterations ", IterationCounter); // return true; // } // if (Residual >= OldResidual) divergencecounter++; // else divergencecounter = 0; // if (IterationCounter >= MaxIteration) { // Console.WriteLine("Elliptic Reinit Max Iterations Reached"); // return true; // }; // if (divergencecounter > MaxIteration / 2) { // Console.WriteLine("Elliptic Reinit diverged - Aborting"); // throw new ApplicationException(); // } // OldResidual = Residual; // IterationCounter++; // return false; //} //bool PreviouslyOnSubgrid = false; /// <summary> /// Updates the Operator Matrix after level-set motion /// </summary> /// <param name="Restriction"> /// The subgrid, on which the ReInit is performed /// </param> /// <param name="IncludingInterface"> /// !! Not yet functional !! /// True, if the subgrid contains the interface, this causes all external edges of the subgrid to be treated as boundaries /// False, for the rest of the domain, thus the flux to the adjacent cells wil be evaluated /// </param> public void UpdateOperators(SubGrid Restriction = null, bool IncludingInterface = true) { if (!IncludingInterface) { throw new NotImplementedException("Untested, not yet functional!"); } using (new FuncTrace()) { //using (var slv = new ilPSP.LinSolvers.MUMPS.MUMPSSolver()) { //using (var slv = new ilPSP.LinSolvers.PARDISO.PARDISOSolver()) { //using (var slv = new ilPSP.LinSolvers.HYPRE.GMRES()) { if (Control.Upwinding) { OldPhi.Clear(); OldPhi.Acc(1.0, Phi); //Calculate LevelSetGradient.Clear(); LevelSetGradient.Gradient(1.0, Phi, Restriction?.VolumeMask); //LevelSetGradient.Gradient(1.0, Phi); //LevelSetGradient.GradientByFlux(1.0, Phi); MeanLevelSetGradient.Clear(); MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient, Restriction?.VolumeMask); //MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient); } if (slv != null) { slv.Dispose(); } slv = Control.solverFactory(); OpMatrix_interface.Clear(); OpAffine_interface.Clear(); // Build the Quadrature-Scheme for the interface operator // Note: The HMF-Quadrature over a surface is formally a volume quadrature, since it uses the volume quadrature nodes. //XSpatialOperatorExtensions.ComputeMatrixEx(Operator_interface, ////Operator_interface.ComputeMatrixEx( // LevelSetTracker, // Phi.Mapping, // null, // Phi.Mapping, // OpMatrix_interface, // OpAffine_interface, // false, // 0, // false, // subGrid:Restriction, // whichSpc: LevelSetTracker.GetSpeciesId("A") // ); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker, Phi.Mapping, null, Phi.Mapping); MultiphaseCellAgglomerator dummy = LevelSetTracker.GetAgglomerator(LevelSetTracker.SpeciesIdS.ToArray(), Phi.Basis.Degree * 2 + 2, 0.0); //mtxBuilder.SpeciesOperatorCoefficients[LevelSetTracker.GetSpeciesId("A")].CellLengthScales = dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]; mtxBuilder.CellLengthScales.Add(LevelSetTracker.GetSpeciesId("A"), dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]); mtxBuilder.time = 0; mtxBuilder.MPITtransceive = false; mtxBuilder.ComputeMatrix(OpMatrix_interface, OpAffine_interface); // Regenerate OpMatrix for subgrid -> adjacent cells must be trated as boundary if (Restriction != null) { OpMatrix_bulk.Clear(); OpAffine_bulk.Clear(); //Operator_bulk.ComputeMatrix( // Phi.Mapping, // parameterFields, // Phi.Mapping, // OpMatrix_bulk, OpAffine_bulk, // OnlyAffine: false, sgrd: Restriction); EdgeQuadratureScheme edgescheme; //if (Control.Upwinding) { // edgescheme = new EdgeQuadratureScheme(true, IncludingInterface ? Restriction.AllEdgesMask : null); //} //else { edgescheme = new EdgeQuadratureScheme(true, IncludingInterface ? Restriction.InnerEdgesMask : null); //} Operator_bulk.ComputeMatrixEx(Phi.Mapping, parameterFields, Phi.Mapping, OpMatrix_bulk, OpAffine_bulk, false, 0, edgeQuadScheme: edgescheme, volQuadScheme: new CellQuadratureScheme(true, IncludingInterface ? Restriction.VolumeMask : null) ); //PreviouslyOnSubgrid = true; } // recalculate full Matrix //else if (PreviouslyOnSubgrid) { else { OpMatrix_bulk.Clear(); OpAffine_bulk.Clear(); Operator_bulk.ComputeMatrixEx(Phi.Mapping, parameterFields, Phi.Mapping, OpMatrix_bulk, OpAffine_bulk, false, 0 ); //PreviouslyOnSubgrid = false; } /// Compose the Matrix /// This is symmetric due to the symmetry of the SIP and the penalty term OpMatrix.Clear(); OpMatrix.Acc(1.0, OpMatrix_bulk); OpMatrix.Acc(1.0, OpMatrix_interface); OpMatrix.AssumeSymmetric = !Control.Upwinding; //OpMatrix.AssumeSymmetric = false; /// Compose the RHS of the above operators. (-> Boundary Conditions) /// This does NOT include the Nonlinear RHS, which will be added later OpAffine.Clear(); OpAffine.AccV(1.0, OpAffine_bulk); OpAffine.AccV(1.0, OpAffine_interface); #if Debug ilPSP.Connectors.Matlab.BatchmodeConnector matlabConnector; matlabConnector = new BatchmodeConnector(); #endif if (Restriction != null) { SubVecIdx = Phi.Mapping.GetSubvectorIndices(Restriction, true, new int[] { 0 }); int L = SubVecIdx.Length; SubMatrix = new MsrMatrix(L); SubRHS = new double[L]; SubSolution = new double[L]; OpMatrix.AccSubMatrixTo(1.0, SubMatrix, SubVecIdx, default(int[]), SubVecIdx, default(int[])); slv.DefineMatrix(SubMatrix); #if Debug Console.WriteLine("ConditionNumber of ReInit-Matrix is " + SubMatrix.condest().ToString("E")); #endif } else { slv.DefineMatrix(OpMatrix); #if Debug Console.WriteLine("ConditionNumber of ReInit-Matrix is " + OpMatrix.condest().ToString("E")); #endif } } }