def elliptic_oned_demo(args): args['PROBLEM-NUMBER'] = int(args['PROBLEM-NUMBER']) assert 0 <= args['PROBLEM-NUMBER'] <= 1, ValueError('Invalid problem number.') args['N'] = int(args['N']) rhss = [ExpressionFunction('ones(x.shape[:-1]) * 10', 1, ()), ExpressionFunction('(x - 0.5)**2 * 1000', 1, ())] rhs = rhss[args['PROBLEM-NUMBER']] d0 = ExpressionFunction('1 - x', 1, ()) d1 = ExpressionFunction('x', 1, ()) parameter_space = CubicParameterSpace({'diffusionl': 0}, 0.1, 1) f0 = ProjectionParameterFunctional('diffusionl', 0) f1 = ExpressionParameterFunctional('1', {}) problem = StationaryProblem( domain=LineDomain(), rhs=rhs, diffusion=LincombFunction([d0, d1], [f0, f1]), dirichlet_data=ConstantFunction(value=0, dim_domain=1), name='1DProblem' ) print('Discretize ...') discretizer = discretize_stationary_fv if args['--fv'] else discretize_stationary_cg d, data = discretizer(problem, diameter=1 / args['N']) print(data['grid']) print() print('Solve ...') U = d.solution_space.empty() for mu in parameter_space.sample_uniformly(10): U.append(d.solve(mu)) d.visualize(U, title='Solution for diffusionl in [0.1, 1]')
def elliptic_oned_demo(args): args['PROBLEM-NUMBER'] = int(args['PROBLEM-NUMBER']) assert 0 <= args['PROBLEM-NUMBER'] <= 1, ValueError('Invalid problem number.') args['N'] = int(args['N']) rhss = [GenericFunction(lambda X: np.ones(X.shape[:-1]) * 10, dim_domain=1), GenericFunction(lambda X: (X[..., 0] - 0.5) ** 2 * 1000, dim_domain=1)] rhs = rhss[args['PROBLEM-NUMBER']] d0 = GenericFunction(lambda X: 1 - X[..., 0], dim_domain=1) d1 = GenericFunction(lambda X: X[..., 0], dim_domain=1) parameter_space = CubicParameterSpace({'diffusionl': 0}, 0.1, 1) f0 = ProjectionParameterFunctional('diffusionl', 0) f1 = GenericParameterFunctional(lambda mu: 1, {}) print('Solving on OnedGrid(({0},{0}))'.format(args['N'])) print('Setup Problem ...') problem = EllipticProblem(domain=LineDomain(), rhs=rhs, diffusion_functions=(d0, d1), diffusion_functionals=(f0, f1), dirichlet_data=ConstantFunction(value=0, dim_domain=1), name='1DProblem') print('Discretize ...') discretizer = discretize_elliptic_fv if args['--fv'] else discretize_elliptic_cg discretization, _ = discretizer(problem, diameter=1 / args['N']) print('The parameter type is {}'.format(discretization.parameter_type)) U = discretization.solution_space.empty() for mu in parameter_space.sample_uniformly(10): U.append(discretization.solve(mu)) print('Plot ...') discretization.visualize(U, title='Solution for diffusionl in [0.1, 1]')
def elliptic2_demo(args): args['PROBLEM-NUMBER'] = int(args['PROBLEM-NUMBER']) assert 0 <= args['PROBLEM-NUMBER'] <= 1, ValueError('Invalid problem number.') args['N'] = int(args['N']) rhss = [ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), LincombFunction( [ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), ConstantFunction(1.,2)], [ProjectionParameterFunctional('mu', 0), ExpressionParameterFunctional('0.1', {})])] dirichlets = [ExpressionFunction('zeros(x.shape[:-1])', 2, ()), LincombFunction( [ExpressionFunction('2 * x[..., 0]', 2, ()), ConstantFunction(1.,2)], [ProjectionParameterFunctional('mu', 0), ExpressionParameterFunctional('0.5', {})])] neumanns = [None, LincombFunction( [ExpressionFunction('1 - x[..., 1]', 2, ()), ConstantFunction(1.,2)], [ProjectionParameterFunctional('mu', 0), ExpressionParameterFunctional('0.5**2', {})])] robins = [None, (LincombFunction( [ExpressionFunction('x[..., 1]', 2, ()), ConstantFunction(1.,2)], [ProjectionParameterFunctional('mu', 0), ExpressionParameterFunctional('1', {})]), ConstantFunction(1.,2))] domains = [RectDomain(), RectDomain(right='neumann', top='dirichlet', bottom='robin')] rhs = rhss[args['PROBLEM-NUMBER']] dirichlet = dirichlets[args['PROBLEM-NUMBER']] neumann = neumanns[args['PROBLEM-NUMBER']] domain = domains[args['PROBLEM-NUMBER']] robin = robins[args['PROBLEM-NUMBER']] problem = StationaryProblem( domain=RectDomain(), rhs=rhs, diffusion=LincombFunction( [ExpressionFunction('1 - x[..., 0]', 2, ()), ExpressionFunction('x[..., 0]', 2, ())], [ProjectionParameterFunctional('mu', 0), ExpressionParameterFunctional('1', {})] ), dirichlet_data=dirichlet, neumann_data=neumann, robin_data=robin, parameter_space=CubicParameterSpace({'mu': 0}, 0.1, 1), name='2DProblem' ) print('Discretize ...') discretizer = discretize_stationary_fv if args['--fv'] else discretize_stationary_cg m, data = discretizer(problem, diameter=1. / args['N']) print(data['grid']) print() print('Solve ...') U = m.solution_space.empty() for mu in m.parameter_space.sample_uniformly(10): U.append(m.solve(mu)) m.visualize(U, title='Solution for mu in [0.1, 1]')
def __init__(self, num_blocks=(3, 3), parameter_range=(0.1, 1), rhs=ConstantFunction(dim_domain=2)): domain = RectDomain() parameter_space = CubicParameterSpace( {'diffusion': (num_blocks[1], num_blocks[0])}, *parameter_range) def parameter_functional_factory(x, y): return ProjectionParameterFunctional( component_name='diffusion', component_shape=(num_blocks[1], num_blocks[0]), coordinates=(num_blocks[1] - y - 1, x), name='diffusion_{}_{}'.format(x, y)) diffusion_functions = tuple( ThermalBlockDiffusionFunction(x, y, num_blocks[0], num_blocks[1]) for x, y in product(xrange(num_blocks[0]), xrange(num_blocks[1]))) parameter_functionals = tuple( parameter_functional_factory(x, y) for x, y in product(xrange(num_blocks[0]), xrange(num_blocks[1]))) super(ThermalBlockProblem, self).__init__(domain, rhs, diffusion_functions, parameter_functionals, name='ThermalBlock') self.parameter_space = parameter_space self.parameter_range = parameter_range self.num_blocks = num_blocks
def burgers_problem_2d(vx=1., vy=1., torus=True, initial_data_type='sin', parameter_range=(1., 2.)): """Two-dimensional Burgers-type problem. The problem is to solve :: ∂_t u(x, t, μ) + ∇ ⋅ (v * u(x, t, μ)^μ) = 0 u(x, 0, μ) = u_0(x) for u with t in [0, 0.3], x in [0, 2] x [0, 1]. Parameters ---------- vx The x component of the velocity vector v. vy The y component of the velocity vector v. torus If `True`, impose periodic boundary conditions. Otherwise, Dirichlet left and bottom, outflow top and right. initial_data_type Type of initial data (`'sin'` or `'bump'`). parameter_range The interval in which μ is allowed to vary. """ assert initial_data_type in ('sin', 'bump') if initial_data_type == 'sin': initial_data = ExpressionFunction( "0.5 * (sin(2 * pi * x[..., 0]) * sin(2 * pi * x[..., 1]) + 1.)", 2, ()) dirichlet_data = ConstantFunction(dim_domain=2, value=0.5) else: initial_data = ExpressionFunction( "(x[..., 0] >= 0.5) * (x[..., 0] <= 1) * 1", 2, ()) dirichlet_data = ConstantFunction(dim_domain=2, value=0.) return InstationaryProblem( StationaryProblem( domain=TorusDomain([[0, 0], [2, 1]]) if torus else RectDomain([[0, 0], [2, 1]], right=None, top=None), dirichlet_data=dirichlet_data, rhs=None, nonlinear_advection=ExpressionFunction("abs(x)**exponent * v", 1, (2, ), {'exponent': ()}, {'v': np.array([vx, vy])}), nonlinear_advection_derivative=ExpressionFunction( "exponent * abs(x)**(exponent-1) * sign(x) * v", 1, (2, ), {'exponent': ()}, {'v': np.array([vx, vy])}), ), initial_data=initial_data, T=0.3, parameter_space=CubicParameterSpace({'exponent': 0}, *parameter_range), name="burgers_problem_2d({}, {}, {}, '{}')".format( vx, vy, torus, initial_data_type))
def burgers_problem(v=1., circle=True, initial_data_type='sin', parameter_range=(1., 2.)): """One-dimensional Burgers-type problem. The problem is to solve :: ∂_t u(x, t, μ) + ∂_x (v * u(x, t, μ)^μ) = 0 u(x, 0, μ) = u_0(x) for u with t in [0, 0.3] and x in [0, 2]. Parameters ---------- v The velocity v. circle If `True`, impose periodic boundary conditions. Otherwise Dirichlet left, outflow right. initial_data_type Type of initial data (`'sin'` or `'bump'`). parameter_range The interval in which μ is allowed to vary. """ assert initial_data_type in ('sin', 'bump') if initial_data_type == 'sin': initial_data = ExpressionFunction('0.5 * (sin(2 * pi * x) + 1.)', 1, ()) dirichlet_data = ConstantFunction(dim_domain=1, value=0.5) else: initial_data = ExpressionFunction('(x >= 0.5) * (x <= 1) * 1.', 1, ()) dirichlet_data = ConstantFunction(dim_domain=1, value=0.) return InstationaryProblem( StationaryProblem( domain=CircleDomain([0, 2]) if circle else LineDomain([0, 2], right=None), dirichlet_data=dirichlet_data, rhs=None, nonlinear_advection=ExpressionFunction('abs(x)**exponent * v', 1, (1, ), {'exponent': ()}, {'v': v}), nonlinear_advection_derivative=ExpressionFunction( 'exponent * abs(x)**(exponent-1) * sign(x) * v', 1, (1, ), {'exponent': ()}, {'v': v}), ), T=0.3, initial_data=initial_data, parameter_space=CubicParameterSpace({'exponent': 0}, *parameter_range), name="burgers_problem({}, {}, '{}')".format(v, circle, initial_data_type))
def __init__(self, domain=RectDomain(), rhs=None, parameter_range=(0., 100.), dirichlet_data=None, neumann_data=None): self.parameter_range = parameter_range # needed for with_ parameter_space = CubicParameterSpace({'k': ()}, *parameter_range) super().__init__( diffusion_functions=[ConstantFunction(1., dim_domain=domain.dim)], diffusion_functionals=[1.], reaction_functions=[ConstantFunction(1., dim_domain=domain.dim)], reaction_functionals=[ExpressionParameterFunctional('-k**2', {'k': ()})], domain=domain, rhs=rhs or ConstantFunction(1., dim_domain=domain.dim), parameter_space=parameter_space, dirichlet_data=dirichlet_data, neumann_data=neumann_data)
def helmholtz_problem(domain=RectDomain(), rhs=None, parameter_range=(0., 100.), dirichlet_data=None, neumann_data=None): """Helmholtz equation problem. This problem is to solve the Helmholtz equation :: - ∆ u(x, k) - k^2 u(x, k) = f(x, k) on a given domain. Parameters ---------- domain A |DomainDescription| of the domain the problem is posed on. rhs The |Function| f(x, μ). parameter_range A tuple `(k_min, k_max)` describing the interval in which k is allowd to vary. dirichlet_data |Function| providing the Dirichlet boundary values. neumann_data |Function| providing the Neumann boundary values. """ return StationaryProblem( domain=domain, rhs=rhs or ConstantFunction(1., dim_domain=domain.dim), dirichlet_data=dirichlet_data, neumann_data=neumann_data, diffusion=ConstantFunction(1., dim_domain=domain.dim), reaction=LincombFunction([ConstantFunction(1., dim_domain=domain.dim)], [ExpressionParameterFunctional('-k**2', {'k': ()})]), parameter_space=CubicParameterSpace({'k': ()}, *parameter_range), name='helmholtz_problem' )
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(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 __init__(self, vx=1., vy=1., torus=True, initial_data_type='sin', parameter_range=(1., 2.)): assert initial_data_type in ('sin', 'bump') flux_function = Burgers2DFlux(vx, vy) flux_function_derivative = Burgers2DFluxDerivative(vx, vy) if initial_data_type == 'sin': initial_data = Burgers2DSinInitialData() dirichlet_data = ConstantFunction(dim_domain=2, value=0.5) else: initial_data = Burgers2DBumpInitialData() dirichlet_data = ConstantFunction(dim_domain=2, value=0) 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 __init__(self, v=1., circle=True, initial_data_type='sin', parameter_range=(1., 2.)): assert initial_data_type in ('sin', 'bump') flux_function = BurgersFlux(v) flux_function_derivative = BurgersFluxDerivative(v) if initial_data_type == 'sin': initial_data = BurgersSinInitialData() dirichlet_data = ConstantFunction(dim_domain=1, value=0.5) else: initial_data = BurgersBumpInitialData() dirichlet_data = ConstantFunction(dim_domain=1, value=0) 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 elliptic2_demo(args): args['PROBLEM-NUMBER'] = int(args['PROBLEM-NUMBER']) assert 0 <= args['PROBLEM-NUMBER'] <= 1, ValueError( 'Invalid problem number.') args['N'] = int(args['N']) rhss = [ ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), ExpressionFunction('(x[..., 0] - 0.5)**2 * 1000', 2, ()) ] rhs = rhss[args['PROBLEM-NUMBER']] problem = StationaryProblem( domain=RectDomain(), rhs=rhs, diffusion=LincombFunction([ ExpressionFunction('1 - x[..., 0]', 2, ()), ExpressionFunction('x[..., 0]', 2, ()) ], [ ProjectionParameterFunctional('diffusionl', 0), ExpressionParameterFunctional('1', {}) ]), parameter_space=CubicParameterSpace({'diffusionl': 0}, 0.1, 1), name='2DProblem') print('Discretize ...') discretizer = discretize_stationary_fv if args[ '--fv'] else discretize_stationary_cg m, data = discretizer(problem, diameter=1. / args['N']) print(data['grid']) print() print('Solve ...') U = m.solution_space.empty() for mu in m.parameter_space.sample_uniformly(10): U.append(m.solve(mu)) m.visualize(U, title='Solution for diffusionl in [0.1, 1]')
def discretize_stationary_from_disk(parameter_file): """Load a linear affinely decomposed |StationaryModel| from file. The model is defined via an `.ini`-style file as follows :: [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) ... [parameter] μ_1: a_1,b_1 ... μ_n: a_n,b_n [products] Prod1: P_1.mat Prod2: P_2.mat ... Here, `L_1.mat`, `L_2.mat`, ..., `F_1.mat`, `F_2.mat`, ... are files containing matrices `L_1`, `L_2`, ... and vectors `F_1.mat`, `F_2.mat`, ... which correspond to the affine components of the operator and right-hand side. The respective coefficient functionals, are given via the string expressions `l_1(...)`, `l_2(...)`, ..., `f_1(...)` in the (scalar-valued) |Parameter| components `w_1`, ..., `w_n`. The allowed lower and upper bounds `a_i, b_i` for the component `μ_i` are specified in the `[parameters]` section. The resulting operator and right-hand side are then of the form :: L(μ) = l_1(μ)*L_1 + l_2(μ)*L_2+ ... F(μ) = f_1(μ)*F_1 + f_2(μ)*L_2+ ... In the `[products]` section, an optional list of inner products `Prod1`, `Prod2`, .. with corresponding matrices `P_1.mat`, `P_2.mat` can be specified. Example:: [system-matrices] matrix1.mat: 1. matrix2.mat: 1. - theta**2 [rhs-vectors] rhs.mat: 1. [parameter] theta: 0, 0.5 [products] h1: h1.mat l2: mass.mat Parameters ---------- parameter_file Path to the parameter file. Returns ------- m The |StationaryModel| that has been generated. """ assert ".ini" == parameter_file[ -4:], f'Given file is not an .ini file: {parameter_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 'rhs-vectors' in config.sections() assert 'parameter' in config.sections() system_mat = config.items('system-matrices') 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 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 # Create and return stationary model return StationaryModel(operator=system_lincombOperator, rhs=rhs_lincombOperator, parameter_space=parameter_space, products=products)
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)
def prepare(cfg): logger = getLogger('.OS2015_SISC__6_2.prepare') logger.setLevel('INFO') reference_needed = ( (cfg['greedy_use_estimator'] or cfg['estimate_some_errors']) and ('discretization_error' in cfg['estimator_compute'] or 'full_error' in cfg['estimator_compute'] or 'model_reduction_error' in cfg['estimator_compute']) or cfg['local_indicators'] == 'model_reduction_error') logger.info('Initializing DUNE module ({}):'.format(cfg['dune_example'])) Example = dune_module.__dict__[cfg['dune_example']] example = Example(partitioning=cfg['dune_partitioning'], num_refinements=cfg['dune_num_refinements'], oversampling_layers=cfg['dune_oversampling_layers'], products=cfg['dune_products'], with_reference=reference_needed, info_log_levels=cfg['dune_log_info_level'], debug_log_levels=cfg['dune_log_debug_level'], enable_warnings=cfg['dune_log_enable_warnings'], enable_colors=True, info_color='blue') _, wrapper = wrap_module(dune_module) discretization = wrapper[example.discretization()] logger.info(' grid has {} subdomain{}'.format( discretization.num_subdomains, '' if discretization.num_subdomains == 1 else 's')) logger.info(' discretization has {} DoFs'.format( discretization.solution_space.dim)) discretization = discretization.with_(parameter_space=CubicParameterSpace( discretization.parameter_type, cfg['parameter_range'][0], cfg['parameter_range'][1])) logger.info(' parameter type is {}'.format(discretization.parameter_type)) example.visualize(cfg['dune_example']) def create_product(products, product_type): if product_type is None: return None, 'None' if not isinstance(product_type, tuple): return products[product_type], product_type else: prods = [products[tt] for tt in product_type] product_name = product_type[0] for ii in np.arange(1, len(product_type)): product_name += '_plus_' + product_type[ii] return LincombOperator(operators=prods, coefficients=[1 for pp in prods ]), product_name logger.info('Preparing products and norms ...') mu_hat_dune = wrapper.DuneParameter('mu', cfg['mu_hat_value']) mu_bar_dune = wrapper.DuneParameter('mu', cfg['mu_bar_value']) all_global_products = {} all_local_products = [{} for ss in np.arange(discretization.num_subdomains)] # get all products from the discretization and assemble the parametric ones for nm, pr in discretization.products.items(): if not pr.parametric: all_global_products[nm] = pr else: all_global_products[nm] = pr.assemble(mu=wrapper[mu_bar_dune]) for ss in np.arange(discretization.num_subdomains): pr = discretization.local_product(ss, nm) if pr.parametric: all_local_products[ss][nm] = pr.assemble( mu=wrapper[mu_bar_dune]) else: all_local_products[ss][nm] = pr # combine products (if necessarry) global_product, _ = create_product(all_global_products, cfg['extension_product']) local_products, _ = map( list, zip(*[ create_product(all_local_pr, cfg['extension_product']) for all_local_pr in all_local_products ])) # assert all(nm == local_products_name[0] for nm in local_products_name) # local_products_name = local_products_name[0] norm, _ = create_product(all_global_products, cfg['greedy_error_norm']) norm = induced_norm(norm) if norm is not None else None return { 'example': example, 'discretization': discretization, 'local_products': local_products, 'norm': norm, 'mu_bar_dune': mu_bar_dune, 'mu_hat_dune': mu_hat_dune, 'wrapper': wrapper }
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
def _discretize_fenics(xblocks, yblocks, grid_num_intervals, element_order): # assemble system matrices - FEniCS code ######################################## import dolfin as df mesh = df.UnitSquareMesh(grid_num_intervals, grid_num_intervals, 'crossed') V = df.FunctionSpace(mesh, 'Lagrange', element_order) u = df.TrialFunction(V) v = df.TestFunction(V) diffusion = df.Expression('(lower0 <= x[0]) * (open0 ? (x[0] < upper0) : (x[0] <= upper0)) *' '(lower1 <= x[1]) * (open1 ? (x[1] < upper1) : (x[1] <= upper1))', lower0=0., upper0=0., open0=0, lower1=0., upper1=0., open1=0, element=df.FunctionSpace(mesh, 'DG', 0).ufl_element()) def assemble_matrix(x, y, nx, ny): diffusion.user_parameters['lower0'] = x/nx diffusion.user_parameters['lower1'] = y/ny diffusion.user_parameters['upper0'] = (x + 1)/nx diffusion.user_parameters['upper1'] = (y + 1)/ny diffusion.user_parameters['open0'] = (x + 1 == nx) diffusion.user_parameters['open1'] = (y + 1 == ny) return df.assemble(df.inner(diffusion * df.nabla_grad(u), df.nabla_grad(v)) * df.dx) mats = [assemble_matrix(x, y, xblocks, yblocks) for x in range(xblocks) for y in range(yblocks)] mat0 = mats[0].copy() mat0.zero() h1_mat = df.assemble(df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx) l2_mat = df.assemble(u * v * df.dx) f = df.Constant(1.) * v * df.dx F = df.assemble(f) bc = df.DirichletBC(V, 0., df.DomainBoundary()) for m in mats: bc.zero(m) bc.apply(mat0) bc.apply(h1_mat) bc.apply(F) # wrap everything as a pyMOR model ################################## # FEniCS wrappers from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator, FenicsVisualizer # generic pyMOR classes from pymor.models.basic import StationaryModel from pymor.operators.constructions import LincombOperator, VectorOperator from pymor.parameters.functionals import ProjectionParameterFunctional from pymor.parameters.spaces import CubicParameterSpace # define parameter functionals (same as in pymor.analyticalproblems.thermalblock) def parameter_functional_factory(x, y): return ProjectionParameterFunctional(component_name='diffusion', component_shape=(yblocks, xblocks), index=(yblocks - y - 1, x), name=f'diffusion_{x}_{y}') parameter_functionals = tuple(parameter_functional_factory(x, y) for x in range(xblocks) for y in range(yblocks)) # wrap operators ops = [FenicsMatrixOperator(mat0, V, V)] + [FenicsMatrixOperator(m, V, V) for m in mats] op = LincombOperator(ops, (1.,) + parameter_functionals) rhs = VectorOperator(FenicsVectorSpace(V).make_array([F])) h1_product = FenicsMatrixOperator(h1_mat, V, V, name='h1_0_semi') l2_product = FenicsMatrixOperator(l2_mat, V, V, name='l2') # build model visualizer = FenicsVisualizer(FenicsVectorSpace(V)) parameter_space = CubicParameterSpace(op.parameter_type, 0.1, 1.) fom = StationaryModel(op, rhs, products={'h1_0_semi': h1_product, 'l2': l2_product}, parameter_space=parameter_space, visualizer=visualizer) return fom
def discretize(grid_and_problem_data, solver_options, mpi_comm): ################ Setup logger = getLogger('discretize_elliptic_block_swipdg.discretize') logger.info('discretizing ... ') grid, boundary_info = grid_and_problem_data['grid'], grid_and_problem_data[ 'boundary_info'] local_all_dirichlet_boundary_info = make_subdomain_boundary_info( grid, {'type': 'xt.grid.boundaryinfo.alldirichlet'}) local_subdomains, num_local_subdomains, num_global_subdomains = _get_subdomains( grid) local_all_neumann_boundary_info = make_subdomain_boundary_info( grid, {'type': 'xt.grid.boundaryinfo.allneumann'}) block_space = make_block_dg_space(grid) global_rt_space = make_rt_space(grid) subdomain_rt_spaces = [ global_rt_space.restrict_to_dd_subdomain_view(grid, ii) for ii in range(num_global_subdomains) ] local_patterns = [ block_space.local_space(ii).compute_pattern('face_and_volume') for ii in range(block_space.num_blocks) ] coupling_patterns = { 'in_in': {}, 'out_out': {}, 'in_out': {}, 'out_in': {} } coupling_matrices = { 'in_in': {}, 'out_out': {}, 'in_out': {}, 'out_in': {} } for ii in range(num_global_subdomains): ii_size = block_space.local_space(ii).size() for jj in grid.neighboring_subdomains(ii): jj_size = block_space.local_space(jj).size() if ii < jj: # Assemble primally (visit each coupling only once). coupling_patterns['in_in'][(ii, jj)] = block_space.local_space( ii).compute_pattern('face_and_volume') coupling_patterns['out_out'][( ii, jj)] = block_space.local_space(jj).compute_pattern( 'face_and_volume') coupling_patterns['in_out'][( ii, jj)] = block_space.compute_coupling_pattern( ii, jj, 'face') coupling_patterns['out_in'][( ii, jj)] = block_space.compute_coupling_pattern( jj, ii, 'face') coupling_matrices['in_in'][(ii, jj)] = Matrix( ii_size, ii_size, coupling_patterns['in_in'][(ii, jj)]) coupling_matrices['out_out'][(ii, jj)] = Matrix( jj_size, jj_size, coupling_patterns['out_out'][(ii, jj)]) coupling_matrices['in_out'][(ii, jj)] = Matrix( ii_size, jj_size, coupling_patterns['in_out'][(ii, jj)]) coupling_matrices['out_in'][(ii, jj)] = Matrix( jj_size, ii_size, coupling_patterns['out_in'][(ii, jj)]) boundary_patterns = {} for ii in grid.boundary_subdomains(): boundary_patterns[ii] = block_space.local_space(ii).compute_pattern( 'face_and_volume') ################ Assemble LHS and RHS lambda_, kappa = grid_and_problem_data['lambda'], grid_and_problem_data[ 'kappa'] if isinstance(lambda_, dict): lambda_funcs = lambda_['functions'] lambda_coeffs = lambda_['coefficients'] else: lambda_funcs = [ lambda_, ] lambda_coeffs = [ 1, ] logger.debug('block op ... ') ops, block_ops = zip(*(discretize_lhs( lf, grid, block_space, local_patterns, boundary_patterns, coupling_matrices, kappa, local_all_neumann_boundary_info, boundary_info, coupling_patterns, solver_options) for lf in lambda_funcs)) global_operator = LincombOperator(ops, lambda_coeffs, solver_options=solver_options, name='GlobalOperator') logger.debug('block op global done ') block_op = LincombOperator(block_ops, lambda_coeffs, name='lhs', solver_options=solver_options) logger.debug('block op done ') f = grid_and_problem_data['f'] if isinstance(f, dict): f_funcs = f['functions'] f_coeffs = f['coefficients'] else: f_funcs = [ f, ] f_coeffs = [ 1, ] rhss, block_rhss = zip(*(discretize_rhs( ff, grid, block_space, global_operator, block_ops, block_op) for ff in f_funcs)) global_rhs = LincombOperator(rhss, f_coeffs) block_rhs = LincombOperator(block_rhss, f_coeffs) solution_space = block_op.source ################ Assemble interpolation and reconstruction operators logger.info('discretizing interpolation ') # Oswald interpolation error operator oi_op = BlockDiagonalOperator([ OswaldInterpolationErrorOperator(ii, block_op.source, grid, block_space) for ii in range(num_global_subdomains) ], name='oswald_interpolation_error') # Flux reconstruction operator fr_op = LincombOperator([ BlockDiagonalOperator([ FluxReconstructionOperator(ii, block_op.source, grid, block_space, global_rt_space, subdomain_rt_spaces, lambda_xi, kappa) for ii in range(num_global_subdomains) ]) for lambda_xi in lambda_funcs ], lambda_coeffs, name='flux_reconstruction') ################ Assemble inner products and error estimator operators logger.info('discretizing inner products ') lambda_bar, lambda_hat = grid_and_problem_data[ 'lambda_bar'], grid_and_problem_data['lambda_hat'] mu_bar, mu_hat = grid_and_problem_data['mu_bar'], grid_and_problem_data[ 'mu_hat'] operators = {} local_projections = [] local_rt_projections = [] local_oi_projections = [] local_div_ops = [] local_l2_products = [] data = dict(grid=grid, block_space=block_space, local_projections=local_projections, local_rt_projections=local_rt_projections, local_oi_projections=local_oi_projections, local_div_ops=local_div_ops, local_l2_products=local_l2_products) for ii in range(num_global_subdomains): neighborhood = grid.neighborhood_of(ii) ################ Assemble local inner products local_dg_space = block_space.local_space(ii) # we want a larger pattern to allow for axpy with other matrices tmp_local_matrix = Matrix( local_dg_space.size(), local_dg_space.size(), local_dg_space.compute_pattern('face_and_volume')) local_energy_product_ops = [] local_energy_product_coeffs = [] for func, coeff in zip(lambda_funcs, lambda_coeffs): local_energy_product_ops.append( make_elliptic_matrix_operator(func, kappa, tmp_local_matrix.copy(), local_dg_space, over_integrate=0)) local_energy_product_coeffs.append(coeff) local_energy_product_ops.append( make_penalty_product_matrix_operator( grid, ii, local_all_dirichlet_boundary_info, local_dg_space, func, kappa, over_integrate=0)) local_energy_product_coeffs.append(coeff) local_l2_product = make_l2_matrix_operator(tmp_local_matrix.copy(), local_dg_space) del tmp_local_matrix local_assembler = make_system_assembler(local_dg_space) for local_product_op in local_energy_product_ops: local_assembler.append(local_product_op) local_assembler.append(local_l2_product) local_assembler.assemble() local_energy_product_name = 'local_energy_dg_product_{}'.format(ii) local_energy_product = LincombOperator([ DuneXTMatrixOperator(op.matrix(), source_id='domain_{}'.format(ii), range_id='domain_{}'.format(ii)) for op in local_energy_product_ops ], local_energy_product_coeffs, name=local_energy_product_name) operators[local_energy_product_name] = \ local_energy_product.assemble(mu_bar).with_(name=local_energy_product_name) local_l2_product = DuneXTMatrixOperator( local_l2_product.matrix(), source_id='domain_{}'.format(ii), range_id='domain_{}'.format(ii)) local_l2_products.append(local_l2_product) # assemble local elliptic product matrix = make_local_elliptic_matrix_operator(grid, ii, local_dg_space, lambda_bar, kappa) matrix.assemble() local_elliptic_product = DuneXTMatrixOperator( matrix.matrix(), range_id='domain_{}'.format(ii), source_id='domain_{}'.format(ii)) ################ Assemble local to global projections # assemble projection (solution space) -> (ii space) local_projection = BlockProjectionOperator(block_op.source, ii) local_projections.append(local_projection) # assemble projection (RT spaces on neighborhoods of subdomains) -> (local RT space on ii) ops = np.full(num_global_subdomains, None) for kk in neighborhood: component = grid.neighborhood_of(kk).index(ii) assert fr_op.range.subspaces[kk].subspaces[ component].id == 'LOCALRT_{}'.format(ii) ops[kk] = BlockProjectionOperator(fr_op.range.subspaces[kk], component) local_rt_projection = BlockRowOperator( ops, source_spaces=fr_op.range.subspaces, name='local_rt_projection_{}'.format(ii)) local_rt_projections.append(local_rt_projection) # assemble projection (OI spaces on neighborhoods of subdomains) -> (ii space) ops = np.full(num_global_subdomains, None) for kk in neighborhood: component = grid.neighborhood_of(kk).index(ii) assert oi_op.range.subspaces[kk].subspaces[ component].id == 'domain_{}'.format(ii) ops[kk] = BlockProjectionOperator(oi_op.range.subspaces[kk], component) local_oi_projection = BlockRowOperator( ops, source_spaces=oi_op.range.subspaces, name='local_oi_projection_{}'.format(ii)) local_oi_projections.append(local_oi_projection) ################ Assemble additional operators for error estimation # assemble local divergence operator local_rt_space = global_rt_space.restrict_to_dd_subdomain_view( grid, ii) local_div_op = make_divergence_matrix_operator_on_subdomain( grid, ii, local_dg_space, local_rt_space) local_div_op.assemble() local_div_op = DuneXTMatrixOperator( local_div_op.matrix(), source_id='LOCALRT_{}'.format(ii), range_id='domain_{}'.format(ii), name='local_divergence_{}'.format(ii)) local_div_ops.append(local_div_op) ################ Assemble error estimator operators -- Nonconformity operators['nc_{}'.format(ii)] = \ Concatenation([local_oi_projection.T, local_elliptic_product, local_oi_projection], name='nonconformity_{}'.format(ii)) ################ Assemble error estimator operators -- Residual if len(f_funcs) == 1: assert f_coeffs[0] == 1 local_div = Concatenation([local_div_op, local_rt_projection]) local_rhs = VectorFunctional( block_rhs.operators[0]._array._blocks[ii]) operators['r_fd_{}'.format(ii)] = \ Concatenation([local_rhs, local_div], name='r1_{}'.format(ii)) operators['r_dd_{}'.format(ii)] = \ Concatenation([local_div.T, local_l2_product, local_div], name='r2_{}'.format(ii)) ################ Assemble error estimator operators -- Diffusive flux operators['df_aa_{}'.format(ii)] = LincombOperator( [ assemble_estimator_diffusive_flux_aa( lambda_xi, lambda_xi_prime, grid, ii, block_space, lambda_hat, kappa, solution_space) for lambda_xi in lambda_funcs for lambda_xi_prime in lambda_funcs ], [ ProductParameterFunctional([c1, c2]) for c1 in lambda_coeffs for c2 in lambda_coeffs ], name='diffusive_flux_aa_{}'.format(ii)) operators['df_bb_{}'.format( ii)] = assemble_estimator_diffusive_flux_bb( grid, ii, subdomain_rt_spaces, lambda_hat, kappa, local_rt_projection) operators['df_ab_{}'.format(ii)] = LincombOperator( [ assemble_estimator_diffusive_flux_ab( lambda_xi, grid, ii, block_space, subdomain_rt_spaces, lambda_hat, kappa, local_rt_projection, local_projection) for lambda_xi in lambda_funcs ], lambda_coeffs, name='diffusive_flux_ab_{}'.format(ii)) ################ Final assembly logger.info('final assembly ') # instantiate error estimator min_diffusion_evs = np.array([ min_diffusion_eigenvalue(grid, ii, lambda_hat, kappa) for ii in range(num_global_subdomains) ]) subdomain_diameters = np.array( [subdomain_diameter(grid, ii) for ii in range(num_global_subdomains)]) if len(f_funcs) == 1: assert f_coeffs[0] == 1 local_eta_rf_squared = np.array([ apply_l2_product(grid, ii, f_funcs[0], f_funcs[0], over_integrate=2) for ii in range(num_global_subdomains) ]) else: local_eta_rf_squared = None estimator = EllipticEstimator(grid, min_diffusion_evs, subdomain_diameters, local_eta_rf_squared, lambda_coeffs, mu_bar, mu_hat, fr_op, oswald_interpolation_error=oi_op, mpi_comm=mpi_comm) l2_product = BlockDiagonalOperator(local_l2_products) # instantiate discretization neighborhoods = [ grid.neighborhood_of(ii) for ii in range(num_global_subdomains) ] local_boundary_info = make_subdomain_boundary_info( grid_and_problem_data['grid'], {'type': 'xt.grid.boundaryinfo.alldirichlet'}) d = DuneDiscretization(global_operator=global_operator, global_rhs=global_rhs, neighborhoods=neighborhoods, enrichment_data=(grid, local_boundary_info, lambda_, kappa, f, block_space), operator=block_op, rhs=block_rhs, visualizer=DuneGDTVisualizer(block_space), operators=operators, products={'l2': l2_product}, estimator=estimator, data=data) parameter_range = grid_and_problem_data['parameter_range'] logger.info('final assembly B') d = d.with_(parameter_space=CubicParameterSpace( d.parameter_type, parameter_range[0], parameter_range[1])) logger.info('final assembly C') return d, data
if __name__ == '__main__': argvs = sys.argv parser = OptionParser() parser.add_option("--dir", dest="dir", default="./") opt, argc = parser.parse_args(argvs) print(opt, argc) rhs = ExpressionFunction('(x[..., 0] - 0.5)**2 * 1000', 2, ()) problem = StationaryProblem( domain=RectDomain(), rhs=rhs, diffusion=LincombFunction( [ExpressionFunction('1 - x[..., 0]', 2, ()), ExpressionFunction('x[..., 0]', 2, ())], [ProjectionParameterFunctional( 'diffusionl', 0), ExpressionParameterFunctional('1', {})] ), parameter_space=CubicParameterSpace({'diffusionl': 0}, 0.01, 0.1), name='2DProblem' ) args = {'N': 100, 'samples': 10} m, data = discretize_stationary_cg(problem, diameter=1. / args['N']) U = m.solution_space.empty() for mu in m.parameter_space.sample_uniformly(args['samples']): U.append(m.solve(mu)) Us = U * 1.5 plot = m.visualize((U, Us), title='Solution for diffusionl=0.5')
def space(): return CubicParameterSpace({'diffusionl': 1}, 0.1, 1)
def discretize(DIM, N, ORDER): # ### problem definition import dolfin as df if DIM == 2: mesh = df.UnitSquareMesh(N, N) elif DIM == 3: mesh = df.UnitCubeMesh(N, N, N) else: raise NotImplementedError V = df.FunctionSpace(mesh, "CG", ORDER) g = df.Constant(1.0) c = df.Constant(1.) class DirichletBoundary(df.SubDomain): def inside(self, x, on_boundary): return abs(x[0] - 1.0) < df.DOLFIN_EPS and on_boundary db = DirichletBoundary() bc = df.DirichletBC(V, g, db) u = df.Function(V) v = df.TestFunction(V) f = df.Expression("x[0]*sin(x[1])", degree=2) F = df.inner( (1 + c * u**2) * df.grad(u), df.grad(v)) * df.dx - f * v * df.dx df.solve(F == 0, u, bc, solver_parameters={"newton_solver": { "relative_tolerance": 1e-6 }}) # ### pyMOR wrapping from pymor.bindings.fenics import FenicsVectorSpace, FenicsOperator, FenicsVisualizer from pymor.models.basic import StationaryModel from pymor.operators.constructions import VectorOperator from pymor.parameters.spaces import CubicParameterSpace space = FenicsVectorSpace(V) op = FenicsOperator( F, space, space, u, (bc, ), parameter_setter=lambda mu: c.assign(float(mu['c'])), parameter_type={'c': ()}, solver_options={'inverse': { 'type': 'newton', 'rtol': 1e-6 }}) rhs = VectorOperator(op.range.zeros()) fom = StationaryModel(op, rhs, visualizer=FenicsVisualizer(space), parameter_space=CubicParameterSpace({'c': ()}, 0., 1000.)) return fom
def discretize(grid_and_problem_data, polorder=1, solver_options=None): logger = getLogger('discretize_elliptic_swipdg.discretize') logger.info('discretizing ... ') over_integrate = 2 grid, boundary_info = grid_and_problem_data['grid'], grid_and_problem_data[ 'boundary_info'] _lambda, kappa, f = (grid_and_problem_data['lambda'], grid_and_problem_data['kappa'], grid_and_problem_data['f']) lambda_bar, lambda_bar = grid_and_problem_data[ 'lambda_bar'], grid_and_problem_data['lambda_bar'] mu_bar, mu_hat, parameter_range = ( grid_and_problem_data['mu_bar'], grid_and_problem_data['mu_hat'], grid_and_problem_data['parameter_range']) space = make_dg_space(grid) # prepare operators and functionals if isinstance(_lambda, dict): system_ops = [ make_elliptic_swipdg_matrix_operator(lambda_func, kappa, boundary_info, space, over_integrate) for lambda_func in _lambda['functions'] ] elliptic_ops = [ make_elliptic_matrix_operator(lambda_func, kappa, space, over_integrate) for lambda_func in _lambda['functions'] ] else: system_ops = [ make_elliptic_swipdg_matrix_operator(_lambda, kappa, boundary_info, space, over_integrate), ] elliptic_ops = [ make_elliptic_matrix_operator(_lambda, kappa, space, over_integrate), ] if isinstance(f, dict): rhs_functionals = [ make_l2_volume_vector_functional(f_func, space, over_integrate) for f_func in f['functions'] ] else: rhs_functionals = [ make_l2_volume_vector_functional(f, space, over_integrate), ] l2_matrix_with_system_pattern = system_ops[0].matrix().copy() l2_operator = make_l2_matrix_operator(l2_matrix_with_system_pattern, space) # assemble everything in one grid walk system_assembler = make_system_assembler(space) for op in system_ops: system_assembler.append(op) for op in elliptic_ops: system_assembler.append(op) for func in rhs_functionals: system_assembler.append(func) system_assembler.append(l2_operator) system_assembler.walk() # wrap everything if isinstance(_lambda, dict): op = LincombOperator([ DuneXTMatrixOperator(o.matrix(), dof_communicator=space.dof_communicator) for o in system_ops ], _lambda['coefficients']) elliptic_op = LincombOperator( [DuneXTMatrixOperator(o.matrix()) for o in elliptic_ops], _lambda['coefficients']) else: op = DuneXTMatrixOperator(system_ops[0].matrix()) elliptic_op = DuneXTMatrixOperator(elliptic_ops[0].matrix()) if isinstance(f, dict): rhs = LincombOperator([ VectorFunctional(op.range.make_array([func.vector()])) for func in rhs_functionals ], f['coefficients']) else: rhs = VectorFunctional( op.range.make_array([rhs_functionals[0].vector()])) operators = { 'l2': DuneXTMatrixOperator(l2_matrix_with_system_pattern), 'elliptic': elliptic_op, 'elliptic_mu_bar': DuneXTMatrixOperator(elliptic_op.assemble(mu=mu_bar).matrix) } d = StationaryDiscretization(op, rhs, operators=operators, visualizer=DuneGDTVisualizer(space)) d = d.with_(parameter_space=CubicParameterSpace( d.parameter_type, parameter_range[0], parameter_range[1])) return d, {'space': space}
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 thermalblock_demo(args): args['--grid'] = int(args['--grid']) args['RBSIZE'] = int(args['RBSIZE']) args['--test'] = int(args['--test']) args['--ipython-engines'] = int(args['--ipython-engines']) args['--extension-alg'] = args['--extension-alg'].lower() assert args['--extension-alg'] in {'trivial', 'gram_schmidt'} args['--product'] = args['--product'].lower() assert args['--product'] in {'trivial', 'h1'} args['--reductor'] = args['--reductor'].lower() assert args['--reductor'] in {'traditional', 'residual_basis'} args['--cache-region'] = args['--cache-region'].lower() args['--validation-mus'] = int(args['--validation-mus']) args['--rho'] = float(args['--rho']) args['--gamma'] = float(args['--gamma']) args['--theta'] = float(args['--theta']) problem = thermal_block_problem(num_blocks=(2, 2)) functionals = [ ExpressionParameterFunctional('diffusion[0]', {'diffusion': (2, )}), ExpressionParameterFunctional('diffusion[1]**2', {'diffusion': (2, )}), ExpressionParameterFunctional('diffusion[0]', {'diffusion': (2, )}), ExpressionParameterFunctional('diffusion[1]', {'diffusion': (2, )}) ] problem = problem.with_( diffusion=problem.diffusion.with_(coefficients=functionals), parameter_space=CubicParameterSpace({'diffusion': (2, )}, 0.1, 1.)) print('Discretize ...') fom, _ = discretize_stationary_cg(problem, diameter=1. / args['--grid']) if args['--list-vector-array']: from pymor.playground.discretizers.numpylistvectorarray import convert_to_numpy_list_vector_array fom = convert_to_numpy_list_vector_array(fom) if args['--cache-region'] != 'none': fom.enable_caching(args['--cache-region']) if args['--plot-solutions']: print('Showing some solutions') Us = () legend = () for mu in fom.parameter_space.sample_randomly(2): print(f"Solving for diffusion = \n{mu['diffusion']} ... ") sys.stdout.flush() Us = Us + (fom.solve(mu), ) legend = legend + (str(mu['diffusion']), ) fom.visualize(Us, legend=legend, title='Detailed Solutions for different parameters', block=True) print('RB generation ...') product = fom.h1_0_semi_product if args['--product'] == 'h1' else None coercivity_estimator = ExpressionParameterFunctional( 'min([diffusion[0], diffusion[1]**2])', fom.parameter_type) reductors = { 'residual_basis': CoerciveRBReductor(fom, product=product, coercivity_estimator=coercivity_estimator), 'traditional': SimpleCoerciveRBReductor(fom, product=product, coercivity_estimator=coercivity_estimator) } reductor = reductors[args['--reductor']] pool = new_parallel_pool(ipython_num_engines=args['--ipython-engines'], ipython_profile=args['--ipython-profile']) greedy_data = rb_adaptive_greedy( fom, reductor, validation_mus=args['--validation-mus'], rho=args['--rho'], gamma=args['--gamma'], theta=args['--theta'], use_estimator=not args['--without-estimator'], error_norm=fom.h1_0_semi_norm, max_extensions=args['RBSIZE'], visualize=not args['--no-visualize-refinement']) rom = greedy_data['rom'] if args['--pickle']: print( f"\nWriting reduced model to file {args['--pickle']}_reduced ...") with open(args['--pickle'] + '_reduced', 'wb') as f: dump(rom, f) print( f"Writing detailed model and reductor to file {args['--pickle']}_detailed ..." ) with open(args['--pickle'] + '_detailed', 'wb') as f: dump((fom, reductor), f) print('\nSearching for maximum error on random snapshots ...') results = reduction_error_analysis( rom, fom=fom, reductor=reductor, estimator=True, error_norms=(fom.h1_0_semi_norm, ), condition=True, test_mus=args['--test'], basis_sizes=25 if args['--plot-error-sequence'] else 1, plot=True, pool=pool) real_rb_size = rom.solution_space.dim print(''' *** RESULTS *** Problem: number of blocks: 2x2 h: sqrt(2)/{args[--grid]} Greedy basis generation: estimator disabled: {args[--without-estimator]} extension method: {args[--extension-alg]} product: {args[--product]} prescribed basis size: {args[RBSIZE]} actual basis size: {real_rb_size} elapsed time: {greedy_data[time]} '''.format(**locals())) print(results['summary']) sys.stdout.flush() if args['--plot-error-sequence']: from matplotlib import pyplot as plt plt.show(results['figure']) if args['--plot-err']: mumax = results['max_error_mus'][0, -1] U = fom.solve(mumax) URB = reductor.reconstruct(rom.solve(mumax)) fom.visualize( (U, URB, U - URB), legend=('Detailed Solution', 'Reduced Solution', 'Error'), title='Maximum Error Solution', separate_colorbars=True, block=True)
def discretize_stationary_from_disk(parameter_file): """Generates stationary discretization only based on data 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:: L(u, w) = F(w) with an operator L and a linear functional F with a parameter w given as system matrices and rhs vectors in an affine decomposition on the hard disk. Parameters ---------- parameterFile String containing the path to the .ini parameter file. Returns ------- discretization The |Discretization| that has been generated. Example ------- Following parameter file is suitable for a discrete elliptic problem with L(u, w) = (f_1(w)*K1 + f_2(w)*K2+...)*u and F(w) = g_1(w)*L1+g_2(w)*L2+... 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. 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) ... [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 ... """ 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 'rhs-vectors' in config.sections() assert 'parameter' in config.sections() system_mat = config.items('system-matrices') 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 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 # Create and return stationary discretization return StationaryDiscretization(operator=system_lincombOperator, rhs=rhs_lincombOperator, parameter_space=parameter_space, products=products)
def text_problem(text='pyMOR', font_name=None): import numpy as np from PIL import Image, ImageDraw, ImageFont from tempfile import NamedTemporaryFile font_list = [font_name] if font_name else [ 'DejaVuSansMono.ttf', 'VeraMono.ttf', 'UbuntuMono-R.ttf', 'Arial.ttf' ] font = None for filename in font_list: try: font = ImageFont.truetype( filename, 64) # load some font from file of given size except (OSError, IOError): pass if font is None: raise ValueError('Could not load TrueType font') size = font.getsize(text) # compute width and height of rendered text size = (size[0] + 20, size[1] + 20 ) # add a border of 10 pixels around the text def make_bitmap_function( char_num ): # we need to genereate a BitmapFunction for each character img = Image.new('L', size) # create new Image object of given dimensions d = ImageDraw.Draw(img) # create ImageDraw object for the given Image # in order to position the character correctly, we first draw all characters from the first # up to the wanted character d.text((10, 10), text[:char_num + 1], font=font, fill=255) # next we erase all previous character by drawing a black rectangle if char_num > 0: d.rectangle( ((0, 0), (font.getsize(text[:char_num])[0] + 10, size[1])), fill=0, outline=0) # open a new temporary file with NamedTemporaryFile( suffix='.png' ) as f: # after leaving this 'with' block, the temporary # file is automatically deleted img.save(f, format='png') return BitmapFunction(f.name, bounding_box=[(0, 0), size], range=[0., 1.]) # create BitmapFunctions for each character dfs = [make_bitmap_function(n) for n in range(len(text))] # create an indicator function for the background background = ConstantFunction(1., 2) - LincombFunction( dfs, np.ones(len(dfs))) # form the linear combination dfs = [background] + dfs coefficients = [1] + [ ProjectionParameterFunctional('diffusion', (len(text), ), (i, )) for i in range(len(text)) ] diffusion = LincombFunction(dfs, coefficients) return StationaryProblem(domain=RectDomain(dfs[1].bounding_box, bottom='neumann'), neumann_data=ConstantFunction(-1., 2), diffusion=diffusion, parameter_space=CubicParameterSpace( diffusion.parameter_type, 0.1, 1.))
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 }
def thermal_block_problem(num_blocks=(3, 3), parameter_range=(0.1, 1)): """Analytical description of a 2D 'thermal block' diffusion problem. The problem is to solve the elliptic equation :: - ∇ ⋅ [ d(x, μ) ∇ u(x, μ) ] = f(x, μ) on the domain [0,1]^2 with Dirichlet zero boundary values. The domain is partitioned into nx x ny blocks and the diffusion function d(x, μ) is constant on each such block (i,j) with value μ_ij. :: ---------------------------- | | | | | μ_11 | μ_12 | μ_13 | | | | | |--------------------------- | | | | | μ_21 | μ_22 | μ_23 | | | | | ---------------------------- Parameters ---------- num_blocks The tuple `(nx, ny)` parameter_range A tuple `(μ_min, μ_max)`. Each |Parameter| component μ_ij is allowed to lie in the interval [μ_min, μ_max]. """ def parameter_functional_factory(ix, iy): return ProjectionParameterFunctional(component_name='diffusion', component_shape=(num_blocks[1], num_blocks[0]), index=(num_blocks[1] - iy - 1, ix), name=f'diffusion_{ix}_{iy}') def diffusion_function_factory(ix, iy): if ix + 1 < num_blocks[0]: X = '(x[..., 0] >= ix * dx) * (x[..., 0] < (ix + 1) * dx)' else: X = '(x[..., 0] >= ix * dx)' if iy + 1 < num_blocks[1]: Y = '(x[..., 1] >= iy * dy) * (x[..., 1] < (iy + 1) * dy)' else: Y = '(x[..., 1] >= iy * dy)' return ExpressionFunction(f'{X} * {Y} * 1.', 2, (), {}, {'ix': ix, 'iy': iy, 'dx': 1. / num_blocks[0], 'dy': 1. / num_blocks[1]}, name=f'diffusion_{ix}_{iy}') return StationaryProblem( domain=RectDomain(), rhs=ConstantFunction(dim_domain=2, value=1.), diffusion=LincombFunction([diffusion_function_factory(ix, iy) for ix, iy in product(range(num_blocks[0]), range(num_blocks[1]))], [parameter_functional_factory(ix, iy) for ix, iy in product(range(num_blocks[0]), range(num_blocks[1]))], name='diffusion'), parameter_space=CubicParameterSpace({'diffusion': (num_blocks[1], num_blocks[0])}, *parameter_range), name=f'ThermalBlock({num_blocks})' )
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 norm(U): return np.max(nonblocked_disc.h1_norm(U)) class Reconstructor(object): def __init__(self, disc, RB):