updated SoL code
This commit is contained in:
1 parent
4b466d5852
commit
6d0651923e
2 files changed
+447
-132
No files matched your search
+438
-122
@@ -103,7 +103,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
@@ -116,7 +116,6 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Downloading training data (73MB), this can take a moment the first time...\n",
|
||||
"Loaded data, 6 training sims\n"
|
||||
]
|
||||
}
|
||||
@@ -124,13 +123,13 @@
|
||||
"source": [
|
||||
"import os, sys, logging, argparse, pickle, glob, random, distutils.dir_util\n",
|
||||
"\n",
|
||||
"if not os.path.isfile('data-karman2d-train.pickle'):\n",
|
||||
"if not os.path.isfile('sol-data-karman-2d-train.pickle'):\n",
|
||||
" import urllib.request\n",
|
||||
" url=\"https://ge.in.tum.de/download/2020-solver-in-the-loop/sol-karman-2d-data.pickle\"\n",
|
||||
" print(\"Downloading training data (73MB), this can take a moment the first time...\")\n",
|
||||
" urllib.request.urlretrieve(url, 'data-karman2d-train.pickle')\n",
|
||||
" urllib.request.urlretrieve(url, 'sol-data-karman-2d-train.pickle')\n",
|
||||
"\n",
|
||||
"with open('data-karman2d-train.pickle', 'rb') as f: dataPreloaded = pickle.load(f)\n",
|
||||
"with open('sol-data-karman-2d-train.pickle', 'rb') as f: dataPreloaded = pickle.load(f)\n",
|
||||
"print(\"Loaded data, {} training sims\".format(len(dataPreloaded)) )\n"
|
||||
]
|
||||
},
|
||||
@@ -153,39 +152,10 @@
|
||||
"id": "BGN4GqxkIueM",
|
||||
"outputId": "095adbf8-1ef6-41fd-938e-6cafcf0fdfdc"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\u001b[K |████████████████████████████████| 2.7MB 4.3MB/s \n",
|
||||
"\u001b[?25h Building wheel for phiflow (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
|
||||
"TensorFlow 1.x selected.\n",
|
||||
"Could not load resample cuda libraries: CUDA binaries not found at /usr/local/lib/python3.6/dist-packages/phi/tf/cuda/build/resample.so. Run \"python setup.py cuda\" to compile them\n",
|
||||
"WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/phi/tf/util.py:119: The name tf.AUTO_REUSE is deprecated. Please use tf.compat.v1.AUTO_REUSE instead.\n",
|
||||
"\n",
|
||||
"WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/phi/tf/profiling.py:12: The name tf.RunOptions is deprecated. Please use tf.compat.v1.RunOptions instead.\n",
|
||||
"\n",
|
||||
"WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/phi/tf/profiling.py:13: The name tf.RunMetadata is deprecated. Please use tf.compat.v1.RunMetadata instead.\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/usr/local/lib/python3.6/dist-packages/phi/viz/display.py:80: UserWarning: GUI is disabled because of missing dependencies: No module named 'dash_core_components'. To install all dependencies, run $ pip install phiflow[gui]\n",
|
||||
" warnings.warn('GUI is disabled because of missing dependencies: %s. To install all dependencies, run $ pip install phiflow[gui]' % import_error)\n",
|
||||
"/usr/local/lib/python3.6/dist-packages/phi/tf/flow.py:15: UserWarning: TensorFlow-CUDA solver is not available. To compile it, download phiflow sources and run\n",
|
||||
"$ python setup.py tf_cuda\n",
|
||||
"before reinstalling phiflow.\n",
|
||||
" warnings.warn(\"TensorFlow-CUDA solver is not available. To compile it, download phiflow sources and run\\n$ python setup.py tf_cuda\\nbefore reinstalling phiflow.\")\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install --upgrade --quiet phiflow\n",
|
||||
"%tensorflow_version 1.x\n",
|
||||
"#!pip install --upgrade --quiet phiflow\n",
|
||||
"#%tensorflow_version 1.x\n",
|
||||
"\n",
|
||||
"from phi.tf.flow import *\n",
|
||||
"import phi.tf.util\n",
|
||||
@@ -228,7 +198,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"id": "6WNMcdWUw4EP"
|
||||
},
|
||||
@@ -280,7 +250,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 4,
|
||||
"metadata": {
|
||||
"id": "qIrWYTy6xscA"
|
||||
},
|
||||
@@ -292,7 +262,7 @@
|
||||
" keras.layers.Conv2D(filters=32, kernel_size=5, padding='same', activation=tf.nn.relu),\n",
|
||||
" keras.layers.Conv2D(filters=64, kernel_size=5, padding='same', activation=tf.nn.relu),\n",
|
||||
" keras.layers.Conv2D(filters=2, kernel_size=5, padding='same', activation=None), # u, v\n",
|
||||
" ])\n"
|
||||
" ])"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -306,7 +276,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"id": "TyfpA7Fbx0ro"
|
||||
},
|
||||
@@ -366,14 +336,14 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 6,
|
||||
"metadata": {
|
||||
"id": "hhGFpTjGyRyg"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def to_keras(fluidstate, ext_const_channel):\n",
|
||||
" # drop the unused edges of the staggered velocity grid making its dim same to the centered grid's\n",
|
||||
" # drop the unused edges of the staggered velocity grid making its size the same as the centered grid\n",
|
||||
" return math.concat(\n",
|
||||
" [\n",
|
||||
" fluidstate.velocity.staggered_tensor()[:, :-1:, :-1:, 0:2],\n",
|
||||
@@ -405,14 +375,14 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"id": "tjywcdD2y20t"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"class Dataset():\n",
|
||||
" def __init__(self, data_preloaded, num_frames, num_sims=None, batch_size=1):\n",
|
||||
" def __init__(self, data_preloaded, num_frames, num_sims=None, batch_size=1, is_testset=False):\n",
|
||||
" self.epoch = None\n",
|
||||
" self.epochIdx = 0\n",
|
||||
" self.batch = None\n",
|
||||
@@ -427,17 +397,22 @@
|
||||
" self.numBatches = num_sims//batch_size\n",
|
||||
" self.numFrames = num_frames\n",
|
||||
" self.numSteps = num_frames\n",
|
||||
"\n",
|
||||
" #with open('/Users/thuerey/temp/sol-karman-2d-data.pickle', 'rb') as f: self.dataPreloaded = pickle.load(f)\n",
|
||||
" \n",
|
||||
" self.dataSims = ['karman-fdt-hires-set/sim_%06d'%i for i in range(num_sims) ]\n",
|
||||
" # initialize directory keys (using naming scheme from SoL codebase)\n",
|
||||
" # constant additional per-sim channel: Reynolds numbers from data generation\n",
|
||||
" # hard coded for training and test data here\n",
|
||||
" if not is_testset:\n",
|
||||
" self.dataSims = ['karman-fdt-hires-set/sim_%06d'%i for i in range(num_sims) ]\n",
|
||||
" ReNrs = [160000.0, 320000.0, 640000.0, 1280000.0, 2560000.0, 5120000.0]\n",
|
||||
" self.extConstChannelPerSim = { self.dataSims[i]:[ReNrs[i]] for i in range(num_sims) }\n",
|
||||
" else:\n",
|
||||
" self.dataSims = ['karman-fdt-hires-testset-reduced/sim_%06d'%i for i in range(num_sims) ]\n",
|
||||
" ReNrs = [240000.0, 960000.0, 3840000.0] \n",
|
||||
" self.extConstChannelPerSim = { self.dataSims[i]:[ReNrs[i]] for i in range(num_sims) }\n",
|
||||
"\n",
|
||||
" self.dataFrms = [ np.arange(num_frames) for _ in self.dataSims ] \n",
|
||||
"\n",
|
||||
" # constant additional per-sim channel: Reynolds numbers from data generation\n",
|
||||
" ReNrs = [160000.0, 320000.0, 640000.0, 1280000.0, 2560000.0, 5120000.0]\n",
|
||||
" self.extConstChannelPerSim = { self.dataSims[i]:[ReNrs[i]] for i in range(num_sims) }\n",
|
||||
"\n",
|
||||
" #print(format(self.dataPreloaded[self.dataSims[0]][0][0].shape )) # debugging example: check shape of a single density field\n",
|
||||
" #print(format(self.dataPreloaded[self.dataSims[0]][0][0].shape )) # debugging example: check shape of a single marker density field\n",
|
||||
"\n",
|
||||
" # the data has the following shape ['sim', frame, field (dens/vel)] where each field is [batch-size, y-size, x-size, channels]\n",
|
||||
" self.resolution = self.dataPreloaded[self.dataSims[0]][0][0].shape[1:3] \n",
|
||||
@@ -445,7 +420,7 @@
|
||||
" # compute data statistics for normalization\n",
|
||||
" self.dataStats = {\n",
|
||||
" 'std': (\n",
|
||||
" np.std(np.concatenate([np.absolute(self.dataPreloaded[asim][i][0].reshape(-1)) for asim in self.dataSims for i in range(num_frames)], axis=-1)), # density\n",
|
||||
" np.std(np.concatenate([np.absolute(self.dataPreloaded[asim][i][0].reshape(-1)) for asim in self.dataSims for i in range(num_frames)], axis=-1)), # marker density\n",
|
||||
" (\n",
|
||||
" np.std(np.concatenate([np.absolute(self.dataPreloaded[asim][i][1][...,0].reshape(-1)) for asim in self.dataSims for i in range(num_frames)])), # vel[0]\n",
|
||||
" np.std(np.concatenate([np.absolute(self.dataPreloaded[asim][i][1][...,1].reshape(-1)) for asim in self.dataSims for i in range(num_frames)])), # vel[1]\n",
|
||||
@@ -454,7 +429,8 @@
|
||||
" 'ext.std': [ np.std([np.absolute(self.extConstChannelPerSim[asim][0]) for asim in self.dataSims]) ] # Re\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" print(\"Data stats: \"+format(self.dataStats))\n",
|
||||
" if not is_testset:\n",
|
||||
" print(\"Data stats: \"+format(self.dataStats))\n",
|
||||
"\n",
|
||||
" # re-shuffle data for next epoch\n",
|
||||
" def newEpoch(self, exclude_tail=0, shuffle_data=True):\n",
|
||||
@@ -491,7 +467,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"id": "Dfwd4TnqN1Tn"
|
||||
},
|
||||
@@ -535,12 +511,14 @@
|
||||
"id": "bIWnyPYlz8q7"
|
||||
},
|
||||
"source": [
|
||||
"After all the definitions we can finally run some code. We can define the data set with the downloaded data from the first cell:"
|
||||
"Note that the `density` here denotes a passively advected marker field, and not the density of the fluid. Below we'll be focusing on the velocity only, the marker density is tracked purely for visualization purposes.\n",
|
||||
"\n",
|
||||
"After all the definitions we can finally run some code. We can define the dataset object with the downloaded data from the first cell."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
@@ -558,15 +536,11 @@
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"output_dir = \"./\" # TODO create? , replaced params['train'] and params['tf']\n",
|
||||
"nsims = 6\n",
|
||||
"batch_size = 3\n",
|
||||
"simsteps = 500\n",
|
||||
"\n",
|
||||
"dataset = Dataset( data_preloaded=dataPreloaded, num_frames=simsteps, num_sims=nsims, batch_size=batch_size )\n",
|
||||
"#dataset.newEpoch()\n",
|
||||
"#print(format(getData(dataset,1)))\n",
|
||||
"#print(format(dataset.getData(1)))\n"
|
||||
"dataset = Dataset( data_preloaded=dataPreloaded, num_frames=simsteps, num_sims=nsims, batch_size=batch_size )\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -575,7 +549,7 @@
|
||||
"id": "0N92RooWPzeA"
|
||||
},
|
||||
"source": [
|
||||
"Additionally, we can define several global variables to control the training and the simulation.\n",
|
||||
"Additionally, we've defined several global variables to control the training and the simulation.\n",
|
||||
"\n",
|
||||
"The most important and interesting one is `msteps`. It defines the number of simulation steps that are unrolled at each training iteration. This directly influences the runtime of each training step, as we first have to simulation all steps forward, and then backpropagate the gradient through all `msteps` simulation steps interleaved with the NN evaluations. However, this is where we'll receive important feedback in terms of gradients how the inferred corrections actually influence a running simulation. Hence, larger `msteps` are typically better.\n",
|
||||
"\n",
|
||||
@@ -584,7 +558,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 10,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
@@ -597,7 +571,7 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"WARNING:tensorflow:From /tensorflow-1.15.2/python3.6/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.\n",
|
||||
"WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1630: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.\n",
|
||||
"Instructions for updating:\n",
|
||||
"If using Keras pass *_constraint arguments to layers.\n",
|
||||
"Model: \"sequential\"\n",
|
||||
@@ -620,8 +594,8 @@
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:23: DeprecationWarning: placeholder_like may not respect the batch dimension. For State objects, use placeholder(state.shape) instead.\n",
|
||||
"/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:24: DeprecationWarning: placeholder_like may not respect the batch dimension. For State objects, use placeholder(state.shape) instead.\n"
|
||||
"/Users/thuerey/Library/Python/3.7/lib/python/site-packages/ipykernel_launcher.py:23: DeprecationWarning: placeholder_like may not respect the batch dimension. For State objects, use placeholder(state.shape) instead.\n",
|
||||
"/Users/thuerey/Library/Python/3.7/lib/python/site-packages/ipykernel_launcher.py:24: DeprecationWarning: placeholder_like may not respect the batch dimension. For State objects, use placeholder(state.shape) instead.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -674,7 +648,8 @@
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "D5NeMcLGQaxh"
|
||||
"id": "D5NeMcLGQaxh",
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
@@ -716,7 +691,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 12,
|
||||
"metadata": {
|
||||
"id": "K2JcO3-QQgC9"
|
||||
},
|
||||
@@ -760,7 +735,7 @@
|
||||
"train_step = opt.minimize(loss)\n",
|
||||
"\n",
|
||||
"tf_session = tf.Session() \n",
|
||||
"scene = Scene.create(output_dir, count=batch_size, mkdir=False, copy_calling_script=False)\n",
|
||||
"scene = Scene.create(\".\", count=batch_size, mkdir=False, copy_calling_script=False)\n",
|
||||
"sess = Session(scene, session=tf_session)\n",
|
||||
"tf.compat.v1.keras.backend.set_session(tf_session)\n",
|
||||
"\n",
|
||||
@@ -768,7 +743,7 @@
|
||||
"\n",
|
||||
"# optional, load existing network...\n",
|
||||
"if resume>0: \n",
|
||||
" ld_network = keras.models.load_model(output_dir+'/nn_epoch{:04d}.h5'.format(resume))\n",
|
||||
" ld_network = keras.models.load_model('./nn_epoch{:04d}.h5'.format(resume))\n",
|
||||
" network.set_weights(ld_network.get_weights())\n"
|
||||
]
|
||||
},
|
||||
@@ -783,13 +758,12 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 14,
|
||||
"metadata": {
|
||||
"id": "Am3hSdNgRPEh"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"def lr_schedule(epoch, current_lr):\n",
|
||||
" lr = current_lr\n",
|
||||
" if epoch == 25: lr *= 0.5\n",
|
||||
@@ -807,12 +781,12 @@
|
||||
"source": [
|
||||
"Finally, we can start training! This is very straight forward now, we simply loop over the desired number of iterations, get a batch each time via `getData`, feed it into the source simulation input `source_in`, and compare it in the loss with the `reference` data for the batch.\n",
|
||||
"\n",
|
||||
"The setup above will automatically take care that the differentiable physics setup used here provides the right gradient information, and connects to the tensorflow network. Be warned: due to the complexity of the setup, this training can take a while..."
|
||||
"The setup above will automatically take care that the differentiable physics setup used here provides the right gradient information, and connects to the tensorflow network. Be warned: due to the complexity of the setup, this training run can take a while... (If you have a saved `final.h5` model from a previous run, you can potentially skip this block and load the previously trained model instead.)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"colab": {
|
||||
"base_uri": "https://localhost:8080/"
|
||||
@@ -825,39 +799,39 @@
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"epoch 001/004, batch 001/002, step 0001/0496: loss=8114.626953125\n",
|
||||
"epoch 001/004, batch 001/002, step 0002/0496: loss=3371.28125\n",
|
||||
"epoch 001/004, batch 001/002, step 0003/0496: loss=1594.294189453125\n",
|
||||
"epoch 001/004, batch 001/002, step 0032/0496: loss=261.2645263671875\n",
|
||||
"epoch 001/004, batch 001/002, step 0063/0496: loss=124.70037078857422\n",
|
||||
"epoch 001/004, batch 001/002, step 0094/0496: loss=86.60037231445312\n",
|
||||
"epoch 001/004, batch 001/002, step 0125/0496: loss=93.21685028076172\n",
|
||||
"epoch 001/004, batch 001/002, step 0156/0496: loss=64.77877807617188\n",
|
||||
"epoch 001/004, batch 001/002, step 0187/0496: loss=58.933082580566406\n",
|
||||
"epoch 001/004, batch 001/002, step 0218/0496: loss=51.40797805786133\n",
|
||||
"epoch 001/004, batch 001/002, step 0249/0496: loss=42.819091796875\n",
|
||||
"epoch 001/004, batch 001/002, step 0280/0496: loss=46.30024719238281\n",
|
||||
"epoch 001/004, batch 001/002, step 0311/0496: loss=41.07358932495117\n",
|
||||
"epoch 001/004, batch 001/002, step 0342/0496: loss=40.12362289428711\n",
|
||||
"epoch 001/004, batch 001/002, step 0373/0496: loss=41.094932556152344\n",
|
||||
"epoch 001/004, batch 001/002, step 0404/0496: loss=36.17275619506836\n",
|
||||
"epoch 001/004, batch 001/002, step 0435/0496: loss=37.64105987548828\n",
|
||||
"epoch 001/004, batch 001/002, step 0466/0496: loss=33.44026184082031\n",
|
||||
"epoch 001/004, batch 002/002, step 0001/0496: loss=36.6204719543457\n",
|
||||
"epoch 001/004, batch 002/002, step 0002/0496: loss=29.037982940673828\n",
|
||||
"epoch 001/004, batch 002/002, step 0003/0496: loss=27.977163314819336\n",
|
||||
"epoch 002/004, batch 001/002, step 0001/0496: loss=13.540712356567383\n",
|
||||
"epoch 002/004, batch 001/002, step 0125/0496: loss=12.313040733337402\n",
|
||||
"epoch 002/004, batch 001/002, step 0249/0496: loss=11.129035949707031\n",
|
||||
"epoch 002/004, batch 001/002, step 0373/0496: loss=11.969249725341797\n",
|
||||
"epoch 003/004, batch 001/002, step 0001/0496: loss=8.394614219665527\n",
|
||||
"epoch 003/004, batch 001/002, step 0125/0496: loss=7.2177557945251465\n",
|
||||
"epoch 003/004, batch 001/002, step 0249/0496: loss=8.274188041687012\n",
|
||||
"epoch 003/004, batch 001/002, step 0373/0496: loss=9.177286148071289\n",
|
||||
"epoch 004/004, batch 001/002, step 0001/0496: loss=6.306344985961914\n",
|
||||
"epoch 004/004, batch 001/002, step 0125/0496: loss=4.158570289611816\n",
|
||||
"epoch 004/004, batch 001/002, step 0249/0496: loss=4.282064437866211\n",
|
||||
"epoch 004/004, batch 001/002, step 0373/0496: loss=5.2111334800720215\n"
|
||||
"epoch 001/004, batch 001/002, step 0001/0496: loss=6816.91162109375\n",
|
||||
"epoch 001/004, batch 001/002, step 0002/0496: loss=4036.171875\n",
|
||||
"epoch 001/004, batch 001/002, step 0003/0496: loss=1627.97412109375\n",
|
||||
"epoch 001/004, batch 001/002, step 0032/0496: loss=344.7778625488281\n",
|
||||
"epoch 001/004, batch 001/002, step 0063/0496: loss=166.46800231933594\n",
|
||||
"epoch 001/004, batch 001/002, step 0094/0496: loss=113.92779541015625\n",
|
||||
"epoch 001/004, batch 001/002, step 0125/0496: loss=91.14945983886719\n",
|
||||
"epoch 001/004, batch 001/002, step 0156/0496: loss=73.96617126464844\n",
|
||||
"epoch 001/004, batch 001/002, step 0187/0496: loss=60.41331481933594\n",
|
||||
"epoch 001/004, batch 001/002, step 0218/0496: loss=60.62569046020508\n",
|
||||
"epoch 001/004, batch 001/002, step 0249/0496: loss=54.98934555053711\n",
|
||||
"epoch 001/004, batch 001/002, step 0280/0496: loss=46.72457504272461\n",
|
||||
"epoch 001/004, batch 001/002, step 0311/0496: loss=41.06715393066406\n",
|
||||
"epoch 001/004, batch 001/002, step 0342/0496: loss=41.29859924316406\n",
|
||||
"epoch 001/004, batch 001/002, step 0373/0496: loss=37.749908447265625\n",
|
||||
"epoch 001/004, batch 001/002, step 0404/0496: loss=27.011524200439453\n",
|
||||
"epoch 001/004, batch 001/002, step 0435/0496: loss=28.442049026489258\n",
|
||||
"epoch 001/004, batch 001/002, step 0466/0496: loss=31.86280059814453\n",
|
||||
"epoch 001/004, batch 002/002, step 0001/0496: loss=30.664321899414062\n",
|
||||
"epoch 001/004, batch 002/002, step 0002/0496: loss=29.717803955078125\n",
|
||||
"epoch 001/004, batch 002/002, step 0003/0496: loss=29.26577377319336\n",
|
||||
"epoch 002/004, batch 001/002, step 0001/0496: loss=17.874845504760742\n",
|
||||
"epoch 002/004, batch 001/002, step 0125/0496: loss=18.53813362121582\n",
|
||||
"epoch 002/004, batch 001/002, step 0249/0496: loss=21.788429260253906\n",
|
||||
"epoch 002/004, batch 001/002, step 0373/0496: loss=8.640719413757324\n",
|
||||
"epoch 003/004, batch 001/002, step 0001/0496: loss=6.8903045654296875\n",
|
||||
"epoch 003/004, batch 001/002, step 0125/0496: loss=8.793163299560547\n",
|
||||
"epoch 003/004, batch 001/002, step 0249/0496: loss=5.2972636222839355\n",
|
||||
"epoch 003/004, batch 001/002, step 0373/0496: loss=6.923160076141357\n",
|
||||
"epoch 004/004, batch 001/002, step 0001/0496: loss=4.272143363952637\n",
|
||||
"epoch 004/004, batch 001/002, step 0125/0496: loss=4.24481725692749\n",
|
||||
"epoch 004/004, batch 001/002, step 0249/0496: loss=5.760097026824951\n",
|
||||
"epoch 004/004, batch 001/002, step 0373/0496: loss=4.635688781738281\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -890,10 +864,10 @@
|
||||
"\n",
|
||||
" dataset.nextBatch()\n",
|
||||
"\n",
|
||||
" if j%10==9: network.save(output_dir+'/nn_epoch{:04d}.h5'.format(j+1))\n",
|
||||
" if j%10==9: network.save('./nn_epoch{:04d}.h5'.format(j+1))\n",
|
||||
"\n",
|
||||
"# all done! save final version\n",
|
||||
"network.save(output_dir+'/final.h5')\n"
|
||||
"network.save('./final.h5')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -904,21 +878,26 @@
|
||||
"source": [
|
||||
"The loss should go down from above 1000 initially to below 10. This is a good sign, but of course it's even more important to see how the resulting solver fares on new inputs.\n",
|
||||
"\n",
|
||||
"Note that after training we're realized a hybrid solver, consisting of a regular _source_ simulator, and a network that was trained to specificially interact with this simulator for a chosen domain of simulation cases.\n",
|
||||
"Note that with this training approach we've realized a hybrid solver, consisting of a regular _source_ simulator, and a network that was trained to specificially interact with this simulator for a chosen domain of simulation cases.\n",
|
||||
"\n",
|
||||
"Due to the size of this example, we'll refer you to the external code - the network trained here should be directly useable in [this apply script](https://github.com/tum-pbs/Solver-in-the-Loop/blob/master/karman-2d/karman_apply.py).\n",
|
||||
"Let's see how well this works by applying it to a set of test data inputs with new Reynolds numbers that were not part of the training data.\n",
|
||||
"\n",
|
||||
"---\n",
|
||||
"To keep things somewhat simple, we won't aim for a high performance version of our hybrid solver. For performance, please checck out the external code base: the network trained here should be directly useable in [this apply script](https://github.com/tum-pbs/Solver-in-the-Loop/blob/master/karman-2d/karman_apply.py).\n",
|
||||
"\n",
|
||||
"## Next steps\n",
|
||||
"---"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Evaluation \n",
|
||||
"\n",
|
||||
"* Modify the training to further reduce the training error. With the medium network you should be able to get the loss down to around 1.\n",
|
||||
"In order to evaluate the performance of our DL-powered solver, we essentially only need to repeat the inner loop of each training iteration for more steps. While we were limited to `msteps` evaluations at training time, we can now run our solver for arbitrary lengths. This is a good test for how well our solver has learned to keep the data within the desired distribution, and represents a generalization test for longer rollouts.\n",
|
||||
"\n",
|
||||
"* Export the network to the external github code, and run it on new wake flow cases. You'll see that a reduced training error not always directly correlates with an improved test performance\n",
|
||||
"We can reuse the solver code from above, but in the following, we will consider two simulated versions: for comparison, we'll run one reference simulation in the _source_ space (i.e., without any modifications). This version receives the regular outputs of each evaluation of the simulator, and ignores the learned correction (denoted as `sourcesim` below). The second version, `prediction`, repeatedly computes the source solver plus the learned correction, and advances this state in the solver.\n",
|
||||
"\n",
|
||||
"* Turn off the differentiable physics training (by setting `msteps=1`), and compare it with the DP version\n",
|
||||
"\n",
|
||||
"* Try to train with even more `msteps`. Note that due to the recurrent nature of the training, you'll probabaly have to load a pre-trained state to stabilize the first iterations"
|
||||
"A subtle but important point: we still have to use the normalization from the original training data set here, i.e., the `dataset.dataStats['std']` values. Below we'll create a new test data set with it's own mean and standard deviation, but the model never saw this data before. It was trained with the data in `dataset` above, and hence we have to use the constants from there to make sure the model receives values that it can relate to the data it was trained with."
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -928,7 +907,344 @@
|
||||
"id": "RumKebW_05xp"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
"source": [
|
||||
"# similar to msteps from before\n",
|
||||
"evalsteps=1\n",
|
||||
"\n",
|
||||
"sourcesim_in = phi.tf.util.placeholder_like(source) # reuse source from above\n",
|
||||
"sourcesim, prediction, correction = [], [], []\n",
|
||||
"\n",
|
||||
"for i in range(evalsteps):\n",
|
||||
" sourcesim += [\n",
|
||||
" KarmanFlow().step(\n",
|
||||
" sourcesim_in if i==0 else prediction[-1],\n",
|
||||
" re=Re_in,\n",
|
||||
" res=source_res[-1], \n",
|
||||
" velBCy=velBCy,\n",
|
||||
" velBCyMask=velBCyMask\n",
|
||||
" )\n",
|
||||
" ]\n",
|
||||
"\n",
|
||||
" # important: use normalization from _original_ dataset here, not the testdata below\n",
|
||||
" correction += [\n",
|
||||
" to_staggered(\n",
|
||||
" network(\n",
|
||||
" to_keras(sourcesim[-1], Re_in)/[\n",
|
||||
" *(dataset.dataStats['std'][1]), # velocity\n",
|
||||
" dataset.dataStats['ext.std'][0] # Re\n",
|
||||
" ]\n",
|
||||
" ) * dataset.dataStats['std'][1],\n",
|
||||
" box=source.velocity.box\n",
|
||||
" )\n",
|
||||
" ]\n",
|
||||
"\n",
|
||||
" prediction += [sourcesim[-1].copied_with(velocity=sourcesim[-1].velocity + correction[-1])]\n",
|
||||
" "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now we also need a set of new data to apply the learned solver to. Below, we'll download a new set of Reynolds numbers (inbetween the ones used for training), so that we can later on run the unmodified simulator and the DL-powered one on these cases.\n",
|
||||
"\n",
|
||||
"We're creating a new dataset object `dataset_test` here, which organizes the data. We're simply using the first batch of the unshuffled dataset, though."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Loaded test data, 3 training sims\n",
|
||||
"dict_keys(['karman-fdt-hires-testset-reduced/sim_000000', 'karman-fdt-hires-testset-reduced/sim_000001', 'karman-fdt-hires-testset-reduced/sim_000002'])\n",
|
||||
"Reynolds numbers in test data set: [240000.0, 960000.0, 3840000.0]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"if not os.path.isfile('sol-data-karman-2d-test.pickle'):\n",
|
||||
" import urllib.request\n",
|
||||
" url=\"https://ge.in.tum.de/download/2020-solver-in-the-loop/sol-data-karman-2d-test.pickle\"\n",
|
||||
" print(\"Downloading test data (38MB), this can take a moment the first time...\")\n",
|
||||
" urllib.request.urlretrieve(url, 'sol-data-karman-2d-test.pickle')\n",
|
||||
"\n",
|
||||
"with open('sol-data-karman-2d-test.pickle', 'rb') as f: data_test_preloaded = pickle.load(f)\n",
|
||||
"print(\"Loaded test data, {} training sims\".format(len(data_test_preloaded)) )\n",
|
||||
"\n",
|
||||
"print(format(data_test_preloaded.keys()))\n",
|
||||
"dataset_test = Dataset( data_preloaded=data_test_preloaded, is_testset=True, num_frames=simsteps, num_sims=3, batch_size=batch_size )\n",
|
||||
"\n",
|
||||
"# we only need 1 batch to start with\n",
|
||||
"dataset_test.newEpoch(shuffle_data=False)\n",
|
||||
"batch = getData(dataset_test, consecutive_frames=msteps) \n",
|
||||
"re_nr = batch[2] # Reynolds numbers\n",
|
||||
"source_test = source.copied_with(density=batch[0][0], velocity=batch[1][0])\n",
|
||||
"reference = [ reference[k].copied_with(density=batch[0][k+1], velocity=batch[1][k+1]) for k in range(msteps) ]\n",
|
||||
"\n",
|
||||
"print(\"Reynolds numbers in test data set: \"+format(re_nr))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Now we can evaluate the _source_ simulation, and the _prediction_ of our learned hybrid solver:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Source simulation steps 121\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"steps_source = [source_test]\n",
|
||||
"\n",
|
||||
"for i in range(120):\n",
|
||||
" my_feed_dict = { sourcesim_in: steps_source[-1], Re_in: re_nr, lr_in: current_lr }\n",
|
||||
" sourcesim_out = sess.run([sourcesim[0]], my_feed_dict) \n",
|
||||
" steps_source.append( sourcesim_out[0] )\n",
|
||||
"\n",
|
||||
"print(\"Source simulation steps \"+format(len(steps_source)))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Steps with hybrid solver 121\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"steps_pred = [source_test]\n",
|
||||
"\n",
|
||||
"for i in range(120):\n",
|
||||
" my_feed_dict = { sourcesim_in: steps_pred[-1], Re_in: re_nr, lr_in: current_lr }\n",
|
||||
" prediction_out = sess.run([prediction[0]], my_feed_dict) # w corr\n",
|
||||
" steps_pred.append( prediction_out[0] )\n",
|
||||
"\n",
|
||||
"print(\"Steps with hybrid solver \"+format(len(steps_pred)))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Let's visualize the differences of the two outputs by plotting the y component of the velocities over time. The two following code cells show six velocity snapshots for the batch index `b` in intervals of 20 time steps."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 54,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 1152x360 with 6 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import pylab\n",
|
||||
"b = 1 # batch index for the following comparisons\n",
|
||||
"\n",
|
||||
"fig, axes = pylab.subplots(1, 6, figsize=(16, 5))\n",
|
||||
"for i in range(1,7):\n",
|
||||
" v = steps_source[i*20].velocity.data[0].data[b,:,:,0] \n",
|
||||
" axes[i-1].imshow( v , origin='lower', cmap='magma')\n",
|
||||
" axes[i-1].set_title(f\" Source simulation t={i*20} \")\n",
|
||||
"pylab.tight_layout()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 55,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 1152x360 with 6 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"fig, axes = pylab.subplots(1, 6, figsize=(16, 5))\n",
|
||||
"for i in range(1,7):\n",
|
||||
" v = steps_pred[i*20].velocity.data[0].data[b,:,:,0] \n",
|
||||
" axes[i-1].imshow( v , origin='lower', cmap='magma')\n",
|
||||
" axes[i-1].set_title(f\" Hybrid solver t={i*20} \")\n",
|
||||
"pylab.tight_layout()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"They both start out with the same initial state at $t=0$ (a downsampled solution from the reference solution manifold), and at $t=20$ the solutions still share similarities. Over time, the source version strongly diffuses the strucutres in the flow and looses momentum. The flow behind the obstacles becomes straight, and lacks clear vortices. \n",
|
||||
"\n",
|
||||
"The version produced by the hybrid solver does much better. It preserves the vortex shedding even after more than one hundred updates. Note that both outputs were produced by the same underlying solver. The second version just profits from the learned corrector which has learned to revert the overly strong dissipation of the solver. However, it also produces some visible axis aligned structures, especially near the sides of the domain. These could be alleviated with improved training setups, e.g., more look-ahead, and a larger model.\n",
|
||||
"\n",
|
||||
"We can also compare and quantify how the models do w.r.t. reference data. The next cell plots one time step of the three versions: the reference data after 50 steps, and the re-simulated version of the source and our hybrid solver, together with a per-cell error of the two:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 56,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 1008x360 with 4 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"index = 50 # time step index\n",
|
||||
"\n",
|
||||
"ref = [ math.concat( dataset_test.dataPreloaded[ dataset_test.dataSims[b] ][ j ][1] , axis=0) for j in range(121) ]\n",
|
||||
"\n",
|
||||
"fig, axes = pylab.subplots(1, 4, figsize=(14, 5))\n",
|
||||
"\n",
|
||||
"v = ref[index][:,:,0] \n",
|
||||
"axes[0].imshow( v , origin='lower', cmap='magma')\n",
|
||||
"axes[0].set_title(f\" Reference \")\n",
|
||||
"\n",
|
||||
"v = steps_source[index].velocity.data[0].data[b,:,:,0] \n",
|
||||
"axes[1].imshow( v , origin='lower', cmap='magma')\n",
|
||||
"axes[1].set_title(f\" Source \")\n",
|
||||
"\n",
|
||||
"v = steps_pred[index].velocity.data[0].data[b,:,:,0] \n",
|
||||
"axes[2].imshow( v , origin='lower', cmap='magma')\n",
|
||||
"axes[2].set_title(f\" Learned \")\n",
|
||||
"\n",
|
||||
"# show error side by side\n",
|
||||
"err_source = ref[index][:,1:-2,0] - steps_source[index].velocity.data[0].data[b,:,1:-1,0] \n",
|
||||
"err_pred = ref[index][:,1:-2,0] - steps_pred[index].velocity.data[0].data[b,:,1:-1,0] \n",
|
||||
"v = np.concatenate([err_source,err_pred], axis=1)\n",
|
||||
"axes[3].imshow( v , origin='lower', cmap='magma')\n",
|
||||
"axes[3].set_title(f\" Errors: Source & Learned\")\n",
|
||||
"\n",
|
||||
"pylab.tight_layout()\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This shows very clearly how the pure source simulation in the middle deviates from the reference on the left. Apart from the slight vertical streaks, the learned version stays much closer to the reference solution. \n",
|
||||
"\n",
|
||||
"The two per-cell error images on the right also illustrate this: the source version has much larger errors that show how it systematically underestimates the vortices that should form. The error for the learned version is much more evenly distributed, and significantly smaller.\n",
|
||||
"\n",
|
||||
"Next, we can quantify these observations:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 57,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"MAE for source: 0.05912385508418083 , and hybrid: 0.0402643121778965\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"image/png": "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 truncated
|
||||
"text/plain": [
|
||||
"<Figure size 432x288 with 1 Axes>"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"needs_background": "light"
|
||||
},
|
||||
"output_type": "display_data"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"errors_source, errors_pred = [], []\n",
|
||||
"for index in range(100):\n",
|
||||
" vs = ref[index][:,1:-2,0] - steps_source[index].velocity.data[0].data[b,:,1:-1,0] \n",
|
||||
" vp = ref[index][:,1:-2,0] - steps_pred[index].velocity.data[0].data[b,:,1:-1,0] \n",
|
||||
" errors_source.append(np.mean(np.abs(vs))) \n",
|
||||
" errors_pred.append(np.mean(np.abs(vp)))\n",
|
||||
" #print(\"Errors for step \"+format(index)+\" source: \"+format(np.mean(np.abs(vs))) +\" , hybrid: \"+format(np.mean(np.abs(vp))))\n",
|
||||
"\n",
|
||||
"fig = pylab.figure().gca()\n",
|
||||
"pltx = np.linspace(0,99,100)\n",
|
||||
"fig.plot(pltx, errors_source, lw=2, color='mediumblue', label='Source') \n",
|
||||
"fig.plot(pltx, errors_pred, lw=2, color='green', label='Hybrid')\n",
|
||||
"pylab.xlabel('Time step'); pylab.ylabel('Error'); fig.legend()\n",
|
||||
"\n",
|
||||
"print(\"MAE for source: \"+format(np.mean(errors_source)) +\" , and hybrid: \"+format(np.mean(errors_pred)) )\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The overall mean absolute error (MAE) is almost 50% larger for the regular simulation. The graph below shows this behavior over time: the error of the source version is clearly above the errors of the hybrid simulator.\n",
|
||||
"\n",
|
||||
"This concludes our evaluation. Note that the improved behavior of the hybrid solver is difficult to reliably measure with simple vector norms such as an MAE or $L^2$ norm. To achieve this, we'd need to employ other, domain specific metrics. In this case, metrics for fluids based on vorticity and turbulence properties of the flow would be applicable. However, in this text we instead want to focus on DL-related topics, and target another inverse problem with differentiable physics solvers in the next chapter."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"---\n",
|
||||
"\n",
|
||||
"## Next steps\n",
|
||||
"\n",
|
||||
"* Modify the training to further reduce the training error. With the _medium_ network you should be able to get the loss down to around 1.\n",
|
||||
"\n",
|
||||
"* Use the external github code to generate new test data, and run your model on these cases. You'll see that a reduced training error not always directly correlates with an improved test performance.\n",
|
||||
"\n",
|
||||
"* Turn off the differentiable physics training (by setting `msteps=1`), and compare it with the DP version.\n",
|
||||
"\n",
|
||||
"* Likewise, train a model with a larger `msteps` setting, e.g., 8 or 16. Note that due to the recurrent nature of the training, you'll probabaly have to load a pre-trained state to stabilize the first iterations."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
@@ -952,7 +1268,7 @@
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.5"
|
||||
"version": "3.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
||||
@@ -65,11 +65,8 @@ The contents of the following files would not have been possible without the hel
|
||||
- [Nils Thuerey](https://ge.in.tum.de/about/n-thuerey/)
|
||||
- [Kiwon Um](https://ge.in.tum.de/about/kiwon/)
|
||||
|
||||
<!-- % some markdown tests follow ...
|
||||
|
||||
---
|
||||
|
||||
a b c
|
||||
<!--
|
||||
% some markdown tests follow ...
|
||||
|
||||
```{admonition} My title2
|
||||
:class: seealso
|
||||
@@ -85,12 +82,17 @@ See also... Test link: {doc}`supervised`
|
||||
|
||||
## TODOs , include
|
||||
|
||||
- DP intro, check transpose of Jacobians in equations
|
||||
- DP SoL, generate result
|
||||
- DP control, show targets at bottom?
|
||||
- include latent space physics, mention LSTM, end of supervised?
|
||||
- update teaser image
|
||||
- DP intro, check transpose of Jacobians in equations
|
||||
- outlook: include latent space physics & LSTMs, also ContConv benjamin (see below)
|
||||
|
||||
|
||||
<!--
|
||||
temporary notes, remove:
|
||||
-->
|
||||
|
||||
## Other planned content
|
||||
|
||||
Supervised simple starting point
|
||||
@@ -123,9 +125,6 @@ TODO, for version 2.x add:
|
||||
time series, sequence prediction?] {cite}`wiewel2019lss,bkim2019deep,wiewel2020lsssubdiv`
|
||||
include DeepFluids variant?
|
||||
|
||||
[BAYES , prob?]
|
||||
include results Jakob / Maximilian
|
||||
|
||||
[unstruct / lagrangian] {cite}`prantl2019tranquil,ummenhofer2019contconv`
|
||||
include ContConv / Lukas
|
||||
|
||||
|
||||
Reference in new issue
Block a user