def __init__(self, T, initial_data, operator, rhs, mass=None, time_stepper=None, num_values=None, output_functional=None, products=None, error_estimator=None, visualizer=None, name=None): if isinstance(rhs, VectorArray): assert rhs in operator.range rhs = VectorOperator(rhs, name='rhs') if isinstance(initial_data, VectorArray): assert initial_data in operator.source initial_data = VectorOperator(initial_data, name='initial_data') mass = mass or IdentityOperator(operator.source) rhs = rhs or ZeroOperator(operator.source, NumpyVectorSpace(1)) assert isinstance(time_stepper, TimeStepper) assert initial_data.source.is_scalar assert operator.source == initial_data.range assert rhs.linear and rhs.range == operator.range and rhs.source.is_scalar assert mass.linear and mass.source == mass.range == operator.source assert output_functional is None or output_functional.source == operator.source super().__init__(products=products, error_estimator=error_estimator, visualizer=visualizer, name=name) self.parameters_internal = {'t': 1} self.__auto_init(locals()) self.solution_space = operator.source self.linear = operator.linear and (output_functional is None or output_functional.linear) if output_functional is not None: self.dim_output = output_functional.range.dim
def __init__(self, T, initial_data, operator, rhs, mass=None, time_stepper=None, num_values=None, output_functional=None, products=None, parameter_space=None, estimator=None, visualizer=None, name=None): if isinstance(rhs, VectorArrayInterface): assert rhs in operator.range rhs = VectorOperator(rhs, name='rhs') if isinstance(initial_data, VectorArrayInterface): assert initial_data in operator.source initial_data = VectorOperator(initial_data, name='initial_data') assert isinstance(time_stepper, TimeStepperInterface) assert initial_data.source.is_scalar assert operator.source == initial_data.range assert rhs is None \ or rhs.linear and rhs.range == operator.range and rhs.source.is_scalar assert mass is None \ or mass.linear and mass.source == mass.range == operator.source assert output_functional is None or output_functional.source == operator.source super().__init__(products=products, estimator=estimator, visualizer=visualizer, name=name) self.build_parameter_type(initial_data, operator, rhs, mass, output_functional, provides={'_t': 0}) self.__auto_init(locals()) self.solution_space = operator.source self.linear = operator.linear and (output_functional is None or output_functional.linear)
def _build_dual_models(self): assert self.primal_rom is not None assert self.RBPrimal is not None RBbasis = self.RBPrimal rhs_operators = list( self.fom.output_functional_dict['d_u_linear_part'].operators) rhs_coefficients = list( self.fom.output_functional_dict['d_u_linear_part'].coefficients) bilinear_part = self.fom.output_functional_dict['d_u_bilinear_part'] for i in range(len(RBbasis)): u = RBbasis[i] if isinstance(bilinear_part, LincombOperator): for j, op in enumerate(bilinear_part.operators): rhs_operators.append(VectorOperator(op.apply(u))) rhs_coefficients.append( ExpressionParameterFunctional( 'basis_coefficients[{}]'.format(i), {'basis_coefficients': len(RBbasis)}) * bilinear_part.coefficients[j]) else: rhs_operators.append( VectorOperator(bilinear_part.apply(u, None))) rhs_coefficients.append(1. * ExpressionParameterFunctional( 'basis_coefficients[{}]'.format(i), {'basis_coefficients': len(RBbasis)})) dual_rhs_operator = LincombOperator(rhs_operators, rhs_coefficients) dual_intermediate_fom = self.fom.primal_model.with_( rhs=dual_rhs_operator) if self.reductor_type == 'simple_coercive': print('building simple coercive dual reductor...') dual_reductor = SimpleCoerciveRBReductor( dual_intermediate_fom, RB=self.RBDual, product=self.opt_product, coercivity_estimator=self.coercivity_estimator) elif self.reductor_type == 'non_assembled': print('building non assembled dual reductor...') dual_reductor = NonAssembledCoerciveRBReductor( dual_intermediate_fom, RB=self.RBDual, product=self.opt_product, coercivity_estimator=self.coercivity_estimator) else: print('building coercive dual reductor...') dual_reductor = CoerciveRBReductor( dual_intermediate_fom, RB=self.RBDual, product=self.opt_product, coercivity_estimator=self.coercivity_estimator) dual_rom = dual_reductor.reduce() return dual_intermediate_fom, dual_rom, dual_reductor
def __init__(self, T, initial_data, operator, rhs, mass=None, time_stepper=None, num_values=None, outputs=None, products=None, parameter_space=None, estimator=None, visualizer=None, cache_region=None, name=None): if isinstance(rhs, VectorArrayInterface): assert rhs in operator.range rhs = VectorOperator(rhs, name='rhs') if isinstance(initial_data, VectorArrayInterface): assert initial_data in operator.source initial_data = VectorOperator(initial_data, name='initial_data') assert isinstance(time_stepper, TimeStepperInterface) assert initial_data.source.is_scalar assert operator.source == initial_data.range assert rhs is None \ or rhs.linear and rhs.range == operator.range and rhs.source.is_scalar assert mass is None \ or mass.linear and mass.source == mass.range == operator.source super().__init__(products=products, estimator=estimator, visualizer=visualizer, cache_region=cache_region, name=name) self.T = T self.initial_data = initial_data self.operator = operator self.rhs = rhs self.mass = mass self.solution_space = self.operator.source self.time_stepper = time_stepper self.num_values = num_values self.outputs = FrozenDict(outputs or {}) self.linear = operator.linear and all( output.linear for output in self.outputs.values()) self.build_parameter_type(self.initial_data, self.operator, self.rhs, self.mass, provides={'_t': 0}) self.parameter_space = parameter_space
def thermalblock_vector_factory(xblocks, yblocks, diameter, seed): from pymor.operators.constructions import VectorOperator _, _, U, V, sp, rp = thermalblock_factory(xblocks, yblocks, diameter, seed) op = VectorOperator(U.copy(ind=0)) U = NumpyVectorArray(np.random.random((7, 1)), copy=False) sp = NumpyMatrixOperator(np.eye(1) * 2) return op, None, U, V, sp, rp
def thermalblock_vector_factory(xblocks, yblocks, diameter, seed): from pymor.operators.constructions import VectorOperator _, _, U, V, sp, rp = thermalblock_factory(xblocks, yblocks, diameter, seed) op = VectorOperator(U[0]) U = op.source.make_array(np.random.random((7, 1))) sp = NumpyMatrixOperator(np.eye(1) * 2) return op, None, U, V, sp, rp
def __init__(self, T, initial_data, operator, rhs, mass=None, time_stepper=None, num_values=None, products=None, operators=None, parameter_space=None, estimator=None, visualizer=None, cache_region=None, name=None): if isinstance(initial_data, VectorArrayInterface): initial_data = VectorOperator(initial_data, name='initial_data') assert isinstance(time_stepper, TimeStepperInterface) assert initial_data.source.is_scalar assert operator.source == operator.range == initial_data.range assert rhs is None \ or rhs.linear and rhs.source == operator.source and rhs.range.is_scalar assert mass is None \ or mass.linear and mass.source == mass.range == operator.source super().__init__(initial_data=initial_data, operator=operator, rhs=rhs, mass=mass, operators=operators, products=products, estimator=estimator, visualizer=visualizer, cache_region=cache_region, name=name) self.T = T self.solution_space = self.operator.source self.time_stepper = time_stepper self.num_values = num_values self.build_parameter_type(self.initial_data, self.operator, self.rhs, self.mass, provides={'_t': 0}) self.parameter_space = parameter_space if hasattr(time_stepper, 'nt'): self.add_with_arguments = self.add_with_arguments | {'time_stepper_nt'}
def __init__(self, operator, rhs, output_functional=None, products=None, error_estimator=None, visualizer=None, name=None): if isinstance(rhs, VectorArray): assert rhs in operator.range rhs = VectorOperator(rhs, name='rhs') assert rhs.range == operator.range and rhs.source.is_scalar and rhs.linear assert output_functional is None or output_functional.source == operator.source super().__init__(products=products, error_estimator=error_estimator, visualizer=visualizer, name=name) self.__auto_init(locals()) self.solution_space = operator.source self.linear = operator.linear and (output_functional is None or output_functional.linear) if output_functional is not None: self.output_space = output_functional.range
def __init__(self, operator, rhs, outputs=None, products=None, parameter_space=None, estimator=None, visualizer=None, cache_region=None, name=None): if isinstance(rhs, VectorArrayInterface): assert rhs in operator.range rhs = VectorOperator(rhs, name='rhs') assert rhs.range == operator.range and rhs.source.is_scalar and rhs.linear super().__init__(products=products, estimator=estimator, visualizer=visualizer, cache_region=cache_region, name=name) self.operator = operator self.rhs = rhs self.outputs = FrozenDict(outputs or {}) self.solution_space = self.operator.source self.build_parameter_type(operator, rhs) self.parameter_space = parameter_space
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 discretize(dim, n, order): # ### problem definition import dolfin as df if dim == 2: mesh = df.UnitSquareMesh(n, n) elif dim == 3: mesh = df.UnitCubeMesh(n, n, n) else: raise NotImplementedError V = df.FunctionSpace(mesh, "CG", order) g = df.Constant(1.0) c = df.Constant(1.) class DirichletBoundary(df.SubDomain): def inside(self, x, on_boundary): return abs(x[0] - 1.0) < df.DOLFIN_EPS and on_boundary db = DirichletBoundary() bc = df.DirichletBC(V, g, db) u = df.Function(V) v = df.TestFunction(V) f = df.Expression("x[0]*sin(x[1])", degree=2) F = df.inner( (1 + c * u**2) * df.grad(u), df.grad(v)) * df.dx - f * v * df.dx df.solve(F == 0, u, bc, solver_parameters={"newton_solver": { "relative_tolerance": 1e-6 }}) # ### pyMOR wrapping from pymor.bindings.fenics import FenicsVectorSpace, FenicsOperator, FenicsVisualizer from pymor.models.basic import StationaryModel from pymor.operators.constructions import VectorOperator space = FenicsVectorSpace(V) op = FenicsOperator( F, space, space, u, (bc, ), parameter_setter=lambda mu: c.assign(mu['c'].item()), parameters={'c': 1}, solver_options={'inverse': { 'type': 'newton', 'rtol': 1e-6 }}) rhs = VectorOperator(op.range.zeros()) fom = StationaryModel(op, rhs, visualizer=FenicsVisualizer(space)) return fom
def action_NumpyMatrixOperator(self, op): vector = op.source.dim == 1 functional = op.range.dim == 1 if vector and functional: raise NotImplementedError if vector: space = NumpyListVectorSpace(op.range.dim, op.range.id) return VectorOperator(space.from_numpy(op.matrix.reshape((1, -1))), op.name) elif functional: space = NumpyListVectorSpace(op.source.dim, op.source.id) return VectorFunctional(space.from_numpy(op.matrix.ravel()), op.name) else: return op.with_(new_type=NumpyListVectorArrayMatrixOperator)
def _discretize_fenics(xblocks, yblocks, grid_num_intervals, element_order): # assemble system matrices - FEniCS code ######################################## import dolfin as df mesh = df.UnitSquareMesh(grid_num_intervals, grid_num_intervals, 'crossed') V = df.FunctionSpace(mesh, 'Lagrange', element_order) u = df.TrialFunction(V) v = df.TestFunction(V) diffusion = df.Expression('(lower0 <= x[0]) * (open0 ? (x[0] < upper0) : (x[0] <= upper0)) *' '(lower1 <= x[1]) * (open1 ? (x[1] < upper1) : (x[1] <= upper1))', lower0=0., upper0=0., open0=0, lower1=0., upper1=0., open1=0, element=df.FunctionSpace(mesh, 'DG', 0).ufl_element()) def assemble_matrix(x, y, nx, ny): diffusion.user_parameters['lower0'] = x/nx diffusion.user_parameters['lower1'] = y/ny diffusion.user_parameters['upper0'] = (x + 1)/nx diffusion.user_parameters['upper1'] = (y + 1)/ny diffusion.user_parameters['open0'] = (x + 1 == nx) diffusion.user_parameters['open1'] = (y + 1 == ny) return df.assemble(df.inner(diffusion * df.nabla_grad(u), df.nabla_grad(v)) * df.dx) mats = [assemble_matrix(x, y, xblocks, yblocks) for x in range(xblocks) for y in range(yblocks)] mat0 = mats[0].copy() mat0.zero() h1_mat = df.assemble(df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx) l2_mat = df.assemble(u * v * df.dx) f = df.Constant(1.) * v * df.dx F = df.assemble(f) bc = df.DirichletBC(V, 0., df.DomainBoundary()) for m in mats: bc.zero(m) bc.apply(mat0) bc.apply(h1_mat) bc.apply(F) # wrap everything as a pyMOR model ################################## # FEniCS wrappers from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator, FenicsVisualizer # generic pyMOR classes from pymor.models.basic import StationaryModel from pymor.operators.constructions import LincombOperator, VectorOperator from pymor.parameters.functionals import ProjectionParameterFunctional from pymor.parameters.spaces import CubicParameterSpace # define parameter functionals (same as in pymor.analyticalproblems.thermalblock) def parameter_functional_factory(x, y): return ProjectionParameterFunctional(component_name='diffusion', component_shape=(yblocks, xblocks), index=(yblocks - y - 1, x), name=f'diffusion_{x}_{y}') parameter_functionals = tuple(parameter_functional_factory(x, y) for x in range(xblocks) for y in range(yblocks)) # wrap operators ops = [FenicsMatrixOperator(mat0, V, V)] + [FenicsMatrixOperator(m, V, V) for m in mats] op = LincombOperator(ops, (1.,) + parameter_functionals) rhs = VectorOperator(FenicsVectorSpace(V).make_array([F])) h1_product = FenicsMatrixOperator(h1_mat, V, V, name='h1_0_semi') l2_product = FenicsMatrixOperator(l2_mat, V, V, name='l2') # build model visualizer = FenicsVisualizer(FenicsVectorSpace(V)) parameter_space = CubicParameterSpace(op.parameter_type, 0.1, 1.) fom = StationaryModel(op, rhs, products={'h1_0_semi': h1_product, 'l2': l2_product}, parameter_space=parameter_space, visualizer=visualizer) return fom
def __init__(self, T, initial_data, operator, rhs=None, mass=None, time_stepper=None, num_values=None, products=None, operators=None, functionals=None, vector_operators=None, parameter_space=None, estimator=None, visualizer=None, cache_region='disk', name=None): functionals = functionals or {} operators = operators or {} vector_operators = vector_operators or {} if isinstance(initial_data, VectorArrayInterface): initial_data = VectorOperator(initial_data, name='initial_data') assert isinstance(initial_data, OperatorInterface) assert initial_data.source == NumpyVectorSpace(1) assert 'initial_data' not in vector_operators or initial_data == vector_operators[ 'initial_data'] assert isinstance(operator, OperatorInterface) assert operator.source == operator.range == initial_data.range assert 'operator' not in operators or operator == operators['operator'] assert rhs is None or isinstance(rhs, OperatorInterface) and rhs.linear assert rhs is None or rhs.source == operator.source and rhs.range.dim == 1 assert 'rhs' not in functionals or rhs == functionals['rhs'] assert mass is None or isinstance(mass, OperatorInterface) and mass.linear assert mass is None or mass.source == mass.range == operator.source assert 'mass' not in operators or mass == operators['mass'] assert isinstance(time_stepper, TimeStepperInterface) assert all(f.source == operator.source for f in functionals.values()) operators_with_operator_mass = {'operator': operator, 'mass': mass} operators_with_operator_mass.update(operators) functionals_with_rhs = {'rhs': rhs} if rhs else {} functionals_with_rhs.update(functionals) vector_operators_with_initial_data = {'initial_data': initial_data} vector_operators_with_initial_data.update(vector_operators) super(InstationaryDiscretization, self).__init__( operators=operators_with_operator_mass, functionals=functionals_with_rhs, vector_operators=vector_operators_with_initial_data, products=products, estimator=estimator, visualizer=visualizer, cache_region=cache_region, name=name) self.T = T self.solution_space = operator.source self.initial_data = initial_data self.operator = operator self.rhs = rhs self.mass = mass self.time_stepper = time_stepper self.num_values = num_values self.build_parameter_type(inherits=(initial_data, operator, rhs, mass), provides={'_t': 0}) self.parameter_space = parameter_space if hasattr(time_stepper, 'nt'): self.with_arguments = self.with_arguments.union( {'time_stepper_nt'})
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