|
@@ -1,114 +0,0 @@
|
|
|
-{
|
|
|
- "cells": [
|
|
|
- {
|
|
|
- "cell_type": "markdown",
|
|
|
- "metadata": {},
|
|
|
- "source": [
|
|
|
- "# A MINI-WEATHER APPLICATION\n",
|
|
|
- "\n",
|
|
|
- "In this lab we will accelerate a Fluid Simulation in the context of atmosphere and weather simulation.\n",
|
|
|
- "The mini weather code mimics the basic dynamics seen in the atmspheric weather and climate.\n",
|
|
|
- "\n",
|
|
|
- "The figure below demonstrates how a narrow jet of fast and slightly cold wind is injected into a balanced, neutral atmosphere at rest from the left domain near the model.\n",
|
|
|
- "\n",
|
|
|
- "<img src=\"images/Time.jpg\" width=\"80%\" height=\"80%\">\n",
|
|
|
- "\n",
|
|
|
- "Simulation is a repetitive process from 0 to the desired simulated time, increasing by Δt on every iteration.\n",
|
|
|
- "Each Δt step is practically the same operation. Each simulation is solving a differential equation that represents how the flow of the atmosphere (fluid) changes according to small perturbations. To simplify this solution the code uses dimensional splitting: Each dimension X and Z are treated independently.\n",
|
|
|
- "\n",
|
|
|
- "<img src=\"images/X_Y.jpg\" width=\"80%\" height=\"80%\">\n",
|
|
|
- "\n",
|
|
|
- "The differential equation has a time derivative that needs integrating, and a simple low-storage Runge-Kutta ODE solver is used to integrate the time derivative. Each time step, the order in which the dimentions are solved is reversed, giving second-order accuracy. \n",
|
|
|
- "\n",
|
|
|
- "<img src=\"images/Range-Kutta.jpg\" width=\"70%\" height=\"70%\">\n",
|
|
|
- "\n",
|
|
|
- "### The objective of this exercise is not to dwell into the Maths part of it but to make use of OpenACC to parallelize and improve the performance.\n",
|
|
|
- "\n",
|
|
|
- "The general flow of the code is as shown in diagram below. For each time step the differential equations are solved.\n",
|
|
|
- "\n",
|
|
|
- "<img src=\"images/Outer_Loop.jpg\" width=\"70%\" height=\"70%\">\n",
|
|
|
- "\n",
|
|
|
- "\n",
|
|
|
- "```cpp\n",
|
|
|
- "while (etime < sim_time) {\n",
|
|
|
- " //If the time step leads to exceeding the simulation time, shorten it for the last step\n",
|
|
|
- " if (etime + dt > sim_time) { dt = sim_time - etime; }\n",
|
|
|
- " //Perform a single time step\n",
|
|
|
- " perform_timestep(state,state_tmp,flux,tend,dt);\n",
|
|
|
- " //Inform the user\n",
|
|
|
- " if (masterproc) { printf( \"Elapsed Time: %lf / %lf\\n\", etime , sim_time ); }\n",
|
|
|
- " //Update the elapsed time and output counter\n",
|
|
|
- " etime = etime + dt;\n",
|
|
|
- " output_counter = output_counter + dt;\n",
|
|
|
- " //If it's time for output, reset the counter, and do output\n",
|
|
|
- " if (output_counter >= output_freq) {\n",
|
|
|
- " output_counter = output_counter - output_freq;\n",
|
|
|
- " output(state,etime);\n",
|
|
|
- " }\n",
|
|
|
- " }\n",
|
|
|
- " \n",
|
|
|
- "```\n",
|
|
|
- "\n",
|
|
|
- "At every time step the direction is reversed to get second order derivative.\n",
|
|
|
- "\n",
|
|
|
- "\n",
|
|
|
- "<img src=\"images/Time_Step.jpg\" width=\"70%\" height=\"70%\">\n",
|
|
|
- "\n",
|
|
|
- "```cpp\n",
|
|
|
- "void perform_timestep( double *state , double *state_tmp , double *flux , double *tend , double dt ) {\n",
|
|
|
- " if (direction_switch) {\n",
|
|
|
- " //x-direction first\n",
|
|
|
- " semi_discrete_step( state , state , state_tmp , dt / 3 , DIR_X , flux , tend );\n",
|
|
|
- " semi_discrete_step( state , state_tmp , state_tmp , dt / 2 , DIR_X , flux , tend );\n",
|
|
|
- " semi_discrete_step( state , state_tmp , state , dt / 1 , DIR_X , flux , tend );\n",
|
|
|
- " //z-direction second\n",
|
|
|
- " semi_discrete_step( state , state , state_tmp , dt / 3 , DIR_Z , flux , tend );\n",
|
|
|
- " semi_discrete_step( state , state_tmp , state_tmp , dt / 2 , DIR_Z , flux , tend );\n",
|
|
|
- " semi_discrete_step( state , state_tmp , state , dt / 1 , DIR_Z , flux , tend );\n",
|
|
|
- " } else {\n",
|
|
|
- " //z-direction second\n",
|
|
|
- " semi_discrete_step( state , state , state_tmp , dt / 3 , DIR_Z , flux , tend );\n",
|
|
|
- " semi_discrete_step( state , state_tmp , state_tmp , dt / 2 , DIR_Z , flux , tend );\n",
|
|
|
- " semi_discrete_step( state , state_tmp , state , dt / 1 , DIR_Z , flux , tend );\n",
|
|
|
- " //x-direction first\n",
|
|
|
- " semi_discrete_step( state , state , state_tmp , dt / 3 , DIR_X , flux , tend );\n",
|
|
|
- " semi_discrete_step( state , state_tmp , state_tmp , dt / 2 , DIR_X , flux , tend );\n",
|
|
|
- " semi_discrete_step( state , state_tmp , state , dt / 1 , DIR_X , flux , tend );\n",
|
|
|
- " }\n",
|
|
|
- " if (direction_switch) { direction_switch = 0; } else { direction_switch = 1; }\n",
|
|
|
- "}\n",
|
|
|
- "```\n",
|
|
|
- "\n",
|
|
|
- "<img src=\"images/Semi_Discrete.jpg\" width=\"70%\" height=\"70%\">\n",
|
|
|
- "\n",
|
|
|
- "--- \n",
|
|
|
- "\n",
|
|
|
- "## Licensing \n",
|
|
|
- "\n",
|
|
|
- "This material is released by NVIDIA Corporation under the Creative Commons Attribution 4.0 International (CC BY 4.0). "
|
|
|
- ]
|
|
|
- }
|
|
|
- ],
|
|
|
- "metadata": {
|
|
|
- "anaconda-cloud": {},
|
|
|
- "kernelspec": {
|
|
|
- "display_name": "Python 3",
|
|
|
- "language": "python",
|
|
|
- "name": "python3"
|
|
|
- },
|
|
|
- "language_info": {
|
|
|
- "codemirror_mode": {
|
|
|
- "name": "ipython",
|
|
|
- "version": 3
|
|
|
- },
|
|
|
- "file_extension": ".py",
|
|
|
- "mimetype": "text/x-python",
|
|
|
- "name": "python",
|
|
|
- "nbconvert_exporter": "python",
|
|
|
- "pygments_lexer": "ipython3",
|
|
|
- "version": "3.7.4"
|
|
|
- }
|
|
|
- },
|
|
|
- "nbformat": 4,
|
|
|
- "nbformat_minor": 1
|
|
|
-}
|