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