Exemple #1
0
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]')
Exemple #2
0
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')
Exemple #3
0
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 ...')
    discretizer = discretize_stationary_fv if args[
        '--fv'] else discretize_stationary_cg
    d, data = discretizer(analytical_problem=problem, diameter=args['CLSCALE'])
    grid = data['grid']
    print(grid)
    print()

    print('Solve ...')
    U = d.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(0)) if args['--fv'] else solution(grid.centers(2)
                                                                ))

    d.visualize((U, U_ref, U - U_ref),
                legend=('Solution', 'Analytical solution (circular boundary)',
                        'Error'),
                separate_colorbars=True)
Exemple #4
0
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]')
Exemple #5
0
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]')
Exemple #6
0
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()
Exemple #7
0
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)
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')
Exemple #9
0
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')