def deprecated_signature(self, function_replace_map=None): if self._signature is None: from ufl.algorithms.signature import compute_form_signature self._signature = compute_form_signature(self, function_replace_map) assert self._signature return self._signature
def _store(self, obj, form, bcs): form_sig = compute_form_signature(form) if self.invalid_count[form_sig] > parameters["assembly_cache"]["max_misses"]: if self.invalid_count[form_sig] == \ parameters["assembly_cache"]["max_misses"] + 1: debug("form %s missed too many times, excluding from cache." % form) else: cache_entry = _CacheEntry(obj, form, bcs) self.cache[form_sig] = cache_entry self.evict()
def _lookup(self, form, bcs): form_sig = compute_form_signature(form) cache_entry = self.cache.get(form_sig, None) retval = None if cache_entry is not None: if not cache_entry.is_valid(form, bcs): self.invalid_count[form_sig] += 1 del self.cache[form_sig] return None else: self.invalid_count[form_sig] = 0 retval = cache_entry.get_object() self._hits += 1 self._hits_size += retval.nbytes return retval
def preprocess(form, object_names=None, common_cell=None, element_mapping=None): """ Preprocess raw input form to obtain form metadata, including a modified (preprocessed) form more easily manipulated by form compilers. The original form is left untouched. Currently, the following transformations are made to the preprocessed form: expand_compounds (side effect of calling expand_derivatives) expand_derivatives renumber arguments and coefficients and apply evt. element mapping """ tic = Timer('preprocess') # TODO: Reposition tic calls after refactoring. # Check that we get a form ufl_assert(isinstance(form, Form), "Expecting Form.") original_form = form # Object names is empty if not given object_names = object_names or {} # Element mapping is empty if not given element_mapping = element_mapping or {} # Create empty form data form_data = FormData() # Store copies of preprocess input data, for future validation if called again... form_data._input_object_names = dict(object_names) form_data._input_element_mapping = dict(element_mapping) #form_data._input_common_cell = no need to store this # Store name of form if given, otherwise empty string # such that automatic names can be assigned externally form_data.name = object_names.get(id(form), "") # Extract common cell common_cell = extract_common_cell(form, common_cell) # TODO: Split out expand_compounds from expand_derivatives # Expand derivatives tic('expand_derivatives') form = expand_derivatives(form, common_cell.geometric_dimension()) # EXPR # Propagate restrictions of interior facet integrals to the terminal nodes form = propagate_restrictions(form) # INTEGRAL, EXPR # --- BEGIN DOMAIN SPLITTING AND JOINING # Store domain metadata per domain type form_data.domain_data = extract_domain_data(form) # Split up integrals and group by domain type and domain id, # adding integrands with same domain and compiler data sub_integral_data = integral_dict_to_sub_integral_data( form.integral_groups()) # TODO: Replace integral_data with this through ufl and ffc? if 0: print_sub_integral_data(sub_integral_data) # Reconstruct form from these integrals in a more canonical representation form = reconstruct_form_from_sub_integral_data(sub_integral_data, form_data.domain_data) # Represent in the way ffc expects TODO: Change ffc? Fine for now. form_data.integral_data = convert_sub_integral_data_to_integral_data( sub_integral_data) # --- END DOMAIN SPLITTING AND JOINING # --- BEGIN FUNCTION ANALYSIS # --- BEGIN SPLIT EXPR JOIN # Replace arguments and coefficients with new renumbered objects tic('extract_arguments_and_coefficients') original_arguments, original_coefficients = \ extract_arguments_and_coefficients(form) tic('build_element_mapping') element_mapping = build_element_mapping(element_mapping, common_cell, original_arguments, original_coefficients) tic('build_argument_replace_map') # TODO: Remove renumbered ones? replace_map, renumbered_arguments, renumbered_coefficients = \ build_argument_replace_map(original_arguments, original_coefficients, element_mapping) # Note: This is the earliest point signature can be computed # Build mapping to original arguments and coefficients, which is # useful if the original arguments have data attached to them inv_replace_map = dict((w, v) for (v, w) in replace_map.iteritems()) original_arguments = [inv_replace_map[v] for v in renumbered_arguments] original_coefficients = [ inv_replace_map[w] for w in renumbered_coefficients ] # TODO: Build mapping from object to position instead? But we need mapped elements as well anyway. #argument_positions = { v: i } #coefficient_positions = { w: i } # Store data extracted by preprocessing form_data.original_arguments = original_arguments form_data.original_coefficients = original_coefficients # --- END SPLIT INTEGRAL JOIN # Mappings from elements and functions (coefficients and arguments) # that reside in form to objects with canonical numbering as well as # completed cells and elements # TODO: Create additional function mappings per integral, # to have different counts? Depends on future UFC design. form_data.element_replace_map = element_mapping form_data.function_replace_map = replace_map # Store some useful dimensions form_data.rank = len(form_data.original_arguments) form_data.num_coefficients = len(form_data.original_coefficients) # Store argument names form_data.argument_names = \ [object_names.get(id(form_data.original_arguments[i]), "v%d" % i) for i in range(form_data.rank)] # Store coefficient names form_data.coefficient_names = \ [object_names.get(id(form_data.original_coefficients[i]), "w%d" % i) for i in range(form_data.num_coefficients)] # --- END FUNCTION ANALYSIS # --- BEGIN SIGNATURE COMPUTATION # TODO: Compute signatures of each INTEGRAL and EXPR as well, perhaps compute it hierarchially from integral_data? # Store signature of form tic('signature') # TODO: Remove signature() from Form, not safe to cache with a replacement map #form_data.signature = form.signature(form_data.function_replace_map) form_data.signature = compute_form_signature( form, form_data.function_replace_map) # --- END SIGNATURE COMPUTATION # --- BEGIN CONSISTENCY CHECKS # Check that we don't have a mixed linear/bilinear form or anything like that ufl_assert( len(compute_form_arities(form)) == 1, "All terms in form must have same rank.") # --- END CONSISTENCY CHECKS # --- BEGIN ELEMENT DATA # Store elements, sub elements and element map tic('extract_elements') form_data.argument_elements = tuple(f.element() for f in renumbered_arguments) form_data.coefficient_elements = tuple(f.element() for f in renumbered_coefficients) form_data.elements = form_data.argument_elements + form_data.coefficient_elements form_data.unique_elements = unique_tuple(form_data.elements) form_data.sub_elements = extract_sub_elements(form_data.elements) form_data.unique_sub_elements = unique_tuple(form_data.sub_elements) # --- END ELEMENT DATA # --- BEGIN DOMAIN DATA # Store element domains (NB! This is likely to change!) # TODO: DOMAINS: What is a sensible way to store domains for a form? form_data.domains = tuple( sorted(set(element.domain() for element in form_data.unique_elements))) # Store toplevel domains (NB! This is likely to change!) # TODO: DOMAINS: What is a sensible way to store domains for a form? form_data.top_domains = tuple( sorted(set(domain.top_domain() for domain in form_data.domains))) # Store common cell form_data.cell = common_cell # Store data related to cell form_data.geometric_dimension = form_data.cell.geometric_dimension() form_data.topological_dimension = form_data.cell.topological_dimension() # Store number of domains for integral types form_data.num_sub_domains = extract_num_sub_domains(form) # --- END DOMAIN DATA # A coarse profiling implementation TODO: Add counting of nodes, Add memory usage tic.end() if preprocess.enable_profiling: print tic # Store preprocessed form and return form_data.preprocessed_form = form form_data.preprocessed_form._is_preprocessed = True # Attach signatures to original and preprocessed forms TODO: Avoid this? ufl_assert(form_data.preprocessed_form._signature is None, "") form_data.preprocessed_form._signature = form_data.signature ufl_assert(original_form._signature is None, "") original_form._signature = form_data.signature return form_data
def preprocess(form, object_names=None, common_cell=None, element_mapping=None): """ Preprocess raw input form to obtain form metadata, including a modified (preprocessed) form more easily manipulated by form compilers. The original form is left untouched. Currently, the following transformations are made to the preprocessed form: expand_compounds (side effect of calling expand_derivatives) expand_derivatives renumber arguments and coefficients and apply evt. element mapping """ tic = Timer('preprocess') # TODO: Reposition tic calls after refactoring. # Check that we get a form ufl_assert(isinstance(form, Form), "Expecting Form.") original_form = form # Object names is empty if not given object_names = object_names or {} # Element mapping is empty if not given element_mapping = element_mapping or {} # Create empty form data form_data = FormData() # Store copies of preprocess input data, for future validation if called again... form_data._input_object_names = dict(object_names) form_data._input_element_mapping = dict(element_mapping) #form_data._input_common_cell = no need to store this # Store name of form if given, otherwise empty string # such that automatic names can be assigned externally form_data.name = object_names.get(id(form), "") # Extract common cell common_cell = extract_common_cell(form, common_cell) # TODO: Split out expand_compounds from expand_derivatives # Expand derivatives tic('expand_derivatives') form = expand_derivatives(form, common_cell.geometric_dimension()) # EXPR # Propagate restrictions of interior facet integrals to the terminal nodes form = propagate_restrictions(form) # INTEGRAL, EXPR # --- BEGIN DOMAIN SPLITTING AND JOINING # Store domain metadata per domain type form_data.domain_data = extract_domain_data(form) # Split up integrals and group by domain type and domain id, # adding integrands with same domain and compiler data sub_integral_data = integral_dict_to_sub_integral_data(form.integral_groups()) # TODO: Replace integral_data with this through ufl and ffc? if 0: print_sub_integral_data(sub_integral_data) # Reconstruct form from these integrals in a more canonical representation form = reconstruct_form_from_sub_integral_data(sub_integral_data, form_data.domain_data) # Represent in the way ffc expects TODO: Change ffc? Fine for now. form_data.integral_data = convert_sub_integral_data_to_integral_data(sub_integral_data) # --- END DOMAIN SPLITTING AND JOINING # --- BEGIN FUNCTION ANALYSIS # --- BEGIN SPLIT EXPR JOIN # Replace arguments and coefficients with new renumbered objects tic('extract_arguments_and_coefficients') original_arguments, original_coefficients = \ extract_arguments_and_coefficients(form) tic('build_element_mapping') element_mapping = build_element_mapping(element_mapping, common_cell, original_arguments, original_coefficients) tic('build_argument_replace_map') # TODO: Remove renumbered ones? replace_map, renumbered_arguments, renumbered_coefficients = \ build_argument_replace_map(original_arguments, original_coefficients, element_mapping) # Note: This is the earliest point signature can be computed # Build mapping to original arguments and coefficients, which is # useful if the original arguments have data attached to them inv_replace_map = dict((w,v) for (v,w) in replace_map.iteritems()) original_arguments = [inv_replace_map[v] for v in renumbered_arguments] original_coefficients = [inv_replace_map[w] for w in renumbered_coefficients] # TODO: Build mapping from object to position instead? But we need mapped elements as well anyway. #argument_positions = { v: i } #coefficient_positions = { w: i } # Store data extracted by preprocessing form_data.original_arguments = original_arguments form_data.original_coefficients = original_coefficients # --- END SPLIT INTEGRAL JOIN # Mappings from elements and functions (coefficients and arguments) # that reside in form to objects with canonical numbering as well as # completed cells and elements # TODO: Create additional function mappings per integral, # to have different counts? Depends on future UFC design. form_data.element_replace_map = element_mapping form_data.function_replace_map = replace_map # Store some useful dimensions form_data.rank = len(form_data.original_arguments) form_data.num_coefficients = len(form_data.original_coefficients) # Store argument names form_data.argument_names = \ [object_names.get(id(form_data.original_arguments[i]), "v%d" % i) for i in range(form_data.rank)] # Store coefficient names form_data.coefficient_names = \ [object_names.get(id(form_data.original_coefficients[i]), "w%d" % i) for i in range(form_data.num_coefficients)] # --- END FUNCTION ANALYSIS # --- BEGIN SIGNATURE COMPUTATION # TODO: Compute signatures of each INTEGRAL and EXPR as well, perhaps compute it hierarchially from integral_data? # Store signature of form tic('signature') # TODO: Remove signature() from Form, not safe to cache with a replacement map #form_data.signature = form.signature(form_data.function_replace_map) form_data.signature = compute_form_signature(form, form_data.function_replace_map) # --- END SIGNATURE COMPUTATION # --- BEGIN CONSISTENCY CHECKS # Check that we don't have a mixed linear/bilinear form or anything like that ufl_assert(len(compute_form_arities(form)) == 1, "All terms in form must have same rank.") # --- END CONSISTENCY CHECKS # --- BEGIN ELEMENT DATA # Store elements, sub elements and element map tic('extract_elements') form_data.argument_elements = tuple(f.element() for f in renumbered_arguments) form_data.coefficient_elements = tuple(f.element() for f in renumbered_coefficients) form_data.elements = form_data.argument_elements + form_data.coefficient_elements form_data.unique_elements = unique_tuple(form_data.elements) form_data.sub_elements = extract_sub_elements(form_data.elements) form_data.unique_sub_elements = unique_tuple(form_data.sub_elements) # --- END ELEMENT DATA # --- BEGIN DOMAIN DATA # Store element domains (NB! This is likely to change!) # TODO: DOMAINS: What is a sensible way to store domains for a form? form_data.domains = tuple(sorted(set(element.domain() for element in form_data.unique_elements))) # Store toplevel domains (NB! This is likely to change!) # TODO: DOMAINS: What is a sensible way to store domains for a form? form_data.top_domains = tuple(sorted(set(domain.top_domain() for domain in form_data.domains))) # Store common cell form_data.cell = common_cell # Store data related to cell form_data.geometric_dimension = form_data.cell.geometric_dimension() form_data.topological_dimension = form_data.cell.topological_dimension() # Store number of domains for integral types form_data.num_sub_domains = extract_num_sub_domains(form) # --- END DOMAIN DATA # A coarse profiling implementation TODO: Add counting of nodes, Add memory usage tic.end() if preprocess.enable_profiling: print tic # Store preprocessed form and return form_data.preprocessed_form = form form_data.preprocessed_form._is_preprocessed = True # Attach signatures to original and preprocessed forms TODO: Avoid this? ufl_assert(form_data.preprocessed_form._signature is None, "") form_data.preprocessed_form._signature = form_data.signature ufl_assert(original_form._signature is None, "") original_form._signature = form_data.signature return form_data
def _compute_signature(self): from ufl.algorithms.signature import compute_form_signature self._signature = compute_form_signature(self, self._compute_renumbering())