def elliptic_gmsh_demo(args): args['ANGLE'] = float(args['ANGLE']) args['NUM_POINTS'] = int(args['NUM_POINTS']) args['CLSCALE'] = float(args['CLSCALE']) problem = StationaryProblem( domain=CircularSectorDomain(args['ANGLE'], radius=1, num_points=args['NUM_POINTS']), diffusion=ConstantFunction(1, dim_domain=2), rhs=ConstantFunction(np.array(0.), dim_domain=2, name='rhs'), dirichlet_data=ExpressionFunction('sin(polar(x)[1] * pi/angle)', 2, (), {}, {'angle': args['ANGLE']}, name='dirichlet') ) print('Discretize ...') m, data = discretize_stationary_cg(analytical_problem=problem, diameter=args['CLSCALE']) grid = data['grid'] print(grid) print() print('Solve ...') U = m.solve() solution = ExpressionFunction('(lambda r, phi: r**(pi/angle) * sin(phi * pi/angle))(*polar(x))', 2, (), {}, {'angle': args['ANGLE']}) U_ref = U.space.make_array(solution(grid.centers(2))) m.visualize((U, U_ref, U-U_ref), legend=('Solution', 'Analytical solution (circular boundary)', 'Error'), separate_colorbars=True)
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': 1}, {'v': np.array([vx, vy])}), nonlinear_advection_derivative=ExpressionFunction( "exponent * abs(x)**(exponent-1) * sign(x) * v", 1, (2, ), {'exponent': 1}, {'v': np.array([vx, vy])}), ), initial_data=initial_data, T=0.3, parameter_ranges=parameter_range, name=f"burgers_problem_2d({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[0] * v', 1, (1, ), {'exponent': 1}, {'v': v}), nonlinear_advection_derivative=ExpressionFunction( 'exponent * abs(x)**(exponent[0]-1) * sign(x) * v', 1, (1, ), {'exponent': 1}, {'v': v}), ), T=0.3, initial_data=initial_data, parameter_ranges={'exponent': parameter_range}, name=f"burgers_problem({v}, {circle}, '{initial_data_type}')")
def main( problem_number: int = Argument( ..., min=0, max=1, help='Selects the problem to solve [0 or 1].'), n: int = Argument(..., help='Grid interval count.'), fv: bool = Option( False, help='Use finite volume discretization instead of finite elements.'), ): """Solves the Poisson equation in 1D using pyMOR's builtin discreization toolkit.""" rhss = [ ExpressionFunction('ones(x.shape[:-1]) * 10', 1, ()), ExpressionFunction('(x - 0.5)**2 * 1000', 1, ()) ] rhs = rhss[problem_number] d0 = ExpressionFunction('1 - x', 1, ()) d1 = ExpressionFunction('x', 1, ()) f0 = ProjectionParameterFunctional('diffusionl') f1 = 1. problem = StationaryProblem(domain=LineDomain(), rhs=rhs, diffusion=LincombFunction([d0, d1], [f0, f1]), dirichlet_data=ConstantFunction(value=0, dim_domain=1), name='1DProblem') parameter_space = problem.parameters.space(0.1, 1) print('Discretize ...') discretizer = discretize_stationary_fv if fv else discretize_stationary_cg m, data = discretizer(problem, diameter=1 / n) print(data['grid']) print() print('Solve ...') U = m.solution_space.empty() for mu in parameter_space.sample_uniformly(10): U.append(m.solve(mu)) m.visualize(U, title='Solution for diffusionl in [0.1, 1]')
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}')
def main( angle: float = Argument(..., help='The angle of the circular sector.'), num_points: int = Argument( ..., help='The number of points that form the arc of the circular sector.'), clscale: float = Argument(..., help='Mesh element size scaling factor.'), ): """Solves the Poisson equation in 2D on a circular sector domain of radius 1 using an unstructured mesh. Note that Gmsh (http://geuz.org/gmsh/) is required for meshing. """ problem = StationaryProblem( domain=CircularSectorDomain(angle, radius=1, num_points=num_points), diffusion=ConstantFunction(1, dim_domain=2), rhs=ConstantFunction(np.array(0.), dim_domain=2, name='rhs'), dirichlet_data=ExpressionFunction('sin(polar(x)[1] * pi/angle)', 2, (), {}, {'angle': angle}, name='dirichlet')) print('Discretize ...') m, data = discretize_stationary_cg(analytical_problem=problem, diameter=clscale) grid = data['grid'] print(grid) print() print('Solve ...') U = m.solve() solution = ExpressionFunction( '(lambda r, phi: r**(pi/angle) * sin(phi * pi/angle))(*polar(x))', 2, (), {}, {'angle': angle}) U_ref = U.space.make_array(solution(grid.centers(2))) m.visualize((U, U_ref, U - U_ref), legend=('Solution', 'Analytical solution (circular boundary)', 'Error'), separate_colorbars=True)
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, ()) f0 = ProjectionParameterFunctional('diffusionl') f1 = 1. problem = StationaryProblem(domain=LineDomain(), rhs=rhs, diffusion=LincombFunction([d0, d1], [f0, f1]), dirichlet_data=ConstantFunction(value=0, dim_domain=1), name='1DProblem') parameter_space = problem.parameters.space(0.1, 1) 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 parameter_space.sample_uniformly(10): U.append(m.solve(mu)) m.visualize(U, title='Solution for diffusionl in [0.1, 1]')
def elliptic_demo(args): args['PROBLEM-NUMBER'] = int(args['PROBLEM-NUMBER']) assert 0 <= args['PROBLEM-NUMBER'] <= 1, ValueError('Invalid problem number') args['DIRICHLET-NUMBER'] = int(args['DIRICHLET-NUMBER']) assert 0 <= args['DIRICHLET-NUMBER'] <= 2, ValueError('Invalid Dirichlet boundary number.') args['NEUMANN-NUMBER'] = int(args['NEUMANN-NUMBER']) assert 0 <= args['NEUMANN-NUMBER'] <= 2, ValueError('Invalid Neumann boundary number.') args['NEUMANN-COUNT'] = int(args['NEUMANN-COUNT']) assert 0 <= args['NEUMANN-COUNT'] <= 3, ValueError('Invalid Neumann boundary count.') rhss = [ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), ExpressionFunction('(x[..., 0] - 0.5) ** 2 * 1000', 2, ())] dirichlets = [ExpressionFunction('zeros(x.shape[:-1])', 2, ()), ExpressionFunction('ones(x.shape[:-1])', 2, ()), ExpressionFunction('x[..., 0]', 2, ())] neumanns = [None, ConstantFunction(3., dim_domain=2), ExpressionFunction('50*(0.1 <= x[..., 1]) * (x[..., 1] <= 0.2)' '+50*(0.8 <= x[..., 1]) * (x[..., 1] <= 0.9)', 2, ())] domains = [RectDomain(), RectDomain(right='neumann'), RectDomain(right='neumann', top='neumann'), RectDomain(right='neumann', top='neumann', bottom='neumann')] rhs = rhss[args['PROBLEM-NUMBER']] dirichlet = dirichlets[args['DIRICHLET-NUMBER']] neumann = neumanns[args['NEUMANN-NUMBER']] domain = domains[args['NEUMANN-COUNT']] problem = StationaryProblem( domain=domain, diffusion=ConstantFunction(1, dim_domain=2), rhs=rhs, dirichlet_data=dirichlet, neumann_data=neumann ) for n in [32, 128]: print('Discretize ...') discretizer = discretize_stationary_fv if args['--fv'] else discretize_stationary_cg m, data = discretizer( analytical_problem=problem, grid_type=RectGrid if args['--rect'] else TriaGrid, diameter=np.sqrt(2) / n if args['--rect'] else 1. / n ) grid = data['grid'] print(grid) print() print('Solve ...') U = m.solve() m.visualize(U, title=repr(grid)) print()
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.1]) ] dirichlets = [ ExpressionFunction('zeros(x.shape[:-1])', 2, ()), LincombFunction([ ExpressionFunction('2 * x[..., 0]', 2, ()), ConstantFunction(1., 2) ], [ProjectionParameterFunctional('mu'), 0.5]) ] neumanns = [ None, LincombFunction([ ExpressionFunction('1 - x[..., 1]', 2, ()), ConstantFunction(1., 2) ], [ProjectionParameterFunctional('mu'), 0.5**2]) ] robins = [ None, (LincombFunction( [ExpressionFunction('x[..., 1]', 2, ()), ConstantFunction(1., 2)], [ProjectionParameterFunctional('mu'), 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=domain, rhs=rhs, diffusion=LincombFunction([ ExpressionFunction('1 - x[..., 0]', 2, ()), ExpressionFunction('x[..., 0]', 2, ()) ], [ProjectionParameterFunctional('mu'), 1]), dirichlet_data=dirichlet, neumann_data=neumann, robin_data=robin, parameter_ranges=(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 problem.parameter_space.sample_uniformly(10): U.append(m.solve(mu)) m.visualize(U, title='Solution for mu 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']) norm = args['NORM'] norm = float(norm) if not norm.lower() in ('h1', 'l2') else norm.lower() rhss = [ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), LincombFunction( [ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), ConstantFunction(1.,2)], [ProjectionParameterFunctional('mu'), 0.1])] dirichlets = [ExpressionFunction('zeros(x.shape[:-1])', 2, ()), LincombFunction( [ExpressionFunction('2 * x[..., 0]', 2, ()), ConstantFunction(1.,2)], [ProjectionParameterFunctional('mu'), 0.5])] neumanns = [None, LincombFunction( [ExpressionFunction('1 - x[..., 1]', 2, ()), ConstantFunction(1.,2)], [ProjectionParameterFunctional('mu'), 0.5**2])] robins = [None, (LincombFunction( [ExpressionFunction('x[..., 1]', 2, ()), ConstantFunction(1.,2)], [ProjectionParameterFunctional('mu'), 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=domain, rhs=rhs, diffusion=LincombFunction( [ExpressionFunction('1 - x[..., 0]', 2, ()), ExpressionFunction('x[..., 0]', 2, ())], [ProjectionParameterFunctional('mu'), 1] ), dirichlet_data=dirichlet, neumann_data=neumann, robin_data=robin, parameter_ranges=(0.1, 1), name='2DProblem' ) if isinstance(norm, float) and not args['--fv']: # use a random parameter to construct an energy product mu_bar = problem.parameters.parse(norm) else: mu_bar = None print('Discretize ...') if args['--fv']: m, data = discretize_stationary_fv(problem, diameter=1. / args['N']) else: m, data = discretize_stationary_cg(problem, diameter=1. / args['N'], mu_energy_product=mu_bar) print(data['grid']) print() print('Solve ...') U = m.solution_space.empty() for mu in problem.parameter_space.sample_uniformly(10): U.append(m.solve(mu)) if mu_bar is not None: # use the given energy product norm_squared = U[-1].norm(m.products['energy'])[0] print('Energy norm of the last snapshot: ', np.sqrt(norm_squared)) if not args['--fv']: if args['NORM'] == 'h1': norm_squared = U[-1].norm(m.products['h1_0_semi'])[0] print('H^1_0 semi norm of the last snapshot: ', np.sqrt(norm_squared)) if args['NORM'] == 'l2': norm_squared = U[-1].norm(m.products['l2_0'])[0] print('L^2_0 norm of the last snapshot: ', np.sqrt(norm_squared)) m.visualize(U, title='Solution for mu in [0.1, 1]')
def main( problem_number: int = Argument(..., min=0, max=1, help='Selects the problem to solve [0 or 1].'), n: int = Argument(..., help='Triangle count per direction'), norm: str = Argument( ..., help="h1: compute the h1-norm of the last snapshot.\n\n" "l2: compute the l2-norm of the last snapshot.\n\n" "k: compute the energy norm of the last snapshot, where the energy-product" "is constructed with a parameter {'mu': k}." ), fv: bool = Option(False, help='Use finite volume discretization instead of finite elements.'), ): """Solves the Poisson equation in 2D using pyMOR's builtin discreization toolkit.""" norm = float(norm) if not norm.lower() in ('h1', 'l2') else norm.lower() rhss = [ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), LincombFunction( [ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), ConstantFunction(1., 2)], [ProjectionParameterFunctional('mu'), 0.1])] dirichlets = [ExpressionFunction('zeros(x.shape[:-1])', 2, ()), LincombFunction( [ExpressionFunction('2 * x[..., 0]', 2, ()), ConstantFunction(1., 2)], [ProjectionParameterFunctional('mu'), 0.5])] neumanns = [None, LincombFunction( [ExpressionFunction('1 - x[..., 1]', 2, ()), ConstantFunction(1., 2)], [ProjectionParameterFunctional('mu'), 0.5**2])] robins = [None, (LincombFunction( [ExpressionFunction('x[..., 1]', 2, ()), ConstantFunction(1., 2)], [ProjectionParameterFunctional('mu'), 1]), ConstantFunction(1., 2))] domains = [RectDomain(), RectDomain(right='neumann', top='dirichlet', bottom='robin')] rhs = rhss[problem_number] dirichlet = dirichlets[problem_number] neumann = neumanns[problem_number] domain = domains[problem_number] robin = robins[problem_number] problem = StationaryProblem( domain=domain, rhs=rhs, diffusion=LincombFunction( [ExpressionFunction('1 - x[..., 0]', 2, ()), ExpressionFunction('x[..., 0]', 2, ())], [ProjectionParameterFunctional('mu'), 1] ), dirichlet_data=dirichlet, neumann_data=neumann, robin_data=robin, parameter_ranges=(0.1, 1), name='2DProblem' ) if isinstance(norm, float) and not fv: # use a random parameter to construct an energy product mu_bar = problem.parameters.parse(norm) else: mu_bar = None print('Discretize ...') if fv: m, data = discretize_stationary_fv(problem, diameter=1. / n) else: m, data = discretize_stationary_cg(problem, diameter=1. / n, mu_energy_product=mu_bar) print(data['grid']) print() print('Solve ...') U = m.solution_space.empty() for mu in problem.parameter_space.sample_uniformly(10): U.append(m.solve(mu)) if mu_bar is not None: # use the given energy product norm_squared = U[-1].norm(m.products['energy'])[0] print('Energy norm of the last snapshot: ', np.sqrt(norm_squared)) if not fv: if norm == 'h1': norm_squared = U[-1].norm(m.products['h1_0_semi'])[0] print('H^1_0 semi norm of the last snapshot: ', np.sqrt(norm_squared)) if norm == 'l2': norm_squared = U[-1].norm(m.products['l2_0'])[0] print('L^2_0 norm of the last snapshot: ', np.sqrt(norm_squared)) m.visualize(U, title='Solution for mu in [0.1, 1]')
return function_with_closure generic_functions = \ [GenericFunction(lambda x: x, dim_domain=2, shape_range=(2,)), GenericFunction(lambda x, mu: mu['c'][0]*x, dim_domain=1, shape_range=(1,), parameters={'c': 1}), GenericFunction(A.unimportable_function, dim_domain=7, shape_range=()), GenericFunction(get_function_with_closure(42), dim_domain=1, shape_range=(2,))] picklable_generic_functions = \ [GenericFunction(importable_function, dim_domain=3, shape_range=(1,))] expression_functions = \ [ExpressionFunction('x', dim_domain=2, shape_range=(2,)), ExpressionFunction("c[0]*x", dim_domain=1, shape_range=(1,), parameters={'c': 1}), ExpressionFunction("c[2]*sin(x)", dim_domain=1, shape_range=(1,), parameters={'c': 3})] @pytest.fixture(params=constant_functions + generic_functions + picklable_generic_functions + expression_functions) def function(request): return request.param @pytest.fixture(params=constant_functions + picklable_generic_functions + expression_functions) def picklable_function(request): return request.param
def main( problem_number: int = Argument( ..., min=0, max=1, help='Selects the problem to solve [0 or 1].'), dirichlet_number: int = Argument( ..., min=0, max=2, help='Selects the Dirichlet data function [0 to 2].'), neumann_number: int = Argument( ..., min=0, max=2, help='Selects the Neumann data function.'), neumann_count: int = Argument( ..., min=0, max=3, help='0: no neumann boundary\n\n' '1: right edge is neumann boundary\n\n' '2: right+top edges are neumann boundary\n\n' '3: right+top+bottom edges are neumann boundary\n\n'), fv: bool = Option( False, help='Use finite volume discretization instead of finite elements.' ), rect: bool = Option(False, help='Use RectGrid instead of TriaGrid.'), ): """Solves the Poisson equation in 2D using pyMOR's builtin discreization toolkit.""" rhss = [ ExpressionFunction('ones(x.shape[:-1]) * 10', 2, ()), ExpressionFunction('(x[..., 0] - 0.5) ** 2 * 1000', 2, ()) ] dirichlets = [ ExpressionFunction('zeros(x.shape[:-1])', 2, ()), ExpressionFunction('ones(x.shape[:-1])', 2, ()), ExpressionFunction('x[..., 0]', 2, ()) ] neumanns = [ None, ConstantFunction(3., dim_domain=2), ExpressionFunction( '50*(0.1 <= x[..., 1]) * (x[..., 1] <= 0.2)' '+50*(0.8 <= x[..., 1]) * (x[..., 1] <= 0.9)', 2, ()) ] domains = [ RectDomain(), RectDomain(right='neumann'), RectDomain(right='neumann', top='neumann'), RectDomain(right='neumann', top='neumann', bottom='neumann') ] rhs = rhss[problem_number] dirichlet = dirichlets[dirichlet_number] neumann = neumanns[neumann_number] domain = domains[neumann_count] problem = StationaryProblem(domain=domain, diffusion=ConstantFunction(1, dim_domain=2), rhs=rhs, dirichlet_data=dirichlet, neumann_data=neumann) for n in [32, 128]: print('Discretize ...') discretizer = discretize_stationary_fv if fv else discretize_stationary_cg m, data = discretizer(analytical_problem=problem, grid_type=RectGrid if rect else TriaGrid, diameter=np.sqrt(2) / n if rect else 1. / n) grid = data['grid'] print(grid) print() print('Solve ...') U = m.solve() m.visualize(U, title=repr(grid)) print()
return function_with_closure generic_functions = \ [GenericFunction(lambda x: x, dim_domain=2, shape_range=(2,)), GenericFunction(lambda x, mu: mu['c']*x, dim_domain=1, shape_range=(1,), parameter_type={'c': ()}), GenericFunction(A.unimportable_function, dim_domain=7, shape_range=()), GenericFunction(get_function_with_closure(42), dim_domain=1, shape_range=(2,))] picklable_generic_functions = \ [GenericFunction(importable_function, dim_domain=3, shape_range=(1,))] expression_functions = \ [ExpressionFunction('x', dim_domain=2, shape_range=(2,)), ExpressionFunction("c*x", dim_domain=1, shape_range=(1,), parameter_type={'c': ()}), ExpressionFunction("c[2]*sin(x)", dim_domain=1, shape_range=(1,), parameter_type={'c': (3,)})] @pytest.fixture(params=constant_functions + generic_functions + picklable_generic_functions + expression_functions) def function(request): return request.param @pytest.fixture(params=constant_functions + picklable_generic_functions + expression_functions) def picklable_function(request): return request.param
def main( diameter: float = Argument( 0.1, help='Diameter option for the domain discretizer.'), r: int = Argument(5, help='Order of the ROMs.'), ): r"""2D heat equation demo. Discretization of the PDE: .. math:: :nowrap: \begin{align*} \partial_t z(x, y, t) &= \Delta z(x, y, t), & 0 < x, y < 1,\ t > 0 \\ -\nabla z(0, y, t) \cdot n &= z(0, y, t) - u(t), & 0 < y < 1, t > 0 \\ -\nabla z(1, y, t) \cdot n &= z(1, y, t), & 0 < y < 1, t > 0 \\ -\nabla z(0, x, t) \cdot n &= z(0, x, t), & 0 < x < 1, t > 0 \\ -\nabla z(1, x, t) \cdot n &= z(1, x, t), & 0 < x < 1, t > 0 \\ z(x, y, 0) &= 0 & 0 < x, y < 1 \\ y(t) &= \int_0^1 z(1, y, t) dy, & t > 0 \\ \end{align*} where :math:`u(t)` is the input and :math:`y(t)` is the output. """ set_log_levels({'pymor.algorithms.gram_schmidt.gram_schmidt': 'WARNING'}) p = InstationaryProblem(StationaryProblem( domain=RectDomain([[0., 0.], [1., 1.]], left='robin', right='robin', top='robin', bottom='robin'), diffusion=ConstantFunction(1., 2), robin_data=(ConstantFunction(1., 2), ExpressionFunction('(x[...,0] < 1e-10) * 1.', 2)), outputs=[('l2_boundary', ExpressionFunction('(x[...,0] > (1 - 1e-10)) * 1.', 2))]), ConstantFunction(0., 2), T=1.) fom, _ = discretize_instationary_cg(p, diameter=diameter, nt=100) fom.visualize(fom.solve()) lti = fom.to_lti() print(f'order of the model = {lti.order}') print(f'number of inputs = {lti.dim_input}') print(f'number of outputs = {lti.dim_output}') # System poles poles = lti.poles() fig, ax = plt.subplots() ax.plot(poles.real, poles.imag, '.') ax.set_title('System poles') plt.show() # Magnitude plot of the full model w = np.logspace(-1, 3, 100) fig, ax = plt.subplots() lti.mag_plot(w, ax=ax) ax.set_title('Magnitude plot of the full model') plt.show() # Hankel singular values hsv = lti.hsv() fig, ax = plt.subplots() ax.semilogy(range(1, len(hsv) + 1), hsv, '.-') ax.set_title('Hankel singular values') plt.show() # Norms of the system print(f'FOM H_2-norm: {lti.h2_norm():e}') if config.HAVE_SLYCOT: print(f'FOM H_inf-norm: {lti.hinf_norm():e}') else: print('Skipped H_inf-norm calculation due to missing slycot.') print(f'FOM Hankel-norm: {lti.hankel_norm():e}') # Model order reduction run_mor_method(lti, w, BTReductor(lti), 'BT', r, tol=1e-5) run_mor_method(lti, w, LQGBTReductor(lti), 'LQGBT', r, tol=1e-5) run_mor_method(lti, w, BRBTReductor(lti), 'BRBT', r, tol=1e-5) run_mor_method(lti, w, IRKAReductor(lti), 'IRKA', r) run_mor_method(lti, w, TSIAReductor(lti), 'TSIA', r) run_mor_method(lti, w, OneSidedIRKAReductor(lti, 'V'), 'OS-IRKA', r)
def main( diameter: float = Argument( 0.01, help='Diameter option for the domain discretizer.'), r: int = Argument(5, help='Order of the ROMs.'), ): """Parametric 1D heat equation example.""" set_log_levels({'pymor.algorithms.gram_schmidt.gram_schmidt': 'WARNING'}) # Model p = InstationaryProblem(StationaryProblem( domain=LineDomain([0., 1.], left='robin', right='robin'), diffusion=LincombFunction([ ExpressionFunction('(x[...,0] <= 0.5) * 1.', 1), ExpressionFunction('(0.5 < x[...,0]) * 1.', 1) ], [1, ProjectionParameterFunctional('diffusion')]), robin_data=(ConstantFunction(1., 1), ExpressionFunction('(x[...,0] < 1e-10) * 1.', 1)), outputs=(('l2_boundary', ExpressionFunction('(x[...,0] > (1 - 1e-10)) * 1.', 1)), ), ), ConstantFunction(0., 1), T=3.) fom, _ = discretize_instationary_cg(p, diameter=diameter, nt=100) fom.visualize(fom.solve(mu=0.1)) fom.visualize(fom.solve(mu=1)) fom.visualize(fom.solve(mu=10)) lti = fom.to_lti() print(f'order of the model = {lti.order}') print(f'number of inputs = {lti.dim_input}') print(f'number of outputs = {lti.dim_output}') mu_list = [0.1, 1, 10] w_list = np.logspace(-1, 3, 100) # System poles fig, ax = plt.subplots() for mu in mu_list: poles = lti.poles(mu=mu) ax.plot(poles.real, poles.imag, '.', label=fr'$\mu = {mu}$') ax.set_title('System poles') ax.legend() plt.show() # Magnitude plots fig, ax = plt.subplots() for mu in mu_list: lti.mag_plot(w_list, ax=ax, mu=mu, label=fr'$\mu = {mu}$') ax.set_title('Magnitude plot of the full model') ax.legend() plt.show() # Hankel singular values fig, ax = plt.subplots() for mu in mu_list: hsv = lti.hsv(mu=mu) ax.semilogy(range(1, len(hsv) + 1), hsv, label=fr'$\mu = {mu}$') ax.set_title('Hankel singular values') ax.legend() plt.show() # System norms for mu in mu_list: print(f'mu = {mu}:') print(f' H_2-norm of the full model: {lti.h2_norm(mu=mu):e}') if config.HAVE_SLYCOT: print( f' H_inf-norm of the full model: {lti.hinf_norm(mu=mu):e}') print(f' Hankel-norm of the full model: {lti.hankel_norm(mu=mu):e}') # Model order reduction run_mor_method_param(lti, r, w_list, mu_list, BTReductor, 'BT') run_mor_method_param(lti, r, w_list, mu_list, LQGBTReductor, 'LQGBT') run_mor_method_param(lti, r, w_list, mu_list, BRBTReductor, 'BRBT') run_mor_method_param(lti, r, w_list, mu_list, IRKAReductor, 'IRKA') run_mor_method_param(lti, r, w_list, mu_list, TSIAReductor, 'TSIA') run_mor_method_param(lti, r, w_list, mu_list, OneSidedIRKAReductor, 'OS-IRKA', version='V')