33from fidimag.atomistic.energy import Energy
44from libcpp.vector cimport vector
55from libcpp.utility cimport pair
6-
6+ from libcpp.algorithm cimport sort
77cimport numpy as np
88import numpy as np
99
@@ -31,6 +31,14 @@ cdef extern from "tree.hpp":
3131
3232
3333cdef extern from " calculate.hpp" :
34+ void evaluate_approx(vector[Particle] particles, vector[Cell] cells,
35+ size_t ncrit, double theta, size_t order, double * F)
36+
37+ void evaluate_approx_lazy(vector[Particle] particles, vector[Cell] cells,
38+ size_t ncrit, size_t order, double * F,
39+ vector[pair[size_t, size_t]] M2L_list,
40+ vector[pair[size_t, size_t]] P2P_list)
41+
3442 void evaluate_P2M(vector[Particle] particles,
3543 vector[Cell] cells,
3644 size_t cell,
@@ -62,8 +70,23 @@ cdef extern from "calculate.hpp":
6270 double * F,
6371 size_t n)
6472
73+ void interact_dehnen_lazy(size_t A, size_t B,
74+ vector[Cell] cells,
75+ vector[Particle] particles,
76+ double theta, size_t order,
77+ const size_t ncrit,
78+ vector[pair[size_t, size_t]] M2L_list,
79+ vector[pair[size_t, size_t]] P2P_list)
6580
6681
82+ void build_interaction_lists(vector[pair[size_t, size_t]] M2L_list,
83+ vector[pair[size_t, size_t]]P2P_list,
84+ vector[Cell] cells,
85+ vector[Particle] particles,
86+ double theta,
87+ size_t order,
88+ size_t ncrit
89+ )
6790
6891
6992cdef class FMM:
@@ -75,18 +98,23 @@ cdef class FMM:
7598 cdef Cell root
7699 cdef vector[double ] M
77100 cdef vector[double ] L
101+ cdef vector[pair[size_t, size_t]] M2L_list
102+ cdef vector[pair[size_t, size_t]] P2P_list
78103 cdef size_t Msize
79104 cdef size_t Lsize
80105 cdef public double [:, :] coords
106+ cdef double theta
81107
82- def __cinit__ (self , size_t n , size_t ncrit , size_t order , double [:, :] coords , double [:] mu ):
108+ def __cinit__ (self , size_t n , size_t ncrit , double theta , size_t order , double [:, :] coords , double [:] mu ):
109+ if order > 11 :
110+ raise ValueError (" Order needs to be < 12" )
83111 # self.particles = vector[Particle]
84-
112+ self .theta = theta
85113 # Don't remove this line, or the memory goes out of scope!
86114 self .coords = coords
87115 self .ncrit = ncrit
88116 self .order = order
89- print (' FMM Order = {}' .format(order))
117+ # print('FMM Order = {}'.format(order))
90118 xs = np.asarray(self .coords[:, 0 ])
91119 ys = np.asarray(self .coords[:, 1 ])
92120 zs = np.asarray(self .coords[:, 2 ])
@@ -108,16 +136,7 @@ cdef class FMM:
108136 & mu[3 * i])
109137 self .particles.push_back(self .p)
110138 self .cells = build_tree(self .particles, self .root, ncrit, order)
111- print (f" Cython: cells.size() {self.cells.size()}" )
112-
113-
114- print (f" r[0] = {self.particles[0].r[0]}, {self.particles[0].r[1]}, {self.particles[0].r[2]}" )
115-
116- print (f" mu[0] = {self.particles[0].mu[0]}, {self.particles[0].mu[1]}, {self.particles[0].mu[2]}" )
117-
118- # Need to allocate memory for the M and L arrays.
119- # vector[double] M(cells.size() * (Nterms(order) - Nterms(0)), 0.0)
120- # vector[double] L(cells.size() * Nterms(order - 1), 0.0)
139+ print (f" DemagFMM tree built with {self.cells.size()} cells" )
121140
122141 self .Msize = Nterms(order) - Nterms(0 )
123142 self .Lsize = Nterms(order - 1 )
@@ -128,6 +147,12 @@ cdef class FMM:
128147 self .cells[i].M = & self .M[i* self .Msize]
129148 self .cells[i].L = & self .L[i* self .Lsize]
130149
150+ # vector[pair[size_t, size_t]] M2L_list
151+ # vector[pair[size_t, size_t]] P2P_list
152+ print (" Setting up interaction list" )
153+ # interact_dehnen_lazy(0, 0, self.cells, self.particles, theta, order, ncrit, self.M2L_list, self.P2P_list)
154+ build_interaction_lists(self .M2L_list, self .P2P_list, self .cells, self .particles, self .theta, order, ncrit)
155+ print (" Done" )
131156
132157 def P2M (self ):
133158 evaluate_P2M(self .particles, self .cells, 0 , self .ncrit, self .order)
@@ -137,24 +162,31 @@ cdef class FMM:
137162
138163
139164 def compute_field (self , double theta , double [:] F ):
140- F[:] = 0
141- print (' compute field' )
142- print (" P2M starting" )
143- evaluate_P2M(self .particles, self .cells, 0 , self .ncrit, self .order)
144- print (" M2M starting" )
145- evaluate_M2M(self .particles, self .cells, self .order)
146-
147- print (f" mu[0] = {self.particles[0].mu[0]}, {self.particles[0].mu[1]}, {self.particles[0].mu[2]}" )
148-
149- print (np.max(self .M))
150-
151- print (" interact_dehnen starting" )
152- interact_dehnen(0 , 0 , self .cells, self .particles, theta, self .order, self .ncrit, & F[0 ])
153- print (" L2L starting" )
154- evaluate_L2L(self .cells, self .order)
155- print (" L2P starting" )
156- evaluate_L2P(self .particles, self .cells, & F[0 ], self .ncrit, self .order)
157- print (F[0 ])
165+ # print("Computing field...")
166+ for i in range (self .Msize * self .cells.size()):
167+ self .M[i] = 0.0
168+ for i in range (self .Lsize * self .cells.size()):
169+ self .L[i] = 0.0
170+ for i in range (3 * self .n):
171+ F[i] = 0.0
172+ # print('compute field')
173+ # print("P2M starting")
174+ # evaluate_P2M(self.particles, self.cells, 0, self.ncrit, self.order)
175+ # #print("M2M starting")
176+ # evaluate_M2M(self.particles, self.cells, self.order)
177+
178+ # #print(f"mu[0] = {self.particles[0].mu[0]}, {self.particles[0].mu[1]}, {self.particles[0].mu[2]}")
179+
180+ # #print(np.max(self.M))
181+
182+ # #print("interact_dehnen starting")
183+ # interact_dehnen(0, 0, self.cells, self.particles, theta, self.order, self.ncrit, &F[0])
184+ # #print("L2L starting")
185+ # evaluate_L2L(self.cells, self.order)
186+ # #print("L2P starting")
187+ # evaluate_L2P(self.particles, self.cells, &F[0], self.ncrit, self.order)
188+ # evaluate_approx(self.particles, self.cells, self.ncrit, theta, self.order, &F[0])
189+ evaluate_approx_lazy(self .particles, self .cells, self .ncrit, self .order, & F[0 ], self .M2L_list, self .P2P_list)
158190
159191 def compute_field_exact (self , double [:] F_exact ):
160192 evaluate_direct(self .particles, & F_exact[0 ], self .n)
0 commit comments