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 run(domain, order): omega = domain.create_region('Omega', 'all') bbox = domain.get_mesh_bounding_box() min_x, max_x = bbox[:, 0] min_y, max_y = bbox[:, 1] eps = 1e-8 * (max_x - min_x) gamma1 = domain.create_region('Gamma1', 'vertices in (x < %.10f)' % (min_x + eps), 'facet') gamma2 = domain.create_region('Gamma2', 'vertices in (x > %.10f)' % (max_x - eps), 'facet') gamma3 = domain.create_region('Gamma3', 'vertices in y < %.10f' % (min_y + eps), 'facet') gamma4 = domain.create_region('Gamma4', 'vertices in y > %.10f' % (max_y - eps), 'facet') field = Field.from_args('fu', nm.float64, 1, omega, approx_order=order) u = FieldVariable('u', 'unknown', field) v = FieldVariable('v', 'test', field, primary_var_name='u') integral = Integral('i', order=2 * order) t1 = Term.new('dw_laplace(v, u)', integral, omega, v=v, u=u) eq = Equation('eq', t1) eqs = Equations([eq]) fix1 = EssentialBC('fix1', gamma1, {'u.0': 0.4}) fix2 = EssentialBC('fix2', gamma2, {'u.0': 0.0}) def get_shift(ts, coors, region): return nm.ones_like(coors[:, 0]) dof_map_fun = Function('dof_map_fun', per.match_x_line) shift_fun = Function('shift_fun', get_shift) sper = LinearCombinationBC('sper', [gamma3, gamma4], {'u.0': 'u.0'}, dof_map_fun, 'shifted_periodic', arguments=(shift_fun, )) ls = ScipyDirect({}) nls = Newton({}, lin_solver=ls) pb = Problem('laplace', equations=eqs) pb.set_bcs(ebcs=Conditions([fix1, fix2]), lcbcs=Conditions([sper])) pb.set_solver(nls) state = pb.solve() return pb, state
def _get_fixed_displacementsBCs(self, domain): """ Fix the left top and bottom points in x, y and z Args: domain: an Sfepy domain Returns: the Sfepy boundary conditions """ min_xyz = domain.get_mesh_bounding_box()[0] max_xyz = domain.get_mesh_bounding_box()[1] kwargs = {} fix_points_dict = {'u.0': 0.0, 'u.1': 0.0} if len(min_xyz) == 3: kwargs = {'z': (max_xyz[2], min_xyz[2])} fix_points_dict['u.2'] = 0.0 fix_x_points_ = self._subdomain_func(x=(min_xyz[0],), y=(max_xyz[1], min_xyz[1]), **kwargs) fix_x_points = Function('fix_x_points', fix_x_points_) region_fix_points = domain.create_region( 'region_fix_points', 'vertices by fix_x_points', 'vertex', functions=Functions([fix_x_points])) return EssentialBC('fix_points_BC', region_fix_points, fix_points_dict)
def _get_shift_displacementsBCs(self, domain): """ Fix the right top and bottom points in x, y and z Args: domain: an Sfepy domain Returns: the Sfepy boundary conditions """ min_xyz = domain.get_mesh_bounding_box()[0] max_xyz = domain.get_mesh_bounding_box()[1] kwargs = {} if len(min_xyz) == 3: kwargs = {'z': (max_xyz[2], min_xyz[2])} displacement = self.macro_strain * (max_xyz[0] - min_xyz[0]) shift_points_dict = {'u.0': displacement} shift_x_points_ = self._subdomain_func(x=(max_xyz[0],), y=(max_xyz[1], min_xyz[1]), **kwargs) shift_x_points = Function('shift_x_points', shift_x_points_) region_shift_points = domain.create_region( 'region_shift_points', 'vertices by shift_x_points', 'vertex', functions=Functions([shift_x_points])) return EssentialBC('shift_points_BC', region_shift_points, shift_points_dict)
def eval_force(region_name): strain = problem.evaluate( 'ev_cauchy_strain.i.%s(u)' % region_name, mode='qp', verbose=False, ) D = problem.evaluate( 'ev_integrate_mat.i.%s(solid.D, u)' % region_name, mode='qp', verbose=False, ) normal = nm.array([1, 0, 0], dtype=nm.float64) s2f = get_full_indices(len(normal)) stress = nm.einsum('cqij,cqjk->cqik', D, strain) # Full (matrix) form of stress. mstress = stress[..., s2f, 0] # Force in normal direction. force = nm.einsum('cqij,i,j->cq', mstress, normal, normal) def get_force(ts, coors, mode=None, **kwargs): if mode == 'qp': return {'force': force.reshape(coors.shape[0], 1, 1)} aux = Material('aux', function=Function('get_force', get_force)) middle_force = -problem.evaluate( 'ev_integrate_mat.i.%s(aux.force, u)' % region_name, aux=aux, verbose=False, ) output('%s section axial force:' % region_name, middle_force)
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_material(self, property_array, domain): """ Creates an SfePy material from the material property fields for the quadrature points. Args: property_array: array of the properties with shape (n_x, n_y, n_z, 2) Returns: an SfePy material """ min_xyz = domain.get_mesh_bounding_box()[0] dims = domain.get_mesh_bounding_box().shape[1] def _material_func_(ts, coors, mode=None, **kwargs): if mode == 'qp': ijk_out = np.empty_like(coors, dtype=int) ijk = np.floor((coors - min_xyz[None]) / self.dx, ijk_out, casting="unsafe") ijk_tuple = tuple(ijk.swapaxes(0, 1)) property_array_qp = property_array[ijk_tuple] lam = property_array_qp[..., 0] mu = property_array_qp[..., 1] lam = np.ascontiguousarray(lam.reshape((lam.shape[0], 1, 1))) mu = np.ascontiguousarray(mu.reshape((mu.shape[0], 1, 1))) from sfepy.mechanics.matcoefs import stiffness_from_lame stiffness = stiffness_from_lame(dims, lam=lam, mu=mu) return {'lam': lam, 'mu': mu, 'D': stiffness} else: return material_func = Function('material_func', _material_func_) return Material('m', function=material_func)
def solveLaplaceEquationTetrahedral(mesh, meshVTK, boundaryPoints, boundaryConditions): """ mesh: path to a 3D mesh / sfepy mesh """ if isinstance(mesh, str): mesh = Mesh.from_file(mesh) #Set domains domain = FEDomain('domain', mesh) omega = domain.create_region('Omega', 'all') boundary = domain.create_region( 'gamma', 'vertex %s' % ','.join(map(str, range(meshVTK.GetNumberOfPoints()))), 'facet') #set fields field = Field.from_args('fu', np.float64, 1, omega, approx_order=1) u = FieldVariable('u', 'unknown', field) v = FieldVariable('v', 'test', field, primary_var_name='u') m = Material('m', val=[1.]) #Define element integrals integral = Integral('i', order=3) #Equations defining t1 = Term.new('dw_laplace( v, u )', integral, omega, v=v, u=u) eq = Equation('balance', t1) eqs = Equations([eq]) heatBoundary = boundaryConditions points = boundaryPoints #Boundary conditions c = ClosestPointStupid(points, heatBoundary, meshVTK) def u_fun(ts, coors, bc=None, problem=None, c=c): c.distances = [] v = np.zeros(len(coors)) for i, p in enumerate(coors): v[i] = c.interpolate(p) #c.findClosestPoint(p) return v bc_fun = Function('u_fun', u_fun) fix1 = EssentialBC('fix_u', boundary, {'u.all': bc_fun}) #Solve problem ls = ScipyDirect({}) nls = Newton({}, lin_solver=ls) pb = Problem('heat', equations=eqs) pb.set_bcs(ebcs=Conditions([fix1])) pb.set_solver(nls) state = pb.solve(verbose=False, save_results=False) u = state.get_parts()['u'] return u
def test_solving(self): from sfepy.base.base import IndexedStruct from sfepy.discrete import (FieldVariable, Material, Problem, Function, Equation, Equations, Integral) from sfepy.discrete.conditions import Conditions, EssentialBC from sfepy.terms import Term from sfepy.solvers.ls import ScipyDirect from sfepy.solvers.nls import Newton from sfepy.mechanics.matcoefs import stiffness_from_lame u = FieldVariable('u', 'unknown', self.field) v = FieldVariable('v', 'test', self.field, primary_var_name='u') m = Material('m', D=stiffness_from_lame(self.dim, 1.0, 1.0)) f = Material('f', val=[[0.02], [0.01]]) bc_fun = Function('fix_u_fun', fix_u_fun, extra_args={'extra_arg' : 'hello'}) fix_u = EssentialBC('fix_u', self.gamma1, {'u.all' : bc_fun}) shift_u = EssentialBC('shift_u', self.gamma2, {'u.0' : 0.1}) integral = Integral('i', order=3) t1 = Term.new('dw_lin_elastic(m.D, v, u)', integral, self.omega, m=m, v=v, u=u) t2 = Term.new('dw_volume_lvf(f.val, v)', integral, self.omega, f=f, v=v) eq = Equation('balance', t1 + t2) eqs = Equations([eq]) ls = ScipyDirect({}) nls_status = IndexedStruct() nls = Newton({}, lin_solver=ls, status=nls_status) pb = Problem('elasticity', equations=eqs, nls=nls, ls=ls) ## pb.save_regions_as_groups('regions') pb.time_update(ebcs=Conditions([fix_u, shift_u])) state = pb.solve() name = op.join(self.options.out_dir, 'test_high_level_solving.vtk') pb.save_state(name, state) ok = nls_status.condition == 0 if not ok: self.report('solver did not converge!') _ok = state.has_ebc() if not _ok: self.report('EBCs violated!') ok = ok and _ok return ok
def func(min_xyz, max_xyz): def shift_(_, coors, __): return np.ones_like(coors[:, 0]) * macro_strain * (max_xyz[0] - min_xyz[0]) return pipe( [("plus", max_xyz[0]), ("minus", min_xyz[0])], map_(get_region_func(None, "x", domain)), list, lambda x: LinearCombinationBC( "lcbc", x, {"u.0": "u.0"}, Function("match_x_plane", per.match_x_plane), "shifted_periodic", arguments=(Function("shift", shift_),), ), lambda x: Conditions([x]), )
def _get_linear_combinationBCs(self, domain): """ The right nodes are periodic with the left nodes but also displaced. Args: domain: an Sfepy domain Returns: the Sfepy boundary conditions """ min_xyz = domain.get_mesh_bounding_box()[0] max_xyz = domain.get_mesh_bounding_box()[1] xplus_ = self._subdomain_func(x=(max_xyz[0], )) xminus_ = self._subdomain_func(x=(min_xyz[0], )) xplus = Function('xplus', xplus_) xminus = Function('xminus', xminus_) region_x_plus = domain.create_region('region_x_plus', 'vertices by xplus', 'facet', functions=Functions([xplus])) region_x_minus = domain.create_region('region_x_minus', 'vertices by xminus', 'facet', functions=Functions([xminus])) match_x_plane = Function('match_x_plane', per.match_x_plane) def shift_(ts, coors, region): return np.ones_like( coors[:, 0]) * self.macro_strain * (max_xyz[0] - min_xyz[0]) shift = Function('shift', shift_) lcbc = LinearCombinationBC('lcbc', [region_x_plus, region_x_minus], {'u.0': 'u.0'}, match_x_plane, 'shifted_periodic', arguments=(shift, )) return Conditions([lcbc])
def get_material(calc_stiffness, calc_prestress): """Get the material Args: calc_stiffness: the function for calculating the stiffness tensor calc_prestress: the function for calculating the prestress Returns: the material """ def _material_func_(_, coors, mode=None, **__): if mode == "qp": return dict(D=calc_stiffness(coors), stress=calc_prestress(coors)) return None return Material("m", function=Function("material_func", _material_func_))
def func(min_xyz, max_xyz): return pipe( dict(z_points=(max_xyz[2], min_xyz[2])) if len(min_xyz) == 3 else dict(), lambda x: subdomain_func( x_points=x_points_f(min_xyz, max_xyz), y_points=(max_xyz[1], min_xyz[1]), **x, ), lambda x: Function(f"{name}_x_points", x), lambda x: domain.create_region( f"region_{name}_points", f"vertices by {name}_x_points", "vertex", functions=Functions([x]), ), lambda x: EssentialBC( f"{name}_points_BC", x, points_dict_f(min_xyz, max_xyz) ), )
def _get_material(property_array, domain, delta_x): """ Creates an SfePy material from the material property fields for the quadrature points. Args: property_array: array of the properties with shape (n_x, n_y, n_z, 2) domain: the Sfepy domain delta_x: the grid spacing Returns: a SfePy material """ reshape = lambda x: np.ascontiguousarray(x.reshape((x.shape[0], 1, 1))) def _material_func_(_, coors, mode=None, **__): if mode == "qp": return pipe( np.empty_like(coors, dtype=int), lambda x: np.floor( (coors - domain.get_mesh_bounding_box()[0][None]) / delta_x, x, casting="unsafe", ), lambda x: x.swapaxes(0, 1), tuple, lambda x: property_array[x], lambda x: dict( lam=reshape(x[..., 0]), mu=reshape(x[..., 1]), D=stiffness_from_lame( domain.get_mesh_bounding_box().shape[1], lam=x[..., 0], mu=x[..., 1], ), ), ) return None return Material("m", function=Function("material_func", _material_func_))
def get_region_func(max_x, dim_string, domain, name_minmax): """Generate the Sfepy region Args: max_x: max value in the x direction dim_string: either "x", "y", or "z" domain: the Sfepy domain name_minmax: tuple of name and min / max Returns: the Sfepy region """ return pipe( subdomain_func(max_x=max_x, **{dim_string + "_points": (name_minmax[1],)}), lambda x: Function(dim_string + name_minmax[0], x), lambda x: domain.create_region( "region_{0}_{1}".format(dim_string, name_minmax[0]), "vertices by {0}".format(x.name), "facet", functions=Functions([x]), ), )
def get_bc(domain, delta_x, index, cond): """Make a displacement boundary condition Args: domain: the Sfepy domain delta_x: the mesh spacing index: the index (either 0 or 1) depends on direction of axes cond: the BC dictionary Returns: the Sfepy boundary condition """ return pipe( Function("fix_points", subdomain(index, domain, delta_x * 1e-3)), lambda x: domain.create_region( "region_fix_points", "vertices by fix_points", "vertex", functions=Functions([x]), ), lambda x: EssentialBC("fix_points_BC", x, cond), )
def main(): from sfepy import data_dir parser = OptionParser(usage=usage, version='%prog') parser.add_option('-s', '--show', action="store_true", dest='show', default=False, help=help['show']) options, args = parser.parse_args() mesh = Mesh.from_file(data_dir + '/meshes/2d/rectangle_tri.mesh') domain = FEDomain('domain', mesh) min_x, max_x = domain.get_mesh_bounding_box()[:, 0] eps = 1e-8 * (max_x - min_x) omega = domain.create_region('Omega', 'all') gamma1 = domain.create_region('Gamma1', 'vertices in x < %.10f' % (min_x + eps), 'facet') gamma2 = domain.create_region('Gamma2', 'vertices in x > %.10f' % (max_x - eps), 'facet') field = Field.from_args('fu', nm.float64, 'vector', omega, approx_order=2) u = FieldVariable('u', 'unknown', field) v = FieldVariable('v', 'test', field, primary_var_name='u') m = Material('m', D=stiffness_from_lame(dim=2, lam=1.0, mu=1.0)) f = Material('f', val=[[0.02], [0.01]]) integral = Integral('i', order=3) t1 = Term.new('dw_lin_elastic(m.D, v, u)', integral, omega, m=m, v=v, u=u) t2 = Term.new('dw_volume_lvf(f.val, v)', integral, omega, f=f, v=v) eq = Equation('balance', t1 + t2) eqs = Equations([eq]) fix_u = EssentialBC('fix_u', gamma1, {'u.all': 0.0}) bc_fun = Function('shift_u_fun', shift_u_fun, extra_args={'shift': 0.01}) shift_u = EssentialBC('shift_u', gamma2, {'u.0': bc_fun}) ls = ScipyDirect({}) nls_status = IndexedStruct() nls = Newton({}, lin_solver=ls, status=nls_status) pb = Problem('elasticity', equations=eqs, nls=nls, ls=ls) pb.save_regions_as_groups('regions') pb.time_update(ebcs=Conditions([fix_u, shift_u])) vec = pb.solve() print(nls_status) pb.save_state('linear_elasticity.vtk', vec) if options.show: view = Viewer('linear_elasticity.vtk') view(vector_mode='warp_norm', rel_scaling=2, is_scalar_bar=True, is_wireframe=True)
def main(): parser = ArgumentParser(description=__doc__.rstrip(), formatter_class=RawDescriptionHelpFormatter) parser.add_argument('output_dir', help=helps['output_dir']) parser.add_argument('--dims', metavar='dims', action='store', dest='dims', default='1.0,1.0,1.0', help=helps['dims']) parser.add_argument('--shape', metavar='shape', action='store', dest='shape', default='7,7,7', help=helps['shape']) parser.add_argument('--centre', metavar='centre', action='store', dest='centre', default='0.0,0.0,0.0', help=helps['centre']) parser.add_argument('-3', '--3d', action='store_true', dest='is_3d', default=False, help=helps['3d']) parser.add_argument('--order', metavar='int', type=int, action='store', dest='order', default=1, help=helps['order']) options = parser.parse_args() dim = 3 if options.is_3d else 2 dims = nm.array(eval(options.dims), dtype=nm.float64)[:dim] shape = nm.array(eval(options.shape), dtype=nm.int32)[:dim] centre = nm.array(eval(options.centre), dtype=nm.float64)[:dim] output('dimensions:', dims) output('shape: ', shape) output('centre: ', centre) mesh0 = gen_block_mesh(dims, shape, centre, name='block-fem', verbose=True) domain0 = FEDomain('d', mesh0) bbox = domain0.get_mesh_bounding_box() min_x, max_x = bbox[:, 0] eps = 1e-8 * (max_x - min_x) cnt = (shape[0] - 1) // 2 g0 = 0.5 * dims[0] grading = nm.array([g0 / 2**ii for ii in range(cnt)]) + eps + centre[0] - g0 domain, subs = refine_towards_facet(domain0, grading, 'x <') omega = domain.create_region('Omega', 'all') gamma1 = domain.create_region('Gamma1', 'vertices in (x < %.10f)' % (min_x + eps), 'facet') gamma2 = domain.create_region('Gamma2', 'vertices in (x > %.10f)' % (max_x - eps), 'facet') field = Field.from_args('fu', nm.float64, 1, omega, approx_order=options.order) if subs is not None: field.substitute_dofs(subs) u = FieldVariable('u', 'unknown', field) v = FieldVariable('v', 'test', field, primary_var_name='u') integral = Integral('i', order=2*options.order) t1 = Term.new('dw_laplace(v, u)', integral, omega, v=v, u=u) eq = Equation('eq', t1) eqs = Equations([eq]) def u_fun(ts, coors, bc=None, problem=None): """ Define a displacement depending on the y coordinate. """ if coors.shape[1] == 2: min_y, max_y = bbox[:, 1] y = (coors[:, 1] - min_y) / (max_y - min_y) val = (max_y - min_y) * nm.cos(3 * nm.pi * y) else: min_y, max_y = bbox[:, 1] min_z, max_z = bbox[:, 2] y = (coors[:, 1] - min_y) / (max_y - min_y) z = (coors[:, 2] - min_z) / (max_z - min_z) val = ((max_y - min_y) * (max_z - min_z) * nm.cos(3 * nm.pi * y) * (1.0 + 3.0 * (z - 0.5)**2)) return val bc_fun = Function('u_fun', u_fun) fix1 = EssentialBC('shift_u', gamma1, {'u.0' : bc_fun}) fix2 = EssentialBC('fix2', gamma2, {'u.all' : 0.0}) ls = ScipyDirect({}) nls = Newton({}, lin_solver=ls) pb = Problem('heat', equations=eqs, nls=nls, ls=ls) pb.time_update(ebcs=Conditions([fix1, fix2])) state = pb.solve() if subs is not None: field.restore_dofs() filename = os.path.join(options.output_dir, 'hanging.vtk') ensure_path(filename) pb.save_state(filename, state) if options.order > 1: pb.save_state(filename, state, linearization=Struct(kind='adaptive', min_level=0, max_level=8, eps=1e-3))
def main(argv=None): options = parse_args(argv=argv) # vvvvvvvvvvvvvvvv # approx_order = 2 # ^^^^^^^^^^^^^^^^ # # Setup output names outputs_folder = options.output_dir domain_name = "domain_1D" problem_name = "iburgers_1D" output_folder = pjoin(outputs_folder, problem_name, str(approx_order)) output_format = "vtk" save_timestn = 100 clear_folder(pjoin(output_folder, "*." + output_format)) configure_output({ 'output_screen': True, 'output_log_name': pjoin(output_folder, f"last_run_{problem_name}_{approx_order}.txt") }) # ------------ # | Get mesh | # ------------ X1 = 0. XN = 1. n_nod = 100 n_el = n_nod - 1 mesh = get_gen_1D_mesh_hook(X1, XN, n_nod).read(None) # ----------------------------- # | Create problem components | # ----------------------------- integral = Integral('i', order=approx_order * 2) domain = FEDomain(domain_name, mesh) omega = domain.create_region('Omega', 'all') left = domain.create_region('Gamma1', 'vertices in x == %.10f' % X1, 'vertex') right = domain.create_region('Gamma2', 'vertices in x == %.10f' % XN, 'vertex') field = DGField('dgfu', nm.float64, 'scalar', omega, approx_order=approx_order) u = FieldVariable('u', 'unknown', field, history=1) v = FieldVariable('v', 'test', field, primary_var_name='u') MassT = Term.new('dw_dot(v, u)', integral, omega, u=u, v=v) velo = nm.array(1.0) def adv_fun(u): vu = velo.T * u[..., None] return vu def adv_fun_d(u): v1 = velo.T * nm.ones(u.shape + (1, )) return v1 burg_velo = velo.T / nm.linalg.norm(velo) def burg_fun(u): vu = burg_velo * u[..., None]**2 return vu def burg_fun_d(u): v1 = 2 * burg_velo * u[..., None] return v1 StiffT = Term.new('dw_ns_dot_grad_s(fun, fun_d, u[-1], v)', integral, omega, u=u, v=v, fun=burg_fun, fun_d=burg_fun_d) # alpha = Material('alpha', val=[.0]) # FluxT = AdvectDGFluxTerm("adv_lf_flux(a.val, v, u)", "a.val, v, u[-1]", # integral, omega, u=u, v=v, a=a, alpha=alpha) FluxT = Term.new('dw_dg_nonlinear_laxfrie_flux(fun, fun_d, v, u[-1])', integral, omega, u=u, v=v, fun=burg_fun, fun_d=burg_fun_d) eq = Equation('balance', MassT - StiffT + FluxT) eqs = Equations([eq]) # ------------------------------ # | Create boundary conditions | # ------------------------------ left_fix_u = EssentialBC('left_fix_u', left, {'u.all': 1.0}) right_fix_u = EssentialBC('right_fix_u', right, {'u.all': 0.0}) # ---------------------------- # | Create initial condition | # ---------------------------- def ghump(x): """ Nice gaussian. """ return nm.exp(-200 * x**2) def ic_wrap(x, ic=None): return ghump(x - .3) ic_fun = Function('ic_fun', ic_wrap) ics = InitialCondition('ic', omega, {'u.0': ic_fun}) # ------------------ # | Create problem | # ------------------ pb = Problem(problem_name, equations=eqs, conf=Struct(options={"save_times": save_timestn}, ics={}, ebcs={}, epbcs={}, lcbcs={}, materials={}), active_only=False) pb.setup_output(output_dir=output_folder, output_format=output_format) pb.set_ics(Conditions([ics])) # ------------------ # | Create limiter | # ------------------ limiter = MomentLimiter1D # --------------------------- # | Set time discretization | # --------------------------- CFL = .2 max_velo = nm.max(nm.abs(velo)) t0 = 0 t1 = .2 dx = nm.min(mesh.cmesh.get_volumes(1)) dt = dx / max_velo * CFL / (2 * approx_order + 1) tn = int(nm.ceil((t1 - t0) / dt)) dtdx = dt / dx # ------------------ # | Create solver | # ------------------ ls = ScipyDirect({}) nls_status = IndexedStruct() nls = Newton({'is_linear': True}, lin_solver=ls, status=nls_status) tss_conf = { 't0': t0, 't1': t1, 'n_step': tn, 'limiters': { "dgfu": limiter } } tss = TVDRK3StepSolver(tss_conf, nls=nls, context=pb, verbose=True) # --------- # | Solve | # --------- pb.set_solver(tss) state_end = pb.solve() output("Solved equation \n\n\t\t u_t - div(f(u))) = 0\n") output(f"With IC: {ic_fun.name}") # output("and EBCs: {}".format(pb.ebcs.names)) # output("and EPBCS: {}".format(pb.epbcs.names)) output("-------------------------------------") output(f"Approximation order is {approx_order}") output(f"Space divided into {mesh.n_el} cells, " + f"{len(mesh.coors)} steps, step size is {dx}") output(f"Time divided into {tn - 1} nodes, {tn} steps, step size is {dt}") output(f"CFL coefficient was {CFL} and " + f"order correction {1 / (2 * approx_order + 1)}") output(f"Courant number c = max(abs(u)) * dt/dx = {max_velo * dtdx}") output("------------------------------------------") output(f"Time stepping solver is {tss.name}") output(f"Limiter used: {limiter.name}") output("======================================") # ---------- # | Plot 1D| # ---------- if options.plot: load_and_plot_fun(output_folder, domain_name, t0, t1, min(tn, save_timestn), ic_fun)
def main(): from sfepy import data_dir parser = OptionParser(usage=usage, version='%prog') parser.add_option('--diffusivity', metavar='float', type=float, action='store', dest='diffusivity', default=1e-5, help=helps['diffusivity']) parser.add_option('--ic-max', metavar='float', type=float, action='store', dest='ic_max', default=2.0, help=helps['ic_max']) parser.add_option('--order', metavar='int', type=int, action='store', dest='order', default=2, help=helps['order']) parser.add_option('-r', '--refine', metavar='int', type=int, action='store', dest='refine', default=0, help=helps['refine']) parser.add_option('-p', '--probe', action="store_true", dest='probe', default=False, help=helps['probe']) parser.add_option('-s', '--show', action="store_true", dest='show', default=False, help=helps['show']) options, args = parser.parse_args() assert_((0 < options.order), 'temperature approximation order must be at least 1!') output('using values:') output(' diffusivity:', options.diffusivity) output(' max. IC value:', options.ic_max) output('uniform mesh refinement level:', options.refine) mesh = Mesh.from_file(data_dir + '/meshes/3d/cylinder.mesh') domain = FEDomain('domain', mesh) if options.refine > 0: for ii in xrange(options.refine): output('refine %d...' % ii) domain = domain.refine() output('... %d nodes %d elements' % (domain.shape.n_nod, domain.shape.n_el)) omega = domain.create_region('Omega', 'all') left = domain.create_region('Left', 'vertices in x < 0.00001', 'facet') right = domain.create_region('Right', 'vertices in x > 0.099999', 'facet') field = Field.from_args('fu', nm.float64, 'scalar', omega, approx_order=options.order) T = FieldVariable('T', 'unknown', field, history=1) s = FieldVariable('s', 'test', field, primary_var_name='T') m = Material('m', diffusivity=options.diffusivity * nm.eye(3)) integral = Integral('i', order=2 * options.order) t1 = Term.new('dw_diffusion(m.diffusivity, s, T)', integral, omega, m=m, s=s, T=T) t2 = Term.new('dw_volume_dot(s, dT/dt)', integral, omega, s=s, T=T) eq = Equation('balance', t1 + t2) eqs = Equations([eq]) # Boundary conditions. ebc1 = EssentialBC('T1', left, {'T.0': 2.0}) ebc2 = EssentialBC('T2', right, {'T.0': -2.0}) # Initial conditions. def get_ic(coors, ic): x, y, z = coors.T return 2 - 40.0 * x + options.ic_max * nm.sin(4 * nm.pi * x / 0.1) ic_fun = Function('ic_fun', get_ic) ic = InitialCondition('ic', omega, {'T.0': ic_fun}) ls = ScipyDirect({}) nls_status = IndexedStruct() nls = Newton({'is_linear': True}, lin_solver=ls, status=nls_status) pb = Problem('heat', equations=eqs, nls=nls, ls=ls) pb.set_bcs(ebcs=Conditions([ebc1, ebc2])) pb.set_ics(Conditions([ic])) tss = SimpleTimeSteppingSolver({ 't0': 0.0, 't1': 100.0, 'n_step': 11 }, problem=pb) tss.init_time() if options.probe: # Prepare probe data. probes, labels = gen_lines(pb) ev = pb.evaluate order = 2 * (options.order - 1) gfield = Field.from_args('gu', nm.float64, 'vector', omega, approx_order=options.order - 1) dvel = FieldVariable('dvel', 'parameter', gfield, primary_var_name='(set-to-None)') cfield = Field.from_args('gu', nm.float64, 'scalar', omega, approx_order=options.order - 1) component = FieldVariable('component', 'parameter', cfield, primary_var_name='(set-to-None)') nls_options = {'eps_a': 1e-16, 'i_max': 1} if options.show: plt.ion() # Solve the problem using the time stepping solver. suffix = tss.ts.suffix for step, time, state in tss(): if options.probe: # Probe the solution. dvel_qp = ev('ev_diffusion_velocity.%d.Omega(m.diffusivity, T)' % order, copy_materials=False, mode='qp') project_by_component(dvel, dvel_qp, component, order, nls_options=nls_options) all_results = [] for ii, probe in enumerate(probes): fig, results = probe_results(ii, T, dvel, probe, labels[ii]) all_results.append(results) plt.tight_layout() fig.savefig('time_poisson_interactive_probe_%s.png' % (suffix % step), bbox_inches='tight') if options.show: plt.draw() for ii, results in enumerate(all_results): output('probe %d (%s):' % (ii, probes[ii].name)) output.level += 2 for key, res in ordered_iteritems(results): output(key + ':') val = res[1] output(' min: %+.2e, mean: %+.2e, max: %+.2e' % (val.min(), val.mean(), val.max())) output.level -= 2
def create_local_problem(omega_gi, order): """ Local problem definition using a domain corresponding to the global region `omega_gi`. """ mesh = omega_gi.domain.mesh # All tasks have the whole mesh. bbox = mesh.get_bounding_box() min_x, max_x = bbox[:, 0] eps_x = 1e-8 * (max_x - min_x) mesh_i = Mesh.from_region(omega_gi, mesh, localize=True) domain_i = FEDomain('domain_i', mesh_i) omega_i = domain_i.create_region('Omega', 'all') gamma1_i = domain_i.create_region('Gamma1', 'vertices in (x < %.10f)' % (min_x + eps_x), 'facet', allow_empty=True) gamma2_i = domain_i.create_region('Gamma2', 'vertices in (x > %.10f)' % (max_x - eps_x), 'facet', allow_empty=True) field_i = Field.from_args('fu', nm.float64, 1, omega_i, approx_order=order) output('number of local field DOFs:', field_i.n_nod) u_i = FieldVariable('u_i', 'unknown', field_i) v_i = FieldVariable('v_i', 'test', field_i, primary_var_name='u_i') integral = Integral('i', order=2 * order) mat = Material('m', lam=10, mu=5) t1 = Term.new('dw_laplace(m.lam, v_i, u_i)', integral, omega_i, m=mat, v_i=v_i, u_i=u_i) def _get_load(coors): val = nm.ones_like(coors[:, 0]) for coor in coors.T: val *= nm.sin(4 * nm.pi * coor) return val def get_load(ts, coors, mode=None, **kwargs): if mode == 'qp': return {'val': _get_load(coors).reshape(coors.shape[0], 1, 1)} load = Material('load', function=Function('get_load', get_load)) t2 = Term.new('dw_volume_lvf(load.val, v_i)', integral, omega_i, load=load, v_i=v_i) eq = Equation('balance', t1 - 100 * t2) eqs = Equations([eq]) ebc1 = EssentialBC('ebc1', gamma1_i, {'u_i.all': 0.0}) ebc2 = EssentialBC('ebc2', gamma2_i, {'u_i.all': 0.1}) pb = Problem('problem_i', equations=eqs, active_only=False) pb.time_update(ebcs=Conditions([ebc1, ebc2])) pb.update_materials() return pb
def main(cli_args): dims = parse_argument_list(cli_args.dims, float) shape = parse_argument_list(cli_args.shape, int) centre = parse_argument_list(cli_args.centre, float) material_parameters = parse_argument_list(cli_args.material_parameters, float) order = cli_args.order ts_vals = cli_args.ts.split(',') ts = { 't0': float(ts_vals[0]), 't1': float(ts_vals[1]), 'n_step': int(ts_vals[2]) } do_plot = cli_args.plot ### Mesh and regions ### mesh = gen_block_mesh(dims, shape, centre, name='block', verbose=False) domain = FEDomain('domain', mesh) omega = domain.create_region('Omega', 'all') lbn, rtf = domain.get_mesh_bounding_box() box_regions = define_box_regions(3, lbn, rtf) regions = dict( [[r, domain.create_region(r, box_regions[r][0], box_regions[r][1])] for r in box_regions]) ### Fields ### scalar_field = Field.from_args('fu', np.float64, 'scalar', omega, approx_order=order - 1) vector_field = Field.from_args('fv', np.float64, 'vector', omega, approx_order=order) u = FieldVariable('u', 'unknown', vector_field, history=1) v = FieldVariable('v', 'test', vector_field, primary_var_name='u') p = FieldVariable('p', 'unknown', scalar_field, history=1) q = FieldVariable('q', 'test', scalar_field, primary_var_name='p') ### Material ### c10, c01 = material_parameters m = Material( 'm', mu=2 * c10, kappa=2 * c01, ) ### Boundary conditions ### x_sym = EssentialBC('x_sym', regions['Left'], {'u.0': 0.0}) y_sym = EssentialBC('y_sym', regions['Near'], {'u.1': 0.0}) z_sym = EssentialBC('z_sym', regions['Bottom'], {'u.2': 0.0}) disp_fun = Function('disp_fun', get_displacement) displacement = EssentialBC('displacement', regions['Right'], {'u.0': disp_fun}) ebcs = Conditions([x_sym, y_sym, z_sym, displacement]) ### Terms and equations ### integral = Integral('i', order=2 * order) term_neohook = Term.new('dw_tl_he_neohook(m.mu, v, u)', integral, omega, m=m, v=v, u=u) term_mooney = Term.new('dw_tl_he_mooney_rivlin(m.kappa, v, u)', integral, omega, m=m, v=v, u=u) term_pressure = Term.new('dw_tl_bulk_pressure(v, u, p)', integral, omega, v=v, u=u, p=p) term_volume_change = Term.new('dw_tl_volume(q, u)', integral, omega, q=q, u=u, term_mode='volume') term_volume = Term.new('dw_volume_integrate(q)', integral, omega, q=q) eq_balance = Equation('balance', term_neohook + term_mooney + term_pressure) eq_volume = Equation('volume', term_volume_change - term_volume) equations = Equations([eq_balance, eq_volume]) ### Solvers ### ls = ScipyDirect({}) nls_status = IndexedStruct() nls = Newton({'i_max': 5}, lin_solver=ls, status=nls_status) ### Problem ### pb = Problem('hyper', equations=equations) pb.set_bcs(ebcs=ebcs) pb.set_ics(ics=Conditions([])) tss = SimpleTimeSteppingSolver(ts, nls=nls, context=pb) pb.set_solver(tss) ### Solution ### axial_stress = [] axial_displacement = [] def stress_strain_fun(*args, **kwargs): return stress_strain(*args, order=order, global_stress=axial_stress, global_displacement=axial_displacement, **kwargs) pb.solve(save_results=True, post_process_hook=stress_strain_fun) if do_plot: plot_graphs(material_parameters, axial_stress, axial_displacement, undeformed_length=dims[0])
def find_level_interface(domain, refine_flag): """ Find facets of the coarse mesh that are on the coarse-refined cell boundary. ids w.r.t. current mesh: - facets: global, local w.r.t. cells[:, 0], local w.r.t. cells[:, 1] - interface cells: - cells[:, 0] - cells to refine - cells[:, 1] - their facet sharing neighbors (w.r.t. both meshes) - cells[:, 2] - facet kind: 0 = face, 1 = edge """ if not refine_flag.any(): facets = nm.zeros((0, 3), dtype=nm.uint32) cells = nm.zeros((0, 3), dtype=nm.uint32) return facets, cells, 0, None, None def _get_refine(coors, domain=None): return nm.nonzero(refine_flag)[0] def _get_coarse(coors, domain=None): return nm.nonzero(1 - refine_flag)[0] get_refine = Function('get_refine', _get_refine) get_coarse = Function('get_coarse', _get_coarse) functions = Functions([get_refine, get_coarse]) region0 = domain.create_region('coarse', 'cells by get_coarse', functions=functions, add_to_regions=False, allow_empty=True) region1 = domain.create_region('refine', 'cells by get_refine', functions=functions, add_to_regions=False) cmesh = domain.mesh.cmesh dim = cmesh.dim if dim == 2: oe = 0 facets = nm.intersect1d(region0.facets, region1.facets) cmesh.setup_connectivity(dim - 1, dim) cells, offs = cmesh.get_incident(dim, facets, dim - 1, ret_offsets=True) assert_((nm.diff(offs) == 2).all()) ii = cmesh.get_local_ids(facets, dim - 1, cells, offs, dim) ii = ii.reshape((-1, 2)) cells = cells.reshape((-1, 2)) ii = nm.where(refine_flag[cells], ii[:, :1], ii[:, 1:]) cells = nm.where(refine_flag[cells], cells[:, :1], cells[:, 1:]) facets = nm.c_[facets, ii] cells = nm.c_[cells, nm.zeros_like(cells[:, 1])] else: # if dim == 3: gel = domain.geom_els['3_8'] epf = gel.get_edges_per_face() cmesh.setup_connectivity(dim, dim) fc, coffs = cmesh.get_incident(dim, region1.cells, dim, ret_offsets=True) cc = nm.repeat(region1.cells, nm.diff(coffs)) aux = nm.c_[cc, fc] """ nnn[:, 0] cells to refine, nnn[:, 1] non-refined neighbours, nnn[:, 2] neighbour kind : 0 face, 1 edge. """ nn = aux[refine_flag[fc] == 0] cf = nn[:, 0].copy().astype(nm.uint32) cc = nn[:, 1].copy().astype(nm.uint32) vc, vco = cmesh.get_incident(0, cc, dim, ret_offsets=True) vf, vfo = cmesh.get_incident(0, cf, dim, ret_offsets=True) vc = vc.reshape((-1, 8)) vf = vf.reshape((-1, 8)) nnn = [] oe = 0 ov = nn.shape[0] for ii in range(vc.shape[0]): aux = set(vc[ii]).intersection(vf[ii]) nc = len(aux) if nc == 1: nnn.append((0, 0, 2)) ov -= 1 elif nc == 4: nnn.append((nn[ii, 0], nn[ii, 1], 0)) oe += 1 else: nnn.append((nn[ii, 0], nn[ii, 1], 1)) nnn = nm.array(nnn) if nnn.shape[0] == 0: facets = nm.zeros((0, 3), dtype=nm.uint32) cells = nm.zeros((0, 4), dtype=nm.uint32) return facets, cells, 0, region0, region1 # Sort by neighbour kind, skip vertex-only neighbours. ii = nm.argsort(nnn[:, 2]) nnn = nnn[ii][:ov] cf = cf[ii][:ov] cc = cc[ii][:ov] ec, eco = cmesh.get_incident(1, cc, dim, ret_offsets=True) ef, efo = cmesh.get_incident(1, cf, dim, ret_offsets=True) ec = ec.reshape((-1, 12)) ef = ef.reshape((-1, 12)) fc, fco = cmesh.get_incident(2, cc, dim, ret_offsets=True) ff, ffo = cmesh.get_incident(2, cf, dim, ret_offsets=True) fc = fc.reshape((-1, 6)) ff = ff.reshape((-1, 6)) emask = nm.zeros((domain.shape.n_el, 12), dtype=nm.bool) ffs = [] for ii in range(oe): facet = nm.intersect1d(fc[ii], ff[ii])[0] i1 = nm.where(ff[ii] == facet)[0][0] i0 = nm.where(fc[ii] == facet)[0][0] ffs.append((facet, i1, i0)) emask[nnn[ii, 0], epf[i1]] = True for ii in range(oe, nnn.shape[0]): facet = nm.intersect1d(ec[ii], ef[ii])[0] i1 = nm.where(ef[ii] == facet)[0][0] i0 = nm.where(ec[ii] == facet)[0][0] ffs.append((facet, i1, i0)) ffs = nm.array(ffs) ie = nm.where(nnn[:, 2] == 1)[0] ennn = nnn[ie] effs = ffs[ie] omit = ie[emask[ennn[:, 0], effs[:, 1]]] valid = nm.ones(nnn.shape[0], dtype=nm.bool) valid[omit] = False cells = nnn[valid] facets = ffs[valid] return facets, cells, oe, region0, region1
def set_bc_impl(ts, coors, bc=None, problem=None, **kwargs): x = coors[:, 0] y = coors[:, 1] val = np.sin(x / np.pi) * np.sin(y / np.pi) # val = 0*x # val = 0.0001*np.ones(x.size) return val # fix_u = EssentialBC('fix_u', omega, {'u.all' : 0.0}) # bc1 = EssentialBC('Gamma_Left', gammaL, {'t.0' : -20.0}) # bc2 = EssentialBC('Gamma_Right', gammaR, {'t.0' : 20.0}) set_bc_fun = Function('set_bc_impl', set_bc_impl) bc1 = EssentialBC('Gamma_Left', gammaL, {'t.0': set_bc_fun}) bc2 = EssentialBC('Gamma_Right', gammaR, {'t.0': set_bc_fun}) bc3 = EssentialBC('Gamma_Top', gammaT, {'t.0': set_bc_fun}) bc4 = EssentialBC('Gamma_Bottom', gammaB, {'t.0': set_bc_fun}) ls = ScipyDirect({}) nls_status = IndexedStruct() newtonConfig = {'i_max': 10, 'eps_a': 1e-10, 'eps_r': 1} nls = Newton(newtonConfig, lin_solver=ls, status=nls_status) pb = Problem('Poisson', equations=eqs, nls=nls, ls=ls) pb.save_regions_as_groups('regions')
def create_local_problem(omega_gi, orders): """ Local problem definition using a domain corresponding to the global region `omega_gi`. """ order_u, order_p = orders mesh = omega_gi.domain.mesh # All tasks have the whole mesh. bbox = mesh.get_bounding_box() min_x, max_x = bbox[:, 0] eps_x = 1e-8 * (max_x - min_x) min_y, max_y = bbox[:, 1] eps_y = 1e-8 * (max_y - min_y) mesh_i = Mesh.from_region(omega_gi, mesh, localize=True) domain_i = FEDomain('domain_i', mesh_i) omega_i = domain_i.create_region('Omega', 'all') gamma1_i = domain_i.create_region('Gamma1', 'vertices in (x < %.10f)' % (min_x + eps_x), 'facet', allow_empty=True) gamma2_i = domain_i.create_region('Gamma2', 'vertices in (x > %.10f)' % (max_x - eps_x), 'facet', allow_empty=True) gamma3_i = domain_i.create_region('Gamma3', 'vertices in (y < %.10f)' % (min_y + eps_y), 'facet', allow_empty=True) field1_i = Field.from_args('fu', nm.float64, mesh.dim, omega_i, approx_order=order_u) field2_i = Field.from_args('fp', nm.float64, 1, omega_i, approx_order=order_p) output('field 1: number of local DOFs:', field1_i.n_nod) output('field 2: number of local DOFs:', field2_i.n_nod) u_i = FieldVariable('u_i', 'unknown', field1_i, order=0) v_i = FieldVariable('v_i', 'test', field1_i, primary_var_name='u_i') p_i = FieldVariable('p_i', 'unknown', field2_i, order=1) q_i = FieldVariable('q_i', 'test', field2_i, primary_var_name='p_i') if mesh.dim == 2: alpha = 1e2 * nm.array([[0.132], [0.132], [0.092]]) else: alpha = 1e2 * nm.array([[0.132], [0.132], [0.132], [0.092], [0.092], [0.092]]) mat = Material('m', D=stiffness_from_lame(mesh.dim, lam=10, mu=5), k=1, alpha=alpha) integral = Integral('i', order=2*(max(order_u, order_p))) t11 = Term.new('dw_lin_elastic(m.D, v_i, u_i)', integral, omega_i, m=mat, v_i=v_i, u_i=u_i) t12 = Term.new('dw_biot(m.alpha, v_i, p_i)', integral, omega_i, m=mat, v_i=v_i, p_i=p_i) t21 = Term.new('dw_biot(m.alpha, u_i, q_i)', integral, omega_i, m=mat, u_i=u_i, q_i=q_i) t22 = Term.new('dw_laplace(m.k, q_i, p_i)', integral, omega_i, m=mat, q_i=q_i, p_i=p_i) eq1 = Equation('eq1', t11 - t12) eq2 = Equation('eq1', t21 + t22) eqs = Equations([eq1, eq2]) ebc1 = EssentialBC('ebc1', gamma1_i, {'u_i.all' : 0.0}) ebc2 = EssentialBC('ebc2', gamma2_i, {'u_i.0' : 0.05}) def bc_fun(ts, coors, **kwargs): val = 0.3 * nm.sin(4 * nm.pi * (coors[:, 0] - min_x) / (max_x - min_x)) return val fun = Function('bc_fun', bc_fun) ebc3 = EssentialBC('ebc3', gamma3_i, {'p_i.all' : fun}) pb = Problem('problem_i', equations=eqs, active_only=False) pb.time_update(ebcs=Conditions([ebc1, ebc2, ebc3])) pb.update_materials() return pb
# ------------------------------ # | Create bounrady conditions | # ------------------------------ left_fix_u = EssentialBC('left_fix_u', left, {'u.all': 1.0}) right_fix_u = EssentialBC('right_fix_u', right, {'u.all': 0.0}) # ---------------------------- # | Create initial condition | # ---------------------------- def ic_wrap(x, ic=None): return ghump(x - .3) ic_fun = Function('ic_fun', ic_wrap) ics = InitialCondition('ic', omega, {'u.0': ic_fun}) # ------------------ # | Create problem | # ------------------ pb = Problem(problem_name, equations=eqs, conf=Struct(options={"save_times": save_timestn}, ics={}, ebcs={}, epbcs={}, lcbcs={}, materials={}), active_only=False) pb.setup_output(output_dir=output_folder, output_format=output_format)
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