Exemple #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="SolutionVec">Current Point</param>
        /// <param name="f0">Function at current point</param>
        /// <param name="xinit">initial iterate</param>
        /// <param name="errstep">error of step</param>
        /// <returns></returns>
        double[] GMRES(CoordinateVector SolutionVec, double[] currentX, double[] f0, double[] xinit, out double errstep)
        {
            using (var tr = new FuncTrace()) {
                int n = f0.Length;

                int reorth = 1; // Orthogonalization method -> 1: Brown/Hindmarsh condition, 3: Always reorthogonalize

                // RHS of the linear equation system
                double[] b = new double[n];
                b.AccV(1, f0);

                double[] x = new double[n];
                double[] r = new double[n];

                int Nloc = base.CurrentLin.OperatorMatrix.RowPartitioning.LocalLength;
                int Ntot = base.CurrentLin.OperatorMatrix.RowPartitioning.TotalLength;

                r = b;

                //Initial solution
                if (xinit.L2Norm() != 0)
                {
                    x = xinit.CloneAs();
                    r.AccV(-1, dirder(SolutionVec, currentX, x, f0));
                }
                // Precond = null;
                if (Precond != null)
                {
                    var temp2 = r.CloneAs();
                    r.ClearEntries();
                    //this.OpMtxRaw.InvertBlocks(OnlyDiagonal: false, Subblocks: false).SpMV(1, temp2, 0, r);
                    Precond.Solve(r, temp2);
                }

                int                   m = maxKrylovDim;
                double[][]            V = (m + 1).ForLoop(i => new double[Nloc]);     //   V(1:n,1:m+1) = zeros(n,m);
                MultidimensionalArray H = MultidimensionalArray.Create(m + 1, m + 1); //   H(1:m,1:m) = zeros(m,m);
                double[]              c = new double[m + 1];
                double[]              s = new double[m + 1];
                double[]              y;
                double                rho = r.L2NormPow2().MPISum().Sqrt();
                errstep = rho;
                double[] g = new double[m + 1];
                g[0] = rho;

                Console.WriteLine("Error NewtonGMRES:   " + rho);

                // Termination of entry
                if (rho < GMRESConvCrit)
                {
                    return(SolutionVec.ToArray());
                }

                V[0].SetV(r, alpha: (1.0 / rho));
                double beta = rho;
                int    k    = 1;

                while ((rho > GMRESConvCrit) && k <= m)
                {
                    V[k].SetV(dirder(SolutionVec, currentX, V[k - 1], f0));
                    //CurrentLin.OperatorMatrix.SpMV(1.0, V[k-1], 0.0, temp3);
                    // Call directional derivative
                    //V[k].SetV(f0);

                    if (Precond != null)
                    {
                        var temp3 = V[k].CloneAs();
                        V[k].ClearEntries();
                        //this.OpMtxRaw.InvertBlocks(false,false).SpMV(1, temp3, 0, V[k]);
                        Precond.Solve(V[k], temp3);
                    }

                    double normav = V[k].L2NormPow2().MPISum().Sqrt();

                    // Modified Gram-Schmidt
                    for (int j = 1; j <= k; j++)
                    {
                        H[j - 1, k - 1] = GenericBlas.InnerProd(V[k], V[j - 1]).MPISum();
                        V[k].AccV(-H[j - 1, k - 1], V[j - 1]);
                    }
                    H[k, k - 1] = V[k].L2NormPow2().MPISum().Sqrt();
                    double normav2 = H[k, k - 1];


                    // Reorthogonalize ?
                    if ((reorth == 1 && Math.Round(normav + 0.001 * normav2, 3) == Math.Round(normav, 3)) || reorth == 3)
                    {
                        for (int j = 1; j <= k; j++)
                        {
                            double hr = GenericBlas.InnerProd(V[k], V[j - 1]).MPISum();
                            H[j - 1, k - 1] = H[j - 1, k - 1] + hr;
                            V[k].AccV(-hr, V[j - 1]);
                        }
                        H[k, k - 1] = V[k].L2NormPow2().MPISum().Sqrt();
                    }

                    // Watch out for happy breakdown
                    if (H[k, k - 1] != 0)
                    {
                        V[k].ScaleV(1 / H[k, k - 1]);
                    }



                    // Form and store the information for the new Givens rotation
                    //if (k > 1) {
                    //    // for (int i = 1; i <= k; i++) {
                    //    H.SetColumn(k - 1, givapp(c.GetSubVector(0, k - 1), s.GetSubVector(0, k - 1), H.GetColumn(k - 1), k - 1));
                    //    //}
                    //}

                    // Givens rotation from SoftGMRES
                    double temp;
                    for (int l = 1; l <= k - 1; l++)
                    {
                        // apply Givens rotation, H is Hessenbergmatrix
                        temp = c[l - 1] * H[l - 1, k - 1] + s[l - 1] * H[l + 1 - 1, k - 1];
                        H[l + 1 - 1, k - 1] = -s[l - 1] * H[l - 1, k - 1] + c[l - 1] * H[l + 1 - 1, k - 1];
                        H[l - 1, k - 1]     = temp;
                    }
                    //	 [cs(i),sn(i)] = rotmat( H(i,i), H(i+1,i) ); % form i-th rotation matrix
                    rotmat(out c[k - 1], out s[k - 1], H[k - 1, k - 1], H[k + 1 - 1, k - 1]);
                    temp                = c[k - 1] * g[k - 1]; //                       % approximate residual norm
                    H[k - 1, k - 1]     = c[k - 1] * H[k - 1, k - 1] + s[k - 1] * H[k + 1 - 1, k - 1];
                    H[k + 1 - 1, k - 1] = 0.0;


                    // Don't divide by zero if solution has  been found
                    var nu = (H[k - 1, k - 1].Pow2() + H[k, k - 1].Pow2()).Sqrt();
                    if (nu != 0)
                    {
                        //c[k - 1] = H[k - 1, k - 1] / nu;
                        //s[k - 1] = H[k, k - 1] / nu;
                        //H[k - 1, k - 1] = c[k - 1] * H[k - 1, k - 1] - s[k - 1] * H[k, k - 1];
                        //H[k, k - 1] = 0;

                        // givapp for g
                        g[k + 1 - 1] = -s[k - 1] * g[k - 1];
                        g[k - 1]     = temp;

                        //var w1 = c[k - 1] * g[k - 1] - s[k - 1] * g[k];
                        //var w2 = s[k - 1] * g[k - 1] + c[k - 1] * g[k];
                        //g[k - 1] = w1;
                        //g[k] = w2;
                    }

                    rho = Math.Abs(g[k]);

                    Console.WriteLine("Error NewtonGMRES:   " + rho);

                    k++;
                }

                Console.WriteLine("GMRES completed after:   " + k + "steps");

                k--;



                // update approximation and exit
                //y = H(1:i,1:i) \ g(1:i);
                y = new double[k];
                H.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { k - 1, k - 1 })
                .Solve(y, g.GetSubVector(0, k));

                int totalIter = k;

                // x = x + V(:,1:i)*y;
                for (int ii = 0; ii < k; ii++)
                {
                    x.AccV(y[ii], V[ii]);
                }

                // update approximation and exit
                //using (StreamWriter writer = new StreamWriter(m_SessionPath + "//GMRES_Stats.txt", true)) {
                //    writer.WriteLine("");
                //}

                errstep = rho;

                return(x);
            }
        }
Exemple #2
0
        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
                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);

                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);
                        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.");
                    }

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

                    OnIterationCallback(itc, x.CloneAs(), f0.CloneAs(), this.CurrentLin);
                }

                SolutionVec = m_SolutionVec;
            }
        }
Exemple #3
0
        //bool solveVelocity = true;

        //double VelocitySolver_ConvergenceCriterion = 1e-5;

        //double StressSolver_ConvergenceCriterion = 1e-5;

        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;
                //double sigma0 = 0.1;
                double sigma1 = 0.5;
                //double maxarm = 20;
                //double 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);
                EvaluateOperator(1, SolutionVec.Mapping.ToArray(), f0);

                Console.WriteLine("Residual base.init:   " + f0.L2NormPow2().MPISum().Sqrt());
                //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];
                //BlockMsrMatrix CurrentJac;

                OnIterationCallback(itc, x.CloneAs(), f0.CloneAs(), this.CurrentLin);

                using (new BlockTrace("Slv Iter", tr)) {
                    while ((fnorm > ConvCrit * fNormo * 0 + ConvCrit && itc < MaxIter) || itc < MinIter)
                    {
                        rat    = fnorm / fNormo;
                        fNormo = fnorm;
                        itc++;

                        // How should the inverse of the Jacobian be approximated?
                        if (ApproxJac == ApproxInvJacobianOptions.GMRES)
                        {
                            if (Precond != null)
                            {
                                Precond.Init(CurrentLin);
                            }
                            //base.EvalResidual(x, ref f0);
                            f0.ScaleV(-1.0);
                            step = Krylov(SolutionVec, x, f0, out errstep);
                        }
                        else if (ApproxJac == ApproxInvJacobianOptions.DirectSolver)
                        {
                            /*
                             * double[] _step = step.ToArray();
                             * double[] _f0 = f0.ToArray();
                             * double _check_norm;
                             * {
                             *  var CurrentJac = CurrentLin.OperatorMatrix;
                             *  var _solver = new ilPSP.LinSolvers.PARDISO.PARDISOSolver();      // .MUMPS.MUMPSSolver();
                             *  _solver.DefineMatrix(CurrentJac);
                             *  _step.ClearEntries();
                             *  var _check = _f0.CloneAs();
                             *  _f0.ScaleV(-1.0);
                             *  _solver.Solve(_step, _f0);
                             *
                             *  CurrentLin.OperatorMatrix.SpMV(-1.0, _step, -1.0, _check);
                             *  _check_norm = _check.L2Norm();
                             * }
                             */

                            var solver = linsolver;
                            //var mgo = new MultigridOperator(m_AggBasisSeq, SolutionVec.Mapping, CurrentJac, null, m_MultigridOperatorConfig);
                            solver.Init(CurrentLin);
                            step.ClearEntries();
                            var check = f0.CloneAs();
                            f0.ScaleV(-1.0);
                            solver.ResetStat();
                            solver.Solve(step, f0);

                            /*
                             * double check_norm;
                             * {
                             *  CurrentLin.OperatorMatrix.SpMV(-1.0, step, -1.0, check);
                             *  check_norm = check.L2Norm();
                             * }
                             *
                             *
                             * double dist = GenericBlas.L2Dist(step, _step);
                             *
                             *
                             * Console.WriteLine("    conv: " + solver.Converged + " /iter = " + solver.ThisLevelIterations + " /dist  = " + dist + " /resNrm = " + check_norm + " /parresNrm = " + _check_norm);
                             */
                            //step.SetV(step);

                            //if (solver.Converged == false)
                            //    Debugger.Launch();
                        }
                        else
                        {
                            throw new NotImplementedException("Your approximation option for the jacobian seems not to be existent.");
                        }



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

                        double nft = ft.L2NormPow2().MPISum().Sqrt();
                        double nf0 = f0.L2NormPow2().MPISum().Sqrt();
                        double ff0 = nf0 * nf0;
                        double ffc = nft * nft;
                        double ffm = nft * nft;

                        //    Console.WriteLine("    Residuum 0:" + nf0);

                        // 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("    Residuum:  " + nft + " lambda = " + lambda);
#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
                        if (itc % constant_newton_it == 0)
                        {
                            base.Update(SolutionVec.Mapping.Fields, ref xt);
                            if (constant_newton_it != 1)
                            {
                                Console.WriteLine("Jacobian is updated: it {0}", itc);
                            }
                        }

                        // residual evaluation & callback
                        base.EvalResidual(xt, ref ft);

                        EvaluateOperator(1, SolutionVec.Mapping.Fields, ft);

                        fnorm = ft.L2NormPow2().MPISum().Sqrt();

                        x  = xt;
                        f0 = ft.CloneAs();

                        OnIterationCallback(itc, x.CloneAs(), f0.CloneAs(), this.CurrentLin);
                    }
                }

                SolutionVec = m_SolutionVec;
            }
        }
Exemple #4
0
        public DrinksController(DataService dataService)
        {
            Precond.IsNotNull(dataService);

            this.dataService = dataService;
        }
            SolveModelWithSubdomains(double stiffnessRatio, InterfaceSolver interfaceSolver, Precond precond, MatrixQ q,
                Residual residualConvergence, double factorizationTolerance, double pcgConvergenceTolerance)
        {
            // Model
            Model multiSubdomainModel = CreateModel(stiffnessRatio);

            // Solver
            var factorizationTolerances = new Dictionary<int, double>();
            foreach (Subdomain s in multiSubdomainModel.Subdomains) factorizationTolerances[s.ID] = factorizationTolerance;
            //var fetiMatrices = new DenseFeti1SubdomainMatrixManager.Factory();
            //var fetiMatrices = new SkylineFeti1SubdomainMatrixManager.Factory();
            var fetiMatrices = new SkylineFeti1SubdomainMatrixManager.Factory(new OrderingAmdSuiteSparse());
            var solverBuilder = new Feti1Solver.Builder(fetiMatrices, factorizationTolerances);

            // Homogeneous/heterogeneous problem, matrix Q.
            solverBuilder.ProblemIsHomogeneous = stiffnessRatio == 1.0;
            if (q == MatrixQ.Identity) solverBuilder.ProjectionMatrixQIsIdentity = true;
            else solverBuilder.ProjectionMatrixQIsIdentity = false;

            // Preconditioner
            if (precond == Precond.Lumped) solverBuilder.PreconditionerFactory = new LumpedPreconditioner.Factory();
            else if (precond == Precond.DirichletDiagonal)
            {
                solverBuilder.PreconditionerFactory = new DiagonalDirichletPreconditioner.Factory();
            }
            else solverBuilder.PreconditionerFactory = new DirichletPreconditioner.Factory();

            // PCG may need to use the exact residual for the comparison with the expected values
            bool residualIsExact = residualConvergence == Residual.Exact;
            ExactFeti1PcgConvergence.Factory exactResidualConvergence = null;
            if (residualIsExact)
            {
                exactResidualConvergence = new ExactFeti1PcgConvergence.Factory(
                    CreateSingleSubdomainModel(stiffnessRatio), solverBuilder.DofOrderer,
                        (model, solver) => new ProblemStructural(model, solver));
            }

            // Lagrange separation method
            if (interfaceSolver == InterfaceSolver.Method1)
            {
                var interfaceProblemSolverBuilder = new Feti1UnprojectedInterfaceProblemSolver.Builder();
                interfaceProblemSolverBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(maxIterations);
                interfaceProblemSolverBuilder.PcgConvergenceTolerance = pcgConvergenceTolerance;
                if (residualIsExact) interfaceProblemSolverBuilder.PcgConvergenceStrategyFactory = exactResidualConvergence;
                Feti1UnprojectedInterfaceProblemSolver interfaceProblemSolver = interfaceProblemSolverBuilder.Build();
                solverBuilder.InterfaceProblemSolver = interfaceProblemSolver;
            }
            else
            {
                var interfaceProblemSolverBuilder = new Feti1ProjectedInterfaceProblemSolver.Builder();
                interfaceProblemSolverBuilder.MaxIterationsProvider = new FixedMaxIterationsProvider(maxIterations);
                interfaceProblemSolverBuilder.PcgConvergenceTolerance = pcgConvergenceTolerance;
                if (residualIsExact) interfaceProblemSolverBuilder.PcgConvergenceStrategyFactory = exactResidualConvergence;

                if (interfaceSolver == InterfaceSolver.Method2)
                {
                    interfaceProblemSolverBuilder.LagrangeSeparation = LagrangeMultiplierSeparation.Simple;
                    interfaceProblemSolverBuilder.ProjectionSideMatrix = ProjectionSide.Left;
                    interfaceProblemSolverBuilder.ProjectionSidePreconditioner = ProjectionSide.Left;
                }
                else if (interfaceSolver == InterfaceSolver.Method3)
                {
                    interfaceProblemSolverBuilder.LagrangeSeparation = LagrangeMultiplierSeparation.WithProjection;
                    interfaceProblemSolverBuilder.ProjectionSideMatrix = ProjectionSide.Both;
                    interfaceProblemSolverBuilder.ProjectionSidePreconditioner = ProjectionSide.None;
                }
                else if (interfaceSolver == InterfaceSolver.Method4)
                {
                    interfaceProblemSolverBuilder.LagrangeSeparation = LagrangeMultiplierSeparation.WithProjection;
                    interfaceProblemSolverBuilder.ProjectionSideMatrix = ProjectionSide.Both;
                    interfaceProblemSolverBuilder.ProjectionSidePreconditioner = ProjectionSide.Left;
                }
                else // default
                {
                    interfaceProblemSolverBuilder.LagrangeSeparation = LagrangeMultiplierSeparation.WithProjection;
                    interfaceProblemSolverBuilder.ProjectionSideMatrix = ProjectionSide.Both;
                    interfaceProblemSolverBuilder.ProjectionSidePreconditioner = ProjectionSide.Both;
                }

                Feti1ProjectedInterfaceProblemSolver interfaceProblemSolver = interfaceProblemSolverBuilder.Build();
                solverBuilder.InterfaceProblemSolver = interfaceProblemSolver;

                // Only needed in methods 2,3,4, default (where there is lagrange separation)
                if (residualIsExact) exactResidualConvergence.InterfaceProblemSolver = interfaceProblemSolver; 
            }

            Feti1Solver fetiSolver = solverBuilder.BuildSolver(multiSubdomainModel);
            if (residualIsExact) exactResidualConvergence.FetiSolver = fetiSolver;

            // Structural problem provider
            var provider = new ProblemStructural(multiSubdomainModel, fetiSolver);

            // Linear static analysis
            var childAnalyzer = new LinearAnalyzer(multiSubdomainModel, fetiSolver, provider);
            var parentAnalyzer = new StaticAnalyzer(multiSubdomainModel, fetiSolver, provider, childAnalyzer);

            // Run the analysis
            parentAnalyzer.Initialize();
            parentAnalyzer.Solve();

            // Gather the global displacements
            var sudomainDisplacements = new Dictionary<int, IVectorView>();
            foreach (var ls in fetiSolver.LinearSystems) sudomainDisplacements[ls.Key] = ls.Value.Solution;
            Vector globalDisplacements = fetiSolver.GatherGlobalDisplacements(sudomainDisplacements);

            // Other stats
            int numUniqueGlobalDofs = multiSubdomainModel.Nodes.Count * 2;
            int numExtenedDomainDofs = 0;
            foreach (var subdomain in multiSubdomainModel.Subdomains) numExtenedDomainDofs += subdomain.Nodes.Count * 2;

            return (globalDisplacements, fetiSolver.Logger, numUniqueGlobalDofs, numExtenedDomainDofs);
        }
        // Stiffness ratio = 1E-6
        //[InlineData(1E-6, InterfaceSolver.Method1, Precond.Dirichlet, MatrixQ.Identity, Residual.Exact, 40)] // converges, stagnates almost before the tolerance and then diverges
        //[InlineData(1E-6, InterfaceSolver.Method2, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 9)] // converges, stagnates almost before the tolerance and then diverges
        //[InlineData(1E-6, InterfaceSolver.Method3, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 23)] //3
        //[InlineData(1E-6, InterfaceSolver.Method4, Precond.Dirichlet, MatrixQ.Precond, Residual.Exact, 9)] // converges, stagnates almost before the tolerance and then diverges
        //[InlineData(1E-6, InterfaceSolver.Default, Precond.Dirichlet, MatrixQ.Precond, Residual.Approximate, 9)]
        public static void Run(double stiffnessRatio, InterfaceSolver interfaceSolver, Precond precond, MatrixQ q,
            Residual convergence, int iterExpected)
        {
            //InterfaceSolver interfaceSolver = 0;
            double factorizationTol = 1E-3, pcpgConvergenceTol = 1E-5;
            IVectorView directDisplacements = SolveModelWithoutSubdomains(stiffnessRatio);
            (IVectorView ddDisplacements, SolverLogger logger, int numUniqueGlobalDofs, int numExtenedDomainDofs) =
                SolveModelWithSubdomains(stiffnessRatio, interfaceSolver, precond, q, convergence, 
                    factorizationTol, pcpgConvergenceTol);
            double normalizedError = directDisplacements.Subtract(ddDisplacements).Norm2() / directDisplacements.Norm2();

            int analysisStep = 0;
            Assert.Equal(882, numUniqueGlobalDofs);    // 882 includes constrained and free dofs
            Assert.Equal(1056, numExtenedDomainDofs); // 1056 includes constrained and free dofs
            Assert.Equal(190, logger.GetNumDofs(analysisStep, "Lagrange multipliers"));

            // The error is provided in the reference solution the, but it is almost impossible for two different codes run on 
            // different machines to achieve the exact same accuracy.
            Assert.Equal(0.0, normalizedError, 5);

            // Allow a tolerance: It is ok if my solver is better or off by 1 iteration 
            int pcgIterations = logger.GetNumIterationsOfIterativeAlgorithm(analysisStep);
            Assert.InRange(pcgIterations, 1, iterExpected + 1); // the upper bound is inclusive!
        }
Exemple #7
0
        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;
            }
        }
Exemple #8
0
        /// <summary>
        /// Adds or updates the drink. Drink may not be null.
        /// </summary>
        /// <exception cref="ArgumentNullException">drink</exception>
        public void AddOrUpdate(Drink drink)
        {
            Precond.IsNotNull(drink?.Name);

            drinks[drink.Name] = drink;
        }