def convert_meshfunctions_to_submesh(mesh, submesh, meshfunctions_on_mesh): assert meshfunctions_on_mesh is None or (isinstance( meshfunctions_on_mesh, list) and len(meshfunctions_on_mesh) > 0) if meshfunctions_on_mesh is None: return None meshfunctions_on_submesh = list() # Create submesh subdomains for mesh_subdomain in meshfunctions_on_mesh: submesh_subdomain = MeshFunction("size_t", submesh, mesh_subdomain.dim()) submesh_subdomain.set_all(0) assert submesh_subdomain.dim() in (submesh.topology().dim(), submesh.topology().dim() - 1) if submesh_subdomain.dim() == submesh.topology().dim(): for submesh_cell in cells(submesh): submesh_subdomain.array()[ submesh_cell.index()] = mesh_subdomain.array()[ submesh.submesh_to_mesh_cell_local_indices[ submesh_cell.index()]] elif submesh_subdomain.dim() == submesh.topology().dim() - 1: for submesh_facet in facets(submesh): submesh_subdomain.array()[ submesh_facet.index()] = mesh_subdomain.array()[ submesh.submesh_to_mesh_facet_local_indices[ submesh_facet.index()]] else: # impossible to arrive here anyway, thanks to the assert raise TypeError( "Invalid arguments in convert_meshfunctions_to_submesh.") meshfunctions_on_submesh.append(submesh_subdomain) return meshfunctions_on_submesh
def boundaries(mesh): boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0) for f in facets(mesh): boundaries.array()[f.index()] = 0 for v in vertices(f): boundaries.array()[f.index()] += v.global_index() return boundaries
def test_convert_diffpack_2d(self): from dolfin import Mesh, MPI, MeshFunction fname = os.path.join(os.path.dirname(__file__), "data", "diffpack_tri") dfname = fname + ".xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.diffpack2xml(fname + ".grid", dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) self.assertEqual(mesh.num_vertices(), 41) self.assertEqual(mesh.num_cells(), 64) self.assertEqual(len(mesh.domains().markers(2)), 64) mf_basename = dfname.replace(".xml", "_marker_%d.xml") for marker, num in [(1, 10), (2, 5), (3, 5)]: mf_name = mf_basename % marker mf = MeshFunction("size_t", mesh, mf_name) self.assertEqual(sum(mf.array() == marker), num) os.unlink(mf_name) # Clean up os.unlink(dfname)
def mplot_cellfunction( cell_function: df.MeshFunction) -> Tuple[plt.Figure, Any]: """Return a pseudocolor plot of an unstructured triangular grid.""" fig, ax = plt.subplots(1) tri = mesh2triang(cell_function.mesh()) ax.tripcolor(tri, facecolors=cell_function.array()) return fig, ax
def test_convert_diffpack(self): from dolfin import Mesh, MPI, MeshFunction, mpi_comm_world if MPI.size(mpi_comm_world()) != 1: return fname = os.path.join("data", "diffpack_tet") dfname = fname + ".xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.diffpack2xml(fname + ".grid", dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) self.assertEqual(mesh.num_vertices(), 27) self.assertEqual(mesh.num_cells(), 48) self.assertEqual(len(mesh.domains().markers(3)), 48) self.assertEqual(len(mesh.domains().markers(2)), 16) mf_basename = dfname.replace(".xml", "_marker_%d.xml") for marker, num in [(3, 9), (6, 9), (7, 3), (8, 1)]: mf_name = mf_basename % marker mf = MeshFunction("size_t", mesh, mf_name) self.assertEqual(sum(mf.array() == marker), num) os.unlink(mf_name) # Clean up os.unlink(dfname)
def test_mesh_function_assign_2D_cells(): mesh = UnitSquareMesh(MPI.comm_world, 3, 3) ncells = mesh.num_cells() f = MeshFunction("int", mesh, mesh.topology.dim, 0) for cell in Cells(mesh): f[cell] = ncells - cell.index() g = MeshValueCollection("int", mesh, 2) g.assign(f) assert ncells == f.size() assert ncells == g.size() f2 = MeshFunction("int", mesh, g, 0) for cell in Cells(mesh): value = ncells - cell.index() assert value == g.get_value(cell.index(), 0) assert f2[cell] == g.get_value(cell.index(), 0) h = MeshValueCollection("int", mesh, 2) global_indices = mesh.topology.global_indices(2) ncells_global = mesh.num_entities_global(2) for cell in Cells(mesh): if global_indices[cell.index()] in [5, 8, 10]: continue value = ncells_global - global_indices[cell.index()] h.set_value(cell.index(), int(value)) f3 = MeshFunction("int", mesh, h, 0) values = f3.array() values[values > ncells_global] = 0. assert MPI.sum(mesh.mpi_comm(), values.sum() * 1.0) == 140.
def test_convert_diffpack_2d(self): from dolfin import Mesh, MPI, MeshFunction, mpi_comm_world fname = os.path.join(os.path.dirname(__file__), "data", "diffpack_tri") dfname = fname+".xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.diffpack2xml(fname+".grid", dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) self.assertEqual(mesh.num_vertices(), 41) self.assertEqual(mesh.num_cells(), 64) self.assertEqual(len(mesh.domains().markers(2)), 64) mf_basename = dfname.replace(".xml", "_marker_%d.xml") for marker, num in [(1,10), (2,5), (3,5)]: mf_name = mf_basename % marker mf = MeshFunction("size_t", mesh, mf_name) self.assertEqual(sum(mf.array()==marker), num) os.unlink(mf_name) # Clean up os.unlink(dfname)
def create(mesh, domain_ids, invert=False): """ Creates a wrapped mesh from a super mesh for a given collection of domain IDs. *Arguments* mesh (:class:`dolfin.Mesh`) The mesh. domain_ids (:class:`[int]`) List of domain IDs invert (:class:`bool`) Invert list of domain IDs *Returns* :class:`WrappedMesh` The wrapped mesh """ if invert or isinstance(domain_ids, list) or isinstance(domain_ids, tuple): if isinstance(domain_ids, int): domain_ids = (domain_ids,) subdomains = MeshFunction('size_t', mesh, 3, mesh.domains()) combined_subdomains = CellFunction("size_t", mesh, 0) for domain_id in domain_ids: combined_subdomains.array()[subdomains.array() == domain_id] = 1 submesh = SubMesh(mesh, combined_subdomains, 0 if invert else 1) else: submesh = SubMesh(mesh, domain_ids) submesh.__class__ = WrappedMesh submesh._init(mesh) return submesh
def dP(self, domain = "all"): """ Convenience wrapper for integral-point measure. If the mesh does not contain any cell domains, the measure for the whole mesh is returned. *Arguments* domain (:class:`string` / :class:`int`) name or ID of domain *Returns* :class:`dolfin:Measure` the measure """ if not self.mesh_has_domains(): return Measure('dP', self.mesh) if not self._dP.has_key(domain): v = TestFunction(self.FunctionSpace()) values = assemble(v*self.dx(domain)).array() # TODO improve this? markers = ((np.sign(np.ceil(values) - 0.5) + 1.0) / 2.0).astype(np.uint64) vertex_domains = MeshFunction('size_t', self.mesh, 0) vertex_domains.array()[:] = markers self._dP[domain] = Measure('dP', self.mesh)[vertex_domains](1) return self._dP[domain]
def test_convert_diffpack(self): from dolfin import Mesh, MPI, MeshFunction if MPI.num_processes() != 1: return fname = os.path.join("data", "diffpack_tet") dfname = fname+".xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.diffpack2xml(fname+".grid", dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) self.assertEqual(mesh.num_vertices(), 27) self.assertEqual(mesh.num_cells(), 48) self.assertEqual(mesh.domains().markers(3).size(), 48) self.assertEqual(mesh.domains().markers(2).size(), 16) mf_basename = dfname.replace(".xml", "_marker_%d.xml") for marker, num in [(3, 9), (6, 9), (7, 3), (8, 1)]: mf_name = mf_basename % marker mf = MeshFunction("uint", mesh, mf_name) self.assertEqual(sum(mf.array()==marker), num) os.unlink(mf_name) # Clean up os.unlink(dfname)
def load_data(mesh, mesh_f, dim, data): ''' Represent mesh_f over dim entities of mesh as collection of vertices. Can have mesh as mesh function or (h5_file, data_set) ''' try: h5_file, data_set = mesh_f mf = MeshFunction('size_t', mesh, dim, 0) h5_file.read(mf, data_set) except ValueError: mf = mesh_f data_set = '%d dim entites' % mf.dim() # Mapf for encoding entities as vertices mesh.init(dim, 0) e2v = mesh.topology()(dim, 0) tags = set(mf.array()) # Don't encode zero - we initialize to it if 0 in tags: tags.remove(0) info('%s evolves tags %r' % (data_set, tags)) for tag in tags: data[(dim, tag)] = np.array([e2v(e.index()) for e in SubsetIterator(mf, tag)], dtype='uintp') return data
def create(mesh, domain_ids, invert=False): """ Creates a wrapped mesh from a super mesh for a given collection of domain IDs. *Arguments* mesh (:class:`dolfin.Mesh`) The mesh. domain_ids (:class:`[int]`) List of domain IDs invert (:class:`bool`) Invert list of domain IDs *Returns* :class:`WrappedMesh` The wrapped mesh """ if invert or isinstance(domain_ids, list) or isinstance( domain_ids, tuple): if isinstance(domain_ids, int): domain_ids = (domain_ids, ) subdomains = MeshFunction('size_t', mesh, 3, mesh.domains()) combined_subdomains = CellFunction("size_t", mesh, 0) for domain_id in domain_ids: combined_subdomains.array()[subdomains.array() == domain_id] = 1 submesh = SubMesh(mesh, combined_subdomains, 0 if invert else 1) else: submesh = SubMesh(mesh, domain_ids) submesh.__class__ = WrappedMesh submesh._init(mesh) return submesh
def transfer_markers(mesh, f, markers=None): ''' Let mesh be a mesh embedded into mesh(f). Transfer all markers from f to the mesh. ''' # Check that we are embdded parent_mesh = f.mesh() assert parent_mesh.id() in mesh.parent_entity_map # If we are embedded then the transfer is only possible of the lower # dimensional entities assert f.dim() < mesh.topology().dim() cdim = mesh.topology().dim() edim = f.dim() # That of entities # All not zeros if markers is None: markers = set(f.array()) - set((0, )) # The idea is to look up mesh.entities in parent by vertex ids child_parent_vertex = mesh.parent_entity_map[parent_mesh.id()][0] child_parent_cell = mesh.parent_entity_map[parent_mesh.id()][cdim] # child_entity -> as vertex in child -> as vertex in parent # \- connected child cells -> parent -> cells -> parent cell entities as vertex # Entity in terms of vertices mesh.init(edim, 0) ch_e2v = mesh.topology()(edim, 0) # The connected cell; we already have child to parent for cell mesh.init(edim, cdim) ch_e2c = mesh.topology()(edim, cdim) # Then parent entities parent_mesh.init(cdim, edim) p_c2e = parent_mesh.topology()(cdim, edim) # In terms of vertices parent_mesh.init(edim, 0) p_e2v = parent_mesh.topology()(edim, 0) child_f = MeshFunction('size_t', mesh, edim, 0) ch_values = child_f.array() # Assignee p_values = f.array() for entity in range(len(ch_values)): # As vertices in parent e_as_vertex = set(child_parent_vertex[v] for v in ch_e2v(entity)) ch_cells = iter(ch_e2c(entity)) # One of the cells entities should match for ch_cell in ch_cells: for p_entity in p_c2e(child_parent_cell[ch_cell]): found = p_values[p_entity] in markers and set(p_e2v(p_entity)) == e_as_vertex # Can assign color if found: break if found: ch_values[entity] = p_values[p_entity] break return child_f
def __init__( self, time: df.Constant, mesh: df.Mesh, cell_model: CellModel, parameters: CoupledODESolverParameters, cell_function: df.MeshFunction, ) -> None: """Initialise parameters. NB! Keep I_s for compatibility""" # Store input self._mesh = mesh self._time = time self._model = cell_model # FIXME: For initial conditions and num states # Extract some information from cell model self._num_states = self._model.num_states() self._parameters = parameters _cell_function_tags = set(cell_function.array()) if not set(self._parameters.valid_cell_tags) <= _cell_function_tags: msg = "Valid cell tag not found in cell function. Expected {}, for {}." raise ValueError( msg.format(set(self._parameters.valid_cell_tags), _cell_function_tags)) valid_cell_tags = self._parameters.valid_cell_tags # Create (vector) function space for potential + states self._function_space_VS = df.VectorFunctionSpace(self._mesh, "CG", 1, dim=self._num_states + 1) # Initialize solution field self.vs_prev = df.Function(self._function_space_VS, name="vs_prev") self.vs = df.Function(self._function_space_VS, name="vs") self.ode_module = load_module( "LatticeODESolver", recompile=self._parameters.reload_extension_modules, verbose=self._parameters.reload_extension_modules) self.ode_solver = self.ode_module.LatticeODESolver( self._function_space_VS._cpp_object, VectorSizet(cell_function.array()), self._parameters.parameter_map)
def refineMesh(m, l, u): cell_markers = MeshFunction('bool', m, 1) cell_markers.set_all(False) coords = m.coordinates() midpoints = 0.5 * (coords[:-1] + coords[1:]) ref_idx = np.where((midpoints > l) & (midpoints < u))[0] cell_markers.array()[ref_idx] = True m = refine(m, cell_markers) return m
def test_ale(): # Create some mesh mesh = UnitSquareMesh(4, 5) # Make some cell function # FIXME: Initialization by array indexing is probably # not a good way for parallel test cellfunc = MeshFunction('size_t', mesh, mesh.topology().dim()) cellfunc.array()[0:4] = 0 cellfunc.array()[4:] = 1 # Create submeshes - this does not work in parallel submesh0 = SubMesh(mesh, cellfunc, 0) submesh1 = SubMesh(mesh, cellfunc, 1) # Move submesh0 disp = Constant(("0.1", "-0.1")) ALE.move(submesh0, disp) # Move and smooth submesh1 accordignly ALE.move(submesh1, submesh0) # Move mesh accordingly parent_vertex_indices_0 = \ submesh0.data().array('parent_vertex_indices', 0) parent_vertex_indices_1 = \ submesh1.data().array('parent_vertex_indices', 0) mesh.coordinates()[parent_vertex_indices_0[:]] = \ submesh0.coordinates()[:] mesh.coordinates()[parent_vertex_indices_1[:]] = \ submesh1.coordinates()[:] # If test passes here then it is probably working # Check for cell quality for sure magic_number = 0.28 rmin = MeshQuality.radius_ratio_min_max(mesh)[0] assert rmin > magic_number
def check_boundaries_are_marked( mesh: df.Mesh, ffun: df.MeshFunction, markers: Dict[str, int], boundaries: List[str], ) -> None: # Check that all boundary faces are marked num_boundary_facets = df.BoundaryMesh(mesh, "exterior").num_cells() if num_boundary_facets != sum( [np.sum(ffun.array() == markers[boundary]) for boundary in boundaries], ): raise RuntimeError( ("Not all boundary faces are marked correctly. Make sure all " "boundary facets are marked as: {}" "").format(", ".join( ["{} = {}".format(k, v) for k, v in markers.items()])), )
def _init_for_append_if_needed(self): # Initialize dof to cells map only the first time if len(self.dof_to_cells) == 0: self.dof_to_cells = list() # of size len(V) for (component, V_component) in enumerate(self.V): dof_to_cells = self._compute_dof_to_cells(V_component) # Debugging log(DEBUG, "DOFs to cells map (component " + str(component) + ") on processor " + str(self.mpi_comm.rank) + ":") for (global_dof, cells_) in dof_to_cells.items(): log(DEBUG, "\t" + str(global_dof) + ": " + str([cell.global_index() for cell in cells_])) # Add to storage self.dof_to_cells.append(dof_to_cells) self.dof_to_cells = tuple(self.dof_to_cells) # Initialize cells marker N = self._get_next_index() reduced_mesh_markers = MeshFunction("bool", self.mesh, self.mesh.topology().dim()) reduced_mesh_markers.set_all(False) if N > 0: reduced_mesh_markers.array()[:] = self.reduced_mesh_markers[N - 1].array() assert N not in self.reduced_mesh_markers self.reduced_mesh_markers[N] = reduced_mesh_markers
def derived_bcs(V, original_bcs, u_): new_bcs = [] # Check first if user has declared subdomains subdomain = original_bcs[0].user_sub_domain() if subdomain is None: mesh = V.mesh() ff = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0) for i, bc in enumerate(original_bcs): bc.apply(u_[0].vector()) # Need to initialize bc m = bc.markers() # Get facet indices of boundary ff.array()[m] = i + 1 new_bcs.append(DirichletBC(V, Constant(0), ff, i + 1)) else: for i, bc in enumerate(original_bcs): subdomain = bc.user_sub_domain() new_bcs.append(DirichletBC(V, Constant(0), subdomain)) return new_bcs
def load_data(mesh, h5_file, data_set, dim, data): ''' Fill the data dictionary with data_set representing mesh function with dim over mesh read from h5_file according to key spec expected by tiling algorithm. ''' mf = MeshFunction('size_t', mesh, dim, 0) h5_file.read(mf, data_set) # Data to evolve mesh.init(dim, 0) e2v = tile.topology()(dim, 0) tags = set(mf.array()) # Don't evolve zero - we initialize to it if 0 in tags: tags.remove(0) info('%s evolves tags %r' % (data_set, tags)) for tag in tags: data[(dim, tag)] = np.array([e2v(e.index()) for e in SubsetIterator(mf, tag)], dtype='uintp') return data
def create_boundary(self, domains, interior, exterior): """ mark commmon facets between two domains with 1 and a return FacetFunction""" edges = MeshFunction("size_t", domains.mesh(), domains.mesh().topology().dim() - 1) edges.set_all(0) # count number of boundary facets Nfacets = 0 for facet in facets(domains.mesh()): cells = facet.entities(2) if facet.exterior() == False: cell1 = cells[0] cell2 = cells[1] domain1 = domains.array()[cells[0]] domain2 = domains.array()[cells[1]] if (sorted([domain1, domain2]) == sorted([interior, exterior])): idx = facet.index() edges.array()[idx] = True Nfacets += 1 return (edges, Nfacets)
def les_setup(u_, mesh, assemble_matrix, CG1Function, nut_krylov_solver, bcs, **NS_namespace): """ Set up for solving the Germano Dynamic LES model applying Lagrangian Averaging. """ # Create function spaces CG1 = FunctionSpace(mesh, "CG", 1) p, q = TrialFunction(CG1), TestFunction(CG1) dim = mesh.geometry().dim() # Define delta and project delta**2 to CG1 delta = pow(CellVolume(mesh), 1. / dim) delta_CG1_sq = project(delta, CG1) delta_CG1_sq.vector().set_local(delta_CG1_sq.vector().array()**2) delta_CG1_sq.vector().apply("insert") # Define nut_ Sij = sym(grad(u_)) magS = sqrt(2 * inner(Sij, Sij)) Cs = Function(CG1) nut_form = Cs**2 * delta**2 * magS # Create nut_ BCs ff = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0) bcs_nut = [] for i, bc in enumerate(bcs['u0']): bc.apply(u_[0].vector()) # Need to initialize bc m = bc.markers() # Get facet indices of boundary ff.array()[m] = i + 1 bcs_nut.append(DirichletBC(CG1, Constant(0), ff, i + 1)) nut_ = CG1Function(nut_form, mesh, method=nut_krylov_solver, bcs=bcs_nut, bounded=True, name="nut") # Create functions for holding the different velocities u_CG1 = as_vector([Function(CG1) for i in range(dim)]) u_filtered = as_vector([Function(CG1) for i in range(dim)]) dummy = Function(CG1) ll = LagrangeInterpolator() # Assemble required filter matrices and functions G_under = Function(CG1, assemble(TestFunction(CG1) * dx)) G_under.vector().set_local(1. / G_under.vector().array()) G_under.vector().apply("insert") G_matr = assemble(inner(p, q) * dx) # Set up functions for Lij and Mij Lij = [Function(CG1) for i in range(dim * dim)] Mij = [Function(CG1) for i in range(dim * dim)] # Check if case is 2D or 3D and set up uiuj product pairs and # Sij forms, assemble required matrices Sijcomps = [Function(CG1) for i in range(dim * dim)] Sijfcomps = [Function(CG1) for i in range(dim * dim)] # Assemble some required matrices for solving for rate of strain terms Sijmats = [assemble_matrix(p.dx(i) * q * dx) for i in range(dim)] if dim == 3: tensdim = 6 uiuj_pairs = ((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2)) else: tensdim = 3 uiuj_pairs = ((0, 0), (0, 1), (1, 1)) # Set up Lagrange functions JLM = Function(CG1) JLM.vector()[:] += 1E-32 JMM = Function(CG1) JMM.vector()[:] += 1 return dict(Sij=Sij, nut_form=nut_form, nut_=nut_, delta=delta, bcs_nut=bcs_nut, delta_CG1_sq=delta_CG1_sq, CG1=CG1, Cs=Cs, u_CG1=u_CG1, u_filtered=u_filtered, ll=ll, Lij=Lij, Mij=Mij, Sijcomps=Sijcomps, Sijfcomps=Sijfcomps, Sijmats=Sijmats, JLM=JLM, JMM=JMM, dim=dim, tensdim=tensdim, G_matr=G_matr, G_under=G_under, dummy=dummy, uiuj_pairs=uiuj_pairs)
def __init__( self, time: df.Constant, mesh: df.Mesh, intracellular_conductivity: Dict[int, df.Expression], extracellular_conductivity: Dict[int, df.Expression], cell_function: df.MeshFunction, cell_tags: CellTags, interface_function: df.MeshFunction, interface_tags: InterfaceTags, parameters: CoupledBidomainParameters, neumann_boundary_condition: Dict[int, df.Expression] = None, v_prev: df.Function = None, surface_to_volume_factor: Union[float, df.Constant] = None, membrane_capacitance: Union[float, df.Constant] = None, ) -> None: self._time = time self._mesh = mesh self._parameters = parameters # Strip none from cell tags cell_tags = set(cell_tags) - {None} if surface_to_volume_factor is None: surface_to_volume_factor = df.constant(1) if membrane_capacitance is None: membrane_capacitance = df.constant(1) # Set Chi*Cm self._chi_cm = df.Constant(surface_to_volume_factor) * df.Constant( membrane_capacitance) if not set(intracellular_conductivity.keys()) == { *tuple(extracellular_conductivity.keys()) }: raise ValueError( "intracellular conductivity and lambda does not havemnatching keys." ) if not set(cell_tags) == set(intracellular_conductivity.keys()): raise ValueError("Cell tags does not match conductivity keys") self._intracellular_conductivity = intracellular_conductivity self._extracellular_conductivity = extracellular_conductivity # Check cell tags _cell_function_tags = set(cell_function.array()) if set(cell_tags) != _cell_function_tags: # If not equal msg = "Mismatching cell tags. Expected {}, got {}" raise ValueError(msg.format(set(cell_tags), _cell_function_tags)) self._cell_tags = set(cell_tags) self._cell_function = cell_function restrict_tags = self._parameters.restrict_tags if set(restrict_tags) >= self._cell_tags: msg = "restrict tags ({})is not a subset of cell tags ({})" raise ValueError(msg.format(set(restrict_tags), self._cell_tags)) self._restrict_tags = set(restrict_tags) # Check interface tags _interface_function_tags = {*set(interface_function.array()), None} if not set(interface_tags ) <= _interface_function_tags: # if not subset of msg = "Mismatching interface tags. Expected {}, got {}" raise ValueError( msg.format(set(interface_tags), _interface_function_tags)) self._interface_function = interface_function self._interface_tags = interface_tags # Set up function spaces self._transmembrane_function_space = df.FunctionSpace( self._mesh, "CG", 1) transmembrane_element = df.FiniteElement("CG", self._mesh.ufl_cell(), 1) extracellular_element = df.FiniteElement("CG", self._mesh.ufl_cell(), 1) if neumann_boundary_condition is None: self._neumann_bc: Dict[int, df.Expression] = dict() else: self._neumann_bc = neumann_boundary_condition if self._parameters.linear_solver_type == "direct": lagrange_element = df.FiniteElement("R", self._mesh.ufl_cell(), 0) mixed_element = df.MixedElement( (transmembrane_element, extracellular_element, lagrange_element)) else: mixed_element = df.MixedElement( (transmembrane_element, extracellular_element)) self._VUR = df.FunctionSpace( mesh, mixed_element) # TODO: rename to something sensible # Set-up solution fields: if v_prev is None: self._merger = df.FunctionAssigner( self._transmembrane_function_space, self._VUR.sub(0)) self._v_prev = df.Function(self._transmembrane_function_space, name="v_prev") else: self._merger = None self._v_prev = v_prev self._vur = df.Function(self._VUR, name="vur") # TODO: Give sensible name # For normlising rhs_vector. TODO: Unsure about this. Check the nullspace from cbcbeat self._extracellular_dofs = np.asarray(self._VUR.sub(1).dofmap().dofs()) # Mark first timestep self._timestep: df.Constant = None
def model(self, parameters=None, logger=None): def format(arr): return np.array(arr) # Setup parameters, logger self.set_parameters(parameters) self.set_logger(logger) # Get parameters parameters = self.get_parameters() #SS#if not parameters.get('simulate'): #SS# return # Setup data self.set_data(reset=True) self.set_observables(reset=True) # Show simulation settings self.get_logger()('\n\t'.join([ 'Simulating:', *[ '%s : %r' % (param, parameters[param] if not isinstance( parameters[param], dict) else list(parameters[param])) for param in ['fields', 'num_elem', 'N', 'dt', 'D', 'alpha', 'tol'] ] ])) # Data mesh mesh = IntervalMesh(MPI.comm_world, parameters['num_elem'], parameters['L_0'], parameters['L_1']) # Fields V = {} W = {} fields_n = {} fields = {} w = {} fields_0 = {} potential = {} potential_derivative = {} bcs = {} R = {} J = {} # v2d_vector = {} observables = {} for field in parameters['fields']: # Define functions V[field] = {} w[field] = {} for space in parameters['spaces']: V[field][space] = getattr( dolfin, parameters['spaces'][space]['type'])( mesh, parameters['spaces'][space]['family'], parameters['spaces'][space]['degree']) w[field][space] = TestFunction(V[field][space]) space = V[field][parameters['fields'][field]['space']] test = w[field][parameters['fields'][field]['space']] fields_n[field] = Function(space, name='%sn' % (field)) fields[field] = Function(space, name=field) # Inital condition fields_0[field] = Expression( parameters['fields'][field]['initial'], element=space.ufl_element()) fields_n[field] = project(fields_0[field], space) fields[field].assign(fields_n[field]) # Define potential if parameters['potential'].get('kwargs') is None: parameters['potential']['kwargs'] = {} for k in parameters['potential']['kwargs']: if parameters['potential']['kwargs'][k] is None: parameters['potential']['kwargs'][k] = fields[k] potential[field] = Expression( parameters['potential']['expression'], degree=parameters['potential']['degree'], **parameters['potential']['kwargs']) potential_derivative[field] = Expression( parameters['potential']['derivative'], degree=parameters['potential']['degree'] - 1, **parameters['potential']['kwargs']) #Subdomain for defining Positive grain sub_domains = MeshFunction('size_t', mesh, mesh.topology().dim(), 0) #BC condition bcs[field] = [] if parameters['fields'][field]['bcs'] == 'dirichlet': BC_l = CompiledSubDomain('near(x[0], side) && on_boundary', side=parameters['L_0']) BC_r = CompiledSubDomain('near(x[0], side) && on_boundary', side=parameters['L_1']) bcl = DirichletBC(V, fields_n[field], BC_l) bcr = DirichletBC(V, fields_n[field], BC_r) bcs[field].extend([bcl, bcr]) elif parameters['fields'][field]['bcs'] == 'neumann': bcs[field].extend([]) # Residual and Jacobian R[field] = ( ((fields[field] - fields_n[field]) / parameters['dt'] * test * dx) + (inner(parameters['D'] * grad(test), grad(fields[field])) * dx) + (parameters['alpha'] * potential_derivative[field] * test * dx)) J[field] = derivative(R[field], fields[field]) # Observables observables[field] = {} files = { 'xdmf': XDMFFile(MPI.comm_world, self.get_paths()['xdmf']), 'hdf5': HDF5File(MPI.comm_world, self.get_paths()['hdf5'], 'w'), } files['hdf5'].write(mesh, '/mesh') eps = lambda n, key, field, observables, tol: ( n == 0) or (abs(observables[key]['total_energy'][n] - observables[ key]['total_energy'][n - 1]) / (observables[key]['total_energy'][0]) > tol) flag = {field: True for field in parameters['fields']} tol = { field: parameters['tol'][field] if isinstance( parameters['tol'], dict) else parameters['tol'] for field in parameters['fields'] } phases = {'p': 1, 'm': 2} n = 0 problem = {} solver = {} while (n < parameters['N'] and any([flag[field] for field in parameters['fields']])): self.get_logger()('Time: %d' % (n)) for field in parameters['fields']: if not flag[field]: continue # Solve problem[field] = NonlinearVariationalProblem( R[field], fields[field], bcs[field], J[field]) solver[field] = NonlinearVariationalSolver(problem[field]) solver[field].solve() # Get field array array = assemble( (1 / CellVolume(mesh)) * inner(fields[field], w[field]['Z']) * dx).get_local() # Observables observables[field]['Time'] = parameters['dt'] * n # observables[field]['energy_density'] = format(0.5*dot(grad(fields[field]),grad(fields[field]))*dx) observables[field]['gradient_energy'] = format( assemble(0.5 * dot(grad(fields[field]), grad(fields[field])) * dx(domain=mesh))) observables[field]['landau_energy'] = format( assemble(potential[field] * dx(domain=mesh))) observables[field]['diffusion_energy'] = format( assemble( project( div(project(grad(fields[field]), V[field]['W'])), V[field]['Z']) * dx(domain=mesh)) ) #Diffusion part of chemical potential observables[field]['spinodal_energy'] = format( assemble( potential_derivative[field] * dx(domain=mesh))) #Spinodal part of chemical potential observables[field]['total_energy'] = parameters[ 'D'] * observables[field]['gradient_energy'] + parameters[ 'alpha'] * observables[field]['landau_energy'] observables[field]['chi'] = parameters['alpha'] * observables[ field]['diffusion_energy'] - parameters['D'] * observables[ field]['spinodal_energy'] # Phase observables sub_domains.set_all(0) sub_domains.array()[:] = np.where(array > 0.0, phases['p'], phases['m']) phases_dxp = Measure('dx', domain=mesh, subdomain_data=sub_domains) for phase in phases: dxp = phases_dxp(phases[phase]) observables[field]['Phi_0%s' % (phase)] = format( assemble(1 * dxp)) observables[field]['Phi_1%s' % (phase)] = format( assemble(fields[field] * dxp)) observables[field]['Phi_2%s' % (phase)] = format( assemble(fields[field] * fields[field] * dxp)) observables[field]['Phi_3%s' % (phase)] = format( assemble(fields[field] * fields[field] * fields[field] * dxp)) observables[field]['Phi_4%s' % (phase)] = format( assemble(fields[field] * fields[field] * fields[field] * fields[field] * dxp)) observables[field]['Phi_5%s' % (phase)] = format( assemble(fields[field] * fields[field] * fields[field] * fields[field] * fields[field] * dxp)) observables[field]['gradient_energy_%s' % (phase)] = format( assemble( 0.5 * dot(grad(fields[field]), grad(fields[field])) * dxp)) observables[field]['landau_energy_%s' % (phase)] = format( assemble(potential[field] * dxp)) observables[field][ 'total_energy_%s' % (phase)] = parameters['D'] * observables[field][ 'gradient_energy_%s' % (phase)] + parameters['alpha'] * observables[ field]['landau_energy_%s' % (phase)] observables[field][ 'diffusion_energy_%s' % (phase)] = format( assemble( project( div( project(grad(fields[field]), V[field]['W'])), V[field]['Z']) * dxp)) #Diffusion part of chemical potential observables[field][ 'spinodal_energy_%s' % (phase)] = format( assemble( potential_derivative[field] * dxp)) #Spinodal part of chemical potential observables[field][ 'chi_%s' % (phase)] = parameters['alpha'] * observables[field][ 'spinodal_energy_%s' % (phase)] - parameters['D'] * observables[field][ 'diffusion_energy_%s' % (phase)] files['hdf5'].write(fields[field], '/%s' % (field), n) files['xdmf'].write(fields[field], n) fields_n[field].assign(fields[field]) self.set_data({field: array}) self.set_observables({field: observables[field]}) flag[field] = eps(n, field, fields[field], self.get_observables(), tol[field]) n += 1 for file in files: files[file].close() return
def test_convert_triangle(self): # Disabled because it fails, see FIXME below # test no. 1 from dolfin import Mesh, MPI if MPI.num_processes() != 1: return fname = os.path.join("data", "triangle") dfname = fname+".xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.triangle2xml(fname, dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) self.assertEqual(mesh.num_vertices(), 96) self.assertEqual(mesh.num_cells(), 159) # Clean up os.unlink(dfname) # test no. 2 from dolfin import MPI, Mesh, MeshFunction, \ edges, Edge, faces, Face, \ SubsetIterator, facets, CellFunction if MPI.num_processes() != 1: return fname = os.path.join("data", "test_Triangle_3") dfname = fname+".xml" dfname0 = fname+".attr0.xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.triangle2xml(fname, dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) mesh.init() mfun = MeshFunction('double', mesh, dfname0) self.assertEqual(mesh.num_vertices(), 58) self.assertEqual(mesh.num_cells(), 58) # Create a size_t CellFunction and assign the values based on the # converted Meshfunction cf = CellFunction("size_t", mesh) cf.array()[mfun.array()==10.0] = 0 cf.array()[mfun.array()==-10.0] = 1 # Meassure total area of cells with 1 and 2 marker add = lambda x, y : x+y area0 = reduce(add, (Face(mesh, cell.index()).area() \ for cell in SubsetIterator(cf, 0)), 0.0) area1 = reduce(add, (Face(mesh, cell.index()).area() \ for cell in SubsetIterator(cf, 1)), 0.0) total_area = reduce(add, (face.area() for face in faces(mesh)), 0.0) # Check that all cells in the two domains are either above or below y=0 self.assertTrue(all(cell.midpoint().y()<0 for cell in SubsetIterator(cf, 0))) self.assertTrue(all(cell.midpoint().y()>0 for cell in SubsetIterator(cf, 1))) # Check that the areas add up self.assertAlmostEqual(area0+area1, total_area) # Measure the edge length of the two edge domains edge_markers = mesh.domains().facet_domains() self.assertTrue(edge_markers is not None) length0 = reduce(add, (Edge(mesh, e.index()).length() \ for e in SubsetIterator(edge_markers, 0)), 0.0) length1 = reduce(add, (Edge(mesh, e.index()).length() \ for e in SubsetIterator(edge_markers, 1)), 0.0) # Total length of all edges and total length of boundary edges total_length = reduce(add, (e.length() for e in edges(mesh)), 0.0) boundary_length = reduce(add, (Edge(mesh, f.index()).length() \ for f in facets(mesh) if f.exterior()), 0.0) # Check that the edges add up self.assertAlmostEqual(length0+length1, total_length) self.assertAlmostEqual(length1, boundary_length) # Clean up os.unlink(dfname) os.unlink(dfname0)
def test_creation_and_marking(): class Left(SubDomain): def inside(self, x, on_boundary): return x[:, 0] < np.finfo(float).eps class LeftOnBoundary(SubDomain): def inside(self, x, on_boundary): return np.logical_and(x[:, 0] < np.finfo(float).eps, on_boundary) class Right(SubDomain): def inside(self, x, on_boundary): return x[:, 0] > 1.0 - np.finfo(float).eps class RightOnBoundary(SubDomain): def inside(self, x, on_boundary): return np.logical_and(x[:, 0] > 1.0 - np.finfo(float).eps, on_boundary) subdomain_pairs = [(Left(), Right()), (LeftOnBoundary(), RightOnBoundary())] for ind, MeshClass in enumerate( [UnitIntervalMesh, UnitSquareMesh, UnitCubeMesh]): dim = ind + 1 args = [10] * dim mesh = MeshClass(MPI.comm_world, *args) mesh.create_connectivity_all() for left, right in subdomain_pairs: for t_dim, f_dim in [(0, 0), (mesh.topology.dim - 1, dim - 1), (mesh.topology.dim, dim)]: f = MeshFunction("size_t", mesh, t_dim, 0) left.mark(f, 1) right.mark(f, 2) correct = { (1, 0): 1, (1, 0): 1, (1, 1): 0, (2, 0): 11, (2, 1): 10, (2, 2): 0, (3, 0): 121, (3, 2): 200, (3, 3): 0 } # Check that the number of marked entities are at least the # correct number (it can be larger in parallel) assert all(value >= correct[dim, f_dim] for value in [ MPI.sum(mesh.mpi_comm(), float((f.array() == 2).sum())), MPI.sum(mesh.mpi_comm(), float((f.array() == 1).sum())), ]) for t_dim, f_dim in [(0, 0), (mesh.topology.dim - 1, dim - 1), (mesh.topology.dim, dim)]: f = MeshFunction("size_t", mesh, t_dim, 0) class AllTrue(SubDomain): def inside(self, x, on_boundary): return np.full(x.shape[0], True) class AllFalse(SubDomain): def inside(self, x, on_boundary): return np.full(x.shape[0], False) empty = AllFalse() every = AllTrue() empty.mark(f, 1) every.mark(f, 2) # Check that the number of marked entities is correct assert sum(f.array() == 1) == 0 assert sum(f.array() == 2) == mesh.num_entities(f_dim)
c2v = dual_mesh.topology()(2, 0) for idx_old, (f, l) in enumerate(zip(mapping[:-1], mapping[1:])): # f:l are cells of the patch idx_new, = reduce(operator.and_, map(set, (c2v(c) for c in range(f, l)))) patch_vertices.append(idx_new) assert np.linalg.norm(x_old[idx_old] - x_new[idx_new]) < 1E-13 # The patch overlap vertices are unqiue assert len(set(patch_vertices)) == len(patch_vertices) File('old_mesh.pvd') << mesh # Show how to build the patch mapping from the data of the dual mesh cell_f = MeshFunction('size_t', dual_mesh, 2, 0) values = cell_f.array() for idx, (f, l) in enumerate(zip(mapping[:-1], mapping[1:])): values[f:l] = idx File('dual_mesh.pvd') << cell_f # Scaling nvertices, times = [], [] for n in (4, 8, 16, 32, 64, 128, 256, 512): mesh = UnitSquareMesh(n, n) nvertices.append(mesh.num_vertices()) timer = df.Timer('f') dual_mesh = DualMesh(mesh) time = timer.stop()
# ------------------------------------------------------------------- if __name__ == '__main__': from dolfin import (CompiledSubDomain, DomainBoundary, SubsetIterator, UnitSquareMesh, Facet) from xii import EmbeddedMesh mesh = UnitSquareMesh(4, 4) surfaces = MeshFunction('size_t', mesh, 2, 0) CompiledSubDomain('x[0] > 0.5-DOLFIN_EPS').mark(surfaces, 1) # What should be trasfered f = MeshFunction('size_t', mesh, 1, 0) DomainBoundary().mark(f, 1) CompiledSubDomain('near(x[0], 0.5)').mark(f, 1) # Assign funky colors for i, e in enumerate(SubsetIterator(f, 1), 1): f[e] = i ch_mesh = EmbeddedMesh(surfaces, 1) ch_f = transfer_markers(ch_mesh, f) # Every color in child is found in parent and we get the midpoint right p_values, ch_values = list(f.array()), list(ch_f.array()) for ch_value in set(ch_f.array()) - set((0, )): assert ch_value in p_values x = Facet(mesh, p_values.index(ch_value)).midpoint() y = Facet(ch_mesh, ch_values.index(ch_value)).midpoint() assert x.distance(y) < 1E-13
P1 = FiniteElement('P', 'triangle', 2) element = MixedElement([P1, P1, P1]) ME = FunctionSpace(mesh, element) subdomain = CompiledSubDomain( '(pow((x[0] - 7.5E-3), 2) + pow((x[1] - 7.5E-3), 2)) <= pow(2.5E-3, 2)') subdomains = MeshFunction("size_t", mesh, 2) subdomains.set_all(0) subdomain.mark(subdomains, 1) fc = Constant(2.0) # FCD V0_r = FunctionSpace(mesh, 'DG', 0) fc_function = Function(V0_r) fc_val = [0.0, fc] help = np.asarray(subdomains.array(), dtype=np.int32) fc_function.vector()[:] = np.choose(help, fc_val) zeroth = plot(fc_function, title="Fixed charge density, $c^f$") plt.colorbar(zeroth) plot(fc_function) plt.xlim(0.0, 0.015) plt.xticks([0.0, 0.005, 0.01, 0.015]) plt.ylim(0.0, 0.015) plt.yticks([0.0, 0.005, 0.01, 0.015]) plt.show() Sol_c = Constant(1.0) Poten = 50.0E-3 l_bc_an = DirichletBC(ME.sub(0), Sol_c, left_boundary) r_bc_an = DirichletBC(ME.sub(0), Sol_c, right_boundary) l_bc_ca = DirichletBC(ME.sub(1), Sol_c, left_boundary)
def subdomains(mesh): subdomains = MeshFunction("size_t", mesh, mesh.topology().dim(), 0) for c in cells(mesh): subdomains.array()[c.index()] = c.global_index() return subdomains
def test_convert_triangle( self): # Disabled because it fails, see FIXME below # test no. 1 from dolfin import Mesh, MPI fname = os.path.join(os.path.dirname(__file__), "data", "triangle") dfname = fname + ".xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.triangle2xml(fname, dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) self.assertEqual(mesh.num_vertices(), 96) self.assertEqual(mesh.num_cells(), 159) # Clean up os.unlink(dfname) # test no. 2 from dolfin import MPI, Mesh, MeshFunction, \ edges, Edge, faces, Face, \ SubsetIterator, facets fname = os.path.join(os.path.dirname(__file__), "data", "test_Triangle_3") dfname = fname + ".xml" dfname0 = fname + ".attr0.xml" # Read triangle file and convert to a dolfin xml mesh file meshconvert.triangle2xml(fname, dfname) # Read in dolfin mesh and check number of cells and vertices mesh = Mesh(dfname) mesh.init() mfun = MeshFunction('double', mesh, dfname0) self.assertEqual(mesh.num_vertices(), 58) self.assertEqual(mesh.num_cells(), 58) # Create a size_t MeshFunction and assign the values based on the # converted Meshfunction cf = MeshFunction("size_t", mesh, mesh.topology().dim()) cf.array()[mfun.array() == 10.0] = 0 cf.array()[mfun.array() == -10.0] = 1 # Meassure total area of cells with 1 and 2 marker add = lambda x, y: x + y area0 = reduce(add, (Face(mesh, cell.index()).area() \ for cell in SubsetIterator(cf, 0)), 0.0) area1 = reduce(add, (Face(mesh, cell.index()).area() \ for cell in SubsetIterator(cf, 1)), 0.0) total_area = reduce(add, (face.area() for face in faces(mesh)), 0.0) # Check that all cells in the two domains are either above or below y=0 self.assertTrue( all(cell.midpoint().y() < 0 for cell in SubsetIterator(cf, 0))) self.assertTrue( all(cell.midpoint().y() > 0 for cell in SubsetIterator(cf, 1))) # Check that the areas add up self.assertAlmostEqual(area0 + area1, total_area) # Measure the edge length of the two edge domains #edge_markers = mesh.domains().facet_domains() edge_markers = mesh.domains().markers(mesh.topology().dim() - 1) self.assertTrue(edge_markers is not None) #length0 = reduce(add, (Edge(mesh, e.index()).length() \ # for e in SubsetIterator(edge_markers, 0)), 0.0) length0, length1 = 0.0, 0.0 for item in list(edge_markers.items()): if item[1] == 0: e = Edge(mesh, int(item[0])) length0 += Edge(mesh, int(item[0])).length() elif item[1] == 1: length1 += Edge(mesh, int(item[0])).length() # Total length of all edges and total length of boundary edges total_length = reduce(add, (e.length() for e in edges(mesh)), 0.0) boundary_length = reduce(add, (Edge(mesh, f.index()).length() \ for f in facets(mesh) if f.exterior()), 0.0) # Check that the edges add up self.assertAlmostEqual(length0 + length1, total_length) self.assertAlmostEqual(length1, boundary_length) # Clean up os.unlink(dfname) os.unlink(dfname0)