├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── ReadMe.txt ├── TuringPatternKernels ├── PatternDynamic.cu ├── PatternDynamic.cuh ├── PatternType.h └── TuringPatternKernels.vcxproj ├── TuringPatterns.cpp ├── TuringPatterns.sln ├── TuringPatterns.vcxproj ├── TuringPatterns.vcxproj.filters ├── TuringPatterns.vcxproj.user ├── TuringPatterns ├── TuringPatterns.vcxproj ├── TuringPatterns.vcxproj.user └── main.cu ├── _config.yml ├── bacteria2_compressed.gif ├── bacteria_compressed.gif ├── br_stripes_compressed.gif ├── coral2_compressed.gif ├── coral3_compressed.gif ├── coral_compressed.gif ├── fhn_compressed.gif ├── fhnb_compressed.gif ├── lines_compressed.gif ├── patternRunner.py ├── plotter.py ├── schnakenberg_compressed.gif ├── stdafx.cpp ├── stdafx.h └── targetver.h /.gitignore: -------------------------------------------------------------------------------- 1 | /home/raiden/programming/TuringPatterns/cmake/.gitignore.in -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "cmake"] 2 | path = cmake 3 | url = git@github.com:pmontalb/CmakeUtilities.git 4 | [submodule "PdeFiniteDifferenceSolver"] 5 | path = PdeFiniteDifferenceSolver 6 | url = git@github.com:pmontalb/PdeFiniteDifferenceSolver.git 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(TuringPatterns) 3 | 4 | include(cmake/All.cmake) 5 | set(LANGUAGES_USE_CUDA ON CACHE BOOL "" FORCE) 6 | 7 | # PdeFiniteDifference 8 | add_subdirectory(PdeFiniteDifferenceSolver ${CMAKE_BINARY_DIR}/PdeFiniteDifferenceSolver EXCLUDE_FROM_ALL) 9 | 10 | create_cuda_library( 11 | NAME 12 | TuringPatternKernels 13 | SOURCES 14 | TuringPatternKernels/PatternDynamic.cu 15 | DEPENDENCIES 16 | CudaLightKernels 17 | PUBLIC_INCLUDE_DIRECTORIES 18 | TuringPatternKernels 19 | ) 20 | 21 | create_cuda_executable( 22 | NAME 23 | TuringPatterns 24 | SOURCES 25 | TuringPatterns/main.cu 26 | DEPENDENCIES 27 | TuringPatternKernels PdeFiniteDifferenceSolverManager 28 | PRIVATE_INCLUDE_DIRECTORIES 29 | PdeFiniteDifferenceSolver 30 | SYSTEM_DEPENDENCIES 31 | forge 32 | ) 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Paolo Montalbano 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Turing Patterns: A C++/CUDA application for simulating 2D reaction-diffusion dynamics showing diffusion driven instability 2 | 3 | This repository implements the numerical schemes for simulating the most popular reaction diffusion dynamics that exhibits Turing instability. 4 | 5 | The general two-dimensional PDE is of the form: 6 | 7 | 8 | 9 | The numerical scheme implemented is a simple Forward Euler scheme, which is known to be unstable but easy to implement. As opposed to the usual stability condition, the introduciton of a source term makes it more unstable, although dt in the region of dx^2 seem to be a reasonable choice. An extension to this could be a Runge-Kutta solver or an IMEX scheme, where the source term is considered in the explicit portion. 10 | 11 | The Finite Difference schemes are implemented in CUDA. Since the non-linear nature of the dynamics I found it easier to implement without making use of CuBLAS. 12 | 13 | The dynamics that I've implemented are: 14 | - Gray-Scott 15 | - Brussellator 16 | - Schnakernberg 17 | - Thomas 18 | - Fitz-Hugh Nagumo 19 | 20 | I made a python script that calls the C++ executable and gather the numerical results and produce the color plot animation. I saved the resulting GIFs, which are shown below: 21 | 22 |

23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |

34 | -------------------------------------------------------------------------------- /ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : TuringPatterns Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this TuringPatterns application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your TuringPatterns application. 9 | 10 | 11 | TuringPatterns.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | TuringPatterns.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | TuringPatterns.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named TuringPatterns.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /TuringPatternKernels/PatternDynamic.cu: -------------------------------------------------------------------------------- 1 | #include "PatternDynamic.cuh" 2 | 3 | EXTERN_C 4 | { 5 | /** 6 | * [u, v]' += dt * [f(u,v); g(u,v)]' 7 | */ 8 | EXPORT int _ApplyPatternDynamic(MemoryBuffer u, MemoryBuffer v, const PatternType type, const double dt, const double param1, const double param2) 9 | { 10 | #define APPLY_PATTERN_DYNAMIC(TYPE)\ 11 | switch (u.mathDomain)\ 12 | {\ 13 | case MathDomain::Float:\ 14 | CUDA_CALL_SINGLE(__##TYPE##__, (float*)u.pointer, (float*)v.pointer, (float)dt, (float)param1, (float)param2, u.size);\ 15 | break;\ 16 | case MathDomain::Double:\ 17 | CUDA_CALL_SINGLE(__##TYPE##__, (double*)u.pointer, (double*)v.pointer, (double)dt, (double)param1, (double)param2, u.size);\ 18 | break;\ 19 | default:\ 20 | return CudaKernelException::_NotImplementedException;\ 21 | } 22 | 23 | switch (type) 24 | { 25 | case PatternType::FitzHughNagumo: 26 | APPLY_PATTERN_DYNAMIC(FitzHughNagumo); 27 | break; 28 | case PatternType::Thomas: 29 | APPLY_PATTERN_DYNAMIC(Thomas); 30 | break; 31 | case PatternType::Schnakenberg: 32 | APPLY_PATTERN_DYNAMIC(Schnakenberg); 33 | break; 34 | case PatternType::Brussellator: 35 | APPLY_PATTERN_DYNAMIC(Brussellator); 36 | break; 37 | case PatternType::GrayScott: 38 | APPLY_PATTERN_DYNAMIC(GrayScott); 39 | break; 40 | default: 41 | return CudaKernelException::_NotImplementedException; 42 | } 43 | 44 | #undef APPLY_PATTERN_DYNAMIC 45 | return cudaGetLastError(); 46 | } 47 | } 48 | 49 | template 50 | GLOBAL void __FitzHughNagumo__(T* RESTRICT uNew, T* RESTRICT vNew, const T dt, const T param1, const T param2, const size_t sz) 51 | { 52 | CUDA_FUNCTION_PROLOGUE 53 | 54 | CUDA_FOR_LOOP_PROLOGUE 55 | 56 | const T u = uNew[i]; 57 | const T v = vNew[i]; 58 | uNew[i] += dt * (u * (1.0 - u * u) - v + param1); 59 | vNew[i] += dt * param2 * (u - v); 60 | 61 | CUDA_FOR_LOOP_EPILOGUE 62 | } 63 | 64 | template 65 | GLOBAL void __Thomas__(T* RESTRICT uNew, T* RESTRICT vNew, const T dt, const T param1, const T param2, const size_t sz) 66 | { 67 | static constexpr T rho = { 13.0 }; 68 | static constexpr T K = { 0.05 }; 69 | static constexpr T alpha = { 1.5 }; 70 | static constexpr T gamma = { 200.0 }; 71 | 72 | CUDA_FUNCTION_PROLOGUE 73 | 74 | CUDA_FOR_LOOP_PROLOGUE 75 | const T u = uNew[i]; 76 | const T v = vNew[i]; 77 | 78 | const T h = rho * u * v / (1.0 + u + K * u * u); 79 | 80 | uNew[i] += dt * gamma * (param1 - u - h); 81 | vNew[i] += dt * gamma * (alpha * (param2 - v) - h); 82 | 83 | CUDA_FOR_LOOP_EPILOGUE 84 | } 85 | 86 | template 87 | GLOBAL void __Schnakenberg__(T* RESTRICT uNew, T* RESTRICT vNew, const T dt, const T param1, const T param2, const size_t sz) 88 | { 89 | CUDA_FUNCTION_PROLOGUE 90 | 91 | CUDA_FOR_LOOP_PROLOGUE 92 | const T u = uNew[i]; 93 | const T v = vNew[i]; 94 | const T u2v = u * u * v; 95 | 96 | uNew[i] += dt * (param1 - u + u2v); 97 | vNew[i] += dt * (param2 - u2v); 98 | 99 | CUDA_FOR_LOOP_EPILOGUE 100 | } 101 | 102 | template 103 | GLOBAL void __Brussellator__(T* RESTRICT uNew, T* RESTRICT vNew, const T dt, const T param1, const T param2, const size_t sz) 104 | { 105 | CUDA_FUNCTION_PROLOGUE 106 | 107 | CUDA_FOR_LOOP_PROLOGUE 108 | const T u = uNew[i]; 109 | const T v = vNew[i]; 110 | const T u2v = u * u * v; 111 | 112 | uNew[i] += dt * (param1 - (param2 + 1.0) * u + u2v); 113 | vNew[i] += dt * (param2 * u - u2v); 114 | 115 | CUDA_FOR_LOOP_EPILOGUE 116 | } 117 | 118 | template 119 | GLOBAL void __GrayScott__(T* RESTRICT uNew, T* RESTRICT vNew, const T dt, const T param1, const T param2, const size_t sz) 120 | { 121 | CUDA_FUNCTION_PROLOGUE 122 | 123 | CUDA_FOR_LOOP_PROLOGUE 124 | const T u = uNew[i]; 125 | const T v = vNew[i]; 126 | const T uv2 = u * v * v; 127 | 128 | uNew[i] += dt * (-uv2 + param1 * (1.0 - u)); 129 | vNew[i] += dt * (uv2 - (param1 + param2) * v); 130 | 131 | CUDA_FOR_LOOP_EPILOGUE 132 | } -------------------------------------------------------------------------------- /TuringPatternKernels/PatternDynamic.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | //#include 4 | #include 5 | #include 6 | 7 | #include "PatternType.h" 8 | 9 | EXTERN_C 10 | { 11 | /** 12 | * [u, v]' += dt * [f(u,v); g(u,v)]' 13 | */ 14 | EXPORT int _ApplyPatternDynamic(MemoryBuffer u, MemoryBuffer v, const PatternType type, const double dt, const double param1, const double param2); 15 | } 16 | 17 | template 18 | GLOBAL void __FitzHughNagumo__(T* RESTRICT u, T* RESTRICT v, const T dt, const T param1, const T param2, const size_t sz); 19 | 20 | template 21 | GLOBAL void __Thomas__(T* RESTRICT u, T* RESTRICT v, const T dt, const T param1, const T param2, const size_t sz); 22 | 23 | template 24 | GLOBAL void __Schnakenberg__(T* RESTRICT u, T* RESTRICT v, const T dt, const T param1, const T param2, const size_t sz); 25 | 26 | template 27 | GLOBAL void __Brussellator__(T* RESTRICT u, T* RESTRICT v, const T dt, const T param1, const T param2, const size_t sz); 28 | 29 | template 30 | GLOBAL void __GrayScott__(T* RESTRICT u, T* RESTRICT v, const T dt, const T param1, const T param2, const size_t sz); 31 | -------------------------------------------------------------------------------- /TuringPatternKernels/PatternType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | EXTERN_C 6 | { 7 | /** 8 | * Defines the time discretizer type 9 | */ 10 | enum class PatternType 11 | { 12 | Null = 0, 13 | 14 | FitzHughNagumo = 1, 15 | Thomas = 2, 16 | Schnakenberg = 3, 17 | Brussellator = 4, 18 | GrayScott = 5, 19 | }; 20 | } -------------------------------------------------------------------------------- /TuringPatternKernels/TuringPatternKernels.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {3695B232-419E-46F9-98FE-8BDE862F6DC1} 22 | TuringPatternKernels 23 | 10.0.16299.0 24 | 25 | 26 | 27 | DynamicLibrary 28 | true 29 | MultiByte 30 | v141 31 | 32 | 33 | Application 34 | false 35 | true 36 | MultiByte 37 | v141 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | true 52 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)\..\CudaLightKernels;$(SolutionDir)\TuringPatternKernels; 53 | 54 | 55 | 56 | Level3 57 | Disabled 58 | WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 59 | 60 | 61 | true 62 | Console 63 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 64 | 65 | 66 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 67 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 68 | 69 | 70 | 64 71 | $(SolutionDir)\..\CudaLightKernels;$(SolutionDir)\TuringPatternKernels; 72 | 73 | 74 | 75 | 76 | Level3 77 | MaxSpeed 78 | true 79 | true 80 | WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 81 | 82 | 83 | true 84 | true 85 | true 86 | Console 87 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 88 | 89 | 90 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 91 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 92 | 93 | 94 | 64 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /TuringPatterns.cpp: -------------------------------------------------------------------------------- 1 | // TuringPatterns.cpp : Defines the entry point for the console application. 2 | // 3 | 4 | #include "FiniteDifference\Parabolic.h" 5 | #include "FiniteDifference\Pattern.h" 6 | #include "cnpy.h" 7 | #include "stdafx.h" 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #pragma region Example parabolic PDE solvers 16 | 17 | void Example1D() 18 | { 19 | using namespace la; 20 | 21 | CVector grid = la::LinSpace(0.0, 1.0, 16); 22 | auto x = grid.Get(); 23 | std::vector initialCondition(grid.size()); 24 | for (size_t i = 0; i < initialCondition.size(); i++) 25 | initialCondition[i] = exp(-5 * (x[i] - .5) * (x[i] - .5)); 26 | 27 | CVector ic(grid); 28 | ic.ReadFrom(initialCondition); 29 | fd::CParabolicData1D input(grid, ic, 1.0, EBoundaryCondition::ZeroFlux); 30 | 31 | double dt = 1e-4; 32 | fd::CParabolicSolver1D solver(input, dt); 33 | 34 | CVector solution(grid.size()); 35 | solver.Initialize(solution); 36 | 37 | CMatrix toPlot(solution.size(), 100); 38 | 39 | toPlot.columns[0]->ReadFrom(solution); 40 | size_t nIterPerRound = 10; 41 | for (size_t n = 1; n < toPlot.nCols(); n++) 42 | { 43 | solver.Iterate(solution, nIterPerRound); 44 | toPlot.columns[n]->ReadFrom(solution); 45 | } 46 | 47 | cnpy::npy_save("results1D.npy", toPlot.Get(), "w"); 48 | } 49 | 50 | void Example2D() 51 | { 52 | using namespace la; 53 | using namespace std::chrono; 54 | 55 | high_resolution_clock::time_point start = high_resolution_clock::now(); 56 | high_resolution_clock::time_point t1 = high_resolution_clock::now(); 57 | 58 | CVector xGrid = la::LinSpace(0.0, 1.0, 128); 59 | CVector yGrid = la::LinSpace(0.0, 1.0, 128); 60 | 61 | high_resolution_clock::time_point t2 = high_resolution_clock::now(); 62 | std::cout << "Created grid in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; 63 | 64 | t1 = high_resolution_clock::now(); 65 | 66 | auto x = xGrid.Get(); 67 | auto y = yGrid.Get(); 68 | std::vector initialCondition(xGrid.size() * yGrid.size()); 69 | for (size_t j = 0; j < yGrid.size(); j++) 70 | for (size_t i = 0; i < xGrid.size(); i++) 71 | initialCondition[i + x.size() * j] = exp(-5 * ((x[i] - .5) * (x[i] - .5) + (y[j] - .5) * (y[j] - .5))); 72 | 73 | CMatrix ic(xGrid.size(), yGrid.size()); 74 | ic.ReadFrom(initialCondition); 75 | 76 | t2 = high_resolution_clock::now(); 77 | std::cout << "Created initial condition in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; 78 | 79 | fd::CParabolicData2D input(xGrid, yGrid, ic, 1.0, EBoundaryCondition::ZeroFlux); 80 | 81 | double dt = 1e-6; 82 | fd::CParabolicSolver2D solver(input, dt); 83 | 84 | CMatrix solution(xGrid.size(), yGrid.size()); 85 | solver.Initialize(solution); 86 | 87 | CTensor toPlot(solution.nRows(), 100); 88 | 89 | toPlot.matrices[0]->ReadFrom(solution); 90 | size_t nIterPerRound = 1000; 91 | for (size_t n = 1; n < toPlot.nMatrices(); n++) 92 | { 93 | t1 = high_resolution_clock::now(); 94 | 95 | solver.Iterate(solution, nIterPerRound); 96 | 97 | t2 = high_resolution_clock::now(); 98 | std::cout << "Done " << nIterPerRound << " iterations in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; 99 | 100 | toPlot.matrices[n]->ReadFrom(solution); 101 | } 102 | 103 | 104 | t1 = high_resolution_clock::now(); 105 | cnpy::npy_save("results2D.npy", &toPlot.Get()[0], { toPlot.nMatrices(), toPlot.nCols(), toPlot.nRows() }, "w"); 106 | t2 = high_resolution_clock::now(); 107 | std::cout << "Saved NPY in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; 108 | 109 | high_resolution_clock::time_point end = high_resolution_clock::now(); 110 | 111 | std::cout << "Finished in " << duration_cast>(end - start).count() << " seconds." << std::endl; 112 | } 113 | 114 | #pragma endregion 115 | 116 | struct RunParameters 117 | { 118 | EPatternType patternType = EPatternType::GrayScott; 119 | EBoundaryCondition boundaryCondition = EBoundaryCondition::Periodic; 120 | 121 | size_t xDimension = 256; 122 | double xMin = 0.0; 123 | double xMax = 0.0; 124 | 125 | size_t yDimension = 256; 126 | double yMin = 0.0; 127 | double yMax = 0.0; 128 | 129 | /// Number of plots 130 | size_t nIter = 200; 131 | 132 | /// Number of iterations between each plot 133 | size_t nIterPerRound = 1000; 134 | 135 | double dt = 1.0; 136 | 137 | double whiteNoiseScale = .05; 138 | 139 | double uDiffusion = 0.0; 140 | double vDiffusion = 0.0; 141 | 142 | double patternParameter1 = 0.0; 143 | double patternParameter2 = 0.0; 144 | 145 | char* solutionFile = ""; 146 | }; 147 | 148 | #pragma region Implementation 149 | 150 | typedef void (*MakeInitialConditionDelegate)(la::CMatrix& uInitialCondition, la::CMatrix& vInitialCondition, const RunParameters& params); 151 | 152 | double BinarySearch(const std::function& f, double a, double b, const double tolerance = 1e-8) 153 | { 154 | double fa = f(a); 155 | double fb = f(b); 156 | 157 | if (fa * fb > 0) 158 | throw std::exception("f doesn't change sign"); 159 | 160 | double c = 0; 161 | for (size_t i = 0; i < 1000; i++) 162 | { 163 | c = .5 * (a + b); 164 | const double fc = f(c); 165 | fa = f(a); 166 | fb = f(b); 167 | 168 | if (fabs(fc) < tolerance) 169 | return c; 170 | 171 | if (fa * fc > 0) 172 | a = c; 173 | else 174 | b = c; 175 | } 176 | 177 | std::cout << "CONVERGENCE ERROR" << std::endl; 178 | throw; 179 | } 180 | 181 | template 182 | void MakeInitialCondition(la::CMatrix& uInitialCondition, la::CMatrix& vInitialCondition, const RunParameters& params) 183 | { 184 | switch (patternType) 185 | { 186 | case EPatternType::FitzHughNagumo: 187 | uInitialCondition.Set(0.0); 188 | vInitialCondition.Set(0.0); 189 | break; 190 | case EPatternType::Thomas: 191 | { 192 | auto f = [&](const double v) { 193 | const double u = -1.5 * (params.patternParameter2 - v) + params.patternParameter1; 194 | const double h = 13.0 * u * v / (1.0 + u + 0.05 * u * u); 195 | return h - (params.patternParameter1 - u); 196 | }; 197 | const double v0 = BinarySearch(f, 0.0, 100.0); 198 | const double u0 = -1.5 * (params.patternParameter2 - v0) + params.patternParameter1; 199 | 200 | uInitialCondition.Set(u0); 201 | vInitialCondition.Set(v0); 202 | } 203 | break; 204 | case EPatternType::Schnakernberg: 205 | uInitialCondition.Set(params.patternParameter1 + params.patternParameter2); 206 | vInitialCondition.Set(params.patternParameter2 / ((params.patternParameter1 + params.patternParameter2) * (params.patternParameter1 + params.patternParameter2))); 207 | break; 208 | case EPatternType::Brussellator: 209 | uInitialCondition.Set(params.patternParameter1); 210 | vInitialCondition.Set(params.patternParameter2 / params.patternParameter1); 211 | break; 212 | case EPatternType::GrayScott: 213 | { 214 | uInitialCondition.Set(1.0); 215 | vInitialCondition.Set(0.0); 216 | 217 | std::vector uCenteredSquare(uInitialCondition.size()); 218 | std::vector vCenteredSquare(uInitialCondition.size()); 219 | size_t squareStartX = uInitialCondition.nRows() * 2 / 5; 220 | size_t squareEndX = uInitialCondition.nRows() * 3 / 5; 221 | size_t squareStartY = uInitialCondition.nCols() * 2 / 5; 222 | size_t squareEndY = uInitialCondition.nCols() * 3 / 5; 223 | for (size_t j = squareStartY; j < squareEndY; j++) 224 | { 225 | for (size_t i = squareStartX; i < squareEndX; i++) 226 | { 227 | uCenteredSquare[i + uInitialCondition.nRows() * j] = -.5; 228 | vCenteredSquare[i + uInitialCondition.nRows() * j] = .25; 229 | } 230 | } 231 | la::CMatrix uAddition(uInitialCondition); 232 | uAddition.ReadFrom(uCenteredSquare); 233 | la::CMatrix vAddition(vInitialCondition); 234 | vAddition.ReadFrom(vCenteredSquare); 235 | 236 | uInitialCondition.AddEqual(uAddition); 237 | vInitialCondition.AddEqual(vAddition); 238 | } 239 | break; 240 | default: 241 | break; 242 | } 243 | } 244 | 245 | void RunDelegate(MakeInitialConditionDelegate makeInitialCondition, const RunParameters& params) 246 | { 247 | using namespace la; 248 | using namespace std::chrono; 249 | 250 | high_resolution_clock::time_point start = high_resolution_clock::now(); 251 | high_resolution_clock::time_point t1 = high_resolution_clock::now(); 252 | 253 | // ************ Make Grid ************ 254 | CVector xGrid = la::LinSpace(params.xMin, params.xMax, params.xDimension); 255 | CVector yGrid = la::LinSpace(params.yMin, params.yMax, params.yDimension); 256 | 257 | high_resolution_clock::time_point t2 = high_resolution_clock::now(); 258 | 259 | std::cout << "Created grid in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; // *********************************** 260 | 261 | // ***************** Make Initial Condition ****************** 262 | t1 = high_resolution_clock::now(); 263 | 264 | CMatrix whiteNoise = la::RandomGaussian(xGrid.size(), yGrid.size()); 265 | whiteNoise.Scale(params.whiteNoiseScale); 266 | 267 | CMatrix uInitialCondition(xGrid.size(), yGrid.size()); 268 | CMatrix vInitialCondition(xGrid.size(), yGrid.size()); 269 | makeInitialCondition(uInitialCondition, vInitialCondition, params); 270 | 271 | uInitialCondition.AddEqual(whiteNoise); 272 | vInitialCondition.AddEqual(whiteNoise); 273 | 274 | t2 = high_resolution_clock::now(); 275 | std::cout << "Created initial condition in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; 276 | // *************************************************************** 277 | 278 | // **************** Initialize Solver *************** 279 | t1 = high_resolution_clock::now(); 280 | 281 | fd::CPatternData2D input(xGrid, yGrid, uInitialCondition, vInitialCondition, params.uDiffusion, params.vDiffusion, params.patternType, params.boundaryCondition); 282 | fd::CPatternSolver2D solver(input, params.dt); 283 | 284 | CMatrix uSolution(xGrid.size(), yGrid.size()); 285 | CMatrix vSolution(xGrid.size(), yGrid.size()); 286 | solver.Initialize(uSolution, vSolution); 287 | 288 | CTensor toPlot(uSolution.nRows(), uSolution.nCols(), params.nIter); 289 | 290 | toPlot.matrices[0]->ReadFrom(uSolution); 291 | std::cout << "Solver setup in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; 292 | // **************************************************** 293 | 294 | 295 | // ************** Iterate solver *************** 296 | for (size_t n = 1; n < toPlot.nMatrices(); n++) 297 | { 298 | t1 = high_resolution_clock::now(); 299 | 300 | solver.Iterate(uSolution, vSolution, params.nIterPerRound, params.patternParameter1, params.patternParameter2); 301 | 302 | t2 = high_resolution_clock::now(); 303 | std::cout << "Done " << params.nIterPerRound << " iterations in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; 304 | 305 | toPlot.matrices[n]->ReadFrom(uSolution); 306 | } 307 | // ********************************************* 308 | 309 | // ************** Save solution to CSV ************ 310 | t1 = high_resolution_clock::now(); 311 | cnpy::npy_save(params.solutionFile, &toPlot.Get()[0], { toPlot.nMatrices(), toPlot.nCols(), toPlot.nRows() }, "w"); 312 | t2 = high_resolution_clock::now(); 313 | std::cout << "Saved csv in " << duration_cast>(t2 - t1).count() << " seconds." << std::endl; 314 | 315 | high_resolution_clock::time_point end = high_resolution_clock::now(); 316 | 317 | std::cout << "Finished in " << duration_cast>(end - start).count() << " seconds." << std::endl; 318 | // ************************************************* 319 | } 320 | 321 | #pragma endregion 322 | 323 | void Run(const RunParameters& params) 324 | { 325 | MakeInitialConditionDelegate makeInitialCondition = nullptr; 326 | 327 | switch (params.patternType) 328 | { 329 | case EPatternType::FitzHughNagumo: 330 | makeInitialCondition = MakeInitialCondition; 331 | break; 332 | case EPatternType::Thomas: 333 | makeInitialCondition = MakeInitialCondition; 334 | break; 335 | case EPatternType::Schnakernberg: 336 | makeInitialCondition = MakeInitialCondition; 337 | break; 338 | case EPatternType::Brussellator: 339 | makeInitialCondition = MakeInitialCondition; 340 | break; 341 | case EPatternType::GrayScott: 342 | makeInitialCondition = MakeInitialCondition; 343 | break; 344 | default: 345 | break; 346 | } 347 | 348 | RunDelegate(makeInitialCondition, params); 349 | } 350 | 351 | int main(int argc, char** argv) 352 | { 353 | RunParameters params; 354 | 355 | #define PARSE(PARAM, TYPE) \ 356 | if (!strcmp(argv[c], "-" #PARAM)) \ 357 | params.##PARAM = std::ato##TYPE(argv[++c]); 358 | 359 | for (size_t c = 1; c < argc; c++) 360 | { 361 | if (!strcmp(argv[c], "-pattern")) 362 | { 363 | ++c; 364 | if (!strcmp(argv[c], "GrayScott")) 365 | params.patternType = EPatternType::GrayScott; 366 | else if (!strcmp(argv[c], "Brussellator")) 367 | params.patternType = EPatternType::Brussellator; 368 | else if (!strcmp(argv[c], "Schnakenberg")) 369 | params.patternType = EPatternType::Schnakernberg; 370 | else if (!strcmp(argv[c], "Thomas")) 371 | params.patternType = EPatternType::Thomas; 372 | else if (!strcmp(argv[c], "FitzHughNagumo")) 373 | params.patternType = EPatternType::FitzHughNagumo; 374 | } 375 | if (!strcmp(argv[c], "-boundaryCondition")) 376 | { 377 | ++c; 378 | if (!strcmp(argv[c], "Periodic")) 379 | params.boundaryCondition = EBoundaryCondition::Periodic; 380 | else if (!strcmp(argv[c], "ZeroFlux")) 381 | params.boundaryCondition = EBoundaryCondition::ZeroFlux; 382 | } 383 | if (!strcmp(argv[c], "-solutionFile")) 384 | { 385 | params.solutionFile = argv[++c]; 386 | } 387 | PARSE(xDimension, i); 388 | PARSE(xMin, f); 389 | PARSE(xMax, f); 390 | PARSE(yDimension, i); 391 | PARSE(yMin, f); 392 | PARSE(yMax, f); 393 | PARSE(nIter, i); 394 | PARSE(nIterPerRound, i); 395 | PARSE(dt, f); 396 | PARSE(whiteNoiseScale, f); 397 | PARSE(uDiffusion, f); 398 | PARSE(vDiffusion, f); 399 | PARSE(patternParameter1, f); 400 | PARSE(patternParameter2, f); 401 | } 402 | 403 | if (params.xMin == params.xMax) 404 | { 405 | params.xMin = 0; 406 | params.xMax = params.xDimension - 1; 407 | } 408 | if (params.yMin == params.yMax) 409 | { 410 | params.yMin = 0; 411 | params.yMax = params.yDimension - 1; 412 | } 413 | 414 | Run(params); 415 | 416 | return 0; 417 | } 418 | -------------------------------------------------------------------------------- /TuringPatterns.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2008 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CudaLight", "..\CudaLight\CudaLight\CudaLight.vcxproj", "{ACB311A5-3BB8-41F4-AA98-552FFCA078F2}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CudaLightKernels", "..\CudaLightKernels\CudaLightKernels.vcxproj", "{FEB675FC-E9C3-40FD-B987-CC8BF85888EC}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Npy++", "..\Npy++\Npy++.vcxproj", "{014413C8-BE38-48A4-9F99-9C98A08BC668}" 11 | EndProject 12 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PdeFiniteDifferenceKernels", "..\PdeFiniteDifferenceKernels\PdeFiniteDifferenceKernels.vcxproj", "{61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}" 13 | EndProject 14 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TuringPatterns", "TuringPatterns\TuringPatterns.vcxproj", "{8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}" 15 | EndProject 16 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PdeFiniteDifferenceSolverManager", "..\PdeFiniteDifferenceSolver\PdeFiniteDifferenceSolverManager\PdeFiniteDifferenceSolverManager.vcxproj", "{55A522FB-4950-488F-9B8A-2CD625A9AA15}" 17 | EndProject 18 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TuringPatternKernels", "TuringPatternKernels\TuringPatternKernels.vcxproj", "{3695B232-419E-46F9-98FE-8BDE862F6DC1}" 19 | EndProject 20 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "forge", "..\forge\build\src\backend\opengl\forge.vcxproj", "{8F7F5DD3-9DD7-3108-BC1F-477092B67281}" 21 | EndProject 22 | Global 23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 24 | Debug|x64 = Debug|x64 25 | Debug|x86 = Debug|x86 26 | MinSizeRel|x64 = MinSizeRel|x64 27 | MinSizeRel|x86 = MinSizeRel|x86 28 | Release|x64 = Release|x64 29 | Release|x86 = Release|x86 30 | RelWithDebInfo|x64 = RelWithDebInfo|x64 31 | RelWithDebInfo|x86 = RelWithDebInfo|x86 32 | EndGlobalSection 33 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 34 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.Debug|x64.ActiveCfg = Debug|x64 35 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.Debug|x64.Build.0 = Debug|x64 36 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.Debug|x86.ActiveCfg = Debug|Win32 37 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.Debug|x86.Build.0 = Debug|Win32 38 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.MinSizeRel|x64.ActiveCfg = Release|x64 39 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.MinSizeRel|x64.Build.0 = Release|x64 40 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.MinSizeRel|x86.ActiveCfg = Release|Win32 41 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.MinSizeRel|x86.Build.0 = Release|Win32 42 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.Release|x64.ActiveCfg = Release|x64 43 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.Release|x64.Build.0 = Release|x64 44 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.Release|x86.ActiveCfg = Release|Win32 45 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.Release|x86.Build.0 = Release|Win32 46 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.RelWithDebInfo|x64.ActiveCfg = Release|x64 47 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.RelWithDebInfo|x64.Build.0 = Release|x64 48 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 49 | {ACB311A5-3BB8-41F4-AA98-552FFCA078F2}.RelWithDebInfo|x86.Build.0 = Release|Win32 50 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.Debug|x64.ActiveCfg = Debug|x64 51 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.Debug|x64.Build.0 = Debug|x64 52 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.Debug|x86.ActiveCfg = Debug|x64 53 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.MinSizeRel|x64.ActiveCfg = Release|x64 54 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.MinSizeRel|x64.Build.0 = Release|x64 55 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.MinSizeRel|x86.ActiveCfg = Release|x64 56 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.MinSizeRel|x86.Build.0 = Release|x64 57 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.Release|x64.ActiveCfg = Release|x64 58 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.Release|x64.Build.0 = Release|x64 59 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.Release|x86.ActiveCfg = Release|x64 60 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.RelWithDebInfo|x64.ActiveCfg = Release|x64 61 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.RelWithDebInfo|x64.Build.0 = Release|x64 62 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.RelWithDebInfo|x86.ActiveCfg = Release|x64 63 | {FEB675FC-E9C3-40FD-B987-CC8BF85888EC}.RelWithDebInfo|x86.Build.0 = Release|x64 64 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.Debug|x64.ActiveCfg = Debug|x64 65 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.Debug|x64.Build.0 = Debug|x64 66 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.Debug|x86.ActiveCfg = Debug|Win32 67 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.Debug|x86.Build.0 = Debug|Win32 68 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.MinSizeRel|x64.ActiveCfg = Release|x64 69 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.MinSizeRel|x64.Build.0 = Release|x64 70 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.MinSizeRel|x86.ActiveCfg = Release|Win32 71 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.MinSizeRel|x86.Build.0 = Release|Win32 72 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.Release|x64.ActiveCfg = Release|x64 73 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.Release|x64.Build.0 = Release|x64 74 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.Release|x86.ActiveCfg = Release|Win32 75 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.Release|x86.Build.0 = Release|Win32 76 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.RelWithDebInfo|x64.ActiveCfg = Release|x64 77 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.RelWithDebInfo|x64.Build.0 = Release|x64 78 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 79 | {014413C8-BE38-48A4-9F99-9C98A08BC668}.RelWithDebInfo|x86.Build.0 = Release|Win32 80 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.Debug|x64.ActiveCfg = Debug|x64 81 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.Debug|x64.Build.0 = Debug|x64 82 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.Debug|x86.ActiveCfg = Debug|x64 83 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.MinSizeRel|x64.ActiveCfg = Release|x64 84 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.MinSizeRel|x64.Build.0 = Release|x64 85 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.MinSizeRel|x86.ActiveCfg = Release|x64 86 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.MinSizeRel|x86.Build.0 = Release|x64 87 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.Release|x64.ActiveCfg = Release|x64 88 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.Release|x64.Build.0 = Release|x64 89 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.Release|x86.ActiveCfg = Release|x64 90 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.RelWithDebInfo|x64.ActiveCfg = Release|x64 91 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.RelWithDebInfo|x64.Build.0 = Release|x64 92 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.RelWithDebInfo|x86.ActiveCfg = Release|x64 93 | {61B7561F-1E85-4A06-8ABA-74E4F0EEEF34}.RelWithDebInfo|x86.Build.0 = Release|x64 94 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.Debug|x64.ActiveCfg = Debug|x64 95 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.Debug|x64.Build.0 = Debug|x64 96 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.Debug|x86.ActiveCfg = Debug|x64 97 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.MinSizeRel|x64.ActiveCfg = Release|x64 98 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.MinSizeRel|x64.Build.0 = Release|x64 99 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.MinSizeRel|x86.ActiveCfg = Release|x64 100 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.MinSizeRel|x86.Build.0 = Release|x64 101 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.Release|x64.ActiveCfg = Release|x64 102 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.Release|x64.Build.0 = Release|x64 103 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.Release|x86.ActiveCfg = Release|x64 104 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.RelWithDebInfo|x64.ActiveCfg = Release|x64 105 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.RelWithDebInfo|x64.Build.0 = Release|x64 106 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.RelWithDebInfo|x86.ActiveCfg = Release|x64 107 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C}.RelWithDebInfo|x86.Build.0 = Release|x64 108 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.Debug|x64.ActiveCfg = Debug|x64 109 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.Debug|x64.Build.0 = Debug|x64 110 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.Debug|x86.ActiveCfg = Debug|Win32 111 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.Debug|x86.Build.0 = Debug|Win32 112 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.MinSizeRel|x64.ActiveCfg = Release|x64 113 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.MinSizeRel|x64.Build.0 = Release|x64 114 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.MinSizeRel|x86.ActiveCfg = Release|Win32 115 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.MinSizeRel|x86.Build.0 = Release|Win32 116 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.Release|x64.ActiveCfg = Release|x64 117 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.Release|x64.Build.0 = Release|x64 118 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.Release|x86.ActiveCfg = Release|Win32 119 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.Release|x86.Build.0 = Release|Win32 120 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.RelWithDebInfo|x64.ActiveCfg = Release|x64 121 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.RelWithDebInfo|x64.Build.0 = Release|x64 122 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.RelWithDebInfo|x86.ActiveCfg = Release|Win32 123 | {55A522FB-4950-488F-9B8A-2CD625A9AA15}.RelWithDebInfo|x86.Build.0 = Release|Win32 124 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.Debug|x64.ActiveCfg = Debug|x64 125 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.Debug|x64.Build.0 = Debug|x64 126 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.Debug|x86.ActiveCfg = Debug|x64 127 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.MinSizeRel|x64.ActiveCfg = Release|x64 128 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.MinSizeRel|x64.Build.0 = Release|x64 129 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.MinSizeRel|x86.ActiveCfg = Release|x64 130 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.MinSizeRel|x86.Build.0 = Release|x64 131 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.Release|x64.ActiveCfg = Release|x64 132 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.Release|x64.Build.0 = Release|x64 133 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.Release|x86.ActiveCfg = Release|x64 134 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.RelWithDebInfo|x64.ActiveCfg = Release|x64 135 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.RelWithDebInfo|x64.Build.0 = Release|x64 136 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.RelWithDebInfo|x86.ActiveCfg = Release|x64 137 | {3695B232-419E-46F9-98FE-8BDE862F6DC1}.RelWithDebInfo|x86.Build.0 = Release|x64 138 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.Debug|x64.ActiveCfg = Debug|x64 139 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.Debug|x64.Build.0 = Debug|x64 140 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.Debug|x86.ActiveCfg = Debug|x64 141 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.MinSizeRel|x64.ActiveCfg = MinSizeRel|x64 142 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.MinSizeRel|x64.Build.0 = MinSizeRel|x64 143 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.MinSizeRel|x86.ActiveCfg = MinSizeRel|x64 144 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.Release|x64.ActiveCfg = Release|x64 145 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.Release|x64.Build.0 = Release|x64 146 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.Release|x86.ActiveCfg = Release|x64 147 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64 148 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64 149 | {8F7F5DD3-9DD7-3108-BC1F-477092B67281}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|x64 150 | EndGlobalSection 151 | GlobalSection(SolutionProperties) = preSolution 152 | HideSolutionNode = FALSE 153 | EndGlobalSection 154 | GlobalSection(ExtensibilityGlobals) = postSolution 155 | SolutionGuid = {44180EE1-DC91-4D3C-8F90-5808CB4D5D40} 156 | EndGlobalSection 157 | EndGlobal 158 | -------------------------------------------------------------------------------- /TuringPatterns.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {D3FD5FD6-F74C-496C-9E03-43B4285F5370} 23 | Win32Proj 24 | TuringPatterns 25 | 10.0.16299.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v141 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v141 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v141 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | $(SolutionDir)\..\Npy++;$(SolutionDir)\..\CudaLightKernels;$(SolutionDir)..\CudaLight;$(IncludePath) 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Use 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | Use 101 | Level4 102 | Disabled 103 | _DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 104 | true 105 | false 106 | true 107 | $(SolutionDir)\..\Npy++;$(SolutionDir)\..\CudaLightKernels;$(SolutionDir)..\CudaLight; 108 | 109 | 110 | Console 111 | true 112 | $(SolutionDir)$(Platform)\$(Configuration)\ 113 | CudaManager.lib;FiniteDifference.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 114 | 115 | 116 | 117 | 118 | Level3 119 | Use 120 | MaxSpeed 121 | true 122 | true 123 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | true 125 | 126 | 127 | Console 128 | true 129 | true 130 | true 131 | 132 | 133 | 134 | 135 | EnableAllWarnings 136 | Use 137 | Full 138 | true 139 | true 140 | NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 141 | true 142 | false 143 | true 144 | AnySuitable 145 | Speed 146 | true 147 | 148 | 149 | Console 150 | true 151 | true 152 | true 153 | CudaManager.lib;FiniteDifference.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 154 | $(SolutionDir)$(Platform)\$(Configuration)\ 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | Create 167 | Create 168 | Create 169 | Create 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /TuringPatterns.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /TuringPatterns.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -pattern Thomas -xDimension 64 -yDimension 64 -nIter 100 -nIterPerRound 10 -dt 1.0 -whiteNoiseScale .05 -patternParameter1 4.5 -patternParameter2 6.75 -solutionFile "br.csv" -uDiffusion 2 -vDiffusion 16 5 | WindowsLocalDebugger 6 | 7 | 8 | -pattern Thomas -xDimension 64 -yDimension 64 -nIter 100 -nIterPerRound 10 -dt 1.0 -whiteNoiseScale .05 -patternParameter1 4.5 -patternParameter2 6.75 -solutionFile "br.csv" -uDiffusion 2 -vDiffusion 16 9 | WindowsLocalDebugger 10 | 11 | -------------------------------------------------------------------------------- /TuringPatterns/TuringPatterns.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {8f7f5dd3-9dd7-3108-bc1f-477092b67281} 19 | 20 | 21 | 22 | {8A5AA9D0-27A7-4A8A-A389-1ED29AF7F08C} 23 | TuringPatterns 24 | 10.0.16299.0 25 | 26 | 27 | 28 | Application 29 | true 30 | MultiByte 31 | v141 32 | 33 | 34 | Application 35 | false 36 | true 37 | MultiByte 38 | v141 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | true 53 | $(SolutionDir)\..\CudaLight\CudaLight;$(SolutionDir)\..\CudaLightKernels;$(SolutionDir)\..\PdeFiniteDifferenceSolver\PdeFiniteDifferenceSolverManager;$(SolutionDir)\..\PdeFiniteDifferenceKernels;$(SolutionDir)\..\forge\build\include;$(SolutionDir)\..\forge\include;$(SolutionDir)\..\forge;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(SolutionDir)\..\Npy++\Npy++;$(SolutionDir)\..\Npy++\MemoryMapping;$(SolutionDir)\..\Npy++\zlib-1.2.7.f-win64-v1\;$(SolutionDir)\TuringPatternKernels 54 | 55 | 56 | 57 | Level3 58 | Disabled 59 | WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 60 | 61 | 62 | true 63 | Console 64 | TuringPatternKernels.lib;Npy++.lib;CudaLight.lib;CudaLightKernels.lib;PdeFiniteDifferenceSolverManager.lib;PdeFiniteDifferenceKernels.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;opengl32.lib;cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 65 | %(AdditionalLibraryDirectories);$(CudaToolkitLibDir);$(OutDir);; 66 | 67 | 68 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 69 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 70 | 71 | 72 | 64 73 | $(SolutionDir)\..\CudaLight\CudaLight;$(SolutionDir)\..\CudaLightKernels;$(SolutionDir)\..\PdeFiniteDifferenceSolver\PdeFiniteDifferenceSolverManager;$(SolutionDir)\..\PdeFiniteDifferenceKernels;$(SolutionDir)\..\forge\build\include;$(SolutionDir)\..\forge\include;$(SolutionDir)\..\forge;$(SolutionDir)\TuringPatternKernels 74 | _WINDOWS;OS_WIN;WIN32_MEAN_AND_LEAN;FGDLL;CMAKE_INTDIR="Debug";%(Defines) 75 | false 76 | false 77 | 78 | 79 | 80 | 81 | Level3 82 | MaxSpeed 83 | true 84 | true 85 | WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 86 | 87 | 88 | true 89 | true 90 | true 91 | Console 92 | cudart.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 93 | 94 | 95 | echo copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 96 | copy "$(CudaToolkitBinDir)\cudart*.dll" "$(OutDir)" 97 | 98 | 99 | 64 100 | 101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /TuringPatterns/TuringPatterns.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -pattern GrayScott -bc ZeroFlux -dt 1 -nIter 4096 -nIterPerRound 10 -xd 100 -yd 100 -wns 0.05 -ud 0.16 -vd 0.08 -p1 0.035 -p2 0.065 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /TuringPatterns/main.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #define USE_FORGE_CUDA_COPY_HELPERS 22 | #include 23 | 24 | //#define PLOT_3D 25 | #define SAVE_TO_FILE 26 | 27 | namespace ep 28 | { 29 | #define PARSE(E, X)\ 30 | if (!strcmp(text.c_str(), #X))\ 31 | return E::X; 32 | 33 | PatternType ParsePatternType(const std::string &text) 34 | { 35 | #define PARSE_WORKER(X) PARSE(PatternType, X); 36 | 37 | PARSE_WORKER(FitzHughNagumo); 38 | PARSE_WORKER(Thomas); 39 | PARSE_WORKER(Schnakenberg); 40 | PARSE_WORKER(Brussellator); 41 | PARSE_WORKER(GrayScott); 42 | 43 | #undef PARSE_WORKER 44 | 45 | return PatternType::Null; 46 | } 47 | 48 | #undef PARSE 49 | } 50 | 51 | template 52 | using vector = cl::Vector; 53 | 54 | template 55 | using matrix = cl::ColumnWiseMatrix; 56 | 57 | template 58 | using sType = typename vector::stdType; 59 | 60 | struct RunParameters 61 | { 62 | PatternType patternType = PatternType::GrayScott; 63 | BoundaryConditionType boundaryCondition = BoundaryConditionType::Periodic; 64 | 65 | size_t xDimension = 64; 66 | double xMin = 0.0; 67 | double xMax = 1.0; 68 | 69 | size_t yDimension = 64; 70 | double yMin = 0.0; 71 | double yMax = 1.0; 72 | 73 | /// Number of plots 74 | size_t nIter = 2000; 75 | size_t nIterPerRound = 10; 76 | 77 | double dt = 1.0; 78 | 79 | double whiteNoiseScale = .05; 80 | 81 | double uDiffusion = 0.16; 82 | double vDiffusion = 0.08; 83 | 84 | double patternParameter1 = 0.035; 85 | double patternParameter2 = 0.065; 86 | 87 | double zMin = 0.1; 88 | double zMax = 1.5; 89 | 90 | std::string outputFile = ""; 91 | }; 92 | 93 | template 94 | void MakeInitialCondition(matrix& uInitialCondition, matrix& vInitialCondition, const RunParameters& params) 95 | { 96 | switch (patternType) 97 | { 98 | case PatternType::FitzHughNagumo: 99 | uInitialCondition.Set(0.0); 100 | vInitialCondition.Set(0.0); 101 | break; 102 | case PatternType::Thomas: 103 | { 104 | auto f = [&](const double v) 105 | { 106 | const double u = -1.5 * (params.patternParameter2 - v) + params.patternParameter1; 107 | const double h = 13.0 * u * v / (1.0 + u + 0.05 * u * u); 108 | return h - (params.patternParameter1 - u); 109 | }; 110 | auto binarySearch = [&](double a, double b, const double tolerance = 1e-8) 111 | { 112 | double fa = f(a); 113 | double fb = f(b); 114 | 115 | if (fa * fb > 0) 116 | throw std::logic_error("f doesn't change sign"); 117 | 118 | double c = 0; 119 | for (size_t i = 0; i < 1000; i++) 120 | { 121 | c = .5 * (a + b); 122 | const double fc = f(c); 123 | fa = f(a); 124 | fb = f(b); 125 | 126 | if (fabs(fc) < tolerance) 127 | return c; 128 | 129 | if (fa * fc > 0) 130 | a = c; 131 | else 132 | b = c; 133 | } 134 | 135 | std::cout << "CONVERGENCE ERROR" << std::endl; 136 | throw; 137 | }; 138 | 139 | const double v0 = binarySearch(0.0, 100.0); 140 | const double u0 = -1.5 * (params.patternParameter2 - v0) + params.patternParameter1; 141 | 142 | uInitialCondition.Set(u0); 143 | vInitialCondition.Set(v0); 144 | } 145 | break; 146 | case PatternType::Schnakenberg: 147 | uInitialCondition.Set(params.patternParameter1 + params.patternParameter2); 148 | vInitialCondition.Set(params.patternParameter2 / ((params.patternParameter1 + params.patternParameter2) * (params.patternParameter1 + params.patternParameter2))); 149 | break; 150 | case PatternType::Brussellator: 151 | uInitialCondition.Set(params.patternParameter1); 152 | vInitialCondition.Set(params.patternParameter2 / params.patternParameter1); 153 | break; 154 | case PatternType::GrayScott: 155 | { 156 | uInitialCondition.Set(1.0); 157 | vInitialCondition.Set(0.0); 158 | 159 | std::vector> uCenteredSquare(uInitialCondition.size()); 160 | std::vector> vCenteredSquare(vInitialCondition.size()); 161 | size_t squareStartX = uInitialCondition.nRows() * 2 / 5; 162 | size_t squareEndX = uInitialCondition.nRows() * 3 / 5; 163 | size_t squareStartY = uInitialCondition.nCols() * 2 / 5; 164 | size_t squareEndY = uInitialCondition.nCols() * 3 / 5; 165 | for (size_t j = squareStartY; j < squareEndY; j++) 166 | { 167 | for (size_t i = squareStartX; i < squareEndX; i++) 168 | { 169 | uCenteredSquare[i + uInitialCondition.nRows() * j] = -.5; 170 | vCenteredSquare[i + uInitialCondition.nRows() * j] = .25; 171 | } 172 | } 173 | matrix uAddition(uCenteredSquare, uInitialCondition.nRows(), uInitialCondition.nCols()); 174 | matrix vAddition(vCenteredSquare, vInitialCondition.nRows(), vInitialCondition.nCols()); 175 | 176 | uInitialCondition += uAddition; 177 | vInitialCondition += vAddition; 178 | } 179 | break; 180 | default: 181 | break; 182 | } 183 | } 184 | 185 | template 186 | void runner(const RunParameters& params) 187 | { 188 | std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); 189 | 190 | // ************ Make Grid ************ 191 | vector xGrid = vector::LinSpace(params.xMin, params.xMax, params.xDimension); 192 | vector yGrid = vector::LinSpace(params.yMin, params.yMax, params.yDimension); 193 | 194 | std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); \ 195 | 196 | std::cout << "Created grid in " << std::chrono::duration_cast>(t2 - t1).count() << " seconds." << std::endl; \ 197 | // *********************************** 198 | 199 | // ***************** Make Initial Condition ****************** 200 | t1 = std::chrono::high_resolution_clock::now(); 201 | 202 | matrix whiteNoise(xGrid.size(), yGrid.size()); 203 | whiteNoise.RandomGaussian(1234); 204 | whiteNoise.Scale(params.whiteNoiseScale); 205 | 206 | matrix uInitialCondition(xGrid.size(), yGrid.size()); 207 | matrix vInitialCondition(xGrid.size(), yGrid.size()); 208 | MakeInitialCondition(uInitialCondition, vInitialCondition, params); 209 | 210 | uInitialCondition += whiteNoise; 211 | vInitialCondition += whiteNoise; 212 | 213 | t2 = std::chrono::high_resolution_clock::now(); 214 | std::cout << "Created initial condition in " << std::chrono::duration_cast>(t2 - t1).count() << " seconds." << std::endl; 215 | // *************************************************************** 216 | 217 | // **************** Initialize Solver *************** 218 | t1 = std::chrono::high_resolution_clock::now(); 219 | 220 | BoundaryCondition leftBc(params.boundaryCondition, 0.0); 221 | BoundaryCondition rightBc(params.boundaryCondition, 0.0); 222 | BoundaryCondition downBc(params.boundaryCondition, 0.0); 223 | BoundaryCondition upBc(params.boundaryCondition, 0.0); 224 | BoundaryCondition2D bc(leftBc, rightBc, downBc, upBc); 225 | 226 | pde::PdeInputData2D uData(uInitialCondition, xGrid, yGrid, 0.0, 0.0, params.uDiffusion, params.dt, SolverType::ImplicitEuler, SpaceDiscretizerType::Centered, bc); 227 | pde::PdeInputData2D vData(vInitialCondition, xGrid, yGrid, 0.0, 0.0, params.vDiffusion, params.dt, SolverType::ImplicitEuler, SpaceDiscretizerType::Centered, bc); 228 | 229 | pde::AdvectionDiffusionSolver2D uSolver(std::move(uData)); 230 | pde::AdvectionDiffusionSolver2D vSolver(std::move(vData)); 231 | 232 | std::cout << "Solver setup in " << std::chrono::duration_cast>(t2 - t1).count() << " seconds." << std::endl; 233 | // **************************************************** 234 | 235 | auto _xGrid = xGrid.Get(); 236 | auto _yGrid = yGrid.Get(); 237 | 238 | #ifndef SAVE_TO_FILE 239 | // solution matrix is a collection of flattened solutions over time 240 | forge::Window wnd(1024, 768, "Pattern"); 241 | wnd.makeCurrent(); 242 | 243 | #ifdef PLOT_3D 244 | forge::Chart chart(FG_CHART_3D); 245 | 246 | auto _ic = uInitialCondition.Get(); 247 | chart.setAxesLimits(_xGrid.front(), _xGrid.back(), _yGrid.front(), _yGrid.back(), params.zMin, params.zMax); 248 | chart.setAxesTitles("x-axis", "y-axis", "z-axis"); 249 | 250 | forge::Surface surf = chart.surface(_xGrid.size(), _yGrid.size(), forge::f32); 251 | surf.setColor(FG_BLUE); 252 | 253 | GfxHandle* handle; 254 | createGLBuffer(&handle, surf.vertices(), FORGE_VERTEX_BUFFER); 255 | #else 256 | forge::Image img(_xGrid.size(), _yGrid.size(), FG_RGBA, forge::f32); 257 | 258 | GfxHandle* handle = 0; 259 | createGLBuffer(&handle, img.pixels(), FORGE_IMAGE_BUFFER); 260 | #endif 261 | 262 | bool toDo = true; 263 | 264 | #ifdef PLOT_3D 265 | cl::Vector xyzTriple(3 * uInitialCondition.size()); 266 | #else 267 | MemoryBuffer colorMap(0, 4 * uInitialCondition.size(), MemorySpace::Device, MathDomain::Float); 268 | dm::detail::Alloc(colorMap); 269 | 270 | vector uNormalised(uInitialCondition.size()); 271 | vector minDummy(uNormalised.size(), 1.0); 272 | #endif 273 | 274 | do 275 | { 276 | if (toDo) 277 | { 278 | for (unsigned m = 0; m < params.nIter; ++m) 279 | { 280 | for (unsigned n = 0; n < params.nIterPerRound; ++n) 281 | { 282 | uSolver.Advance(1); 283 | vSolver.Advance(1); 284 | _ApplyPatternDynamic(uSolver.solution->columns[0]->GetBuffer(), vSolver.solution->columns[0]->GetBuffer(), type, params.dt, params.patternParameter1, params.patternParameter2); 285 | } 286 | 287 | #ifdef PLOT_3D 288 | matrix::MakeTriple(xyzTriple, xGrid, yGrid, *uSolver.solution->columns[0]); 289 | copyToGLBuffer(handle, reinterpret_cast(xyzTriple.GetBuffer().pointer), surf.verticesSize()); 290 | wnd.draw(chart); 291 | #else 292 | double min = uSolver.solution->columns[0]->Minimum(); 293 | minDummy.Set(min); 294 | uNormalised.AddEqual(minDummy, -1.0); 295 | 296 | double max = uSolver.solution->columns[0]->AbsoluteMaximum(); 297 | uNormalised.ReadFrom(*uSolver.solution->columns[0]); 298 | uNormalised.Scale(1.0 / max); 299 | _MakeRgbaJetColorMap(colorMap, uNormalised.GetBuffer()); 300 | copyToGLBuffer(handle, (ComputeResourceHandle)colorMap.pointer, img.size()); 301 | wnd.draw(img); 302 | #endif 303 | } 304 | } 305 | 306 | #ifdef PLOT_3D 307 | wnd.draw(chart); 308 | #else 309 | wnd.draw(img); 310 | #endif 311 | toDo = false; 312 | } 313 | while (!wnd.close()); 314 | 315 | releaseGLBuffer(handle); 316 | #else 317 | std::vector> solutionMatrix; 318 | 319 | for (unsigned m = 0; m < params.nIter; ++m) 320 | { 321 | t1 = std::chrono::high_resolution_clock::now(); 322 | 323 | for (unsigned n = 0; n < params.nIterPerRound; ++n) 324 | { 325 | uSolver.Advance(1); 326 | vSolver.Advance(1); 327 | _ApplyPatternDynamic(uSolver.solution->columns[0]->GetBuffer(), vSolver.solution->columns[0]->GetBuffer(), type, params.dt, params.patternParameter1, params.patternParameter2); 328 | } 329 | 330 | t2 = std::chrono::high_resolution_clock::now(); 331 | std::cout << "Step " << m << " done in " << std::chrono::duration_cast>(t2 - t1).count() << " seconds." << std::endl; 332 | 333 | const auto solution = uSolver.solution->columns[0]->Get(); 334 | solutionMatrix.insert(solutionMatrix.end(), solution.begin(), solution.end()); 335 | } 336 | 337 | cl::MatrixToBinaryFile>(solutionMatrix, params.nIter, uSolver.solution->columns[0]->size(), params.outputFile, false); 338 | #endif 339 | } 340 | 341 | int main(int argc, char** argv) 342 | { 343 | clp::CommandLineArgumentParser ap(argc, argv); 344 | 345 | auto mathDomain = ep::ParseMathDomain(ap.GetArgumentValue("-md", "Float")); 346 | auto patternType = ep::ParsePatternType(ap.GetArgumentValue("-pattern", "GrayScott")); 347 | 348 | RunParameters rp; 349 | std::string bc = ap.GetArgumentValue("-bc", "Periodic"); 350 | if (bc == "Periodic") 351 | rp.boundaryCondition = BoundaryConditionType::Periodic; 352 | if (bc == "ZeroFlux") 353 | rp.boundaryCondition = BoundaryConditionType::Neumann; 354 | rp.dt = ap.GetArgumentValue("-dt", rp.dt); 355 | rp.nIter = ap.GetArgumentValue("-nIter", rp.nIter); 356 | rp.nIterPerRound = ap.GetArgumentValue("-nIterPerRound", rp.nIterPerRound); 357 | rp.xDimension = ap.GetArgumentValue("-xd", rp.xDimension); 358 | rp.yDimension = ap.GetArgumentValue("-yd", rp.yDimension); 359 | rp.xMin = ap.GetArgumentValue("-xm", rp.xMin); 360 | rp.xMax = ap.GetArgumentValue("-xM", 0.0); 361 | if (rp.xMax == 0) 362 | rp.xMax = rp.xDimension - 1.0; 363 | rp.yDimension = ap.GetArgumentValue("-yd", rp.yDimension); 364 | rp.yMin = ap.GetArgumentValue("-ym", rp.yMin); 365 | rp.yMax = ap.GetArgumentValue("-yM", 0.0); 366 | if (rp.yMax == 0) 367 | rp.yMax = rp.yDimension - 1.0; 368 | rp.zMin = ap.GetArgumentValue("-zm", rp.zMin); 369 | rp.zMax = ap.GetArgumentValue("-zM", rp.zMax); 370 | 371 | rp.whiteNoiseScale = ap.GetArgumentValue("-wns", rp.whiteNoiseScale); 372 | rp.uDiffusion = ap.GetArgumentValue("-ud", rp.uDiffusion); 373 | rp.vDiffusion = ap.GetArgumentValue("-vd", rp.vDiffusion); 374 | rp.patternParameter1 = ap.GetArgumentValue("-p1", rp.patternParameter1); 375 | rp.patternParameter2 = ap.GetArgumentValue("-p2", rp.patternParameter2); 376 | rp.outputFile = ap.GetArgumentValue("-of", "sol.cl"); 377 | 378 | switch (mathDomain) 379 | { 380 | case MathDomain::Float: 381 | switch (patternType) 382 | { 383 | case PatternType::FitzHughNagumo: 384 | runner(rp); 385 | break; 386 | case PatternType::Thomas: 387 | runner(rp); 388 | break; 389 | case PatternType::Schnakenberg: 390 | runner(rp); 391 | break; 392 | case PatternType::Brussellator: 393 | runner(rp); 394 | break; 395 | case PatternType::GrayScott: 396 | runner(rp); 397 | break; 398 | default: 399 | break; 400 | } 401 | break; 402 | case MathDomain::Double: 403 | switch (patternType) 404 | { 405 | case PatternType::FitzHughNagumo: 406 | runner(rp); 407 | break; 408 | case PatternType::Thomas: 409 | runner(rp); 410 | break; 411 | case PatternType::Schnakenberg: 412 | runner(rp); 413 | break; 414 | case PatternType::Brussellator: 415 | runner(rp); 416 | break; 417 | case PatternType::GrayScott: 418 | runner(rp); 419 | break; 420 | default: 421 | break; 422 | } 423 | default: 424 | throw NotImplementedException(); 425 | } 426 | 427 | return 0; 428 | } -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-minimal -------------------------------------------------------------------------------- /bacteria2_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/bacteria2_compressed.gif -------------------------------------------------------------------------------- /bacteria_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/bacteria_compressed.gif -------------------------------------------------------------------------------- /br_stripes_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/br_stripes_compressed.gif -------------------------------------------------------------------------------- /coral2_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/coral2_compressed.gif -------------------------------------------------------------------------------- /coral3_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/coral3_compressed.gif -------------------------------------------------------------------------------- /coral_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/coral_compressed.gif -------------------------------------------------------------------------------- /fhn_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/fhn_compressed.gif -------------------------------------------------------------------------------- /fhnb_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/fhnb_compressed.gif -------------------------------------------------------------------------------- /lines_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/lines_compressed.gif -------------------------------------------------------------------------------- /patternRunner.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from subprocess import Popen 3 | import os 4 | from plotter import animate_colormap 5 | 6 | CWD = os.getcwd() 7 | if os.name == 'nt': 8 | debugBin = "{}\\x64\\Debug\\TuringPatterns.exe".format(CWD) 9 | releaseBin = "{}\\x64\\Release\\TuringPatterns.exe".format(CWD) 10 | 11 | GRID_FILE = "{}\\grid.npy".format(CWD) 12 | INITIAL_CONDITION_FILE = "{}\\ic.npy".format(CWD) 13 | 14 | X_GRID_FILE = "{}\\x_grid.npy".format(CWD) 15 | Y_GRID_FILE = "{}\\y_grid.npy".format(CWD) 16 | else: 17 | debugBin = "{}/cmake-build-gcc-debug/TuringPatterns".format(CWD) 18 | releaseBin = "{}/cmake-build-gcc-release/TuringPatterns".format(CWD) 19 | 20 | GRID_FILE = "{}/grid.npy".format(CWD) 21 | INITIAL_CONDITION_FILE = "{}/ic.npy".format(CWD) 22 | 23 | X_GRID_FILE = "{}/x_grid.npy".format(CWD) 24 | Y_GRID_FILE = "{}/y_grid.npy".format(CWD) 25 | 26 | chosenBin = debugBin 27 | 28 | def read_solution(file_name, N, N_x, N_y): 29 | _tensor = np.load(file_name).flatten() 30 | tensor = [] 31 | for n in range(N): 32 | m = np.zeros((N_x, N_y)) 33 | for i in range(N_x): 34 | for j in range(N_y): 35 | m[j, i] = _tensor[i + j * N_x + n * N_x * N_y] 36 | tensor.append(m) 37 | return np.array(tensor) 38 | 39 | 40 | def run_gray_scott_bacteria(run=True, save=False): 41 | N = 100 42 | N_x = 64 43 | N_y = 64 44 | if run: 45 | p = Popen([chosenBin] + 46 | ["-pattern", "GrayScott"] + 47 | ["-bc", "Periodic"] + 48 | ["-xd", str(N_x)] + 49 | ["-yd", str(N_y)] + 50 | ["-nIter", str(N)] + 51 | ["-nIterPerRound", "100"] + 52 | ["-dt", "1.0"] + 53 | ["-wns", ".05"] + 54 | ["-ud", ".16"] + 55 | ["-vd", ".08"] + 56 | ["-p1", "0.035"] + 57 | ["-p2", ".065"] + 58 | ["-of", "bacteria.npy"]) 59 | p.communicate() 60 | 61 | tensor = read_solution("bacteria.npy", N, N_x, N_y) 62 | 63 | animate_colormap(tensor, 64 | np.linspace(0.0, 1.0, N_x), 65 | np.linspace(0.0, 1.0, N_y), 66 | cmap='RdBu', 67 | show=not save, 68 | save=save, 69 | name="bacteria.gif") 70 | 71 | 72 | def run_gray_scott_bacteria2(run=True, save=False): 73 | N = 100 74 | N_x = 64 75 | N_y = 64 76 | if run: 77 | p = Popen([chosenBin] + 78 | ["-pattern", "GrayScott"] + 79 | ["-bc", "Periodic"] + 80 | ["-xd", str(N_x)] + 81 | ["-yd", str(N_y)] + 82 | ["-nIter", str(N)] + 83 | ["-nIterPerRound", "100"] + 84 | ["-dt", "1.0"] + 85 | ["-wns", ".05"] + 86 | ["-ud", ".14"] + 87 | ["-vd", ".06"] + 88 | ["-p1", "0.035"] + 89 | ["-p2", ".065"] + 90 | ["-of", "bacteria2.npy"]) 91 | p.communicate() 92 | 93 | tensor = read_solution("bacteria2.npy", N, N_x, N_y) 94 | 95 | animate_colormap(tensor, 96 | np.linspace(0.0, 1.0, tensor.shape[2]), 97 | np.linspace(0.0, 1.0, tensor.shape[1]), 98 | cmap='RdBu', 99 | show=not save, 100 | save=save, 101 | name="bacteria2.gif") 102 | 103 | 104 | def run_gray_scott_coral(run=True, save=False): 105 | N = 100 106 | N_x = 100 107 | N_y = 100 108 | if run: 109 | p = Popen([chosenBin] + 110 | ["-pattern", "GrayScott"] + 111 | ["-bc", "Periodic"] + 112 | ["-xd", str(N_x)] + 113 | ["-yd", str(N_y)] + 114 | ["-nIter", str(N)] + 115 | ["-nIterPerRound", "100"] + 116 | ["-dt", ".5"] + 117 | ["-wns", ".05"] + 118 | ["-ud", ".19"] + 119 | ["-vd", ".05"] + 120 | ["-p1", ".06"] + 121 | ["-p2", ".02"] + 122 | ["-of", "coral.npy"]) 123 | p.communicate() 124 | 125 | tensor = read_solution("coral.npy", N, N_x, N_y) 126 | 127 | animate_colormap(tensor, 128 | np.linspace(0.0, 1.0, tensor.shape[2]), 129 | np.linspace(0.0, 1.0, tensor.shape[1]), 130 | cmap='RdBu', 131 | show=not save, 132 | save=save, 133 | name="coral.gif") 134 | 135 | 136 | def run_gray_scott_coral2(run=True, save=False): 137 | N = 100 138 | N_x = 100 139 | N_y = 100 140 | if run: 141 | p = Popen([chosenBin] + 142 | ["-pattern", "GrayScott"] + 143 | ["-bc", "ZeroFlux"] + 144 | ["-xd", str(N_x)] + 145 | ["-yd", str(N_y)] + 146 | ["-nIter", str(N)] + 147 | ["-nIterPerRound", "100"] + 148 | ["-dt", ".5"] + 149 | ["-wns", ".05"] + 150 | ["-ud", ".19"] + 151 | ["-vd", ".05"] + 152 | ["-p1", ".01"] + 153 | ["-p2", ".015"] + 154 | ["-of", "coral2.npy"]) 155 | p.communicate() 156 | 157 | tensor = read_solution("coral2.npy", N, N_x, N_y) 158 | 159 | animate_colormap(tensor, 160 | np.linspace(0.0, 1.0, tensor.shape[2]), 161 | np.linspace(0.0, 1.0, tensor.shape[1]), 162 | cmap='RdBu', 163 | show=not save, 164 | save=save, 165 | name="coral2.gif") 166 | 167 | 168 | def run_gray_scott_coral3(run=True, save=False): 169 | N = 100 170 | N_x = 100 171 | N_y = 100 172 | if run: 173 | p = Popen([chosenBin] + 174 | ["-pattern", "GrayScott"] + 175 | ["-bc", "Periodic"] + 176 | ["-xd", str(N_x)] + 177 | ["-yd", str(N_x)] + 178 | ["-nIter", "100"] + 179 | ["-nIterPerRound", "100"] + 180 | ["-dt", ".5"] + 181 | ["-wns", ".05"] + 182 | ["-ud", ".19"] + 183 | ["-vd", ".05"] + 184 | ["-p1", ".03"] + 185 | ["-p2", ".025"] + 186 | ["-of", "coral3.npy"]) 187 | p.communicate() 188 | 189 | tensor = read_solution("coral3.npy", N, N_x, N_y) 190 | 191 | animate_colormap(tensor, 192 | np.linspace(0.0, 1.0, tensor.shape[2]), 193 | np.linspace(0.0, 1.0, tensor.shape[1]), 194 | cmap='RdBu', 195 | show=not save, 196 | save=save, 197 | name="coral3.gif") 198 | 199 | 200 | def run_gray_scott_lines(run=True, save=False): 201 | N = 100 202 | N_x = 100 203 | N_y = 100 204 | if run: 205 | p = Popen([chosenBin] + 206 | ["-pattern", "GrayScott"] + 207 | ["-bc", "Periodic"] + 208 | ["-xd", str(N_x)] + 209 | ["-yd", str(N_x)] + 210 | ["-nIter", "100"] + 211 | ["-nIterPerRound", "100"] + 212 | ["-dt", "1"] + 213 | ["-wns", ".05"] + 214 | ["-ud", ".16"] + 215 | ["-vd", ".08"] + 216 | ["-p1", ".05"] + 217 | ["-p2", ".065"] + 218 | ["-of", "lines.npy"]) 219 | p.communicate() 220 | 221 | tensor = read_solution("lines.npy", N, N_x, N_y) 222 | 223 | animate_colormap(tensor, 224 | np.linspace(0.0, 1.0, tensor.shape[2]), 225 | np.linspace(0.0, 1.0, tensor.shape[1]), 226 | cmap='RdBu', 227 | show=not save, 228 | save=save, 229 | name="lines.gif") 230 | 231 | 232 | def run_brussellator_stripes(run=True, save=False): 233 | N = 100 234 | N_x = 64 235 | N_y = 64 236 | if run: 237 | p = Popen([chosenBin] + 238 | ["-pattern", "Brussellator"] + 239 | ["-bc", "ZeroFlux"] + 240 | ["-xd", str(N_x)] + 241 | ["-yd", str(N_y)] + 242 | ["-nIter", str(N)] + 243 | ["-nIterPerRound", "100"] + 244 | ["-dt", "0.01"] + 245 | ["-wns", ".05"] + 246 | ["-ud", "2"] + 247 | ["-vd", "16"] + 248 | ["-p1", "4.5"] + 249 | ["-p2", "7.5"] + 250 | ["-of", "br_stripes.npy"]) 251 | p.communicate() 252 | 253 | tensor = read_solution("br_stripes.npy", N, N_x, N_y) 254 | 255 | animate_colormap(tensor, 256 | np.linspace(0.0, 1.0, tensor.shape[2]), 257 | np.linspace(0.0, 1.0, tensor.shape[1]), 258 | cmap='RdBu', 259 | show=not save, 260 | save=save, 261 | name="br_stripes.gif") 262 | 263 | 264 | def run_brussellator_dots(run=True, save=False): 265 | N = 100 266 | N_x = 100 267 | N_y = 100 268 | if run: 269 | p = Popen([chosenBin] + 270 | ["-pattern", "Brussellator"] + 271 | ["-bc", "Periodic"] + 272 | ["-xd", str(N_x)] + 273 | ["-yd", str(N_x)] + 274 | ["-nIter", str(N)] + 275 | ["-nIterPerRound", "100"] + 276 | ["-dt", "0.005"] + 277 | ["-wns", ".05"] + 278 | ["-ud", "2"] + 279 | ["-vd", "16"] + 280 | ["-p1", "4.5"] + 281 | ["-p2", "12"] + 282 | ["-of", "br_dots.npy"]) 283 | p.communicate() 284 | 285 | tensor = read_solution("br_dots.npy", N, N_x, N_y) 286 | 287 | animate_colormap(tensor, 288 | np.linspace(0.0, 1.0, tensor.shape[2]), 289 | np.linspace(0.0, 1.0, tensor.shape[1]), 290 | cmap='Spectral', 291 | show=not save, 292 | save=save, 293 | name="br_dots.gif") 294 | 295 | 296 | def run_schnakenberg(run=True, save=False): 297 | N = 100 298 | N_x = 64 299 | N_y = 64 300 | if run: 301 | p = Popen([chosenBin] + 302 | ["-pattern", "Schnakenberg"] + 303 | ["-bc", "ZeroFlux"] + 304 | ["-xd", str(N_x)] + 305 | ["-yd", str(N_x)] + 306 | ["-nIter", str(N)] + 307 | ["-nIterPerRound", "200"] + 308 | ["-dt", "0.01"] + 309 | ["-wns", ".05"] + 310 | ["-ud", "1.0"] + 311 | ["-vd", "10"] + 312 | ["-p1", ".1"] + 313 | ["-p2", ".9"] + 314 | ["-of", "schnakenberg.npy"]) 315 | p.communicate() 316 | 317 | tensor = read_solution("schnakenberg.npy", N, N_x, N_y) 318 | 319 | animate_colormap(tensor, 320 | np.linspace(0.0, 1.0, tensor.shape[2]), 321 | np.linspace(0.0, 1.0, tensor.shape[1]), 322 | cmap='seismic', 323 | show=not save, 324 | save=save, 325 | name="schnakenberg.gif") 326 | 327 | 328 | def run_thomas(run=True, save=False): 329 | N = 100 330 | N_x = 64 331 | N_y = 64 332 | if run: 333 | p = Popen([chosenBin] + 334 | ["-pattern", "Thomas"] + 335 | ["-bc", "ZeroFlux"] + 336 | ["-xd", str(N_x)] + 337 | ["-yd", str(N_x)] + 338 | ["-nIter", str(N)] + 339 | ["-nIterPerRound", "100"] + 340 | ["-dt", "0.0005"] + 341 | ["-wns", ".1"] + 342 | ["-ud", "1.0"] + 343 | ["-vd", "28"] + 344 | ["-p1", "150"] + 345 | ["-p2", "100"] + 346 | ["-of", "thomas.npy"]) 347 | p.communicate() 348 | 349 | tensor = read_solution("thomas.npy", N, N_x, N_y) 350 | 351 | animate_colormap(tensor, 352 | np.linspace(0.0, 1.0, tensor.shape[2]), 353 | np.linspace(0.0, 1.0, tensor.shape[1]), 354 | cmap='seismic', 355 | show=not save, 356 | save=save, 357 | name="schnakenberg.gif") 358 | 359 | 360 | def run_fitz_hugh_nagumo(run=True, save=False): 361 | N = 100 362 | N_x = 64 363 | N_y = 64 364 | if run: 365 | p = Popen([chosenBin] + 366 | ["-pattern", "FitzHughNagumo"] + 367 | ["-bc", "ZeroFlux"] + 368 | ["-xd", str(N_x)] + 369 | ["-yd", str(N_x)] + 370 | ["-nIter", str(N)] + 371 | ["-nIterPerRound", "1000"] + 372 | ["-dt", "0.001"] + 373 | ["-wns", ".05"] + 374 | ["-ud", "1"] + 375 | ["-vd", "100"] + 376 | ["-p1", "-0.005"] + 377 | ["-p2", "10.0"] + 378 | ["-of", "fhn.npy"]) 379 | p.communicate() 380 | 381 | tensor = read_solution("fhn.npy", N, N_x, N_y) 382 | 383 | animate_colormap(tensor, 384 | np.linspace(0.0, 1.0, tensor.shape[2]), 385 | np.linspace(0.0, 1.0, tensor.shape[1]), 386 | cmap='RdBu', 387 | show=not save, 388 | save=save, 389 | name="fhn.gif") 390 | 391 | 392 | def run_fitz_hugh_nagumo_low_beta(run=True, save=False): 393 | N = 100 394 | N_x = 100 395 | N_y = 100 396 | if run: 397 | p = Popen([chosenBin] + 398 | ["-pattern", "FitzHughNagumo"] + 399 | ["-bc", "ZeroFlux"] + 400 | ["-xd", str(N_x)] + 401 | ["-yd", str(N_x)] + 402 | ["-nIter", "100"] + 403 | ["-nIterPerRound", "1000"] + 404 | ["-dt", "0.001"] + 405 | ["-wns", ".05"] + 406 | ["-ud", "1"] + 407 | ["-vd", "100"] + 408 | ["-p1", "0.01"] + 409 | ["-p2", ".25"] + 410 | ["-of", "fhnb.npy"]) 411 | p.communicate() 412 | 413 | tensor = read_solution("fhnb.npy", N, N_x, N_y) 414 | 415 | animate_colormap(tensor, 416 | np.linspace(0.0, 1.0, tensor.shape[2]), 417 | np.linspace(0.0, 1.0, tensor.shape[1]), 418 | cmap='RdBu', 419 | show=not save, 420 | save=save, 421 | name="fhnb.gif") 422 | 423 | 424 | def run_fitz_hugh_nagumo_spatial(run=True, save=False): 425 | N = 100 426 | N_x = 100 427 | N_y = 100 428 | if run: 429 | p = Popen([chosenBin] + 430 | ["-pattern", "FitzHughNagumo"] + 431 | ["-bc", "ZeroFlux"] + 432 | ["-xd", str(N_x)] + 433 | ["-yd", str(N_x)] + 434 | ["-nIter", "100"] + 435 | ["-nIterPerRound", "1000"] + 436 | ["-dt", "0.001"] + 437 | ["-wns", ".05"] + 438 | ["-ud", "1"] + 439 | ["-vd", "100"] + 440 | ["-p1", "0.01"] + 441 | ["-p2", "10"] + 442 | ["-of", "fhns.npy"]) 443 | p.communicate() 444 | 445 | tensor = read_solution("fhns.npy", N, N_x, N_y) 446 | 447 | animate_colormap(tensor, 448 | np.linspace(0.0, 1.0, tensor.shape[2]), 449 | np.linspace(0.0, 1.0, tensor.shape[1]), 450 | cmap='RdBu', 451 | show=not save, 452 | save=save, 453 | name="fhns.gif") 454 | 455 | 456 | if __name__ == "__main__": 457 | run_gray_scott_bacteria(run=True, save=False) 458 | # run_gray_scott_bacteria2(run=True, save=False) 459 | # run_gray_scott_coral(run=True, save=False) 460 | # run_gray_scott_coral2(run=True, save=False) 461 | # run_gray_scott_coral3(run=False, save=False) 462 | # run_gray_scott_lines(run=True, save=False) 463 | # run_brussellator_stripes(run=True, save=False) 464 | # run_brussellator_dots(run=True, save=False) 465 | # run_schnakenberg(run=True, save=False) 466 | # run_thomas(run=True, save=False) 467 | # run_fitz_hugh_nagumo(run=True, save=False) -------------------------------------------------------------------------------- /plotter.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from mpl_toolkits.mplot3d import Axes3D 3 | from matplotlib import cm 4 | import matplotlib.pyplot as plt 5 | import matplotlib.animation as animation 6 | from subprocess import Popen 7 | import os 8 | 9 | debugDll = os.getcwd() + "\\x64\\Debug\\TuringPatterns.exe" 10 | releaseDll = os.getcwd() + "\\x64\\Release\\TuringPatterns.exe" 11 | 12 | 13 | def __ax_formatter(ax, title="", x_label="", y_label="", show_legend=False): 14 | ax.set_title(title) 15 | ax.set_xlabel(x_label) 16 | ax.set_ylabel(y_label) 17 | 18 | if show_legend: 19 | ax.legend(loc='best') 20 | 21 | 22 | def surf(z, x, y, title="", x_label="", y_label="", show_legend=False, show=False): 23 | fig = plt.figure() 24 | ax = fig.gca(projection='3d') 25 | 26 | # Create X and Y data 27 | x_grid, y_grid = np.meshgrid(x, y) 28 | 29 | ax.plot_surface(x_grid, y_grid, z, cmap=cm.coolwarm, rstride=16, cstride=16, antialiased=True) 30 | 31 | __ax_formatter(ax, title, x_label, y_label, show_legend) 32 | 33 | if show: 34 | plt.show() 35 | 36 | 37 | def plot(z, x, title="", x_label="", y_label="", show_legend=False, show=False): 38 | fig = plt.figure() 39 | ax = fig.add_subplot(111) 40 | 41 | for i in range(len(x)): 42 | ax.plot(z[:, i]) 43 | 44 | __ax_formatter(ax, title, x_label, y_label, show_legend) 45 | 46 | if show: 47 | plt.show() 48 | 49 | 50 | def animate(z, x, show=False, save=False, name=""): 51 | fig, ax = plt.subplots() 52 | 53 | line, = ax.plot(x, z[:, 0]) 54 | 55 | def update_line(i): 56 | if i >= z.shape[1]: 57 | return line, 58 | line.set_ydata(z[:, i]) # update the data 59 | return line, 60 | 61 | # Init only required for blitting to give a clean slate. 62 | def init(): 63 | line.set_ydata(z[:, 0]) 64 | return line, 65 | 66 | ani = animation.FuncAnimation(fig, update_line, np.arange(1, 200), init_func=init, interval=25, blit=True) 67 | 68 | if show: 69 | plt.show() 70 | 71 | if save: 72 | ani.save(name, writer='imagemagick', fps=60) 73 | 74 | 75 | def animate_3D(z, x, y, rstride=1, cstride=1, cmap=cm.coolwarm, show=False, save=False, name=""): 76 | fig = plt.figure() 77 | ax = fig.gca(projection='3d') 78 | 79 | # Create X and Y data 80 | x_grid, y_grid = np.meshgrid(x, y) 81 | 82 | line = ax.plot_surface(x_grid, y_grid, z[0], cmap=cmap, rstride=rstride, cstride=cstride, antialiased=True) 83 | 84 | def update_line(i): 85 | if i >= z.shape[0]: 86 | return line, 87 | ax.clear() 88 | l = ax.plot_surface(x_grid, y_grid, z[i], cmap=cm.coolwarm,rstride=rstride, cstride=cstride, antialiased=True) 89 | return l, 90 | 91 | ani = animation.FuncAnimation(fig, update_line, np.arange(1, 200), interval=25, blit=False) 92 | 93 | if show: 94 | plt.show() 95 | 96 | if save: 97 | ani.save(name, writer='imagemagick', fps=60) 98 | 99 | 100 | def animate_colormap(z, x, y, cmap='PuBu_r', shading='gouraud', show=False, save=False, name=""): 101 | fig, ax = plt.subplots() 102 | x, y = np.meshgrid(x, y) 103 | ax.pcolormesh(x, y, z[0], shading=shading, cmap=cmap) 104 | 105 | def update_line(i): 106 | if i >= z.shape[0]: 107 | return None, 108 | ax.clear() 109 | ax.pcolormesh(x, y, z[i], shading=shading, cmap=cmap) 110 | return None, 111 | 112 | ani = animation.FuncAnimation(fig, update_line, np.arange(1, 200), interval=25, blit=False) 113 | 114 | if show: 115 | plt.show() 116 | 117 | if save: 118 | ani.save(name, writer='imagemagick', fps=60) 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /schnakenberg_compressed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmontalb/TuringPatterns/64cb1bc66a00a9c50d33ea08da143403cbf98bbe/schnakenberg_compressed.gif -------------------------------------------------------------------------------- /stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // TuringPatterns.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | #include 13 | -------------------------------------------------------------------------------- /targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | --------------------------------------------------------------------------------