void DelComputeOperatorMatrix(BlockMsrMatrix OpMtx, double[] OpAffine, UnsetteledCoordinateMapping Mapping, DGField[] CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double phystime) { DGField[] Params = null; if (this.Control.Eq == Equation.ScalarTransport) { Params = this.V.ToArray(); } else if (this.Control.Eq == Equation.HeatEq) { Params = null; } else if (this.Control.Eq == Equation.Burgers) { Params = CurrentState; } else { throw new NotImplementedException(); } // compute operator Debug.Assert(OpMtx.InfNorm() == 0.0); Debug.Assert(OpAffine.L2Norm() == 0.0); //Operator.ComputeMatrixEx(this.LsTrk, // Mapping, Params, Mapping, // OpMtx, OpAffine, false, phystime, true, // AgglomeratedCellLengthScales, null, null, // AgglomeratedCellLengthScales.Keys.ToArray()); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator.GetMatrixBuilder(this.LsTrk, Mapping, Params, Mapping, AgglomeratedCellLengthScales.Keys.ToArray()); mtxBuilder.time = phystime; mtxBuilder.MPITtransceive = true; mtxBuilder.ComputeMatrix(OpMtx, OpAffine); }
protected virtual void DelComputeOperatorMatrix(BlockMsrMatrix OpMatrix, double[] OpAffine, UnsetteledCoordinateMapping Mapping, DGField[] CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double phystime) { OpAffine.ClearEntries(); bool Eval = false; if (OpMatrix == null) { Eval = true; OpMatrix = new BlockMsrMatrix(uResidual.Mapping, u.Mapping); } else { OpMatrix.Clear(); } //Op.ComputeMatrixEx(base.LsTrk, // u.Mapping, null, uResidual.Mapping, // OpMatrix, OpAffine, false, // phystime, // false, // base.LsTrk.SpeciesIdS.ToArray()); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, u.Mapping, null, uResidual.Mapping); mtxBuilder.CellLengthScales.AddRange(AgglomeratedCellLengthScales); mtxBuilder.time = phystime; mtxBuilder.ComputeMatrix(OpMatrix, OpAffine); if (Eval) { OpMatrix.SpMV(1.0, new CoordinateVector(CurrentState), 1.0, OpAffine); } }
protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { //phystime = 1.8; LsUpdate(phystime); // operator-matrix assemblieren OperatorMatrix = new BlockMsrMatrix(ProblemMapping); AltOperatorMatrix = new MsrMatrix(ProblemMapping); double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength]; MultiphaseCellAgglomerator Agg; // Agglomerator setup //Agg = new MultiphaseCellAgglomerator(new CutCellMetrics(MomentFittingVariant, m_quadOrder, LsTrk, LsTrk.GetSpeciesId("B")), this.THRESHOLD, false); Agg = LsTrk.GetAgglomerator(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, m_quadOrder, __AgglomerationTreshold: this.THRESHOLD); Console.WriteLine("Inter-Process agglomeration? " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.InterProcessAgglomeration); // operator matrix assembly //Op.ComputeMatrixEx(LsTrk, // ProblemMapping, null, ProblemMapping, // OperatorMatrix, Affine, false, 0.0, true, // Agg.CellLengthScales, null, null, // LsTrk.SpeciesIdS.ToArray()); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, ProblemMapping, null, ProblemMapping, LsTrk.SpeciesIdS.ToArray()); mtxBuilder.time = 0.0; mtxBuilder.ComputeMatrix(OperatorMatrix, Affine); Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, this.ProblemMapping, this.ProblemMapping); //Op.ComputeMatrixEx(LsTrk, // ProblemMapping, null, ProblemMapping, // AltOperatorMatrix, Affine, false, 0.0, true, // Agg.CellLengthScales, null, null, // LsTrk.SpeciesIdS.ToArray()); mtxBuilder.ComputeMatrix(AltOperatorMatrix, Affine); Agg.ManipulateMatrixAndRHS(AltOperatorMatrix, Affine, this.ProblemMapping, this.ProblemMapping); int nnz = this.OperatorMatrix.GetTotalNoOfNonZeros(); Console.WriteLine("Number of non-zeros in matrix: " + nnz); int nnz2 = this.AltOperatorMatrix.GetTotalNoOfNonZeros(); Assert.IsTrue(nnz == nnz2, "Number of non-zeros in matrix different for " + OperatorMatrix.GetType() + " and " + AltOperatorMatrix.GetType()); Console.WriteLine("Number of non-zeros in matrix (reference): " + nnz2); MsrMatrix Comp = AltOperatorMatrix.CloneAs(); Comp.Acc(-1.0, OperatorMatrix); double CompErr = Comp.InfNorm(); double Denom = Math.Max(AltOperatorMatrix.InfNorm(), OperatorMatrix.InfNorm()); double CompErrRel = Denom > Math.Sqrt(double.Epsilon) ? CompErr / Denom : CompErr; Console.WriteLine("Comparison: " + CompErrRel); Assert.LessOrEqual(CompErrRel, 1.0e-7, "Huge difference between MsrMatrix and BlockMsrMatrix."); base.TerminationKey = true; return(0.0); }
/// <summary> /// base matrix assembly /// </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="ParamsMap"></param> /// <param name="AgglomeratedCellLengthScales"></param> /// <param name="time"></param> public void AssembleMatrix <T>(BlockMsrMatrix OpMatrix, double[] OpAffine, UnsetteledCoordinateMapping RowMapping, UnsetteledCoordinateMapping ColMapping, IEnumerable <T> CurrentState, IList <DGField> ParamsMap, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double time) where T : DGField { // checks if (ColMapping.BasisS.Count != m_XOp.DomainVar.Count) { throw new ArgumentException(); } if (RowMapping.BasisS.Count != m_XOp.CodomainVar.Count) { throw new ArgumentException(); } if (OpMatrix == null && CurrentState == null) { throw new ArgumentException(); } SpeciesId[] SpcToCompute = AgglomeratedCellLengthScales.Keys.ToArray(); if (OpMatrix != null) { XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = m_XOp.GetMatrixBuilder(LsTrk, ColMapping, ParamsMap, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; } mtxBuilder.time = time; mtxBuilder.ComputeMatrix(OpMatrix, OpAffine); } else { XSpatialOperatorMk2.XEvaluatorNonlin eval = m_XOp.GetEvaluatorEx(this.LsTrk, CurrentState.ToArray(), ParamsMap, RowMapping, SpcToCompute); foreach (var kv in AgglomeratedCellLengthScales) { eval.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; } eval.time = time; eval.Evaluate(1.0, 1.0, OpAffine); } }
/// <summary> /// Create Spatial Operators and build the corresponding Matrices /// </summary> public void UpdateRHS(SinglePhaseField Extension, SinglePhaseField InterfaceValue, bool nearfield) { this.Extension = Extension; OpAffine.Clear(); //XSpatialOperatorExtensions.ComputeMatrixEx(Operator_interface, ////Operator_interface.ComputeMatrixEx( // LevelSetTracker, // Extension.Mapping, // new List<DGField> { InterfaceValue }, // Extension.Mapping, // OpMatrix_interface, // OpAffine_interface, // OnlyAffine: true, // time: 0, // MPIParameterExchange: false, // whichSpc: LevelSetTracker.GetSpeciesId("A"), // subGrid: nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1) : null // ); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker, Extension.Mapping, new List <DGField> { InterfaceValue }, Extension.Mapping); mtxBuilder.time = 0; mtxBuilder.MPITtransceive = false; mtxBuilder.ComputeAffine(OpAffine_interface); if (OpAffine.L2Norm() == 0) { Console.WriteLine("RHS of Bulk equation is empty as expected."); } OpAffine.Clear(); OpAffine.AccV(1.0, OpAffine_bulk); OpAffine.AccV(1.0, OpAffine_interface); }
/// <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."); * } */ }
private void AssembleMatrix(double MU_A, double MU_B, out BlockMsrMatrix M, out double[] b, out MultiphaseCellAgglomerator agg, out MassMatrixFactory massFact) { using (var tr = new FuncTrace()) { // create operator // =============== if (this.Control.SetDefaultDiriBndCnd) { this.Control.xLaplaceBCs.g_Diri = ((CommonParamsBnd inp) => 0.0); this.Control.xLaplaceBCs.IsDirichlet = (inp => true); } double D = this.GridData.SpatialDimension; int p = u.Basis.Degree; double penalty_base = (p + 1) * (p + D) / D; double penalty_multiplyer = base.Control.penalty_multiplyer; XQuadFactoryHelper.MomentFittingVariants momentFittingVariant; if (D == 3) { momentFittingVariant = XQuadFactoryHelper.MomentFittingVariants.Classic; } momentFittingVariant = this.Control.CutCellQuadratureType; int order = this.u.Basis.Degree * 2; Op = new XSpatialOperatorMk2(1, 1, (A, B, C) => order, this.LsTrk.SpeciesNames, "u", "c1"); var lengthScales = ((BoSSS.Foundation.Grid.Classic.GridData)GridData).Cells.PenaltyLengthScales; var lap = new XLaplace_Bulk(this.LsTrk, penalty_multiplyer * penalty_base, "u", this.Control.xLaplaceBCs, 1.0, MU_A, MU_B, lengthScales, this.Control.ViscosityMode); Op.EquationComponents["c1"].Add(lap); // Bulk form Op.EquationComponents["c1"].Add(new XLaplace_Interface(this.LsTrk, MU_A, MU_B, penalty_base * 2, this.Control.ViscosityMode)); // coupling form Op.Commit(); // create agglomeration // ==================== var map = new UnsetteledCoordinateMapping(u.Basis); //agg = new MultiphaseCellAgglomerator( // new CutCellMetrics(momentFittingVariant, // QuadOrderFunc.SumOfMaxDegrees(RoundUp: true)(map.BasisS.Select(bs => bs.Degree).ToArray(), new int[0], map.BasisS.Select(bs => bs.Degree).ToArray()), // //this.HMFDegree, // LsTrk, this.LsTrk.SpeciesIdS.ToArray()), // this.Control.AgglomerationThreshold, false); agg = LsTrk.GetAgglomerator(this.LsTrk.SpeciesIdS.ToArray(), order, this.Control.AgglomerationThreshold); // compute matrix // ============= using (new BlockTrace("XdgMatrixAssembly", tr)) { M = new BlockMsrMatrix(map, map); b = new double[M.RowPartitioning.LocalLength]; //Op.ComputeMatrixEx(LsTrk, // map, null, map, // M, b, false, 0.0, true, // agg.CellLengthScales, null, null, //out massFact, // this.LsTrk.SpeciesIdS.ToArray()); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(this.LsTrk, map, null, map); mtxBuilder.CellLengthScales.AddRange(agg.CellLengthScales); mtxBuilder.time = 0.0; mtxBuilder.MPITtransceive = true; mtxBuilder.ComputeMatrix(M, b); } // compare with linear evaluation // ============================== DGField[] testDomainFieldS = map.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray(); CoordinateVector test = new CoordinateVector(testDomainFieldS); DGField[] errFieldS = map.BasisS.Select(bb => new XDGField(bb as XDGBasis)).ToArray(); CoordinateVector Err = new CoordinateVector(errFieldS); var eval = Op.GetEvaluatorEx(LsTrk, testDomainFieldS, null, map); eval.CellLengthScales.AddRange(agg.CellLengthScales); eval.time = 0.0; 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, b); M.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(); Assert.LessOrEqual(ErrDist, Ref * 1.0e-5, "Mismatch between explicit evaluation of XDG operator and matrix."); // agglomeration wahnsinn // ====================== agg.ManipulateMatrixAndRHS(M, b, map, map); foreach (var S in this.LsTrk.SpeciesNames) { Console.WriteLine(" Species {0}: no of agglomerated cells: {1}", S, agg.GetAgglomerator(this.LsTrk.GetSpeciesId(S)).AggInfo.SourceCells.NoOfItemsLocally); } // mass matrix factory // =================== Basis maxB = map.BasisS.ElementAtMax(bss => bss.Degree); //massFact = new MassMatrixFactory(maxB, agg); massFact = LsTrk.GetXDGSpaceMetrics(this.LsTrk.SpeciesIdS.ToArray(), order).MassMatrixFactory; } }
// Local Variables for Iteration // <summary> // Counter for Iteration Steps // </summary> //double OldResidual = double.MaxValue; //int divergencecounter = 0; ///// <summary> ///// Checks for Reaching Max. Number of Iterations and Divergence of Algorithm ///// </summary> ///// <param name="Residual">Change Rate of the Algorithm</param> ///// <returns>Reaching Max Iterations, Aborts when diverged</returns> //public bool CheckAbortCriteria(double Residual, int IterationCounter) { // if (Residual <= ConvergenceCriterion) { // Console.WriteLine("EllipticReInit converged after {0} Iterations ", IterationCounter); // return true; // } // if (Residual >= OldResidual) divergencecounter++; // else divergencecounter = 0; // if (IterationCounter >= MaxIteration) { // Console.WriteLine("Elliptic Reinit Max Iterations Reached"); // return true; // }; // if (divergencecounter > MaxIteration / 2) { // Console.WriteLine("Elliptic Reinit diverged - Aborting"); // throw new ApplicationException(); // } // OldResidual = Residual; // IterationCounter++; // return false; //} //bool PreviouslyOnSubgrid = false; /// <summary> /// Updates the Operator Matrix after level-set motion /// </summary> /// <param name="Restriction"> /// The subgrid, on which the ReInit is performed /// </param> /// <param name="IncludingInterface"> /// !! Not yet functional !! /// True, if the subgrid contains the interface, this causes all external edges of the subgrid to be treated as boundaries /// False, for the rest of the domain, thus the flux to the adjacent cells wil be evaluated /// </param> public void UpdateOperators(SubGrid Restriction = null, bool IncludingInterface = true) { if (!IncludingInterface) { throw new NotImplementedException("Untested, not yet functional!"); } using (new FuncTrace()) { //using (var slv = new ilPSP.LinSolvers.MUMPS.MUMPSSolver()) { //using (var slv = new ilPSP.LinSolvers.PARDISO.PARDISOSolver()) { //using (var slv = new ilPSP.LinSolvers.HYPRE.GMRES()) { if (Control.Upwinding) { OldPhi.Clear(); OldPhi.Acc(1.0, Phi); //Calculate LevelSetGradient.Clear(); LevelSetGradient.Gradient(1.0, Phi, Restriction?.VolumeMask); //LevelSetGradient.Gradient(1.0, Phi); //LevelSetGradient.GradientByFlux(1.0, Phi); MeanLevelSetGradient.Clear(); MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient, Restriction?.VolumeMask); //MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient); } if (slv != null) { slv.Dispose(); } slv = Control.solverFactory(); OpMatrix_interface.Clear(); OpAffine_interface.Clear(); // Build the Quadrature-Scheme for the interface operator // Note: The HMF-Quadrature over a surface is formally a volume quadrature, since it uses the volume quadrature nodes. //XSpatialOperatorExtensions.ComputeMatrixEx(Operator_interface, ////Operator_interface.ComputeMatrixEx( // LevelSetTracker, // Phi.Mapping, // null, // Phi.Mapping, // OpMatrix_interface, // OpAffine_interface, // false, // 0, // false, // subGrid:Restriction, // whichSpc: LevelSetTracker.GetSpeciesId("A") // ); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker, Phi.Mapping, null, Phi.Mapping); MultiphaseCellAgglomerator dummy = LevelSetTracker.GetAgglomerator(LevelSetTracker.SpeciesIdS.ToArray(), Phi.Basis.Degree * 2 + 2, 0.0); //mtxBuilder.SpeciesOperatorCoefficients[LevelSetTracker.GetSpeciesId("A")].CellLengthScales = dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]; mtxBuilder.CellLengthScales.Add(LevelSetTracker.GetSpeciesId("A"), dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]); mtxBuilder.time = 0; mtxBuilder.MPITtransceive = false; mtxBuilder.ComputeMatrix(OpMatrix_interface, OpAffine_interface); // Regenerate OpMatrix for subgrid -> adjacent cells must be trated as boundary if (Restriction != null) { OpMatrix_bulk.Clear(); OpAffine_bulk.Clear(); //Operator_bulk.ComputeMatrix( // Phi.Mapping, // parameterFields, // Phi.Mapping, // OpMatrix_bulk, OpAffine_bulk, // OnlyAffine: false, sgrd: Restriction); EdgeQuadratureScheme edgescheme; //if (Control.Upwinding) { // edgescheme = new EdgeQuadratureScheme(true, IncludingInterface ? Restriction.AllEdgesMask : null); //} //else { edgescheme = new EdgeQuadratureScheme(true, IncludingInterface ? Restriction.InnerEdgesMask : null); //} Operator_bulk.ComputeMatrixEx(Phi.Mapping, parameterFields, Phi.Mapping, OpMatrix_bulk, OpAffine_bulk, false, 0, edgeQuadScheme: edgescheme, volQuadScheme: new CellQuadratureScheme(true, IncludingInterface ? Restriction.VolumeMask : null) ); //PreviouslyOnSubgrid = true; } // recalculate full Matrix //else if (PreviouslyOnSubgrid) { else { OpMatrix_bulk.Clear(); OpAffine_bulk.Clear(); Operator_bulk.ComputeMatrixEx(Phi.Mapping, parameterFields, Phi.Mapping, OpMatrix_bulk, OpAffine_bulk, false, 0 ); //PreviouslyOnSubgrid = false; } /// Compose the Matrix /// This is symmetric due to the symmetry of the SIP and the penalty term OpMatrix.Clear(); OpMatrix.Acc(1.0, OpMatrix_bulk); OpMatrix.Acc(1.0, OpMatrix_interface); OpMatrix.AssumeSymmetric = !Control.Upwinding; //OpMatrix.AssumeSymmetric = false; /// Compose the RHS of the above operators. (-> Boundary Conditions) /// This does NOT include the Nonlinear RHS, which will be added later OpAffine.Clear(); OpAffine.AccV(1.0, OpAffine_bulk); OpAffine.AccV(1.0, OpAffine_interface); #if Debug ilPSP.Connectors.Matlab.BatchmodeConnector matlabConnector; matlabConnector = new BatchmodeConnector(); #endif if (Restriction != null) { SubVecIdx = Phi.Mapping.GetSubvectorIndices(Restriction, true, new int[] { 0 }); int L = SubVecIdx.Length; SubMatrix = new MsrMatrix(L); SubRHS = new double[L]; SubSolution = new double[L]; OpMatrix.AccSubMatrixTo(1.0, SubMatrix, SubVecIdx, default(int[]), SubVecIdx, default(int[])); slv.DefineMatrix(SubMatrix); #if Debug Console.WriteLine("ConditionNumber of ReInit-Matrix is " + SubMatrix.condest().ToString("E")); #endif } else { slv.DefineMatrix(OpMatrix); #if Debug Console.WriteLine("ConditionNumber of ReInit-Matrix is " + OpMatrix.condest().ToString("E")); #endif } } }
/// <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); } }
protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { Console.WriteLine(" Timestep # " + TimestepNo + ", phystime = " + phystime); //phystime = 1.8; LsUpdate(phystime); // operator-matrix assemblieren MsrMatrix OperatorMatrix = new MsrMatrix(u.Mapping, u.Mapping); double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength]; // Agglomerator setup MultiphaseCellAgglomerator Agg = LsTrk.GetAgglomerator(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, QuadOrder, this.THRESHOLD); // plausibility of cell length scales if (SER_PAR_COMPARISON) { TestLengthScales(QuadOrder, TimestepNo); } Console.WriteLine("Inter-Process agglomeration? " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.InterProcessAgglomeration); if (this.THRESHOLD > 0.01) { TestAgglomeration_Extraploation(Agg); TestAgglomeration_Projection(QuadOrder, Agg); } CheckExchange(true); CheckExchange(false); // operator matrix assembly XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, u.Mapping, null, u.Mapping); mtxBuilder.time = 0.0; mtxBuilder.ComputeMatrix(OperatorMatrix, Affine); Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, u.Mapping, u.Mapping); // mass matrix factory var Mfact = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, QuadOrder, 1).MassMatrixFactory;// new MassMatrixFactory(u.Basis, Agg); // Mass matrix/Inverse Mass matrix //var MassInv = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, true, LsTrk.GetSpeciesId("B")); var Mass = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, false, LsTrk.GetSpeciesId("B")); Agg.ManipulateMatrixAndRHS(Mass, default(double[]), u.Mapping, u.Mapping); var MassInv = Mass.InvertBlocks(OnlyDiagonal: true, Subblocks: true, ignoreEmptyBlocks: true, SymmetricalInversion: false); // test that operator depends only on B-species values double DepTest = LsTrk.Regions.GetSpeciesSubGrid("B").TestMatrixDependency(OperatorMatrix, u.Mapping, u.Mapping); Console.WriteLine("Matrix dependency test: " + DepTest); Assert.LessOrEqual(DepTest, 0.0); // diagnostic output Console.WriteLine("Number of Agglomerations (all species): " + Agg.TotalNumberOfAgglomerations); Console.WriteLine("Number of Agglomerations (species 'B'): " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.SourceCells.NoOfItemsLocally.MPISum()); // operator auswerten: double[] x = new double[Affine.Length]; BLAS.daxpy(x.Length, 1.0, Affine, 1, x, 1); OperatorMatrix.SpMVpara(1.0, u.CoordinateVector, 1.0, x); MassInv.SpMV(1.0, x, 0.0, du_dx.CoordinateVector); Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).Extrapolate(du_dx.Mapping); // markieren, wo ueberhaupt A und B sind Bmarker.AccConstant(1.0, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); Amarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("A").VolumeMask); if (usePhi0 && usePhi1) { Xmarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("X").VolumeMask); } // compute error ERR.Clear(); ERR.Acc(1.0, du_dx_Exact, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); ERR.Acc(-1.0, du_dx, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); double L2Err = ERR.L2Norm(LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); Console.WriteLine("L2 Error: " + L2Err); XERR.Clear(); XERR.GetSpeciesShadowField("B").Acc(1.0, ERR, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); double xL2Err = XERR.L2Norm(); Console.WriteLine("L2 Error (in XDG space): " + xL2Err); // check error double ErrorThreshold = 1.0e-1; if (this.MomentFittingVariant == XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes) { ErrorThreshold = 1.0e-6; // HMF is designed for such integrands and should perform close to machine accuracy; on general integrands, the precision is different. } bool IsPassed = ((L2Err <= ErrorThreshold || this.THRESHOLD <= ErrorThreshold) && xL2Err <= ErrorThreshold); if (IsPassed) { Console.WriteLine("Test PASSED"); } else { Console.WriteLine("Test FAILED: check errors."); //PlotCurrentState(phystime, TimestepNo, 3); } if (TimestepNo > 1) { if (this.THRESHOLD > ErrorThreshold) { // without agglomeration, the error in very tiny cut-cells may be large over the whole cell // However, the error in the XDG-space should be small under all circumstances Assert.LessOrEqual(L2Err, ErrorThreshold, "DG L2 error of computing du_dx"); } Assert.LessOrEqual(xL2Err, ErrorThreshold, "XDG L2 error of computing du_dx"); } // return/Ende base.NoOfTimesteps = 17; //base.NoOfTimesteps = 2; dt = 0.3; return(dt); }
/// <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); } }
protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { LsUpdate(phystime); // operator-matrix assemblieren OperatorMatrix = new BlockMsrMatrix(MG_Mapping.ProblemMapping); AltOperatorMatrix = new MsrMatrix(MG_Mapping.ProblemMapping); double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength]; MultiphaseCellAgglomerator Agg; Agg = LsTrk.GetAgglomerator(this.LsTrk.SpeciesIdS.ToArray(), m_quadOrder, __AgglomerationTreshold: this.THRESHOLD); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, MG_Mapping.ProblemMapping, null, MG_Mapping.ProblemMapping); mtxBuilder.time = 0.0; mtxBuilder.ComputeMatrix(OperatorMatrix, Affine); Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, MG_Mapping.ProblemMapping, MG_Mapping.ProblemMapping); foreach (var S in this.LsTrk.SpeciesNames) { Console.WriteLine(" Species {0}: no of agglomerated cells: {1}", S, Agg.GetAgglomerator(this.LsTrk.GetSpeciesId(S)).AggInfo.SourceCells.NoOfItemsLocally); } MGOp = new MultigridOperator(XAggB, map, OperatorMatrix, this.massFact.GetMassMatrix(map, false), OpConfig, null); Debug.Assert(MGOp.OperatorMatrix != null); Debug.Assert(MGOp.Mapping != null); someVec = GetRHS(Affine, OperatorMatrix); mtxBuilder.ComputeMatrix(AltOperatorMatrix, Affine); Agg.ManipulateMatrixAndRHS(AltOperatorMatrix, Affine, MG_Mapping.ProblemMapping, MG_Mapping.ProblemMapping); //LsTrk.GetSpeciesName(((XdgAggregationBasis)MGOp.Mapping.AggBasis[0]).UsedSpecies[1]); //LsTrk.GetSpeciesName(((XdgAggregationBasis)MGOp.Mapping.AggBasis[0]).UsedSpecies[0]); int nnz = this.OperatorMatrix.GetTotalNoOfNonZeros(); Console.WriteLine("Number of non-zeros in matrix: " + nnz); int nnz2 = this.AltOperatorMatrix.GetTotalNoOfNonZeros(); Assert.IsTrue(nnz == nnz2, "Number of non-zeros in matrix different for " + OperatorMatrix.GetType() + " and " + AltOperatorMatrix.GetType()); Console.WriteLine("Number of non-zeros in matrix (reference): " + nnz2); MsrMatrix Comp = AltOperatorMatrix.CloneAs(); Comp.Acc(-1.0, OperatorMatrix); double CompErr = Comp.InfNorm(); double Denom = Math.Max(AltOperatorMatrix.InfNorm(), OperatorMatrix.InfNorm()); double CompErrRel = Denom > Math.Sqrt(double.Epsilon) ? CompErr / Denom : CompErr; Console.WriteLine("Comparison: " + CompErrRel); Assert.LessOrEqual(CompErrRel, 1.0e-7, "Huge difference between MsrMatrix and BlockMsrMatrix."); base.TerminationKey = true; return(0.0); }
protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { Console.WriteLine(" Timestep # " + TimestepNo + ", phystime = " + phystime); //phystime = 1.8; LsUpdate(phystime); // operator-matrix assemblieren MsrMatrix OperatorMatrix = new MsrMatrix(u.Mapping, u.Mapping); double[] Affine = new double[OperatorMatrix.RowPartitioning.LocalLength]; MultiphaseCellAgglomerator Agg; MassMatrixFactory Mfact; // Agglomerator setup int quadOrder = Op.QuadOrderFunction(new int[] { u.Basis.Degree }, new int[0], new int[] { u.Basis.Degree }); //Agg = new MultiphaseCellAgglomerator(new CutCellMetrics(MomentFittingVariant, quadOrder, LsTrk, ), this.THRESHOLD, false); Agg = LsTrk.GetAgglomerator(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, quadOrder, this.THRESHOLD); Console.WriteLine("Inter-Process agglomeration? " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.InterProcessAgglomeration); if (this.THRESHOLD > 0.01) { TestAgglomeration_Extraploation(Agg); TestAgglomeration_Projection(quadOrder, Agg); } // operator matrix assembly //Op.ComputeMatrixEx(LsTrk, // u.Mapping, null, u.Mapping, // OperatorMatrix, Affine, false, 0.0, true, // Agg.CellLengthScales, null, null, // LsTrk.GetSpeciesId("B")); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, u.Mapping, null, u.Mapping, LsTrk.GetSpeciesId("B")); mtxBuilder.time = 0.0; mtxBuilder.ComputeMatrix(OperatorMatrix, Affine); Agg.ManipulateMatrixAndRHS(OperatorMatrix, Affine, u.Mapping, u.Mapping); // mass matrix factory Mfact = LsTrk.GetXDGSpaceMetrics(new SpeciesId[] { LsTrk.GetSpeciesId("B") }, quadOrder, 1).MassMatrixFactory;// new MassMatrixFactory(u.Basis, Agg); // Mass matrix/Inverse Mass matrix //var MassInv = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, true, LsTrk.GetSpeciesId("B")); var Mass = Mfact.GetMassMatrix(u.Mapping, new double[] { 1.0 }, false, LsTrk.GetSpeciesId("B")); Agg.ManipulateMatrixAndRHS(Mass, default(double[]), u.Mapping, u.Mapping); var MassInv = Mass.InvertBlocks(OnlyDiagonal: true, Subblocks: true, ignoreEmptyBlocks: true, SymmetricalInversion: false); // test that operator depends only on B-species values double DepTest = LsTrk.Regions.GetSpeciesSubGrid("B").TestMatrixDependency(OperatorMatrix, u.Mapping, u.Mapping); Console.WriteLine("Matrix dependency test: " + DepTest); Assert.LessOrEqual(DepTest, 0.0); // diagnostic output Console.WriteLine("Number of Agglomerations (all species): " + Agg.TotalNumberOfAgglomerations); Console.WriteLine("Number of Agglomerations (species 'B'): " + Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).AggInfo.SourceCells.NoOfItemsLocally.MPISum()); // operator auswerten: double[] x = new double[Affine.Length]; BLAS.daxpy(x.Length, 1.0, Affine, 1, x, 1); OperatorMatrix.SpMVpara(1.0, u.CoordinateVector, 1.0, x); MassInv.SpMV(1.0, x, 0.0, du_dx.CoordinateVector); Agg.GetAgglomerator(LsTrk.GetSpeciesId("B")).Extrapolate(du_dx.Mapping); // markieren, wo ueberhaupt A und B sind Bmarker.AccConstant(1.0, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); Amarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("A").VolumeMask); Xmarker.AccConstant(+1.0, LsTrk.Regions.GetSpeciesSubGrid("X").VolumeMask); // compute error ERR.Clear(); ERR.Acc(1.0, du_dx_Exact, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); ERR.Acc(-1.0, du_dx, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); double L2Err = ERR.L2Norm(LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); Console.WriteLine("L2 Error: " + L2Err); XERR.Clear(); XERR.GetSpeciesShadowField("B").Acc(1.0, ERR, LsTrk.Regions.GetSpeciesSubGrid("B").VolumeMask); double xL2Err = XERR.L2Norm(); Console.WriteLine("L2 Error (in XDG space): " + xL2Err); // check error if (TimestepNo > 1) { if (this.THRESHOLD > 0.01) { // without agglomeration, the error in very tiny cut-cells may be large over the whole cell // However, the error in the XDG-space should be small under all circumstances Assert.LessOrEqual(L2Err, 1.0e-6); } Assert.LessOrEqual(xL2Err, 1.0e-6); } bool IsPassed = ((L2Err <= 1.0e-6 || this.THRESHOLD <= 0.01) && xL2Err <= 1.0e-7); if (IsPassed) { Console.WriteLine("Test PASSED"); } else { Console.WriteLine("Test FAILED: check errors."); } // return/Ende base.NoOfTimesteps = 17; //base.NoOfTimesteps = 2; dt = 0.3; return(dt); }
/// <summary> /// Create Spatial Operators and build the corresponding Matrices /// </summary> public void ComputeMatrices(IList <DGField> InterfaceParams, bool nearfield) { OpMatrix = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine = new double[OpMatrix.RowPartitioning.LocalLength]; OpMatrix_bulk = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine_bulk = new double[OpMatrix.RowPartitioning.LocalLength]; OpMatrix_interface = new MsrMatrix(this.Extension.Mapping, this.Extension.Mapping); OpAffine_interface = new double[OpMatrix.RowPartitioning.LocalLength]; //LevelSetTracker.GetLevelSetGradients(0,); // bulk part of the matrix //Operator_bulk.ComputeMatrix( // Extension.Mapping, // LevelSetGradient.ToArray(), // Extension.Mapping, // OpMatrix_bulk, OpAffine_bulk, // OnlyAffine: false, sgrd: null); switch (Control.FluxVariant) { case FluxVariant.GradientBased: // Flux Direction based on Mean Level Set Gradient BulkParams = new List <DGField> { }; // Hack, to make ArrayTools.Cat produce a List of DGFields // second Hack: Does only work, when InterfaceParams is according to a single component flux, // else, we will have to change the boundary edge flux BulkParams = ArrayTools.Cat(BulkParams, LevelSetGradient.ToArray(), Phi, MeanLevelSetGradient.ToArray(), InterfaceParams.ToArray()); MeanLevelSetGradient.Clear(); MeanLevelSetGradient.AccLaidBack(1.0, LevelSetGradient); break; case FluxVariant.ValueBased: // Flux Direction Based on Cell-Averaged Level-Set Value BulkParams = ArrayTools.Cat(LevelSetGradient.ToArray(), Phi, MeanLevelSet); MeanLevelSet.Clear(); MeanLevelSet.AccLaidBack(1.0, Phi); break; case FluxVariant.SWIP: BulkParams = LevelSetGradient.ToArray(); break; default: throw new Exception(); } // Build Operator Operator_bulk.ComputeMatrixEx(Extension.Mapping, BulkParams, Extension.Mapping, OpMatrix_bulk, OpAffine_bulk, OnlyAffine: false, time: 0.0, edgeQuadScheme: new EdgeQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).InnerEdgesMask : null), volQuadScheme: new CellQuadratureScheme(true, nearfield ? LevelSetTracker.Regions.GetNearFieldSubgrid(1).VolumeMask : null) ); //Operator_interface.ComputeMatrixEx( // LevelSetTracker, // Extension.Mapping, // InterfaceParams, // Extension.Mapping, // OpMatrix_interface, // OpAffine_interface, // OnlyAffine: false, // time: 0, // MPIParameterExchange: false, // whichSpc: LevelSetTracker.GetSpeciesId("A") // ); Operator_interface.OperatorCoefficientsProvider = delegate(LevelSetTracker lstrk, SpeciesId spc, int quadOrder, int TrackerHistoryIdx, double time) { var r = new CoefficientSet() { }; //throw new NotImplementedException("todo"); return(r); }; XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Operator_interface.GetMatrixBuilder(LevelSetTracker, Extension.Mapping, InterfaceParams, Extension.Mapping); MultiphaseCellAgglomerator dummy = LevelSetTracker.GetAgglomerator(LevelSetTracker.SpeciesIdS.ToArray(), 2 * Extension.Basis.Degree + 2, 0.0); mtxBuilder.CellLengthScales.Add(LevelSetTracker.GetSpeciesId("A"), dummy.CellLengthScales[LevelSetTracker.GetSpeciesId("A")]); mtxBuilder.time = 0; mtxBuilder.MPITtransceive = false; mtxBuilder.ComputeMatrix(OpMatrix_interface, OpAffine_interface); #if DEBUG OpMatrix_bulk.CheckForNanOrInfM(); OpAffine_bulk.CheckForNanOrInfV(); OpMatrix_interface.CheckForNanOrInfM(); OpAffine_interface.CheckForNanOrInfV(); #endif //Only for Debugging purposes Debug.Assert(OpMatrix_interface.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of InterfaceOperator is 0"); Debug.Assert(OpMatrix_bulk.GetDiagVector().L2Norm() > 0, "L2-Norm of Diagonal of BulkOperator is 0"); #if DEBUG //Console.WriteLine( "L2-Norm of Diagonal of InterfaceOperator is {0}", OpMatrix_interface.GetDiagVector().L2Norm() ); #endif OpMatrix.Clear(); OpMatrix.Acc(1.0, OpMatrix_bulk); OpMatrix.Acc(1.0, OpMatrix_interface); //Console.WriteLine("Op-Matrix Symmetry-Deviation: {0}", OpMatrix.SymmetryDeviation()); OpMatrix.AssumeSymmetric = false; OpAffine.Clear(); OpAffine.AccV(1.0, OpAffine_bulk); OpAffine.AccV(1.0, OpAffine_interface); #if DEBUG //Console.WriteLine("Condition Number of Extension Operator {0}", OpMatrix.condest()); #endif }
protected virtual void DelComputeOperatorMatrix(BlockMsrMatrix OpMatrix, double[] OpAffine, UnsetteledCoordinateMapping Mapping, DGField[] CurrentState, Dictionary <SpeciesId, MultidimensionalArray> AgglomeratedCellLengthScales, double phystime) { OpAffine.ClearEntries(); bool Eval = false; if (OpMatrix == null) { Eval = true; OpMatrix = new BlockMsrMatrix(uResidual.Mapping, u.Mapping); } else { OpMatrix.Clear(); } //Op.ComputeMatrixEx(base.LsTrk, // u.Mapping, null, uResidual.Mapping, // OpMatrix, OpAffine, false, // phystime, // false, // base.LsTrk.SpeciesIdS.ToArray()); XSpatialOperatorMk2.XEvaluatorLinear mtxBuilder = Op.GetMatrixBuilder(base.LsTrk, u.Mapping, null, uResidual.Mapping, base.LsTrk.SpeciesIdS.ToArray()); foreach (var kv in AgglomeratedCellLengthScales) { mtxBuilder.SpeciesOperatorCoefficients[kv.Key].CellLengthScales = kv.Value; } mtxBuilder.time = phystime; mtxBuilder.ComputeMatrix(OpMatrix, OpAffine); if (Eval) { OpMatrix.SpMV(1.0, new CoordinateVector(CurrentState), 1.0, OpAffine); } /* * if (!Mapping.EqualsPartition(uResidual.Mapping)) * throw new ArgumentException(); * * if (OpMatrix != null) { * OpMatrix.Clear(); * OpAffine.ClearEntries(); * * Op.ComputeMatrixEx(base.LsTrk, * u.Mapping, null, Mapping, * OpMatrix, OpAffine, false, * phystime, * false, * base.LsTrk.SpeciesIdS.ToArray()); * } else { * var eval = Op.GetEvaluatorEx(base.LsTrk, * CurrentState, null, Mapping, * base.LsTrk.SpeciesIdS.ToArray()); * * eval.time = phystime; * * eval.Evaluate(1.0, 1.0, OpAffine); * } */ }