Commit cb632b10 authored by Frederik Hennig's avatar Frederik Hennig
Browse files

Merge branch 'master' into fix_macroscopic_value_kernels

parents 84ce16ba e7823f08
Pipeline #35452 passed with stages
in 47 minutes and 49 seconds
......@@ -159,7 +159,7 @@ def polynomial_to_exponent_representation(polynomial, dim=3):
summands = [polynomial] if polynomial.func != sp.Add else polynomial.args
for expr in summands:
if len(expr.atoms(sp.Symbol) - set(MOMENT_SYMBOLS)) > 0:
raise ValueError("Invalid moment polynomial: " + str(expr))
raise ValueError(f"Invalid moment polynomial: {str(expr)}")
c, x_exp, y_exp, z_exp = sp.Wild('c'), sp.Wild('xexp'), sp.Wild('yexp'), sp.Wild('zc')
match_res = expr.match(c * x**x_exp * y**y_exp * z**z_exp)
assert match_res[x_exp].is_integer and match_res[y_exp].is_integer and match_res[z_exp].is_integer
......@@ -393,10 +393,10 @@ def discrete_moment(func, moment, stencil, shift_velocity=None):
func: list of distribution functions for each direction
moment: can either be a exponent tuple, or a sympy polynomial expression
stencil: sequence of directions
shift_velocity: velocity vector u to compute central moments, the lattice velocity is replaced by
(lattice_velocity - shift_velocity)
shift_velocity: velocity vector :math:`\mathbf{u}` to compute central moments, the lattice
velocity is replaced by (lattice_velocity - shift_velocity)
"""
assert len(stencil) == len(func)
assert stencil.Q == len(func)
if shift_velocity is None:
shift_velocity = (0,) * len(stencil[0])
res = 0
......@@ -437,7 +437,7 @@ def moment_matrix(moments, stencil, shift_velocity=None):
evaluated = evaluated.subs(var, stencil_entry - shift)
return evaluated
return sp.Matrix(len(moments), len(stencil), generator)
return sp.Matrix(len(moments), stencil.Q, generator)
def set_up_shift_matrix(moments, stencil, velocity_symbols=sp.symbols("u_:3")):
......@@ -460,7 +460,7 @@ def set_up_shift_matrix(moments, stencil, velocity_symbols=sp.symbols("u_:3")):
N = sp.simplify(MN * M.inv())
assert N.is_lower, "Calculating the shift matrix gave not a lower diagonal matrix. Thus it failed"
assert sum(N[i, i] for i in range(len(stencil))) == len(stencil), "Calculating the shift matrix failed. " \
assert sum(N[i, i] for i in range(stencil.Q)) == stencil.Q, "Calculating the shift matrix failed. " \
"There are entries on the diagonal which are not equal to one"
return N
......@@ -474,15 +474,15 @@ def gram_schmidt(moments, stencil, weights=None):
moments: sequence of moments, either in tuple or polynomial form
stencil: stencil as sequence of directions
weights: optional weights, that define the scalar product which is used for normalization.
Scalar product :math:`< a,b > = \sum a_i b_i w_i` with weights :math:`w_i`.
Scalar product :math:`< \mathbf{a},\mathbf{b} > = \sum a_i b_i w_i` with weights :math:`w_i`.
Passing no weights sets all weights to 1.
Returns:
set of orthogonal moments in polynomial form
"""
if weights is None:
weights = sp.eye(len(stencil))
weights = sp.eye(stencil.Q)
if type(weights) is list:
assert len(weights) == len(stencil)
assert len(weights) == stencil.Q
weights = sp.diag(*weights)
if type(moments[0]) is tuple:
......@@ -499,8 +499,8 @@ def gram_schmidt(moments, stencil, weights=None):
prev_element = orthogonalized_vectors[j]
denominator = prev_element.dot(weights * prev_element)
if denominator == 0:
raise ValueError("Not an independent set of vectors given: "
"vector %d is dependent on previous vectors" % (i,))
raise ValueError(f"Not an independent set of vectors given: "
f"vector {i} is dependent on previous vectors")
overlap = current_element.dot(weights * prev_element) / denominator
current_element -= overlap * prev_element
moments[i] -= overlap * moments[j]
......@@ -535,6 +535,15 @@ def get_default_moment_set_for_stencil(stencil):
)
to_remove = set(extend_moments_with_permutations(non_matched_moments))
return sorted(to_poly(set(all27_moments) - to_remove) + additional_moments, key=moment_sort_key)
if stencil.D == 3 and stencil.Q == 7:
x, y, z = MOMENT_SYMBOLS
non_matched_moments = [(1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 2, 0),
(1, 2, 2), (2, 0, 0), (2, 2, 0), (2, 2, 2)]
additional_moments = (x ** 2 - y ** 2,
x ** 2 - z ** 2,
x ** 2 + y ** 2 + z ** 2)
to_remove = set(extend_moments_with_permutations(non_matched_moments))
return sorted(to_poly(set(all27_moments) - to_remove) + additional_moments, key=moment_sort_key)
raise NotImplementedError("No default moment system available for this stencil - define matched moments yourself")
......@@ -569,8 +578,7 @@ def monomial_to_polynomial_transformation_matrix(monomials, polynomials):
polynomials: sequence of polynomials in the MOMENT_SYMBOLS
>>> x, y, z = MOMENT_SYMBOLS
>>> polys = [7 * x**2 + 3 * x + 2 * y **2, \
9 * x**2 - 5 * x]
>>> polys = [7 * x**2 + 3 * x + 2 * y **2, 9 * x**2 - 5 * x]
>>> mons = list(extract_monomials(polys, dim=2))
>>> mons.sort()
>>> monomial_to_polynomial_transformation_matrix(mons, polys)
......@@ -605,7 +613,7 @@ def central_moment_reduced_monomial_to_polynomial_matrix(polynomials, stencil, v
reduced_polynomials = non_aliased_polynomial_raw_moments(polynomials, stencil)
reduced_monomials = sorted(extract_monomials(reduced_polynomials), key=exponent_tuple_sort_key)
assert len(reduced_monomials) == len(stencil), "Could not extract a base set of correct size from the polynomials."
assert len(reduced_monomials) == stencil.Q, "Could not extract a base set of correct size from the polynomials."
N = set_up_shift_matrix(reduced_monomials, stencil, velocity_symbols=velocity_symbols)
N_P = set_up_shift_matrix(polynomials, stencil, velocity_symbols=velocity_symbols)
......@@ -638,21 +646,20 @@ def moment_equality_table(stencil, discrete_equilibrium=None, continuous_equilib
import ipy_table
from lbmpy.continuous_distribution_measures import continuous_moment
dim = len(stencil[0])
u = sp.symbols("u_:{dim}".format(dim=dim))
u = sp.symbols(f"u_:{stencil.D}")
if discrete_equilibrium is None:
from lbmpy.maxwellian_equilibrium import discrete_maxwellian_equilibrium
discrete_equilibrium = discrete_maxwellian_equilibrium(stencil, c_s_sq=sp.Rational(1, 3), compressible=True,
u=u, order=truncate_order)
if continuous_equilibrium is None:
from lbmpy.maxwellian_equilibrium import continuous_maxwellian_equilibrium
continuous_equilibrium = continuous_maxwellian_equilibrium(dim=dim, u=u, c_s_sq=sp.Rational(1, 3))
continuous_equilibrium = continuous_maxwellian_equilibrium(dim=stencil.D, u=u, c_s_sq=sp.Rational(1, 3))
table = []
matched_moments = 0
non_matched_moments = 0
moments_list = [list(moments_of_order(o, dim, include_permutations=False)) for o in range(max_order + 1)]
moments_list = [list(moments_of_order(o, stencil.D, include_permutations=False)) for o in range(max_order + 1)]
colors = dict()
nr_of_columns = max([len(v) for v in moments_list]) + 1
......@@ -663,11 +670,11 @@ def moment_equality_table(stencil, discrete_equilibrium=None, continuous_equilib
for order, moments in enumerate(moments_list):
row = [' '] * nr_of_columns
row[0] = '%d' % (order,)
row[0] = f'{order}'
for moment, col_idx in zip(moments, range(1, len(row))):
multiplicity = moment_multiplicity(moment)
dm = discrete_moment(discrete_equilibrium, moment, stencil)
cm = continuous_moment(continuous_equilibrium, moment, symbols=sp.symbols("v_0 v_1 v_2")[:dim])
cm = continuous_moment(continuous_equilibrium, moment, symbols=sp.symbols("v_0 v_1 v_2")[:stencil.D])
difference = sp.simplify(dm - cm)
if truncate_order:
difference = sp.simplify(remove_higher_order_terms(difference, symbols=u, order=truncate_order))
......@@ -678,7 +685,7 @@ def moment_equality_table(stencil, discrete_equilibrium=None, continuous_equilib
colors[(order + 1, col_idx)] = 'lightGreen'
matched_moments += multiplicity
row[col_idx] = '%s x %d' % (moment, moment_multiplicity(moment))
row[col_idx] = f'{moment} x {moment_multiplicity(moment)}'
table.append(row)
......@@ -687,8 +694,8 @@ def moment_equality_table(stencil, discrete_equilibrium=None, continuous_equilib
for cell_idx, color in colors.items():
ipy_table.set_cell_style(cell_idx[0], cell_idx[1], color=color)
print("Matched moments %d - non matched moments %d - total %d" %
(matched_moments, non_matched_moments, matched_moments + non_matched_moments))
print(f"Matched moments {matched_moments} - non matched moments {non_matched_moments} "
f"- total {matched_moments + non_matched_moments}")
return table_display
......@@ -719,8 +726,8 @@ def moment_equality_table_by_stencil(name_to_stencil_dict, moments, truncate_ord
colors = {}
for stencil_idx, stencil in enumerate(stencils):
dim = len(stencil[0])
u = sp.symbols("u_:{dim}".format(dim=dim))
dim = stencil.D
u = sp.symbols(f"u_:{dim}")
discrete_equilibrium = discrete_maxwellian_equilibrium(stencil, c_s_sq=sp.Rational(1, 3), compressible=True,
u=u, order=truncate_order)
continuous_equilibrium = continuous_maxwellian_equilibrium(dim=dim, u=u, c_s_sq=sp.Rational(1, 3))
......@@ -777,7 +784,7 @@ def __unique_permutations(elements: Sequence[T]) -> Iterable[T]:
"""
if len(elements) == 1:
yield (elements[0],)
yield elements[0],
else:
unique_elements = set(elements)
for first_element in unique_elements:
......
......@@ -17,11 +17,11 @@ def symmetric_symbolic_surface_tension(i, j):
if i == j:
return 0
index = (i, j) if i < j else (j, i)
return sp.Symbol("%s_%d_%d" % ((surface_tension_symbol_name,) + index))
return sp.Symbol(f"{surface_tension_symbol_name}_{index[0]}_{index[1]}")
def symbolic_order_parameters(num_symbols):
return sp.symbols("%s_:%i" % (order_parameter_symbol_name, num_symbols))
return sp.symbols(f"{order_parameter_symbol_name}_:{num_symbols}")
def free_energy_functional_3_phases(order_parameters=None, interface_width=interface_width_symbol, transformed=True,
......@@ -65,7 +65,7 @@ def free_energy_functional_n_phases_penalty_term(order_parameters, interface_wid
penalty_term_factor=0.01):
num_phases = len(order_parameters)
if kappa is None:
kappa = sp.symbols("kappa_:%d" % (num_phases,))
kappa = sp.symbols(f"kappa_:{num_phases}")
if not hasattr(kappa, "__len__"):
kappa = [kappa] * num_phases
......@@ -166,7 +166,8 @@ def free_energy_functional_n_phases(num_phases=None, surface_tensions=symmetric_
def lambda_coeff(k, l):
if symbolic_lambda:
return sp.Symbol("Lambda_%d%d" % ((k, l) if k < l else (l, k)))
symbol_names = (k, l) if k < l else (l, k)
return sp.Symbol(f"Lambda_{symbol_names[0]}{symbol_names[1]}")
n = num_phases - 1
if k == l:
assert surface_tensions(l, l) == 0
......@@ -241,7 +242,7 @@ def chemical_potentials_from_free_energy(free_energy, order_parameters=None):
def force_from_phi_and_mu(order_parameters, dim, mu=None):
if mu is None:
mu = sp.symbols("mu_:%d" % (len(order_parameters),))
mu = sp.symbols(f"mu_:{len(order_parameters)}")
return sp.Matrix([sum(- c_i * Diff(mu_i, a) for c_i, mu_i in zip(order_parameters, mu))
for a in range(dim)])
......@@ -298,7 +299,7 @@ def extract_gamma(free_energy, order_parameters):
continue
if len(diff_factors) != 2:
raise ValueError("Could not determine Λ because of term " + str(product))
raise ValueError(f"Could not determine Λ because of term {str(product)}")
indices = sorted([order_parameters.index(d.args[0]) for d in diff_factors])
increment = prod(e for e in product if e.func != Diff)
......
......@@ -2,7 +2,6 @@ import sympy as sp
from lbmpy.maxwellian_equilibrium import get_weights
from lbmpy.methods.creationfunctions import create_from_equilibrium
from lbmpy.stencils import get_stencil
from pystencils.sympyextensions import kronecker_delta, multidimensional_sum
......@@ -19,8 +18,6 @@ def cahn_hilliard_lb_method(stencil, mu, relaxation_rate=sp.Symbol("omega"), gam
relaxation_rate: relaxation rate of method
gamma: tunable parameter affecting the second order equilibrium moment
"""
if isinstance(stencil, str):
stencil = get_stencil(stencil)
weights = get_weights(stencil, c_s_sq=sp.Rational(1, 3))
kd = kronecker_delta
......@@ -30,7 +27,7 @@ def cahn_hilliard_lb_method(stencil, mu, relaxation_rate=sp.Symbol("omega"), gam
yield r
op = sp.Symbol("rho")
v = sp.symbols("u_:%d" % (len(stencil[0]),))
v = sp.symbols(f"u_:{stencil.D}")
equilibrium = []
for d, w in zip(stencil, weights):
......
......@@ -11,11 +11,12 @@ except ImportError:
import sympy as sp
from lbmpy.creationfunctions import create_lb_update_rule
from lbmpy.creationfunctions import create_lb_update_rule, LBMConfig, LBMOptimisation
from lbmpy.enums import Stencil
from lbmpy.macroscopic_value_kernels import pdf_initialization_assignments
from lbmpy.phasefield.analytical import chemical_potentials_from_free_energy, force_from_phi_and_mu
from lbmpy.phasefield.cahn_hilliard_lbm import cahn_hilliard_lb_method
from lbmpy.stencils import get_stencil
from lbmpy.stencils import LBStencil
from pystencils import Assignment, create_data_handling, create_kernel
from pystencils.fd import Diff, discretize_spatial, expand_diff_full
from pystencils.fd.derivation import FiniteDifferenceStencilDerivation
......@@ -78,7 +79,7 @@ def create_model(domain_size, num_phases, coeff_a, coeff_epsilon, gabd, alpha=1,
dh = create_data_handling(domain_size, periodicity=(True, True), default_ghost_layers=2)
c = dh.add_array("c", values_per_cell=num_phases)
rho = dh.add_array("rho")
rho = dh.add_array("rho", values_per_cell=1)
mu = dh.add_array("mu", values_per_cell=num_phases, latex_name="\\mu")
force = dh.add_array("F", values_per_cell=dh.dim)
u = dh.add_array("u", values_per_cell=dh.dim)
......@@ -87,8 +88,8 @@ def create_model(domain_size, num_phases, coeff_a, coeff_epsilon, gabd, alpha=1,
pdf_field = []
pdf_dst_field = []
for i in range(num_phases):
pdf_field_local = dh.add_array("pdf_ch_%d" % i, values_per_cell=9) # 9 for D2Q9
pdf_dst_field_local = dh.add_array("pdfs_ch_%d_dst" % i, values_per_cell=9)
pdf_field_local = dh.add_array(f"pdf_ch_{i}", values_per_cell=9) # 9 for D2Q9
pdf_dst_field_local = dh.add_array(f"pdfs_ch_{i}_dst", values_per_cell=9)
pdf_field.append(pdf_field_local)
pdf_dst_field.append(pdf_dst_field_local)
......@@ -117,15 +118,16 @@ def create_model(domain_size, num_phases, coeff_a, coeff_epsilon, gabd, alpha=1,
ch_collide_kernels = []
ch_methods = []
for i in range(num_phases):
ch_method = cahn_hilliard_lb_method(get_stencil("D2Q9"), mu(i),
ch_method = cahn_hilliard_lb_method(LBStencil(Stencil.D2Q9), mu(i),
relaxation_rate=1.0, gamma=1.0)
ch_methods.append(ch_method)
ch_update_rule = create_lb_update_rule(lb_method=ch_method,
kernel_type='collide_only',
density_input=c(i),
velocity_input=u.center_vector,
compressible=True,
optimization={"symbolic_field": pdf_field[i]})
lbm_config = LBMConfig(lb_method=ch_method, kernel_type='collide_only', density_input=c(i),
velocity_input=u.center_vector, compressible=True)
lbm_opt = LBMOptimisation(symbolic_field=pdf_field[i])
ch_update_rule = create_lb_update_rule(lbm_config=lbm_config,
lbm_optimisation=lbm_opt)
ch_assign = ch_update_rule.all_assignments
ch_kernel = create_kernel(ch_assign).compile()
ch_collide_kernels.append(ch_kernel)
......@@ -134,10 +136,11 @@ def create_model(domain_size, num_phases, coeff_a, coeff_epsilon, gabd, alpha=1,
for i in range(num_phases):
ch_method = ch_methods[i]
ch_update_rule = create_lb_update_rule(lb_method=ch_method,
kernel_type='stream_pull_only',
temporary_field_name=pdf_dst_field[i].name,
optimization={"symbolic_field": pdf_field[i]})
lbm_config = LBMConfig(lb_method=ch_method, kernel_type='stream_pull_only',
temporary_field_name=pdf_dst_field[i].name)
lbm_opt = LBMOptimisation(symbolic_field=pdf_field[i])
ch_update_rule = create_lb_update_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt)
ch_assign = ch_update_rule.all_assignments
ch_kernel = create_kernel(ch_assign).compile()
ch_stream_kernels.append(ch_kernel)
......@@ -147,7 +150,9 @@ def create_model(domain_size, num_phases, coeff_a, coeff_epsilon, gabd, alpha=1,
for i in range(num_phases):
ch_method = ch_methods[i]
init_assign = pdf_initialization_assignments(lb_method=ch_method,
density=c_vec[i], velocity=(0, 0), pdfs=pdf_field[i].center_vector)
density=c_vec[i],
velocity=(0, 0),
pdfs=pdf_field[i].center_vector)
init_kernel = create_kernel(init_assign).compile()
init_kernels.append(init_kernel)
......@@ -159,17 +164,16 @@ def create_model(domain_size, num_phases, coeff_a, coeff_epsilon, gabd, alpha=1,
getter_kernel = create_kernel(output_assign).compile()
getter_kernels.append(getter_kernel)
collide_assign = create_lb_update_rule(kernel_type='collide_only',
relaxation_rate=1.0,
force=force,
optimization={"symbolic_field": pdf_hydro_field},
compressible=True)
lbm_config = LBMConfig(kernel_type='collide_only', relaxation_rate=1.0, force=force, compressible=True)
lbm_opt = LBMOptimisation(symbolic_field=pdf_hydro_field)
collide_assign = create_lb_update_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt)
collide_kernel = create_kernel(collide_assign).compile()
stream_assign = create_lb_update_rule(kernel_type='stream_pull_only',
temporary_field_name=pdf_hydro_dst_field.name,
optimization={"symbolic_field": pdf_hydro_field},
output={"density": rho, "velocity": u})
lbm_config = LBMConfig(kernel_type='stream_pull_only', temporary_field_name=pdf_hydro_dst_field.name,
output={"density": rho, "velocity": u})
lbm_opt = LBMOptimisation(symbolic_field=pdf_hydro_field)
stream_assign = create_lb_update_rule(lbm_config=lbm_config, lbm_optimisation=lbm_opt)
stream_kernel = create_kernel(stream_assign).compile()
method_collide = collide_assign.method
......
......@@ -174,7 +174,7 @@ class PhaseFieldStep:
compute_density_in_every_step=True,
density_data_index=i,
flag_interface=self.hydro_lbm_step.boundary_handling.flag_interface,
name=name + "_chLbm_%d" % (i,),
name=name + f"_chLbm_{i}",
optimization=optimization)
self.cahn_hilliard_steps.append(ch_step)
......
import numpy as np
from lbmpy.creationfunctions import create_lb_function
from lbmpy.enums import Stencil
from lbmpy.macroscopic_value_kernels import pdf_initialization_assignments
from lbmpy.phasefield.analytical import force_from_phi_and_mu
from lbmpy.phasefield.cahn_hilliard_lbm import cahn_hilliard_lb_method
from lbmpy.phasefield.kerneleqs import mu_kernel
from lbmpy.stencils import get_stencil
from lbmpy.stencils import LBStencil
from pystencils import Assignment, create_data_handling, create_kernel, Target
from pystencils.fd import discretize_spatial
from pystencils.fd.spatial import fd_stencils_forth_order_isotropic
......@@ -36,7 +37,7 @@ class PhaseFieldStepDirect:
dh = data_handling
self.data_handling = dh
stencil = get_stencil('D3Q19' if dh.dim == 3 else 'D2Q9')
stencil = LBStencil(Stencil.D3Q19) if dh.dim == 3 else LBStencil(Stencil.D2Q9)
self.free_energy = free_energy
......@@ -45,14 +46,14 @@ class PhaseFieldStepDirect:
gpu = target == Target.GPU
phi_size = len(order_parameters)
gl = kernel_parameters['ghost_layers']
self.phi_field = dh.add_array('{}_phi'.format(name), values_per_cell=phi_size, gpu=gpu, latex_name='φ',
self.phi_field = dh.add_array(f'{name}_phi', values_per_cell=phi_size, gpu=gpu, latex_name='φ',
ghost_layers=gl)
self.mu_field = dh.add_array("{}_mu".format(name), values_per_cell=phi_size, gpu=gpu, latex_name="μ",
self.mu_field = dh.add_array(f"{name}_mu", values_per_cell=phi_size, gpu=gpu, latex_name="μ",
ghost_layers=gl)
self.vel_field = dh.add_array("{}_u".format(name), values_per_cell=data_handling.dim, gpu=gpu, latex_name="u",
self.vel_field = dh.add_array(f"{name}_u", values_per_cell=data_handling.dim, gpu=gpu, latex_name="u",
ghost_layers=gl)
self.force_field = dh.add_array("{}_force".format(name), values_per_cell=dh.dim, gpu=gpu, latex_name="F",
self.force_field = dh.add_array(f"{name}_force", values_per_cell=dh.dim, gpu=gpu, latex_name="F",
ghost_layers=gl)
self.phi = SlicedGetterDataHandling(self.data_handling, self.phi_field.name)
......@@ -62,11 +63,11 @@ class PhaseFieldStepDirect:
self.ch_pdfs = []
for i in range(len(order_parameters)):
src = dh.add_array("{}_ch_src{}".format(name, i), values_per_cell=len(stencil), ghost_layers=gl)
dst = dh.add_array("{}_ch_dst{}".format(name, i), values_per_cell=len(stencil), ghost_layers=gl)
src = dh.add_array(f"{name}_ch_src{i}", values_per_cell=stencil.Q, ghost_layers=gl)
dst = dh.add_array(f"{name}_ch_dst{i}", values_per_cell=stencil.Q, ghost_layers=gl)
self.ch_pdfs.append((src, dst))
self.hydro_pdfs = (dh.add_array("{}_hydro_src".format(name), values_per_cell=len(stencil), ghost_layers=gl),
dh.add_array("{}_hydro_dst".format(name), values_per_cell=len(stencil), ghost_layers=gl))
self.hydro_pdfs = (dh.add_array(f"{name}_hydro_src", values_per_cell=stencil.Q, ghost_layers=gl),
dh.add_array(f"{name}_hydro_dst", values_per_cell=stencil.Q, ghost_layers=gl))
# Compute Kernels
mu_assignments = mu_kernel(self.free_energy, order_parameters, self.phi_field, self.mu_field)
......
......@@ -42,10 +42,8 @@ class ContactAngle(Boundary):
angle = TypedSymbol("a", self._data_type)
tmp = TypedSymbol("tmp", self._data_type)
result = []
result.append(Assignment(tmp, sum([x * x for x in neighbor])))
result.append(Assignment(dist, 0.5 * sp.sqrt(tmp)))
result.append(Assignment(angle, math.cos(math.radians(self._contact_angle))))
result = [Assignment(tmp, sum([x * x for x in neighbor])), Assignment(dist, 0.5 * sp.sqrt(tmp)),
Assignment(angle, math.cos(math.radians(self._contact_angle)))]
var = - dist * (4.0 / self._interface_width) * angle
tmp = 1 + var
......
......@@ -22,24 +22,22 @@ def chemical_potential_symbolic(phi_field, stencil, beta, kappa):
beta: coefficient related to surface tension and interface thickness
kappa: coefficient related to surface tension and interface thickness
"""
dimensions = len(stencil[0])
q = len(stencil)
lap = sp.simplify(0)
for i in range(dimensions):
for i in range(stencil.D):
deriv = FiniteDifferenceStencilDerivation((i, i), stencil)
for j in range(dimensions):
for j in range(stencil.D):
# assume the stencil is symmetric
deriv.assume_symmetric(dim=j, anti_symmetric=False)
# set weights for missing degrees of freedom in the calculation and assume the stencil is isotropic
if q == 9:
if stencil.Q == 9:
res = deriv.get_stencil(isotropic=True)
lap += res.apply(phi_field.center)
elif q == 15:
elif stencil.Q == 15:
deriv.set_weight((0, 0, 0), sp.Rational(-32, 27))
res = deriv.get_stencil(isotropic=True)
lap += res.apply(phi_field.center)
elif q == 19:
elif stencil.Q == 19:
res = deriv.get_stencil(isotropic=True)
lap += res.apply(phi_field.center)
else:
......@@ -59,26 +57,24 @@ def isotropic_gradient_symbolic(phi_field, stencil):
phi_field: the phase-field on which the isotropic gradient is applied
stencil: stencil to derive the finite difference for the gradient (2nd order isotropic)
"""
dimensions = len(stencil[0])
q = len(stencil)
deriv = FiniteDifferenceStencilDerivation((0,), stencil)
deriv.assume_symmetric(0, anti_symmetric=True)
deriv.assume_symmetric(1, anti_symmetric=False)
if dimensions == 3:
if stencil.D == 3:
deriv.assume_symmetric(2, anti_symmetric=False)
# set weights for missing degrees of freedom in the calculation and assume the stencil is isotropic
# furthermore the stencils gets rotated to get the y and z components
if q == 9:
if stencil.Q == 9:
res = deriv.get_stencil(isotropic=True)
grad = [res.apply(phi_field.center), res.rotate_weights_and_apply(phi_field.center, (0, 1)), 0]
elif q == 15:
elif stencil.Q == 15:
res = deriv.get_stencil(isotropic=True)
grad = [res.apply(phi_field.center),
res.rotate_weights_and_apply(phi_field.center, (0, 1)),
res.rotate_weights_and_apply(phi_field.center, (1, 2))]
elif q == 19:
elif stencil.Q == 19:
deriv.set_weight((0, 0, 0), sp.sympify(0))
deriv.set_weight((1, 0, 0), sp.Rational(1, 6))
......@@ -149,7 +145,7 @@ def viscous_force(lb_velocity_field, phi_field, mrt_method, tau, density_heavy,
field. If it is not given the stencil of the LB method will be applied.
"""
stencil = mrt_method.stencil
dimensions = len(stencil[0])
dimensions = stencil.D
if fd_stencil is None:
fd_stencil = stencil
......@@ -226,7 +222,6 @@ def hydrodynamic_force(lb_velocity_field, phi_field, lb_method, tau,
field. If it is not given the stencil of the LB method will be applied.
"""
stencil = lb_method.stencil
dimensions = len(stencil[0])
if fd_stencil is None:
fd_stencil = stencil
......@@ -236,7 +231,7 @@ def hydrodynamic_force(lb_velocity_field, phi_field, lb_method, tau,
fs = surface_tension_force(phi_field, stencil, beta, kappa, fd_stencil)
result = []
for i in range(dimensions):
for i in range(stencil.D):
result.append(fs[i] + fp[i] + fm[i] + body_force[i])
return result
......@@ -255,10 +250,9 @@ def interface_tracking_force(phi_field, stencil, interface_thickness, fd_stencil
if fd_stencil is None:
fd_stencil = stencil
dimensions = len(stencil[0])
normal_fd = normalized_isotropic_gradient_symbolic(phi_field, stencil, fd_stencil)
result = []
for i in range(dimensions):
for i in range(stencil.D):
result.append(((1.0 - 4.0 * (phi_field.center - 0.5) ** 2) / interface_thickness) * normal_fd[i])
return result
......@@ -276,7 +270,6 @@ def get_update_rules_velocity(src_field, u_in, lb_method, force_model, density,
sub_iterations: number of updates of the velocity field
"""
stencil = lb_method.stencil
dimensions = len(stencil[0])
rho = lb_method.conserved_quantity_computation.zeroth_order_moment_symbol
u_symp = lb_method.conserved_quantity_computation.first_order_moment_symbols
......@@ -298,24 +291,24 @@ def get_update_rules_velocity(src_field, u_in, lb_method, force_model, density,
update_u.append(Assignment(rho, m0[0]))
index = 0
aleph = sp.symbols(f"aleph_:{dimensions * sub_iterations}")
aleph = sp.symbols(f"aleph_:{stencil.D * sub_iterations}")
for i in range(dimensions):
for i in range(stencil.D):
update_u.append(Assignment(aleph[i], u_in.center_vector[i]))
index += 1
for k in range(sub_iterations - 1):
subs_dict = dict(zip(u_symp, aleph[k * dimensions:index]))
for i in range(dimensions):
subs_dict = dict(zip(u_symp, aleph[k * stencil.D:index]))
for i in range(stencil.D):
update_u.append(Assignment(aleph[index], m0[indices[i]] + force[i].subs(subs_dict) / density / 2))
index += 1
subs_dict = dict(zip(u_symp, aleph[index - dimensions:index]))
subs_dict = dict(zip(u_symp, aleph[index - stencil.D:index]))
for i in range(dimensions):
for i in range(stencil.D