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);
 }
Beispiel #4
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
            });
        }