def get_bc(max_x_func, domain, dim, bc_dict_func): """Get the periodic boundary condition Args: max_x_func: function for finding the maximum value of x domain: the Sfepy domain dim: the x, y or z direction bc_dict_func: function to generate the bc dict Returns: the boundary condition and the sfepy function """ dim_dict = lambda x: [ ("x", per.match_x_plane), ("y", per.match_y_plane), ("z", per.match_z_plane), ][dim][x] return pipe( domain.get_mesh_bounding_box(), lambda x: PeriodicBC( "periodic_{0}".format(dim_dict(0)), list( map_( get_region_func(max_x_func(x), dim_dict(0), domain), zip(("plus", "minus"), x[:, dim][::-1]), ) ), bc_dict_func(x), match="match_{0}_plane".format(dim_dict(0)), ), lambda x: (x, Function("match_{0}_plane".format(dim_dict(0)), dim_dict(1))), )
def _get_periodicBC_X(self, domain, dim): dim_dict = {1: ('y', per.match_y_plane), 2: ('z', per.match_z_plane)} dim_string = dim_dict[dim][0] match_plane = dim_dict[dim][1] min_, max_ = domain.get_mesh_bounding_box()[:, dim] min_x, max_x = domain.get_mesh_bounding_box()[:, 0] plus_ = self._subdomain_func(max_x=max_x, **{dim_string: (max_,)}) minus_ = self._subdomain_func(max_x=max_x, **{dim_string: (min_,)}) plus_string = dim_string + 'plus' minus_string = dim_string + 'minus' plus = Function(plus_string, plus_) minus = Function(minus_string, minus_) region_plus = domain.create_region( 'region_{0}_plus'.format(dim_string), 'vertices by {0}'.format( plus_string), 'facet', functions=Functions([plus])) region_minus = domain.create_region( 'region_{0}_minus'.format(dim_string), 'vertices by {0}'.format( minus_string), 'facet', functions=Functions([minus])) match_plane = Function( 'match_{0}_plane'.format(dim_string), match_plane) bc_dict = {'u.0': 'u.0'} bc = PeriodicBC('periodic_{0}'.format(dim_string), [region_plus, region_minus], bc_dict, match='match_{0}_plane'.format(dim_string)) return bc, match_plane
def test_epbcs(self): from sfepy.discrete import Function, Functions from sfepy.discrete.conditions import Conditions, PeriodicBC from sfepy.discrete.common.dof_info import expand_nodes_to_equations from sfepy.discrete.fem.periodic import match_y_line variables = self.variables regions = self.problem.domain.regions match_y_line = Function('match_y_line', match_y_line) pbc = PeriodicBC('pbc', [regions['LeftStrip'], regions['RightStrip']], {'u.[1,0]': 'u.[0,1]'}, match='match_y_line') functions = Functions([match_y_line]) epbcs = Conditions([pbc]) variables.equation_mapping(ebcs=None, epbcs=epbcs, ts=None, functions=functions) vec = init_vec(variables) variables.apply_ebc(vec) var = variables['u'] var_bcs = epbcs.group_by_variables()['u'] bc = var_bcs['pbc'] bc.canonize_dof_names(var.dofs) nods0 = var.field.get_dofs_in_region(bc.regions[0]) nods1 = var.field.get_dofs_in_region(bc.regions[1]) coors0 = var.field.get_coor(nods0) coors1 = var.field.get_coor(nods1) i0, i1 = match_y_line(coors0, coors1) eq0 = expand_nodes_to_equations(nods0[i0], bc.dofs[0], var.dofs) eq1 = expand_nodes_to_equations(nods1[i1], bc.dofs[1], var.dofs) ok = True _ok = len(nm.setdiff1d(eq0, var.eq_map.master)) == 0 if not _ok: self.report('master equations mismatch! (set(%s) == set(%s))' % (eq0, var.eq_map.master)) ok = ok and _ok _ok = len(nm.setdiff1d(eq1, var.eq_map.slave)) == 0 if not _ok: self.report('slave equations mismatch! (set(%s) == set(%s))' % (eq1, var.eq_map.slave)) ok = ok and _ok off = variables.di.indx['u'].start _ok = nm.allclose(vec[off + eq0], vec[off + eq1], atol=1e-14, rtol=0.0) if not _ok: self.report('periodicity test failed! (%s == %s)' % (vec[off + eq0], vec[off + eq0])) ok = ok and _ok return ok