// // /// <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); } }