Simulation numérique en percoration Python-invasive

introduction

Python peut vraiment tout faire, donc je pense qu'il existe de nombreuses façons de l'utiliser, mais j'aimerais vous présenter comment je l'utilise. Le package que j'utilise souvent est numpy. Il est accompagné d'un calcul numérique. Je suis vraiment en difficulté sans ça. Les autres sont matplotlib et scipy. Ensuite, j'utilise Tkinter pour afficher la boîte de dialogue. Je pense que beaucoup de gens utilisent ce domaine, donc je pense qu'il est facile de collecter des informations.

Enfin, j'aimerais créer un cluster de percoration invasive et mettre tout un programme pour calculer sa dimension fractale. Par défaut, numpy, scipy et matplotlib ne sont pas inclus, vous devez donc les inclure en premier.

Quand j'étais pressé d'entrer dans un ordinateur portable dans le laboratoire

windows7 --Python, SciPy, Installation de matplotlib (Windows) --Qiita:

C'était incroyablement pratique. Merci de votre aide.

Lorsque vous le mettez dans Ubuntu, vous devez utiliser apt avec obéissance.

Pour le modèle du programme ci-dessous, pardonnez-moi en copiant et collant mon rapport ...

À propos de la percoration invasive

numpy.random.random([x, y])

Donc, maintenant que j'ai expliqué l'image du modèle, je voudrais aborder le contenu du code. Explication du code Premièrement, à partir du point de base, les points de la grille sont représentés comme une matrice en utilisant un tableau numpy (l'endroit où il est écrit comme self.lattice). Dans une matrice de x lignes et y colonnes, un tableau de nombres aléatoires avec des éléments 0 à 1 peut être créé. Dans ce modèle, on suppose que la valeur du nombre aléatoire donné à chacun représente la résistance. Ensuite, comme nous le faisons dans la clause while, comme écrit dans le commentaire, les points de grille avec la valeur de résistance minimale sont occupés dans l'ordre à partir des points autour des points de grille occupés. Où j'ai conçu

#Définissez les coordonnées de la grille avec la plus petite valeur aux points environnants sur mm
mm = min([(v,k) for k,v in nnsite.items()])[1]

La clé et la valeur du dictionnaire nnsite sont extraites par nnsite.items (), et la clé avec la valeur minimale est obtenue en comparant la magnitude de la première valeur du taple passé, qui est la spécification de min.

class TopWindow:
    
    def quit(self):
        self.root.destroy()
        sys.exit()
        
    def show_window(self, title="title", *args):
        self.root = Tk()
        self.root.title(title)
        frames = []
        for i, arg in enumerate(args):
            frames.append(Frame(self.root, padx=5, pady=5))
            for k, v in arg:
                Button(frames[i],text=k,command=v).pack(expand=YES, fill='x')
            frames[i].pack(fill='x')
        f = Frame(self.root, padx=5, pady=5)
        Button(f,text='quit',command=self.quit).pack(expand=YES, fill='x')
        f.pack(fill='x')
        self.root.mainloop()

Spécifiez la fonction associée à l'étiquette de bouton dans l'ensemble de taples donné à l'argument. Lors de l'appel

run = (('run', pushed), ('save canvas to sample.eps', pr))
run2 = (('calculate D', b4_pushed),)
top.show_window("Invasion Percolation", run, run2)

Faire.

Je ne peux pas expliquer tous les autres détails, je vais donc vous présenter le type d'écran obtenu à la suite de la simulation et le type de résultat d'exécution obtenu.

<img src = "http: //blog-imgs-64.fc2" .com / y / u / z / yuzugosho / 2014-08-06.png "alt =" Exemple d'exécution "border =" 0 "width =" 689 "height =" 531 "/>

inavasion_percolation_D

De cette façon, une boîte de dialogue sera affichée, cliquez sur Exécuter pour générer un cluster de percoration, et Calculate_D vous donnera le graphique ci-dessus. Le sens est omis.

invasion_percolation.py


#! /usr/bin/env python
# -*- coding:utf-8 -*-
#
# written by ssh0, August 2014.

from Tkinter import *
import sys
import numpy as np
import scipy.optimize as optimize
import matplotlib.pyplot as plt

class Percolation:

    def __init__(self, Lx=40, Ly=20):
        self.sub = None
        self.Lx = Lx
        self.Ly = Ly

    def perc_cluster(self):
        self.lattice = np.random.random([self.Lx+2, self.Ly])
        Lx = self.Lx
        Ly = self.Ly
        
        #L'extrémité gauche est tous les sites occupés
        self.lattice[:1, :] = 1.5
        
        self.lattice[Lx+1:, :] = 0
        if self.sub is None or not self.sub.winfo_exists():
            lattice = self.lattice
            ne = [(0, -1), (0, 1), (-1, 0), (1, 0)]
            
            #Conservez les coordonnées des points environnants au format dictionnaire
            nnsite = {(1, y):lattice[1, y] for y in range(Ly)}
            
            percolate = False
            while len(nnsite) != 0 and percolate == False:
                
                #Définissez les coordonnées de la grille avec la plus petite valeur aux points environnants sur mm
                mm = min([(v,k) for k,v in nnsite.items()])[1]
                
                lattice[mm] = 1
                del nnsite[mm]
                
                #Lister les coordonnées des points autour de mm en nn(Appliquer une condition aux limites périodique dans la direction y)
                nn = [(mm[0] + nx, (mm[1] + ny)%Ly) for nx, ny in ne
                                if lattice[mm[0] + nx, (mm[1] + ny)%Ly] < 1]
                
                #Exclut les nn déjà inclus dans nnsite--> nnlist
                nnlist = list(set(nn) - set(nnsite.keys()))
                
                #Ajouter de nouveaux points périphériques à nnsite
                for n in nnlist:
                    nnsite[n] = lattice[n]
                
                #Lorsque le point de grille occupé est à l'extrémité droite, il est considéré comme percolé.
                if mm[0] == Lx:
                    percolate = True
            
            self.lattice = lattice[1:-1, :]
        return self.lattice
    
    def draw_canvas(self, rect, Lx, Ly):
        default_size = 640 # default size of canvas
        r = int(default_size/(2*Lx))
        fig_size_x = 2*r*Lx
        fig_size_y = 2*r*Ly
        margin = 10
        sub = Toplevel()
        
        sub.title('invasion percolation')
        self.canvas = Canvas(sub, width=fig_size_x+2*margin,
                    height=fig_size_y+2*margin)
        self.canvas.create_rectangle(margin, margin,
                    fig_size_x+margin, fig_size_y+margin,
                    outline='black', fill='white')
        self.canvas.pack()
        
        c = self.canvas.create_rectangle
        
        site = np.where(rect==1)
        for m, n in zip(site[0], site[1]):
            c(2*m*r+margin, 2*n*r+margin,
                        2*(m+1)*r+margin, 2*(n+1)*r+margin,
                        outline='black', fill='black')
    
    def get_fractal_dim(self, trial=20, Lmin=20, Lmax=40, Lsample=10):
        
        #Une valeur entière entre Lmin et Lmax afin qu'elle soit uniformément espacée lors de l'enregistrement autant que possible.
        L = np.array([int(i) for i 
                    in np.logspace(np.log10(Lmin), np.log10(Lmax), Lsample)])
        
        M_L = []
        for l in L:
            self.Lx = l*2
            self.Ly = l
            m_L = 0
            for i in range(trial):
                lattice = self.perc_cluster()
                
                #Nombre total de sites occupés dans le réseau central L × L
                m_L += np.sum(lattice[int(l/2)+1:l+int(l/2),:]==1)
            
            M_L.append(m_L/float(trial))
            print "L = %d, M_L = %f" % (l, M_L[-1])
        
        M_L = np.array(M_L)

        def fit_func(parameter0, L, M_L):
            log = np.log
            c1 = parameter0[0]
            c2 = parameter0[1]
            residual = log(M_L) - c1 - c2*log(L)
            return residual
        
        parameter0 = [0.1, 2.0]
        result = optimize.leastsq(fit_func, parameter0, args=(L, M_L))
        c1 = result[0][0]
        D = result[0][1]
        print "D = %f" % D
        
        def fitted(L, c1, D):
            return np.exp(c1)*(L**D)
        
        fig = plt.figure("Fractal Dimension")
        ax = fig.add_subplot(111)
        ax.plot(L, M_L, '-o', label=r"$M(L)$")
        ax.plot(L, fitted(L, c1, D), label="fit func: D = %f" % D)
        ax.set_xlabel(r'$\ln L$', fontsize=16)
        ax.set_ylabel(r'$\ln M(L)$', fontsize=16)
        ax.set_xscale('log')
        ax.set_yscale('log')
        ax.set_ymargin(0.05)
        fig.tight_layout()
        plt.legend(loc='best')
        plt.show()

class TopWindow:
    
    def quit(self):
        self.root.destroy()
        sys.exit()
        
    def show_window(self, title="title", *args):
        self.root = Tk()
        self.root.title(title)
        frames = []
        for i, arg in enumerate(args):
            frames.append(Frame(self.root, padx=5, pady=5))
            for k, v in arg:
                Button(frames[i],text=k,command=v).pack(expand=YES, fill='x')
            frames[i].pack(fill='x')
        f = Frame(self.root, padx=5, pady=5)
        Button(f,text='quit',command=self.quit).pack(expand=YES, fill='x')
        f.pack(fill='x')
        self.root.mainloop()

if __name__ == '__main__':
    Lx = 40
    Ly = 20
    top = TopWindow()
    per = Percolation(Lx, Ly)
    count = 1

    def pr():
        global count
        d = per.canvas.postscript(file="figure_%d.eps" % count)
        print "saved the figure to a eps file"
        count += 1

    def pushed():
        per.perc_cluster()
        per.draw_canvas(per.lattice, Lx, Ly)

    def b4_pushed():
        trial = 100; Lmin = 20; Lmax = 100; Lsample = 10
        per.get_fractal_dim(trial, Lmin, Lmax, Lsample)
    
    run = (('run', pushed), ('save canvas to sample.eps', pr))
    run2 = (('calculate D', b4_pushed),)
    top.show_window("Invasion Percolation", run, run2)

Recommended Posts

Simulation numérique en percoration Python-invasive
Simulation numérique en Python (2) - Agrégation déterminant la vitesse de diffusion (DLA)
Simulation de diffraction des rayons X avec Python