/// <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);
        }
Beispiel #3
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);
        }
        /// <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");
        }