/// <summary> /// ctor. /// </summary> /// <param name="xb"> /// XDG basis on original grid /// </param> /// <param name="parentBasis"> /// basis on parent grid /// </param> /// <param name="ag"> /// aggregation grid level. /// </param> /// <param name="inj"> /// injection operators. /// </param> internal XdgAggregationBasis(XDGBasis xb, XdgAggregationBasis parentBasis, AggregationGridData ag, MultidimensionalArray[] inj) : base(xb.NonX_Basis, parentBasis, ag, inj) // { using (new FuncTrace()) { this.XDGBasis = xb; this.XCompositeBasis = new MultidimensionalArray[base.AggGrid.iLogicalCells.NoOfLocalUpdatedCells][]; } }
public XdgAggregationBasis(XDGBasis xb, AggregationGrid ag) : base(xb.NonX_Basis, ag) // { using (new FuncTrace()) { this.XDGBasis = xb; this.XCompositeBasis = new MultidimensionalArray[base.AggGrid.iLogicalCells.NoOfLocalUpdatedCells][]; } }
/// <summary> /// Initialization of the solver/preconditioner. /// </summary> protected void InitMultigrid(DGField[] Fields, bool useX) { Basis[] bs; if (useX) { bs = new Basis[Fields.Length]; for (int i = 0; i < bs.Length; i++) { bs[i] = new XDGBasis(m_LsTrk, Fields[i].Basis.Degree); } } else { bs = Fields.Select(f => f.Basis).ToArray(); } this.MultigridBasis = AggregationGridBasis.CreateSequence(this.MultigridSequence, bs); }
protected override void CreateFields() { LevSet = new LevelSet(new Basis(this.GridData, 2), "LevelSet"); base.LsTrk = new LevelSetTracker((GridData)this.GridData, XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes, 1, new string[] { "A", "B" }, LevSet); var xBasis = new XDGBasis(base.LsTrk, DEGREE); u = new XDGField(xBasis, "u"); uResidual = new XDGField(xBasis, "Res"); uEx = new XDGField(xBasis, "uEx"); Amarker = new SinglePhaseField(new Basis(this.GridData, 0), "Amarker"); Bmarker = new SinglePhaseField(new Basis(this.GridData, 0), "Bmarker"); MPICellRank = new SinglePhaseField(new Basis(this.GridData, 0), "MPIRank"); base.m_RegisteredFields.Add(LevSet); base.m_RegisteredFields.Add(u); base.m_RegisteredFields.Add(uEx); base.m_RegisteredFields.Add(uResidual); base.m_RegisteredFields.Add(Amarker); base.m_RegisteredFields.Add(Bmarker); base.m_RegisteredFields.Add(MPICellRank); }
protected override void CreateFields() { LevSet = new LevelSet(new Basis(this.GridData, 2), "LevelSet"); base.LsTrk = new LevelSetTracker(this.GridData, 1, new string[] { "A", "B" }, LevSet); var xBasis = new XDGBasis(base.LsTrk, DEGREE); u = new XDGField(xBasis, "u"); uResidual = new XDGField(xBasis, "Res"); uEx = new XDGField(xBasis, "uEx"); Amarker = new SinglePhaseField(new Basis(this.GridData, 0), "Amarker"); Bmarker = new SinglePhaseField(new Basis(this.GridData, 0), "Bmarker"); MPICellRank = new SinglePhaseField(new Basis(this.GridData, 0), "MPIRank"); base.m_RegisteredFields.Add(LevSet); base.m_RegisteredFields.Add(u); base.m_RegisteredFields.Add(uEx); base.m_RegisteredFields.Add(uResidual); base.m_RegisteredFields.Add(Amarker); base.m_RegisteredFields.Add(Bmarker); base.m_RegisteredFields.Add(MPICellRank); }
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); XSpatialOperator Dummy = new XSpatialOperator(1, 0, 1, QuadOrderFunc.SumOfMaxDegrees(RoundUp: true), "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 } } }); }
/// <summary> /// /// </summary> public void AssembleMatrix_Timestepper <T>( int CutCellQuadOrder, BlockMsrMatrix OpMatrix, double[] OpAffine, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, IEnumerable <T> CurrentState, VectorField <SinglePhaseField> SurfaceForce, VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature, UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping, double time, IEnumerable <T> CoupledCurrentState = null, IEnumerable <T> CoupledParams = null) where T : DGField { if (ColMapping.BasisS.Count != this.Op.DomainVar.Count) { throw new ArgumentException(); } if (RowMapping.BasisS.Count != this.Op.CodomainVar.Count) { throw new ArgumentException(); } // check: var Tracker = this.LsTrk; int D = Tracker.GridDat.SpatialDimension; if (CurrentState != null && CurrentState.Count() != (D + 1)) { throw new ArgumentException(); } if (OpMatrix == null && CurrentState == null) { throw new ArgumentException(); } DGField[] U0; if (CurrentState != null) { U0 = CurrentState.Take(D).ToArray(); } else { U0 = null; } LevelSet Phi = (LevelSet)(Tracker.LevelSets[0]); SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea; // advanced settings for the navier slip boundary condition // ======================================================== CellMask SlipArea; switch (this.dntParams.GNBC_Localization) { case NavierSlip_Localization.Bulk: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask; break; } case NavierSlip_Localization.ContactLine: { SlipArea = null; break; } case NavierSlip_Localization.Nearband: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth)); break; } case NavierSlip_Localization.Prescribed: { throw new NotImplementedException(); } default: throw new ArgumentException(); } MultidimensionalArray SlipLengths; SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs(); SlipLengths.Clear(); //SlipLengths.AccConstant(-1.0); if (SlipArea != null) { foreach (Chunk cnk in SlipArea) { for (int i = cnk.i0; i < cnk.JE; i++) { switch (this.dntParams.GNBC_SlipLength) { case NavierSlip_SlipLength.hmin_DG: { int degU = ColMapping.BasisS.ToArray()[0].Degree; SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1); break; } case NavierSlip_SlipLength.hmin_Grid: { SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i]; break; } case NavierSlip_SlipLength.Prescribed_SlipLength: { SlipLengths[i] = this.physParams.sliplength; break; } case NavierSlip_SlipLength.Prescribed_Beta: { SlipLengths[i] = -1.0; break; } } } } } // parameter assembly // ================== // normals: SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions. if (this.NormalsRequired) { if (LevelSetGradient == null) { LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory); LevelSetGradient.Gradient(1.0, Phi); } Normals = LevelSetGradient.ToArray(); } else { Normals = new SinglePhaseField[D]; } // curvature: SinglePhaseField Curvature; if (this.CurvatureRequired) { Curvature = ExternalyProvidedCurvature; } else { Curvature = null; } // linearization velocity: DGField[] U0_U0mean; if (this.U0meanrequired) { XDGBasis U0meanBasis = new XDGBasis(Tracker, 0); VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory); U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean); } else { U0_U0mean = new DGField[2 * D]; } // Temperature gradient for evaporation VectorField <DGField> GradTemp = new VectorField <DGField>(D, U0[0].Basis, XDGField.Factory); if (CoupledCurrentState != null) { DGField Temp = CoupledCurrentState.ToArray()[0]; GradTemp = new VectorField <DGField>(D, Temp.Basis, "GradTemp", XDGField.Factory); XNSEUtils.ComputeGradientForParam(Temp, GradTemp, this.LsTrk); } // concatenate everything var Params = ArrayTools.Cat <DGField>( U0_U0mean, Curvature, ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]), Normals, ((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D]), ((evaporation) ? CoupledCurrentState.ToArray <DGField>() : new SinglePhaseField[1]), ((evaporation) ? CoupledParams.ToArray <DGField>() : new SinglePhaseField[1])); //((evaporation) ? GradTemp.ToArray() : new SinglePhaseField[D])); // linearization velocity: if (this.U0meanrequired) { VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray()); U0mean.Clear(); if (this.physParams.IncludeConvection) { ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper); } } // assemble the matrix & affine vector // =================================== // compute matrix if (OpMatrix != null) { //Op.ComputeMatrixEx(Tracker, // ColMapping, Params, RowMapping, // OpMatrix, OpAffine, false, time, true, // AgglomeratedCellLengthScales, // InterfaceLengths, SlipLengths, // SpcToCompute); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); } if (Op.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); } } mtxBuilder.time = time; mtxBuilder.ComputeMatrix(OpMatrix, OpAffine); } else { XSpatialOperatorMk2.XEvaluatorNonlin eval = Op.GetEvaluatorEx(Tracker, CurrentState.ToArray(), Params, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); } if (Op.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); } } eval.time = time; eval.Evaluate(1.0, 1.0, OpAffine); #if DEBUG // remark: remove this piece in a few months from now on (09may18) if no problems occur //{ // BlockMsrMatrix checkOpMatrix = new BlockMsrMatrix(RowMapping, ColMapping); // double[] checkAffine = new double[OpAffine.Length]; // Op.ComputeMatrixEx(Tracker, // ColMapping, Params, RowMapping, // OpMatrix, OpAffine, false, time, true, // AgglomeratedCellLengthScales, // InterfaceLengths, SlipLengths, // SpcToCompute); // double[] checkResult = checkAffine.CloneAs(); // var currentVec = new CoordinateVector(CurrentState.ToArray()); // checkOpMatrix.SpMV(1.0, new CoordinateVector(CurrentState.ToArray()), 1.0, checkResult); // double L2_dist = GenericBlas.L2DistPow2(checkResult, OpAffine).MPISum().Sqrt(); // double RefNorm = (new double[] { checkResult.L2NormPow2(), OpAffine.L2NormPow2(), currentVec.L2NormPow2() }).MPISum().Max().Sqrt(); // Assert.LessOrEqual(L2_dist, RefNorm * 1.0e-6); // Debug.Assert(L2_dist < RefNorm * 1.0e-6); //} #endif } // check // ===== /* * { * DGField[] testDomainFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray(); * CoordinateVector test = new CoordinateVector(testDomainFieldS); * * DGField[] errFieldS = ColMapping.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray(); * CoordinateVector Err = new CoordinateVector(errFieldS); * * var eval = Op.GetEvaluatorEx(LsTrk, * testDomainFieldS, Params, RowMapping); * * foreach (var s in this.LsTrk.SpeciesIdS) * eval.SpeciesOperatorCoefficients[s].CellLengthScales = AgglomeratedCellLengthScales[s]; * * eval.time = time; * int L = test.Count; * Random r = new Random(); * for(int i = 0; i < L; i++) { * test[i] = r.NextDouble(); * } * * * * double[] R1 = new double[L]; * double[] R2 = new double[L]; * eval.Evaluate(1.0, 1.0, R1); * * R2.AccV(1.0, OpAffine); * OpMatrix.SpMV(1.0, test, 1.0, R2); * * Err.AccV(+1.0, R1); * Err.AccV(-1.0, R2); * * double ErrDist = GenericBlas.L2DistPow2(R1, R2).MPISum().Sqrt(); * * double Ref = test.L2NormPow2().MPISum().Sqrt(); * * Debug.Assert(ErrDist <= Ref*1.0e-5, "Mismatch between explicit evaluation of XDG operator and matrix."); * } */ }
/// <summary> /// Computes a mapping from the new, cell local DG coordinate index to the previous/old DG coordinate index, or vice-versa. /// </summary> /// <param name="jCell"> /// Local cell index. /// </param> /// <param name="New2Old"> /// If true, a mapping from new species index to previous/old species index is returned, /// if false the other way around. /// </param> /// <param name="LsTrk"> /// </param> /// <param name="Map"> /// DG coordinate mapping. /// </param> /// <returns> /// Null, if there is no change in species ordering in cell <paramref name="jCell"/> /// from the previous level-set tracker state to the actual. /// /// Otherwise, if <paramref name="New2Old"/> is true, an array of the same length /// as the number of degrees-of-freedom currently in cell <paramref name="jCell"/>. /// - index: current DOF index in cell <paramref name="jCell"/>. /// - content: index of this DOF with respect to the previous level-set-tracker state. /// If <paramref name="New2Old"/> false, the other way around. /// </returns> public static int[] MappingUpdate(LevelSetTracker LsTrk, int jCell, UnsetteledCoordinateMapping Map, bool New2Old) { int[] SpeciesMap = SpeciesUpdate(LsTrk, jCell, New2Old); if (SpeciesMap == null) { return(null); } int NoVar = Map.NoOfVariables; XDGBasis[] XBasiseS = new XDGBasis[NoVar]; Basis[] BasiseS = new Basis[NoVar]; int[] Ns = new int[NoVar]; for (int iVar = 0; iVar < NoVar; iVar++) { Basis b = Map.BasisS[iVar]; XBasiseS[iVar] = b as XDGBasis; if (XBasiseS[iVar] != null) { BasiseS[iVar] = XBasiseS[iVar].NonX_Basis; } else { BasiseS[iVar] = b; } Ns[iVar] = BasiseS[iVar].Length; } //List<int> oldIdx = new List<int>(); //List<int> newIdx = new List<int>(); int[] IdxMap = new int[Map.MaxTotalNoOfCoordinatesPerCell]; ArrayTools.SetAll(IdxMap, int.MinValue); bool AnyRelocation = false; int i0 = Map.LocalUniqueCoordinateIndex(0, jCell, 0); for (int iVar = 0; iVar < NoVar; iVar++) { int i0Var = Map.LocalUniqueCoordinateIndex(iVar, jCell, 0); int N = Ns[iVar]; int offset = i0Var - i0; if (XBasiseS[iVar] != null) { // XDG-field for (int i = 0; i < SpeciesMap.Length; i++) { int ii = SpeciesMap[i]; for (int n = 0; n < N; n++) { int idxS = offset + n + i * N; int idxT = ii >= 0 ? offset + n + ii * N : int.MinValue; Debug.Assert(IdxMap[idxS] < 0); IdxMap[idxS] = idxT; AnyRelocation |= (idxS != idxT); } } } else { // single-phase-field for (int n = 0; n < N; n++) { int idx = offset + n; //oldIdx.Add(idx); //newIdx.Add(idx); Debug.Assert(IdxMap[idx] < 0); IdxMap[idx] = idx; } } } return(IdxMap); //if (AnyRelocation) // return IdxMap; //else // return null; }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="OpMatrix"></param> /// <param name="OpAffine"></param> /// <param name="RowMapping"></param> /// <param name="ColMapping"></param> /// <param name="CurrentState"></param> /// <param name="AgglomeratedCellLengthScales"></param> /// <param name="time"></param> /// <param name="CutCellQuadOrder"></param> /// <param name="SurfaceForce"></param> /// <param name="LevelSetGradient"></param> /// <param name="ExternalyProvidedCurvature"></param> public void AssembleMatrix <T>(BlockMsrMatrix OpMatrix, double[] OpAffine, UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping, IEnumerable <T> CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double time, int CutCellQuadOrder, VectorField <SinglePhaseField> SurfaceForce, VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature) where T : DGField { // checks: if (ColMapping.BasisS.Count != this.m_XOp.DomainVar.Count) { throw new ArgumentException(); } if (RowMapping.BasisS.Count != this.m_XOp.CodomainVar.Count) { throw new ArgumentException(); } int D = this.LsTrk.GridDat.SpatialDimension; if (CurrentState != null && CurrentState.Count() != (D + 1)) { throw new ArgumentException(); } if (OpMatrix == null && CurrentState == null) { throw new ArgumentException(); } DGField[] U0; if (CurrentState != null) { U0 = CurrentState.Take(D).ToArray(); } else { U0 = null; } // advanced settings for the navier slip boundary condition // ======================================================== CellMask SlipArea; switch (this.dntParams.GNBC_Localization) { case NavierSlip_Localization.Bulk: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask; break; } case NavierSlip_Localization.ContactLine: { SlipArea = null; break; } case NavierSlip_Localization.Nearband: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth)); break; } case NavierSlip_Localization.Prescribed: { throw new NotImplementedException(); } default: throw new ArgumentException(); } MultidimensionalArray SlipLengths; SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs(); SlipLengths.Clear(); //SlipLengths.AccConstant(-1.0); if (SlipArea != null) { foreach (Chunk cnk in SlipArea) { for (int i = cnk.i0; i < cnk.JE; i++) { switch (this.dntParams.GNBC_SlipLength) { case NavierSlip_SlipLength.hmin_DG: { int degU = ColMapping.BasisS.ToArray()[0].Degree; SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1); break; } case NavierSlip_SlipLength.hmin_Grid: { SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i]; break; } case NavierSlip_SlipLength.Prescribed_SlipLength: { SlipLengths[i] = this.physParams.sliplength; break; } case NavierSlip_SlipLength.Prescribed_Beta: { SlipLengths[i] = -1.0; break; } } } } } // parameter assembly // ================== LevelSet Phi = (LevelSet)(this.LsTrk.LevelSets[0]); SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); // normals: SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions. if (this.NormalsRequired) { if (LevelSetGradient == null) { LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory); LevelSetGradient.Gradient(1.0, Phi); } Normals = LevelSetGradient.ToArray(); } else { Normals = new SinglePhaseField[D]; } // curvature: SinglePhaseField Curvature; if (this.CurvatureRequired) { Curvature = ExternalyProvidedCurvature; } else { Curvature = null; } // linearization velocity: DGField[] U0_U0mean; if (this.U0meanrequired) { XDGBasis U0meanBasis = new XDGBasis(this.LsTrk, 0); VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory); U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean); } else { U0_U0mean = new DGField[2 * D]; } // Temperature gradient for evaporation //VectorField<DGField> GradTemp = new VectorField<DGField>(D, new XDGBasis(LsTrk, 0), XDGField.Factory); //if (CoupledCurrentState != null) { // DGField Temp = CoupledCurrentState.ToArray()[0]; // GradTemp = new VectorField<DGField>(D, Temp.Basis, "GradTemp", XDGField.Factory); // XNSEUtils.ComputeGradientForParam(Temp, GradTemp, this.LsTrk); //} // concatenate everything var Params = ArrayTools.Cat <DGField>( U0_U0mean, Normals, Curvature, ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D])); // linearization velocity: if (this.U0meanrequired) { VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray()); U0mean.Clear(); if (this.physParams.IncludeConvection) { ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper); } } // assemble the matrix & affine vector // =================================== IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea; // compute matrix if (OpMatrix != null) { XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = this.m_XOp.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); } if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); } } mtxBuilder.time = time; mtxBuilder.ComputeMatrix(OpMatrix, OpAffine); } else { XSpatialOperatorMk2.XEvaluatorNonlin eval = this.m_XOp.GetEvaluatorEx(this.LsTrk, CurrentState.ToArray(), Params, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; eval.SpeciesOperatorCoefficients[kv.Key].EdgeLengthScales = kv.Value; eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); } if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); } } eval.time = time; eval.Evaluate(1.0, 1.0, OpAffine); } }
/// <summary> /// /// </summary> public void AssembleMatrix <T>(BlockMsrMatrix OpMatrix, double[] OpAffine, UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping, IEnumerable <T> CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double time, int CutCellQuadOrder, VectorField <SinglePhaseField> SurfaceForce, VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature, bool[] updateSolutionParams = null, DGField[] ExtParams = null) where T : DGField { //IEnumerable<T> CoupledCurrentState = null, IEnumerable<T> CoupledParams = null) where T : DGField { // checks: if (ColMapping.BasisS.Count != this.m_XOp.DomainVar.Count) { throw new ArgumentException(); } if (RowMapping.BasisS.Count != this.m_XOp.CodomainVar.Count) { throw new ArgumentException(); } int D = this.LsTrk.GridDat.SpatialDimension; if (CurrentState != null && !config.solveEnergy && !config.solveHeat && CurrentState.Count() != (D + 1)) { throw new ArgumentException(); } if (OpMatrix == null && CurrentState == null) { throw new ArgumentException(); } DGField[] U0; if (CurrentState != null) { U0 = CurrentState.Take(D).ToArray(); } else { U0 = null; } // parameter assembly // ================== #region param assembly LevelSet Phi = (LevelSet)(this.LsTrk.LevelSets[0]); SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); // linearization velocity: DGField[] U0_U0mean; if (this.U0meanrequired) { XDGBasis U0meanBasis = new XDGBasis(this.LsTrk, 0); VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory); U0mean.Clear(); if (this.physParams.IncludeConvection) { ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper); } U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean); } else { U0_U0mean = new DGField[2 * D]; } // linearization velocity: //if (this.U0meanrequired) { // VectorField<XDGField> U0mean = new VectorField<XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray()); // U0mean.Clear(); // if (this.physParams.IncludeConvection) // ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper); //} // normals: SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions. if (this.NormalsRequired) { if (LevelSetGradient == null) { LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory); LevelSetGradient.Gradient(1.0, Phi); } Normals = LevelSetGradient.ToArray(); } else { Normals = new SinglePhaseField[D]; } // curvature: SinglePhaseField Curvature; if (this.CurvatureRequired) { Curvature = ExternalyProvidedCurvature; } else { Curvature = null; } // velocity gradient vectors var VelMap = new CoordinateMapping(U0); DGField[] VelParam = VelMap.Fields.ToArray(); VectorField <DGField> GradVelX = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityXGradient", XDGField.Factory); for (int d = 0; d < D; d++) { foreach (var Spc in this.LsTrk.SpeciesIdS) { DGField f_Spc = ((VelParam[0] as XDGField).GetSpeciesShadowField(Spc)); SubGrid sf = this.LsTrk.Regions.GetSpeciesSubGrid(Spc); (GradVelX[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf); } } GradVelX.ForEach(F => F.CheckForNanOrInf(true, true, true)); VectorField <DGField> GradVelY = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityYGradient", XDGField.Factory); for (int d = 0; d < D; d++) { foreach (var Spc in this.LsTrk.SpeciesIdS) { DGField f_Spc = ((VelParam[1] as XDGField).GetSpeciesShadowField(Spc)); SubGrid sf = this.LsTrk.Regions.GetSpeciesSubGrid(Spc); (GradVelY[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf); } } GradVelY.ForEach(F => F.CheckForNanOrInf(true, true, true)); VectorField <DGField> GradVelXGradX = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityXGradX_Gradient", XDGField.Factory); for (int d = 0; d < D; d++) { foreach (var Spc in this.LsTrk.SpeciesIdS) { DGField f_Spc = ((GradVelX[0] as XDGField).GetSpeciesShadowField(Spc)); SubGrid sf = this.LsTrk.Regions.GetSpeciesSubGrid(Spc); (GradVelXGradX[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf); } } GradVelXGradX.ForEach(F => F.CheckForNanOrInf(true, true, true)); VectorField <DGField> GradVelXGradY = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityXGradY_Gradient", XDGField.Factory); for (int d = 0; d < D; d++) { foreach (var Spc in this.LsTrk.SpeciesIdS) { DGField f_Spc = ((GradVelX[1] as XDGField).GetSpeciesShadowField(Spc)); SubGrid sf = this.LsTrk.Regions.GetSpeciesSubGrid(Spc); (GradVelXGradY[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf); } } GradVelXGradY.ForEach(F => F.CheckForNanOrInf(true, true, true)); VectorField <DGField> GradVelYGradX = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityYGradX_Gradient", XDGField.Factory); for (int d = 0; d < D; d++) { foreach (var Spc in this.LsTrk.SpeciesIdS) { DGField f_Spc = ((GradVelY[0] as XDGField).GetSpeciesShadowField(Spc)); SubGrid sf = this.LsTrk.Regions.GetSpeciesSubGrid(Spc); (GradVelYGradX[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf); } } GradVelYGradX.ForEach(F => F.CheckForNanOrInf(true, true, true)); VectorField <DGField> GradVelYGradY = new VectorField <DGField>(D, VelParam[0].Basis, "VelocityYGradY_Gradient", XDGField.Factory); for (int d = 0; d < D; d++) { foreach (var Spc in this.LsTrk.SpeciesIdS) { DGField f_Spc = ((GradVelY[1] as XDGField).GetSpeciesShadowField(Spc)); SubGrid sf = this.LsTrk.Regions.GetSpeciesSubGrid(Spc); (GradVelYGradY[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf); } } GradVelYGradY.ForEach(F => F.CheckForNanOrInf(true, true, true)); // pressure and gradient var PressMap = new CoordinateMapping(CurrentState.ToArray()[D]); DGField[] PressParam = PressMap.Fields.ToArray(); VectorField <DGField> PressGrad = new VectorField <DGField>(D, PressParam[0].Basis, "PressureGrad", XDGField.Factory); for (int d = 0; d < D; d++) { foreach (var Spc in this.LsTrk.SpeciesIdS) { DGField f_Spc = ((PressParam[0] as XDGField).GetSpeciesShadowField(Spc)); SubGrid sf = this.LsTrk.Regions.GetSpeciesSubGrid(Spc); (PressGrad[d] as XDGField).GetSpeciesShadowField(Spc).DerivativeByFlux(1.0, f_Spc, d, optionalSubGrid: sf); } } PressGrad.ForEach(F => F.CheckForNanOrInf(true, true, true)); // gravity var GravMap = new CoordinateMapping(ExtParams); DGField[] GravParam = GravMap.Fields.ToArray(); // heat flux for evaporation DGField[] HeatFluxParam = new DGField[D]; if (config.solveHeat) { if (config.conductMode == ConductivityInSpeciesBulk.ConductivityMode.SIP && updateSolutionParams[D + 1]) { HeatFluxParam = new VectorField <XDGField>(D, CurrentState.ToArray()[D + 1].Basis, "HeatFlux0_", XDGField.Factory).ToArray(); Dictionary <string, double> kSpc = new Dictionary <string, double>(); kSpc.Add("A", -thermParams.k_A); kSpc.Add("B", -thermParams.k_B); XNSEUtils.ComputeGradientForParam(CurrentState.ToArray()[D + 1], HeatFluxParam, this.LsTrk, kSpc, this.LsTrk.Regions.GetCutCellSubGrid()); } else if (config.conductMode != ConductivityInSpeciesBulk.ConductivityMode.SIP && updateSolutionParams[D + 2]) { var HeatFluxMap = new CoordinateMapping(CurrentState.ToArray().GetSubVector(D + 2, D)); HeatFluxParam = HeatFluxMap.Fields.ToArray(); } else { HeatFluxParam = storedParams.GetSubVector(2 * D + 4, D); } } if (ExtParams != null) { HeatFluxParam = ExtParams; } #endregion // concatenate everything var Params = ArrayTools.Cat <DGField>( U0_U0mean, Normals, Curvature, ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D])); if (config.solveEnergy) { Params = ArrayTools.Cat <DGField>(Params.ToArray <DGField>(), GradVelX, GradVelY, GradVelXGradX, GradVelXGradY, GradVelYGradX, GradVelYGradY, PressParam, PressGrad, GravMap); } if (config.solveHeat) { Params = ArrayTools.Cat <DGField>(Params.ToArray <DGField>(), CurrentState.ToArray <DGField>().GetSubVector(D + 1, 1), HeatFluxParam, new SinglePhaseField[1]); } // store old params for (int p = 0; p < Params.Length; p++) { if (Params[p] != null) { storedParams[p] = Params[p].CloneAs(); } } // advanced settings for the navier slip boundary condition // ======================================================== CellMask SlipArea; switch (this.dntParams.GNBC_Localization) { case NavierSlip_Localization.Bulk: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask; break; } case NavierSlip_Localization.ContactLine: { SlipArea = null; break; } case NavierSlip_Localization.Nearband: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth)); break; } case NavierSlip_Localization.Prescribed: { throw new NotImplementedException(); } default: throw new ArgumentException(); } MultidimensionalArray SlipLengths; SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs(); SlipLengths.Clear(); //SlipLengths.AccConstant(-1.0); if (SlipArea != null) { foreach (Chunk cnk in SlipArea) { for (int i = cnk.i0; i < cnk.JE; i++) { switch (this.dntParams.GNBC_SlipLength) { case NavierSlip_SlipLength.hmin_DG: { int degU = ColMapping.BasisS.ToArray()[0].Degree; SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1); break; } case NavierSlip_SlipLength.hmin_Grid: { SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i]; break; } case NavierSlip_SlipLength.Prescribed_SlipLength: { SlipLengths[i] = this.physParams.sliplength; break; } case NavierSlip_SlipLength.Prescribed_Beta: { SlipLengths[i] = -1.0; break; } } } } } // interface coefficients // ====================== MultidimensionalArray lambdaI, muI; lambdaI = SlipLengths.CloneAs(); lambdaI.Clear(); muI = SlipLengths.CloneAs(); muI.Clear(); foreach (Chunk cnk in this.LsTrk.Regions.GetCutCellMask()) { for (int i = cnk.i0; i < cnk.JE; i++) { double lI = 0.0; double mI = 0.0; // do the magic!!! if (this.LsTrk.GridDat.Cells.CellCenter[i, 0] > 0 && this.LsTrk.GridDat.Cells.CellCenter[i, 1] > 0) { } if (this.LsTrk.GridDat.Cells.CellCenter[i, 0] > 0 && this.LsTrk.GridDat.Cells.CellCenter[i, 1] < 0) { //lI = config.physParams.Sigma; mI = config.physParams.Sigma; } if (this.LsTrk.GridDat.Cells.CellCenter[i, 0] < 0 && this.LsTrk.GridDat.Cells.CellCenter[i, 1] < 0) { //lI = -config.physParams.Sigma; mI = -config.physParams.Sigma; } if (this.LsTrk.GridDat.Cells.CellCenter[i, 0] < 0 && this.LsTrk.GridDat.Cells.CellCenter[i, 1] > 0) { //lI = 10 * config.physParams.Sigma; mI = 10 * config.physParams.Sigma; } lambdaI[i] = lI; muI[i] = mI; } } // assemble the matrix & affine vector // =================================== IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea; BitArray EvapMicroRegion = this.LsTrk.GridDat.GetBoundaryCells().GetBitMask(); EvapMicroRegion.SetAll(false); // compute matrix if (OpMatrix != null) { XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = this.m_XOp.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping); foreach (var kv in AgglomeratedCellLengthScales) { mtxBuilder.CellLengthScales[kv.Key] = kv.Value; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["SlipLengths"] = SlipLengths; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["EvapMicroRegion"] = EvapMicroRegion; if (config.prescribedMassflux != null) { double[] dummyX = new double[] { 0.0, 0.0 }; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["prescribedMassflux"] = config.prescribedMassflux(dummyX, time); } } if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["InterfaceLengths"] = kv.Value; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["lambda_interface"] = lambdaI; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["mu_interface"] = muI; } } mtxBuilder.time = time; mtxBuilder.ComputeMatrix(OpMatrix, OpAffine); } else { XSpatialOperatorMk2.XEvaluatorNonlin eval = this.m_XOp.GetEvaluatorEx(this.LsTrk, CurrentState.ToArray(), Params, RowMapping); foreach (var kv in AgglomeratedCellLengthScales) { eval.CellLengthScales[kv.Key] = kv.Value; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["SlipLengths"] = SlipLengths; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["EvapMicroRegion"] = EvapMicroRegion; if (config.prescribedMassflux != null) { double[] dummyX = new double[] { 0.0, 0.0 }; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["prescribedMassflux"] = config.prescribedMassflux(dummyX, time); } } if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["InterfaceLengths"] = kv.Value; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["lambda_interface"] = lambdaI; this.m_XOp.UserDefinedValues[this.LsTrk.GetSpeciesName(kv.Key)]["mu_interface"] = muI; } } eval.time = time; eval.Evaluate(1.0, 1.0, OpAffine); } }
/// <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]; } 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++) { 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++; } } Debug.Assert(data_j.Length == c); oldFieldsData[j] = data_j; } } else { throw new NotSupportedException(); } }
void ParameterUpdate(IEnumerable <DGField> CurrentState, IEnumerable <DGField> ParameterVar, int CutCellQuadOrder, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales) { LevelSet Phi = (LevelSet)(this.LsTrk.LevelSets[0]); SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); DGField[] U0; if (CurrentState != null) { U0 = CurrentState.Take(D).ToArray(); } else { U0 = null; } DGField[] Stress0; Stress0 = CurrentState.Skip(D + 1).Take(3).ToArray(); if (U0.Count() != D) { throw new ArgumentException("Spatial dimesion and number of velocity parameter components does not match!"); } if (Stress0.Count() != D + 1) { throw new ArgumentException("Spatial dimesion and number of stress parameter components does not match!"); } // linearization velocity: DGField[] U0_U0mean; if (this.U0meanrequired) { XDGBasis U0meanBasis = new XDGBasis(this.LsTrk, 0); VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory); U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean); U0mean.Clear(); ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper); } else { U0_U0mean = new DGField[2 * D]; } //if (this.Control.SetParamsAnalyticalSol == false) { //SinglePhaseField[] __VelocityXGradient = ParameterVar.Skip(2 * D).Take(D).Select(f => f as SinglePhaseField).ToArray(); //SinglePhaseField[] __VelocityYGradient = ParameterVar.Skip(3 * D).Take(D).Select(f => f as SinglePhaseField).ToArray(); //Debug.Assert(ArrayTools.AreEqual(__VelocityXGradient, VelocityXGradient.ToArray(), (fa, fb) => object.ReferenceEquals(fa, fb))); //Debug.Assert(ArrayTools.AreEqual(__VelocityYGradient, VelocityYGradient.ToArray(), (fa, fb) => object.ReferenceEquals(fa, fb))); //if (VelocityXGradient == null) { // VelocityXGradient = new VectorField<XDGField>(D, CurrentState.ElementAt(0).Basis, "VelocityX_Gradient", XDGField.Factory); //} VelocityXGradient.Clear(); VelocityXGradient.GradientByFlux(1.0, U0[0]); //if (VelocityYGradient == null) { // VelocityYGradient = new VectorField<XDGField>(D, CurrentState.ElementAt(1).Basis, "VelocityY_Gradient", XDGField.Factory); //} VelocityYGradient.Clear(); VelocityYGradient.GradientByFlux(1.0, U0[1]); //} if (this.useArtificialDiffusion == true) { throw new NotImplementedException("artificial diffusion not jet fully implemented..."); //SinglePhaseField __ArtificialViscosity = ParameterVar.Skip(5 * D + 1).Take(1).Select(f => f as SinglePhaseField).ToArray()[0]; //if (!object.ReferenceEquals(this.artificalViscosity, __ArtificialViscosity)) // throw new ApplicationException(); //ArtificialViscosity.ProjectArtificalViscosityToDGField(__ArtificialViscosity, perssonsensor, this.Control.SensorLimit, artificialMaxViscosity); } }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="OpMatrix"></param> /// <param name="OpAffine"></param> /// <param name="RowMapping"></param> /// <param name="ColMapping"></param> /// <param name="CurrentState"></param> /// <param name="AgglomeratedCellLengthScales"></param> /// <param name="time"></param> /// <param name="CutCellQuadOrder"></param> /// <param name="SurfaceForce"></param> /// <param name="LevelSetGradient"></param> /// <param name="ExternalyProvidedCurvature"></param> public void AssembleMatrix <T>(BlockMsrMatrix OpMatrix, double[] OpAffine, UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping, IEnumerable <T> CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double time, int CutCellQuadOrder, VectorField <SinglePhaseField> SurfaceForce, VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature, double currentWeissenberg, IEnumerable <T> CoupledCurrentState = null, IEnumerable <T> CoupledParams = null) where T : DGField { // checks: if (ColMapping.BasisS.Count != this.m_XOp.DomainVar.Count) { throw new ArgumentException(); } if (RowMapping.BasisS.Count != this.m_XOp.CodomainVar.Count) { throw new ArgumentException(); } int D = this.LsTrk.GridDat.SpatialDimension; if (CurrentState != null && CurrentState.Count() != (D + 4)) { throw new ArgumentException(); } if (OpMatrix == null && CurrentState == null) { throw new ArgumentException(); } DGField[] U0; if (CurrentState != null) { U0 = CurrentState.Take(D).ToArray(); } else { U0 = null; } DGField[] Stress0; Stress0 = CurrentState.Skip(D + 1).Take(3).ToArray(); if (U0.Count() != D) { throw new ArgumentException("Spatial dimesion and number of velocity parameter components does not match!"); } if (Stress0.Count() != D + 1) { throw new ArgumentException("Spatial dimesion and number of stress parameter components does not match!"); } // advanced settings for the navier slip boundary condition // ======================================================== CellMask SlipArea; switch (this.dntParams.GNBC_Localization) { case NavierSlip_Localization.Bulk: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask; break; } case NavierSlip_Localization.ContactLine: { SlipArea = null; break; } case NavierSlip_Localization.Nearband: { SlipArea = this.LsTrk.GridDat.BoundaryCells.VolumeMask.Intersect(this.LsTrk.Regions.GetNearFieldMask(this.LsTrk.NearRegionWidth)); break; } case NavierSlip_Localization.Prescribed: { throw new NotImplementedException(); } default: throw new ArgumentException(); } MultidimensionalArray SlipLengths; SlipLengths = this.LsTrk.GridDat.Cells.h_min.CloneAs(); SlipLengths.Clear(); //SlipLengths.AccConstant(-1.0); if (SlipArea != null) { foreach (Chunk cnk in SlipArea) { for (int i = cnk.i0; i < cnk.JE; i++) { switch (this.dntParams.GNBC_SlipLength) { case NavierSlip_SlipLength.hmin_DG: { int degU = ColMapping.BasisS.ToArray()[0].Degree; SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i] / (degU + 1); break; } case NavierSlip_SlipLength.hmin_Grid: { SlipLengths[i] = SlipLengths[i] = this.LsTrk.GridDat.Cells.h_min[i]; break; } case NavierSlip_SlipLength.Prescribed_SlipLength: { SlipLengths[i] = this.physParams.sliplength; break; } case NavierSlip_SlipLength.Prescribed_Beta: { SlipLengths[i] = -1.0; break; } } } } } // parameter assembly // ================== LevelSet Phi = (LevelSet)(this.LsTrk.LevelSets[0]); SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); // normals: SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions. if (this.NormalsRequired) { if (LevelSetGradient == null) { LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory); LevelSetGradient.Gradient(1.0, Phi); } Normals = LevelSetGradient.ToArray(); } else { Normals = new SinglePhaseField[D]; } // curvature: SinglePhaseField Curvature; if (this.CurvatureRequired) { Curvature = ExternalyProvidedCurvature; } else { Curvature = null; } // Velocity and stresses for linearization // linearization velocity: DGField[] U0_U0mean; if (this.U0meanrequired) { XDGBasis U0meanBasis = new XDGBasis(this.LsTrk, 0); VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory); U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean); } else { U0_U0mean = new DGField[2 * D]; } if (VelocityXGradient == null) { VelocityXGradient = new VectorField <XDGField>(D, CurrentState.ElementAt(0).Basis, "VelocityX_Gradient", XDGField.Factory); } if (VelocityYGradient == null) { VelocityYGradient = new VectorField <XDGField>(D, CurrentState.ElementAt(1).Basis, "VelocityY_Gradient", XDGField.Factory); } // concatenate everything var Params = ArrayTools.Cat <DGField>( U0_U0mean, VelocityXGradient, VelocityYGradient, Stress0, //artificalViscosity, Normals, Curvature, ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D])); // linearization velocity: if (this.U0meanrequired) { VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray()); U0mean.Clear(); if (this.physParams.IncludeConvection) { ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper); } } // assemble the matrix & affine vector // =================================== IDictionary <SpeciesId, MultidimensionalArray> InterfaceLengths = this.LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), CutCellQuadOrder).CutCellMetrics.InterfaceArea; BitArray EvapMicroRegion = this.LsTrk.GridDat.GetBoundaryCells().GetBitMask(); EvapMicroRegion.SetAll(false); // compute matrix if (OpMatrix != null) { if (!useJacobianForOperatorMatrix) { XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = this.m_XOp.GetMatrixBuilder(LsTrk, ColMapping, Params, RowMapping, SpcToCompute); this.ParameterUpdate(CurrentState, Params, CutCellQuadOrder, AgglomeratedCellLengthScales); foreach (var kv in AgglomeratedCellLengthScales) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; mtxBuilder.SpeciesOperatorCoefficients[kv.Key].EdgeLengthScales = this.LsTrk.GridDat.Edges.h_max_Edge; mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("EvapMicroRegion", EvapMicroRegion); } if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); } } mtxBuilder.time = time; mtxBuilder.ComputeMatrix(OpMatrix, OpAffine); foreach (var kv in AgglomeratedCellLengthScales) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("Weissenbergnumber", currentWeissenberg); } } else { throw new NotImplementedException("The FDbuilder for the Jacobian is missing for the XSpatial Opearator!"); // Finite Difference Linearization //XSpatialOperatorMk2.XEvaluatorLinear FDBuilder = this.m_XOp.GetFDJacobianBuilder(domMap, Params, codMap, this.ParameterUpdate); //foreach (var kv in AgglomeratedCellLengthScales) { // FDbuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; // FDbuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); // FDbuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("EvapMicroRegion", EvapMicroRegion); //} //if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0) { // foreach (var kv in InterfaceLengths) { // FDbuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); // } //} //FDbuilder.time = time; //FDbuilder.ComputeMatrix(OpMatrix, OpAffine); //// FDJacobian has (Mx +b) as RHS, for unsteady calc. we must subtract Mx for real affine Vector! //OpMatrix.SpMV(-1.0, new CoordinateVector(CurrentState), 1.0, OpAffine); //foreach (var kv in AgglomeratedCellLengthScales) { // FDbuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("Weissenbergnumber", currentWeissenberg); //} } } else { XSpatialOperatorMk2.XEvaluatorNonlin eval = this.m_XOp.GetEvaluatorEx(this.LsTrk, CurrentState.ToArray(), Params, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; eval.SpeciesOperatorCoefficients[kv.Key].EdgeLengthScales = this.LsTrk.GridDat.Edges.h_max_Edge; eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("SlipLengths", SlipLengths); eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("EvapMicroRegion", EvapMicroRegion); eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("Weissenbergnumber", currentWeissenberg); } if (this.m_XOp.SurfaceElementOperator.TotalNoOfComponents > 0) { foreach (var kv in InterfaceLengths) { eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("InterfaceLengths", kv.Value); } } eval.time = time; eval.Evaluate(1.0, 1.0, OpAffine); } }
/// <summary> /// /// </summary> public void AssembleMatrix_Timestepper <T>( int CutCellQuadOrder, BlockMsrMatrix OpMatrix, double[] OpAffine, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, IEnumerable <T> U0, VectorField <SinglePhaseField> SurfaceForce, VectorField <SinglePhaseField> LevelSetGradient, SinglePhaseField ExternalyProvidedCurvature, UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping, double time) where T : DGField { if (ColMapping.BasisS.Count != this.Op.DomainVar.Count) { throw new ArgumentException(); } if (RowMapping.BasisS.Count != this.Op.CodomainVar.Count) { throw new ArgumentException(); } // check: var Tracker = this.LsTrk; int D = Tracker.GridDat.SpatialDimension; if (U0 != null && U0.Count() != D) { throw new ArgumentException(); } LevelSet Phi = (LevelSet)(Tracker.LevelSets[0]); SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); // parameter assembly // ================== // normals: SinglePhaseField[] Normals; // Normal vectors: length not normalized - will be normalized at each quad node within the flux functions. if (this.NormalsRequired) { if (LevelSetGradient == null) { LevelSetGradient = new VectorField <SinglePhaseField>(D, Phi.Basis, SinglePhaseField.Factory); LevelSetGradient.Gradient(1.0, Phi); } Normals = LevelSetGradient.ToArray(); } else { Normals = new SinglePhaseField[D]; } // curvature: SinglePhaseField Curvature; if (this.CurvatureRequired) { Curvature = ExternalyProvidedCurvature; } else { Curvature = null; } // linearization velocity: DGField[] U0_U0mean; if (this.U0meanrequired) { XDGBasis U0meanBasis = new XDGBasis(Tracker, 0); VectorField <XDGField> U0mean = new VectorField <XDGField>(D, U0meanBasis, "U0mean_", XDGField.Factory); U0_U0mean = ArrayTools.Cat <DGField>(U0, U0mean); } else { U0_U0mean = new DGField[2 * D]; } // concatenate everything var Params = ArrayTools.Cat <DGField>( U0_U0mean, Curvature, ((SurfaceForce != null) ? SurfaceForce.ToArray() : new SinglePhaseField[D]), Normals); // linearization velocity: if (this.U0meanrequired) { VectorField <XDGField> U0mean = new VectorField <XDGField>(U0_U0mean.Skip(D).Take(D).Select(f => ((XDGField)f)).ToArray()); U0mean.Clear(); if (this.physParams.IncludeConvection) { ComputeAverageU(U0, U0mean, CutCellQuadOrder, LsTrk.GetXDGSpaceMetrics(SpcToCompute, CutCellQuadOrder, 1).XQuadSchemeHelper); } } // assemble the matrix & affine vector // =================================== // compute matrix Op.ComputeMatrixEx(Tracker, ColMapping, Params, RowMapping, OpMatrix, OpAffine, false, time, true, AgglomeratedCellLengthScales, SpcToCompute); }
/// <summary> /// /// </summary> /// <param name="ProblemMapping"></param> /// <param name="MultigridSequence"></param> /// <param name="useX"> /// Create an XDG aggregation basis even if <paramref name="ProblemMapping"/> only contains DG basis. /// </param> /// <returns></returns> public static AggregationGridBasis[][] CreateAggregationGridBasis(UnsetteledCoordinateMapping ProblemMapping, LevelSetTracker _LsTrk, AggregationGrid[] MultigridSequence, bool useX) { Debug.Assert(object.ReferenceEquals(_LsTrk.GridDat, ProblemMapping.GridDat)); Basis[] BasisS = ProblemMapping.BasisS.ToArray(); Debug.Assert(BasisS.Where(b => !object.ReferenceEquals(b.GridDat, _LsTrk.GridDat)).Count() == 0); AggregationGridBasis[][] MultigridBasis = new AggregationGridBasis[MultigridSequence.Length][]; XDGBasis maxXDGbasis = null; Basis maxDGbasis = null; foreach (var b in BasisS) { if (b is XDGBasis) { XDGBasis xb = (XDGBasis)b; if (maxXDGbasis == null || maxXDGbasis.Degree < xb.Degree) { maxXDGbasis = xb; } } else { if (maxDGbasis == null || maxDGbasis.Degree < b.Degree) { maxDGbasis = b; } } } if (useX) { if (maxDGbasis != null) { if (maxXDGbasis == null || maxXDGbasis.Degree < maxDGbasis.Degree) { maxXDGbasis = new XDGBasis(_LsTrk, maxDGbasis.Degree); } } } XdgAggregationBasis[] mgXdgB; if (maxXDGbasis != null) { mgXdgB = MultigridSequence.Select(aggGrd => new XdgAggregationBasis(maxXDGbasis, aggGrd)).ToArray(); } else { mgXdgB = null; } AggregationGridBasis[] mgDgB; if (maxDGbasis != null) { mgDgB = MultigridSequence.Select(aggGrd => new AggregationGridBasis(maxDGbasis, aggGrd)).ToArray(); } else { mgDgB = null; } for (int iLevel = 0; iLevel < MultigridSequence.Length; iLevel++) { MultigridBasis[iLevel] = new AggregationGridBasis[BasisS.Length]; for (int r = 0; r < BasisS.Length; r++) { if (BasisS[r] is XDGBasis || useX) { MultigridBasis[iLevel][r] = mgXdgB[iLevel]; } else { MultigridBasis[iLevel][r] = mgDgB[iLevel]; } } } return(MultigridBasis); }
protected override void CreateFields() { // Create level set and level set tracker this.LevelSet = new LevelSet(new Basis(this.GridData, this.Control.LevelSetDegree), XDGShockVariables.LevelSet); this.LevelSetTracker = new LevelSetTracker((GridData)this.GridData, XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes, 1, new string[] { "A", "B" }, this.LevelSet); base.LsTrk = this.LevelSetTracker; // Create mandatory conservative fields int D = CompressibleEnvironment.NumberOfDimensions; this.Density = new XDGField(new XDGBasis(this.LevelSetTracker, this.Control.DensityDegree), CompressibleVariables.Density); XDGField[] momentumFields = new XDGField[D]; XDGBasis momentumBasis = new XDGBasis(this.LevelSetTracker, this.Control.MomentumDegree); for (int d = 0; d < D; d++) { string variableName = CompressibleVariables.Momentum[d]; momentumFields[d] = new XDGField(momentumBasis, variableName); } this.Momentum = new VectorField <XDGField>(momentumFields); this.Energy = new XDGField(new XDGBasis(this.LevelSetTracker, this.Control.EnergyDegree), CompressibleVariables.Energy); // Create fields for residuals XDGBasis basis = new XDGBasis(this.LevelSetTracker, this.Control.DensityDegree); this.Residuals = new XDGField[D + 2]; this.Residuals[0] = new XDGField(basis, "residual_" + CompressibleVariables.Density); for (int d = 0; d < D; d++) { this.Residuals[d + 1] = new XDGField(basis, "residual_" + CompressibleVariables.Momentum[d]); } this.Residuals[D + 1] = new XDGField(basis, "residual_" + CompressibleVariables.Energy); // Create derived fields this.DerivedVariableToXDGFieldMap = new Dictionary <DerivedVariable <XDGField>, XDGField>(); this.DerivedVariableToSinglePhaseFieldMap = new Dictionary <DerivedVariable <SinglePhaseField>, SinglePhaseField>(); foreach (KeyValuePair <Variable, int> pair in this.Control.VariableToDegreeMap) { Variable variable = pair.Key; int degree = pair.Value; if (variable is DerivedVariable <XDGField> xdgVar) { this.DerivedVariableToXDGFieldMap.Add(xdgVar, new XDGField(new XDGBasis(this.LevelSetTracker, degree), variable.Name)); } else if (variable is DerivedVariable <SinglePhaseField> singleVar) { this.DerivedVariableToSinglePhaseFieldMap.Add(singleVar, new SinglePhaseField(new Basis(this.GridData, degree), variable.Name)); } } // Register all fields for plotting // Fields for the conservative variables are plotted in any case this.m_IOFields.Add(LevelSet); this.m_IOFields.AddRange(ConservativeFields); this.m_IOFields.AddRange(DerivedVariableToXDGFieldMap.Values); this.m_IOFields.AddRange(DerivedVariableToSinglePhaseFieldMap.Values); // Register fields for, e.g. applying the initial conditions; this.m_RegisteredFields.Add(LevelSet); this.m_RegisteredFields.AddRange(ConservativeFields); this.m_RegisteredFields.AddRange(DerivedVariableToXDGFieldMap.Values); this.m_RegisteredFields.AddRange(DerivedVariableToSinglePhaseFieldMap.Values); // Add sensor if (this.Control.SensorVariable != null) { switch (this.Control.SensorType) { case SensorTypes.PerssonSensor: this.Sensor = new XDGPerssonSensor(ConservativeFields.First(s => s.Identification.Equals(this.Control.SensorVariable)), this.Control.SensorLimit, this.LevelSetTracker, this.NonlinearQuadratureDegree); break; default: throw new NotImplementedException(); } } // Initialize artificial viscosity field, if artificial viscosity has been activated in the control file if (this.Control.VariableToDegreeMap.ContainsKey(XDGShockVariables.ArtificialViscosity)) { this.ArtificialViscosityField = new SinglePhaseField(new Basis(this.GridData, 2), "artificialViscosity"); switch (this.Control.ArtificialViscosityLawType) { case ArtificialViscosityLawTypes.SmoothedHeaviside: this.ArtificialViscosityLaw = new SmoothedHeavisideArtificialViscosityLaw(this.Sensor, ConservativeFields.First(s => s.Identification.Equals(this.Control.SensorVariable)).Basis.Degree, this.Control.SensorLimit); break; default: throw new NotImplementedException(); } } }