Skip to content

Commit 85ce99d

Browse files
committed
Some minor fixes and bump version
1 parent 463d422 commit 85ce99d

9 files changed

+55
-50
lines changed

demo/ChannelFlow2D.py

+14-14
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ def __init__(self,
9090
self.TD = TensorProductSpace(comm, (self.D0, self.F1), modify_spaces_inplace=True) # Streamwise velocity
9191
self.TC = TensorProductSpace(comm, (self.C0, self.F1), modify_spaces_inplace=True) # No bc
9292
self.BD = VectorSpace([self.TB, self.TD]) # Velocity vector space
93-
self.CD = VectorSpace(self.TD) # Dirichlet vector space
93+
self.CD = VectorSpace(self.TC) # Dirichlet vector space
9494

9595
# Padded space for dealiasing
96-
self.TDp = self.TD.get_dealiased(padding_factor)
96+
self.TDp = self.TC.get_dealiased(padding_factor)
9797

9898
self.u_ = Function(self.BD) # Velocity vector solution
9999
self.H_ = Function(self.CD) # convection
@@ -110,9 +110,9 @@ def __init__(self,
110110
# Classes for fast projections. All are not used except if self.conv=0
111111
self.dudx = Project(Dx(self.u_[0], 0, 1), self.TD)
112112
if self.conv == 0:
113-
self.dudy = Project(Dx(self.u_[0], 1, 1), self.TB)
113+
self.dudy = Project(Dx(self.u_[0], 1, 1), self.TC)
114114
self.dvdx = Project(Dx(self.u_[1], 0, 1), self.TC)
115-
self.dvdy = Project(Dx(self.u_[1], 1, 1), self.TD)
115+
self.dvdy = Project(Dx(self.u_[1], 1, 1), self.TC)
116116

117117
self.curl = Project(curl(self.u_), self.TC)
118118
self.divu = Project(div(self.u_), self.TD)
@@ -130,8 +130,8 @@ def __init__(self,
130130
v = TestFunction(self.TB)
131131

132132
# Chebyshev matrices are not sparse, so need a tailored solver. Legendre has simply 5 nonzero diagonals and can use generic solvers.
133-
#sol1 = chebyshev.la.Biharmonic if self.B0.family() == 'chebyshev' else la.SolverGeneric1ND
134-
sol1 = la.SolverGeneric1ND
133+
sol1 = chebyshev.la.Biharmonic if self.B0.family() == 'chebyshev' else la.SolverGeneric1ND
134+
#sol1 = la.SolverGeneric1ND
135135

136136
self.pdes = {
137137

@@ -151,7 +151,7 @@ def __init__(self,
151151
# v. Momentum equation for Fourier wavenumber 0
152152
if comm.Get_rank() == 0:
153153
v0 = TestFunction(self.D00)
154-
self.h1 = Function(self.D00) # Copy from H_[1, :, 0, 0] (cannot use view since not contiguous)
154+
self.h1 = Function(self.C00) # Copy from H_[1, :, 0, 0] (cannot use view since not contiguous)
155155
source = Array(self.C00)
156156
source[:] = -self.dpdy # dpdy set by subclass
157157
sol = chebyshev.la.Helmholtz if self.B0.family() == 'chebyshev' else la.Solver
@@ -164,13 +164,14 @@ def __init__(self,
164164
solver=sol,
165165
latex=r"\frac{\partial v}{\partial t} = \nu \frac{\partial^2 v}{\partial x^2} - N_y - \frac{\partial p}{\partial y}"),
166166
}
167-
168-
def convection(self):
167+
168+
def convection(self, rk):
169169
H = self.H_.v
170170
self.up = self.u_.backward(padding_factor=self.padding_factor)
171171
up = self.up.v
172172
if self.conv == 0:
173-
dudxp = self.dudx().backward(padding_factor=self.padding_factor).v
173+
dudx = self.dudx() if rk == 0 else self.dudx.output_array
174+
dudxp = dudx.backward(padding_factor=self.padding_factor).v
174175
dudyp = self.dudy().backward(padding_factor=self.padding_factor).v
175176
dvdxp = self.dvdx().backward(padding_factor=self.padding_factor).v
176177
dvdyp = self.dvdy().backward(padding_factor=self.padding_factor).v
@@ -192,7 +193,7 @@ def compute_v(self, rk):
192193

193194
# Find velocity components v from div. constraint
194195
u[1] = 1j*self.dudx()/self.K[1]
195-
196+
196197
# Still have to compute for wavenumber = 0, 0
197198
if comm.Get_rank() == 0:
198199
# v component
@@ -206,7 +207,6 @@ def compute_pressure(self):
206207
self.d2udx2 = Project(self.nu*Dx(self.u_[0], 0, 2), self.TC)
207208
N0 = self.N0 = FunctionSpace(self.N[0], self.B0.family(), bc={'left': {'N': self.d2udx2()}, 'right': {'N': self.d2udx2()}})
208209
TN = self.TN = TensorProductSpace(comm, (N0, self.F1), modify_spaces_inplace=True)
209-
#sol = chebyshev.la.Helmholtz if self.B0.family() == 'chebyshev' else la.SolverGeneric1ND
210210
sol = la.SolverGeneric1ND
211211
self.divH = Inner(TestFunction(TN), -div(self.H_))
212212
self.solP = sol(inner(TestFunction(TN), div(grad(TrialFunction(TN)))))
@@ -251,15 +251,15 @@ def tofile(self, tstep):
251251
self.file_u.write(tstep, {'u': [self.u_.backward(mesh='uniform')]}, as_scalar=True)
252252

253253
def prepare_step(self, rk):
254-
self.convection()
254+
self.convection(rk)
255255

256256
def assemble(self):
257257
for pde in self.pdes.values():
258258
pde.assemble()
259259
if comm.Get_rank() == 0:
260260
for pde in self.pdes1d.values():
261261
pde.assemble()
262-
262+
263263
def solve(self, t=0, tstep=0, end_time=1000):
264264
self.assemble()
265265
while t < end_time-1e-8:

demo/KleinGordon.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
ue = 0.1*exp(-(x**2 + y**2 + z**2))
3030

3131
# Size of discretization
32-
N = (32, 32, 32)
32+
N = (31, 32, 33)
3333

3434
# Defocusing or focusing
3535
gamma = 1
@@ -104,8 +104,8 @@ def update(self, fu, fu_hat, t, tstep, **params):
104104
if rank == 0 and tstep % params['plot_tstep'] == 0 and params['plot_tstep'] > 0:
105105
fu = fu_hat.backward(fu)
106106
f, u = fu[:]
107-
image.ax.clear()
108-
image.ax.contourf(X[1][..., 0], X[0][..., 0], u[..., N[2]//2], 100)
107+
#image.axes.clear()
108+
image.axes.contourf(X[1][..., 0], X[0][..., 0], u[..., N[2]//2], 100)
109109
plt.pause(1e-6)
110110
transformed = True
111111

@@ -144,7 +144,7 @@ def update(self, fu, fu_hat, t, tstep, **params):
144144
'write_tstep': (50, {'fu': [fu]}),
145145
'Compute_energy': 100,
146146
'plot_tstep': 100,
147-
'end_time': 100.,
147+
'end_time': 10.,
148148
'file': file0}
149149
dt = 0.005
150150
#integrator = ETDRK4(TT, N=NonlinearRHS, update=update, **par)

demo/OrrSommerfeld.py

-2
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,8 @@ def plot(self, t, tstep):
8282
if comm.Get_rank() == 0 and comm.Get_size() == 1:
8383
ub = self.u_.backward(self.ub)
8484
X = self.X
85-
self.im1.axes.clear()
8685
self.im1.axes.contourf(X[1][:, :, 0], X[0][:, :, 0], ub[0, :, :, 0], 100)
8786
self.im1.autoscale()
88-
self.im2.axes.clear()
8987
self.im2.axes.contourf(X[1][:, :, 0], X[0][:, :, 0], ub[1, :, :, 0], 100)
9088
self.im2.autoscale()
9189
self.im3.set_UVC(ub[1, :, :, 0]-(1-self.X[0][:, :, 0]**2), ub[0, :, :, 0])

demo/OrrSommerfeld2D.py

+13-15
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,26 @@
55

66
class OrrSommerfeld(KMM):
77

8-
def __init__(self, N=(32, 32), domain=((-1, 1), (0, 2*np.pi)), Re=8000.,
8+
def __init__(self, N=(32, 32), domain=((-1, 1), (0, 2*np.pi)), Re=8000., alfa=1.,
99
dt=0.1, conv=0, modplot=100, modsave=1e8, moderror=100, filename='KMM',
1010
family='C', padding_factor=(1, 1.5), checkpoint=1000, timestepper='IMEXRK3'):
11-
KMM.__init__(self, N=N, domain=domain, nu=1/Re, dt=dt, conv=conv, modplot=modplot,
11+
KMM.__init__(self, N=N, domain=(domain[0], (domain[1][0], domain[1][1]/alfa)), nu=1/Re, dt=dt, conv=conv, modplot=modplot,
1212
modsave=modsave, moderror=moderror, filename=filename, family=family,
1313
padding_factor=padding_factor, checkpoint=checkpoint, timestepper=timestepper,
1414
dpdy=-2/Re)
1515
self.Re = Re
16+
self.alfa = alfa
1617

1718
def initialize(self, from_checkpoint=False):
1819
if from_checkpoint:
1920
return self.init_from_checkpoint()
2021

2122
from OrrSommerfeld_eigs import OrrSommerfeld
22-
self.OS = OS = OrrSommerfeld(Re=self.Re, N=128)
23+
self.OS = OS = OrrSommerfeld(Re=self.Re, N=128, alfa=self.alfa)
2324
eigvals, eigvectors = OS.solve(False)
2425
OS.eigvals, OS.eigvectors = eigvals, eigvectors
2526
self.initOS(OS, eigvals, eigvectors, self.ub)
2627
self.u_ = self.ub.forward(self.u_)
27-
# Compute convection from data in context (i.e., context.U_hat and context.g)
28-
# This is the convection at t=0
2928
self.e0 = 0.5*dx(self.ub[0]**2+(self.ub[1]-(1-self.X[0]**2))**2)
3029
self.acc = np.zeros(1)
3130
return 0, 0
@@ -37,16 +36,16 @@ def initOS(self, OS, eigvals, eigvectors, U, t=0.):
3736
OS.eigval = eigval
3837
for j in range(U.shape[2]):
3938
y = X[1][0, j]
40-
v = (1-x**2) + 1e-7*np.real(dphidy*np.exp(1j*(y-eigval*t)))
41-
u = -1e-7*np.real(1j*phi*np.exp(1j*(y-eigval*t)))
39+
v = (1-x**2) + 1e-7*np.real(dphidy*np.exp(1j*self.alfa*(y-eigval*t)))
40+
u = -1e-7*np.real(1j*self.alfa*phi*np.exp(1j*self.alfa*(y-eigval*t)))
4241
U[0, :, j] = u
4342
U[1, :, j] = v
4443

4544
def compute_error(self, t):
4645
ub = self.u_.backward(self.ub)
4746
pert = (ub[1] - (1-self.X[0]**2))**2 + ub[0]**2
4847
e1 = 0.5*dx(pert)
49-
exact = np.exp(2*np.imag(self.OS.eigval)*t)
48+
exact = np.exp(2*np.imag(self.alfa*self.OS.eigval)*t)
5049
U0 = self.work[(ub, 0, True)]
5150
self.initOS(self.OS, self.OS.eigvals, self.OS.eigvectors, U0, t=t)
5251
pert = (ub[0] - U0[0])**2 + (ub[1] - U0[1])**2
@@ -80,10 +79,8 @@ def plot(self, t, tstep):
8079
if comm.Get_rank() == 0 and comm.Get_size() == 1:
8180
ub = self.u_.backward(self.ub)
8281
X = self.X
83-
self.im1.axes.clear()
8482
self.im1.axes.contourf(X[1], X[0], ub[0], 100)
8583
self.im1.autoscale()
86-
self.im2.axes.clear()
8784
self.im2.axes.contourf(X[1], X[0], ub[1], 100)
8885
self.im2.autoscale()
8986
self.im3.set_UVC(ub[1]-(1-self.X[0]**2), ub[0])
@@ -105,25 +102,26 @@ def print_energy_and_divergence(self, t, tstep):
105102
from mpi4py_fft import generate_xdmf
106103
t0 = time()
107104
N = (128, 32)
108-
config['optimization']['mode'] = 'numba'
105+
config['optimization']['mode'] = 'cython'
109106
d = {
110107
'N': N,
111108
'Re': 8000.,
112-
'dt': 0.01,
109+
'dt': 0.002,
113110
'filename': f'KMM_OS_{N[0]}_{N[1]}',
114111
'conv': 0,
115-
'modplot': 100,
112+
'alfa': 1,
113+
'modplot': -1,
116114
'modsave': 1000,
117115
'moderror': 10,
118116
'family': 'C',
119117
'checkpoint': 10000000,
120118
'padding_factor': 1,
121-
'timestepper': 'IMEXRK222'
119+
'timestepper': 'IMEXRK443'
122120
}
123121
OS = True
124122
c = OrrSommerfeld(**d)
125123
t, tstep = c.initialize(from_checkpoint=False)
126-
c.solve(t=t, tstep=tstep, end_time=1)
124+
c.solve(t=t, tstep=tstep, end_time=0.1)
127125
print('Computing time %2.4f'%(time()-t0))
128126
if comm.Get_rank() == 0:
129127
generate_xdmf('_'.join((d['filename'], 'U'))+'.h5')

shenfun/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"""
3030
#pylint: disable=wildcard-import,no-name-in-module
3131

32-
__version__ = '4.2.0'
32+
__version__ = '4.2.1'
3333
__author__ = 'Mikael Mortensen'
3434

3535
import numpy as np

shenfun/forms/arguments.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ def FunctionSpace(N, family='Fourier', bc=None, dtype='d', quad=None,
346346
else:
347347
raise NotImplementedError
348348
B = bases[''.join(key)]
349-
349+
350350
return B(N, **par)
351351

352352
elif family.lower() in ('hermite', 'h'):

shenfun/la.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ def perform_lu(self):
132132
if self._lu is None:
133133
if isinstance(self.mat, SparseMatrix):
134134
self.mat = self.mat.diags('csc')
135+
self.mat.eliminate_zeros()
136+
if self.mat.nnz < 2:
137+
self._lu = None
138+
return self._lu
135139
self._lu = splu(self.mat, permc_spec=config['matrix']['sparse']['permc_spec'])
136140
self.dtype = self.mat.dtype.char
137141
self._inner_arg = (self._lu, self.dtype)
@@ -238,7 +242,8 @@ def __call__(self, b, u=None, axis=0, constraints=()):
238242
b = self.apply_bcs(b, u, axis=axis)
239243
b = self.apply_constraints(b, constraints, axis=axis)
240244
lu = self.perform_lu() # LU must be performed after constraints, because constraints modify the matrix
241-
u = self.solve(b, u, axis, lu)
245+
if not lu is None:
246+
u = self.solve(b, u, axis, lu)
242247
if hasattr(u, 'set_boundary_dofs'):
243248
u.set_boundary_dofs()
244249
return u
@@ -838,7 +843,6 @@ def __init__(self, mats, format=None):
838843
SparseMatrixSolver.__init__(self, mats)
839844
self.mat = self.mat.diags(format)
840845

841-
842846
class SolverGeneric2ND:
843847
"""Generic solver for problems consisting of tensorproduct matrices
844848
containing two non-diagonal submatrices.
@@ -1371,15 +1375,17 @@ def solve(self, u, b, solvers1D, naxes):
13711375
for i, sol in enumerate(solvers1D):
13721376
s[paxes[0]] = i
13731377
s0 = tuple(s)
1374-
sol.inner_solve(u[s0], sol._inner_arg)
1378+
if sol._inner_arg is not None:
1379+
sol.inner_solve(u[s0], sol._inner_arg)
13751380

13761381
elif u.ndim == 3:
13771382
for i, m in enumerate(solvers1D):
13781383
s[paxes[0]] = i
13791384
for j, sol in enumerate(m):
13801385
s[paxes[1]] = j
13811386
s0 = tuple(s)
1382-
sol.inner_solve(u[s0], sol._inner_arg)
1387+
if sol._inner_arg is not None:
1388+
sol.inner_solve(u[s0], sol._inner_arg)
13831389

13841390
def __call__(self, b, u=None, constraints=(), fast=True):
13851391
"""Solve problem with one non-diagonal direction
@@ -1472,9 +1478,7 @@ def __call__(self, b, u=None, constraints=()):
14721478
space = b.function_space()
14731479
if u is None:
14741480
u = Function(space)
1475-
else:
1476-
assert u.shape == b.shape
1477-
1481+
14781482
if self.bc_mat: # Add contribution to right hand side due to inhomogeneous boundary conditions
14791483
u.set_boundary_dofs()
14801484
w0 = np.zeros_like(b)

shenfun/matrixbase.py

+3
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,9 @@ def get_solver(self):
446446
"""
447447
from .la import (Solve, TDMA, TDMA_O, FDMA, TwoDMA, ThreeDMA, PDMA,
448448
DiagMA, HeptaDMA)
449+
if self.scale == 0:
450+
return Solve
451+
449452
if len(self) == 1:
450453
if list(self.keys())[0] == 0:
451454
return DiagMA

shenfun/utilities/findbasis.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,10 @@ def get_stencil_matrix(bcs, family, alpha=None, beta=None, gn=1):
4646
r = []
4747
for key in bcs.orderednames():
4848
k, v = key[0], key[1:]
49-
if v == 'R':
50-
alfa = bcs[lra[k]]['R'][0]
51-
f = [bnd_values(k=0)[lr[k]], bnd_values(k=1)[lr[k]]]
49+
if v in 'WR':
50+
k0 = 0 if v == 'R' else 1
51+
alfa = bcs[lra[k]][v][0]
52+
f = [bnd_values(k=k0)[lr[k]], bnd_values(k=k0+1)[lr[k]]]
5253
s.append([sp.simplify(f[0](n+j)+alfa*f[1](n+j)) for j in range(1, 1+bcs.num_bcs())])
5354
r.append(-sp.simplify(f[0](n)+alfa*f[1](n)))
5455
else:
@@ -100,9 +101,10 @@ def _computematrix(first):
100101
s = []
101102
for key in bcs.orderednames():
102103
k, v = key[0], key[1:]
103-
if v == 'R':
104-
alfa = bcs[lra[k]]['R'][0]
105-
f = [bnd_values(k=0)[lr[k]], bnd_values(k=1)[lr[k]]]
104+
if v in 'WR':
105+
k0 = 0 if v == 'R' else 1
106+
alfa = bcs[lra[k]][v][0]
107+
f = [bnd_values(k=k0)[lr[k]], bnd_values(k=k0+1)[lr[k]]]
106108
s.append([sp.simplify(f[0](j)+alfa*f[1](j)) for j in range(first, first+bcs.num_bcs())])
107109
else:
108110
f = bnd_values(k=bc[v])[lr[k]]

0 commit comments

Comments
 (0)