def get_additional_code_nodes(self, lb_method): """Return a list of code nodes that will be added in the generated code before the index field loop. Args: lb_method: Lattice Boltzmann method. See :func:`lbmpy.creationfunctions.create_lb_method` Returns: list containing NeighbourOffsetArrays """ return [NeighbourOffsetArrays(lb_method.stencil)]
def __call__(self, f_out, f_in, dir_symbol, inv_dir, lb_method, index_field): vel_from_idx_field = callable(self._velocity) vel = [index_field(f'vel_{i}') for i in range(self.dim)] if vel_from_idx_field else self._velocity assert self.dim == lb_method.dim, \ f"Dimension of UBB ({self.dim}) does not match dimension of method ({lb_method.dim})" neighbor_offset = NeighbourOffsetArrays.neighbour_offset(dir_symbol, lb_method.stencil) velocity = tuple(v_i.get_shifted(*neighbor_offset) if isinstance(v_i, Field.Access) and not vel_from_idx_field else v_i for v_i in vel) if self._adaptVelocityToForce: cqc = lb_method.conserved_quantity_computation shifted_vel_eqs = cqc.equilibrium_input_equations_from_init_values(velocity=velocity) shifted_vel_eqs = shifted_vel_eqs.new_without_subexpressions() velocity = [eq.rhs for eq in shifted_vel_eqs.new_filtered(cqc.first_order_moment_symbols).main_assignments] c_s_sq = sp.Rational(1, 3) weight_info = LbmWeightInfo(lb_method, data_type=self.data_type) weight_of_direction = weight_info.weight_of_direction vel_term = 2 / c_s_sq * sum([d_i * v_i for d_i, v_i in zip(neighbor_offset, velocity)]) * weight_of_direction( dir_symbol, lb_method) # Better alternative: in conserved value computation # rename what is currently called density to "virtual_density" # provide a new quantity density, which is constant in case of incompressible models if not lb_method.conserved_quantity_computation.zero_centered_pdfs: cqc = lb_method.conserved_quantity_computation density_symbol = sp.Symbol("rho") pdf_field_accesses = [f_out(i) for i in range(len(lb_method.stencil))] density_equations = cqc.output_equations_from_pdfs(pdf_field_accesses, {'density': density_symbol}) density_symbol = lb_method.conserved_quantity_computation.defined_symbols()['density'] result = density_equations.all_assignments result += [Assignment(f_in(inv_dir[dir_symbol]), f_out(dir_symbol) - vel_term * density_symbol)] return result else: return [Assignment(f_in(inv_dir[dir_symbol]), f_out(dir_symbol) - vel_term)]
def __call__(self, f_out, f_in, dir_symbol, inv_dir, lb_method, index_field): subexpressions = [] boundary_assignments = [] dtdx = sp.Rational(self.dt, self.dx) neighbor_offset = NeighbourOffsetArrays.neighbour_offset(dir_symbol, lb_method.stencil) tangential_offset = tuple(offset - normal for offset, normal in zip(neighbor_offset, self.normal_direction)) interpolated_pdf_sym = sp.Symbol('pdf_inter') interpolated_pdf_asm = Assignment(interpolated_pdf_sym, (index_field[0]('pdf') * (self.c * dtdx)) + ((sp.Number(1) - self.c * dtdx) * index_field[0]('pdf_nd'))) subexpressions.append(interpolated_pdf_asm) asm = Assignment(f_in.center(inv_dir[dir_symbol]), interpolated_pdf_sym) boundary_assignments.append(asm) asm = Assignment(index_field[0]('pdf'), f_out[tangential_offset](inv_dir[dir_symbol])) boundary_assignments.append(asm) asm = Assignment(index_field[0]('pdf_nd'), interpolated_pdf_sym) boundary_assignments.append(asm) return AssignmentCollection(boundary_assignments, subexpressions=subexpressions)
def __call__(self, f_out, f_in, dir_symbol, inv_dir, lb_method, index_field): neighbour_offset = NeighbourOffsetArrays.neighbour_offset(dir_symbol, lb_method.stencil) return [Assignment(f_in(inv_dir[dir_symbol]), self.constant), Assignment(f_out[neighbour_offset](dir_symbol), self.constant)]
def __call__(self, f_out, f_in, dir_symbol, inv_dir, lb_method, index_field): neighbor_offset = NeighbourOffsetArrays.neighbour_offset(dir_symbol, lb_method.stencil) tangential_offset = tuple(offset - normal for offset, normal in zip(neighbor_offset, self.normal_direction)) return Assignment(f_in.center(inv_dir[dir_symbol]), f_out[tangential_offset](inv_dir[dir_symbol]))