Skip to content

Commit d95574f

Browse files
committed
Fix bug in sparse assembly, add lookupTwoPoint
1 parent 5318b1f commit d95574f

7 files changed

+125
-2
lines changed

fem/PyNucleus_fem/DoFMaps.pyx

+15
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,21 @@ def str2DoFMap(element):
22642264
raise NotImplementedError('Unknown DoFMap: {}'.format(element))
22652265

22662266

2267+
def DoFMap2str(dm):
2268+
if isinstance(dm, P0_DoFMap):
2269+
return 'P0'
2270+
elif isinstance(dm, P1_DoFMap):
2271+
return 'P1'
2272+
elif isinstance(dm, P2_DoFMap):
2273+
return 'P2'
2274+
elif isinstance(dm, P3_DoFMap):
2275+
return 'P3'
2276+
elif isinstance(dm, N1e_DoFMap):
2277+
return 'N1e'
2278+
else:
2279+
raise NotImplementedError('Unknown DoFMap: {}'.format(type(dm)))
2280+
2281+
22672282
def getAvailableDoFMaps():
22682283
return ['P0', 'P1', 'P2', 'P3', 'N1e']
22692284

nl/PyNucleus_nl/nonlocalAssembly.pyx

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ from PyNucleus_base.ip_norm cimport (ip_distributed_nonoverlapping,
1818
norm_distributed_nonoverlapping)
1919
from PyNucleus_fem.functions cimport function, constant
2020
from PyNucleus_fem.DoFMaps cimport P0_DoFMap, P1_DoFMap, Product_DoFMap
21+
from PyNucleus_fem.DoFMaps import DoFMap2str
2122
from PyNucleus_fem.meshCy cimport sortEdge, encode_edge, decode_edge
2223
from PyNucleus_fem.femCy cimport local_matrix_t
2324
from PyNucleus_fem.femCy import assembleMatrix, mass_1d_sym_scalar_anisotropic, mass_2d_sym_scalar_anisotropic

nl/PyNucleus_nl/nonlocalAssembly_{SCALAR}.pxi

+1-1
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,7 @@ cdef class {SCALAR_label}nonlocalBuilder:
11051105
# We want to capture all element x element interactions.
11061106
# We set up a temporary dofmap and construct a near field wrt that.
11071107
if self.dm2 is None:
1108-
treeDM = dofmapFactory('P1', self.dm.mesh, -1)
1108+
treeDM = dofmapFactory(DoFMap2str(self.dm), self.dm.mesh, -1)
11091109
else:
11101110
treeDM = self.dm.combine(self.dm2)
11111111

nl/PyNucleus_nl/nonlocalProblems.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
leftRightTwoPoint,
3838
interfaceTwoPoint,
3939
smoothedLeftRightTwoPoint,
40-
lambdaTwoPoint)
40+
lambdaTwoPoint,
41+
lookupTwoPoint)
4142
from . interactionDomains import (fullSpace,
4243
ball1_retriangulation,
4344
ball1_barycenter,
@@ -103,6 +104,7 @@ def build(self, name, *args, **kwargs):
103104
twoPointFunctionFactory.register('leftRight', leftRightTwoPoint, aliases=['leftRightTwoPoint'])
104105
twoPointFunctionFactory.register('interface', interfaceTwoPoint, aliases=['interfaceTwoPoint'])
105106
twoPointFunctionFactory.register('lambda', lambdaTwoPoint)
107+
twoPointFunctionFactory.register('lookup', lookupTwoPoint)
106108

107109
interactionFactory = factory()
108110
interactionFactory.register('fullSpace', fullSpace, aliases=['full'])

nl/PyNucleus_nl/twoPointFunctions.pxd

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
cimport numpy as np
99
from PyNucleus_base.myTypes cimport INDEX_t, REAL_t, COMPLEX_t, BOOL_t
1010
from PyNucleus_fem.functions cimport function, complexFunction
11+
from PyNucleus_fem.DoFMaps cimport DoFMap, shapeFunction
12+
from PyNucleus_fem.meshCy cimport cellFinder2
1113

1214

1315
include "twoPointFunctions_decl_REAL.pxi"

nl/PyNucleus_nl/twoPointFunctions_decl_{SCALAR}.pxi

+8
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ cdef class {SCALAR_label}constantTwoPoint({SCALAR_label}twoPointFunction):
2323
public {SCALAR}_t value
2424

2525

26+
cdef class {SCALAR_label}lookupTwoPoint({SCALAR_label}twoPointFunction):
27+
cdef:
28+
public DoFMap dm
29+
cellFinder2 cellFinder
30+
{SCALAR}_t[::1] vals1, vals2
31+
{SCALAR}_t[:, ::1] A
32+
33+
2634
cdef class {SCALAR_label}parametrizedTwoPointFunction({SCALAR_label}twoPointFunction):
2735
cdef:
2836
void *params

nl/PyNucleus_nl/twoPointFunctions_{SCALAR}.pxi

+95
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,101 @@ cdef class {SCALAR_label}constantTwoPoint({SCALAR_label}twoPointFunction):
151151
return {SCALAR_label}constantTwoPoint, (self.value, )
152152

153153

154+
cdef class {SCALAR_label}lookupTwoPoint({SCALAR_label}twoPointFunction):
155+
def __init__(self, DoFMap dm, {SCALAR}_t[:, ::1] A, BOOL_t symmetric, cellFinder2 cF=None):
156+
super({SCALAR_label}lookupTwoPoint, self).__init__(symmetric, 1)
157+
self.dm = dm
158+
self.A = A
159+
if cF is None:
160+
self.cellFinder = cellFinder2(self.dm.mesh)
161+
else:
162+
self.cellFinder = cF
163+
self.vals1 = uninitialized((self.dm.dofs_per_element), dtype={SCALAR})
164+
self.vals2 = uninitialized((self.dm.dofs_per_element), dtype={SCALAR})
165+
166+
cdef void eval(self, REAL_t[::1] x, REAL_t[::1] y, {SCALAR}_t[::1] value):
167+
cdef:
168+
shapeFunction shapeFun
169+
REAL_t val
170+
INDEX_t cellNo1, cellNo2, dof1, dof2, k1, k2
171+
cellNo1 = self.cellFinder.findCell(x)
172+
if cellNo1 == -1:
173+
value[0] = 0.
174+
return
175+
for k1 in range(self.dm.dofs_per_element):
176+
dof2 = self.dm.cell2dof(cellNo1, k1)
177+
if dof2 >= 0:
178+
shapeFun = self.dm.getLocalShapeFunction(k1)
179+
shapeFun.evalPtr(&self.cellFinder.bary[0], NULL, &val)
180+
self.vals1[k1] = val
181+
else:
182+
self.vals1[k1] = 0.
183+
184+
cellNo2 = self.cellFinder.findCell(y)
185+
if cellNo2 == -1:
186+
value[0] = 0.
187+
return
188+
for k2 in range(self.dm.dofs_per_element):
189+
dof1 = self.dm.cell2dof(cellNo2, k2)
190+
if dof1 >= 0:
191+
shapeFun = self.dm.getLocalShapeFunction(k2)
192+
shapeFun.evalPtr(&self.cellFinder.bary[0], NULL, &val)
193+
self.vals2[k2] = val
194+
else:
195+
self.vals2[k2] = 0.
196+
197+
value[0] = 0.
198+
for k1 in range(self.dm.dofs_per_element):
199+
dof1 = self.dm.cell2dof(cellNo1, k1)
200+
for k2 in range(self.dm.dofs_per_element):
201+
dof2 = self.dm.cell2dof(cellNo2, k2)
202+
value[0] += self.vals1[k1]*self.A[dof1, dof2]*self.vals2[k2]
203+
204+
cdef void evalPtr(self, INDEX_t dim, REAL_t* x, REAL_t* y, {SCALAR}_t* value):
205+
cdef:
206+
shapeFunction shapeFun
207+
REAL_t val
208+
INDEX_t cellNo1, cellNo2, dof, dof1, dof2, k1, k2
209+
cellNo1 = self.cellFinder.findCellPtr(x)
210+
if cellNo1 == -1:
211+
value[0] = 0.
212+
return
213+
for k1 in range(self.dm.dofs_per_element):
214+
dof = self.dm.cell2dof(cellNo1, k1)
215+
if dof >= 0:
216+
shapeFun = self.dm.getLocalShapeFunction(k1)
217+
shapeFun.evalPtr(&self.cellFinder.bary[0], NULL, &val)
218+
self.vals1[k1] = val
219+
else:
220+
self.vals1[k1] = 0.
221+
222+
cellNo2 = self.cellFinder.findCellPtr(y)
223+
if cellNo2 == -1:
224+
value[0] = 0.
225+
return
226+
for k2 in range(self.dm.dofs_per_element):
227+
dof = self.dm.cell2dof(cellNo2, k2)
228+
if dof >= 0:
229+
shapeFun = self.dm.getLocalShapeFunction(k2)
230+
shapeFun.evalPtr(&self.cellFinder.bary[0], NULL, &val)
231+
self.vals2[k2] = val
232+
else:
233+
self.vals2[k2] = 0.
234+
235+
value[0] = 0.
236+
for k1 in range(self.dm.dofs_per_element):
237+
dof1 = self.dm.cell2dof(cellNo1, k1)
238+
for k2 in range(self.dm.dofs_per_element):
239+
dof2 = self.dm.cell2dof(cellNo2, k2)
240+
value[0] += self.vals1[k1]*self.A[dof1, dof2]*self.vals2[k2]
241+
242+
def __repr__(self):
243+
return 'lookup {}'.format(self.dm)
244+
245+
def __reduce__(self):
246+
return {SCALAR_label}lookupTwoPoint, (self.dm, np.array(self.A), self.symmetric)
247+
248+
154249
cdef class {SCALAR_label}parametrizedTwoPointFunction({SCALAR_label}twoPointFunction):
155250
def __init__(self, BOOL_t symmetric, INDEX_t valueSize):
156251
super({SCALAR_label}parametrizedTwoPointFunction, self).__init__(symmetric, valueSize)

0 commit comments

Comments
 (0)