Commit 0698e79c authored by MischaD's avatar MischaD
Browse files

Solution Expected Function

parent 674eea74
......@@ -9,13 +9,13 @@ from .shell import Shell
class Lattice:
BY_NAME = {"D2Q9": {"dimension": 2, "order": 4, "shell_list": [1, 2, 4]},
"D2V17": {"dimension": 2, "order": 6, "shell_list": [1, 2, 4, 8, 9]},
"D2V37": {"dimension": 2, "order": 8, "shell_list": [1, 2, 4, 5, 8, 9, 10, 16]},
"D3Q19": {"dimension": 3, "order": 4, "shell_list": [1, 2, 4]},
"D3Q15": {"dimension": 3, "order": 4, "shell_list": [1, 3, 4]},
BY_NAME = {"D2Q9": {"dimension": 2, "order": 4, "shell_list": [1, 2, 4], "seed": 44},
"D2V17": {"dimension": 2, "order": 6, "shell_list": [1, 2, 4, 8, 9], "seed": 44},
"D2V37": {"dimension": 2, "order": 8, "shell_list": [1, 2, 4, 5, 8, 9, 10, 16], "seed": 44},
"D3Q19": {"dimension": 3, "order": 4, "shell_list": [1, 2, 4], "seed": 44},
"D3Q15": {"dimension": 3, "order": 4, "shell_list": [1, 3, 4], "seed": 44},
"D3Q41-ZOT": {"dimension": 3, "order": 6, "shell_list": [1, 2, 3, 9, 16, 27], "boundary": "sup",
"unwanted_subshells": ["221", "511"]},
"unwanted_subshells": ["221", "511"], "seed": 44},
}
def __init__(self, dimension=2, order=4, shell_list=[1, 2, 4], seed=None, boundary=None, unwanted_subshells=[], svd_tolerance=1e-8):
......@@ -83,16 +83,16 @@ class Lattice:
return string
@classmethod
def from_name(cls, name, seed=None):
def from_name(cls, name):
"""Initiate the Lattice with the correct values corresponding to a know Lattice in literature.
A complete list can be seen in Lattice.BY_NAME.keys()"""
kwargs = cls.BY_NAME.get(name)
if not kwargs:
raise ValueError("No Lattice with this name is known or implemented")
return cls(**kwargs, seed=seed)
return cls(**kwargs)
@classmethod
def from_order(cls, dimension, order, seed=None):
def from_order(cls, dimension, order):
"""
:param dimension:
:param order:
......@@ -227,13 +227,16 @@ class Lattice:
reduced_rhs[i, :] = rhs[i, :] / singular_value
if cols - rows > 0:
# TODO Better
raise InfiniteSolutionsException("Reduce order, remove shells, or use continue.py in "
"https://github.com/BDuenweg/Lattice-Boltzmann-weights")
self._solution = np.dot(np.transpose(V), reduced_rhs)
return self._solution
def _calculate_coefficients(self):
"""Use _all_velocity_vectors and _solution to calculate the coefficients of the
weigth polynomials. Writes them into _coefficients
"""
solution_columns = self._order // 2
coefficients = np.zeros((1 + solution_columns))
coefficients[0] = 1
......@@ -275,8 +278,13 @@ class Lattice:
self._interval = sp.Complement(interval, sp.FiniteSet(0))
return self._interval
def calculate_polynomials(self):
c_s_sq = sp.Symbol("c_s_sq")
def solution_expected(self):
"""Evaluate if the order, dimension and amount of shells entered are expected to retrieve a solution.
This is in no way a guarantee on the existence of a solution or whether or not the program
will finish successful, but it can be used as a quick hint on the existence of a solution.
Changes the state of self._solution and self._velocity vectors for future calculations."""
if self._order % 2 == 1:
self._order -= 1
logger.warning("Only odd order valid. Decrease by one")
......@@ -292,30 +300,32 @@ class Lattice:
self._svd()
self._calculate_coefficients()
return self._solution is not None
apporx_coeffs = [[approximate_ratio(x) for x in pol_coffs] for pol_coffs in self._coefficients]
def calculate_polynomials(self, approximate=True):
"""Main algorithm as proposed by D. Spiller and B Duenweg.
self._weight_polynomials = [sp.Poly([approximate_ratio(x) for x in pol_coffs], c_s_sq) for pol_coffs in self._coefficients]
if not self._weight_polynomials:
raise NoSolutionException("Something went wrong")
Divided into the part where the existence of a solution and calculated together with all the velocity
vectors. If one is expected the coefficients are calculated, the interval evaluated and the weight
polynomials returned.
self._interval = self._calculate_valid_interval()
if self._interval == sp.EmptySet():
return []
return self._weight_polynomials
:param approximate: Use python Fraction to approximate the calculated polynomial coefficients as rational
number. This should give better results, since they should have a rational representation.
def calculate_reduced_weights(self, boundary="inf"):
"""
Calculate the weights of this lattice for a reduced model.
If the smallest or biggest value of the valid interval is taken, they reduce
the amount of shells necessary by one.
Overwrites the weight values in self.shell
:return: List of Sympy Polynomials."""
:param boundary: "inf" --> smallest possible value is taken, otherwise the largest
:return: list of weights in the order of their shells.
"""
return self.calculate_weights(boundary=boundary)
self.solution_expected()
self._calculate_coefficients()
c_s_sq = sp.Symbol("c_s_sq")
if approximate:
self._weight_polynomials = [sp.Poly([approximate_ratio(x) for x in pol_coffs], c_s_sq) for pol_coffs in self._coefficients]
else:
self._weight_polynomials = [sp.Poly(pol_coffs, c_s_sq) for pol_coffs in
self._coefficients]
self._interval = self._calculate_valid_interval()
return [] if self._interval == sp.EmptySet else self._weight_polynomials
def calculate_weights(self, c_s_sq=None, boundary=None):
"""
......@@ -330,7 +340,7 @@ class Lattice:
:param c_s_sq: Float value for the speed of sound, has to be inside of the valid interval
:param boundary: Get reduced model by using the infimum or supremum of the interval. Fallback value if
no c_s_sq is given
:return:
:return: weights With zero weight(s) included
"""
if not self._weight_polynomials:
......@@ -358,9 +368,11 @@ class Lattice:
def velocity_set(self):
"""
Returns the values that are important for the Lattice Boltzmann Model, i.e.
Removes unwanted shells, i.e. weight == = and
returns the values that are important for the Lattice Boltzmann Model, i.e.
a list of the velocity values their corresponding weights and the value for the speed of sound.
:return: (c_s_sq, weights, velocities): c_s_sq
:return: (c_s_sq, weights, velocities)
"""
if not self.weights:
self.calculate_weights()
......
......@@ -4,6 +4,16 @@ from lbmweights import Lattice
from lbmweights.utils.mylog import logger
class SolutionExpected(unittest.TestCase):
def setUp(self):
pass
def test_solution_expected(self):
for name, lattice_args in Lattice.BY_NAME.items():
lattice = Lattice(**lattice_args)
self.assertTrue(lattice.solution_expected())
class TestQ9(unittest.TestCase):
def setUp(self):
self.seed = 20
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment