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
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
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
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}
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
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}
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))