def test_cumulants_from_pdfs(): """ Tests if the following transformations are equivalent: - directly pdfs to cumulant - indirect pdfs -> raw moments -> cumulants """ stencil = LBStencil(Stencil.D2Q9) indices = moments_up_to_component_order(2, dim=stencil.D) pdf_symbols = sp.symbols(f"f_:{stencil.Q}") direct_version = cumulants_from_pdfs(stencil, pdf_symbols=pdf_symbols, cumulant_indices=indices) polynomial_moment_indices = exponents_to_polynomial_representations( indices) direct_version2 = cumulants_from_pdfs( stencil, pdf_symbols=pdf_symbols, cumulant_indices=polynomial_moment_indices) for idx, value in direct_version.items(): poly = exponent_to_polynomial_representation(idx) assert direct_version2[poly] == value moment_dict = { idx: discrete_moment(pdf_symbols, idx, stencil) for idx in indices } indirect_version = { idx: cumulant_as_function_of_raw_moments(idx, moment_dict) for idx in indices } for idx in indices: assert sp.simplify(direct_version[idx] - indirect_version[idx]) == 0
def get_post_collision_moment(self, ce_moment, exponent=1, pre_collision_moment_name="\\Pi"): if (ce_moment, exponent) in self._postCollisionMomentCache: return self._postCollisionMomentCache[(ce_moment, exponent)] stencil = self._method.stencil moment2pdf = self._inverseMomentMatrix moment_tuple = ce_moment.moment_tuple moment_symbols = [] for moment, (eq_value, rr) in self._method.relaxation_info_dict.items(): if isinstance(moment, tuple): moment_symbols.append(-rr**exponent * CeMoment( pre_collision_moment_name, moment, ce_moment.superscript)) else: exponent_repr = polynomial_to_exponent_representation(moment) moment_symbols.append( -rr**exponent * sum(coeff * CeMoment(pre_collision_moment_name, moment_tuple, ce_moment.superscript) for coeff, moment_tuple in exponent_repr)) moment_symbols = sp.Matrix(moment_symbols) post_collision_value = discrete_moment( tuple(moment2pdf * moment_symbols), moment_tuple, stencil) self._postCollisionMomentCache[(ce_moment, exponent)] = post_collision_value return post_collision_value
def get_moments_of_discrete_maxwellian_equilibrium(stencil, moments, rho=sp.Symbol("rho"), u=sp.symbols("u_:3"), c_s_sq=sp.Symbol("c_s")**2, order=None, compressible=True): """Compute moments of discrete maxwellian equilibrium. Args: stencil: stencil is required to compute moments of discrete function moments: moments in polynomial or exponent-tuple form rho: symbol or value for the density u: symbols or values for the macroscopic velocity c_s_sq: symbol for speed of sound squared, defaults to symbol c_s**2 order: highest order of u terms compressible: compressible or incompressible form """ from lbmpy.moments import discrete_moment if order is None: order = 4 mb = discrete_maxwellian_equilibrium(stencil, rho, u, order, c_s_sq, compressible) return tuple( [discrete_moment(mb, moment, stencil).expand() for moment in moments])
def moment_constraint_equations(stencil, equilibrium, moment_to_value_dict, u=sp.symbols("u_:3")): """Returns a set of equations that have to be fulfilled for a generic equilibrium to match moment conditions passed in moment_to_value_dict. This dict is expected to map moment tuples to values.""" dim = len(stencil[0]) u = u[:dim] equilibrium = tuple(equilibrium) constraint_equations = set() for moment, desired_value in moment_to_value_dict.items(): generic_moment = discrete_moment(equilibrium, moment, stencil) equations = sp.poly(generic_moment - desired_value, *u).coeffs() constraint_equations.update(equations) return list(constraint_equations)
def create_from_equilibrium( stencil, equilibrium, moment_to_relaxation_rate_dict, compressible=False, force_model=None, moment_transform_class=PdfsToMomentsByChimeraTransform): r""" Creates a moment-based LB method using a given equilibrium distribution function Args: stencil: instance of :class:`lbmpy.stencils.LBStencil` equilibrium: list of equilibrium terms, dependent on rho and u, one for each stencil direction moment_to_relaxation_rate_dict: relaxation rate for each moment, or a symbol/float if all should relaxed with the same rate compressible: see create_with_discrete_maxwellian_eq_moments force_model: see create_with_discrete_maxwellian_eq_moments moment_transform_class: class to define the transformation to the moment space """ if any( isinstance(moment_to_relaxation_rate_dict, t) for t in (sp.Symbol, float, int)): moment_to_relaxation_rate_dict = { m: moment_to_relaxation_rate_dict for m in get_default_moment_set_for_stencil(stencil) } 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 equal to the number of stencil entries" density_velocity_computation = DensityVelocityComputation( stencil, compressible, force_model) rr_dict = OrderedDict([ (mom, RelaxationInfo( discrete_moment(equilibrium, mom, stencil).expand(), rr)) for mom, rr in zip(mom_to_rr_dict.keys(), mom_to_rr_dict.values()) ]) return MomentBasedLbMethod(stencil, rr_dict, density_velocity_computation, force_model, moment_transform_class)
def get_pre_collision_moment(self, ce_moment): assert ce_moment.superscript == 0, "Only equilibrium moments can be obtained with this function" if ce_moment not in self._momentCache: self._momentCache[ce_moment] = discrete_moment( self._eq, ce_moment.moment_tuple, self._stencil) return self._momentCache[ce_moment]