@@ -308,21 +308,25 @@ def select_expression(expressions, index):
308308 return ComponentTensor (selected , alpha )
309309
310310
311- def delta_elimination (sum_indices , factors ):
311+ def delta_elimination (sum_indices , factors , index_replacer = None ):
312312 """IndexSum-Delta cancellation.
313313
314314 :arg sum_indices: free indices for contractions
315315 :arg factors: product factors
316+ :kwarg index_replacer: MemoizerArg(filtered_replace_indices)
317+
316318 :returns: optimised (sum_indices, factors)
317319 """
320+ if index_replacer is None :
321+ index_replacer = MemoizerArg (filtered_replace_indices )
322+
318323 sum_indices = list (sum_indices ) # copy for modification
319324
320325 def substitute (expression , from_ , to_ ):
321326 if from_ not in expression .free_indices :
322327 return expression
323328 elif isinstance (expression , Delta ):
324- mapper = MemoizerArg (filtered_replace_indices )
325- return mapper (expression , ((from_ , to_ ),))
329+ return index_replacer (expression , ((from_ , to_ ),))
326330 else :
327331 return Indexed (ComponentTensor (expression , (from_ ,)), (to_ ,))
328332
@@ -490,9 +494,9 @@ def applier(expr):
490494 return partial (_renamer , rename_map , set ())
491495
492496
493- def traverse_product (expression , stop_at = None , rename_map = None ):
497+ def traverse_product (expression , stop_at = None , rename_map = None , index_replacer = None ):
494498 """Traverses a product tree and collects factors, also descending into
495- tensor contractions (IndexSum). The nominators of divisions are
499+ tensor contractions (IndexSum). The numerators of divisions are
496500 also broken up, but not the denominators.
497501
498502 :arg expression: a GEM expression
@@ -501,13 +505,17 @@ def traverse_product(expression, stop_at=None, rename_map=None):
501505 subexpression is not broken into further factors
502506 even if it is a product-like expression.
503507 :arg rename_map: an rename map for consistent index renaming
508+ :kwarg index_replacer: MemoizerArg(filtered_replace_indices)
509+
504510 :returns: (sum_indices, terms)
505511 - sum_indices: list of indices to sum over
506512 - terms: list of product terms
507513 """
508514 if rename_map is None :
509515 rename_map = make_rename_map ()
510516 renamer = make_renamer (rename_map )
517+ if index_replacer is None :
518+ index_replacer = MemoizerArg (filtered_replace_indices )
511519
512520 sum_indices = []
513521 terms = []
@@ -520,7 +528,7 @@ def traverse_product(expression, stop_at=None, rename_map=None):
520528 elif isinstance (expr , IndexSum ):
521529 indices , applier = renamer (expr .multiindex )
522530 sum_indices .extend (indices )
523- stack .extend (remove_componenttensors ( map ( applier , expr .children )) )
531+ stack .extend (index_replacer ( applier ( c ), ()) for c in expr .children )
524532 elif isinstance (expr , Product ):
525533 stack .extend (reversed (expr .children ))
526534 elif isinstance (expr , Division ):
@@ -575,13 +583,18 @@ def contraction(expression, ignore=None):
575583 This routine was designed with finite element coefficient
576584 evaluation in mind.
577585 """
586+
587+ # Common memoizer to remove ComponentTensors
588+ index_replacer = MemoizerArg (filtered_replace_indices )
589+
578590 # Eliminate annoying ComponentTensors
579- expression , = remove_componenttensors ([ expression ] )
591+ expression = index_replacer ( expression , () )
580592
581593 # Flatten product tree, eliminate deltas, sum factorise
582594 def rebuild (expression ):
583- sum_indices , factors = delta_elimination (* traverse_product (expression ))
584- factors = remove_componenttensors (factors )
595+ sum_indices , factors = traverse_product (expression , index_replacer = index_replacer )
596+ sum_indices , factors = delta_elimination (sum_indices , factors , index_replacer = index_replacer )
597+ factors = [index_replacer (f , ()) for f in factors ]
585598 if ignore is not None :
586599 # TODO: This is a really blunt instrument and one might
587600 # plausibly want the ignored indices to be contracted on
@@ -610,7 +623,7 @@ def rebuild(expression):
610623 # Rebuild each split component
611624 tensor = ComponentTensor (expression , lt_fis )
612625 entries = [Indexed (tensor , zeta ) for zeta in numpy .ndindex (tensor .shape )]
613- entries = remove_componenttensors ( entries )
626+ entries = [ index_replacer ( e , ()) for e in entries ]
614627 return Indexed (ListTensor (
615628 numpy .array (list (map (rebuild , entries ))).reshape (tensor .shape )
616629 ), lt_fis )
0 commit comments