Example #1
0
def unpicklable_misc_operator_with_arrays_and_products_factory(n):
    if n == 0:
        from pymor.operators.numpy import NumpyGenericOperator
        op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 20, 4, 3, n)
        mat = op.matrix
        op2 = NumpyGenericOperator(mapping=lambda U: mat.dot(U.T).T, adjoint_mapping=lambda U: mat.T.dot(U.T).T,
                                   dim_source=100, dim_range=20, linear=True)
        return op2, _, U, V, sp, rp
    else:
        assert False
Example #2
0
def create_robin_solop(localizer, bilifo, source_space, omega_star_space):
    # Robin-Loesungsoperator
    def solve(va):
        g = localizer.to_space(NumpyVectorSpace.make_array(va), source_space,
                               omega_star_space)
        solution = bilifo.apply_inverse(g)
        return solution.data

    cavesize = len(localizer.join_spaces(source_space))
    rangesize = len(localizer.join_spaces(omega_star_space))
    return NumpyGenericOperator(solve,
                                dim_source=cavesize,
                                dim_range=rangesize,
                                linear=True)
Example #3
0
def create_dirichlet_solop(localizer, local_op, rhsop, source_space,
                           training_space):
    # Dirichlet-Loesungsoperator
    def solve(va):
        solution = local_op.apply_inverse(
            -rhsop.apply(NumpyVectorSpace.make_array(va)))
        return solution.data

    cavesize = len(localizer.join_spaces(source_space))
    rangesize = len(localizer.join_spaces(training_space))
    return NumpyGenericOperator(solve,
                                dim_source=cavesize,
                                dim_range=rangesize,
                                linear=True)
Example #4
0
def create_dirichlet_transfer(localizer, local_op, rhsop, source_space,
                              training_space, range_space, pou):
    # Dirichlet-Transferoperator
    def transfer(va):
        range_solution = localizer.to_space(
            local_op.apply_inverse(
                -rhsop.apply(NumpyVectorSpace.make_array(va))), training_space,
            range_space)
        return pou[range_space](range_solution).data

    cavesize = len(localizer.join_spaces(source_space))
    rangesize = len(localizer.join_spaces(range_space))
    return NumpyGenericOperator(transfer,
                                dim_source=cavesize,
                                dim_range=rangesize,
                                linear=True)
Example #5
0
def create_robin_transfer(localizer, bilifo, source_space, omega_star_space,
                          range_space, pou):
    # Robin-Transferoperator
    def transfer(va):
        g = localizer.to_space(NumpyVectorSpace.make_array(va), source_space,
                               omega_star_space)
        solution = bilifo.apply_inverse(g)
        range_solution = localizer.to_space(solution, omega_star_space,
                                            range_space)
        return pou[range_space](range_solution).data

    cavesize = len(localizer.join_spaces(source_space))
    rangesize = len(localizer.join_spaces(range_space))
    return NumpyGenericOperator(transfer,
                                dim_source=cavesize,
                                dim_range=rangesize,
                                linear=True)
Example #6
0
def discretize_instationary_fv(analytical_problem, diameter=None, domain_discretizer=None, grid_type=None,
                               num_flux='lax_friedrichs', lxf_lambda=1., eo_gausspoints=5, eo_intervals=1,
                               grid=None, boundary_info=None, num_values=None, time_stepper=None, nt=None,
                               preassemble=True):
    """Discretizes an |InstationaryProblem| with a |StationaryProblem| as stationary part
    using the finite volume method.

    Parameters
    ----------
    analytical_problem
        The |InstationaryProblem| to discretize.
    diameter
        If not `None`, `diameter` is passed to the `domain_discretizer`.
    domain_discretizer
        Discretizer to be used for discretizing the analytical domain. This has
        to be a function `domain_discretizer(domain_description, diameter, ...)`.
        If further arguments should be passed to the discretizer, use
        :func:`functools.partial`. If `None`, |discretize_domain_default| is used.
    grid_type
        If not `None`, this parameter is forwarded to `domain_discretizer` to specify
        the type of the generated |Grid|.
    num_flux
        The numerical flux to use in the finite volume formulation. Allowed
        values are `'lax_friedrichs'`, `'engquist_osher'`, `'simplified_engquist_osher'`
        (see :mod:`pymor.discretizers.builtin.fv`).
    lxf_lambda
        The stabilization parameter for the Lax-Friedrichs numerical flux
        (ignored, if different flux is chosen).
    eo_gausspoints
        Number of Gauss points for the Engquist-Osher numerical flux
        (ignored, if different flux is chosen).
    eo_intervals
        Number of sub-intervals to use for integration when using Engquist-Osher
        numerical flux (ignored, if different flux is chosen).
    grid
        Instead of using a domain discretizer, the |Grid| can also be passed directly
        using this parameter.
    boundary_info
        A |BoundaryInfo| specifying the boundary types of the grid boundary entities.
        Must be provided if `grid` is specified.
    num_values
        The number of returned vectors of the solution trajectory. If `None`, each
        intermediate vector that is calculated is returned.
    time_stepper
        The :class:`time-stepper <pymor.algorithms.timestepping.TimeStepper>`
        to be used by :class:`~pymor.models.basic.InstationaryModel.solve`.
    nt
        If `time_stepper` is not specified, the number of time steps for implicit
        Euler time stepping.
    preassemble
        If `True`, preassemble all operators in the resulting |Model|.

    Returns
    -------
    m
        The |Model| that has been generated.
    data
        Dictionary with the following entries:

            :grid:           The generated |Grid|.
            :boundary_info:  The generated |BoundaryInfo|.
            :unassembled_m:  In case `preassemble` is `True`, the generated |Model|
                             before preassembling operators.
    """

    assert isinstance(analytical_problem, InstationaryProblem)
    assert isinstance(analytical_problem.stationary_part, StationaryProblem)
    assert grid is None or boundary_info is not None
    assert boundary_info is None or grid is not None
    assert grid is None or domain_discretizer is None
    assert (time_stepper is None) != (nt is None)

    p = analytical_problem

    m, data = discretize_stationary_fv(p.stationary_part, diameter=diameter, domain_discretizer=domain_discretizer,
                                       grid_type=grid_type, num_flux=num_flux, lxf_lambda=lxf_lambda,
                                       eo_gausspoints=eo_gausspoints, eo_intervals=eo_intervals, grid=grid,
                                       boundary_info=boundary_info)
    grid = data['grid']

    if p.initial_data.parametric:
        def initial_projection(U, mu):
            I = p.initial_data.evaluate(grid.quadrature_points(0, order=2), mu).squeeze()
            I = np.sum(I * grid.reference_element.quadrature(order=2)[1], axis=1) * (1. / grid.reference_element.volume)
            I = m.solution_space.make_array(I)
            return I.lincomb(U).to_numpy()
        I = NumpyGenericOperator(initial_projection, dim_range=grid.size(0), linear=True, range_id=m.solution_space.id,
                                 parameter_type=p.initial_data.parameter_type)
    else:
        I = p.initial_data.evaluate(grid.quadrature_points(0, order=2)).squeeze()
        I = np.sum(I * grid.reference_element.quadrature(order=2)[1], axis=1) * (1. / grid.reference_element.volume)
        I = m.solution_space.make_array(I)

    if time_stepper is None:
        if p.stationary_part.diffusion is None:
            time_stepper = ExplicitEulerTimeStepper(nt=nt)
        else:
            time_stepper = ImplicitEulerTimeStepper(nt=nt)

    rhs = None if isinstance(m.rhs, ZeroOperator) else m.rhs

    m = InstationaryModel(operator=m.operator, rhs=rhs, mass=None, initial_data=I, T=p.T,
                          products=m.products, time_stepper=time_stepper,
                          parameter_space=p.parameter_space, visualizer=m.visualizer,
                          num_values=num_values, name=f'{p.name}_FV')

    if preassemble:
        data['unassembled_m'] = m
        m = preassemble_(m)

    return m, data
Example #7
0
def discretize_nonlinear_instationary_advection_fv(analytical_problem,
                                                   diameter=None,
                                                   nt=100,
                                                   num_flux='lax_friedrichs',
                                                   lxf_lambda=1.,
                                                   eo_gausspoints=5,
                                                   eo_intervals=1,
                                                   num_values=None,
                                                   domain_discretizer=None,
                                                   grid=None,
                                                   boundary_info=None):
    """Discretizes an |InstationaryAdvectionProblem| using the finite volume method.

    Simple explicit Euler time-stepping is used for time-discretization.

    Parameters
    ----------
    analytical_problem
        The |InstationaryAdvectionProblem| to discretize.
    diameter
        If not `None`, `diameter` is passed to the `domain_discretizer`.
    nt
        The number of time-steps.
    num_flux
        The numerical flux to use in the finite volume formulation. Allowed
        values are `'lax_friedrichs'`, `'engquist_osher'`, `'simplified_engquist_osher'`.
        (See :mod:`pymor.operators.fv`.)
    lxf_lambda
        The stabilization parameter for the Lax-Friedrichs numerical flux.
        (Ignored, if different flux is chosen.)
    eo_gausspoints
        Number of Gauss points for the Engquist-Osher numerical flux.
        (Ignored, if different flux is chosen.)
    eo_intervals
        Number of sub-intervals to use for integration when using Engquist-Osher
        numerical flux. (Ignored, if different flux is chosen.)
    num_values
        The number of returned vectors of the solution trajectory. If `None`, each
        intermediate vector that is calculated is returned.
    domain_discretizer
        Discretizer to be used for discretizing the analytical domain. This has
        to be a function `domain_discretizer(domain_description, diameter, ...)`.
        If further arguments should be passed to the discretizer, use
        :func:`functools.partial`. If `None`, |discretize_domain_default| is used.
    grid
        Instead of using a domain discretizer, the |Grid| can also be passed directly
        using this parameter.
    boundary_info
        A |BoundaryInfo| specifying the boundary types of the grid boundary entities.
        Must be provided if `grid` is specified.

    Returns
    -------
    discretization
        The |Discretization| that has been generated.
    data
        Dictionary with the following entries:

            :grid:           The generated |Grid|.
            :boundary_info:  The generated |BoundaryInfo|.


    """

    assert isinstance(analytical_problem, InstationaryAdvectionProblem)
    assert grid is None or boundary_info is not None
    assert boundary_info is None or grid is not None
    assert grid is None or domain_discretizer is None
    assert num_flux in ('lax_friedrichs', 'engquist_osher',
                        'simplified_engquist_osher')

    if grid is None:
        domain_discretizer = domain_discretizer or discretize_domain_default
        if diameter is None:
            grid, boundary_info = domain_discretizer(analytical_problem.domain)
        else:
            grid, boundary_info = domain_discretizer(analytical_problem.domain,
                                                     diameter=diameter)

    p = analytical_problem

    if num_flux == 'lax_friedrichs':
        L = nonlinear_advection_lax_friedrichs_operator(
            grid,
            boundary_info,
            p.flux_function,
            dirichlet_data=p.dirichlet_data,
            lxf_lambda=lxf_lambda)
    elif num_flux == 'engquist_osher':
        L = nonlinear_advection_engquist_osher_operator(
            grid,
            boundary_info,
            p.flux_function,
            p.flux_function_derivative,
            gausspoints=eo_gausspoints,
            intervals=eo_intervals,
            dirichlet_data=p.dirichlet_data)
    else:
        L = nonlinear_advection_simplified_engquist_osher_operator(
            grid,
            boundary_info,
            p.flux_function,
            p.flux_function_derivative,
            dirichlet_data=p.dirichlet_data)
    F = None if p.rhs is None else L2ProductFunctional(grid, p.rhs)

    if p.initial_data.parametric:

        def initial_projection(U, mu):
            I = p.initial_data.evaluate(grid.quadrature_points(0, order=2),
                                        mu).squeeze()
            I = np.sum(I * grid.reference_element.quadrature(order=2)[1],
                       axis=1) * (1. / grid.reference_element.volume)
            I = NumpyVectorArray(I, copy=False)
            return I.lincomb(U).data

        inject_sid(
            initial_projection, __name__ +
            '.discretize_nonlinear_instationary_advection_fv.initial_data',
            p.initial_data, grid)
        I = NumpyGenericOperator(initial_projection,
                                 dim_range=grid.size(0),
                                 linear=True,
                                 parameter_type=p.initial_data.parameter_type)
    else:
        I = p.initial_data.evaluate(grid.quadrature_points(0,
                                                           order=2)).squeeze()
        I = np.sum(I * grid.reference_element.quadrature(order=2)[1],
                   axis=1) * (1. / grid.reference_element.volume)
        I = NumpyVectorArray(I, copy=False)
        inject_sid(
            I, __name__ +
            '.discretize_nonlinear_instationary_advection_fv.initial_data',
            p.initial_data, grid)

    products = {'l2': L2Product(grid, boundary_info)}
    if grid.dim == 2:
        visualizer = PatchVisualizer(grid=grid,
                                     bounding_box=grid.domain,
                                     codim=0)
    elif grid.dim == 1:
        visualizer = Matplotlib1DVisualizer(grid, codim=0)
    else:
        visualizer = None
    parameter_space = p.parameter_space if hasattr(p,
                                                   'parameter_space') else None
    time_stepper = ExplicitEulerTimeStepper(nt=nt)

    discretization = InstationaryDiscretization(
        operator=L,
        rhs=F,
        initial_data=I,
        T=p.T,
        products=products,
        time_stepper=time_stepper,
        parameter_space=parameter_space,
        visualizer=visualizer,
        num_values=num_values,
        name='{}_FV'.format(p.name))

    return discretization, {'grid': grid, 'boundary_info': boundary_info}
Example #8
0
def discretize_parabolic_fv(analytical_problem, diameter=None, domain_discretizer=None,
                           grid=None, boundary_info=None, num_values=None, time_stepper=None, nt=None):
    """Discretizes an |ParabolicProblem| using the finite volume method.

    Parameters
    ----------
    analytical_problem
        The |ParabolicProblem| to discretize.
    diameter
        If not `None`, `diameter` is passed to the `domain_discretizer`.
    domain_discretizer
        Discretizer to be used for discretizing the analytical domain. This has
        to be a function `domain_discretizer(domain_description, diameter, ...)`.
        If further arguments should be passed to the discretizer, use
        :func:`functools.partial`. If `None`, |discretize_domain_default| is used.
    grid
        Instead of using a domain discretizer, the |Grid| can also be passed directly
        using this parameter.
    boundary_info
        A |BoundaryInfo| specifying the boundary types of the grid boundary entities.
        Must be provided if `grid` is specified.
    num_values
        The number of returned vectors of the solution trajectory. If `None`, each
        intermediate vector that is calculated is returned.
    time_stepper
        The time-stepper to be used by :class:`~pymor.discretizations.basic.InstationaryDiscretization.solve`. Has to
        satisfy the :class:`~pymor.algorithms.timestepping.TimeStepperInterface`.
    nt
        The number of time-steps. If provided implicit euler time-stepping is used.

    Returns
    -------
    discretization
        The |Discretization| that has been generated.
    data
        Dictionary with the following entries:

            :grid:           The generated |Grid|.
            :boundary_info:  The generated |BoundaryInfo|.
    """

    assert isinstance(analytical_problem, ParabolicProblem)
    assert grid is None or boundary_info is not None
    assert boundary_info is None or grid is not None
    assert grid is None or domain_discretizer is None
    assert time_stepper is None or nt is None

    p = analytical_problem

    d, data = discretize_elliptic_fv(p.elliptic_part(), diameter=diameter, domain_discretizer=domain_discretizer,
                                         grid=grid, boundary_info=boundary_info)

    if p.initial_data.parametric:
        def initial_projection(U, mu):
            I = p.initial_data.evaluate(grid.quadrature_points(0, order=2), mu).squeeze()
            I = np.sum(I * grid.reference_element.quadrature(order=2)[1], axis=1) * (1. / grid.reference_element.volume)
            I = NumpyVectorArray(I, copy=False)
            return I.lincomb(U).data
        I = NumpyGenericOperator(initial_projection, dim_range=grid.size(0), linear=True,
                                 parameter_type=p.initial_data.parameter_type)
    else:
        I = p.initial_data.evaluate(grid.quadrature_points(0, order=2)).squeeze()
        I = np.sum(I * grid.reference_element.quadrature(order=2)[1], axis=1) * (1. / grid.reference_element.volume)
        I = NumpyVectorArray(I, copy=False)

    if time_stepper is None:
        time_stepper = ImplicitEulerTimeStepper(nt=nt)

    discretization = InstationaryDiscretization(operator=d.operator, rhs=d.rhs, mass=None, initial_data=I, T=p.T,
                                                products=d.products, time_stepper=time_stepper,
                                                parameter_space=d.parameter_space, visualizer=d.visualizer,
                                                num_values=num_values, name='{}_FV'.format(p.name))

    return discretization, data