Nektar++
Classes | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Private Member Functions | Static Private Attributes | List of all members
CellMLToNektar.optimize.LookupTableAnalyser Class Reference
Inheritance diagram for CellMLToNektar.optimize.LookupTableAnalyser:
[legend]

Classes

class  LUTState
 

Public Member Functions

def __init__ (self)
 
def config (self)
 
def var_is_membrane_potential (self, var)
 
def is_allowed_variable (self, var)
 
def is_keying_var (self, var)
 
def set_params (self, **kw)
 
def get_param (self, param_name, table_var)
 
def create_state_from_annotations (self, expr)
 
def analyse_for_lut (self, expr, var_checker_fn)
 
def check_divide_by_table (self, expr, operand_states)
 
def check_commutative_tables (self, expr, operand_states)
 
def annotate_as_suitable (self, expr, table_var)
 
def remove_lut_annotations (self, expr, remove_reason=False)
 
def analyse_model (self, doc, solver_info, annotate_failures=True, annotate_outermost_only=True)
 
def calculate_dependencies (self, expr)
 

Static Public Member Functions

def copy_lut_annotations (from_expr, to_expr)
 

Public Attributes

 doc
 
 solver_info
 
 annotate_failures
 
 annotate_outermost_only
 

Static Public Attributes

 lut_expensive_funcs
 

Private Member Functions

def _find_tables (self, expr, table_dict)
 
def _determine_unneeded_tables (self)
 
def _determine_duplicate_tables (self)
 

Static Private Attributes

dictionary _LT_DEFAULTS
 

Detailed Description

Analyses & annotates a CellML model to indicate where lookup
tables can be used.

Definition at line 384 of file optimize.py.

Constructor & Destructor Documentation

◆ __init__()

def CellMLToNektar.optimize.LookupTableAnalyser.__init__ (   self)
Create an analyser.

Definition at line 390 of file optimize.py.

390 def __init__(self):
391 """Create an analyser."""
392 # No model to analyse yet
393 self.doc = None
394 # Set default parameter values
395 self.set_params()
396

Member Function Documentation

◆ _determine_duplicate_tables()

def CellMLToNektar.optimize.LookupTableAnalyser._determine_duplicate_tables (   self)
private
Determine whether we have multiple tables for the same expression.

Any expression that is identical to a previous table will be re-annotated to refer to the
previous table, instead of declaring a new one.

This is a temporary measure until we have proper sub-expression elimination for the Jacobian
and residual calculations.

Definition at line 860 of file optimize.py.

860 def _determine_duplicate_tables(self):
861 """Determine whether we have multiple tables for the same expression.
862
863 Any expression that is identical to a previous table will be re-annotated to refer to the
864 previous table, instead of declaring a new one.
865
866 This is a temporary measure until we have proper sub-expression elimination for the Jacobian
867 and residual calculations.
868 """
869 uniq_tables = []
870 for expr in self.doc.lookup_tables:
871 for table in uniq_tables:
872 if expr.same_tree(table):
873 lt_name = table.getAttributeNS(NSS['lut'], u'table_name', u'')
874 # Need to remove old name before we can set a new one (grr amara)
875 del expr.table_name
876 expr.xml_set_attribute((u'lut:table_name', NSS['lut']), lt_name)
877 break
878 else:
879 uniq_tables.append(expr)
880

References Nektar::LibUtilities::H5DataSource.doc, CellMLToNektar.optimize.PartialEvaluator.doc, CellMLToNektar.optimize.LookupTableAnalyser.doc, CellMLToNektar.translators.CellMLTranslator.doc, and CellMLToNektar.translators.ConfigurationStore.doc.

◆ _determine_unneeded_tables()

def CellMLToNektar.optimize.LookupTableAnalyser._determine_unneeded_tables (   self)
private
Determine whether some expressions identified as lookup tables aren't actually used.

This occurs if some ODEs have been linearised, in which case the original definitions
will have been analysed for lookup tables, but aren't actually used.

TODO: The original definitions might be used for computing derived quantities...

Definition at line 834 of file optimize.py.

834 def _determine_unneeded_tables(self):
835 """Determine whether some expressions identified as lookup tables aren't actually used.
836
837 This occurs if some ODEs have been linearised, in which case the original definitions
838 will have been analysed for lookup tables, but aren't actually used.
839
840 TODO: The original definitions might be used for computing derived quantities...
841 """
842 original_tables = {}
843 new_tables = {}
844 def f(exprs, table_dict):
845 exprs = filter(lambda n: isinstance(n, (mathml_ci, mathml_apply, mathml_piecewise)), exprs)
846 for node in self.doc.model.calculate_extended_dependencies(exprs):
847 if isinstance(node, mathml_apply):
848 self._find_tables(node, table_dict)
849 for u, t, eqns in self.solver_info.get_linearised_odes():
850 original_defn = u.get_ode_dependency(t)
851 f([original_defn], original_tables)
852 f(eqns, new_tables)
853 for id_ in set(original_tables.keys()) - set(new_tables.keys()):
854 expr = original_tables[id_]
855 self.remove_lut_annotations(expr)
856 expr.xml_set_attribute((u'lut:reason', NSS['lut']),
857 u'Expression will not be used in generated code.')
858 DEBUG('lookup-tables', 'Not annotating probably unused expression', expr)
859
def DEBUG(facility, *args)
Definition: utilities.py:95

References CellMLToNektar.optimize.LookupTableAnalyser._find_tables(), CellMLToNektar.utilities.DEBUG(), Nektar::LibUtilities::H5DataSource.doc, CellMLToNektar.optimize.PartialEvaluator.doc, CellMLToNektar.optimize.LookupTableAnalyser.doc, CellMLToNektar.translators.CellMLTranslator.doc, CellMLToNektar.translators.ConfigurationStore.doc, CellMLToNektar.optimize.LookupTableAnalyser.remove_lut_annotations(), CellMLToNektar.optimize.PartialEvaluator.solver_info, and CellMLToNektar.optimize.LookupTableAnalyser.solver_info.

◆ _find_tables()

def CellMLToNektar.optimize.LookupTableAnalyser._find_tables (   self,
  expr,
  table_dict 
)
private
Helper method for _determine_unneeded_tables.

Definition at line 826 of file optimize.py.

826 def _find_tables(self, expr, table_dict):
827 """Helper method for _determine_unneeded_tables."""
828 if expr.getAttributeNS(NSS['lut'], u'possible', '') == u'yes':
829 table_dict[id(expr)] = expr
830 else:
831 for e in self.doc.model.xml_element_children(expr):
832 self._find_tables(e, table_dict)
833

References CellMLToNektar.optimize.LookupTableAnalyser._find_tables(), Nektar::LibUtilities::H5DataSource.doc, CellMLToNektar.optimize.PartialEvaluator.doc, CellMLToNektar.optimize.LookupTableAnalyser.doc, CellMLToNektar.translators.CellMLTranslator.doc, and CellMLToNektar.translators.ConfigurationStore.doc.

Referenced by CellMLToNektar.optimize.LookupTableAnalyser._determine_unneeded_tables(), and CellMLToNektar.optimize.LookupTableAnalyser._find_tables().

◆ analyse_for_lut()

def CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut (   self,
  expr,
  var_checker_fn 
)
Check if the given expression can be replaced by a lookup table.

The first argument is the expression to check; the second is a
function which takes a variable object and returns True iff this
variable is permitted within a lookup table expression.

If self.annotate_failures is True then annotate <apply> and
<piecewise> expressions which don't qualify with the reason
why they do not.
This can be:
 'no_var' - doesn't contain the table variable
 'bad_var <vname>' - contains a variable which isn't permitted
 'no_func' - doesn't contain an expensive function
or a comma separated combination of the above.
The annotation is stored as the lut:reason attribute.

If self.annotate_outermost_only is True then only annotate the
outermost qualifying expression, rather than also annotating
qualifying subexpressions.

Definition at line 556 of file optimize.py.

556 def analyse_for_lut(self, expr, var_checker_fn):
557 """Check if the given expression can be replaced by a lookup table.
558
559 The first argument is the expression to check; the second is a
560 function which takes a variable object and returns True iff this
561 variable is permitted within a lookup table expression.
562
563 If self.annotate_failures is True then annotate <apply> and
564 <piecewise> expressions which don't qualify with the reason
565 why they do not.
566 This can be:
567 'no_var' - doesn't contain the table variable
568 'bad_var <vname>' - contains a variable which isn't permitted
569 'no_func' - doesn't contain an expensive function
570 or a comma separated combination of the above.
571 The annotation is stored as the lut:reason attribute.
572
573 If self.annotate_outermost_only is True then only annotate the
574 outermost qualifying expression, rather than also annotating
575 qualifying subexpressions.
576 """
577 # If this is a cloned expression, then just copy any annotations on the original.
578 if isinstance(expr, mathml):
579 source_expr = expr.get_original_of_clone()
580 else:
581 source_expr = None
582 if source_expr and source_expr.getAttributeNS(NSS['lut'], u'possible', '') != '':
583 LookupTableAnalyser.copy_lut_annotations(source_expr, expr)
584 state = self.create_state_from_annotations(source_expr)
585 DEBUG('lookup-tables', "No need to analyse clone", expr.xml(), state.suitable(), state.reason())
586 else:
587 # Initialise the indicators
588 state = self.LUTState()
589 # Process current node
590 if isinstance(expr, mathml_ci):
591 # Variable reference
592 if var_checker_fn(expr.variable):
593 # Could be a permitted var that isn't a keying var
594 if self.is_keying_var(expr.variable):
595 assert state.table_var is None # Sanity check
596 state.has_var = True
597 state.table_var = expr.variable
598 else:
599 state.bad_vars.add(expr.variable.name)
600 elif isinstance(expr, mathml_piecewise):
601 # Recurse into pieces & otherwise options
602 if hasattr(expr, u'otherwise'):
603 r = self.analyse_for_lut(child_i(expr.otherwise, 1),
604 var_checker_fn)
605 state.update(r)
606 for piece in getattr(expr, u'piece', []):
607 r = self.analyse_for_lut(child_i(piece, 1), var_checker_fn)
608 state.update(r)
609 r = self.analyse_for_lut(child_i(piece, 2), var_checker_fn)
610 state.update(r)
611 elif isinstance(expr, mathml_apply):
612 # Check function
613 if (not state.has_func and
614 expr.operator().localName in self.lut_expensive_funcs):
615 state.has_func = True
616 # Check operands
617 operand_states = {}
618 for operand in expr.operands():
619 r = self.analyse_for_lut(operand, var_checker_fn)
620 state.update(r)
621 operand_states[id(operand)] = r
622 # Check qualifiers
623 for qual in expr.qualifiers():
624 r = self.analyse_for_lut(qual, var_checker_fn)
625 state.update(r)
626 # Special case additional optimisations
627 if self.config and self.config.options.combine_commutative_tables and not state.suitable():
628 if isinstance(expr.operator(), reduce_commutative_nary):
629 self.check_commutative_tables(expr, operand_states)
630 elif isinstance(expr.operator(), mathml_divide):
631 self.check_divide_by_table(expr, operand_states)
632 else:
633 # Just recurse into children
634 for e in expr.xml_children:
635 if getattr(e, 'nodeType', None) == Node.ELEMENT_NODE:
636 r = self.analyse_for_lut(e, var_checker_fn)
637 state.update(r)
638 # Annotate the expression if appropriate
639 if isinstance(expr, (mathml_apply, mathml_piecewise)):
640 if state.suitable():
641 self.annotate_as_suitable(expr, state.table_var)
642 else:
643 if self.annotate_failures:
644 expr.xml_set_attribute((u'lut:reason', NSS['lut']), state.reason())
645 return state
646
def child_i(elt, i)
Definition: pycml.py:3449

References CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut(), CellMLToNektar.optimize.LookupTableAnalyser.annotate_as_suitable(), CellMLToNektar.optimize.LookupTableAnalyser.annotate_failures, CellMLToNektar.optimize.LookupTableAnalyser.annotate_outermost_only, CellMLToNektar.optimize.LookupTableAnalyser.check_commutative_tables(), CellMLToNektar.optimize.LookupTableAnalyser.check_divide_by_table(), CellMLToNektar.pycml.child_i(), CellMLToNektar.optimize.LookupTableAnalyser.config(), CellMLToNektar.translators.CellMLTranslator.config(), CellMLToNektar.optimize.LookupTableAnalyser.create_state_from_annotations(), CellMLToNektar.utilities.DEBUG(), CellMLToNektar.optimize.LookupTableAnalyser.is_keying_var(), and CellMLToNektar.optimize.LookupTableAnalyser.lut_expensive_funcs.

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut().

◆ analyse_model()

def CellMLToNektar.optimize.LookupTableAnalyser.analyse_model (   self,
  doc,
  solver_info,
  annotate_failures = True,
  annotate_outermost_only = True 
)
Analyse the given document.

This method checks all expressions (and subexpressions)
in the given document for whether they could be converted to
use a lookup table, and annotates them appropriately.

By default expressions which don't qualify will be annotated
to indicate why; set annotate_failures to False to suppress
this.

Also by default only the outermost suitable expression in any
given tree will be annotated; if you want to annotate suitable
subexpressions of a suitable expression then pass
annotate_outermost_only as False.

Definition at line 758 of file optimize.py.

760 annotate_outermost_only=True):
761 """Analyse the given document.
762
763 This method checks all expressions (and subexpressions)
764 in the given document for whether they could be converted to
765 use a lookup table, and annotates them appropriately.
766
767 By default expressions which don't qualify will be annotated
768 to indicate why; set annotate_failures to False to suppress
769 this.
770
771 Also by default only the outermost suitable expression in any
772 given tree will be annotated; if you want to annotate suitable
773 subexpressions of a suitable expression then pass
774 annotate_outermost_only as False.
775 """
776 self.doc = doc
777 self.solver_info = solver_info
778 self.annotate_failures = annotate_failures
779 self.annotate_outermost_only = annotate_outermost_only
780 doc.lookup_tables = {}
781 # How to check for allowed variables
782 if hasattr(doc, '_cml_config'):
783 checker_fn = self.is_allowed_variable
784 else:
785 checker_fn = self.var_is_membrane_potential
786
787 # Check all expressions
788 for expr in (e for e in doc.model.get_assignments()
789 if isinstance(e, mathml_apply)):
790 ops = expr.operands()
791 ops.next()
792 e = ops.next()
793 self.analyse_for_lut(e, checker_fn)
794 for expr in solver_info.get_modifiable_mathematics():
795 self.analyse_for_lut(expr, checker_fn)
796
797 if solver_info.has_modifiable_mathematics():
798 self._determine_unneeded_tables()
799
800 # Assign names (numbers) to the lookup tables found.
801 # Also work out which ones can share index variables into the table.
802 doc.lookup_tables = doc.lookup_tables.keys()
803 doc.lookup_tables.sort(cmp=element_path_cmp)
804 doc.lookup_table_indexes, n = {}, 0
805 for i, expr in enumerate(doc.lookup_tables):
806 expr.xml_set_attribute((u'lut:table_name', NSS['lut']), unicode(i))
807 comp = expr.get_component()
808 var = comp.get_variable_by_name(expr.var).get_source_variable(recurse=True)
809 key = (expr.min, expr.max, expr.step, var)
810 if not key in doc.lookup_table_indexes:
811 doc.lookup_table_indexes[key] = unicode(n)
812 n += 1
813 expr.xml_set_attribute((u'lut:table_index', NSS['lut']), doc.lookup_table_indexes[key])
814
815 if solver_info.has_modifiable_mathematics():
816 self._determine_duplicate_tables()
817
818 # Re-do dependency analysis so that an expression using lookup
819 # tables only depends on the keying variable.
820 for expr in (e for e in doc.model.get_assignments()
821 if isinstance(e, mathml_apply)):
822 expr.classify_variables(root=True,
823 dependencies_only=True,
824 needs_special_treatment=self.calculate_dependencies)
825

References Nektar::LibUtilities::H5DataSource.doc, CellMLToNektar.optimize.PartialEvaluator.doc, CellMLToNektar.optimize.LookupTableAnalyser.doc, CellMLToNektar.translators.CellMLTranslator.doc, and CellMLToNektar.translators.ConfigurationStore.doc.

◆ annotate_as_suitable()

def CellMLToNektar.optimize.LookupTableAnalyser.annotate_as_suitable (   self,
  expr,
  table_var 
)
Annotate the given expression as being suitable for a lookup table.

Definition at line 714 of file optimize.py.

714 def annotate_as_suitable(self, expr, table_var):
715 """Annotate the given expression as being suitable for a lookup table."""
716 if self.annotate_outermost_only:
717 # Remove annotations from (expr and) child expressions
718 self.remove_lut_annotations(expr)
719 for param in ['min', 'max', 'step']:
720 expr.xml_set_attribute((u'lut:' + param, NSS['lut']),
721 self.get_param('table_' + param, table_var))
722 expr.xml_set_attribute((u'lut:var', NSS['lut']), table_var.name)
723 expr.xml_set_attribute((u'lut:possible', NSS['lut']), u'yes')
724 self.doc.lookup_tables[expr] = True
725

References CellMLToNektar.optimize.LookupTableAnalyser.annotate_outermost_only, Nektar::LibUtilities::H5DataSource.doc, CellMLToNektar.optimize.PartialEvaluator.doc, CellMLToNektar.optimize.LookupTableAnalyser.doc, CellMLToNektar.translators.CellMLTranslator.doc, CellMLToNektar.translators.ConfigurationStore.doc, CellMLToNektar.optimize.LookupTableAnalyser.get_param(), and CellMLToNektar.optimize.LookupTableAnalyser.remove_lut_annotations().

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut(), CellMLToNektar.optimize.LookupTableAnalyser.check_commutative_tables(), and CellMLToNektar.optimize.LookupTableAnalyser.check_divide_by_table().

◆ calculate_dependencies()

def CellMLToNektar.optimize.LookupTableAnalyser.calculate_dependencies (   self,
  expr 
)
Determine the dependencies of an expression that might use a lookup table.

This method is suitable for use as the needs_special_treatment function in
mathml_apply.classify_variables.  It is used to override the default recursion
into sub-trees.  It takes a single sub-tree as argument, and returns either
the dependency set for that sub-tree, or None to use the default recursion.

Expressions that can use a lookup table only depend on the keying variable.

Definition at line 881 of file optimize.py.

881 def calculate_dependencies(self, expr):
882 """Determine the dependencies of an expression that might use a lookup table.
883
884 This method is suitable for use as the needs_special_treatment function in
885 mathml_apply.classify_variables. It is used to override the default recursion
886 into sub-trees. It takes a single sub-tree as argument, and returns either
887 the dependency set for that sub-tree, or None to use the default recursion.
888
889 Expressions that can use a lookup table only depend on the keying variable.
890 """
891 if expr.getAttributeNS(NSS['lut'], u'possible', '') == u'yes':
892 key_var_name = expr.getAttributeNS(NSS['lut'], u'var')
893 key_var = expr.component.get_variable_by_name(key_var_name).get_source_variable(recurse=True)
894 return set([key_var])
895 # If not a table, use default behaviour
896 return None
897
898

◆ check_commutative_tables()

def CellMLToNektar.optimize.LookupTableAnalyser.check_commutative_tables (   self,
  expr,
  operand_states 
)
Check whether we can combine suitable operands into a new expression.

If expr has a commutative (and associative) n-ary operator, but is not suitable as a
whole to become a lookup table (checked by caller) then we might still be able to
do slightly better than just analysing its operands.  If multiple operands can be
replaced by tables keyed on the same variable, these can be combined into a new
application of the same operator as expr, which can then be replaced as a whole
by a single lookup table, and made an operand of expr.

Alternatively, if at least one operand can be replaced by a table, and a subset of
other operands do not contain other variables, then they can be included in the single
table.

Definition at line 664 of file optimize.py.

664 def check_commutative_tables(self, expr, operand_states):
665 """Check whether we can combine suitable operands into a new expression.
666
667 If expr has a commutative (and associative) n-ary operator, but is not suitable as a
668 whole to become a lookup table (checked by caller) then we might still be able to
669 do slightly better than just analysing its operands. If multiple operands can be
670 replaced by tables keyed on the same variable, these can be combined into a new
671 application of the same operator as expr, which can then be replaced as a whole
672 by a single lookup table, and made an operand of expr.
673
674 Alternatively, if at least one operand can be replaced by a table, and a subset of
675 other operands do not contain other variables, then they can be included in the single
676 table.
677 """
678 # Operands that can be replaced by tables
679 table_operands = filter(lambda op: operand_states[id(op)].suitable(), expr.operands())
680 if not table_operands:
681 return
682 # Sort these suitable operands by table_var (map var id to var & operand list, respectively)
683 table_vars, table_var_operands = {}, {}
684 for oper in table_operands:
685 table_var = operand_states[id(oper)].table_var
686 table_var_id = id(table_var)
687 if not table_var_id in table_vars:
688 table_vars[table_var_id] = table_var
689 table_var_operands[table_var_id] = []
690 table_var_operands[table_var_id].append(oper)
691 # Figure out if any operands aren't suitable by themselves but could be included in a table
692 potential_operands = {id(None): []}
693 for table_var_id in table_vars.keys():
694 potential_operands[table_var_id] = []
695 for op in expr.operands():
696 state = operand_states[id(op)]
697 if not state.suitable() and not state.bad_vars:
698 if not state.table_var in potential_operands:
699 potential_operands[id(state.table_var)] = []
700 potential_operands[id(state.table_var)].append(op)
701 # Do any combining
702 for table_var_id in table_vars.keys():
703 suitable_opers = table_var_operands[table_var_id] + potential_operands[table_var_id] + potential_operands[id(None)]
704 if len(suitable_opers) > 1:
705 # Create new sub-expression with the suitable operands
706 for oper in suitable_opers:
707 expr.safe_remove_child(oper)
708 new_expr = mathml_apply.create_new(expr, expr.operator().localName, suitable_opers)
709 expr.xml_append(new_expr)
710 self.annotate_as_suitable(new_expr, table_vars[table_var_id])
711 # Remove the operands with no table_var from consideration with other keying vars
712 potential_operands[id(None)] = []
713

References CellMLToNektar.optimize.LookupTableAnalyser.annotate_as_suitable().

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut().

◆ check_divide_by_table()

def CellMLToNektar.optimize.LookupTableAnalyser.check_divide_by_table (   self,
  expr,
  operand_states 
)
Convert division by a table into multiplication.

This is called if expr, a division, cannot be replaced as a whole by a lookup table.
If the denominator can be replaced by a table, then convert expr into a multiplication
by the reciprocal, moving the division into the table.

Definition at line 647 of file optimize.py.

647 def check_divide_by_table(self, expr, operand_states):
648 """Convert division by a table into multiplication.
649
650 This is called if expr, a division, cannot be replaced as a whole by a lookup table.
651 If the denominator can be replaced by a table, then convert expr into a multiplication
652 by the reciprocal, moving the division into the table.
653 """
654 numer, denom = list(expr.operands())
655 state = operand_states[id(denom)]
656 if state.suitable():
657 expr.safe_remove_child(numer)
658 expr.safe_remove_child(denom)
659 recip = mathml_apply.create_new(expr, u'divide', [(u'1', u'dimensionless'), denom])
660 times = mathml_apply.create_new(expr, u'times', [numer, recip])
661 expr.replace_child(expr, times, expr.xml_parent)
662 self.annotate_as_suitable(recip, state.table_var)
663

References CellMLToNektar.optimize.LookupTableAnalyser.annotate_as_suitable().

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut().

◆ config()

def CellMLToNektar.optimize.LookupTableAnalyser.config (   self)
Get the current document's configuration store.

Definition at line 398 of file optimize.py.

398 def config(self):
399 """Get the current document's configuration store."""
400 return getattr(self.doc, '_cml_config', None)
401

References Nektar::LibUtilities::H5DataSource.doc, CellMLToNektar.optimize.PartialEvaluator.doc, CellMLToNektar.optimize.LookupTableAnalyser.doc, CellMLToNektar.translators.CellMLTranslator.doc, and CellMLToNektar.translators.ConfigurationStore.doc.

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut(), CellMLToNektar.optimize.LookupTableAnalyser.get_param(), CellMLToNektar.optimize.LookupTableAnalyser.is_allowed_variable(), CellMLToNektar.optimize.LookupTableAnalyser.is_keying_var(), CellMLToNektar.translators.CellMLTranslator.lut_factor(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_assignment(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_backward_euler_mathematics(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_derivative_calculations(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_derived_quantities(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_lut_class(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_lut_indexing_methods(), CellMLToNektar.translators.CellMLTranslator.output_lut_methods(), CellMLToNektar.translators.CellMLTranslator.output_lut_row_lookup_methods(), CellMLToNektar.translators.CellMLTranslator.output_single_lookup(), CellMLToNektar.translators.CellMLTranslator.output_table_index_checking(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_table_index_checking(), CellMLToNektar.translators.CellMLTranslator.output_table_index_generation(), and CellMLToNektar.translators.CellMLTranslator.output_table_index_generation_code().

◆ copy_lut_annotations()

def CellMLToNektar.optimize.LookupTableAnalyser.copy_lut_annotations (   from_expr,
  to_expr 
)
static
Copy any lookup table annotations from one expression to another.

Definition at line 727 of file optimize.py.

727 def copy_lut_annotations(from_expr, to_expr):
728 """Copy any lookup table annotations from one expression to another."""
729 for pyname, fullname in from_expr.xml_attributes.iteritems():
730 if fullname[1] == NSS['lut']:
731 to_expr.xml_set_attribute(fullname, getattr(from_expr, pyname))
732

◆ create_state_from_annotations()

def CellMLToNektar.optimize.LookupTableAnalyser.create_state_from_annotations (   self,
  expr 
)
Create a LUTState instance from an already annotated expression.

Definition at line 537 of file optimize.py.

537 def create_state_from_annotations(self, expr):
538 """Create a LUTState instance from an already annotated expression."""
539 state = self.LUTState()
540 possible = expr.getAttributeNS(NSS['lut'], u'possible', '')
541 if possible == u'yes':
542 varname = expr.getAttributeNS(NSS['lut'], u'var')
543 state.table_var = expr.component.get_variable_by_name(varname)
544 elif possible == u'no':
545 reason = expr.getAttributeNS(NSS['lut'], u'reason', '')
546 reasons = reason.split(u',')
547 for reason in reasons:
548 if reason == u'no_var':
549 state.has_var = False
550 elif reason == u'no_func':
551 state.has_func = False
552 elif reason.startswith(u'bad_var '):
553 state.bad_vars.add(reason[8:])
554 return state
555

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut().

◆ get_param()

def CellMLToNektar.optimize.LookupTableAnalyser.get_param (   self,
  param_name,
  table_var 
)
Get the value of the lookup table parameter.

table_var is the variable object being used to key this table.

If the document has a config store, lookup the value there.
If that doesn't give us a value, use that given using set_params.

Definition at line 453 of file optimize.py.

453 def get_param(self, param_name, table_var):
454 """Get the value of the lookup table parameter.
455
456 table_var is the variable object being used to key this table.
457
458 If the document has a config store, lookup the value there.
459 If that doesn't give us a value, use that given using set_params.
460 """
461 try:
462 val = self.config.lut_config[
463 table_var.get_source_variable(recurse=True)][param_name]
464 except AttributeError, KeyError:
465 val = getattr(self, param_name)
466 return val
467

References CellMLToNektar.optimize.LookupTableAnalyser.config(), and CellMLToNektar.translators.CellMLTranslator.config().

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.annotate_as_suitable().

◆ is_allowed_variable()

def CellMLToNektar.optimize.LookupTableAnalyser.is_allowed_variable (   self,
  var 
)
Return True iff the given variable is allowed in a lookup table.

This method uses the config store in the document to check the variable object.

Definition at line 410 of file optimize.py.

410 def is_allowed_variable(self, var):
411 """Return True iff the given variable is allowed in a lookup table.
412
413 This method uses the config store in the document to check the variable object.
414 """
415 var = var.get_source_variable(recurse=True)
416 allowed = (var in self.config.lut_config or
417 (self.config.options.include_dt_in_tables and
418 var is self.solver_info.get_dt().get_source_variable(recurse=True)))
419 return allowed
420

References CellMLToNektar.optimize.LookupTableAnalyser.config(), CellMLToNektar.translators.CellMLTranslator.config(), CellMLToNektar.optimize.PartialEvaluator.solver_info, and CellMLToNektar.optimize.LookupTableAnalyser.solver_info.

◆ is_keying_var()

def CellMLToNektar.optimize.LookupTableAnalyser.is_keying_var (   self,
  var 
)
Return True iff the given variable can be used as a table key.

Will check the config store if it exists.  If not, the variable name must match self.table_var.

Definition at line 421 of file optimize.py.

421 def is_keying_var(self, var):
422 """Return True iff the given variable can be used as a table key.
423
424 Will check the config store if it exists. If not, the variable name must match self.table_var.
425 """
426 if self.config:
427 return var.get_source_variable(recurse=True) in self.config.lut_config
428 else:
429 return var.name == self.table_var
430

References CellMLToNektar.optimize.LookupTableAnalyser.config(), CellMLToNektar.translators.CellMLTranslator.config(), and CellMLToNektar.optimize.LookupTableAnalyser.LUTState.table_var.

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut().

◆ remove_lut_annotations()

def CellMLToNektar.optimize.LookupTableAnalyser.remove_lut_annotations (   self,
  expr,
  remove_reason = False 
)
Remove lookup table annotations from the given expression.

By default this will only remove annotations from expressions
(and sub-expressions) that can be converted to use lookup tables.
If remove_reason is True, then the lut:reason attributes on
non-qualifying expressions will also be removed.

Definition at line 733 of file optimize.py.

733 def remove_lut_annotations(self, expr, remove_reason=False):
734 """Remove lookup table annotations from the given expression.
735
736 By default this will only remove annotations from expressions
737 (and sub-expressions) that can be converted to use lookup tables.
738 If remove_reason is True, then the lut:reason attributes on
739 non-qualifying expressions will also be removed.
740 """
741 # Remove from this expression
742 delete_table = False
743 for pyname in getattr(expr, 'xml_attributes', {}).keys():
744 fullname = expr.xml_attributes[pyname]
745 if fullname[1] == NSS['lut']:
746 if remove_reason or fullname[0] != u'lut:reason':
747 expr.__delattr__(pyname)
748 if fullname[0] != u'lut:reason':
749 delete_table = True
750 # Delete expr from list of lookup tables?
751 if delete_table:
752 del self.doc.lookup_tables[expr]
753 # Recurse into children
754 for e in expr.xml_children:
755 if getattr(e, 'nodeType', None) == Node.ELEMENT_NODE:
756 self.remove_lut_annotations(e, remove_reason)
757

References Nektar::LibUtilities::H5DataSource.doc, CellMLToNektar.optimize.PartialEvaluator.doc, CellMLToNektar.optimize.LookupTableAnalyser.doc, CellMLToNektar.translators.CellMLTranslator.doc, CellMLToNektar.translators.ConfigurationStore.doc, and CellMLToNektar.optimize.LookupTableAnalyser.remove_lut_annotations().

Referenced by CellMLToNektar.optimize.LookupTableAnalyser._determine_unneeded_tables(), CellMLToNektar.optimize.LookupTableAnalyser.annotate_as_suitable(), and CellMLToNektar.optimize.LookupTableAnalyser.remove_lut_annotations().

◆ set_params()

def CellMLToNektar.optimize.LookupTableAnalyser.set_params (   self,
**  kw 
)
Set parameters controlling lookup table generation.

Keyword parameters control the lookup table settings, which are
stored as attributes on suitable expressions.
table_min - minimum table entry (unicode) -> lut:min
table_max - maximum table entry (unicode) -> lut:max
table_step - table step size (unicode) -> lut:step
table_var - the name of the variable indexing the table (unicode) -> lut:var

Definition at line 435 of file optimize.py.

435 def set_params(self, **kw):
436 """Set parameters controlling lookup table generation.
437
438 Keyword parameters control the lookup table settings, which are
439 stored as attributes on suitable expressions.
440 table_min - minimum table entry (unicode) -> lut:min
441 table_max - maximum table entry (unicode) -> lut:max
442 table_step - table step size (unicode) -> lut:step
443 table_var - the name of the variable indexing the table (unicode) -> lut:var
444 """
445 defaults = self._LT_DEFAULTS
446 for attr in defaults:
447 if attr in kw:
448 setattr(self, attr, kw[attr])
449 else:
450 setattr(self, attr, getattr(self, attr, defaults[attr]))
451 return
452

References CellMLToNektar.optimize.LookupTableAnalyser._LT_DEFAULTS.

◆ var_is_membrane_potential()

def CellMLToNektar.optimize.LookupTableAnalyser.var_is_membrane_potential (   self,
  var 
)
Determine if the given variable represents the transmembrane potential.

This method takes an instance of cellml_variable and returns a boolean.

Definition at line 402 of file optimize.py.

402 def var_is_membrane_potential(self, var):
403 """Determine if the given variable represents the transmembrane potential.
404
405 This method takes an instance of cellml_variable and returns a boolean.
406 """
407 return (var.name in [u'V', u'membrane__V'] and
408 var.get_type(follow_maps=True) == VarTypes.State)
409

Member Data Documentation

◆ _LT_DEFAULTS

dictionary CellMLToNektar.optimize.LookupTableAnalyser._LT_DEFAULTS
staticprivate
Initial value:
= {'table_min': u'-100.0001',
'table_max': u'49.9999',
'table_step': u'0.01',
'table_var': u'V'}

Definition at line 431 of file optimize.py.

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.set_params().

◆ annotate_failures

CellMLToNektar.optimize.LookupTableAnalyser.annotate_failures

◆ annotate_outermost_only

CellMLToNektar.optimize.LookupTableAnalyser.annotate_outermost_only

◆ doc

CellMLToNektar.optimize.LookupTableAnalyser.doc

Definition at line 393 of file optimize.py.

Referenced by CellMLToNektar.optimize.LookupTableAnalyser._determine_duplicate_tables(), CellMLToNektar.optimize.LookupTableAnalyser._determine_unneeded_tables(), CellMLToNektar.optimize.PartialEvaluator._do_reduce_eval_loop(), CellMLToNektar.optimize.LookupTableAnalyser._find_tables(), CellMLToNektar.translators.ConfigurationStore._find_transmembrane_currents_from_voltage_ode(), CellMLToNektar.translators.ConfigurationStore._find_variable(), CellMLToNektar.optimize.PartialEvaluator._get_assignment_exprs(), CellMLToNektar.optimize.LookupTableAnalyser.analyse_model(), CellMLToNektar.optimize.LookupTableAnalyser.annotate_as_suitable(), CellMLToNektar.optimize.LookupTableAnalyser.config(), CellMLToNektar.translators.CellMLTranslator.config(), CellMLToNektar.translators.ConfigurationStore.expose_variables(), CellMLToNektar.translators.ConfigurationStore.find_current_vars(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.get_stimulus_assignment(), CellMLToNektar.optimize.PartialEvaluator.is_instantiable(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.lut_parameters(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_backward_euler_mathematics(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_constructor(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_derived_quantities(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_equations(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_get_i_ionic(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_intracellular_calcium(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_lut_class(), CellMLToNektar.translators.CellMLTranslator.output_lut_declarations(), CellMLToNektar.translators.CellMLTranslator.output_lut_deletion(), CellMLToNektar.translators.CellMLTranslator.output_lut_generation(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_lut_indexing_methods(), CellMLToNektar.translators.CellMLTranslator.output_lut_indices(), CellMLToNektar.translators.CellMLTranslator.output_lut_methods(), CellMLToNektar.translators.CellMLTranslator.output_lut_row_lookup_memory(), CellMLToNektar.translators.CellMLTranslator.output_lut_row_lookup_methods(), CellMLToNektar.CellMLToNektarTranslator.CellMLToNektarTranslator.output_rush_larsen_mathematics(), CellMLToNektar.translators.CellMLTranslator.output_table_index_generation(), CellMLToNektar.translators.ConfigurationStore.read_configuration_file(), CellMLToNektar.optimize.LookupTableAnalyser.remove_lut_annotations(), CellMLToNektar.translators.CellMLTranslator.scan_for_lookup_tables(), and CellMLToNektar.translators.ConfigurationStore.validate_metadata().

◆ lut_expensive_funcs

CellMLToNektar.optimize.LookupTableAnalyser.lut_expensive_funcs
static
Initial value:
= frozenset(('exp', 'log', 'ln', 'root',
'sin', 'cos', 'tan',
'sec', 'csc', 'cot',
'sinh', 'cosh', 'tanh',
'sech', 'csch', 'coth',
'arcsin', 'arccos', 'arctan',
'arcsinh', 'arccosh', 'arctanh',
'arcsec', 'arccsc', 'arccot',
'arcsech', 'arccsch', 'arccoth'))

Definition at line 469 of file optimize.py.

Referenced by CellMLToNektar.optimize.LookupTableAnalyser.analyse_for_lut().

◆ solver_info

CellMLToNektar.optimize.LookupTableAnalyser.solver_info