def __init__(self, mock_problem, expression_type, basis_generation): self.V = mock_problem.V # Parametrized function to be interpolated mu = SymbolicParameters(mock_problem, self.V, (1., )) x = SpatialCoordinate(self.V.mesh()) f = (1 - x[0]) * cos(3 * pi * mu[0] * (1 + x[0])) * exp(-mu[0] * (1 + x[0])) # folder_prefix = os.path.join("test_eim_approximation_09_tempdir", expression_type, basis_generation) assert expression_type in ("Function", "Vector", "Matrix") if expression_type == "Function": # Call Parent constructor EIMApproximation.__init__(self, mock_problem, ParametrizedExpressionFactory(f), folder_prefix, basis_generation) elif expression_type == "Vector": v = TestFunction(self.V) form = f * v * dx # Call Parent constructor EIMApproximation.__init__(self, mock_problem, ParametrizedTensorFactory(form), folder_prefix, basis_generation) elif expression_type == "Matrix": u = TrialFunction(self.V) v = TestFunction(self.V) form = f * u * v * dx # Call Parent constructor EIMApproximation.__init__(self, mock_problem, ParametrizedTensorFactory(form), folder_prefix, basis_generation) else: # impossible to arrive here anyway thanks to the assert raise AssertionError("Invalid expression_type")
def __init__(self, V, **kwargs): # Call parent ParametrizedProblem.__init__( self, os.path.join("test_eim_approximation_17_tempdir", expression_type, basis_generation, "mock_problem")) # Minimal subset of a ParametrizedDifferentialProblem self.V = V self._solution = Function(V) self.components = ["u", "s", "p"] # Parametrized function to be interpolated x = SpatialCoordinate(V.mesh()) mu = SymbolicParameters(self, V, (-1., -1.)) self.f00 = 1. / sqrt( pow(x[0] - mu[0], 2) + pow(x[1] - mu[1], 2) + 0.01) self.f01 = 1. / sqrt( pow(x[0] - mu[0], 4) + pow(x[1] - mu[1], 4) + 0.01) # Inner product f = TrialFunction(self.V) g = TestFunction(self.V) self.inner_product = assemble(inner(f, g) * dx) # Collapsed vector and space self.V0 = V.sub(0).collapse() self.V00 = V.sub(0).sub(0).collapse() self.V1 = V.sub(1).collapse()
def _init_EIM_approximations(self): # Preprocess each term in the affine expansions. # Note that this cannot be done in __init__, because operators may depend on self.mu, # which is not defined at __init__ time. Moreover, it cannot be done either by init, # because the init method is called by offline stage of the reduction method instance, # but we need EIM approximations to be already set up at the time the reduction method # instance is built. Thus, we will call this method in the reduction method instance # constructor (having a safeguard in place to avoid repeated calls). assert ((len(self.separated_forms) == 0) == (len( self.EIM_approximations) == 0)) if len(self.EIM_approximations ) == 0: # initialize EIM approximations only once # Initialize symbolic parameters only once (may be shared between EIM and exact evaluation) if self.mu_symbolic is None: self.mu_symbolic = SymbolicParameters( self, self.V, self.mu) # Temporarily replace float parameters with symbols, so that we can detect if operators # are parametrized mu_float = self.mu self.mu = self.mu_symbolic # Loop over each term for term in self.terms: try: forms = self.assemble_operator(term) except ValueError: # possibily raised e.g. because output computation is optional pass else: Q = len(forms) self.separated_forms[ term] = AffineExpansionSeparatedFormsStorage(Q) for q in range(Q): self.separated_forms[term][ q] = SeparatedParametrizedForm(forms[q]) self.separated_forms[term][q].separate() # All parametrized coefficients should be approximated by EIM for (addend_index, addend) in enumerate( self.separated_forms[term] [q].coefficients): for (factor, factor_name) in zip( addend, self.separated_forms[term] [q].placeholders_names(addend_index)): if factor not in self.EIM_approximations: factory_factor = ParametrizedExpressionFactory( factor) if factory_factor.is_time_dependent( ): EIMApproximationType = TimeDependentEIMApproximation else: EIMApproximationType = EIMApproximation self.EIM_approximations[ factor] = EIMApproximationType( self, factory_factor, os.path.join( self.name(), "eim", factor_name), basis_generation) # Restore float parameters self.mu = mu_float
def attach_symbolic_parameters(self): # Initialize symbolic parameters only once (may be shared between DEIM/EIM and exact evaluation) if self.mu_symbolic is None: self.mu_symbolic = SymbolicParameters( self, self.V, self.mu) # Swap storage if self.attach_symbolic_parameters__calls == 0: self.mu_float = self.mu self.mu = self.mu_symbolic self.attach_symbolic_parameters__calls += 1
def _init_operators_exact(self): # Initialize symbolic parameters only once if self.mu_symbolic is None: self.mu_symbolic = SymbolicParameters( self, self.V, self.mu) # Initialize offline/online switch storage only once (may be shared between EIM/DEIM and exact evaluation) OfflineOnlineClassMethod = self.offline_online_backend.OfflineOnlineClassMethod OfflineOnlineExpansionStorage = self.offline_online_backend.OfflineOnlineExpansionStorage OfflineOnlineExpansionStorageSize = self.offline_online_backend.OfflineOnlineExpansionStorageSize OfflineOnlineSwitch = self.offline_online_backend.OfflineOnlineSwitch if not isinstance(self.Q, OfflineOnlineSwitch): assert isinstance(self.Q, dict) assert len(self.Q) is 0 self.Q = OfflineOnlineExpansionStorageSize() if not isinstance(self.operator, OfflineOnlineSwitch): assert isinstance(self.operator, dict) assert len(self.operator) is 0 self.operator = OfflineOnlineExpansionStorage( self, "OperatorExpansionStorage") if not isinstance(self.assemble_operator, OfflineOnlineSwitch): assert inspect.ismethod(self.assemble_operator) self._assemble_operator_exact = self.assemble_operator self.assemble_operator = OfflineOnlineClassMethod( self, "assemble_operator") if not isinstance(self.compute_theta, OfflineOnlineSwitch): assert inspect.ismethod(self.compute_theta) self._compute_theta_exact = self.compute_theta self.compute_theta = OfflineOnlineClassMethod( self, "compute_theta") # Temporarily replace float parameters with symbols, so that the forms do not hardcode # the current value of the parameter while assemblying. mu_float = self.mu self.mu = self.mu_symbolic # Setup offline/online switches former_stage = OfflineOnlineSwitch.get_current_stage() for stage_exact in self._apply_exact_evaluation_at_stages: OfflineOnlineSwitch.set_current_stage(stage_exact) # Enforce exact evaluation of assemble_operator and compute_theta self.assemble_operator.attach( self._assemble_operator_exact, lambda term: True) self.compute_theta.attach(self._compute_theta_exact, lambda term: True) # Setup offline/online operators storage with exact operators self.operator.set_is_affine(False) self._init_operators() self.operator.unset_is_affine() # Restore former stage in offline/online switch storage OfflineOnlineSwitch.set_current_stage(former_stage) # Restore float parameters self.mu = mu_float
def __init__(self, V, **kwargs): # Call parent ParametrizedProblem.__init__(self, os.path.join("test_eim_approximation_12_tempdir", expression_type, basis_generation, "mock_problem")) # Minimal subset of a ParametrizedDifferentialProblem self.V = V self._solution = Function(V) self.components = ["u"] # Parametrized function to be interpolated x = SpatialCoordinate(V.mesh()) mu = SymbolicParameters(self, V, (1., )) self.f = (1-x[0])*cos(3*pi*mu[0]*(1+x[0]))*exp(-mu[0]*(1+x[0])) # Inner product f = TrialFunction(self.V) g = TestFunction(self.V) self.inner_product = assemble(f*g*dx)
def _init_DEIM_approximations(self): # Preprocess each term in the affine expansions. # Note that this cannot be done in __init__, because operators may depend on self.mu, # which is not defined at __init__ time. Moreover, it cannot be done either by init, # because the init method is called by offline stage of the reduction method instance, # but we need DEIM approximations to be already set up at the time the reduction method # instance is built. Thus, we will call this method in the reduction method instance # constructor (having a safeguard in place to avoid repeated calls). assert ((len(self.DEIM_approximations) == 0) == (len( self.non_DEIM_forms) == 0)) if len(self.DEIM_approximations ) == 0: # initialize DEIM approximations only once # Initialize symbolic parameters only once (may be shared between DEIM and exact evaluation) if self.mu_symbolic is None: self.mu_symbolic = SymbolicParameters( self, self.V, self.mu) # Temporarily replace float parameters with symbols, so that we can detect if operators # are parametrized mu_float = self.mu self.mu = self.mu_symbolic # Loop over each term for term in self.terms: try: forms = self.assemble_operator(term) except ValueError: # possibily raised e.g. because output computation is optional pass else: self.DEIM_approximations[term] = dict() self.non_DEIM_forms[term] = dict() for (q, form_q) in enumerate(forms): factory_form_q = ParametrizedTensorFactory( form_q) if factory_form_q.is_parametrized(): if factory_form_q.is_time_dependent(): DEIMApproximationType = TimeDependentDEIMApproximation else: DEIMApproximationType = DEIMApproximation self.DEIM_approximations[term][ q] = DEIMApproximationType( self, factory_form_q, self.name() + "/deim/" + factory_form_q.name(), basis_generation) else: self.non_DEIM_forms[term][q] = form_q # Restore float parameters self.mu = mu_float