Skip to content

Commit dc4decb

Browse files
committed
Add SphereEllProduct and tests
1 parent 8b709a9 commit dc4decb

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

dedalus/core/operators.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2654,6 +2654,36 @@ def operate(self, out):
26542654
comp_out += symbols * comp_in # TEMPORARY
26552655

26562656

2657+
class SphereEllProduct(SeparableSphereOperator):
2658+
2659+
name = "SphereEllProduct"
2660+
complex_operator = False
2661+
subaxis_dependence = [False, True]
2662+
2663+
def __init__(self, operand, coordsys, ell_r_func, out=None):
2664+
super().__init__(operand, out=out)
2665+
self.ell_r_func = ell_r_func
2666+
self.coordsys = coordsys
2667+
self.operand = operand
2668+
self.input_basis = operand.domain.get_basis(coordsys)
2669+
self.output_basis = self.input_basis
2670+
self.first_axis = self.input_basis.first_axis
2671+
self.last_axis = self.input_basis.last_axis
2672+
# FutureField requirements
2673+
self.domain = operand.domain
2674+
self.tensorsig = operand.tensorsig
2675+
self.dtype = operand.dtype
2676+
2677+
def symbol(self, spinindex_in, spinindex_out, local_ell, radius):
2678+
return self.ell_r_func(local_ell, radius)
2679+
2680+
def new_operand(self, operand, **kw):
2681+
return SphereEllProduct(operand, self.coordsys, self.ell_r_func, **kw)
2682+
2683+
def spinindex_out(self, spinindex_in):
2684+
return (spinindex_in,)
2685+
2686+
26572687
class PolarMOperator(SpectralOperator):
26582688

26592689
subaxis_dependence = [True, True] # Depends on m and n

dedalus/tests/test_sphere2D_calculus.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,3 +470,36 @@ def test_divergence_cleaning(Nphi, Ntheta, dealias, dtype):
470470
h.change_scales(1)
471471
assert np.allclose(u['g'], h['g'])
472472

473+
474+
@pytest.mark.parametrize('Nphi', Nphi_range)
475+
@pytest.mark.parametrize('Ntheta', Ntheta_range)
476+
@pytest.mark.parametrize('dealias', dealias_range)
477+
@pytest.mark.parametrize('dtype', [np.float64, np.complex128])
478+
def test_sphere_ell_product_scalar(Nphi, Ntheta, dealias, dtype):
479+
c, d, b, phi, theta = build_sphere(Nphi, Ntheta, dealias, dtype)
480+
f = field.Field(dist=d, bases=(b,), dtype=dtype)
481+
g = field.Field(dist=d, bases=(b,), dtype=dtype)
482+
f.fill_random('g')
483+
func = lambda ell, r: ell + 3
484+
for ell, m_ind, ell_ind in b.ell_maps:
485+
g['c'][m_ind, ell_ind] = func(ell, b.radius) * f['c'][m_ind, ell_ind]
486+
h = operators.SphereEllProduct(f, c, func).evaluate()
487+
assert np.allclose(g['c'], h['c'])
488+
489+
490+
@pytest.mark.parametrize('Nphi', Nphi_range)
491+
@pytest.mark.parametrize('Ntheta', Ntheta_range)
492+
@pytest.mark.parametrize('dealias', dealias_range)
493+
@pytest.mark.parametrize('dtype', [np.float64, np.complex128])
494+
def test_sphere_ell_product_vector(Nphi, Ntheta, dealias, dtype):
495+
c, d, b, phi, theta = build_sphere(Nphi, Ntheta, dealias, dtype)
496+
f = field.Field(dist=d, bases=(b,), dtype=dtype, tensorsig=(c,))
497+
g = field.Field(dist=d, bases=(b,), dtype=dtype, tensorsig=(c,))
498+
f.fill_random('g')
499+
func = lambda ell, r: ell + 3
500+
for ell, m_ind, ell_ind in b.ell_maps:
501+
for i in range(c.dim):
502+
g['c'][i, m_ind, ell_ind] = func(ell, b.radius) * f['c'][i, m_ind, ell_ind]
503+
h = operators.SphereEllProduct(f, c, func).evaluate()
504+
assert np.allclose(g['c'], h['c'])
505+

0 commit comments

Comments
 (0)