Ejemplo n.º 1
0
        /// <summary>
        /// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized.
        /// </summary>
        /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
        public override void Solve(Matrix <Complex> input, Matrix <Complex> result)
        {
            // The solution X should have the same number of columns as B
            if (input.ColumnCount != result.ColumnCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
            }

            // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
            if (EigenValues.Count != input.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameRowDimension);
            }

            // The solution X row dimension is equal to the column dimension of A
            if (EigenValues.Count != result.RowCount)
            {
                throw new ArgumentException(Resources.ArgumentMatrixSameColumnDimension);
            }

            if (IsSymmetric)
            {
                var order = EigenValues.Count;
                var tmp   = new Complex[order];

                for (var k = 0; k < order; k++)
                {
                    for (var j = 0; j < order; j++)
                    {
                        Complex value = 0.0;
                        if (j < order)
                        {
                            for (var i = 0; i < order; i++)
                            {
                                value += EigenVectors.At(i, j).Conjugate() * input.At(i, k);
                            }

                            value /= EigenValues[j].Real;
                        }

                        tmp[j] = value;
                    }

                    for (var j = 0; j < order; j++)
                    {
                        Complex value = 0.0;
                        for (var i = 0; i < order; i++)
                        {
                            value += EigenVectors.At(j, i) * tmp[i];
                        }

                        result.At(j, k, value);
                    }
                }
            }
            else
            {
                throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized.
        /// </summary>
        /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</param>
        public override void Solve(Matrix <float> input, Matrix <float> result)
        {
            // The solution X should have the same number of columns as B
            if (input.ColumnCount != result.ColumnCount)
            {
                throw new ArgumentException("Matrix column dimensions must agree.");
            }

            // The dimension compatibility conditions for X = A\B require the two matrices A and B to have the same number of rows
            if (EigenValues.Count != input.RowCount)
            {
                throw new ArgumentException("Matrix row dimensions must agree.");
            }

            // The solution X row dimension is equal to the column dimension of A
            if (EigenValues.Count != result.RowCount)
            {
                throw new ArgumentException("Matrix column dimensions must agree.");
            }

            if (IsSymmetric)
            {
                var order = EigenValues.Count;
                var tmp   = new float[order];

                for (var k = 0; k < order; k++)
                {
                    for (var j = 0; j < order; j++)
                    {
                        float value = 0;
                        if (j < order)
                        {
                            for (var i = 0; i < order; i++)
                            {
                                value += EigenVectors.At(i, j) * input.At(i, k);
                            }

                            value /= (float)EigenValues[j].Real;
                        }

                        tmp[j] = value;
                    }

                    for (var j = 0; j < order; j++)
                    {
                        float value = 0;
                        for (var i = 0; i < order; i++)
                        {
                            value += EigenVectors.At(j, i) * tmp[i];
                        }

                        result.At(j, k, value);
                    }
                }
            }
            else
            {
                throw new ArgumentException("Matrix must be symmetric.");
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A SVD factorized.
        /// </summary>
        /// <param name="input">The right hand side vector, <b>b</b>.</param>
        /// <returns>The left hand side <see cref="Vector{T}"/>, <b>x</b>.</returns>
        public virtual Vector <T> Solve(Vector <T> input)
        {
            var x = EigenVectors.CreateVector(EigenVectors.ColumnCount);

            Solve(input, x);
            return(x);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Solves a system of linear equations, <b>AX = B</b>, with A SVD factorized.
        /// </summary>
        /// <param name="input">The right hand side <see cref="Matrix{T}"/>, <b>B</b>.</param>
        /// <returns>The left hand side <see cref="Matrix{T}"/>, <b>X</b>.</returns>
        public virtual Matrix <T> Solve(Matrix <T> input)
        {
            var result = EigenVectors.CreateMatrix(EigenVectors.ColumnCount, input.ColumnCount);

            Solve(input, result);
            return(result);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A EVD factorized.
        /// </summary>
        /// <param name="input">The right hand side vector, <b>b</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
        public override void Solve(Vector <Complex> input, Vector <Complex> result)
        {
            // Ax=b where A is an m x m matrix
            // Check that b is a column vector with m entries
            if (EigenValues.Count != input.Count)
            {
                throw new ArgumentException(Resources.ArgumentVectorsSameLength);
            }

            // Check that x is a column vector with n entries
            if (EigenValues.Count != result.Count)
            {
                throw Matrix.DimensionsDontMatch <ArgumentException>(EigenValues, result);
            }

            if (IsSymmetric)
            {
                // Symmetric case -> x = V * inv(λ) * VH * b;
                var     order = EigenValues.Count;
                var     tmp   = new Complex[order];
                Complex value;

                for (var j = 0; j < order; j++)
                {
                    value = 0;
                    if (j < order)
                    {
                        for (var i = 0; i < order; i++)
                        {
                            value += EigenVectors.At(i, j).Conjugate() * input[i];
                        }

                        value /= EigenValues[j].Real;
                    }

                    tmp[j] = value;
                }

                for (var j = 0; j < order; j++)
                {
                    value = 0;
                    for (int i = 0; i < order; i++)
                    {
                        value += EigenVectors.At(j, i) * tmp[i];
                    }

                    result[j] = value;
                }
            }
            else
            {
                throw new ArgumentException(Resources.ArgumentMatrixSymmetric);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Solves a system of linear equations, <b>Ax = b</b>, with A EVD factorized.
        /// </summary>
        /// <param name="input">The right hand side vector, <b>b</b>.</param>
        /// <param name="result">The left hand side <see cref="Matrix{T}"/>, <b>x</b>.</param>
        public override void Solve(Vector <float> input, Vector <float> result)
        {
            // Ax=b where A is an m x m matrix
            // Check that b is a column vector with m entries
            if (EigenValues.Count != input.Count)
            {
                throw new ArgumentException("All vectors must have the same dimensionality.");
            }

            // Check that x is a column vector with n entries
            if (EigenValues.Count != result.Count)
            {
                throw new ArgumentException("Matrix dimensions must agree.");
            }

            if (IsSymmetric)
            {
                // Symmetric case -> x = V * inv(λ) * VT * b;
                var   order = EigenValues.Count;
                var   tmp   = new float[order];
                float value;

                for (var j = 0; j < order; j++)
                {
                    value = 0;
                    if (j < order)
                    {
                        for (var i = 0; i < order; i++)
                        {
                            value += EigenVectors.At(i, j) * input[i];
                        }

                        value /= (float)EigenValues[j].Real;
                    }

                    tmp[j] = value;
                }

                for (var j = 0; j < order; j++)
                {
                    value = 0;
                    for (int i = 0; i < order; i++)
                    {
                        value += EigenVectors.At(j, i) * tmp[i];
                    }

                    result[j] = value;
                }
            }
            else
            {
                throw new ArgumentException("Matrix must be symmetric.");
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// 平行ビームの電子回折計算
        /// </summary>
        /// <param name="maxNumOfBloch"></param>
        /// <param name="voltage"></param>
        /// <param name="rotation"></param>
        /// <param name="thickness"></param>
        /// <returns></returns>
        public Beam[] GetDifractedBeamAmpriltudes(int maxNumOfBloch, double voltage, Matrix3D rotation, double thickness)
        {
            var useEigen = !MathNet.Numerics.Control.TryUseNativeMKL();

            if (AccVoltage != voltage)
            {
                uDictionary = new Dictionary <int, (Complex, Complex)>();
            }

            //波数を計算
            var k_vac = UniversalConstants.Convert.EnergyToElectronWaveNumber(voltage);
            //U0を計算
            var u0    = getU(voltage, (0, 0, 0), 0).Real.Real;
            var vecK0 = getVecK0(k_vac, u0);

            if (MaxNumOfBloch != maxNumOfBloch || AccVoltage != voltage || EigenValues == null || EigenVectors == null || !rotation.Equals(BaseRotation))
            {
                MaxNumOfBloch = maxNumOfBloch;
                AccVoltage    = voltage;
                BaseRotation  = new Matrix3D(rotation);
                Thickness     = thickness;

                //計算対象のg-Vectorsを決める。
                Beams = Find_gVectors(BaseRotation, vecK0);

                if (Beams == null || Beams.Length == 0)
                {
                    return(new Beam[0]);
                }

                var potentialMatrix = getEigenProblemMatrix(Beams);

                //A行列に関する固有値、固有ベクトルを取得
                if (useEigen)
                {
                    (EigenValues, EigenVectors) = NativeWrapper.EigenSolver(potentialMatrix);
                }
                else
                {
                    var evd = DMat.OfArray(potentialMatrix).Evd(Symmetricity.Asymmetric);
                    EigenValues  = evd.EigenValues.AsArray();
                    EigenVectors = (DMat)evd.EigenVectors;
                }

                //(EigenVectors, EigenValues) = RefineEigenProblem(DMat.OfArray(potentialMatrix), (DMat)evd.EigenVectors, evd.EigenValues.ToArray());
            }
            int len = EigenValues.Count();

            var psi0 = DVec.OfArray(new Complex[len]);//入射面での波動関数を定義

            psi0[0] = 1;

            var alpha = EigenVectors.Inverse() * psi0;//アルファベクトルを求める

            //ガンマの対称行列×アルファを作成
            var gamma_alpha = new DVec(Enumerable.Range(0, len).Select(n => Exp(TwoPiI * EigenValues[n] * thickness) * alpha[n]).ToArray());

            //出射面での境界条件を考慮した位相にするため、以下の1行を追加 (20190827)
            var p = new DiagonalMatrix(len, len, Beams.Select(b => Exp(PiI * (b.P - 2 * k_vac * Surface.Z) * thickness)).ToArray());
            //var p = new DiagonalMatrix(len, len, Beams.Select(b => new Complex(1, 0)).ToArray());

            //深さZにおけるψを求める
            var psi_atZ = p * EigenVectors * gamma_alpha;

            for (int i = 0; i < Beams.Length && i < len; i++)
            {
                Beams[i].Psi = psi_atZ[i];
            }

            return(Beams);
        }