/// <summary> /// Jacobi iteration /// </summary> public void Solve <U, V>(U xl, V bl) where U : IList <double> where V : IList <double> { int L = xl.Count; double[] ql = new double[L]; double iter0_ResNorm = 0; for (int iIter = 0; true; iIter++) { ql.SetV(bl); Mtx.SpMV(-1.0, xl, 1.0, ql); double ResNorm = ql.L2NormPow2().MPISum().Sqrt(); if (iIter == 0) { iter0_ResNorm = ResNorm; if (this.IterationCallback != null) { double[] _xl = xl.ToArray(); double[] _bl = bl.ToArray(); Mtx.SpMV(-1.0, _xl, 1.0, _bl); this.IterationCallback(iIter + 1, _xl, _bl, this.m_MultigridOp); } } if (!TerminationCriterion(iIter, iter0_ResNorm, ResNorm)) { m_Converged = true; return; } Diag.SpMV(1.0, xl, 1.0, ql); //xl.ScaleV(1.0 - omega); invDiag.SpMV(omega, ql, 1.0 - omega, xl); //for(int i = 0; i < L; i++) { // xl[i] = omega * ((ql[i] + diag[i] * xl[i]) / diag[i]) // + (1.0 - omega) * xl[i]; //} if (this.IterationCallback != null) { double[] _xl = xl.ToArray(); double[] _bl = bl.ToArray(); Mtx.SpMV(-1.0, _xl, 1.0, _bl); this.IterationCallback(iIter + 1, _xl, _bl, this.m_MultigridOp); } } }
/// <summary> /// computes the residual on this level. /// </summary> public void Residual(double[] Res, double[] X, double[] B) { Debug.Assert(Res.Length == m_MgOperator.Mapping.LocalLength); Debug.Assert(X.Length == m_MgOperator.Mapping.LocalLength); Debug.Assert(B.Length == m_MgOperator.Mapping.LocalLength); int L = Res.Length; Array.Copy(B, Res, L); OpMatrix.SpMV(-1.0, X, 1.0, Res); //Res.AccV(1.0, B); /* * int L = Res.Count; * * var OpMatrix_coarse = m_MgOperator.CoarserLevel.OperatorMatrix; * int Lc = OpMatrix_coarse._RowPartitioning.LocalLength; * * double[] Xc = new double[Lc]; * double[] Bc = new double[Lc]; * m_MgOperator.CoarserLevel.Restrict(X, Xc); * m_MgOperator.CoarserLevel.Restrict(B, Bc); * * double[] Res_coarse = Bc; Bc = null; * OpMatrix_coarse.SpMV(-1.0, Xc, 1.0, Res_coarse); * * m_MgOperator.CoarserLevel.Restrict(Res, Res_coarse); * * double[] Res1 = new double[L];// Res.ToArray(); * m_MgOperator.CoarserLevel.Prolongate(-1.0, Res1, 0.0, Res_coarse); * * double alpha = ParallelBlas.MPI_ddot(Res, Res1) / Res1.L2NormPow2().MPISum(); * * * * double[] RemRes = Res.ToArray(); * RemRes.AccV(-alpha, Res1); * * Res1.ScaleV(alpha); * * * int iLevel = m_MgOperator.LevelIndex; * Console.Write(" "); * for(int iLv = 0; iLv <= iLevel; iLv++) { * Console.Write(" "); * } * * Console.WriteLine(iLevel + " " + Res.L2Norm().ToString("0.####E-00") + " " + RemRes.L2Norm().ToString("0.####E-00") + " " + Res1.L2Norm().ToString("0.####E-00") + " " + GenericBlas.InnerProd(RemRes, Res1)); * * //viz.PlotVectors(new double[][] { Res.ToArray(), Res1, Res_coarse, RemRes }, new[] { "Residual", "ProloResi", "CarseResi", "RestResi" }); */ }
/// <summary> /// computes the residual on this level. /// </summary> public void Residual <V1, V2, V3>(V1 rl, V2 xl, V3 bl) where V1 : IList <double> where V2 : IList <double> where V3 : IList <double> { OpMatrix.SpMV(-1.0, xl, 0.0, rl); rl.AccV(1.0, bl); }
/// <summary> /// computes the residual on this level. /// </summary> public double Residual <V1, V2, V3>(V1 rl, V2 xl, V3 bl) where V1 : IList <double> where V2 : IList <double> where V3 : IList <double> { OpMatrix.SpMV(-1.0, xl, 0.0, rl); rl.AccV(1.0, bl); return(rl.MPI_L2Norm()); }
protected virtual void UpdateChangeRate(double PhysTime, double[] k) { BlockMsrMatrix OpMtx = new BlockMsrMatrix(this.CurrentStateMapping); double[] OpAff = new double[this.CurrentStateMapping.LocalLength]; base.ComputeOperatorMatrix(OpMtx, OpAff, this.CurrentStateMapping, this.CurrentStateMapping.Fields.ToArray(), base.GetAgglomeratedLengthScales(), PhysTime); k.SetV(OpAff); OpMtx.SpMV(1.0, this.m_CurrentState, 1.0, k); }
static void RestictionMatrixTestRec(int p, IEnumerable <MultigridMapping> MgMapSeq) { var currentLevelMap = MgMapSeq.First(); AggregationGridBasis AggBasis = currentLevelMap.AggBasis[0]; var map = new UnsetteledCoordinateMapping(new Basis(grid, p)); Random rnd = new Random(); double[] OrigVec = map.LocalLength.ForLoop(i => rnd.NextDouble()); double[] RestVec = new double[AggBasis.LocalDim]; double[] PrlgVec = new double[OrigVec.Length]; double[] RestVec2 = new double[RestVec.Length]; double[] PrlgVec2 = new double[OrigVec.Length]; AggBasis.RestictFromFullGrid(OrigVec, RestVec); AggBasis.ProlongateToFullGrid(PrlgVec, RestVec); BlockMsrMatrix RestOp = new BlockMsrMatrix(MgMapSeq.First(), MgMapSeq.First().ProblemMapping); AggBasis.GetRestrictionMatrix(RestOp, MgMapSeq.First(), 0); RestOp.SpMV(1.0, OrigVec, 0.0, RestVec2); BlockMsrMatrix PrlgOp = RestOp.Transpose(); PrlgOp.SpMV(1.0, RestVec2, 0.0, PrlgVec2); double RestErrNorm = GenericBlas.L2Dist(RestVec2, RestVec); double PrlgErrNorm = GenericBlas.L2Dist(PrlgVec2, PrlgVec); double LostInfNorm = GenericBlas.L2Dist(OrigVec, PrlgVec2); //Console.WriteLine("Rest. matrix test: {0}, Prolong. matrix test {1}, Lost info {2}", RestErrNorm, PrlgErrNorm, LostInfNorm); Assert.IsTrue(RestErrNorm < 1.0e-10); Assert.IsTrue(PrlgErrNorm < 1.0e-10); // restriction onto level itself BlockMsrMatrix RestMtx = currentLevelMap.FromOtherLevelMatrix(currentLevelMap); BlockMsrMatrix ShldBeEye = BlockMsrMatrix.Multiply(RestMtx, RestMtx.Transpose()); ShldBeEye.AccEyeSp(-1.0); double errNorm = ShldBeEye.InfNorm(); Console.WriteLine("Id norm {0} \t (level {1})", errNorm, currentLevelMap.AggGrid.MgLevel); Assert.IsTrue(errNorm < 1.0e-8); // recursion if (MgMapSeq.Count() > 1) { RestictionMatrixTestRec(p, MgMapSeq.Skip(1)); } }
void DerivativeByFluxLinear(SinglePhaseField fin, SinglePhaseField fres, int d, SinglePhaseField fBnd) { var Op = (new LinearDerivFlx(d)).Operator(); BlockMsrMatrix OpMtx = new BlockMsrMatrix(fres.Mapping, fin.Mapping); double[] OpAff = new double[fres.Mapping.LocalLength]; Op.ComputeMatrixEx(fin.Mapping, new DGField[] { fBnd }, fres.Mapping, OpMtx, OpAff, OnlyAffine: false); fres.Clear(); fres.CoordinateVector.Acc(1.0, OpAff); OpMtx.SpMV(1.0, fin.CoordinateVector, 1.0, fres.CoordinateVector); }
/// <summary> /// Jacobi iteration /// </summary> /// <param name="l">muligrid level</param> /// <param name="NoOfIter">number of Jacobi-Iterations</param> public void Solve <U, V>(U xl, V bl) where U : IList <double> where V : IList <double> { int L = xl.Count; double[] ql = new double[L]; for (int iIter = 0; iIter < NoOfIterations; iIter++) { this.m_ThisLevelIterations++; ql.SetV(bl); Mtx.SpMV(-1.0, xl, 1.0, ql); if (this.m_Tolerance > 0) { double ResNorm = ql.L2NormPow2().MPISum().Sqrt(); if (ResNorm < this.m_Tolerance) { m_Converged = true; return; } } for (int i = 0; i < L; i++) { xl[i] = omega * ((ql[i] + diag[i] * xl[i]) / diag[i]) + (1.0 - omega) * xl[i]; } if (this.IterationCallback != null) { double[] _xl = xl.ToArray(); double[] _bl = bl.ToArray(); Mtx.SpMV(-1.0, _xl, 1.0, _bl); this.IterationCallback(iIter, _xl, _bl, this.m_mgop); } } }
private void RKstage(double dt, double[][] k, int s, BlockMsrMatrix MsInv, BlockMsrMatrix M0, double[] u0, double[] coefficients) { // Copy coordinates to temp array since SpMV (below) does not // support in-place computation double[] tempCoordinates = CurrentState.ToArray(); M0.SpMV(1.0, u0, 0.0, tempCoordinates); // Non-agglomerated for (int l = 0; l < s; l++) { tempCoordinates.AccV(-coefficients[l] * dt, k[l]); // Non-agglomerated } speciesMap.Agglomerator.ManipulateRHS(tempCoordinates, Mapping); MsInv.SpMV(1.0, tempCoordinates, 0.0, CurrentState); speciesMap.Agglomerator.Extrapolate(CurrentState.Mapping); }
static void PolynomialRestAndPrlgTestRec(int p, MultigridMapping[] MgMapSeq) { var AggBasis = MgMapSeq.First().AggBasis[0]; //var AggBasis = aggBasisEs[1]; //{ var Orig = new SinglePhaseField(new Basis(grid, p)); SetTestValue(Orig); var Test = Orig.CloneAs(); double[] OrigVec = Orig.CoordinateVector.ToArray(); double[] RestVec = new double[AggBasis.LocalDim]; double[] PrlgVec = new double[OrigVec.Length]; AggBasis.RestictFromFullGrid(OrigVec, RestVec); Test.Clear(); AggBasis.ProlongateToFullGrid(PrlgVec, RestVec); BlockMsrMatrix RestOp = new BlockMsrMatrix(MgMapSeq[0], MgMapSeq[0].ProblemMapping); AggBasis.GetRestrictionMatrix(RestOp, MgMapSeq[0], 0); double[] RestVec2 = new double[RestVec.Length]; RestOp.SpMV(1.0, OrigVec, 0.0, RestVec2); Test.Clear(); Test.CoordinateVector.Acc(1.0, PrlgVec); Test.Acc(-1.0, Orig); double ErrNorm = Test.L2Norm(); Console.WriteLine("Polynomial Restriction/Prolongation test (p={1}, level={2}): {0}", ErrNorm, p, -MgMapSeq.Length); Assert.Less(ErrNorm, 1.0e-8); if (MgMapSeq.Length > 1) { PolynomialRestAndPrlgTestRec(p, MgMapSeq.Skip(1).ToArray()); } }
static void RestictionMatrixTestRec(int p, IEnumerable <MultigridMapping> MgMapSeq) { AggregationGridBasis AggBasis = MgMapSeq.First().AggBasis[0]; var map = new UnsetteledCoordinateMapping(new Basis(grid, p)); Random rnd = new Random(); double[] OrigVec = map.LocalLength.ForLoop(i => rnd.NextDouble()); double[] RestVec = new double[AggBasis.LocalDim]; double[] PrlgVec = new double[OrigVec.Length]; double[] RestVec2 = new double[RestVec.Length]; double[] PrlgVec2 = new double[OrigVec.Length]; AggBasis.RestictFromFullGrid(OrigVec, RestVec); AggBasis.ProlongateToFullGrid(PrlgVec, RestVec); BlockMsrMatrix RestOp = new BlockMsrMatrix(MgMapSeq.First(), MgMapSeq.First().ProblemMapping); AggBasis.GetRestrictionMatrix(RestOp, MgMapSeq.First(), 0); RestOp.SpMV(1.0, OrigVec, 0.0, RestVec2); BlockMsrMatrix PrlgOp = RestOp.Transpose(); PrlgOp.SpMV(1.0, RestVec2, 0.0, PrlgVec2); double RestErrNorm = GenericBlas.L2Dist(RestVec2, RestVec); double PrlgErrNorm = GenericBlas.L2Dist(PrlgVec2, PrlgVec); double LostInfNorm = GenericBlas.L2Dist(OrigVec, PrlgVec2); //Console.WriteLine("Rest. matrix test: {0}, Prolong. matrix test {1}, Lost info {2}", RestErrNorm, PrlgErrNorm, LostInfNorm); Debug.Assert(RestErrNorm < 1.0e-10); Debug.Assert(PrlgErrNorm < 1.0e-10); if (MgMapSeq.Count() > 1) { RestictionMatrixTestRec(p, MgMapSeq.Skip(1)); } }
public static void SpMVTest( [Values(XDGusage.none, XDGusage.mixed1, XDGusage.mixed2, XDGusage.all)] XDGusage UseXdg, [Values(1, 3)] int DGOrder, [Values(false, true)] bool compressL1, [Values(false, true)] bool compressL2) { unsafe { int[] Params = new int[8], ParamsGlob = new int[8]; fixed(int *pParams = Params, pParamsGlob = ParamsGlob) { pParams[0] = (int)UseXdg; pParams[1] = DGOrder; pParams[2] = compressL1 ? 1 : 0; pParams[3] = compressL2 ? 1 : 0; pParams[4] = -pParams[0]; pParams[5] = -pParams[1]; pParams[6] = -pParams[2]; pParams[7] = -pParams[3]; csMPI.Raw.Allreduce((IntPtr)pParams, (IntPtr)pParamsGlob, 8, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.MIN, csMPI.Raw._COMM.WORLD); } int[] ParamsMin = ParamsGlob.GetSubVector(0, 4); int[] ParamsMax = ParamsGlob.GetSubVector(4, 4); for (int i = 0; i < 4; i++) { if (Params[i] != ParamsMin[i]) { throw new ApplicationException(); } if (Params[i] != -ParamsMax[i]) { throw new ApplicationException(); } } Console.WriteLine("SpMVTest({0},{1},{2},{3})", UseXdg, DGOrder, compressL1, compressL2); } using (var solver = new Matrix_MPItestMain() { m_UseXdg = UseXdg, m_DGorder = DGOrder }) { // create the test data // ==================== BoSSS.Solution.Application.CommandLineOptions opts = null; //opts = new BoSSS.Solution.Application.CommandLineOptions(); solver.Init(null, opts); solver.RunSolverMode(); Stopwatch stw = new Stopwatch(); stw.Reset(); BlockMsrMatrix M = solver.OperatorMatrix; double[] B = new double[M.RowPartitioning.LocalLength]; double[] X = new double[M.ColPartition.LocalLength]; Random R = new Random(); for (int i = 0; i < X.Length; i++) { X[i] = R.NextDouble(); } for (int i = 0; i < B.Length; i++) { B[i] = R.NextDouble(); } double[] Bb4 = B.CloneAs(); double RefNorm = B.L2NormPow2().MPISum().Sqrt() * 1e-10; stw.Start(); M.SpMV(1.6, X, 0.5, B); stw.Stop(); //M.SaveToTextFileSparse(@"C:\tmp\M.txt"); //M11.SaveToTextFileSparse(@"C:\tmp\M11.txt"); //M12.SaveToTextFileSparse(@"C:\tmp\M12.txt"); //M21.SaveToTextFileSparse(@"C:\tmp\M21.txt"); //M22.SaveToTextFileSparse(@"C:\tmp\M22.txt"); //M22xM21.SaveToTextFileSparse(@"C:\tmp\M22xM21.txt"); using (var MatlabRef = new BatchmodeConnector()) { MultidimensionalArray CheckRes = MultidimensionalArray.Create(1, 1); MatlabRef.PutSparseMatrix(M, "M"); MatlabRef.PutVector(Bb4, "Bref"); MatlabRef.PutVector(B, "B"); MatlabRef.PutVector(X, "X"); MatlabRef.Cmd("Bref = Bref*0.5 + M*X*1.6;"); MatlabRef.Cmd("errB = norm(B - Bref, 2);"); MatlabRef.Cmd("CheckRes = [errB];"); MatlabRef.GetMatrix(CheckRes, "CheckRes"); MatlabRef.Execute(); Console.WriteLine("Matlab check SpMV: " + CheckRes[0, 0]); Assert.LessOrEqual(CheckRes[0, 0], RefNorm, "Error in SpMV"); } Console.WriteLine("Time spend in matrix operations: " + stw.Elapsed.TotalSeconds + " sec."); TotTime_MatrixOp += stw.Elapsed; } }
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; XSpatialOperator Op = new XSpatialOperator(1, 1, (A, B, C) => order, "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()); } // 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); foreach (var s in this.LsTrk.SpeciesIdS) { eval.SpeciesOperatorCoefficients[s].CellLengthScales = agg.CellLengthScales[s]; } 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; } }
// // /// <summary> /// applies the agglomeration on a general matrix /// </summary> /// <param name="Matrix">the matrix that should be manipulated.</param> /// <param name="Rhs">the right-hand-side that should be manipulated</param> /// <param name="ColMap"></param> /// <param name="ColMapAggSw">Turns column agglomeration on/off fore each variable individually; default == null is on. </param> /// <param name="RowMap"></param> /// <param name="RowMapAggSw">The same shit as for <paramref name="ColMapAggSw"/>, just for rows.</param> public void ManipulateMatrixAndRHS<M, T>(M Matrix, T Rhs, UnsetteledCoordinateMapping RowMap, UnsetteledCoordinateMapping ColMap, bool[] RowMapAggSw = null, bool[] ColMapAggSw = null) where M : IMutableMatrixEx where T : IList<double> { MPICollectiveWatchDog.Watch(); //var mtxS = GetFrameMatrices(Matrix, RowMap, ColMap); if (Matrix == null && Rhs == null) // nothing to do return; if (TotalNumberOfAgglomerations <= 0) // nothing to do return; if (RowMapAggSw != null) throw new NotImplementedException(); // generate agglomeration sparse matrices // ====================================== int RequireRight; if (Matrix == null) { // we don't need multiplication-from-the-right at all RequireRight = 0; } else { if (RowMap.EqualsUnsetteled(ColMap) && ArrayTools.ListEquals(ColMapAggSw, RowMapAggSw)) { // we can use the same matrix for right and left multiplication RequireRight = 1; } else { // separate matrix for the multiplication-from-the-right is required RequireRight = 2; } } BlockMsrMatrix LeftMul = null, RightMul = null; { foreach (var kv in DictAgglomeration) { var Species = kv.Key; var m_Agglomerator = kv.Value; if (m_Agglomerator != null) { CellMask spcMask = this.Tracker.Regions.GetSpeciesMask(Species); MiniMapping rowMini = new MiniMapping(RowMap, Species, this.Tracker.Regions); BlockMsrMatrix LeftMul_Species = m_Agglomerator.GetRowManipulationMatrix(RowMap, rowMini.MaxDeg, rowMini.NoOfVars, rowMini.i0Func, rowMini.NFunc, false, spcMask); if (LeftMul == null) { LeftMul = LeftMul_Species; } else { LeftMul.Acc(1.0, LeftMul_Species); } if (!object.ReferenceEquals(LeftMul, RightMul) && RightMul != null) { MiniMapping colMini = new MiniMapping(ColMap, Species, this.Tracker.Regions); BlockMsrMatrix RightMul_Species = m_Agglomerator.GetRowManipulationMatrix(ColMap, colMini.MaxDeg, colMini.NoOfVars, colMini.i0Func, colMini.NFunc, false, spcMask); if (RightMul == null) { RightMul = RightMul_Species; } else { RightMul.Acc(1.0, RightMul_Species); } } else if (RequireRight == 1) { RightMul = LeftMul; } else { RightMul = null; } } } } // apply the agglomeration to the matrix // ===================================== if (Matrix != null) { BlockMsrMatrix RightMulTr = RightMul.Transpose(); BlockMsrMatrix _Matrix; if (Matrix is BlockMsrMatrix) { _Matrix = (BlockMsrMatrix)((object)Matrix); } else { _Matrix = Matrix.ToBlockMsrMatrix(RowMap, ColMap); } var AggMatrix = BlockMsrMatrix.Multiply(LeftMul, BlockMsrMatrix.Multiply(_Matrix, RightMulTr)); if (object.ReferenceEquals(_Matrix, Matrix)) { _Matrix.Clear(); _Matrix.Acc(1.0, AggMatrix); } else { Matrix.Acc(-1.0, _Matrix); // das ist so Matrix.Acc(1.0, AggMatrix); // meagaschlecht !!!!!! } } // apply the agglomeration to the Rhs // ================================== if (Rhs != null) { double[] tmp = Rhs.ToArray(); if (object.ReferenceEquals(tmp, Rhs)) throw new ApplicationException("Flache kopie sollte eigentlich ausgeschlossen sein!?"); LeftMul.SpMV(1.0, tmp, 0.0, Rhs); } }
/// <summary> /// computes derivatives in various ways and compares them against known values. /// </summary> protected override double RunSolverOneStep(int TimestepNo, double phystime, double dt) { base.EndTime = 0.0; base.NoOfTimesteps = 0; int D = this.GridData.SpatialDimension; int J = this.GridData.iLogicalCells.NoOfLocalUpdatedCells; Console.WriteLine("DerivativeTest.exe, test case #" + GRID_CASE + " ******************************"); //var Fix = this.GridData.iGeomEdges.FaceIndices; //for(int iEdge = 0; iEdge < Fix.GetLength(0); iEdge++) { // Debug.Assert(Fix[iEdge, 0] >= 0); // Debug.Assert(Fix[iEdge, 1] >= 0); //} // sealing test // ================= if (this.GridData is Foundation.Grid.Classic.GridData) { TestSealing(this.GridData); } // cell volume and edge area check, if possible // =============================================== if (this.CellVolume > 0) { double err = 0; double Treshold = 1.0e-10; for (int j = 0; j < J; j++) { err += Math.Abs(this.GridData.iLogicalCells.GetCellVolume(j) - this.CellVolume); } bool passed = (err < Treshold); m_passed = m_passed && passed; Console.WriteLine("Cell volume error: " + err + " passed? " + passed); Console.WriteLine("--------------------------------------------"); } if (this.EdgeArea > 0) { double err = 0; double Treshold = 1.0e-10; int E = this.GridData.iLogicalEdges.Count; for (int e = 0; e < E; e++) { err += Math.Abs(this.GridData.iLogicalEdges.GetEdgeArea(e) - this.EdgeArea); } bool passed = (err < Treshold); m_passed = m_passed && passed; Console.WriteLine("Edge area error: " + err + " passed? " + passed); Console.WriteLine("--------------------------------------------"); } // Orthonormality of basis in physical coords // ========================================== { Basis Bs = this.f1.Basis; int N = Bs.Length; int degQuad = this.GridData.iLogicalCells.GetInterpolationDegree(0) * D + Bs.Degree + 3; int[] jG2jL = this.GridData.iGeomCells.GeomCell2LogicalCell; // mass matrix: should be identity! MultidimensionalArray MassMatrix = MultidimensionalArray.Create(J, N, N); // compute mass matrix by quadrature. var quad = CellQuadrature.GetQuadrature(new int[] { N, N }, base.GridData, (new CellQuadratureScheme()).Compile(base.GridData, degQuad), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { NodeSet QuadNodes = QR.Nodes; MultidimensionalArray BasisVals = Bs.CellEval(QuadNodes, i0, Length); EvalResult.Multiply(1.0, BasisVals, BasisVals, 0.0, "jknm", "jkn", "jkm"); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { if (jG2jL != null) { for (int i = 0; i < Length; i++) { int jG = i + i0; MassMatrix.ExtractSubArrayShallow(jG2jL[jG], -1, -1) .Acc(1.0, ResultsOfIntegration.ExtractSubArrayShallow(i, -1, -1)); } } else { MassMatrix.SetSubArray(ResultsOfIntegration, new int[] { i0, 0, 0 }, new int[] { i0 + Length - 1, N - 1, N - 1 }); } }, cs: CoordinateSystem.Physical); quad.Execute(); // check that mass matrix is Id. int MaxErrorCell = -1; double MaxError = -1; for (int j = 0; j < J; j++) { MultidimensionalArray MassMatrix_j = MassMatrix.ExtractSubArrayShallow(j, -1, -1); MassMatrix_j.AccEye(-1.0); double Norm_j = MassMatrix_j.InfNorm(); if (Norm_j > MaxError) { MaxError = Norm_j; MaxErrorCell = j; } } bool passed = (MaxError < 1.0e-8); m_passed = m_passed && passed; Console.WriteLine("Mass Matrix, maximum error in Cell #" + MaxErrorCell + ", mass matrix error norm: " + MaxError + " passed? " + passed); } // Broken Derivatives // ================= double totalVolume = (new SubGrid(CellMask.GetFullMask(this.GridData))).Volume; for (int d = 0; d < D; d++) { // compute f1Gradient_Numerical[d].Clear(); f1Gradient_Numerical[d].Derivative(1.0, f1, d); f2Gradient_Numerical[d].Clear(); f2Gradient_Numerical[d].Derivative(1.0, f2, d); // subtract analytical var Errfield1 = f1Gradient_Numerical[d].CloneAs(); Errfield1.Acc(-1, f1Gradient_Analytical[d]); var Errfield2 = f2Gradient_Numerical[d].CloneAs(); Errfield2.Acc(-1, f2Gradient_Analytical[d]); Console.WriteLine("Broken Derivatives: "); double Treshold = 1.0e-10; if (AltRefSol) { Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold } double err1_dx = Errfield1.L2Norm() / totalVolume; bool passed = (err1_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed)); double err2_dx = Errfield2.L2Norm() / totalVolume; passed = (err2_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed)); Console.WriteLine("--------------------------------------------"); } // Flux Derivatives // ================= for (int d = 0; d < D; d++) { // compute f1Gradient_Numerical[d].Clear(); f1Gradient_Numerical[d].DerivativeByFlux(1.0, f1, d); f2Gradient_Numerical[d].Clear(); f2Gradient_Numerical[d].DerivativeByFlux(1.0, f2, d); f1Gradient_Numerical[d].CheckForNanOrInf(true, true, true); f2Gradient_Numerical[d].CheckForNanOrInf(true, true, true); // subtract analytical var Errfield1 = f1Gradient_Numerical[d].CloneAs(); Errfield1.Acc(-1, f1Gradient_Analytical[d]); var Errfield2 = f2Gradient_Numerical[d].CloneAs(); Errfield2.Acc(-1, f2Gradient_Analytical[d]); Console.WriteLine("Flux Derivatives: "); double Treshold = 1.0e-10; if (AltRefSol) { Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold } double err1_dx = Errfield1.L2Norm() / totalVolume; bool passed = (err1_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed)); double err2_dx = Errfield2.L2Norm() / totalVolume; passed = (err2_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed)); Console.WriteLine("--------------------------------------------"); } // Linear flux Derivatives // ======================= for (int d = 0; d < D; d++) { double[] korrekto = f1Gradient_Numerical[d].CoordinateVector.ToArray(); // compute DerivativeByFluxLinear(f1, f1Gradient_Numerical[d], d, f1); DerivativeByFluxLinear(f2, f2Gradient_Numerical[d], d, f2); // subtract analytical var Errfield1 = f1Gradient_Numerical[d].CloneAs(); Errfield1.Acc(-1, f1Gradient_Analytical[d]); var Errfield2 = f2Gradient_Numerical[d].CloneAs(); Errfield2.Acc(-1, f2Gradient_Analytical[d]); Console.WriteLine("Linear Flux Derivatives: "); double Treshold = 1.0e-10; if (AltRefSol) { Treshold = 1.0e-4; // not exactly polynomial, therefore a higher threshold } double err1_dx = Errfield1.L2Norm() / totalVolume; bool passed = (err1_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df1/dx{0}_Numerical - df1/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err1_dx, passed)); double err2_dx = Errfield2.L2Norm() / totalVolume; passed = (err2_dx < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| df2/dx{0}_Numerical - df2/dx{0}_Analytical ||_2 = {1}, passed? {2}", d, err2_dx, passed)); Console.WriteLine("--------------------------------------------"); } // Laplacian, nonlinear // ==================== if (!AltRefSol) { var Laplace = (new ipLaplace()).Operator(1); Laplace.Evaluate(new DGField[] { this.f1 }, new DGField[] { this.Laplace_f1_Numerical }); Laplace.Evaluate(new DGField[] { this.f2 }, new DGField[] { this.Laplace_f2_Numerical }); double Treshold = 1.0e-8; // subtract analytical var Errfield1 = Laplace_f1_Numerical.CloneAs(); Errfield1.Acc(-1, Laplace_f1_Analytical); var Errfield2 = Laplace_f2_Numerical.CloneAs(); Errfield2.Acc(-1, Laplace_f2_Analytical); double err_Lf1 = Errfield1.L2Norm() / totalVolume; bool passed = (err_Lf1 < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf1, passed)); double err_Lf2 = Errfield2.L2Norm() / totalVolume; passed = (err_Lf2 < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (nonlinear evaluation), passed? {1}", err_Lf2, passed)); Console.WriteLine("--------------------------------------------"); } // Laplacian, linear // ==================== if (!AltRefSol) { var Laplace = (new ipLaplace()).Operator(1); var LaplaceMtx = new BlockMsrMatrix(this.f1.Mapping, this.Laplace_f1_Numerical.Mapping); var LaplaceAffine = new double[LaplaceMtx.RowPartitioning.LocalLength]; Laplace.ComputeMatrix(this.f1.Mapping, null, this.Laplace_f1_Numerical.Mapping, LaplaceMtx, LaplaceAffine, false); this.Laplace_f1_Numerical.CoordinateVector.SetV(LaplaceAffine); LaplaceMtx.SpMV(1.0, this.f1.CoordinateVector, 1.0, this.Laplace_f1_Numerical.CoordinateVector); this.Laplace_f2_Numerical.CoordinateVector.SetV(LaplaceAffine); LaplaceMtx.SpMV(1.0, this.f2.CoordinateVector, 1.0, this.Laplace_f2_Numerical.CoordinateVector); // subtract analytical var Errfield1 = Laplace_f1_Numerical.CloneAs(); Errfield1.Acc(-1, Laplace_f1_Analytical); var Errfield2 = Laplace_f2_Numerical.CloneAs(); Errfield2.Acc(-1, Laplace_f2_Analytical); double Treshold = 1.0e-8; double err_Lf1 = Errfield1.L2Norm() / totalVolume; bool passed = (err_Lf1 < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| /\\f1 Numerical - /\\f1 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf1, passed)); double err_Lf2 = Errfield2.L2Norm() / totalVolume; passed = (err_Lf2 < Treshold); m_passed = m_passed && passed; Console.WriteLine(string.Format("|| /\\f2 Numerical - /\\f2 Analytical ||_2 = {0} (linear evaluation), passed? {1}", err_Lf2, passed)); // comparison of finite difference Jacobian and Operator matrix if (TestFDJacobian) { this.f1.Clear(); var FDJbuilder = Laplace.GetFDJacobianBuilder(this.f1.Mapping.Fields, null, this.f1.Mapping, delegate(IEnumerable <DGField> U0, IEnumerable <DGField> Params) { return; }); var CheckMatrix = new BlockMsrMatrix(FDJbuilder.CodomainMapping, FDJbuilder.DomainMapping); var CheckAffine = new double[FDJbuilder.CodomainMapping.LocalLength]; FDJbuilder.ComputeMatrix(CheckMatrix, CheckAffine); var ErrMatrix = LaplaceMtx.CloneAs(); var ErrAffine = LaplaceAffine.CloneAs(); ErrMatrix.Acc(-1.0, CheckMatrix); ErrAffine.AccV(-1.0, CheckAffine); double LinfMtx = ErrMatrix.InfNorm(); double L2Aff = ErrAffine.L2NormPow2().MPISum().Sqrt(); bool passed1 = (LinfMtx < 1.0e-3); bool passed2 = (L2Aff < Treshold); Console.WriteLine("Finite Difference Jacobian: Matrix/Affine delta norm {0} {1}, passed? {2} {3}", LinfMtx, L2Aff, passed1, passed2); m_passed = m_passed && passed1; m_passed = m_passed && passed2; } Console.WriteLine("--------------------------------------------"); } // finally... // ================= if (m_passed) { Console.WriteLine("All tests passed. *****************************"); } else { Console.WriteLine("Some error above threshold. *******************"); } return(0.0); // return some artificial timestep }
/// <summary> /// implementation of the CG algorithm /// </summary> /// <param name="_x"></param> /// <param name="_R"></param> /// <param name="stats"></param> public void Solve <Vec1, Vec2>(Vec1 _x, Vec2 _R) where Vec1 : IList <double> where Vec2 : IList <double> { double[] x, R; if (_x is double[]) { x = _x as double[]; } else { x = _x.ToArray(); } if (_R is double[]) { R = _R as double[]; } else { R = _R.ToArray(); } int L = x.Length; double[] P = new double[L]; //double[] R = rhs; // rhs is only needed once, so we can use it to store residuals double[] V = new double[L]; double[] Z = new double[L]; // compute P0, R0 // ============== GenericBlas.dswap(L, x, 1, P, 1); m_OptMatrix.SpMV(-1.0, P, 1.0, R); if (IterationCallback != null) { IterationCallback(NoOfIterations, P.CloneAs(), R.CloneAs(), this.m_MgOp); } GenericBlas.dswap(L, x, 1, P, 1); if (Precond != null) { Precond.Solve(Z, R); P.SetV(Z); } else { P.SetV(R); } double alpha = R.InnerProd(P); double alpha_0 = alpha; double ResNorm; ResNorm = Math.Sqrt(alpha); // iterate // ======= NoOfIterations++; // one iteration has allready been performed (P0, R0) for (int n = 1; n < this.m_MaxIterations; n++) { if (ResNorm <= m_Tolerance && NoOfIterations >= m_MinIterations) { this.m_Converged = true; break; } NoOfIterations++; if (Math.Abs(alpha) <= double.Epsilon) { // numerical breakdown break; } m_Matrix.SpMV(1.0, P, 0, V); double VxP = V.InnerProd(P); //Console.WriteLine("VxP: {0}", VxP); if (double.IsNaN(VxP) || double.IsInfinity(VxP)) { throw new ArithmeticException(); } double lambda = alpha / VxP; if (double.IsNaN(lambda) || double.IsInfinity(lambda)) { throw new ArithmeticException(); } x.AccV(lambda, P); R.AccV(-lambda, V); if (IterationCallback != null) { IterationCallback(NoOfIterations, x.CloneAs(), R.CloneAs(), this.m_MgOp); } if (Precond != null) { Z.Clear(); Precond.Solve(Z, R); } else { Z.SetV(R); } double alpha_neu = R.InnerProd(Z).MPISum(); // compute residual norm ResNorm = R.L2NormPow2().MPISum().Sqrt(); P.ScaleV(alpha_neu / alpha); P.AccV(1.0, Z); alpha = alpha_neu; } if (!object.ReferenceEquals(_x, x)) { _x.SetV(x); } if (!object.ReferenceEquals(_R, R)) { _R.SetV(R); } return; }
public void UpdateSensorValues(CNSFieldSet fieldSet, ISpeciesMap speciesMap, CellMask cellMask) { DGField fieldToTest = fieldSet.ConservativeVariables. Concat(fieldSet.DerivedFields.Values). Where(f => f.Identification == sensorVariable.Name). Single(); int degree = fieldToTest.Basis.Degree; int noOfCells = fieldToTest.GridDat.iLogicalCells.NoOfLocalUpdatedCells; if (sensorValues == null || sensorValues.Length != noOfCells) { sensorValues = new double[noOfCells]; } IMatrix coordinatesTimesMassMatrix; IMatrix coordinatesTruncatedTimesMassMatrix; if (speciesMap is ImmersedSpeciesMap ibmMap) { // Note: This has to be the _non_-agglomerated mass matrix // because we still live on the non-agglomerated mesh at this // point BlockMsrMatrix massMatrix = ibmMap.GetMassMatrixFactory(fieldToTest.Mapping).NonAgglomeratedMassMatrix; // Old DGField temp = fieldToTest.CloneAs(); massMatrix.SpMV(1.0, fieldToTest.CoordinateVector, 0.0, temp.CoordinateVector); coordinatesTimesMassMatrix = temp.Coordinates; // Neu DGField uTruncated = fieldToTest.CloneAs(); // Set all coordinates to zero for (int cell = 0; cell < uTruncated.Coordinates.NoOfRows; cell++) { for (int coordinate = 0; coordinate < uTruncated.Coordinates.NoOfCols; coordinate++) { uTruncated.Coordinates[cell, coordinate] = 0; } } // Copy only the coordiantes that belong to the highest modes foreach (int cell in cellMask.ItemEnum) { foreach (int coordinate in fieldToTest.Basis.GetPolynomialIndicesForDegree(cell, degree)) { uTruncated.Coordinates[cell, coordinate] = fieldToTest.Coordinates[cell, coordinate]; } } // Calculate M times u DGField vecF_Field = fieldToTest.CloneAs(); massMatrix.SpMV(1.0, uTruncated.CoordinateVector, 0.0, vecF_Field.CoordinateVector); coordinatesTruncatedTimesMassMatrix = vecF_Field.Coordinates; } else { // Mass matrix is identity coordinatesTimesMassMatrix = fieldToTest.Coordinates; coordinatesTruncatedTimesMassMatrix = fieldToTest.Coordinates; } //IMatrix coordinatesTimesMassMatrix = fieldToTest.Coordinates; //cellMask.SaveToTextFile("fluidCells.txt"); // This is equivalent to norm(restrictedField) / norm(originalField) // Note: THIS WILL FAIL IN CUT CELLS foreach (int cell in cellMask.ItemEnum) { double numerator = 0.0; foreach (int coordinate in fieldToTest.Basis.GetPolynomialIndicesForDegree(cell, degree)) { //numerator += fieldToTest.Coordinates[cell, coordinate] * fieldToTest.Coordinates[cell, coordinate]; numerator += fieldToTest.Coordinates[cell, coordinate] * coordinatesTruncatedTimesMassMatrix[cell, coordinate]; } double denominator = 0.0; for (int coordinate = 0; coordinate < fieldToTest.Basis.Length; coordinate++) { //denominator += fieldToTest.Coordinates[cell, coordinate] * fieldToTest.Coordinates[cell, coordinate]; denominator += fieldToTest.Coordinates[cell, coordinate] * coordinatesTimesMassMatrix[cell, coordinate]; } double result; if (denominator == 0.0) { result = 0.0; } else { result = numerator / denominator; } //Debug.Assert(denominator != 0, "Persson sensor: Denominator is zero!"); //Debug.Assert(!(numerator / denominator).IsNaN(), "Persson sensor: Sensor value is NaN!"); //Debug.Assert(numerator / denominator >= 0, "Persson sensor: Sensor value is negative!"); sensorValues[cell] = result; } }
public void Solve <V1, V2>(V1 _X, V2 _B) where V1 : IList <double> where V2 : IList <double> { using (var tr = new FuncTrace()) { double[] X, B; if (_X is double[]) { X = _X as double[]; } else { X = _X.ToArray(); } if (_B is double[]) { B = _B as double[]; } else { B = _B.ToArray(); } double bnrm2 = B.L2NormPow2().MPISum().Sqrt(); if (bnrm2 == 0.0) { bnrm2 = 1.0; } int Nloc = Matrix.RowPartitioning.LocalLength; int Ntot = Matrix.RowPartitioning.TotalLength; double[] r = new double[Nloc]; double[] z = new double[Nloc]; //r = M \ ( b-A*x );, where M is the precond z.SetV(B); Matrix.SpMV(-1.0, X, 1.0, z); if (IterationCallback != null) { IterationCallback(0, X.CloneAs(), z.CloneAs(), this.m_mgop); } if (this.Precond != null) { r.Clear(); this.Precond.Solve(r, z); } else { r.SetV(z); } // Inserted for real residual double error2 = z.L2NormPow2().MPISum().Sqrt(); double error = (r.L2NormPow2().MPISum().Sqrt()) / bnrm2; if (error < this.m_Tolerance) { if (!object.ReferenceEquals(_X, X)) { _X.SetV(X); } B.SetV(z); this.m_Converged = true; return; } if (MaxKrylovDim <= 0) { throw new NotSupportedException("unsupported restart length."); } int m = MaxKrylovDim; double[][] V = (m + 1).ForLoop(i => new double[Nloc]); // V(1:n,1:m+1) = zeros(n,m+1); MultidimensionalArray H = MultidimensionalArray.Create(m + 1, m); // H(1:m+1,1:m) = zeros(m+1,m); double[] cs = new double[m]; double[] sn = new double[m]; //double[] s = new double[m+1]; double[] e1 = new double[Nloc]; //if(Matrix.RowPartitioning.Rank == 0) e1[0] = 1.0; double[] s = new double[Nloc], w = new double[Nloc], y; double temp; int iter; for (iter = 1; iter <= m_MaxIterations; iter++) { // GMRES iterations // r = M \ ( b-A*x ); z.SetV(B); Matrix.SpMV(-1.0, X, 1.0, z); error2 = z.L2NormPow2().MPISum().Sqrt(); if (this.Precond != null) { r.Clear(); this.Precond.Solve(r, z); } else { r.SetV(z); } // V(:,1) = r / norm( r ); double norm_r = r.L2NormPow2().MPISum().Sqrt(); V[0].SetV(r, alpha: (1.0 / norm_r)); //s = norm( r )*e1; s.SetV(e1, alpha: norm_r); int i; #region Gram-Schmidt (construct orthonormal basis using Gram-Schmidt) for (i = 1; i <= m; i++) { this.NoOfIterations++; #region Arnoldi procdure //w = M \ (A*V(:,i)); Matrix.SpMV(1.0, V[i - 1], 0.0, z); if (this.Precond != null) { w.Clear(); this.Precond.Solve(w, z); } else { w.SetV(z); } for (int k = 1; k <= i; k++) { H[k - 1, i - 1] = GenericBlas.InnerProd(w, V[k - 1]).MPISum(); //w = w - H(k,i)*V(:,k); w.AccV(-H[k - 1, i - 1], V[k - 1]); } double norm_w = w.L2NormPow2().MPISum().Sqrt(); H[i + 1 - 1, i - 1] = norm_w; // the +1-1 actually makes me sure I haven't forgotten to subtract -1 when porting the code //V(:,i+1) = w / H(i+1,i); V[i + 1 - 1].SetV(w, alpha: (1.0 / norm_w)); #endregion #region Givens rotation for (int k = 1; k <= i - 1; k++) { // apply Givens rotation, H is Hessenbergmatrix temp = cs[k - 1] * H[k - 1, i - 1] + sn[k - 1] * H[k + 1 - 1, i - 1]; H[k + 1 - 1, i - 1] = -sn[k - 1] * H[k - 1, i - 1] + cs[k - 1] * H[k + 1 - 1, i - 1]; H[k - 1, i - 1] = temp; } // [cs(i),sn(i)] = rotmat( H(i,i), H(i+1,i) ); % form i-th rotation matrix rotmat(out cs[i - 1], out sn[i - 1], H[i - 1, i - 1], H[i + 1 - 1, i - 1]); temp = cs[i - 1] * s[i - 1]; // % approximate residual norm H[i - 1, i - 1] = cs[i - 1] * H[i - 1, i - 1] + sn[i - 1] * H[i + 1 - 1, i - 1]; H[i + 1 - 1, i - 1] = 0.0; #endregion // update the residual vector (s == beta in many pseudocodes) s[i + 1 - 1] = -sn[i - 1] * s[i - 1]; s[i - 1] = temp; error = Math.Abs(s[i + 1 - 1]) / bnrm2; //{ // int rootRank = Matrix.RowPartitioning.FindProcess(i + 1 - 1); // if (Matrix.RowPartitioning.Rank == rootRank) { // } else { // error = double.NaN; // } // unsafe { // csMPI.Raw.Bcast((IntPtr)(&error), 1, csMPI.Raw._DATATYPE.DOUBLE, rootRank, Matrix.RowPartitioning.MPI_Comm); // } //} //using (StreamWriter writer = new StreamWriter(m_SessionPath + "//GMRES_Stats.txt", true)) //{ Console.WriteLine(i + " " + error); //} if (error <= m_Tolerance) { // update approximation and exit //using (StreamWriter writer = new StreamWriter(m_SessionPath + "//GMRES_Stats.txt", true)) //{ // writer.WriteLine(""); //} //y = H(1:i,1:i) \ s(1:i); y = new double[i]; H.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { i - 1, i - 1 }) .Solve(y, s.GetSubVector(0, i)); // x = x + V(:,1:i)*y; for (int ii = 0; ii < i; ii++) { X.AccV(y[ii], V[ii]); } this.m_Converged = true; break; } } #endregion //Debugger.Launch(); if (error <= this.m_Tolerance) { this.m_Converged = true; break; } // y = H(1:m,1:m) \ s(1:m); y = new double[m]; H.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { m - 1, m - 1 }) .Solve(y, s.GetSubVector(0, m)); // update approximation: x = x + V(:,1:m)*y; for (int ii = 0; ii < m; ii++) { X.AccV(y[ii], V[ii]); } // compute residual: r = M \ ( b-A*x ) z.SetV(B); Matrix.SpMV(-1.0, X, 1.0, z); if (IterationCallback != null) { error2 = z.L2NormPow2().MPISum().Sqrt(); IterationCallback(iter, X.CloneAs(), z.CloneAs(), this.m_mgop); //IterationCallback(this.NoOfIterations, X.CloneAs(), z.CloneAs(), this.m_mgop); } if (this.Precond != null) { r.Clear(); this.Precond.Solve(r, z); } else { r.SetV(z); } norm_r = r.L2NormPow2().MPISum().Sqrt(); s[i + 1 - 1] = norm_r; error = s[i + 1 - 1] / bnrm2; // % check convergence // if (error2 <= m_Tolerance) Check for error not error2 //break; } if (IterationCallback != null) { z.SetV(B); Matrix.SpMV(-1.0, X, 1.0, z); IterationCallback(iter, X.CloneAs(), z.CloneAs(), this.m_mgop); } if (!object.ReferenceEquals(_X, X)) { _X.SetV(X); } B.SetV(z); } }
/// <summary> /// % /// </summary> public void Solve <U, V>(U X, V B) where U : IList <double> where V : IList <double> // { using (var tr = new FuncTrace()) { double[] Residual = this.TestSolution ? B.ToArray() : null; string SolverName = "NotSet"; using (var solver = GetSolver(m_Mtx)) { SolverName = solver.GetType().FullName; //Console.Write("Direct solver run {0}, using {1} ... ", IterCnt, solver.GetType().Name); IterCnt++; solver.Solve(X, B); //Console.WriteLine("done."); } m_ThisLevelIterations++; if (Residual != null) { //Console.Write("Checking residual (run {0}) ... ", IterCnt - 1); double RhsNorm = Residual.L2NormPow2().MPISum().Sqrt(); double MatrixInfNorm = m_Mtx.InfNorm(); m_Mtx.SpMV(-1.0, X, 1.0, Residual); double ResidualNorm = Residual.L2NormPow2().MPISum().Sqrt(); double SolutionNorm = X.L2NormPow2().MPISum().Sqrt(); double Denom = Math.Max(MatrixInfNorm, Math.Max(RhsNorm, Math.Max(SolutionNorm, Math.Sqrt(double.Epsilon)))); double RelResidualNorm = ResidualNorm / Denom; //Console.WriteLine("done: Abs.: {0}, Rel.: {1}", ResidualNorm, RelResidualNorm); if (RelResidualNorm > 1.0e-10) { //Console.WriteLine("High residual from direct solver: abs {0}, rel {1}", ResidualNorm , ResidualNorm / SolutionNorm); m_Mtx.SaveToTextFileSparse("Mtx.txt"); X.SaveToTextFile("X.txt"); B.SaveToTextFile("B.txt"); string ErrMsg; using (var stw = new StringWriter()) { stw.WriteLine("High residual from direct solver (using {0}).", SolverName); stw.WriteLine(" L2 Norm of RHS: " + RhsNorm); stw.WriteLine(" L2 Norm of Solution: " + SolutionNorm); stw.WriteLine(" L2 Norm of Residual: " + ResidualNorm); stw.WriteLine(" Relative Residual norm: " + RelResidualNorm); stw.WriteLine(" Matrix Inf norm: " + MatrixInfNorm); stw.WriteLine("Dumping text versions of Matrix, Solution and RHS."); ErrMsg = stw.ToString(); } Console.WriteLine(ErrMsg); } } if (this.IterationCallback != null) { double[] _xl = X.ToArray(); double[] _bl = B.ToArray(); m_Mtx.SpMV(-1.0, _xl, 1.0, _bl); this.IterationCallback(1, _xl, _bl, this.m_MultigridOp); } } }
public static void XDG_MatrixPolynomialRestAndPrlgTest( [Values(0, 1, 2, 3)] int p, [Values(0.0, 0.3)] double AggregationThreshold, [Values(0, 1)] int TrackerWidth) { XQuadFactoryHelper.MomentFittingVariants variant = XQuadFactoryHelper.MomentFittingVariants.OneStepGaussAndStokes; var xt = new XDGTestSetup(p, AggregationThreshold, TrackerWidth, MultigridOperator.Mode.Eye, variant); // test matrix version of the restriction operator // ----------------------------------------------- List <MultigridMapping> MultigridMaps = new List <MultigridMapping>(); for (var mgop = xt.XdgMultigridOp; mgop != null; mgop = mgop.CoarserLevel) { MultigridMaps.Add(mgop.Mapping); } for (int iLevel = 0; iLevel < MgSeq.Length; iLevel++) { MultigridMapping mgMap = MultigridMaps[iLevel]; var XAggBasis = mgMap.AggBasis[0]; // set the test field: XDGField Test = new XDGField(xt.XB, "Test"); Random rand = new Random(); for (int i = 0; i < Test.CoordinateVector.Count; i++) { Test.CoordinateVector[i] = rand.NextDouble(); } xt.agg.ClearAgglomerated(Test.CoordinateVector, Test.Mapping); // do restriction/prolongation (Reference) double[] RestVecRef = new double[XAggBasis.LocalDim]; XAggBasis.RestictFromFullGrid(Test.CoordinateVector, RestVecRef); // and now with the matrix: BlockMsrMatrix RestMtx = new BlockMsrMatrix(mgMap, mgMap.ProblemMapping); XAggBasis.GetRestrictionMatrix(RestMtx, mgMap, 0); double[] RestVec = new double[mgMap.LocalLength]; RestMtx.SpMV(1.0, Test.CoordinateVector, 0.0, RestVec); double[] X1 = new double[xt.XdgMultigridOp.Mapping.LocalLength]; XDGField X2 = new XDGField(Test.Basis); xt.XdgMultigridOp.TransformSolInto(Test.CoordinateVector, X1); xt.XdgMultigridOp.TransformSolFrom(X2.CoordinateVector, X1); //xt.agg.Extrapolate(X2.CoordinatesAsVector, X2.Mapping); var ERR2 = Test.CloneAs(); ERR2.Acc(-1.0, X2); double ERR2Norm = ERR2.L2Norm(); //Console.WriteLine("MultigridOperator TranformInto/FransformFrom mismatch: " + ERR2Norm); Assert.LessOrEqual(ERR2Norm, 1.0e-8); // compare double ERR = 0.0; int Nmax = XAggBasis.MaximalLength; for (int jAgg = 0; jAgg < mgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; jAgg++) { int i0Ref = jAgg * Nmax; int i0Tst = mgMap.LocalUniqueIndex(0, jAgg, 0); int N = mgMap.GetLength(jAgg); for (int n = 0; n < N; n++) { double dist = RestVecRef[i0Ref + n] - RestVec[i0Tst + n]; ERR += dist.Pow2(); } } Console.WriteLine("Restriction matrix test (iLevel = {0}): {1}", iLevel, ERR); Assert.LessOrEqual(ERR, 1.0e-8); // double[] PrlgVecA = new double[XAggBasis.LocalDim]; double[] PrlgVecB = new double[mgMap.LocalLength]; for (int jAgg = 0; jAgg < mgMap.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; jAgg++) { int i0Ref = jAgg * Nmax; int i0Tst = mgMap.LocalUniqueIndex(0, jAgg, 0); int N = mgMap.GetLength(jAgg); for (int n = 0; n < N; n++) { double rndVal = rand.NextDouble(); PrlgVecA[i0Ref + n] = rndVal; PrlgVecB[i0Tst + n] = rndVal; } } XDGField QA = new XDGField(Test.Basis); XDGField QB = new XDGField(Test.Basis); XAggBasis.ProlongateToFullGrid(QA.CoordinateVector, PrlgVecA); var PrlgMtx = RestMtx.Transpose(); PrlgMtx.SpMV(1.0, PrlgVecB, 0.0, QB.CoordinateVector); XDGField ERR5 = QA.CloneAs(); ERR5.Acc(-1.0, QB); double ERR5_Norm = ERR5.L2Norm(); Console.WriteLine("Prolongation matrix test (iLevel = {0}): {1}", iLevel, ERR5_Norm); Assert.LessOrEqual(ERR5_Norm, 1.0e-8); } }
/// <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, 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, 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); XSpatialOperator.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 (evaporation) { BitArray EvapMicroRegion = new BitArray(this.LsTrk.GridDat.Cells.Count);; // this.LsTrk.GridDat.GetBoundaryCells().GetBitMask(); mtxBuilder.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("EvapMicroRegion", EvapMicroRegion); } } 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); #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 } else { XSpatialOperator.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 (evaporation) { BitArray EvapMicroRegion = new BitArray(this.LsTrk.GridDat.Cells.Count); eval.SpeciesOperatorCoefficients[kv.Key].UserDefinedValues.Add("EvapMicroRegion", EvapMicroRegion); } } 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); } // 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."); * } */ }