Monte Carlo is an advanced simulation capability provided by Trick that allows users to repeatedly run copies of a simulation with different input values. Users can vary the input space of a simulation via input file, random value generation, or by calculating values from previous Monte Carlo runs in a process called optimization. This tutorial will show you how to develop simulations that can take advantage of this capability.
**For a thorough explanation of Monte Carlo and its features, read the [Monte Carlo User Guide](/trick/documentation/simulation_capabilities/UserGuide-Monte-Carlo).**
The core simulation this tutorial is built around is a slight modification of the Analytical Cannon simulation created earlier in the tutorial. **The primary modification made was to change the *init_angle* attribute from radians to degrees.**
### cannon.h
This header file contains the cannon structure we are going to use to create our simulation object and function prototypes we will use to specify our Trick jobs.
```C
/*
PURPOSE: Cannon structure and simulation functions.
*/
#ifndef CANNON_H
#define CANNON_H
#include "trick_utils/comm/include/tc.h"
#include "trick_utils/comm/include/tc_proto.h"
typedef struct
{
double vel0[2]; // *i m Initial velocity of the cannonball.
double pos0[2]; // *i m Initial position of the cannonball.
double init_speed; // *i m/s Initial barrel speed.
double init_angle; // *i ° Launch angle of cannon.
double acc[2]; // m/s2 xy-acceleration
double vel[2]; // m/s xy-velocity
double pos[2]; // m xy-position
double time; // s Model time.
double timeRate; // -- Model time per sim time.
int impact; // -- Has impact occured?
double impactTime; // s Time of impact.
} CANNON;
#ifdef __cplusplus
extern "C" {
#endif
// Function prototypes.
int cannon_default_data(CANNON*);
int cannon_init(CANNON*);
int cannon_analytic(CANNON*);
#ifdef __cplusplus
}
#endif
#endif // #ifndef CANNON_H
```
### cannon.c
This .c file contains the logic used to advance our simulation as well as the default data and initial data we wish to with our cannon object.
The simulation definition file simply sets up our simulation objects and configures their respective Trick jobs.
```C++
/*
PURPOSE: Monte tutorial simulation definition.
LIBRARY DEPENDENCIES: ((cannon/src/cannon.c))
*/
#include "sim_objects/default_trick_sys.sm"
##include "cannon/include/cannon.h"
class CannonSimObject : public Trick::SimObject
{
public:
CANNON cannon;
CannonSimObject()
{
("default_data") cannon_default_data(&cannon);
("initialization") cannon_init(&cannon);
(0.01, "scheduled") cannon_analytic(&cannon);
}
};
CannonSimObject cso;
```
### Data Recording
Visualizing the differences between the various Monte Carlo methods requires us to first establish a data recording file. In order to do this, the simulation must first be compiled; run the following command in your shell and compile the simulation above.
```
trick-CP
```
After successfully compiling the simulation, open the Trick Data Recording Editor with the following
01. In the left pane will be *cso*, the CannonSimObject we created. Expand this tree and double click on the pos[2] variable. Ensure the variable appears in the "Selected Variables" section at the bottom.
01. At the top, change DR Cycle from 0.1 to 0.01.
01. Save the data recording file in the simulation directory.
### Test Run
Create a sub-directory called *RUN_test* in your simulation directory. In this new directory create an input file named *test.py*. This input file executes the data recording file you saved above and stops the simulation after 10 seconds of simulation time.
Expand the cso.cannon.pos[0-1] variable in the left pane and create a curve with pos[1] as the Y axis and pos[0] as the X axis. Once your DP Content looks like the above image, click the comparison plot button in the actions menu.
In each of the bellow sections, you can repeat these steps to visualize the differences between Monte Carlo implementations.
## The Task
**What would be the optimal launch angle required to ensure our cannonball travels the furthest distance?** Let us assume that we have no conception of physics or trigonometry and that we don't already know the answer.
Input files allow you to specify the exact values you want on a particular simulation run. Input files are the most precise implementation, but they require more effort to setup and modify later down the road. Input files can contain multiple (tab or space) delimited columns filled with numerical information.
Random Input Generation provides users with the ability to statistically generate input values along a Gaussian or Poisson distribution. Random generation is less precise than an input file, but it is more extensible and much easier to modify.
Optimization is the process of evaluating the previous run's data for use in the next run. In essence, you are optimizing each subsequent run and closing in on a specific value; in this instance, we are closing in on the optimal launch angle.
### optimization.h
We need to create two new Trick jobs to house our optimization logic. Create this file in your include directory.
```C
/*
PURPOSE: Function prototypes for Monte Carlo optimization.
*/
#ifndef OPTIMIZATION_H
#define OPTIMIZATION_H
#include "../include/cannon.h"
#ifdef __cplusplus
extern "C" {
#endif
int cannon_slave_post(CANNON *);
int cannon_master_post(CANNON *);
#ifdef __cplusplus
}
#endif
#endif
```
### optimization.c
What we are doing in these two functions is sending the slave's cannon structure from after the run has completed back to the master. The master then analyzes the data and sends the new run information to the slave. This cycles over and over again until we hit the number of runs specified in our input script. Create this file in your src directory.
The last thing that we need to do is modify our simulation definition file and add the two new Trick jobs. As you can see, we have added a new library dependency, a new ## inclusion, and two new constructor jobs.