{"id":35124080,"url":"https://github.com/scottfr/simulation","last_synced_at":"2026-04-01T20:44:27.807Z","repository":{"id":57361627,"uuid":"461223943","full_name":"scottfr/simulation","owner":"scottfr","description":"Node and browser JavaScript library to run simulations. Supports System Dynamics modeling, Differential Equation mathematical modeling, and Agent Based Modeling.","archived":false,"fork":false,"pushed_at":"2025-12-27T19:02:56.000Z","size":796,"stargazers_count":130,"open_issues_count":3,"forks_count":22,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-12-30T02:25:40.552Z","etag":null,"topics":["agent-based-modeling","differential-equations","mathematical-modelling","modeling","simulation","system-dynamics"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scottfr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-02-19T14:59:50.000Z","updated_at":"2025-12-27T18:11:03.000Z","dependencies_parsed_at":"2024-10-27T18:47:58.870Z","dependency_job_id":"ea2b0d7e-3c5d-4569-8e06-7c81442016c8","html_url":"https://github.com/scottfr/simulation","commit_stats":{"total_commits":4,"total_committers":1,"mean_commits":4.0,"dds":0.0,"last_synced_commit":"eff41ca0d56fd29320007938a621f4a9d584783a"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/scottfr/simulation","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottfr%2Fsimulation","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottfr%2Fsimulation/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottfr%2Fsimulation/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottfr%2Fsimulation/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scottfr","download_url":"https://codeload.github.com/scottfr/simulation/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottfr%2Fsimulation/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31291784,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-based-modeling","differential-equations","mathematical-modelling","modeling","simulation","system-dynamics"],"created_at":"2025-12-28T01:32:38.278Z","updated_at":"2026-04-01T20:44:27.796Z","avatar_url":"https://github.com/scottfr.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `simulation` - Simulation and modeling for Node and browsers\n\n`simulation` is a multi-method simulation package for Node or the browser. Use it to create models for the environment, business, or other areas. For example, it can be used to create models of disease spread, population growth, or the adoption of a product in the marketplace.\n\n`simulation` supports differential equation models (also called System Dynamics models) in addition to Agent Based Models, or any mixture of the two techniques.\n\nIn addition to building models directly with the package, `simulation` also supports importing and running models in the [ModelJSON](https://github.com/scottfr/modeljson) format or the [Insight Maker](https://insightmaker.com) format.\n\n## Quickstart\n\nCopy this HTML into an *index.html* file and open it in your browser.\n\n```html\n\u003cscript type=\"importmap\"\u003e\n  {\n    \"imports\": {\n      \"simulation\": \"https://unpkg.com/simulation@8.0.0\",\n      \"chart.js\": \"https://unpkg.com/chart.js@3.9.1/dist/chart.esm.js\"\n    }\n  }\n\u003c/script\u003e\n\n\u003cscript type=\"module\"\u003e\n\nimport { Model } from \"simulation\";\nimport { Chart, registerables } from 'chart.js';\n\n// Define the simulation model\n\nlet m = new Model({\n    timeLength: 20\n});\nlet people = m.Stock({\n  name: \"People\",\n  initial: 10000\n});\nlet netGrowth = m.Flow(null, people, {\n  rate: \"[People] * 0.10\"\n});\n\n\n// Simulate the model\n\nlet res = m.simulate();\n\n\n// Create the chart of population growth using Chart.js\n\nChart.register(...registerables);\nnew Chart(document.getElementById('chart').getContext('2d'), {\n    type: 'line',\n    data: {\n        labels: res.times(),\n        datasets: [{\n            label: 'Population',\n            data: res.series(people),\n            borderColor: 'blue'\n        }]\n    }\n});\n\n\u003c/script\u003e\n\n\u003ccanvas id=\"chart\"\u003e\u003c/canvas\u003e\n```\n\n![Canvas Chart](docs/images/canvas_chart.png)\n\nNote that this neither bundles nor minifies the code. For production use cases, it is recommended to use a bundler.\n\n## Installing with NPM\n\nTo use the package with NPM and Node.js, run this command:\n\n```shell\nnpm install --save simulation\n```\n\nThe rest of this README will assume you are using `simulation` in Node with ES6 module syntax.\n\nIn the README, we will also be using the optional `simulation-viz-console` package to visualize results in a console. It may be installed with:\n\n```shell\nnpm install --save simulation-viz-console\n```\n\n## Example usage\n\n### Our first simulation model\n\nLet's create a simulation model of the world population over the next 100 years. Start by importing the `simulation` and `simulation-viz-console` packages.\n\n```javascript\nimport { Model } from \"simulation\";\nimport { table, plot } from \"simulation-viz-console\";\n```\n\n\u003e [!NOTE]\n\u003e If you get the error `SyntaxError: Cannot use import statement outside a module` when running this in Node, add `\"type\": \"module\"` to your `package.json` or change your file extension from `.js` to `.mjs`. See [here](https://nodejs.org/api/esm.html#enabling) for more information.\n\nNext, we initialize a model:\n\n```javascript\nlet m = new Model({\n  timeStart: 2020,\n  timeLength: 100,\n  timeUnits: \"Years\"\n});\n```\n\n\u003e [!TIP]\n\u003e Use VSCode or another editor that supports JSDoc type annotations. `simulation` makes extensive use of type annotations to indicate available options. Add `// @ts-check` to the top of a JavaScript file in VSCode to enable automatic type checking of the code, this will help catch errors.\n\nThis creates a model that will simulate 100 years, starting at the year 2020.\n\n`simulation` models are composed out of building blocks called \"primitives\". In this model we're going to use three primitives:\n\n* A **Stock** to store the number of people in the world population. Generally, stocks store things like people, dollars, water, or anything else\n* A **Flow** to define the change in the population stock. Flows model the movement of material between stocks.\n* A **Variable** to define the net growth rate for the population. In this model, that will be a constant value, but it could also be a dynamic equation.\n\n```javascript\n// Start with 7 billion people in the \"people\" stock\nlet people = m.Stock({\n  name: \"People\",\n  initial: 7e9\n});\n\n// Use a net growth rate of 2% a year\nlet growthRate = m.Variable({\n  name: \"Growth Rate\",\n  value: 0.02\n});\n\n// The population growth each year is the number of people times the growth rate\n// Please note that we refer to the value of other primitives in the model with the\n// [name] syntax.\nlet netGrowth = m.Flow(null, people, {\n  rate: \"[People] * [Growth Rate]\"\n});\n\n// For the netGrowth flow to be able to reference the growthRate, we need to link the primitives\nm.Link(growthRate, netGrowth);\n```\n\nWe've set up our model, now take a look at the results:\n\n```javascript\nlet results = m.simulate();\n\ntable(results, people);\nplot(results, people);\n```\n\nWhich outputs:\n\n```\n╔══════════════╤════════════════╗\n║ Time [years] │         People ║\n╟──────────────┼────────────────╢\n║         2020 │  7000000000.00 ║\n║         2021 │  7140000000.00 ║\n║         2022 │  7282800000.00 ║\n...\n║         2118 │ 48743293759.87 ║\n║         2119 │ 49718159635.07 ║\n║         2120 │ 50712522827.77 ║\n╚══════════════╧════════════════╝\n```\n\n![Population Growth Image](docs/images/pop_growth.png)\n\nPutting it all together we get the following. You can copy this into a `main.js` file, and run it with `node main.js`:\n\n```javascript\nimport { Model } from \"simulation\";\nimport { table, plot } from \"simulation-viz-console\";\n\n\nlet m = new Model({\n  timeStart: 2020,\n  timeLength: 100,\n  timeUnits: \"Years\"\n});\n\n// Start with 7 billion people in the \"people\" stock\nlet people = m.Stock({\n  name: \"People\",\n  initial: 7e9\n});\n\n// Use a net growth rate of 2% a year\nlet growthRate = m.Variable({\n  name: \"Growth Rate\",\n  value: 0.02\n});\n\n// The population growth each year is the number of people times the growth rate\n// Please note that we refer to the value of other primitives in the model with the\n// [name] syntax.\nlet netGrowth = m.Flow(null, people, {\n  rate: \"[People] * [Growth Rate]\"\n});\n\n// For the netGrowth flow to be able to reference the growthRate, we need to link the primitives\nm.Link(growthRate, netGrowth);\n\n\nlet results = m.simulate();\n\ntable(results, people);\nplot(results, people);\n```\n\n### Modeling the spread of a disease\n\nLet's now look at a more complex model: disease spread. One simple way to model the spread of a disease is to assume there are three categories of people:\n\n* **Susceptible** people who are healthy and can be infected,\n* **Infected** people who are sick and spreading the disease,\n* and, **Recovered** people who were infected but are now better. We'll also assume recovered people are now immune to the disease.\n\nWe'll use three stocks to represent these categories, and we'll use flows to move people between them.\n\n```javascript\nimport { Model } from \"simulation\";\nimport { table, plot } from \"simulation-viz-console\";\n\n\nlet m = new Model();\n\n// Start with 1,000 healthy, susceptible people\nlet s = m.Stock({\n  name: \"Susceptible\",\n  initial: 1000\n});\n\n// One infected person\nlet i = m.Stock({\n  name: \"Infected\",\n  initial: 1\n});\n\n// And no recovered people\nlet r = m.Stock({\n  name: \"Recovered\",\n  initial: 0\n});\n\n\n// The number of people becoming sick is the product of the\n// healthy and sick people times a constant.\n\nm.Flow(s, i, {\n  name: \"Infection\",\n  rate: \"[Susceptible] * [Infected] * 0.0003\"\n});\n\n\n// People recover at a fixed rate\n\nm.Flow(i, r, {\n  name: \"Recovery\",\n  rate: \"[Infected] * 0.015\"\n});\n\n\nplot(m.simulate(), [s, i, r]);\n```\n\nTaking a look at the results for this model. We can see there is an initial spike in infections that declines as people move to the *Recovered*, immune state.\n\n\n![Disease Dynamics Image](docs/images/sir_disease.png)\n\n\n### Modeling disease with agents\n\nThe models we have looked at so far are System Dynamics differential equation models. They assume average changes across a continuous population. In reality though, when looking at the spread of disease you have many distinct individuals and interactions.\n\nThe `simulation` package supports Agent Based Modeling for cases where you want to simulate events at the level of an individual rather than in aggregate.\n\nFor this model, we're going to use a couple new types of primitives:\n\n* **Agent** We'll use an Agent primitive to define what a \"person\" is in our model. When the model runs, a separate agent will be created for each person, and it will contain all the properties for that person.\n* **Population** A population represents a collection of agents with a given Agent definition. We'll have a population of 20 people in this example.\n* **State** A State represents a boolean condition. For example sick/not-sick, employed/not-employed, etc. We'll use these to represent whether our agents are healthy or sick.\n* **Transition** A Transition moves agents between states. For example, you could have a model with \"Employed\" and \"Unemployed\" states. When a person is hired, they are transitioned from the unemployed to the employed states. We'll use a transition to move agents between health states. \n\n```javascript\nimport { Model } from \"simulation\";\nimport { table, plot } from \"simulation-viz-console\";\n\n\nlet m = new Model();\n\n// Define the person agent for our model\nlet person = m.Agent({\n  name: \"Person\"\n});\n\n// Add a healthy state to the person agent, our agents\n// will all start healthy.\n//\n// Note we use `person.State` rather than `m.State` to add the state\n// to the agent definition, not to the model in general.\nlet healthyState = person.State({\n  name: \"Healthy\",\n  startActive: true\n});\n\n// Add an infected state to our person agent. For each agent\n// it will start with the opposite value of that agent's healthy\n// state.\nlet infectedState = person.State({\n  name: \"Infected\",\n  startActive: \"not [Healthy]\"\n});\n\n// Since the Infected state uses the Healthy state in its equation,\n// we need to explicitly link them\nperson.Link(healthyState, infectedState);\n\n// Add a transition to convert people from the Healthy to Infected states.\n// You can have a variety of different transition conditions. Here, we'll\n// use a simple 2% chance of transitioning each time period.\nperson.Transition(healthyState, infectedState, {\n  trigger: \"Probability\",\n  value: 0.02\n});\n\n\n// Create a population of 20 person agents\nlet population = m.Population({\n  name: \"Population\",\n  populationSize: 20,\n  agentBase: person\n});\n\n// The population needs to reference the person agent so we\n// explicitly link them\nm.Link(person, population);\n\n// Create summary statistics for our simulation that count up the number\n// of healthy and infected people\nlet healthyCount = m.Variable({\n  name: \"Healthy Count\",\n  value: \"[Population].FindState([Healthy]).Count()\"\n});\nm.Link(population, healthyCount);\n\n\nlet infectedCount = m.Variable({\n  name: \"Infected Count\",\n  value: \"[Population].FindState([Infected]).Count()\"\n});\nm.Link(population, infectedCount);\n\n\nplot(m.simulate(), [healthyCount, infectedCount]);\n```\n\nHere are typical results you might see:\n\n![ABM Disease](docs/images/abm_disease.png)\n\n### Using units in models\n\nMost models are of a physical system and each primitive has units. For example in our disease or population models, the stocks have units of \"People\", and the flow rates have units of \"People/Year\" (or some other time units).\n\nIn our models above, this was implicit. However, it can be useful to explicitly specify the units for each primitive in your model. When you do, `simulation` will check the units during the simulation to ensure they aren't violated. This typing can help prevent bugs in your models.\n\n`simulation` has a large number of common units built-in, but you can also define your own custom units.\n\nLet's look at a quick example that models the water level in a lake. Here `simulation` checks the units in the model and also transparently converts between units like `acre feet`, `gallons`, `months`, `years` and `hours`.\n\nAlso note the use of `{4 year}` in the evaporation equation. The `{123 units}` syntax allows you to use numbers with units directly in your equations. So you can do things like `{10 people}` or `{10 people/year^2}`.\n\n\n```javascript\nimport { Model } from \"simulation\";\nimport { table, plot } from \"simulation-viz-console\";\n\n\nlet m = new Model({\n  timeUnits: \"Months\",\n  timeLength: 72\n});\n\n// Model a lake's water volume as a stock\nlet lake = m.Stock({\n  name: \"Lake\",\n  initial: 100,\n  units: \"acre feet\"\n});\n\n// A river flowing into the lake is modeled as a flow\nlet river = m.Flow(null, lake, {\n  name: \"Inflow River\",\n  rate: \"1000 * (seasonal() + 2)\", // the seasonal() function creates a sine wave over the course of the year, representing different rates of evaporation in summer vs winter\n  units: \"gallons / hour\"\n});\n\n// Evaporation from the lake is also modelled as a flow\nlet evaporation = m.Flow(lake, null, {\n  name: \"Evaporation\",\n  rate: \"[Lake] / {4 year}\", // 1/4 of the lake's volume evaporates per year\n  units: \"acre feet / year\"\n});\n\nlet results = m.simulate();\n\ntable(results, [lake, river, evaporation]);\nplot(results, lake);\n```\n\nOutputs:\n\n```\n╔═══════════════╤══════════════════╤═══════════════════════════════╤════════════════════════════════╗\n║ Time [months] │ Lake [acre feet] │ Inflow River [gallons / hour] │ Evaporation [acre feet / year] ║\n╟───────────────┼──────────────────┼───────────────────────────────┼────────────────────────────────╢\n║             0 │           100.00 │                       3000.00 │                          25.00 ║\n║             1 │           104.64 │                       2866.03 │                          26.16 ║\n║             2 │           108.88 │                       2500.00 │                          27.22 ║\n...\n║            70 │           184.74 │                       2500.00 │                          46.18 ║\n║            71 │           186.49 │                       2866.03 │                          46.62 ║\n║            72 │           189.03 │                       3000.00 │                          47.26 ║\n╚═══════════════╧══════════════════╧═══════════════════════════════╧════════════════════════════════╝\n```\n\n![Lake Volume](docs/images/lake_volume.png)\n\n### Using vectors in your model\n\nLet's revisit the population model from earlier. What if we wanted to simulate the population growth for the world but also break it down by country?\n\nWe could do this by creating a separate stock and flow for each country, but that would become tedious (and inefficient).\n\nInstead, `simulation` supports vectors. Vectors can be used in place of regular scalar values in your models. They are denoted with curly brackets.\n\nFor example, `{1, 2, 3} * {1, 2, 3}` will return `{1, 4, 9}`. You can also name the elements of a vector. For example, `{cats: 10, dogs: 2} * {dogs: 3, cats: 20}` will return `{dogs: 6, cats: 200}`.\n\nUsing vectors, we can modify our population model above to simulate individual countries in North America without changing the model structure. We just need to define country specific populations and growth rates using vectors. We'll add some units to our model too:\n\n\n```javascript\nimport { Model } from \"simulation\";\nimport { plot } from \"simulation-viz-console\";\n\n\nlet m = new Model({\n  timeStart: 2020,\n  timeLength: 100,\n  timeUnits: \"Years\"\n});\n\nlet people = m.Stock({\n  name: \"People\",\n  initial: \"{usa: 320, canada: 38, mexico: 120}\",\n  units: \"Millions\"\n});\n\n\nlet growthRate = m.Variable({\n  name: \"Growth Rate\",\n  value: \"{usa: 0.004, canada: 0.011, mexico: 0.011}\",\n  units: \"1 / Years\"\n});\n\nlet netGrowth = m.Flow(null, people, {\n  rate: \"[People] * [Growth Rate]\",\n  units: \"Millions / Year\"\n});\n\nm.Link(growthRate, netGrowth);\n\n\nplot(m.simulate(), [people]);\n```\n\n![Population Countries](docs/images/population_countries.png)\n\n\n## Interactive simulations\n\nWhen building interactive simulations, you can adjust values within the simulation while it is running.\n\nTo do so, use the `simulateAsync` method of a `Model`. `simulateAsync` returns a promise that resolves to the completed simulation results or rejects with an error.\n\n`simulateAsync` takes a single parameter containing an object with an async `onStep` function. `onStep` is awaited at the end of each time step.\n\nWhen `onStep` is called, it is passed the current simulation state along with a `setValue(primitive, value)` method. Calling `setValue` sets the current value of `primitive` to `value`.\n\nHere is an example of an interactive simulation where the user decides how much water flows into a bucket each time step:\n\n\n```javascript\nimport { Model } from \"simulation\";\nimport { plot } from \"simulation-viz-console\";\nimport readline from 'readline';\n\n\nconst rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout\n});\n\nfunction getNumber(prompt) {\n  return new Promise((resolve) =\u003e {\n    rl.question(prompt, (answer) =\u003e {\n      resolve(answer);\n    });\n  });\n};\n\n\nlet m = new Model({\n  timeStart: 2020,\n  timeLength: 5,\n  timeUnits: \"Years\",\n  timeStep: 1\n});\n\n\nlet bucket = m.Stock({\n  name: \"Bucket\",\n  initial: 0\n});\n\n\nlet inflow = m.Flow(null, bucket, {\n  name: \"Inflow\",\n  rate: 0\n});\n\n\nlet results = await m.simulateAsync({\n  onStep: async (simulation) =\u003e {\n    if (simulation.time === m.timeStart + m.timeLength) {\n      // It's the end of the simulation, so we don't need to ask for input\n      return;\n    }\n    console.log(`[Time: ${simulation.time}; Current bucket volume: ${simulation.results.value(bucket, simulation.time)}]`);\n\n    let newRate = await getNumber(\"Enter the new inflow rate as a number (e.g. 5 or 2.7): \");\n\n    simulation.setValue(inflow, newRate); \n  }\n});\n\n\nplot(results, [inflow, bucket]);\n\nprocess.exit();\n```\n\n\n## Equations\n\n`simulation` uses a DSL for its equations. This allows us to cleanly implement features like built-in units and vectors. Documentation for the equation capabilities are available [here](/equations.md). A brief overview of capabilities follows.\n\nValues of other primitives are referenced with the notation `[Primitive Name]`. When referencing a primitive, the primitives must either be connected directly (e.g. a flow connected to a stock) or connected via a link (e.g. `Model.link(referencedPrimitive, referencingPrimitive)`).\n\nNumbers with units may be defined with curly brackets. For example `{1 meters} * {200 centimeters}` (evaluates to 2 square meters).\n\nThe equation language supports common operators. `+`, `-`, `/`, `*`, `^`, `%` for mathematics (scalar and vector). `=`, `\u003c\u003e`, `\u003e`, `\u003c`, `\u003c=`, `\u003e=` for comparison (note that equality and inequality are `=` and `\u003c\u003e` respectively). `and`, `or`, `not` for boolean logic. `+` for string concatenation.\n\nLocal variables are supported in equations:\n\n```\nz \u003c- [x] + 1 # the arrow operator (\u003c-) is used for assignment\nz * 2 # The last evaluated value is returned automatically for multi-line equations\n```\n\nComments are supported:\n\n```\n# this is comment\n\n// so is this\n\n/*\nmulti-line\ncomment\n*/\n```\n\nConditionals are supported:\n\n```\nif [x] \u003e 10 then\n  100\nelse if [x] \u003e 5 then\n  50\nelse\n  10\nend if\n```\n\nLooping is supported:\n\n```\nx \u003c- 1\nwhile x \u003c 10\n  x \u003c- x + 1\nend loop\nx\n```\n\n```\nsum \u003c- 0\nfor x from 1 to 10\n   sum \u003c- sum + x\nend loop\nsum\n```\n\nCustom functions may also be defined:\n\n```\nfunction add(x, y)\n  x + y\nend function\n\nadd(1, 2)\n```\n\n### Built-in functions\n\n`simulation` has an [extensive list of built-in functions](/equations.md).\n\n\n## Simulation algorithms\n\n`simulation` uses a numerical solver to evaluate the differential equations in the model. It supports two solvers: Euler's method and a 4th order Runge Kutta solver.\n\nEach solver is parameterized by the simulation time step. You can configure them on your model instance:\n\n```javascript\nlet m = new Model({\n    algorithm: \"RK4\",\n    timeStep: 1\n});\n```\n\n```javascript\nlet m = new Model({\n    algorithm: \"Euler\",\n    timeStep: 0.1\n});\n```\n\nEuler's method is the simpler of the two methods. It evaluates all the flow rates at the start of the simulation. It then moves the simulation forward by the `timeStep` you specified using those rates. It then reevaluates the flows. It repeats this process until it reaches the end of the simulation.\n\nThe 4th order Runge Kutta method is more complex and requires four different flow rate evaluations for each time step. These four rates are averaged to get the final flow rate which is used to move the simulation forward by the time step.\n\nModel accuracy may be increased by decreasing the time step (at the cost of increased computation). Cutting the time step in half will double the computation required. Between the two methods, Runge Kutta is more accurate per unit of computation than Euler's method. The exception is if your model contains sharp discontinuities in flow rates (like step functions), in which case the averaging behavior in the Runge Kutta method may not be desirable.\n\n\n\n## Importing and exporting ModelJSON files\n\n`simulation` supports importing and exporting models using the [ModelJSON format](https://github.com/scottfr/modeljson).\n\nHere we load a ModelJSON model and run it. Then we modify the model and convert the changed model back to ModelJSON.\n\n```javascript\nimport { loadModelJSON, toModelJSON } from \"simulation\";\n\n// Load the model JSON for a model with a single variable\nlet model = loadModelJSON({\n  elements: [\n    { type: \"VARIABLE\", name: \"Y\", behavior: { value: \"years()\" } }\n  ]\n});\n\n\nlet v = model.getVariable(v =\u003e v.name === \"Y\");\n\n// Run the model and print the value of the variable\nlet res = model.simulate();\nconsole.log(\"Final value: \", res.value(v))\n\n\n// Modify the model, changing the variable name\nv.name = \"Year count\"\n\n// Get the new ModelJSON\nconsole.log(toModelJSON(model));\n```\n\n\nNote that not all features of `simulation` models are supported in ModelJSON. For example, ModelJSON does not support the Agent Population primitive.\n\n\n## Importing models from InsightMaker.com\n\n`simulation` supports importing and running models built with [Insight Maker](https://insightmaker.com).\n\nFirst export your model from Insight Maker from the `Share` menu.\n\nThen, you can use:\n\n```javascript\nimport { loadInsightMaker } from \"simulation\";\n\nlet model = loadInsightMaker(\"\u003cModel Text....\u003e\");\n\n// You may modify the loaded model before running it\n\n// In this case we'll change the value of the variable primitive \"Growth Rate\"\nlet rate = model.getVariable(v =\u003e v.name === \"Growth Rate\");\n\n// Give it a random value between 0 and 3;\nrate.value = Math.random() * 3;\n\n// run the simulation\nlet results = model.simulate();\n```\n\n# Citation\n\nIf you use this package in your published research, please cite:\n\n```\n@article{FORTMANNROE201428,\ntitle = {Insight Maker: A general-purpose tool for web-based modeling \u0026 simulation},\njournal = {Simulation Modelling Practice and Theory},\nvolume = {47},\npages = {28-45},\nyear = {2014},\nissn = {1569-190X},\ndoi = {https://doi.org/10.1016/j.simpat.2014.03.013},\nurl = {https://www.sciencedirect.com/science/article/pii/S1569190X14000513},\nauthor = {Scott Fortmann-Roe},\nkeywords = {Modeling, Simulation, Web-based technologies, System Dynamics, Agent-Based Modeling},\nabstract = {A web-based, general-purpose simulation and modeling tool is presented in this paper. The tool, Insight Maker, has been designed to make modeling and simulation accessible to a wider audience of users. Insight Maker integrates three general modeling approaches – System Dynamics, Agent-Based Modeling, and imperative programming – in a unified modeling framework. The environment provides a graphical model construction interface that is implemented purely in client-side code that runs on users’ machines. Advanced features, such as model scripting and an optimization tool, are also described. Insight Maker, under development for several years, has gained significant adoption with currently more than 20,000 registered users. In addition to detailing the tool and its guiding philosophy, this first paper on Insight Maker describes lessons learned from the development of a complex web-based simulation and modeling tool.}\n}\n```\n\n# License\n\nDistributed under the AGPL License. See [LICENSE](LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottfr%2Fsimulation","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscottfr%2Fsimulation","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottfr%2Fsimulation/lists"}