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)
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
def parabolic_demo(): p = ThermalBlockProblem(parameter_range=(0.01, 1)) d_stat, d_data = discretize_elliptic_cg(p, diameter=1.0 / 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)
def discretize(n, nt, blocks): h = 1. / blocks ops = [ WrappedDiffusionOperator.create(n, h * i, h * (i + 1)) for i in range(blocks) ] pfs = [ ProjectionParameterFunctional('diffusion_coefficients', (blocks, ), (i, )) for i in range(blocks) ] operator = LincombOperator(ops, pfs) initial_data = operator.source.zeros() # use data property of WrappedVector to setup rhs # note that we cannot use the data property of ListVectorArray, # since ListVectorArray will always return a copy rhs_vec = operator.range.zeros() rhs_data = rhs_vec._list[0].data rhs_data[:] = np.ones(len(rhs_data)) rhs_data[0] = 0 rhs_data[len(rhs_data) - 1] = 0 rhs = VectorFunctional(rhs_vec) # hack together a visualizer ... grid = OnedGrid(domain=(0, 1), num_intervals=n) visualizer = Matplotlib1DVisualizer(grid) time_stepper = ExplicitEulerTimeStepper(nt) parameter_space = CubicParameterSpace(operator.parameter_type, 0.1, 1) d = InstationaryDiscretization(T=1e-0, operator=operator, rhs=rhs, initial_data=initial_data, time_stepper=time_stepper, num_values=20, parameter_space=parameter_space, visualizer=visualizer, name='C++-Discretization', cache_region=None) return d
def discretize_nonlinear_instationary_advection_fv(analytical_problem, diameter=None, nt=100, num_flux='lax_friedrichs', lxf_lambda=1., eo_gausspoints=5, eo_intervals=1, num_values=None, domain_discretizer=None, grid=None, boundary_info=None): """Discretizes an |InstationaryAdvectionProblem| using the finite volume method. Simple explicit Euler time-stepping is used for time-discretization. Parameters ---------- analytical_problem The |InstationaryAdvectionProblem| to discretize. diameter If not `None`, `diameter` is passed to the `domain_discretizer`. nt The number of time-steps. num_flux The numerical flux to use in the finite volume formulation. Allowed values are `'lax_friedrichs'`, `'engquist_osher'`, `'simplified_engquist_osher'`. (See :mod:`pymor.operators.fv`.) lxf_lambda The stabilization parameter for the Lax-Friedrichs numerical flux. (Ignored, if different flux is chosen.) eo_gausspoints Number of Gauss points for the Engquist-Osher numerical flux. (Ignored, if different flux is chosen.) eo_intervals Number of sub-intervals to use for integration when using Engquist-Osher numerical flux. (Ignored, if different flux is chosen.) num_values The number of returned vectors of the solution trajectory. If `None`, each intermediate vector that is calculated is returned. domain_discretizer Discretizer to be used for discretizing the analytical domain. This has to be a function `domain_discretizer(domain_description, diameter, ...)`. If further arguments should be passed to the discretizer, use :func:`functools.partial`. If `None`, |discretize_domain_default| is used. grid Instead of using a domain discretizer, the |Grid| can also be passed directly using this parameter. boundary_info A |BoundaryInfo| specifying the boundary types of the grid boundary entities. Must be provided if `grid` is specified. Returns ------- discretization The |Discretization| that has been generated. data Dictionary with the following entries: :grid: The generated |Grid|. :boundary_info: The generated |BoundaryInfo|. """ assert isinstance(analytical_problem, InstationaryAdvectionProblem) assert grid is None or boundary_info is not None assert boundary_info is None or grid is not None assert grid is None or domain_discretizer is None assert num_flux in ('lax_friedrichs', 'engquist_osher', 'simplified_engquist_osher') if grid is None: domain_discretizer = domain_discretizer or discretize_domain_default if diameter is None: grid, boundary_info = domain_discretizer(analytical_problem.domain) else: grid, boundary_info = domain_discretizer(analytical_problem.domain, diameter=diameter) p = analytical_problem if num_flux == 'lax_friedrichs': L = nonlinear_advection_lax_friedrichs_operator( grid, boundary_info, p.flux_function, dirichlet_data=p.dirichlet_data, lxf_lambda=lxf_lambda) elif num_flux == 'engquist_osher': L = nonlinear_advection_engquist_osher_operator( grid, boundary_info, p.flux_function, p.flux_function_derivative, gausspoints=eo_gausspoints, intervals=eo_intervals, dirichlet_data=p.dirichlet_data) else: L = nonlinear_advection_simplified_engquist_osher_operator( grid, boundary_info, p.flux_function, p.flux_function_derivative, dirichlet_data=p.dirichlet_data) F = None if p.rhs is None else L2ProductFunctional(grid, p.rhs) if p.initial_data.parametric: def initial_projection(U, mu): I = p.initial_data.evaluate(grid.quadrature_points(0, order=2), mu).squeeze() I = np.sum(I * grid.reference_element.quadrature(order=2)[1], axis=1) * (1. / grid.reference_element.volume) I = NumpyVectorArray(I, copy=False) return I.lincomb(U).data inject_sid( initial_projection, __name__ + '.discretize_nonlinear_instationary_advection_fv.initial_data', p.initial_data, grid) I = NumpyGenericOperator(initial_projection, dim_range=grid.size(0), linear=True, parameter_type=p.initial_data.parameter_type) else: I = p.initial_data.evaluate(grid.quadrature_points(0, order=2)).squeeze() I = np.sum(I * grid.reference_element.quadrature(order=2)[1], axis=1) * (1. / grid.reference_element.volume) I = NumpyVectorArray(I, copy=False) inject_sid( I, __name__ + '.discretize_nonlinear_instationary_advection_fv.initial_data', p.initial_data, grid) products = {'l2': L2Product(grid, boundary_info)} if grid.dim == 2: visualizer = PatchVisualizer(grid=grid, bounding_box=grid.domain, codim=0) elif grid.dim == 1: visualizer = Matplotlib1DVisualizer(grid, codim=0) else: visualizer = None parameter_space = p.parameter_space if hasattr(p, 'parameter_space') else None time_stepper = ExplicitEulerTimeStepper(nt=nt) discretization = InstationaryDiscretization( operator=L, rhs=F, initial_data=I, T=p.T, products=products, time_stepper=time_stepper, parameter_space=parameter_space, visualizer=visualizer, num_values=num_values, name='{}_FV'.format(p.name)) return discretization, {'grid': grid, 'boundary_info': boundary_info}
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
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
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 an |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.discretizations.basic.InstationaryDiscretization.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 |Discretization|. Returns ------- d 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, 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 d, 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 = d.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 = d.l2_0_product d = InstationaryDiscretization(operator=d.operator, rhs=d.rhs, mass=mass, initial_data=I, T=p.T, products=d.products, time_stepper=time_stepper, parameter_space=p.parameter_space, visualizer=d.visualizer, num_values=num_values, name='{}_CG'.format(p.name)) if preassemble: data['unassembled_d'] = d d = preassemble_(d) return d, data
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)
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 an |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.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). 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.discretizations.basic.InstationaryDiscretization.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 |Discretization|. 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, 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 d, 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 = d.solution_space.make_array(I) return I.lincomb(U).data I = NumpyGenericOperator(initial_projection, dim_range=grid.size(0), linear=True, range_id=d.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 = d.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(d.rhs, ZeroOperator) else d.rhs discretization = InstationaryDiscretization( operator=d.operator, rhs=rhs, mass=None, initial_data=I, T=p.T, products=d.products, time_stepper=time_stepper, parameter_space=p.parameter_space, visualizer=d.visualizer, num_values=num_values, name='{}_FV'.format(p.name)) if preassemble: data['unassembled_discretization'] = discretization discretization = preassemble_(discretization) return discretization, data
def discretize_instationary_from_disk(parameter_file, T=None, steps=None, u0=None, time_stepper=None): """Load a linear affinely decomposed |InstationaryDiscretization| from file. Similarly to :func:`discretize_stationary_from_disk`, the discretization 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.TimeStepperInterface>` to use. If `None`, implicit Euler time stepping is used. Returns ------- discretization The |InstationaryDiscretization| 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, source_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 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)
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)
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 ...') # nonblocked_disc.visualize(U)
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)
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 }