Source code for multipie.multipole.util.structure_samb_util

"""
This file provides utility functions for calculation of structure multipole basis set.
"""
import sympy as sp
import numpy as np

from gcoreutils.nsarray import NSArray


# ==================================================
[docs] def cs_list(s, real=False): """ list of c### and s### contained in the given equation. Args: s (str/Symbol): string object to be converted to symbol. real (bool): real symbol ? If real=True, the object is recognized as a real number. Returns: list: [c###/s###] """ s = sp.expand(sp.sympify(str(s))) cs_lst = [] n = 1 while s != 0: cn, sn = sp.Symbol(f"c{n:03d}"), sp.Symbol(f"s{n:03d}") c = sp.diff(s, cn) s = sp.limit(s, cn, 0) if c != 0: cs_lst.append(cn) c = sp.diff(s, sn) s = sp.limit(s, sn, 0) if c != 0: cs_lst.append(sn) n += 1 if real: cs_lst = [sp.Symbol(str(csn), real=True) for csn in cs_lst] return cs_lst
# ==================================================
[docs] def to_symbol(s, real=False): """ convert string to symbol. Args: s (str): string object to be converted to symbol. real (bool): real symbol ? If real=True, the object is recognized as a real number. Returns: Symbol: symbol. """ cs_lst = cs_list(s) s = sp.expand(sp.sympify(str(s))) d = {sp.Symbol(str(csn), real=real): s.coeff(csn) for csn in cs_lst} return sp.expand(sum([c * csn for csn, c in d.items()]))
# ==================================================
[docs] def inner_product(f1, f2): """ inner product of two structure factors. Args: f1 (str/Symbol): F1. f2 (str/Symbol): F2. Returns: NSArray: inner product of F1 and F2. Notes: - F1 and F2 are polynomials in terms of c### and s### (### are given by lst) only without const. terms. """ f1 = str(f1) f2 = str(f2) ip_str = {} for csi in cs_list(f1): for csj in cs_list(f2): if csi != csj: ip_str[str(csi * csj)] = "(0)" else: ip_str[str(csi * csj)] = "(1/2)" prod = str((NSArray(f1) * NSArray(f2)).expand()) for k, v in ip_str.items(): prod = prod.replace(k, v) prod = sp.expand(sp.sympify(prod)) return prod
# ==================================================
[docs] def normalize_fk(fk): """ normalize k function. Args: fk (str/Symbol): function of k. Returns: Symbol: normalized k function. """ return fk / sp.sqrt(inner_product(fk, fk))
# ==================================================
[docs] def orthogonalize_fk(v, nmax=None): """ orthogonalize list of function of k by Gram-Schmidt orthogonalization method. Args: v (NSArray): list of function of k to be orthogonalized. nmax (int, optional): max. number of nonzero basis. Returns: NSArray: orthogonalized list of function of k. """ ev = [] cnt = 0 for v0 in v: s = sp.S(0) for evi in ev: s += inner_product(evi, v0) * evi e = v0 - s e = sp.expand(e) d = sp.sqrt(inner_product(e, e)) if d != 0: e = e / d e = sp.expand(e) cnt += 1 else: e = sp.S(0) ev.append(e) if nmax is not None and cnt == nmax: break idx = np.array([i for i, b in enumerate(ev) if not b == sp.S(0)]) return ev, idx
# ==================================================
[docs] def decompose_fk(fk, k_samb_set): """ decompose k function into linear combination of structure multipoles. Args: fk (str/Symbol): function of k. k_samb_set (list): [ ("kmp_#", "formfactor") ]. Returns: dict: dictionary of expansion coefficient {"smp_#": coeff}. """ fk = sp.expand(to_symbol(fk)) if fk == sp.S(0): return {} coeffs = {} for kmp_i, fk_ in k_samb_set: fk_ = sp.expand(to_symbol(fk_)) c = inner_product(fk, fk_) if c != 0: coeffs[kmp_i] = c return coeffs
# ================================================== def test(): c1, s1, c2, s2 = sp.symbols("c001 s001 c002 s002") eq = sp.expand(sp.sqrt(2) * (c1 - sp.I * s1) + sp.sqrt(3) * (c2 + sp.I * s2)) print(f"eq = {eq}") cs_lst = cs_list(eq) print(cs_lst) eq_ = sp.conjugate(to_symbol(str(eq), real=True)) print(f"eq_ = {eq_}") f1 = sp.expand(sp.sqrt(2) * (c1 - s1)) f2 = sp.expand(sp.sqrt(3) * (c1 + s1)) print(f"inner_product(f1, f1) = {inner_product(f1, f1)}") print(f"inner_product(f1, f2) = {inner_product(f1, f2)}") print(f"inner_product(f2, f2) = {inner_product(f2, f2)}") v = [f1, f2] v = orthogonalize_fk(v)[0] print(f"orthogonalize_fk = {v}") k_samb_set = [("kmp_1", v[0]), ("kmp_2", v[1])] print(f"decompose_fk = {decompose_fk(c1, k_samb_set)}") # test()