示例#1
0
        public static Quaternion FromLogQuaternion(Vector3DBase v)
        {
            double theta = v.Length;

            v = v / theta * Math.Sin(theta);
            return(new Quaternion(Math.Cos(theta), v.X, v.Y, v.Z));
        }
示例#2
0
 public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
 {
     if (destinationType == typeof(string) && value is Vector3DBase)
     {
         Vector3DBase g = (Vector3DBase)value;
         return(string.Format("{0}, {1}, {2}", g.X, g.Y, g.Z));
     }
     return(base.ConvertTo(context, culture, value, destinationType));
 }
示例#3
0
        /// <summary>
        /// シュミット上の点を返す
        /// </summary>
        /// <param name="vec"></param>
        /// <returns></returns>
        public static PointD ConvertVectorToSchmidt(Vector3DBase vec)
        {
            if (vec == null)
            {
                return(new PointD(-100, -100));
            }
            var v = Vector3DBase.Normarize(vec);

            return(v.Z >= -0.999999 ? new PointD(v.X / Math.Sqrt(1 + v.Z), v.Y / Math.Sqrt(1 + v.Z)) : new PointD(-100, -100));
        }
示例#4
0
 /// <summary>
 /// ピクセルが対応する逆空間ベクトルを計算し、ReciprocalVectorsにセットする
 /// </summary>
 /// <returns></returns>
 private void SetReciporocalVectors()
 {
     ReciprocalVectors = new Vector3DBase[ImageWidth * ImageHeight];
     Parallel.For(0, ImageHeight, y =>
     {
         for (int x = 0; x < ImageWidth; x++)
         {
             ReciprocalVectors[y * ImageWidth + x] = convertClientToReciprocalSpace(x, y);
         }
     });
 }
示例#5
0
文件: Euler.cs 项目: lulzzz/PDIndexer
        //public enum Setting { XYX, XYZ, XZX, XZY, YXY, YXZ, YZX, YZY, ZXY, ZXZ, ZYX, ZYZ}

        /// <summary>
        /// 任意のセッティングのオイラー角に分解する.  => MathNet.FindMinimumの方が簡単なので、お蔵入り
        /// </summary>
        /// <param name="rot"></param>
        /// <param name="setting"></param>
        /// <returns></returns>
        public static double[] DecomposeMatrix(Matrix3D rot, Vector3DBase v1, Vector3DBase v2, Vector3DBase v3)
        {
            Matrix3D funcRot(double[] angle) => Matrix3D.Rot(v1, angle[0]) * Matrix3D.Rot(v2, angle[1]) * Matrix3D.Rot(v3, angle[2]);


            var func = new Marquardt.Function(
                new Func <double[], double[], double>((x, prm) =>
            {
                var res = funcRot(prm);
                if (x[0] == 0.0)
                {
                    return(res.E11);
                }
                else if (x[0] == 1.0)
                {
                    return(res.E12);
                }
                else if (x[0] == 2.0)
                {
                    return(res.E13);
                }
                else if (x[0] == 3.0)
                {
                    return(res.E21);
                }
                else if (x[0] == 4.0)
                {
                    return(res.E22);
                }
                else if (x[0] == 5.0)
                {
                    return(res.E23);
                }
                else if (x[0] == 6.0)
                {
                    return(res.E31);
                }
                else if (x[0] == 7.0)
                {
                    return(res.E32);
                }
                else if (x[0] == 8.0)
                {
                    return(res.E33);
                }
                else
                {
                    return(0);
                }
            }),
                new[] { 0.1, 0.2, 0.3 });


            var obsValues = new[] {
示例#6
0
        public Matrix3D(Vector3DBase v1, Vector3DBase v2, Vector3DBase v3)
        {
            E11 = v1.X;
            E21 = v1.Y;
            E31 = v1.Z;

            E12 = v2.X;
            E22 = v2.Y;
            E32 = v2.Z;

            E13 = v3.X;
            E23 = v3.Y;
            E33 = v3.Z;
        }
示例#7
0
        /// <summary>
        /// 対数Quatanion (方向が回転軸で長さがθ/2のベクトル)を得る.
        /// </summary>
        /// <param name="q"></param>
        /// <returns></returns>
        public static Vector3DBase ToLogQuaternion(Quaternion q)
        {
            Vector3DBase v     = new Vector3DBase(q.X, q.Y, q.Z);
            double       theta = Math.Acos(q.W);

            if (q.W >= 1)
            {
                return(v);
            }
            else
            {
                return(v / v.Length * theta);
            }
        }
示例#8
0
        private void numericBoxStrain_ValueChanged(object sender, EventArgs e)
        {
            skipCrystalChangedEvent = true;
            var m = StrainMatrix * new Matrix3D(originalCrystal.A_Axis, originalCrystal.B_Axis, originalCrystal.C_Axis);//この歪の計算は間違っている!直さなければ。。。

            var a = new Vector3DBase(m.E11, m.E21, m.E31);
            var b = new Vector3DBase(m.E12, m.E22, m.E32);
            var c = new Vector3DBase(m.E13, m.E23, m.E33);

            numericBoxA.Value           = a.Length * 10;
            numericBoxB.Value           = b.Length * 10;
            numericBoxC.Value           = c.Length * 10;
            numericBoxAlpha.RadianValue = Vector3DBase.AngleBetVectors(b, c);
            numericBoxBeta.RadianValue  = Vector3DBase.AngleBetVectors(c, a);
            numericBoxGamma.RadianValue = Vector3DBase.AngleBetVectors(a, b);

            CrystalControl.symmetryControl.CellConstants = (numericBoxA.Value, numericBoxB.Value, numericBoxC.Value, numericBoxAlpha.RadianValue, numericBoxBeta.RadianValue, numericBoxGamma.RadianValue);
            Application.DoEvents();
            skipCrystalChangedEvent = false;

            calculateStress();
        }
        /// <summary>
        /// 回折スポットおよび指数ラベルの描画
        /// </summary>
        /// <param name="graphics">描画対象のグラフィックオブジェクト</param>
        /// <param name="drawLabel">ラベルを描画するかどうか</param>
        /// <param name="outputOnlySpotInformation">このフラグがTrueの場合は、画面描画は行わずにspotの情報だけを返す</param>
        public List <SpotInformation> GetDiffractionSpots(Matrix3D rotation, IEnumerable <Vector3D> gVector, double coeff)
        {
            var    spotInformation = new List <SpotInformation>();
            double sigma           = spotRadiusOnDetector;

            //描画するスポットを決める
            foreach (Vector3D g in gVector)
            {
                Vector3DBase vec = rotation * g;
                if (vec.Z > -3 * excitationError)
                {
                    vec.Y = -vec.Y; vec.Z = -vec.Z;//ここでベクトルのY,Zの符号を反転
                    double L2 = vec.X * vec.X + vec.Y * vec.Y;
                    double dev = ewaldRadius - Math.Sqrt(L2 + (vec.Z + ewaldRadius) * (vec.Z + ewaldRadius)), dev2 = dev * dev;
                    if (dev2 < 9 * error2)
                    {
                        if (-sinTau * vec.Y + cosTau * (vec.Z + ewaldRadius) > 0)//(vec.X, vec.Y, vec.Z + EwaldRadius) と(0, -sinTau, cosTau) の内積が0より大きい)
                        {
                            //2020/02/03の変更対処済み
                            var    point = Geometriy.GetCrossPoint(0, sinTau, -cosTau, cameraLength2, new Vector3D(0, 0, 0), new Vector3D(vec.X, vec.Y, vec.Z + ewaldRadius));
                            PointD pt    = new PointD(point.X, point.Y * cosTau + point.Z * sinTau);

                            //if (IsDetectorArea(pt))
                            {
                                double intensity = g.RelativeIntensity / (sigma * sqrt2PI) * Math.Exp(-dev2 / error2 / 2);
                                if (intensity > 1E-3)
                                {
                                    spotInformation.Add(new SpotInformation(pt.X, pt.Y, intensity * coeff, sigma));
                                }
                            }
                        }
                    }
                }
            }
            return(spotInformation);
        }
示例#10
0
 public Vector3DBase(Vector3DBase v)
 {
     X = v.X; Y = v.Y; Z = v.Z;
 }
        private void execute(string filename = "")
        {
            var n            = 0;
            var initialRot   = new Matrix3D(FormDiffractionSimulator.formMain.Crystal.RotationMatrix);
            var originalAxes = new Matrix3D(OriginalCrystal.A_Axis * 10, OriginalCrystal.B_Axis * 10, OriginalCrystal.C_Axis * 10);

            //データ数を減らす
            var numMax = 4;
            var ptTemp = graphControl.Profile.Pt;
            var pt     = new List <PointD>();

            for (int i = 0; i < ptTemp.Count; i += numMax)
            {
                var num = Math.Min(numMax, ptTemp.Count - i);
                var p   = new PointD();
                for (int j = i; j < i + num; j++)
                {
                    p += ptTemp[j];
                }
                pt.Add(p / num);
            }

            //var pt = graphControl.Profile.Pt;

            var states = new List <(double depth, double pressure, double thickness)>();

            for (int i = 0; i < pt.Count - 1; i++)
            {
                states.Add(((pt[i].X + pt[i + 1].X) / 2, (pt[i].Y + pt[i + 1].Y) / 2, pt[i + 1].X - pt[i].X));
            }

            int count = checkBoxOmegaStep.Checked ? numericBoxOmegaTimes.ValueInteger : 1;

            toolStripProgressBar.Maximum = states.Count * count;
            toolStripProgressBar.Value   = 0;


            //無回転の時の圧縮面の法線ベクトル
            int cH = numericBoxShockedPlaneH.ValueInteger, cK = numericBoxShockedPlaneK.ValueInteger, cL = numericBoxShockedPlaneL.ValueInteger;
            var compressedPlane = (cH * OriginalCrystal.A_Star + cK * OriginalCrystal.B_Star + cL * OriginalCrystal.C_Star).Normarize();
            //無回転の時の圧縮面の法線ベクトルを(1,0,0)方向に向ける回転ベクトル
            var m1 = Matrix3D.Rot(Vector3DBase.VectorProduct(compressedPlane, new Vector3DBase(1, 0, 0)), Math.Acos(compressedPlane.X));

            //無回転時の圧縮面と平行なベクトル
            (int h, int k, int l, Vector3DBase vec)v1 = (-cK, cH, 0, (-cK * OriginalCrystal.A_Axis + cH * OriginalCrystal.B_Axis).Normarize());
            (int h, int k, int l, Vector3DBase vec)v2 = (0, -cL, cK, (-cL * OriginalCrystal.B_Axis + cK * OriginalCrystal.C_Axis).Normarize());
            if (v1.vec.Length2 < 0.1)
            {
                v1 = (-cL, 0, cH, (-cL * OriginalCrystal.A_Axis + cH * OriginalCrystal.C_Axis).Normarize());
            }
            if (v2.vec.Length2 < 0.1)
            {
                v2 = (-cL, 0, cH, (-cL * OriginalCrystal.A_Axis + cH * OriginalCrystal.C_Axis).Normarize());
            }

            //回転状態の圧縮面の法線ベクトル
            var shockDirection = initialRot * compressedPlane;

            //無回転の時のスリップ面の法線ベクトル
            var slipPlane = (numericBoxSlipPlaneH.Value * OriginalCrystal.A_Star + numericBoxSlipPlaneK.Value * OriginalCrystal.B_Star + numericBoxSlipPlaneL.Value * OriginalCrystal.C_Star).Normarize();
            //回転時のスリップ面と圧縮面の外積ベクトル
            var rotationAxis2019 = Vector3DBase.AngleBetVectors(slipPlane, compressedPlane) < Math.PI / 2 ?
                                   initialRot * Vector3DBase.VectorProduct(slipPlane, compressedPlane) :
                                   initialRot *Vector3DBase.VectorProduct(compressedPlane, slipPlane);

            //(0,0,1)方向をrotationAxis2019に向ける回転ベクトル
            var m2 = Matrix3D.Rot(Vector3DBase.VectorProduct(new Vector3DBase(0, 0, 1), rotationAxis2019), Math.Acos(rotationAxis2019.Z));

            //2018モデル。結晶は圧縮軸に垂直な方向を回転軸として回転すると仮定。その回転軸のリストを設定
            List <Vector3DBase> rotationAxes2018 = new List <Vector3DBase>();
            var div1 = numericBoxDivisionOfRotationAxis.ValueInteger;//回転軸を分割する数
            var initialNormalDirection = Math.Abs(shockDirection.Z) < 0.5 ? new Vector3DBase(shockDirection.Y, -shockDirection.X, 0) : new Vector3DBase(0, -shockDirection.Z, shockDirection.Y);

            for (int rot = 0; rot < div1; rot++)
            {
                rotationAxes2018.Add(Matrix3D.Rot(shockDirection, 2 * Math.PI * rot / div1) * initialNormalDirection);
            }

            var div2 = numericBoxDivisionOfRotationAngle.ValueInteger;//回転量を分割する数

            double front = graphControl.LineList[0].X, back = graphControl.LineList[1].X;
            double omegaC = numericBoxCompressedOmega.RadianValue, sigmaOmegaC = numericBoxCompressedOmegaSigma.RadianValue;
            double omegaR = numericBoxReleasedOmega.RadianValue, sigmaOmegaR = numericBoxReleasedOmegaSigma.RadianValue;
            double thetaC_A = numericBoxCompressedThetaA.RadianValue, thetaC_B = numericBoxCompressedThetaB.RadianValue;
            double thetaR_A = numericBoxReleasedThetaA.RadianValue, thetaR_B = numericBoxReleasedThetaB.RadianValue;
            var    absorption    = 1.0;
            var    compiledImage = new double[FormDiffractionSimulator.FormDiffractionSimulatorGeometry.DetectorWidth * FormDiffractionSimulator.FormDiffractionSimulatorGeometry.DetectorHeight];
            var    spots         = new List <SpotInformation>();
            long   beforeSec     = 0;

            //メインループ開始
            for (int i = 0; i < states.Count; i++)
            {
                FormDiffractionSimulator.SkipDrawing = FormDiffractionSimulator.formMain.SkipDrawing = checkBoxSkipDrawing.Checked;
                var rotationList = new List <(Matrix3D rot, double weight)>();

                if (states[i].depth < front)//Uncompressedの時
                {
                    rotationList.Add((Matrix3D.IdentityMatrix, 1));
                }
                else
                {
                    var time1 = states[i].depth < back ? (states[i].depth - front) / numericBoxUp.Value : (back - front) / numericBoxUp.Value;
                    var time2 = states[i].depth < back ? 0.0 : (states[i].depth - back) / numericBoxUr.Value;
                    var omega = omegaC * time1 + omegaR * time2;
                    var range = 2.0;

                    if (radioButton2018Model.Checked)//2018モデルの時
                    {
                        var sigmaOmega = Math.Sqrt(time1 * sigmaOmegaC * time1 * sigmaOmegaC + time2 * sigmaOmegaR * time2 * sigmaOmegaR);

                        double start = Math.Max(0, omega - range * sigmaOmega), end = omega + range * sigmaOmega, step = (end - start) / div2;
                        var    rotationAngles = new List <PointD>();
                        for (var speed = start; speed <= end + step / 2; speed += step)
                        {
                            rotationAngles.Add(new PointD(speed, Math.Exp(-(speed - omega) * (speed - omega) / 2 / sigmaOmega / sigmaOmega)));
                        }
                        foreach (var axis in rotationAxes2018)
                        {
                            foreach (var angle in rotationAngles)
                            {
                                rotationList.Add((Matrix3D.Rot(axis, angle.X), angle.Y));
                            }
                        }
                    }
                    else//2019モデルの時
                    {
                        double sigmaTheta = states[i].depth < back ? thetaC_A + thetaC_B * time1 : thetaC_A * time1 + thetaR_A + thetaR_B * time2, sigmaTheta2 = sigmaTheta * sigmaTheta;
                        double sigmaOmega = sigmaOmegaC * time1 + sigmaOmegaR * time2, sigmaOmega2 = sigmaOmega * sigmaOmega;

                        double stepTheta = (range * sigmaTheta) / ((int)Math.Sqrt(div1) + 1);
                        double startR = Math.Max(0, omega - range * sigmaOmega), endR = omega + range * sigmaOmega, stepR = (endR - startR) / div2;
                        double stepPhi = (2 * Math.PI) / ((int)Math.Sqrt(div1) + 1);
                        if (stepTheta == 0)
                        {
                            stepTheta = double.PositiveInfinity;
                        }
                        if (stepR == 0)
                        {
                            stepR = double.PositiveInfinity;
                        }

                        for (var theta = stepTheta / 2; theta <= range * sigmaTheta; theta += stepTheta)
                        {
                            for (var phi = 0.0; phi < 2 * Math.PI; phi += stepPhi)
                            {
                                for (var r = startR; r <= endR; r += stepR)
                                {
                                    var v = new Vector3DBase(Math.Sin(theta) * Math.Cos(phi), Math.Sin(theta) * Math.Sin(phi), Math.Cos(theta));
                                    rotationList.Add((Matrix3D.Rot(m2 * v, r), Math.Exp(-(r - omega) * (r - omega) / 2 / sigmaOmega2 - theta * theta / 2 / sigmaTheta2) * r * r * Math.Sin(theta)));
                                }
                            }
                        }
                    }
                }
                var sum = rotationList.Sum(r => r.weight);
                rotationList = rotationList.Select(r => (r.rot, r.weight / sum)).ToList();

                //ここから、圧縮による格子定数の変化
                Matrix3D newAxes = originalAxes;
                if (states[i].depth >= front)
                {
                    var volume = EOS.InverseThirdBirchMurnaghan(numericBoxEOS_K0.Value, numericBoxEOS_Kprime.Value, states[i].pressure * 100);
                    if ((states[i].depth < back && radioButtonCompressedUniaxial.Checked) || (states[i].depth >= back && radioButtonReleasedUniaxial.Checked))
                    {
                        newAxes = m1.Inverse() * new Matrix3D(1 / volume, 0, 0, 0, 1, 0, 0, 0, 1) * m1 * originalAxes;
                    }
                    else
                    {
                        newAxes = new Matrix3D(Math.Pow(1 / volume, 1.0 / 3.0), 0, 0, 0, Math.Pow(1 / volume, 1.0 / 3.0), 0, 0, 0, Math.Pow(1 / volume, 1.0 / 3.0)) * originalAxes;
                    }
                }
                var a = new Vector3DBase(newAxes.E11, newAxes.E21, newAxes.E31);
                var b = new Vector3DBase(newAxes.E12, newAxes.E22, newAxes.E32);
                var c = new Vector3DBase(newAxes.E13, newAxes.E23, newAxes.E33);
                FormDiffractionSimulator.SkipDrawing = FormDiffractionSimulator.formMain.SkipDrawing = true;
                CrystalControl.CellConstants         = (a.Length, b.Length, c.Length, Vector3DBase.AngleBetVectors(b, c), Vector3DBase.AngleBetVectors(c, a), Vector3DBase.AngleBetVectors(a, b));

                var corrRot = newAxes * new Matrix3D(CrystalControl.Crystal.A_Axis * 10, CrystalControl.Crystal.B_Axis * 10, CrystalControl.Crystal.C_Axis * 10).Inverse();

                // ここまで

                //候補となるgの絞り込み
                FormDiffractionSimulator.SetVector(true);
                List <Vector3D> gVector = new List <Vector3D>();
                foreach (var g in FormDiffractionSimulator.formMain.Crystal.VectorOfG.Where(g => g.Flag && g.RelativeIntensity > 1E-6))
                {
                    var vec = initialRot * corrRot * g;
                    vec.Y = -vec.Y; vec.Z = -vec.Z;                           //ここでベクトルのY,Zの符号を反転
                    if (-sinTau * vec.Y + cosTau * (vec.Z + ewaldRadius) > 0) //(vec.X, vec.Y, vec.Z + EwaldRadius) と(0, -sinTau, cosTau) の内積が0より大きい)
                    {
                        //2020/02/03の変更対処済み
                        var point = Geometriy.GetCrossPoint(0, -sinTau, cosTau, cameraLength2, new Vector3D(0, 0, 0), new Vector3D(vec.X, vec.Y, vec.Z + ewaldRadius));
                        if (IsDetectorArea(new PointD(point.X, point.Y * cosTau + point.Z * sinTau)))
                        {
                            gVector.Add(g);
                        }
                    }
                }//ここまで

                //ここから揺動のループ
                var effectiveThickness = states[i].thickness / (shockDirection * new Vector3DBase(0, 0, 1));
                absorption *= Math.Exp(-numericBoxMassAbsorption.Value * FormDiffractionSimulator.formMain.Crystal.Density * effectiveThickness / 10000);
                foreach (var(rot, weight) in rotationList)
                {
                    var temp = GetDiffractionSpots(rot * initialRot * corrRot, gVector, states[i].thickness * absorption * absorption * weight);//入射と出射で二回absorptionをかける
                    spots.AddRange(temp);
                    if (n++ % 100 == 0 && !checkBoxSkipDrawing.Checked)
                    {
                        FormDiffractionSimulator.formMain.SetRotation(rot * initialRot * corrRot);
                    }
                }

                // if (spots.Count > 100 || i == states.Count - 1)
                {
                    var image = getImageData(spots);
                    for (int j = 0; j < compiledImage.Length; j++)
                    {
                        compiledImage[j] += image[j];
                    }
                    spots.Clear();
                }

                toolStripProgressBar.Value++;
                toolStripStatusLabel1.Text =
                    "Time elapsed: " + (sw.ElapsedMilliseconds / 1000.0).ToString("f1") + " sec., per slice: " + (sw.ElapsedMilliseconds - beforeSec).ToString() + " msec., wait for more " +
                    (sw.ElapsedMilliseconds / 1000.0 / toolStripProgressBar.Value * (toolStripProgressBar.Maximum - toolStripProgressBar.Value)).ToString("f1") + " sec.";
                beforeSec = sw.ElapsedMilliseconds;
                Application.DoEvents();
            }//メインループここまで

            compiledImage = compiledImage.Select(intensity => intensity * 1E6).ToArray();
            PseudoBitmap pseud = new PseudoBitmap(compiledImage, FormDiffractionSimulator.FormDiffractionSimulatorGeometry.DetectorWidth);

            Tiff.Writer("temp.tif", compiledImage, 2, FormDiffractionSimulator.FormDiffractionSimulatorGeometry.DetectorWidth);
            FormDiffractionSimulator.FormDiffractionSimulatorGeometry.ReadImage("temp.tif");

            if (filename != "")
            {
                File.Copy("temp.tif", filename, true);
            }

            FormDiffractionSimulator.SkipDrawing = FormDiffractionSimulator.formMain.SkipDrawing = false;
        }
示例#12
0
        private Profile Mindex()
        {
            if (crystal == null || crystal.Crystallites == null)
            {
                return(null);
            }
            Profile p = new Profile();

            for (int i = 0; i <= 120; i++)
            {
                p.Pt.Add(new PointD(i, 0));
            }

            Random rn = new Random();

            Vector3DBase a = new Vector3DBase(1, 0, 0);
            Vector3DBase b = new Vector3DBase(0, 1, 0);
            Vector3DBase c = new Vector3DBase(0, 0, 1);

            Vector3DBase[]  v1          = divideVector(a, crystal.Symmetry);
            Vector3DBase[]  v2          = divideVector(b, crystal.Symmetry);
            Vector3DBase[]  v3          = divideVector(c, crystal.Symmetry);
            List <Matrix3D> symmetryMat = new List <Matrix3D>();

            for (int i = 0; i < v1.Length; i++)
            {
                if (new Matrix3D(v1[i], v2[i], v3[i]).Determinant() > 0)
                {
                    symmetryMat.Add(new Matrix3D(v1[i], v2[i], v3[i]));
                }
            }

            Parallel.For(0, crystal.Crystallites.TotalCrystalline, i =>
            {
                Matrix3D m1, m2;
                lock (lockObject)
                {
                    m1 = crystal.Crystallites.Rotations[rn.Next(crystal.Crystallites.TotalCrystalline)];
                    m2 = crystal.Crystallites.Rotations[rn.Next(crystal.Crystallites.TotalCrystalline)];
                }
                double dia = double.MinValue;
                Matrix3D r = m1.Transpose() * m2;
                for (int j = 0; j < symmetryMat.Count; j++)
                {
                    Matrix3D r2 = r * symmetryMat[j];
                    dia         = Math.Max((r2.E11 + r2.E22 + r2.E33 - 1) / 2, dia);
                    dia         = Math.Max((-r2.E11 - r2.E22 + r2.E33 - 1) / 2, dia);
                    dia         = Math.Max((r2.E11 - r2.E22 - r2.E33 - 1) / 2, dia);
                    dia         = Math.Max((-r2.E11 + r2.E22 - r2.E33 - 1) / 2, dia);
                }
                if (dia >= -1 && dia <= 1)
                {
                    int angle = (int)Math.Round(Math.Acos(dia) / Math.PI * 180, MidpointRounding.AwayFromZero);
                    if (angle >= 0 && angle <= 120)
                    {
                        p.Pt[angle] += new PointD(0, 1);
                    }
                }
            });
            for (int i = 0; i <= 120; i++)
            {
                p.Pt[i] = new PointD(p.Pt[i].X, p.Pt[i].Y / crystal.Crystallites.TotalCrystalline);
            }

            return(p);
        }
示例#13
0
        private Vector3DBase[] divideVector(Vector3DBase baseVec, Symmetry sym)
        {
            List <Vector3DBase> vec = new List <Vector3DBase>();
            double x = baseVec.X, y = baseVec.Y, z = baseVec.Z;
            double sqrt3 = Math.Sqrt(3);

            switch (sym.LaueGroupNumber)
            {
            case 0:    //unknown
                vec.Add(baseVec);
                break;

            case 1:    //-1
                vec.Add(new Vector3DBase(x, y, z));
                vec.Add(new Vector3DBase(-x, -y, -z));
                break;

            case 2:    // 2/m
                switch (sym.MainAxis)
                {
                case "a":
                    vec.Add(new Vector3DBase(x, y, z));
                    vec.Add(new Vector3DBase(-x, -y, -z));
                    vec.Add(new Vector3DBase(-x, y, z));
                    vec.Add(new Vector3DBase(x, -y, -z));
                    break;

                case "b":
                    vec.Add(new Vector3DBase(x, y, z));
                    vec.Add(new Vector3DBase(-x, -y, -z));
                    vec.Add(new Vector3DBase(x, -y, z));
                    vec.Add(new Vector3DBase(-x, y, -z));
                    break;

                case "c":
                    vec.Add(new Vector3DBase(x, y, z));
                    vec.Add(new Vector3DBase(-x, -y, -z));
                    vec.Add(new Vector3DBase(x, y, -z));
                    vec.Add(new Vector3DBase(-x, -y, z));
                    break;
                }
                break;

            case 3:    // mmm
                vec.Add(new Vector3DBase(x, y, z));
                vec.Add(new Vector3DBase(-x, -y, -z));
                vec.Add(new Vector3DBase(-x, y, z));
                vec.Add(new Vector3DBase(x, -y, -z));
                vec.Add(new Vector3DBase(x, -y, z));
                vec.Add(new Vector3DBase(-x, y, -z));
                vec.Add(new Vector3DBase(x, y, -z));
                vec.Add(new Vector3DBase(-x, -y, z));
                break;

            case 4:     //4/m
                vec.Add(new Vector3DBase(+x, +y, +z));
                vec.Add(new Vector3DBase(-x, -y, +z));
                vec.Add(new Vector3DBase(-y, +x, +z));
                vec.Add(new Vector3DBase(+y, -x, +z));

                vec.Add(new Vector3DBase(+x, +y, -z));
                vec.Add(new Vector3DBase(-x, -y, -z));
                vec.Add(new Vector3DBase(-y, +x, -z));
                vec.Add(new Vector3DBase(+y, -x, -z));
                break;

            case 5:     //4/mmm

                vec.Add(new Vector3DBase(+x, +y, +z));
                vec.Add(new Vector3DBase(-x, -y, +z));
                vec.Add(new Vector3DBase(-y, +x, +z));
                vec.Add(new Vector3DBase(+y, -x, +z));

                vec.Add(new Vector3DBase(+x, -y, +z));
                vec.Add(new Vector3DBase(-x, +y, +z));
                vec.Add(new Vector3DBase(+y, +x, +z));
                vec.Add(new Vector3DBase(-y, -x, +z));

                vec.Add(new Vector3DBase(+x, +y, -z));
                vec.Add(new Vector3DBase(-x, -y, -z));
                vec.Add(new Vector3DBase(-y, +x, -z));
                vec.Add(new Vector3DBase(+y, -x, -z));

                vec.Add(new Vector3DBase(+x, -y, -z));
                vec.Add(new Vector3DBase(-x, +y, -z));
                vec.Add(new Vector3DBase(+y, +x, -z));
                vec.Add(new Vector3DBase(-y, -x, -z));
                break;

            case 6:                                //-3
                if (sym.SpaceGroupHMsubStr != "R") //Hexaセルの場合
                {
                    vec.Add(new Vector3DBase(+x, +y, +z));
                    vec.Add(new Vector3DBase(+(-x - sqrt3 * y) / 2, +(+sqrt3 * x - y) / 2, +z));
                    vec.Add(new Vector3DBase(+(-x + sqrt3 * y) / 2, +(-sqrt3 * x - y) / 2, +z));

                    vec.Add(-vec[0]);
                    vec.Add(-vec[1]);
                    vec.Add(-vec[2]);
                }
                else    //Rhomboセルの場合 未完成
                {
                }
                break;

            case 7:                                //-3m 未完成
                if (sym.SpaceGroupHMsubStr != "R") //Hexaセルの場合
                {
                    vec.Add(new Vector3DBase(+x, +y, +z));
                    vec.Add(new Vector3DBase(+(-x - sqrt3 * y) / 2, +(+sqrt3 * x - y) / 2, +z));
                    vec.Add(new Vector3DBase(+(-x + sqrt3 * y) / 2, +(-sqrt3 * x - y) / 2, +z));

                    vec.Add(-vec[0]);
                    vec.Add(-vec[1]);
                    vec.Add(-vec[2]);
                    if (sym.SpaceGroupHallStr.Contains("\""))    //3m1の場合
                    {
                        vec.Add(new Vector3DBase(-x, +y, +z));
                        vec.Add(new Vector3DBase(-(-x - sqrt3 * y) / 2, +(+sqrt3 * x - y) / 2, +z));
                        vec.Add(new Vector3DBase(-(-x + sqrt3 * y) / 2, +(-sqrt3 * x - y) / 2, +z));
                    }
                    else
                    {
                        vec.Add(new Vector3DBase(+x, -y, +z));
                        vec.Add(new Vector3DBase(+(-x - sqrt3 * y) / 2, -(+sqrt3 * x - y) / 2, +z));
                        vec.Add(new Vector3DBase(+(-x + sqrt3 * y) / 2, -(-sqrt3 * x - y) / 2, +z));
                    }
                    vec.Add(-vec[6]);
                    vec.Add(-vec[7]);
                    vec.Add(-vec[8]);
                }
                else     //Rhomboセルの場合 未完成
                {
                }
                break;

            case 8:    //6/m
                vec.Add(new Vector3DBase(+x, +y, +z));
                vec.Add(new Vector3DBase(+(-x - sqrt3 * y) / 2, +(+sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(+(-x + sqrt3 * y) / 2, +(-sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(-x, -y, +z));
                vec.Add(new Vector3DBase(-(-x - sqrt3 * y) / 2, -(+sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(-(-x + sqrt3 * y) / 2, -(-sqrt3 * x - y) / 2, +z));

                vec.Add(-vec[0]);
                vec.Add(-vec[1]);
                vec.Add(-vec[2]);
                vec.Add(-vec[3]);
                vec.Add(-vec[4]);
                vec.Add(-vec[5]);
                break;

            case 9:    //6/mmm
                vec.Add(new Vector3DBase(+x, +y, +z));
                vec.Add(new Vector3DBase(+(-x - sqrt3 * y) / 2, +(+sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(+(-x + sqrt3 * y) / 2, +(-sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(-x, -y, +z));
                vec.Add(new Vector3DBase(-(-x - sqrt3 * y) / 2, -(+sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(-(-x + sqrt3 * y) / 2, -(-sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(-x, +y, +z));
                vec.Add(new Vector3DBase(-(-x - sqrt3 * y) / 2, +(+sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(-(-x + sqrt3 * y) / 2, +(-sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(+x, -y, +z));
                vec.Add(new Vector3DBase(+(-x - sqrt3 * y) / 2, -(+sqrt3 * x - y) / 2, +z));
                vec.Add(new Vector3DBase(+(-x + sqrt3 * y) / 2, -(-sqrt3 * x - y) / 2, +z));

                vec.Add(-vec[0]);
                vec.Add(-vec[1]);
                vec.Add(-vec[2]);
                vec.Add(-vec[3]);
                vec.Add(-vec[4]);
                vec.Add(-vec[5]);
                vec.Add(-vec[6]);
                vec.Add(-vec[7]);
                vec.Add(-vec[8]);
                vec.Add(-vec[9]);
                vec.Add(-vec[10]);
                vec.Add(-vec[11]);
                break;

            case 10:    //m3
                vec.Add(new Vector3DBase(+x, +y, +z));
                vec.Add(new Vector3DBase(-x, -y, +z));
                vec.Add(new Vector3DBase(-x, +y, -z));
                vec.Add(new Vector3DBase(+x, -y, -z));

                vec.Add(new Vector3DBase(+z, +x, +y));
                vec.Add(new Vector3DBase(-z, -x, +y));
                vec.Add(new Vector3DBase(-z, +x, -y));
                vec.Add(new Vector3DBase(+z, -x, -y));

                vec.Add(new Vector3DBase(+y, +z, +x));
                vec.Add(new Vector3DBase(-y, -z, +x));
                vec.Add(new Vector3DBase(-y, +z, -x));
                vec.Add(new Vector3DBase(+y, -z, -x));

                vec.Add(new Vector3DBase(-x, -y, -z));
                vec.Add(new Vector3DBase(+x, +y, -z));
                vec.Add(new Vector3DBase(+x, -y, +z));
                vec.Add(new Vector3DBase(-x, +y, +z));

                vec.Add(new Vector3DBase(-z, -x, -y));
                vec.Add(new Vector3DBase(+z, +x, -y));
                vec.Add(new Vector3DBase(+z, -x, +y));
                vec.Add(new Vector3DBase(-z, +x, +y));

                vec.Add(new Vector3DBase(-y, -z, -x));
                vec.Add(new Vector3DBase(+y, +z, -x));
                vec.Add(new Vector3DBase(+y, -z, +x));
                vec.Add(new Vector3DBase(-y, +z, +x));
                break;

            case 11:    //m3m
                vec.Add(new Vector3DBase(+x, +y, +z));
                vec.Add(new Vector3DBase(-x, -y, +z));
                vec.Add(new Vector3DBase(-x, +y, -z));
                vec.Add(new Vector3DBase(+x, -y, -z));

                vec.Add(new Vector3DBase(+z, +x, +y));
                vec.Add(new Vector3DBase(-z, -x, +y));
                vec.Add(new Vector3DBase(-z, +x, -y));
                vec.Add(new Vector3DBase(+z, -x, -y));

                vec.Add(new Vector3DBase(+y, +z, +x));
                vec.Add(new Vector3DBase(-y, -z, +x));
                vec.Add(new Vector3DBase(-y, +z, -x));
                vec.Add(new Vector3DBase(+y, -z, -x));

                vec.Add(new Vector3DBase(-x, -y, -z));
                vec.Add(new Vector3DBase(+x, +y, -z));
                vec.Add(new Vector3DBase(+x, -y, +z));
                vec.Add(new Vector3DBase(-x, +y, +z));

                vec.Add(new Vector3DBase(-z, -x, -y));
                vec.Add(new Vector3DBase(+z, +x, -y));
                vec.Add(new Vector3DBase(+z, -x, +y));
                vec.Add(new Vector3DBase(-z, +x, +y));

                vec.Add(new Vector3DBase(-y, -z, -x));
                vec.Add(new Vector3DBase(+y, +z, -x));
                vec.Add(new Vector3DBase(+y, -z, +x));
                vec.Add(new Vector3DBase(-y, +z, +x));

                vec.Add(new Vector3DBase(+y, +x, +z));
                vec.Add(new Vector3DBase(-y, -x, +z));
                vec.Add(new Vector3DBase(-y, +x, -z));
                vec.Add(new Vector3DBase(+y, -x, -z));

                vec.Add(new Vector3DBase(+z, +y, +x));
                vec.Add(new Vector3DBase(-z, -y, +x));
                vec.Add(new Vector3DBase(-z, +y, -x));
                vec.Add(new Vector3DBase(+z, -y, -x));

                vec.Add(new Vector3DBase(+x, +z, +y));
                vec.Add(new Vector3DBase(-x, -z, +y));
                vec.Add(new Vector3DBase(-x, +z, -y));
                vec.Add(new Vector3DBase(+x, -z, -y));

                vec.Add(new Vector3DBase(-y, -x, -z));
                vec.Add(new Vector3DBase(+y, +x, -z));
                vec.Add(new Vector3DBase(+y, -x, +z));
                vec.Add(new Vector3DBase(-y, +x, +z));

                vec.Add(new Vector3DBase(-z, -y, -x));
                vec.Add(new Vector3DBase(+z, +y, -x));
                vec.Add(new Vector3DBase(+z, -y, +x));
                vec.Add(new Vector3DBase(-z, +y, +x));

                vec.Add(new Vector3DBase(-x, -z, -y));
                vec.Add(new Vector3DBase(+x, +z, -y));
                vec.Add(new Vector3DBase(+x, -z, +y));
                vec.Add(new Vector3DBase(-x, +z, +y));
                break;
            }
            return(vec.ToArray());
        }
示例#14
0
        public double[][] generateDensityArrayNormal(double angleResolution)
        {
            if (crystal == null || crystal.Crystallites == null)
            {
                return(null);
            }

            int x = (int)numericUpDown1.Value, y = (int)numericUpDown2.Value, z = (int)numericUpDown3.Value;

            //double[][] pixelsを初期化
            int radialDivision = (int)(Math.PI / angleResolution / 2);

            double[][] pixels  = new double[radialDivision][];
            for (int i = 0; i < radialDivision; i++)
            {
                double circumference  = (i + 0.5) / radialDivision * Math.PI * 2;
                int    sectorDivision = (int)Math.Round(circumference * radialDivision, MidpointRounding.ToEven);
                pixels[i] = new double[sectorDivision];
                for (int j = 0; j < pixels[i].Length; j++)
                {
                    pixels[i][j] = 0;
                }
            }

            //前回の条件と同じとき
            if (index != null && index.Length == Crystal.Crystallites.Rotations.Length)
            {
                if (x == justBeforeX && y == justBeforeY && z == justBeforeZ && angleResolution == justBeforeResolution && crystal.Crystallites.Rotations.Length == justBeforeCrystallineNumber &&
                    justBeforePoleFigureMode == radioButtonPoleFigure.Checked && justBeforePlanesMode == radioButtonPlanes.Checked)
                {
                    for (int i = 0; i < crystal.Crystallites.Rotations.Length; i++)
                    {
                        foreach (int p in index[i])
                        {
                            pixels[p / ushort.MaxValue][p % ushort.MaxValue] += crystal.Crystallites.Density[i] * crystal.Crystallites.SolidAngle[i];
                        }
                    }
                    for (int radial = 0; radial < pixels.Length; radial++)
                    {
                        double area = (1.0 + 2 * radial) / pixels[radial].Length;
                        for (int sector = 0; sector < pixels[radial].Length; sector++)
                        {
                            pixels[radial][sector] /= 10000 * area;
                        }
                    }
                    return(pixels);
                }
            }
            else
            {
                index = new uint[Crystal.Crystallites.Rotations.Length][];
            }
            justBeforeX          = x; justBeforeY = y; justBeforeZ = z; justBeforeCrystallineNumber = crystal.Crystallites.Rotations.Length;
            justBeforeResolution = angleResolution; justBeforePoleFigureMode = radioButtonPoleFigure.Checked; justBeforePlanesMode = radioButtonPlanes.Checked;

            Symmetry sym = crystal.Symmetry;

            Vector3DBase[] srcVector;

            //Normal
            if (radioButtonPoleFigure.Checked)
            {
                if (radioButtonPlanes.Checked)
                {//計算する面指数と等価な指数を算出
                    var indices = SymmetryStatic.GenerateEquivalentPlanes(x, y, z, sym);
                    srcVector = new Vector3DBase[indices.Length];
                    for (int k = 0; k < indices.Length; k++)
                    {
                        srcVector[k] = crystal.A_Star * indices[k].H + crystal.B_Star * indices[k].K + crystal.C_Star * indices[k].L;
                        if (srcVector[k].Length2 > 0)
                        {
                            srcVector[k] /= srcVector[k].Length;
                        }
                    }
                }
                else
                {//計算する軸指数と等価な指数を算出
                    var indices = SymmetryStatic.GenerateEquivalentAxes(x, y, z, sym);
                    //indices = new AxisIndex[] { new AxisIndex(0, 0, 1) };
                    srcVector = new Vector3DBase[indices.Length];
                    for (int k = 0; k < indices.Length; k++)
                    {
                        srcVector[k] = crystal.A_Axis * indices[k].U + crystal.B_Axis * indices[k].V + crystal.C_Axis * indices[k].W;
                        if (srcVector[k].Length2 > 0)
                        {
                            srcVector[k] /= srcVector[k].Length;
                        }
                    }
                }
            }
            //Inverse
            else
            {
                srcVector = new Vector3DBase[] { new Vector3DBase(x, y, z) };
                if (srcVector[0].Length2 > 0)
                {
                    srcVector[0] /= srcVector[0].Length;
                }
            }

            List <uint> tempIndex = new List <uint>();

            for (int i = 0; i < crystal.Crystallites.Rotations.Length; i++)
            {
                tempIndex.Clear();
                Matrix3D rot = crystal.Crystallites.Rotations[i] * Crystallite.TiltMatrix;

                Vector3DBase[] vectors = new Vector3DBase[srcVector.Length];
                if (radioButtonPoleFigure.Checked)//PoleFigureのとき
                {
                    for (int j = 0; j < vectors.Length; j++)
                    {
                        vectors[j] = rot * srcVector[j];
                    }
                }
                else//InversePoleFigureのとき
                {
                    vectors = divideVector(rot.Transpose() * srcVector[0], sym);
                }

                foreach (Vector3DBase v in vectors)
                {
                    if (v.Z > 0)
                    {
                        PointD pt     = new PointD(v.X / Math.Sqrt(1 + v.Z), v.Y / Math.Sqrt(1 + v.Z));
                        int    radial = (int)Math.Round(pt.Length * radialDivision - 0.5, MidpointRounding.ToEven);
                        if (radial < pixels.Length)
                        {
                            int sector = (int)Math.Round(Math.Atan2(pt.Y, pt.X) / 2 / Math.PI * pixels[radial].Length, MidpointRounding.ToEven);
                            if (sector < 0)
                            {
                                sector += pixels[radial].Length;
                            }
                            //lock (lockObject)
                            pixels[radial][sector] += crystal.Crystallites.Density[i] * crystal.Crystallites.SolidAngle[i];
                            tempIndex.Add((uint)(radial * ushort.MaxValue + sector));
                        }
                    }
                }
                index[i] = tempIndex.ToArray();
            }

            //最後に面積を計算して規格化
            for (int radial = 0; radial < pixels.Length; radial++)
            {
                double area = (1.0 + 2 * radial) / pixels[radial].Length;
                for (int sector = 0; sector < pixels[radial].Length; sector++)
                {
                    pixels[radial][sector] /= 10000 * area;
                }
            }
            return(pixels);
        }
示例#15
0
        /// <summary>
        /// v1をなるべくv2に近づけるような回転行列を求める。戻り値は、残差の二乗和を個数で割ったもの
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static double GetRotationMatrix(Vector3DBase[] v1, Vector3DBase[] v2, ref Matrix3D result, Matrix3D initialRotation = null)
        {
            if (initialRotation == null)
            {
                //初期回転行列を求める
                initialRotation = new Matrix3D();
            }
            var euler = Euler.GetEulerAngle(initialRotation);

            int length = v1.Length;

            double   phi = euler.Phi, theta = euler.Theta, psi = euler.Psi;
            double   phi_New, theta_New, psi_New;
            Matrix3D rot = initialRotation, rot_New;

            Vector3DBase[,] diff = new Vector3DBase[3, length];
            var Alpha = new DMat(3, 3);
            var Beta  = new DMat(3, 1);

            Vector3DBase[] ResidualCurrent = new Vector3DBase[length];
            Vector3DBase[] ResidualNew = new Vector3DBase[length];
            double         ResidualSquareCurrent, ResidualSquareNew = 0;
            int            count = 0;

            //現在の残差を計算
            ResidualSquareCurrent = 0;
            for (int i = 0; i < length; i++)
            {
                ResidualCurrent[i]     = rot * v1[i] - v2[i];
                ResidualSquareCurrent += ResidualCurrent[i] * ResidualCurrent[i];
            }

            double lambda = 1;

            while (lambda < 1000000000 && count < 3000)//lambdaが大きくなりすぎた時か、試行回数が一定以上になった時、止める
            {
                count++;
                double cosPhi = Math.Cos(phi), sinPhi = Math.Sin(phi), cosTheta = Math.Cos(theta), sinTheta = Math.Sin(theta), cosPsi = Math.Cos(psi), sinPsi = Math.Sin(psi);
                for (int i = 0; i < length; i++)//偏微分を作る 「回転行列の偏微分」というMathematicaファイルを参照
                {
                    //∂F/∂phi
                    diff[0, i] = new Vector3DBase(
                        v1[i].X * (-cosPsi * sinPhi - cosPhi * cosTheta * sinPsi) + v1[i].Y * (cosPhi * cosPsi * cosTheta - sinPhi * sinPsi) + v1[i].Z * cosPhi * sinTheta,
                        v1[i].Y * (-cosPsi * cosTheta * sinPhi - cosPhi * sinPsi) + v1[i].X * (-cosPhi * cosPsi + cosTheta * sinPhi * sinPsi) - v1[i].Z * sinPhi * sinTheta,
                        0
                        );
                    //∂F/∂theta
                    diff[1, i] = new Vector3DBase(
                        v1[i].Z * cosTheta * sinPhi - v1[i].Y * cosPsi * sinPhi * sinTheta + v1[i].X * sinPhi * sinPsi * sinTheta,
                        v1[i].Z * cosPhi * cosTheta - v1[i].Y * cosPhi * cosPsi * sinTheta + v1[i].X * cosPhi * sinPsi * sinTheta,
                        -v1[i].Y * cosPsi * cosTheta + v1[i].X * cosTheta * sinPsi - v1[i].Z * sinTheta
                        );
                    //∂F/∂psi
                    diff[2, i] = new Vector3DBase(
                        v1[i].X * (-cosPsi * cosTheta * sinPhi - cosPhi * sinPsi) + v1[i].Y * (cosPhi * cosPsi - cosTheta * sinPhi * sinPsi),
                        v1[i].Y * (-cosPsi * sinPhi - cosPhi * cosTheta * sinPsi) + v1[i].X * (-cosPhi * cosPsi * cosTheta + sinPhi * sinPsi),
                        v1[i].X * cosPsi * sinTheta + v1[i].Y * sinPsi * sinTheta
                        );
                }

                //行列Alpha, Betaを作る
                for (int k = 0; k < 3; k++)
                {
                    for (int l = 0; l < 3; l++)
                    {
                        Alpha[k, l] = 0;
                        for (int i = 0; i < length; i++)
                        {
                            Alpha[k, l] += diff[k, i] * diff[l, i];
                        }

                        if (k == l)
                        {
                            Alpha[k, l] *= (1 + lambda);
                        }
                    }
                    Beta[k, 0] = 0;
                    for (int i = 0; i < length; i++)
                    {
                        Beta[k, 0] += ResidualCurrent[i] * diff[k, i];
                    }
                }

                if (!Alpha.TryInverse(out Matrix alphaInv))
                {
                    return(-1);
                }

                var delta = alphaInv * Beta;

                phi_New   = phi - delta[0, 0];
                theta_New = theta - delta[1, 0];
                psi_New   = psi + delta[2, 0];

                //あたらしいパラメータでの残差の二乗和を計算
                ResidualSquareNew = 0;
                rot_New           = Euler.SetEulerAngle(phi_New, theta_New, psi_New);
                for (int i = 0; i < length; i++)
                {
                    ResidualNew[i]     = rot_New * v1[i] - v2[i];
                    ResidualSquareNew += ResidualNew[i] * ResidualNew[i];
                }

                if (ResidualSquareCurrent > ResidualSquareNew)     //新旧の残差の二乗和を比較
                {                                                  //改善したとき
                    if ((ResidualSquareCurrent - ResidualSquareNew) / ResidualSquareCurrent > 0.0000000001 || count < 15 || lambda > 1)
                    {                                              //改善率が0.0000000001 以上 (まだまだ改善の余地がある)、あるいはcountが15以下 (回数が少ない)、あるいはlambdaが1より大きいとき (まだまだ改善の余地がある)
                        ResidualSquareCurrent = ResidualSquareNew; //残差の二乗和を書き換える
                        lambda *= 0.4;                             //lambdaを小さくする
                        for (int i = 0; i < length; i++)
                        {
                            ResidualCurrent[i] = ResidualNew[i];         //残差行列を書き換える
                        }
                        phi = phi_New; theta = theta_New; psi = psi_New; //新旧パラメータを書き換える
                    }
                    else
                    {
                        break;
                    }
                }

                else//改善しなかったとき
                {
                    lambda *= 2.5;//lambdaを大きくする
                }
            }

            return(ResidualSquareCurrent);
        }