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