Skip to content

Commit be4210a

Browse files
committed
clean ups
1 parent f6e6fb4 commit be4210a

18 files changed

+144
-53
lines changed

Dockerfile

+3
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,6 @@ ENV OMPI_MCA_hwloc_base_binding_policy=hwthread \
5050
OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
5151

5252
RUN python -m ipykernel install --name=PyNucleus
53+
54+
COPY README.container.rst /README.container.rst
55+
RUN echo '[ ! -z "$TERM" -a -r /README.container.rst ] && cat /README.container.rst' >> /etc/bash.bashrc

PyNucleus/__init__.py

+43-12
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,50 @@
55
# If you want to use this code, please refer to the README.rst and LICENSE files. #
66
###################################################################################
77

8-
import importlib
9-
import pkgutil
108
import sys
119

1210
subpackages = {}
1311
__all__ = []
14-
for finder, name, ispkg in pkgutil.iter_modules():
15-
if ispkg and name.find('PyNucleus_') == 0:
16-
importName = name[len('PyNucleus_'):]
17-
module = importlib.import_module(name, 'PyNucleus')
18-
sys.modules['PyNucleus.'+importName] = module
19-
subpackages[importName] = module
20-
names = [name for name in module.__dict__ if not name.startswith('_')]
21-
locals().update({name: getattr(module, name) for name in names})
22-
if hasattr(module, '__all__'):
23-
__all__ += module.__all__
12+
13+
from PyNucleus_packageTools import *
14+
import PyNucleus_packageTools as packageTools
15+
16+
sys.modules['PyNucleus.packageTools'] = packageTools
17+
subpackages['packageTools'] = packageTools
18+
19+
from PyNucleus_base import *
20+
import PyNucleus_base as base
21+
22+
sys.modules['PyNucleus.base'] = base
23+
subpackages['base'] = base
24+
__all__ += base.__all__
25+
26+
from PyNucleus_metisCy import *
27+
import PyNucleus_metisCy as metisCy
28+
29+
sys.modules['PyNucleus.metisCy'] = metisCy
30+
subpackages['metisCy'] = metisCy
31+
32+
from PyNucleus_fem import *
33+
import PyNucleus_fem as fem
34+
35+
sys.modules['PyNucleus.fem'] = fem
36+
subpackages['fem'] = fem
37+
__all__ += fem.__all__
38+
39+
from PyNucleus_multilevelSolver import *
40+
import PyNucleus_multilevelSolver as multilevelSolver
41+
42+
sys.modules['PyNucleus.multilevelSolver'] = multilevelSolver
43+
subpackages['multilevelSolver'] = multilevelSolver
44+
__all__ += multilevelSolver.__all__
45+
46+
try:
47+
from PyNucleus_nl import *
48+
import PyNucleus_nl as nl
49+
50+
sys.modules['PyNucleus.nl'] = nl
51+
subpackages['nl'] = nl
52+
__all__ += nl.__all__
53+
except ImportError:
54+
pass

README.container.rst

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
This is a container image for PyNucleus.
3+
4+
The drivers and examples for PyNucleus can be found in /pynucleus/drivers and /pynucleus/examples
5+
6+
The directory from which the container was launched on the host system is mapped to /user

base/PyNucleus_base/utilsFem.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1822,7 +1822,9 @@ def setDriverArgs(self):
18221822

18231823
@property
18241824
def timer(self):
1825-
return self.driver.getTimer()
1825+
if self._timer is None:
1826+
self._timer = self.driver.getTimer()
1827+
return self._timer
18261828

18271829
def processCmdline(self, params):
18281830
pass

compose.yaml

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: 3
33
services:
44

55
# Launch with:
6-
# docker compose run --profile interactive pynucleus
6+
# docker compose run pynucleus
77
pynucleus:
88
image: ghcr.io/sandialabs/pynucleus:latest
99
build: .
@@ -22,23 +22,24 @@ services:
2222
- /tmp/.X11-unix:/tmp/.X11-unix
2323
- $XAUTHORITY:/root/.Xauthority
2424
network_mode: host
25+
hostname: pynucleus-container
2526

2627
# Launch with:
2728
# docker compose up
2829
# Then open localhost:8889 in your browser
2930
pynucleus-jupyter:
3031
image: ghcr.io/sandialabs/pynucleus:latest
3132
build: .
32-
command: jupyter notebook --port=8888 --no-browser --ip=0.0.0.0 --allow-root --NotebookApp.token='' --NotebookApp.password='' --notebook-dir=/pynucleus/user --KernelSpecManager.ensure_native_kernel=False --KernelSpecManager.allowed_kernelspecs=pynucleus
33+
command: jupyter notebook --port=8888 --no-browser --ip=0.0.0.0 --allow-root --NotebookApp.token='' --NotebookApp.password='' --notebook-dir=/notebooks --KernelSpecManager.ensure_native_kernel=False --KernelSpecManager.allowed_kernelspecs=pynucleus
3334
environment:
3435
# expose host proxies
3536
- http_proxy=${http_proxy}
3637
- https_proxy=${https_proxy}
3738
- HTTP_PROXY=${HTTP_PROXY}
3839
- HTTPS_PROXY=${HTTPS_PROXY}
3940
volumes:
40-
# The current directory on host gets mapped to /pynucleus/user in the container
41-
- $PWD/notebooks:/pynucleus/user
41+
# The notebook subdirectory on host gets mapped to /notebooks in the container
42+
- $PWD/notebooks:/notebooks
4243
ports:
4344
# Expose a Jupyter notebook server from the container
4445
- 8889:8888

drivers/runNonlocalInterface.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@
9292
with d.timer('assemble matrices'):
9393
buildDense = True
9494

95-
A1 = getFracLapl(domain1Mesh, dm1, nIP.kernel1, boundaryCondition=HOMOGENEOUS_NEUMANN, dense=buildDense,
95+
A1 = getFracLapl(dm1, nIP.kernel1, boundaryCondition=HOMOGENEOUS_NEUMANN, dense=buildDense,
9696
forceRebuild=d.forceRebuild, genKernel=d.genKernel, trySparsification=True, doSave=True)
97-
A2 = getFracLapl(domain2Mesh, dm2, nIP.kernel2, boundaryCondition=HOMOGENEOUS_NEUMANN, dense=buildDense,
97+
A2 = getFracLapl(dm2, nIP.kernel2, boundaryCondition=HOMOGENEOUS_NEUMANN, dense=buildDense,
9898
forceRebuild=d.forceRebuild, genKernel=d.genKernel, trySparsification=True, doSave=True)
9999

100100
# domain-domain interaction

fem/PyNucleus_fem/DoFMaps.pyx

+12-4
Original file line numberDiff line numberDiff line change
@@ -805,11 +805,19 @@ cdef class DoFMap:
805805
return assembleRHSgrad(fun, self, coeff, qr)
806806

807807
def assembleNonlocal(self, kernel, str matrixFormat='DENSE', DoFMap dm2=None, BOOL_t returnNearField=False, **kwargs):
808-
"""Assemble a nonlocal operator of the form
808+
"""Assemble a nonlocal operator.
809+
810+
For finite horizon kernels
811+
812+
.. math::
813+
814+
\\iint_{D \\times D} (u(x)-u(y)) (v(x) \\gamma(x, y) - v(y) \\gamma(y, x)) dy dx
815+
816+
and for infinite horizon kernels
809817
810818
.. math::
811819
812-
\\int_D (u(x)-u(y)) \\gamma(x, y) dy
820+
\\iint_{D \\times D} (u(x)-u(y)) (v(x) \\gamma(x, y) - v(y) \\gamma(y, x)) dy dx + 2\\int_{D} u(x) v(x) \\int_{D^c} \\gamma(x, y) dy dx
813821
814822
:param kernel: The kernel function :math:`\\gamma`
815823
@@ -861,11 +869,11 @@ cdef class DoFMap:
861869
if isinstance(kernel, ComplexKernel):
862870
from PyNucleus_nl.nonlocalAssembly import ComplexnonlocalBuilder
863871

864-
builder = ComplexnonlocalBuilder(self.mesh, self, kernel, dm2=dm2, **kwargs)
872+
builder = ComplexnonlocalBuilder(self, kernel, dm2=dm2, **kwargs)
865873
else:
866874
from PyNucleus_nl.nonlocalAssembly import nonlocalBuilder
867875

868-
builder = nonlocalBuilder(self.mesh, self, kernel, dm2=dm2, **kwargs)
876+
builder = nonlocalBuilder(self, kernel, dm2=dm2, **kwargs)
869877
if matrixFormat.upper() == 'DENSE':
870878
return builder.getDense()
871879
elif matrixFormat.upper() == 'DIAGONAL':

fem/PyNucleus_fem/__init__.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,10 @@
1414
from . factories import functionFactory, dofmapFactory, meshFactory
1515
from . pdeProblems import diffusionProblem, helmholtzProblem
1616
__all__ = ['functionFactory', 'dofmapFactory', 'meshFactory',
17-
'diffusionProblem', 'helmholtzProblem']
17+
'diffusionProblem', 'helmholtzProblem',
18+
'PHYSICAL', 'INTERIOR_NONOVERLAPPING', 'INTERIOR', 'NO_BOUNDARY',
19+
'DIRICHLET', 'HOMOGENEOUS_DIRICHLET',
20+
'NEUMANN', 'HOMOGENEOUS_NEUMANN',
21+
'NORM', 'boundaryConditions',
22+
'P0_DoFMap', 'P1_DoFMap', 'P2_DoFMap', 'P3_DoFMap',
23+
'str2DoFMap', 'str2DoFMapOrder', 'getAvailableDoFMaps']

nl/PyNucleus_nl/__init__.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@
3131
nonlocalMeshFactory)
3232
from . discretizedProblems import (discretizedNonlocalProblem,
3333
discretizedTransientProblem)
34-
__all__ = [twoPointFunctionFactory, fractionalOrderFactory, interactionFactory, kernelFactory, nonlocalMeshFactory,
35-
fractionalLaplacianProblem, nonlocalPoissonProblem, transientFractionalProblem,
36-
discretizedNonlocalProblem, discretizedTransientProblem]
34+
__all__ = ['twoPointFunctionFactory', 'fractionalOrderFactory', 'interactionFactory', 'kernelFactory', 'nonlocalMeshFactory',
35+
'fractionalLaplacianProblem', 'nonlocalPoissonProblem', 'transientFractionalProblem',
36+
'discretizedNonlocalProblem', 'discretizedTransientProblem']

nl/PyNucleus_nl/discretizedProblems.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ def __init__(self, driver, continuumProblem):
354354
super().__init__(driver)
355355
self.continuumProblem = continuumProblem
356356
self.addRemote(self.continuumProblem)
357+
driver.addToProcessHook(self.setTimerManager)
357358

358359
def setDriverArgs(self):
359360
p = self.driver.addGroup('solver')
@@ -367,6 +368,9 @@ def setDriverArgs(self):
367368
self.setDriverFlag('matrixFormat', acceptedValues=['H2', 'sparse', 'sparsified', 'dense'], help='matrix format', group=p)
368369
self.setDriverFlag('debugAssemblyTimes', False, group=p)
369370

371+
def setTimerManager(self, params):
372+
self._timer = self.driver.getTimer().getSubManager(logging.getLogger(__name__))
373+
370374
@generates(['meshHierarchy', 'finalMesh',
371375
'dm', 'dmBC', 'dmInterior',
372376
'R_interior', 'P_interior',
@@ -518,7 +522,7 @@ def buildBCoperator(self, dmInterior, dmBC,
518522
assemblyParams['dense'] = matrixFormat == 'dense'
519523
assemblyParams['matrixFormat'] = matrixFormat
520524
assemblyParams['tag'] = tag
521-
self.A_BC = getFracLapl(dmInterior.mesh, dmInterior, dm2=dmBC, **assemblyParams)
525+
self.A_BC = getFracLapl(dmInterior, dm2=dmBC, **assemblyParams)
522526
else:
523527
self.A_BC = None
524528

@@ -638,7 +642,7 @@ def solve(self, b, dm, dmInterior, dmBC, P_interior, P_bc, solver, boundaryCondi
638642
@generates('adjointModelSolution')
639643
def adjointSolve(self, b, dm, dmInterior, P_interior, adjointSolver, tol, maxiter):
640644
uInterior = dmInterior.zeros()
641-
with self.timer('solve {}'.format(self.__class__.__name__)):
645+
with self.timer('solve adjoint {}'.format(self.__class__.__name__)):
642646
its = adjointSolver(b, uInterior)
643647

644648
resError = (b-adjointSolver.A*uInterior).norm(False)

nl/PyNucleus_nl/helpers.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,9 @@ def processBC(tag, boundaryCondition, kernel):
114114
return tag, zeroExterior
115115

116116

117-
def getFracLapl(mesh, DoFMap, kernel=None, rangedOpParams={}, **kwargs):
117+
def getFracLapl(DoFMap, kernel=None, rangedOpParams={}, **kwargs):
118118

119+
mesh = DoFMap.mesh
119120
if kernel is None and len(rangedOpParams) == 0:
120121
return DoFMap.assembleStiffness(dm2=kwargs.get('dm2', None))
121122
assert kernel is not None or 's' in rangedOpParams, (kernel, rangedOpParams)
@@ -188,7 +189,7 @@ def getFracLapl(mesh, DoFMap, kernel=None, rangedOpParams={}, **kwargs):
188189
intervalOps = []
189190
for s in n:
190191
kernel = getFractionalKernel(mesh.dim, constFractionalOrder(s), horizon, scaling=scaling, normalized=normalized)
191-
intervalOps.append(delayedFractionalLaplacianOp(mesh, DoFMap, kernel, **kwargs))
192+
intervalOps.append(delayedFractionalLaplacianOp(DoFMap, kernel, **kwargs))
192193
ops.append(intervalOps)
193194
A = multiIntervalInterpolationOperator(intervals, nodes, ops)
194195
return A
@@ -263,10 +264,10 @@ def getFracLapl(mesh, DoFMap, kernel=None, rangedOpParams={}, **kwargs):
263264
if dm2 is not None and matrixFormat.upper() in ('H2', 'SPARSE', 'SPARSIFIED') and DoFMap.num_boundary_dofs > 0:
264265
# currently not implemented
265266
dm, R_interior, R_bc = DoFMap.getFullDoFMap(dm2)
266-
A = getFracLapl(mesh, dm, kernel, rangedOpParams={}, **kwargs)
267+
A = getFracLapl(dm, kernel, rangedOpParams={}, **kwargs)
267268
A = R_interior*A*R_bc.transpose()
268269
return A
269-
builder = nonlocalBuilder(mesh, DoFMap, kernel, params, zeroExterior=zeroExterior, comm=comm, logging=logging, PLogger=PLogger, dm2=dm2)
270+
builder = nonlocalBuilder(DoFMap, kernel, params, zeroExterior=zeroExterior, comm=comm, logging=logging, PLogger=PLogger, dm2=dm2)
270271
if diagonal:
271272
with timer('Assemble diagonal matrix {}, zeroExterior={}'.format(kernel, zeroExterior)):
272273
A = builder.getDiagonal()
@@ -343,7 +344,7 @@ def build(self, buildType):
343344
self.params['assemblyComm'] = self.comm
344345
self.params['assembleOnRoot'] = False
345346
self.params['forceUnsymmetric'] = True
346-
self.S = getFracLapl(mesh, DoFMap, **self.params)
347+
self.S = getFracLapl(DoFMap, **self.params)
347348
self.A = self.S
348349
# if not s.symmetric:
349350
# from PyNucleus_base.linear_operators import Dense_LinearOperator
@@ -650,10 +651,9 @@ def construct(self):
650651

651652

652653
class delayedFractionalLaplacianOp(delayedConstructionOperator):
653-
def __init__(self, mesh, dm, kernel, **kwargs):
654+
def __init__(self, dm, kernel, **kwargs):
654655
super().__init__(dm.num_dofs,
655656
dm.num_dofs)
656-
self.mesh = mesh
657657
self.dm = dm
658658
self.kernel = kernel
659659
self.kwargs = kwargs
@@ -662,7 +662,7 @@ def construct(self):
662662
from copy import copy
663663
d = copy(self.kwargs)
664664
d.update(self.params)
665-
A = getFracLapl(self.mesh, self.dm, self.kernel, **d)
665+
A = getFracLapl(self.dm, self.kernel, **d)
666666
return A
667667

668668

nl/PyNucleus_nl/nonlocalAssembly.pyx

+4-4
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ cdef class horizonCorrected(TimeStepperLinearOperator):
196196
if Ainf is None:
197197
scaling = constantTwoPoint(0.5)
198198
infiniteKernel = kernel.getModifiedKernel(horizon=constant(np.inf), scaling=scaling)
199-
infBuilder = nonlocalBuilder(self.mesh, self.dm, infiniteKernel, zeroExterior=True, comm=self.comm, logging=self.logging)
199+
infBuilder = nonlocalBuilder(self.dm, infiniteKernel, zeroExterior=True, comm=self.comm, logging=self.logging)
200200
self.Ainf = infBuilder.getH2()
201201
else:
202202
self.Ainf = Ainf
@@ -233,7 +233,7 @@ cdef class horizonCorrected(TimeStepperLinearOperator):
233233
self.kernel = kernel
234234

235235
complementKernel = kernel.getComplementKernel()
236-
builder = nonlocalBuilder(self.mesh, self.dm, complementKernel, zeroExterior=True, comm=self.comm, logging=self.logging)
236+
builder = nonlocalBuilder(self.dm, complementKernel, zeroExterior=True, comm=self.comm, logging=self.logging)
237237
correction = builder.getH2()
238238

239239
self.S = self.Ainf
@@ -363,7 +363,7 @@ def assembleNonlocalOperator(meshBase mesh,
363363
MPI.Comm comm=None,
364364
**kwargs):
365365
kernel = getFractionalKernel(mesh.dim, s, horizon)
366-
builder = nonlocalBuilder(mesh, dm, kernel, params, zeroExterior, comm, **kwargs)
366+
builder = nonlocalBuilder(dm, kernel, params, zeroExterior, comm, **kwargs)
367367
return builder.getDense()
368368

369369

@@ -487,7 +487,7 @@ def assembleNearField(list Pnear,
487487
comm=None,
488488
**kwargs):
489489
kernel = getFractionalKernel(mesh.dim, s, horizon)
490-
builder = nonlocalBuilder(mesh, dm, kernel, params, zeroExterior, comm, logging=True, **kwargs)
490+
builder = nonlocalBuilder(dm, kernel, params, zeroExterior, comm, logging=True, **kwargs)
491491
A = builder.assembleClusters(Pnear)
492492
return A
493493

nl/PyNucleus_nl/nonlocalAssembly_{SCALAR}.pxi

-3
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,6 @@ cdef class {SCALAR_label}IndexManagerMixed({SCALAR_label}IndexManager):
858858

859859
cdef class {SCALAR_label}nonlocalBuilder:
860860
def __init__(self,
861-
meshBase mesh,
862861
DoFMap dm,
863862
{SCALAR_label}Kernel kernel,
864863
dict params={},
@@ -875,7 +874,6 @@ cdef class {SCALAR_label}nonlocalBuilder:
875874

876875
self.dm = dm
877876
self.mesh = self.dm.mesh
878-
assert self.dm.mesh == mesh
879877
if dm2 is not None:
880878
self.dm2 = dm2
881879
assert type(self.dm) == type(self.dm2)
@@ -889,7 +887,6 @@ cdef class {SCALAR_label}nonlocalBuilder:
889887
self.params = params
890888

891889
assert isinstance(self.kernel.horizon, constant), "Need horizon to be constant."
892-
assert kernel.dim == mesh.dim, "Kernel dimension must match mesh dimension"
893890
assert kernel.dim == dm.mesh.dim, "Kernel dimension must match dm.mesh dimension"
894891

895892
# volume integral

tests/test_drivers_intFracLapl.py

+32
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,38 @@ def testMatvecs(runDistOp_params, extra):
189189
runDriver(path, py, ranks=4, cacheDir=cacheDir, extra=extra)
190190

191191

192+
@pytest.fixture(scope='module', params=[
193+
('interval', 'const(0.25)', 0.01, 100.0),
194+
('interval', 'const(0.75)', 0.01, 100.0),
195+
# ('square', 'const(0.25)', 1.0, 20.0),
196+
('square', 'const(0.75)', 1.0, 20.0),
197+
],
198+
ids=idfunc)
199+
def runDistOpFinite_params(request):
200+
return request.param
201+
202+
203+
@pytest.mark.slow
204+
def testMatvecsFinite(runDistOpFinite_params, extra):
205+
base = getPath()+'/../'
206+
domain, fractionalOrder, horizon, horizonToMeshSize = runDistOpFinite_params
207+
py = ['testDistOp.py',
208+
'--domain', domain,
209+
'--s', fractionalOrder,
210+
'--horizon', str(horizon),
211+
'--horizonToMeshSize', str(horizonToMeshSize),
212+
# '--problem', 'constant',
213+
'--buildSparse',
214+
'--buildH2Reduced',
215+
'--buildDistributedH2Bcast',
216+
'--buildDistributedH2',
217+
# '--doSolve'
218+
]
219+
py += ['--no-write']
220+
path = base+'drivers'
221+
cacheDir = getPath()+'/'
222+
runDriver(path, py, ranks=4, cacheDir=cacheDir, extra=extra)
223+
192224
@pytest.fixture(scope='module', params=[
193225
('doubleInterval', 'fractional', 'fractional', '0.2', '0.4', '0.2', '0.2', 'exact-sin-variableSolJump-fluxJump'),
194226
('doubleInterval', 'fractional', 'fractional', '0.2', '0.4', '0.2', '0.4', 'exact-sin-variableSolJump-fluxJump'),

0 commit comments

Comments
 (0)