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 __init__(self, args): self.args = args self.first = True self.problem = thermal_block_problem(num_blocks=(args['XBLOCKS'], args['YBLOCKS']), parameter_range=(PARAM_MIN, PARAM_MAX)) self.m, pack = discretize_stationary_cg(self.problem, diameter=1. / args['--grid']) self.grid = pack['grid']
def __init__(self, xblocks, yblocks, snapshots, rbsize, grid, product): self.snapshots, self.rbsize, self.product = snapshots, rbsize, product self.xblocks, self.yblocks = xblocks, yblocks self.first = True self.problem = thermal_block_problem(num_blocks=(xblocks, yblocks), parameter_range=(PARAM_MIN, PARAM_MAX)) self.m, pack = discretize_stationary_cg(self.problem, diameter=1. / grid) self.grid = pack['grid']
def test_visualize_patch(backend_gridtype): backend, gridtype = backend_gridtype domain = LineDomain() if gridtype is OnedGrid else RectDomain() dim = 1 if gridtype is OnedGrid else 2 rhs = GenericFunction(lambda X: np.ones(X.shape[:-1]) * 10, dim) # NOQA dirichlet = GenericFunction(lambda X: np.zeros(X.shape[:-1]), dim) # NOQA diffusion = GenericFunction(lambda X: np.ones(X.shape[:-1]), dim) # NOQA problem = StationaryProblem(domain=domain, rhs=rhs, dirichlet_data=dirichlet, diffusion=diffusion) grid, bi = discretize_domain_default(problem.domain, grid_type=gridtype) m, data = discretize_stationary_cg(analytical_problem=problem, grid=grid, boundary_info=bi) U = m.solve() try: visualize_patch(data['grid'], U=U, backend=backend) except QtMissing as ie: pytest.xfail("Qt missing") finally: stop_gui_processes()
def thermalblock_factory(xblocks, yblocks, diameter, seed): from pymor.analyticalproblems.thermalblock import thermal_block_problem from pymor.discretizers.builtin import discretize_stationary_cg from pymor.functions.basic import GenericFunction from pymor.discretizers.builtin.cg import InterpolationOperator p = thermal_block_problem((xblocks, yblocks)) m, m_data = discretize_stationary_cg(p, diameter) f = GenericFunction(lambda X, mu: X[..., 0]**mu['exp'] + X[..., 1], dim_domain=2, parameter_type={'exp': ()}) iop = InterpolationOperator(m_data['grid'], f) U = m.operator.source.empty() V = m.operator.range.empty() np.random.seed(seed) for exp in np.random.random(5): U.append(iop.as_vector(exp)) for exp in np.random.random(6): V.append(iop.as_vector(exp)) return m.operator, m.parameter_space.sample_randomly(1, seed=seed)[0], U, V, m.h1_product, m.l2_product
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 discretize_pymor(xblocks, yblocks, grid_num_intervals, use_list_vector_array): from pymor.analyticalproblems.thermalblock import thermal_block_problem from pymor.discretizers.builtin import discretize_stationary_cg from pymor.playground.discretizers.numpylistvectorarray import convert_to_numpy_list_vector_array print('Discretize ...') # setup analytical problem problem = thermal_block_problem(num_blocks=(xblocks, yblocks)) # discretize using continuous finite elements fom, _ = discretize_stationary_cg(problem, diameter=1. / grid_num_intervals) if use_list_vector_array: fom = convert_to_numpy_list_vector_array(fom) summary = f'''pyMOR model: number of blocks: {xblocks}x{yblocks} grid intervals: {grid_num_intervals} ListVectorArray: {use_list_vector_array} ''' return fom, summary
def thermalblock_demo(args): args['--grid'] = int(args['--grid']) args['RBSIZE'] = int(args['RBSIZE']) args['--test'] = int(args['--test']) args['--ipython-engines'] = int(args['--ipython-engines']) args['--extension-alg'] = args['--extension-alg'].lower() assert args['--extension-alg'] in {'trivial', 'gram_schmidt'} args['--product'] = args['--product'].lower() assert args['--product'] in {'trivial', 'h1'} args['--reductor'] = args['--reductor'].lower() assert args['--reductor'] in {'traditional', 'residual_basis'} args['--cache-region'] = args['--cache-region'].lower() args['--validation-mus'] = int(args['--validation-mus']) args['--rho'] = float(args['--rho']) args['--gamma'] = float(args['--gamma']) args['--theta'] = float(args['--theta']) problem = thermal_block_problem(num_blocks=(2, 2)) functionals = [ ExpressionParameterFunctional('diffusion[0]', {'diffusion': 2}), ExpressionParameterFunctional('diffusion[1]**2', {'diffusion': 2}), ExpressionParameterFunctional('diffusion[0]', {'diffusion': 2}), ExpressionParameterFunctional('diffusion[1]', {'diffusion': 2}) ] problem = problem.with_( diffusion=problem.diffusion.with_(coefficients=functionals), ) print('Discretize ...') fom, _ = discretize_stationary_cg(problem, diameter=1. / args['--grid']) if args['--list-vector-array']: from pymor.discretizers.builtin.list import convert_to_numpy_list_vector_array fom = convert_to_numpy_list_vector_array(fom) if args['--cache-region'] != 'none': # building a cache_id is only needed for persistent CacheRegions cache_id = f"pymordemos.thermalblock_adaptive {args['--grid']}" fom.enable_caching(args['--cache-region'], cache_id) if args['--plot-solutions']: print('Showing some solutions') Us = () legend = () for mu in problem.parameter_space.sample_randomly(2): print(f"Solving for diffusion = \n{mu['diffusion']} ... ") sys.stdout.flush() Us = Us + (fom.solve(mu), ) legend = legend + (str(mu['diffusion']), ) fom.visualize(Us, legend=legend, title='Detailed Solutions for different parameters', block=True) print('RB generation ...') product = fom.h1_0_semi_product if args['--product'] == 'h1' else None coercivity_estimator = ExpressionParameterFunctional( 'min([diffusion[0], diffusion[1]**2])', fom.parameters) reductors = { 'residual_basis': CoerciveRBReductor(fom, product=product, coercivity_estimator=coercivity_estimator), 'traditional': SimpleCoerciveRBReductor(fom, product=product, coercivity_estimator=coercivity_estimator) } reductor = reductors[args['--reductor']] pool = new_parallel_pool(ipython_num_engines=args['--ipython-engines'], ipython_profile=args['--ipython-profile']) greedy_data = rb_adaptive_greedy( fom, reductor, problem.parameter_space, validation_mus=args['--validation-mus'], rho=args['--rho'], gamma=args['--gamma'], theta=args['--theta'], use_estimator=not args['--without-estimator'], error_norm=fom.h1_0_semi_norm, max_extensions=args['RBSIZE'], visualize=not args['--no-visualize-refinement']) rom = greedy_data['rom'] if args['--pickle']: print( f"\nWriting reduced model to file {args['--pickle']}_reduced ...") with open(args['--pickle'] + '_reduced', 'wb') as f: dump(rom, f) print( f"Writing detailed model and reductor to file {args['--pickle']}_detailed ..." ) with open(args['--pickle'] + '_detailed', 'wb') as f: dump((fom, reductor), f) print('\nSearching for maximum error on random snapshots ...') results = reduction_error_analysis( rom, fom=fom, reductor=reductor, estimator=True, error_norms=(fom.h1_0_semi_norm, ), condition=True, test_mus=problem.parameter_space.sample_randomly(args['--test']), basis_sizes=25 if args['--plot-error-sequence'] else 1, plot=True, pool=pool) real_rb_size = rom.solution_space.dim print(''' *** RESULTS *** Problem: number of blocks: 2x2 h: sqrt(2)/{args[--grid]} Greedy basis generation: estimator disabled: {args[--without-estimator]} extension method: {args[--extension-alg]} product: {args[--product]} prescribed basis size: {args[RBSIZE]} actual basis size: {real_rb_size} elapsed time: {greedy_data[time]} '''.format(**locals())) print(results['summary']) sys.stdout.flush() if args['--plot-error-sequence']: from matplotlib import pyplot as plt plt.show(results['figure']) if args['--plot-err']: mumax = results['max_error_mus'][0, -1] U = fom.solve(mumax) URB = reductor.reconstruct(rom.solve(mumax)) fom.visualize( (U, URB, U - URB), legend=('Detailed Solution', 'Reduced Solution', 'Error'), title='Maximum Error Solution', separate_colorbars=True, block=True)
# License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) from itertools import product import pytest from pkg_resources import resource_filename from pymor.discretizers.builtin import discretize_stationary_cg, discretize_instationary_fv from pymor.discretizers.disk import discretize_stationary_from_disk, discretize_instationary_from_disk from pymortests.fixtures.analyticalproblem import ( picklable_thermalblock_problems, non_picklable_thermalblock_problems, burgers_problems) picklable_model_generators = \ [lambda p=p, d=d: discretize_stationary_cg(p, diameter=d)[0] for p, d in product(picklable_thermalblock_problems, [1./50., 1./100.])] + \ [lambda p=p, d=d: discretize_instationary_fv(p, diameter=d, nt=100)[0] for p, d in product(burgers_problems, [1./10., 1./15.])] + \ [lambda p=p: discretize_stationary_from_disk(parameter_file=p) for p in (resource_filename('pymortests', 'testdata/parameter_stationary.ini'),)] + \ [lambda p=p: discretize_instationary_from_disk(parameter_file=p) for p in (resource_filename('pymortests', 'testdata/parameter_instationary.ini'),)] non_picklable_model_generators = \ [lambda p=p, d=d: discretize_stationary_cg(p, diameter=d)[0] for p, d in product(non_picklable_thermalblock_problems, [1./20., 1./30.])] model_generators = picklable_model_generators + non_picklable_model_generators
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 discretize_quadratic_pdeopt_stationary_cg(problem, diameter=np.sqrt(2) / 100., weights=None, parameter_scales=None, domain_of_interest=None, desired_temperature=None, mu_for_u_d=None, mu_for_tikhonov=False, parameters_in_q=True, product='h1_l2_boundary', solver_options=None, use_corrected_functional=True, use_corrected_gradient=False, adjoint_approach=False): if use_corrected_functional: print('I am using the corrected functional!!') else: print('I am using the OLD functional!!') if use_corrected_gradient: print('I am using the corrected gradient!!') else: if adjoint_approach: print( 'I am using the adjoint approach for computing the gradient!!') print('I am using the OLD gradient!!') mu_bar = _construct_mu_bar(problem) print(mu_bar) primal_fom, data = discretize_stationary_cg(problem, diameter=diameter, grid_type=RectGrid, energy_product=mu_bar) #Preassemble non parametric parts: simplify, put the constant part in only one function simplified_operators = [ ZeroOperator(primal_fom.solution_space, primal_fom.solution_space) ] simplified_coefficients = [1] to_pre_assemble = ZeroOperator(primal_fom.solution_space, primal_fom.solution_space) if isinstance(primal_fom.operator, LincombOperator): for (i, coef) in enumerate(primal_fom.operator.coefficients): if isinstance(coef, Parametric): simplified_coefficients.append(coef) simplified_operators.append(primal_fom.operator.operators[i]) else: to_pre_assemble += coef * primal_fom.operator.operators[i] else: to_pre_assemble += primal_fom.operator simplified_operators[0] += to_pre_assemble simplified_operators[0] = simplified_operators[0].assemble() lincomb_operator = LincombOperator( simplified_operators, simplified_coefficients, solver_options=primal_fom.operator.solver_options) simplified_rhs = [ ZeroOperator(primal_fom.solution_space, NumpyVectorSpace(1)) ] simplified_rhs_coefficients = [1] to_pre_assemble = ZeroOperator(primal_fom.solution_space, NumpyVectorSpace(1)) if isinstance(primal_fom.rhs, LincombOperator): for (i, coef) in enumerate(primal_fom.rhs.coefficients): if isinstance(coef, Parametric): simplified_rhs_coefficients.append(coef) simplified_rhs.append(primal_fom.rhs.operators[i]) else: to_pre_assemble += coef * primal_fom.rhs.operators[i] else: to_pre_assemble += primal_fom.rhs simplified_rhs[0] += to_pre_assemble simplified_rhs[0] = simplified_rhs[0].assemble() lincomb_rhs = LincombOperator(simplified_rhs, simplified_rhs_coefficients) primal_fom = primal_fom.with_(operator=lincomb_operator, rhs=lincomb_rhs) grid = data['grid'] d = grid.dim # prepare data functions if desired_temperature is not None: u_desired = ConstantFunction(desired_temperature, d) if domain_of_interest is None: domain_of_interest = ConstantFunction(1., d) if mu_for_u_d is not None: domain_of_interest = ConstantFunction(1., d) modifified_mu = mu_for_u_d.copy() for key in mu_for_u_d.keys(): if len(mu_for_u_d[key]) == 0: modifified_mu.pop(key) u_d = primal_fom.solve(modifified_mu) else: assert desired_temperature is not None u_d = InterpolationOperator(grid, u_desired).as_vector() if grid.reference_element is square: L2_OP = L2ProductQ1 else: L2_OP = L2ProductP1 Restricted_L2_OP = L2_OP(grid, data['boundary_info'], dirichlet_clear_rows=False, coefficient_function=domain_of_interest) l2_u_d_squared = Restricted_L2_OP.apply2(u_d, u_d)[0][0] constant_part = 0.5 * l2_u_d_squared # assemble output functional from pdeopt.theta import build_output_coefficient if weights is not None: weight_for_J = weights.pop('state') else: weight_for_J = 1. if isinstance(weight_for_J, dict): assert len( weight_for_J ) == 4, 'you need to give all derivatives including second order' state_functional = ExpressionParameterFunctional( weight_for_J['function'], weight_for_J['parameter_type'], derivative_expressions=weight_for_J['derivative'], second_derivative_expressions=weight_for_J['second_derivatives']) elif isinstance(weight_for_J, float) or isinstance(weight_for_J, int): state_functional = ConstantParameterFunctional(weight_for_J) else: assert 0, 'state weight needs to be an integer or a dict with derivatives' if mu_for_tikhonov: if mu_for_u_d is not None: mu_for_tikhonov = mu_for_u_d else: assert isinstance(mu_for_tikhonov, dict) output_coefficient = build_output_coefficient( primal_fom.parameter_type, weights, mu_for_tikhonov, parameter_scales, state_functional, constant_part) else: output_coefficient = build_output_coefficient( primal_fom.parameter_type, weights, None, parameter_scales, state_functional, constant_part) output_functional = {} output_functional['output_coefficient'] = output_coefficient output_functional['linear_part'] = LincombOperator( [VectorOperator(Restricted_L2_OP.apply(u_d))], [-state_functional]) # j(.) output_functional['bilinear_part'] = LincombOperator( [Restricted_L2_OP], [0.5 * state_functional]) # k(.,.) output_functional['d_u_linear_part'] = LincombOperator( [VectorOperator(Restricted_L2_OP.apply(u_d))], [-state_functional]) # j(.) output_functional['d_u_bilinear_part'] = LincombOperator( [Restricted_L2_OP], [state_functional]) # 2k(.,.) l2_boundary_product = RobinBoundaryOperator( grid, data['boundary_info'], robin_data=(ConstantFunction(1, 2), ConstantFunction(1, 2)), name='l2_boundary_product') # choose product if product == 'h1_l2_boundary': opt_product = primal_fom.h1_semi_product + l2_boundary_product # h1_semi + l2_boundary elif product == 'fixed_energy': opt_product = primal_fom.energy_product # energy w.r.t. mu_bar (see above) else: assert 0, 'product: {} is not nown'.format(product) print('my product is {}'.format(product)) primal_fom = primal_fom.with_( products=dict(opt=opt_product, l2_boundary=l2_boundary_product, **primal_fom.products)) pde_opt_fom = QuadraticPdeoptStationaryModel( primal_fom, output_functional, opt_product=opt_product, use_corrected_functional=use_corrected_functional, use_corrected_gradient=use_corrected_gradient) return pde_opt_fom, data, mu_bar
def discretize_fin_pdeopt_stationary_cg(problem, grid, boundary_info, mu_for_u_d, product='h1_l2_boundary', use_corrected_functional=True, use_corrected_gradient=False, add_constant_term=False): if use_corrected_functional: print('I am using the corrected functional!!') else: print('I am using the OLD functional!!') if use_corrected_gradient: print('I am using the corrected gradient!!') else: print('I am using the OLD gradient!!') mu_bar = _construct_mu_bar(problem) print(mu_bar) primal_fom, data = discretize_stationary_cg(problem, grid=grid, boundary_info=boundary_info, energy_product=mu_bar) u_d = primal_fom.solve(mu_for_u_d) Boundary_Functional = primal_fom.rhs.operators[1] T_root_d = Boundary_Functional.apply_adjoint(u_d) T_root_d_squared = T_root_d.to_numpy()[0][0]**2 # assemble output functional from pdeopt.theta import build_output_coefficient weights = {} mu_for_tikhonov = {} parameter_scales = {} for key, item in mu_for_u_d.items(): if isinstance(item, list): weights[key] = 1. / item[0]**2 else: weights[key] = 1. / item**2 mu_for_tikhonov[key] = mu_for_u_d[key] parameter_scales[key] = 1. if add_constant_term: state_functional = ConstantParameterFunctional(1.) output_coefficient = build_output_coefficient( primal_fom.parameter_type, weights, mu_for_tikhonov, parameter_scales, state_functional=state_functional, constant_part=0.5 * T_root_d_squared) else: output_coefficient = build_output_coefficient( primal_fom.parameter_type, weights, mu_for_tikhonov, parameter_scales) output_functional = {} class Boundary_squared_half(ImmutableObject): def __init__(self, source, range): self.__auto_init(locals()) self.linear = False def apply2(self, u, v, mu=None): return Boundary_Functional.apply_adjoint(u).to_numpy( ) * Boundary_Functional.apply_adjoint(v).to_numpy() * 0.5 class Boundary_squared(ImmutableObject): def __init__(self, source, range): self.__auto_init(locals()) self.linear = False def apply2(self, u, v, mu=None): return Boundary_Functional.apply_adjoint(u).to_numpy( ) * Boundary_Functional.apply_adjoint(v).to_numpy() def apply(self, u, mu=None): b = (Boundary_Functional.apply_adjoint(u).to_numpy()[0][0] * Boundary_Functional).as_vector() return b source_ = Boundary_Functional.source range_ = Boundary_Functional.range output_functional['output_coefficient'] = output_coefficient output_functional[ 'linear_part'] = -1 * Boundary_Functional * T_root_d.to_numpy()[0][ 0] # j(.) output_functional['bilinear_part'] = Boundary_squared_half( range_, range_) # k(.,.) output_functional[ 'd_u_linear_part'] = -1 * Boundary_Functional * T_root_d.to_numpy()[0][ 0] # j(.) output_functional['d_u_bilinear_part'] = Boundary_squared( range_, range_) # 2k(.,.) # choose product l2_boundary_product = RobinBoundaryOperator( grid, data['boundary_info'], robin_data=(ConstantFunction(1, 2), ConstantFunction(1, 2)), name='l2_boundary_product') # choose product if product == 'h1_l2_boundary': opt_product = primal_fom.h1_semi_product + l2_boundary_product # h1_semi + l2_boundary elif product == 'fixed_energy': opt_product = primal_fom.energy_product # energy w.r.t. mu_bar (see above) else: assert 0, 'product: {} is not known'.format(product) print('my product is {}'.format(product)) primal_fom = primal_fom.with_( products=dict(opt=opt_product, l2_boundary=l2_boundary_product, **primal_fom.products)) pde_opt_fom = QuadraticPdeoptStationaryModel( primal_fom, output_functional, opt_product=opt_product, fin_model=True, use_corrected_functional=use_corrected_functional, use_corrected_gradient=use_corrected_gradient) return pde_opt_fom, data, mu_bar
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]')
def main( rbsize: int = Argument(..., help='Size of the reduced basis.'), cache_region: Choices('none memory disk persistent') = Option( 'none', help='Name of cache region to use for caching solution snapshots.' ), error_estimator: bool = Option(True, help='Use error estimator for basis generation.'), gamma: float = Option(0.2, help='Weight factor for age penalty term in refinement indicators.'), grid: int = Option(100, help='Use grid with 2*NI*NI elements.'), ipython_engines: int = Option( 0, help='If positive, the number of IPython cluster engines to use for parallel greedy search. ' 'If zero, no parallelization is performed.' ), ipython_profile: str = Option(None, help='IPython profile to use for parallelization.'), list_vector_array: bool = Option( False, help='Solve using ListVectorArray[NumpyVector] instead of NumpyVectorArray.' ), pickle: str = Option( None, help='Pickle reduced discretization, as well as reductor and high-dimensional model to files with this prefix.' ), plot_err: bool = Option(False, help='Plot error.'), plot_solutions: bool = Option(False, help='Plot some example solutions.'), plot_error_sequence: bool = Option(False, help='Plot reduction error vs. basis size.'), product: Choices('euclidean h1') = Option( 'h1', help='Product w.r.t. which to orthonormalize and calculate Riesz representatives.' ), reductor: Choices('traditional residual_basis') = Option( 'residual_basis', help='Reductor (error estimator) to choose (traditional, residual_basis).' ), rho: float = Option(1.1, help='Maximum allowed ratio between error on validation set and on training set.'), test: int = Option(10, help='Use COUNT snapshots for stochastic error estimation.'), theta: float = Option(0., help='Ratio of elements to refine.'), validation_mus: int = Option(0, help='Size of validation set.'), visualize_refinement: bool = Option(True, help='Visualize the training set refinement indicators.'), ): """Modified thermalblock demo using adaptive greedy basis generation algorithm.""" problem = thermal_block_problem(num_blocks=(2, 2)) functionals = [ExpressionParameterFunctional('diffusion[0]', {'diffusion': 2}), ExpressionParameterFunctional('diffusion[1]**2', {'diffusion': 2}), ExpressionParameterFunctional('diffusion[0]', {'diffusion': 2}), ExpressionParameterFunctional('diffusion[1]', {'diffusion': 2})] problem = problem.with_( diffusion=problem.diffusion.with_(coefficients=functionals), ) print('Discretize ...') fom, _ = discretize_stationary_cg(problem, diameter=1. / grid) if list_vector_array: from pymor.discretizers.builtin.list import convert_to_numpy_list_vector_array fom = convert_to_numpy_list_vector_array(fom) if cache_region != 'none': # building a cache_id is only needed for persistent CacheRegions cache_id = f"pymordemos.thermalblock_adaptive {grid}" fom.enable_caching(cache_region.value, cache_id) if plot_solutions: print('Showing some solutions') Us = () legend = () for mu in problem.parameter_space.sample_randomly(2): print(f"Solving for diffusion = \n{mu['diffusion']} ... ") sys.stdout.flush() Us = Us + (fom.solve(mu),) legend = legend + (str(mu['diffusion']),) fom.visualize(Us, legend=legend, title='Detailed Solutions for different parameters', block=True) print('RB generation ...') product_op = fom.h1_0_semi_product if product == 'h1' else None coercivity_estimator = ExpressionParameterFunctional('min([diffusion[0], diffusion[1]**2])', fom.parameters) reductors = {'residual_basis': CoerciveRBReductor(fom, product=product_op, coercivity_estimator=coercivity_estimator), 'traditional': SimpleCoerciveRBReductor(fom, product=product_op, coercivity_estimator=coercivity_estimator)} reductor = reductors[reductor] pool = new_parallel_pool(ipython_num_engines=ipython_engines, ipython_profile=ipython_profile) greedy_data = rb_adaptive_greedy( fom, reductor, problem.parameter_space, validation_mus=validation_mus, rho=rho, gamma=gamma, theta=theta, use_error_estimator=error_estimator, error_norm=fom.h1_0_semi_norm, max_extensions=rbsize, visualize=visualize_refinement ) rom = greedy_data['rom'] if pickle: print(f"\nWriting reduced model to file {pickle}_reduced ...") with open(pickle + '_reduced', 'wb') as f: dump(rom, f) print(f"Writing detailed model and reductor to file {pickle}_detailed ...") with open(pickle + '_detailed', 'wb') as f: dump((fom, reductor), f) print('\nSearching for maximum error on random snapshots ...') results = reduction_error_analysis(rom, fom=fom, reductor=reductor, error_estimator=True, error_norms=(fom.h1_0_semi_norm,), condition=True, test_mus=problem.parameter_space.sample_randomly(test), basis_sizes=25 if plot_error_sequence else 1, plot=True, pool=pool) real_rb_size = rom.solution_space.dim print(''' *** RESULTS *** Problem: number of blocks: 2x2 h: sqrt(2)/{grid} Greedy basis generation: error estimator enalbed: {error_estimator} product: {product} prescribed basis size: {rbsize} actual basis size: {real_rb_size} elapsed time: {greedy_data[time]} '''.format(**locals())) print(results['summary']) sys.stdout.flush() if plot_error_sequence: from matplotlib import pyplot as plt plt.show() if plot_err: mumax = results['max_error_mus'][0, -1] U = fom.solve(mumax) URB = reductor.reconstruct(rom.solve(mumax)) fom.visualize((U, URB, U - URB), legend=('Detailed Solution', 'Reduced Solution', 'Error'), title='Maximum Error Solution', separate_colorbars=True, block=True)