コード例 #1
0
ファイル: parabolic.py プロジェクト: michaellaier/pymor
def parabolic_demo():
    p = ThermalBlockProblem(parameter_range=(0.01, 1))
    d_stat, d_data = discretize_elliptic_cg(p, diameter=1. / 100)
    U0 = NumpyVectorArray(np.zeros(d_stat.operator.source.dim))
    time_stepper = ImplicitEulerTimeStepper(50)

    d = InstationaryDiscretization(operator=d_stat.operator,
                                   rhs=d_stat.rhs,
                                   mass=d_stat.l2_product,
                                   initial_data=U0,
                                   T=1,
                                   products=d_stat.products,
                                   time_stepper=time_stepper,
                                   parameter_space=d_stat.parameter_space,
                                   visualizer=d_stat.visualizer)

    mu = next(d.parameter_space.sample_randomly(1))
    R = d.solve(mu)
    d.visualize(R)
コード例 #2
0
def discretize(grid_and_problem_data, T, nt, polorder):

    d, data = discretize_stationary(grid_and_problem_data, polorder)
    assert isinstance(d.parameter_space, CubicParameterSpace)
    parameter_range = grid_and_problem_data['parameter_range']

    d = InstationaryDiscretization(T,
                                   d.operator.source.zeros(1),
                                   d.operator,
                                   d.rhs,
                                   mass=d.operators['l2'],
                                   time_stepper=ImplicitEulerTimeStepper(nt=nt,
                                                                         solver_options='operator'),
                                   products=d.products,
                                   operators={kk: vv for kk, vv in d.operators.items()
                                              if kk not in ('operator', 'rhs') and vv not in (d.operators, d.rhs)},
                                   visualizer=DuneGDTVisualizer(data['space']))
    d = d.with_(parameter_space=CubicParameterSpace(d.parameter_type, parameter_range[0], parameter_range[1]))

    return d, data
コード例 #3
0
def _discretize_fenics():

    # assemble system matrices - FEniCS code
    ########################################

    import dolfin as df

    # discrete function space
    mesh = df.UnitSquareMesh(GRID_INTERVALS, GRID_INTERVALS, 'crossed')
    V = df.FunctionSpace(mesh, 'Lagrange', FENICS_ORDER)
    u = df.TrialFunction(V)
    v = df.TestFunction(V)

    # data functions
    bottom_diffusion = df.Expression('(x[0] > 0.45) * (x[0] < 0.55) * (x[1] < 0.7) * 1.',
                                     element=df.FunctionSpace(mesh, 'DG', 0).ufl_element())
    top_diffusion = df.Expression('(x[0] > 0.35) * (x[0] < 0.40) * (x[1] > 0.3) * 1. +'
                                  '(x[0] > 0.60) * (x[0] < 0.65) * (x[1] > 0.3) * 1.',
                                  element=df.FunctionSpace(mesh, 'DG', 0).ufl_element())
    initial_data = df.Expression('(x[0] > 0.45) * (x[0] < 0.55) * (x[1] < 0.7) * 10.',
                                 element=df.FunctionSpace(mesh, 'DG', 0).ufl_element())
    neumann_data = df.Expression('(x[0] > 0.45) * (x[0] < 0.55) * 1000.',
                                 element=df.FunctionSpace(mesh, 'DG', 0).ufl_element())

    # assemble matrices and vectors
    l2_mat = df.assemble(df.inner(u, v) * df.dx)
    l2_0_mat = l2_mat.copy()
    h1_mat = df.assemble(df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx)
    h1_0_mat = h1_mat.copy()
    mat0 = h1_mat.copy()
    mat0.zero()
    bottom_mat = df.assemble(bottom_diffusion * df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx)
    top_mat = df.assemble(top_diffusion * df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx)
    u0 = df.project(initial_data, V).vector()
    f = df.assemble(neumann_data * v * df.ds)

    # boundary treatment
    def dirichlet_boundary(x, on_boundary):
        tol = 1e-14
        return on_boundary and (abs(x[0]) < tol or abs(x[0] - 1) < tol or abs(x[1] - 1) < tol)

    bc = df.DirichletBC(V, df.Constant(0.), dirichlet_boundary)
    bc.apply(l2_0_mat)
    bc.apply(h1_0_mat)
    bc.apply(mat0)
    bc.zero(bottom_mat)
    bc.zero(top_mat)
    bc.apply(f)
    bc.apply(u0)

    # wrap everything as a pyMOR model
    ##################################

    from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator, FenicsVisualizer

    fom = InstationaryModel(
        T=1.,

        initial_data=FenicsVectorSpace(V).make_array([u0]),

        operator=LincombOperator([FenicsMatrixOperator(mat0, V, V),
                                  FenicsMatrixOperator(h1_0_mat, V, V),
                                  FenicsMatrixOperator(bottom_mat, V, V),
                                  FenicsMatrixOperator(top_mat, V, V)],
                                 [1.,
                                  1.,
                                  100. - 1.,
                                  ExpressionParameterFunctional('top[0] - 1.', {'top': 1})]),

        rhs=VectorOperator(FenicsVectorSpace(V).make_array([f])),

        mass=FenicsMatrixOperator(l2_0_mat, V, V, name='l2'),

        products={'l2': FenicsMatrixOperator(l2_mat, V, V, name='l2'),
                  'l2_0': FenicsMatrixOperator(l2_0_mat, V, V, name='l2_0'),
                  'h1': FenicsMatrixOperator(h1_mat, V, V, name='h1'),
                  'h1_0_semi': FenicsMatrixOperator(h1_0_mat, V, V, name='h1_0_semi')},

        time_stepper=ImplicitEulerTimeStepper(nt=NT),

        visualizer=FenicsVisualizer(FenicsVectorSpace(V))
    )

    return fom
コード例 #4
0
def discretize_instationary_cg(analytical_problem,
                               diameter=None,
                               domain_discretizer=None,
                               grid_type=None,
                               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 finite elements.

    Parameters
    ----------
    analytical_problem
        The |InstationaryProblem| to discretize.
    diameter
        If not `None`, `diameter` is passed as an argument 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 `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|.
    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.TimeStepperInterface>`
        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_cg(p.stationary_part,
                                       diameter=diameter,
                                       domain_discretizer=domain_discretizer,
                                       grid_type=grid_type,
                                       grid=grid,
                                       boundary_info=boundary_info)

    if p.initial_data.parametric:
        I = InterpolationOperator(data['grid'], p.initial_data)
    else:
        I = p.initial_data.evaluate(data['grid'].centers(data['grid'].dim))
        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)

    mass = m.l2_0_product

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

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

    return m, data
コード例 #5
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
コード例 #6
0
ファイル: parabolic.py プロジェクト: simon-ca/pymor
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
コード例 #7
0
ファイル: parabolic.py プロジェクト: simon-ca/pymor
def discretize_parabolic_cg(analytical_problem, diameter=None, domain_discretizer=None,
                           grid=None, boundary_info=None, num_values=None, time_stepper=None, nt=None):
    """Discretizes an |ParabolicProblem| using finite elements.

    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_cg(p.elliptic_part(), diameter=diameter, domain_discretizer=domain_discretizer,
        grid=grid, boundary_info=boundary_info)

    if p.initial_data.parametric:
        I = InterpolationOperator(data['grid'], p.initial_data)
    else:
        I = p.initial_data.evaluate(data['grid'].centers(data['grid'].dim))
        I = NumpyVectorArray(I, copy=False)

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

    mass = d.l2_0_product

    discretization = InstationaryDiscretization(operator=d.operator, rhs=d.rhs, mass=mass, 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='{}_CG'.format(p.name))

    return discretization, data
コード例 #8
0
ファイル: disk.py プロジェクト: weslowrie/pymor
def discretize_instationary_from_disk(parameter_file,
                                      T=None,
                                      steps=None,
                                      u0=None,
                                      time_stepper=None):
    """Load a linear affinely decomposed |InstationaryModel| from file.

    Similarly to :func:`discretize_stationary_from_disk`, the model is
    specified via an `ini.`-file of the following form ::

        [system-matrices]
        L_1.mat: l_1(μ_1,...,μ_n)
        L_2.mat: l_2(μ_1,...,μ_n)
        ...

        [rhs-vectors]
        F_1.mat: f_1(μ_1,...,μ_n)
        F_2.mat: f_2(μ_1,...,μ_n)
        ...

        [mass-matrix]
        D.mat

        [initial-solution]
        u0: u0.mat

        [parameter]
        μ_1: a_1,b_1
        ...
        μ_n: a_n,b_n

        [products]
        Prod1: P_1.mat
        Prod2: P_2.mat
        ...

        [time]
        T: final time
        steps: number of time steps


    Parameters
    ----------
    parameter_file
        Path to the '.ini' parameter file.
    T
        End-time of desired solution. If `None`, the value specified in the
        parameter file is used.
    steps
        Number of time steps to. If `None`, the value specified in the
        parameter file is used.
    u0
        Initial solution. If `None` the initial solution is obtained
        from parameter file.
    time_stepper
        The desired :class:`time stepper <pymor.algorithms.timestepping.TimeStepper>`
        to use. If `None`, implicit Euler time stepping is used.

    Returns
    -------
    m
        The |InstationaryModel| that has been generated.
    """
    assert ".ini" == parameter_file[-4:], "Given file is not an .ini file"
    assert os.path.isfile(parameter_file)
    base_path = os.path.dirname(parameter_file)

    # Get input from parameter file
    config = configparser.ConfigParser()
    config.optionxform = str
    config.read(parameter_file)

    # Assert that all needed entries given
    assert 'system-matrices' in config.sections()
    assert 'mass-matrix' in config.sections()
    assert 'rhs-vectors' in config.sections()
    assert 'parameter' in config.sections()

    system_mat = config.items('system-matrices')
    mass_mat = config.items('mass-matrix')
    rhs_vec = config.items('rhs-vectors')
    parameter = config.items('parameter')

    # Dict of parameters types and ranges
    parameter_type = {}
    parameter_range = {}

    # get parameters
    for i in range(len(parameter)):
        parameter_name = parameter[i][0]
        parameter_list = tuple(
            float(j) for j in parameter[i][1].replace(" ", "").split(','))
        parameter_range[parameter_name] = parameter_list
        # Assume scalar parameter dependence
        parameter_type[parameter_name] = 0

    # Create parameter space
    parameter_space = CubicParameterSpace(parameter_type=parameter_type,
                                          ranges=parameter_range)

    # Assemble operators
    system_operators, system_functionals = [], []

    # get parameter functionals and system matrices
    for i in range(len(system_mat)):
        path = os.path.join(base_path, system_mat[i][0])
        expr = system_mat[i][1]
        parameter_functional = ExpressionParameterFunctional(
            expr, parameter_type=parameter_type)
        system_operators.append(
            NumpyMatrixOperator.from_file(path,
                                          source_id='STATE',
                                          range_id='STATE'))
        system_functionals.append(parameter_functional)

    system_lincombOperator = LincombOperator(system_operators,
                                             coefficients=system_functionals)

    # get rhs vectors
    rhs_operators, rhs_functionals = [], []

    for i in range(len(rhs_vec)):
        path = os.path.join(base_path, rhs_vec[i][0])
        expr = rhs_vec[i][1]
        parameter_functional = ExpressionParameterFunctional(
            expr, parameter_type=parameter_type)
        op = NumpyMatrixOperator.from_file(path, range_id='STATE')
        assert isinstance(op.matrix, np.ndarray)
        op = op.with_(matrix=op.matrix.reshape((-1, 1)))
        rhs_operators.append(op)
        rhs_functionals.append(parameter_functional)

    rhs_lincombOperator = LincombOperator(rhs_operators,
                                          coefficients=rhs_functionals)

    # get mass matrix
    path = os.path.join(base_path, mass_mat[0][1])
    mass_operator = NumpyMatrixOperator.from_file(path,
                                                  source_id='STATE',
                                                  range_id='STATE')

    # Obtain initial solution if not given
    if u0 is None:
        u_0 = config.items('initial-solution')
        path = os.path.join(base_path, u_0[0][1])
        op = NumpyMatrixOperator.from_file(path, range_id='STATE')
        assert isinstance(op.matrix, np.ndarray)
        u0 = op.with_(matrix=op.matrix.reshape((-1, 1)))

    # get products if given
    if 'products' in config.sections():
        product = config.items('products')
        products = {}
        for i in range(len(product)):
            product_name = product[i][0]
            product_path = os.path.join(base_path, product[i][1])
            products[product_name] = NumpyMatrixOperator.from_file(
                product_path, source_id='STATE', range_id='STATE')
    else:
        products = None

    # Further specifications
    if 'time' in config.sections():
        if T is None:
            assert 'T' in config.options('time')
            T = float(config.get('time', 'T'))
        if steps is None:
            assert 'steps' in config.options('time')
            steps = int(config.get('time', 'steps'))

    # Use implicit euler time stepper if no time-stepper given
    if time_stepper is None:
        time_stepper = ImplicitEulerTimeStepper(steps)
    else:
        time_stepper = time_stepper(steps)

    # Create and return instationary model
    return InstationaryModel(operator=system_lincombOperator,
                             rhs=rhs_lincombOperator,
                             parameter_space=parameter_space,
                             initial_data=u0,
                             T=T,
                             time_stepper=time_stepper,
                             mass=mass_operator,
                             products=products)
コード例 #9
0
def make_pymor_bindings(V, dx, ds, solver_options):
    '''Assemble the Fenics operator and binds them to pymor.Operator with parameter separation
    Returns the full order model (pymor.Model)'''
    import pymor.basic as pmb
    from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator
    from pymor.algorithms.timestepping import ImplicitEulerTimeStepper

    space = FenicsVectorSpace(V)

    # Operators matrix
    u = df.TrialFunction(V)
    v = df.TestFunction(V)
    mass_mat = [
        df.assemble(df.inner(u, v) * dx(i)) for i in domain_dict.values()
    ]
    diff_mat = [
        df.assemble(df.inner(df.grad(u), df.grad(v)) * dx(i))
        for i in domain_dict.values()
    ]
    robin_left_mat = df.assemble(u * v * ds(1))
    source_mat = df.assemble(v * dx(domain_dict['die']))

    # Norms matrix
    l2_mat = df.assemble(df.inner(u, v) * df.dx)
    l2_0_mat = l2_mat.copy()
    h1_mat = df.assemble(df.inner(df.grad(u), df.grad(v)) * dx)
    h1_0_mat = h1_mat.copy()

    # Operators
    mass_op = [
        FenicsMatrixOperator(M, V, V, solver_options=solver_options)
        for M in mass_mat
    ]
    diff_op = [
        FenicsMatrixOperator(M, V, V, solver_options=solver_options)
        for M in diff_mat
    ]
    robin_left_op = FenicsMatrixOperator(robin_left_mat,
                                         V,
                                         V,
                                         solver_options=solver_options)
    source_op = pmb.VectorOperator(space.make_array([source_mat]))

    # Param projection
    project_lamb = [
        pmb.ProjectionParameterFunctional(f'lamb_{dom}', 1, 0)
        for dom in domain_dict.keys()
    ]
    project_capa = [
        pmb.ProjectionParameterFunctional(f'capa_{dom}', 1, 0)
        for dom in domain_dict.keys()
    ]

    # Separated operator
    mass = pmb.LincombOperator(mass_op, project_capa)

    op = pmb.LincombOperator(
        [*diff_op, robin_left_op],
        [*project_lamb,
         pmb.ExpressionParameterFunctional('h[0]', {'h': 1})])

    rhs = pmb.LincombOperator(
        [source_op], [pmb.ExpressionParameterFunctional('phi[0]', {'phi': 1})])

    end_time = 10 * 60
    dt = 5
    fom = InstationaryParametricMassModel(
        T=end_time,
        initial_data=space.make_array([df.project(df.Constant(0),
                                                  V).vector()]),
        operator=op,
        rhs=rhs,
        mass=mass,
        time_stepper=ImplicitEulerTimeStepper(end_time // dt),
        num_values=None,
        products={
            'l2': FenicsMatrixOperator(l2_mat, V, V),
            'l2_0': FenicsMatrixOperator(l2_0_mat, V, V),
            'h1': FenicsMatrixOperator(h1_mat, V, V),
            'h1_0_semi': FenicsMatrixOperator(h1_0_mat, V, V)
        },
        visualizer=None)
    return fom
コード例 #10
0
ファイル: disk.py プロジェクト: simon-ca/pymor
def discretize_instationary_from_disk(parameter_file, T=None, steps=None, u0=None, time_stepper=None):
    """Generates instationary discretization based on data given loaded from files.

    The path and further specifications to these objects are given in an '.ini'
    parameter file (see example below). Suitable for discrete problems given by::

        M(u(t), w) + L(u(t), w, t) = F(t, w)
                              u(0) = u_0

    for t in [0,T], where L is a linear time-dependent
    |Operator|, F is a time-dependent linear |Functional|, u_0 the
    initial data and w the parameter. The mass |Operator| M is assumed to be linear,
    time-independent and |Parameter|-independent.

    Parameters
    ----------
    parameter_file
        String containing the path to the '.ini' parameter file.
    T
        End-time of desired solution, if None obtained from parameter file
    steps
        Number of time steps to do, if None obtained from parameter file
    u0
        Initial solution, if None obtained from parameter file
    time_stepper
        The desired time_stepper to use, if None an Implicit euler scheme is used.

    Returns
    -------
    discretization
        The |Discretization| that has been generated.

    Example
    -------
    Following parameter file is suitable for a discrete parabolic problem with

    L(u(w), w) = (f_1(w)*K1 + f_2(w)*K2+...)*u, F(w) = g_1(w)*L1+g_2(w)*L2+..., M = D and
    u_0(w)=u0 with parameter w_i in [a_i,b_i], where f_i(w) and g_i(w) are strings of valid python
    expressions.

    Optional products can be provided to introduce a dict of inner products on the discrete space.
    Time specifications like T and steps can also be provided, but are optional when already given
    by call of this method. The content of the file is then given as::

        [system-matrices]
        # path_to_object: parameter_functional_associated_with_object
        K1.mat: f_1(w_1,...,w_n)
        K2.mat: f_2(w_1,...,w_n)
        ...

        [rhs-vectors]
        L1.mat: g_1(w_1,...,w_n)
        L2.mat: g_2(w_1,...,w_n)
        ...

        [mass-matrix]
        D.mat

        [initial-solution]
        u0: u0.mat

        [parameter]
        # Name: lower_bound,upper_bound
        w_1: a_1,b_1
        ...
        w_n: a_n,b_n

        [products]
        # Name: path_to_object
        Prod1: S.mat
        Prod2: T.mat
        ...

        [time]
        # fixed_Name: value
        T: 10.0
        steps: 100
    """
    assert ".ini" == parameter_file[-4:], "Given file is not an .ini file"
    base_path = os.path.dirname(parameter_file)

    # Get input from parameter file
    config = configparser.ConfigParser()
    config.optionxform = str
    config.read(parameter_file)

    # Assert that all needed entries given
    assert 'system-matrices' in config.sections()
    assert 'mass-matrix' in config.sections()
    assert 'rhs-vectors' in config.sections()
    assert 'parameter' in config.sections()

    system_mat = config.items('system-matrices')
    mass_mat = config.items('mass-matrix')
    rhs_vec = config.items('rhs-vectors')
    parameter = config.items('parameter')

    # Dict of parameters types and ranges
    parameter_type = {}
    parameter_range = {}

    # get parameters
    for i in range(len(parameter)):
        parameter_name = parameter[i][0]
        parameter_list = tuple(float(j) for j in parameter[i][1].replace(" ", "").split(','))
        parameter_range[parameter_name] = parameter_list
        # Assume scalar parameter dependence
        parameter_type[parameter_name] = 0

    # Create parameter space
    parameter_space = CubicParameterSpace(parameter_type=parameter_type, ranges=parameter_range)

    # Assemble operators
    system_operators, system_functionals = [], []

    # get parameter functionals and system matrices
    for i in range(len(system_mat)):
        path = os.path.join(base_path, system_mat[i][0])
        expr = system_mat[i][1]
        parameter_functional = ExpressionParameterFunctional(expr, parameter_type=parameter_type)
        system_operators.append(NumpyMatrixOperator.from_file(path))
        system_functionals.append(parameter_functional)

    system_lincombOperator = LincombOperator(system_operators, coefficients=system_functionals)

    # get rhs vectors
    rhs_operators, rhs_functionals = [], []

    for i in range(len(rhs_vec)):
        path = os.path.join(base_path, rhs_vec[i][0])
        expr = rhs_vec[i][1]
        parameter_functional = ExpressionParameterFunctional(expr, parameter_type=parameter_type)
        op = NumpyMatrixOperator.from_file(path)
        assert isinstance(op._matrix, np.ndarray)
        op = op.with_(matrix=op._matrix.reshape((1, -1)))
        rhs_operators.append(op)
        rhs_functionals.append(parameter_functional)

    rhs_lincombOperator = LincombOperator(rhs_operators, coefficients=rhs_functionals)

    # get mass matrix
    path = os.path.join(base_path, mass_mat[0][1])
    mass_operator = NumpyMatrixOperator.from_file(path)

    # Obtain initial solution if not given
    if u0 is None:
        u_0 = config.items('initial-solution')
        path = os.path.join(base_path, u_0[0][1])
        op = NumpyMatrixOperator.from_file(path)
        assert isinstance(op._matrix, np.ndarray)
        u0 = op.with_(matrix=op._matrix.reshape((-1, 1)))

    # get products if given
    if 'products' in config.sections():
        product = config.items('products')
        products = {}
        for i in range(len(product)):
            product_name = product[i][0]
            product_path = os.path.join(base_path, product[i][1])
            products[product_name] = NumpyMatrixOperator.from_file(product_path)
    else:
        products = None

    # Further specifications
    if 'time' in config.sections():
        if T is None:
            assert 'T' in config.options('time')
            T = float(config.get('time', 'T'))
        if steps is None:
            assert 'steps' in config.options('time')
            steps = int(config.get('time', 'steps'))

    # Use implicit euler time stepper if no time-stepper given
    if time_stepper is None:
        time_stepper = ImplicitEulerTimeStepper(steps)
    else:
        time_stepper = time_stepper(steps)

    # Create and return instationary discretization
    return InstationaryDiscretization(operator=system_lincombOperator, rhs=rhs_lincombOperator,
                                      parameter_space=parameter_space, initial_data=u0, T=T,
                                      time_stepper=time_stepper, mass=mass_operator, products=products)
コード例 #11
0
def reductor(discretization,
             RB,
             vector_product=None,
             disable_caching=True,
             extends=None):
    if RB is None:
        RB = [
            stat_blocked_disc.local_operator(ss).source.empty()
            for ss in np.arange(stat_blocked_disc.num_subdomains)
        ]
    rd, rc, reduction_data = reduce_generic_rb(stat_blocked_disc, RB,
                                               vector_product, disable_caching,
                                               extends)

    def unblock_op(op):
        assert op._blocks[0][0] is not None
        if isinstance(op._blocks[0][0], LincombOperator):
            coefficients = op._blocks[0][0].coefficients
            operators = [
                None for kk in np.arange(len(op._blocks[0][0].operators))
            ]
            for kk in np.arange(len(op._blocks[0][0].operators)):
                ops = [[
                    op._blocks[ii][jj].operators[kk]
                    if op._blocks[ii][jj] is not None else None
                    for jj in np.arange(op.num_source_blocks)
                ] for ii in np.arange(op.num_range_blocks)]
                operators[kk] = unblock_op(BlockOperator(ops))
            return LincombOperator(operators=operators,
                                   coefficients=coefficients)
        else:
            assert all(
                all([
                    isinstance(block, NumpyMatrixOperator
                               ) if block is not None else True
                    for block in row
                ]) for row in op._blocks)
            if op.source.dim == 0 and op.range.dim == 0:
                return NumpyMatrixOperator(np.zeros((0, 0)))
            elif op.source.dim == 1:
                mat = np.concatenate([
                    op._blocks[ii][0]._matrix
                    for ii in np.arange(op.num_range_blocks)
                ],
                                     axis=1)
            elif op.range.dim == 1:
                mat = np.concatenate([
                    op._blocks[0][jj]._matrix
                    for jj in np.arange(op.num_source_blocks)
                ],
                                     axis=1)
            else:
                mat = bmat([[
                    coo_matrix(op._blocks[ii][jj]._matrix)
                    if op._blocks[ii][jj] is not None else coo_matrix(
                        (op._range_dims[ii], op._source_dims[jj]))
                    for jj in np.arange(op.num_source_blocks)
                ] for ii in np.arange(op.num_range_blocks)]).toarray()
            return NumpyMatrixOperator(mat)

    reduced_op = unblock_op(rd.operator)
    reduced_rhs = unblock_op(rd.rhs)
    return (InstationaryDiscretization(
        T=config['end_time'],
        initial_data=reduced_op.source.zeros(1),
        operator=reduced_op,
        rhs=unblock_op(rd.rhs),
        mass=unblock_op(rd.products['l2']),
        time_stepper=ImplicitEulerTimeStepper(config['nt']),
        products={
            kk: unblock_op(rd.products[kk])
            for kk in rd.products.keys()
        },
        operators={
            kk: unblock_op(rd.operators[kk])
            for kk in rd.operators.keys() if kk != 'operator'
        },
        functionals={
            kk: unblock_op(rd.functionals[kk])
            for kk in rd.functionals.keys() if kk != 'rhs'
        },
        vector_operators={
            kk: unblock_op(rd.vector_operators[kk])
            for kk in rd.vector_operators.keys()
        },
        parameter_space=rd.parameter_space,
        cache_region='disk',
        name='reduced non-blocked discretization'),
            Reconstructor(stat_blocked_disc, RB), reduction_data)
コード例 #12
0
    stat_blocked_disc.num_subdomains))
logger.info('  discretization has {} DoFs'.format(
    stat_nonblocked_disc.solution_space.dim))
logger.info('  parameter type is {}'.format(
    stat_nonblocked_disc.parameter_type))
# logger.info('visualizing grid and data functions ...')
# example.visualize(problem_cfg.get_str('type'))

nonblocked_disc = InstationaryDiscretization(
    T=config['end_time'],
    initial_data=make_listvectorarray(
        wrapper[stat_nonblocked_disc._impl.create_vector()]),
    operator=stat_nonblocked_disc.operator,
    rhs=stat_nonblocked_disc.rhs,
    mass=stat_nonblocked_disc.products['l2'],
    time_stepper=ImplicitEulerTimeStepper(
        config['nt'], invert_options=solver_options.get_str('type')),
    products=stat_nonblocked_disc.products,
    operators=stat_nonblocked_disc.operators,
    functionals=stat_nonblocked_disc.functionals,
    vector_operators=stat_nonblocked_disc.vector_operators,
    visualizer=InstationaryDuneVisualizer(
        stat_nonblocked_disc,
        problem_cfg.get_str('type') + '.solution'),
    parameter_space=CubicParameterSpace(stat_nonblocked_disc.parameter_type,
                                        0.1, 10),
    cache_region='disk',
    name='detailed non-blocked discretization')

# mu = 0.6
# U = nonblocked_disc.solve(mu)
# logger.info('visualizing trajectory ...')
コード例 #13
0
def discretize(grid_and_problem_data, T, nt):
    d, d_data = discretize_ell(grid_and_problem_data)
    assert isinstance(d.parameter_space, CubicParameterSpace)
    parameter_range = grid_and_problem_data['parameter_range']
    block_space = d_data['block_space']
    # assemble global L2 product
    l2_mat = d.global_operator.operators[0].matrix.copy(
    )  # to ensure matching pattern
    l2_mat.scal(0.)
    for ii in range(block_space.num_blocks):
        local_l2_product = d.l2_product._blocks[ii, ii]
        block_space.mapper.copy_local_to_global(
            local_l2_product.matrix, local_l2_product.matrix.pattern(), ii,
            l2_mat)
    mass = d.l2_product
    operators = {
        k: v
        for k, v in d.operators.items() if k not in d.special_operators
    }
    global_mass = DuneXTMatrixOperator(l2_mat)

    local_div_ops, local_l2_products, local_projections, local_rt_projections = \
        d_data['local_div_ops'], d_data['local_l2_products'], d_data['local_projections'], d_data['local_rt_projections']

    for ii in range(d_data['grid'].num_subdomains):

        local_div = Concatenation(
            [local_div_ops[ii], local_rt_projections[ii]])

        operators['r_ud_{}'.format(ii)] = \
            Concatenation([local_projections[ii].T, local_l2_products[ii], local_div], name='r_ud_{}'.format(ii))

        operators['r_l2_{}'.format(ii)] = \
            Concatenation([local_projections[ii].T, local_l2_products[ii], local_projections[ii]],
                          name='r_l2_{}'.format(ii))

    e = d.estimator
    estimator = ParabolicEstimator(e.min_diffusion_evs, e.subdomain_diameters,
                                   e.local_eta_rf_squared, e.lambda_coeffs,
                                   e.mu_bar, e.mu_hat, e.flux_reconstruction,
                                   e.oswald_interpolation_error)

    d = InstationaryDuneDiscretization(
        d.global_operator,
        d.global_rhs,
        global_mass,
        T,
        d.operator.source.zeros(1),
        d.operator,
        d.rhs,
        mass=mass,
        time_stepper=ImplicitEulerTimeStepper(nt=nt,
                                              solver_options='operator'),
        products=d.products,
        operators=operators,
        estimator=estimator,
        visualizer=DuneGDTVisualizer(block_space))
    d = d.with_(parameter_space=CubicParameterSpace(
        d.parameter_type, parameter_range[0], parameter_range[1]))

    return d, d_data
コード例 #14
0
def reductor(config,
             detailed_data,
             discretization,
             RB,
             vector_product=None,
             disable_caching=True,
             extends=None):
    elliptic_disc = detailed_data['elliptic_disc']
    elliptic_LRBMS_disc = detailed_data['elliptic_LRBMS_disc']
    T = config['end_time']
    nt = config['nt']
    if RB is None:
        RB = [
            elliptic_LRBMS_disc.local_operator(ss).source.empty()
            for ss in np.arange(elliptic_LRBMS_disc.num_subdomains)
        ]
    rd, rc, reduction_data = reduce_generic_rb(elliptic_LRBMS_disc, RB,
                                               vector_product, disable_caching,
                                               extends)
    rc = Reconstructor(elliptic_LRBMS_disc, RB)

    def unblock_op(op, sparse=False):
        assert op._blocks[0][0] is not None
        if isinstance(op._blocks[0][0], LincombOperator):
            coefficients = op._blocks[0][0].coefficients
            operators = [
                None for kk in np.arange(len(op._blocks[0][0].operators))
            ]
            for kk in np.arange(len(op._blocks[0][0].operators)):
                ops = [[
                    op._blocks[ii][jj].operators[kk]
                    if op._blocks[ii][jj] is not None else None
                    for jj in np.arange(op.num_source_blocks)
                ] for ii in np.arange(op.num_range_blocks)]
                operators[kk] = unblock_op(BlockOperator(ops))
            return LincombOperator(operators=operators,
                                   coefficients=coefficients)
        else:
            assert all(
                all([
                    isinstance(block, NumpyMatrixOperator
                               ) if block is not None else True
                    for block in row
                ]) for row in op._blocks)
            if op.source.dim == 0 and op.range.dim == 0:
                return NumpyMatrixOperator(np.zeros((0, 0)))
            elif op.source.dim == 1:
                mat = np.concatenate([
                    op._blocks[ii][0]._matrix
                    for ii in np.arange(op.num_range_blocks)
                ],
                                     axis=1)
            elif op.range.dim == 1:
                mat = np.concatenate([
                    op._blocks[0][jj]._matrix
                    for jj in np.arange(op.num_source_blocks)
                ],
                                     axis=1)
            else:
                mat = bmat([[
                    coo_matrix(op._blocks[ii][jj]._matrix)
                    if op._blocks[ii][jj] is not None else coo_matrix(
                        (op._range_dims[ii], op._source_dims[jj]))
                    for jj in np.arange(op.num_source_blocks)
                ] for ii in np.arange(op.num_range_blocks)])
                mat = mat.toarray()
            return NumpyMatrixOperator(mat)

    reduced_op = unblock_op(rd.operator, True)
    reduced_rhs = unblock_op(rd.rhs)
    estimator = ReducedAgainstWeak(
        rc, detailed_data['example'], detailed_data['wrapper'],
        detailed_data['bochner_norms']['elliptic_penalty'],
        detailed_data['space_products']['l2'], T, detailed_data['mu_min'],
        detailed_data['mu_max'], detailed_data['mu_hat'],
        detailed_data['mu_bar'], detailed_data['mu_tilde'])
    return (InstationaryDiscretization(
        T=T,
        initial_data=reduced_op.source.zeros(1),
        operator=reduced_op,
        rhs=unblock_op(rd.rhs),
        mass=unblock_op(rd.products['l2']),
        time_stepper=ImplicitEulerTimeStepper(nt),
        products={
            kk: unblock_op(rd.products[kk])
            for kk in rd.products.keys()
        },
        operators={
            kk: unblock_op(rd.operators[kk])
            for kk in rd.operators.keys() if kk != 'operator'
        },
        functionals={
            kk: unblock_op(rd.functionals[kk])
            for kk in rd.functionals.keys() if kk != 'rhs'
        },
        vector_operators={
            kk: unblock_op(rd.vector_operators[kk])
            for kk in rd.vector_operators.keys()
        },
        parameter_space=rd.parameter_space,
        estimator=estimator,
        cache_region='disk',
        name='reduced discretization ({} DoFs)'.format(reduced_op.source.dim)),
            rc, reduction_data)
コード例 #15
0
def discretize(num_elements,
               num_partitions,
               T,
               nt,
               initial_data,
               parameter_range,
               name='detailed discretization'):
    Example = examples[2]['aluconformgrid']['fem']['istl']

    logger_cfg = Example.logger_options()
    logger_cfg.set('info', -1, True)
    logger_cfg.set('info_color', 'blue', True)

    grid_cfg = Example.grid_options('grid.multiscale.provider.cube')
    grid_cfg.set('lower_left', '[0 0]', True)
    grid_cfg.set('upper_right', '[5 1]', True)
    grid_cfg.set('num_elements', num_elements, True)
    grid_cfg.set('num_partitions', num_partitions, True)

    boundary_cfg = Example.boundary_options(
        'stuff.grid.boundaryinfo.alldirichlet')

    problem_cfg = Example.problem_options(
        'hdd.linearelliptic.problem.OS2015.spe10model1')
    problem_cfg.set('parametric_channel', 'true', True)
    problem_cfg.set('channel_boundary_layer', '0', True)
    problem_cfg.set('filename', 'perm_case1.dat', True)
    problem_cfg.set('lower_left', '[0 0]', True)
    problem_cfg.set('upper_right', '[5 1]', True)
    problem_cfg.set('num_elements', '[100 20]', True)
    problem_cfg.set('forces.0.domain', '[0.95 1.10; 0.30 0.45]', True)
    problem_cfg.set('forces.0.value', '2000', True)
    problem_cfg.set('forces.1.domain', '[3.00 3.15; 0.75 0.90]', True)
    problem_cfg.set('forces.1.value', '-1000', True)
    problem_cfg.set('forces.2.domain', '[4.25 4.40; 0.25 0.40]', True)
    problem_cfg.set('forces.2.value', '-1000', True)
    problem_cfg.set('channel.0.value', '-1.07763239495', True)
    problem_cfg.set('channel.1.value', '-1.07699512772', True)
    problem_cfg.set('channel.2.value', '-1.07356156439', True)
    problem_cfg.set('channel.3.value', '-1.06602281736', True)
    problem_cfg.set('channel.4.value', '-1.06503683743', True)
    problem_cfg.set('channel.5.value', '-1.07974870426', True)
    problem_cfg.set('channel.6.value', '-1.05665895923', True)
    problem_cfg.set('channel.7.value', '-1.08310334837', True)
    problem_cfg.set('channel.8.value', '-1.05865484973', True)
    problem_cfg.set('channel.9.value', '-1.05871039535', True)
    problem_cfg.set('channel.10.value', '-1.08136695901', True)
    problem_cfg.set('channel.11.value', '-1.08490172721', True)
    problem_cfg.set('channel.12.value', '-1.06641120758', True)
    problem_cfg.set('channel.13.value', '-1.06812773298', True)
    problem_cfg.set('channel.14.value', '-1.07695652049', True)
    problem_cfg.set('channel.15.value', '-1.08630079205', True)
    problem_cfg.set('channel.16.value', '-1.08273722112', True)
    problem_cfg.set('channel.17.value', '-1.07500402155', True)
    problem_cfg.set('channel.18.value', '-1.08607142562', True)
    problem_cfg.set('channel.19.value', '-1.07268761799', True)
    problem_cfg.set('channel.20.value', '-1.08537037362', True)
    problem_cfg.set('channel.21.value', '-1.08466927273', True)
    problem_cfg.set('channel.22.value', '-1.08444661815', True)
    problem_cfg.set('channel.23.value', '-1.08957037967', True)
    problem_cfg.set('channel.24.value', '-1.08047394052', True)
    problem_cfg.set('channel.25.value', '-1.08221229083', True)
    problem_cfg.set('channel.26.value', '-1.08568599863', True)
    problem_cfg.set('channel.27.value', '-1.08428347872', True)
    problem_cfg.set('channel.28.value', '-1.09104098734', True)
    problem_cfg.set('channel.29.value', '-1.09492700673', True)
    problem_cfg.set('channel.30.value', '-1.09760440537', True)
    problem_cfg.set('channel.31.value', '-1.09644989453', True)
    problem_cfg.set('channel.32.value', '-1.09441681025', True)
    problem_cfg.set('channel.33.value', '-1.09533290654', True)
    problem_cfg.set('channel.34.value', '-1.1001430808', True)
    problem_cfg.set('channel.35.value', '-1.10065627621', True)
    problem_cfg.set('channel.36.value', '-1.10125877186', True)
    problem_cfg.set('channel.37.value', '-1.10057485893', True)
    problem_cfg.set('channel.38.value', '-1.10002261906', True)
    problem_cfg.set('channel.39.value', '-1.10219154209', True)
    problem_cfg.set('channel.40.value', '-1.09994463801', True)
    problem_cfg.set('channel.41.value', '-1.10265630533', True)
    problem_cfg.set('channel.42.value', '-1.10448566526', True)
    problem_cfg.set('channel.43.value', '-1.10735820121', True)
    problem_cfg.set('channel.44.value', '-1.1070022367', True)
    problem_cfg.set('channel.45.value', '-1.10777650387', True)
    problem_cfg.set('channel.46.value', '-1.10892785562', True)
    problem_cfg.set('channel.0.domain', '[1.7 1.75; 0.5 0.55]', True)
    problem_cfg.set('channel.1.domain', '[1.75 1.8; 0.5 0.55]', True)
    problem_cfg.set('channel.2.domain', '[1.8 1.85; 0.5 0.55]', True)
    problem_cfg.set('channel.3.domain', '[1.85 1.9; 0.5 0.55]', True)
    problem_cfg.set('channel.4.domain', '[1.9 1.95; 0.5 0.55]', True)
    problem_cfg.set('channel.5.domain', '[1.95 2.0; 0.5 0.55]', True)
    problem_cfg.set('channel.6.domain', '[2.0 2.05; 0.5 0.55]', True)
    problem_cfg.set('channel.7.domain', '[2.05 2.1; 0.5 0.55]', True)
    problem_cfg.set('channel.8.domain', '[2.1 2.15; 0.5 0.55]', True)
    problem_cfg.set('channel.9.domain', '[2.15 2.2; 0.5 0.55]', True)
    problem_cfg.set('channel.10.domain', '[2.2 2.25; 0.5 0.55]', True)
    problem_cfg.set('channel.11.domain', '[2.25 2.3; 0.5 0.55]', True)
    problem_cfg.set('channel.12.domain', '[2.3 2.35; 0.5 0.55]', True)
    problem_cfg.set('channel.13.domain', '[2.35 2.4; 0.5 0.55]', True)
    problem_cfg.set('channel.14.domain', '[2.4 2.45; 0.5 0.55]', True)
    problem_cfg.set('channel.15.domain', '[2.45 2.5; 0.5 0.55]', True)
    problem_cfg.set('channel.16.domain', '[2.5 2.55; 0.5 0.55]', True)
    problem_cfg.set('channel.17.domain', '[2.55 2.6; 0.5 0.55]', True)
    problem_cfg.set('channel.18.domain', '[2.6 2.65; 0.5 0.55]', True)
    problem_cfg.set('channel.19.domain', '[2.65 2.7; 0.5 0.55]', True)
    problem_cfg.set('channel.20.domain', '[2.7 2.75; 0.5 0.55]', True)
    problem_cfg.set('channel.21.domain', '[2.75 2.8; 0.5 0.55]', True)
    problem_cfg.set('channel.22.domain', '[2.8 2.85; 0.5 0.55]', True)
    problem_cfg.set('channel.23.domain', '[2.85 2.9; 0.5 0.55]', True)
    problem_cfg.set('channel.24.domain', '[2.9 2.95; 0.5 0.55]', True)
    problem_cfg.set('channel.25.domain', '[2.95 3.0; 0.5 0.55]', True)
    problem_cfg.set('channel.26.domain', '[3.0 3.05; 0.5 0.55]', True)
    problem_cfg.set('channel.27.domain', '[3.05 3.1; 0.5 0.55]', True)
    problem_cfg.set('channel.28.domain', '[3.1 3.15; 0.5 0.55]', True)
    problem_cfg.set('channel.29.domain', '[3.15 3.2; 0.5 0.55]', True)
    problem_cfg.set('channel.30.domain', '[3.2 3.25; 0.5 0.55]', True)
    problem_cfg.set('channel.31.domain', '[3.25 3.3; 0.5 0.55]', True)
    problem_cfg.set('channel.32.domain', '[3.3 3.35; 0.5 0.55]', True)
    problem_cfg.set('channel.33.domain', '[3.35 3.4; 0.5 0.55]', True)
    problem_cfg.set('channel.34.domain', '[3.4 3.45; 0.5 0.55]', True)
    problem_cfg.set('channel.35.domain', '[3.45 3.5; 0.5 0.55]', True)
    problem_cfg.set('channel.36.domain', '[3.5 3.55; 0.5 0.55]', True)
    problem_cfg.set('channel.37.domain', '[3.55 3.6; 0.5 0.55]', True)
    problem_cfg.set('channel.38.domain', '[3.6 3.65; 0.5 0.55]', True)
    problem_cfg.set('channel.39.domain', '[3.65 3.7; 0.5 0.55]', True)
    problem_cfg.set('channel.40.domain', '[3.7 3.75; 0.5 0.55]', True)
    problem_cfg.set('channel.41.domain', '[3.75 3.8; 0.5 0.55]', True)
    problem_cfg.set('channel.42.domain', '[3.8 3.85; 0.5 0.55]', True)
    problem_cfg.set('channel.43.domain', '[3.85 3.9; 0.5 0.55]', True)
    problem_cfg.set('channel.44.domain', '[3.9 3.95; 0.5 0.55]', True)
    problem_cfg.set('channel.45.domain', '[3.95 4.0; 0.5 0.55]', True)
    problem_cfg.set('channel.46.domain', '[4.0 4.05; 0.5 0.55]', True)
    problem_cfg.set('channel.47.value', '-1.10372589211', True)
    problem_cfg.set('channel.48.value', '-1.1020889988', True)
    problem_cfg.set('channel.49.value', '-1.09806955069', True)
    problem_cfg.set('channel.50.value', '-1.10000902421', True)
    problem_cfg.set('channel.51.value', '-1.08797468724', True)
    problem_cfg.set('channel.52.value', '-1.08827472176', True)
    problem_cfg.set('channel.53.value', '-1.08692237109', True)
    problem_cfg.set('channel.54.value', '-1.07893190093', True)
    problem_cfg.set('channel.55.value', '-1.08748373853', True)
    problem_cfg.set('channel.56.value', '-1.07445197324', True)
    problem_cfg.set('channel.57.value', '-1.08246613163', True)
    problem_cfg.set('channel.58.value', '-1.06726790504', True)
    problem_cfg.set('channel.59.value', '-1.07891217847', True)
    problem_cfg.set('channel.60.value', '-1.07260827126', True)
    problem_cfg.set('channel.61.value', '-1.07094062748', True)
    problem_cfg.set('channel.62.value', '-1.0692399429', True)
    problem_cfg.set('channel.63.value', '-1.00099885701', True)
    problem_cfg.set('channel.64.value', '-1.00109544002', True)
    problem_cfg.set('channel.65.value', '-0.966491003242', True)
    problem_cfg.set('channel.66.value', '-0.802284684014', True)
    problem_cfg.set('channel.67.value', '-0.980790923021', True)
    problem_cfg.set('channel.68.value', '-0.614478271687', True)
    problem_cfg.set('channel.69.value', '-0.288129858959', True)
    problem_cfg.set('channel.70.value', '-0.929509396842', True)
    problem_cfg.set('channel.71.value', '-0.992376505995', True)
    problem_cfg.set('channel.72.value', '-0.968162494855', True)
    problem_cfg.set('channel.73.value', '-0.397316938901', True)
    problem_cfg.set('channel.74.value', '-0.970934956609', True)
    problem_cfg.set('channel.75.value', '-0.784344730096', True)
    problem_cfg.set('channel.76.value', '-0.539725422323', True)
    problem_cfg.set('channel.77.value', '-0.915632282372', True)
    problem_cfg.set('channel.78.value', '-0.275089177273', True)
    problem_cfg.set('channel.79.value', '-0.949684959286', True)
    problem_cfg.set('channel.80.value', '-0.936132529794', True)
    problem_cfg.set('channel.47.domain', '[2.6 2.65; 0.45 0.50]', True)
    problem_cfg.set('channel.48.domain', '[2.65 2.7; 0.45 0.50]', True)
    problem_cfg.set('channel.49.domain', '[2.7 2.75; 0.45 0.50]', True)
    problem_cfg.set('channel.50.domain', '[2.75 2.8; 0.45 0.50]', True)
    problem_cfg.set('channel.51.domain', '[2.8 2.85; 0.45 0.50]', True)
    problem_cfg.set('channel.52.domain', '[2.85 2.9; 0.45 0.50]', True)
    problem_cfg.set('channel.53.domain', '[2.9 2.95; 0.45 0.50]', True)
    problem_cfg.set('channel.54.domain', '[2.95 3.0; 0.45 0.50]', True)
    problem_cfg.set('channel.55.domain', '[3.0 3.05; 0.45 0.50]', True)
    problem_cfg.set('channel.56.domain', '[3.05 3.1; 0.45 0.50]', True)
    problem_cfg.set('channel.57.domain', '[3.1 3.15; 0.45 0.50]', True)
    problem_cfg.set('channel.58.domain', '[3.15 3.2; 0.45 0.50]', True)
    problem_cfg.set('channel.59.domain', '[3.2 3.25; 0.45 0.50]', True)
    problem_cfg.set('channel.60.domain', '[3.25 3.3; 0.45 0.50]', True)
    problem_cfg.set('channel.61.domain', '[3.3 3.35; 0.45 0.50]', True)
    problem_cfg.set('channel.62.domain', '[3.35 3.4; 0.45 0.50]', True)
    problem_cfg.set('channel.63.domain', '[3.4 3.45; 0.45 0.50]', True)
    problem_cfg.set('channel.64.domain', '[3.45 3.5; 0.45 0.50]', True)
    problem_cfg.set('channel.65.domain', '[3.5 3.55; 0.45 0.50]', True)
    problem_cfg.set('channel.66.domain', '[3.55 3.6; 0.45 0.50]', True)
    problem_cfg.set('channel.67.domain', '[3.6 3.65; 0.45 0.50]', True)
    problem_cfg.set('channel.68.domain', '[3.65 3.7; 0.45 0.50]', True)
    problem_cfg.set('channel.69.domain', '[3.7 3.75; 0.45 0.50]', True)
    problem_cfg.set('channel.70.domain', '[3.75 3.8; 0.45 0.50]', True)
    problem_cfg.set('channel.71.domain', '[3.8 3.85; 0.45 0.50]', True)
    problem_cfg.set('channel.72.domain', '[3.85 3.9; 0.45 0.50]', True)
    problem_cfg.set('channel.73.domain', '[3.9 3.95; 0.45 0.50]', True)
    problem_cfg.set('channel.74.domain', '[3.95 4.0; 0.45 0.50]', True)
    problem_cfg.set('channel.75.domain', '[4.0 4.05; 0.45 0.50]', True)
    problem_cfg.set('channel.76.domain', '[4.05 4.1; 0.45 0.50]', True)
    problem_cfg.set('channel.77.domain', '[4.1 4.15; 0.45 0.50]', True)
    problem_cfg.set('channel.78.domain', '[4.15 4.2; 0.45 0.50]', True)
    problem_cfg.set('channel.79.domain', '[4.2 4.25; 0.45 0.50]', True)
    problem_cfg.set('channel.80.domain', '[4.25 4.3; 0.45 0.50]', True)
    problem_cfg.set('channel.81.value', '-1.10923642795', True)
    problem_cfg.set('channel.82.value', '-1.10685618623', True)
    problem_cfg.set('channel.83.value', '-1.1057800376', True)
    problem_cfg.set('channel.84.value', '-1.10187723629', True)
    problem_cfg.set('channel.85.value', '-1.10351710464', True)
    problem_cfg.set('channel.86.value', '-1.10037551137', True)
    problem_cfg.set('channel.87.value', '-1.09724407076', True)
    problem_cfg.set('channel.88.value', '-1.09604600208', True)
    problem_cfg.set('channel.89.value', '-1.09354469656', True)
    problem_cfg.set('channel.90.value', '-1.08934455354', True)
    problem_cfg.set('channel.91.value', '-1.08155476586', True)
    problem_cfg.set('channel.92.value', '-1.07815397899', True)
    problem_cfg.set('channel.93.value', '-1.09174062023', True)
    problem_cfg.set('channel.94.value', '-1.07433616068', True)
    problem_cfg.set('channel.95.value', '-1.08030587701', True)
    problem_cfg.set('channel.81.domain', '[1.95 2.0; 0.40 0.45]', True)
    problem_cfg.set('channel.82.domain', '[2.0 2.05; 0.40 0.45]', True)
    problem_cfg.set('channel.83.domain', '[2.05 2.1; 0.40 0.45]', True)
    problem_cfg.set('channel.84.domain', '[2.1 2.15; 0.40 0.45]', True)
    problem_cfg.set('channel.85.domain', '[2.15 2.2; 0.40 0.45]', True)
    problem_cfg.set('channel.86.domain', '[2.2 2.25; 0.40 0.45]', True)
    problem_cfg.set('channel.87.domain', '[2.25 2.3; 0.40 0.45]', True)
    problem_cfg.set('channel.88.domain', '[2.3 2.35; 0.40 0.45]', True)
    problem_cfg.set('channel.89.domain', '[2.35 2.4; 0.40 0.45]', True)
    problem_cfg.set('channel.90.domain', '[2.4 2.45; 0.40 0.45]', True)
    problem_cfg.set('channel.91.domain', '[2.45 2.5; 0.40 0.45]', True)
    problem_cfg.set('channel.92.domain', '[2.5 2.55; 0.40 0.45]', True)
    problem_cfg.set('channel.93.domain', '[2.55 2.6; 0.40 0.45]', True)
    problem_cfg.set('channel.94.domain', '[2.6 2.65; 0.40 0.45]', True)
    problem_cfg.set('channel.95.domain', '[2.65 2.7; 0.40 0.45]', True)
    problem_cfg.set('channel.96.value', '-1.00032869407', True)
    problem_cfg.set('channel.97.value', '-1.01175908905', True)
    problem_cfg.set('channel.98.value', '-1.04954395793', True)
    problem_cfg.set('channel.99.value', '-1.017967697', True)
    problem_cfg.set('channel.100.value', '-1.04647184091', True)
    problem_cfg.set('channel.101.value', '-1.01911894831', True)
    problem_cfg.set('channel.102.value', '-1.00699340158', True)
    problem_cfg.set('channel.103.value', '-0.995492960025', True)
    problem_cfg.set('channel.104.value', '-1.0373059007', True)
    problem_cfg.set('channel.96.domain', '[2.25 2.3; 0.35 0.40]', True)
    problem_cfg.set('channel.97.domain', '[2.3 2.35; 0.35 0.40]', True)
    problem_cfg.set('channel.98.domain', '[2.35 2.4; 0.35 0.40]', True)
    problem_cfg.set('channel.99.domain', '[2.4 2.45; 0.35 0.40]', True)
    problem_cfg.set('channel.100.domain', '[2.45 2.5; 0.35 0.40]', True)
    problem_cfg.set('channel.101.domain', '[2.5 2.55; 0.35 0.40]', True)
    problem_cfg.set('channel.102.domain', '[2.55 2.6; 0.35 0.40]', True)
    problem_cfg.set('channel.103.domain', '[2.6 2.65; 0.35 0.40]', True)
    problem_cfg.set('channel.104.domain', '[2.65 2.7; 0.35 0.4]', True)

    example = Example(logger_cfg, grid_cfg, boundary_cfg, problem_cfg,
                      ['l2', 'h1', 'elliptic_penalty'])

    elliptic_LRBMS_disc = wrapper[example.discretization()]
    parameter_space = CubicParameterSpace(elliptic_LRBMS_disc.parameter_type,
                                          parameter_range[0],
                                          parameter_range[1])
    elliptic_LRBMS_disc = elliptic_LRBMS_disc.with_(
        parameter_space=parameter_space)
    elliptic_disc = elliptic_LRBMS_disc.as_nonblocked().with_(
        parameter_space=parameter_space)

    def prolong(coarse_disc, coarse_U):
        time_grid_ref = OnedGrid(domain=(0., T), num_intervals=nt)
        time_grid = OnedGrid(domain=(0., T), num_intervals=(len(coarse_U) - 1))
        U_fine = [None for ii in time_grid_ref.centers(1)]
        for n in np.arange(len(time_grid_ref.centers(1))):
            t_n = time_grid_ref.centers(1)[n]
            coarse_entity = min((time_grid.centers(1) <= t_n).nonzero()[0][-1],
                                time_grid.size(0) - 1)
            a = time_grid.centers(1)[coarse_entity]
            b = time_grid.centers(1)[coarse_entity + 1]
            SF = np.array((1. / (a - b) * t_n - b / (a - b),
                           1. / (b - a) * t_n - a / (b - a)))
            U_t = coarse_U.copy(ind=coarse_entity)
            U_t.scal(SF[0][0])
            U_t.axpy(SF[1][0], coarse_U, x_ind=(coarse_entity + 1))
            U_fine[n] = wrapper[example.prolong(coarse_disc._impl,
                                                U_t._list[0]._impl)]
        return make_listvectorarray(U_fine)

    if isinstance(initial_data, str):
        initial_data = make_listvectorarray(
            wrapper[example.project(initial_data)])
        # initial_data = elliptic_disc.operator.apply_inverse(initial_data, mu=(1, 1))
    else:
        coarse_disc = initial_data[0]
        initial_data = initial_data[1]
        assert len(initial_data) == 1
        initial_data = example.prolong(coarse_disc._impl,
                                       initial_data._list[0]._impl)
        initial_data = make_listvectorarray(wrapper[initial_data])

    parabolic_disc = InstationaryDiscretization(
        T=T,
        initial_data=initial_data,
        operator=elliptic_disc.operator,
        rhs=elliptic_disc.rhs,
        mass=elliptic_disc.products['l2'],
        time_stepper=ImplicitEulerTimeStepper(nt, solver_options='operator'),
        products=elliptic_disc.products,
        operators=elliptic_disc.operators,
        functionals=elliptic_disc.functionals,
        vector_operators=elliptic_disc.vector_operators,
        visualizer=InstationaryDuneVisualizer(elliptic_disc,
                                              'dune_discretization.solution'),
        parameter_space=parameter_space,
        cache_region='disk',
        name='{} ({} DoFs)'.format(name, elliptic_disc.solution_space.dim))

    return {
        'example': example,
        'initial_data': initial_data,
        'wrapper': wrapper,
        'elliptic_LRBMS_disc': elliptic_LRBMS_disc,
        'elliptic_disc': elliptic_disc,
        'parabolic_disc': parabolic_disc,
        'prolongator': prolong
    }