def __init__(self, problem, verbosity=0): """ :param ProblemData problem: :param int verbosity: :return: """ self.parameters = parameters["discretization"] self.verb = verbosity self.vis_folder = os.path.join(problem.out_folder, "MESH") self.core = problem.core self.G = problem.G if self.verb > 1: print pid+"Loading mesh" t_load = Timer("DD: Data loading") if not problem.mesh_module: if self.verb > 1: print pid + " mesh data" self.mesh = Mesh(problem.mesh_files.mesh) if self.verb > 1: print pid + " physical data" self.cell_regions_fun = MeshFunction("size_t", self.mesh, problem.mesh_files.physical_regions) if self.verb > 1: print pid + " boundary data" self.boundaries = MeshFunction("size_t", self.mesh, problem.mesh_files.facet_regions) else: self.mesh = problem.mesh_module.mesh self.cell_regions_fun = problem.mesh_module.regions try: self.boundaries = problem.mesh_module.boundaries except AttributeError: self.boundaries = None assert self.mesh assert self.boundaries is None or self.boundaries.array().size > 0 if self.verb > 2: print pid+" mesh info: " + str(self.mesh) if self.verb > 1: print0("Defining function spaces" ) self.t_spaces = Timer("DD: Function spaces construction") # Spaces that must be specified by the respective subclasses self.V = None # solution space self.Vphi1 = None # 1-g scalar flux space # XS / TH space self.V0 = FunctionSpace(self.mesh, "DG", 0) self.ndof0 = self.V0.dim() dofmap = self.V0.dofmap() self.local_ndof0 = dofmap.local_dimension("owned") self.cell_regions = self.cell_regions_fun.array() assert self.cell_regions.size == self.local_ndof0
def construct_A_from_mesh_functions(dim, A_expr, mesh): if dim == 2: a01 = MeshFunction("double", mesh, dim) a11 = MeshFunction("double", mesh, dim) A1 = A_expr[0] A2 = A_expr[1] a00 = MeshFunction("double", mesh, dim) for cell in cells(mesh): if cell.midpoint().x() < 0.5: if dim == 2: a00[cell] = A1[0][0] a11[cell] = A1[1][1] a01[cell] = A1[0][1] else: if dim == 2: a00[cell] = A2[0][0] a11[cell] = A2[1][1] a01[cell] = A2[0][1] # Code for C++ evaluation of conductivity conductivity_code = """ class Conductivity : public Expression { public: // Create expression with 3 components Conductivity() : Expression(3) {} // Function for evaluating expression on each cell void eval(Array<double>& values, const Array<double>& x, const ufc::cell& cell) const { const uint D = cell.topological_dimension; const uint cell_index = cell.index; values[0] = (*a00)[cell_index]; values[1] = (*a01)[cell_index]; values[2] = (*a11)[cell_index]; } // The data stored in mesh functions std::shared_ptr<MeshFunction<double> > a00; std::shared_ptr<MeshFunction<double> > a01; std::shared_ptr<MeshFunction<double> > a11; }; """ a = Expression(cppcode=conductivity_code) a.a00 = a00 a.a01 = a01 a.a11 = a11 A = as_matrix(((a[0], a[1]), (a[1], a[2]))) return A
def markBoundarySubdomains(mesh, boundaries, **kwargs): '''Mark the boundaries of a mesh given a geometry All interior faces are marked with zero boundaries is a dictionary {label: definition of boundary} ''' bndSubdomains = MeshFunction("size_t", mesh, mesh.geometry().dim()-1) bndSubdomains.set_all(0) for i in boundaries: class BndSubDomain(SubDomain): def inside(self, x, on_boundary): value = array([0.0]) boundaries[i].eval(value, x) return (value==1.0) and on_boundary aux = BndSubDomain() aux.mark(bndSubdomains, i) # Save Dolfin XML format of the subdomains if 'outputXmlGz' in kwargs: File(kwargs['outputXmlGz']) << bndSubdomains # Save sub domains to VTK files if 'outputPvd' in kwargs: File(kwargs['outputPvd']) << bndSubdomains return bndSubdomains ## If there exist dirichlet boundary #if hasDirichlet: # if os.path.isfile(dirichletPath): # dirichletSubdomain = MeshFunction("bool", mesh, dirichletPath) # else: # # Mark faces # dirichletSubdomain.set_all(False) # class Aux(SubDomain): # def inside(self, x, on_boundary): # value = array([0.0]) # physics.dirichletBnd.eval(value, x) # return (value==1.0) and on_boundary # aux = Aux() # aux.mark(dirichletSubdomain, True) # aux.mark(bndSubdomains, 0)
def __init__(self, args, tc, metadata): self.has_analytic_solution = False self.problem_code = 'FACB' super(Problem, self).__init__(args, tc, metadata) self.name = 'test on real mesh' self.status_functional_str = 'not selected' # input parameters self.factor = args.factor self.scale_factor.append(self.factor) self.nu = 0.001 * args.nufactor # kinematic viscosity # Import gmsh mesh self.compatible_meshes = ['bench3D_1', 'bench3D_2', 'bench3D_3'] if args.mesh not in self.compatible_meshes: exit('Bad mesh, should be some from %s' % str(self.compatible_meshes)) self.mesh = Mesh("meshes/" + args.mesh + ".xml") self.cell_function = MeshFunction( "size_t", self.mesh, "meshes/" + args.mesh + "_physical_region.xml") self.facet_function = MeshFunction( "size_t", self.mesh, "meshes/" + args.mesh + "_facet_region.xml") self.dsIn = Measure("ds", subdomain_id=2, subdomain_data=self.facet_function) self.dsOut = Measure("ds", subdomain_id=3, subdomain_data=self.facet_function) self.dsWall = Measure("ds", subdomain_id=1, subdomain_data=self.facet_function) self.dsCyl = Measure("ds", subdomain_id=5, subdomain_data=self.facet_function) self.normal = FacetNormal(self.mesh) print("Mesh name: ", args.mesh, " ", self.mesh) print("Mesh norm max: ", self.mesh.hmax()) print("Mesh norm min: ", self.mesh.hmin()) self.actual_time = None self.v_in = None
def markBoundariesOfMesh(mesh, geo, **kwargs): '''Mark the boundaries of a mesh given a geometry All interior faces are marked with zero If the geometry has no marks, it will be mared using the convention: face[0] = 1 face[1] = 2 ... face[N] = N+1 ''' # Reference point indexes in each face geoBndPoints = [ face[0] for face in geo._faces ] # Face normals geoNormals = geo.getNormals() # Create mesh functions over the cell facets faceSubdomains = MeshFunction("size_t", mesh, geo._nDim-1) # Mark all facets of the domain as 0 faceSubdomains.set_all(0) # Mark boundary faces for face elements for i in range(geo.getNoFaces()): class BndSubDomain(SubDomain): def inside(self, x, on_boundary): return near( geoNormals[i].dot(Point(x)-geo._points[geoBndPoints[i]]), 0.0 ) and on_boundary aSubDomain = BndSubDomain() label = i+1 if hasattr(geo, 'facesMarkers'): label = geo.facesMarkers[i] aSubDomain.mark(faceSubdomains, label) # Save Dolfin XML format of the subdomains if 'outputXmlGz' in kwargs: File(kwargs['outputXmlGz']) << faceSubdomains # Save sub domains to VTK files if 'outputPvd' in kwargs: File(kwargs['outputPvd']) << faceSubdomains return faceSubdomains
def loadMesh(mesh): """ :param mesh: name of mesh file (without extension) :return: tuple mesh, facet function read from .hdf5 file """ f = HDF5File(mpi_comm_world(), 'meshes/'+mesh+'.hdf5', 'r') mesh = Mesh() f.read(mesh, 'mesh', False) facet_function = MeshFunction("size_t", mesh) f.read(facet_function, 'facet_function') return mesh, facet_function
# Load mesh if isfile(meshPath): mesh = Mesh(meshPath) else: print("Mesh bndFile does not exist!") exit(1) #plot(mesh, interactive=True) ### ### Mesh ### # Here we consider 0 as a internal face bndSubdomains = markBoundariesOfMesh(mesh, geo, outputPvd="localBoundary.pvd") globalBndSubdomains = MeshFunction("size_t", mesh, geo._nDim - 1) # If there exist marked boundary if 'boundaries' in dir(physics): if (reutilizeBoundaryInfo and isfile(bndPath)): globalBndSubdomains = MeshFunction("size_t", mesh, bndPath) else: globalBndSubdomains = markBoundarySubdomains(mesh, physics.boundaries, outputXmlGz=bndPath, outputPvd=bndPvd) else: globalBndSubdomains.set_all(0) # Boundary measures ds = Measure('ds', domain=mesh, subdomain_data=bndSubdomains)
def construct_from_mesh_functions(dim, A_expr, mesh): """ :param dim: geometrical dimension :param A_expr: expression defining diffusion matrix :param mesh: mesh-discretization of the domain :return: cell-wise function """ # Define scalar cell-wise function for dim = 1 a00 = MeshFunction("double", mesh, dim) # Define function expression from the problem data (depending on how many of the conditions are discussed ) A1 = A_expr[0] A2 = A_expr[1] # Case for dimension higher then one (symmetric case) if dim >= 2: a01 = MeshFunction("double", mesh, dim) a11 = MeshFunction("double", mesh, dim) # Case for dimension higher then two (symmetric case) if dim >= 3: a02 = MeshFunction("double", mesh, dim) a12 = MeshFunction("double", mesh, dim) a22 = MeshFunction("double", mesh, dim) for cell in cells(mesh): if cell.midpoint().x( ) < 0.5: # this condition checks whethe the elements on the left part of the domain A = A_expr[0] else: A = A_expr[1] a00[cell] = A[0][0] if dim >= 2: a11[cell] = A[1][1] a01[cell] = A[0][1] if dim >= 3: a02[cell] = A[0][2] a12[cell] = A[1][2] a22[cell] = A[2][2] # Code for C++ evaluation of conductivity conductivity_code = """ class Conductivity : public Expression { public: // Create expression with 3 components Conductivity() : Expression(3) {} // Function for evaluating expression on each cell void eval(Array<double>& values, const Array<double>& x, const ufc::cell& cell) const { const uint D = cell.topological_dimension; const uint cell_index = cell.index; values[0] = (*a00)[cell_index]; values[1] = (*a01)[cell_index]; values[2] = (*a11)[cell_index]; } // The data stored in mesh functions std::shared_ptr<MeshFunction<double> > a00; std::shared_ptr<MeshFunction<double> > a01; std::shared_ptr<MeshFunction<double> > a11; }; """ # Define expression via C++ code a = Expression(cppcode=conductivity_code) a.a00 = a00 if dim >= 2: a.a01 = a01 a.a11 = a11 if dim >= 3: a.a02 = a02 a.a12 = a12 a.a22 = a22 # Define matrix depending on the dimension if dim == 1: A = a[0] elif dim == 2: # A = |a[0] a[1]| # |a[1] a[2]| A = as_matrix(((a[0], a[1]), (a[1], a[2]))) elif dim == 3: # A = |a[0] a[1] a[2]| # |a[1] a[3] a[4]| # |a[2] a[4] a[5]| A = as_matrix( ((a[0], a[1], a[2]), (a[1], a[3], a[4]), (a[2], a[3], a[5]))) return A
class Discretization(object): def __init__(self, problem, verbosity=0): """ :param ProblemData problem: :param int verbosity: :return: """ self.parameters = parameters["discretization"] self.verb = verbosity self.vis_folder = os.path.join(problem.out_folder, "MESH") self.core = problem.core self.G = problem.G if self.verb > 1: print pid+"Loading mesh" t_load = Timer("DD: Data loading") if not problem.mesh_module: if self.verb > 1: print pid + " mesh data" self.mesh = Mesh(problem.mesh_files.mesh) if self.verb > 1: print pid + " physical data" self.cell_regions_fun = MeshFunction("size_t", self.mesh, problem.mesh_files.physical_regions) if self.verb > 1: print pid + " boundary data" self.boundaries = MeshFunction("size_t", self.mesh, problem.mesh_files.facet_regions) else: self.mesh = problem.mesh_module.mesh self.cell_regions_fun = problem.mesh_module.regions try: self.boundaries = problem.mesh_module.boundaries except AttributeError: self.boundaries = None assert self.mesh assert self.boundaries is None or self.boundaries.array().size > 0 if self.verb > 2: print pid+" mesh info: " + str(self.mesh) if self.verb > 1: print0("Defining function spaces" ) self.t_spaces = Timer("DD: Function spaces construction") # Spaces that must be specified by the respective subclasses self.V = None # solution space self.Vphi1 = None # 1-g scalar flux space # XS / TH space self.V0 = FunctionSpace(self.mesh, "DG", 0) self.ndof0 = self.V0.dim() dofmap = self.V0.dofmap() self.local_ndof0 = dofmap.local_dimension("owned") self.cell_regions = self.cell_regions_fun.array() assert self.cell_regions.size == self.local_ndof0 def __create_cell_dof_mapping(self, dofmap): """ Generate cell -> dof mapping for all cells of current partition. Note: in DG(0) space, there is one dof per element and no ghost cells. :param GenericDofMap dofmap: DG(0) dofmap """ if self.verb > 2: print0("Constructing cell -> dof mapping") timer = Timer("DD: Cell->dof construction") code = \ ''' #include <dolfin/mesh/Cell.h> namespace dolfin { void fill_in(Array<int>& local_cell_dof_map, const Mesh& mesh, const GenericDofMap& dofmap) { std::size_t local_dof_range_start = dofmap.ownership_range().first; int* cell_dof_data = local_cell_dof_map.data(); for (CellIterator c(mesh); !c.end(); ++c) *cell_dof_data++ = dofmap.cell_dofs(c->index())[0] - local_dof_range_start; } } ''' cell_mapping_module = compile_extension_module(code) cell_dof_array = IntArray(self.local_ndof0) cell_mapping_module.fill_in(cell_dof_array, self.mesh, dofmap) self._local_cell_dof_map = cell_dof_array.array() timer.stop() def __create_cell_layers_mapping(self): """ Generate a cell -> axial layer mapping for all cells of current partition. Note that keys are ordered by the associated DG(0) dof, not by the cell index in the mesh. """ if self.verb > 2: print0("Constructing cell -> layer mapping") timer = Timer("DD: Cell->layer construction") code = \ ''' #include <dolfin/mesh/Cell.h> namespace dolfin { void fill_in(Array<int>& local_cell_layers, const Mesh& mesh, const Array<int>& cell_dofs, const Array<double>& layer_boundaries) { std::size_t num_layers = layer_boundaries.size() - 1; unsigned int layer; for (CellIterator c(mesh); !c.end(); ++c) { double midz = c->midpoint().z(); for (layer = 0; layer < num_layers; layer++) if (layer_boundaries[layer] <= midz && midz <= layer_boundaries[layer+1]) break; int dof = cell_dofs[c->index()]; local_cell_layers[dof] = layer; } } } ''' cell_mapping_module = compile_extension_module(code) cell_layers_array = IntArray(self.local_ndof0) cell_mapping_module.fill_in(cell_layers_array, self.mesh, self.local_cell_dof_map, self.core.layer_boundaries) self._local_cell_layers = cell_layers_array.array() timer.stop() def __create_cell_vol_mapping(self): """ Generate cell -> volume mapping for all cells of current partition. Note that keys are ordered by the associated DG(0) dof, not by the cell index in the mesh. This map is required for calculating various densities from total region integrals (like cell power densities from cell-integrated powers). """ if self.verb > 2: print0("Constructing cell -> volume mapping") timer = Timer("DD: Cell->vol construction") code = \ ''' #include <dolfin/mesh/Cell.h> namespace dolfin { void fill_in(Array<double>& cell_vols, const Mesh& mesh, const Array<int>& cell_dofs) { for (CellIterator c(mesh); !c.end(); ++c) cell_vols[cell_dofs[c->index()]] = c->volume(); } } ''' cell_mapping_module = compile_extension_module(code) cell_vol_array = DoubleArray(self.local_ndof0) cell_mapping_module.fill_in(cell_vol_array, self.mesh, self.local_cell_dof_map) self._local_cell_volumes = cell_vol_array.array() timer.stop() @property def local_cell_dof_map(self): try: self._local_cell_dof_map except AttributeError: self.__create_cell_dof_mapping(self.V0.dofmap()) return self._local_cell_dof_map @property def local_cell_volumes(self): try: self._local_cell_volumes except AttributeError: self.__create_cell_vol_mapping() return self._local_cell_volumes @property def local_cell_layers(self): try: self._local_cell_layers except AttributeError: self.__create_cell_layers_mapping() return self._local_cell_layers def visualize_mesh_data(self): timer = Timer("DD: Mesh data visualization") if self.verb > 2: print0("Visualizing mesh data") File(os.path.join(self.vis_folder, "mesh.pvd"), "compressed") << self.mesh if self.boundaries: File(os.path.join(self.vis_folder, "boundaries.pvd"), "compressed") << self.boundaries File(os.path.join(self.vis_folder, "mesh_regions.pvd"), "compressed") << self.cell_regions_fun # Create MeshFunction to hold cell process rank processes = CellFunction('size_t', self.mesh, MPI.rank(comm)) File(os.path.join(self.vis_folder, "mesh_partitioning.pvd"), "compressed") << processes def print_diagnostics(self): print "\nDiscretization diagnostics" print MPI.rank(comm), self.mesh.num_entities(self.mesh.topology().dim()) dofmap = self.V0.dofmap() print MPI.rank(comm), dofmap.ownership_range() print MPI.rank(comm), numpy.min(dofmap.collapse(self.mesh)[1].values()), \ numpy.max(dofmap.collapse(self.mesh)[1].values()) print "#Owned by {}: {}".format(MPI.rank(comm), dofmap.local_dimension("owned")) print "#Unowned by {}: {}".format(MPI.rank(comm), dofmap.local_dimension("unowned"))