class ParabolicRBReductor(InstationaryRBReductor): r"""Reduced Basis Reductor for parabolic equations. This reductor uses :class:`~pymor.reductors.basic.InstationaryRBReductor` for the actual RB-projection. The only addition is the assembly of an error estimator which bounds the discrete l2-in time / energy-in space error similar to [GP05]_, [HO08]_ as follows: .. math:: \left[ C_a^{-1}(\mu)\|e_N(\mu)\|^2 + \sum_{n=1}^{N} \Delta t\|e_n(\mu)\|^2_e \right]^{1/2} \leq \left[ C_a^{-2}(\mu)\Delta t \sum_{n=1}^{N}\|\mathcal{R}^n(u_n(\mu), \mu)\|^2_{e,-1} + C_a^{-1}(\mu)\|e_0\|^2 \right]^{1/2} Here, :math:`\|\cdot\|` denotes the norm induced by the problem's mass matrix (e.g. the L^2-norm) and :math:`\|\cdot\|_e` is an arbitrary energy norm w.r.t. which the space operator :math:`A(\mu)` is coercive, and :math:`C_a(\mu)` is a lower bound for its coercivity constant. Finally, :math:`\mathcal{R}^n` denotes the implicit Euler timestepping residual for the (fixed) time step size :math:`\Delta t`, .. math:: \mathcal{R}^n(u_n(\mu), \mu) := f - M \frac{u_{n}(\mu) - u_{n-1}(\mu)}{\Delta t} - A(u_n(\mu), \mu), where :math:`M` denotes the mass operator and :math:`f` the source term. The dual norm of the residual is computed using the numerically stable projection from [BEOR14]_. Parameters ---------- fom The |InstationaryModel| which is to be reduced. RB |VectorArray| containing the reduced basis on which to project. product The energy inner product |Operator| w.r.t. which the reduction error is estimated and `RB` is orthonormalized. coercivity_estimator `None` or a |Parameterfunctional| returning a lower bound :math:`C_a(\mu)` for the coercivity constant of `fom.operator` w.r.t. `product`. """ def __init__(self, fom, RB=None, product=None, coercivity_estimator=None, check_orthonormality=None, check_tol=None): if not isinstance(fom.time_stepper, ImplicitEulerTimeStepper): raise NotImplementedError if fom.mass is not None and fom.mass.parametric and 't' in fom.mass.parameters: raise NotImplementedError super().__init__(fom, RB, product=product, check_orthonormality=check_orthonormality, check_tol=check_tol) self.coercivity_estimator = coercivity_estimator self.residual_reductor = ImplicitEulerResidualReductor( self.bases['RB'], fom.operator, fom.mass, fom.T / fom.time_stepper.nt, rhs=fom.rhs, product=product) self.initial_residual_reductor = ResidualReductor( self.bases['RB'], IdentityOperator(fom.solution_space), fom.initial_data, product=fom.l2_product, riesz_representatives=False) def assemble_estimator(self): residual = self.residual_reductor.reduce() initial_residual = self.initial_residual_reductor.reduce() estimator = ParabolicRBEstimator( residual, self.residual_reductor.residual_range_dims, initial_residual, self.initial_residual_reductor.residual_range_dims, self.coercivity_estimator) return estimator def assemble_estimator_for_subbasis(self, dims): return self._last_rom.estimator.restricted_to_subbasis( dims['RB'], m=self._last_rom)
class ParabolicRBReductor(GenericRBReductor): r"""Reduced Basis Reductor for parabolic equations. This reductor uses :class:`~pymor.reductors.basic.GenericRBReductor` for the actual RB-projection. The only addition is the assembly of an error estimator which bounds the discrete l2-in time / energy-in space error similar to [GP05]_, [HO08]_ as follows: .. math:: \left[ C_a^{-1}(\mu)\|e_N(\mu)\|^2 + \sum_{n=1}^{N} \Delta t\|e_n(\mu)\|^2_e \right]^{1/2} \leq \left[ C_a^{-1}(\mu)\Delta t \sum_{n=1}^{N}\|\mathcal{R}^n(u_n(\mu), \mu)\|^2_{e,-1} + C_a^{-1}(\mu)\|e_0\|^2 \right]^{1/2} Here, :math:`\|\cdot\|` denotes the norm induced by the problem's mass matrix (e.g. the L^2-norm) and :math:`\|\cdot\|_e` is an arbitrary energy norm w.r.t. which the space operator :math:`A(\mu)` is coercive, and :math:`C_a(\mu)` is a lower bound for its coercivity constant. Finally, :math:`\mathcal{R}^n` denotes the implicit Euler timestepping residual for the (fixed) time step size :math:`\Delta t`, .. math:: \mathcal{R}^n(u_n(\mu), \mu) := f - M \frac{u_{n}(\mu) - u_{n-1}(\mu)}{\Delta t} - A(u_n(\mu), \mu), where :math:`M` denotes the mass operator and :math:`f` the source term. The dual norm of the residual is computed using the numerically stable projection from [BEOR14]_. .. warning:: The reduced basis `RB` is required to be orthonormal w.r.t. the given energy product. If not, the projection of the initial values will be computed incorrectly. .. [GP05] M. A. Grepl, A. T. Patera, A Posteriori Error Bounds For Reduced-Basis Approximations Of Parametrized Parabolic Partial Differential Equations, M2AN 39(1), 157-181, 2005. .. [HO08] B. Haasdonk, M. Ohlberger, Reduced basis method for finite volume approximations of parametrized evolution equations, M2AN 42(2), 277-302, 2008. Parameters ---------- d The |InstationaryDiscretization| which is to be reduced. RB |VectorArray| containing the reduced basis on which to project. product The energy inner product |Operator| w.r.t. the reduction error is estimated. RB must be to be orthonomrmal w.r.t. this product! coercivity_estimator `None` or a |Parameterfunctional| returning a lower bound :math:`C_a(\mu)` for the coercivity constant of `d.operator` w.r.t. `product`. """ def __init__(self, d, RB=None, product=None, coercivity_estimator=None): assert isinstance(d.time_stepper, ImplicitEulerTimeStepper) super().__init__(d, RB, product=product) self.coercivity_estimator = coercivity_estimator self.residual_reductor = ImplicitEulerResidualReductor( self.RB, d.operator, d.mass, d.T / d.time_stepper.nt, functional=d.rhs, product=product ) self.initial_residual_reductor = ResidualReductor( self.RB, IdentityOperator(d.solution_space), d.initial_data, product=d.l2_product ) def _reduce(self): with self.logger.block('RB projection ...'): rd = super()._reduce() with self.logger.block('Assembling error estimator ...'): residual = self.residual_reductor.reduce() initial_residual = self.initial_residual_reductor.reduce() estimator = ParabolicRBEstimator(residual, self.residual_reductor.residual_range_dims, initial_residual, self.initial_residual_reductor.residual_range_dims, self.coercivity_estimator) rd = rd.with_(estimator=estimator) return rd
class ParabolicRBReductor(GenericRBReductor): r"""Reduced Basis Reductor for parabolic equations. This reductor uses :class:`~pymor.reductors.basic.GenericRBReductor` for the actual RB-projection. The only addition is the assembly of an error estimator which bounds the discrete l2-in time / energy-in space error similar to [GP05]_, [HO08]_ as follows: .. math:: \left[ C_a^{-1}(\mu)\|e_N(\mu)\|^2 + \sum_{n=1}^{N} \Delta t\|e_n(\mu)\|^2_e \right]^{1/2} \leq \left[ C_a^{-1}(\mu)\Delta t \sum_{n=1}^{N}\|\mathcal{R}^n(u_n(\mu), \mu)\|^2_{e,-1} + C_a^{-1}(\mu)\|e_0\|^2 \right]^{1/2} Here, :math:`\|\cdot\|` denotes the norm induced by the problem's mass matrix (e.g. the L^2-norm) and :math:`\|\cdot\|_e` is an arbitrary energy norm w.r.t. which the space operator :math:`A(\mu)` is coercive, and :math:`C_a(\mu)` is a lower bound for its coercivity constant. Finally, :math:`\mathcal{R}^n` denotes the implicit Euler timestepping residual for the (fixed) time step size :math:`\Delta t`, .. math:: \mathcal{R}^n(u_n(\mu), \mu) := f - M \frac{u_{n}(\mu) - u_{n-1}(\mu)}{\Delta t} - A(u_n(\mu), \mu), where :math:`M` denotes the mass operator and :math:`f` the source term. The dual norm of the residual is computed using the numerically stable projection from [BEOR14]_. Parameters ---------- d The |InstationaryDiscretization| which is to be reduced. RB |VectorArray| containing the reduced basis on which to project. basis_is_orthonormal Indicate whether or not the basis is orthonormal w.r.t. `product`. product The energy inner product |Operator| w.r.t. which the reduction error is estimated and `RB` is orthonormalized. coercivity_estimator `None` or a |Parameterfunctional| returning a lower bound :math:`C_a(\mu)` for the coercivity constant of `d.operator` w.r.t. `product`. """ def __init__(self, d, RB=None, basis_is_orthonormal=None, product=None, coercivity_estimator=None): assert isinstance(d.time_stepper, ImplicitEulerTimeStepper) super().__init__(d, RB, basis_is_orthonormal=basis_is_orthonormal, product=product) self.coercivity_estimator = coercivity_estimator self.residual_reductor = ImplicitEulerResidualReductor( self.RB, d.operator, d.mass, d.T / d.time_stepper.nt, rhs=d.rhs, product=product ) self.initial_residual_reductor = ResidualReductor( self.RB, IdentityOperator(d.solution_space), d.initial_data, product=d.l2_product, riesz_representatives=False ) def _reduce(self): with self.logger.block('RB projection ...'): rd = super()._reduce() with self.logger.block('Assembling error estimator ...'): residual = self.residual_reductor.reduce() initial_residual = self.initial_residual_reductor.reduce() estimator = ParabolicRBEstimator(residual, self.residual_reductor.residual_range_dims, initial_residual, self.initial_residual_reductor.residual_range_dims, self.coercivity_estimator) rd = rd.with_(estimator=estimator) return rd
class ParabolicRBReductor(GenericRBReductor): r"""Reduced Basis Reductor for parabolic equations. This reductor uses :class:`~pymor.reductors.basic.GenericRBReductor` for the actual RB-projection. The only addition is the assembly of an error estimator which bounds the discrete l2-in time / energy-in space error similar to [GP05]_, [HO08]_ as follows: .. math:: \left[ C_a^{-1}(\mu)\|e_N(\mu)\|^2 + \sum_{n=1}^{N} \Delta t\|e_n(\mu)\|^2_e \right]^{1/2} \leq \left[ C_a^{-1}(\mu)\Delta t \sum_{n=1}^{N}\|\mathcal{R}^n(u_n(\mu), \mu)\|^2_{e,-1} + C_a^{-1}(\mu)\|e_0\|^2 \right]^{1/2} Here, :math:`\|\cdot\|` denotes the norm induced by the problem's mass matrix (e.g. the L^2-norm) and :math:`\|\cdot\|_e` is an arbitrary energy norm w.r.t. which the space operator :math:`A(\mu)` is coercive, and :math:`C_a(\mu)` is a lower bound for its coercivity constant. Finally, :math:`\mathcal{R}^n` denotes the implicit Euler timestepping residual for the (fixed) time step size :math:`\Delta t`, .. math:: \mathcal{R}^n(u_n(\mu), \mu) := f - M \frac{u_{n}(\mu) - u_{n-1}(\mu)}{\Delta t} - A(u_n(\mu), \mu), where :math:`M` denotes the mass operator and :math:`f` the source term. The dual norm of the residual is computed using the numerically stable projection from [BEOR14]_. .. warning:: The reduced basis `RB` is required to be orthonormal w.r.t. the given energy product. If not, the projection of the initial values will be computed incorrectly. .. [GP05] M. A. Grepl, A. T. Patera, A Posteriori Error Bounds For Reduced-Basis Approximations Of Parametrized Parabolic Partial Differential Equations, M2AN 39(1), 157-181, 2005. .. [HO08] B. Haasdonk, M. Ohlberger, Reduced basis method for finite volume approximations of parametrized evolution equations, M2AN 42(2), 277-302, 2008. Parameters ---------- discretization The |InstationaryDiscretization| which is to be reduced. RB |VectorArray| containing the reduced basis on which to project. product The energy inner product |Operator| w.r.t. the reduction error is estimated. RB must be to be orthonomrmal w.r.t. this product! coercivity_estimator `None` or a |Parameterfunctional| returning a lower bound :math:`C_a(\mu)` for the coercivity constant of `discretization.operator` w.r.t. `product`. """ def __init__(self, d, RB=None, product=None, coercivity_estimator=None): assert isinstance(d.time_stepper, ImplicitEulerTimeStepper) super().__init__(d, RB, product=product) self.coercivity_estimator = coercivity_estimator self.residual_reductor = ImplicitEulerResidualReductor( self.RB, d.operator, d.mass, d.T / d.time_stepper.nt, functional=d.rhs, product=product) self.initial_residual_reductor = ResidualReductor( self.RB, IdentityOperator(d.solution_space), d.initial_data, product=d.l2_product) def _reduce(self): with self.logger.block('RB projection ...'): rd = super()._reduce() with self.logger.block('Assembling error estimator ...'): residual = self.residual_reductor.reduce() initial_residual = self.initial_residual_reductor.reduce() estimator = ParabolicRBEstimator( residual, self.residual_reductor.residual_range_dims, initial_residual, self.initial_residual_reductor.residual_range_dims, self.coercivity_estimator) rd = rd.with_(estimator=estimator) return rd
class ParabolicRBReductor(InstationaryRBReductor): r"""Reduced Basis Reductor for parabolic equations. This reductor uses :class:`~pymor.reductors.basic.InstationaryRBReductor` for the actual RB-projection. The only addition is the assembly of an error estimator which bounds the discrete l2-in time / energy-in space error similar to [GP05]_, [HO08]_ as follows: .. math:: \left[ C_a^{-1}(\mu)\|e_N(\mu)\|^2 + \sum_{n=1}^{N} \Delta t\|e_n(\mu)\|^2_e \right]^{1/2} \leq \left[ C_a^{-1}(\mu)\Delta t \sum_{n=1}^{N}\|\mathcal{R}^n(u_n(\mu), \mu)\|^2_{e,-1} + C_a^{-1}(\mu)\|e_0\|^2 \right]^{1/2} Here, :math:`\|\cdot\|` denotes the norm induced by the problem's mass matrix (e.g. the L^2-norm) and :math:`\|\cdot\|_e` is an arbitrary energy norm w.r.t. which the space operator :math:`A(\mu)` is coercive, and :math:`C_a(\mu)` is a lower bound for its coercivity constant. Finally, :math:`\mathcal{R}^n` denotes the implicit Euler timestepping residual for the (fixed) time step size :math:`\Delta t`, .. math:: \mathcal{R}^n(u_n(\mu), \mu) := f - M \frac{u_{n}(\mu) - u_{n-1}(\mu)}{\Delta t} - A(u_n(\mu), \mu), where :math:`M` denotes the mass operator and :math:`f` the source term. The dual norm of the residual is computed using the numerically stable projection from [BEOR14]_. Parameters ---------- fom The |InstationaryModel| which is to be reduced. RB |VectorArray| containing the reduced basis on which to project. product The energy inner product |Operator| w.r.t. which the reduction error is estimated and `RB` is orthonormalized. coercivity_estimator `None` or a |Parameterfunctional| returning a lower bound :math:`C_a(\mu)` for the coercivity constant of `fom.operator` w.r.t. `product`. """ def __init__(self, fom, RB=None, product=None, coercivity_estimator=None, check_orthonormality=None, check_tol=None): assert isinstance(fom.time_stepper, ImplicitEulerTimeStepper) super().__init__(fom, RB, product=product, check_orthonormality=check_orthonormality, check_tol=check_tol) self.coercivity_estimator = coercivity_estimator self.residual_reductor = ImplicitEulerResidualReductor( self.bases['RB'], fom.operator, fom.mass, fom.T / fom.time_stepper.nt, rhs=fom.rhs, product=product ) self.initial_residual_reductor = ResidualReductor( self.bases['RB'], IdentityOperator(fom.solution_space), fom.initial_data, product=fom.l2_product, riesz_representatives=False ) def assemble_estimator(self): residual = self.residual_reductor.reduce() initial_residual = self.initial_residual_reductor.reduce() estimator = ParabolicRBEstimator(residual, self.residual_reductor.residual_range_dims, initial_residual, self.initial_residual_reductor.residual_range_dims, self.coercivity_estimator) return estimator def assemble_estimator_for_subbasis(self, dims): return self._last_rom.estimator.restricted_to_subbasis(dims['RB'], m=self._last_rom)