def test_LincombParameterFunctional(): dict_of_d_mus = {'mu': ['200 * mu[0]', '2 * mu[0]'], 'nu': ['cos(nu[0])']} epf = ExpressionParameterFunctional('100 * mu[0]**2 + 2 * mu[1] * mu[0] + sin(nu[0])', {'mu': 2, 'nu': 1}, 'functional_with_derivative_and_second_derivative', dict_of_d_mus) pf = ProjectionParameterFunctional('mu', 2, 0) mu = Mu({'mu': [10,2], 'nu': [3]}) zero = pf - pf two_pf = pf + pf three_pf = pf + 2*pf pf_plus_one = pf + 1 sum_ = epf + pf pf_squared = (pf + 2*epf) * (pf - 2*epf) + 4 * epf * epf assert zero(mu) == 0 assert two_pf(mu) == 2 * pf(mu) assert three_pf(mu) == 3 * pf(mu) assert pf_plus_one(mu) == pf(mu) + 1 assert sum_(mu) == epf(mu) + pf(mu) assert pf_squared(mu) == pf(mu) * pf(mu) assert sum_.d_mu('mu', 0)(mu) == epf.d_mu('mu', 0)(mu) + pf.d_mu('mu', 0)(mu) assert sum_.d_mu('mu', 1)(mu) == epf.d_mu('mu', 1)(mu) + pf.d_mu('mu', 1)(mu) assert sum_.d_mu('nu', 0)(mu) == epf.d_mu('nu', 0)(mu) + pf.d_mu('nu', 0)(mu)
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 test_ProjectionParameterFunctional(): pf = ProjectionParameterFunctional('mu', (2, ), (0, )) mu = {'mu': (10, 2)} derivative_to_first_index = pf.d_mu('mu', 0) derivative_to_second_index = pf.d_mu('mu', 1) der_mu_1 = derivative_to_first_index.evaluate(mu) der_mu_2 = derivative_to_second_index.evaluate(mu) assert pf.evaluate(mu) == 10 assert der_mu_1 == 1 assert der_mu_2 == 0
def test_ProjectionParameterFunctional(): pf = ProjectionParameterFunctional('mu', 2, 0) mu = Mu({'mu': (10,2)}) derivative_to_first_index = pf.d_mu('mu', 0) derivative_to_second_index = pf.d_mu('mu', 1) second_derivative_first_first = pf.d_mu('mu', 0).d_mu('mu', 0) second_derivative_first_second = pf.d_mu('mu', 0).d_mu('mu', 1) second_derivative_second_first = pf.d_mu('mu', 1).d_mu('mu', 0) second_derivative_second_second = pf.d_mu('mu', 1).d_mu('mu', 1) der_mu_1 = derivative_to_first_index.evaluate(mu) der_mu_2 = derivative_to_second_index.evaluate(mu) hes_mu_1_mu_1 = second_derivative_first_first.evaluate(mu) hes_mu_1_mu_2 = second_derivative_first_second.evaluate(mu) hes_mu_2_mu_1 = second_derivative_second_first.evaluate(mu) hes_mu_2_mu_2 = second_derivative_second_second.evaluate(mu) assert pf.evaluate(mu) == 10 assert der_mu_1 == 1 assert der_mu_2 == 0 assert hes_mu_1_mu_1 == 0 assert hes_mu_1_mu_2 == 0 assert hes_mu_2_mu_1 == 0 assert hes_mu_2_mu_2 == 0
def test_d_mu_of_LincombOperator(): dict_of_d_mus = {'mu': ['100', '2'], 'nu': 'cos(nu)'} pf = ProjectionParameterFunctional('mu', (2, ), (0, )) epf = ExpressionParameterFunctional('100 * mu[0] + 2 * mu[1] + sin(nu)', { 'mu': (2, ), 'nu': () }, 'functional_with_derivative', dict_of_d_mus) mu = {'mu': (10, 2), 'nu': 0} space = NumpyVectorSpace(1) zero_op = ZeroOperator(space, space) operators = [zero_op, zero_op, zero_op] coefficients = [1., pf, epf] operator = LincombOperator(operators, coefficients) op_sensitivity_to_first_mu = operator.d_mu('mu', 0) op_sensitivity_to_second_mu = operator.d_mu('mu', 1) op_sensitivity_to_nu = operator.d_mu('nu', ()) eval_mu_1 = op_sensitivity_to_first_mu.evaluate_coefficients(mu) eval_mu_2 = op_sensitivity_to_second_mu.evaluate_coefficients(mu) eval_nu = op_sensitivity_to_nu.evaluate_coefficients(mu) assert operator.evaluate_coefficients(mu) == [1., 10, 1004.] assert eval_mu_1 == [0., 1., 100.] assert eval_mu_2 == [0., 0., 2.] assert eval_nu == [0., 0., 1.]
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].to_numpy() rhs_data[:] = np.ones(len(rhs_data)) rhs_data[0] = 0 rhs_data[len(rhs_data) - 1] = 0 rhs = VectorOperator(rhs_vec) # hack together a visualizer ... grid = OnedGrid(domain=(0, 1), num_intervals=n) visualizer = OnedVisualizer(grid) time_stepper = ExplicitEulerTimeStepper(nt) fom = InstationaryModel(T=1e-0, operator=operator, rhs=rhs, initial_data=initial_data, time_stepper=time_stepper, num_values=20, visualizer=visualizer, name='C++-Model') return fom
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 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 test_expand(): ops = [NumpyMatrixOperator(np.eye(1) * i) for i in range(8)] pfs = [ProjectionParameterFunctional('p', 9, i) for i in range(8)] prods = [o * p for o, p in zip(ops, pfs)] op = ((prods[0] + prods[1] + prods[2]) @ (prods[3] + prods[4] + prods[5]) @ (prods[6] + prods[7])) eop = expand(op) assert isinstance(eop, LincombOperator) assert len(eop.operators) == 3 * 3 * 2 assert all( isinstance(o, ConcatenationOperator) and len(o.operators) == 3 for o in eop.operators) assert ({to_matrix(o)[0, 0] for o in eop.operators} == { i0 * i1 * i2 for i0, i1, i2 in product([0, 1, 2], [3, 4, 5], [6, 7]) }) assert ({ frozenset(p.index for p in pf.factors) for pf in eop.coefficients } == { frozenset([i0, i1, i2]) for i0, i1, i2 in product([0, 1, 2], [3, 4, 5], [6, 7]) })
def test_LincombParameterFunctional(): dict_of_d_mus = {'mu': ['200 * mu[0]', '2 * mu[0]'], 'nu': ['cos(nu[0])']} epf = ExpressionParameterFunctional('100 * mu[0]**2 + 2 * mu[1] * mu[0] + sin(nu[0])', {'mu': 2, 'nu': 1}, 'functional_with_derivative_and_second_derivative', dict_of_d_mus) pf = ProjectionParameterFunctional('mu', 2, 0) mu = Mu({'mu': [10,2], 'nu': [3]}) zero = pf - pf two_pf = pf + pf two_pf_named = two_pf.with_(name='some_interesting_quantity') three_pf = pf + 2*pf three_pf_ = pf + two_pf three_pf_named = pf + two_pf_named pf_plus_one = pf + 1 pf_plus_one_ = 1 + pf sum_ = epf + pf + 1 - 3 pf_squared_ = pf * pf pf_squared_named = pf_squared_.with_(name='some_interesting_quantity') pf_times_pf_squared = pf * pf_squared_ pf_times_pf_squared_named = pf * pf_squared_named pf_squared = 4 * epf * epf * 1 + (pf + 2*epf) * (pf - 2*epf) assert zero(mu) == 0 assert two_pf(mu) == 2 * pf(mu) assert three_pf(mu) == 3 * pf(mu) assert three_pf_(mu) == 3 * pf(mu) assert pf_plus_one(mu) == pf(mu) + 1 assert pf_plus_one_(mu) == pf(mu) + 1 assert sum_(mu) == epf(mu) + pf(mu) + 1 - 3 assert pf_squared_(mu) == pf(mu) * pf(mu) assert pf_squared(mu) == pf(mu) * pf(mu) assert pf_times_pf_squared(mu) == pf(mu) * pf(mu) * pf(mu) # derivatives are linear assert sum_.d_mu('mu', 0)(mu) == epf.d_mu('mu', 0)(mu) + pf.d_mu('mu', 0)(mu) assert sum_.d_mu('mu', 1)(mu) == epf.d_mu('mu', 1)(mu) + pf.d_mu('mu', 1)(mu) assert sum_.d_mu('nu', 0)(mu) == epf.d_mu('nu', 0)(mu) + pf.d_mu('nu', 0)(mu) # sums and products are not nested assert len(sum_.coefficients) == 4 assert len(pf_squared.functionals[0].factors) == 4 # named functions will not be merged and still be nested assert three_pf_named(mu) == three_pf_(mu) assert len(three_pf_named.coefficients) != len(three_pf_.coefficients) assert pf_times_pf_squared_named(mu) == pf_times_pf_squared(mu) assert len(pf_times_pf_squared_named.factors) != len(pf_times_pf_squared.factors)
def test_ProductParameterFunctional(): # Projection ParameterFunctional pf = ProjectionParameterFunctional('mu', 2, 0) # Expression ParameterFunctional dict_of_d_mus = {'nu': ['2*nu']} dict_of_second_derivative = {'nu': [{'nu': ['2']}]} epf = ExpressionParameterFunctional('nu**2', {'nu': 1}, 'expression_functional', dict_of_d_mus, dict_of_second_derivative) mu = Mu({'mu': (10,2), 'nu': 3}) productf = pf * epf * 2. * pf derivative_to_first_index = productf.d_mu('mu', 0) derivative_to_second_index = productf.d_mu('mu', 1) derivative_to_third_index = productf.d_mu('nu', 0) second_derivative_first_first = productf.d_mu('mu', 0).d_mu('mu', 0) second_derivative_first_second = productf.d_mu('mu', 0).d_mu('mu', 1) second_derivative_first_third = productf.d_mu('mu', 0).d_mu('nu', 0) second_derivative_second_first = productf.d_mu('mu', 1).d_mu('mu', 0) second_derivative_second_second = productf.d_mu('mu', 1).d_mu('mu', 1) second_derivative_second_third = productf.d_mu('mu', 1).d_mu('nu', 0) second_derivative_third_first = productf.d_mu('nu', 0).d_mu('mu', 0) second_derivative_third_second = productf.d_mu('nu', 0).d_mu('mu', 1) second_derivative_third_third = productf.d_mu('nu', 0).d_mu('nu', 0) der_mu_1 = derivative_to_first_index.evaluate(mu) der_mu_2 = derivative_to_second_index.evaluate(mu) der_nu_3 = derivative_to_third_index.evaluate(mu) hes_mu_1_mu_1 = second_derivative_first_first.evaluate(mu) hes_mu_1_mu_2 = second_derivative_first_second.evaluate(mu) hes_mu_1_nu_3 = second_derivative_first_third.evaluate(mu) hes_mu_2_mu_1 = second_derivative_second_first.evaluate(mu) hes_mu_2_mu_2 = second_derivative_second_second.evaluate(mu) hes_mu_2_nu_3 = second_derivative_second_third.evaluate(mu) hes_nu_3_mu_1 = second_derivative_third_first.evaluate(mu) hes_nu_3_mu_2 = second_derivative_third_second.evaluate(mu) hes_nu_3_nu_3 = second_derivative_third_third.evaluate(mu) # note that productf(mu,nu) = 2 * pf(mu)**2 * epf(nu) # and thus: # d_mu productf(mu,nu) = 2 * 2 * pf(mu) * (d_mu pf)(mu) * epf(nu) # d_nu productf(mu,nu) = 2 * pf(mu)**2 * (d_nu epf)(nu) # and so forth assert der_mu_1 == 2 * 2 * 10 * 1 * 9 assert der_mu_2 == 0 assert der_nu_3 == 2 * 10**2 * 6 assert hes_mu_1_mu_1 == 2 * 2 * 9 assert hes_mu_1_mu_2 == 0 assert hes_mu_1_nu_3 == 2 * 2 * 10 * 1 * 6 assert hes_mu_2_mu_1 == 0 assert hes_mu_2_mu_2 == 0 assert hes_mu_2_nu_3 == 0 assert hes_nu_3_mu_1 == 2 * 2 * 10 * 1 * 6 assert hes_nu_3_mu_2 == 0 assert hes_nu_3_nu_3 == 2 * 10**2 * 2
def test_simple_ProductParameterFunctional(): pf = ProjectionParameterFunctional('mu', 2, 0) mu = Mu({'mu': (10,2)}) productf = pf * 2 * 3 derivative_to_first_index = productf.d_mu('mu', 0) derivative_to_second_index = productf.d_mu('mu', 1) second_derivative_first_first = productf.d_mu('mu', 0).d_mu('mu', 0) second_derivative_first_second = productf.d_mu('mu', 0).d_mu('mu', 1) second_derivative_second_first = productf.d_mu('mu', 1).d_mu('mu', 0) second_derivative_second_second = productf.d_mu('mu', 1).d_mu('mu', 1) der_mu_1 = derivative_to_first_index.evaluate(mu) der_mu_2 = derivative_to_second_index.evaluate(mu) hes_mu_1_mu_1 = second_derivative_first_first.evaluate(mu) hes_mu_1_mu_2 = second_derivative_first_second.evaluate(mu) hes_mu_2_mu_1 = second_derivative_second_first.evaluate(mu) hes_mu_2_mu_2 = second_derivative_second_second.evaluate(mu) assert der_mu_1 == 2 * 3 assert der_mu_2 == 0 assert hes_mu_1_mu_1 == 0 assert hes_mu_1_mu_2 == 0 assert hes_mu_2_mu_1 == 0 assert hes_mu_2_mu_2 == 0 dict_of_d_mus = {'mu': ['2*mu']} dict_of_second_derivative = {'mu': [{'mu': ['2']}]} epf = ExpressionParameterFunctional('mu**2', {'mu': 1}, 'functional_with_derivative_and_second_derivative', dict_of_d_mus, dict_of_second_derivative) productf = epf * 2 mu = Mu({'mu': 3}) derivative_to_first_index = productf.d_mu('mu') second_derivative_first_first = productf.d_mu('mu').d_mu('mu') der_mu = derivative_to_first_index.evaluate(mu) hes_mu_mu = second_derivative_first_first.evaluate(mu) assert productf.evaluate(mu) == 2 * 3 ** 2 assert der_mu == 2 * 2 * 3 assert hes_mu_mu == 2 * 2
def test_output_d_mu(): from pymordemos.linear_optimization import create_fom grid_intervals = 10 training_samples = 3 fom, mu_bar = create_fom(grid_intervals, vector_valued_output=True) easy_fom, _ = create_fom(grid_intervals, vector_valued_output=False) parameter_space = fom.parameters.space(0, np.pi) training_set = parameter_space.sample_uniformly(training_samples) #verifying that the adjoint and sensitivity gradients are the same and that solve_d_mu works for mu in training_set: gradient_with_adjoint_approach = fom.output_d_mu(mu, return_array=True, use_adjoint=True) gradient_with_sensitivities = fom.output_d_mu(mu, return_array=True, use_adjoint=False) assert np.allclose(gradient_with_adjoint_approach, gradient_with_sensitivities) u_d_mu = fom.solve_d_mu('diffusion', 1, mu=mu).to_numpy() u_d_mu_ = fom.compute(solution_d_mu=True, mu=mu)['solution_d_mu']['diffusion'][1].to_numpy() assert np.allclose(u_d_mu, u_d_mu_) # test the complex case complex_fom = easy_fom.with_(operator=easy_fom.operator.with_( operators=[op* (1+2j) for op in easy_fom.operator.operators])) complex_gradient_adjoint = complex_fom.output_d_mu(mu, return_array=True, use_adjoint=True) complex_gradient = complex_fom.output_d_mu(mu, return_array=True, use_adjoint=False) assert np.allclose(complex_gradient_adjoint, complex_gradient) complex_fom = easy_fom.with_(output_functional=easy_fom.output_functional.with_( operators=[op* (1+2j) for op in easy_fom.output_functional.operators])) complex_gradient_adjoint = complex_fom.output_d_mu(mu, return_array=True, use_adjoint=True) complex_gradient = complex_fom.output_d_mu(mu, return_array=True, use_adjoint=False) assert np.allclose(complex_gradient_adjoint, complex_gradient) # another fom to test the 3d case ops, coefs = fom.operator.operators, fom.operator.coefficients ops += (fom.operator.operators[1],) coefs += (ProjectionParameterFunctional('nu', 1, 0),) fom_ = fom.with_(operator=LincombOperator(ops, coefs)) parameter_space = fom_.parameters.space(0, np.pi) training_set = parameter_space.sample_uniformly(training_samples) for mu in training_set: gradient_with_adjoint_approach = fom_.output_d_mu(mu, return_array=True, use_adjoint=True) gradient_with_sensitivities = fom_.output_d_mu(mu, return_array=True, use_adjoint=False) assert np.allclose(gradient_with_adjoint_approach, gradient_with_sensitivities)
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 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 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 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 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 misc_operator_with_arrays_and_products_factory(n): if n == 0: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 10, 4, 3, n) op = ComponentProjection(np.random.randint(0, 100, 10), U.space) return op, _, U, V, sp, rp elif n == 1: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 0, 4, 3, n) op = ComponentProjection([], U.space) return op, _, U, V, sp, rp elif n == 2: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 3, 4, 3, n) op = ComponentProjection([3, 3, 3], U.space) return op, _, U, V, sp, rp elif n == 3: from pymor.operators.constructions import AdjointOperator op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 20, 4, 3, n) op = AdjointOperator(op, with_apply_inverse=True) return op, _, V, U, rp, sp elif n == 4: from pymor.operators.constructions import AdjointOperator op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(100, 20, 4, 3, n) op = AdjointOperator(op, with_apply_inverse=False) return op, _, V, U, rp, sp elif 5 <= n <= 7: from pymor.operators.constructions import SelectionOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory(30, 30, 4, 3, n) op1 = NumpyMatrixOperator(np.random.random((30, 30))) op2 = NumpyMatrixOperator(np.random.random((30, 30))) op = SelectionOperator([op0, op1, op2], ProjectionParameterFunctional('x', ()), [0.3, 0.6]) return op, op.parse_parameter((n-5)/2), V, U, rp, sp elif n == 8: from pymor.operators.block import BlockDiagonalOperator from pymor.vectorarrays.block import BlockVectorArray op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory(10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory(20, 20, 4, 3, n+1) op2, _, U2, V2, sp2, rp2 = numpy_matrix_operator_with_arrays_and_products_factory(30, 30, 4, 3, n+2) op = BlockDiagonalOperator([op0, op1, op2]) sp = BlockDiagonalOperator([sp0, sp1, sp2]) rp = BlockDiagonalOperator([rp0, rp1, rp2]) U = BlockVectorArray([U0, U1, U2]) V = BlockVectorArray([V0, V1, V2]) return op, _, U, V, sp, rp elif n == 9: from pymor.operators.block import BlockDiagonalOperator, BlockOperator from pymor.vectorarrays.block import BlockVectorArray op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory(10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory(20, 20, 4, 3, n+1) op2, _, U2, V2, sp2, rp2 = numpy_matrix_operator_with_arrays_and_products_factory(20, 10, 4, 3, n+2) op = BlockOperator([[op0, op2], [None, op1]]) sp = BlockDiagonalOperator([sp0, sp1]) rp = BlockDiagonalOperator([rp0, rp1]) U = BlockVectorArray([U0, U1]) V = BlockVectorArray([V0, V1]) return op, None, U, V, sp, rp else: assert False
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}')
def test_d_mu_of_LincombOperator(): dict_of_d_mus = {'mu': ['100', '2 * mu[0]'], 'nu': 'cos(nu)'} dict_of_second_derivative = { 'mu': [{ 'mu': ['0', '2'], 'nu': '0' }, { 'mu': ['2', '0'], 'nu': '0' }], 'nu': { 'mu': ['0', '0'], 'nu': '-sin(nu)' } } pf = ProjectionParameterFunctional('mu', (2, ), (0, )) epf = ExpressionParameterFunctional( '100 * mu[0] + 2 * mu[1] * mu[0] + sin(nu)', { 'mu': (2, ), 'nu': () }, 'functional_with_derivative', dict_of_d_mus, dict_of_second_derivative) mu = {'mu': (10, 2), 'nu': 0} space = NumpyVectorSpace(1) zero_op = ZeroOperator(space, space) operators = [zero_op, zero_op, zero_op] coefficients = [1., pf, epf] operator = LincombOperator(operators, coefficients) op_sensitivity_to_first_mu = operator.d_mu('mu', 0) op_sensitivity_to_second_mu = operator.d_mu('mu', 1) op_sensitivity_to_nu = operator.d_mu('nu', ()) eval_mu_1 = op_sensitivity_to_first_mu.evaluate_coefficients(mu) eval_mu_2 = op_sensitivity_to_second_mu.evaluate_coefficients(mu) eval_nu = op_sensitivity_to_nu.evaluate_coefficients(mu) second_derivative_first_mu_first_mu = operator.d_mu('mu', 0).d_mu('mu', 0) second_derivative_first_mu_second_mu = operator.d_mu('mu', 0).d_mu('mu', 1) second_derivative_first_mu_nu = operator.d_mu('mu', 0).d_mu('nu') second_derivative_second_mu_first_mu = operator.d_mu('mu', 1).d_mu('mu', 0) second_derivative_second_mu_second_mu = operator.d_mu('mu', 1).d_mu('mu', 1) second_derivative_second_mu_nu = operator.d_mu('mu', 1).d_mu('nu') second_derivative_nu_first_mu = operator.d_mu('nu').d_mu('mu', 0) second_derivative_nu_second_mu = operator.d_mu('nu').d_mu('mu', 1) second_derivative_nu_nu = operator.d_mu('nu').d_mu('nu') hes_mu_1_mu_1 = second_derivative_first_mu_first_mu.evaluate_coefficients( mu) hes_mu_1_mu_2 = second_derivative_first_mu_second_mu.evaluate_coefficients( mu) hes_mu_1_nu = second_derivative_first_mu_nu.evaluate_coefficients(mu) hes_mu_2_mu_1 = second_derivative_second_mu_first_mu.evaluate_coefficients( mu) hes_mu_2_mu_2 = second_derivative_second_mu_second_mu.evaluate_coefficients( mu) hes_mu_2_nu = second_derivative_second_mu_nu.evaluate_coefficients(mu) hes_nu_mu_1 = second_derivative_nu_first_mu.evaluate_coefficients(mu) hes_nu_mu_2 = second_derivative_nu_second_mu.evaluate_coefficients(mu) hes_nu_nu = second_derivative_nu_nu.evaluate_coefficients(mu) assert operator.evaluate_coefficients(mu) == [1., 10, 1040.] assert eval_mu_1 == [0., 1., 100.] assert eval_mu_2 == [0., 0., 2. * 10] assert eval_nu == [0., 0., 1.] assert hes_mu_1_mu_1 == [0., 0., 0.] assert hes_mu_1_mu_2 == [0., 0., 2] assert hes_mu_1_nu == [0., 0., 0] assert hes_mu_2_mu_1 == [0., 0., 2] assert hes_mu_2_mu_2 == [0., 0., 0] assert hes_mu_2_nu == [0., 0., 0] assert hes_nu_mu_1 == [0., 0., 0] assert hes_nu_mu_2 == [0., 0., 0] assert hes_nu_nu == [0., 0., -0]
def misc_operator_with_arrays_and_products_factory(n): if n == 0: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 10, 4, 3, n) op = ComponentProjection(np.random.randint(0, 100, 10), U.space) return op, _, U, V, sp, rp elif n == 1: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 0, 4, 3, n) op = ComponentProjection([], U.space) return op, _, U, V, sp, rp elif n == 2: from pymor.operators.constructions import ComponentProjection _, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 3, 4, 3, n) op = ComponentProjection([3, 3, 3], U.space) return op, _, U, V, sp, rp elif n == 3: from pymor.operators.constructions import AdjointOperator op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 20, 4, 3, n) op = AdjointOperator(op, with_apply_inverse=True) return op, _, V, U, rp, sp elif n == 4: from pymor.operators.constructions import AdjointOperator op, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 100, 20, 4, 3, n) op = AdjointOperator(op, with_apply_inverse=False) return op, _, V, U, rp, sp elif 5 <= n <= 7: from pymor.operators.constructions import SelectionOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0, _, U, V, sp, rp = numpy_matrix_operator_with_arrays_and_products_factory( 30, 30, 4, 3, n) op1 = NumpyMatrixOperator(np.random.random((30, 30))) op2 = NumpyMatrixOperator(np.random.random((30, 30))) op = SelectionOperator([op0, op1, op2], ProjectionParameterFunctional('x'), [0.3, 0.6]) return op, op.parameters.parse((n - 5) / 2), V, U, rp, sp elif n == 8: from pymor.operators.block import BlockDiagonalOperator op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory( 20, 20, 4, 3, n + 1) op2, _, U2, V2, sp2, rp2 = numpy_matrix_operator_with_arrays_and_products_factory( 30, 30, 4, 3, n + 2) op = BlockDiagonalOperator([op0, op1, op2]) sp = BlockDiagonalOperator([sp0, sp1, sp2]) rp = BlockDiagonalOperator([rp0, rp1, rp2]) U = op.source.make_array([U0, U1, U2]) V = op.range.make_array([V0, V1, V2]) return op, _, U, V, sp, rp elif n == 9: from pymor.operators.block import BlockDiagonalOperator, BlockOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0a, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op0b, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op0c, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory( 20, 20, 4, 3, n + 1) op2a, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2b, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op0 = (op0a * ProjectionParameterFunctional('p', 3, 0) + op0b * ProjectionParameterFunctional('p', 3, 1) + op0c * ProjectionParameterFunctional('p', 3, 1)) op2 = (op2a * ProjectionParameterFunctional('p', 3, 0) + op2b * ProjectionParameterFunctional('q', 1)) op = BlockOperator([[op0, op2], [None, op1]]) mu = op.parameters.parse({'p': [1, 2, 3], 'q': 4}) sp = BlockDiagonalOperator([sp0, sp1]) rp = BlockDiagonalOperator([rp0, rp1]) U = op.source.make_array([U0, U1]) V = op.range.make_array([V0, V1]) return op, mu, U, V, sp, rp elif n == 10: from pymor.operators.block import BlockDiagonalOperator, BlockColumnOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory( 20, 20, 4, 3, n + 1) op2a, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2b, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2 = (op2a * ProjectionParameterFunctional('p', 3, 0) + op2b * ProjectionParameterFunctional('q', 1)) op = BlockColumnOperator([op2, op1]) mu = op.parameters.parse({'p': [1, 2, 3], 'q': 4}) sp = sp1 rp = BlockDiagonalOperator([rp0, rp1]) U = U1 V = op.range.make_array([V0, V1]) return op, mu, U, V, sp, rp elif n == 11: from pymor.operators.block import BlockDiagonalOperator, BlockRowOperator from pymor.parameters.functionals import ProjectionParameterFunctional op0, _, U0, V0, sp0, rp0 = numpy_matrix_operator_with_arrays_and_products_factory( 10, 10, 4, 3, n) op1, _, U1, V1, sp1, rp1 = numpy_matrix_operator_with_arrays_and_products_factory( 20, 20, 4, 3, n + 1) op2a, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2b, _, _, _, _, _ = numpy_matrix_operator_with_arrays_and_products_factory( 20, 10, 4, 3, n + 2) op2 = (op2a * ProjectionParameterFunctional('p', 3, 0) + op2b * ProjectionParameterFunctional('q', 1)) op = BlockRowOperator([op0, op2]) mu = op.parameters.parse({'p': [1, 2, 3], 'q': 4}) sp = BlockDiagonalOperator([sp0, sp1]) rp = rp0 U = op.source.make_array([U0, U1]) V = V0 return op, mu, U, V, sp, rp else: assert False
def main( n: int = Argument(100, help='Order of the FOM.'), r: int = Argument(10, help='Order of the ROMs.'), ): """Synthetic parametric demo. See the `MOR Wiki page <http://modelreduction.org/index.php/Synthetic_parametric_model>`_. """ # Model # set coefficients a = -np.linspace(1e1, 1e3, n // 2) b = np.linspace(1e1, 1e3, n // 2) c = np.ones(n // 2) d = np.zeros(n // 2) # build 2x2 submatrices aa = np.empty(n) aa[::2] = a aa[1::2] = a bb = np.zeros(n) bb[::2] = b # set up system matrices Amu = sps.diags(aa, format='csc') A0 = sps.diags([bb, -bb], [1, -1], shape=(n, n), format='csc') B = np.zeros((n, 1)) B[::2, 0] = 2 C = np.empty((1, n)) C[0, ::2] = c C[0, 1::2] = d # form operators A0 = NumpyMatrixOperator(A0) Amu = NumpyMatrixOperator(Amu) B = NumpyMatrixOperator(B) C = NumpyMatrixOperator(C) A = A0 + Amu * ProjectionParameterFunctional('mu') # form a model lti = LTIModel(A, B, C) mu_list = [1 / 50, 1 / 20, 1 / 10, 1 / 5, 1 / 2, 1] w = np.logspace(0.5, 3.5, 200) # 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 plot fig, ax = plt.subplots() for mu in mu_list: lti.mag_plot(w, ax=ax, mu=mu, label=fr'$\mu = {mu}$') 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, mu_list, BTReductor, 'BT') run_mor_method_param(lti, r, w, mu_list, IRKAReductor, 'IRKA')
def parameter_functional_factory(ix, iy): return ProjectionParameterFunctional('diffusion', size=num_blocks[0]*num_blocks[1], index=ix + iy*num_blocks[0], name=f'diffusion_{ix}_{iy}')
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))
def parameter_functional_factory(x, y): return ProjectionParameterFunctional('diffusion', size=yblocks*xblocks, index=yblocks - y - 1 + x * yblocks, name=f'diffusion_{x}_{y}')
def init_grid_and_problem(config, mu_bar=(1, 1, 1, 1), mu_hat=(1, 1, 1, 1)): logger = getLogger('thermalblock_problem.thermalblock_problem') logger.info('initializing grid and problem ... ') lower_left = [-1, -1] upper_right = [1, 1] inner_boundary_id = 18446744073709551573 grid = make_grid((lower_left, upper_right), config['num_subdomains'], config['half_num_fine_elements_per_subdomain_and_dim'], inner_boundary_id) all_dirichlet_boundary_info = make_boundary_info( grid, {'type': 'xt.grid.boundaryinfo.alldirichlet'}) XBLOCKS = 2 YBLOCKS = 2 def diffusion_function_factory(ix, iy): values = [[0.]] * (YBLOCKS * XBLOCKS) values[ix + XBLOCKS * iy] = [1.] return make_checkerboard_function_1x1(grid_provider=grid, lower_left=lower_left, upper_right=upper_right, num_elements=[XBLOCKS, YBLOCKS], values=values, name='diffusion_{}_{}'.format( ix, iy)) diffusion_functions = [ diffusion_function_factory(ix, iy) for ix, iy in product(range(XBLOCKS), range(YBLOCKS)) ] parameter_type = {'diffusion': (YBLOCKS, XBLOCKS)} coefficients = [ ProjectionParameterFunctional(component_name='diffusion', component_shape=(YBLOCKS, XBLOCKS), coordinates=(YBLOCKS - y - 1, x)) for x in range(XBLOCKS) for y in range(YBLOCKS) ] kappa = make_constant_function_2x2(grid, [[1., 0.], [0., 1.]], name='kappa') f = make_expression_function_1x1( grid, 'x', '0.5*pi*pi*cos(0.5*pi*x[0])*cos(0.5*pi*x[1])', order=2, name='f') lambda_bar_values = [[0.]] * (YBLOCKS * XBLOCKS) lambda_hat_values = [[0.]] * (YBLOCKS * XBLOCKS) counter = 0 for ix in range(YBLOCKS): for iy in range(XBLOCKS): lambda_bar_values[ix + XBLOCKS * iy] = [ coefficients[counter].evaluate(mu_bar) ] lambda_hat_values[ix + XBLOCKS * iy] = [ coefficients[counter].evaluate(mu_hat) ] counter += 1 lambda_bar = make_checkerboard_function_1x1( grid_provider=grid, lower_left=lower_left, upper_right=upper_right, num_elements=[XBLOCKS, YBLOCKS], values=lambda_bar_values, name='lambda_bar') lambda_hat = make_checkerboard_function_1x1( grid_provider=grid, lower_left=lower_left, upper_right=upper_right, num_elements=[XBLOCKS, YBLOCKS], values=lambda_hat_values, name='lambda_hat') return { 'grid': grid, 'boundary_info': all_dirichlet_boundary_info, 'inner_boundary_id': inner_boundary_id, 'lambda': { 'functions': diffusion_functions, 'coefficients': coefficients }, 'lambda_bar': lambda_bar, 'lambda_hat': lambda_hat, 'kappa': kappa, 'f': f, 'parameter_type': parameter_type, 'mu_bar': mu_bar, 'mu_hat': mu_hat, 'mu_min': (min(0.1, b, h) for b, h in zip(mu_bar, mu_hat)), 'mu_max': (max(1, b, h) for b, h in zip(mu_bar, mu_hat)), 'parameter_range': (min((0.1, ) + mu_bar + mu_hat), max((1, ) + mu_bar + mu_hat)) }
def Fin_problem(parameter_dimension=2): assert parameter_dimension == 2 or parameter_dimension == 6, 'This dimension is not available' if parameter_dimension == 2: functions = [ ExpressionFunction( '(2.5 <= x[..., 0]) * (x[..., 0] <= 3.5) * (0 <= x[..., 1]) * (x[..., 1] <=4)* 1.', dim_domain=2, shape_range=()), ExpressionFunction( '(0 <= x[..., 0]) * (x[..., 0] < 2.5) * (0.75 <= x[..., 1]) * (x[..., 1] <= 1) *1. \ + (3.5 < x[..., 0]) * (x[..., 0] <= 6) * (0.75 <= x[..., 1]) * (x[..., 1] <= 1)* 1. \ + (0 <= x[..., 0]) * (x[..., 0] < 2.5) * (1.75 <= x[..., 1]) * (x[..., 1] <= 2) * 1. \ + (3.5 < x[..., 0]) * (x[..., 0] <= 6) * (1.75 <= x[..., 1]) * (x[..., 1] <= 2) * 1. \ + (0 <= x[..., 0]) * (x[..., 0] < 2.5) * (2.75 <= x[..., 1]) * (x[..., 1] <= 3) *1. \ + (3.5 < x[..., 0]) * (x[..., 0] <= 6) * (2.75 <= x[..., 1]) * (x[..., 1] <= 3) * 1. \ + (0 <= x[..., 0]) * (x[..., 0] < 2.5) * (3.75 <= x[..., 1]) * (x[..., 1] <= 4) *1. \ + (3.5 < x[..., 0]) * (x[..., 0] <= 6) * (3.75 <= x[..., 1]) * (x[..., 1] <= 4) * 1.', dim_domain=2, shape_range=()) ] coefficients = [1, ProjectionParameterFunctional('k', (), ())] diffusion = LincombFunction(functions, coefficients) parameter_ranges = { 'biot': np.array([0.01, 1]), 'k': np.array([0.1, 10]) } parameter_type = {'biot': (), 'k': ()} elif parameter_dimension == 6: functions = [ ExpressionFunction( '(2.5 <= x[..., 0]) * (x[..., 0] <= 3.5) * (0 <= x[..., 1]) * (x[..., 1] <= 4) * 1.', dim_domain=2, shape_range=()), ExpressionFunction( '(0 <= x[..., 0]) * (x[..., 0] < 2.5) * (0.75 <= x[..., 1]) * (x[..., 1] <= 1) * \ 1. + (3.5 < x[..., 0]) * (x[..., 0] <= 6) * (0.75 <= x[..., 1]) * (x[..., 1] <=1) * 1.', dim_domain=2, shape_range=()), ExpressionFunction( '(0 <= x[..., 0]) * (x[..., 0] < 2.5) * (1.75 <= x[..., 1]) * (x[..., 1] <= 2) * 1. \ + (3.5 < x[..., 0]) * (x[..., 0] <= 6) * (1.75 <= x[..., 1]) * (x[..., 1] <= 2) * 1.', dim_domain=2, shape_range=()), ExpressionFunction( '(0 <= x[..., 0]) * (x[..., 0] < 2.5) * (2.75 <= x[..., 1]) * (x[..., 1] <= 3) *1. \ + (3.5 < x[..., 0]) * (x[..., 0] <= 6) * (2.75 <= x[..., 1]) * (x[..., 1] <= 3) * 1.', dim_domain=2, shape_range=()), ExpressionFunction( '(0 <= x[..., 0]) * (x[..., 0] < 2.5) * (3.75 <= x[..., 1]) * (x[..., 1] <= 4) *1. \ + (3.5 < x[..., 0]) * (x[..., 0] <= 6) * (3.75 <= x[..., 1]) * (x[..., 1] <= 4) * 1.', dim_domain=2, shape_range=()) ] coefficients = [ ProjectionParameterFunctional('k0', (), ()), ProjectionParameterFunctional('k1', (), ()), ProjectionParameterFunctional('k2', (), ()), ProjectionParameterFunctional('k3', (), ()), ProjectionParameterFunctional('k4', (), ()) ] diffusion = LincombFunction(functions, coefficients) parameter_ranges = np.array([[0.01, 0.1, 0.1, 0.1, 0.1, 0.1], [1, 10, 10, 10, 10, 10]]) parameter_ranges = { 'biot': np.array([0.01, 1]), 'k0': np.array([0.1, 10]), 'k1': np.array([0.1, 10]), 'k2': np.array([0.1, 10]), 'k3': np.array([0.1, 10]), 'k4': np.array([0.1, 10]) } parameter_type = { 'biot': (), 'k0': (), 'k1': (), 'k2': (), 'k3': (), 'k4': () } domain = RectDomain([[0, 0], [6, 4]]) parameter_space = CubicParameterSpace(parameter_type, ranges=parameter_ranges) problem = StationaryProblem( domain=domain, diffusion=diffusion, rhs=ConstantFunction(0, 2), neumann_data=ConstantFunction(-1, 2), robin_data=(LincombFunction( [ConstantFunction(1, 2)], [ProjectionParameterFunctional('biot', (), ())]), ConstantFunction(0, 2)), parameter_space=parameter_space) return problem
B = np.zeros((n, 1)) B[::2, 0] = 2 C = np.empty((1, n)) C[0, ::2] = c C[0, 1::2] = d # In[ ]: A0 = NumpyMatrixOperator(A0) Amu = NumpyMatrixOperator(Amu) B = NumpyMatrixOperator(B) C = NumpyMatrixOperator(C) # In[ ]: A = A0 + Amu * ProjectionParameterFunctional('mu', ()) # In[ ]: lti = LTIModel(A, B, C) # # Magnitude plot # In[ ]: mu_list_short = [1 / 50, 1 / 20, 1 / 10, 1 / 5, 1 / 2, 1] # In[ ]: w = np.logspace(0.5, 3.5, 200)