def computeVelocityField(mesh): Xh = dl.VectorFunctionSpace(mesh, 'Lagrange', 2) Wh = dl.FunctionSpace(mesh, 'Lagrange', 1) XW = dl.MixedFunctionSpace([Xh, Wh]) Re = 1e2 g = dl.Expression(('0.0', '(x[0] < 1e-14) - (x[0] > 1 - 1e-14)')) bc1 = dl.DirichletBC(XW.sub(0), g, v_boundary) bc2 = dl.DirichletBC(XW.sub(1), dl.Constant(0), q_boundary, 'pointwise') bcs = [bc1, bc2] vq = dl.Function(XW) (v, q) = dl.split(vq) (v_test, q_test) = dl.TestFunctions(XW) def strain(v): return dl.sym(dl.nabla_grad(v)) F = ((2. / Re) * dl.inner(strain(v), strain(v_test)) + dl.inner(dl.nabla_grad(v) * v, v_test) - (q * dl.div(v_test)) + (dl.div(v) * q_test)) * dl.dx dl.solve(F == 0, vq, bcs, solver_parameters={ "newton_solver": { "relative_tolerance": 1e-4, "maximum_iterations": 100 } }) return v
def get_Dirichlet_bc(self): r""" Returns the Dirichlet boundary conditions for the IR theory: .. math:: \hat{\pi}(\hat{r}_{\rm max}) = \hat{W}(\hat{r}_{\rm max}) = \hat{Y}(\hat{r}_{\rm max}) = 0 The Neumann boundary conditions .. math:: \left\lbrace \frac{d\hat{\pi}}{d\hat{r}}(0) = 0; \frac{d\hat{W}}{d\hat{r}}(0) = \mathrm{finite} \right\rbrace are natural boundary conditions in the finite element method, and are implemented within the variational formulation. """ # define values at infinity # for 'infinity', we use the last mesh point, i.e. r_max (i.e. mesh[-1]) piD = d.Constant(0.) wD = d.Constant(0.) yD = d.Constant(0.) # define 'infinity' boundary: the rightmost mesh point - within machine precision def boundary(x): return self.fem.mesh.r_max - x[0] < d.DOLFIN_EPS bc_pi = d.DirichletBC(self.V.sub(0), piD, boundary, method='pointwise') bc_w = d.DirichletBC(self.V.sub(1), wD, boundary, method='pointwise') bc_y = d.DirichletBC(self.V.sub(2), yD, boundary, method='pointwise') Dirichlet_bc = [bc_pi, bc_w, bc_y] return Dirichlet_bc
def __init__(self, mesh, Vh, Prior): """ Construct a model by proving - the mesh - the finite element spaces for the STATE/ADJOINT variable and the PARAMETER variable - the Prior information """ self.mesh = mesh self.Vh = Vh # Initialize Expressions self.mtrue = dl.Expression( 'log(2 + 7*(pow(pow(x[0] - 0.5,2) + pow(x[1] - 0.5,2),0.5) > 0.2))', element=Vh[PARAMETER].ufl_element()) self.f = dl.Constant(1.0) self.u_o = dl.Vector() self.u_bdr = dl.Constant(0.0) self.u_bdr0 = dl.Constant(0.0) self.bc = dl.DirichletBC(self.Vh[STATE], self.u_bdr, u_boundary) self.bc0 = dl.DirichletBC(self.Vh[STATE], self.u_bdr0, u_boundary) # Assemble constant matrices self.prior = Prior self.Wuu = self.assembleWuu() self.computeObservation(self.u_o) self.A = None self.At = None self.C = None self.Wmm = None self.Wmu = None self.gauss_newton_approx = False
def __init__(self, mesh, Vh, targets, prior): """ Construct a model by proving - the mesh - the finite element spaces for the STATE/ADJOINT variable and the PARAMETER variable - the Prior information """ self.mesh = mesh self.Vh = Vh # Initialize Expressions self.f = dl.Expression("0.0") self.u_bdr = dl.Expression("x[1]") self.u_bdr0 = dl.Expression("0.0") self.bc = dl.DirichletBC(self.Vh[STATE], self.u_bdr, u_boundary) self.bc0 = dl.DirichletBC(self.Vh[STATE], self.u_bdr0, u_boundary) # Assemble constant matrices self.prior = prior self.B = assemblePointwiseObservation(Vh[STATE], targets) self.A = [] self.At = [] self.C = [] self.Raa = [] self.Wau = [] self.u_o = dl.Vector() self.B.init_vector(self.u_o, 0) self.noise_variance = 0
def stokes(self): P2 = df.VectorElement("CG", self.mesh.ufl_cell(), 2) P1 = df.FiniteElement("CG", self.mesh.ufl_cell(), 1) TH = P2 * P1 VQ = df.FunctionSpace(self.mesh, TH) mf = self.mf self.no_slip = df.Constant((0., 0)) U0_str = "4.*U_m*x[1]*(.41-x[1])/(.41*.41)" U0 = df.Expression((U0_str, "0"), U_m=self.U_m, degree=2) bc0 = df.DirichletBC(VQ.sub(0), df.Constant((0, 0)), mf, self.bc_dict["obstacle"]) bc1 = df.DirichletBC(VQ.sub(0), df.Constant((0, 0)), mf, self.bc_dict["channel_walls"]) bc2 = df.DirichletBC(VQ.sub(0), U0, mf, self.bc_dict["inlet"]) bc3 = df.DirichletBC(VQ.sub(1), df.Constant(0), mf, self.bc_dict["outlet"]) bcs = [bc0, bc1, bc2, bc3] vup = df.TestFunction(VQ) up = df.TrialFunction(VQ) up_ = df.Function(VQ) u, p = df.split(up) # Trial vu, vp = df.split(vup) # Test u_, p_ = df.split(up_) # Function holding the solution inner, grad, dx, div = df.inner, df.grad, df.dx, df.div F = self.mu*inner(grad(vu), grad(u))*dx - inner(div(vu), p)*dx \ - inner(vp, div(u))*dx df.solve(df.lhs(F) == df.rhs(F), up_, bcs=bcs) self.u_.assign(df.project(u_, self.V)) self.p_.assign(df.project(p_, self.Q)) return
def test_3d(self): prm = c.Parameters(c.Constraint.FULL) mesh = df.UnitCubeMesh(5, 5, 5) u_bc = 42.0 problem = c.MechanicsProblem(mesh, prm, law(prm)) bcs = [] bcs.append(df.DirichletBC(problem.Vd.sub(0), 0, boundary.plane_at(0))) bcs.append( df.DirichletBC(problem.Vd.sub(0), u_bc, boundary.plane_at(1))) bcs.append( df.DirichletBC(problem.Vd.sub(1), 0, boundary.plane_at(0, "y"))) bcs.append( df.DirichletBC(problem.Vd.sub(2), 0, boundary.plane_at(0, "z"))) problem.set_bcs(bcs) u = problem.solve() xs = np.linspace(0, 1, 5) for x in xs: for y in xs: for z in xs: u_fem = u((x, y, z)) # print(u_fem) u_correct = (x * u_bc, -y * u_bc * prm.nu, -z * u_bc * prm.nu) self.assertAlmostEqual(u_fem[0], u_correct[0]) self.assertAlmostEqual(u_fem[1], u_correct[1]) self.assertAlmostEqual(u_fem[2], u_correct[2])
def get_bc_dofs(self, boundary_conditions): """ Construct the blocked u-DOF's for the stability problem """ debug = False # Construct homogeneous BCs bcs_Z = [] zero = dolfin.Constant(0.0) if self.u.geometric_dimension() > 1: # vector zeros = dolfin.Constant([ 0.0, ] * self.u.geometric_dimension()) elif self.u.geometric_dimension() == 1: # scalar zeros = dolfin.Constant(0.) for bc in self.bcs[0]: if hasattr(bc, 'sub_domain'): new_bc = dolfin.DirichletBC(self.Z.sub(0), zeros, bc.sub_domain, bc.method()) elif hasattr(bc, 'domain_args'): new_bc = dolfin.DirichletBC(self.Z.sub(0), zeros, bc.domain_args[0], bc.domain_args[1], bc.method()) else: raise RuntimeError( "Couldn't find where bcs for displacement are applied") bcs_Z.append(new_bc) for bc in self.bcs[1]: if hasattr(bc, 'sub_domain'): new_bc = dolfin.DirichletBC(self.Z.sub(1), zero, bc.sub_domain, bc.method()) elif hasattr(bc, 'domain_args'): new_bc = dolfin.DirichletBC(self.Z.sub(1), zero, bc.domain_args[0], bc.domain_args[1], bc.method()) else: raise RuntimeError( "Couldn't find where bcs for damage are applied") bcs_Z.append(new_bc) # Locate the DOF's corresponding to the BC bc_keys = [set(bc.get_boundary_values().keys()) for bc in bcs_Z] dofmap = self.Z.dofmap() bc_keys_glob = [] for bc_key in bc_keys: bc_key_global = [] for x in bc_key: bc_key_global.append(dofmap.local_to_global_index(x)) bc_keys_glob.append(set(bc_key_global)) if bc_keys_glob: self.bc_dofs = reduce(lambda x, y: x.union(y), bc_keys_glob) else: self.bc_dofs = set() self.bcs_Z = bcs_Z return self.bc_dofs
def set_DirichletBC(self, V, logger, subspace=None, value=None): """ Set Dirichlet Boundary Conditions. :param V: FEniCS Function Space :param logger: global logger :param subspace: for instance for EQS we need values for subspaces :param value: if there is no value in the input file, we can set it (needed for the imaginary part in EQS for instance) """ if 'Dirichlet' in self.boundary_dict: self.boundary_info = self.boundary_dict['Dirichlet'] if value is None: valuetag = None logger.debug("Set Dirichlet boundaries with info: {}".format( self.boundary_info)) else: valuetag = True logger.debug( "Set Dirichlet boundaries for all facets with value {}.". format(value)) for boundary_key in self.boundary_info: if valuetag is None: value = self.boundary_info[boundary_key] if subspace is None: if boundary_key in self.facet_dict: self.bc.append( d.DirichletBC(V, d.Constant(value), self.facets, self.facet_dict[boundary_key])) logger.info( "Set boundary for: {}, value {}, facet number {}". format(boundary_key, value, self.facet_dict[boundary_key])) elif boundary_key in self.subdomain_dict: raise Exception('BC must be facet!') # self.bc.append(d.DirichletBC(V, d.Constant(value), self.subdomains, self.subdomain_dict[boundary_key])) # logger.info("Set boundary for: {}, value {}, subdomain number {}".format(boundary_key, value, self.subdomain_dict[boundary_key])) else: raise Exception( "BC neither match facets nor subdomains!!!!") else: if boundary_key in self.facet_dict: self.bc.append( d.DirichletBC(V.sub(subspace), value, self.facets, self.facet_dict[boundary_key])) logger.info( "Set boundary for: {} and subspace {}, value {}, facet number {}" .format(boundary_key, subspace, value, self.facet_dict[boundary_key])) elif boundary_key in self.subdomain_dict: raise Exception('BC must be facet!') # self.bc.append(d.DirichletBC(V.sub(subspace), value, self.subdomains, self.subdomain_dict[boundary_key])) # logger.info("Set boundary for: {} and subspace {}, value {}, subdomain number {}".format(boundary_key, subspace, value, self.subdomain_dict[boundary_key])) else: raise Exception( "BC neither match facets nor subdomains!!!!")
def create_bcs(W, boundary_markers, pinpoint=None): bcs = [] zero, vec_zero = df.Constant(0.0), df.Constant((0.0, 0.0)) bcs.append(df.DirichletBC(W.sub(0), vec_zero, boundary_markers, 1)) bcs.append(df.DirichletBC(W.sub(0).sub(1), zero, boundary_markers, 2)) bcs.append(df.DirichletBC(W.sub(0).sub(1), zero, boundary_markers, 3)) bcs.append(df.DirichletBC(W.sub(0).sub(1), zero, boundary_markers, 4)) return bcs
def make_dirichlet_bcs(W): V = W if W.sub(0).num_sub_spaces() == 0 else W.sub(0) if BC_type == 'fix_x': no_base_x_tran_bc = df.DirichletBC(V.sub(0), df.Constant(0.0), marked_mesh, patient.markers["BASE"][0]) elif BC_type == 'fixed': no_base_x_tran_bc = df.DirichletBC(V, df.Constant( (0.0, 0.0, 0.0)), marked_mesh, patient.markers["BASE"][0]) return no_base_x_tran_bc
def __init__(self, parameters, mesh_name, facet_name, bc_dict={ "obstacle": 2, "channel_walls": 1, "inlet": 3, "outlet": 4 }): """ Create the required function spaces, functions and boundary conditions for a channel flow problem """ self.bc_dict = bc_dict self.mesh = df.Mesh() with df.XDMFFile(mesh_name) as infile: infile.read(self.mesh) mvc = df.MeshValueCollection("size_t", self.mesh, self.mesh.topology().dim() - 1) with df.XDMFFile(facet_name) as infile: infile.read(mvc, "name_to_read") self.mf = mf = df.cpp.mesh.MeshFunctionSizet(self.mesh, mvc) self.V = V = df.VectorFunctionSpace(self.mesh, 'P', parameters["degree velocity"]) self.Q = Q = df.FunctionSpace(self.mesh, 'P', parameters["degree pressure"]) self.rho = df.Constant(parameters["density [kg/m3]"]) self.mu = df.Constant(parameters["viscosity [Pa*s]"]) self.dt = df.Constant(parameters["dt [s]"]) self.g = df.Constant((0, 0)) self.vu, self.vp = df.TestFunction(V), df.TestFunction(Q) self.u_, self.p_ = df.Function(V), df.Function(Q) self.u_1, self.p_1 = df.Function(V), df.Function(Q) self.u_k, self.p_k = df.Function(V), df.Function(Q) self.u, self.p = df.TrialFunction(V), df.TrialFunction(Q) # unknown! self.U_m = U_m = parameters["velocity [m/s]"] x = [0, .41 / 2] # center of the channel Ucenter = 4. * U_m * x[1] * (.41 - x[1]) / (.41 * .41) U0_str = "4.*U_m*x[1]*(.41-x[1])/(.41*.41)" self.U_mean = np.mean(2 / 3 * Ucenter) U0 = df.Expression((U0_str, "0"), U_m=U_m, degree=2) bc0 = df.DirichletBC(V, df.Constant((0, 0)), mf, bc_dict["obstacle"]) bc1 = df.DirichletBC(V, df.Constant((0, 0)), mf, bc_dict["channel_walls"]) bc2 = df.DirichletBC(V, U0, mf, bc_dict["inlet"]) bc3 = df.DirichletBC(Q, df.Constant(0), mf, bc_dict["outlet"]) self.bcu = [bc0, bc1, bc2] self.bcp = [bc3] self.ds_ = df.Measure("ds", domain=self.mesh, subdomain_data=mf) return
def setUp(self): d.set_log_level(d.LogLevel.WARNING) N = 50 order = 2 tF = 0.10 # Dirichlet boundary characteristic time tau = tF / 10.0 # time step h = 0.001 self.num_steps = round(tF / h) # Mesh and Function space mesh = d.UnitIntervalMesh(N) V = d.FunctionSpace(mesh, "P", order) w = d.TestFunction(V) v = d.TrialFunction(V) # Initial conditions chosen such that the wave travels to the right uInit = d.Expression( "((1./3 < x[0]) && (x[0] < 2./3)) ? 0.5*(1-cos(2*pi*3*(x[0]-1./3))) : 0.", degree=2, ) u = d.interpolate(uInit, V) # values # Dirichlet boundary on the right with its derivatives g = d.Expression( "(t < total) ? 0.4*(1.-cos(2*pi*t/total))/2. : 0.", degree=2, t=0.0, total=tau, ) dg = d.Expression( "(t < total) ? 0.4*(pi/total) * sin(2*pi*t/total) : 0.", degree=2, t=0.0, total=tau, ) def updateBC(t): g.t = t dg.t = t def right(x, on_boundary): return on_boundary and d.near(x[0], 1.0) bc0 = d.DirichletBC(V, g, right) bc1 = d.DirichletBC(V, dg, right) self.bc = [bc0, bc1] L1 = -d.inner(d.grad(w), d.grad(u)) * d.dx L2 = w * v * d.dx self.parameters = (L1, L2, u, h, updateBC)
def calculate_interpolation(self): def boundary(x, on_boundary): return on_boundary V = self.function_space bc_Re = dolfin.DirichletBC(V, self.interpolant_expression_Re, boundary) bc_Im = dolfin.DirichletBC(V, self.interpolant_expression_Im, boundary) bc_Re.apply(self.u_r.vector()) bc_Im.apply(self.u_i.vector()) x = np.zeros(self.u_r.vector().size(), np.complex128) x[:] = self.u_r.vector().array() + 1j * self.u_i.vector().array() return x
def computeVelocityField(self): """ The steady-state Navier-Stokes equation for velocity v: -1/Re laplace v + nabla q + v dot nabla v = 0 in Omega nabla dot v = 0 in Omega v = g on partial Omega """ Xh = dl.VectorFunctionSpace(self.mesh, 'Lagrange', self.eldeg) Wh = dl.FunctionSpace(self.mesh, 'Lagrange', 1) mixed_element = dl.MixedElement([Xh.ufl_element(), Wh.ufl_element()]) XW = dl.FunctionSpace(self.mesh, mixed_element) Re = dl.Constant(self.Re) def v_boundary(x, on_boundary): return on_boundary def q_boundary(x, on_boundary): return x[0] < dl.DOLFIN_EPS and x[1] < dl.DOLFIN_EPS g = dl.Expression(('0.0', '(x[0] < 1e-14) - (x[0] > 1 - 1e-14)'), element=Xh.ufl_element()) bc1 = dl.DirichletBC(XW.sub(0), g, v_boundary) bc2 = dl.DirichletBC(XW.sub(1), dl.Constant(0), q_boundary, 'pointwise') bcs = [bc1, bc2] vq = dl.Function(XW) (v, q) = ufl.split(vq) (v_test, q_test) = dl.TestFunctions(XW) def strain(v): return ufl.sym(ufl.grad(v)) F = ((2. / Re) * ufl.inner(strain(v), strain(v_test)) + ufl.inner(ufl.nabla_grad(v) * v, v_test) - (q * ufl.div(v_test)) + (ufl.div(v) * q_test)) * ufl.dx dl.solve(F == 0, vq, bcs, solver_parameters={ "newton_solver": { "relative_tolerance": 1e-4, "maximum_iterations": 100, "linear_solver": "default" } }) return v
def __init__(self, mesh, Vh, prior): """ Construct a model by proving - the mesh - the finite element spaces for the STATE/ADJOINT variable and the PARAMETER variable - the prior information """ self.mesh = mesh self.Vh = Vh # Initialize Expressions mtrue_exp = dl.Expression( '0.2*(15.0 - 5.0*sin(3.1416*(x[1]/20.0 - 0.5)))', element=Vh[PARAMETER].ufl_element()) self.mtrue = dl.interpolate(mtrue_exp, self.Vh[PARAMETER]).vector() self.f = dl.Expression(("0.0", "0.0022", "0.0"), element=Vh[STATE].ufl_element()) self.u_o = dl.Vector() self.u_bdr = dl.Expression(("0.0", "0.0", "0.0"), element=Vh[STATE].ufl_element()) self.u_bdr0 = dl.Expression(("0.0", "0.0", "0.0"), element=Vh[STATE].ufl_element()) self.bc = dl.DirichletBC(self.Vh[STATE], self.u_bdr, Gamma_D) self.bc0 = dl.DirichletBC(self.Vh[STATE], self.u_bdr0, Gamma_D) # Assemble constant matrices self.prior = prior self.Wuu = self.assembleWuu() self.computeObservation(self.u_o) self.A = None self.At = None self.C = None self.Wmm = None self.Wmu = None self.gauss_newton_approx = True self.solver = PETScKrylovSolver(mesh.mpi_comm(), "cg", amg_method()) self.solver_fwd_inc = PETScKrylovSolver(mesh.mpi_comm(), "cg", amg_method()) self.solver_adj_inc = PETScKrylovSolver(mesh.mpi_comm(), "cg", amg_method()) self.solver.parameters["relative_tolerance"] = 1e-9 self.solver.parameters["absolute_tolerance"] = 1e-12 self.solver_fwd_inc.parameters = self.solver.parameters self.solver_adj_inc.parameters = self.solver.parameters
def create_bcs(W, boundary_markers, periodic_boundary=None, pinpoint=None): bcs = [] zero, vec_zero = df.Constant(0.0), df.Constant((0.0, 0.0)) bcs.append(df.DirichletBC(W.sub(0), vec_zero, boundary_markers, 1)) bcs.append(df.DirichletBC(W.sub(0), vec_zero, boundary_markers, 3)) if periodic_boundary is None: bcs.append(df.DirichletBC(W.sub(0).sub(0), zero, boundary_markers, 2)) bcs.append(df.DirichletBC(W.sub(0).sub(0), zero, boundary_markers, 4)) if pinpoint is not None: bcs.append(df.DirichletBC(W.sub(1), zero, pinpoint, method="pointwise")) return bcs
def update_boundary_conditions(self): """ Update the boundary conditions for new wall location and new wall temperature. """ # Update the thermal boundary condition at the wall based on the current concentration Tf_wall_last = self.Tf_wall self.Tf = Tf_depression(self.C,linear=True)/abs(self.T_inf) self.C_wall = dolfin.project(self.C,self.sol_V).vector()[self.sol_idx_wall] Tf_wall_hold = Tf_depression(self.C_wall,linear=True)/abs(self.T_inf) self.Tf_wall = Tf_wall_last + (Tf_wall_hold-Tf_wall_last)*self.Tf_reg # Reset ice boundary condition self.bc_iWall = dolfin.DirichletBC(self.ice_V, self.Tf_wall, self.iWall) # Reset solution boundary condition self.bc_sWall = dolfin.DirichletBC(self.sol_V, self.Tf_wall, self.sWall)
def stefan_function_spaces(degree=DEGREE): T_ele = dolfin.FiniteElement("CG", mesh.ufl_cell(), degree) T = dolfin.FunctionSpace(mesh, T_ele) boundary_conditions = [ dolfin.DirichletBC(T, theta_analytic, boundary[0], 1), dolfin.DirichletBC(T, theta_analytic, boundary[0], 2) ] theta = dolfin.Function(T) _theta = dolfin.TrialFunction(T) theta_ = dolfin.TestFunction(T) return (T, boundary_conditions, theta, _theta, theta_)
def burgers_spacedisc(N=10, nu=None, x0=0.0, xE=1.0, retfemdict=False, condensemats=True): mesh = dolfin.IntervalMesh(N, x0, xE) V = dolfin.FunctionSpace(mesh, 'CG', 1) u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) # boundaries and conditions ugamma = dolfin.Expression('0', degree=1) def _spaceboundary(x, on_boundary): return on_boundary diribc = dolfin.DirichletBC(V, ugamma, _spaceboundary) mass = assemble(v*u*dx) stif = assemble(nu*inner(nabla_grad(v), nabla_grad(u))*dx) M = dts.mat_dolfin2sparse(mass) A = dts.mat_dolfin2sparse(stif) M, _, bcdict = dts.condense_velmatsbybcs(M, [diribc], return_bcinfo=True) ininds = bcdict['ininds'] A, rhsa = dts.condense_velmatsbybcs(A, [diribc]) def burger_nonl(vvec, t): v0 = expandvfunc(vvec, V=V, ininds=ininds) bnl = assemble(0.5*v*((v0*v0).dx(0))*dx) return bnl.array()[ininds] if retfemdict: return M, A, rhsa, burger_nonl, dict(V=V, diribc=diribc, ininds=ininds) else: return M, A, rhsa, burger_nonl
def get_distance_function(config, domains): V = dolfin.FunctionSpace(config.domain.mesh, "CG", 1) v = dolfin.TestFunction(V) d = dolfin.TrialFunction(V) sol = dolfin.Function(V) s = dolfin.interpolate(Constant(1.0), V) domains_func = dolfin.Function(dolfin.FunctionSpace(config.domain.mesh, "DG", 0)) domains_func.vector().set_local(domains.array().astype(numpy.float)) def boundary(x): eps_x = config.params["turbine_x"] eps_y = config.params["turbine_y"] min_val = 1 for e_x, e_y in [(-eps_x, 0), (eps_x, 0), (0, -eps_y), (0, eps_y)]: try: min_val = min(min_val, domains_func((x[0] + e_x, x[1] + e_y))) except RuntimeError: pass return min_val == 1.0 bc = dolfin.DirichletBC(V, 0.0, boundary) # Solve the diffusion problem with a constant source term log(INFO, "Solving diffusion problem to identify feasible area ...") a = dolfin.inner(dolfin.grad(d), dolfin.grad(v)) * dolfin.dx L = dolfin.inner(s, v) * dolfin.dx dolfin.solve(a == L, sol, bc) return sol
def solve(self, vkscale=1., lscale=1., sscale=1.): """This approach only works for small grids since the memory requirements rapidly become prohibitive. (nl, nk, nv) = (8, 45, 40) is just barely doable on my laptop. If the memory is available, computation time is not significant. """ D = d.Function(self.tensor_space) # diffusion tensor Q = d.Function(self.scalar_space) # source term u = d.TrialFunction(self.scalar_space) # u is my 'f' v = d.TestFunction(self.scalar_space) soln = d.Function(self.scalar_space) a = d.dot(d.dot(D, d.grad(u)), d.grad(v)) * d.dx L = Q * v * d.dx equation = (a == L) soln = d.Function(self.scalar_space) bc = d.DirichletBC(self.scalar_space, d.Constant(0), direct_boundary) dbuf = np.zeros(D.vector().size()).reshape((-1, 3, 3)) dbuf[:,0,0] = self.D_VV * vkscale dbuf[:,1,0] = self.D_VK * vkscale dbuf[:,0,1] = self.D_VK * vkscale dbuf[:,1,1] = self.D_KK * vkscale dbuf[:,2,2] = self.D_LL * lscale D.vector()[:] = dbuf.reshape((-1,)) Q.vector()[:] = self.source_term * sscale d.solve(equation, soln, bc) return self.to_cube(soln.vector().array())
def do_one_L_problem(self, i_vk, C_VK_data=0.1): """Solve the L equation for one (K,V) position using the "mixed" methodology, so that we get on-grid solutions of both `f` and `df/dL`. This requires that we use a 2nd-degree element to solve for the `df/dL` vector, called `sigma` here. """ W = d.FunctionSpace(self.l_mesh, self.c12.l_element * self.c11.l_element) D = d.Function(self.c12.l_space) # note: W.sub(0) does not work C_VK = d.Function(self.c11.l_space) sigma, u = d.TrialFunctions(W) # u is my 'f', sigma is df/dL tau, v = d.TestFunctions(W) soln = d.Function(W) bc = [d.DirichletBC(W.sub(1), d.Constant(0), direct_boundary)] a = (u * tau.dx(0) + d.dot(sigma, tau) + D * sigma * v.dx(0)) * d.dx L = C_VK * v * d.dx equation = (a == L) # typical D value: 1e-23 ddata = np.array(self.c12.D_LL[:,i_vk]) #print('D:', ddata.min(), ddata.max(), ddata.mean(), np.sqrt((ddata**2).mean())) D.vector()[:] = ddata C_VK.vector()[:] = C_VK_data C_VK.vector()[self.i_lmax] += self.c11.source_term[:,i_vk] d.solve(equation, soln, bc) sigma, u = soln.split(deepcopy=True) return self.c11.l_sort(), self.c11.l_sort(u), self.c12.l_sort(), self.c12.l_sort(sigma)
def checktheboundarycoordinates(bcsd, femp, plot=False): g1 = dolfin.Constant((0, 0)) for bc in bcsd: bcrl = dolfin.DirichletBC(femp['V'], g1, bc()) bcdict = bcrl.get_boundary_values() print(list(bcdict.keys())) bcinds = list(bcdict.keys()) V = femp['V'] cylmesh = femp['V'].mesh() if plot: dolfin.plot(cylmesh) dolfin.interactive(True) gdim = cylmesh.geometry().dim() dofmap = V.dofmap() # Get coordinates as len(dofs) x gdim array dofs_x = dofmap.tabulate_all_coordinates(cylmesh).reshape((-1, gdim)) # for dof, dof_x in zip(dofs, dofs_x): # print dof, ':', dof_x xcenter = 0.2 ycenter = 0.2 for bcind in bcinds: dofx = dofs_x[bcind, :] dx = dofx[0] - xcenter dy = dofx[1] - ycenter r = dolfin.sqrt(dx*dx + dy*dy) print(bcind, ':', dofx, r)
def homogenize_boundaries(bcs): if isinstance(bcs,dl.DirichletBC): bcs = [bcs] hbcs=[dl.DirichletBC(bc) for bc in bcs] for hbc in hbcs: hbc.homogenize() return hbcs
def compute_velocity(mesh, Vh, a, u): #export the velocity field v = - exp( a ) \grad u: then we solve ( exp(-a) v, w) = ( u, div w) Vv = dl.FunctionSpace(mesh, 'RT', 1) v = dl.Function(Vv, name="velocity") vtrial = dl.TrialFunction(Vv) vtest = dl.TestFunction(Vv) afun = dl.Function(Vh[PARAMETER], a) ufun = dl.Function(Vh[STATE], u) Mv = dl.exp(-afun) * dl.inner(vtrial, vtest) * dl.dx n = dl.FacetNormal(mesh) class TopBoundary(dl.SubDomain): def inside(self, x, on_boundary): return on_boundary and x[1] > 1 - dl.DOLFIN_EPS Gamma_M = TopBoundary() boundaries = dl.FacetFunction("size_t", mesh) boundaries.set_all(0) Gamma_M.mark(boundaries, 1) dss = dl.Measure("ds")[boundaries] rhs = ufun * dl.div(vtest) * dl.dx - dl.dot(vtest, n) * dss(1) bcv = dl.DirichletBC(Vv, dl.Expression(("0.0", "0.0")), v_boundary) dl.solve(Mv == rhs, v, bcv) return v
def get_essential_bc(self, var=None, bc_reverse_map=None): if var is None: var = self.essential_var if bc_reverse_map is None: bc_reverse_map = self.reverse_map mu = self.mesh_util fsr = mu.function_subspace_registry ebc_space = fsr.get_function_space(var.m, collapsed=False) ebc_collapsed_space = fsr.get_function_space(var.m, collapsed=True) facet_function = mu.mesh_data.facet_function var_units = var.units essential_bcs = [] for value, fvss in bc_reverse_map.items(): value = value.object value_ = dolfin.project(value.m_as(var_units), ebc_collapsed_space) # TODO: determine when usage of geometric marking is necessary for fv, sign in fvss: essential_bcs.append( dolfin.DirichletBC(ebc_space, value_, facet_function, fv)) return essential_bcs
def plotbeam(dtheta): """ Utility function to represent the shape of beam given the rotation field theta(s) and the boundary conditions It formulate in the weak form and solve with the finite element method the equations x'(s) = cos(theta(s)), x(0)=0 y'(s) = sin(theta(s)), y(0)=0 """ V = dtheta.function_space() x_ = dolfin.Function(V) y_ = dolfin.Function(V) test = dolfin.TestFunction(V) trial = dolfin.TrialFunction(V) # Solve x'(s)=cos(theta), x(0)=0 with FE dx = dolfin.dx a = trial.dx(0) * test * dx fx = dolfin.interpolate( dolfin.Expression("cos(dtheta)", dtheta=dtheta, pi=dolfin.pi, degree=1), V) Lx = fx * test * dx bc = dolfin.DirichletBC(V, 0., "near(x[0], 0.) && on_boundary") dolfin.solve(a == Lx, x_, bc) # Solve y'(s)=sing(theta), y(0)=0 with FE fy = dolfin.interpolate( dolfin.Expression("sin(dtheta)", dtheta=dtheta, pi=dolfin.pi, degree=1), V) Ly = fy * test * dx dolfin.solve(a == Ly, y_, bc) p = plt.plot(x_.compute_vertex_values(), y_.compute_vertex_values()) return (p, x_, y_)
def _generate_dirichlet_bc(self, boundary, bc_type, is_linearised=False): """ Given a boundary and a boundary condition type (one from the 'bc_to_fs' dict), we generate a dolfin DirichletBC based on the boundary expression for this boundary condition. """ if bc_type == "noslip" or (bc_type == "inflow" and is_linearised): if self.geometric_dimension == 1: value = dolf.Constant(0.0) else: value = dolf.Constant((0.0,) * self.geometric_dimension) elif bc_type == "isothermal" or (bc_type == "temperature" and is_linearised): value = dolf.Constant(0.0) elif bc_type == "inflow" or bc_type == "temperature": value = self._parse_dolf_expression(boundary.bcond[bc_type]) else: raise TypeError(f"Invalid boundary condition type for Dirichlet condition.") function_space = self.bc_to_fs[bc_type] return [ dolf.DirichletBC( function_space, value, self.domain.boundary_parts, boundary.surface_index, ) ]
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 solve_laplace(V, poisson, objects, boundaries, ext_bnd_id): """ This function solves Laplace's equation, div grad phi = 0, for each surface component j with boundary condition phi = 1 on component j and phi = 0 on every other component. Args: V : DOLFIN function space poisson : Poisson solver objects : A list containing all the objects boundaries : DOLFIN MeshFunction over facet regions ext_bnd_id : The number given to the exterior facet regions in gmsh returns: A list of calculated electric fields for every surface component (object). """ bcs = poisson.bcs poisson.bcs = [df.DirichletBC(V, df.Constant(0.0), boundaries, ext_bnd_id)] esolver = ESolver(V) num_objects = len(objects) object_e_field = [0.0] * num_objects for i, o in enumerate(objects): for j, p in enumerate(objects): if i == j: p.set_potential(1.0) else: p.set_potential(0.0) rho = df.Function(V) # zero by default phi = poisson.solve(rho, objects) object_e_field[i] = esolver.solve(phi) poisson.bcs = bcs return object_e_field