@@ -379,34 +379,6 @@ def _get_initial_order_off_axis(recurrence):
379379 r_c = recurrence .subs (n , i )
380380 return i
381381
382- def move_center_origin_source_arbitrary_expression (pde : LinearPDESystemOperator ) -> sp .Expr :
383- r"""
384- A function that "shifts" the recurrence so it's center is placed
385- at the origin and source is the input for the recurrence generated.
386- Outputs an expression that evaluates to 0 rather than s(n) in terms
387- of s(n-1), etc. This is different from move_center_origin_source_arbitrary,
388- because we are "shifting" an EXPRESSION, not s(n) in terms of s(n-1), etc.
389-
390- :arg recurrence: a recurrence relation in :math:`s(n)`
391- """
392- r = recurrence_from_pde (pde )
393-
394- idx_l , terms = _extract_idx_terms_from_recurrence (r )
395-
396- # How much do we need to shift the recurrence relation
397- shift_idx = max (idx_l )
398-
399- n = sp .symbols ("n" )
400- r = r .subs (n , n - shift_idx )
401-
402- idx_l , terms = _extract_idx_terms_from_recurrence (r )
403-
404- r_ret = r
405- for i in range (len (idx_l )):
406- r_ret = r_ret .subs (terms [i ], (- 1 )** (n + idx_l [i ])* terms [i ])
407-
408- return r_ret , (max (idx_l )+ 1 - min (idx_l ))
409-
410382
411383def move_center_origin_source_arbitrary (r : sp .Expr ) -> sp .Expr :
412384 r"""
@@ -415,8 +387,8 @@ def move_center_origin_source_arbitrary(r: sp.Expr) -> sp.Expr:
415387 Assuming the recurrence is formulated so that evaluating it gives
416388 s(n) in terms of s(n-1), .., etc. We do NOT want a recurrence
417389 EXPRESSION as input, i.e. an expression containing s(n), s(n-1),
418- ..., that evaluates to 0.
419- Use move_center_origin_source_arbitrary_expression for this .
390+ ..., that evaluates to 0.
391+ Use move_center_origin_source_arbitrary_expression for EXPRESSIONS .
420392
421393 :arg recurrence: a recurrence relation in :math:`s(n)`
422394 """
@@ -431,7 +403,7 @@ def move_center_origin_source_arbitrary(r: sp.Expr) -> sp.Expr:
431403 return r_ret * ((- 1 )** (n + 1 ))
432404
433405
434- def get_reindexed_and_center_origin_recurrence (pde ) -> tuple [int , int ,
406+ def get_reindexed_and_center_origin_on_axis_recurrence (pde ) -> tuple [int , int ,
435407 sp .Expr ]:
436408 r"""
437409 A function that "shifts" the recurrence so the expansion center is placed
@@ -453,24 +425,70 @@ def get_reindexed_and_center_origin_recurrence(pde) -> tuple[int, int,
453425 return n_initial , order , r_s
454426
455427# ================ OFF-AXIS RECURRENCE =================
456- def get_off_axis_recurrence (pde : LinearPDESystemOperator ) -> sp .Expr :
428+ def move_center_origin_source_arbitrary_expression (pde : LinearPDESystemOperator ) -> sp .Expr :
457429 r"""
458- A function that takes in as input a pde and outputs a SHIFTED
459- + REINDEXED off-axis recurrence
430+ A function that "shifts" the recurrence so it's center is placed
431+ at the origin and source is the input for the recurrence generated.
432+ Outputs an expression that evaluates to 0 rather than s(n) in terms
433+ of s(n-1), etc. This is different from move_center_origin_source_arbitrary,
434+ because we are "shifting" an EXPRESSION, not s(n) in terms of s(n-1), etc.
435+
436+ :arg recurrence: a recurrence relation in :math:`s(n)`
437+ """
438+ r = recurrence_from_pde (pde )
439+
440+ idx_l , terms = _extract_idx_terms_from_recurrence (r )
441+ n = sp .symbols ("n" )
442+
443+ r_ret = r
444+ for i in range (len (idx_l )):
445+ r_ret = r_ret .subs (terms [i ], (- 1 )** (n + idx_l [i ])* terms [i ])
446+
447+ return r_ret
448+
449+ def get_reindexed_and_center_origin_off_axis_recurrence (pde : LinearPDESystemOperator ) -> sp .Expr :
450+ r"""
451+ A function that takes in as input a pde and outputs a off-axis recurrence
452+ for derivatives taken at the origin with an arbitrary source location.
453+ The recurrence is reindexed so it gives s(n) in terms of s(n-1), ..., etc.
460454 """
461455 var = _make_sympy_vec ("x" , 1 )
462- r_exp = move_center_origin_source_arbitrary_expression (pde )[ 0 ] .subs (var [0 ], 0 )
456+ r_exp = move_center_origin_source_arbitrary_expression (pde ).subs (var [0 ], 0 )
463457 recur_order , recur = reindex_recurrence_relation (r_exp )
464- print (recur )
465458 start_order = _get_initial_order_off_axis (recur )
466459 return start_order , recur_order , recur
467460
468- def get_taylor_expression (pde , deriv_order , taylor_order = 4 ):
469- #recursively substitute, and output the "order" of the taylor expression
470- t_recurrence = get_off_axis_recurrence (pde )[2 ]
471- var = _make_sympy_vec ("x" , 2 )
461+
462+ def get_off_axis_expression (pde , taylor_order = 4 ):
463+ r"""
464+ A function that takes in as input a pde, and outputs
465+ the Taylor expression that gives the deriv_order th derivative
466+ to a taylor_order order Taylor series with respect to x_1 and
467+ s(i) where s(i) comes from the off-axis recurrence. See
468+ get_reindexed_and_center_origin_off_axis_recurrence.
469+ """
470+ s = sp .Function ("s" )
472471 n = sp .symbols ("n" )
472+ deriv_order = n
473+
474+ t_recurrence = get_reindexed_and_center_origin_off_axis_recurrence (pde )[2 ]
475+ var = _make_sympy_vec ("x" , 2 )
473476 exp = 0
474477 for i in range (taylor_order ):
475478 exp += t_recurrence .subs (n , deriv_order + i )/ math .factorial (i ) * var [0 ]** i
476- return exp
479+
480+ #While derivatives w/order larger than the deriv_order exist in our taylor expression
481+ #replace them with smaller order derivatives
482+ idx_l , _ = _extract_idx_terms_from_recurrence (exp )
483+ max_idx = max (idx_l )
484+
485+ while max_idx > 0 :
486+ for ind in idx_l :
487+ if ind > 0 :
488+ exp = exp .subs (s (n + ind ), t_recurrence .subs (n , n + ind ))
489+
490+ idx_l , _ = _extract_idx_terms_from_recurrence (exp )
491+ max_idx = max (idx_l )
492+ exp_range = max (idx_l ) - min (idx_l )
493+
494+ return exp , exp_range
0 commit comments