def __init__(self, mesh, num, denom, method="CR"): """ Assemble matrices and cache matrices. """ self.V = FunctionSpace(mesh, method, 1) # save coordinates of DOFs self.dofs = np.reshape(self.V.dofmap().tabulate_all_coordinates(mesh), (-1, 2)) u = TrialFunction(self.V) v = TestFunction(self.V) self.boundary = MeshFunction("size_t", mesh, 1) # assemble matrices a = inner(grad(u), grad(v)) * dx b = u * v * dx self.A = uBLASSparseMatrix() self.A = assemble(a, tensor=self.A) self.A.compress() self.B = uBLASSparseMatrix() self.B = assemble(b, tensor=self.B) self.B.compress() size = mesh.size(2) # cell diameter calculation self.H2 = (num ** 2 + denom ** 2) * 1.0 / size # print "Theoretical cell diameter: ", sqrt(self.H2) # print "FEniCS calculated: ", mesh.hmax() # Matrices have rational entries. We can rescale to get integers # and save as scipy matrices scaleB = 6.0*size/num/denom self.scaleB = scaleB self.B *= scaleB r, c, val = self.B.data() val = np.round(val) self.B = sps.csr_matrix((val, c, r)) # check if B is diagonal assert len(self.B.diagonal()) == self.B.nnz # find B inverse self.Binv = sps.csr_matrix((1.0/val, c, r)) scaleA = 1.0*num*denom/2 self.scaleA = scaleA self.A *= scaleA r, c, val = self.A.data() self.A = sps.csr_matrix((np.round(val), c, r)) self.scale = scaleA/scaleB print 'scaling A by: ', scaleA print 'scaling B by: ', scaleB print 'eigenvalues scale by:', self.scale
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()
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 from numpy import intc def to_scipy_csr(mat, dtype=None, imagify=False): (row,col,data) = mat.data() # get sparse data col = intc(col) row = intc(row)
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 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