public IVector GetOtherRhsComponents(ILinearSystem linearSystem, IVector currentSolution) { #region old code //// u[id]: old solution //// v[id]: current solution //// vv: old acceleration //// v2: current acceleration //// v1: current velocity ////double vv = v2[id].Data[j]; ////v2[id].Data[j] = a0 * (v[id].Data[j] - u[id].Data[j]) - a2 * v1[id].Data[j] - a3 * vv; ////v1[id].Data[j] += a6 * vv + a7 * v2[id].Data[j]; //int id = subdomain.ID; //Vector<double> currentAcceleration = new Vector<double>(subdomain.Solution.Length); //Vector<double> currentVelocity = new Vector<double>(subdomain.Solution.Length); //Vector<double> uu = new Vector<double>(subdomain.Solution.Length); //Vector<double> uc = new Vector<double>(subdomain.Solution.Length); //for (int j = 0; j < subdomain.Rhs.Length; j++) //{ // currentAcceleration.Data[j] = a0 * (currentSolution[j] - v[id].Data[j]) - a2 * v1[id].Data[j] - a3 * v2[id].Data[j]; // currentVelocity.Data[j] = v1[id].Data[j] + a6 * v2[id].Data[j] + a7 * currentAcceleration.Data[j]; // uu.Data[j] = a0 * currentSolution[j] + a2 * currentVelocity.Data[j] + a3 * currentAcceleration.Data[j]; // uc.Data[j] = a1 * currentSolution[j] + a4 * currentVelocity.Data[j] + a5 * currentAcceleration.Data[j]; //} //Vector<double> tempResult = new Vector<double>(subdomain.Solution.Length); //Vector<double> result = new Vector<double>(subdomain.Solution.Length); //provider.MassMatrixVectorProduct(subdomain, uu, tempResult.Data); //result.Add(tempResult); //provider.DampingMatrixVectorProduct(subdomain, uc, tempResult.Data); //result.Add(tempResult); //return result.Data; //Vector<double> uu = new Vector<double>(subdomain.Solution.Length); //Vector<double> uc = new Vector<double>(subdomain.Solution.Length); //int id = subdomain.ID; //for (int j = 0; j < subdomain.Rhs.Length; j++) //{ // uu.Data[j] = -a0 * (v[id].Data[j] - currentSolution[j]) - a2 * v1[id].Data[j] - a3 * v2[id].Data[j]; // uc.Data[j] = -a1 * (v[id].Data[j] - currentSolution[j]) - a4 * v1[id].Data[j] - a5 * v2[id].Data[j]; //} //provider.MassMatrixVectorProduct(subdomain, uu, tempResult.Data); //result.Add(tempResult); //provider.DampingMatrixVectorProduct(subdomain, uc, tempResult.Data); //result.Add(tempResult); ////CalculateRhsImplicit(subdomain, result.Data, false); ////result.Scale(-1d); #endregion // result = a0 * (M * u) + a1 * (C * u) IVector result = providers[0].MassMatrixVectorProduct(linearSystem.Subdomain, currentSolution); IVector temp = providers[0].DampingMatrixVectorProduct(linearSystem.Subdomain, currentSolution); result.LinearCombinationIntoThis(a0, temp, a1); return(result); }
/// <summary> /// Calculates inertia forces and damping forces. /// </summary> public IVector GetOtherRhsComponents(ILinearSystem linearSystem, IVector currentSolution) { IVector result = provider.MassMatrixVectorProduct(linearSystem.Subdomain, currentSolution); IVector temp = provider.DampingMatrixVectorProduct(linearSystem.Subdomain, currentSolution); result.LinearCombinationIntoThis(a0, temp, a1); return(result); }
internal static void Calculate(ILinearTransformation matrix, IVectorView rhs, IVectorView solution, IVector residual) { //TODO: There is a BLAS operation y = y + a * A*x, that would be perfect for here. rhs.Copy() and then that. matrix.Multiply(solution, residual); residual.LinearCombinationIntoThis(-1.0, rhs, 1.0); }
private IterativeStatistics SolveInternal(int maxIterations) { // δnew = δ0 = r * r resDotRes = residual.DotProduct(residual); // The convergence criterion must be initialized immediately after the first r and r*r are computed. residualConvergence.Initialize(this); // This is also used as output double residualNormRatio = double.NaN; // d = r direction = residual.Copy(); // Allocate memory for other vectors, which will be reused during each iteration matrixTimesDirection = Rhs.CreateZeroVectorWithSameFormat(); for (Iteration = 0; Iteration < maxIterations; ++Iteration) { // q = A * d Matrix.Multiply(direction, matrixTimesDirection); // α = δnew / (d * q) StepSize = ResDotRes / (direction.DotProduct(matrixTimesDirection)); // x = x + α * d solution.AxpyIntoThis(direction, StepSize); // δold = δnew double resDotResOld = ResDotRes; // Normally the residual vector is updated as: r = r - α * q and δnew = r * r. // However corrections might need to be applied. residualUpdater.UpdateResidual(this, residual, out resDotRes); // At this point we can check if CG has converged and exit, thus avoiding the uneccesary operations that follow. residualNormRatio = residualConvergence.EstimateResidualNormRatio(this); if (residualNormRatio <= residualTolerance) { return(new IterativeStatistics { AlgorithmName = name, HasConverged = true, NumIterationsRequired = Iteration + 1, ResidualNormRatioEstimation = residualNormRatio }); } // β = δnew / δold ParamBeta = ResDotRes / resDotResOld; // d = r + β * d //TODO: benchmark the two options to find out which is faster //direction = residual.Axpy(direction, beta); //This allocates a new vector d, copies r and GCs the existing d. direction.LinearCombinationIntoThis(ParamBeta, residual, 1.0); //This performs additions instead of copying and needless multiplications. } // We reached the max iterations before CG converged return(new IterativeStatistics { AlgorithmName = name, HasConverged = false, NumIterationsRequired = maxIterations, ResidualNormRatioEstimation = residualNormRatio }); }