def _get_forces_as_point_sources(self): """ Creates 2 dicts of PointSources that can be applied to the assembled system. Applies filter_point_source to avoid forces being applied to already existing Dirichlet BC, since this would lead to an overdetermined system that cannot be solved. :return: Returns lists of PointSources TODO: get rid of this legacy code, dicts should be used for a PointSource, since they can provide the location of the PointSouce, as well. Even, inside the FEniCS user code. """ # PointSources are scalar valued, therefore we need an individual scalar valued PointSource for each dimension in a vector-valued setting # TODO: a vector valued PointSource would be more straightforward, but does not exist (as far as I know) x_forces = dict() # dict of PointSources for Forces in x direction y_forces = dict() # dict of PointSources for Forces in y direction vertices_x = self._coupling_mesh_vertices[0, :] vertices_y = self._coupling_mesh_vertices[1, :] for i in range(self._n_vertices): px, py = vertices_x[i], vertices_y[i] key = (px, py) x_forces[key] = PointSource(self._function_space.sub(0), Point(px, py), self._read_data[i, 0]) y_forces[key] = PointSource(self._function_space.sub(1), Point(px, py), self._read_data[i, 1]) # Avoid application of PointSource and Dirichlet boundary condition at the same point by filtering x_forces = filter_point_sources(x_forces, self._Dirichlet_Boundary) y_forces = filter_point_sources(y_forces, self._Dirichlet_Boundary) return x_forces.values(), y_forces.values() # don't return dictionary, but list of PointSources
def test_pointsource_vector_fs(mesh, point): """Tests point source when given constructor PointSource(V, point, mag) with a vector for a vector function space that isn't placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ rank = MPI.rank(mesh.mpi_comm()) V = VectorFunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(dot(Constant([0.0] * mesh.geometry().dim()), v) * dx) if rank == 0: ps = PointSource(V, point, 10.0) else: ps = PointSource(V, []) ps.apply(b) # Checks array sums to correct value b_sum = b.sum() assert round(b_sum - 10.0 * V.num_sub_spaces()) == 0 # Checks point source is added to correct part of the array v2d = vertex_to_dof_map(V) for v in vertices(mesh): if near(v.midpoint().distance(point), 0.0): for spc_idx in range(V.num_sub_spaces()): ind = v2d[v.index() * V.num_sub_spaces() + spc_idx] if ind < len(b.get_local()): assert np.round(b.get_local()[ind] - 10.0) == 0
def test_pointsource_matrix_second_constructor(mesh, point): """Tests point source when given different constructor PointSource(V1, V2, point, mag) with a matrix and when placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. Currently only implemented if V1=V2. """ V1 = FunctionSpace(mesh, "CG", 1) V2 = FunctionSpace(mesh, "CG", 1) rank = MPI.rank(mesh.mpi_comm()) u, v = TrialFunction(V1), TestFunction(V2) w = Function(V1) A = assemble(Constant(0.0) * u * v * dx) if rank == 0: ps = PointSource(V1, V2, point, 10.0) else: ps = PointSource(V1, V2, []) ps.apply(A) # Checks array sums to correct value a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 10.0) == 0 # Checks point source is added to correct part of the array A.get_diagonal(w.vector()) v2d = vertex_to_dof_map(V1) for v in vertices(mesh): if near(v.midpoint().distance(point), 0.0): ind = v2d[v.index()] if ind < len(A.array()): assert np.round(w.vector()[ind] - 10.0) == 0
def test_pointsource_mixed_space(mesh, point): """Tests point source when given constructor PointSource(V, point, mag) with a vector for a mixed function space that isn't placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ rank = MPI.rank(mesh.mpi_comm()) ele1 = FiniteElement("CG", mesh.ufl_cell(), 1) ele2 = FiniteElement("DG", mesh.ufl_cell(), 2) ele3 = VectorElement("CG", mesh.ufl_cell(), 2) V = FunctionSpace(mesh, MixedElement([ele1, ele2, ele3])) value_dimension = V.element().value_dimension(0) v = TestFunction(V) b = assemble(dot(Constant([0.0] * value_dimension), v) * dx) if rank == 0: ps = PointSource(V, point, 10.0) else: ps = PointSource(V, []) ps.apply(b) # Checks array sums to correct value b_sum = b.sum() assert round(b_sum - 10.0 * value_dimension) == 0
def test_multi_ps_matrix(mesh): """Tests point source PointSource(V, source) for mulitple point sources applied to a matrix for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ c_ids = [0, 1, 2] rank = MPI.rank(mesh.mpi_comm()) V = VectorFunctionSpace(mesh, "CG", 1, dim=2) u, v = TrialFunction(V), TestFunction(V) A = assemble(Constant(0.0) * dot(u, v) * dx) source = [] if rank == 0: for c_id in c_ids: cell = Cell(mesh, c_id) point = cell.midpoint() source.append((point, 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks b sums to correct value a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 2 * len(c_ids) * 10) == 0
def test_multi_ps_vector(mesh): """Tests point source PointSource(V, source) for mulitple point sources applied to a vector for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ c_ids = [0, 1, 2] rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) source = [] if rank == 0: for c_id in c_ids: cell = Cell(mesh, c_id) point = cell.midpoint() source.append((point, 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value b_sum = b.sum() assert round(b_sum - len(c_ids) * 10.0) == 0
def add_points(self, src_loc): """ Create and add more point sources """ for pts in self.src_loc: self.src_loc.append(pts) delta = PointSource(self.V, self.list2point(pts)) bs = self.b.copy() delta.apply(bs) self.PtSrc.append(self._PointSourcecorrection(bs))
def _modify_linear_equation(self, x, y, z): logger.debug( 'Defining point source to compensate boundary flux...') point = Point(0, 0, 0) delta = PointSource(self._fm.function_space, point, -self._boundary_flux()) logger.debug('Done. Applying changes to the vector...') delta.apply(self._known_terms) logger.debug('Done.')
def main_slice_fem(mesh, subdomains, boundaries, src_pos, snk_pos): sigma_ROI = Constant(params.sigma_roi) sigma_SLICE = Constant(params.sigma_slice) sigma_SALINE = Constant(params.sigma_saline) sigma_AIR = Constant(0.) V = FunctionSpace(mesh, "CG", 2) v = TestFunction(V) u = TrialFunction(V) phi = Function(V) dx = Measure("dx")(subdomain_data=subdomains) ds = Measure("ds")(subdomain_data=boundaries) a = inner(sigma_ROI * grad(u), grad(v))*dx(params.roivol) + \ inner(sigma_SLICE * grad(u), grad(v))*dx(params.slicevol) + \ inner(sigma_SALINE * grad(u), grad(v))*dx(params.salinevol) L = Constant(0) * v * dx A = assemble(a) b = assemble(L) x_pos, y_pos, z_pos = src_pos point = Point(x_pos, y_pos, z_pos) delta = PointSource(V, point, 1.) delta.apply(b) x_pos, y_pos, z_pos = snk_pos point1 = Point(x_pos, y_pos, z_pos) delta1 = PointSource(V, point1, -1.) delta1.apply(b) solver = KrylovSolver("cg", "ilu") solver.parameters["maximum_iterations"] = 1000 solver.parameters["absolute_tolerance"] = 1E-8 solver.parameters["monitor_convergence"] = True info(solver.parameters, True) # set_log_level(PROGRESS) does not work in fenics 2018.1.0 solver.solve(A, phi.vector(), b) ele_pos_list = params.ele_coords vals = extract_pots(phi, ele_pos_list) # np.save(os.path.join('results', save_as), vals) return vals
def test_point_outside(): """Tests point source fails if given a point outside the domain.""" mesh = UnitIntervalMesh(10) point = Point(1.2) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) assemble(Constant(0.0) * v * dx) # Runtime Error is only produced on one process which causes the # whole function to fail but makes this test hang in parallel. with pytest.raises(RuntimeError): PointSource(V, point, 10.0)
def gaussian_distribution(mb, mu, sigma, function=None, lumping=True, nsteps=100): "Gaussian distribution via heat equation" tend = 0.5 * sigma**2 dt = Constant(tend / nsteps, name="smooth") # prepare the problem P1e = FiniteElement("CG", mb.ufl_cell(), 1) Ve = FunctionSpace(mb, P1e) u, v = TrialFunction(Ve), TestFunction(Ve) uold = Function(Ve) if lumping: # diffusion K = assemble(dt * inner(grad(u), grad(v)) * dx) # we use mass lumping to avoid negative values Md = assemble(action(u * v * dx, Constant(1.0))) # full matrix (divide my mass) M = Matrix(K) M.zero() M.set_diagonal(Md) A = M + K else: a = u * v * dx + dt * inner(grad(u), grad(v)) * dx L = uold * v * dx A = assemble(a) # initial conditions dist = function or Function(Ve) dist.vector().zero() PointSource(Ve, mu, 1.0).apply(dist.vector()) # iterations for t in range(nsteps): uold.assign(dist) if lumping: solve(A, dist.vector(), M * uold.vector()) else: b = assemble(L) solve(A, dist.vector(), b) # normalize area = assemble(dist * dx) dist.vector()[:] /= area if function is None: return dist
def test_pointsource_vector(mesh): """Tests point source when given constructor PointSource(V, point, mag) with a vector that isn't placed at a node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor """ cell = Cell(mesh, 0) point = cell.midpoint() rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) if rank == 0: ps = PointSource(V, point, 10.0) else: ps = PointSource(V, []) ps.apply(b) # Checks array sums to correct value b_sum = b.sum() assert round(b_sum - 10.0) == 0
def __init__(self, V, src_loc): """ Inputs: V = FunctionSpace src_loc = iterable that returns coordinates of the point """ self.V = V self.src_loc = src_loc test = TestFunction(self.V) f = Constant('0') L = f * test * dx self.b = assemble(L) self.PtSrc = [] for pts in self.src_loc: delta = PointSource(self.V, self.list2point(pts)) bs = self.b.copy() delta.apply(bs) self.PtSrc.append(self._PointSourcecorrection(bs))
def test_multi_ps_matrix_node_vector_fs(mesh): """Tests point source applied to a matrix with given constructor PointSource(V, source) and a vector function space when points placed at 3 vertices for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ point = [0.0, 0.5, 1.0] rank = MPI.rank(mesh.mpi_comm()) V = VectorFunctionSpace(mesh, "CG", 1, dim=2) u, v = TrialFunction(V), TestFunction(V) w = Function(V) A = assemble(Constant(0.0) * dot(u, v) * dx) dim = mesh.geometry().dim() source = [] point_coords = np.zeros(dim) for p in point: for i in range(dim): point_coords[i - 1] = p if rank == 0: source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks array sums to correct value A.get_diagonal(w.vector()) a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - 2 * len(point) * 10) == 0 # Check if coordinates are in portion of mesh and if so check that # diagonal components sum to the correct value. mesh_coords = V.tabulate_dof_coordinates() for p in point: for i in range(dim): point_coords[i] = p j = 0 for i in range(len(mesh_coords) // (dim)): mesh_coords_check = mesh_coords[j:j + dim - 1] if np.array_equal(point_coords, mesh_coords_check) is True: assert np.round(w.vector()[j // (dim)] - 10.0) == 0.0 j += dim
def test_multi_ps_vector_node_local(mesh): """Tests point source when given constructor PointSource(V, V, point, mag) with a matrix when points placed at 3 node for 1D, 2D and 3D. Local points given to constructor. """ V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) source = [] point_coords = mesh.coordinates()[0] source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value size = MPI.size(mesh.mpi_comm()) b_sum = b.sum() assert round(b_sum - size * 10.0) == 0
def test_multi_ps_vector_node(mesh): """Tests point source when given constructor PointSource(V, V, point, mag) with a matrix when points placed at 3 node for 1D, 2D and 3D. Global points given to constructor from rank 0 processor. """ point = [0.0, 0.5, 1.0] dim = mesh.geometry().dim() rank = MPI.rank(mesh.mpi_comm()) V = FunctionSpace(mesh, "CG", 1) v = TestFunction(V) b = assemble(Constant(0.0) * v * dx) source = [] point_coords = np.zeros(dim) for p in point: for i in range(dim): point_coords[i - 1] = p if rank == 0: source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(b) # Checks b sums to correct value b_sum = b.sum() assert round(b_sum - len(point) * 10.0) == 0 # Checks values added to correct part of vector mesh_coords = V.tabulate_dof_coordinates() for p in point: for i in range(dim): point_coords[i] = p j = 0 for i in range(len(mesh_coords) // (dim)): mesh_coords_check = mesh_coords[j:j + dim - 1] if np.array_equal(point_coords, mesh_coords_check) is True: assert np.round(b.array()[j // (dim)] - 10.0) == 0.0 j += dim
def test_multi_ps_matrix_node_local(mesh): """Tests point source when given constructor PointSource(V, V, point, mag) with a matrix when points placed at 3 node for 1D, 2D and 3D. Local points given to constructor. """ V = FunctionSpace(mesh, "CG", 1) u, v = TrialFunction(V), TestFunction(V) w = Function(V) A = assemble(Constant(0.0) * u * v * dx) source = [] point_coords = mesh.coordinates()[0] source.append((Point(point_coords), 10.0)) ps = PointSource(V, source) ps.apply(A) # Checks matrix sums to correct value. A.get_diagonal(w.vector()) size = MPI.size(mesh.mpi_comm()) a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array())) assert round(a_sum - size * 10.0) == 0
from dolfin import UnitSquareMesh, FunctionSpace, TestFunction, TrialFunction,\ Constant, Expression, assemble, dx, Point, PointSource, plot, interactive,\ inner, nabla_grad, Function, solve, MPI, mpi_comm_world import numpy as np from fenicstools.sourceterms import PointSources mycomm = mpi_comm_world() myrank = MPI.rank(mycomm) mesh = UnitSquareMesh(2, 2) V = FunctionSpace(mesh, 'Lagrange', 1) trial = TrialFunction(V) test = TestFunction(V) f0 = Constant('0') L0 = f0 * test * dx b = assemble(L0) P = Point(0.1, 0.5) delta = PointSource(V, P, 1.0) delta.apply(b) myown = PointSources(V, [[0.1, 0.5], [0.9, 0.5]]) print 'p{}: max(PointSource)={}, max(PointSources[0])={}, max(PointSources[1])={}'.format(\ myrank, max(abs(b.array())), max(abs(myown[0].array())), max(abs(myown[1].array())))