0

int[]ミラー インデックス (hkl)、つまりここに配列に格納された整数のトリプル (hkl) を使用して結晶学的計算を少し行っています。私はC#を使用しています。最大の hmax、kmax、および lmax を設定すると、これまでのところ、すべての等価物を含むリストを埋めることができました。

List<int[]> milind = new List<int[]>;
int[] mindex = new int[3];
for ( int h = -hmax ; h <= hmax; h++)
{
    mindex[0] = h;
    for ( int k = -kmax ; k <= kmax; k++)
    {
        mindex[1] = k;
        for ( int l = -lmax ; l <= lmax; l++)
        {
             mindex[2] = l;
             milind.Add(mindex);
        }
    }
} 

質問: C# を使用して、すべての等価物、つまり 1 つのセット [h,k,l] の順列を削除/フィルタリングするにはどうすればよいですか?

例: を持っているとしましょう。[h=1,k=0,l=0]削除/フィルタリングしたい: [0,1,0][0,0,1][-1,0,0]、 ... など。リストにのみを[0,-1,0]残し[0,0,-1]ます。[0,0,1]

さらに情報が必要な場合は、お知らせください。

4

2 に答える 2

1

次のように、インデックスの「正規」形式を定義します。

  • [h] は最大マグニチュード インデックスで、符号は +1 です。
  • [k] は 2 番目に大きいマグニチュード インデックスです。
  • [l] は残りのインデックス
  • すべての共通要因が除外されました

次に、すべてのインデックスを正規の形式に変換し、既に見つかったものと重複している場合は削除します。

このフォームでは、Miller インデックスの並べ替え、検索の高速化なども可能です。

私は物理学の学位を持っています。ミラー指数が大きくなりすぎないことはわかっていました。;-)

これが「正規化」手順です。因数分解に総当たりを使用しますが、問題の領域にはそれで十分だと思います。パフォーマンスが後で対処できる問題である場合。

2013-03-09: 事前に計算された素数の表 <= 31 を使用するように更新

  public struct MillerIndex {
    public int H { get; private set; }
    public int K { get; private set; }
    public int L { get; private set; }

    public MillerIndex( int h, int k, int l) : this() {
      H = h;  K = k;  L = l;
    }
  }

  public static class MillereHandler {

    static IList<int> Primes = new List<int> {2,3,5,7,11,13,17,19,23,29,31};

    public static MillerIndex GetCanonical(MillerIndex mi) {
      int h, k, l, sign;
      if (Math.Abs(mi.H) > Math.Abs(mi.K) && Math.Abs(mi.H) >  Math.Abs(mi.L) ) {
        sign = Math.Sign(mi.H);
        h = mi.H;
        k = Math.Abs(mi.K) > Math.Abs(mi.L) ? mi.K : mi.L;
        l = Math.Abs(mi.K) > Math.Abs(mi.L) ? mi.L : mi.K;
      } else if (Math.Abs(mi.K) > Math.Abs(mi.H) && Math.Abs(mi.K) >  Math.Abs(mi.L) ) {
        sign = Math.Sign(mi.K);
        h = mi.K;
        k = Math.Abs(mi.H) > Math.Abs(mi.L) ? mi.H : mi.L;
        l = Math.Abs(mi.H) > Math.Abs(mi.L) ? mi.L : mi.H;
      } else {
        sign = Math.Sign(mi.L);
        h = mi.L;
        k = Math.Abs(mi.H) > Math.Abs(mi.K) ? mi.H : mi.K;
        l = Math.Abs(mi.H) > Math.Abs(mi.K) ? mi.K : mi.H;
      }

      h *= sign;  k *= sign;  l *= sign;

      foreach (var i in Primes.Where(i=> (i^2) < l) ) {
        while ( (h/i)*i == h  &&  (k/i)*i == k &&  (l/i)*i == l ) {
          h /= h/i;  k /= k/i;  l /= l/i;
        }
      }

      return new MillerIndex(h, k, l);
    }
  }
于 2013-03-07T18:51:45.070 に答える