Example #1
0
 def indicator_factory(dd, bt):
     def indicator(X):
         L = np.logical_and(float_cmp(X[:, 0], dd.domain[0]), dd.left == bt)
         R = np.logical_and(float_cmp(X[:, 0], dd.domain[1]), dd.right == bt)
         return np.logical_or(L, R)
     inject_sid(indicator, indicator_id, dd, bt)
     return indicator
Example #2
0
 def indicator_factory(dd, bt):
     def indicator(X):
         T = np.logical_and(float_cmp(X[:, 1], dd.domain[1, 1]), dd.top == bt)
         B = np.logical_and(float_cmp(X[:, 1], dd.domain[0, 1]), dd.bottom == bt)
         TB = np.logical_or(T, B)
         return TB
     inject_sid(indicator, indicator_id, dd, bt)
     return indicator
Example #3
0
 def indicator_factory(dd, bt):
     def indicator(X):
         L = np.logical_and(float_cmp(X[:, 0], dd.domain[0, 0]), dd.left == bt)
         R = np.logical_and(float_cmp(X[:, 0], dd.domain[1, 0]), dd.right == bt)
         T = np.logical_and(float_cmp(X[:, 1], dd.domain[1, 1]), dd.top == bt)
         B = np.logical_and(float_cmp(X[:, 1], dd.domain[0, 1]), dd.bottom == bt)
         LR = np.logical_or(L, R)
         TB = np.logical_or(T, B)
         return np.logical_or(LR, TB)
     inject_sid(indicator, indicator_id, dd, bt)
     return indicator
Example #4
0
    def __init__(self, vx=1., vy=1., torus=True, initial_data_type='sin', parameter_range=(1., 2.)):

        assert initial_data_type in ('sin', 'bump')

        def burgers_flux(U, mu):
            U = U.reshape(U.shape[:-1])
            U_exp = np.sign(U) * np.power(np.abs(U), mu['exponent'])
            R = np.empty(U.shape + (2,))
            R[..., 0] = U_exp * vx
            R[..., 1] = U_exp * vy
            return R
        inject_sid(burgers_flux, str(Burgers2DProblem) + '.burgers_flux', vx, vy)

        def burgers_flux_derivative(U, mu):
            U = U.reshape(U.shape[:-1])
            U_exp = mu['exponent'] * (np.sign(U) * np.power(np.abs(U), mu['exponent']-1))
            R = np.empty(U.shape + (2,))
            R[..., 0] = U_exp * vx
            R[..., 1] = U_exp * vy
            return R
        inject_sid(burgers_flux_derivative, str(Burgers2DProblem) + '.burgers_flux_derivative', vx, vy)

        flux_function = GenericFunction(burgers_flux, dim_domain=1, shape_range=(2,),
                                        parameter_type={'exponent': 0},
                                        name='burgers_flux')

        flux_function_derivative = GenericFunction(burgers_flux_derivative, dim_domain=1, shape_range=(2,),
                                                   parameter_type={'exponent': 0},
                                                   name='burgers_flux')

        if initial_data_type == 'sin':
            def initial_data(x):
                return 0.5 * (np.sin(2 * np.pi * x[..., 0]) * np.sin(2 * np.pi * x[..., 1]) + 1.)
            inject_sid(initial_data, str(Burgers2DProblem) + '.initial_data_sin')
            dirichlet_data = ConstantFunction(dim_domain=2, value=0.5)
        else:
            def initial_data(x):
                return (x[..., 0] >= 0.5) * (x[..., 0] <= 1) * 1
            inject_sid(initial_data, str(Burgers2DProblem) + '.initial_data_bump')
            dirichlet_data = ConstantFunction(dim_domain=2, value=0)

        initial_data = GenericFunction(initial_data, dim_domain=2)

        domain = TorusDomain([[0, 0], [2, 1]]) if torus else RectDomain([[0, 0], [2, 1]], right=None, top=None)

        super(Burgers2DProblem, self).__init__(domain=domain,
                                               rhs=None,
                                               flux_function=flux_function,
                                               flux_function_derivative=flux_function_derivative,
                                               initial_data=initial_data,
                                               dirichlet_data=dirichlet_data,
                                               T=0.3, name='Burgers2DProblem')

        self.parameter_space = CubicParameterSpace({'exponent': 0}, *parameter_range)
        self.parameter_range = parameter_range
        self.initial_data_type = initial_data_type
        self.torus = torus
        self.vx = vx
        self.vy = vy
def discretize_nonlinear_instationary_advection_diffusion_fv(analytical_problem, diameter=None, nt=100, num_flux='lax_friedrichs',
                                                   lxf_lambda=1., domain_discretizer=None, grid=None, boundary_info=None):

    assert isinstance(analytical_problem, InstationaryAdvectionDiffusionProblem)
    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')

    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)
    else:
        L = nonlinear_advection_engquist_osher_operator(grid, boundary_info, p.flux_function, p.flux_function_derivative,
                                            dirichlet_data=p.dirichlet_data)

    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)
    inject_sid(I, __name__ + '.discretize_nonlinear_instationary_advection_diffusion_fv.initial_data', p.initial_data, grid)

    D = DiffusionOperator(grid, boundary_info, p.diffusion)
    D = type(D).lincomb(operators=[D], name='diffusion', coefficients_name='diffusion')
    F = None if p.rhs is None else DiffusionRHSOperatorFunctional(grid, boundary_info, p.rhs, 
                                                                  p.neumann_data, p.dirichlet_data, p.diffusion)
    F = type(F).lincomb(operators=[F], name='rhs', coefficients_name='diffusion')
    
    products = {'l2': L2Product(grid, boundary_info)}
    visualizer = PatchVisualizer(grid=grid, bounding_box=grid.domain, codim=0)
    parameter_space = p.parameter_space if hasattr(p, 'parameter_space') else None

    discretization = InstationaryImexDiscretization(explicit_operator=L, implicit_operator=D, rhs=F, 
                                                                  initial_data=I, T=p.T, nt=nt, products=products,
                                                                  parameter_space=parameter_space, visualizer=visualizer,
                                                                  name='{}_FV'.format(p.name))

    return discretization, {'grid': grid, 'boundary_info': boundary_info}
Example #6
0
    def __init__(self, v=1., circle=True, initial_data_type='sin', parameter_range=(1., 2.)):

        assert initial_data_type in ('sin', 'bump')

        def burgers_flux(U, mu):
            U_exp = np.sign(U) * np.power(np.abs(U), mu['exponent'])
            R = U_exp * v
            return R
        inject_sid(burgers_flux, str(BurgersProblem) + '.burgers_flux', v)

        def burgers_flux_derivative(U, mu):
            U_exp = mu['exponent'] * (np.sign(U) * np.power(np.abs(U), mu['exponent']-1))
            R = U_exp * v
            return R
        inject_sid(burgers_flux_derivative, str(BurgersProblem) + '.burgers_flux_derivative', v)

        flux_function = GenericFunction(burgers_flux, dim_domain=1, shape_range=(1,),
                                        parameter_type={'exponent': 0},
                                        name='burgers_flux')

        flux_function_derivative = GenericFunction(burgers_flux_derivative, dim_domain=1, shape_range=(1,),
                                                   parameter_type={'exponent': 0},
                                                   name='burgers_flux')

        if initial_data_type == 'sin':
            def initial_data(x):
                return 0.5 * (np.sin(2 * np.pi * x[..., 0]) + 1.)
            inject_sid(initial_data, str(BurgersProblem) + '.initial_data_sin')
            dirichlet_data = ConstantFunction(dim_domain=1, value=0.5)
        else:
            def initial_data(x):
                return (x[..., 0] >= 0.5) * (x[..., 0] <= 1) * 1
            inject_sid(initial_data, str(BurgersProblem) + '.initial_data_bump')
            dirichlet_data = ConstantFunction(dim_domain=1, value=0)

        initial_data = GenericFunction(initial_data, dim_domain=1)

        if circle:
            domain = CircleDomain([0, 2])
        else:
            domain = LineDomain([0, 2], right=None)

        super(BurgersProblem, self).__init__(domain=domain,
                                             rhs=None,
                                             flux_function=flux_function,
                                             flux_function_derivative=flux_function_derivative,
                                             initial_data=initial_data,
                                             dirichlet_data=dirichlet_data,
                                             T=0.3, name='BurgersProblem')

        self.parameter_space = CubicParameterSpace({'exponent': 0}, *parameter_range)
        self.parameter_range = parameter_range
        self.initial_data_type = initial_data_type
        self.circle = circle
        self.v = v
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, 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 provided.

    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 diffusion_function_factory(x, y):
     func = lambda X: (1. * (X[..., 0] >= x * dx) * (X[..., 0] < (x + 1) * dx)
                          * (X[..., 1] >= y * dy) * (X[..., 1] < (y + 1) * dy))
     inject_sid(func, diffusion_function_id, x, y, dx, dy)
     return GenericFunction(func, dim_domain=2, name='diffusion_function_{}_{}'.format(x, y))