0

宇宙論的シミュレーションから特定の量を計算するための Python コードをいくつか書きました。これは、粒子がサイズ 8,000^3 のボックス内に含まれているかどうかを確認することによって行われます。原点から開始し、ボックス内に含まれるすべての粒子が見つかったときにボックスを進めます。全体で約 200 万個のパーティクルを数えており、シミュレーション ボリュームの合計サイズは 150,000^3 であるため、これには長い時間がかかります。

以下にコードを投稿します。改善方法について何か提案はありますか?

前もって感謝します。

from __future__ import division
import numpy as np




def check_range(pos, i, j, k):
    a = 0
    if i <= pos[2] < i+8000:
            if j <= pos[3] < j+8000:
                    if k <= pos[4] < k+8000:
                            a = 1
    return a


def sigma8(data):

    N = []

    to_do = data

    print 'Counting number of particles per cell...'

    for k in range(0,150001,8000):
            for j in range(0,150001,8000):
                    for i in range(0,150001,8000):
                            temp = []
                            n = []
                            for count in range(len(to_do)):
                                    n.append(check_range(to_do[count],i,j,k))
                                    to_do[count][1] = n[count]
                                    if to_do[count][1] == 0:
                                           temp.append(to_do[count])
                                    #Only particles that have not been found are
                                    # searched for again

                            to_do = temp
                            N.append(sum(n))
                    print 'Next row'
            print 'Next slice, %i still to find' % len(to_do)

    print 'Calculating sigma8...'

    if not sum(N) == len(data):
            return 'Error!\nN measured = {0}, total N = {1}'.format(sum(N), len(data))

    else:
            return 'sigma8 = %.4f, variance = %.4f, mean = %.4f' % (np.sqrt(sum((N-np.mean(N))**2)/len(N))/np.mean(N), np.var(N),np.mean(N))
4

1 に答える 1

2

いくつかのコードを投稿しようとしますが、私の一般的な考え方は次のとおりです__init__。. 各ボックスには一意の名前を付ける必要があります。これは、左下隅の座標 (またはボックスの位置を特定するために使用する名前) にすることができます。

パーティクルごとに Particle クラスの新しいインスタンスを取得し、(コレクション モジュールから) Counter を使用します。

粒子クラスは次のようになります。

# static consts - outside so that every instance of Particle doesn't take them along
# for the ride...
MAX_X = 150,000
X_STEP = 8000
# etc.

class Particle(object):

    def __init__(self, data):
        self.x = data[xvalue]
        self.y = data[yvalue]
        self.z = data[zvalue]
        self.compute_box_label()

    def compute_box_label(self):
        import math

        x_label = math.floor(self.x / X_STEP)
        y_label = math.floor(self.y / Y_STEP)
        z_label = math.floor(self.z / Z_STEP) 
        self.box_label = str(x_label) + '-' + str(y_label) + '-' + str(z_label)

とにかく、あなたのsigma8関数は次のようになると思います:

def sigma8(data):
    import collections as col

    particles = [Particle(x) for x in data]
    boxes = col.Counter([x.box_label for x in particles])
    counts = boxes.most_common()

    #some other stuff

countsボックスのラベルをそのボックス内の粒子の数にマップするタプルのリストになります。(ここでは、粒子を区別できないものとして扱っています。)

リスト内包表記を使用すると、ループを使用するよりもはるかに高速です---その理由は、基本的に基になる C に依存しているためだと思いますが、私は質問する人ではありません。カウンターも(おそらく)高度に最適化されています。

注: このコードはテストされていないため、ここでカット アンド ペースト アンド ホープ イット ワークスの方法を試してはいけません。

于 2013-02-24T22:45:19.857 に答える