public static void ComputeAverageU <T>(IEnumerable <T> U0, VectorField <XDGField> U0mean, int order, XQuadSchemeHelper qh, LevelSetTracker LsTrk) where T : DGField { using (FuncTrace ft = new FuncTrace()) { var CC = LsTrk.Regions.GetCutCellMask(); int D = LsTrk.GridDat.SpatialDimension; double minvol = Math.Pow(LsTrk.GridDat.Cells.h_minGlobal, D); //var qh = new XQuadSchemeHelper(agg); foreach (var Spc in LsTrk.SpeciesIdS) // loop over species... //var Spc = this.LsTrk.GetSpeciesId("B"); { // shadow fields { DGField[] U0_Spc = U0.Select(U0_d => (U0_d is XDGField) ? ((DGField)((U0_d as XDGField).GetSpeciesShadowField(Spc))) : ((DGField)U0_d)).ToArray(); var U0mean_Spc = U0mean.Select(U0mean_d => U0mean_d.GetSpeciesShadowField(Spc)).ToArray(); // normal cells: for (int d = 0; d < D; d++) { U0mean_Spc[d].AccLaidBack(1.0, U0_Spc[d], LsTrk.Regions.GetSpeciesMask(Spc)); } // cut cells var scheme = qh.GetVolumeQuadScheme(Spc, IntegrationDomain: LsTrk.Regions.GetCutCellMask()); var rule = scheme.Compile(LsTrk.GridDat, order); CellQuadrature.GetQuadrature(new int[] { D + 1 }, // vector components: ( avg_vel[0], ... , avg_vel[D-1], cell_volume ) LsTrk.GridDat, rule, delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { EvalResult.Clear(); for (int d = 0; d < D; d++) { U0_Spc[d].Evaluate(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, d)); } var Vol = EvalResult.ExtractSubArrayShallow(-1, -1, D); Vol.SetAll(1.0); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { int jCell = i + i0; double Volume = ResultsOfIntegration[i, D]; if (Math.Abs(Volume) < minvol * 1.0e-12) { // keep current value // since the volume of species 'Spc' in cell 'jCell' is 0.0, the value in this cell should have no effect } else { for (int d = 0; d < D; d++) { double IntVal = ResultsOfIntegration[i, d]; U0mean_Spc[d].SetMeanValue(jCell, IntVal / Volume); } } } }).Execute(); } #if DEBUG { var Uncut = LsTrk.Regions.GetCutCellMask().Complement(); VectorField <SinglePhaseField> U0mean_check = new VectorField <SinglePhaseField>(D, new Basis(LsTrk.GridDat, 0), SinglePhaseField.Factory); for (int d = 0; d < D; d++) { U0mean_check[d].ProjectField(1.0, U0.ElementAt(d).Evaluate, new CellQuadratureScheme(false, Uncut).AddFixedOrderRules(LsTrk.GridDat, U0.ElementAt(d).Basis.Degree + 1)); } foreach (var _Spc in LsTrk.SpeciesIdS) // loop over species... { for (int d = 0; d < D; d++) { U0mean_check[d].AccLaidBack(-1.0, U0mean[d].GetSpeciesShadowField(_Spc), Uncut.Intersect(LsTrk.Regions.GetSpeciesMask(_Spc))); } } double checkNorm = U0mean_check.L2Norm(); Debug.Assert(checkNorm < 1.0e-6); } #endif U0mean.ForEach(F => F.CheckForNanOrInf(true, true, true)); } }
public XOptimizedLaplacianArtificialViscosityFlux_Interface(LevelSetTracker levelSetTracker, string ArgumentVarName, double penaltySafetyFactor, double penaltyFactor, Dictionary <SpeciesId, MultidimensionalArray> inverseLengthScales) { this.levelSetTracker = levelSetTracker; this.ArgumentOrdering = new string[] { ArgumentVarName }; this.bulkFlux = new XOptimizedLaplacianArtificialViscosityFlux(null, levelSetTracker, ArgumentVarName, penaltySafetyFactor, penaltyFactor, inverseLengthScales); }
public TransportFlux_Interface(LevelSetTracker lstrk, Func <double[], double, double> NormalVel) { m_LsTrk = lstrk; m_NormalVel = NormalVel; }
public EllipticReInitInterfaceForm(double PenaltyBase, LevelSetTracker LSTrk) { this.PenaltyBase = PenaltyBase; this.LSTrk = LSTrk; }
public LevSetFlx_phi0(LevelSetTracker _LsTrk) : base(_LsTrk) { }
//IDictionary<SpeciesId, IEnumerable<double>> Rho { // get { // int D = this.LsTrk.GridDat.SpatialDimension; // double rho_A = 0, rho_B = 0; // this.m_SIMPLEOptions.Control.confSolver.GetExtProperty("rho_A", true, ref rho_A); // this.m_SIMPLEOptions.Control.confSolver.GetExtProperty("rho_B", true, ref rho_B); // double[] _rho_A = new double[D]; // _rho_A.SetAll(rho_A); // double[] _rho_B = new double[D]; // _rho_B.SetAll(rho_B); // Dictionary<SpeciesId, IEnumerable<double>> R = new Dictionary<SpeciesId, IEnumerable<double>>(); // R.Add(this.LsTrk.GetSpeciesId("A"), _rho_A); // R.Add(this.LsTrk.GetSpeciesId("B"), _rho_B); // return R; // } //} public SIMPLE(LevelSetTracker _LsTrk) { this.LsTrk = _LsTrk; }
internal ParticleHydrodynamics(LevelSetTracker lsTrk) { m_LsTrk = lsTrk; }
public HeatFluxAtLevelSet(int _D, LevelSetTracker _LsTrk, ThermalParameters thermParams, double _sigma) : base(_D, _LsTrk, thermParams, _sigma) { }
/// <summary> /// ctor /// </summary> public CentralDifferencesRHSForm(double PenaltyBase, LevelSetTracker LSTrck) : base(PenaltyBase, LSTrck) { }
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 drag (x-component) and lift (y-component) forces acting on a cylinder wall of a boundary fitted grid. The definition of the wall is HARDCODED! /// </summary> 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(); 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) * StressXXRes[j, k] * Normals[j, k, 0]; acc -= (muA) * 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) * StressXYRes[j, k] * Normals[j, k, 0]; acc -= (muA) * StressYYRes[j, k] * 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_bottom"); 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); }
/// <summary> /// modifies a matrix <paramref name="Mtx"/> and a right-hand-side <paramref name="rhs"/> /// in order to fix the pressure at some reference point /// </summary> /// <param name="map">row mapping for <paramref name="Mtx"/> as well as <paramref name="rhs"/></param> /// <param name="iVar">the index of the pressure variable in the mapping <paramref name="map"/>.</param> /// <param name="LsTrk"></param> /// <param name="Mtx"></param> /// <param name="rhs"></param> static public void SetPressureReferencePoint <T>(UnsetteledCoordinateMapping map, int iVar, LevelSetTracker LsTrk, IMutableMatrixEx Mtx, T rhs) where T : IList <double> { using (new FuncTrace()) { var GridDat = map.GridDat; if (rhs.Count != map.LocalLength) { throw new ArgumentException(); } if (!Mtx.RowPartitioning.EqualsPartition(map) || !Mtx.ColPartition.EqualsPartition(map)) { throw new ArgumentException(); } Basis PressureBasis = (Basis)map.BasisS[iVar]; int D = GridDat.SpatialDimension; long GlobalID, GlobalCellIndex; bool IsInside, onthisProc; GridDat.LocatePoint(new double[D], out GlobalID, out GlobalCellIndex, out IsInside, out onthisProc, LsTrk != null ? LsTrk.Regions.GetCutCellSubGrid().VolumeMask.Complement() : null); int iRowGl = -111; if (onthisProc) { //int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; //NodeSet CenterNode = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell), new double[D]); //MultidimensionalArray LevSetValues = LsTrk.DataHistories[0].Current.GetLevSetValues(CenterNode, jCell, 1); ; //MultidimensionalArray CenterNodeGlobal = MultidimensionalArray.Create(1, D); //GridDat.TransformLocal2Global(CenterNode, CenterNodeGlobal, jCell); //Console.WriteLine("Pressure Ref Point @( {0:0.###E-00} | {1:0.###E-00} )", CenterNodeGlobal[0,0], CenterNodeGlobal[0,1]); //LevelSetSignCode scode = LevelSetSignCode.ComputeLevelSetBytecode(LevSetValues[0, 0]); //ReducedRegionCode rrc; //int No = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); //int iSpc = LsTrk.GetSpeciesIndex(rrc, scode); iRowGl = (int)map.GlobalUniqueCoordinateIndex_FromGlobal(iVar, GlobalCellIndex, 0); } iRowGl = iRowGl.MPIMax(); // clear row // --------- if (onthisProc) { // ref. cell is on local MPI process int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; //ReducedRegionCode rrc; //int NoOfSpc = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); // set matrix row to identity Mtx.ClearRow(iRowGl); Mtx.SetDiagonalElement(iRowGl, 1.0); // clear RHS int iRow = iRowGl - Mtx.RowPartitioning.i0; rhs[iRow] = 0; } // clear column // ------------ { for (int i = Mtx.RowPartitioning.i0; i < Mtx.RowPartitioning.iE; i++) { if (i != iRowGl) { Mtx[i, iRowGl] = 0; } } } } }
/// <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); }
/// <summary> /// modifies a residual (i.e. an operator evaluation) /// in order to fix the pressure at some reference point /// </summary> /// <param name="currentState">current state of velocity & pressure</param> /// <param name="iVar">the index of the pressure variable in the mapping <paramref name="map"/>.</param> /// <param name="LsTrk"></param> /// <param name="Residual"></param> static public void SetPressureReferencePointResidual <T>(CoordinateVector currentState, int iVar, LevelSetTracker LsTrk, T Residual) where T : IList <double> { using (new FuncTrace()) { var map = currentState.Mapping; var GridDat = map.GridDat; if (Residual.Count != map.LocalLength) { throw new ArgumentException(); } Basis PressureBasis = (Basis)map.BasisS[iVar]; int D = GridDat.SpatialDimension; long GlobalID, GlobalCellIndex; bool IsInside, onthisProc; GridDat.LocatePoint(new double[D], out GlobalID, out GlobalCellIndex, out IsInside, out onthisProc, LsTrk.Regions.GetCutCellSubGrid().VolumeMask.Complement()); int iRowGl = -111; if (onthisProc) { int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; NodeSet CenterNode = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell), new double[D]); MultidimensionalArray LevSetValues = LsTrk.DataHistories[0].Current.GetLevSetValues(CenterNode, jCell, 1);; MultidimensionalArray CenterNodeGlobal = MultidimensionalArray.Create(1, D); GridDat.TransformLocal2Global(CenterNode, CenterNodeGlobal, jCell); //Console.WriteLine("Pressure Ref Point @( {0:0.###E-00} | {1:0.###E-00} )", CenterNodeGlobal[0,0], CenterNodeGlobal[0,1]); LevelSetSignCode scode = LevelSetSignCode.ComputeLevelSetBytecode(LevSetValues[0, 0]); ReducedRegionCode rrc; int No = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); int iSpc = LsTrk.GetSpeciesIndex(rrc, scode); iRowGl = (int)map.GlobalUniqueCoordinateIndex_FromGlobal(iVar, GlobalCellIndex, 0); } iRowGl = iRowGl.MPIMax(); // clear row // --------- if (onthisProc) { // set entry in residual vector equal to corresponding value in domain vector // (as if the corresponding matrix would have a 1 in the diagonal element and 0 everywhere else) int iRow = iRowGl - map.i0; Residual[iRow] = currentState[iRow]; } } }
public PotentialSolverPrecond(LevelSetTracker _LsTrk) { this.LsTrk = _LsTrk; }
/// <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.SpeciesNames); // 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, out U0meanrequired); //constitutive eq at interfeac if (config.isContinuity) { XOperatorComponentsFactory.AddInterfaceContinuityEq(m_XOp, config, this.D, LsTrk); // continuity equation } m_XOp.Commit(); }
public ParticleHydrodynamicsIntegration(int spatialDim, VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker levelSetTracker, CellMask cutCells, double fluidViscosity) { m_SpatialDim = spatialDim; m_RequiredOrder = U[0].Basis.Degree * 3 + 2; m_U = U.ToArray(); m_P = P; m_LevelSetTracker = levelSetTracker; m_GridData = m_LevelSetTracker.GridDat; m_CutCells = cutCells; m_FluidViscosity = fluidViscosity; }
public LinearReconstructionQuadRuleFactory(LevelSetTracker tracker, LineAndPointQuadratureFactory lineAndPointFactory) { this.tracker = tracker; this.rootFactory = lineAndPointFactory.GetPointFactory(); }
public ConvectionInBulk_Localized(int SpatDim, IncompressibleMultiphaseBoundaryCondMap _bcmap, int _component, double _rhoA, double _rhoB, double _LFFA, double _LFFB, LevelSetTracker _lsTrk) : base(SpatDim, _bcmap, _component, _rhoA, _rhoB, _LFFA, _LFFB, _lsTrk) { }
/// <summary> /// Backup data for some DG field before update of grid. /// </summary> /// <param name="f"></param> /// <param name="Reference"> /// Unique string reference under which the re-distributed data can be accessed later, within <see cref="RestoreDGField(DGField, string)"/>. /// </param> override public void BackupField(DGField f, string Reference) { if (!object.ReferenceEquals(f.GridDat, m_OldGrid)) { throw new ArgumentException("DG field seems to be assigned to some other grid."); } double[][] oldFieldsData = new double[m_oldJ][]; m_oldDGFieldData.Add(Reference, oldFieldsData); if (f is ConventionalDGField) { Basis oldBasis = f.Basis; int Nj = oldBasis.Length; for (int j = 0; j < m_oldJ; j++) { double[] data_j = new double[Nj]; for (int n = 0; n < Nj; n++) { data_j[n] = f.Coordinates[j, n]; } FwdTrafo(data_j, Nj, 0, (GridData)m_OldGrid, j, f.Basis.Degree); oldFieldsData[j] = data_j; } } else if (f is XDGField) { XDGField xf = f as XDGField; XDGBasis xb = xf.Basis; int Np = xb.NonX_Basis.Length; if (!object.ReferenceEquals(m_OldTracker, xb.Tracker)) { throw new ArgumentException("LevelSetTracker seems duplicate, or something."); } LevelSetTracker lsTrk = m_OldTracker; for (int j = 0; j < m_oldJ; j++) { int NoOfSpc = lsTrk.Regions.GetNoOfSpecies(j); int Nj = xb.GetLength(j); Debug.Assert(Nj == NoOfSpc * Np); double[] data_j = new double[Nj + NoOfSpc + 1]; data_j[0] = NoOfSpc; int c = 1; for (int iSpc = 0; iSpc < NoOfSpc; iSpc++) // loop over species { SpeciesId spc = lsTrk.Regions.GetSpeciesIdFromIndex(j, iSpc); data_j[c] = spc.cntnt; c++; for (int n = 0; n < Np; n++) { data_j[c] = f.Coordinates[j, n + Np * iSpc]; c++; } FwdTrafo(data_j, Np, (Np + 1) * iSpc + 2, (GridData)m_OldGrid, j, f.Basis.Degree); } Debug.Assert(data_j.Length == c); oldFieldsData[j] = data_j; } } else { throw new NotSupportedException(); } }
public HeatConvectionInBulk(int SpatDim, ThermalMultiphaseBoundaryCondMap _bcmap, double _capA, double _capB, double _LFFA, double _LFFB, LevelSetTracker _lsTrk) : base(SpatDim, _bcmap) { capA = _capA; capB = _capB; //varMode = _varMode; this.lsTrk = _lsTrk; this.LFFA = _LFFA; this.LFFB = _LFFB; this.m_bcmap = _bcmap; //base.VelFunction = null; base.TempFunction = null; }
/// <summary> /// Loads the DG coordinates after grid adaptation. /// </summary> /// <param name="f"></param> /// <param name="Reference"> /// Unique string reference under which data has been stored before grid-redistribution. /// </param> public override void RestoreDGField(DGField f, string Reference) { using (new FuncTrace()) { //if(f.Identification == "TestData") { // Console.WriteLine("using oasch"); // Oasch = true; //} else { // Oasch = false; //} int newJ = this.m_newJ; GridData NewGrid = (GridData)m_NewGrid; int pDeg = f.Basis.Degree; // Refined_TestData.Basis.Degree; if (!object.ReferenceEquals(NewGrid, f.Basis.GridDat)) { throw new ArgumentException("DG field must be assigned to new grid."); } f.Clear(); int[][] TargMappingIdx = m_Old2NewCorr.GetTargetMappingIndex(NewGrid.CellPartitioning); double[][][] ReDistDGCoords = m_newDGFieldData_GridAdapta[Reference]; Debug.Assert(ReDistDGCoords.Length == newJ); if (f is ConventionalDGField) { // +++++++++++++++ // normal DG field // +++++++++++++++ int Np = f.Basis.Length; double[] temp = new double[Np]; double[] acc = new double[Np]; for (int j = 0; j < newJ; j++) { if (TargMappingIdx[j] == null) { // unchanged cell Debug.Assert(ReDistDGCoords[j].Length == 1); double[] Coord = ReDistDGCoords[j][0]; Debug.Assert(Coord.Length == Np); BckTrafo(Coord, Np, 0, NewGrid, j, pDeg, 1.0); f.Coordinates.SetRow(j, Coord); } else { int L = ReDistDGCoords[j].Length; for (int l = 0; l < L; l++) { DoCellj(j, f, NewGrid, pDeg, TargMappingIdx[j], ReDistDGCoords[j], l, m_Old2NewCorr, 0, 0, Np, temp, acc); } } } } else if (f is XDGField) { // +++++++++++++++++++++++ // treatment of XDG fields // +++++++++++++++++++++++ // (as always, more difficult) XDGField xf = f as XDGField; LevelSetTracker lsTrk = xf.Basis.Tracker; int Np = xf.Basis.NonX_Basis.Length; double[] temp = new double[Np]; double[] acc = new double[Np]; if (!object.ReferenceEquals(m_NewTracker, lsTrk)) { throw new ArgumentException("LevelSetTracker seems duplicate, or something."); } for (int j = 0; j < newJ; j++) { int NoOfSpc = lsTrk.Regions.GetNoOfSpecies(j); f.Coordinates.ClearRow(j); if (TargMappingIdx[j] == null) { // + + + + + + + + + // unchanged cell // + + + + + + + + + Debug.Assert(ReDistDGCoords[j].Length == 1); double[] ReDistDGCoords_jl = ReDistDGCoords[j][0]; //Debug.Assert(ReDistDGCoords_jl.Length == NoOfSpc*Np + NoOfSpc + 1); //Debug.Assert(ReDistDGCoords_jl[0] == NoOfSpc); int NoOfSpcR = (int)(ReDistDGCoords_jl[0]); // Number of species received! int c = 1; for (int iSpcR = 0; iSpcR < NoOfSpcR; iSpcR++) // loop over received species... //#if DEBUG // SpeciesId rcvSpc; // rcvSpc.cntnt = (int) ReDistDGCoords_jl[c]; // Debug.Assert(rcvSpc == lsTrk.Regions.GetSpeciesIdFromIndex(j, iSpc)); //#endif { SpeciesId rcvSpc; rcvSpc.cntnt = (int)ReDistDGCoords_jl[c]; c++; int iSpcTarg = lsTrk.Regions.GetSpeciesIndex(rcvSpc, j); if (iSpcTarg >= 0) { for (int n = 0; n < Np; n++) { f.Coordinates[j, n + Np * iSpcTarg] = ReDistDGCoords_jl[c]; c++; } } else { //double testNorm = 0; for (int n = 0; n < Np; n++) { //testNorm += ReDistDGCoords_jl[c].Pow2(); c++; } } } Debug.Assert(c == ReDistDGCoords_jl.Length); } else { // + + + + + + + + + + + + + // coarsening or refinement // + + + + + + + + + + + + + int L = ReDistDGCoords[j].Length; for (int l = 0; l < L; l++) { double[] ReDistDGCoords_jl = ReDistDGCoords[j][l]; int NoSpcOrg = (int)ReDistDGCoords_jl[0]; // no of species in original cells int c = 1; for (int iSpcRecv = 0; iSpcRecv < NoSpcOrg; iSpcRecv++) // loop over species in original cell { SpeciesId rcvSpc; rcvSpc.cntnt = (int)ReDistDGCoords_jl[c]; c++; int iSpc = lsTrk.Regions.GetSpeciesIndex(rcvSpc, j); // species index in new cell //Debug.Assert(iSpcRecv == iSpc || L > 1); int N0rcv = c; c += Np; if (iSpc >= 0) { DoCellj(j, xf, NewGrid, pDeg, TargMappingIdx[j], ReDistDGCoords[j], l, m_Old2NewCorr, N0rcv, Np * iSpc, Np, temp, acc); } } Debug.Assert(c == ReDistDGCoords_jl.Length); } } } } else { throw new NotImplementedException(); } } }
public LevSetFlx(LevelSetTracker _LsTrk) { m_LsTrk = _LsTrk; }
public FrontTrackingLevelSet2D(VectorField <SinglePhaseField> Velocity_New, VectorField <SinglePhaseField> Velocity_Old, SinglePhaseField Interface, LevelSetTracker InterfaceTrck, VectorField <SinglePhaseField> LevelSetGradient, int max_AddandAttract_Iteration, int NarrowBandWidth, IGridData Grid, bool LevelSetCorrectionWithNeighbourCells, int ReseedingInterval, MinimalDistanceSearchMode LevelSetCorrection, TopologyMergingMode TopologyMerging, NormalVectorDampingMode NormalVectorDamping, double EdgeLengthToCurvatureFraction) : base(Velocity_New, Velocity_Old, Interface, InterfaceTrck, LevelSetGradient, NarrowBandWidth, Grid, ReseedingInterval, LevelSetCorrection, TopologyMerging, NormalVectorDamping, 1) { this.EdgeLengthToCurvatureFraction = EdgeLengthToCurvatureFraction; }
public XDGTestSetup( int p, double AggregationThreshold, int TrackerWidth, MultigridOperator.Mode mumo, XQuadFactoryHelper.MomentFittingVariants momentFittingVariant, ScalarFunction LevSetFunc = null) { // Level set, tracker and XDG basis // ================================ if (LevSetFunc == null) { LevSetFunc = ((_2D)((x, y) => 0.8 * 0.8 - x * x - y * y)).Vectorize(); } LevSet = new LevelSet(new Basis(grid, 2), "LevelSet"); LevSet.Clear(); LevSet.ProjectField(LevSetFunc); LsTrk = new LevelSetTracker(grid, XQuadFactoryHelper.MomentFittingVariants.Classic, TrackerWidth, new string[] { "A", "B" }, LevSet); LsTrk.UpdateTracker(); XB = new XDGBasis(LsTrk, p); XSpatialOperatorMk2 Dummy = new XSpatialOperatorMk2(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), null, "C1", "u"); //Dummy.EquationComponents["c1"].Add(new Dummy.Commit(); //Tecplot.PlotFields(new DGField[] { LevSet }, "agglo", 0.0, 3); // operator // ======== Debug.Assert(p <= 4); XDGBasis opXB = new XDGBasis(LsTrk, 4); // we want to have a very precise quad rule var map = new UnsetteledCoordinateMapping(opXB); int quadOrder = Dummy.QuadOrderFunction(map.BasisS.Select(bs => bs.Degree).ToArray(), new int[0], map.BasisS.Select(bs => bs.Degree).ToArray()); //agg = new MultiphaseCellAgglomerator(new CutCellMetrics(momentFittingVariant, quadOrder, LsTrk, LsTrk.SpeciesIdS.ToArray()), AggregationThreshold, false); agg = LsTrk.GetAgglomerator(LsTrk.SpeciesIdS.ToArray(), quadOrder, __AgglomerationTreshold: AggregationThreshold); foreach (var S in LsTrk.SpeciesIdS) { Console.WriteLine("Species {0}, no. of agglomerated cells {1} ", LsTrk.GetSpeciesName(S), agg.GetAgglomerator(S).AggInfo.SourceCells.Count()); } // mass matrix factory // =================== // Basis maxB = map.BasisS.ElementAtMax(b => b.Degree); //MassFact = new MassMatrixFactory(maxB, agg); MassFact = LsTrk.GetXDGSpaceMetrics(LsTrk.SpeciesIdS.ToArray(), quadOrder, 1).MassMatrixFactory; // Test field // ========== // set the test field: this is a polynomial function, // but different for each species; On this field, restriction followed by prolongation should be the identity this.Xdg_uTest = new XDGField(this.XB, "uTest"); Dictionary <SpeciesId, double> dumia = new Dictionary <SpeciesId, double>(); int i = 2; foreach (var Spc in LsTrk.SpeciesIdS) { dumia.Add(Spc, i); i -= 1; } SetTestValue(Xdg_uTest, dumia); // dummy operator matrix which fits polynomial degree p // ==================================================== Xdg_opMtx = new BlockMsrMatrix(Xdg_uTest.Mapping, Xdg_uTest.Mapping); Xdg_opMtx.AccEyeSp(120.0); // XDG Aggregation BasiseS // ======================= //XAggB = MgSeq.Select(agGrd => new XdgAggregationBasis[] { new XdgAggregationBasis(uTest.Basis, agGrd) }).ToArray(); XAggB = new XdgAggregationBasis[MgSeq.Length][]; var _XAggB = AggregationGridBasis.CreateSequence(MgSeq, Xdg_uTest.Mapping.BasisS); for (int iLevel = 0; iLevel < XAggB.Length; iLevel++) { XAggB[iLevel] = new[] { (XdgAggregationBasis)(_XAggB[iLevel][0]) }; XAggB[iLevel][0].Update(agg); } // Multigrid Operator // ================== Xdg_opMtx = new BlockMsrMatrix(Xdg_uTest.Mapping, Xdg_uTest.Mapping); Xdg_opMtx.AccEyeSp(120.0); XdgMultigridOp = new MultigridOperator(XAggB, Xdg_uTest.Mapping, Xdg_opMtx, MassFact.GetMassMatrix(Xdg_uTest.Mapping, false), new MultigridOperator.ChangeOfBasisConfig[][] { new MultigridOperator.ChangeOfBasisConfig[] { new MultigridOperator.ChangeOfBasisConfig() { VarIndex = new int[] { 0 }, mode = mumo, Degree = p } } }); }
public SingleComponentInterfaceForm(double PenaltyBase, LevelSetTracker LSTrk) { this.PenaltyBase = PenaltyBase; this.LSTrk = LSTrk; }
/// <summary> /// Based on the Ideas by /// C. Basting and D. Kuzmin, /// “A minimization-based finite element formulation for interface-preserving level set reinitialization”, /// Computing, vol. 95, no. 1, pp. 13–25, Dec. 2012. /// Create Spatial Operators and build the corresponding Matrices /// For the Left-Hand Side of the ReInitProblem /// RHS is computed on the fly in <see cref="ReInitSingleStep"/> /// The Bulk component is constant unless the grid changes, thus it is computed in <see cref="BuildOperators(CellQuadratureScheme)"/>. /// The Interface component changes with its motion. /// This component is calculated in <see cref="UpdateOperators(CellQuadratureScheme)"/>. /// </summary> /// <param name="LSTrck"></param> /// <param name="Control">various parameters <paramref name="EllipticReinitControl"/></param> /// <param name="HMFOrder">order of tghe interface quadrature</param> public EllipticReInit(LevelSetTracker LSTrck, EllipticReInitAlgoControl Control, SinglePhaseField LevelSetForReInit = null) { this.Control = Control; this.LevelSetTracker = LSTrck; if (LevelSetForReInit == null) { Phi = LevelSetTracker.LevelSets[0] as SinglePhaseField; } else { Phi = LevelSetForReInit; } this.underrelaxation = Control.underrelaxation; Residual = new SinglePhaseField(Phi.Basis); OldPhi = new SinglePhaseField(Phi.Basis); NewPhi = new SinglePhaseField(Phi.Basis); foreach (SinglePhaseField f in new List <SinglePhaseField> { Residual, OldPhi, NewPhi }) { f.Clear(); f.Acc(1.0, Phi); } this.D = LevelSetTracker.GridDat.SpatialDimension; this.ConvergenceCriterion = Control.ConvergenceCriterion; this.MaxIteration = Control.MaxIt; double PenaltyBase = ((double)((Phi.Basis.Degree + 1) * (Phi.Basis.Degree + D))) / ((double)D); /// Choose Forms according to Upwinding or Central Fluxes string[] paramNames; int noOfParamFields; IEquationComponent BulkForm; RHSForm myRHSForm; LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, "LevelSetGradient", SinglePhaseField.Factory); MeanLevelSetGradient = new VectorField <SinglePhaseField>(D, new Basis(Phi.GridDat, 0), "MeanLevelSetGradient", SinglePhaseField.Factory); if (Control.Upwinding) { paramNames = new string[] { "OldLevelSet", "MeanLevelSetGradient[0]", "MeanLevelSetGradient[1]" }; noOfParamFields = D; LevelSetGradient.Clear(); LevelSetGradient.Gradient(1.0, Phi); //LevelSetGradient.GradientByFlux(1.0, Phi); MeanLevelSetGradient.Clear(); MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient); parameterFields = ArrayTools.Cat(new SinglePhaseField[] { OldPhi }, MeanLevelSetGradient.ToArray()); //throw new NotImplementedException("ToDO"); BulkForm = new EllipticReInitUpwindForm_Laplace(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck); myRHSForm = new EllipticReInitUpwindForm_RHS(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck); OldDirection = new double[MeanLevelSetGradient.CoordinateVector.ToArray().Length]; for (int i = 0; i < MeanLevelSetGradient.CoordinateVector.Length; i++) { OldDirection[i] = Math.Sign(MeanLevelSetGradient.CoordinateVector[i]); } NewDirection = OldDirection.CloneAs(); } else { paramNames = new string[] { }; noOfParamFields = 0; parameterFields = new SinglePhaseField[] { }; BulkForm = new CentralDifferencesLHSForm(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck.GridDat.Cells.cj); myRHSForm = new CentralDifferencesRHSForm(Control.PenaltyMultiplierFlux * PenaltyBase, LSTrck); } // SIP for the bulk Phase //this.Operator_bulk = new SpatialOperator(1, noOfParamFields, 1, QuadOrderFunc.SumOfMaxDegrees(1, RoundUp: false), variableNames); this.Operator_bulk = BulkForm.Operator(); /// Zero at the Interface /// /// Calculate Quadrature Order Func <int[], int[], int[], int> InterfaceQuadOrder; InterfaceQuadOrder = QuadOrderFunc.FixedOrder(Phi.Basis.Degree * 2 + 2); /// Generate Interface Operator this.Operator_interface = (new EllipticReInitInterfaceForm(Control.PenaltyMultiplierInterface * PenaltyBase, LSTrck)).XOperator(InterfaceQuadOrder); // Nonlinear Part on the RHS /// switch for the potential functions switch (Control.Potential) { case ReInitPotential.BastingDoubleWell: { myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.DoubleWell(d, b)); break; }; case ReInitPotential.BastingSingleWell: { myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWell(d, b)); break; }; case ReInitPotential.SingleWellNear: { myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWellNear(d, b)); break; }; case ReInitPotential.P4DoubleWell: { Console.WriteLine("Warning - This Option for Elliptic ReInit does not work well"); myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.DoubleWellAlternative(d, b)); break; }; case ReInitPotential.SingleWellOnCutDoubleWellElse: { myRHSForm.DiffusionRate = ((d, b) => DiffusionRates.SingleWellOnCutDoubleWellElse(d, b)); break; } } Operator_RHS = myRHSForm.Operator(QuadOrderFunc.SumOfMaxDegrees(2, RoundUp: true)); /// The result of the nonlinear part on the rhs is projected on a single-phase field RHSField = new SinglePhaseField(Phi.Basis, "RHS"); OpMatrix = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping); OpAffine = new double[OpMatrix.RowPartitioning.LocalLength]; /// Matrix and RHS for the Bulk component OpMatrix_bulk = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping); OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength]; /// Matrix and RHS for the Interface Penalty OpMatrix_interface = new MsrMatrix(this.Phi.Mapping, this.Phi.Mapping); OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength]; // Init Parameter Fields OldPhi.Clear(); OldPhi.Acc(1.0, Phi); // Compute Matrices UpdateBulkMatrix(); }
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.ToGeometicalMask())).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++; } }