/// <summary> /// returns the maximum and minimum eigenvalues of the matrix /// </summary> /// <returns>Array myeigs =[MaximumEig, MinimumEig]</returns> public double[] Eigenval() { double[] eigenvalues = new double[2]; MultidimensionalArray eigs = MultidimensionalArray.Create(1, 2); MultidimensionalArray output = MultidimensionalArray.Create(2, 1); int[] DepVars = this.VarGroup; double[] DepVars_subvec = this.m_map.GetSubvectorIndices(true, DepVars).Select(i => i + 1.0).ToArray(); using (BatchmodeConnector bmc = new BatchmodeConnector()){ // if Octave should be used instead of Matlab.... //BatchmodeConnector.Flav = BatchmodeConnector.Flavor.Octave; bmc.PutSparseMatrix(m_OpMtx, "FullMatrix"); bmc.PutVector(DepVars_subvec, "DepVars_subvec"); bmc.Cmd("output = zeros(2,1)"); bmc.Cmd("output(1) = eigs(FullMatrix(DepVars_subvec,DepVars_subvec),1,'lm');"); bmc.Cmd("output(2) = eigs(FullMatrix(DepVars_subvec,DepVars_subvec),1,'sm');"); bmc.GetMatrix(output, "output"); bmc.Execute(false); } double[] myeigs = new double[] { output[0, 0], output[1, 0] }; Debug.Assert(output[0, 0].MPIEquals(), "value does not match on procs"); Debug.Assert(output[1, 0].MPIEquals(), "value does not match on procs"); return(myeigs); }
public static void GetExternalRowsTest( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(4)] int Res) { //Matlabaufruf --> gesamte Matrix nach Matlab schreiben //Teilmatritzen gemäß Globalid extrahieren //Mit ExternalRows vergleichen //Die große Frage: funktioniert der batchmode connector parallel? Beim rausschreiben beachten Utils.TestInit((int)UseXdg, DGOrder); Console.WriteLine("GetExternalRowsTest({0},{1})", UseXdg, DGOrder); //Arrange --- setup mgo and mask MultigridOperator mgo = Utils.CreateTestMGOperator(UseXdg, DGOrder, MatrixShape.laplace, Res); MultigridMapping map = mgo.Mapping; BlockMsrMatrix M = mgo.OperatorMatrix; //Delete this plz ... //M.SaveToTextFileSparse("M"); //int[] A = Utils.GimmeAllBlocksWithSpec(map, 9); //int[] B = Utils.GimmeAllBlocksWithSpec(map, 18); //if (map.MpiRank == 0) { // A.SaveToTextFileDebug("ACells"); // B.SaveToTextFileDebug("BCells"); //} var selector = new SubBlockSelector(map); var dummy = new BlockMsrMatrix(map); // we are only interested in getting indices, so a dummy is sufficient var mask = new BlockMask(selector, dummy); //Arrange --- get stuff to put into matlab int[] GlobalIdx_ext = Utils.GetAllExtCellIdc(map); double[] GlobIdx = GlobalIdx_ext.Length.ForLoop(i => (double)GlobalIdx_ext[i] + 1.0); //Arrange --- get external rows by mask BlockMsrMatrix extrows = BlockMask.GetAllExternalRows(mgo.Mapping, mgo.OperatorMatrix); //Assert --- idc and rows of extrows have to be the same Assert.IsTrue(GlobIdx.Length == extrows._RowPartitioning.LocalLength); //Arrange --- get external rows by matlab var infNorm = MultidimensionalArray.Create(1, 1); using (BatchmodeConnector matlab = new BatchmodeConnector()) { //note: BatchmodeCon maybe working on proc0 but savetotxt file, etc. (I/O) is full mpi parallel //so concider this as full mpi-parallel matlab.PutSparseMatrix(M, "M"); matlab.PutSparseMatrix(extrows, "M_test"); matlab.PutVector(GlobIdx, "Idx"); matlab.Cmd(String.Format("M_ext = M(Idx, :);")); matlab.Cmd("n=norm(M_test-M_ext,inf)"); matlab.GetMatrix(infNorm, "n"); matlab.Execute(); } //Assert --- test if we actually got the right Matrix corresponding to Index Assert.IsTrue(infNorm[0, 0] == 0.0); }
/// <summary> /// returns the condition number of the full matrix /// </summary> public double CondNumMatlab() { int[] DepVars = this.VarGroup; var grd = m_map.GridDat; int NoOfCells = grd.Grid.NumberOfCells; int NoOfBdryCells = grd.GetBoundaryCells().NoOfItemsLocally_WithExternal; var Mtx = m_MultigridOp.OperatorMatrix; // Blocks and selectors // ==================== var InnerCellsMask = grd.GetBoundaryCells().Complement(); var FullSel = new SubBlockSelector(m_MultigridOp.Mapping); FullSel.VariableSelector(this.VarGroup); // Matlab // ====== double[] Full_0Vars = (new BlockMask(FullSel)).GlobalIndices.Select(i => i + 1.0).ToArray(); MultidimensionalArray output = MultidimensionalArray.Create(2, 1); string[] names = new string[] { "Full_0Vars", "Inner_0Vars" }; using (BatchmodeConnector bmc = new BatchmodeConnector()) { // if Octave should be used instead of Matlab.... // BatchmodeConnector.Flav = BatchmodeConnector.Flavor.Octave; bmc.PutSparseMatrix(Mtx, "FullMatrix"); bmc.PutVector(Full_0Vars, "Full_0Vars"); bmc.Cmd("output = ones(2,1);"); bmc.Cmd("output(1) = condest(FullMatrix(Full_0Vars,Full_0Vars));"); bmc.GetMatrix(output, "output"); bmc.Execute(false); double condestFull = output[0, 0]; Debug.Assert(condestFull.MPIEquals(), "value does not match on procs"); Console.WriteLine($"MATLAB condition number: {condestFull:0.###e-00}"); return(condestFull); } }
public static IntersectionMesh CreateMesh(MultidimensionalArray nodes) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); IntersectionMesh mesh; using (var Matlab = new BatchmodeConnector()) { Matlab.PutMatrix(nodes, "Nodes"); // compute Voronoi diagramm Matlab.Cmd("[V, C] = voronoin(Nodes);"); // output (export from matlab) int[][] VocellVertexIndex = new int[nodes.NoOfRows][]; Matlab.GetStaggeredIntArray(VocellVertexIndex, "C"); Matlab.GetMatrix(null, "V"); // run matlab Matlab.Execute(false); // Vertices: List<Vertex> //--------------------------- MultidimensionalArray matlabVertexCoordinates = (MultidimensionalArray)(Matlab.OutputObjects["V"]); List <Vertex> vertexCoordinates = new List <Vertex>(matlabVertexCoordinates.NoOfRows); for (int i = 0; i < matlabVertexCoordinates.NoOfRows; ++i) { Vertex tmp = new Vertex(); tmp.Position = new Vector(matlabVertexCoordinates.GetRow(i)); tmp.ID = i; vertexCoordinates.Add(tmp); } //Cells: int[][] //-------------------------------------------- // correct indices (1-based index to 0-based index) for (int i = 0; i < VocellVertexIndex.Length; ++i) { for (int k = 0; k < VocellVertexIndex[i].Length; k++) { VocellVertexIndex[i][k]--; } } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds); //Convert to mesh data types //-------------------------------------------- mesh = new IntersectionMesh(new OrderedMatlabMesh(VocellVertexIndex, vertexCoordinates)); } return(mesh); }
public static void SubSelection( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(MatrixShape.full_var_spec, MatrixShape.full_spec, MatrixShape.full_var, MatrixShape.full)] MatrixShape MShape, [Values(4)] int Res) { Utils.TestInit((int)UseXdg, DGOrder, (int)MShape, Res); Console.WriteLine("SubSelection({0},{1},{2},{3})", UseXdg, DGOrder, MShape, Res); //Arrange --- create test matrix, MG mapping MultigridOperator mgo = Utils.CreateTestMGOperator(UseXdg, DGOrder, MShape, Res); MultigridMapping map = mgo.Mapping; BlockMsrMatrix M = mgo.OperatorMatrix; //Arrange --- get mask int[] cells = Utils.GetCellsOfOverlappingTestBlock(map); Array.Sort(cells); var sbs = new SubBlockSelector(map); sbs.CellSelector(cells, false); BlockMsrMatrix M_ext = BlockMask.GetAllExternalRows(map, M); var mask = new BlockMask(sbs, M_ext); //Arrange --- get GlobalIdxList int[] idc = Utils.GetIdcOfSubBlock(map, cells); bool[] coup = Utils.SetCoupling(MShape); var M_sub = mask.GetSubBlockMatrix(M, false, coup[0], coup[1]); var infNorm = MultidimensionalArray.Create(4, 1); int rank = map.MpiRank; using (BatchmodeConnector matlab = new BatchmodeConnector()) { double[] GlobIdx = idc.Count().ForLoop(i => (double)idc[i] + 1.0); Assert.IsTrue(GlobIdx.Length == M_sub.NoOfRows); matlab.PutSparseMatrix(M, "M"); // note: M_sub lives on Comm_Self, therefore we have to distinguish between procs ... matlab.PutSparseMatrixRankExclusive(M_sub, "M_sub"); matlab.PutVectorRankExclusive(GlobIdx, "Idx"); matlab.Cmd("M_0 = full(M(Idx_0, Idx_0));"); matlab.Cmd("M_1 = full(M(Idx_1, Idx_1));"); matlab.Cmd("M_2 = full(M(Idx_2, Idx_2));"); matlab.Cmd("M_3 = full(M(Idx_3, Idx_3));"); matlab.Cmd("n=[0; 0; 0; 0];"); matlab.Cmd("n(1,1)=norm(M_0-M_sub_0,inf);"); matlab.Cmd("n(2,1)=norm(M_1-M_sub_1,inf);"); matlab.Cmd("n(3,1)=norm(M_2-M_sub_2,inf);"); matlab.Cmd("n(4,1)=norm(M_3-M_sub_3,inf);"); matlab.GetMatrix(infNorm, "n"); matlab.Execute(); } Assert.IsTrue(infNorm[rank, 0] == 0.0); }
private void OperatorAnalysis() { AggregationGridBasis[][] XAggB = AggregationGridBasis.CreateSequence(base.MultigridSequence, u.Mapping.BasisS); XAggB.UpdateXdgAggregationBasis(this.Op_Agglomeration); var MultigridOp = new MultigridOperator(XAggB, this.u.Mapping, this.Op_Matrix, this.Op_mass.GetMassMatrix(new UnsetteledCoordinateMapping(this.u.Basis), false), OpConfig); var PcOpMatrix = MultigridOp.OperatorMatrix; //PcOpMatrix.SaveToTextFileSparse("C:\\temp\\Xpoisson.txt"); MultidimensionalArray ret = MultidimensionalArray.Create(1, 4); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(PcOpMatrix, "OpMtx"); bmc.Cmd("OpMtxSym = 0.5*(OpMtx + OpMtx');"); bmc.Cmd("condNo = condest(OpMtxSym);"); bmc.Cmd("eigMaxi = eigs(OpMtxSym,1,'lm')"); bmc.Cmd("eigMini = eigs(OpMtxSym,1,'sm')"); bmc.Cmd("lasterr"); bmc.Cmd("[V,r]=chol(OpMtxSym);"); bmc.Cmd("ret = [condNo, eigMaxi, eigMini, r]"); bmc.GetMatrix(ret, "ret"); bmc.Execute(false); } double condNo = ret[0, 0]; double eigMaxi = ret[0, 1]; double eigMini = ret[0, 2]; double posDef = ret[0, 3] == 0 ? 1 : 0; Console.WriteLine("Condition number: {0:0.####E-00}", condNo); if (posDef == 0.0) { Console.WriteLine("WARNING: Operator matrix is not positive definite."); } base.QueryHandler.ValueQuery("condNo", condNo, false); base.QueryHandler.ValueQuery("eigMaxi", eigMaxi, false); base.QueryHandler.ValueQuery("eigMini", eigMini, false); base.QueryHandler.ValueQuery("posDef", posDef, false); }
/// <summary> /// /// </summary> public void AnalyzeOperators(out MultidimensionalArray ret) { ret = MultidimensionalArray.Create(1, 7); // MultidimensionalArray ret = MultidimensionalArray.Create(1, 4); Console.WriteLine("Calling MATLAB/Octave..."); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(OpMatrix, "OpMatrix"); bmc.Cmd("condNoOpMatrix = condest(OpMatrix)"); bmc.Cmd("OpRank = rank(full(OpMatrix))"); bmc.Cmd("OpSize = size(OpMatrix)"); bmc.Cmd("eigiMaxi = eigs(OpMatrix,1,'lm')"); bmc.Cmd("eigiMini = eigs(OpMatrix,1,'sm')"); bmc.Cmd("lasterr"); bmc.Cmd("[V,r]=chol(OpMatrix);"); bmc.Cmd("ret = [condNoOpMatrix, eigiMaxi, eigiMini, r, OpRank, OpSize]"); bmc.GetMatrix(ret, "ret"); bmc.Execute(true); } double condNoOpMatrix = ret[0, 0]; double eigiMaxi = ret[0, 1]; double eigiMini = ret[0, 2]; double posDef = ret[0, 3] == 0 ? 1 : 0; Console.WriteLine("Condition number operator: {0:0.####E-00}", condNoOpMatrix); if (posDef == 0.0) { Console.WriteLine("WARNING: Operator matrix is not positive definite."); } else { Console.WriteLine("Good news: Operator matrix seems to be positive definite."); } }
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; } }
public static void SubMatrixTest( [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("SubMatrixTest({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(); stw.Start(); BlockMsrMatrix M = solver.OperatorMatrix; int[] Ilist1 = solver.ProblemMapping.GetSubvectorIndices(false, 0); int[] Ilist2 = solver.ProblemMapping.GetSubvectorIndices(false, 1); foreach (int i in Ilist1) { Assert.IsTrue(solver.ProblemMapping.IsInLocalRange(i)); } foreach (int i in Ilist2) { Assert.IsTrue(solver.ProblemMapping.IsInLocalRange(i)); } var Blk1 = solver.ProblemMapping.GetSubBlocking(Ilist1, csMPI.Raw._COMM.WORLD, compressL1 ? -1 : 0); var Blk2 = solver.ProblemMapping.GetSubBlocking(Ilist2, csMPI.Raw._COMM.WORLD, compressL2 ? -1 : 0); int[] Tlist1 = compressL1 ? default(int[]) : Blk1.GetOccupiedIndicesList(); int[] Tlist2 = compressL2 ? default(int[]) : Blk2.GetOccupiedIndicesList(); if (Tlist1 != null) { Assert.AreEqual(Tlist1.Length, Ilist1.Length); foreach (int i in Tlist1) { Assert.IsTrue(Blk1.IsInLocalRange(i)); } } if (Tlist2 != null) { Assert.AreEqual(Tlist2.Length, Ilist2.Length); foreach (int i in Tlist2) { Assert.IsTrue(Blk2.IsInLocalRange(i)); } } BlockMsrMatrix M11 = new BlockMsrMatrix(Blk1, Blk1); BlockMsrMatrix M12 = new BlockMsrMatrix(Blk1, Blk2); BlockMsrMatrix M21 = new BlockMsrMatrix(Blk2, Blk1); BlockMsrMatrix M22 = new BlockMsrMatrix(Blk2, Blk2); M.AccSubMatrixTo(1.0, M11, Ilist1, Tlist1, Ilist1, Tlist1); M.AccSubMatrixTo(1.0, M12, Ilist1, Tlist1, Ilist2, Tlist2); M.AccSubMatrixTo(1.0, M21, Ilist2, Tlist2, Ilist1, Tlist1); M.AccSubMatrixTo(1.0, M22, Ilist2, Tlist2, Ilist2, Tlist2); BlockMsrMatrix restored_M = new BlockMsrMatrix(M._RowPartitioning, M._ColPartitioning); int[] Idx1 = compressL1 ? Blk1.LocalLength.ForLoop(i => i + Blk1.i0) : Tlist1; int[] Idx2 = compressL2 ? Blk2.LocalLength.ForLoop(i => i + Blk2.i0) : Tlist2; M11.AccSubMatrixTo(1.0, restored_M, Idx1, Ilist1, Idx1, Ilist1); M12.AccSubMatrixTo(1.0, restored_M, Idx1, Ilist1, Idx2, Ilist2); M21.AccSubMatrixTo(1.0, restored_M, Idx2, Ilist2, Idx1, Ilist1); M22.AccSubMatrixTo(1.0, restored_M, Idx2, Ilist2, Idx2, Ilist2); // test transpose-operator var M_TT = M.Transpose().Transpose(); var M11_TT = M11.Transpose().Transpose(); var M12_TT = M12.Transpose().Transpose(); var M21_TT = M21.Transpose().Transpose(); var M22_TT = M22.Transpose().Transpose(); M_TT.Acc(-1.0, M); M11_TT.Acc(-1.0, M11); M12_TT.Acc(-1.0, M12); M21_TT.Acc(-1.0, M21); M22_TT.Acc(-1.0, M22); double M_TT_norm = M_TT.InfNorm(); double M11_TT_norm = M11_TT.InfNorm(); double M12_TT_norm = M12_TT.InfNorm(); double M21_TT_norm = M21_TT.InfNorm(); double M22_TT_norm = M22_TT.InfNorm(); Assert.IsTrue(M_TT_norm == 0.0, "Transpose^2 is not identity."); Assert.IsTrue(M11_TT_norm == 0.0, "Transpose^2 is not identity."); Assert.IsTrue(M12_TT_norm == 0.0, "Transpose^2 is not identity."); Assert.IsTrue(M21_TT_norm == 0.0, "Transpose^2 is not identity."); Assert.IsTrue(M22_TT_norm == 0.0, "Transpose^2 is not identity."); //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"); //restored_M.SaveToTextFileSparse(@"C:\tmp\Mr.txt"); stw.Stop(); using (var MatlabRef = new BatchmodeConnector()) { MatlabRef.PutVector(Ilist1.Select(i => (double)i + 1.0).ToArray(), "Ilist1"); MatlabRef.PutVector(Ilist2.Select(i => (double)i + 1.0).ToArray(), "Ilist2"); MatlabRef.PutVector(Tlist1 == null ? Ilist1.Length.ForLoop(i => (double)i + 1.0 + Blk1.i0) : Tlist1.Select(i => (double)i + 1.0).ToArray(), "Tlist1"); MatlabRef.PutVector(Tlist2 == null ? Ilist2.Length.ForLoop(i => (double)i + 1.0 + Blk2.i0) : Tlist2.Select(i => (double)i + 1.0).ToArray(), "Tlist2"); MultidimensionalArray CheckRes = MultidimensionalArray.Create(1, 4); MatlabRef.PutSparseMatrix(M, "M"); MatlabRef.PutSparseMatrix(M11, "M11"); MatlabRef.PutSparseMatrix(M12, "M12"); MatlabRef.PutSparseMatrix(M21, "M21"); MatlabRef.PutSparseMatrix(M22, "M22"); MatlabRef.Cmd("L1 = {0};", Blk1.TotalLength); MatlabRef.Cmd("L2 = {0};", Blk2.TotalLength); MatlabRef.Cmd("refM11 = sparse(L1, L1);"); MatlabRef.Cmd("refM12 = sparse(L1, L2);"); MatlabRef.Cmd("refM21 = sparse(L2, L1);"); MatlabRef.Cmd("refM22 = sparse(L2, L2);"); MatlabRef.Cmd("refM11(Tlist1, Tlist1) = M(Ilist1, Ilist1);"); MatlabRef.Cmd("refM12(Tlist1, Tlist2) = M(Ilist1, Ilist2);"); MatlabRef.Cmd("refM21(Tlist2, Tlist1) = M(Ilist2, Ilist1);"); MatlabRef.Cmd("refM22(Tlist2, Tlist2) = M(Ilist2, Ilist2);"); MatlabRef.Cmd("err11 = norm(refM11 - M11, inf);"); MatlabRef.Cmd("err12 = norm(refM12 - M12, inf);"); MatlabRef.Cmd("err21 = norm(refM21 - M21, inf);"); MatlabRef.Cmd("err22 = norm(refM22 - M22, inf);"); MatlabRef.Cmd("CheckRes = [err11, err12, err21, err22];"); MatlabRef.GetMatrix(CheckRes, "CheckRes"); MatlabRef.Execute(); Console.WriteLine("Matlab check 11: " + CheckRes[0, 0]); Console.WriteLine("Matlab check 12: " + CheckRes[0, 1]); Console.WriteLine("Matlab check 21: " + CheckRes[0, 2]); Console.WriteLine("Matlab check 22: " + CheckRes[0, 3]); Assert.IsTrue(CheckRes[0, 0] == 0.0); Assert.IsTrue(CheckRes[0, 1] == 0.0); Assert.IsTrue(CheckRes[0, 2] == 0.0); Assert.IsTrue(CheckRes[0, 3] == 0.0); } stw.Start(); restored_M.Acc(-1.0, M); double err = restored_M.InfNorm(); Console.WriteLine("Submatrix operations error: " + err); Assert.IsTrue(err == 0.0); restored_M.Clear(); restored_M.Acc(1.0, M); IMutuableMatrixEx_Extensions.Acc(restored_M, -1.0, M); double err2 = restored_M.InfNorm(); Console.WriteLine("Submatrix operations error: " + err2); Assert.IsTrue(err2 == 0.0); stw.Stop(); Console.WriteLine("Time spend in matrix operations: " + stw.Elapsed.TotalSeconds + " sec."); TotTime_MatrixOp += stw.Elapsed; } }
/// <summary> /// /// </summary> public void AnalyzeOperators(out MultidimensionalArray ret) { int length = OpMatrix.NoOfRows / Extension.Basis.Length; //int[,] PatternMatrix = new int[length, length]; // lässt sich besser anschauen? MsrMatrix PatternMatrix = new MsrMatrix(length); for (int i = 0; i < length; i++) { for (int j = 0; j < length; j++) { if (OpMatrix[i * Extension.Basis.Length, j *Extension.Basis.Length] != 0) { PatternMatrix[i, j] = 1; } } } ret = MultidimensionalArray.Create(1, 4); Console.WriteLine("Calling MATLAB/Octave..."); MultidimensionalArray L = MultidimensionalArray.Create(PatternMatrix.NoOfRows, PatternMatrix.NoOfRows); MultidimensionalArray U = MultidimensionalArray.Create(PatternMatrix.NoOfRows, PatternMatrix.NoOfRows); MultidimensionalArray P = MultidimensionalArray.Create(PatternMatrix.NoOfRows, PatternMatrix.NoOfRows); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(PatternMatrix, "PatternMatrix"); bmc.Cmd("[L, U, P] = lu(PatternMatrix);"); bmc.PutSparseMatrix(OpMatrix, "OpMatrix"); bmc.Cmd("condNoOpMatrix = condest(OpMatrix);"); bmc.Cmd("eigiMaxi = eigs(OpMatrix,1,'lm')"); bmc.Cmd("eigiMini = eigs(OpMatrix,1,'sm')"); bmc.Cmd("lasterr"); bmc.Cmd("[V,r]=chol(OpMatrix);"); bmc.Cmd("ret = [condNoOpMatrix, eigiMaxi, eigiMini, r]"); bmc.GetMatrix(L, "full(L)"); bmc.GetMatrix(U, "full(U)"); bmc.GetMatrix(P, "full(P)"); bmc.GetMatrix(ret, "ret"); bmc.Execute(true); } //PatternMatrix.SaveToTextFile("Patternmatrix.txt"); //PatternMatrix.SaveToTextFileSparse("PatternmatrixSparse.txt"); double condNoOpMatrix = ret[0, 0]; double eigiMaxi = ret[0, 1]; double eigiMini = ret[0, 2]; double posDef = ret[0, 3] == 0 ? 1 : 0; Console.WriteLine("Condition number operator: {0:0.####E-00}", condNoOpMatrix); if (posDef == 0.0) { Console.WriteLine("WARNING: Operator matrix is not positive definite."); } else { Console.WriteLine("Good news: Operator matrix seems to be positive definite."); } }
public static void MultiplyTest( [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("MultiplyTest({0},{1},{2},{3})", UseXdg, DGOrder, compressL1, compressL2); } using (var solver = new Matrix_MPItestMain() { m_UseXdg = UseXdg, m_DGorder = DGOrder }) { // create the test data // ==================== solver.Init(null); solver.RunSolverMode(); Stopwatch stw = new Stopwatch(); stw.Reset(); stw.Start(); BlockMsrMatrix M = solver.OperatorMatrix; int[] Ilist1 = solver.ProblemMapping.GetSubvectorIndices(false, 0); int[] Ilist2 = solver.ProblemMapping.GetSubvectorIndices(false, 1); foreach (int i in Ilist1) { Assert.IsTrue(solver.ProblemMapping.IsInLocalRange(i)); } foreach (int i in Ilist2) { Assert.IsTrue(solver.ProblemMapping.IsInLocalRange(i)); } var Blk1 = solver.ProblemMapping.GetSubBlocking(Ilist1, csMPI.Raw._COMM.WORLD, compressL1 ? -1 : 0); var Blk2 = solver.ProblemMapping.GetSubBlocking(Ilist2, csMPI.Raw._COMM.WORLD, compressL2 ? -1 : 0); int[] Tlist1 = compressL1 ? default(int[]) : Blk1.GetOccupiedIndicesList(); int[] Tlist2 = compressL2 ? default(int[]) : Blk2.GetOccupiedIndicesList(); if (Tlist1 != null) { Assert.AreEqual(Tlist1.Length, Ilist1.Length); foreach (int i in Tlist1) { Assert.IsTrue(Blk1.IsInLocalRange(i)); } } if (Tlist2 != null) { Assert.AreEqual(Tlist2.Length, Ilist2.Length); foreach (int i in Tlist2) { Assert.IsTrue(Blk2.IsInLocalRange(i)); } } BlockMsrMatrix M11 = new BlockMsrMatrix(Blk1, Blk1); BlockMsrMatrix M12 = new BlockMsrMatrix(Blk1, Blk2); BlockMsrMatrix M21 = new BlockMsrMatrix(Blk2, Blk1); BlockMsrMatrix M22 = new BlockMsrMatrix(Blk2, Blk2); M.AccSubMatrixTo(1.0, M11, Ilist1, Tlist1, Ilist1, Tlist1); M.AccSubMatrixTo(1.0, M12, Ilist1, Tlist1, Ilist2, Tlist2); M.AccSubMatrixTo(1.0, M21, Ilist2, Tlist2, Ilist1, Tlist1); M.AccSubMatrixTo(1.0, M22, Ilist2, Tlist2, Ilist2, Tlist2); /* * MultidimensionalArray CheckRes2 = MultidimensionalArray.Create(1, 4); * using (var MatlabRef = new BatchmodeConnector()) { * * MatlabRef.PutVector(Ilist1.Select(i => (double)i + 1.0).ToArray(), "Ilist1"); * MatlabRef.PutVector(Ilist2.Select(i => (double)i + 1.0).ToArray(), "Ilist2"); * MatlabRef.PutVector(Tlist1 == null ? Ilist1.Length.ForLoop(i => (double)i + 1.0 + Blk1.i0) : Tlist1.Select(i => (double)i + 1.0).ToArray(), "Tlist1"); * MatlabRef.PutVector(Tlist2 == null ? Ilist2.Length.ForLoop(i => (double)i + 1.0 + Blk2.i0) : Tlist2.Select(i => (double)i + 1.0).ToArray(), "Tlist2"); * * MatlabRef.PutSparseMatrix(solver.AltOperatorMatrix, "M"); * * * MatlabRef.Cmd("L1 = {0};", Blk1.TotalLength); * MatlabRef.Cmd("L2 = {0};", Blk2.TotalLength); * //MatlabRef.Cmd("refM11 = sparse(L1, L1);"); * //MatlabRef.Cmd("refM12 = sparse(L1, L2);"); * MatlabRef.Cmd("refM21 = sparse(L2, L1);"); * //MatlabRef.Cmd("refM22 = sparse(L2, L2);"); * * //MatlabRef.Cmd("refM11(Tlist1, Tlist1) = M(Ilist1, Ilist1);"); * //MatlabRef.Cmd("refM12(Tlist1, Tlist2) = M(Ilist1, Ilist2);"); * MatlabRef.Cmd("refM21(Tlist2, Tlist1) = M(Ilist2, Ilist1);"); * //MatlabRef.Cmd("refM22(Tlist2, Tlist2) = M(Ilist2, Ilist2);"); * * //MatlabRef.Cmd("err11 = norm(refM11 - M11, inf);"); * //MatlabRef.Cmd("err12 = norm(refM12 - M12, inf);"); * //MatlabRef.Cmd("err21 = norm(refM21 - M21, inf);"); * //MatlabRef.Cmd("err22 = norm(refM22 - M22, inf);"); * * MatlabRef.Cmd("CheckRes = [refM21(1339, 1321), 0.0, 1.567, 0 ];"); * MatlabRef.GetMatrix(CheckRes2, "CheckRes"); * * MatlabRef.Execute(); * } */ // test multipliation (later verified by matlab) BlockMsrMatrix M11xM12 = new BlockMsrMatrix(M11._RowPartitioning, M12._ColPartitioning); M11xM12.Acc(1.0, M12); BlockMsrMatrix.Multiply(M11xM12, M11, M12); BlockMsrMatrix M22xM21 = new BlockMsrMatrix(M22._RowPartitioning, M21._ColPartitioning); BlockMsrMatrix.Multiply(M22xM21, M22, M21); double ProdNorm = M22xM21.InfNorm(); 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, 4); MatlabRef.PutSparseMatrix(M11, "M11"); MatlabRef.PutSparseMatrix(M12, "M12"); MatlabRef.PutSparseMatrix(M21, "M21"); MatlabRef.PutSparseMatrix(M22, "M22"); MatlabRef.PutSparseMatrix(M11xM12, "M11xM12"); MatlabRef.PutSparseMatrix(M22xM21, "M22xM21"); MatlabRef.Cmd("refM11xM12 = M12 + M11*M12;"); MatlabRef.Cmd("refM22xM21 = M22*M21;"); MatlabRef.Cmd("err1112 = norm(refM11xM12 - M11xM12, inf);"); MatlabRef.Cmd("err2221 = norm(refM22xM21 - M22xM21, inf);"); MatlabRef.Cmd("CheckRes = [err1112, err2221, 0, 0];"); MatlabRef.GetMatrix(CheckRes, "CheckRes"); MatlabRef.Execute(); Console.WriteLine("Matlab check M11*M12: " + CheckRes[0, 0]); Console.WriteLine("Matlab check M22*M21: " + CheckRes[0, 1]); Assert.IsTrue(CheckRes[0, 0] == 0.0); Assert.IsTrue(CheckRes[0, 1] < 1.0e-10 * ProdNorm); //Assert.IsTrue(CheckRes[0, 2] == 0.0); //Assert.IsTrue(CheckRes[0, 3] == 0.0); } Console.WriteLine("Time spend in matrix operations: " + stw.Elapsed.TotalSeconds + " sec."); TotTime_MatrixOp += stw.Elapsed; } }
/// <summary> /// Spatial operator matrix analysis method /// </summary> public void SpatialOperatorMatrixAnalysis(bool CheckAssertions, int AnalysisLevel) { using (var solver = new Rheology()) { int D = solver.Grid.SpatialDimension; if (AnalysisLevel < 0 || AnalysisLevel > 2) { throw new ArgumentException(); } BlockMsrMatrix OpMatrix; double[] OpAffine; solver.AssembleMatrix(out OpMatrix, out OpAffine, solver.CurrentSolution.Mapping.ToArray(), true); // ============================= // AnalysisLevel 0 // ============================= { var OpMatrixT = OpMatrix.Transpose(); CoordinateVector TestVec = new CoordinateVector(solver.CurrentSolution.Mapping.Fields.Select(f => f.CloneAs()).ToArray()); double testsumPos = 0.0; double testsumNeg = 0.0; for (int rnd_seed = 0; rnd_seed < 20; rnd_seed++) { // fill the pressure components of the test vector TestVec.Clear(); Random rnd = new Random(rnd_seed); DGField Pressack = TestVec.Mapping.Fields[D] as DGField; int J = solver.GridData.iLogicalCells.NoOfLocalUpdatedCells; for (int j = 0; j < J; j++) { int N = Pressack.Basis.GetLength(j); for (int n = 0; n < N; n++) { Pressack.Coordinates[j, n] = rnd.NextDouble(); } } // Gradient times P: double[] R1 = new double[TestVec.Count]; OpMatrix.SpMV(1.0, TestVec, 0.0, R1); // R1 = Grad * P //Console.WriteLine("L2 of 'Grad * P': " + R1.L2Norm()); // transpose of Divergence times P: double[] R2 = new double[TestVec.Count]; OpMatrix.SpMV(1.0, TestVec, 0.0, R2); // R2 = divT * P //Console.WriteLine("L2 of 'divT * P': " + R2.L2Norm()); TestVec.Clear(); TestVec.Acc(1.0, R1); TestVec.Acc(1.0, R2); // analyze! testsumNeg += GenericBlas.L2Dist(R1, R2); R2.ScaleV(-1.0); testsumPos += GenericBlas.L2Dist(R1, R2); } Console.WriteLine("Pressure/Divergence Symmetry error in all tests (+): " + testsumPos); Console.WriteLine("Pressure/Divergence Symmetry error in all tests (-): " + testsumNeg); if (CheckAssertions) { Assert.LessOrEqual(Math.Abs(testsumNeg), testsumPos * 1.0e-13); } } // ============================= // AnalysisLevel 1 and 2 // ============================= if (AnalysisLevel > 0) { AggregationGridBasis[][] MgBasis = AggregationGridBasis.CreateSequence(solver.MultigridSequence, solver.CurrentSolution.Mapping.BasisS); MultigridOperator mgOp = new MultigridOperator(MgBasis, solver.CurrentSolution.Mapping, OpMatrix, null, solver.MultigridOperatorConfig); // extract //////////// MsrMatrix FullMatrix = mgOp.OperatorMatrix.ToMsrMatrix(); MsrMatrix DiffMatrix; { int[] VelVarIdx = D.ForLoop(d => d); int[] USubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(VelVarIdx); int[] USubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(VelVarIdx); int L = USubMatrixIdx_Row.Length; DiffMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(DiffMatrix, USubMatrixIdx_Row, default(int[]), USubMatrixIdx_Col, default(int[])); double DiffMatrix_sd = DiffMatrix.SymmetryDeviation(); Console.WriteLine("Diffusion assymetry:" + DiffMatrix_sd); } MsrMatrix SaddlePointMatrix; { int[] VelPVarIdx = new int[] { 0, 1, 2 }; int[] VelPSubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(VelPVarIdx); int[] VelPSubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(VelPVarIdx); int L = VelPSubMatrixIdx_Row.Length; SaddlePointMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(SaddlePointMatrix, VelPSubMatrixIdx_Row, default(int[]), VelPSubMatrixIdx_Col, default(int[])); } //SaddlePointMatrix.SaveToTextFileSparse("C:\\Users\\kikker\\Documents\\MATLAB\\spm.txt"); MsrMatrix ConstitutiveMatrix; { int[] StressVarIdx = new int[] { 3, 4, 5 }; int[] StressSubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(StressVarIdx); int[] StressSubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(StressVarIdx); int L = StressSubMatrixIdx_Row.Length; ConstitutiveMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(ConstitutiveMatrix, StressSubMatrixIdx_Row, default(int[]), StressSubMatrixIdx_Col, default(int[])); } // operator analysis ////////////////////// bool posDef; if (AnalysisLevel > 1) { // +++++++++++++++++++++++++++++++ // check condition number, etc // +++++++++++++++++++++++++++++++ MultidimensionalArray ret = MultidimensionalArray.Create(1, 5); Console.WriteLine("Calling MATLAB/Octave..."); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(FullMatrix, "FullMatrix"); bmc.PutSparseMatrix(SaddlePointMatrix, "SaddlePointMatrix"); bmc.PutSparseMatrix(ConstitutiveMatrix, "ConstitutiveMatrix"); bmc.PutSparseMatrix(DiffMatrix, "DiffMatrix"); bmc.Cmd("DiffMatrix = 0.5*(DiffMatrix + DiffMatrix');"); bmc.Cmd("condNoFullMatrix = condest(FullMatrix);"); bmc.Cmd("condNoSaddlePointMatrix = condest(SaddlePointMatrix);"); bmc.Cmd("condNoConstitutiveMatrix = condest(ConstitutiveMatrix);"); bmc.Cmd("condNoDiffMatrix = condest(DiffMatrix);"); //bmc.Cmd("eigiMaxiSaddle = 1.0; % eigs(SaddlePointMatrix,1,'lm')"); //bmc.Cmd("eigiMiniSaddle = 1.0; % eigs(SaddlePointMatrix,1,'sm')"); //bmc.Cmd("eigiMaxiConst = 1.0; % eigs(ConstitutiveMatrix,1,'lm')"); //bmc.Cmd("eigiMiniConst = 1.0; % eigs(ConstitutiveMatrix,1,'sm')"); //bmc.Cmd("eigiMaxiDiff = 1.0; % eigs(DiffMatrix,1,'lm')"); //bmc.Cmd("eigiMiniDiff = 1.0; % eigs(DiffMatrix,1,'sm')"); bmc.Cmd("lasterr"); bmc.Cmd("[V,r]=chol(SaddlePointMatrix);"); bmc.Cmd("[V,r]=chol(ConstitutiveMatrix);"); bmc.Cmd("ret = [condNoFullMatrix, condNoSaddlePointMatrix, condNoConstitutiveMatrix, condNoDiffMatrix, r]"); //eigiMaxiSaddle, eigiMiniSaddle, eigiMaxiConst, eigiMiniConst, eigiMaxiDiff, eigiMiniDiff, bmc.GetMatrix(ret, "ret"); bmc.Execute(false); } double condNoFullMatrix = ret[0, 0]; double condNoSaddlePMatrix = ret[0, 1]; double condNoConstitutiveMatrix = ret[0, 2]; double condNoDiffMatrix = ret[0, 3]; //double eigiMaxiSaddle = ret[0, 4]; //double eigiMiniSaddle = ret[0, 5]; //double eigiMaxiConst = ret[0, 6]; //double eigiMiniConst = ret[0, 7]; //double eigiMaxiDiff = ret[0, 8]; //double eigiMiniDiff = ret[0, 9]; posDef = ret[0, 4] == 0; //Console.WriteLine("Eigenvalue range of saddle point matrix: {0} to {1}", eigiMiniSaddle, eigiMaxiSaddle); //Console.WriteLine("Eigenvalue range of constitutive matrix: {0} to {1}", eigiMiniConst, eigiMaxiConst); //Console.WriteLine("Eigenvalue range of diffusion matrix: {0} to {1}", eigiMiniDiff, eigiMaxiDiff); Console.WriteLine("Condition number full operator: {0:0.####E-00}", condNoFullMatrix); Console.WriteLine("Condition number saddle point operator: {0:0.####E-00}", condNoSaddlePMatrix); Console.WriteLine("Condition number constitutive operator: {0:0.####E-00}", condNoConstitutiveMatrix); Console.WriteLine("Condition number diffusion operator: {0:0.####E-00}", condNoDiffMatrix); //base.QueryHandler.ValueQuery("ConditionNumber", condNoFullMatrix); } else { // +++++++++++++++++++++++++++++++++++++++ // test only for positive definiteness // +++++++++++++++++++++++++++++++++++++++ var SaddlePMatrixFull = SaddlePointMatrix.ToFullMatrixOnProc0(); var ConstMatrixFull = ConstitutiveMatrix.ToFullMatrixOnProc0(); posDef = true; try { SaddlePMatrixFull.Cholesky(); } catch (ArithmeticException) { posDef = false; } posDef = true; try { ConstMatrixFull.Cholesky(); } catch (ArithmeticException) { posDef = false; } } double SaddlePSymm = SaddlePointMatrix.SymmetryDeviation(); Console.WriteLine("Symmetry deviation of saddle point matrix: " + SaddlePSymm); if (posDef) { Console.WriteLine("Good news: Saddle point operator matrix seems to be positive definite."); } else { Console.WriteLine("WARNING: Saddle point operator matrix is not positive definite."); } double ConstSymm = ConstitutiveMatrix.SymmetryDeviation(); Console.WriteLine("Symmetry deviation of constitutive matrix: " + ConstSymm); if (posDef) { Console.WriteLine("Good news: constitutive operator matrix seems to be positive definite."); } else { Console.WriteLine("WARNING: constitutive operator matrix is not positive definite."); } //if (CheckAssertions) { // if (Control.AdvancedDiscretizationOptions.ViscosityMode == ViscosityMode.FullySymmetric && Control.PhysicalParameters.IncludeConvection == false) { // Assert.IsTrue(posDef, "Positive definiteness test failed."); // double compVal = DiffMatrix.InfNorm() * 1e-13; // Assert.LessOrEqual(DiffSymm, compVal, "Diffusion matrix seems to be non-symmetric."); // } //} } } }
public void Solve <U, V>(U X, V B) where U : IList <double> where V : IList <double> { var Bu = new double[Uidx.Length]; var Xu = Bu.CloneAs(); Bu = B.GetSubVector(Uidx, default(int[])); var Bp = new double[Pidx.Length]; var Xp = Bp.CloneAs(); Bp = B.GetSubVector(Pidx, default(int[])); Xu = X.GetSubVector(Uidx, default(int[])); Xp = X.GetSubVector(Pidx, default(int[])); P = new BlockMsrMatrix(null, null);// Pidx.Length, Pidx.Length); // MultidimensionalArray Schur = MultidimensionalArray.Create(Pidx.Length, Pidx.Length); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(LocalMatrix, "LocalMatrix"); bmc.PutSparseMatrix(divVel, "divVel"); bmc.PutSparseMatrix(pGrad, "pGrad"); bmc.Cmd("invLocalMatrix = inv(full(LocalMatrix))"); bmc.Cmd("Poisson = invLocalMatrix*pGrad"); bmc.Cmd("Schur= divVel*Poisson"); bmc.GetMatrix(Schur, "Schur"); bmc.Execute(false); } P = null; // Schur.ToMsrMatrix(); //P.SaveToTextFileSparse("LocalSchur"); using (var solver = new ilPSP.LinSolvers.MUMPS.MUMPSSolver()) { solver.DefineMatrix(P); solver.Solve(Xp, Bp); } //var temp2 = Xp.CloneAs(); //LocalMatrix.SpMV(1, Xp, 0, temp2); //using (var solver = new ilPSP.LinSolvers.MUMPS.MUMPSSolver()) //{ // solver.DefineMatrix(divVel); // solver.Solve(Xp, temp2); //} // Solve ConvD iff*w=v-q*pGrad pGrad.SpMV(-1, Xp, 1, Bu); using (var solver = new ilPSP.LinSolvers.MUMPS.MUMPSSolver()) { solver.DefineMatrix(ConvDiff); solver.Solve(Xu, Bu); } var temp = new double[Uidx.Length + Pidx.Length]; for (int i = 0; i < Uidx.Length; i++) { temp[Uidx[i]] = Xu[i]; } for (int i = 0; i < Pidx.Length; i++) { temp[Pidx[i]] = Xp[i]; } X.SetV(temp); m_ThisLevelIterations++; }
/// <summary> /// According to the Rouché-Capelli theorem, the system is inconsistent if rank(augMatrix) > rank(Matrix). /// If rank(augMatrix) == rank(Matrix), the system has at least one solution. /// Additionally, if the rank is equal to the number of variables, the solution of the system is unique. /// Remark: This requires the whole RHS not only local!!! /// </summary> /// <param name="OpMatrix"></param> /// <param name="RHS"></param> public void rankAnalysis(BlockMsrMatrix OpMatrix, double[] RHS) { int RHSlen = this.localRHS.Length; Debug.Assert(RHSlen == m_OpMtx.RowPartitioning.LocalLength); MultidimensionalArray outputArray = MultidimensionalArray.Create(2, 1); // The two rank values //At this point OpMatrix and RHS are local, they are collected within bmc on proc rank==0 using (var bmc = new BatchmodeConnector()){ bmc.PutSparseMatrix(OpMatrix, "OpMatrix"); bmc.PutVector(RHS, "RHS"); bmc.Cmd("output = zeros(2,1)"); // First value is rank(OpMatrix), second the rank of the augmented matrix = rank([Matrix|RHS]) bmc.Cmd(""); bmc.Cmd("fullMtx = full(OpMatrix);"); bmc.Cmd("augmentedMtx = [fullMtx RHS];"); bmc.Cmd("output(1) = rank(fullMtx)"); bmc.Cmd("output(2) = rank(augmentedMtx)"); bmc.GetMatrix(outputArray, "output"); bmc.Execute(false); } double[] output = new double[2]; output[0] = outputArray[0, 0]; //Rank matrix output[1] = outputArray[1, 0]; //Rank augmented matrix ( [Matrix|RHS]) double rnkMtx = output[0]; double rnkAugmentedMtx = output[1]; // Some tests Console.WriteLine("=================================================================="); //Output { Console.WriteLine("Results of rank analysis:"); if (rnkAugmentedMtx > rnkMtx) { //throw new Exception("The rank of the augmented matrix shouldn't be greater than the one of the original matrix!!"); Console.WriteLine("======================================================"); Console.WriteLine("WARNING!!!!!!! The rank of the augmented matrix shouldn't be greater than the one of the original matrix!!"); Console.WriteLine("This means that the system doesnt have a solution!"); } if (rnkAugmentedMtx == rnkMtx) { Console.WriteLine("The system has at least a solution"); } //RHS and OpMatrix will be collected in Bmc, so total length has to be considered for RHS: RHS.length will lead to errors in parallel execution if (rnkMtx < RHSlen) { Console.WriteLine("The rank of the matrix is smaller than the number of variables. There are {0} free parameters", (RHS.Length - rnkMtx)); } else if (rnkMtx == RHSlen) { Console.WriteLine("The system has a unique solution :) "); } else { throw new Exception("what? should not happen"); } Console.WriteLine("Rank of the matrix : {0} \n" + "Rank of the augmented matrix : {1} \n" + "Number of variables: {2}", output[0], output[1], RHS.Length); Console.WriteLine("=================================================================="); } Debug.Assert(output[0].MPIEquals(), "value does not match on procs"); Debug.Assert(output[1].MPIEquals(), "value does not match on procs"); }
/// <summary> /// Test on a 2D Voronoi mesh /// </summary> /// <param name="Res"> /// number of randomly chosen Delaunay vertices /// </param> /// <param name="deg"> /// polynomial degree /// </param> /// <param name="solver_name"> /// Name of solver to use. /// </param> public static SipControl TestVoronoi(int Res, SolverCodes solver_name = SolverCodes.classic_pardiso, int deg = 3) { if (System.Environment.MachineName.ToLowerInvariant().EndsWith("rennmaschin") //|| System.Environment.MachineName.ToLowerInvariant().Contains("jenkins") ) { // This is Florians Laptop; // he is to poor to afford MATLAB, so he uses OCTAVE BatchmodeConnector.Flav = BatchmodeConnector.Flavor.Octave; BatchmodeConnector.MatlabExecuteable = "C:\\cygwin64\\bin\\bash.exe"; } var R = new SipControl(); R.ProjectName = "SipPoisson-Voronoi"; R.SessionName = "testrun"; R.savetodb = false; R.FieldOptions.Add("T", new FieldOpts() { Degree = deg, SaveToDB = FieldOpts.SaveToDBOpt.TRUE }); R.FieldOptions.Add("Tex", new FieldOpts() { Degree = deg * 2 }); R.InitialValues_Evaluators.Add("RHS", X => 1.0); R.InitialValues_Evaluators.Add("Tex", X => 0.0); R.ExactSolution_provided = false; R.NoOfMultigridLevels = int.MaxValue; R.solver_name = solver_name; //R.TargetBlockSize = 100; bool IsIn(params double[] X) { Debug.Assert(X.Length == 2); double xi = X[0]; double yi = X[1]; //for(int l = 0; l < bndys.Length; l++) { // Debug.Assert(bndys[l].Normal.Length == 2); // if (bndys[l].PointDistance(xi, yi) > 0.0) // return false; //} if (xi > 1.0) { return(false); } if (yi > 1.0) { return(false); } if (xi < 0 && yi < 0) { return(false); } if (xi < -1) { return(false); } if (yi < -1) { return(false); } return(true); } int Mirror(ref double[] _x, ref double[] _y, AffineManifold[] bndys) { if (_x.Length != _y.Length) { throw new ArgumentException(); } var x = _x.ToList(); var y = _y.ToList(); int N = _x.Length; // filter all points that are outside of the domain for (int n = 0; n < N; n++) { if (!IsIn(x[n], y[n])) { x.RemoveAt(n); y.RemoveAt(n); N--; n--; } } Debug.Assert(x.Count == N); Debug.Assert(y.Count == N); for (int n = 0; n < N; n++) { Debug.Assert(IsIn(x[n], y[n])); } // mirror each point for (int n = 0; n < N; n++) { double xn = x[n]; double yn = y[n]; for (int l = 0; l < bndys.Length; l++) { var bndy_l = bndys[l]; double dist = bndy_l.PointDistance(xn, yn); if (dist < 0) { double xMirr = xn - bndy_l.Normal[0] * dist * 2; double yMirr = yn - bndy_l.Normal[1] * dist * 2; Debug.Assert(bndy_l.PointDistance(xMirr, yMirr) > 0); if (!IsIn(xMirr, yMirr)) { x.Add(xMirr); y.Add(yMirr); } } } } // return _x = x.ToArray(); _y = y.ToArray(); return(N); } GridCommons GridFunc() { GridCommons grd = null; var Matlab = new BatchmodeConnector(); // boundaries for L-domain AffineManifold[] Boundaries = new AffineManifold[6]; Boundaries[0] = new AffineManifold(new[] { 0.0, 1.0 }, new[] { 0.0, 1.0 }); Boundaries[1] = new AffineManifold(new[] { 1.0, 0.0 }, new[] { 1.0, 0.0 }); Boundaries[2] = new AffineManifold(new[] { -1.0, 0.0 }, new[] { -1.0, 0.0 }); Boundaries[3] = new AffineManifold(new[] { -1.0, 0.0 }, new[] { 0.0, 0.0 }); Boundaries[4] = new AffineManifold(new[] { 0.0, -1.0 }, new[] { 0.0, -1.0 }); Boundaries[5] = new AffineManifold(new[] { 0.0, -1.0 }, new[] { 0.0, 0.0 }); // generate Delaunay vertices Random rnd = new Random(0); double[] xNodes = Res.ForLoop(idx => rnd.NextDouble() * 2 - 1); double[] yNodes = Res.ForLoop(idx => rnd.NextDouble() * 2 - 1); int ResFix = Mirror(ref xNodes, ref yNodes, Boundaries); var Nodes = MultidimensionalArray.Create(xNodes.Length, 2); Nodes.SetColumn(0, xNodes); Nodes.SetColumn(1, yNodes); Matlab.PutMatrix(Nodes, "Nodes"); // compute Voronoi diagramm Matlab.Cmd("[V, C] = voronoin(Nodes);"); // output (export from matlab) int[][] OutputVertexIndex = new int[Nodes.NoOfRows][]; Matlab.GetStaggeredIntArray(OutputVertexIndex, "C"); Matlab.GetMatrix(null, "V"); // run matlab Matlab.Execute(false); // import here MultidimensionalArray VertexCoordinates = (MultidimensionalArray)(Matlab.OutputObjects["V"]); // correct indices (1-based index to 0-based index) foreach (int[] cell in OutputVertexIndex) { int K = cell.Length; for (int k = 0; k < K; k++) { cell[k]--; } } // tessellation List <Cell> cells = new List <Cell>(); List <int[]> aggregation = new List <int[]>(); for (int jV = 0; jV < ResFix; jV++) // loop over Voronoi Cells { Debug.Assert(IsIn(Nodes.GetRow(jV))); int[] iVtxS = OutputVertexIndex[jV]; int NV = iVtxS.Length; List <int> Agg2Pt = new List <int>(); for (int iTri = 0; iTri < NV - 2; iTri++) // loop over triangles of voronoi cell { int iV0 = iVtxS[0]; int iV1 = iVtxS[iTri + 1]; int iV2 = iVtxS[iTri + 2]; double[] V0 = VertexCoordinates.GetRow(iV0); double[] V1 = VertexCoordinates.GetRow(iV1); double[] V2 = VertexCoordinates.GetRow(iV2); double[] D1 = V1.Minus(V0); double[] D2 = V2.Minus(V0); Debug.Assert(D1.CrossProduct2D(D2).Abs() > 1.0e-8); if (D1.CrossProduct2D(D2) < 0) { double[] T = V2; int t = iV2; V2 = V1; iV2 = iV1; V1 = T; iV1 = t; } double[] Center = V0.Plus(V1).Plus(V2).Mul(1.0 / 3.0); //Debug.Assert(IsIn(Center[0], Center[1])); Cell Cj = new Cell(); Cj.GlobalID = cells.Count; Cj.Type = CellType.Triangle_3; Cj.TransformationParams = MultidimensionalArray.Create(3, 2); Cj.NodeIndices = new int[] { iV0, iV1, iV2 }; Cj.TransformationParams.SetRow(0, V0); Cj.TransformationParams.SetRow(1, V1); Cj.TransformationParams.SetRow(2, V2); Agg2Pt.Add(cells.Count); cells.Add(Cj); } aggregation.Add(Agg2Pt.ToArray()); } // return grid grd = new Grid2D(Triangle.Instance); grd.Cells = cells.ToArray(); grd.EdgeTagNames.Add(1, BoundaryType.Dirichlet.ToString()); grd.DefineEdgeTags(X => (byte)1); //grd.Plot2DGrid(); // create aggregation grid //var agrd = new AggregationGrid(grd, aggregation.ToArray()); return(grd); }; R.GridFunc = GridFunc; R.AddBoundaryValue(BoundaryType.Dirichlet.ToString(), "T", delegate(double[] X) { //double x = X[0], y = X[1]; return(0.0); //if(Math.Abs(X[0] - (0.0)) < 1.0e-8) // return 0.0; // //throw new ArgumentOutOfRangeException(); }); return(R); }
/// <summary> /// returns the condition number of the full matrix and the inner matrix without boundary terms /// </summary> /// <returns>Array condestOut=[ConditionNumberFullOp, ConditionNumberInnerOp]</returns> public double[] CondNum() { int[] DepVars = this.VarGroup; var grd = m_map.GridDat; int NoOfCells = grd.Grid.NumberOfCells; int NoOfBdryCells = grd.GetBoundaryCells().NoOfItemsLocally_WithExternal; // only for full matrix, if there are no inner cells if (NoOfCells == NoOfBdryCells) { Console.WriteLine(""); Console.WriteLine("Since there are only boundary cells, the condest of the non-existing inner matrix is set to zero!"); double[] Full_0Vars = this.m_map.GetSubvectorIndices(true, DepVars).Select(i => i + 1.0).ToArray(); MultidimensionalArray output = MultidimensionalArray.Create(1, 1); using (BatchmodeConnector bmc = new BatchmodeConnector()){ // if Octave should be used instead of Matlab.... //BatchmodeConnector.Flav = BatchmodeConnector.Flavor.Octave; bmc.PutSparseMatrix(m_OpMtx, "FullMatrix"); bmc.PutVector(Full_0Vars, "Full_0Vars"); bmc.Cmd("output = zeros(1,1)"); bmc.Cmd("output = condest(FullMatrix(Full_0Vars,Full_0Vars));"); bmc.GetMatrix(output, "output"); bmc.Execute(false); } double condestFull = output[0, 0]; double condestInner = 0; double[] condestOut = new double[] { condestFull, condestInner }; return(condestOut); } // for full and inner matrix else { CellMask InnerCellsMask = grd.GetBoundaryCells().Complement(); SubGrid InnerCells = new SubGrid(InnerCellsMask); double[] Full_0Vars = this.m_map.GetSubvectorIndices(true, DepVars).Select(i => i + 1.0).ToArray(); double[] Inner_0Vars = this.m_map.GetSubvectorIndices(InnerCells, true, DepVars).Select(i => i + 1.0).ToArray(); MultidimensionalArray output = MultidimensionalArray.Create(2, 1); string[] names = new string[] { "Full_0Vars", "Inner_0Vars" }; using (BatchmodeConnector bmc = new BatchmodeConnector()){ // if Octave should be used instead of Matlab.... // BatchmodeConnector.Flav = BatchmodeConnector.Flavor.Octave; bmc.PutSparseMatrix(m_OpMtx, "FullMatrix"); bmc.PutVector(Inner_0Vars, "Inner_0Vars"); bmc.PutVector(Full_0Vars, "Full_0Vars"); bmc.Cmd("output = zeros(2,1)"); int k = 1; foreach (var s in names) { bmc.Cmd("output({1}) = condest(FullMatrix({0},{0}));", s, k); k++; } bmc.GetMatrix(output, "output"); bmc.Execute(false); double condestFull = output[0, 0]; double condestInner = output[1, 0]; double[] condestOut = new double[] { condestFull, condestInner }; Debug.Assert(condestOut[0].MPIEquals(), "value does not match on procs"); Debug.Assert(condestOut[1].MPIEquals(), "value does not match on procs"); return(condestOut); } } }
public override void SolverDriver <S>(CoordinateVector SolutionVec, S RHS) { using (var tr = new FuncTrace()) { m_SolutionVec = SolutionVec; int itc; itc = 0; double[] x, xt, xOld, f0, deltaX, ft; double rat; double alpha = 1E-4, sigma0 = 0.1, sigma1 = 0.5, maxarm = 20, gamma = 0.9; // Eval_F0 using (new BlockTrace("Slv Init", tr)) { base.Init(SolutionVec, RHS, out x, out f0); }; Console.WriteLine("Residual base.init: " + f0.L2NormPow2().MPISum().Sqrt()); deltaX = new double[x.Length]; xt = new double[x.Length]; ft = new double[x.Length]; this.CurrentLin.TransformSolFrom(SolutionVec, x); base.EvalResidual(x, ref f0); // fnorm double fnorm = f0.L2NormPow2().MPISum().Sqrt(); double fNormo = 1; double errstep; double[] step = new double[x.Length]; double[] stepOld = new double[x.Length]; MsrMatrix CurrentJac; Console.WriteLine("Start residuum for nonlinear iteration: " + fnorm); OnIterationCallback(itc, x.CloneAs(), f0.CloneAs(), this.CurrentLin); //int[] Velocity_idx = SolutionVec.Mapping.GetSubvectorIndices(false, 0, 1, 2); //int[] Stresses_idx = SolutionVec.Mapping.GetSubvectorIndices(false, 3, 4, 5); //int[] Velocity_fields = new int[] { 0, 1, 2 }; //int[] Stress_fields = new int[] { 3, 4, 5 }; //int NoCoupledIterations = 1; using (new BlockTrace("Slv Iter", tr)) { while (fnorm > ConvCrit && itc < MaxIter) { rat = fnorm / fNormo; fNormo = fnorm; itc++; // How should the inverse of the Jacobian be approximated? if (ApproxJac == ApproxInvJacobianOptions.GMRES) { CurrentJac = new MsrMatrix(x.Length); if (Precond != null) { Precond.Init(CurrentLin); } step = Krylov(SolutionVec, x, f0, out errstep); } else if (ApproxJac == ApproxInvJacobianOptions.DirectSolver) { CurrentJac = diffjac(SolutionVec, x, f0); CurrentJac.SaveToTextFileSparse("Jacobi"); CurrentLin.OperatorMatrix.SaveToTextFileSparse("OpMatrix"); var solver = new ilPSP.LinSolvers.MUMPS.MUMPSSolver(); solver.DefineMatrix(CurrentJac); step.ClearEntries(); solver.Solve(step, f0); } else if (ApproxJac == ApproxInvJacobianOptions.DirectSolverHybrid) { //EXPERIMENTAL_____________________________________________________________________ MultidimensionalArray OpMatrixMatl = MultidimensionalArray.Create(x.Length, x.Length); CurrentJac = diffjac(SolutionVec, x, f0); //Console.WriteLine("Calling MATLAB/Octave..."); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(CurrentJac, "Jacobi"); bmc.PutSparseMatrix(CurrentLin.OperatorMatrix, "OpMatrix"); bmc.Cmd("Jacobi(abs(Jacobi) < 10^-6)=0; dim = length(OpMatrix);"); bmc.Cmd("dim = length(OpMatrix);"); bmc.Cmd(@"for i=1:dim if (i >= 16) && (i <= 33) && (i + 6 <= 33) && (i + 12 <= 33) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 49) && (i <= 66) && (i + 6 <= 66) && (i + 12 <= 66) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 82) && (i <= 99) && (i + 6 <= 99) && (i + 12 <= 99) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 115) && (i <= 132) && (i + 6 <= 132) && (i + 12 <= 132) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 148) && (i <= 165) && (i + 6 <= 165) && (i + 12 <= 165) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 181) && (i <= 198) && (i + 6 <= 198) && (i + 12 <= 198) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 214) && (i <= 231) && (i + 6 <= 231) && (i + 12 <= 231) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 247) && (i <= 264) && (i + 6 <= 264) && (i + 12 <= 264) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 280) && (i <= 297) && (i + 6 <= 297) && (i + 12 <= 297) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 313) && (i <= 330) && (i + 6 <= 330) && (i + 12 <= 330) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 346) && (i <= 363) && (i + 6 <= 363) && (i + 12 <= 363) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 379) && (i <= 396) && (i + 6 <= 396) && (i + 12 <= 396) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 412) && (i <= 429) && (i + 6 <= 429) && (i + 12 <= 429) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 445) && (i <= 462) && (i + 6 <= 462) && (i + 12 <= 462) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 478) && (i <= 495) && (i + 6 <= 495) && (i + 12 <= 495) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end if (i >= 511) && (i <= 528) && (i + 6 <= 528) && (i + 12 <= 528) OpMatrix(i, i) = Jacobi(i, i); OpMatrix(i, i + 6) = Jacobi(i, i + 6); OpMatrix(i + 6, i) = Jacobi(i + 6, i); OpMatrix(i + 12, i + 6) = Jacobi(i + 12, i + 6); OpMatrix(i + 6, i + 12) = Jacobi(i + 6, i + 12); end end"); bmc.Cmd("OpMatrix = full(OpMatrix)"); bmc.GetMatrix(OpMatrixMatl, "OpMatrix"); bmc.Execute(false); } MsrMatrix OpMatrix = OpMatrixMatl.ToMsrMatrix(); var solver = new ilPSP.LinSolvers.MUMPS.MUMPSSolver(); //Console.WriteLine("USING HIGH EXPERIMENTAL OPMATRIX WITH JAC! only for p=1, GridLevel=2"); solver.DefineMatrix(OpMatrix); //______________________________________________________________________________________________________ step.ClearEntries(); solver.Solve(step, f0); } else if (ApproxJac == ApproxInvJacobianOptions.DirectSolverOpMatrix) { CurrentJac = new MsrMatrix(x.Length); CurrentJac = CurrentLin.OperatorMatrix.ToMsrMatrix(); var solver = new ilPSP.LinSolvers.MUMPS.MUMPSSolver(); solver.DefineMatrix(CurrentJac); step.ClearEntries(); solver.Solve(step, f0); } else { throw new NotImplementedException("Your approximation option for the jacobian seems not to be existent."); } //if (itc > NoCoupledIterations) //{ // if (solveVelocity) // { // Console.WriteLine("stress correction = 0"); // foreach (int idx in Stresses_idx) // { // step[idx] = 0.0; // } // } // else // { // Console.WriteLine("velocity correction = 0"); // foreach (int idx in Velocity_idx) // { // step[idx] = 0.0; // } // } //} // Start line search xOld = x; double lambda = 1; double lamm = 1; double lamc = lambda; double iarm = 0; xt = x.CloneAs(); xt.AccV(lambda, step); this.CurrentLin.TransformSolFrom(SolutionVec, xt); EvaluateOperator(1, SolutionVec.Mapping.Fields, ft); var nft = ft.L2NormPow2().MPISum().Sqrt(); var nf0 = f0.L2NormPow2().MPISum().Sqrt(); var ff0 = nf0 * nf0; var ffc = nft * nft; var ffm = nft * nft; // Control of the the step size while (nft >= (1 - alpha * lambda) * nf0 && iarm < maxStep) { // Line search starts here if (iarm == 0) { lambda = sigma1 * lambda; } else { lambda = parab3p(lamc, lamm, ff0, ffc, ffm); } // Update x; xt = x.CloneAs(); xt.AccV(lambda, step); lamm = lamc; lamc = lambda; this.CurrentLin.TransformSolFrom(SolutionVec, xt); EvaluateOperator(1, SolutionVec.Mapping.Fields, ft); nft = ft.L2NormPow2().MPISum().Sqrt(); ffm = ffc; ffc = nft * nft; iarm++; #if DEBUG Console.WriteLine("Step size: " + lambda + "with Residuum: " + nft); #endif } // transform solution back to 'original domain' // to perform the linearization at the new point... // (and for Level-Set-Updates ...) this.CurrentLin.TransformSolFrom(SolutionVec, xt); // update linearization base.Update(SolutionVec.Mapping.Fields, ref xt); // residual evaluation & callback base.EvalResidual(xt, ref ft); // EvaluateOperator(1, SolutionVec.Mapping.Fields, ft); //base.Init(SolutionVec, RHS, out x, out f0); fnorm = ft.L2NormPow2().MPISum().Sqrt(); x = xt; f0 = ft.CloneAs(); //if (itc > NoCoupledIterations) //{ // double coupledL2Res = 0.0; // if (solveVelocity) // { // foreach (int idx in Velocity_idx) // { // coupledL2Res += f0[idx].Pow2(); // } // } // else // { // foreach (int idx in Stresses_idx) // { // coupledL2Res += f0[idx].Pow2(); // } // } // coupledL2Res = coupledL2Res.Sqrt(); // Console.WriteLine("coupled residual = {0}", coupledL2Res); // if (solveVelocity && coupledL2Res < this.VelocitySolver_ConvergenceCriterion) // { // Console.WriteLine("SolveVelocity = false"); // this.solveVelocity = false; // } // else if (!solveVelocity && coupledL2Res < this.StressSolver_ConvergenceCriterion) // { // Console.WriteLine("SolveVelocity = true"); // this.solveVelocity = true; // } //} OnIterationCallback(itc, x.CloneAs(), f0.CloneAs(), this.CurrentLin); } } SolutionVec = m_SolutionVec; } }
public void CreateWithMatlab() { // ================================ // generate voronoi graph in matlab // ================================ int J = this.DelaunayVertices.NoOfRows; int D = this.DelaunayVertices.NoOfCols; if (D != 2) { throw new NotSupportedException("todo"); } int[][] OutputVertexIndex = new int[J * 5][]; MultidimensionalArray VertexCoordinates; { var Matlab = new BatchmodeConnector(); Matlab.PutMatrix(this.DelaunayVertices, "X"); // create mirror points Matlab.Cmd("[J, D] = size(X);"); Matlab.Cmd("Xneg = [-X(:, 1), X(:, 2)];"); Matlab.Cmd("Yneg = [X(:, 1), -X(:, 2)];"); Matlab.Cmd("X2 = [ones(J, 1) * 2, zeros(J, 1)];"); Matlab.Cmd("Y2 = [zeros(J, 1), ones(J, 1) * 2];"); Matlab.Cmd("Xm = X;"); Matlab.Cmd("Xm = [Xm; Xneg]; % mirror at x = 0"); Matlab.Cmd("Xm = [Xm; X2 + Xneg]; % mirror at x = 1"); Matlab.Cmd("Xm = [Xm; Yneg]; % mirror at x = 0"); Matlab.Cmd("Xm = [Xm; Y2 + Yneg]; % mirror at x = 1"); // compute Voronoi diagramm Matlab.Cmd("[V, C] = voronoin(Xm);"); // output (export from matlab) Matlab.GetStaggeredIntArray(OutputVertexIndex, "C"); Matlab.GetMatrix(null, "V"); // run matlab Matlab.Execute(false); // import here VertexCoordinates = (MultidimensionalArray)(Matlab.OutputObjects["V"]); // correct indices (1-based index to 0-based index) foreach (int[] cell in OutputVertexIndex) { int K = cell.Length; for (int k = 0; k < K; k++) { cell[k]--; } } } // =============== // record internal // =============== { // define Cell data { this.m_CellData = new CellData(); this.m_CellData.m_Owner = this; this.m_VertexData = new VertexData(); this.m_LogEdges = new LogEdgeData(); this.m_VertexData.Coordinates = VertexCoordinates; this.m_CellData.CellVertices = OutputVertexIndex.GetSubVector(0, J); this.m_CellData.InfoFlags = new CellInfo[J]; ArrayTools.SetAll(this.m_CellData.InfoFlags, CellInfo.CellIsAffineLinear | CellInfo.IsAggregate); } // decomposition of Voronoi cells to triangles/tetrahedrons { m_CellData.AggregateCellToParts = new int[J][]; if (D == 2) { var Tri = RefElements.Triangle.Instance; m_CellData.RefElements = new RefElement[] { Tri }; int cnt = 0; for (int j = 0; j < J; j++) { int[] VtxIndices = m_CellData.CellVertices[j]; int[] PartIdx = new int[VtxIndices.Length - 2]; for (int i = 0; i < PartIdx.Length; i++) { PartIdx[i] = cnt; cnt++; } m_CellData.AggregateCellToParts[j] = PartIdx; } int NoOfParts = cnt; m_CellData.PartTransformation = MultidimensionalArray.Create(NoOfParts, D, D); m_CellData.PartCenter = MultidimensionalArray.Create(NoOfParts, D); MultidimensionalArray TriangleVtx = MultidimensionalArray.Create(3, D); for (int j = 0; j < J; j++) { int[] VtxIndices = m_CellData.CellVertices[j]; int[] PartIdx = m_CellData.AggregateCellToParts[j]; for (int i = 0; i < PartIdx.Length; i++) { int iV0 = VtxIndices[0]; int iV1 = VtxIndices[i + 1]; int iV2 = VtxIndices[i + 2]; TriangleVtx[0, 0] = m_VertexData.Coordinates[iV0, 0]; TriangleVtx[0, 1] = m_VertexData.Coordinates[iV0, 1]; TriangleVtx[1, 0] = m_VertexData.Coordinates[iV1, 0]; TriangleVtx[1, 1] = m_VertexData.Coordinates[iV1, 1]; TriangleVtx[2, 0] = m_VertexData.Coordinates[iV2, 0]; TriangleVtx[2, 1] = m_VertexData.Coordinates[iV2, 1]; var TR = AffineTrafo.FromPoints(Tri.Vertices, TriangleVtx); m_CellData.PartTransformation.ExtractSubArrayShallow(PartIdx[i], -1, -1).Set(TR.Matrix); m_CellData.PartCenter.ExtractSubArrayShallow(PartIdx[i], -1).SetVector(TR.Affine); } } } else if (D == 3) { throw new NotImplementedException("todo"); } else { throw new NotSupportedException("Unknown spatial dimension."); } } // bounding boxes, transformations { BoundingBox BB = new BoundingBox(D); m_CellData.BoundingBoxTransformation = MultidimensionalArray.Create(J, D, D); m_CellData.BoundingBoxCenter = MultidimensionalArray.Create(J, D); for (int j = 0; j < J; j++) { m_CellData.GetCellBoundingBox(j, BB); for (int d = 0; d < D; d++) { double lo = BB.Min[d]; double hi = BB.Max[d]; m_CellData.BoundingBoxCenter[j, d] = 0.5 * (lo + hi); m_CellData.BoundingBoxTransformation[j, d, d] = 0.5 * (hi - lo); } } } // mapping: vertex to cell { List <int>[] VertexToCell = new List <int> [VertexCoordinates.Length]; for (int j = 0; j < J; j++) { foreach (int iVtx in OutputVertexIndex[j]) { if (VertexToCell[iVtx] == null) { VertexToCell[iVtx] = new List <int>(); } if (!VertexToCell[iVtx].Contains(j)) { VertexToCell[iVtx].Add(j); } } } m_VertexData.VerticeToCell = new int[VertexToCell.Length][]; for (int i = 0; i < VertexToCell.Length; i++) { if (VertexToCell[i] == null) { m_VertexData.VerticeToCell[i] = new int[0]; } else { m_VertexData.VerticeToCell[i] = VertexToCell[i].ToArray(); } } VertexToCell = null; } // cell neighbors, edges { m_CellData.CellNeighbours = new int[J][]; var tmpCells2Edges = new List <int> [J]; Dictionary <int, int> ShareCount = new Dictionary <int, int>(); // key: cell index; value: number of vertices shared with this cell var EdgesTemp = new List <EdgeTemp>(); List <int> Neighs = new List <int>(); List <int> EdgeVtx = new List <int>(); List <int> IdedEdgsAtOneCell = new List <int>(); for (int jCell = 0; jCell < J; jCell++) // loop over cells { ShareCount.Clear(); Neighs.Clear(); IdedEdgsAtOneCell.Clear(); // determine how many vertices 'jCell' shares with other cells foreach (int iVtx in m_CellData.CellVertices[jCell]) { foreach (int jOtherCell in m_VertexData.VerticeToCell[iVtx]) { if (jOtherCell != jCell) { if (!ShareCount.ContainsKey(jOtherCell)) { ShareCount.Add(jOtherCell, 1); } else { ShareCount[jOtherCell]++; } } } } // find faces int[][] FaceIdx = ConvexHullFaces(m_VertexData.Coordinates, m_CellData.CellVertices[jCell]); // determine cell neighbors and edges int NoOfFacesFound = 0; foreach (var kv in ShareCount) { int jCellNeigh = kv.Key; int NoOfSharedVtx = kv.Value; if (NoOfSharedVtx >= D) { // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // cells 'jCell' and 'jCellNeigh' share more than 'D' vertices - this is an edge to another cell, // resp. a face of 'jCell'. // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Debug.Assert(jCellNeigh != jCell); Debug.Assert(!Neighs.Contains(jCellNeigh)); Neighs.Add(jCellNeigh); NoOfFacesFound++; EdgeVtx.Clear(); foreach (int iVtx in m_CellData.CellVertices[jCell]) { if (Array.IndexOf(m_VertexData.VerticeToCell[iVtx], jCellNeigh) >= 0) { EdgeVtx.Add(iVtx); } } if (jCell < jCellNeigh) { // the pairing 'jCell'/'jCellNeigh' will be discovered twice; // we only want to record once var Etmp = new EdgeTemp() { jCell1 = jCell, jCell2 = jCellNeigh, Vertices = EdgeVtx.ToArray() }; EdgesTemp.Add(Etmp); IdedEdgsAtOneCell.Add(EdgesTemp.Count - 1); if (tmpCells2Edges[jCell] == null) { tmpCells2Edges[jCell] = new List <int>(); } if (tmpCells2Edges[jCellNeigh] == null) { tmpCells2Edges[jCellNeigh] = new List <int>(); } tmpCells2Edges[jCell].Add(EdgesTemp.Count); // the funky convention for edges-to-cell: the index is tmpCells2Edges[jCellNeigh].Add(-EdgesTemp.Count); // shifted by 1, out-cell is negative } else { Debug.Assert(jCellNeigh < jCell); int MatchCount = 0; foreach (int i in tmpCells2Edges[jCellNeigh]) { int iEdge = Math.Abs(i) - 1; if (EdgesTemp[iEdge].jCell1 == jCellNeigh && EdgesTemp[iEdge].jCell2 == jCell) { MatchCount++; IdedEdgsAtOneCell.Add(iEdge); } } Debug.Assert(MatchCount == 1); } #if DEBUG if (D == 2) { Debug.Assert(EdgeVtx.Count == 2); } else if (D == 3) { // verify that all vertices of the edge are geometrically in one plane Debug.Assert(EdgeVtx.Count >= 3); var FacePlane = AffineManifold.FromPoints( m_VertexData.Coordinates.GetRowPt(EdgeVtx[0]), m_VertexData.Coordinates.GetRowPt(EdgeVtx[1]), m_VertexData.Coordinates.GetRowPt(EdgeVtx[2]) ); BoundingBox BB = new BoundingBox(D); m_CellData.GetCellBoundingBox(jCell, BB); double h = BB.Diameter; foreach (int iVtx in EdgeVtx) { double dist = Math.Abs(FacePlane.PointDistance(m_VertexData.Coordinates.GetRow(iVtx))); Debug.Assert(dist < h * 1e-8); } } else { throw new NotSupportedException("Unknown spatial dimension."); } #endif } } m_CellData.CellNeighbours[jCell] = Neighs.ToArray(); Debug.Assert(NoOfFacesFound <= FaceIdx.Length); Debug.Assert(NoOfFacesFound == IdedEdgsAtOneCell.Count); // boundary edges if (NoOfFacesFound == FaceIdx.Length) { // nothing to do - all faces/edges identified #if DEBUG for (int i = 0; i < NoOfFacesFound; i++) { int Matches = 0; for (int l = 0; l < NoOfFacesFound; l++) { if (FaceIdx[i].SetEquals(EdgesTemp[IdedEdgsAtOneCell[l]].Vertices)) { Matches++; } } Debug.Assert(Matches == 1); } #endif } else { // missing boundary for (int i = 0; i < FaceIdx.Length; i++) { int Matches = 0; for (int l = 0; l < NoOfFacesFound; l++) { if (FaceIdx[i].SetEquals(EdgesTemp[IdedEdgsAtOneCell[l]].Vertices)) { Matches++; } } Debug.Assert(Matches <= 1); if (Matches == 0) { // boundary edge found var Etmp = new EdgeTemp() { jCell1 = jCell, jCell2 = int.MinValue, Vertices = EdgeVtx.ToArray() }; EdgesTemp.Add(Etmp); tmpCells2Edges[jCell].Add(EdgesTemp.Count); // index shifted by 1 } } } } // convert temporary data structures to the final ones m_CellData.Cells2Edges = new int[J][]; var C2E = m_CellData.Cells2Edges; for (int j = 0; j < J; j++) { C2E[j] = tmpCells2Edges[j] != null ? tmpCells2Edges[j].ToArray() : new int[0]; } m_GeomEdges = new GeomEdgeData(); int NoOfEdges = EdgesTemp.Count; m_GeomEdges.Info = new EdgeInfo[NoOfEdges]; m_LogEdges.CellIndices = new int[NoOfEdges, 2]; m_GeomEdges.VertexIndices = new int[NoOfEdges][]; var Evtx = m_GeomEdges.VertexIndices; var E2C = m_LogEdges.CellIndices; var Einf = m_GeomEdges.Info; for (int iEdge = 0; iEdge < NoOfEdges; iEdge++) { var Etmp = EdgesTemp[iEdge]; E2C[iEdge, 0] = Etmp.jCell1; E2C[iEdge, 1] = Etmp.jCell2; Einf[iEdge] = EdgeInfo.EdgeIsAffineLinear | EdgeInfo.IsAggregate; if (Etmp.jCell2 < 0) { Einf[iEdge] |= EdgeInfo.Boundary; } Evtx[iEdge] = Etmp.Vertices; } } // edge metrics { if (D == 2) { m_GeomEdges.EdgeRefElements = new RefElement[] { Line.Instance }; } else if (D == 3) { m_GeomEdges.EdgeRefElements = new RefElement[] { Triangle.Instance }; } else { throw new NotSupportedException("Unknown spatial dimension."); } int[][] Evtx = m_GeomEdges.VertexIndices; int NoOfParts = 0; int NoOfEdges = m_GeomEdges.Count; for (int iEdge = 0; iEdge < NoOfEdges; iEdge++) { NoOfParts += Evtx[iEdge].Length - D + 1; } Debug.Assert(D != 2 || NoOfParts == NoOfEdges); m_GeomEdges.Edge2CellTrafoIndex = new int[NoOfParts, 2]; var tmpEdg2CellTrafo = new Dictionary <int, Tuple <int, AffineTrafo> >(); // unsolved problem: // (D-1) -- dimensional tesselation of edge is given by D -- dimensional tesselation of adjacent cells // * case D == 2: trivial // * case D == 3: the problem is that two adjacent cells will induce _two different_ tesselations, which // wont match in the general case. MultidimensionalArray PreImage = m_GeomEdges.EdgeRefElements[0].Vertices; MultidimensionalArray Image = MultidimensionalArray.Create(PreImage.NoOfRows, D); //for(int iEdge ) } } }
public static void FastSubMatrixExtraction( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(MatrixShape.laplace)] MatrixShape MShape, [Values(4)] int Res ) { Utils.TestInit((int)UseXdg, DGOrder, (int)MShape); Console.WriteLine("FastSubMatrixExtraction({0},{1},{2})", UseXdg, DGOrder, MShape); //Arrange --- MultigridOperator mgo = Utils.CreateTestMGOperator(UseXdg, DGOrder, MShape, Res); MultigridMapping map = mgo.Mapping; BlockMsrMatrix M = mgo.OperatorMatrix; var sbs = new SubBlockSelector(map); int[] extcells = sbs.AllExternalCellsSelection(); var M_ext = BlockMask.GetAllExternalRows(map, M); var mask = new BlockMask(sbs, M_ext); //Arrange --- get index list of all external cells int[] idc = Utils.GetAllExtCellIdc(map); double[] GlobIdx = idc.Count().ForLoop(i => (double)idc[i] + 1.0); //Arrange --- stopwatch var stw = new Stopwatch(); stw.Reset(); //Act --- Extract SubMatrix stw.Start(); BlockMsrMatrix subM = mask.GetSubBlockMatrix(M); stw.Stop(); //Arrange --- Extract Blocks in Matlab and substract var infNorm = MultidimensionalArray.Create(4, 1); int rank = map.MpiRank; using (BatchmodeConnector matlab = new BatchmodeConnector()) { matlab.PutSparseMatrix(M, "M"); // note: M_sub lives on Comm_Self, therefore we have to distinguish between procs ... matlab.PutSparseMatrixRankExclusive(subM, "M_sub"); matlab.PutVectorRankExclusive(GlobIdx, "Idx"); matlab.Cmd("M_0 = M(Idx_0, Idx_0);"); matlab.Cmd("M_1 = M(Idx_1, Idx_1);"); matlab.Cmd("M_2 = M(Idx_2, Idx_2);"); matlab.Cmd("M_3 = M(Idx_3, Idx_3);"); matlab.Cmd("n=[0; 0; 0; 0];"); matlab.Cmd("n(1,1)=norm(M_0-M_sub_0,inf);"); matlab.Cmd("n(2,1)=norm(M_1-M_sub_1,inf);"); matlab.Cmd("n(3,1)=norm(M_2-M_sub_2,inf);"); matlab.Cmd("n(4,1)=norm(M_3-M_sub_3,inf);"); matlab.GetMatrix(infNorm, "n"); matlab.Execute(); } //Assert --- mask blocks and extracted blocks are the same Assert.IsTrue(infNorm[rank, 0] == 0.0); }
public void Init(MultigridOperator op) { int D = op.Mapping.GridData.SpatialDimension; var M = op.OperatorMatrix; var MgMap = op.Mapping; this.m_mgop = op; if (!M.RowPartitioning.EqualsPartition(MgMap.Partitioning)) { throw new ArgumentException("Row partitioning mismatch."); } if (!M.ColPartition.EqualsPartition(MgMap.Partitioning)) { throw new ArgumentException("Column partitioning mismatch."); } Uidx = MgMap.ProblemMapping.GetSubvectorIndices(true, D.ForLoop(i => i)); Pidx = MgMap.ProblemMapping.GetSubvectorIndices(true, D); int Upart = Uidx.Length; int Ppart = Pidx.Length; ConvDiff = new MsrMatrix(Upart, Upart, 1, 1); pGrad = new MsrMatrix(Upart, Ppart, 1, 1); divVel = new MsrMatrix(Ppart, Upart, 1, 1); var PxP = new MsrMatrix(Ppart, Ppart, 1, 1); M.AccSubMatrixTo(1.0, ConvDiff, Uidx, default(int[]), Uidx, default(int[])); M.AccSubMatrixTo(1.0, pGrad, Uidx, default(int[]), Pidx, default(int[])); M.AccSubMatrixTo(1.0, divVel, Pidx, default(int[]), Uidx, default(int[])); M.AccSubMatrixTo(1.0, PxP, Pidx, default(int[]), Pidx, default(int[])); Mtx = M; int L = M.RowPartitioning.LocalLength; int i0 = Mtx.RowPartitioning.i0; P = new MsrMatrix(Mtx); P.Clear(); // Debugging output //ConvDiff.SaveToTextFileSparse("ConvDiff"); //divVel.SaveToTextFileSparse("divVel"); //pGrad.SaveToTextFileSparse("pGrad"); //PxP.SaveToTextFileSparse("PxP"); velMassMatrix = new MsrMatrix(Upart, Upart, 1, 1); op.MassMatrix.AccSubMatrixTo(1.0, velMassMatrix, Uidx, default(int[]), Uidx, default(int[])); switch (SchurOpt) { case SchurOptions.exact: { // Building complete Schur and Approximate Schur MultidimensionalArray Poisson = MultidimensionalArray.Create(Pidx.Length, Pidx.Length); MultidimensionalArray SchurConvPart = MultidimensionalArray.Create(Pidx.Length, Pidx.Length); MultidimensionalArray Schur = MultidimensionalArray.Create(Pidx.Length, Pidx.Length); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(ConvDiff, "ConvDiff"); bmc.PutSparseMatrix(velMassMatrix, "MassMatrix"); bmc.PutSparseMatrix(divVel, "divVel"); bmc.PutSparseMatrix(pGrad, "pGrad"); bmc.Cmd("Qdiag = diag(diag(MassMatrix))"); bmc.Cmd("invT= inv(Qdiag)"); bmc.Cmd("Poisson = full(invT)*pGrad"); bmc.Cmd("ConvPart = ConvDiff*Poisson"); bmc.Cmd("ConvPart= full(invT)*ConvPart"); bmc.Cmd("ConvPart= divVel*ConvPart"); bmc.Cmd("Poisson = divVel*Poisson"); bmc.Cmd("ConvDiffInv = inv(full(ConvDiff))"); bmc.Cmd("Schur = divVel*ConvDiffInv"); bmc.Cmd("Schur = Schur*pGrad"); bmc.GetMatrix(Poisson, "Poisson"); bmc.GetMatrix(SchurConvPart, "ConvPart"); bmc.GetMatrix(Schur, "-Schur"); bmc.Execute(false); } PoissonMtx_T = Poisson.ToMsrMatrix(); PoissonMtx_H = Poisson.ToMsrMatrix(); SchurConvMtx = SchurConvPart.ToMsrMatrix(); SchurMtx = Schur.ToMsrMatrix(); SchurMtx.Acc(PxP, 1); ConvDiff.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Uidx); pGrad.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Pidx); SchurMtx.AccSubMatrixTo(1.0, P, default(int[]), Pidx, default(int[]), Pidx); return; } case SchurOptions.decoupledApprox: { // Do assembly for approximate Schur inverse invVelMassMatrix = velMassMatrix.CloneAs(); invVelMassMatrix.Clear(); invVelMassMatrixSqrt = invVelMassMatrix.CloneAs(); for (int i = velMassMatrix.RowPartitioning.i0; i < velMassMatrix.RowPartitioning.iE; i++) { if (ApproxScaling) { invVelMassMatrix.SetDiagonalElement(i, 1 / (velMassMatrix[i, i])); invVelMassMatrixSqrt.SetDiagonalElement(i, 1 / (Math.Sqrt(velMassMatrix[i, i]))); } else { invVelMassMatrix.SetDiagonalElement(i, 1); invVelMassMatrixSqrt.SetDiagonalElement(i, 1); } } //invVelMassMatrix.SaveToTextFileSparse("invVelMassMatrix"); //velMassMatrix.SaveToTextFileSparse("velMassMatrix"); //ConvDiffPoissonMtx = MsrMatrix.Multiply(ConvDiff, pGrad); //ConvDiffPoissonMtx = MsrMatrix.Multiply(divVel, ConvDiffPoissonMtx); // Inverse of mass matrix in Matlab //MultidimensionalArray temp = MultidimensionalArray.Create(Uidx.Length, Uidx.Length); //using (BatchmodeConnector bmc = new BatchmodeConnector()) //{ // bmc.PutSparseMatrix(velMassMatrix, "velMassMatrix"); // bmc.Cmd("invVelMassMatrix = inv(full(velMassMatrix))"); // bmc.GetMatrix(temp, "invVelMassMatrix"); // bmc.Execute(false); //} //invVelMassMatrix = temp.ToMsrMatrix(); //ConvDiffPoissonMtx = MsrMatrix.Multiply(ConvDiffPoissonMtx, PoissonMtx); //ConvDiffPoissonMtx = MsrMatrix.Multiply(PoissonMtx, ConvDiffPoissonMtx); //ConvDiff.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Uidx); //pGrad.AccSubMatrixTo(1.0, P, default(int[]), Uidx, default(int[]), Pidx); //ConvDiffPoissonMtx.AccSubMatrixTo(1.0, P, default(int[]), Pidx, default(int[]), Pidx); //op.MassMatrix.SaveToTextFileSparse("MassMatrix"); //velMassMatrix.SaveToTextFileSparse("velMassMatrix2"); // Possion scaled by inverse of the velocity mass matrix PoissonMtx_T = MsrMatrix.Multiply(invVelMassMatrix, pGrad); PoissonMtx_T = MsrMatrix.Multiply(divVel, PoissonMtx_T); ////PoissonMtx_T.Acc(PxP, 1); // p.379 // Poisson scaled by sqrt of inverse of velocity mass matrix PoissonMtx_H = MsrMatrix.Multiply(invVelMassMatrixSqrt, pGrad); PoissonMtx_H = MsrMatrix.Multiply(divVel, PoissonMtx_H); //PoissonMtx_H.Acc(PxP, 1); // p.379 return; } case SchurOptions.SIMPLE: { var invdiag_ConvDiff = ConvDiff.CloneAs(); invdiag_ConvDiff.Clear(); for (int i = ConvDiff.RowPartitioning.i0; i < ConvDiff.RowPartitioning.iE; i++) { invdiag_ConvDiff[i, i] = 1 / ConvDiff[i, i]; } simpleSchur = MsrMatrix.Multiply(invdiag_ConvDiff, pGrad); simpleSchur = MsrMatrix.Multiply(divVel, simpleSchur); return; } default: throw new NotImplementedException("SchurOption"); } //var ConvDiffInvMtx = ConvDiffInv.ToMsrMatrix(); //// x= inv(P)*b !!!!! To be done with approximate Inverse // P.SpMV(1, B, 0, X); }
public static void SubBlockExtraction( [Values(XDGusage.none, XDGusage.all)] XDGusage UseXdg, [Values(2)] int DGOrder, [Values(MatrixShape.diagonal_var_spec, MatrixShape.diagonal_spec, MatrixShape.diagonal_var, MatrixShape.diagonal)] MatrixShape MShape, [Values(4)] int Res ) { Utils.TestInit((int)UseXdg, DGOrder, (int)MShape); Console.WriteLine("SubMatrixIgnoreCoupling({0},{1},{2})", UseXdg, DGOrder, MShape); //Arrange --- create test matrix and MG mapping MultigridOperator mgo = Utils.CreateTestMGOperator(UseXdg, DGOrder, MShape, Res); MultigridMapping map = mgo.Mapping; BlockMsrMatrix M = mgo.OperatorMatrix; //Arrange --- masking of all external cells var sbs = new SubBlockSelector(map); sbs.AllExternalCellsSelection(); var M_ext = BlockMask.GetAllExternalRows(map, M); var mask = new BlockMask(sbs, M_ext); //bool[] coup = Utils.SetCoupling(MShape); //Arrange --- get index dictonary of all external cell indices Dictionary <int, int[]> Didc = Utils.GetDictOfAllExtCellIdc(map); //Arrange --- stopwatch var stw = new Stopwatch(); stw.Reset(); //Act --- Extract subblocks stw.Start(); //var eblocks = mask.GetSubBlocks(M,coup[0],coup[1],coup[2]); var eblocks = mask.GetDiagonalBlocks(M, false, false); stw.Stop(); //Assert --- same number of blocks? Assert.IsTrue(eblocks.Length == M_ext._RowPartitioning.LocalNoOfBlocks); bool test = eblocks.Length.MPIEquals(); Debug.Assert(test); for (int iBlock = 0; iBlock < eblocks.Length; iBlock++) { var infNorm = MultidimensionalArray.Create(4, 1); int rank = map.MpiRank; int ExtBlockIdx = iBlock + map.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; Didc.TryGetValue(ExtBlockIdx, out int[] idc); using (BatchmodeConnector matlab = new BatchmodeConnector()) { double[] GlobIdx = idc.Count().ForLoop(i => (double)idc[i] + 1.0); Assert.IsTrue(GlobIdx.Length == eblocks[iBlock].Lengths[0]); MsrMatrix M_sub = eblocks[iBlock].ConvertToMsr(); matlab.PutSparseMatrix(M, "M"); // note: M_sub lives on Comm_Self, therefore we have to distinguish between procs ... matlab.PutSparseMatrixRankExclusive(M_sub, "M_sub"); matlab.PutVectorRankExclusive(GlobIdx, "Idx"); matlab.Cmd("M_0 = full(M(Idx_0, Idx_0));"); matlab.Cmd("M_1 = full(M(Idx_1, Idx_1));"); matlab.Cmd("M_2 = full(M(Idx_2, Idx_2));"); matlab.Cmd("M_3 = full(M(Idx_3, Idx_3));"); matlab.Cmd("n=[0; 0; 0; 0];"); matlab.Cmd("n(1,1)=norm(M_0-M_sub_0,inf);"); matlab.Cmd("n(2,1)=norm(M_1-M_sub_1,inf);"); matlab.Cmd("n(3,1)=norm(M_2-M_sub_2,inf);"); matlab.Cmd("n(4,1)=norm(M_3-M_sub_3,inf);"); matlab.GetMatrix(infNorm, "n"); matlab.Execute(); } Assert.IsTrue(infNorm[rank, 0] == 0.0); // } }