/// <summary> /// /// </summary> /// <returns></returns> protected override MsrMatrix ComputeMatrix() { MsrMatrix CorrectorMatrix = new MsrMatrix(m_VelocityDivergence[0].LocalLength); for (int comp = 0; comp < m_VelocityDivergence.Length; comp++) { MsrMatrix prod1 = MsrMatrix.Multiply(m_PredictorApproxInv[comp].AssemblyMatrix, m_PressureGradient[comp].OperatorMatrix); MsrMatrix prod2 = MsrMatrix.Multiply(m_VelocityDivergence[comp].OperatorMatrix, prod1); CorrectorMatrix.Acc(1.0, prod2); } //CorrectorMatrix.AssumeSymmetric = false; return(CorrectorMatrix); }
/// <summary> /// /// </summary> /// <returns></returns> protected override MsrMatrix ComputeMatrix() { MsrMatrix CorrectorMatrix = new MsrMatrix(m_DivergenceConti[0].LocalLength); for (int comp = 0; comp < m_DivergenceConti.Length; comp++) { MsrMatrix prod1 = MsrMatrix.Multiply(m_PredictorApproxInv.AssemblyMatrix, m_PressureGradient[comp].OperatorMatrix); MsrMatrix prod2 = MsrMatrix.Multiply(m_DivergenceConti[comp].OperatorMatrix, prod1); CorrectorMatrix.Acc(1.0, prod2); } if (m_PressureStabilization != null) { CorrectorMatrix.Acc(-1.0, m_PressureStabilization.OperatorMatrix); } //CorrectorMatrix.AssumeSymmetric = true; return(CorrectorMatrix); }
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); }
/// <summary> /// Computes a potential solution (i.e. neglects convective/diffusive part) to the current residual /// </summary> /// <param name="X">input/output: solution guess</param> /// <param name="RHS">RHS of the saddle point problem</param> public void Solve <U, V>(U X, V RHS) where U : IList <double> where V : IList <double> // { double[] RESI = RHS.ToArray(); this.m_MgOp.OperatorMatrix.SpMV(-1.0, X, 1.0, RESI); var MM = this.m_MgOp.MassMatrix.CloneAs(); MM.AccEyeSp(-1.0); double nrm = MM.InfNorm(); double[] R1 = new double[USubMatrixIdx_Row.Length]; double[] R2 = new double[PSubMatrixIdx_Row.Length]; RESI.GetSubVector(R1, USubMatrixIdx_Row, default(int[])); RESI.GetSubVector(R2, PSubMatrixIdx_Row, default(int[])); double gamma; if (double.IsInfinity(this.m_SIMPLEOptions.dt)) { gamma = 1.0; } else { gamma = (1.0 + this.m_SIMPLEOptions.dt) / this.m_SIMPLEOptions.dt; } // RHS of Poisson equation double[] Poisson_RHS; { Poisson_RHS = R2; if (this.invMM != null) { double[] tmp = new double[R1.Length]; this.invMM.SpMVpara(1.0, R1, 0.0, tmp); this.VelocityDiv.SpMVpara(1.0, tmp, -gamma, Poisson_RHS); } else { this.VelocityDiv.SpMVpara(1.0, R1, -gamma, Poisson_RHS); } } // LHS of Poisson equation if (m_PressureSolver == null) { m_PressureSolver = m_SIMPLEOptions.PressureSolver; if (m_PressureSolver is PARDISOSolver) { ((PARDISOSolver)m_PressureSolver).CacheFactorization = true; } MsrMatrix MXCorrector; if (invMM != null) { MXCorrector = MsrMatrix.Multiply(this.VelocityDiv, MsrMatrix.Multiply(this.invMM, this.PressureGrad)); } else { MXCorrector = MsrMatrix.Multiply(this.VelocityDiv, this.PressureGrad); } MXCorrector.Acc(-1.0, Stab); m_PressureSolver.DefineMatrix(MXCorrector); } // solve Poisson equation double[] PressureCorr = new double[R2.Length]; m_PressureSolver.Solve(PressureCorr, Poisson_RHS); //// compute velocity correction //double[] VelocityCorr = R1; //this.PressureGrad.SpMV(-1.0 / gamma, PressureCorr, 1.0, VelocityCorr); // apply corrections & return //X.AccV(1.0, VelocityCorr, USubMatrixIdx_Row, default(int[])); // the velocity correction is crap; better not to add it. X.AccV(1.0, PressureCorr, PSubMatrixIdx_Row, default(int[])); NoOfIterations++; }
public void Init(MultigridOperator op) { int D = op.GridData.SpatialDimension; CodName = (new string[] { "mom0", "mom1" }); Params = ArrayTools.Cat( VariableNames.Velocity0Vector(D)); DomName = ArrayTools.Cat(VariableNames.VelocityVector(D)); LocalOp = new SpatialOperator(DomName, Params, CodName, (A, B, C) => 4); for (int d = 0; d < D; d++) { LocalOp.EquationComponents["mom" + d].Add(new LocalDiffusiveFlux() { m_component = d, dt = m_dt, muA = m_muA }); } LocalOp.Commit(); //LocalMatrix = op.MassMatrix.CloneAs().ToMsrMatrix(); //LocalMatrix.Clear(); //var U0 = new VectorField<SinglePhaseField>(op.BaseGridProblemMapping Take(D).Select(F => (SinglePhaseField)F).ToArray()); UnsetteledCoordinateMapping test = new UnsetteledCoordinateMapping(op.BaseGridProblemMapping.BasisS.GetSubVector(0, D)); var U0 = ((BoSSS.Foundation.CoordinateMapping)op.Mapping.ProblemMapping).Fields.GetSubVector(0, 2); var empty = new SinglePhaseField[D]; LocalMatrix = LocalOp.ComputeMatrix(test, empty, test, time: m_dt); Uidx = op.Mapping.ProblemMapping.GetSubvectorIndices(true, D.ForLoop(i => i)); Pidx = op.Mapping.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 VelocityMass = new MsrMatrix(Upart, Upart, 1, 1); var leftChangeBasesVel = new MsrMatrix(Upart, Upart, 1, 1); var rightChangeBasesVel = new MsrMatrix(Upart, Upart, 1, 1); op.MassMatrix.AccSubMatrixTo(1.0, VelocityMass, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); op.LeftChangeOfBasis.AccSubMatrixTo(1.0, leftChangeBasesVel, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); op.RightChangeOfBasis.AccSubMatrixTo(1.0, rightChangeBasesVel, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); var temp = MsrMatrix.Multiply(leftChangeBasesVel, LocalMatrix); LocalMatrix = MsrMatrix.Multiply(temp, rightChangeBasesVel); var M = op.OperatorMatrix; M.AccSubMatrixTo(1.0, ConvDiff, Uidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); M.AccSubMatrixTo(1.0, pGrad, Uidx, default(int[]), Pidx, default(int[]), default(int[]), default(int[])); M.AccSubMatrixTo(1.0, divVel, Pidx, default(int[]), Uidx, default(int[]), default(int[]), default(int[])); LocalMatrix.SaveToTextFileSparse("LocalConvDiffMatrix"); ConvDiff.SaveToTextFileSparse("ConvDiff"); op.MassMatrix.SaveToTextFileSparse("MassMatrix"); VelocityMass.SaveToTextFileSparse("VelocityMass"); }