简介

其实流体力学就是专有名词多, 比如流固耦合. 其实就是流体对固体的一个作用. 固体对流体的一个作用而已. 搞得神神秘秘的服了.

使用诺依曼边界条件的建议水滴代码

using UnityEngine;
using System.Collections; public class wave_motion : MonoBehaviour
{
int size = 100;
float rate = 0.005f; // like alpha ?
float gamma = 0.004f;
float damping = 0.996f;
float[,] old_h;
float[,] low_h; // ei
float[,] vh;
float[,] b; bool [,] cg_mask;
float[,] cg_p;
float[,] cg_r;
float[,] cg_Ap;
bool tag=true; Vector3 cube_v = Vector3.zero;
Vector3 cube_w = Vector3.zero; int[,] dirs;
// Use this for initialization
void Start ()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh;
mesh.Clear (); Vector3[] X=new Vector3[size*size]; for (int i=0; i<size; i++)
for (int j=0; j<size; j++)
{
X[i*size+j].x=i*0.1f-size*0.05f;
X[i*size+j].y=0.3f;
X[i*size+j].z=j*0.1f-size*0.05f;
} int[] T = new int[(size - 1) * (size - 1) * 6];
int index = 0;
for (int i=0; i<size-1; i++)
for (int j=0; j<size-1; j++)
{
T[index*6+0]=(i+0)*size+(j+0);
T[index*6+1]=(i+0)*size+(j+1);
T[index*6+2]=(i+1)*size+(j+1);
T[index*6+3]=(i+0)*size+(j+0);
T[index*6+4]=(i+1)*size+(j+1);
T[index*6+5]=(i+1)*size+(j+0);
index++;
}
mesh.vertices = X;
mesh.triangles = T;
mesh.RecalculateNormals (); low_h = new float[size,size];
old_h = new float[size,size];
vh = new float[size,size];
b = new float[size,size]; cg_mask = new bool [size,size];
cg_p = new float[size,size];
cg_r = new float[size,size];
cg_Ap = new float[size,size]; //方向
dirs = new int[4, 2];
dirs[0, 0] = 1;
dirs[0, 1] = 0;
dirs[1, 0] = -1;
dirs[1, 1] = 0;
dirs[2, 0] = 0;
dirs[2, 1] = 1;
dirs[3, 0] = 0;
dirs[3, 1] = -1; for (int i=0; i<size; i++)
for (int j=0; j<size; j++)
{
low_h[i,j]=99999;
old_h[i,j]= 0.3f;
vh[i,j]=0;
}
} void A_Times(bool[,] mask, float[,] x, float[,] Ax, int li, int ui, int lj, int uj)
{
for(int i=li; i<=ui; i++)
for(int j=lj; j<=uj; j++)
if(i>=0 && j>=0 && i<size && j<size && mask[i,j])
{
Ax[i,j]=0;
if(i!=0) Ax[i,j]-=x[i-1,j]-x[i,j];
if(i!=size-1) Ax[i,j]-=x[i+1,j]-x[i,j];
if(j!=0) Ax[i,j]-=x[i,j-1]-x[i,j];
if(j!=size-1) Ax[i,j]-=x[i,j+1]-x[i,j];
}
} float Dot(bool[,] mask, float[,] x, float[,] y, int li, int ui, int lj, int uj)
{
float ret=0;
for(int i=li; i<=ui; i++)
for(int j=lj; j<=uj; j++)
if(i>=0 && j>=0 && i<size && j<size && mask[i,j])
{
ret+=x[i,j]*y[i,j];
}
return ret;
} void Conjugate_Gradient(bool[,] mask, float[,] b, float[,] x, int li, int ui, int lj, int uj)
{
//Solve the Laplacian problem by CG.
A_Times(mask, x, cg_r, li, ui, lj, uj); for(int i=li; i<=ui; i++)
for(int j=lj; j<=uj; j++)
if(i>=0 && j>=0 && i<size && j<size && mask[i,j])
{
cg_p[i,j]=cg_r[i,j]=b[i,j]-cg_r[i,j];
} float rk_norm=Dot(mask, cg_r, cg_r, li, ui, lj, uj); for(int k=0; k<128; k++)
{
if(rk_norm<1e-10f) break;
A_Times(mask, cg_p, cg_Ap, li, ui, lj, uj);
float alpha=rk_norm/Dot(mask, cg_p, cg_Ap, li, ui, lj, uj); for(int i=li; i<=ui; i++)
for(int j=lj; j<=uj; j++)
if(i>=0 && j>=0 && i<size && j<size && mask[i,j])
{
x[i,j] +=alpha*cg_p[i,j];
cg_r[i,j]-=alpha*cg_Ap[i,j];
} float _rk_norm=Dot(mask, cg_r, cg_r, li, ui, lj, uj);
float beta=_rk_norm/rk_norm;
rk_norm=_rk_norm; for(int i=li; i<=ui; i++)
for(int j=lj; j<=uj; j++)
if(i>=0 && j>=0 && i<size && j<size && mask[i,j])
{
cg_p[i,j]=cg_r[i,j]+beta*cg_p[i,j];
}
} } void get_vh(float[,] new_h, int blk_id)
{
Vector3 p = new Vector3(0, 0, 0);
if (blk_id == 1)
{
GameObject block = GameObject.Find("Cube");
p = block.transform.position;
}
else if(blk_id == 2)
{
GameObject block = GameObject.Find("Block");
p = block.transform.position;
} Mesh mesh = GetComponent<MeshFilter>().mesh;
Vector3[] X = mesh.vertices; int li = (int)Mathf.Ceil((p.x - 0.5f + 5f) / 0.1f);
int lj = (int)Mathf.Ceil((p.z - 0.5f + 5f) / 0.1f);
int ui = (int)Mathf.Floor((p.x + 0.5f + 5f) / 0.1f);
int uj = (int)Mathf.Floor((p.z + 0.5f + 5f) / 0.1f); // for block 1, calculate low_h;
for (int i = li; i <= ui; i++)
for (int j = lj; j <= uj; j++)
if(i >= 0 && j >= 0 && i < size && j < size)
{
cg_mask[i, j] = true;
low_h[i, j] = 0f;
}
else
{
cg_mask[i, j] = false;
low_h[i, j] = new_h[i, j];
} // then set up b and cg_mask for conjugate gradient.
for(int i=0; i<size; i++)
{
for(int j=0; j<size; j++)
{
b[i, j] = (new_h[i, j] - low_h[i, j]) / rate;
}
}
//Solve the Poisson equation to obtain vh (virtual height).
Conjugate_Gradient(cg_mask, b, vh, li, ui, lj, uj);
} void Shallow_Wave(float[,] old_h, float[,] h, float [,] new_h)
{
//Step 1:
//TODO: Compute new_h based on the shallow wave model.
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
float hi_1j = i > 0 ? h[i - 1, j] : h[i, j];
float hi1j = i + 1 < size ? h[i + 1, j] : h[i, j];
float hij_1 = j > 0 ? h[i, j - 1] : h[i, j];
float hij1 = j + 1 < size ? h[i, j + 1] : h[i, j];
new_h[i, j] = h[i, j] + (h[i, j] - old_h[i, j]) * damping +
rate * (hi1j + hij1 + hi_1j + hij_1 - 4 * h[i, j]);
}
}
//Step 2: Block->Water coupling
//for (int i = 0; i < size; i++)
//{
// for (int j = 0; j < size; j++)
// {
// vh[i, j] = 0;
// }
//}
//TODO: for block 1, calculate low_h.
//TODO: then set up b and cg_mask for conjugate gradient.
//TODO: Solve the Poisson equation to obtain vh (virtual height).
//get_vh(new_h, 1);
//TODO: for block 2, calculate low_h.
//TODO: then set up b and cg_mask for conjugate gradient.
//TODO: Solve the Poisson equation to obtain vh (virtual height).
//get_vh(new_h, 2);
//TODO: Diminish vh. //TODO: Update new_h by vh.
//for (int i = 0; i < size; i++)
// for (int j = 0; j < size; j++)
// if (i >= 0 && j >= 0 && i < size && j < size)
// {
// if (i != 0) new_h[i, j] += (vh[i - 1, j] - vh[i, j]) * rate;
// if (i != size - 1) new_h[i, j] += (vh[i + 1, j] - vh[i, j]) * rate;
// if (j != 0) new_h[i, j] += (vh[i, j - 1] - vh[i, j]) * rate;
// if (j != size - 1) new_h[i, j] += (vh[i, j + 1] - vh[i, j]) * rate;
// }
//Step 3
//TODO: old_h <- h; h <- new_h;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
old_h[i, j] = h[i, j];
h[i, j] = new_h[i, j];
}
}
//Step 4: Water->Block coupling.
//More TODO here.
} // Update is called once per frame
void Update ()
{
Mesh mesh = GetComponent<MeshFilter> ().mesh;
Vector3[] X = mesh.vertices;
float[,] new_h = new float[size, size];
float[,] h = new float[size, size]; //TODO: Load X.y into h.
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
h[i, j] = X[i * size + j].y;
}
}
if (Input.GetKeyDown ("r"))
{
//TODO: Add random water.
int i = Random.Range(0, size);
int j = Random.Range(0, size);
float rt = Random.value;
float r = 0;
for (int k = 0; k < 4; k++)
{
int ni = i + dirs[k, 0];
int nj = j + dirs[k, 1];
if (ni >= 0 && ni < size && nj >= 0 && nj < size)
{
r += h[ni, nj] * rt;
h[ni, nj] -= h[ni, nj] * rt;
}
}
//Debug.Log("add_r:" + r);
h[i, j] += r;
} for(int l=0; l<8; l++)
{
Shallow_Wave(old_h, h, new_h);
} //TODO: Store h back into X.y and recalculate normal.
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
X[i * size + j].y = h[i, j];
}
} mesh.vertices = X;
mesh.RecalculateNormals();
}
}

波动效果的公式

\[h_{i, j}^{\text {new }} \leftarrow h_{i, j}+\left(h_{i, j}-h_{i, j}^{\text {old }}\right) * \text { damping }+\left(h_{i-1, j}+h_{i+1, j}+h_{i, j-1}+h_{i, j+1}-4 h_{i, j}\right) * \text { rate. }
\]

波动公式



经过转换其中的变量

这里简化ei=0 即 cube 块 直接和底面进行接触, 如果只考虑一个固体->流体的情况

vh 表示 虚拟高度

接下来就使用这张image



上面的图其实类似



只不过一个是真实高度一个是虚拟高度引起的江河湖海的高度变化.

Games103 浅波模型的更多相关文章

  1. 控制论模型&心流模型&波模型

    1.控制论模型 这是对设定的目标,通过多次输入和输出,反馈调节,最终达成目标的方法.广泛运用于自然科学与社会科学中.反馈的周期长短决定了调节精度的大小以及达到目标的速度.反馈结果与目标背离的立即纠正, ...

  2. osgEarth设置模型旋转角度

    #include<windows.h> #include <osgViewer/Viewer> #include <osgEarthDrivers/gdal/GDALOp ...

  3. 揭秘Keras推荐系统如何建立模型、获取用户爱好

    你是否有过这样的经历?当你在亚马逊商城浏览一些书籍,或者购买过一些书籍后,你的偏好就会被系统学到,系统会基于一些假设为你推荐相关书目.为什么系统会知道,在这背后又藏着哪些秘密呢? 荐系统可以从百万甚至 ...

  4. 深度CTR预估模型中的特征自动组合机制演化简史 zz

    众所周知,深度学习在计算机视觉.语音识别.自然语言处理等领域最先取得突破并成为主流方法.但是,深度学习为什么是在这些领域而不是其他领域最先成功呢?我想一个原因就是图像.语音.文本数据在空间和时间上具有 ...

  5. CTR预估经典模型总结

    计算广告领域中数据特点:    1 正负样本不平衡    2 大量id类特征,高维,多领域(一个类别型特征就是一个field,比如上面的Weekday.Gender.City这是三个field),稀疏 ...

  6. 深度学习笔记之关于基本思想、浅层学习、Neural Network和训练过程(三)

    不多说,直接上干货! 五.Deep Learning的基本思想 假设我们有一个系统S,它有n层(S1,…Sn),它的输入是I,输出是O,形象地表示为: I =>S1=>S2=>….. ...

  7. 计算广告之CTR预估-FNN模型解析

    原论文:Deep learning over multi-field categorical data 地址:https://arxiv.org/pdf/1601.02376.pdf 一.问题由来 基 ...

  8. 深度排序模型概述(一)Wide&Deep/xDeepFM

    本文记录几个在广告和推荐里面rank阶段常用的模型.广告领域机器学习问题的输入其实很大程度了影响了模型的选择,因为输入一般维度非常高,稀疏,同时包含连续性特征和离散型特征.模型即使到现在DeepFM类 ...

  9. 【百奥云GS专栏】全基因组选择之模型篇

    目录 1. 前言 2. BLUP方法 ABLUP GBLUP ssGBLUP RRBLUP 3. 贝叶斯方法 BayesA BayesB BayesC/Cπ/Dπ Bayesian Lasso 4. ...

  10. 机器学习&数据挖掘笔记_14(GMM-HMM语音识别简单理解)

    为了对GMM-HMM在语音识别上的应用有个宏观认识,花了些时间读了下HTK(用htk完成简单的孤立词识别)的部分源码,对该算法总算有了点大概认识,达到了预期我想要的.不得不说,网络上关于语音识别的通俗 ...

随机推荐

  1. 安装yml 与 wget

    一.备份/etc/yum.repos.d/CentOS-Base.repo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-B ...

  2. 一文速通 Python 并行计算:07 Python 多线程编程-线程池的使用和多线程的性能评估

    一文速通 Python 并行计算:07 Python 多线程编程-线程池的使用和多线程的性能评估 摘要: 本文介绍了 Python 线程池(ThreadPoolExecutor)的使用方法,包括线程池 ...

  3. Linux系统的一些基本文件和目录管理命令

    pwd:查看当前目录所在位置. ls:查看当前目录下的文件和目录.例如我们查看根目录下的文件和目录: (注:蓝字的是目录,白字的是文件,绿字的是可执行的文件或装有可执行文件的目录,红字是压缩包) 如果 ...

  4. Java对象相等判断

    你是谁啊?你是不是我??(⊙_⊙)? 我们知道比较对象相等可以使用equal方法(来自Object对象的方法) 但是你打开Object的equal方法你会发现: public boolean equa ...

  5. 定制Django的Tag和Filter(一)

    1.在 app 目录下创建 templatetags 目录(目录名只能是 templatetags). 如: app/ __init__.py models.py templatetags/ __in ...

  6. manim变换效果总结

    在ManimCE中,除了上一篇介绍的丰富的动画效果外,变换效果也是制作精彩视觉内容的重要工具. 变换效果主要用于改变对象的形状.大小.颜色或位置,让对象在动画中呈现出动态的变化. 本文详细总结了 Ma ...

  7. SgLang代码细读-3. Cache

    本地显存池 数据结构 因为kv cache有MHA,MLA,DoubleSparse 等多种自定义类型,需要进行一步抽象将框架和cache类型做隔离, 所以有了2级内存池的设计. 一级保存和cache ...

  8. Spring中的单例Bean是线程安全的吗

    前言   Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean ...

  9. 【2020.11.30提高组模拟】剪辣椒(chilli) 题解

    [2020.11.30提高组模拟]剪辣椒(chilli) 题解 题意简述 给你一棵树,删去两条边,使得形成的三棵新树的大小极差最小化.求最小极差. \(3\le n\le 200,000\). Sol ...

  10. NSMutableDictionary 的内存布局

    有关NSDictionary的内存布局,可以参看<NSDictionary 的内存布局>. 1 类图 和<NSDictionary 的内存布局>中的类图相比较,本章类图多了2个 ...