1919from ..tools .cache import CachedAttribute
2020from ..tools .cache import CachedMethod
2121from ..tools .cache import CachedClass
22- from ..tools import jacobi
2322from ..tools import clenshaw
2423from ..tools .array import reshape_vector , axindex , axslice , interleave_matrices
2524from ..tools .dispatch import MultiClass , SkipDispatchException
2625from ..tools .general import unify , DeferredTuple
2726
28- from .spaces import ParityInterval , Disk
2927from .coords import Coordinate , CartesianCoordinates , S2Coordinates , SphericalCoordinates , PolarCoordinates , AzimuthalCoordinate
3028from .domain import Domain
3129from .field import Operand , LockedField
@@ -478,23 +476,19 @@ def __init__(self, coord, size, bounds, a, b, a0=None, b0=None, dealias=1, libra
478476 self .b0 = float (b0 )
479477 self .library = library
480478 self .grid_params = (coord , bounds , a0 , b0 )
481- self .constant_mode_value = 1 / np .sqrt (jacobi .mass (self .a , self .b ))
479+ self .constant_mode_value = ( 1 / np .sqrt (dedalus_sphere . jacobi .mass (self .a , self .b ))). astype ( np . float64 )
482480
483481 def _native_grid (self , scale ):
484482 """Native flat global grid."""
485483 N , = self .grid_shape ((scale ,))
486- return jacobi .build_grid (N , a = self .a0 , b = self .b0 )
484+ grid , weights = dedalus_sphere .jacobi .quadrature (N , self .a0 , self .b0 )
485+ return grid .astype (np .float64 )
487486
488487 @CachedMethod
489488 def transform_plan (self , grid_size ):
490489 """Build transform plan."""
491490 return self .transforms [self .library ](grid_size , self .size , self .a , self .b , self .a0 , self .b0 )
492491
493- # def weights(self, scales):
494- # """Gauss-Jacobi weights."""
495- # N = self.grid_shape(scales)[0]
496- # return jacobi.build_weights(N, a=self.a, b=self.b)
497-
498492 # def __str__(self):
499493 # space = self.space
500494 # cls = self.__class__
@@ -556,14 +550,30 @@ def Jacobi_matrix(self, size):
556550 size = self .size
557551 return dedalus_sphere .jacobi .operator ('Z' )(size , self .a , self .b ).square
558552
553+ @staticmethod
554+ def conversion_matrix (N , a0 , b0 , a1 , b1 ):
555+ if not float (a1 - a0 ).is_integer ():
556+ raise ValueError ("a0 and a1 must be integer-separated" )
557+ if not float (b1 - b0 ).is_integer ():
558+ raise ValueError ("b0 and b1 must be integer-separated" )
559+ if a0 > a1 :
560+ raise ValueError ("a0 must be less than or equal to a1" )
561+ if b0 > b1 :
562+ raise ValueError ("b0 must be less than or equal to b1" )
563+ A = dedalus_sphere .jacobi .operator ('A' )(+ 1 )
564+ B = dedalus_sphere .jacobi .operator ('B' )(+ 1 )
565+ da , db = int (a1 - a0 ), int (b1 - b0 )
566+ conv = A ** da @ B ** db
567+ return conv (N , a0 , b0 ).astype (np .float64 )
568+
559569 def ncc_matrix (self , arg_basis , coeffs , cutoff = 1e-6 ):
560570 """Build NCC matrix via Clenshaw algorithm."""
561571 if arg_basis is None :
562572 return super ().ncc_matrix (arg_basis , coeffs )
563573 # Kronecker Clenshaw on argument Jacobi matrix
564574 elif isinstance (arg_basis , Jacobi ):
565575 N = self .size
566- J = jacobi .jacobi_matrix ( N , arg_basis .a , arg_basis .b )
576+ J = dedalus_sphere . jacobi .operator ( 'Z' )( N , arg_basis .a , arg_basis .b ). square . astype ( np . float64 )
567577 A , B = clenshaw .jacobi_recursion (N , self .a , self .b , J )
568578 f0 = self .const * sparse .identity (N )
569579 total = clenshaw .kronecker_clenshaw (coeffs , A , B , f0 , cutoff = cutoff )
@@ -595,7 +605,7 @@ def _last_axis_component_ncc_matrix(cls, subproblem, ncc_basis, arg_basis, out_b
595605 A , B = clenshaw .jacobi_recursion (Nmat , a_ncc , b_ncc , J )
596606 f0 = dedalus_sphere .jacobi .polynomials (1 , a_ncc , b_ncc , 1 )[0 ].astype (np .float64 ) * sparse .identity (Nmat )
597607 matrix = clenshaw .matrix_clenshaw (coeffs .ravel (), A , B , f0 , cutoff = cutoff )
598- convert = jacobi .conversion_matrix (Nmat , arg_basis .a , arg_basis .b , out_basis .a , out_basis .b )
608+ convert = Jacobi .conversion_matrix (Nmat , arg_basis .a , arg_basis .b , out_basis .a , out_basis .b )
599609 matrix = convert @ matrix
600610 return matrix [:N , :N ]
601611
@@ -647,7 +657,7 @@ def _full_matrix(input_basis, output_basis):
647657 N = input_basis .size
648658 a0 , b0 = input_basis .a , input_basis .b
649659 a1 , b1 = output_basis .a , output_basis .b
650- matrix = jacobi .conversion_matrix (N , a0 , b0 , a1 , b1 )
660+ matrix = Jacobi .conversion_matrix (N , a0 , b0 , a1 , b1 )
651661 return matrix .tocsr ()
652662
653663
@@ -686,8 +696,9 @@ def _output_basis(input_basis):
686696 def _full_matrix (input_basis , output_basis ):
687697 N = input_basis .size
688698 a , b = input_basis .a , input_basis .b
689- matrix = jacobi .differentiation_matrix (N , a , b ) / input_basis .COV .stretch
690- return matrix .tocsr ()
699+ native_matrix = dedalus_sphere .jacobi .operator ('D' )(+ 1 )(N , a , b ).square .astype (np .float64 )
700+ problem_matrix = native_matrix / input_basis .COV .stretch
701+ return problem_matrix .tocsr ()
691702
692703
693704class InterpolateJacobi (operators .Interpolate , operators .SpectralOperator1D ):
@@ -709,9 +720,9 @@ def _full_matrix(input_basis, output_basis, position):
709720 N = input_basis .size
710721 a , b = input_basis .a , input_basis .b
711722 x = input_basis .COV .native_coord (position )
712- interp_vector = jacobi . build_polynomials ( N , a , b , x )
713- # Return with shape (1, N)
714- return interp_vector [ None , :]
723+ x = np . array ([ x ] )
724+ matrix = dedalus_sphere . jacobi . polynomials ( N , a , b , x ). T
725+ return matrix . astype ( np . float64 )
715726
716727
717728class IntegrateJacobi (operators .Integrate , operators .SpectralOperator1D ):
@@ -731,7 +742,7 @@ def _full_matrix(input_basis, output_basis):
731742 # Build native integration vector
732743 N = input_basis .size
733744 a , b = input_basis .a , input_basis .b
734- integ_vector = jacobi .integration_vector (N , a , b )
745+ integ_vector = dedalus_sphere . jacobi .polynomial_integrals (N , a , b ). astype ( np . float64 )
735746 # Rescale and return with shape (1, N)
736747 return integ_vector [None , :] * input_basis .COV .stretch
737748
@@ -753,7 +764,7 @@ def _full_matrix(input_basis, output_basis):
753764 # Build native integration vector
754765 N = input_basis .size
755766 a , b = input_basis .a , input_basis .b
756- integ_vector = jacobi .integration_vector (N , a , b )
767+ integ_vector = dedalus_sphere . jacobi .polynomial_integrals (N , a , b ). astype ( np . float64 )
757768 ave_vector = integ_vector / 2
758769 # Rescale and return with shape (1, N)
759770 return ave_vector [None , :]
0 commit comments