def _basic_is_time_dependent(expression_or_form, iterator): for node in iterator(expression_or_form): # ... parametrized expressions if isinstance(node, BaseExpression): if is_pull_back_expression( node) and is_pull_back_expression_time_dependent(node): return True else: if has_pybind11(): parameters = node._parameters else: parameters = node.user_parameters if "t" in parameters: return True # ... problem solutions related to nonlinear terms elif wrapping.is_problem_solution_type(node): if wrapping.is_problem_solution(node): (preprocessed_node, component, truth_solution ) = wrapping.solution_identify_component(node) truth_problem = get_problem_from_solution(truth_solution) if hasattr(truth_problem, "set_time"): return True elif wrapping.is_problem_solution_dot(node): return True return False
def _basic_expression_name(expression): str_repr = "" coefficients_replacement = dict() # Preprocess indices first, as their numeric value might change from run to run, but they # are always sorted the same way indices = set() min_index = None for t in traverse_unique_terminals(expression): if isinstance(t, MultiIndex): for i in t.indices(): if isinstance(i, MuteIndex): if min_index is None or i.count() < min_index: min_index = i.count() indices.add(i) for i in indices: coefficients_replacement[repr(i)] = "MuteIndexRBniCS(" + str(i.count() - min_index) + ")" # Process the expression visited = set() for n in wrapping.expression_iterator(expression): if n in visited: continue if hasattr(n, "_cppcode"): coefficients_replacement[repr(n)] = str(n._cppcode) str_repr += repr(n._cppcode) visited.add(n) elif wrapping.is_problem_solution_type(n): if wrapping.is_problem_solution(n): (preprocessed_n, component, truth_solution) = wrapping.solution_identify_component(n) problem = get_problem_from_solution(truth_solution) coefficients_replacement[repr(preprocessed_n)] = "solution of " + str(problem.name()) + " (exact problem decorator: " + str(hasattr(problem, "__is_exact__")) + ", component: " + str(component) + ")" elif wrapping.is_problem_solution_dot(n): (preprocessed_n, component, truth_solution_dot) = wrapping.solution_dot_identify_component(n) problem = get_problem_from_solution_dot(truth_solution_dot) coefficients_replacement[repr(preprocessed_n)] = "solution_dot of " + str(problem.name()) + " (exact problem decorator: " + str(hasattr(problem, "__is_exact__")) + ", component: " + str(component) + ")" else: (preprocessed_n, component, problem) = wrapping.get_auxiliary_problem_for_non_parametrized_function(n) coefficients_replacement[repr(preprocessed_n)] = "non parametrized function associated to auxiliary problem " + str(problem.name()) if len(component) == 1 and component[0] is not None: coefficients_replacement[repr(preprocessed_n)] += ", component " + str(component[0]) elif len(component) > 1: coefficients_replacement[repr(preprocessed_n)] += ", component " + str(component) str_repr += coefficients_replacement[repr(preprocessed_n)] # Make sure to skip any parent solution related to this one visited.add(n) visited.add(preprocessed_n) for parent_n in wrapping.solution_iterator(preprocessed_n): visited.add(parent_n) elif isinstance(n, Constant): vals = n.values() coefficients_replacement[repr(n)] = str(vals) str_repr += repr(str(vals)) visited.add(n) else: str_repr += repr(n) visited.add(n) for key, value in coefficients_replacement.items(): str_repr = str_repr.replace(key, value) hash_code = hashlib.sha1(str_repr.encode("utf-8")).hexdigest() return hash_code
def _basic_expression_description(expression): visited = set() coefficients_repr = dict() for n in wrapping.expression_iterator(expression): if n in visited: continue if hasattr(n, "_cppcode"): coefficients_repr[n] = str(n._cppcode) visited.add(n) elif wrapping.is_problem_solution_type(n): if wrapping.is_problem_solution(n): (preprocessed_n, component, truth_solution) = wrapping.solution_identify_component(n) problem = get_problem_from_solution(truth_solution) coefficients_repr[preprocessed_n] = "solution of " + str( problem.name()) + " (exact problem decorator: " + str( hasattr(problem, "__is_exact__") ) + ", component: " + str(component) + ")" elif wrapping.is_problem_solution_dot(n): (preprocessed_n, component, truth_solution_dot ) = wrapping.solution_dot_identify_component(n) problem = get_problem_from_solution_dot(truth_solution_dot) coefficients_repr[ preprocessed_n] = "solution_dot of " + str( problem.name( )) + " (exact problem decorator: " + str( hasattr(problem, "__is_exact__") ) + ", component: " + str(component) + ")" else: ( preprocessed_n, component, problem ) = wrapping.get_auxiliary_problem_for_non_parametrized_function( n) coefficients_repr[ preprocessed_n] = "non parametrized function associated to auxiliary problem " + str( problem.name()) if len(component) == 1 and component[0] is not None: coefficients_repr[preprocessed_n] += ", component " + str( component[0]) elif len(component) > 1: coefficients_repr[preprocessed_n] += ", component " + str( component) # Make sure to skip any parent solution related to this one visited.add(n) visited.add(preprocessed_n) for parent_n in wrapping.solution_iterator(preprocessed_n): visited.add(parent_n) elif isinstance(n, Constant): vals = n.values() if len(vals) == 1: coefficients_repr[n] = str(vals[0]) else: coefficients_repr[n] = str(vals.reshape(n.ufl_shape)) visited.add(n) else: visited.add(n) return coefficients_repr
def create_interpolation_locations_container(self, **kwargs): # Populate auxiliary_problems_and_components visited = set() auxiliary_problems_and_components = set( ) # of (problem, component) for node in wrapping.form_iterator(self._form, "nodes"): if node in visited: continue # ... problem solutions related to nonlinear terms elif wrapping.is_problem_solution_type(node): if wrapping.is_problem_solution(node): (preprocessed_node, component, truth_solution ) = wrapping.solution_identify_component(node) truth_problem = get_problem_from_solution( truth_solution) auxiliary_problems_and_components.add( (truth_problem, component)) elif wrapping.is_problem_solution_dot(node): (preprocessed_node, component, truth_solution_dot ) = wrapping.solution_dot_identify_component(node) truth_problem = get_problem_from_solution_dot( truth_solution_dot) auxiliary_problems_and_components.add( (truth_problem, component)) else: ( preprocessed_node, component, auxiliary_problem ) = wrapping.get_auxiliary_problem_for_non_parametrized_function( node) auxiliary_problems_and_components.add( (auxiliary_problem, component)) # Make sure to skip any parent solution related to this one visited.add(node) visited.add(preprocessed_node) for parent_node in wrapping.solution_iterator( preprocessed_node): visited.add(parent_node) if len(auxiliary_problems_and_components) == 0: auxiliary_problems_and_components = None # Create reduced mesh assert "auxiliary_problems_and_components" not in kwargs kwargs[ "auxiliary_problems_and_components"] = auxiliary_problems_and_components return backend.ReducedMesh(self._spaces, **kwargs)
def _basic_expression_description(expression): visited = set() coefficients_repr = dict() for n in wrapping.expression_iterator(expression): if n in visited: continue if isinstance(n, BaseExpression): assert isinstance( n, (CompiledExpression, Expression)), "Other expression types are not handled yet" if isinstance(n, Expression): coefficients_repr[n] = str(n._cppcode) elif isinstance(n, CompiledExpression): assert hasattr( n, "f_no_upcast" ), "Only the case of pulled back expressions is currently handled" assert hasattr( n, "shape_parametrization_expression_on_subdomain_no_upcast" ), ("Only the case of pulled back expressions is currently handled" ) coefficients_repr[n] = ("PullBackExpression(" + str( n. shape_parametrization_expression_on_subdomain_no_upcast ._cppcode) + ", " + str(n.f_no_upcast._cppcode) + ")") visited.add(n) elif wrapping.is_problem_solution_type(n): if wrapping.is_problem_solution(n): (preprocessed_n, component, truth_solution) = wrapping.solution_identify_component(n) problem = get_problem_from_solution(truth_solution) coefficients_repr[preprocessed_n] = ( "solution of " + str(problem.name()) + " (exact problem decorator: " + str(hasattr(problem, "__is_exact__")) + ", component: " + str(component) + ")") elif wrapping.is_problem_solution_dot(n): (preprocessed_n, component, truth_solution_dot ) = wrapping.solution_dot_identify_component(n) problem = get_problem_from_solution_dot(truth_solution_dot) coefficients_repr[preprocessed_n] = ( "solution_dot of " + str(problem.name()) + " (exact problem decorator: " + str(hasattr(problem, "__is_exact__")) + ", component: " + str(component) + ")") else: ( preprocessed_n, component, problem ) = wrapping.get_auxiliary_problem_for_non_parametrized_function( n) coefficients_repr[preprocessed_n] = ( "non parametrized function associated to auxiliary problem " + str(problem.name())) if len(component) == 1 and component[0] is not None: coefficients_repr[preprocessed_n] += ", component " + str( component[0]) elif len(component) > 1: coefficients_repr[preprocessed_n] += ", component " + str( component) # Make sure to skip any parent solution related to this one visited.add(n) visited.add(preprocessed_n) for parent_n in wrapping.solution_iterator(preprocessed_n): visited.add(parent_n) elif isinstance(n, Constant): vals = n.values() if len(vals) == 1: coefficients_repr[n] = str(vals[0]) else: coefficients_repr[n] = str(vals.reshape(n.ufl_shape)) visited.add(n) else: visited.add(n) return coefficients_repr
def separate(self): class _SeparatedParametrizedForm_Replacer(Transformer): def __init__(self, mapping): Transformer.__init__(self) self.mapping = mapping def operator(self, e, *ops): if e in self.mapping: return self.mapping[e] else: return e._ufl_expr_reconstruct_(*ops) def terminal(self, e): return self.mapping.get(e, e) logger.log(DEBUG, "*** SEPARATE FORM COEFFICIENTS ***") logger.log(DEBUG, "1. Extract coefficients") integral_to_coefficients = dict() for integral in self._form.integrals(): logger.log( DEBUG, "\t Currently on integrand " + str(integral.integrand())) self._coefficients.append(list()) # of ParametrizedExpression for e in iter_expressions(integral): logger.log(DEBUG, "\t\t Expression " + str(e)) pre_traversal_e = [n for n in pre_traversal(e)] tree_nodes_skip = [False for _ in pre_traversal_e] for (n_i, n) in enumerate(pre_traversal_e): if not tree_nodes_skip[n_i]: # Skip expressions which are trivially non parametrized if isinstance(n, Argument): logger.log( DEBUG, "\t\t Node " + str(n) + " is skipped because it is an Argument") continue elif isinstance(n, Constant): logger.log( DEBUG, "\t\t Node " + str(n) + " is skipped because it is a Constant") continue elif isinstance(n, MultiIndex): logger.log( DEBUG, "\t\t Node " + str(n) + " is skipped because it is a MultiIndex") continue # Skip all expressions with at least one leaf which is an Argument for t in traverse_terminals(n): if isinstance(t, Argument): logger.log( DEBUG, "\t\t Node " + str(n) + " is skipped because it contains an Argument" ) break else: # not broken logger.log( DEBUG, "\t\t Node " + str(n) + " and its descendants are being analyzed for non-parametrized check" ) # Make sure to skip all descendants of this node in the outer loop # Note that a map with key set to the expression is not enough to # mark the node as visited, since the same expression may appear # on different sides of the tree pre_traversal_n = [d for d in pre_traversal(n)] for (d_i, d) in enumerate(pre_traversal_n): assert d == pre_traversal_e[ n_i + d_i] # make sure that we are marking the right node tree_nodes_skip[n_i + d_i] = True # We might be able to strip any (non-parametrized) expression out all_candidates = list() internal_tree_nodes_skip = [ False for _ in pre_traversal_n ] for (d_i, d) in enumerate(pre_traversal_n): if not internal_tree_nodes_skip[d_i]: # Skip all expressions where at least one leaf is not parametrized for t in traverse_terminals(d): if isinstance(t, BaseExpression): if wrapping.is_pull_back_expression( t ) and not wrapping.is_pull_back_expression_parametrized( t): logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " causes the non-parametrized check to break because it contains a non-parametrized pulled back expression" ) break else: parameters = t._parameters if "mu_0" not in parameters: logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " causes the non-parametrized check to break because it contains a non-parametrized expression" ) break elif isinstance(t, Constant): logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " causes the non-parametrized check to break because it contains a constant" ) break elif isinstance( t, GeometricQuantity ) and not isinstance( t, FacetNormal ) and self._strict: logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " causes the non-parametrized check to break because it contains a geometric quantity and strict mode is on" ) break elif wrapping.is_problem_solution_type( t): if not wrapping.is_problem_solution( t ) and not wrapping.is_problem_solution_dot( t): logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " causes the non-parametrized check to break because it contains a non-parametrized function" ) break elif self._strict: # solutions are not allowed, break if wrapping.is_problem_solution( t): ( _, component, solution ) = wrapping.solution_identify_component( t) problem = get_problem_from_solution( solution) logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " causes the non-parametrized check to break because it contains the solution of " + problem.name() + " (exact problem decorator: " + str( hasattr( problem, "__is_exact__" )) + ", component: " + str(component) + ") and strict mode is on" ) break elif wrapping.is_problem_solution_dot( t): ( _, component, solution_dot ) = wrapping.solution_dot_identify_component( t) problem = get_problem_from_solution_dot( solution_dot) logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " causes the non-parametrized check to break because it contains the solution_dot of " + problem.name() + " (exact problem decorator: " + str( hasattr( problem, "__is_exact__" )) + ", component: " + str(component) + ") and strict mode is on" ) else: raise RuntimeError( "Unidentified solution found" ) else: at_least_one_expression_or_solution = False for t in traverse_terminals(d): if isinstance( t, BaseExpression ): # which is parametrized, because previous for loop was not broken at_least_one_expression_or_solution = True logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " is a candidate after non-parametrized check because it contains the parametrized expression " + str(t)) break elif wrapping.is_problem_solution_type( t): if wrapping.is_problem_solution( t): at_least_one_expression_or_solution = True ( _, component, solution ) = wrapping.solution_identify_component( t) problem = get_problem_from_solution( solution) logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " is a candidate after non-parametrized check because it contains the solution of " + problem.name() + " (exact problem decorator: " + str( hasattr( problem, "__is_exact__" )) + ", component: " + str(component) + ")") break elif wrapping.is_problem_solution_dot( t): at_least_one_expression_or_solution = True ( _, component, solution_dot ) = wrapping.solution_dot_identify_component( t) problem = get_problem_from_solution_dot( solution_dot) logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " is a candidate after non-parametrized check because it contains the solution_dot of " + problem.name() + " (exact problem decorator: " + str( hasattr( problem, "__is_exact__" )) + ", component: " + str(component) + ")") break if at_least_one_expression_or_solution: all_candidates.append(d) pre_traversal_d = [ q for q in pre_traversal(d) ] for (q_i, q) in enumerate( pre_traversal_d): assert q == pre_traversal_n[ d_i + q_i] # make sure that we are marking the right node internal_tree_nodes_skip[ d_i + q_i] = True else: logger.log( DEBUG, "\t\t\t Descendant node " + str(d) + " has not passed the non-parametrized because it is not a parametrized expression or a solution" ) # Evaluate candidates if len( all_candidates ) == 0: # the whole expression was actually non-parametrized logger.log( DEBUG, "\t\t Node " + str(n) + " is skipped because it is a non-parametrized coefficient" ) continue elif len( all_candidates ) == 1: # the whole expression was actually parametrized logger.log( DEBUG, "\t\t Node " + str(n) + " will be accepted because it is a non-parametrized coefficient" ) pass else: # part of the expression was not parametrized, and separating the non parametrized part may result in more than one coefficient if self._strict: # non parametrized coefficients are not allowed, so split the expression logger.log( DEBUG, "\t\t\t Node " + str(n) + " will be accepted because it is a non-parametrized coefficient with more than one candidate. It will be split because strict mode is on. Its split coefficients are " + ", ".join([ str(c) for c in all_candidates ])) else: # non parametrized coefficients are allowed, so go on with the whole expression logger.log( DEBUG, "\t\t\t Node " + str(n) + " will be accepted because it is a non-parametrized coefficient with more than one candidate. It will not be split because strict mode is off. Splitting it would have resulted in more than one coefficient, namely " + ", ".join([ str(c) for c in all_candidates ])) all_candidates = [n] # Add the coefficient(s) for candidate in all_candidates: def preprocess_candidate(candidate): if isinstance(candidate, Indexed): assert len( candidate.ufl_operands) == 2 assert isinstance( candidate.ufl_operands[1], MultiIndex) if all([ isinstance( index, FixedIndex) for index in candidate. ufl_operands[1].indices() ]): logger.log( DEBUG, "\t\t\t Preprocessed descendant node " + str(candidate) + " as an Indexed expression with fixed indices, resulting in a candidate " + str(candidate) + " of type " + str(type(candidate))) return candidate # no further preprocessing needed else: logger.log( DEBUG, "\t\t\t Preprocessed descendant node " + str(candidate) + " as an Indexed expression with at least one mute index, resulting in a candidate " + str(candidate. ufl_operands[0]) + " of type " + str( type(candidate. ufl_operands[0]))) return preprocess_candidate( candidate.ufl_operands[0]) elif isinstance(candidate, IndexSum): assert len( candidate.ufl_operands) == 2 assert isinstance( candidate.ufl_operands[1], MultiIndex) assert all([ isinstance(index, MuteIndex) for index in candidate. ufl_operands[1].indices() ]) logger.log( DEBUG, "\t\t\t Preprocessed descendant node " + str(candidate) + " as an IndexSum expression, resulting in a candidate " + str(candidate.ufl_operands[0]) + " of type " + str( type(candidate. ufl_operands[0]))) return preprocess_candidate( candidate.ufl_operands[0]) elif isinstance(candidate, ListTensor): candidates = set([ preprocess_candidate(component) for component in candidate.ufl_operands ]) if len(candidates) == 1: preprocessed_candidate = candidates.pop( ) logger.log( DEBUG, "\t\t\t Preprocessed descendant node " + str(candidate) + " as an ListTensor expression with a unique preprocessed component, resulting in a candidate " + str(preprocessed_candidate) + " of type " + str( type( preprocessed_candidate ))) return preprocess_candidate( preprocessed_candidate) else: at_least_one_mute_index = False candidates_from_components = list( ) for component in candidates: assert isinstance( component, (ComponentTensor, Indexed)) assert len( component.ufl_operands ) == 2 assert isinstance( component. ufl_operands[1], MultiIndex) if not all([ isinstance( index, FixedIndex) for index in component. ufl_operands[1]. indices() ]): at_least_one_mute_index = True candidates_from_components.append( preprocess_candidate( component. ufl_operands[0])) if at_least_one_mute_index: candidates_from_components = set( candidates_from_components ) assert len( candidates_from_components ) == 1 preprocessed_candidate = candidates_from_components.pop( ) logger.log( DEBUG, "\t\t\t Preprocessed descendant node " + str(candidate) + " as an ListTensor expression with multiple preprocessed components with at least one mute index, resulting in a candidate " + str(preprocessed_candidate ) + " of type " + str( type( preprocessed_candidate ))) return preprocess_candidate( preprocessed_candidate) else: logger.log( DEBUG, "\t\t\t Preprocessed descendant node " + str(candidate) + " as an ListTensor expression with multiple preprocessed components with fixed indices, resulting in a candidate " + str(candidate) + " of type " + str(type(candidate))) return candidate # no further preprocessing needed else: logger.log( DEBUG, "\t\t\t No preprocessing required for descendant node " + str(candidate) + " as a coefficient of type " + str(type(candidate))) return candidate preprocessed_candidate = preprocess_candidate( candidate) if preprocessed_candidate not in self._coefficients[ -1]: self._coefficients[-1].append( preprocessed_candidate) logger.log( DEBUG, "\t\t\t Accepting descendant node " + str(preprocessed_candidate) + " as a coefficient of type " + str(type(preprocessed_candidate))) else: logger.log( DEBUG, "\t\t Node " + str(n) + " to be skipped because it is a descendant of a coefficient which has already been detected" ) if len(self._coefficients[-1] ) == 0: # then there were no coefficients to extract logger.log(DEBUG, "\t There were no coefficients to extract") self._coefficients.pop( ) # remove the (empty) element that was added to possibly store coefficients else: logger.log(DEBUG, "\t Extracted coefficients are:") for c in self._coefficients[-1]: logger.log(DEBUG, "\t\t" + str(c)) integral_to_coefficients[integral] = self._coefficients[-1] logger.log(DEBUG, "2. Prepare placeholders and forms with placeholders") for integral in self._form.integrals(): # Prepare measure for the new form (from firedrake/mg/ufl_utils.py) measure = Measure(integral.integral_type(), domain=integral.ufl_domain(), subdomain_id=integral.subdomain_id(), subdomain_data=integral.subdomain_data(), metadata=integral.metadata()) if integral not in integral_to_coefficients: logger.log( DEBUG, "\t Adding form for integrand " + str(integral.integrand()) + " to unchanged forms") self._form_unchanged.append(integral.integrand() * measure) else: logger.log( DEBUG, "\t Preparing form with placeholders for integrand " + str(integral.integrand())) self._placeholders.append(list()) # of Constants placeholders_dict = dict() for c in integral_to_coefficients[integral]: self._placeholders[-1].append( Constant(self._NaN * ones(c.ufl_shape))) placeholders_dict[c] = self._placeholders[-1][-1] logger.log( DEBUG, "\t\t " + str(placeholders_dict[c]) + " is the placeholder for " + str(c)) replacer = _SeparatedParametrizedForm_Replacer( placeholders_dict) new_integrand = apply_transformer(integral.integrand(), replacer) self._form_with_placeholders.append(new_integrand * measure) logger.log( DEBUG, "3. Assert that there are no parametrized expressions left") for form in self._form_with_placeholders: for integral in form.integrals(): for e in pre_traversal(integral.integrand()): if isinstance(e, BaseExpression): assert not ( wrapping.is_pull_back_expression(e) and wrapping. is_pull_back_expression_parametrized(e) ), "Form " + str( integral ) + " still contains a parametrized pull back expression" parameters = e._parameters assert "mu_0" not in parameters, "Form " + str( integral ) + " still contains a parametrized expression" logger.log(DEBUG, "4. Prepare coefficients hash codes") for addend in self._coefficients: self._placeholder_names.append(list()) # of string for factor in addend: self._placeholder_names[-1].append( wrapping.expression_name(factor)) logger.log(DEBUG, "5. Assert list length consistency") assert len(self._coefficients) == len(self._placeholders) assert len(self._coefficients) == len(self._placeholder_names) for (c, p, pn) in zip(self._coefficients, self._placeholders, self._placeholder_names): assert len(c) == len(p) assert len(c) == len(pn) assert len(self._coefficients) == len(self._form_with_placeholders) logger.log(DEBUG, "*** DONE - SEPARATE FORM COEFFICIENTS - DONE ***") logger.log(DEBUG, "")
def _basic_form_on_reduced_function_space(form_wrapper, at): form = form_wrapper._form form_name = form_wrapper.name() form_problem = get_problem_from_parametrized_operator(form_wrapper) reduced_V = at.get_reduced_function_spaces() reduced_subdomain_data = at.get_reduced_subdomain_data() mu = form_problem.mu if hasattr(form_problem, "set_time"): t = form_problem.t else: t = None if (form_name, reduced_V) not in form_cache: visited = set() replacements = dict() truth_problems = list() truth_problem_to_components = { # outer dict index over time derivative 0: dict(), 1: dict() } truth_problem_to_exact_truth_problem = dict() truth_problem_to_reduced_mesh_solution = dict() truth_problem_to_reduced_mesh_solution_dot = dict() truth_problem_to_reduced_mesh_interpolator = { # outer dict index over time derivative 0: dict(), 1: dict() } reduced_problem_to_components = { # outer dict index over time derivative 0: dict(), 1: dict() } reduced_problem_to_reduced_mesh_solution = dict() reduced_problem_to_reduced_mesh_solution_dot = dict() reduced_problem_to_reduced_basis_functions = { # outer dict index over time derivative 0: dict(), 1: dict() } # Look for terminals on truth mesh logger.log(DEBUG, "Traversing terminals of form " + form_name) for node in wrapping.form_iterator(form, "nodes"): if node in visited: continue # ... test and trial functions elif isinstance(node, Argument): logger.log( DEBUG, "\tFound argument, number: " + str(node.number()) + ", part: " + str(node.part())) replacements[node] = wrapping.form_argument_replace( node, reduced_V) visited.add(node) # ... problem solutions related to nonlinear terms elif wrapping.is_problem_solution_type(node): node_is_problem_solution = wrapping.is_problem_solution( node) node_is_problem_solution_dot = wrapping.is_problem_solution_dot( node) if node_is_problem_solution or node_is_problem_solution_dot: if node_is_problem_solution: (preprocessed_node, component, truth_solution ) = wrapping.solution_identify_component(node) truth_problem = get_problem_from_solution( truth_solution) logger.log( DEBUG, "\tFound problem solution of truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ", component: " + str(component) + ")") # Time derivative key for components and interpolator dicts time_derivative = 0 elif node_is_problem_solution_dot: (preprocessed_node, component, truth_solution_dot ) = wrapping.solution_dot_identify_component(node) truth_problem = get_problem_from_solution_dot( truth_solution_dot) logger.log( DEBUG, "\tFound problem solution dot of truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ", component: " + str(component) + ")") # Time derivative key for components and interpolator dicts time_derivative = 1 # Store truth problem if truth_problem not in truth_problems: truth_problems.append(truth_problem) # Store the component if truth_problem not in truth_problem_to_components[ time_derivative]: truth_problem_to_components[time_derivative][ truth_problem] = list() if component not in truth_problem_to_components[ time_derivative][truth_problem]: truth_problem_to_components[time_derivative][ truth_problem].append(component) # Get the function space corresponding to preprocessed_node on the reduced mesh auxiliary_reduced_V = at.get_auxiliary_reduced_function_space( truth_problem, component) # Define and store the replacement assert preprocessed_node not in replacements # as it is related to a new truth solution component replacements[preprocessed_node] = backend.Function( auxiliary_reduced_V) if time_derivative == 0: if truth_problem not in truth_problem_to_reduced_mesh_solution: truth_problem_to_reduced_mesh_solution[ truth_problem] = list() truth_problem_to_reduced_mesh_solution[ truth_problem].append( replacements[preprocessed_node]) elif time_derivative == 1: if truth_problem not in truth_problem_to_reduced_mesh_solution_dot: truth_problem_to_reduced_mesh_solution_dot[ truth_problem] = list() truth_problem_to_reduced_mesh_solution_dot[ truth_problem].append( replacements[preprocessed_node]) # Get interpolator on reduced mesh if truth_problem not in truth_problem_to_reduced_mesh_interpolator[ time_derivative]: truth_problem_to_reduced_mesh_interpolator[ time_derivative][truth_problem] = list() truth_problem_to_reduced_mesh_interpolator[ time_derivative][truth_problem].append( at.get_auxiliary_function_interpolator( truth_problem, component)) else: ( preprocessed_node, component, auxiliary_problem ) = wrapping.get_auxiliary_problem_for_non_parametrized_function( node) logger.log( DEBUG, "\tFound non parametrized function " + str(preprocessed_node) + " associated to auxiliary problem " + str(auxiliary_problem.name()) + ", component: " + str(component)) if preprocessed_node not in replacements: # Get interpolator on reduced mesh auxiliary_truth_problem_to_reduced_mesh_interpolator = at.get_auxiliary_function_interpolator( auxiliary_problem, component) # Define and store the replacement replacements[ preprocessed_node] = auxiliary_truth_problem_to_reduced_mesh_interpolator( preprocessed_node) # Make sure to skip any parent solution related to this one visited.add(node) visited.add(preprocessed_node) for parent_node in wrapping.solution_iterator( preprocessed_node): visited.add(parent_node) # ... geometric quantities elif isinstance(node, GeometricQuantity): logger.log(DEBUG, "\tFound geometric quantity " + str(node)) if len(reduced_V) == 2: assert reduced_V[0].mesh().ufl_domain( ) == reduced_V[1].mesh().ufl_domain() replacements[node] = type(node)(reduced_V[0].mesh()) visited.add(node) else: visited.add(node) # ... and replace them replaced_form = wrapping.form_replace(form, replacements, "nodes") # Look for measures ... if len(reduced_V) == 2: assert reduced_V[0].mesh().ufl_domain() == reduced_V[1].mesh( ).ufl_domain() measure_reduced_domain = reduced_V[0].mesh().ufl_domain() replacements_measures = dict() for integral in wrapping.form_iterator(replaced_form, "integrals"): # Prepare measure for the new form (from firedrake/mg/ufl_utils.py) integral_subdomain_data = integral.subdomain_data() if integral_subdomain_data is not None: integral_reduced_subdomain_data = reduced_subdomain_data[ integral_subdomain_data] else: integral_reduced_subdomain_data = None measure = Measure( integral.integral_type(), domain=measure_reduced_domain, subdomain_id=integral.subdomain_id(), subdomain_data=integral_reduced_subdomain_data, metadata=integral.metadata()) replacements_measures[integral.integrand(), integral.integral_type(), integral.subdomain_id()] = measure # ... and replace them replaced_form_with_replaced_measures = wrapping.form_replace( replaced_form, replacements_measures, "measures") # Cache the resulting dicts form_cache[(form_name, reduced_V)] = replaced_form_with_replaced_measures truth_problems_cache[(form_name, reduced_V)] = truth_problems truth_problem_to_components_cache[( form_name, reduced_V)] = truth_problem_to_components truth_problem_to_exact_truth_problem_cache[( form_name, reduced_V)] = truth_problem_to_exact_truth_problem truth_problem_to_reduced_mesh_solution_cache[( form_name, reduced_V)] = truth_problem_to_reduced_mesh_solution truth_problem_to_reduced_mesh_solution_dot_cache[( form_name, reduced_V)] = truth_problem_to_reduced_mesh_solution_dot truth_problem_to_reduced_mesh_interpolator_cache[( form_name, reduced_V)] = truth_problem_to_reduced_mesh_interpolator reduced_problem_to_components_cache[( form_name, reduced_V)] = reduced_problem_to_components reduced_problem_to_reduced_mesh_solution_cache[( form_name, reduced_V)] = reduced_problem_to_reduced_mesh_solution reduced_problem_to_reduced_mesh_solution_dot_cache[( form_name, reduced_V)] = reduced_problem_to_reduced_mesh_solution_dot reduced_problem_to_reduced_basis_functions_cache[( form_name, reduced_V)] = reduced_problem_to_reduced_basis_functions # Extract from cache replaced_form_with_replaced_measures = form_cache[(form_name, reduced_V)] truth_problems = truth_problems_cache[(form_name, reduced_V)] truth_problem_to_components = truth_problem_to_components_cache[( form_name, reduced_V)] truth_problem_to_exact_truth_problem = truth_problem_to_exact_truth_problem_cache[ (form_name, reduced_V)] truth_problem_to_reduced_mesh_solution = truth_problem_to_reduced_mesh_solution_cache[ (form_name, reduced_V)] truth_problem_to_reduced_mesh_solution_dot = truth_problem_to_reduced_mesh_solution_dot_cache[ (form_name, reduced_V)] truth_problem_to_reduced_mesh_interpolator = truth_problem_to_reduced_mesh_interpolator_cache[ (form_name, reduced_V)] reduced_problem_to_components = reduced_problem_to_components_cache[( form_name, reduced_V)] reduced_problem_to_reduced_mesh_solution = reduced_problem_to_reduced_mesh_solution_cache[ (form_name, reduced_V)] reduced_problem_to_reduced_mesh_solution_dot = reduced_problem_to_reduced_mesh_solution_dot_cache[ (form_name, reduced_V)] reduced_problem_to_reduced_basis_functions = reduced_problem_to_reduced_basis_functions_cache[ (form_name, reduced_V)] # Get list of truth and reduced problems that need to be solved, possibly updating cache required_truth_problems = list() required_reduced_problems = list() for truth_problem in truth_problems: truth_problem_is_solving = hasattr(truth_problem, "_is_solving") if is_training_started(truth_problem): reduced_problem = get_reduced_problem_from_problem( truth_problem) reduced_problem_is_solving = hasattr(reduced_problem, "_is_solving") else: reduced_problem = None reduced_problem_is_solving = False if not truth_problem_is_solving: if is_training_finished(truth_problem): logger.log( DEBUG, "Truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ") is not currently solving, and its offline stage has finished: truth problem will be replaced by reduced problem" ) # Store the replacement for solution if (reduced_problem not in reduced_problem_to_reduced_mesh_solution and truth_problem in truth_problem_to_reduced_mesh_solution): reduced_problem_to_reduced_mesh_solution[ reduced_problem] = truth_problem_to_reduced_mesh_solution[ truth_problem] # Store the component assert reduced_problem not in reduced_problem_to_components[ 0] assert truth_problem in truth_problem_to_components[0] reduced_problem_to_components[0][ reduced_problem] = truth_problem_to_components[0][ truth_problem] # Get reduced problem basis functions on reduced mesh assert reduced_problem not in reduced_problem_to_reduced_basis_functions[ 0] reduced_problem_to_reduced_basis_functions[0][ reduced_problem] = [ at.get_auxiliary_basis_functions_matrix( truth_problem, component) for component in reduced_problem_to_components[0] [reduced_problem] ] # Store the replacement for solution_dot if (reduced_problem not in reduced_problem_to_reduced_mesh_solution_dot and truth_problem in truth_problem_to_reduced_mesh_solution_dot): reduced_problem_to_reduced_mesh_solution_dot[ reduced_problem] = truth_problem_to_reduced_mesh_solution_dot[ truth_problem] # Store the component assert reduced_problem not in reduced_problem_to_components[ 1] assert truth_problem in truth_problem_to_components[1] reduced_problem_to_components[1][ reduced_problem] = truth_problem_to_components[1][ truth_problem] # Get reduced problem basis functions on reduced mesh assert reduced_problem not in reduced_problem_to_reduced_basis_functions[ 1] reduced_problem_to_reduced_basis_functions[1][ reduced_problem] = [ at.get_auxiliary_basis_functions_matrix( truth_problem, component) for component in reduced_problem_to_components[1] [reduced_problem] ] # Append to list of required reduced problems required_reduced_problems.append( (reduced_problem, reduced_problem_is_solving)) else: if (hasattr(truth_problem, "_apply_exact_evaluation_at_stages") and not hasattr(truth_problem, "_apply_EIM_at_stages") and not hasattr(truth_problem, "_apply_DEIM_at_stages")): logger.log( DEBUG, "Truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ") is not currently solving, its offline stage has not finished, and only @ExactParametrizedFunctions has been used: truth solve of this truth problem instance will be called" ) # Init truth problem (if required), as it may not have been initialized truth_problem.init() # Append to list of required truth problems which are not currently solving required_truth_problems.append( (truth_problem, False, reduced_problem_is_solving)) else: logger.log( DEBUG, "Truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ") is not currently solving, its offline stage has not finished, and either @ExactParametrizedFunctions has not been used or it has been used in combination with @DEIM or @EIM: truth solve on an auxiliary instance (with exact problem decorator) will be called, to prevent early initialization of DEIM/EIM data structures" ) # Store the corresponding exact truth problem if truth_problem not in truth_problem_to_exact_truth_problem: exact_truth_problem = exact_problem(truth_problem) truth_problem_to_exact_truth_problem[ truth_problem] = exact_truth_problem # Init exact truth problem (if required), as it may not have been initialized exact_truth_problem.init() else: exact_truth_problem = truth_problem_to_exact_truth_problem[ truth_problem] # Store the replacement for solution if (exact_truth_problem not in truth_problem_to_reduced_mesh_solution and truth_problem in truth_problem_to_reduced_mesh_solution): truth_problem_to_reduced_mesh_solution[ exact_truth_problem] = truth_problem_to_reduced_mesh_solution[ truth_problem] # Store the component assert exact_truth_problem not in truth_problem_to_components[ 0] assert truth_problem in truth_problem_to_components[ 0] truth_problem_to_components[0][ exact_truth_problem] = truth_problem_to_components[ 0][truth_problem] # Get interpolator on reduced mesh assert exact_truth_problem not in truth_problem_to_reduced_mesh_interpolator[ 0] assert truth_problem in truth_problem_to_reduced_mesh_interpolator[ 0] truth_problem_to_reduced_mesh_interpolator[0][ exact_truth_problem] = truth_problem_to_reduced_mesh_interpolator[ 0][truth_problem] # Store the replacement for solution_dot if (exact_truth_problem not in truth_problem_to_reduced_mesh_solution_dot and truth_problem in truth_problem_to_reduced_mesh_solution_dot): truth_problem_to_reduced_mesh_solution_dot[ exact_truth_problem] = truth_problem_to_reduced_mesh_solution_dot[ truth_problem] # Store the component assert exact_truth_problem not in truth_problem_to_components[ 1] assert truth_problem in truth_problem_to_components[ 1] truth_problem_to_components[1][ exact_truth_problem] = truth_problem_to_components[ 1][truth_problem] # Get interpolator on reduced mesh assert exact_truth_problem not in truth_problem_to_reduced_mesh_interpolator[ 1] assert truth_problem in truth_problem_to_reduced_mesh_interpolator[ 1] truth_problem_to_reduced_mesh_interpolator[1][ exact_truth_problem] = truth_problem_to_reduced_mesh_interpolator[ 1][truth_problem] # Append to list of required truth problems which are not currently solving required_truth_problems.append( (exact_truth_problem, False, reduced_problem_is_solving)) else: logger.log( DEBUG, "Truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ") is currently solving: current truth solution will be loaded" ) assert not reduced_problem_is_solving # Append to list of required truth problems which are currently solving required_truth_problems.append((truth_problem, True, False)) # Solve truth problems (which have not been reduced yet) associated to nonlinear terms for (truth_problem, truth_problem_is_solving, reduced_problem_is_solving) in required_truth_problems: if not reduced_problem_is_solving: # Solve (if necessary) truth_problem.set_mu(mu) if not truth_problem_is_solving: logger.log( DEBUG, "Requiring truth problem solve for problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ")") truth_problem.solve() else: logger.log( DEBUG, "Loading current truth problem solution for problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ")") else: reduced_problem = get_reduced_problem_from_problem( truth_problem) logger.log( DEBUG, "Replacing current truth problem solution with reduced solution for problem " + reduced_problem.truth_problem.name()) # Assign to reduced_mesh_solution if truth_problem in truth_problem_to_reduced_mesh_solution: for (reduced_mesh_solution, reduced_mesh_interpolator) in zip( truth_problem_to_reduced_mesh_solution[truth_problem], truth_problem_to_reduced_mesh_interpolator[0] [truth_problem]): solution_to = reduced_mesh_solution if t is None: if not reduced_problem_is_solving: solution_from = reduced_mesh_interpolator( truth_problem._solution) else: solution_from = reduced_mesh_interpolator( reduced_problem. basis_functions[:reduced_problem._solution.N] * reduced_problem._solution) else: if not reduced_problem_is_solving: if not truth_problem_is_solving: solution_from = reduced_mesh_interpolator( truth_problem._solution_over_time.at(t)) else: solution_from = reduced_mesh_interpolator( truth_problem._solution) else: solution_from = reduced_mesh_interpolator( reduced_problem. basis_functions[:reduced_problem._solution.N] * reduced_problem._solution) backend.assign(solution_to, solution_from) # Assign to reduced_mesh_solution_dot if truth_problem in truth_problem_to_reduced_mesh_solution_dot: for (reduced_mesh_solution_dot, reduced_mesh_interpolator) in zip( truth_problem_to_reduced_mesh_solution_dot[ truth_problem], truth_problem_to_reduced_mesh_interpolator[1] [truth_problem]): solution_dot_to = reduced_mesh_solution_dot assert t is not None if not reduced_problem_is_solving: if not truth_problem_is_solving: solution_dot_from = reduced_mesh_interpolator( truth_problem._solution_dot_over_time.at(t)) else: solution_dot_from = reduced_mesh_interpolator( truth_problem._solution_dot) else: solution_dot_from = reduced_mesh_interpolator( reduced_problem.basis_functions[:reduced_problem. _solution_dot.N] * reduced_problem._solution_dot) backend.assign(solution_dot_to, solution_dot_from) # Solve reduced problems associated to nonlinear terms for (reduced_problem, is_solving) in required_reduced_problems: # Solve (if necessary) reduced_problem.set_mu(mu) if not is_solving: logger.log( DEBUG, "Requiring reduced problem solve for problem " + reduced_problem.truth_problem.name()) reduced_problem.solve() else: logger.log( DEBUG, "Loading current reduced problem solution for problem " + reduced_problem.truth_problem.name()) # Assign to reduced_mesh_solution if reduced_problem in reduced_problem_to_reduced_mesh_solution: for (reduced_mesh_solution, reduced_basis_functions) in zip( reduced_problem_to_reduced_mesh_solution[ reduced_problem], reduced_problem_to_reduced_basis_functions[0] [reduced_problem]): solution_to = reduced_mesh_solution solution_from_N = OnlineSizeDict() for c, v in reduced_problem._solution.N.items(): if c in reduced_basis_functions._components_name: solution_from_N[c] = v solution_from = online_backend.OnlineFunction( solution_from_N) if t is None or is_solving: online_backend.online_assign(solution_from, reduced_problem._solution) else: online_backend.online_assign( solution_from, reduced_problem._solution_over_time.at(t)) solution_from = reduced_basis_functions[:solution_from_N] * solution_from backend.assign(solution_to, solution_from) # Assign to reduced_mesh_solution_dot if reduced_problem in reduced_problem_to_reduced_mesh_solution_dot: for (reduced_mesh_solution_dot, reduced_basis_functions) in zip( reduced_problem_to_reduced_mesh_solution_dot[ reduced_problem], reduced_problem_to_reduced_basis_functions[1] [reduced_problem]): solution_dot_to = reduced_mesh_solution_dot solution_dot_from_N = OnlineSizeDict() for c, v in reduced_problem._solution_dot.N.items(): if c in reduced_basis_functions._components_name: solution_dot_from_N[c] = v solution_dot_from = online_backend.OnlineFunction( solution_dot_from_N) assert t is not None if is_solving: online_backend.online_assign( solution_dot_from, reduced_problem._solution_dot) else: online_backend.online_assign( solution_dot_from, reduced_problem._solution_dot_over_time.at(t)) solution_dot_from = reduced_basis_functions[: solution_dot_from_N] * solution_dot_from backend.assign(solution_dot_to, solution_dot_from) # Assemble and return assembled_replaced_form = wrapping.assemble( replaced_form_with_replaced_measures) if not isinstance(assembled_replaced_form, Number): form_rank = assembled_replaced_form.rank() else: form_rank = 0 return (assembled_replaced_form, form_rank)
def _basic_form_on_truth_function_space(form_wrapper, tensor=None): form = form_wrapper._form form_name = form_wrapper.name() form_problem = get_problem_from_parametrized_operator(form_wrapper) mu = form_problem.mu if hasattr(form_problem, "set_time"): t = form_problem.t else: t = None if form_name not in reduced_problem_to_truth_solution_cache: visited = set() truth_problems = list() truth_problem_to_components = { # outer dict index over time derivative 0: dict(), 1: dict() } truth_problem_to_exact_truth_problem = dict() truth_problem_to_truth_solution = dict() truth_problem_to_truth_solution_copy = dict() truth_problem_to_truth_solution_dot = dict() truth_problem_to_truth_solution_dot_copy = dict() reduced_problem_to_components = { # outer dict index over time derivative 0: dict(), 1: dict() } reduced_problem_to_truth_solution = dict() reduced_problem_to_truth_solution_copy = dict() reduced_problem_to_truth_solution_dot = dict() reduced_problem_to_truth_solution_dot_copy = dict() # Look for terminals on truth mesh for node in wrapping.form_iterator(form): if node in visited: continue # ... problem solutions related to nonlinear terms elif wrapping.is_problem_solution_type(node): node_is_problem_solution = wrapping.is_problem_solution( node) node_is_problem_solution_dot = wrapping.is_problem_solution_dot( node) if node_is_problem_solution or node_is_problem_solution_dot: if node_is_problem_solution: (preprocessed_node, component, truth_solution ) = wrapping.solution_identify_component(node) truth_problem = get_problem_from_solution( truth_solution) if truth_problem not in truth_problems: truth_problems.append(truth_problem) # Store the solution if truth_problem not in truth_problem_to_truth_solution: truth_problem_to_truth_solution[ truth_problem] = truth_solution truth_problem_to_truth_solution_copy[ truth_problem] = backend.copy( truth_solution) else: assert truth_problem_to_truth_solution[ truth_problem] is truth_solution assert truth_problem in truth_problem_to_truth_solution_copy # Time derivative key for components dict time_derivative = 0 elif node_is_problem_solution_dot: (preprocessed_node, component, truth_solution_dot ) = wrapping.solution_dot_identify_component(node) truth_problem = get_problem_from_solution_dot( truth_solution_dot) if truth_problem not in truth_problems: truth_problems.append(truth_problem) # Store the solution_dot if truth_problem not in truth_problem_to_truth_solution_dot: truth_problem_to_truth_solution_dot[ truth_problem] = truth_solution_dot truth_problem_to_truth_solution_dot_copy[ truth_problem] = backend.copy( truth_solution_dot) else: assert truth_problem_to_truth_solution_dot[ truth_problem] is truth_solution_dot assert truth_problem in truth_problem_to_truth_solution_dot_copy # Time derivative key for components dict time_derivative = 1 # Store truth problem if truth_problem not in truth_problems: truth_problems.append(truth_problem) # Store the component if truth_problem not in truth_problem_to_components[ time_derivative]: truth_problem_to_components[time_derivative][ truth_problem] = list() if component not in truth_problem_to_components[ time_derivative][truth_problem]: truth_problem_to_components[time_derivative][ truth_problem].append(component) else: ( preprocessed_node, _, _ ) = wrapping.get_auxiliary_problem_for_non_parametrized_function( node) # Make sure to skip any parent solution related to this one visited.add(node) visited.add(preprocessed_node) for parent_node in wrapping.solution_iterator( preprocessed_node): visited.add(parent_node) else: visited.add(node) # Cache the resulting dicts truth_problems_cache[form_name] = truth_problems truth_problem_to_components_cache[ form_name] = truth_problem_to_components truth_problem_to_exact_truth_problem_cache[ form_name] = truth_problem_to_exact_truth_problem truth_problem_to_truth_solution_cache[ form_name] = truth_problem_to_truth_solution truth_problem_to_truth_solution_copy_cache[ form_name] = truth_problem_to_truth_solution_copy truth_problem_to_truth_solution_dot_cache[ form_name] = truth_problem_to_truth_solution_dot truth_problem_to_truth_solution_dot_copy_cache[ form_name] = truth_problem_to_truth_solution_dot_copy reduced_problem_to_components_cache[ form_name] = reduced_problem_to_components reduced_problem_to_truth_solution_cache[ form_name] = reduced_problem_to_truth_solution reduced_problem_to_truth_solution_copy_cache[ form_name] = reduced_problem_to_truth_solution_copy reduced_problem_to_truth_solution_dot_cache[ form_name] = reduced_problem_to_truth_solution_dot reduced_problem_to_truth_solution_dot_copy_cache[ form_name] = reduced_problem_to_truth_solution_dot_copy # Extract from cache truth_problems = truth_problems_cache[form_name] truth_problem_to_components = truth_problem_to_components_cache[ form_name] truth_problem_to_exact_truth_problem = truth_problem_to_exact_truth_problem_cache[ form_name] truth_problem_to_truth_solution = truth_problem_to_truth_solution_cache[ form_name] truth_problem_to_truth_solution_copy = truth_problem_to_truth_solution_copy_cache[ form_name] truth_problem_to_truth_solution_dot = truth_problem_to_truth_solution_dot_cache[ form_name] truth_problem_to_truth_solution_dot_copy = truth_problem_to_truth_solution_dot_copy_cache[ form_name] reduced_problem_to_components = reduced_problem_to_components_cache[ form_name] reduced_problem_to_truth_solution = reduced_problem_to_truth_solution_cache[ form_name] reduced_problem_to_truth_solution_copy = reduced_problem_to_truth_solution_copy_cache[ form_name] reduced_problem_to_truth_solution_dot = reduced_problem_to_truth_solution_dot_cache[ form_name] reduced_problem_to_truth_solution_dot_copy = reduced_problem_to_truth_solution_dot_copy_cache[ form_name] # Get list of truth and reduced problems that need to be solved, possibly updating cache required_truth_problems = list() required_reduced_problems = list() for truth_problem in truth_problems: truth_problem_is_solving = hasattr(truth_problem, "_is_solving") if is_training_started(truth_problem): reduced_problem = get_reduced_problem_from_problem( truth_problem) reduced_problem_is_solving = hasattr(reduced_problem, "_is_solving") else: reduced_problem = None reduced_problem_is_solving = False if not truth_problem_is_solving: if is_training_finished(truth_problem): # Store the solution if (reduced_problem not in reduced_problem_to_truth_solution and truth_problem in truth_problem_to_truth_solution): reduced_problem_to_truth_solution[ reduced_problem] = truth_problem_to_truth_solution[ truth_problem] assert reduced_problem not in reduced_problem_to_truth_solution_copy assert truth_problem in truth_problem_to_truth_solution_copy reduced_problem_to_truth_solution_copy[ reduced_problem] = truth_problem_to_truth_solution_copy[ truth_problem] # Store the component assert reduced_problem not in reduced_problem_to_components assert truth_problem in truth_problem_to_components[0] reduced_problem_to_components[0][ reduced_problem] = truth_problem_to_components[0][ truth_problem] # Store the solution_dot if (reduced_problem not in reduced_problem_to_truth_solution_dot and truth_problem in truth_problem_to_truth_solution_dot): reduced_problem_to_truth_solution_dot[ reduced_problem] = truth_problem_to_truth_solution_dot[ truth_problem] assert reduced_problem not in reduced_problem_to_truth_solution_dot_copy assert truth_problem in truth_problem_to_truth_solution_dot_copy reduced_problem_to_truth_solution_dot_copy[ reduced_problem] = truth_problem_to_truth_solution_dot_copy[ truth_problem] # Store the component assert reduced_problem not in reduced_problem_to_components assert truth_problem in truth_problem_to_components[1] reduced_problem_to_components[1][ reduced_problem] = truth_problem_to_components[1][ truth_problem] # Append to list of required reduced problems required_reduced_problems.append( (reduced_problem, reduced_problem_is_solving)) else: if (hasattr(truth_problem, "_apply_exact_evaluation_at_stages") and not hasattr(truth_problem, "_apply_EIM_at_stages") and not hasattr(truth_problem, "_apply_DEIM_at_stages")): # Init truth problem (if required), as it may not have been initialized truth_problem.init() # Append to list of required truth problems which are not currently solving required_truth_problems.append( (truth_problem, False, reduced_problem_is_solving)) else: # Store the corresponding exact truth problem if truth_problem not in truth_problem_to_exact_truth_problem: exact_truth_problem = exact_problem(truth_problem) truth_problem_to_exact_truth_problem[ truth_problem] = exact_truth_problem # Init exact truth problem (if required), as it may not have been initialized exact_truth_problem.init() else: exact_truth_problem = truth_problem_to_exact_truth_problem[ truth_problem] # Store the solution if (exact_truth_problem not in truth_problem_to_truth_solution and truth_problem in truth_problem_to_truth_solution): truth_problem_to_truth_solution[ exact_truth_problem] = truth_problem_to_truth_solution[ truth_problem] assert exact_truth_problem not in truth_problem_to_truth_solution_copy assert truth_problem in truth_problem_to_truth_solution_copy truth_problem_to_truth_solution_copy[ exact_truth_problem] = truth_problem_to_truth_solution_copy[ truth_problem] # Store the component assert exact_truth_problem not in truth_problem_to_components[ 0] assert truth_problem in truth_problem_to_components[ 0] truth_problem_to_components[0][ exact_truth_problem] = truth_problem_to_components[ 0][truth_problem] # Store the solution_dot if (exact_truth_problem not in truth_problem_to_truth_solution_dot and truth_problem in truth_problem_to_truth_solution_dot): truth_problem_to_truth_solution_dot[ exact_truth_problem] = truth_problem_to_truth_solution_dot[ truth_problem] assert exact_truth_problem not in truth_problem_to_truth_solution_dot_copy assert truth_problem in truth_problem_to_truth_solution_dot_copy truth_problem_to_truth_solution_dot_copy[ exact_truth_problem] = truth_problem_to_truth_solution_dot_copy[ truth_problem] # Store the component assert exact_truth_problem not in truth_problem_to_components[ 1] assert truth_problem in truth_problem_to_components[ 1] truth_problem_to_components[1][ exact_truth_problem] = truth_problem_to_components[ 1][truth_problem] # Append to list of required truth problems which are not currently solving required_truth_problems.append( (exact_truth_problem, False, reduced_problem_is_solving)) else: assert not reduced_problem_is_solving # Append to list of required truth problems which are currently solving required_truth_problems.append((truth_problem, True, False)) # Solve truth problems (which have not been reduced yet) associated to nonlinear terms for (truth_problem, truth_problem_is_solving, reduced_problem_is_solving) in required_truth_problems: if not reduced_problem_is_solving: # Solve (if necessary) truth_problem.set_mu(mu) if not truth_problem_is_solving: log( PROGRESS, "In form_on_truth_function_space, requiring truth problem solve for problem " + truth_problem.name()) truth_problem.solve() else: log( PROGRESS, "In form_on_truth_function_space, loading current truth problem solution for problem " + truth_problem.name()) else: reduced_problem = get_reduced_problem_from_problem( truth_problem) log( PROGRESS, "In form_on_truth_function_space, replacing current truth problem solution with reduced solution for problem " + reduced_problem.truth_problem.name()) # Assign to truth_solution if truth_problem in truth_problem_to_truth_solution: truth_solution = truth_problem_to_truth_solution[truth_problem] backend.assign( truth_problem_to_truth_solution_copy[truth_problem], truth_solution) for component in truth_problem_to_components[0][truth_problem]: solution_to = _sub_from_tuple(truth_solution, component) if t is None: if not reduced_problem_is_solving: solution_from = _sub_from_tuple( truth_problem._solution, component) else: solution_from = _sub_from_tuple( reduced_problem. basis_functions[:reduced_problem._solution.N] * reduced_problem._solution, component) else: if not reduced_problem_is_solving: if not truth_problem_is_solving: solution_from = _sub_from_tuple( truth_problem._solution_over_time.at(t), component) else: solution_from = _sub_from_tuple( truth_problem._solution, component) else: solution_from = _sub_from_tuple( reduced_problem. basis_functions[:reduced_problem._solution.N] * reduced_problem._solution, component) backend.assign(solution_to, solution_from) # Assign to truth_solution_dot if truth_problem in truth_problem_to_truth_solution_dot: truth_solution_dot = truth_problem_to_truth_solution_dot[ truth_problem] backend.assign( truth_problem_to_truth_solution_dot_copy[truth_problem], truth_solution_dot) for component in truth_problem_to_components[1][truth_problem]: solution_dot_to = _sub_from_tuple(truth_solution_dot, component) assert t is not None if not reduced_problem_is_solving: if not truth_problem_is_solving: solution_dot_from = _sub_from_tuple( truth_problem._solution_dot_over_time.at(t), component) else: solution_dot_from = _sub_from_tuple( truth_problem._solution_dot, component) else: solution_dot_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem. _solution_dot.N] * reduced_problem._solution_dot, component) backend.assign(solution_dot_to, solution_dot_from) # Solve reduced problems associated to nonlinear terms for (reduced_problem, is_solving) in required_reduced_problems: # Solve (if necessary) reduced_problem.set_mu(mu) if not is_solving: log( PROGRESS, "In form_on_truth_function_space, requiring reduced problem solve for problem " + reduced_problem.truth_problem.name()) reduced_problem.solve() else: log( PROGRESS, "In form_on_truth_function_space, loading current reduced problem solution for problem " + reduced_problem.truth_problem.name()) # Assign to truth_solution if reduced_problem in reduced_problem_to_truth_solution: truth_solution = reduced_problem_to_truth_solution[ reduced_problem] backend.assign( reduced_problem_to_truth_solution_copy[reduced_problem], truth_solution) for component in reduced_problem_to_components[0][ reduced_problem]: solution_to = _sub_from_tuple(truth_solution, component) if t is None or is_solving: solution_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem. _solution.N] * reduced_problem._solution, component) else: solution_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem. _solution.N] * reduced_problem._solution_over_time.at(t), component) backend.assign(solution_to, solution_from) # Assign to truth_solution_dot if reduced_problem in reduced_problem_to_truth_solution_dot: truth_solution_dot = reduced_problem_to_truth_solution_dot[ reduced_problem] backend.assign( reduced_problem_to_truth_solution_dot_copy[ reduced_problem], truth_solution_dot) for component in reduced_problem_to_components[1][ reduced_problem]: solution_dot_to = _sub_from_tuple(truth_solution_dot, component) assert t is not None if is_solving: solution_dot_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem. _solution_dot.N] * reduced_problem._solution_dot, component) else: solution_dot_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem. _solution_dot.N] * reduced_problem._solution_dot_over_time.at(t), component) backend.assign(solution_dot_to, solution_dot_from) # Assemble assembled_form = wrapping.assemble(form, tensor) if not isinstance(assembled_form, Number): assembled_form.generator = form_wrapper # for I/O form_rank = assembled_form.rank() else: form_rank = 0 # Undo any side effect of truth problem solves for (truth_problem, _, _) in required_truth_problems: if truth_problem in truth_problem_to_truth_solution: truth_solution = truth_problem_to_truth_solution[truth_problem] truth_solution_copy = truth_problem_to_truth_solution_copy[ truth_problem] for component in truth_problem_to_components[0][truth_problem]: solution_to = _sub_from_tuple(truth_solution, component) solution_from = _sub_from_tuple(truth_solution_copy, component) backend.assign(solution_to, solution_from) if truth_problem in truth_problem_to_truth_solution_dot: truth_solution_dot = truth_problem_to_truth_solution_dot[ truth_problem] truth_solution_dot_copy = truth_problem_to_truth_solution_dot_copy[ truth_problem] for component in truth_problem_to_components[1][truth_problem]: solution_dot_to = _sub_from_tuple(truth_solution_dot, component) solution_dot_from = _sub_from_tuple( truth_solution_dot_copy, component) backend.assign(solution_dot_to, solution_dot_from) # Undo any side effect of reduced problem solves for (reduced_problem, _) in required_reduced_problems: if reduced_problem in reduced_problem_to_truth_solution: truth_solution = reduced_problem_to_truth_solution[ reduced_problem] truth_solution_copy = reduced_problem_to_truth_solution_copy[ reduced_problem] for component in reduced_problem_to_components[0][ reduced_problem]: solution_to = _sub_from_tuple(truth_solution, component) solution_from = _sub_from_tuple(truth_solution_copy, component) backend.assign(solution_to, solution_from) if reduced_problem in reduced_problem_to_truth_solution_dot: truth_solution_dot = reduced_problem_to_truth_solution_dot[ reduced_problem] truth_solution_dot_copy = reduced_problem_to_truth_solution_dot_copy[ reduced_problem] for component in reduced_problem_to_components[1][ reduced_problem]: solution_dot_to = _sub_from_tuple(truth_solution_dot, component) solution_dot_from = _sub_from_tuple( truth_solution_dot_copy, component) backend.assign(solution_dot_to, solution_dot_from) # Return return (assembled_form, form_rank)
def _basic_expression_on_truth_mesh(expression_wrapper, function=None): expression = expression_wrapper._expression expression_name = expression_wrapper.name() expression_problem = get_problem_from_parametrized_expression(expression_wrapper) space = expression_wrapper._space mu = expression_problem.mu if hasattr(expression_problem, "set_time"): t = expression_problem.t else: t = None if expression_name not in reduced_problem_to_truth_solution_cache: visited = set() truth_problems = list() truth_problem_to_components = { # outer dict index over time derivative 0: dict(), 1: dict()} truth_problem_to_exact_truth_problem = dict() truth_problem_to_truth_solution = dict() truth_problem_to_truth_solution_copy = dict() truth_problem_to_truth_solution_dot = dict() truth_problem_to_truth_solution_dot_copy = dict() reduced_problem_to_components = { # outer dict index over time derivative 0: dict(), 1: dict()} reduced_problem_to_truth_solution = dict() reduced_problem_to_truth_solution_copy = dict() reduced_problem_to_truth_solution_dot = dict() reduced_problem_to_truth_solution_dot_copy = dict() # Look for terminals on truth mesh logger.log(DEBUG, "Traversing terminals of expression " + expression_name) for node in wrapping.expression_iterator(expression): if node in visited: continue # ... problem solutions related to nonlinear terms elif wrapping.is_problem_solution_type(node): node_is_problem_solution = wrapping.is_problem_solution(node) node_is_problem_solution_dot = wrapping.is_problem_solution_dot(node) if node_is_problem_solution or node_is_problem_solution_dot: if node_is_problem_solution: (preprocessed_node, component, truth_solution) = wrapping.solution_identify_component(node) truth_problem = get_problem_from_solution(truth_solution) logger.log(DEBUG, "\tFound problem solution of truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ", component: " + str(component) + ")") # Store the solution if truth_problem not in truth_problem_to_truth_solution: truth_problem_to_truth_solution[truth_problem] = truth_solution truth_problem_to_truth_solution_copy[truth_problem] = backend.copy(truth_solution) else: assert truth_problem_to_truth_solution[truth_problem] is truth_solution assert truth_problem in truth_problem_to_truth_solution_copy # Time derivative key for components dict time_derivative = 0 elif node_is_problem_solution_dot: (preprocessed_node, component, truth_solution_dot) = wrapping.solution_dot_identify_component(node) truth_problem = get_problem_from_solution_dot(truth_solution_dot) logger.log(DEBUG, "\tFound problem solution dot of truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ", component: " + str(component) + ")") # Store the solution_dot if truth_problem not in truth_problem_to_truth_solution_dot: truth_problem_to_truth_solution_dot[truth_problem] = truth_solution_dot truth_problem_to_truth_solution_dot_copy[ truth_problem] = backend.copy(truth_solution_dot) else: assert truth_problem_to_truth_solution_dot[truth_problem] is truth_solution_dot assert truth_problem in truth_problem_to_truth_solution_dot_copy # Time derivative key for components dict time_derivative = 1 # Store truth problem if truth_problem not in truth_problems: truth_problems.append(truth_problem) # Store the component if truth_problem not in truth_problem_to_components[time_derivative]: truth_problem_to_components[time_derivative][truth_problem] = list() if component not in truth_problem_to_components[time_derivative][truth_problem]: truth_problem_to_components[time_derivative][truth_problem].append(component) else: (preprocessed_node, component, auxiliary_problem) = wrapping.get_auxiliary_problem_for_non_parametrized_function(node) logger.log(DEBUG, "\tFound non parametrized function " + str(preprocessed_node) + " associated to auxiliary problem " + str(auxiliary_problem.name()) + ", component: " + str(component)) # Make sure to skip any parent solution related to this one visited.add(node) visited.add(preprocessed_node) for parent_node in wrapping.solution_iterator(preprocessed_node): visited.add(parent_node) else: visited.add(node) # Cache the resulting dicts truth_problems_cache[expression_name] = truth_problems truth_problem_to_components_cache[expression_name] = truth_problem_to_components truth_problem_to_exact_truth_problem_cache[expression_name] = truth_problem_to_exact_truth_problem truth_problem_to_truth_solution_cache[expression_name] = truth_problem_to_truth_solution truth_problem_to_truth_solution_copy_cache[expression_name] = truth_problem_to_truth_solution_copy truth_problem_to_truth_solution_dot_cache[expression_name] = truth_problem_to_truth_solution_dot truth_problem_to_truth_solution_dot_copy_cache[expression_name] = truth_problem_to_truth_solution_dot_copy reduced_problem_to_components_cache[expression_name] = reduced_problem_to_components reduced_problem_to_truth_solution_cache[expression_name] = reduced_problem_to_truth_solution reduced_problem_to_truth_solution_copy_cache[expression_name] = reduced_problem_to_truth_solution_copy reduced_problem_to_truth_solution_dot_cache[expression_name] = reduced_problem_to_truth_solution_dot reduced_problem_to_truth_solution_dot_copy_cache[ expression_name] = reduced_problem_to_truth_solution_dot_copy # Extract from cache truth_problems = truth_problems_cache[expression_name] truth_problem_to_components = truth_problem_to_components_cache[expression_name] truth_problem_to_exact_truth_problem = truth_problem_to_exact_truth_problem_cache[expression_name] truth_problem_to_truth_solution = truth_problem_to_truth_solution_cache[expression_name] truth_problem_to_truth_solution_copy = truth_problem_to_truth_solution_copy_cache[expression_name] truth_problem_to_truth_solution_dot = truth_problem_to_truth_solution_dot_cache[expression_name] truth_problem_to_truth_solution_dot_copy = truth_problem_to_truth_solution_dot_copy_cache[expression_name] reduced_problem_to_components = reduced_problem_to_components_cache[expression_name] reduced_problem_to_truth_solution = reduced_problem_to_truth_solution_cache[expression_name] reduced_problem_to_truth_solution_copy = reduced_problem_to_truth_solution_copy_cache[expression_name] reduced_problem_to_truth_solution_dot = reduced_problem_to_truth_solution_dot_cache[expression_name] reduced_problem_to_truth_solution_dot_copy = reduced_problem_to_truth_solution_dot_cache[expression_name] # Get list of truth and reduced problems that need to be solved, possibly updating cache required_truth_problems = list() required_reduced_problems = list() for truth_problem in truth_problems: truth_problem_is_solving = hasattr(truth_problem, "_is_solving") if is_training_started(truth_problem): reduced_problem = get_reduced_problem_from_problem(truth_problem) reduced_problem_is_solving = hasattr(reduced_problem, "_is_solving") else: reduced_problem = None reduced_problem_is_solving = False if not truth_problem_is_solving: if is_training_finished(truth_problem): logger.log(DEBUG, "Truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ") is not currently solving, and its offline stage has finished:" + " truth problem will be replaced by reduced problem") # Store the solution if (reduced_problem not in reduced_problem_to_truth_solution and truth_problem in truth_problem_to_truth_solution): reduced_problem_to_truth_solution[ reduced_problem] = truth_problem_to_truth_solution[truth_problem] assert reduced_problem not in reduced_problem_to_truth_solution_copy assert truth_problem in truth_problem_to_truth_solution_copy reduced_problem_to_truth_solution_copy[ reduced_problem] = truth_problem_to_truth_solution_copy[truth_problem] # Store the component assert reduced_problem not in reduced_problem_to_components[0] assert truth_problem in truth_problem_to_components[0] reduced_problem_to_components[ 0][reduced_problem] = truth_problem_to_components[0][truth_problem] # Store the solution_dot if (reduced_problem not in reduced_problem_to_truth_solution_dot and truth_problem in truth_problem_to_truth_solution_dot): reduced_problem_to_truth_solution_dot[ reduced_problem] = truth_problem_to_truth_solution_dot[truth_problem] assert reduced_problem not in reduced_problem_to_truth_solution_dot_copy assert truth_problem in truth_problem_to_truth_solution_dot_copy reduced_problem_to_truth_solution_dot_copy[ reduced_problem] = truth_problem_to_truth_solution_dot_copy[truth_problem] # Store the component assert reduced_problem not in reduced_problem_to_components[1] assert truth_problem in truth_problem_to_components[1] reduced_problem_to_components[ 1][reduced_problem] = truth_problem_to_components[1][truth_problem] # Append to list of required reduced problems required_reduced_problems.append((reduced_problem, reduced_problem_is_solving)) else: if (hasattr(truth_problem, "_apply_exact_evaluation_at_stages") and not hasattr(truth_problem, "_apply_EIM_at_stages") and not hasattr(truth_problem, "_apply_DEIM_at_stages")): logger.log(DEBUG, "Truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ") is not currently solving, its offline stage has not finished," + " and only @ExactParametrizedFunctions has been used:" + " truth solve of this truth problem instance will be called") # Init truth problem (if required), as it may not have been initialized truth_problem.init() # Append to list of required truth problems which are not currently solving required_truth_problems.append((truth_problem, False, reduced_problem_is_solving)) else: logger.log(DEBUG, "Truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ") is not currently solving, its offline stage has not finished," + " and either @ExactParametrizedFunctions has not been used" + " or it has been used in combination with @DEIM or @EIM:" + " truth solve on an auxiliary instance (with exact problem decorator)" + " will be called, to prevent early initialization of DEIM/EIM data structures") # Store the corresponding exact truth problem if truth_problem not in truth_problem_to_exact_truth_problem: exact_truth_problem = exact_problem(truth_problem) truth_problem_to_exact_truth_problem[truth_problem] = exact_truth_problem # Init exact truth problem (if required), as it may not have been initialized exact_truth_problem.init() else: exact_truth_problem = truth_problem_to_exact_truth_problem[truth_problem] # Store the solution if (exact_truth_problem not in truth_problem_to_truth_solution and truth_problem in truth_problem_to_truth_solution): truth_problem_to_truth_solution[ exact_truth_problem] = truth_problem_to_truth_solution[truth_problem] assert exact_truth_problem not in truth_problem_to_truth_solution_copy assert truth_problem in truth_problem_to_truth_solution_copy truth_problem_to_truth_solution_copy[ exact_truth_problem] = truth_problem_to_truth_solution_copy[truth_problem] # Store the component assert exact_truth_problem not in truth_problem_to_components[0] assert truth_problem in truth_problem_to_components[0] truth_problem_to_components[ 0][exact_truth_problem] = truth_problem_to_components[0][truth_problem] # Store the solution_dot if (exact_truth_problem not in truth_problem_to_truth_solution_dot and truth_problem in truth_problem_to_truth_solution_dot): truth_problem_to_truth_solution_dot[ exact_truth_problem] = truth_problem_to_truth_solution_dot[truth_problem] assert exact_truth_problem not in truth_problem_to_truth_solution_dot_copy assert truth_problem in truth_problem_to_truth_solution_dot_copy truth_problem_to_truth_solution_dot_copy[ exact_truth_problem] = truth_problem_to_truth_solution_dot_copy[truth_problem] # Store the component assert exact_truth_problem not in truth_problem_to_components[1] assert truth_problem in truth_problem_to_components[1] truth_problem_to_components[ 1][exact_truth_problem] = truth_problem_to_components[1][truth_problem] # Append to list of required truth problems which are not currently solving required_truth_problems.append((exact_truth_problem, False, reduced_problem_is_solving)) else: logger.log(DEBUG, "Truth problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ") is currently solving: current truth solution will be loaded") assert not reduced_problem_is_solving # Append to list of required truth problems which are currently solving required_truth_problems.append((truth_problem, True, False)) # Solve truth problems (which have not been reduced yet) associated to nonlinear terms for (truth_problem, truth_problem_is_solving, reduced_problem_is_solving) in required_truth_problems: if not reduced_problem_is_solving: # Solve (if necessary) truth_problem.set_mu(mu) if not truth_problem_is_solving: logger.log(DEBUG, "Requiring truth problem solve for problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ")") truth_problem.solve() else: logger.log(DEBUG, "Loading current truth problem solution for problem " + truth_problem.name() + " (exact problem decorator: " + str(hasattr(truth_problem, "__is_exact__")) + ")") else: reduced_problem = get_reduced_problem_from_problem(truth_problem) logger.log(DEBUG, "Replacing current truth problem solution with reduced solution for problem " + reduced_problem.truth_problem.name()) # Assign to truth_solution if truth_problem in truth_problem_to_truth_solution: truth_solution = truth_problem_to_truth_solution[truth_problem] backend.assign(truth_problem_to_truth_solution_copy[truth_problem], truth_solution) for component in truth_problem_to_components[0][truth_problem]: solution_to = _sub_from_tuple(truth_solution, component) if t is None: if not reduced_problem_is_solving: solution_from = _sub_from_tuple(truth_problem._solution, component) else: solution_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem._solution.N] * reduced_problem._solution, component) else: if not reduced_problem_is_solving: if not truth_problem_is_solving: solution_from = _sub_from_tuple(truth_problem._solution_over_time.at(t), component) else: solution_from = _sub_from_tuple(truth_problem._solution, component) else: solution_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem._solution.N] * reduced_problem._solution, component) backend.assign(solution_to, solution_from) # Assign to truth_solution_dot if truth_problem in truth_problem_to_truth_solution_dot: truth_solution_dot = truth_problem_to_truth_solution_dot[truth_problem] backend.assign(truth_problem_to_truth_solution_dot_copy[truth_problem], truth_solution_dot) for component in truth_problem_to_components[1][truth_problem]: solution_dot_to = _sub_from_tuple(truth_solution_dot, component) assert t is not None if not reduced_problem_is_solving: if not truth_problem_is_solving: solution_dot_from = _sub_from_tuple(truth_problem._solution_dot_over_time.at(t), component) else: solution_dot_from = _sub_from_tuple(truth_problem._solution_dot, component) else: solution_dot_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem._solution_dot.N] * reduced_problem._solution_dot, component) backend.assign(solution_dot_to, solution_dot_from) # Solve reduced problems associated to nonlinear terms for (reduced_problem, is_solving) in required_reduced_problems: # Solve (if necessary) reduced_problem.set_mu(mu) if not is_solving: logger.log(DEBUG, "Requiring reduced problem solve for problem " + reduced_problem.truth_problem.name()) reduced_problem.solve() else: logger.log(DEBUG, "Loading current reduced problem solution for problem " + reduced_problem.truth_problem.name()) # Assign to truth_solution if reduced_problem in reduced_problem_to_truth_solution: truth_solution = reduced_problem_to_truth_solution[reduced_problem] backend.assign(reduced_problem_to_truth_solution_copy[reduced_problem], truth_solution) for component in reduced_problem_to_components[0][reduced_problem]: solution_to = _sub_from_tuple(truth_solution, component) if t is None or is_solving: solution_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem._solution.N] * reduced_problem._solution, component) else: solution_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem._solution.N] * reduced_problem._solution_over_time.at(t), component) backend.assign(solution_to, solution_from) # Assign to truth_solution_dot if reduced_problem in reduced_problem_to_truth_solution_dot: truth_solution_dot = reduced_problem_to_truth_solution_dot[reduced_problem] backend.assign(reduced_problem_to_truth_solution_dot_copy[reduced_problem], truth_solution_dot) for component in reduced_problem_to_components[1][reduced_problem]: solution_dot_to = _sub_from_tuple(truth_solution_dot, component) assert t is not None if is_solving: solution_dot_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem._solution_dot.N] * reduced_problem._solution_dot, component) else: solution_dot_from = _sub_from_tuple( reduced_problem.basis_functions[:reduced_problem._solution_dot.N] * reduced_problem._solution_dot_over_time.at(t), component) backend.assign(solution_dot_to, solution_dot_from) # Evaluate if function is None: function = backend.Function(space) wrapping.evaluate_expression(expression, function) # Undo any side effect of truth problem solves for (truth_problem, _, _) in required_truth_problems: if truth_problem in truth_problem_to_truth_solution: truth_solution = truth_problem_to_truth_solution[truth_problem] truth_solution_copy = truth_problem_to_truth_solution_copy[truth_problem] for component in truth_problem_to_components[0][truth_problem]: solution_to = _sub_from_tuple(truth_solution, component) solution_from = _sub_from_tuple(truth_solution_copy, component) backend.assign(solution_to, solution_from) if truth_problem in truth_problem_to_truth_solution_dot: truth_solution_dot = truth_problem_to_truth_solution_dot[truth_problem] truth_solution_dot_copy = truth_problem_to_truth_solution_dot_copy[truth_problem] for component in truth_problem_to_components[1][truth_problem]: solution_dot_to = _sub_from_tuple(truth_solution_dot, component) solution_dot_from = _sub_from_tuple(truth_solution_dot_copy, component) backend.assign(solution_dot_to, solution_dot_from) # Undo any side effect of reduced problem solves for (reduced_problem, _) in required_reduced_problems: if reduced_problem in reduced_problem_to_truth_solution: truth_solution = reduced_problem_to_truth_solution[reduced_problem] truth_solution_copy = reduced_problem_to_truth_solution_copy[reduced_problem] for component in reduced_problem_to_components[0][reduced_problem]: solution_to = _sub_from_tuple(truth_solution, component) solution_from = _sub_from_tuple(truth_solution_copy, component) backend.assign(solution_to, solution_from) if reduced_problem in reduced_problem_to_truth_solution_dot: truth_solution_dot = reduced_problem_to_truth_solution_dot[reduced_problem] truth_solution_dot_copy = reduced_problem_to_truth_solution_dot_copy[reduced_problem] for component in reduced_problem_to_components[1][reduced_problem]: solution_dot_to = _sub_from_tuple(truth_solution_dot, component) solution_dot_from = _sub_from_tuple(truth_solution_dot_copy, component) backend.assign(solution_dot_to, solution_dot_from) # Return return function
def _basic_expression_on_reduced_mesh(expression_wrapper, at): expression = expression_wrapper._expression expression_name = expression_wrapper.name() expression_problem = get_problem_from_parametrized_expression(expression_wrapper) reduced_space = at.get_reduced_function_space() reduced_mesh = at.get_reduced_mesh() mu = expression_problem.mu if hasattr(expression_problem, "set_time"): t = expression_problem.t else: t = None if (expression_name, reduced_mesh) not in expression_cache: visited = set() replacements = dict() truth_problems = list() truth_problem_to_components = { # outer dict index over time derivative 0: dict(), 1: dict() } truth_problem_to_exact_truth_problem = dict() truth_problem_to_reduced_mesh_solution = dict() truth_problem_to_reduced_mesh_solution_dot = dict() truth_problem_to_reduced_mesh_interpolator = { # outer dict index over time derivative 0: dict(), 1: dict() } reduced_problem_to_components = { # outer dict index over time derivative 0: dict(), 1: dict() } reduced_problem_to_reduced_mesh_solution = dict() reduced_problem_to_reduced_mesh_solution_dot = dict() reduced_problem_to_reduced_basis_functions = { # outer dict index over time derivative 0: dict(), 1: dict() } # Look for terminals on truth mesh for node in wrapping.expression_iterator(expression): if node in visited: continue # ... problem solutions related to nonlinear terms elif wrapping.is_problem_solution_type(node): node_is_problem_solution = wrapping.is_problem_solution(node) node_is_problem_solution_dot = wrapping.is_problem_solution_dot(node) if node_is_problem_solution or node_is_problem_solution_dot: if node_is_problem_solution: (preprocessed_node, component, truth_solution) = wrapping.solution_identify_component(node) truth_problem = get_problem_from_solution(truth_solution) # Time derivative key for components and interpolator dicts time_derivative = 0 elif node_is_problem_solution_dot: (preprocessed_node, component, truth_solution_dot) = wrapping.solution_dot_identify_component(node) truth_problem = get_problem_from_solution_dot(truth_solution_dot) # Time derivative key for components and interpolator dicts time_derivative = 1 # Store truth problem if truth_problem not in truth_problems: truth_problems.append(truth_problem) # Store the component if truth_problem not in truth_problem_to_components[time_derivative]: truth_problem_to_components[time_derivative][truth_problem] = list() if component not in truth_problem_to_components[time_derivative][truth_problem]: truth_problem_to_components[time_derivative][truth_problem].append(component) # Get the function space corresponding to preprocessed_node on the reduced mesh auxiliary_reduced_V = at.get_auxiliary_reduced_function_space(truth_problem, component) # Define and store the replacement assert preprocessed_node not in replacements # as it is related to a new truth solution component replacements[preprocessed_node] = backend.Function(auxiliary_reduced_V) if time_derivative is 0: if truth_problem not in truth_problem_to_reduced_mesh_solution: truth_problem_to_reduced_mesh_solution[truth_problem] = list() truth_problem_to_reduced_mesh_solution[truth_problem].append(replacements[preprocessed_node]) elif time_derivative is 1: if truth_problem not in truth_problem_to_reduced_mesh_solution_dot: truth_problem_to_reduced_mesh_solution_dot[truth_problem] = list() truth_problem_to_reduced_mesh_solution_dot[truth_problem].append(replacements[preprocessed_node]) # Get interpolator on reduced mesh if truth_problem not in truth_problem_to_reduced_mesh_interpolator[time_derivative]: truth_problem_to_reduced_mesh_interpolator[time_derivative][truth_problem] = list() truth_problem_to_reduced_mesh_interpolator[time_derivative][truth_problem].append(at.get_auxiliary_function_interpolator(truth_problem, component)) else: (preprocessed_node, component, auxiliary_problem) = wrapping.get_auxiliary_problem_for_non_parametrized_function(node) if preprocessed_node not in replacements: # Get interpolator on reduced mesh auxiliary_truth_problem_to_reduced_mesh_interpolator = at.get_auxiliary_function_interpolator(auxiliary_problem, component) # Define and store the replacement replacements[preprocessed_node] = auxiliary_truth_problem_to_reduced_mesh_interpolator(preprocessed_node) # Make sure to skip any parent solution related to this one visited.add(node) visited.add(preprocessed_node) for parent_node in wrapping.solution_iterator(preprocessed_node): visited.add(parent_node) # ... geometric quantities elif isinstance(node, GeometricQuantity): replacements[node] = type(node)(reduced_mesh) visited.add(node) else: visited.add(node) # ... and replace them replaced_expression = wrapping.expression_replace(expression, replacements) # Cache the resulting dicts expression_cache[(expression_name, reduced_mesh)] = replaced_expression truth_problems_cache[(expression_name, reduced_mesh)] = truth_problems truth_problem_to_components_cache[(expression_name, reduced_mesh)] = truth_problem_to_components truth_problem_to_exact_truth_problem_cache[(expression_name, reduced_mesh)] = truth_problem_to_exact_truth_problem truth_problem_to_reduced_mesh_solution_cache[(expression_name, reduced_mesh)] = truth_problem_to_reduced_mesh_solution truth_problem_to_reduced_mesh_solution_dot_cache[(expression_name, reduced_mesh)] = truth_problem_to_reduced_mesh_solution_dot truth_problem_to_reduced_mesh_interpolator_cache[(expression_name, reduced_mesh)] = truth_problem_to_reduced_mesh_interpolator reduced_problem_to_components_cache[(expression_name, reduced_mesh)] = reduced_problem_to_components reduced_problem_to_reduced_mesh_solution_cache[(expression_name, reduced_mesh)] = reduced_problem_to_reduced_mesh_solution reduced_problem_to_reduced_mesh_solution_dot_cache[(expression_name, reduced_mesh)] = reduced_problem_to_reduced_mesh_solution_dot reduced_problem_to_reduced_basis_functions_cache[(expression_name, reduced_mesh)] = reduced_problem_to_reduced_basis_functions # Extract from cache replaced_expression = expression_cache[(expression_name, reduced_mesh)] truth_problems = truth_problems_cache[(expression_name, reduced_mesh)] truth_problem_to_components = truth_problem_to_components_cache[(expression_name, reduced_mesh)] truth_problem_to_exact_truth_problem = truth_problem_to_exact_truth_problem_cache[(expression_name, reduced_mesh)] truth_problem_to_reduced_mesh_solution = truth_problem_to_reduced_mesh_solution_cache[(expression_name, reduced_mesh)] truth_problem_to_reduced_mesh_solution_dot = truth_problem_to_reduced_mesh_solution_dot_cache[(expression_name, reduced_mesh)] truth_problem_to_reduced_mesh_interpolator = truth_problem_to_reduced_mesh_interpolator_cache[(expression_name, reduced_mesh)] reduced_problem_to_components = reduced_problem_to_components_cache[(expression_name, reduced_mesh)] reduced_problem_to_reduced_mesh_solution = reduced_problem_to_reduced_mesh_solution_cache[(expression_name, reduced_mesh)] reduced_problem_to_reduced_mesh_solution_dot = reduced_problem_to_reduced_mesh_solution_dot_cache[(expression_name, reduced_mesh)] reduced_problem_to_reduced_basis_functions = reduced_problem_to_reduced_basis_functions_cache[(expression_name, reduced_mesh)] # Get list of truth and reduced problems that need to be solved, possibly updating cache required_truth_problems = list() required_reduced_problems = list() for truth_problem in truth_problems: truth_problem_is_solving = hasattr(truth_problem, "_is_solving") if is_training_started(truth_problem): reduced_problem = get_reduced_problem_from_problem(truth_problem) reduced_problem_is_solving = hasattr(reduced_problem, "_is_solving") else: reduced_problem = None reduced_problem_is_solving = False if not truth_problem_is_solving: if is_training_finished(truth_problem): # Store the replacement for solution if ( reduced_problem not in reduced_problem_to_reduced_mesh_solution and truth_problem in truth_problem_to_reduced_mesh_solution ): reduced_problem_to_reduced_mesh_solution[reduced_problem] = truth_problem_to_reduced_mesh_solution[truth_problem] # Store the component assert reduced_problem not in reduced_problem_to_components[0] assert truth_problem in truth_problem_to_components[0] reduced_problem_to_components[0][reduced_problem] = truth_problem_to_components[0][truth_problem] # Get reduced problem basis functions on reduced mesh assert reduced_problem not in reduced_problem_to_reduced_basis_functions[0] reduced_problem_to_reduced_basis_functions[0][reduced_problem] = [at.get_auxiliary_basis_functions_matrix(truth_problem, component) for component in reduced_problem_to_components[0][reduced_problem]] # Store the replacement for solution_dot if ( reduced_problem not in reduced_problem_to_reduced_mesh_solution_dot and truth_problem in truth_problem_to_reduced_mesh_solution_dot ): reduced_problem_to_reduced_mesh_solution_dot[reduced_problem] = truth_problem_to_reduced_mesh_solution_dot[truth_problem] # Store the component assert reduced_problem not in reduced_problem_to_components[1] assert truth_problem in truth_problem_to_components[1] reduced_problem_to_components[1][reduced_problem] = truth_problem_to_components[1][truth_problem] # Get reduced problem basis functions on reduced mesh assert reduced_problem not in reduced_problem_to_reduced_basis_functions[1] reduced_problem_to_reduced_basis_functions[1][reduced_problem] = [at.get_auxiliary_basis_functions_matrix(truth_problem, component) for component in reduced_problem_to_components[1][reduced_problem]] # Append to list of required reduced problems required_reduced_problems.append((reduced_problem, reduced_problem_is_solving)) else: if ( hasattr(truth_problem, "_apply_exact_evaluation_at_stages") and not hasattr(truth_problem, "_apply_EIM_at_stages") and not hasattr(truth_problem, "_apply_DEIM_at_stages") ): # Init truth problem (if required), as it may not have been initialized truth_problem.init() # Append to list of required truth problems which are not currently solving required_truth_problems.append((truth_problem, False, reduced_problem_is_solving)) else: # Store the corresponding exact truth problem if truth_problem not in truth_problem_to_exact_truth_problem: exact_truth_problem = exact_problem(truth_problem) truth_problem_to_exact_truth_problem[truth_problem] = exact_truth_problem # Init exact truth problem (if required), as it may not have been initialized exact_truth_problem.init() else: exact_truth_problem = truth_problem_to_exact_truth_problem[truth_problem] # Store the replacement for solution if ( exact_truth_problem not in truth_problem_to_reduced_mesh_solution and truth_problem in truth_problem_to_reduced_mesh_solution ): truth_problem_to_reduced_mesh_solution[exact_truth_problem] = truth_problem_to_reduced_mesh_solution[truth_problem] # Store the component assert exact_truth_problem not in truth_problem_to_components[0] assert truth_problem in truth_problem_to_components[0] truth_problem_to_components[0][exact_truth_problem] = truth_problem_to_components[0][truth_problem] # Get interpolator on reduced mesh assert exact_truth_problem not in truth_problem_to_reduced_mesh_interpolator[0] assert truth_problem in truth_problem_to_reduced_mesh_interpolator[0] truth_problem_to_reduced_mesh_interpolator[0][exact_truth_problem] = truth_problem_to_reduced_mesh_interpolator[0][truth_problem] # Store the replacement for solution_dot if ( exact_truth_problem not in truth_problem_to_reduced_mesh_solution_dot and truth_problem in truth_problem_to_reduced_mesh_solution_dot ): truth_problem_to_reduced_mesh_solution_dot[exact_truth_problem] = truth_problem_to_reduced_mesh_solution_dot[truth_problem] # Store the component assert exact_truth_problem not in truth_problem_to_components[1] assert truth_problem in truth_problem_to_components[1] truth_problem_to_components[1][exact_truth_problem] = truth_problem_to_components[1][truth_problem] # Get interpolator on reduced mesh assert exact_truth_problem not in truth_problem_to_reduced_mesh_interpolator[1] assert truth_problem in truth_problem_to_reduced_mesh_interpolator[1] truth_problem_to_reduced_mesh_interpolator[1][exact_truth_problem] = truth_problem_to_reduced_mesh_interpolator[1][truth_problem] # Append to list of required truth problems which are not currently solving required_truth_problems.append((exact_truth_problem, False, reduced_problem_is_solving)) else: assert not reduced_problem_is_solving # Append to list of required truth problems which are currently solving required_truth_problems.append((truth_problem, True, False)) # Solve truth problems (which have not been reduced yet) associated to nonlinear terms for (truth_problem, truth_problem_is_solving, reduced_problem_is_solving) in required_truth_problems: if not reduced_problem_is_solving: # Solve (if necessary) truth_problem.set_mu(mu) if not truth_problem_is_solving: log(PROGRESS, "In expression_on_reduced_mesh, requiring truth problem solve for problem " + truth_problem.name()) truth_problem.solve() else: log(PROGRESS, "In expression_on_reduced_mesh, loading current truth problem solution for problem " + truth_problem.name()) else: reduced_problem = get_reduced_problem_from_problem(truth_problem) log(PROGRESS, "In expression_on_reduced_mesh, replacing current truth problem solution with reduced solution for problem " + reduced_problem.truth_problem.name()) # Assign to reduced_mesh_solution if truth_problem in truth_problem_to_reduced_mesh_solution: for (reduced_mesh_solution, reduced_mesh_interpolator) in zip(truth_problem_to_reduced_mesh_solution[truth_problem], truth_problem_to_reduced_mesh_interpolator[0][truth_problem]): solution_to = reduced_mesh_solution if t is None: if not reduced_problem_is_solving: solution_from = reduced_mesh_interpolator(truth_problem._solution) else: solution_from = reduced_mesh_interpolator(reduced_problem.basis_functions[:reduced_problem._solution.N]*reduced_problem._solution) else: if not reduced_problem_is_solving: if not truth_problem_is_solving: solution_from = reduced_mesh_interpolator(truth_problem._solution_over_time.at(t)) else: solution_from = reduced_mesh_interpolator(truth_problem._solution) else: solution_from = reduced_mesh_interpolator(reduced_problem.basis_functions[:reduced_problem._solution.N]*reduced_problem._solution) backend.assign(solution_to, solution_from) # Assign to reduced_mesh_solution_dot if truth_problem in truth_problem_to_reduced_mesh_solution_dot: for (reduced_mesh_solution_dot, reduced_mesh_interpolator) in zip(truth_problem_to_reduced_mesh_solution_dot[truth_problem], truth_problem_to_reduced_mesh_interpolator[1][truth_problem]): solution_dot_to = reduced_mesh_solution_dot assert t is not None if not reduced_problem_is_solving: if not truth_problem_is_solving: solution_dot_from = reduced_mesh_interpolator(truth_problem._solution_dot_over_time.at(t)) else: solution_dot_from = reduced_mesh_interpolator(truth_problem._solution_dot) else: solution_dot_from = reduced_mesh_interpolator(reduced_problem.basis_functions[:reduced_problem._solution_dot.N]*reduced_problem._solution_dot) backend.assign(solution_dot_to, solution_dot_from) # Solve reduced problems associated to nonlinear terms for (reduced_problem, is_solving) in required_reduced_problems: # Solve (if necessary) reduced_problem.set_mu(mu) if not is_solving: log(PROGRESS, "In expression_on_reduced_mesh, requiring reduced problem solve for problem " + reduced_problem.truth_problem.name()) reduced_problem.solve() else: log(PROGRESS, "In expression_on_reduced_mesh, loading current reduced problem solution for problem " + reduced_problem.truth_problem.name()) # Assign to reduced_mesh_solution if reduced_problem in reduced_problem_to_reduced_mesh_solution: for (reduced_mesh_solution, reduced_basis_functions) in zip(reduced_problem_to_reduced_mesh_solution[reduced_problem], reduced_problem_to_reduced_basis_functions[0][reduced_problem]): solution_to = reduced_mesh_solution solution_from_N = OnlineSizeDict() for c, v in reduced_problem._solution.N.items(): if c in reduced_basis_functions._components_name: solution_from_N[c] = v solution_from = online_backend.OnlineFunction(solution_from_N) if t is None or is_solving: online_backend.online_assign(solution_from, reduced_problem._solution) else: online_backend.online_assign(solution_from, reduced_problem._solution_over_time.at(t)) solution_from = reduced_basis_functions[:solution_from_N]*solution_from backend.assign(solution_to, solution_from) # Assign to reduced_mesh_solution_dot if reduced_problem in reduced_problem_to_reduced_mesh_solution_dot: for (reduced_mesh_solution_dot, reduced_basis_functions) in zip(reduced_problem_to_reduced_mesh_solution_dot[reduced_problem], reduced_problem_to_reduced_basis_functions[1][reduced_problem]): solution_dot_to = reduced_mesh_solution_dot solution_dot_from_N = OnlineSizeDict() for c, v in reduced_problem._solution_dot.N.items(): if c in reduced_basis_functions._components_name: solution_dot_from_N[c] = v solution_dot_from = online_backend.OnlineFunction(solution_dot_from_N) assert t is not None if is_solving: online_backend.online_assign(solution_dot_from, reduced_problem._solution_dot) else: online_backend.online_assign(solution_dot_from, reduced_problem._solution_dot_over_time.at(t)) solution_dot_from = reduced_basis_functions[:solution_dot_from_N]*solution_dot_from backend.assign(solution_dot_to, solution_dot_from) # Evaluate and return reduced_function = backend.Function(reduced_space) wrapping.evaluate_expression(expression, reduced_function, replaced_expression) return reduced_function