def fenics_vector_array_factory(length, space, seed): V = FenicsVectorSpace(fenics_spaces[space]) U = V.zeros(length) dim = V.dim np.random.seed(seed) for v, a in zip(U._list, np.random.random((length, dim))): v.real_part.impl[:] = a if np.random.randint(2): UU = V.zeros(length) for v, a in zip(UU._list, np.random.random((length, dim))): v.real_part.impl[:] = a for u, uu in zip(U._list, UU._list): u.imag_part = uu.real_part return U
def fenics_nonlinear_operator_factory(): import dolfin as df from pymor.bindings.fenics import FenicsVectorSpace, FenicsOperator, FenicsMatrixOperator class DirichletBoundary(df.SubDomain): def inside(self, x, on_boundary): return abs(x[0] - 1.0) < df.DOLFIN_EPS and on_boundary mesh = df.UnitSquareMesh(10, 10) V = df.FunctionSpace(mesh, "CG", 2) g = df.Constant(1.) c = df.Constant(1.) db = DirichletBoundary() bc = df.DirichletBC(V, g, db) u = df.TrialFunction(V) v = df.TestFunction(V) w = df.Function(V) f = df.Expression("x[0]*sin(x[1])", degree=2) F = df.inner((1 + c*w**2)*df.grad(w), df.grad(v))*df.dx - f*v*df.dx space = FenicsVectorSpace(V) op = FenicsOperator(F, space, space, w, (bc,), parameter_setter=lambda mu: c.assign(float(mu['c'])), parameter_type={'c': ()}, solver_options={'inverse': {'type': 'newton', 'rtol': 1e-6}}) prod = FenicsMatrixOperator(df.assemble(u*v*df.dx), V, V) return op, op.parse_parameter(42), op.source.random(), op.range.random(), prod, prod
def _fenics_vector_spaces(draw, np_data_list, compatible, count, dims): ret = [] for d, ar in zip(dims, np_data_list): assume(d > 1) if d not in _FENICS_spaces: _FENICS_spaces[d] = FenicsVectorSpace(df.FunctionSpace(df.UnitIntervalMesh(d - 1), 'Lagrange', 1)) ret.append((_FENICS_spaces[d], ar)) return ret
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 make_pymor_bindings(V, dx, ds, solver_options): import pymor.basic as pmb from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator from pymor.algorithms.timestepping import ImplicitEulerTimeStepper space = FenicsVectorSpace(V) # Operators matrix u = df.TrialFunction(V) v = df.TestFunction(V) mass_mat = [df.assemble(df.inner(u, v)*dx(i)) for i in domain_dict.values()] diff_mat = [df.assemble(df.inner(df.grad(u), df.grad(v))*dx(i)) for i in domain_dict.values()] robin_left_mat = df.assemble(u*v*ds(1)) source_mat = df.assemble(v*dx(domain_dict['die'])) # Function continues here with pymor bindings (see below)
def _discretize_fenics(): # assemble system matrices - FEniCS code ######################################## import dolfin as df # discrete function space mesh = df.UnitSquareMesh(GRID_INTERVALS, GRID_INTERVALS, 'crossed') V = df.FunctionSpace(mesh, 'Lagrange', FENICS_ORDER) u = df.TrialFunction(V) v = df.TestFunction(V) # data functions bottom_diffusion = df.Expression('(x[0] > 0.45) * (x[0] < 0.55) * (x[1] < 0.7) * 1.', element=df.FunctionSpace(mesh, 'DG', 0).ufl_element()) top_diffusion = df.Expression('(x[0] > 0.35) * (x[0] < 0.40) * (x[1] > 0.3) * 1. +' '(x[0] > 0.60) * (x[0] < 0.65) * (x[1] > 0.3) * 1.', element=df.FunctionSpace(mesh, 'DG', 0).ufl_element()) initial_data = df.Expression('(x[0] > 0.45) * (x[0] < 0.55) * (x[1] < 0.7) * 10.', element=df.FunctionSpace(mesh, 'DG', 0).ufl_element()) neumann_data = df.Expression('(x[0] > 0.45) * (x[0] < 0.55) * 1000.', element=df.FunctionSpace(mesh, 'DG', 0).ufl_element()) # assemble matrices and vectors l2_mat = df.assemble(df.inner(u, v) * df.dx) l2_0_mat = l2_mat.copy() h1_mat = df.assemble(df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx) h1_0_mat = h1_mat.copy() mat0 = h1_mat.copy() mat0.zero() bottom_mat = df.assemble(bottom_diffusion * df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx) top_mat = df.assemble(top_diffusion * df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx) u0 = df.project(initial_data, V).vector() f = df.assemble(neumann_data * v * df.ds) # boundary treatment def dirichlet_boundary(x, on_boundary): tol = 1e-14 return on_boundary and (abs(x[0]) < tol or abs(x[0] - 1) < tol or abs(x[1] - 1) < tol) bc = df.DirichletBC(V, df.Constant(0.), dirichlet_boundary) bc.apply(l2_0_mat) bc.apply(h1_0_mat) bc.apply(mat0) bc.zero(bottom_mat) bc.zero(top_mat) bc.apply(f) bc.apply(u0) # wrap everything as a pyMOR model ################################## from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator, FenicsVisualizer fom = InstationaryModel( T=1., initial_data=FenicsVectorSpace(V).make_array([u0]), operator=LincombOperator([FenicsMatrixOperator(mat0, V, V), FenicsMatrixOperator(h1_0_mat, V, V), FenicsMatrixOperator(bottom_mat, V, V), FenicsMatrixOperator(top_mat, V, V)], [1., 1., 100. - 1., ExpressionParameterFunctional('top[0] - 1.', {'top': 1})]), rhs=VectorOperator(FenicsVectorSpace(V).make_array([f])), mass=FenicsMatrixOperator(l2_0_mat, V, V, name='l2'), products={'l2': FenicsMatrixOperator(l2_mat, V, V, name='l2'), 'l2_0': FenicsMatrixOperator(l2_0_mat, V, V, name='l2_0'), 'h1': FenicsMatrixOperator(h1_mat, V, V, name='h1'), 'h1_0_semi': FenicsMatrixOperator(h1_0_mat, V, V, name='h1_0_semi')}, time_stepper=ImplicitEulerTimeStepper(nt=NT), visualizer=FenicsVisualizer(FenicsVectorSpace(V)) ) return fom
def _discretize_fenics(): # assemble system matrices - FEniCS code ######################################## import dolfin as df mesh = df.UnitSquareMesh(GRID_INTERVALS, GRID_INTERVALS, 'crossed') V = df.FunctionSpace(mesh, 'Lagrange', FENICS_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) 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 # define parameter functionals (same as in pymor.analyticalproblems.thermalblock) parameter_functionals = [ ProjectionParameterFunctional(component_name='diffusion', component_shape=(YBLOCKS, XBLOCKS), index=(YBLOCKS - y - 1, x)) 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') # 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}, parameter_space=parameter_space, visualizer=visualizer) return fom
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 make_pymor_bindings(V, dx, ds, solver_options): '''Assemble the Fenics operator and binds them to pymor.Operator with parameter separation Returns the full order model (pymor.Model)''' import pymor.basic as pmb from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator from pymor.algorithms.timestepping import ImplicitEulerTimeStepper space = FenicsVectorSpace(V) # Operators matrix u = df.TrialFunction(V) v = df.TestFunction(V) mass_mat = [ df.assemble(df.inner(u, v) * dx(i)) for i in domain_dict.values() ] diff_mat = [ df.assemble(df.inner(df.grad(u), df.grad(v)) * dx(i)) for i in domain_dict.values() ] robin_left_mat = df.assemble(u * v * ds(1)) source_mat = df.assemble(v * dx(domain_dict['die'])) # Norms matrix l2_mat = df.assemble(df.inner(u, v) * df.dx) l2_0_mat = l2_mat.copy() h1_mat = df.assemble(df.inner(df.grad(u), df.grad(v)) * dx) h1_0_mat = h1_mat.copy() # Operators mass_op = [ FenicsMatrixOperator(M, V, V, solver_options=solver_options) for M in mass_mat ] diff_op = [ FenicsMatrixOperator(M, V, V, solver_options=solver_options) for M in diff_mat ] robin_left_op = FenicsMatrixOperator(robin_left_mat, V, V, solver_options=solver_options) source_op = pmb.VectorOperator(space.make_array([source_mat])) # Param projection project_lamb = [ pmb.ProjectionParameterFunctional(f'lamb_{dom}', 1, 0) for dom in domain_dict.keys() ] project_capa = [ pmb.ProjectionParameterFunctional(f'capa_{dom}', 1, 0) for dom in domain_dict.keys() ] # Separated operator mass = pmb.LincombOperator(mass_op, project_capa) op = pmb.LincombOperator( [*diff_op, robin_left_op], [*project_lamb, pmb.ExpressionParameterFunctional('h[0]', {'h': 1})]) rhs = pmb.LincombOperator( [source_op], [pmb.ExpressionParameterFunctional('phi[0]', {'phi': 1})]) end_time = 10 * 60 dt = 5 fom = InstationaryParametricMassModel( T=end_time, initial_data=space.make_array([df.project(df.Constant(0), V).vector()]), operator=op, rhs=rhs, mass=mass, time_stepper=ImplicitEulerTimeStepper(end_time // dt), num_values=None, products={ 'l2': FenicsMatrixOperator(l2_mat, V, V), 'l2_0': FenicsMatrixOperator(l2_0_mat, V, V), 'h1': FenicsMatrixOperator(h1_mat, V, V), 'h1_0_semi': FenicsMatrixOperator(h1_0_mat, V, V) }, visualizer=None) return fom