Beispiel #1
0
        private IVector CalculateRhsImplicit(ILinearSystem linearSystem, bool addRhs)
        {
            int id = linearSystem.Subdomain.ID;

            capacityTimesTemperature[id]     = provider.MassMatrixVectorProduct(linearSystem.Subdomain, temperature[id]);
            conductivityTimesTemperature[id] = provider.DampingMatrixVectorProduct(linearSystem.Subdomain, temperature[id]);

            IVector rhsResult = rhsPrevious[id].LinearCombination(1 - beta, rhs[id], beta);

            rhsResult.AxpyIntoThis(capacityTimesTemperature[id], 1 / timeStep);
            rhsResult.AxpyIntoThis(conductivityTimesTemperature[id], -(1 - beta));

            rhsPrevious[id] = rhs[id];
            return(rhsResult);
        }
Beispiel #2
0
        /// <summary>
        /// Calculates the initial approximation to the linear system's solution vector, by using a series of conjugate direction
        /// vectors that have been stored previously by PCG during the solution of other linear systems with the same matrix.
        /// This method should be used to solve linear systems with different right hand side vectors and the same matrix.
        /// </summary>
        /// <param name="rhsNew">The right hand side vector of the new linear system.</param>
        /// <param name="initialSolution">
        /// The initial approximation to the solution vector, which PCG will improve. It will be overwritten by this method.
        /// </param>
        /// <param name="isSolutionZero">
        /// Set to true if <paramref name="initialSolution"/> is the zero vector, to avoid clearing it.
        /// </param>
        /// <exception cref="InvalidOperationException">Thrown if there are no direction vectors stored yet.</exception>
        public void CalculateInitialSolutionFromStoredDirections(IVectorView rhsNew, IVector initialSolution,
                                                                 bool isSolutionZero)
        {
            if (reorthoCache.Directions.Count < 1)
            {
                throw new InvalidOperationException("There are no direction vectors stored.");
            }
            if (!isSolutionZero)
            {
                initialSolution.Clear();
            }

            //TODO: An implementation by G. Stavroulakis discarded the last stored direction vector at this point. Why?
            //reorthoCache.RemoveNewDirectionVectorData(1);

            // x0 = D_nd * x_d, x_d = inv(Q_nd * D_nd) * D_nd^T * b
            // D_nd = [d_1 ... d_nd], Q_nd = A * D_nd = [q_1 ... q_nd], Q_nd * D_nd = diag([d1*A*d1 ... d_nd*A*d_nd])
            for (int i = 0; i < reorthoCache.Directions.Count; ++i)
            {
                // x_d[i] = 1/(d_i * q_i) * (d_i * b)
                double xd = reorthoCache.Directions[i].DotProduct(rhsNew) / reorthoCache.DirectionsTimesMatrixTimesDirections[i];

                Debug.Assert(!double.IsNaN(xd));
                Debug.Assert(!double.IsPositiveInfinity(xd));
                Debug.Assert(!double.IsNegativeInfinity(xd));

                // x0 += d_i * x_d[i]
                initialSolution.AxpyIntoThis(reorthoCache.Directions[i], xd);
            }
        }
Beispiel #3
0
 /// <summary>
 /// Gram–Schmidt orthogonalization to the stored vectors, without normalization.
 /// </summary>
 /// <param name="v">The vector to reorthogonalize. It will be overwritten with the result. If there are no stored
 ///     vectors, it will remain unchanged without being copied.</param>
 internal void Reorthogonalize(IVector v)
 {
     // reorthogonalize 1 by 1
     foreach (var p in store)
     {
         // we don't have to normalize since it is explicitly done in the code and so we don't need to redo it
         v.AxpyIntoThis(p, -(v.DotProduct(p)));   // orthogonalize to each stored vector
     }
 }
Beispiel #4
0
        private IVector CalculateRhsImplicit(ILinearSystem linearSystem, bool addRhs)
        {
            //TODO: what is the meaning of addRhs? Do we need this when solving dynamic thermal equations?

            // result = (1-b)* rhsPrevious + beta * rhs + 1/dt * 1stOrderMatrix * unknown - (1-b) * 0thOrderMatrix * unknown
            int id = linearSystem.Subdomain.ID;

            firstOrderMatrixTimesUnknown[id]  = provider.MassMatrixVectorProduct(linearSystem.Subdomain, unknown[id]);
            zerothOrderMatrixTimesUnknown[id] = provider.DampingMatrixVectorProduct(linearSystem.Subdomain, unknown[id]);

            IVector rhsResult = rhsPrevious[id].LinearCombination(1 - beta, rhs[id], beta);

            rhsResult.AxpyIntoThis(firstOrderMatrixTimesUnknown[id], 1 / timeStep);
            rhsResult.AxpyIntoThis(zerothOrderMatrixTimesUnknown[id], -(1 - beta));

            rhsPrevious[id] = rhs[id];
            return(rhsResult);
        }
Beispiel #5
0
        private IVector CalculateRhsImplicit(ILinearSystem linearSystem, bool addRhs)
        {
            //TODO: what is the meaning of addRhs? Do we need this when solving dynamic thermal equations?

            // result = (1-b)* rhsPrevious + beta * rhs + 1/dt * Capacity * temperature - (1-b) * Conductivity * temperature
            int id = linearSystem.Subdomain.ID;

            capacityTimesTemperature[id]     = provider.MassMatrixVectorProduct(linearSystem.Subdomain, temperature[id]);
            conductivityTimesTemperature[id] = provider.DampingMatrixVectorProduct(linearSystem.Subdomain, temperature[id]);

            IVector rhsResult = rhsPrevious[id].LinearCombination(1 - beta, rhs[id], beta);

            rhsResult.AxpyIntoThis(capacityTimesTemperature[id], 1 / timeStep);
            rhsResult.AxpyIntoThis(conductivityTimesTemperature[id], -(1 - beta));

            rhsPrevious[id] = rhs[id];
            return(rhsResult);
        }
Beispiel #6
0
        private IVector CalculateRhsImplicit(ILinearSystem linearSystem, int modelNo, bool addRhs)
        {
            //TODO: what is the meaning of addRhs? Do we need this when solving dynamic thermal equations?
            //TODO: stabilizingRhs has not been implemented

            // result = -dt(conductuvity*temperature + rhs -dt(stabilizingConductivity*temperature + StabilizingRhs))
            int id = linearSystem.Subdomain.ID;

            firstOrderMatrixTimesUnknown[modelNo][id]  = providers[modelNo].MassMatrixVectorProduct(linearSystem.Subdomain, unknown[modelNo][id]);
            secondOrderMatrixTimesUnknown[modelNo][id] = providers[modelNo].DampingMatrixVectorProduct(linearSystem.Subdomain, unknown[modelNo][id]);

            IVector rhsResult = rhsPrevious[modelNo][id].LinearCombination(1 - beta, rhs[modelNo][id], beta);

            rhsResult.AxpyIntoThis(firstOrderMatrixTimesUnknown[modelNo][id], 1 / timeStep);
            rhsResult.AxpyIntoThis(secondOrderMatrixTimesUnknown[modelNo][id], -(1 - beta));

            rhsPrevious[modelNo][id] = rhs[modelNo][id];
            return(rhsResult);
        }
Beispiel #7
0
 private void UpdateDirectionVector(IVectorView preconditionedResidual, IVector direction)
 {
     // d = s - sum(β_i * d_i), 0 <= i < currentIteration
     // β_i = (s * q_i) / (d_i * q_i)
     direction.CopyFrom(preconditionedResidual);
     for (int i = 0; i < reorthoCache.Directions.Count; ++i)
     {
         double beta = preconditionedResidual.DotProduct(reorthoCache.MatrixTimesDirections[i])
                       / reorthoCache.DirectionsTimesMatrixTimesDirections[i];
         direction.AxpyIntoThis(reorthoCache.Directions[i], -beta);
     }
 }
        /// <summary>
        /// See <see cref="IPcgResidualUpdater.UpdateResidual(PcgAlgorithmBase, IVector)"/>
        /// </summary>
        public void UpdateResidual(PcgAlgorithmBase pcg, IVector residual)
        {
            //TODO: perhaps this should be done in an Initialize() method
            if (numIterationsBeforeCorrection == int.MinValue)
            {
                numIterationsBeforeCorrection = (int)Math.Floor(Math.Sqrt(pcg.Rhs.Length));
            }

            if ((pcg.Iteration % numIterationsBeforeCorrection == 0) && (pcg.Iteration != 0)) //The first iteration uses the correct residual.
            {
                // Calculate the exact residual: r = b - A * x
                ExactResidual.Calculate(pcg.Matrix, pcg.Rhs, pcg.Solution, residual);
            }
            else
            {
                // Normally the residual vector is updated as: r = r - α * A*d
                residual.AxpyIntoThis(pcg.MatrixTimesDirection, -pcg.StepSize);
            }
        }
Beispiel #9
0
        public void UpdateResidual(CGAlgorithm cg, IVector residual, out double resDotRes)
        {
            // Update the residual vector normally: r = r - α * A*d
            residual.AxpyIntoThis(cg.MatrixTimesDirection, -cg.StepSize);
            resDotRes = residual.DotProduct(residual); //TODO: it is weird that this sets resDotRes and cg.ResDotRes

            // Check if the CG will converge. TODO: Remove duplicate comutations: this check will also be done by CG later.
            double residualNormRatio = convergence.EstimateResidualNormRatio(cg); // let's pray that ICGResidualConvergence does not mutate any fields
            bool   hasConverged      = residualNormRatio <= residualTolerance;

            // Avoid premature convergence by calculating th exact residual.
            if (hasConverged)
            {
                // Exact residual: r = b - A * x
                ExactResidual.Calculate(cg.Matrix, cg.Rhs, cg.Solution, residual);

                // Recalculate the r * r
                resDotRes = residual.DotProduct(residual);
            }
        }
        /// <summary>
        /// Calculates the initial approximation to the linear system's solution vector, by using a series of conjugate direction
        /// vectors that have been stored previously by PCG during the solution of other linear systems with the same matrix.
        /// This method should be used to solve linear systems with different right hand side vectors and the same matrix.
        /// </summary>
        /// <param name="rhsNew">The right hand side vector of the new linear system.</param>
        /// <param name="initialSolution">
        /// The initial approximation to the solution vector, which PCG will improve. It will be overwritten by this method.
        /// </param>
        /// <exception cref="InvalidOperationException">Thrown if there are no direction vectors stored yet.</exception>
        public void CalculateInitialSolutionFromStoredDirections(IVectorView rhsNew, IVector initialSolution)
        {
            //TODO: An implementation by G. Stavroulakis discarded the last stored direction vector at this point. Why?
            //reorthoCache.RemoveNewDirectionVectorData(1);

            // x0 = D_nd * x_d, x_d = inv(Q_nd * D_nd) * D_nd^T * b
            // D_nd = [d_1 ... d_nd], Q_nd = A * D_nd = [q_1 ... q_nd], Q_nd * D_nd = diag([d1*A*d1 ... d_nd*A*d_nd])
            for (int i = 0; i < ReorthoCache.Directions.Count; ++i)
            {
                // x_d[i] = (d_i * b) / (d_i * q_i)
                double xd = ReorthoCache.Directions[i].DotProduct(rhsNew) / ReorthoCache.DirectionsTimesMatrixTimesDirections[i];

                Debug.Assert(!double.IsNaN(xd));
                Debug.Assert(!double.IsPositiveInfinity(xd));
                Debug.Assert(!double.IsNegativeInfinity(xd));

                // x0 += d_i * x_d[i]
                initialSolution.AxpyIntoThis(ReorthoCache.Directions[i], xd);
            }
        }
 /// <summary>
 /// See <see cref="ICGResidualUpdater.UpdateResidual(CGAlgorithm, IVector, out double)"/>
 /// </summary>
 public void UpdateResidual(CGAlgorithm cg, IVector residual, out double resDotRes)
 {
     // Normally the residual vector is updated as: r = r - α * A*d
     residual.AxpyIntoThis(cg.MatrixTimesDirection, -cg.StepSize);
     resDotRes = residual.DotProduct(residual);
 }
 /// <summary>
 /// See <see cref="IPcgResidualUpdater.UpdateResidual(PcgAlgorithmBase, IVector)"/>
 /// </summary>
 public void UpdateResidual(PcgAlgorithmBase pcg, IVector residual)
 {
     // Normally the residual vector is updated as: r = r - α * A*d
     residual.AxpyIntoThis(pcg.MatrixTimesDirection, -pcg.StepSize);
 }
Beispiel #13
0
 /// <summary>
 /// Performs the operation:
 /// <paramref name="thisVector"/>[i] = <paramref name="thisVector"/>[i] + <paramref name="otherVector"/>[i], for
 /// 0 &lt;= i &lt; <paramref name="thisVector"/>.<see cref="IIndexable1D.Length"/>
 /// = <paramref name="otherVector"/>.<see cref="IIndexable1D.Length"/>.
 /// The resulting vector overwrites the entries of this <see cref="IVector"/> instance.
 /// </summary>
 /// <param name="thisVector">
 /// A vector with the same <see cref="IIndexable1D.Length"/> as <paramref name="otherVector"/>.
 /// </param>
 /// <param name="otherVector">
 /// A vector with the same <see cref="IIndexable1D.Length"/> as <paramref name="thisVector"/>.
 /// </param>
 /// <exception cref="NonMatchingDimensionsException">
 /// Thrown if <paramref name="thisVector"/> and <paramref name="otherVector"/> have different
 /// <see cref="IIndexable1D.Length"/>.
 /// </exception>
 public static void AddIntoThis(this IVector thisVector, IVectorView otherVector)
 => thisVector.AxpyIntoThis(otherVector, 1.0);
Beispiel #14
0
 /// <summary>
 /// Performs the operation:
 /// <paramref name="thisVector"/>[i] = <paramref name="thisVector"/>[i] - <paramref name="otherVector"/>[i],
 /// for 0 &lt;= i &lt; <paramref name="thisVector"/>.<see cref="IIndexable1D.Length"/>
 /// = <paramref name="otherVector"/>.<see cref="IIndexable1D.Length"/>.
 /// The resulting vector overwrites the entries of this <see cref="IVector"/> instance.
 /// </summary>
 /// <param name="thisVector">
 /// A vector with the same <see cref="IIndexable1D.Length"/> as <paramref name="otherVector"/>.
 /// </param>
 /// <param name="otherVector">
 /// A vector with the same <see cref="IIndexable1D.Length"/> as <paramref name="thisVector"/>.
 /// </param>
 /// <exception cref="NonMatchingDimensionsException">
 /// Thrown if <paramref name="thisVector"/> and <paramref name="otherVector"/> have different
 /// <see cref="IIndexable1D.Length"/>.
 /// </exception>
 public static void SubtractIntoThis(this IVector thisVector, IVectorView otherVector)
 => thisVector.AxpyIntoThis(otherVector, -1.0);