晶体学米勒指数从列表中删除等效指数

时间:2013-03-07 18:35:25

标签: c# list filter

我正在用米勒指数(hkl)做一些晶体学计算,即这里存储在int[]数组中的整数三元组(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#删除/过滤所有等价物,即一组[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]

如果您需要更多信息,请告诉我们。

2 个答案:

答案 0 :(得分:1)

为您的索引定义“规范”表单,例如:

  • [h]是最大幅度指数,符号+1;
  • [k]是第二大量级指数;
  • [l]是剩余索引
  • 已经考虑了所有常见因素

现在将所有索引转换为规范形式,如果它们与已找到的索引重复,则将其删除。

此表格还允许您对米勒指数进行排序,加快搜索等等。

我有物理学位;我知道米勒的指数不会太大。 ; - )

这是一个“规范化”程序。它使用蛮力进行分解,但我认为这对于问题域是足够的;如果性能是一个可以在以后解决的问题。

2013-03-09:更新为使用预先计算的素数表&lt; = 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);
    }
  }

答案 1 :(得分:0)

我只想补充Pieter的答案。取消常见因素是不正确的。 (200)反射与(100)反射不同。所以使用素数的所有努力都是不必要的。

如果你有立方对称性,那么生成规范形式的最简单方法是通过取绝对值然后对三个数字进行排序来使所有指数为正。因此[0,-2,-1] - &gt; [0,2,1] - &gt; [0,1,2]