def __init__(self, stencil, moment_polynomials, equilibrium_density, equilibrium_velocity, conserved_quantity_equations=None, **kwargs): super(FastCentralMomentTransform, self).__init__( stencil, moment_polynomials, equilibrium_density, equilibrium_velocity, conserved_quantity_equations=conserved_quantity_equations, **kwargs) # Potentially, de-aliasing is required if len(self.moment_exponents) != self.q: P, m_reduced = central_moment_reduced_monomial_to_polynomial_matrix(self.moment_polynomials, self.stencil, velocity_symbols=equilibrium_velocity) self.mono_to_poly_matrix = P self.moment_exponents = m_reduced else: self.mono_to_poly_matrix = monomial_to_polynomial_transformation_matrix(self.moment_exponents, self.moment_polynomials) self.poly_to_mono_matrix = self.mono_to_poly_matrix.inv() moment_matrix_without_shift = moment_matrix(self.moment_exponents, self.stencil) shift_matrix = set_up_shift_matrix(self.moment_exponents, self.stencil, equilibrium_velocity) self.inv_monomial_matrix = moment_matrix_without_shift.inv() * shift_matrix.inv()
def __init__(self, stencil, moment_polynomials, equilibrium_density, equilibrium_velocity, conserved_quantity_equations=None, **kwargs): super(PdfsToCentralMomentsByShiftMatrix, self).__init__( stencil, moment_polynomials, equilibrium_density, equilibrium_velocity, conserved_quantity_equations=conserved_quantity_equations, **kwargs) # Potentially, de-aliasing is required if len(self.moment_exponents) != self.q: P, m_reduced = central_moment_reduced_monomial_to_polynomial_matrix(self.moment_polynomials, self.stencil, velocity_symbols=equilibrium_velocity) self.mono_to_poly_matrix = P self.moment_exponents = m_reduced else: self.mono_to_poly_matrix = monomial_to_polynomial_transformation_matrix(self.moment_exponents, self.moment_polynomials) if 'moment_exponents' in kwargs: del kwargs['moment_exponents'] self.raw_moment_transform = PdfsToMomentsByChimeraTransform( stencil, None, equilibrium_density, equilibrium_velocity, conserved_quantity_equations=conserved_quantity_equations, moment_exponents=self.moment_exponents, **kwargs) self.shift_matrix = set_up_shift_matrix(self.moment_exponents, self.stencil, self.equilibrium_velocity) self.inv_shift_matrix = self.shift_matrix.inv() self.poly_to_mono_matrix = self.mono_to_poly_matrix.inv()
def __init__(self, stencil, moment_polynomials, equilibrium_density, equilibrium_velocity, **kwargs): super(PdfsToCentralMomentsByMatrix, self).__init__( stencil, moment_polynomials, equilibrium_density, equilibrium_velocity, **kwargs) moment_matrix_without_shift = moment_matrix(self.moment_polynomials, self.stencil) shift_matrix = set_up_shift_matrix(self.moment_polynomials, self.stencil, equilibrium_velocity) self.forward_matrix = shift_matrix * moment_matrix_without_shift self.backward_matrix = moment_matrix_without_shift.inv() * shift_matrix.inv()
def backward_transform(self, pdf_symbols, simplification=True, subexpression_base='sub_k_to_f', start_from_monomials=False): r"""Returns an assignment collection containing equations for post-collision populations, expressed in terms of the post-collision polynomial central moments by matrix-multiplication. The moment transformation matrix :math:`K` provided by :func:`lbmpy.moments.moment_matrix` is inverted and used to compute the pre-collision moments as :math:`\mathbf{f}^{\ast} = K^{-1} \cdot \mathbf{K}_{\mathrm{post}}`, which is returned element-wise. Args: pdf_symbols: List of symbols that represent the post-collision populations simplification: Simplification specification. See :class:`AbstractMomentTransform` subexpression_base: The base name used for any subexpressions of the transformation. start_from_monomials: Return equations for monomial moments. Use only when specifying ``moment_exponents`` in constructor! """ simplification = self._get_simp_strategy(simplification) if start_from_monomials: assert len(self.moment_exponents) == self.q, "Could not derive invertible monomial transform." \ f"Expected {self.q} monomials, but got {len(self.moment_exponents)}." mm_inv = moment_matrix(self.moment_exponents, self.stencil).inv() shift_inv = set_up_shift_matrix(self.moment_exponents, self.stencil, self.equilibrium_velocity).inv() km_inv = mm_inv * shift_inv post_collision_moments = self.post_collision_monomial_symbols else: km_inv = self.backward_matrix post_collision_moments = self.post_collision_symbols m_to_f_vec = km_inv * sp.Matrix(post_collision_moments) main_assignments = [Assignment(f, eq) for f, eq in zip(pdf_symbols, m_to_f_vec)] symbol_gen = SymbolGen(subexpression_base) ac = AssignmentCollection(main_assignments, subexpression_symbol_generator=symbol_gen) if simplification: ac = simplification.apply(ac) return ac
def continuous_force_central_moments(self, lb_method): raw_moments = self.continuous_force_raw_moments(lb_method) u = lb_method.first_order_equilibrium_moment_symbols shift_matrix = set_up_shift_matrix(lb_method.moments, lb_method.stencil, velocity_symbols=u) return (shift_matrix * raw_moments).expand()
def shift_matrix(self): return set_up_shift_matrix(self.moments, self.stencil)
def create_with_discrete_maxwellian_eq_moments( stencil, moment_to_relaxation_rate_dict, compressible=False, force_model=None, equilibrium_order=2, c_s_sq=sp.Rational(1, 3), central_moment_space=False, moment_transform_class=None, central_moment_transform_class=PdfsToCentralMomentsByShiftMatrix): r"""Creates a moment-based LBM by taking a list of moments with corresponding relaxation rate. These moments are relaxed against the moments of the discrete Maxwellian distribution. Args: stencil: instance of :class:`lbmpy.stencils.LBStenil` moment_to_relaxation_rate_dict: dict that has as many entries as the stencil. Each moment, which can be represented by an exponent tuple or in polynomial form (see `lbmpy.moments`), is mapped to a relaxation rate. compressible: incompressible LBM methods split the density into :math:`\rho = \rho_0 + \Delta \rho` where :math:`\rho_0` is chosen as one, and the first moment of the pdfs is :math:`\Delta \rho` . This approximates the incompressible Navier-Stokes equations better than the standard compressible model. force_model: force model instance, or None if no external forces equilibrium_order: approximation order of macroscopic velocity :math:`\mathbf{u}` in the equilibrium c_s_sq: Speed of sound squared central_moment_space: If set to True, an instance of :class:`lbmpy.methods.momentbased.CentralMomentBasedLbMethod` is returned, and the the collision will be performed in the central moment space. moment_transform_class: Class implementing the transform from populations to moment space. central_moment_transform_class: Class implementing the transform from populations to central moment space. Returns: Instance of either :class:`lbmpy.methods.momentbased.MomentBasedLbMethod` or :class:`lbmpy.methods.momentbased.CentralMomentBasedLbMethod` """ mom_to_rr_dict = OrderedDict(moment_to_relaxation_rate_dict) assert len(mom_to_rr_dict) == stencil.Q, \ "The number of moments has to be the same as the number of stencil entries" density_velocity_computation = DensityVelocityComputation( stencil, compressible, force_model) moments = tuple(mom_to_rr_dict.keys()) eq_values = get_moments_of_discrete_maxwellian_equilibrium( stencil, moments, c_s_sq=c_s_sq, compressible=compressible, order=equilibrium_order) if central_moment_space: N = set_up_shift_matrix(moments, stencil) eq_values = sp.simplify(N * sp.Matrix(eq_values)) rr_dict = OrderedDict([ (mom, RelaxationInfo(eq_mom, rr)) for mom, rr, eq_mom in zip( mom_to_rr_dict.keys(), mom_to_rr_dict.values(), eq_values) ]) if central_moment_space: return CentralMomentBasedLbMethod(stencil, rr_dict, density_velocity_computation, force_model, central_moment_transform_class) else: return MomentBasedLbMethod(stencil, rr_dict, density_velocity_computation, force_model, moment_transform_class)
def test_central_moment_class(): stencil = LBStencil(Stencil.D2Q9) lbm_config = LBMConfig(stencil=stencil, method=Method.CENTRAL_MOMENT, relaxation_rates=[1.2, 1.3, 1.4, 1.5], equilibrium_order=4, compressible=True) method = create_lb_method(lbm_config=lbm_config) lbm_config = LBMConfig(stencil=stencil, method=Method.SRT, relaxation_rate=1.2, equilibrium_order=4, compressible=True) srt = create_lb_method(lbm_config=lbm_config) rho = method.zeroth_order_equilibrium_moment_symbol u = method.first_order_equilibrium_moment_symbols cs_sq = sp.Rational(1, 3) force_model = Luo(force=sp.symbols(f"F_:{2}")) eq = (rho, 0, 0, 0, 0, 2 * rho * cs_sq, 0, 0, rho * cs_sq**2) default_moments = cascaded_moment_sets_literature(stencil) default_moments = [item for sublist in default_moments for item in sublist] assert method.central_moment_transform_class == PdfsToCentralMomentsByShiftMatrix assert method.conserved_quantity_computation.zeroth_order_moment_symbol == rho assert method.conserved_quantity_computation.first_order_moment_symbols == u assert method.moment_equilibrium_values == eq assert method.force_model is None method.set_force_model(force_model) assert method.force_model == force_model assert method.relaxation_matrix[0, 0] == 0 assert method.relaxation_matrix[1, 1] == 0 assert method.relaxation_matrix[2, 2] == 0 method.set_conserved_moments_relaxation_rate(1.9) assert method.relaxation_matrix[0, 0] == 1.9 assert method.relaxation_matrix[1, 1] == 1.9 assert method.relaxation_matrix[2, 2] == 1.9 moments = list() for i in method.relaxation_info_dict: moments.append(i) assert moments == default_moments for i in range(len(stencil)): assert method.relaxation_rates[i] == method.relaxation_matrix[i, i] M = method.moment_matrix N = method.shift_matrix assert M == moment_matrix(moments, stencil=stencil) assert N == set_up_shift_matrix(moments, stencil=stencil) assert get_weights(stencil) == method.weights eq_terms_central = method.get_equilibrium_terms() eq_terms_srt = srt.get_equilibrium_terms() for i in range(len(stencil)): assert sp.simplify(eq_terms_central[i] - eq_terms_srt[i]) == 0 method = create_lb_method( lbm_config=LBMConfig(stencil=LBStencil(Stencil.D2Q9), method=Method.CENTRAL_MOMENT, relaxation_rates=[1.7, 1.8, 1.2, 1.3, 1.4], equilibrium_order=4, compressible=True)) assert method.relaxation_matrix[0, 0] == 0 assert method.relaxation_matrix[1, 1] == 0 assert method.relaxation_matrix[2, 2] == 0 method = create_lb_method( lbm_config=LBMConfig(stencil=LBStencil(Stencil.D2Q9), method=Method.CENTRAL_MOMENT, relaxation_rates=[1.3] * 9, equilibrium_order=4, compressible=True)) np.testing.assert_almost_equal(sum(method.relaxation_rates), 1.3 * 9)