def get_N_form(self): try: return self.N_form except AttributeError: pass # Set up magnetic field and equivalent electric current forms H_r = -curl(self.E_i)/(self.k0*Z0) H_i = curl(self.E_r)/(self.k0*Z0) J_r = cross(self.n, H_r) J_i = cross(self.n, H_i) #------------------------------ # Set up form for far field potential N theta_hat = self.theta_hat phi_hat = self.phi_hat phase = self.phase N_r = J_r*dolfin.cos(phase) - J_i*dolfin.sin(phase) N_i = J_r*dolfin.sin(phase) + J_i*dolfin.cos(phase) # UFL does not seem to like vector valued functionals, so we split the # final functional from into theta and phi components self.N_form = dict( r_theta=dot(theta_hat, N_r)*ds, r_phi=dot(phi_hat, N_r)*ds, i_theta=dot(theta_hat, N_i)*ds, i_phi=dot(phi_hat, N_i)*ds) return self.N_form
def _get_form(self): n = self.function_space.cell().n k0 = self.k0 E_i = self.E_i E_r = self.E_r mu_r = self._get_mur_function() return (1/k0/Z0)*dolfin.dot(n, (dolfin.cross(E_r, -dolfin.curl(E_i)/mu_r) + dolfin.cross(E_i, dolfin.curl(E_r)/mu_r)))*dolfin.ds
def _get_form(self): n = self.function_space.cell().n k0 = self.k0 E_i = self.E_i E_r = self.E_r mu_r = self._get_mur_function() return (1 / k0 / Z0) * dolfin.dot( n, (dolfin.cross(E_r, -dolfin.curl(E_i) / mu_r) + dolfin.cross(E_i, dolfin.curl(E_r) / mu_r))) * dolfin.ds
def rigid_motion_term(mesh, u, r): position = dolfin.SpatialCoordinate(mesh) RM = [ Constant((1, 0, 0)), Constant((0, 1, 0)), Constant((0, 0, 1)), dolfin.cross(position, Constant((1, 0, 0))), dolfin.cross(position, Constant((0, 1, 0))), dolfin.cross(position, Constant((0, 0, 1))), ] return sum(dolfin.dot(u, zi) * r[i] * dolfin.dx for i, zi in enumerate(RM))
def __init__(self, mesh): self.mesh = mesh self.S1 = df.FunctionSpace(mesh, 'CG', 1) self.S3 = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3) #zero = df.Expression('0.3') m_init = df.Constant([1, 1, 1.0]) self.m = df.interpolate(m_init, self.S3) self.field = df.interpolate(m_init, self.S3) self.dmdt = df.interpolate(m_init, self.S3) self.spin = self.m.vector().array() self.t = 0 #It seems it's not safe to specify rank in df.interpolate??? self._alpha = df.interpolate(df.Constant("0.001"), self.S1) self._alpha.vector().set_local(self._alpha.vector().array()) print 'dolfin', self._alpha.vector().array() self.llg = LLG(self.S1, self.S3, unit_length=1e-9) #normalise doesn't work due to the wrong order self.llg.set_m(m_init, normalise=True) parameters = { 'absolute_tolerance': 1e-10, 'relative_tolerance': 1e-10, 'maximum_iterations': int(1e5) } demag = Demag() demag.parameters['phi_1'] = parameters demag.parameters['phi_2'] = parameters self.exchange = Exchange(13e-12) self.zeeman = Zeeman([0, 0, 1e5]) self.llg.effective_field.add(self.exchange) #self.llg.effective_field.add(demag) self.llg.effective_field.add(self.zeeman) self.m_petsc = df.as_backend_type(self.llg.m_field.f.vector()).vec() self.h_petsc = df.as_backend_type(self.field.vector()).vec() self.alpha_petsc = df.as_backend_type(self._alpha.vector()).vec() self.dmdt_petsc = df.as_backend_type(self.dmdt.vector()).vec() alpha = 0.001 gamma = 2.21e5 LLG1 = -gamma / (1 + alpha * alpha) * df.cross( self.m, self.field) - alpha * gamma / (1 + alpha * alpha) * df.cross( self.m, df.cross(self.m, self.field)) self.L = df.dot(LLG1, df.TestFunction(self.S3)) * df.dP
def skyrmion_number_density_function(self): """ This function returns the skyrmion number density function calculated from the spin texture in this simulation instance. This function can be probed to determine the local nature of the skyrmion number. """ integrand = -0.25 / np.pi * df.dot( self.m_field.f, df.cross(df.Dx(self.m_field.f, 0), df.Dx(self.m_field.f, 1))) # Build the function space of the mesh nodes. dofmap = self.S3.dofmap() S1 = df.FunctionSpace(self.S3.mesh(), "Lagrange", 1, constrained_domain=dofmap.constrained_domain) # Find the skyrmion density at the mesh nodes using the above function # space. nodalSkx = df.dot(integrand, df.TestFunction(S1)) * df.dx nodalVolumeS1 = nodal_volume(S1, self.unit_length) skDensity = df.assemble(nodalSkx).array() * self.unit_length\ ** self.S3.mesh().topology().dim() / nodalVolumeS1 # Build the skyrmion number density dolfin function from the skDensity # array. skDensityFunc = df.Function(S1) skDensityFunc.vector()[:] = skDensity return skDensityFunc
def get_L_form(self): try: return self.L_form except AttributeError: pass # Set up equivalent magnetic current forms M_r = -cross(self.n, self.E_r) M_i = -cross(self.n, self.E_i) #------------------------------ # Set up form for far field potential L theta_hat = self.theta_hat phi_hat = self.phi_hat phase = self.phase L_r = M_r * dolfin.cos(phase) - M_i * dolfin.sin(phase) L_i = M_r * dolfin.sin(phase) + M_i * dolfin.cos(phase) self.L_form = dict(r_theta=dot(theta_hat, L_r) * ds, r_phi=dot(phi_hat, L_r) * ds, i_theta=dot(theta_hat, L_i) * ds, i_phi=dot(phi_hat, L_i) * ds) return self.L_form
def get_L_form(self): try: return self.L_form except AttributeError: pass # Set up equivalent magnetic current forms M_r = -cross(self.n, self.E_r) M_i = -cross(self.n, self.E_i) #------------------------------ # Set up form for far field potential L theta_hat = self.theta_hat phi_hat = self.phi_hat phase = self.phase L_r = M_r*dolfin.cos(phase) - M_i*dolfin.sin(phase) L_i = M_r*dolfin.sin(phase) + M_i*dolfin.cos(phase) self.L_form = dict( r_theta=dot(theta_hat, L_r)*ds, r_phi=dot(phi_hat, L_r)*ds, i_theta=dot(theta_hat, L_i)*ds, i_phi=dot(phi_hat, L_i)*ds) return self.L_form
def skyrmion_number(self): """ This function returns the skyrmion number calculated from the spin texture in this simulation instance. If the sim object is 3D, the skyrmion number is calculated from the magnetisation of the top surface (since the skyrmion number formula is only defined for 2D). Details about computing functionals over subsets of the mesh (the method used in this function to calculate the skyrmion number) can be found at: https://bitbucket.org/fenics-project/dolfin/src/master/demo/undocumented/lift-drag/python/demo_lift-drag.py """ mesh = self.mesh # Get m field and define skyrmion number integrand m = self.m_field.f integrand = -0.25 / np.pi * df.dot(m, df.cross(df.Dx(m, 0), df.Dx(m, 1))) # determine if 3D system or not. Act accordingly. if self.mesh.topology().dim() == 3: mesh_coords = mesh.coordinates() z_max = max(mesh_coords[:, 2]) # Define a subdomain which consists of the top surface of the geometry class Top(df.SubDomain): def inside(self, pt, on_boundary): x, y, z = pt return z >= z_max - df.DOLFIN_EPS and on_boundary # Define a set of Markers from a MeshFunction (which is a function that # can be evaluated at a set of mesh entities). Set all the marks to Zero. markers = df.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) markers.set_all(0) top = Top() # Redefine the marks on the top surface to 1. top.mark(markers, 1) # Define ds so that it only computes where the marker=1 (top surface) ds = df.ds[markers] # Assemble the integrand on the the original domain, but only over the # marked region (top surface). S = df.assemble(form=integrand * ds(1, domain=mesh)) else: S = df.assemble(integrand * df.dx) return S
def cross(self, other): """ Return vector field representing the cross product of this field with `other`. """ if not isinstance(other, Field): raise TypeError("Argument must be a Field. Got: {} ({})".format( other, type(other))) if not (self.value_dim() == 3 and other.value_dim() == 3): raise ValueError( "The cross product is only defined for 3d vector fields.") # We use Claas Abert's 'point measure hack' for the vertex-wise cross product. w = df.TestFunction(self.functionspace) v_res = df.assemble(df.dot(df.cross(self.f, other.f), w) * df.dP) return Field(self.functionspace, value=v_res)
def get_bilinear_form(self, test_function=None, trial_function=None): """Calculate and return the bilinear form associated with the boundary condition. The form is calculated as: M{<n S{times} v, n S{times} u>}, where M{v} and M{u} are the test and trial functions, respectively. @keyword test_function: override the stored test function space. (default: None.) @keyword trial_function: override the stored trial function space. (default: None.) """ V = self.function_space if test_function is None: v = dolfin.TestFunction(self.function_space) else: v = test_function if trial_function is None: u = dolfin.TrialFunction(self.function_space) else: u = trial_function n = V.cell().n s_0 = inner(cross(n, v), cross(n, u)) * ds return s_0
def get_bilinear_form(self, test_function=None, trial_function=None): """Calculate and return the bilinear form associated with the boundary condition. The form is calculated as: M{<n S{times} v, n S{times} u>}, where M{v} and M{u} are the test and trial functions, respectively. @keyword test_function: override the stored test function space. (default: None.) @keyword trial_function: override the stored trial function space. (default: None.) """ V = self.function_space if test_function is None: v = dolfin.TestFunction(self.function_space) else: v = test_function if trial_function is None: u = dolfin.TrialFunction(self.function_space) else: u = trial_function n = V.cell().n s_0 = inner(cross(n, v), cross(n, u))*ds return s_0
def get_N_form(self): try: return self.N_form except AttributeError: pass # Set up magnetic field and equivalent electric current forms H_r = -curl(self.E_i) / (self.k0 * Z0) H_i = curl(self.E_r) / (self.k0 * Z0) J_r = cross(self.n, H_r) J_i = cross(self.n, H_i) #------------------------------ # Set up form for far field potential N theta_hat = self.theta_hat phi_hat = self.phi_hat phase = self.phase N_r = J_r * dolfin.cos(phase) - J_i * dolfin.sin(phase) N_i = J_r * dolfin.sin(phase) + J_i * dolfin.cos(phase) # UFL does not seem to like vector valued functionals, so we split the # final functional from into theta and phi components self.N_form = dict(r_theta=dot(theta_hat, N_r) * ds, r_phi=dot(phi_hat, N_r) * ds, i_theta=dot(theta_hat, N_i) * ds, i_phi=dot(phi_hat, N_i) * ds) return self.N_form
beta_endo_lv=0, beta_epi_lv=0, ) circ, _, _ = ldrb.dolfin_ldrb( mesh=mesh, fiber_space=space, ffun=ffun, markers=markers, alpha_endo_lv=0, alpha_epi_lv=0, beta_endo_lv=0, beta_epi_lv=0, ) rad = dolfin.project(dolfin.cross(circ, long), circ.function_space()) # # For the single ventricle it is much simpler # else: long, circ, rad = ldrb.dolfin_ldrb( mesh=mesh, fiber_space=space, ffun=ffun, markers=markers, alpha_endo_lv=-90, alpha_epi_lv=-90, beta_endo_lv=0,
for i in subIds: dA[i] = dlfn.Measure("ds", subMeshes[i], subdomain_data=facetSubMeshFuns[i]) dV[i] = dlfn.Measure("dx", subMeshes[i]) normals[i] = dlfn.FacetNormal(subMeshes[i]) #------------------------------------------------------------------------------# # weak forms and assembly in interior #------------------------------------------------------------------------------# # linear forms in interior domain from dolfin import curl, inner, dot, cross, grad jumpM = dlfn.Constant((0.0, 0.0, -1.0)) a_int = inner(curl(A), curl(B)) * dV[intId] b_int = dot(A, grad(v)) * dV[intId] c_int = u * dot(normals[intId], curl(B)) * dA[intId](intrfcId) l_int = dot(cross(normals[intId], jumpM), B) * dA[intId](intrfcId) # assemble (0,0)-block matA = dlfn.assemble(a_int) rhs_int = dlfn.assemble(l_int) # assemble (0,1)-block matB = dlfn.assemble(b_int) # assemble (0,2)-block matC = dlfn.assemble(c_int) #------------------------------------------------------------------------------# # weak forms and assembly in exterior #------------------------------------------------------------------------------# # linear forms in exterior domain a_ext = inner(grad(phi), grad(psi)) * dV[extId] l_ext = dlfn.Constant(0.) * psi * dV[extId] # apply boundary condition bc = dlfn.DirichletBC(extH1, dlfn.Constant(0.), facetSubMeshFuns[extId],
A, phi = dlfn.TrialFunctions(Vh) # test functions delA, psi = dlfn.TestFunctions(Vh) # geometric objects n = dlfn.FacetNormal(mesh) P = dlfn.Identity(dim) - dlfn.outer(n, n) # Dirichlet boundary condition on exterior surface bcA = dlfn.DirichletBC(Vh.sub(0), dlfn.Constant((0.0, 0.0, 0.0)), facetIds, bndryId) bcPhi = dlfn.DirichletBC(Vh.sub(1), dlfn.Constant(0.0), facetIds, bndryId) # bilinear form a = dlfn.dot(dlfn.curl(A), dlfn.curl(delA)) * dV() \ + dlfn.dot(A, dlfn.grad(psi)) * dV() \ + dlfn.dot(dlfn.grad(phi), delA) * dV() # rhs form l = dlfn.dot(dlfn.cross(n("+"), jumpM("+")), delA("+")) * dA(intrfcId) # compute solution sol = dlfn.Function(Vh) lin_problem = dlfn.LinearVariationalProblem(a, l, sol, bcs=[bcA, bcPhi]) lin_solver = dlfn.LinearVariationalSolver(lin_problem) lin_solver_parameters = lin_solver.parameters lin_solver.solve() # sub solutions solA = sol.sub(0) solPhi = sol.sub(1) # output to pvd pvd_A = dlfn.File("solution-A.pvd") pvd_A << solA # solving for magnetic field Wh = dlfn.VectorFunctionSpace(mesh, "CG", 1) curlA = dlfn.project(dlfn.curl(solA), Wh)
# Define function space order = 1 V = dol.FunctionSpace(mesh, "Nedelec 1st kind H(curl)", order) # Define basis and bilinear form k_0 = 2*N.pi*freq/c0 u = dol.TrialFunction(V) v = dol.TestFunction(V) m = eps_r*inner(v, u)*dx # Mass form s = (1/mu_r)*dot(curl(v), curl(u))*dx # Stiffness form n = V.cell().n s_0 = inner ( cross ( n, v), cross ( n, u ) )*ds def boundary(x, on_boundary): return on_boundary # Assemble forms M = dol.uBLASSparseMatrix() S = dol.uBLASSparseMatrix() S_0 = dol.uBLASSparseMatrix() dol.assemble(m, tensor=M, mesh=mesh) dol.assemble(s, tensor=S, mesh=mesh) dol.assemble(s_0, tensor=S_0, mesh=mesh) from scipy.sparse import csr_matrix from pyamg import smoothed_aggregation_solver
def main(): # Define mesh domain_subdivisions = N.array( N.ceil(N.sqrt(2) * domain_size / max_edge_len), N.uint) print 'Numer of domain subdomain_subdivisions: ', domain_subdivisions mesh = dolfin.UnitCube(*domain_subdivisions) # Transform mesh to correct dimensions mesh.coordinates()[:] *= domain_size # Centred around [0,0,0] mesh.coordinates()[:] -= domain_size / 2 ## Translate mesh slightly so that source coordinate lies at ## centroid of an element io = mesh.intersection_operator() source_elnos = io.all_intersected_entities(source_point) closest_elno = source_elnos[(N.argmin([ source_point.distance(dolfin.Cell(mesh, i).midpoint()) for i in source_elnos ]))] centre_pt = dolfin.Cell(mesh, closest_elno).midpoint() centre_coord = N.array([centre_pt.x(), centre_pt.y(), centre_pt.z()]) # There seems to be an issue with the intersect operator if the # mesh coordinates are changed after calling it for the first # time. Since we called it to find the centroid, we should init a # new mesh mesh_coords = mesh.coordinates().copy() mesh = dolfin.UnitCube(*domain_subdivisions) mesh.coordinates()[:] = mesh_coords mesh.coordinates()[:] -= centre_coord ## # Define function space V = dolfin.FunctionSpace(mesh, "Nedelec 1st kind H(curl)", order) k_0 = 2 * N.pi * freq / c0 # Freespace wave number # Definite test- and trial functions u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) # Define the bilinear forms m = eps_r * inner(v, u) * dx # Mass form s = (1 / mu_r) * dot(curl(v), curl(u)) * dx # Stiffness form n = V.cell().n # Get the surface normal s_0 = inner(cross(n, v), cross(n, u)) * ds # ABC boundary condition form # Assemble forms using uBLASS matrices so that we can easily export to scipy print 'Assembling forms' M = dolfin.uBLASSparseMatrix() S = dolfin.uBLASSparseMatrix() S_0 = dolfin.uBLASSparseMatrix() dolfin.assemble(m, tensor=M, mesh=mesh) dolfin.assemble(s, tensor=S, mesh=mesh) dolfin.assemble(s_0, tensor=S_0, mesh=mesh) print 'Number of degrees of freedom: ', M.size(0) # Set up RHS b = N.zeros(M.size(0), dtype=N.complex128) dofnos, rhs_contrib = calc_pointsource_contrib(V, source_coord, source_value) rhs_contrib = 1j * k_0 * Z0 * rhs_contrib b[dofnos] += rhs_contrib Msp = dolfin_ublassparse_to_scipy_csr(M) Ssp = dolfin_ublassparse_to_scipy_csr(S) S_0sp = dolfin_ublassparse_to_scipy_csr(S_0) # A is the system matrix that must be solved A = Ssp - k_0**2 * Msp + 1j * k_0 * S_0sp solved = False if solver == 'iterative': # solve using scipy bicgstab print 'solve using scipy bicgstab' x = solve_sparse_system(A, b) elif solver == 'direct': import scipy.sparse.linalg A_lu = scipy.sparse.linalg.factorized(A.T) x = A_lu(b) else: raise ValueError("solver must have value 'iterative' or 'direct'") dolfin.set_log_active(False) # evaluation seems to make a lot of noise u_re = dolfin.Function(V) u_im = dolfin.Function(V) # N.require is important, since dolfin seems to expect a contiguous array u_re.vector()[:] = N.require(N.real(x), requirements='C') u_im.vector()[:] = N.require(N.imag(x), requirements='C') E_field = N.zeros((len(field_pts), 3), dtype=N.complex128) for i, fp in enumerate(field_pts): try: E_field[i, :] = u_re(fp) + 1j * u_im(fp) except (RuntimeError, StandardError): E_field[i, :] = N.nan + 1j * N.nan import pylab as P r1 = field_pts[:] / lam x1 = r1[:, 0] E_ana = N.abs(analytical_result) E_num = E_field P.figure() P.plot(x1, N.abs(E_num[:, 0]), '-g', label='x_num') P.plot(x1, N.abs(E_num[:, 1]), '-b', label='y_num') P.plot(x1, N.abs(E_num[:, 2]), '-r', label='z_num') P.plot(analytical_pts, E_ana, '--r', label='z_ana') P.ylabel('E-field Magnitude') P.xlabel('Distance (wavelengths)') P.legend(loc='best') P.grid(True) P.show()
def as_real_imag(self, deep=True, **hints): u_re, u_im = self.args[0].as_real_imag() v_re, v_im = self.args[1].as_real_imag() return (cross(u_re, v_re) - cross(u_im, v_im), cross(u_re, v_im) + cross(v_re, u_im))
def _setup_implicit_problem(self): assert hasattr(self, "_parameters") assert hasattr(self, "_mesh") assert hasattr(self, "_Wh") assert hasattr(self, "_coefficients") assert hasattr(self, "_one") assert hasattr(self, "_omega") assert hasattr(self, "_v0") assert hasattr(self, "_v00") assert hasattr(self, "_T0") assert hasattr(self, "_T00") print " setup implicit problem..." #======================================================================= # retrieve imex coefficients a, c = self._imex_alpha, self._imex_gamma #======================================================================= # trial and test function (del_v, del_p, del_T) = dlfn.TestFunctions(self._Wh) v, p, T = dlfn.split(self._sol) # volume element dV = dlfn.Measure("dx", domain=self._mesh) # reference to time step timestep = self._timestep #======================================================================= from dolfin import dot, grad # 1) momentum equation momentum_eqn = ( dot((a[0] * v + a[1] * self._v0 + a[2] * self._v00) / timestep, del_v) + dot(dot(grad(v), v), del_v) + self._coefficients[1] * a_op(c[0] * v + c[1] * self._v0 + c[2] * self._v00, del_v) - b_op(del_v, p) - b_op(v, del_p)) * dV # 2) momentum equation: coriolis term if self._parameters.rotation is True: assert self._coefficients[0] != 0.0 print " adding rotation to the model..." # add Coriolis term if self._space_dim == 2: momentum_eqn += self._coefficients[0] * (-v[1] * del_v[0] + v[0] * del_v[1]) * dV elif self._space_dim == 3: assert hasattr(self, "_rotation_vector") assert isinstance(self._rotation_vector, (dlfn.Constant, dlfn.Expression)) from dolfin import cross momentum_eqn += self._coefficients[0] * dot( cross(self._rotation_vector, v), del_v) * dV # 3) momentum equation: coriolis term if self._parameters.buoyancy is True: assert self._coefficients[2] != 0.0 assert hasattr(self, "_gravity") and isinstance( self._gravity, (dlfn.Expression, dlfn.Constant)) print " adding buoyancy to the model..." # add buoyancy term momentum_eqn += self._coefficients[2] * T * dot( self._gravity, del_v) * dV #======================================================================= # 4) energy equation energy_eqn = ( (a[0] * T + a[1] * self._T0 + a[2] * self._T00) / timestep * del_T + dot(v, grad(T)) * del_T + self._coefficients[3] * a_op(c[0] * T + c[1] * self._T0 + c[2] * self._T00, del_T)) * dV #======================================================================= # full problem self._eqn = momentum_eqn + energy_eqn if not hasattr(self, "_dirichlet_bcs"): self._setup_boundary_conditons() self._jacobian = dlfn.derivative(self._eqn, self._sol) problem = dlfn.NonlinearVariationalProblem(self._eqn, self._sol, J=self._jacobian, bcs=self._dirichlet_bcs) self._solver = dlfn.NonlinearVariationalSolver(problem) prm = self._solver.parameters prm["newton_solver"]["absolute_tolerance"] = 1e-6 prm["newton_solver"]["relative_tolerance"] = 1e-9 prm["newton_solver"]["maximum_iterations"] = 10
def _setup_imex_problem(self): assert hasattr(self, "_parameters") assert hasattr(self, "_mesh") assert hasattr(self, "_Wh") assert hasattr(self, "_coefficients") assert hasattr(self, "_one") assert hasattr(self, "_omega") assert hasattr(self, "_v0") assert hasattr(self, "_v00") assert hasattr(self, "_T0") assert hasattr(self, "_T00") print " setup explicit imex problem..." #======================================================================= # retrieve imex coefficients a, b, c = self._imex_alpha, self._imex_beta, self._imex_gamma #======================================================================= # trial and test function (del_v, del_p, del_T) = dlfn.TestFunctions(self._Wh) (dv, dp, dT) = dlfn.TrialFunctions(self._Wh) # volume element dV = dlfn.Measure("dx", domain=self._mesh) # reference to time step timestep = self._timestep #======================================================================= from dolfin import dot, grad, inner # 1) lhs momentum equation lhs_momentum = a[0] / timestep * dot(dv, del_v) * dV \ + c[0] * self._coefficients[1] * a_op(dv, del_v) * dV\ - b_op(del_v, dp) * dV\ - b_op(dv, del_p) * dV # 2a) rhs momentum equation: time derivative rhs_momentum = -dot( a[1] / timestep * self._v0 + a[2] / timestep * self._v00, del_v) * dV # 2b) rhs momentum equation: nonlinear term nonlinear_term_velocity = b[0] * dot(grad(self._v0), self._v0) \ + b[1] * dot(grad(self._v00), self._v00) rhs_momentum -= dot(nonlinear_term_velocity, del_v) * dV # 2c) rhs momentum equation: linear term rhs_momentum -= self._coefficients[1] * inner( c[1] * grad(self._v0) + c[2] * grad(self._v00), grad(del_v)) * dV # 2d) rhs momentum equation: coriolis term if self._parameters.rotation is True: assert self._coefficients[0] != 0.0 print " adding rotation to the model..." # defining extrapolated velocity extrapolated_velocity = (self._one + self._omega) * self._v0 \ - self._omega * self._v00 # set Coriolis term if self._space_dim == 2: rhs_momentum -= self._coefficients[0] * ( -extrapolated_velocity[1] * del_v[0] + extrapolated_velocity[0] * del_v[1]) * dV elif self._space_dim == 3: from dolfin import cross coriolis_term = cross(self._rotation_vector, extrapolated_velocity) rhs_momentum -= self._coefficients[0] * dot( coriolis_term, del_v) * dV print " adding rotation to the model..." # 2e) rhs momentum equation: buoyancy term if self._parameters.buoyancy is True: assert self._coefficients[2] != 0.0 # defining extrapolated temperature extrapolated_temperature = ( self._one + self._omega) * self._T0 - self._omega * self._T00 # buoyancy term print " adding buoyancy to the model..." rhs_momentum -= self._coefficients[ 2] * extrapolated_temperature * dot(self._gravity, del_v) * dV #======================================================================= # 3) lhs energy equation lhs_energy = a[0] / timestep * dot(dT, del_T) * dV \ + self._coefficients[3] * a_op(dT, del_T) * dV # 4a) rhs energy equation: time derivative rhs_energy = -dot( a[1] / timestep * self._T0 + a[2] / timestep * self._T00, del_T) * dV # 4b) rhs energy equation: nonlinear term nonlinear_term_temperature = b[0] * dot(self._v0, grad(self._T0)) \ + b[1] * dot(self._v00, grad(self._T00)) rhs_energy -= nonlinear_term_temperature * del_T * dV # 4c) rhs energy equation: linear term rhs_energy -= self._coefficients[3] \ * dot(c[1] * grad(self._T0) + c[2] * grad(self._T00), grad(del_T)) * dV #======================================================================= # full problem self._lhs = lhs_momentum + lhs_energy self._rhs = rhs_momentum + rhs_energy if not hasattr(self, "_dirichlet_bcs"): self._setup_boundary_conditions() if self._parameters.use_assembler_method: # system assembler self._assembler = dlfn.SystemAssembler(self._lhs, self._rhs, bcs=self._dirichlet_bcs) self._system_matrix = dlfn.Matrix() self._system_rhs = dlfn.Vector() self._solver = dlfn.LUSolver(self._system_matrix) else: # linear problem problem = dlfn.LinearVariationalProblem(self._lhs, self._rhs, self._sol, bcs=self._dirichlet_bcs) self._solver = dlfn.LinearVariationalSolver(problem)
def main(): # Define mesh domain_subdivisions = N.array(N.ceil(N.sqrt(2)*domain_size/max_edge_len), N.uint) print 'Numer of domain subdomain_subdivisions: ', domain_subdivisions mesh = dolfin.UnitCube(*domain_subdivisions) # Transform mesh to correct dimensions mesh.coordinates()[:] *= domain_size # Centred around [0,0,0] mesh.coordinates()[:] -= domain_size/2 ## Translate mesh slightly so that source coordinate lies at ## centroid of an element source_elnos = mesh.all_intersected_entities(source_point) closest_elno = source_elnos[(N.argmin([source_point.distance(dolfin.Cell(mesh, i).midpoint()) for i in source_elnos]))] centre_pt = dolfin.Cell(mesh, closest_elno).midpoint() centre_coord = N.array([centre_pt.x(), centre_pt.y(), centre_pt.z()]) # There seems to be an issue with the intersect operator if the # mesh coordinates are changed after calling it for the first # time. Since we called it to find the centroid, we should init a # new mesh mesh_coords = mesh.coordinates().copy() mesh = dolfin.UnitCube(*domain_subdivisions) mesh.coordinates()[:] = mesh_coords mesh.coordinates()[:] -= centre_coord ## # Define function space V = dolfin.FunctionSpace(mesh, "Nedelec 1st kind H(curl)", order) k_0 = 2*N.pi*freq/c0 # Freespace wave number # Definite test- and trial functions u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) # Define the bilinear forms m = eps_r*inner(v, u)*dx # Mass form s = (1/mu_r)*dot(curl(v), curl(u))*dx # Stiffness form n = V.cell().n # Get the surface normal s_0 = inner(cross(n, v), cross(n, u))*ds # ABC boundary condition form # Assemble forms using uBLASS matrices so that we can easily export to scipy print 'Assembling forms' M = dolfin.uBLASSparseMatrix() S = dolfin.uBLASSparseMatrix() S_0 = dolfin.uBLASSparseMatrix() dolfin.assemble(m, tensor=M, mesh=mesh) dolfin.assemble(s, tensor=S, mesh=mesh) dolfin.assemble(s_0, tensor=S_0, mesh=mesh) print 'Number of degrees of freedom: ', M.size(0) # Set up RHS b = N.zeros(M.size(0), dtype=N.complex128) dofnos, rhs_contrib = calc_pointsource_contrib(V, source_coord, source_value) rhs_contrib = 1j*k_0*Z0*rhs_contrib b[dofnos] += rhs_contrib Msp = dolfin_ublassparse_to_scipy_csr(M) Ssp = dolfin_ublassparse_to_scipy_csr(S) S_0sp = dolfin_ublassparse_to_scipy_csr(S_0) # A is the system matrix that must be solved A = Ssp - k_0**2*Msp + 1j*k_0*S_0sp solved = False; if solver == 'iterative': # solve using scipy bicgstab print 'solve using scipy bicgstab' x = solve_sparse_system ( A, b ) elif solver == 'direct': import scipy.sparse.linalg A_lu = scipy.sparse.linalg.factorized(A.T) x = A_lu(b) else: raise ValueError("solver must have value 'iterative' or 'direct'") dolfin.set_log_active(False) # evaluation seems to make a lot of noise u_re = dolfin.Function(V) u_im = dolfin.Function(V) # N.require is important, since dolfin seems to expect a contiguous array u_re.vector()[:] = N.require(N.real(x), requirements='C') u_im.vector()[:] = N.require(N.imag(x), requirements='C') E_field = N.zeros((len(field_pts), 3), dtype=N.complex128) for i, fp in enumerate(field_pts): try: E_field[i,:] = u_re(fp) + 1j*u_im(fp) except (RuntimeError, StandardError): E_field[i,:] = N.nan + 1j*N.nan import pylab as P r1 = field_pts[:]/lam x1 = r1[:,0] E_ana = N.abs(analytical_result) E_num = E_field P.figure() P.plot(x1, N.abs(E_num[:,0]), '-g', label='x_num') P.plot(x1, N.abs(E_num[:,1]), '-b', label='y_num') P.plot(x1, N.abs(E_num[:,2]), '-r', label='z_num') P.plot(analytical_pts, E_ana, '--r', label='z_ana') P.ylabel('E-field Magnitude') P.xlabel('Distance (wavelengths)') P.legend(loc='best') P.grid(True) P.show()
def cross_product(a, b, S3): """ Function computing the cross product of two vector functions. The result is a dolfin vector. """ return df.assemble(df.dot(df.cross(a, b), df.TestFunction(S3)) * df.dP)
def generate_matrices(mesh_file, order): """ Generate the matrices for a 1\lambda spherical domain with an infintesimal dipole at the origin. @param mesh_file: the full path and filename to the spherical mesh to be used (this is a femmesh file). @todo: change the mesh type to a gmsh mesh. """ problem_data = { 'l': 2.9979245800000002e-4, 'I': 1.0, 'f': 1.0e9, 'source_coord': np.array([0, 0, 0.]), 'order': order, } lam = c0 / problem_data['f'] # load the mesh and scale coordinates accordingly mesh = femmesh_2_dolfin_mesh(mesh_file) mesh.init() mesh.coordinates()[:] *= lam eps_r = 1 mu_r = 1 freq = problem_data['f'] source_coord = problem_data['source_coord'] source_point = dolfin.Point(*source_coord) source_value = np.array([0, 0, 1.]) * problem_data['I'] * problem_data['l'] V = dolfin.FunctionSpace(mesh, "Nedelec 1st kind H(curl)", problem_data['order']) print 'DOFs: ', V.dim() # Define basis and bilinear form k_0 = 2 * np.pi * freq / c0 u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) m = eps_r * inner(v, u) * dx # Mass form s = (1 / mu_r) * dot(curl(v), curl(u)) * dx # Stiffness form n = V.cell().n s_0 = inner(cross(n, v), cross(n, u)) * ds def boundary(x, on_boundary): return on_boundary # Assemble forms print 'assembling forms' M = dolfin.uBLASSparseMatrix() S = dolfin.uBLASSparseMatrix() S_0 = dolfin.uBLASSparseMatrix() dolfin.assemble(m, tensor=M, mesh=mesh) dolfin.assemble(s, tensor=S, mesh=mesh) dolfin.assemble(s_0, tensor=S_0, mesh=mesh) # Set up RHS b = np.zeros(M.size(0), dtype=np.complex128) dofnos, rhs_contrib = point_source.calc_pointsource_contrib( V, source_coord, source_value) rhs_contrib = 1j * k_0 * Z0 * rhs_contrib b[dofnos] += rhs_contrib Msp = dolfin_ublassparse_to_scipy_csr(M) Ssp = dolfin_ublassparse_to_scipy_csr(S) S_0sp = dolfin_ublassparse_to_scipy_csr(S_0) A = Ssp - k_0**2 * Msp + 1j * k_0 * S_0sp return A, b
def Cost(xp): comm = nMPI.COMM_WORLD mpi_rank = comm.Get_rank() x1, x2 = xp #The two variables (length and feed offset) rs = 8.0 # radiation boundary radius l = x1 # Patch length w = 4.5 # Patch width s1 = x2 * x1 / 2.0 # Feed offset h = 1.0 # Patch height t = 0.05 # Metal thickness lc = 1.0 # Coax length rc = 0.25 # Coax shield radius cc = 0.107 #Coax center conductor 50 ohm air diel eps = 1.0e-4 tol = 1.0e-6 eta = 377.0 # vacuum intrinsic wave impedance eps_c = 1.0 # dielectric permittivity k0 = 2.45 * 2.0 * np.pi / 30.0 # Frequency in GHz ls = 0.025 #Mesh density parameters for GMSH lm = 0.8 lw = 0.06 lp = 0.3 # Run GMSH only on one MPI processor (process 0). # We use the GMSH Python interface to generate the geometry and mesh objects if mpi_rank == 0: print("x[0] = {0:<f}, x[1] = {1:<f} ".format(xp[0], xp[1])) print("length = {0:<f}, width = {1:<f}, feed offset = {2:<f}".format(l, w, s1)) gmsh.initialize() gmsh.option.setNumber('General.Terminal', 1) gmsh.model.add("SimplePatchOpt") # Radiation sphere gmsh.model.occ.addSphere(0.0, 0.0, 0.0, rs, 1) gmsh.model.occ.addBox(0.0, -rs, 0.0, rs, 2*rs, rs, 2) gmsh.model.occ.intersect([(3,1)],[(3,2)], 3, removeObject=True, removeTool=True) # Patch gmsh.model.occ.addBox(0.0, -l/2, h, w/2, l, t, 4) # coax center gmsh.model.occ.addCylinder(0.0, s1, -lc, 0.0, 0.0, lc+h, cc, 5, 2.0*np.pi) # coax shield gmsh.model.occ.addCylinder(0.0, s1, -lc, 0.0, 0.0, lc, rc, 7) gmsh.model.occ.addBox(0.0, s1-rc, -lc, rc, 2.0*rc, lc, 8) gmsh.model.occ.intersect([(3,7)], [(3,8)], 9, removeObject=True, removeTool=True) gmsh.model.occ.fuse([(3,3)], [(3,9)], 10, removeObject=True, removeTool=True) # cutout internal boundaries gmsh.model.occ.cut([(3,10)], [(3,4),(3,5)], 11, removeObject=True, removeTool=True) gmsh.option.setNumber('Mesh.MeshSizeMin', ls) gmsh.option.setNumber('Mesh.MeshSizeMax', lm) gmsh.option.setNumber('Mesh.Algorithm', 6) gmsh.option.setNumber('Mesh.Algorithm3D', 1) gmsh.option.setNumber('Mesh.MshFileVersion', 4.1) gmsh.option.setNumber('Mesh.Format', 1) gmsh.option.setNumber('Mesh.MinimumCirclePoints', 36) gmsh.option.setNumber('Mesh.CharacteristicLengthFromCurvature', 1) gmsh.model.occ.synchronize() pts = gmsh.model.getEntities(0) gmsh.model.mesh.setSize(pts, lm) #Set background mesh density pts = gmsh.model.getEntitiesInBoundingBox(-eps, -l/2-eps, h-eps, w/2+eps, l/2+eps, h+t+eps) gmsh.model.mesh.setSize(pts, ls) pts = gmsh.model.getEntitiesInBoundingBox(-eps, s1-rc-eps, -lc-eps, rc+eps, s1+rc+eps, h+eps) gmsh.model.mesh.setSize(pts, lw) pts = gmsh.model.getEntitiesInBoundingBox(-eps, -rc-eps, -eps, rc+eps, rc+eps, eps) gmsh.model.mesh.setSize(pts, lw) # Embed points to reduce mesh density on patch faces fce1 = gmsh.model.getEntitiesInBoundingBox(-eps, -l/2-eps, h+t-eps, w/2+eps, l/2+eps, h+t+eps, 2) gmsh.model.occ.synchronize() gmsh.model.geo.addPoint(w/4, -l/4, h+t, lp, 1000) gmsh.model.geo.addPoint(w/4, 0.0, h+t, lp, 1001) gmsh.model.geo.addPoint(w/4, l/4, h+t, lp, 1002) gmsh.model.geo.synchronize() gmsh.model.occ.synchronize() print(fce1) fce2 = gmsh.model.getEntitiesInBoundingBox(-eps, -l/2-eps, h-eps, w/2+eps, l/2+eps, h+eps, 2) gmsh.model.geo.addPoint(w/4, -9*l/32, h, lp, 1003) gmsh.model.geo.addPoint(w/4, 0.0, h, lp, 1004) gmsh.model.geo.addPoint(w/4, 9*l/32, h, lp, 1005) gmsh.model.geo.synchronize() for tt in fce1: gmsh.model.mesh.embed(0, [1000, 1001, 1002], 2, tt[1]) for tt in fce2: gmsh.model.mesh.embed(0, [1003, 1004, 1005], 2, tt[1]) print(fce2) gmsh.model.occ.remove(fce1) gmsh.model.occ.remove(fce2) gmsh.model.occ.synchronize() gmsh.model.addPhysicalGroup(3, [11], 1) gmsh.model.setPhysicalName(3, 1, "Air") gmsh.model.mesh.optimize("Relocate3D", niter=5) gmsh.model.mesh.generate(3) gmsh.write("SimplePatch.msh") gmsh.finalize() # Mesh generation is finished. We now use Meshio to translate GMSH mesh to xdmf file for # importation into Fenics FE solver msh = meshio.read("SimplePatch.msh") for cell in msh.cells: if cell.type == "tetra": tetra_cells = cell.data for key in msh.cell_data_dict["gmsh:physical"].keys(): if key == "tetra": tetra_data = msh.cell_data_dict["gmsh:physical"][key] tetra_mesh = meshio.Mesh(points=msh.points, cells={"tetra": tetra_cells}, cell_data={"VolumeRegions":[tetra_data]}) meshio.write("mesh.xdmf", tetra_mesh) # Here we import the mesh into Fenics mesh = dolfin.Mesh() with dolfin.XDMFFile("mesh.xdmf") as infile: infile.read(mesh) mvc = dolfin.MeshValueCollection("size_t", mesh, 3) with dolfin.XDMFFile("mesh.xdmf") as infile: infile.read(mvc, "VolumeRegions") cf = dolfin.cpp.mesh.MeshFunctionSizet(mesh, mvc) # The boundary classes for the FE solver class PEC(dolfin.SubDomain): def inside(self, x, on_boundary): return on_boundary class InputBC(dolfin.SubDomain): def inside(self, x, on_boundary): return on_boundary and dolfin.near(x[2], -lc, tol) class OutputBC(dolfin.SubDomain): def inside(self, x, on_boundary): rr = np.sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2]) return on_boundary and dolfin.near(rr, 8.0, 1.0e-1) class PMC(dolfin.SubDomain): def inside(self, x, on_boundary): return on_boundary and dolfin.near(x[0], 0.0, tol) # Volume domains dolfin.File("VolSubDomains.pvd").write(cf) dolfin.File("Mesh.pvd").write(mesh) # Mark boundaries sub_domains = dolfin.MeshFunction("size_t", mesh, mesh.topology().dim() - 1) sub_domains.set_all(4) pec = PEC() pec.mark(sub_domains, 0) in_port = InputBC() in_port.mark(sub_domains, 1) out_port = OutputBC() out_port.mark(sub_domains, 2) pmc = PMC() pmc.mark(sub_domains, 3) dolfin.File("BoxSubDomains.pvd").write(sub_domains) # Set up function spaces cell = dolfin.tetrahedron ele_type = dolfin.FiniteElement('N1curl', cell, 2, variant="integral") # H(curl) element for EM V2 = dolfin.FunctionSpace(mesh, ele_type * ele_type) V = dolfin.FunctionSpace(mesh, ele_type) (u_r, u_i) = dolfin.TrialFunctions(V2) (v_r, v_i) = dolfin.TestFunctions(V2) dolfin.info(mesh) #surface integral definitions from boundaries ds = dolfin.Measure('ds', domain = mesh, subdomain_data = sub_domains) #volume regions dx_air = dolfin.Measure('dx', domain = mesh, subdomain_data = cf, subdomain_id = 1) dx_subst = dolfin.Measure('dx', domain = mesh, subdomain_data = cf, subdomain_id = 2) # with source and sink terms u0 = dolfin.Constant((0.0, 0.0, 0.0)) #PEC definition # The incident field sources (E and H-fields) h_src = dolfin.Expression(('-(x[1] - s) / (2.0 * pi * (pow(x[0], 2.0) + pow(x[1] - s,2.0)))', 'x[0] / (2.0 * pi *(pow(x[0],2.0) + pow(x[1] - s,2.0)))', 0.0), degree = 2, s = s1) e_src = dolfin.Expression(('x[0] / (2.0 * pi * (pow(x[0], 2.0) + pow(x[1] - s,2.0)))', 'x[1] / (2.0 * pi *(pow(x[0],2.0) + pow(x[1] - s,2.0)))', 0.0), degree = 2, s = s1) Rrad = dolfin.Expression(('sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2])'), degree = 2) #Boundary condition dictionary boundary_conditions = {0: {'PEC' : u0}, 1: {'InputBC': (h_src)}, 2: {'OutputBC': Rrad}} n = dolfin.FacetNormal(mesh) #Build PEC boundary conditions for real and imaginary parts bcs = [] for i in boundary_conditions: if 'PEC' in boundary_conditions[i]: bc = dolfin.DirichletBC(V2.sub(0), boundary_conditions[i]['PEC'], sub_domains, i) bcs.append(bc) bc = dolfin.DirichletBC(V2.sub(1), boundary_conditions[i]['PEC'], sub_domains, i) bcs.append(bc) # Build input BC source term and loading term integral_source = [] integrals_load =[] for i in boundary_conditions: if 'InputBC' in boundary_conditions[i]: r = boundary_conditions[i]['InputBC'] bb1 = 2.0 * (k0 * eta) * dolfin.inner(v_i, dolfin.cross(n, r)) * ds(i) #Factor of two from field equivalence principle integral_source.append(bb1) bb2 = dolfin.inner(dolfin.cross(n, v_i), dolfin.cross(n, u_r)) * k0 * np.sqrt(eps_c) * ds(i) integrals_load.append(bb2) bb2 = dolfin.inner(-dolfin.cross(n, v_r), dolfin.cross(n, u_i)) * k0 * np.sqrt(eps_c) * ds(i) integrals_load.append(bb2) for i in boundary_conditions: if 'OutputBC' in boundary_conditions[i]: r = boundary_conditions[i]['OutputBC'] bb2 = (dolfin.inner(dolfin.cross(n, v_i), dolfin.cross(n, u_r)) * k0 + 1.0 * dolfin.inner(dolfin.cross(n, v_i), dolfin.cross(n, u_i)) / r)* ds(i) integrals_load.append(bb2) bb2 = (dolfin.inner(-dolfin.cross(n, v_r), dolfin.cross(n, u_i)) * k0 + 1.0 * dolfin.inner(dolfin.cross(n, v_r), dolfin.cross(n, u_r)) / r)* ds(i) integrals_load.append(bb2) # for PMC, do nothing. Natural BC. a = (dolfin.inner(dolfin.curl(v_r), dolfin.curl(u_r)) + dolfin.inner(dolfin.curl(v_i), dolfin.curl(u_i)) - eps_c * k0 * k0 * (dolfin.inner(v_r, u_r) + dolfin.inner(v_i, u_i))) * dx_subst + (dolfin.inner(dolfin.curl(v_r), dolfin.curl(u_r)) + dolfin.inner(dolfin.curl(v_i), dolfin.curl(u_i)) - k0 * k0 * (dolfin.inner(v_r, u_r) + dolfin.inner(v_i, u_i))) * dx_air + sum(integrals_load) L = sum(integral_source) u1 = dolfin.Function(V2) vdim = u1.vector().size() print("Solution vector size =", vdim) dolfin.solve(a == L, u1, bcs, solver_parameters = {'linear_solver' : 'mumps'}) #Here we write files of the field solution for inspection u1_r, u1_i = u1.split(True) fp = dolfin.File("EField_r.pvd") fp << u1_r fp = dolfin.File("EField_i.pvd") fp << u1_i # Compute power relationships and reflection coefficient H = dolfin.interpolate(h_src, V) # Get input field P = dolfin.assemble((-dolfin.dot(u1_r,dolfin.cross(dolfin.curl(u1_i),n))+dolfin.dot(u1_i,dolfin.cross(dolfin.curl(u1_r),n))) * ds(2)) P_refl = dolfin.assemble((-dolfin.dot(u1_i,dolfin.cross(dolfin.curl(u1_r), n)) + dolfin.dot(u1_r, dolfin.cross(dolfin.curl(u1_i), n))) * ds(1)) P_inc = dolfin.assemble((dolfin.dot(H, H) * eta / (2.0 * np.sqrt(eps_c))) * ds(1)) print("Integrated power on port 2:", P/(2.0 * k0 * eta)) print("Incident power at port 1:", P_inc) print("Integrated reflected power on port 1:", P_inc - P_refl / (2.0 * k0 * eta)) #Reflection coefficient is returned as cost function rho_old = (P_inc - P_refl / (2.0 * k0 * eta)) / P_inc #Fraction of incident power reflected as objective function return rho_old
def setup_kinematics(self): from dolfin import cross, sqrt, dot if self.nsd == 2: # Get the dual basis self.Gsup1 = self.Gsub1 / dot(self.Gsub1, self.Gsub1) R = as_tensor([[0, -1], [1, 0]]) self.gsub1 = self.Gsub1 + self.u.dx(0) gradu = outer(self.u.dx(0), self.Gsup1) I = Identity(self.nsd) self.F = I + gradu self.C = dot(self.F.T, self.F) self.Gsub3 = dot(R, self.Gsub1) self.gsub3 = dot(R, self.gsub1) lmbda = sqrt( dot(self.gsub1, self.gsub1) / dot(self.Gsub1, self.Gsub1)) self.lambda1, self.lambda2 = lmbda, lmbda self.lambda3 = 1 / self.lambda1 elif self.nsd == 3: from dolfin import cross, sqrt, dot from fenicsmembranes.calculus_utils import contravariant_base_vector # Get the contravariant tangent basis self.Gsup1 = contravariant_base_vector(self.Gsub1, self.Gsub2) self.Gsup2 = contravariant_base_vector(self.Gsub2, self.Gsub1) # Reference normal self.Gsub3 = cross(self.Gsub1, self.Gsub2) self.Gsup3 = self.Gsub3 / dot(self.Gsub3, self.Gsub3) # Construct the covariant convective basis self.gsub1 = self.Gsub1 + self.u.dx(0) self.gsub2 = self.Gsub2 + self.u.dx(1) # Construct the contravariant convective basis self.gsup1 = contravariant_base_vector(self.gsub1, self.gsub2) self.gsup2 = contravariant_base_vector(self.gsub2, self.gsub1) # Deformed normal self.gsub3 = cross(self.gsub1, self.gsub2) self.gsup3 = self.gsub3 / dot(self.gsub3, self.gsub3) # Deformation gradient gradu = outer(self.u.dx(0), self.Gsup1) + outer( self.u.dx(1), self.Gsup2) I = Identity(self.nsd) self.F = I + gradu self.C = self.F.T * self.F # from initial to current # 3x2 deformation tensors # TODO: check/test self.F_0 = as_tensor([self.Gsub1, self.Gsub2]).T self.F_n = as_tensor([self.gsub1, self.gsub2]).T # 2x2 surface metrics self.C_0 = self.get_metric(self.Gsub1, self.Gsub2) self.C_0_sup = self.get_metric(self.Gsup1, self.Gsup2) self.C_n = self.get_metric(self.gsub1, self.gsub2) # TODO: not tested. do we need these? self.det_C_0 = dot(self.Gsub1, self.Gsub1) * dot( self.Gsub2, self.Gsub2) - dot(self.Gsub1, self.Gsub2)**2 self.det_C_n = dot(self.gsub1, self.gsub1) * dot( self.gsub2, self.gsub2) - dot(self.gsub1, self.gsub2)**2 self.lambda1, self.lambda2, self.lambda3 = self.get_lambdas() self.I1 = inner(inv(self.C_0), self.C_n) self.I2 = det(self.C_n) / det(self.C_0) else: raise Exception("Could not infer spatial dimension") # Unit normals self.J_A = sqrt(dot(self.Gsub3, self.Gsub3)) self.N = self.Gsub3 / self.J_A self.j_a = sqrt(dot(self.gsub3, self.gsub3)) self.n = self.gsub3 / self.j_a
def calcs(fname): data = pickle.load(open(fname+'.pickle')) mesh = dolfin.Mesh(data['meshfile']) elen = np.array([e.length() for e in dolfin.edges(mesh)]) ave_elen = np.average(elen) material_meshfn = dolfin.MeshFunction('uint', mesh, data['materialsfile']) V = dolfin.FunctionSpace(mesh, "Nedelec 1st kind H(curl)", data['order']) x = data['x'] x_r = as_dolfin_vector(x.real) x_i = as_dolfin_vector(x.imag) E_r = dolfin.Function(V, x_r) E_i = dolfin.Function(V, x_i) k0 = 2*np.pi*data['freq']/c0 n = V.cell().n ReS = (1/k0/Z0)*dolfin.dot(n, (dolfin.cross(E_r, -dolfin.curl(E_i)) + dolfin.cross(E_i, dolfin.curl(E_r))))*dolfin.ds energy_flux = dolfin.assemble(ReS) surface_flux = SurfaceFlux(V) surface_flux.set_dofs(x) surface_flux.set_k0(k0) energy_flux2 = surface_flux.calc_flux() assert(np.allclose(energy_flux, energy_flux2, rtol=1e-8, atol=1e-8)) def boundary(x, on_boundary): return on_boundary E_r_dirich = dolfin.DirichletBC(V, E_r, boundary) x_r_dirich = as_dolfin_vector(np.zeros(len(x))) E_r_dirich.apply(x_r_dirich) E_i_dirich = dolfin.DirichletBC(V, E_i, boundary) x_i_dirich = as_dolfin_vector(np.zeros(len(x))) E_i_dirich.apply(x_i_dirich) x_dirich = x_r_dirich.array() + 1j*x_i_dirich.array() emfunc = CalcEMFunctional(V) emfunc.set_k0(k0) cell_domains = dolfin.CellFunction('uint', mesh) cell_domains.set_all(0) cell_region = 1 boundary_cells = Geometry.BoundaryEdgeCells(mesh) boundary_cells.mark(cell_domains, cell_region) emfunc.set_cell_domains(cell_domains, cell_region) emfunc.set_E_dofs(x) emfunc.set_g_dofs(1j*x_dirich.conjugate()/k0/Z0) var_energy_flux = emfunc.calc_functional().conjugate() var_surf_flux = VariationalSurfaceFlux(V) var_surf_flux.set_dofs(x) var_surf_flux.set_k0(k0) var_energy_flux2 = var_surf_flux.calc_flux() assert(np.allclose(var_energy_flux, var_energy_flux2, rtol=1e-8, atol=1e-8)) complex_voltage = ComplexVoltageAlongLine(V) complex_voltage.set_dofs(x) volts = complex_voltage.calculate_voltage(*data['source_endpoints']) result = dict(h=ave_elen, order=order, volts=volts, sflux=energy_flux, vflux=var_energy_flux) print 'source power: ', volts*data['I'] print 'energy flux: ', energy_flux print 'var energy flux: ', var_energy_flux # print '|'.join(str(s) for s in ('', volts*data['I'], energy_flux, # var_energy_flux, '')) return result
def s_number(m, dx): s_density = df.dot(m, df.cross(df.Dx(m, 0), df.Dx(m, 1))) return 1/(4*np.pi) * df.assemble(s_density*dx)
+ time_step * c[0] * equation_coefficients[1] * a_operator(dv, del_v) \ - time_step * b_operator(del_v, dp) \ - time_step * b_operator(dv, del_p) rhs_momentum = a[1] * dot(v0, del_v) * dV \ - a[2] * dot(v00, del_v) * dV \ - time_step * b[1] * c_operator(v0, v0, del_v) \ + time_step * b[2] * c_operator(v00, v00, del_v) \ + time_step * equation_coefficients[2] * extrapolated_temperature * dot(gravity_vector, del_v) * dV if rotation == True: print "\nAdding rotation to the model...\n" if space_dim == 2: rhs_momentum += - time_step * equation_coefficients[0] * dot(cross_2D(extrapolated_velocity), del_v) * dV elif space_dim == 3: rotation_vector = dlfn.Constant((0., 0., 1.)) rhs_momentum += - time_step * equation_coefficients[0] * dot( dlfn.cross(rotation_vector, extrapolated_velocity), del_v) * dV # energy equation lhs_energy = a[0] * dot(dT, del_T) * dV \ + time_step * equation_coefficients[3] * a_operator(dT, del_T) rhs_energy = a[1] * dot(T0, del_T) * dV \ - a[2] * dot(T00, del_T) * dV \ - time_step * b[1] * c_operator(v0, T0, del_T) \ + time_step * b[2] * c_operator(v00, T00, del_T) lhs = lhs_momentum + lhs_energy #=============================================================================== # full problem lhs = lhs_momentum + lhs_energy rhs = rhs_momentum + rhs_energy if not use_assembler_method: # linear problem
This should be replaced in the parts of the code where dmdt is computed. """ import dolfin as df import time mesh = df.IntervalMesh(1000, 0, 1) S3 = df.VectorFunctionSpace(mesh, 'CG', 1, 3) a = df.Function(S3) b = df.Function(S3) a.assign(df.Constant((1, 0, 0))) # unit x vector b.assign(df.Constant((0, 1, 0))) # unit y vector alpha = 01 gamma = 2.11e5 m = df.Function(S3) m.assign(df.Constant((0, 0, 1))) Heff = df.Function(S3) Heff.assign(df.Constant((0, 0.3, 0.2))) dmdt = df.Function(S3) start = time.time() for i in range(1000): L = df.dot( -gamma / (1 + alpha * alpha) * df.cross(m, Heff) - alpha * gamma / (1 + alpha * alpha) * df.cross(m, df.cross(m, Heff)), df.TestFunction(S3)) * df.dP df.assemble(L, tensor=dmdt.vector()) stop = time.time() print 'Time:', stop - start
# define dmdt, test and trial functions dmdt = df.Function(V) v = df.TrialFunction(V) w = df.TestFunction(V) # define the exchange field # f_ex = df.Constant(2*A/(mu0*Ms)) # results for m_x at times t_array in mx_simulation = np.zeros(t_array.shape) for i, t in enumerate(t_array): mx_simulation[i] = m((0, 0, 0))[0] a = df.inner(df.Constant(alpha) * v + df.cross(m, v), w) * df.dx L = df.inner(gamma * Heff, w) * df.dx df.solve(a == L, dmdt) m += dmdt * df.Constant(dt) m = df.project(m / df.sqrt(df.dot(m, m)), V) ################### # Analytic solution ################### mx_analytic = macrospin_analytic_solution(alpha, gamma, H, t_array) ################### # Plot comparison. ################### plt.figure(figsize=(8, 5))
V = df.VectorFunctionSpace(mesh, "CG", 1, dim=3) u = df.TrialFunction(V) v = df.TestFunction(V) f = df.Function(V) g = df.Function(V) fxg = df.Function(V) f.assign(df.Constant((1, 0, 0))) g.assign(df.Constant((0, 1, 0))) # FINITE ELEMENT METHOD # but dP instead of dx (both work) a = df.dot(u, v) * df.dP L = df.dot(df.cross(f, g), v) * df.dP u = df.Function(V) start = time.time() for _ in xrange(1000): df.solve(a == L, u) stop = time.time() print "fem, delta = {} s.".format(stop - start) print u.vector().array() # LINEAR ALGEBRA FORMULATION A = df.assemble(a) b = df.Function(V) u = df.Function(V)