def assembleA(self, x, assemble_adjoint=False, assemble_rhs=False): """ Assemble the matrices and rhs for the forward/adjoint problems """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[STATE]) c = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) Avarf = dl.inner( dl.exp(c) * dl.nabla_grad(trial), dl.nabla_grad(test)) * dl.dx if not assemble_adjoint: bform = dl.inner(self.f, test) * dl.dx Matrix, rhs = dl.assemble_system(Avarf, bform, self.bc) else: # Assemble the adjoint of A (i.e. the transpose of A) s = vector2Function(x[STATE], self.Vh[STATE]) bform = dl.inner(dl.Constant(0.), test) * dl.dx Matrix, _ = dl.assemble_system(dl.adjoint(Avarf), bform, self.bc0) Bu = -(self.B * x[STATE]) Bu += self.u_o rhs = dl.Vector() self.B.init_vector(rhs, 1) self.B.transpmult(Bu, rhs) rhs *= 1.0 / self.noise_variance if assemble_rhs: return Matrix, rhs else: return Matrix
def stiffness(self): """The stiffness matrix as a LinearOperator.""" u = TrialFunction(self._fefs) v = TestFunction(self._fefs) a = (nabla_grad(u), nabla_grad(v)) * dx A = assemble(a) return MatrixOperator(A.array())
def __init__(self, parameters, domain): rho = Constant(parameters["density [kg/m3]"]) mu = Constant(parameters["viscosity [Pa*s]"]) dt = Constant(parameters["dt [s]"]) u, u_1, u_k, vu = domain.u, domain.u_1, domain.u_k, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.mesh) acceleration = rho*inner((u-u_1)/dt, vu) * dx convection = dot(div(rho*outer(u_k, u)), vu) * dx convection = rho*dot(dot(u_k, nabla_grad(u)), vu) * dx pressure = (inner(p_1, div(vu))*dx - dot(p_1*n, vu)*ds) diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx) # good # diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx # + dot(mu * (grad(u) + grad(u).T)*n, vu)*ds) # very slow! # F_impl = acceleration + convection + pressure + diffusion # dot(u_1, nabla_grad(u_1)) works # dot(u, nabla_grad(u_1)) does not change! u_mid = (u + u_1) / 2.0 F_impl = rho*dot((u - u_1) / dt, vu)*dx \ + rho*dot(dot(u_1, nabla_grad(u_1)), vu)*dx \ + inner(sigma(u_mid, p_1, mu), epsilon(vu))*dx \ + dot(p_1*n, vu)*ds - dot(mu*nabla_grad(u_mid)*n, vu)*ds self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
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 readV(self, functionspaces_V): # Solutions: self.V = functionspaces_V['V'] self.test = TestFunction(self.V) self.trial = TrialFunction(self.V) self.u0 = Function(self.V) # u(t-Dt) self.u1 = Function(self.V) # u(t) self.u2 = Function(self.V) # u(t+Dt) self.rhs = Function(self.V) self.sol = Function(self.V) # Parameters: self.Vl = functionspaces_V['Vl'] self.lam = Function(self.Vl) self.Vr = functionspaces_V['Vr'] self.rho = Function(self.Vr) if functionspaces_V.has_key('Vm'): self.Vm = functionspaces_V['Vm'] self.mu = Function(self.Vm) self.elastic = True assert(False) else: self.elastic = False self.weak_k = inner(self.lam*nabla_grad(self.trial), \ nabla_grad(self.test))*dx self.weak_m = inner(self.rho*self.trial,self.test)*dx
def _assemble(self): # Get input: self.gamma = self.Parameters['gamma'] if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta'] else: self.beta = 0.0 self.Vm = self.Parameters['Vm'] self.m0 = Function(self.Vm) if self.Parameters.has_key('m0'): setfct(self.m0, self.Parameters['m0']) self.mtrial = TrialFunction(self.Vm) self.mtest = TestFunction(self.Vm) self.mysample = Function(self.Vm) self.draw = Function(self.Vm) # Assemble: self.R = assemble(inner(nabla_grad(self.mtrial), \ nabla_grad(self.mtest))*dx) self.M = assemble(inner(self.mtrial, self.mtest) * dx) self.Msolver = PETScKrylovSolver('cg', 'jacobi') self.Msolver.parameters["maximum_iterations"] = 2000 self.Msolver.parameters["relative_tolerance"] = 1e-24 self.Msolver.parameters["absolute_tolerance"] = 1e-24 self.Msolver.parameters["error_on_nonconvergence"] = True self.Msolver.parameters["nonzero_initial_guess"] = False self.Msolver.set_operator(self.M) # preconditioner is Gamma^{-1}: if self.beta > 1e-10: self.precond = self.gamma * self.R + self.beta * self.M else: self.precond = self.gamma * self.R + (1e-10) * self.M # Minvprior is M.A^2 (if you use M inner-product): self.Minvprior = self.gamma * self.R + self.beta * self.M
def poisson_bilinear_form(coeff_func, V): """Assemble the discrete problem (i.e. the stiffness matrix).""" # setup problem, assemble and apply boundary conditions u = TrialFunction(V) v = TestFunction(V) a = inner(coeff_func * nabla_grad(u), nabla_grad(v)) * dx return a
def set_form(self, form): """ This function is called by simulator.set_form to set up the equations for the electric field. This function will add an equation that sets the field to zero everywhere. Args: form: A FEniCS variational form. """ # first set rho (not used in calculations for this potential) F = Constant(self.simulator.F) rho = Function(self.simulator.geometry.V) for ion in self.simulator.ion_list: rho += F * ion.z * ion.c_new self.rho = rho # update variational form v, d = self.simulator.v_phi, self.simulator.d_phi form += (inner(nabla_grad(self.phi_new), nabla_grad(v)) + self.dummy_new * v + self.phi_new * d) * dx v, d = self.simulator.v_phi_ps, self.simulator.d_phi_ps form += (inner(nabla_grad(self.phi_ps_new), nabla_grad(v)) + self.phi_ps_new * d + v * self.dummy_ps_new) * dx return form
def __init__(self, cparams, dtype_u, dtype_f): """ Initialization routine Args: cparams: custom parameters for the example dtype_u: particle data type (will be passed parent class) dtype_f: acceleration data type (will be passed parent class) """ # define the Dirichlet boundary def Boundary(x, on_boundary): return on_boundary # these parameters will be used later, so assert their existence assert 'c_nvars' in cparams assert 'nu' in cparams assert 't0' in cparams assert 'family' in cparams assert 'order' in cparams assert 'refinements' in cparams # add parameters as attributes for further reference for k,v in cparams.items(): setattr(self,k,v) df.set_log_level(df.WARNING) df.parameters["form_compiler"]["optimize"] = True df.parameters["form_compiler"]["cpp_optimize"] = True # set mesh and refinement (for multilevel) mesh = df.UnitIntervalMesh(self.c_nvars) # mesh = df.UnitSquareMesh(self.c_nvars[0],self.c_nvars[1]) for i in range(self.refinements): mesh = df.refine(mesh) # self.mesh = mesh # define function space for future reference self.V = df.FunctionSpace(mesh, self.family, self.order) tmp = df.Function(self.V) print('DoFs on this level:',len(tmp.vector().array())) # invoke super init, passing number of dofs, dtype_u and dtype_f super(fenics_heat,self).__init__(self.V,dtype_u,dtype_f) self.g = df.Expression('-sin(a*x[0]) * (sin(t) - b*a*a*cos(t))',a=np.pi,b=self.nu,t=self.t0,degree=self.order) # rhs in weak form self.w = df.Function(self.V) v = df.TestFunction(self.V) self.a_K = -self.nu*df.inner(df.nabla_grad(self.w), df.nabla_grad(v))*df.dx + self.g*v*df.dx # mass matrix u = df.TrialFunction(self.V) a_M = u*v*df.dx self.M = df.assemble(a_M) self.bc = df.DirichletBC(self.V, df.Constant(0.0), Boundary)
def sqrt_precision_varf_handler(trial, test): if Theta == None: varfL = dl.inner(dl.nabla_grad(trial), dl.nabla_grad(test))*dl.dx else: varfL = dl.inner(Theta*dl.grad(trial), dl.grad(test))*dl.dx varfM = dl.inner(trial,test)*dl.dx varfmo = mfun*dl.inner(trial,test)*dl.dx return dl.Constant(gamma)*varfL+dl.Constant(delta)*varfM + dl.Constant(pen)*varfmo
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)
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)
def setup_NS(w_NS, u, p, v, q, p0, q0, dx, ds, normal, dirichlet_bcs_NS, neumann_bcs, boundary_to_mark, u_1, rho_, rho_1, mu_, c_1, grad_g_c_, dt, grav, enable_EC, trial_functions, use_iterative_solvers, p_lagrange, mesh, q_rhs, density_per_concentration, K, **namespace): """ Set up the Navier-Stokes subproblem. """ mom_1 = rho_1 * u_1 if enable_EC and density_per_concentration is not None: for drhodci, ci_1, grad_g_ci_, Ki in zip( density_per_concentration, c_1, grad_g_c_, K): if drhodci > 0.: mom_1 += -drhodci*Ki*ci_1*grad_g_ci_ F = (1./dt * rho_1 * df.dot(u - u_1, v) * dx + df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx + 2*mu_*df.inner(df.sym(df.nabla_grad(u)), df.sym(df.nabla_grad(v))) * dx + 0.5*( 1./dt * (rho_ - rho_1) * df.inner(u, v) - df.inner(mom_1, df.nabla_grad(df.dot(u, v)))) * dx - p * df.div(v) * dx - q * df.div(u) * dx - rho_ * df.dot(grav, v) * dx) for boundary_name, pressure in neumann_bcs["p"].iteritems(): F += pressure * df.inner( normal, v) * ds(boundary_to_mark[boundary_name]) if enable_EC: F += sum([ci_1*df.dot(grad_g_ci_, v)*dx for ci_1, grad_g_ci_ in zip(c_1, grad_g_c_)]) if p_lagrange: F += (p*q0 + q*p0)*dx if "u" in q_rhs: F += -df.dot(q_rhs["u"], v)*dx a, L = df.lhs(F), df.rhs(F) if not use_iterative_solvers: problem = df.LinearVariationalProblem(a, L, w_NS, dirichlet_bcs_NS) solver = df.LinearVariationalSolver(problem) else: solver = df.LUSolver("mumps") # solver.set_operator(A) return solver, a, L, dirichlet_bcs_NS return solver
def setup_NSu(w_NSu, u, v, dx, ds, normal, dirichlet_bcs_NSu, neumann_bcs, boundary_to_mark, u_, p_, u_1, p_1, rho_, rho_1, mu_, c_1, grad_g_c_, dt, grav, enable_EC, trial_functions, use_iterative_solvers, mesh, density_per_concentration, viscosity_per_concentration, K, **namespace): """ Set up the Navier-Stokes velocity subproblem. """ solvers = dict() mom_1 = rho_1 * u_1 if enable_EC and density_per_concentration is not None: for drhodci, ci_1, grad_g_ci_, Ki in zip(density_per_concentration, c_1, grad_g_c_, K): if drhodci > 0.: mom_1 += -drhodci * Ki * ci_1 * grad_g_ci_ F_predict = ( 1. / dt * rho_1 * df.dot(u - u_1, v) * dx + df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx + 2 * mu_ * df.inner(df.sym(df.nabla_grad(u)), df.sym(df.nabla_grad(v))) * dx + 0.5 * (1. / dt * (rho_ - rho_1) * df.dot(u, v) - df.inner(mom_1, df.grad(df.dot(u, v)))) * dx - p_1 * df.div(v) * dx - rho_ * df.dot(grav, v) * dx) for boundary_name, pressure in neumann_bcs["p"].iteritems(): F_predict += pressure * df.inner(normal, v) * ds( boundary_to_mark[boundary_name]) if enable_EC: F_predict += sum([ ci_1 * df.dot(grad_g_ci_, v) * dx for ci_1, grad_g_ci_ in zip(c_1, grad_g_c_) ]) a_predict, L_predict = df.lhs(F_predict), df.rhs(F_predict) # if not use_iterative_solvers: problem_predict = df.LinearVariationalProblem(a_predict, L_predict, w_NSu, dirichlet_bcs_NSu) solvers["predict"] = df.LinearVariationalSolver(problem_predict) if use_iterative_solvers: solvers["predict"].parameters["linear_solver"] = "bicgstab" solvers["predict"].parameters["preconditioner"] = "amg" F_correct = (rho_ * df.inner(u - u_, v) * dx - dt * (p_ - p_1) * df.div(v) * dx) a_correct, L_correct = df.lhs(F_correct), df.rhs(F_correct) problem_correct = df.LinearVariationalProblem(a_correct, L_correct, w_NSu, dirichlet_bcs_NSu) solvers["correct"] = df.LinearVariationalSolver(problem_correct) if use_iterative_solvers: solvers["correct"].parameters["linear_solver"] = "bicgstab" solvers["correct"].parameters["preconditioner"] = "amg" #else: # solver = df.LUSolver("mumps") # # solver.set_operator(A) # return solver, a, L, dirichlet_bcs_NS return solvers
def run_test(nbrep=100): mesh = dl.UnitSquareMesh(100,100) V = dl.FunctionSpace(mesh, 'Lagrange', 2) test, trial = dl.TestFunction(V), dl.TrialFunction(V) k = dl.Function(V) wkform = dl.inner(k*dl.nabla_grad(test), dl.nabla_grad(trial))*dl.dx for ii in xrange(nbrep): setfct(k, float(ii+1)) dl.assemble(wkform)
def __init__(self, problem_params, dtype_u=fenics_mesh, dtype_f=rhs_fenics_mesh): """ Initialization routine Args: problem_params (dict): custom parameters for the example dtype_u: FEniCS mesh data type (will be passed to parent class) dtype_f: FEniCS mesh data data type with implicit and explicit parts (will be passed to parent class) """ # define the Dirichlet boundary # def Boundary(x, on_boundary): # return on_boundary # these parameters will be used later, so assert their existence essential_keys = ['c_nvars', 't0', 'family', 'order', 'refinements', 'nu'] for key in essential_keys: if key not in problem_params: msg = 'need %s to instantiate problem, only got %s' % (key, str(problem_params.keys())) raise ParameterError(msg) # set logger level for FFC and dolfin logging.getLogger('FFC').setLevel(logging.WARNING) logging.getLogger('UFL').setLevel(logging.WARNING) # set solver and form parameters df.parameters["form_compiler"]["optimize"] = True df.parameters["form_compiler"]["cpp_optimize"] = True df.parameters['allow_extrapolation'] = True # set mesh and refinement (for multilevel) mesh = df.UnitIntervalMesh(problem_params['c_nvars']) for i in range(problem_params['refinements']): mesh = df.refine(mesh) # define function space for future reference self.V = df.FunctionSpace(mesh, problem_params['family'], problem_params['order']) tmp = df.Function(self.V) print('DoFs on this level:', len(tmp.vector()[:])) # invoke super init, passing number of dofs, dtype_u and dtype_f super(fenics_heat, self).__init__(self.V, dtype_u, dtype_f, problem_params) # Stiffness term (Laplace) u = df.TrialFunction(self.V) v = df.TestFunction(self.V) a_K = -1.0 * df.inner(df.nabla_grad(u), self.params.nu * df.nabla_grad(v)) * df.dx # Mass term a_M = u * v * df.dx self.M = df.assemble(a_M) self.K = df.assemble(a_K) # set forcing term as expression self.g = df.Expression('-cos(a*x[0]) * (sin(t) - b*a*a*cos(t))', a=np.pi, b=self.params.nu, t=self.params.t0, degree=self.params.order)
def defineVariationalForm(self): self.setGroundPlane() self.setMeasures() print("Defining variational form...") self.F = dolfin.inner(self.eps_exp * dolfin.nabla_grad(self.u), dolfin.nabla_grad(self.v)) * self.dx rho = self.setChargeDensity() self.F += rho self.F += self.getBoundaryComponent(self.u, self.v, self.ds)
def setUp(self): mesh = UnitSquareMesh(5, 5, 'crossed') self.V = FunctionSpace(mesh, 'Lagrange', 2) u = interpolate(Expression('1 + 7*(pow(pow(x[0] - 0.5,2) +' + \ ' pow(x[1] - 0.5,2),0.5) > 0.2)'), self.V) test = TestFunction(self.V) trial = TrialFunction(self.V) m = test*trial*dx self.M = assemble(m) k = inner(u*nabla_grad(test), nabla_grad(trial))*dx self.K = assemble(k)
def discrete_energy(x_, solutes, density, permittivity, c_cutoff, EC_scheme, dt, density_per_concentration, surface_tension, interface_thickness, enable_NS, enable_PF, enable_EC, **namespace): if x_ is None: E_list = [] if enable_NS: E_list.append("E_kin") if enable_PF: E_list.append("E_phi") if enable_EC: E_list.extend(["E_{}".format(solute[0]) for solute in solutes] + ["E_V"]) return E_list if enable_S: rho = density[0] veps = permittivity[0] u = x_["u"] if enable_NS: rho = density[0] veps = permittivity[0] u = x_["u"] # grad_p = df.grad(x_["p"]) if enable_PF: sigma_bar = surface_tension * 3. / (2 * math.sqrt(2)) eps = interface_thickness phi = x_["phi"] rho = ramp(phi, density) veps = ramp(phi, permittivity) if enable_EC: grad_V = df.nabla_grad(x_["V"]) M_list = [] for solute in solutes: ci = x_[solute[0]] if enable_PF: betai = ramp(phi, solute[4:6]) else: betai = solute[4] M_list.append(alpha(ci) + betai * ci) E_list = [] if enable_NS or enable_S: E_list.append(0.5 * rho * df.dot(u, u)) if enable_PF: E_list.append(sigma_bar / eps * pf_potential(phi) + 0.5 * sigma_bar * eps * df.dot(df.nabla_grad(phi), df.nabla_grad(phi))) if enable_EC: E_list.extend(M_list + [0.5 * veps * df.dot(grad_V, grad_V)]) return E_list
def setUp(self): mesh = UnitSquareMesh(5, 5, 'crossed') self.V = FunctionSpace(mesh, 'Lagrange', 2) u = interpolate(Expression('1 + 7*(pow(pow(x[0] - 0.5,2) +' + \ ' pow(x[1] - 0.5,2),0.5) > 0.2)'), self.V) test = TestFunction(self.V) trial = TrialFunction(self.V) m = test * trial * dx self.M = assemble(m) k = inner(u * nabla_grad(test), nabla_grad(trial)) * dx self.K = assemble(k)
def assembleRaa(self, x): """ Assemble the derivative of the parameter equation with respect to the parameter (Newton method) """ trial = dl.TrialFunction(self.Vh[PARAMETER]) test = dl.TestFunction(self.Vh[PARAMETER]) s = vector2Function(x[STATE], Vh[STATE]) c = vector2Function(x[PARAMETER], Vh[PARAMETER]) a = vector2Function(x[ADJOINT], Vh[ADJOINT]) varf = dl.inner(dl.nabla_grad(a), dl.exp(c) * dl.nabla_grad(s)) * trial * test * dl.dx return dl.assemble(varf)
def assemble_lhs(coeff, V): """Assemble the discrete problem (i.e. the stiffness matrix).""" # setup problem, assemble and apply boundary conditions u = TrialFunction(V) v = TestFunction(V) a = inner(coeff * nabla_grad(u), nabla_grad(v)) * dx A = assemble(a) # apply boundary conditions bc = homogeneous_bc(V) bc.apply(A) return A
def costab(self, m1, m2): self.gradm1 = project(nabla_grad(m1), self.Vd) self.gradm2 = project(nabla_grad(m2), self.Vd) cost = 0.0 for x, vol in zip(self.x, self.vol): G = np.array([self.gradm1(x), self.gradm2(x)]).T u, s, v = np.linalg.svd(G) sqrts2eps = np.sqrt(s**2 + self.eps) cost += vol * sqrts2eps.sum() cost_global = MPI.sum(self.mpicomm, cost) return self.k * cost_global
def weighted_H1_norm(w, vec, piecewise=False): if piecewise: DG = FunctionSpace(vec.basis.mesh, "DG", 0) s = TestFunction(DG) ae = assemble(w * inner(nabla_grad(vec._fefunc), nabla_grad(vec._fefunc)) * s * dx) norm_vec = np.array([sqrt(e) for e in ae]) # map DG dofs to cell indices dofs = [DG.dofmap().cell_dofs(c.index())[0] for c in cells(vec.basis.mesh)] norm_vec = norm_vec[dofs] else: ae = assemble(w * inner(nabla_grad(vec._fefunc), nabla_grad(vec._fefunc)) * dx) norm_vec = sqrt(ae) return norm_vec
def run_model(kappa,forcing,function_space,boundary_conditions=None): """ Solve complex valued Helmholtz equation by solving coupled system, one for the real part of the solution one for the imaginary part. """ mesh = function_space.mesh() kappa_sq = kappa**2 if boundary_conditions==None: bndry_obj = dl.CompiledSubDomain("on_boundary") boundary_conditions = [['dirichlet',bndry_obj,[0,0]]] num_bndrys = len(boundary_conditions) boundaries = mark_boundaries(mesh,boundary_conditions) dirichlet_bcs = collect_dirichlet_boundaries( function_space,boundary_conditions,boundaries) # To express integrals over the boundary parts using ds(i), we must first # redefine the measure ds in terms of our boundary markers: ds = dl.Measure('ds', domain=mesh, subdomain_data=boundaries) #dx = dl.Measure('dx', domain=mesh) dx = dl.dx (pr, pi) = dl.TrialFunction(function_space) (vr, vi) = dl.TestFunction(function_space) # real part bilinear_form = kappa_sq*(pr*vr - pi*vi)*dx bilinear_form += (-dl.inner(dl.nabla_grad(pr),dl.nabla_grad(vr))+ dl.inner(dl.nabla_grad(pi),dl.nabla_grad(vi)))*dx # imaginary part bilinear_form += kappa_sq*(pr*vi + pi*vr)*dx bilinear_form += -(dl.inner(dl.nabla_grad(pr),dl.nabla_grad(vi))+ dl.inner(dl.nabla_grad(pi),dl.nabla_grad(vr)))*dx for ii in range(num_bndrys): if (boundary_conditions[ii][0]=='robin'): alpha_real, alpha_imag = boundary_conditions[ii][3] bilinear_form -= alpha_real*(pr*vr-pi*vi)*ds(ii) bilinear_form -= alpha_imag*(pr*vi+pi*vr)*ds(ii) forcing_real,forcing_imag=forcing rhs = (forcing_real*vr+forcing_real*vi+forcing_imag*vr-forcing_imag*vi)*dx for ii in range(num_bndrys): if ((boundary_conditions[ii][0]=='robin') or (boundary_conditions[ii][0]=='neumann')): beta_real, beta_imag=boundary_conditions[ii][2] # real part of robin boundary conditions rhs+=(beta_real*vr - beta_imag*vi)*ds(ii) # imag part of robin boundary conditions rhs+=(beta_real*vi + beta_imag*vr)*ds(ii) # compute solution p = dl.Function(function_space) #solve(a == L, p) dl.solve(bilinear_form == rhs, p, bcs=dirichlet_bcs) return p
def assembleC(self, x): """ Assemble the derivative of the forward problem with respect to the parameter """ trial = dl.TrialFunction(self.Vh[PARAMETER]) test = dl.TestFunction(self.Vh[STATE]) s = vector2Function(x[STATE], Vh[STATE]) c = vector2Function(x[PARAMETER], Vh[PARAMETER]) Cvarf = dl.inner( dl.exp(c) * trial * dl.nabla_grad(s), dl.nabla_grad(test)) * dl.dx C = dl.assemble(Cvarf) # print "||c||", x[PARAMETER].norm("l2"), "||s||", x[STATE].norm("l2"), "||C||", C.norm("linf") self.bc0.zero(C) return C
def __init__(self, parameters, domain): rho = Constant(parameters["density [kg/m3]"]) dt = Constant(parameters["dt [s]"]) p, p_1, vp = domain.p, domain.p_1, domain.vp p_1, u_ = domain.p_1, domain.u_ # F = rho/dt * dot(div(u_), vp) * dx + dot(grad(p-p_1), grad(vp)) * dx self.a = dot(nabla_grad(p), nabla_grad(vp))*dx self.L = (dot(nabla_grad(p_1), nabla_grad(vp))*dx - (rho/dt)*div(u_)*vp*dx) self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcp] self.domain = domain return
def gradab(self, m1, m2): self.gradm1 = project(nabla_grad(m1), self.Vd) self.gradm2 = project(nabla_grad(m2), self.Vd) uwv00, uwv00ind = [], [] uwv10, uwv10ind = [], [] uwv01, uwv01ind = [], [] uwv11, uwv11ind = [], [] for ii, x in enumerate(self.x): G = np.array([self.gradm1(x), self.gradm2(x)]).T u, s, v = np.linalg.svd(G) sqrts2eps = np.sqrt(s**2 + self.eps) W = np.diag(s / sqrts2eps) uwv = u.dot(W.dot(v)) uwv00.append(uwv[0][0]) uwv00ind.append(ii) uwv10.append(uwv[1][0]) uwv10ind.append(ii) uwv01.append(uwv[0][1]) uwv01ind.append(ii) uwv11.append(uwv[1][1]) uwv11ind.append(ii) Grad = Function(self.VV) grad = Grad.vector() rhsG = Vector() self.Gx1test.init_vector(rhsG, 1) rhsG.set_local(np.array(uwv00), np.array(uwv00ind, dtype=np.intc)) rhsG.apply('insert') grad.axpy(1.0, self.Gx1test * rhsG) rhsG.zero() rhsG.set_local(np.array(uwv10), np.array(uwv10ind, dtype=np.intc)) rhsG.apply('insert') grad.axpy(1.0, self.Gy1test * rhsG) rhsG.set_local(np.array(uwv01), np.array(uwv01ind, dtype=np.intc)) rhsG.apply('insert') grad.axpy(1.0, self.Gx2test * rhsG) rhsG.set_local(np.array(uwv11), np.array(uwv11ind, dtype=np.intc)) rhsG.apply('insert') grad.axpy(1.0, self.Gy2test * rhsG) return grad * self.k
def testblockdiagonal(): mesh = dl.UnitSquareMesh(40, 40) V1 = dl.FunctionSpace(mesh, "Lagrange", 2) test1, trial1 = dl.TestFunction(V1), dl.TrialFunction(V1) V2 = dl.FunctionSpace(mesh, "Lagrange", 2) test2, trial2 = dl.TestFunction(V2), dl.TrialFunction(V2) V1V2 = createMixedFS(V1, V2) test12, trial12 = dl.TestFunction(V1V2), dl.TrialFunction(V1V2) bd = BlockDiagonal(V1, V2, mesh.mpi_comm()) mpirank = dl.MPI.rank(mesh.mpi_comm()) if mpirank == 0: print 'mass+mass' M1 = dl.assemble(dl.inner(test1, trial1) * dl.dx) M2 = dl.assemble(dl.inner(test1, trial2) * dl.dx) M12bd = bd.assemble(M1, M2) M12 = dl.assemble(dl.inner(test12, trial12) * dl.dx) diff = M12bd - M12 nn = diff.norm('frobenius') if mpirank == 0: print '\nnn={}'.format(nn) if mpirank == 0: print 'mass+2ndD' D2 = dl.assemble( dl.inner(dl.nabla_grad(test1), dl.nabla_grad(trial2)) * dl.dx) M1D2bd = bd.assemble(M1, D2) tt1, tt2 = test12 tl1, tl2 = trial12 M1D2 = dl.assemble( dl.inner(tt1, tl1) * dl.dx + dl.inner(dl.nabla_grad(tt2), dl.nabla_grad(tl2)) * dl.dx) diff = M1D2bd - M1D2 nn = diff.norm('frobenius') if mpirank == 0: print 'nn={}'.format(nn) if mpirank == 0: print 'wM+wM' u11 = dl.interpolate(dl.Expression("x[0]*x[1]", degree=10), V1) u22 = dl.interpolate(dl.Expression("11+x[0]+x[1]", degree=10), V2) M1 = dl.assemble(dl.inner(u11 * test1, trial1) * dl.dx) M2 = dl.assemble(dl.inner(u22 * test1, trial2) * dl.dx) M12bd = bd.assemble(M1, M2) ua, ub = dl.interpolate(dl.Expression(("x[0]*x[1]", "11+x[0]+x[1]"),\ degree=10), V1V2) M12 = dl.assemble( dl.inner(ua * tt1, tl1) * dl.dx + dl.inner(ub * tt2, tl2) * dl.dx) diff = M12bd - M12 nn = diff.norm('frobenius') if mpirank == 0: print 'nn={}'.format(nn)
def assembleWau(self, x): """ Assemble the derivative of the parameter equation with respect to the state """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[PARAMETER]) a = dl.Function(self.Vh[ADJOINT], x[ADJOINT]) c = dl.Function(self.Vh[PARAMETER], x[PARAMETER]) varf = dl.inner(dl.exp(c) * dl.nabla_grad(trial), dl.nabla_grad(a)) * test * dl.dx Wau = dl.assemble(varf) dummy = dl.Vector() Wau.init_vector(dummy, 0) self.bc0.zero_columns(Wau, dummy) return Wau
def __init__(self, parameters, domain): rho = Constant(parameters["density [kg/m3]"]) dt = Constant(parameters["dt [s]"]) p, p_1, vp = domain.p, domain.p_1, domain.vp p_1, u_ = domain.p_1, domain.u_ a2 = dot(nabla_grad(p), nabla_grad(vp)) * dx L2 = dot(nabla_grad(p_1), nabla_grad(vp)) * dx - (rho / dt) * div(u_) * vp * dx A2 = assemble(a2) [bc.apply(A2) for bc in domain.bcp] self.domain = domain self.a2, self.A2, self.L2 = a2, A2, L2 return
def integrateFluidStress(v, p, nu, space_dim): if space_dim == 2: cd_integral = -20. * (nu * v_ref * (1. / l_ref**2) * inner( dlfn.nabla_grad(v), dlfn.nabla_grad(vd)) + v_ref**2 * (1. / l_ref) * inner(grad(v) * v, vd) - p_ref * (1. / l_ref) * p * dlfn.div(vd)) * dV cd = l_ref**2 * dlfn.assemble(cd_integral) cl_integral = -20. * (nu * v_ref * (1. / l_ref**2) * inner( dlfn.nabla_grad(v), dlfn.nabla_grad(vl)) + v_ref**2 * (1. / l_ref) * inner(grad(v) * v, vl) - p_ref * (1. / l_ref) * p * dlfn.div(vl)) * dV cl = l_ref**2 * dlfn.assemble(cl_integral) else: raise ValueError("space dimension unequal 2") return cd, cl
def assembleWau(self, x): """ Assemble the derivative of the parameter equation with respect to the state """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[PARAMETER]) a = vector2Function(x[ADJOINT], Vh[ADJOINT]) c = vector2Function(x[PARAMETER], Vh[PARAMETER]) varf = dl.inner(dl.exp(c) * dl.nabla_grad(trial), dl.nabla_grad(a)) * test * dl.dx Wau = dl.assemble(varf) Wau_t = Transpose(Wau) self.bc0.zero(Wau_t) Wau = Transpose(Wau_t) return Wau
def setup_NSu(u, v, u_, p_, bcs_NSu, u_1, p_1, phi_, rho_, rho_1, g_, M_, nu_, rho_e_, V_, dt, drho, sigma_bar, eps, dveps, grav, enable_PF, enable_EC): """ Set up the Navier-Stokes subproblem. """ # Crank-Nicolson velocity # u_CN = 0.5*(u_1 + u) F_predict = ( 1. / dt * df.sqrt(rho_) * df.dot(df.sqrt(rho_) * u - df.sqrt(rho_1) * u_1, v) * df.dx # + rho_*df.inner(df.grad(u), df.outer(u_1, v))*df.dx # + 2*nu_*df.inner(df.sym(df.grad(u)), df.grad(v))*df.dx # - p_1 * df.div(v)*df.dx # + df.div(u)*q*df.dx + rho_ * df.dot(df.dot(u_1, df.nabla_grad(u)), v) * df.dx + 2 * nu_ * df.inner(df.sym(df.grad(u)), df.sym(df.grad(v))) * df.dx - p_1 * df.div(v) * df.dx - df.dot(rho_ * grav, v) * df.dx) phi_filtered = unit_interval_filter(phi_) if enable_PF: F_predict += -drho * M_ * df.dot( df.dot(df.nabla_grad(g_), df.nabla_grad(u)), v) * df.dx F_predict += -sigma_bar * eps * df.inner( df.outer(df.grad(phi_filtered), df.grad(phi_filtered)), df.grad(v)) * df.dx if enable_EC and rho_e_ != 0: F_predict += rho_e_ * df.dot(df.grad(V_), v) * df.dx if enable_PF and enable_EC: F_predict += dveps * df.dot(df.grad(phi_filtered), v) * df.dot( df.grad(V_), df.grad(V_)) * df.dx # a1, L1 = df.lhs(F_predict), df.rhs(F_predict) F_correct = (df.inner(u - u_, v) * df.dx + dt / rho_ * df.inner(df.grad(p_ - p_1), v) * df.dx) # a3 = df.dot(u, v)*df.dx # L3 = df.dot(u_, v)*df.dx - dt*df.dot(df.grad(p_), v)*df.dx # a3, L3 = df.lhs(F_correct), df.rhs(F_correct) solver = dict() # solver["a1"] = a1 # solver["L1"] = L1 solver["Fu"] = F_predict solver["Fu_corr"] = F_correct # solver["a3"] = a3 # solver["L3"] = L3 solver["bcs"] = bcs_NSu return solver
def setUp(self): mesh = dl.UnitSquareMesh(10, 10) self.mpi_rank = dl.MPI.rank(mesh.mpi_comm()) self.mpi_size = dl.MPI.size(mesh.mpi_comm()) Vh1 = dl.FunctionSpace(mesh, 'Lagrange', 1) uh, vh = dl.TrialFunction(Vh1), dl.TestFunction(Vh1) mh = dl.TrialFunction(Vh1) # Define B ndim = 2 ntargets = 10 np.random.seed(seed=1) targets = np.random.uniform(0.1, 0.9, [ntargets, ndim]) B = assemblePointwiseObservation(Vh1, targets) # Define Asolver alpha = dl.Constant(0.1) varfA = dl.inner(dl.nabla_grad(uh), dl.nabla_grad(vh))*dl.dx +\ alpha*dl.inner(uh,vh)*dl.dx A = dl.assemble(varfA) Asolver = dl.PETScKrylovSolver(A.mpi_comm(), "cg", amg_method()) Asolver.set_operator(A) Asolver.parameters["maximum_iterations"] = 100 Asolver.parameters["relative_tolerance"] = 1e-12 # Define M varfC = dl.inner(mh, vh) * dl.dx C = dl.assemble(varfC) self.J = J_op(B, Asolver, C) self.k_evec = 10 p_evec = 50 myRandom = Random(self.mpi_rank, self.mpi_size) x_vec = dl.Vector(C.mpi_comm()) C.init_vector(x_vec, 1) self.Omega = MultiVector(x_vec, self.k_evec + p_evec) myRandom.normal(1., self.Omega) y_vec = dl.Vector(C.mpi_comm()) B.init_vector(y_vec, 0) self.Omega_adj = MultiVector(y_vec, self.k_evec + p_evec) myRandom.normal(1., self.Omega_adj)
def flux_derivative(self, u, coeff): a = coeff Du = self.differential_op(u) Dsigma = dot(nabla_grad(a), Du) if element_degree(u) >= 2: Dsigma += a * div(Du) return Dsigma
def __init__(self, domain): rho, mu, dt, g = domain.rho, domain.mu, domain.dt, domain.g u, u_1, vu = domain.u, domain.u_1, domain.vu p_1 = domain.p_1 n = FacetNormal(domain.mesh) acceleration = rho * inner((u - u_1) / dt, vu) * dx pressure = inner(p_1, div(vu)) * dx - dot(p_1 * n, vu) * ds body_force = dot(g*rho, vu)*dx \ + dot(Constant((0.0, 0.0)), vu) * ds # diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu))*dx # + dot(mu * (grad(u_1) + grad(u_1).T)*n, vu)*ds) # just fine # diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx) # just fine # just fine, but horribly slow in combination with ??? -> not reproducable diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu)) * dx + dot(mu * (grad(u) + grad(u).T) * n, vu) * ds) # convection = rho*dot(dot(u, nabla_grad(u_1)), vu) * dx # no vortices convection = rho * dot(dot(u_1, nabla_grad(u)), vu) * dx # stabilization = -gamma*psi_p*p_1 # convection = dot(div(rho * outer(u_1, u_1)), vu) * dx # not stable! # convection = rho * dot(dot(u_1, nabla_grad(u_1)), vu) * dx # just fine F_impl = -acceleration - convection + diffusion + pressure + body_force self.a, self.L = lhs(F_impl), rhs(F_impl) self.domain = domain self.A = assemble(self.a) [bc.apply(self.A) for bc in domain.bcu] return
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 setup_NSp(w_NSp, p, q, dirichlet_bcs_NSp, dt, u_, p_1, rho_0, use_iterative_solvers, **namespace): """ Set up Navier-Stokes pressure subproblem. """ F = (df.dot(df.nabla_grad(p - p_1), df.nabla_grad(q)) * df.dx + 1. / dt * rho_0 * df.div(u_) * q * df.dx) a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_NSp, dirichlet_bcs_NSp) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "bicgstab" solver.parameters["preconditioner"] = "amg" return solver
def setup_NSp(w_NSp, p, q, dx, ds, dirichlet_bcs_NSp, neumann_bcs, boundary_to_mark, u_, u_1, p_, p_1, rho_, dt, rho_min, use_iterative_solvers, **namespace): F = (df.dot(df.nabla_grad(p - p_1), df.nabla_grad(q)) * df.dx + 1. / dt * rho_min * df.div(u_) * q * df.dx) a, L = df.lhs(F), df.rhs(F) problem = df.LinearVariationalProblem(a, L, w_NSp, dirichlet_bcs_NSp) solver = df.LinearVariationalSolver(problem) if use_iterative_solvers: solver.parameters["linear_solver"] = "gmres" solver.parameters["preconditioner"] = "hypre_amg" # "amg" # solver.parameters["preconditioner"] = "hypre_euclid" return solver
def computeVelocityField(mesh): Xh = dl.VectorFunctionSpace(mesh,'Lagrange', 2) Wh = dl.FunctionSpace(mesh, 'Lagrange', 1) if dlversion() <= (1,6,0): XW = dl.MixedFunctionSpace([Xh, Wh]) else: mixed_element = dl.MixedElement([Xh.ufl_element(), Wh.ufl_element()]) XW = dl.FunctionSpace(mesh, mixed_element) Re = 1e2 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) = 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, "linear_solver":"default"}}) return v
def run_dolfin(): import dolfin as df x_array = np.linspace(-49.5, 49.5, 100) mesh = df.IntervalMesh(100, -50, 50) Delta = np.sqrt(A / K) xi = 2 * A / D Delta_s = Delta * 1e9 V = df.FunctionSpace(mesh, "Lagrange", 1) u = df.TrialFunction(V) v = df.TestFunction(V) u_ = df.Function(V) F = -df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx - \ (0.5 / Delta_s**2) * df.sin(2 * u) * v * df.dx F = df.action(F, u_) J = df.derivative(F, u_, u) # the boundary condition is from equation (8) theta0 = np.arcsin(Delta / xi) ss = 'x[0]<0? %g: %g ' % (-theta0, theta0) u0 = df.Expression(ss) def u0_boundary(x, on_boundary): return on_boundary bc = df.DirichletBC(V, u0, u0_boundary) problem = df.NonlinearVariationalProblem(F, u_, bcs=bc, J=J) solver = df.NonlinearVariationalSolver(problem) solver.solve() u_array = u_.vector().array() mx_df = [] for x in x_array: mx_df.append(u_(x)) return mx_df
def flux_derivative(self, u, coeff): """First derivative of flux.""" lmbda, mu = coeff Du = self.differential_op(u) I = Identity(u.cell().d) Dsigma = 2.0 * mu * div(Du) + dot(nabla_grad(lmbda), tr(Du) * I) if element_degree(u) >= 2: Dsigma += lmbda * div(tr(Du) * I) return Dsigma
def evaluate_numerical_flux(w, mu, coeff_field, f): '''determine numerical flux sigma_nu with solution w''' Lambda = w.active_indices() maxm = w.max_order if len(coeff_field) < maxm: logger.warning("insufficient length of coefficient field for MultiVector (%i < %i)", len(coeff_field), maxm) maxm = len(coeff_field) # get mean field of coefficient and initialise sigma a0_f = coeff_field.mean_func sigma_mu = a0_f * nabla_grad(w[mu]._fefunc) # iterate m for m in range(maxm): am_f, am_rv = coeff_field[m] # prepare polynomial coefficients beta = am_rv.orth_polys.get_beta(mu[m]) # mu r_mu = -beta[0] * w[mu] # mu+1 mu1 = mu.inc(m) if mu1 in Lambda: w_mu1 = w[mu1] r_mu += beta[1] * w_mu1 # mu-1 mu2 = mu.dec(m) if mu2 in Lambda: w_mu2 = w[mu2] r_mu += beta[-1] * w_mu2 # add flux contribution sigma_mu = sigma_mu + am_f * nabla_grad(r_mu._fefunc) # initialise f if not mu: f_mu = f else: f_mu = Constant(0.0) return sigma_mu, f_mu
def evaluate_evp(basis): """Evaluate EVP""" assert HAVE_SLEPC # get FEniCS function space V = basis._fefs # Define basis and bilinear form u = TrialFunction(V) v = TestFunction(V) a = inner(nabla_grad(u), nabla_grad(v)) * dx # Assemble stiffness form A = PETScMatrix() assemble(a, tensor=A) # Create eigensolver eigensolver = SLEPcEigenSolver(A) # Compute all eigenvalues of A x = \lambda x print "Computing eigenvalues..." eigensolver.solve() return eigensolver
def _assemble(self): # Get input: self.gamma = self.Parameters['gamma'] if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta'] else: self.beta = 0.0 self.Vm = self.Parameters['Vm'] if self.Parameters.has_key('m0'): self.m0 = self.Parameters['m0'].copy(deepcopy=True) isFunction(self.m0) else: self.m0 = Function(self.Vm) self.mtrial = TrialFunction(self.Vm) self.mtest = TestFunction(self.Vm) self.mysample = Function(self.Vm) self.draw = Function(self.Vm) # Assemble: self.R = assemble(inner(nabla_grad(self.mtrial), \ nabla_grad(self.mtest))*dx) self.M = assemble(inner(self.mtrial, self.mtest)*dx) # preconditioner is Gamma^{-1}: if self.beta > 1e-16: self.precond = self.gamma*self.R + self.beta*self.M else: self.precond = self.gamma*self.R + (1e-14)*self.M # Minvprior is M.A^2 (if you use M inner-product): self.Minvprior = self.gamma*self.R + self.beta*self.M
def _assemble(self): # Get input: self.gamma = self.Parameters['gamma'] if self.Parameters.has_key('beta'): self.beta = self.Parameters['beta'] else: self.beta = 0.0 self.Vm = self.Parameters['Vm'] if self.Parameters.has_key('m0'): self.m0 = self.Parameters['m0'].copy(deepcopy=True) isFunction(self.m0) else: self.m0 = Function(self.Vm) self.mtrial = TrialFunction(self.Vm) self.mtest = TestFunction(self.Vm) self.mysample = Function(self.Vm) self.draw = Function(self.Vm) # Assemble: self.R = assemble(inner(nabla_grad(self.mtrial), \ nabla_grad(self.mtest))*dx) self.M = PETScMatrix() assemble(inner(self.mtrial, self.mtest)*dx, tensor=self.M) # preconditioner is Gamma^{-1}: if self.beta > 1e-16: self.precond = self.gamma*self.R + self.beta*self.M else: self.precond = self.gamma*self.R + (1e-14)*self.M # Discrete operator K: self.K = self.gamma*self.R + self.beta*self.M # Get eigenvalues for M: self.eigsolM = SLEPcEigenSolver(self.M) self.eigsolM.solve() # Solver for M^{-1}: self.solverM = LUSolver() self.solverM.parameters['reuse_factorization'] = True self.solverM.parameters['symmetric'] = True self.solverM.set_operator(self.M) # Solver for K^{-1}: self.solverK = LUSolver() self.solverK.parameters['reuse_factorization'] = True self.solverK.parameters['symmetric'] = True self.solverK.set_operator(self.K)
def get_conv_diff(u, v, epsilon, wind, stabilize=True): a = ( epsilon*inner(nabla_grad(u), nabla_grad(v))*dx + inner(nabla_grad(u), wind)*v*dx ) L = f*v*dx if stabilize: a += delta*inner(wind, nabla_grad(u))*inner(wind, nabla_grad(v))*dx L += delta*f*inner(wind, nabla_grad(v))*dx return a, L
def assembleSystem(self): """Assemble the FEM system. This is only run a single time before time-stepping. The values of the coefficient fields need to be updated between time-steps """ # Loop through the entire model and composite the system of equations self.diffusors = [] # [[compartment, species, diffusivity of species],[ ...],[...]] """ Diffusors have source terms """ self.electrostatic_compartments = [] # (compartment) where electrostatic equations reside """ Has source term """ self.potentials = [] # (membrane) """ No spatial derivatives, just construct ODE """ self.channelvars = [] #(membrane, channel, ...) for compartment in self.compartments: s = 0 for species in compartment.species: if compartment.diffusivities[species] < 1e-10: continue self.diffusors.extend([ [compartment,species,compartment.diffusivities[species]] ]) s+=compartment.diffusivities[species]*abs(species.z) if s>0: self.electrostatic_compartments.extend([compartment]) # Otherwise, there are no mobile charges in the compartment # the number of potentials is the number of spatial potentials + number of membrane potentials self.numdiffusers = len(self.diffusors) self.numpoisson = len(self.electrostatic_compartments) # Functions # Reaction-diffusion type # Diffusers :numdiffusers # # Coefficient # Diffusivities self.V_np = dolfin.MixedFunctionSpace([self.v]*(self.numdiffusers)) self.V_poisson = dolfin.MixedFunctionSpace([self.v]*self.numpoisson) #self.V = self.V_diff*self.V_electro self.V = dolfin.MixedFunctionSpace([self.v]*(self.numdiffusers+self.numpoisson)) self.dofs_is = [self.V.sub(j).dofmap().dofs() for j in range(self.numdiffusers+self.numpoisson)] self.N = len(self.dofs_is[0]) self.diffusivities = [dolfin.Function(self.v) for j in range(self.numdiffusers)] self.trialfunctions = dolfin.TrialFunctions(self.V) # Trial function self.testfunctions = dolfin.TestFunctions(self.V) # test functions, one for each field self.sourcefunctions = [dolfin.Function(self.v) for j in range(self.numpoisson+self.numdiffusers)] self.permitivities = [dolfin.Function(self.v) for j in range(self.numpoisson)] # index the compartments! self.functions__ = dolfin.Function(self.V) self.np_assigner = dolfin.FunctionAssigner(self.V_np,[self.v]*self.numdiffusers) self.poisson_assigner = dolfin.FunctionAssigner(self.V_poisson,[self.v]*self.numpoisson) self.full_assigner = dolfin.FunctionAssigner(self.V,[self.v]*(self.numdiffusers+self.numpoisson)) self.prev_value__ = dolfin.Function(self.V) self.prev_value_ = dolfin.split(self.prev_value__) self.prev_value = [dolfin.Function(self.v) for j in range(self.numdiffusers+self.numpoisson)] self.vfractionfunctions = [dolfin.Function(self.v) for j in range(len(self.compartments))] # Each reaction diffusion eqn should be indexed to a single volume fraction function # Each reaction diffusion eqn should be indexed to a single potential function # Each reaction diffusion eqn should be indexed to a single valence self.dt = dolfin.Constant(0.1) self.eqs = [] self.phi = dolfin.Constant(phi) for membrane in self.membranes: self.potentials.extend([membrane]) membrane.phi_m = np.ones(self.N)*membrane.phi_m self.num_membrane_potentials = len(self.potentials) # improve this """ Assemble the equations for the system Order of equations: for compartment in compartments: for species in compartment.species diffusion (in order) volume potential for electrodiffusion Membrane potentials """ for j,compartment in enumerate(self.compartments): self.vfractionfunctions[j].vector()[:] = self.volfrac[compartment] # Set the reaction-diffusion equations for j,(trial,old,test,source,D,diffusor) in enumerate(zip(self.trialfunctions[:self.numdiffusers],self.prev_value_[:self.numdiffusers] \ ,self.testfunctions[:self.numdiffusers], self.sourcefunctions[:self.numdiffusers]\ ,self.diffusivities,self.diffusors)): """ This instance of the loop corresponds to a diffusion species in self.diffusors """ compartment_index = self.compartments.index(diffusor[0]) # we are in this compartment try: phi_index = self.electrostatic_compartments.index(diffusor[0]) + self.numdiffusers self.eqs.extend([ trial*test*dx-test*old*dx+ \ self.dt*(inner(D*nabla_grad(trial),nabla_grad(test)) + \ dolfin.Constant(diffusor[1].z/phi)*inner(D*trial*nabla_grad(self.prev_value[phi_index]),nabla_grad(test)))*dx ]) """ self.eqs.extend([ trial*test*dx-test*old*dx+ \ self.dt*(inner(D*nabla_grad(trial),nabla_grad(test)) + \ dolfin.Constant(diffusor[1].z/phi)*inner(D*trial*nabla_grad(self.prev_value[phi_index]),nabla_grad(test)) - source*test)*dx ]) """ # electrodiffusion here except ValueError: # No electrodiffusion for this species self.eqs.extend([trial*test*dx-old*test*dx+self.dt*(inner(D*nabla_grad(trial),nabla_grad(test))- source*test)*dx ]) self.prev_value[j].vector()[:] = diffusor[0].value(diffusor[1]) self.diffusivities[j].vector()[:] = diffusor[2] #diffusor[0].setValue(diffusor[1],self.prev_value[j].vector().array()) # do this below instead self.full_assigner.assign(self.prev_value__,self.prev_value) self.full_assigner.assign(self.functions__,self.prev_value) # Initial guess for Newton """ Vectorize the values that aren't already vectorized """ for compartment in self.compartments: for j,(species, val) in enumerate(compartment.values.items()): try: length = len(val) compartment.internalVars.extend([(species,self.N,j*self.N)]) compartment.species_internal_lookup[species] = j*self.N except: compartment.values[species]= np.ones(self.N)*val #compartment.internalVars.extend([(species,self.N,j*self.N)]) compartment.species_internal_lookup[species] = j*self.N # Set the electrostatic eqns # Each equation is associated with a single compartment as defined in for j,(trial, test, source, eps, compartment) in enumerate(zip(self.trialfunctions[self.numdiffusers:],self.testfunctions[self.numdiffusers:], \ self.sourcefunctions[self.numdiffusers:], self.permitivities, self.electrostatic_compartments)): # set the permitivity for this equation eps.vector()[:] = F**2*self.volfrac[compartment]/R/T \ *sum([compartment.diffusivities[species]*species.z**2*compartment.value(species) for species in compartment.species],axis=0) self.eqs.extend( [inner(eps*nabla_grad(trial),nabla_grad(test))*dx - source*test*dx] ) compartmentfluxes = self.updateSources() # """ Set indices for the "internal variables" List of tuples (compartment/membrane, num of variables) Each compartment or membrane has method getInternalVars() get_dot_InternalVars(t,values) get_jacobian_InternalVars(t,values) setInternalVars(values) The internal variables for each object are stored starting in y[obj.system_state_offset] """ self.internalVars = [] index = 0 for membrane in self.membranes: index2 = 0 for channel in membrane.channels: channeltmp = channel.getInternalVars() if channeltmp is not None: self.internalVars.extend([ (channel, len(channeltmp),index2)]) channel.system_state_offset = index+index2 channel.internalLength = len(channeltmp) index2+=len(channeltmp) tmp = membrane.getInternalVars() if tmp is not None: self.internalVars.extend( [(membrane,len(tmp),index)] ) membrane.system_state_offset = index index += len(tmp) membrane.points = self.N """ Compartments at the end, so we may reuse some computations """ for compartment in self.compartments: index2 = 0 compartment.system_state_offset = index # offset for this object in the overall state for species, value in compartment.values.items(): compartment.internalVars.extend([(species,len(compartment.value(species)),index2)]) index2 += len(value) tmp = compartment.getInternalVars() self.internalVars.extend( [(compartment,len(tmp),index)] ) index += len(tmp) compartment.points = self.N for key, val in self.volfrac.items(): self.volfrac[key] = val*np.ones(self.N) """ Solver setup below self.pdewolver is the FEM solver for the concentrations self.ode is the ODE solver for the membrane and volume fraction The ODE solve uses LSODA """ # Define the problem and the solver self.equation = sum(self.eqs) self.equation_ = dolfin.action(self.equation, self.functions__) self.J = dolfin.derivative(self.equation_,self.functions__) ffc_options = {"optimize": True, \ "eliminate_zeros": True, \ "precompute_basis_const": True, \ "precompute_ip_const": True, \ "quadrature_degree": 2} self.problem = dolfin.NonlinearVariationalProblem(self.equation_, self.functions__, None, self.J, form_compiler_parameters=ffc_options) self.pdesolver = dolfin.NonlinearVariationalSolver(self.problem) self.pdesolver.parameters['newton_solver']['absolute_tolerance'] = 1e-9 self.pdesolver.parameters['newton_solver']['relative_tolerance'] = 1e-9 """ ODE integrator here. Add ability to customize the parameters in the future """ self.t = 0.0 self.odesolver = ode(self.ode_rhs) # self.odesolver.set_integrator('lsoda', nsteps=3000, first_step=1e-6, max_step=5e-3 ) self.odesolver.set_initial_value(self.getInternalVars(),self.t) self.isAssembled = True
def updatePD(self): """ Update the parameters. parameters should be: - k(x) = factor inside TV - eps = regularization parameter - Vm = FunctionSpace for parameter. ||f||_TV = int k(x) sqrt{|grad f|^2 + eps} dx """ # primal dual variables self.Vw = FunctionSpace(self.Vm.mesh(), 'DG', 0) self.wH = Function(self.Vw*self.Vw) # dual variable used in Hessian (re-scaled) #self.wH = nabla_grad(self.m)/sqrt(self.fTV) # full Hessian self.w = Function(self.Vw*self.Vw) # dual variable for primal-dual, initialized at 0 self.dm = Function(self.Vm) self.dw = Function(self.Vw*self.Vw) self.testw = TestFunction(self.Vw*self.Vw) self.trialw = TrialFunction(self.Vw*self.Vw) # investigate convergence of dual variable self.dualres = self.w*sqrt(self.fTV) - nabla_grad(self.m) self.dualresnorm = inner(self.dualres, self.dualres)*dx self.normgraddm = inner(nabla_grad(self.dm), nabla_grad(self.dm))*dx # Hessian self.wkformPDhess = self.kovsq * ( \ inner(nabla_grad(self.trial), nabla_grad(self.test)) - \ 0.5*( inner(self.wH, nabla_grad(self.test))*\ inner(nabla_grad(self.trial), nabla_grad(self.m)) + \ inner(nabla_grad(self.m), nabla_grad(self.test))*\ inner(nabla_grad(self.trial), self.wH) ) / sqrt(self.fTV) \ )*dx # update dual variable self.Mw = assemble(inner(self.trialw, self.testw)*dx) self.rhswwk = inner(-self.w, self.testw)*dx + \ inner(nabla_grad(self.m)+nabla_grad(self.dm), self.testw) \ /sqrt(self.fTV)*dx + \ inner(-inner(nabla_grad(self.m),nabla_grad(self.dm))* \ self.wH/sqrt(self.fTV), self.testw)*dx
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 discretization ########################################### # FEniCS wrappers from pymor.gui.fenics import FenicsVisualizer from pymor.operators.fenics import FenicsMatrixOperator from pymor.vectorarrays.fenics import FenicsVector # generic pyMOR classes from pymor.discretizations.basic import StationaryDiscretization from pymor.operators.constructions import LincombOperator, VectorFunctional from pymor.parameters.functionals import ProjectionParameterFunctional from pymor.parameters.spaces import CubicParameterSpace from pymor.vectorarrays.list import ListVectorArray # define parameter functionals (same as in pymor.analyticalproblems.thermalblock) def parameter_functional_factory(x, y): return ProjectionParameterFunctional(component_name='diffusion', component_shape=(yblocks, xblocks), coordinates=(yblocks - y - 1, x), name='diffusion_{}_{}'.format(x, y)) parameter_functionals = tuple(parameter_functional_factory(x, y) for x, y in product(xrange(args['XBLOCKS']), xrange(args['YBLOCKS']))) # wrap operators ops = [FenicsMatrixOperator(mat0)] + [FenicsMatrixOperator(m) for m in mats] op = LincombOperator(ops, (1.,) + parameter_functionals) rhs = VectorFunctional(ListVectorArray([FenicsVector(F)])) h1_product = FenicsMatrixOperator(h1_mat, name='h1_0_semi') l2_product = FenicsMatrixOperator(l2_mat, name='l2') # build discretization visualizer = FenicsVisualizer(V) parameter_space = CubicParameterSpace(op.parameter_type, 0.1, 1.) d = StationaryDiscretization(op, rhs, products={'h1_0_semi': h1_product, 'l2': l2_product}, parameter_space=parameter_space, visualizer=visualizer) summary = '''FEniCS discretization: number of blocks: {xblocks}x{yblocks} grid intervals: {grid_num_intervals} finite element order: {element_order} '''.format(**locals()) return d, summary
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 discretization ########################################### # FEniCS wrappers from pymor.gui.fenics import FenicsVisualizer from pymor.operators.fenics import FenicsMatrixOperator from pymor.vectorarrays.fenics import FenicsVector # define parameter functionals (same as in pymor.analyticalproblems.thermalblock) parameter_functionals = [ProjectionParameterFunctional(component_name='diffusion', component_shape=(YBLOCKS, XBLOCKS), coordinates=(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 = VectorFunctional(ListVectorArray([FenicsVector(F, V)])) h1_product = FenicsMatrixOperator(h1_mat, V, V, name='h1_0_semi') # build discretization visualizer = FenicsVisualizer(V) parameter_space = CubicParameterSpace(op.parameter_type, 0.1, 1.) d = StationaryDiscretization(op, rhs, products={'h1_0_semi': h1_product}, parameter_space=parameter_space, visualizer=visualizer) return d
def test_prb88_184422(): mu0 = 4 * np.pi * 1e-7 Ms = 8.6e5 A = 16e-12 D = 3.6e-3 K = 510e3 mesh = CuboidMesh(nx=100, dx=1, unit_length=1e-9) sim = Sim(mesh) sim.driver.set_tols(rtol=1e-10, atol=1e-14) sim.driver.alpha = 0.5 sim.driver.gamma = 2.211e5 sim.Ms = Ms sim.do_precession = False sim.set_m((0, 0, 1)) sim.add(UniformExchange(A)) sim.add(DMI(-D, type='interfacial')) sim.add(UniaxialAnisotropy(K, axis=(0, 0, 1))) sim.relax(dt=1e-13, stopping_dmdt=0.01, max_steps=5000, save_m_steps=None, save_vtk_steps=50) m = sim.spin mx, my, mz = np.split(m, 3) x_array = np.linspace(-49.5, 49.5, 100) #plt.plot(x_array, mx) #plt.plot(x_array, my) #plt.plot(x_array, mz) mesh = df.IntervalMesh(100, -50, 50) Delta = np.sqrt(A / K) xi = 2 * A / D Delta_s = Delta * 1e9 V = df.FunctionSpace(mesh, "Lagrange", 1) u = df.TrialFunction(V) v = df.TestFunction(V) u_ = df.Function(V) F = -df.inner(df.nabla_grad(u), df.nabla_grad(v)) * df.dx - \ (0.5 / Delta_s**2) * df.sin(2 * u) * v * df.dx F = df.action(F, u_) J = df.derivative(F, u_, u) # the boundary condition is from equation (8) theta0 = np.arcsin(Delta / xi) ss = 'x[0]<0? %g: %g ' % (-theta0, theta0) u0 = df.Expression(ss) def u0_boundary(x, on_boundary): return on_boundary bc = df.DirichletBC(V, u0, u0_boundary) problem = df.NonlinearVariationalProblem(F, u_, bcs=bc, J=J) solver = df.NonlinearVariationalSolver(problem) solver.solve() u_array = u_.vector().array() mx_df = [] for x in x_array: mx_df.append(u_(x)) #plt.plot(x_array, mx_df) assert abs(np.max(mx - mx_df)) < 0.05
def update(self, parameters=None): """ Update the parameters. parameters should be: - k(x) = factor inside TV - eps = regularization parameter - Vm = FunctionSpace for parameter. ||f||_TV = int k(x) sqrt{|grad f|^2 + eps} dx """ # reset some variables self.H = None # udpate parameters if parameters == None: parameters = self.parameters else: self.parameters.update(parameters) GN = self.parameters['GNhessian'] self.Vm = self.parameters['Vm'] eps = self.parameters['eps'] self.k = self.parameters['k'] # define functions self.m = Function(self.Vm) self.test, self.trial = TestFunction(self.Vm), TrialFunction(self.Vm) # frequently-used variable self.fTV = inner(nabla_grad(self.m), nabla_grad(self.m)) + Constant(eps) self.kovsq = self.k / sqrt(self.fTV) # # cost functional self.wkformcost = self.k*sqrt(self.fTV)*dx # gradient self.wkformgrad = self.kovsq*inner(nabla_grad(self.m), nabla_grad(self.test))*dx # Hessian self.wkformGNhess = self.kovsq*inner(nabla_grad(self.trial), nabla_grad(self.test))*dx self.wkformFhess = self.kovsq*( \ inner(nabla_grad(self.trial), nabla_grad(self.test)) - \ inner(nabla_grad(self.m), nabla_grad(self.test))*\ inner(nabla_grad(self.trial), nabla_grad(self.m))/self.fTV )*dx if self.isPD(): self.updatePD() self.wkformhess = self.wkformPDhess print 'TV regularization -- primal-dual Newton' else: if GN: self.wkformhess = self.wkformGNhess print 'TV regularization -- GN Hessian' else: self.wkformhess = self.wkformFhess print 'TV regularization -- full Hessian'
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 discretization ########################################### from pymor.bindings.fenics import FenicsVectorSpace, FenicsMatrixOperator, FenicsVisualizer d = InstationaryDiscretization( 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 - 1.', {'top': 0})]), rhs=VectorFunctional(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), parameter_space=CubicParameterSpace({'top': 0}, minimum=1, maximum=100.), visualizer=FenicsVisualizer(FenicsVectorSpace(V)) ) return d
def __init__(self, acousticwavePDE, regularization=None): """ Input: acousticwavePDE should be an instantiation from class AcousticWave """ self.PDE = acousticwavePDE self.PDE.exact = None self.fwdsource = self.PDE.ftime self.MG = Function(self.PDE.Vl) self.MGv = self.MG.vector() self.Grad = Function(self.PDE.Vl) self.Gradv = self.Grad.vector() self.srchdir = Function(self.PDE.Vl) self.delta_m = Function(self.PDE.Vl) LinearOperator.__init__(self, self.MG.vector(), self.MG.vector()) self.obsop = None # Observation operator self.dd = None # observations if regularization == None: self.regularization = ZeroRegularization() else: self.regularization = regularization self.alpha_reg = 1.0 # gradient self.lamtest, self.lamtrial = TestFunction(self.PDE.Vl), TrialFunction(self.PDE.Vl) self.p, self.v = Function(self.PDE.V), Function(self.PDE.V) self.wkformgrad = inner(self.lamtest*nabla_grad(self.p), nabla_grad(self.v))*dx # incremental rhs self.lamhat = Function(self.PDE.Vl) self.ptrial, self.ptest = TrialFunction(self.PDE.V), TestFunction(self.PDE.V) self.wkformrhsincr = inner(self.lamhat*nabla_grad(self.ptrial), nabla_grad(self.ptest))*dx # Hessian self.phat, self.vhat = Function(self.PDE.V), Function(self.PDE.V) self.wkformhess = inner(self.lamtest*nabla_grad(self.phat), nabla_grad(self.v))*dx \ + inner(self.lamtest*nabla_grad(self.p), nabla_grad(self.vhat))*dx # Mass matrix: weak_m = inner(self.lamtrial,self.lamtest)*dx Mass = assemble(weak_m) self.solverM = LUSolver() self.solverM.parameters['reuse_factorization'] = True self.solverM.parameters['symmetric'] = True self.solverM.set_operator(Mass) # Time-integration factors self.factors = np.ones(self.PDE.times.size) self.factors[0], self.factors[-1] = 0.5, 0.5 self.factors *= self.PDE.Dt self.invDt = 1./self.PDE.Dt # Absorbing BCs if self.PDE.abc: #TODO: should probably be tested in other situations if self.PDE.lumpD: print '*** Warning: Damping matrix D is lumped. ',\ 'Make sure gradient is consistent.' self.vD, self.pD, self.p1D, self.p2D = Function(self.PDE.V), \ Function(self.PDE.V), Function(self.PDE.V), Function(self.PDE.V) self.wkformgradD = inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\ *self.pD, self.vD*self.lamtest)*self.PDE.ds(1) self.wkformDprime = inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\ *self.lamhat*self.ptrial, self.ptest)*self.PDE.ds(1) self.dp, self.dph, self.vhatD = Function(self.PDE.V), \ Function(self.PDE.V), Function(self.PDE.V) self.p1hatD, self.p2hatD = Function(self.PDE.V), Function(self.PDE.V) self.wkformhessD = inner(-0.25*sqrt(self.PDE.rho)/(self.PDE.lam*sqrt(self.PDE.lam))\ *self.lamhat*self.dp, self.vD*self.lamtest)*self.PDE.ds(1) \ + inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\ *self.dph, self.vD*self.lamtest)*self.PDE.ds(1)\ + inner(0.5*sqrt(self.PDE.rho/self.PDE.lam)\ *self.dp, self.vhatD*self.lamtest)*self.PDE.ds(1)
def __init__(self, cparams, dtype_u, dtype_f): """ Initialization routine Args: cparams: custom parameters for the example dtype_u: particle data type (will be passed parent class) dtype_f: acceleration data type (will be passed parent class) """ # define the Dirichlet boundary def Boundary(x, on_boundary): return on_boundary # these parameters will be used later, so assert their existence assert 'c_nvars' in cparams assert 't0' in cparams assert 'family' in cparams assert 'order' in cparams assert 'refinements' in cparams # add parameters as attributes for further reference for k,v in cparams.items(): setattr(self,k,v) df.set_log_level(df.WARNING) df.parameters["form_compiler"]["optimize"] = True df.parameters["form_compiler"]["cpp_optimize"] = True # set mesh and refinement (for multilevel) # mesh = df.UnitIntervalMesh(self.c_nvars) # mesh = df.UnitSquareMesh(self.c_nvars[0],self.c_nvars[1]) mesh = df.IntervalMesh(self.c_nvars,0,100) # mesh = df.RectangleMesh(0.0,0.0,2.0,2.0,self.c_nvars[0],self.c_nvars[1]) for i in range(self.refinements): mesh = df.refine(mesh) # self.mesh = mesh # define function space for future reference V = df.FunctionSpace(mesh, self.family, self.order) self.V = V*V # invoke super init, passing number of dofs, dtype_u and dtype_f super(fenics_grayscott,self).__init__(self.V,dtype_u,dtype_f) # rhs in weak form self.w = df.Function(self.V) q1,q2 = df.TestFunctions(self.V) self.w1,self.w2 = df.split(self.w) self.F1 = (-self.Du*df.inner(df.nabla_grad(self.w1), df.nabla_grad(q1)) - self.w1*(self.w2**2)*q1 + self.A*(1-self.w1)*q1)*df.dx self.F2 = (-self.Dv*df.inner(df.nabla_grad(self.w2), df.nabla_grad(q2)) + self.w1*(self.w2**2)*q2 - self.B* self.w2*q2)*df.dx self.F = self.F1+self.F2 # mass matrix u1,u2 = df.TrialFunctions(self.V) a_M = u1*q1*df.dx M1 = df.assemble(a_M) a_M = u2*q2*df.dx M2 = df.assemble(a_M) self.M = M1+M2
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.0, upper0=0.0, open0=0, lower1=0.0, upper1=0.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.0) * v * df.dx F = df.assemble(f) bc = df.DirichletBC(V, 0.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 discretization ########################################### # FEniCS wrappers from pymor.gui.fenics import FenicsVisualizer from pymor.operators.fenics import FenicsMatrixOperator from pymor.vectorarrays.fenics import FenicsVector # generic pyMOR classes from pymor.discretizations.basic import StationaryDiscretization from pymor.operators.constructions import LincombOperator, VectorFunctional from pymor.parameters.functionals import ProjectionParameterFunctional from pymor.parameters.spaces import CubicParameterSpace from pymor.vectorarrays.list import ListVectorArray # define parameter functionals (same as in pymor.analyticalproblems.thermalblock) def parameter_functional_factory(x, y): return ProjectionParameterFunctional( component_name="diffusion", component_shape=(yblocks, xblocks), coordinates=(yblocks - y - 1, x), name="diffusion_{}_{}".format(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.0,) + parameter_functionals) rhs = VectorFunctional(ListVectorArray([FenicsVector(F, V)])) h1_product = FenicsMatrixOperator(h1_mat, V, V, name="h1_0_semi") l2_product = FenicsMatrixOperator(l2_mat, V, V, name="l2") # build discretization visualizer = FenicsVisualizer(V) parameter_space = CubicParameterSpace(op.parameter_type, 0.1, 1.0) d = StationaryDiscretization( op, rhs, products={"h1_0_semi": h1_product, "l2": l2_product}, parameter_space=parameter_space, visualizer=visualizer, ) return d
def discretize(args): # first assemble all matrices for the affine decomposition import dolfin as df mesh = df.UnitSquareMesh(args["--grid"], args["--grid"], "crossed") V = df.FunctionSpace(mesh, "Lagrange", args["--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.0, upper0=0.0, open0=0, lower1=0.0, upper1=0.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, args["XBLOCKS"], args["YBLOCKS"]) for x in range(args["XBLOCKS"]) for y in range(args["YBLOCKS"]) ] mat0 = mats[0].copy() mat0.zero() h1_mat = df.assemble((df.inner(df.nabla_grad(u), df.nabla_grad(v)) + u * v) * df.dx) f = df.Constant(1.0) * v * df.dx F = df.assemble(f) bc = df.DirichletBC(V, 0.0, df.DomainBoundary()) for m in mats: bc.zero(m) bc.apply(mat0) bc.apply(F) # wrap everything as a pyMOR discretization from pymor.gui.fenics import FenicsVisualizer from pymor.operators.fenics import FenicsMatrixOperator from pymor.vectorarrays.fenics import FenicsVector ops = [FenicsMatrixOperator(mat0)] + [FenicsMatrixOperator(m) for m in mats] def parameter_functional_factory(x, y): return ProjectionParameterFunctional( component_name="diffusion", component_shape=(args["XBLOCKS"], args["YBLOCKS"]), coordinates=(args["YBLOCKS"] - y - 1, x), name="diffusion_{}_{}".format(x, y), ) parameter_functionals = tuple( parameter_functional_factory(x, y) for x, y in product(xrange(args["XBLOCKS"]), xrange(args["YBLOCKS"])) ) op = LincombOperator(ops, (1.0,) + parameter_functionals) rhs = VectorFunctional(ListVectorArray([FenicsVector(F)])) h1_product = FenicsMatrixOperator(h1_mat) visualizer = FenicsVisualizer(V) parameter_space = CubicParameterSpace(op.parameter_type, 0.1, 1.0) d = StationaryDiscretization( op, rhs, products={"h1": h1_product}, parameter_space=parameter_space, visualizer=visualizer, cache_region=None ) return d