aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerlaender2019-04-16 22:45:11 +0200
committerAdrian Kummerlaender2019-04-16 22:45:11 +0200
commitfc02e4c5f8c8bbb014449dc27d7b69992ad6043f (patch)
treeaf962916b7b3239c698a4825ba24ea1ddc3377ce
parent89718b245b0246e08f9d0545a636e0cf89642a72 (diff)
downloadcompustream-fc02e4c5f8c8bbb014449dc27d7b69992ad6043f.tar
compustream-fc02e4c5f8c8bbb014449dc27d7b69992ad6043f.tar.gz
compustream-fc02e4c5f8c8bbb014449dc27d7b69992ad6043f.tar.bz2
compustream-fc02e4c5f8c8bbb014449dc27d7b69992ad6043f.tar.xz
compustream-fc02e4c5f8c8bbb014449dc27d7b69992ad6043f.zip
Add basic physical scaling and Knudsen quality criterion
The paper "Automatic grid refinement criterion for lattice Boltzmann method" [2015] by Lagrava et al. describes a criterion for measuring the local simulation quality using a comparison of the theoretical Knudsen number and the quotient of the cells's non-equilibrium and equilibrium function. While this criterion was developed to enable automatic selection of areas to be refined, it also offers a interesting and unique perspective on the fluid structure. As the criterion requires calculation of the modeled Reynolds-, Mach- and Knudsen-numbers I took the time to set up the basics for scaling the simulation to actually model a physical system. Or rather calculating which physical model is represented by the chosen resolution and relaxation time. [2015]: https://arxiv.org/abs/1507.06767
-rw-r--r--src/shader/code/collide.glsl50
-rw-r--r--src/shader/code/vertex.glsl17
2 files changed, 57 insertions, 10 deletions
diff --git a/src/shader/code/collide.glsl b/src/shader/code/collide.glsl
index 3bfd332..9ff6ab3 100644
--- a/src/shader/code/collide.glsl
+++ b/src/shader/code/collide.glsl
@@ -11,6 +11,12 @@ uniform uint nX;
uniform uint nY;
uniform uint iT;
+/// Fluid characteristics
+
+const float physCharLength = 1.0;
+const float physCharVelocity = 1.0;
+const float physViscosity = 0.1;
+
/// LBM constants
const uint q = 9;
@@ -19,9 +25,25 @@ const float weight[q] = float[](
1./9. , 4./9., 1./9. ,
1./36 , 1./9., 1./36.
);
+const float invCs2 = 1./3.;
+
+const float relaxationTime = 0.6;
+const float relaxationFrequency = 1 / relaxationTime;
+
+/// Unit conversion
+
+const float convLength = physCharLength / nX;
+const float convTime = (relaxationTime - 0.5) / invCs2 * convLength*convLength / physViscosity;
+const float convVelocity = convLength / convTime;
+const float convViscosity = convLength * convLength / convTime;
+
+const float latticeCharVelocity = physCharVelocity / convVelocity;
+
+/// Emergent fluid numbers
-const float tau = 0.65;
-const float omega = 1/tau;
+const float Re = physCharVelocity * physCharLength / physViscosity;
+const float Ma = latticeCharVelocity * sqrt(invCs2);
+const float Kn = Ma / Re;
/// Vector utilities
@@ -65,12 +87,18 @@ void set(uint x, uint y, int i, int j, float v) {
streamCells[indexOfLatticeCell(x,y) + indexOfDirection(i,j)] = v;
}
-void setFluid(uint x, uint y, vec2 v) {
+void setFluidVelocity(uint x, uint y, vec2 v) {
const uint idx = indexOfFluidVertex(x, y);
fluidCells[idx + 0] = v.x;
fluidCells[idx + 1] = v.y;
}
+void setFluidQuality(uint x, uint y, float knudsen, int quality) {
+ const uint idx = indexOfFluidVertex(x, y);
+ fluidCells[idx + 0] = knudsen;
+ fluidCells[idx + 1] = quality;
+}
+
int getMaterial(uint x, uint y) {
const uint idx = indexOfFluidVertex(x, y);
return int(fluidCells[idx + 2]);
@@ -149,19 +177,29 @@ void main() {
d = 1.0;
}
- setFluid(x,y,v);
+ //setFluidVelocity(x,y,v);
+
+ float knudsen = 0.0;
for ( int i = -1; i <= 1; ++i ) {
for ( int j = -1; j <= 1; ++j ) {
- set(x+i,y+j,i,j, get(x,y,i,j) + omega * (equilibrium(d,v,i,j) - get(x,y,i,j)));
+ const float feq = equilibrium(d,v,i,j);
+ const float fneq = get(x,y,i,j) - feq;
+ knudsen += abs(fneq / feq);
+
+ set(x+i,y+j,i,j, get(x,y,i,j) + relaxationFrequency * (feq - get(x,y,i,j)));
}
}
+
+ knudsen /= q;
+
+ setFluidQuality(x,y,knudsen,int(round(log2(knudsen / Kn))));
}
if ( isBounceBackCell(material) ) {
for ( int i = -1; i <= 1; ++i ) {
for ( int j = -1; j <= 1; ++j ) {
- set(x+(-1)*i,y+(-1)*j,(-1)*i,(-1)*j, get(x,y,i,j) + omega * (equilibrium(d,v,i,j) - get(x,y,i,j)));
+ set(x+(-1)*i,y+(-1)*j,(-1)*i,(-1)*j, get(x,y,i,j) + relaxationFrequency * (equilibrium(d,v,i,j) - get(x,y,i,j)));
}
}
}
diff --git a/src/shader/code/vertex.glsl b/src/shader/code/vertex.glsl
index 676b68e..7851292 100644
--- a/src/shader/code/vertex.glsl
+++ b/src/shader/code/vertex.glsl
@@ -10,7 +10,8 @@ out VS_OUT {
uniform uint nX;
uniform uint nY;
-const float displayAmplifier = 3.0;
+const float velocityDisplayAmplifier = 3.0;
+const int qualityDisplayRestrictor = 6;
float unit(float x) {
return 1.0/(1.0+exp(-x));
@@ -40,6 +41,14 @@ bool isWallFrontier(int material) {
return material == 2 || material == 3;
}
+float restrictedQuality(float quality) {
+ if ( quality < 0.0 ) {
+ return 0.0;
+ } else {
+ return min(1.0, quality / qualityDisplayRestrictor);
+ }
+}
+
void main() {
const vec2 idx = fluidVertexAtIndex(gl_VertexID);
@@ -58,9 +67,9 @@ void main() {
vs_out.color = vec3(0.0, 0.0, 0.0);
} else {
vs_out.color = mix(
- vec3(-0.5, 0.0, 1.0),
- vec3( 1.0, 0.0, 0.0),
- displayAmplifier * norm(VertexPosition.xy)
+ vec3(0.0, 1.0, 0.0),
+ vec3(1.0, 0.0, 0.0),
+ restrictedQuality(VertexPosition.y)
);
}
}