Ejemplo n.º 1
0
 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")
Ejemplo n.º 2
0
 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()
Ejemplo n.º 3
0
 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
Ejemplo n.º 4
0
 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
Ejemplo n.º 5
0
 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
Ejemplo n.º 6
0
 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)
Ejemplo n.º 7
0
 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