Beispiel #1
0
    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
Beispiel #2
0
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()
Beispiel #3
0
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)
Beispiel #4
0
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()
Beispiel #5
0
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