WaveSimPP 1.0
A C library for solving the wave equation and reconstructing the wave field
All Classes Namespaces Functions Modules Pages
main.cpp
1#include <iostream>
2#include <string>
3#include "ExternalLibraries/cxxopts.hpp"
4
5#include <boost/multi_array.hpp>
6#include <boost/array.hpp>
7#include "CustomLibraries/np.hpp"
8#include "CustomLibraries/np_to_matplot.hpp"
9#include "CustomLibraries/wavePlotter.hpp"
10#include <matplot/matplot.h>
11#include <cassert>
12#include <sstream>
13
14#include "CoreAlgorithm/helper_func.hpp"
15#include "CoreAlgorithm/coeff.hpp"
16#include "CoreAlgorithm/source.hpp"
17#include "CoreAlgorithm/computational.hpp"
18#include "CoreAlgorithm/solver.hpp"
19
20// Command line arguments
21cxxopts::Options options("WaveSimPP", "A wave propagation simulator written in C++.");
22int main(int argc, char *argv[])
23{
24 // Parse command line arguments
25 options.add_options()("d,debug", "Enable debugging", cxxopts::value<bool>()->default_value("false"));
26 options.add_options()("animate", "Render an animation at the end", cxxopts::value<bool>()->default_value("true"));
27 options.add_options()("render", "Render each of the frames at the end", cxxopts::value<bool>()->default_value("false"));
28 options.add_options()("export", "Export the data to a series of csv files", cxxopts::value<bool>()->default_value("false"));
29 options.add_options()("o,output_dir", "Output directory path", cxxopts::value<std::string>()->default_value("output"));
30 options.add_options()("output_filename", "Output filename", cxxopts::value<std::string>()->default_value("output.mp4"));
31 options.add_options()("framerate", "Framerate of output video", cxxopts::value<int>()->default_value("30"));
32 options.add_options()("v,verbose", "Verbose output", cxxopts::value<bool>()->default_value("false"));
33 options.add_options()("source_i", "Source i position", cxxopts::value<int>()->default_value("50"));
34 options.add_options()("source_j", "Source j position", cxxopts::value<int>()->default_value("50"));
35 options.add_options()("nt", "Number of time steps", cxxopts::value<int>()->default_value("1000"));
36 options.add_options()("nx", "Number of x steps", cxxopts::value<int>()->default_value("100"));
37 options.add_options()("nz", "Number of z steps", cxxopts::value<int>()->default_value("100"));
38 options.add_options()("dt", "Time step size", cxxopts::value<double>()->default_value("0.001"));
39 options.add_options()("dx", "x step size", cxxopts::value<double>()->default_value("0.01"));
40 options.add_options()("dz", "z step size", cxxopts::value<double>()->default_value("0.01"));
41 options.add_options()("f,frequency", "Frequency of source", cxxopts::value<double>()->default_value("10.0"));
42 options.add_options()("a,amplitude", "Amplitude of source", cxxopts::value<double>()->default_value("1.0"));
43 options.add_options()("s,shift", "Shift of source", cxxopts::value<double>()->default_value("0.1"));
44 options.add_options()("r,radius", "Radius of velocity profile", cxxopts::value<double>()->default_value("150.0"));
45 options.add_options()("l,num_levels", "Number of levels in the filled contour plot", cxxopts::value<int>()->default_value("100"));
46 options.add_options()("h,help", "Print help");
47 cxxopts::ParseResult result;
48 try
49 {
50 result = options.parse(argc, argv);
51 }
52 catch (const cxxopts::exceptions::exception &e)
53 {
54 std::cerr << "WaveSimPP: " << e.what() << '\n';
55 std::cerr << "usage: WaveSimPP [options] ...\n";
56 return EXIT_FAILURE;
57 }
58 if (result.count("help"))
59 {
60 std::cout << options.help({"", "Group"}) << std::endl;
61 return true;
62 }
63
64 // Define the constants for the simulation
65
66 // Number of x and z grid points
67
68 int nx = result["nx"].as<int>();
69
70 int nz = result["nz"].as<int>();
71 // Number of time steps
72 int nt = result["nt"].as<int>();
73
74 // Differentiation values
75 double dx = result["dx"].as<double>();
76 double dz = result["dz"].as<double>();
77 double dt = result["dt"].as<double>();
78
79 // Define the domain
80 double xmin = 0.0;
81 double xmax = nx * dx;
82 double zmin = 0.0;
83 double zmax = nz * dz;
84 double tmin = 0.0;
85 double tmax = nt * dt;
86
87 // Define the source parameters
88 double f_M = result["frequency"].as<double>();
89 double amp = result["amplitude"].as<double>();
90 double shift = result["shift"].as<double>();
91
92 // Source location
93 int source_is = result["source_i"].as<int>();
94 int source_js = result["source_j"].as<int>();
95 // Create the source
96 boost::multi_array<double, 3> f = waveSimCore::ricker(source_is, source_js, f_M, amp, shift, tmin, tmax, nt, nx, nz);
97
98 // Create the velocity profile
99 double r = result["radius"].as<double>();
100
101 boost::multi_array<double, 2> vel = waveSimCore::get_profile(xmin, xmax, zmin, zmax, nx, nz, r);
102
103 // Solve the wave equation
104 boost::multi_array<double, 3> u = waveSimCore::wave_solver(vel, dt, dx, dz, nt, nx, nz, f);
105
106 // Define the number of different levels for the contour plot
107 int num_levels = result["num_levels"].as<int>();
108 // Create the levels for the contour plot based on the min and max values of u
109 double min_u = np::min(u);
110 double max_u = np::max(u);
111 std::vector<double> levels = matplot::linspace(min_u, max_u, num_levels);
112
113 // Create the x and z axis for the contour plot and convert them to matplot format
114 boost::multi_array<double, 1> x = np::linspace(xmin, xmax, nx);
115 boost::multi_array<double, 1> z = np::linspace(zmin, zmax, nz);
116 const boost::multi_array<double, 1> axis[2] = {x, z};
117 std::vector<boost::multi_array<double, 2>> XcZ = np::meshgrid(axis, false, np::xy);
118
119 matplot::vector_2d Xp = np::convert_to_matplot(XcZ[0]);
120 matplot::vector_2d Zp = np::convert_to_matplot(XcZ[1]);
121
122 // Create the plotter object and animate the results
123 wavePlotter::Plotter my_plotter(u, Xp, Zp, num_levels, nt);
124 my_plotter.setSaveDirectory(result["output_filename"].as<std::string>());
125
126 // If you want to render a specific frame, use this:
127 // my_plotter.renderFrame(int frame_index);
128
129 // Renders the entire animation from start_frame to end_frame
130 int start_frame = 0;
131 int end_frame = nt;
132 int fps = result["framerate"].as<int>();
133 if (result["export"].as<bool>())
134 {
135 my_plotter.renderAllFrames(start_frame, end_frame);
136 }
137 else if (result["animate"].as<bool>())
138 {
139 my_plotter.animate(result["output_filename"].as<std::string>(), start_frame, end_frame, fps);
140 }
141 else
142 {
143 my_plotter.renderAllFrames(start_frame, end_frame);
144 }
145}
This class is used to plot the wave field TODO: make it multithreaded.
Definition: wavePlotter.hpp:22
matplot::vector_2d convert_to_matplot(const boost::multi_array< double, 2 > &arr)
Convert a 2D boost::multi_array to a matplot::vector_2d.
boost::multi_array< double, 3 > ricker(int i_s, int j_s, double f, double amp, double shift, double tmin, double tmax, int nt, int nx, int nz)
Get the Ricker wavelet as a 3D Array.
Definition: source.hpp:14
boost::multi_array< double, 2 > get_profile(double xmin, double xmax, double zmin, double zmax, int nx, int nz, double r)
Get the velocity profile of the model as a 2D Array.
boost::multi_array< double, 3 > wave_solver(boost::multi_array< double, 2 > c, double dt, double dx, double dz, int nt, int nx, int nz, boost::multi_array< double, 3 > f)
Definition: solver.hpp:27
::value constexpr std::vector< boost::multi_array< T, ND > > meshgrid(const boost::multi_array< T, 1 >(&cinput)[ND], bool sparsing=false, indexing indexing_type=xy)
Definition: np.hpp:184
boost::multi_array< double, 1 > linspace(double start, double stop, long unsigned int num)
Implements the numpy linspace function.
Definition: np.hpp:161
::value constexpr T min(boost::multi_array< T, ND > const &input_array)
Implements the numpy min function for an n-dimensionl multi array.
Definition: np.hpp:419
::value constexpr T max(boost::multi_array< T, ND > const &input_array)
Implements the numpy max function for an n-dimensionl multi array.
Definition: np.hpp:384