From b0e6b4693f60882e9830a1c03b7261a38f1cb5e1 Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 14:49:25 +0000 Subject: [PATCH 1/9] add-tutorial --- docs/14.gprmax/1.tutorials/1.quick-start.md | 28 ++-- .../2.scaling-with-mpi - c\303\263pia.md" | 143 ++++++++++++++++++ .../1.tutorials/2.scaling-with-mpi.md | 130 ++++++++++++++++ 3 files changed, 287 insertions(+), 14 deletions(-) create mode 100644 "docs/14.gprmax/1.tutorials/2.scaling-with-mpi - c\303\263pia.md" create mode 100644 docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md diff --git a/docs/14.gprmax/1.tutorials/1.quick-start.md b/docs/14.gprmax/1.tutorials/1.quick-start.md index 68b29c8..a6c8669 100644 --- a/docs/14.gprmax/1.tutorials/1.quick-start.md +++ b/docs/14.gprmax/1.tutorials/1.quick-start.md @@ -13,7 +13,7 @@ We will cover the `Bowtie antenna model` case from the gprMax examples to help y This example shows how to use a built-in antenna model in a simulation. Using a realistic antenna, like a MALA 1.2 GHz model, instead of a simple source improves accuracy, especially for near-field targets and complex antenna-environment interactions. ## Prerequisites -Download the required files [here](https://docs.gprmax.com/en/latest/examples_antennas.html) and save them to a folder named `SimulationFiles`. Then, you’ll be ready to send your simulation to the Cloud. +Download the required files [here](https://docs.gprmax.com/en/latest/examples_antennas.html#bowtie-antenna-model) and save them to a folder named `SimulationFiles`. Then, you’ll be ready to send your simulation to the Cloud. ## Running an gprMax Simulation Here is the code required to run a gprMax simulation using the Inductiva API: @@ -65,28 +65,28 @@ and print a summary of the simulation as shown below. Task status: Success Timeline: - Waiting for Input at 12/11, 14:39:27 0.816 s - In Queue at 12/11, 14:39:28 57.399 s - Preparing to Compute at 12/11, 14:40:26 4.071 s - In Progress at 12/11, 14:40:30 164.437 s - └> 164.254 s python -m gprMax antenna_like_MALA_1200_fs.in - Finalizing at 12/11, 14:43:14 0.559 s - Success at 12/11, 14:43:15 + Waiting for Input at 18/12, 12:29:34 0.919 s + In Queue at 18/12, 12:29:35 36.426 s + Preparing to Compute at 18/12, 12:30:11 2.012 s + In Progress at 18/12, 12:30:13 98.182 s + └> 98.0 s python -m gprMax antenna_like_MALA_1200_fs.in + Finalizing at 18/12, 12:31:51 0.554 s + Success at 18/12, 12:31:52 Data: - Size of zipped output: 29.70 KB - Size of unzipped output: 185.09 KB + Size of zipped output: 25.41 KB + Size of unzipped output: 125.44 KB Number of output files: 5 -Total estimated cost (US$): 0.0037 US$ - Estimated computation cost (US$): 0.0037 US$ - Task orchestration fee (US$): 0 US$ +Total estimated cost (US$): 0.0122 US$ + Estimated computation cost (US$): 0.0022 US$ + Task orchestration fee (US$): 0.010 US$ Note: A per-run orchestration fee (0.010 US$) applies to tasks run from 01 Dec 2025, in addition to the computation costs. Learn more about costs at: https://inductiva.ai/guides/how-it-works/basics/how-much-does-it-cost ``` -As you can see in the "In Progress" line, the part of the timeline that represents the actual execution of the simulation, the core computation time of this simulation was approximately 3 minutes. +As you can see in the "In Progress" line, the part of the timeline that represents the actual execution of the simulation, the core computation time of this simulation was approximately 2 minutes. ::docsbannersmall :: diff --git "a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi - c\303\263pia.md" "b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi - c\303\263pia.md" new file mode 100644 index 0000000..ec2a2ba --- /dev/null +++ "b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi - c\303\263pia.md" @@ -0,0 +1,143 @@ +--- +title: Scale gprMax with MPI +description: "" +seo: + title: "" + description: "" +--- + +gprMax supports parallelism through two main approaches: +- **MPI (Message Passing Interface)**: Enables gprMax to run simulations across multiple compute nodes, making it ideal for large-scale or distributed simulations. +- **OpenMP**: Allows parallel execution on shared-memory systems, letting multiple CPU cores on a single machine handle the simulation concurrently. + +In this tutorial, you will learn how to configure and run gprMax simulations using **MPI**, using the `B-scan with a bowtie antenna model` from the gprMax example cases. + +This example demonstrates creating a B-scan using an antenna model. The setup includes a **metal cylinder** with a diameter of 20 mm buried in a **dielectric half-space** with a relative permittivity of 6. The simulation uses an antenna similar to the **GSSI 1.5 GHz** antenna. + +For a B-scan, the antenna must be repositioned for each A-scan (trace). In this case, the B-scan covers a distance of 270 mm with traces every 5 mm, resulting in **54 separate model runs**. + +## Prerequisites +Before proceeding, make sure you've successfully run your [first gprMax simulation](quick-start). + +Download the required files [here](https://docs.gprmax.com/en/latest/examples_antennas.html#b-scan-with-a-bowtie-antenna-model) and save them to a folder named `b-scan-case`. + +## Understanding OpenMP vs MPI +How gprMax Actually Uses Them: + +MPI (Message Passing Interface) +In gprMax, MPI implements a task farm to distribute multiple independent simulations (like different A-scans in a B-scan) across multiple processes. + +Each MPI worker runs a complete, separate simulation +Task-level parallelism: 60 A-scans → 60 independent MPI processes +Can run on single machine with multiple cores OR multiple compute nodes +Example: B-scan with 200 A-scans distributed to 60 workers + +OpenMP +OpenMP parallelizes the FDTD solver computations within a single simulation using multiple threads on the same processor. + +Intra-simulation parallelism: Makes one simulation run faster +Uses shared memory threads on the same CPU/node +Parallelizes the computational loops of the FDTD method +Example: One A-scan using 4 threads runs ~3-4× faster + +## Sequential processing (using openMP) +Let’s start by running the 54 model sequentially. This means that it will perform the A-scan for the first step (model 1), then it will perform the A-scan for the second step (model 2), etc. + +the 54 model runs will be processed sequentially. This means that it will perform the A-scan for the first step (model 1), then it will perform the A-scan for the second step (model 2), etc. + +This is done by using this command: + +python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 +with -n meaning the number of runs. + +As each model is saved separately, the final result needs to be merged by doing: + +python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in +Which will merge all of the 54 runs into a single file. + +Here's the required script to run this example: + +```python +import inductiva + +# Instantiate machine group +cloud_machine = inductiva.resources.MachineGroup( + machine_type="c2d-highcpu-16", + provider="GCP", + spot=True) + +input_dir = "/Path/to/b-scan-case" + +# Initialize the Simulator +gprmax = inductiva.simulators.GprMax(version="3.1.7") + +commands_sequential = [ + "python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54", + "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" +] + +# Start sequential simulation +task_sequential = gprmax.run(\ + input_dir=input_dir, + commands=commands_sequential, + on=cloud_machine, + n_vcpus=16) + +# Wait for the simulations to finish +task_sequential.wait() +cloud_machine.terminate() +``` + +The simulation took approximately . Let's use MPI to make it faster. + +## MPI Processing +gprMax allows for MPI usage in their simulations. This means that each of the 54 runs can be a separate process. + +To do that we need a machine that has the amount of cpus that supports all of the runs. Then we need to wrap the python command into mpirun, as follows: + +mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn +The --mpi-no-spawn flag is preferred to be used as stated in their documentation. + +Here's how to do it using Inductiva: + +```python +import inductiva + +# Instantiate machine group +cloud_machine = inductiva.resources.MachineGroup( + machine_type="c2d-highcpu-112", + provider="GCP", + spot=True) + +input_dir = "/Path/to/b-scan-case" + +# Initialize the Simulator +gprmax = inductiva.simulators.GprMax(version="3.1.7", use_dev=True) + +commands_mpi = [ + "mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn", + "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" +] + +# Start MPI simulation +task_mpi = gprmax.run(\ + input_dir=input_dir, + commands=commands_mpi, + on=cloud_machine, + n_vcpus=112) + +# Wait for the simulations to finish +task_mpi.wait() +cloud_machine.terminate() +``` + +> ⚠️ **Note on vCPUs and Hyperthreading**: In most cloud environments (like Google Cloud), a vCPU corresponds to a thread, not a full physical core. So a `c2d-standard-8` machine has 8 vCPUs, which typically means 4 physical cores with hyperthreading enabled. + +## Results + + +## Key Takeaways + + +::docsbannersmall +:: diff --git a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md new file mode 100644 index 0000000..2b13aa8 --- /dev/null +++ b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md @@ -0,0 +1,130 @@ +--- +title: Scale gprMax with MPI +description: A step-by-step guide to running gprMax simulations with MPI +seo: + title: Scale gprMax simulations with MPI on Inductiva.AI + description: A step-by-step guide to running gprMax simulations with MPI +--- + +gprMax supports parallelism through **MPI** and **OpenMP**. For a deeper dive into how parallelism works in gprMax, refer to the [official documentation](https://docs.gprmax.com/en/latest/openmp_mpi.html). + +In this tutorial, you will learn how to configure and run gprMax simulations sequentially and using MPI. We will use the `B-scan with a bowtie antenna model` from the gprMax example cases as our demonstration. + +This example creates a B-scan using an antenna model. The setup includes a metal cylinder with a diameter of 20 mm buried in a dielectric half-space with a relative permittivity of 6. The simulation uses an antenna similar to the GSSI 1.5 GHz antenna. + +For a B-scan, the antenna must be repositioned for each A-scan (trace). In this case, the B-scan covers a distance of 270 mm with traces every 5 mm, resulting in **54 separate model runs**. + +## Prerequisites +Download the required files [here](https://docs.gprmax.com/en/latest/examples_antennas.html#b-scan-with-a-bowtie-antenna-model) and save them to a folder named `b-scan-case`. + +## Sequential Processing +First, let's run the 54 models **sequentially**. This means the simulation will process the A-scans one after another: model 1, then model 2, and so on. + +You can do this using the following command: + +``` +python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 +``` + +Here, `-n` specifies the number of runs. + +Each run produces a separate output file. To merge them into a single result file, run: + +``` +python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in +``` + +The required Python script to run this case sequentially on Inductiva is shown below: + +```python +import inductiva + +# Instantiate machine group +cloud_machine = inductiva.resources.MachineGroup( + machine_type="c2d-highcpu-16", + provider="GCP", + spot=True) + +input_dir = "/Path/to/b-scan-case" + +# Initialize the Simulator +gprmax = inductiva.simulators.GprMax(version="3.1.7") + +commands_sequential = [ + "python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54", + "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" +] + +# Start sequential simulation +task_sequential = gprmax.run(\ + input_dir=input_dir, + commands=commands_sequential, + on=cloud_machine, + n_vcpus=16) + +# Wait for the simulations to finish +task_sequential.wait() +cloud_machine.terminate() +``` + +Running these 54 simulations sequentially took approximately **hours and minutes**. + +Next, we will explore MPI-based parallel execution, which will significantly speed up this case. + +## MPI Processing +gprMax supports MPI, allowing each of the 54 runs to be executed **in parallel**. This requires a machine with enough vCPUs to support all the runs. Hence, we'll be running the case on a `c2d-highcpu-112`, which has 112 vCPUs, providing ample resources for all 54 simulations to run concurrently. + +> ⚠️ **Note on vCPUs and Hyperthreading**: In most cloud environments (e.g., Google Cloud), a vCPU represents a single thread rather than a full physical core. By default, Google Cloud VMs provide 2 vCPUs per physical core, so a `c2d-standard-112` machine with 112 vCPUs typically has 56 physical cores with hyperthreading enabled. + +Wrap the Python command with `mpirun` as follows: + +``` +mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn +``` + +- `-n 55` specifies the number of processes. +- `--mpi-no-spawn` is recommended according to the gprMax documentation to avoid MPI process spawning issues. +- +The `--mpi-no-spawn` flag is preferred to be used as stated in their documentation. + +Here’s the Python script to run the case with MPI: + +```python +import inductiva + +# Instantiate machine group +cloud_machine = inductiva.resources.MachineGroup( + machine_type="c2d-highcpu-112", + provider="GCP", + spot=True) + +input_dir = "/Path/to/b-scan-case" + +# Initialize the Simulator +gprmax = inductiva.simulators.GprMax(version="3.1.7", use_dev=True) + +commands_mpi = [ + "mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn", + "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" +] + +# Start MPI simulation +task_mpi = gprmax.run(\ + input_dir=input_dir, + commands=commands_mpi, + on=cloud_machine, + n_vcpus=112) + +# Wait for the simulations to finish +task_mpi.wait() +cloud_machine.terminate() +``` + +This MPI-based simulation significantly reduces the runtime compared to sequential execution, taking approximately **23 minutes**. + +## Results + + + +::docsbannersmall +:: From 975210ad9d96b688ae6e75147c5a32ddb104ab81 Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 14:51:41 +0000 Subject: [PATCH 2/9] Delete 2.scaling-with-mpi.md --- .../1.tutorials/2.scaling-with-mpi.md | 130 ------------------ 1 file changed, 130 deletions(-) delete mode 100644 docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md diff --git a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md deleted file mode 100644 index 2b13aa8..0000000 --- a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Scale gprMax with MPI -description: A step-by-step guide to running gprMax simulations with MPI -seo: - title: Scale gprMax simulations with MPI on Inductiva.AI - description: A step-by-step guide to running gprMax simulations with MPI ---- - -gprMax supports parallelism through **MPI** and **OpenMP**. For a deeper dive into how parallelism works in gprMax, refer to the [official documentation](https://docs.gprmax.com/en/latest/openmp_mpi.html). - -In this tutorial, you will learn how to configure and run gprMax simulations sequentially and using MPI. We will use the `B-scan with a bowtie antenna model` from the gprMax example cases as our demonstration. - -This example creates a B-scan using an antenna model. The setup includes a metal cylinder with a diameter of 20 mm buried in a dielectric half-space with a relative permittivity of 6. The simulation uses an antenna similar to the GSSI 1.5 GHz antenna. - -For a B-scan, the antenna must be repositioned for each A-scan (trace). In this case, the B-scan covers a distance of 270 mm with traces every 5 mm, resulting in **54 separate model runs**. - -## Prerequisites -Download the required files [here](https://docs.gprmax.com/en/latest/examples_antennas.html#b-scan-with-a-bowtie-antenna-model) and save them to a folder named `b-scan-case`. - -## Sequential Processing -First, let's run the 54 models **sequentially**. This means the simulation will process the A-scans one after another: model 1, then model 2, and so on. - -You can do this using the following command: - -``` -python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 -``` - -Here, `-n` specifies the number of runs. - -Each run produces a separate output file. To merge them into a single result file, run: - -``` -python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in -``` - -The required Python script to run this case sequentially on Inductiva is shown below: - -```python -import inductiva - -# Instantiate machine group -cloud_machine = inductiva.resources.MachineGroup( - machine_type="c2d-highcpu-16", - provider="GCP", - spot=True) - -input_dir = "/Path/to/b-scan-case" - -# Initialize the Simulator -gprmax = inductiva.simulators.GprMax(version="3.1.7") - -commands_sequential = [ - "python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54", - "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" -] - -# Start sequential simulation -task_sequential = gprmax.run(\ - input_dir=input_dir, - commands=commands_sequential, - on=cloud_machine, - n_vcpus=16) - -# Wait for the simulations to finish -task_sequential.wait() -cloud_machine.terminate() -``` - -Running these 54 simulations sequentially took approximately **hours and minutes**. - -Next, we will explore MPI-based parallel execution, which will significantly speed up this case. - -## MPI Processing -gprMax supports MPI, allowing each of the 54 runs to be executed **in parallel**. This requires a machine with enough vCPUs to support all the runs. Hence, we'll be running the case on a `c2d-highcpu-112`, which has 112 vCPUs, providing ample resources for all 54 simulations to run concurrently. - -> ⚠️ **Note on vCPUs and Hyperthreading**: In most cloud environments (e.g., Google Cloud), a vCPU represents a single thread rather than a full physical core. By default, Google Cloud VMs provide 2 vCPUs per physical core, so a `c2d-standard-112` machine with 112 vCPUs typically has 56 physical cores with hyperthreading enabled. - -Wrap the Python command with `mpirun` as follows: - -``` -mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn -``` - -- `-n 55` specifies the number of processes. -- `--mpi-no-spawn` is recommended according to the gprMax documentation to avoid MPI process spawning issues. -- -The `--mpi-no-spawn` flag is preferred to be used as stated in their documentation. - -Here’s the Python script to run the case with MPI: - -```python -import inductiva - -# Instantiate machine group -cloud_machine = inductiva.resources.MachineGroup( - machine_type="c2d-highcpu-112", - provider="GCP", - spot=True) - -input_dir = "/Path/to/b-scan-case" - -# Initialize the Simulator -gprmax = inductiva.simulators.GprMax(version="3.1.7", use_dev=True) - -commands_mpi = [ - "mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn", - "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" -] - -# Start MPI simulation -task_mpi = gprmax.run(\ - input_dir=input_dir, - commands=commands_mpi, - on=cloud_machine, - n_vcpus=112) - -# Wait for the simulations to finish -task_mpi.wait() -cloud_machine.terminate() -``` - -This MPI-based simulation significantly reduces the runtime compared to sequential execution, taking approximately **23 minutes**. - -## Results - - - -::docsbannersmall -:: From 5a511d99b40fac5eb4ade804c23a955594729eb0 Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 14:52:15 +0000 Subject: [PATCH 3/9] add-tutorial-2 --- .../2.scaling-with-mpi - c\303\263pia.md" | 143 ------------------ .../1.tutorials/2.scaling-with-mpi.md | 130 ++++++++++++++++ 2 files changed, 130 insertions(+), 143 deletions(-) delete mode 100644 "docs/14.gprmax/1.tutorials/2.scaling-with-mpi - c\303\263pia.md" create mode 100644 docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md diff --git "a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi - c\303\263pia.md" "b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi - c\303\263pia.md" deleted file mode 100644 index ec2a2ba..0000000 --- "a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi - c\303\263pia.md" +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: Scale gprMax with MPI -description: "" -seo: - title: "" - description: "" ---- - -gprMax supports parallelism through two main approaches: -- **MPI (Message Passing Interface)**: Enables gprMax to run simulations across multiple compute nodes, making it ideal for large-scale or distributed simulations. -- **OpenMP**: Allows parallel execution on shared-memory systems, letting multiple CPU cores on a single machine handle the simulation concurrently. - -In this tutorial, you will learn how to configure and run gprMax simulations using **MPI**, using the `B-scan with a bowtie antenna model` from the gprMax example cases. - -This example demonstrates creating a B-scan using an antenna model. The setup includes a **metal cylinder** with a diameter of 20 mm buried in a **dielectric half-space** with a relative permittivity of 6. The simulation uses an antenna similar to the **GSSI 1.5 GHz** antenna. - -For a B-scan, the antenna must be repositioned for each A-scan (trace). In this case, the B-scan covers a distance of 270 mm with traces every 5 mm, resulting in **54 separate model runs**. - -## Prerequisites -Before proceeding, make sure you've successfully run your [first gprMax simulation](quick-start). - -Download the required files [here](https://docs.gprmax.com/en/latest/examples_antennas.html#b-scan-with-a-bowtie-antenna-model) and save them to a folder named `b-scan-case`. - -## Understanding OpenMP vs MPI -How gprMax Actually Uses Them: - -MPI (Message Passing Interface) -In gprMax, MPI implements a task farm to distribute multiple independent simulations (like different A-scans in a B-scan) across multiple processes. - -Each MPI worker runs a complete, separate simulation -Task-level parallelism: 60 A-scans → 60 independent MPI processes -Can run on single machine with multiple cores OR multiple compute nodes -Example: B-scan with 200 A-scans distributed to 60 workers - -OpenMP -OpenMP parallelizes the FDTD solver computations within a single simulation using multiple threads on the same processor. - -Intra-simulation parallelism: Makes one simulation run faster -Uses shared memory threads on the same CPU/node -Parallelizes the computational loops of the FDTD method -Example: One A-scan using 4 threads runs ~3-4× faster - -## Sequential processing (using openMP) -Let’s start by running the 54 model sequentially. This means that it will perform the A-scan for the first step (model 1), then it will perform the A-scan for the second step (model 2), etc. - -the 54 model runs will be processed sequentially. This means that it will perform the A-scan for the first step (model 1), then it will perform the A-scan for the second step (model 2), etc. - -This is done by using this command: - -python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 -with -n meaning the number of runs. - -As each model is saved separately, the final result needs to be merged by doing: - -python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in -Which will merge all of the 54 runs into a single file. - -Here's the required script to run this example: - -```python -import inductiva - -# Instantiate machine group -cloud_machine = inductiva.resources.MachineGroup( - machine_type="c2d-highcpu-16", - provider="GCP", - spot=True) - -input_dir = "/Path/to/b-scan-case" - -# Initialize the Simulator -gprmax = inductiva.simulators.GprMax(version="3.1.7") - -commands_sequential = [ - "python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54", - "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" -] - -# Start sequential simulation -task_sequential = gprmax.run(\ - input_dir=input_dir, - commands=commands_sequential, - on=cloud_machine, - n_vcpus=16) - -# Wait for the simulations to finish -task_sequential.wait() -cloud_machine.terminate() -``` - -The simulation took approximately . Let's use MPI to make it faster. - -## MPI Processing -gprMax allows for MPI usage in their simulations. This means that each of the 54 runs can be a separate process. - -To do that we need a machine that has the amount of cpus that supports all of the runs. Then we need to wrap the python command into mpirun, as follows: - -mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn -The --mpi-no-spawn flag is preferred to be used as stated in their documentation. - -Here's how to do it using Inductiva: - -```python -import inductiva - -# Instantiate machine group -cloud_machine = inductiva.resources.MachineGroup( - machine_type="c2d-highcpu-112", - provider="GCP", - spot=True) - -input_dir = "/Path/to/b-scan-case" - -# Initialize the Simulator -gprmax = inductiva.simulators.GprMax(version="3.1.7", use_dev=True) - -commands_mpi = [ - "mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn", - "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" -] - -# Start MPI simulation -task_mpi = gprmax.run(\ - input_dir=input_dir, - commands=commands_mpi, - on=cloud_machine, - n_vcpus=112) - -# Wait for the simulations to finish -task_mpi.wait() -cloud_machine.terminate() -``` - -> ⚠️ **Note on vCPUs and Hyperthreading**: In most cloud environments (like Google Cloud), a vCPU corresponds to a thread, not a full physical core. So a `c2d-standard-8` machine has 8 vCPUs, which typically means 4 physical cores with hyperthreading enabled. - -## Results - - -## Key Takeaways - - -::docsbannersmall -:: diff --git a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md new file mode 100644 index 0000000..2b13aa8 --- /dev/null +++ b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md @@ -0,0 +1,130 @@ +--- +title: Scale gprMax with MPI +description: A step-by-step guide to running gprMax simulations with MPI +seo: + title: Scale gprMax simulations with MPI on Inductiva.AI + description: A step-by-step guide to running gprMax simulations with MPI +--- + +gprMax supports parallelism through **MPI** and **OpenMP**. For a deeper dive into how parallelism works in gprMax, refer to the [official documentation](https://docs.gprmax.com/en/latest/openmp_mpi.html). + +In this tutorial, you will learn how to configure and run gprMax simulations sequentially and using MPI. We will use the `B-scan with a bowtie antenna model` from the gprMax example cases as our demonstration. + +This example creates a B-scan using an antenna model. The setup includes a metal cylinder with a diameter of 20 mm buried in a dielectric half-space with a relative permittivity of 6. The simulation uses an antenna similar to the GSSI 1.5 GHz antenna. + +For a B-scan, the antenna must be repositioned for each A-scan (trace). In this case, the B-scan covers a distance of 270 mm with traces every 5 mm, resulting in **54 separate model runs**. + +## Prerequisites +Download the required files [here](https://docs.gprmax.com/en/latest/examples_antennas.html#b-scan-with-a-bowtie-antenna-model) and save them to a folder named `b-scan-case`. + +## Sequential Processing +First, let's run the 54 models **sequentially**. This means the simulation will process the A-scans one after another: model 1, then model 2, and so on. + +You can do this using the following command: + +``` +python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 +``` + +Here, `-n` specifies the number of runs. + +Each run produces a separate output file. To merge them into a single result file, run: + +``` +python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in +``` + +The required Python script to run this case sequentially on Inductiva is shown below: + +```python +import inductiva + +# Instantiate machine group +cloud_machine = inductiva.resources.MachineGroup( + machine_type="c2d-highcpu-16", + provider="GCP", + spot=True) + +input_dir = "/Path/to/b-scan-case" + +# Initialize the Simulator +gprmax = inductiva.simulators.GprMax(version="3.1.7") + +commands_sequential = [ + "python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54", + "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" +] + +# Start sequential simulation +task_sequential = gprmax.run(\ + input_dir=input_dir, + commands=commands_sequential, + on=cloud_machine, + n_vcpus=16) + +# Wait for the simulations to finish +task_sequential.wait() +cloud_machine.terminate() +``` + +Running these 54 simulations sequentially took approximately **hours and minutes**. + +Next, we will explore MPI-based parallel execution, which will significantly speed up this case. + +## MPI Processing +gprMax supports MPI, allowing each of the 54 runs to be executed **in parallel**. This requires a machine with enough vCPUs to support all the runs. Hence, we'll be running the case on a `c2d-highcpu-112`, which has 112 vCPUs, providing ample resources for all 54 simulations to run concurrently. + +> ⚠️ **Note on vCPUs and Hyperthreading**: In most cloud environments (e.g., Google Cloud), a vCPU represents a single thread rather than a full physical core. By default, Google Cloud VMs provide 2 vCPUs per physical core, so a `c2d-standard-112` machine with 112 vCPUs typically has 56 physical cores with hyperthreading enabled. + +Wrap the Python command with `mpirun` as follows: + +``` +mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn +``` + +- `-n 55` specifies the number of processes. +- `--mpi-no-spawn` is recommended according to the gprMax documentation to avoid MPI process spawning issues. +- +The `--mpi-no-spawn` flag is preferred to be used as stated in their documentation. + +Here’s the Python script to run the case with MPI: + +```python +import inductiva + +# Instantiate machine group +cloud_machine = inductiva.resources.MachineGroup( + machine_type="c2d-highcpu-112", + provider="GCP", + spot=True) + +input_dir = "/Path/to/b-scan-case" + +# Initialize the Simulator +gprmax = inductiva.simulators.GprMax(version="3.1.7", use_dev=True) + +commands_mpi = [ + "mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn", + "python -m tools.outputfiles_merge cylinder_Bscan_GSSI_1500.in" +] + +# Start MPI simulation +task_mpi = gprmax.run(\ + input_dir=input_dir, + commands=commands_mpi, + on=cloud_machine, + n_vcpus=112) + +# Wait for the simulations to finish +task_mpi.wait() +cloud_machine.terminate() +``` + +This MPI-based simulation significantly reduces the runtime compared to sequential execution, taking approximately **23 minutes**. + +## Results + + + +::docsbannersmall +:: From b4ebc26cb9822ea19c9e64128760b7effed471ad Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 14:53:49 +0000 Subject: [PATCH 4/9] update-index --- docs/14.gprmax/index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/14.gprmax/index.md b/docs/14.gprmax/index.md index c2be3dc..d95f80d 100644 --- a/docs/14.gprmax/index.md +++ b/docs/14.gprmax/index.md @@ -20,6 +20,9 @@ Step-by-step guides to help you learn how to run gprMax through the Inductiva AP - [Test Your Inductiva Setup](/guides/gprmax/tutorials/setup-test) - [Run Your First Simulation](/guides/gprmax/tutorials/quick-start) +* **Advanced Tutorials** + - [Scale gprMax with MPI](/guides/gprmax/tutorials/scaling-with-mpi) + ### Benchmarks A trusted guide to selecting the right simulation hardware for your needs. These benchmarks, conducted using the Inductiva platform, provide insight into how gprMax performs on different hardware configurations. From 57d5e2732eec4210253bb0c7e7c2d3bc3eef4ab3 Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 14:55:24 +0000 Subject: [PATCH 5/9] Update 2.scaling-with-mpi.md --- docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md index 2b13aa8..c98960d 100644 --- a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md +++ b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md @@ -3,7 +3,7 @@ title: Scale gprMax with MPI description: A step-by-step guide to running gprMax simulations with MPI seo: title: Scale gprMax simulations with MPI on Inductiva.AI - description: A step-by-step guide to running gprMax simulations with MPI + description: Step-by-step guide to running gprMax simulations with MPI on Inductiva.AI --- gprMax supports parallelism through **MPI** and **OpenMP**. For a deeper dive into how parallelism works in gprMax, refer to the [official documentation](https://docs.gprmax.com/en/latest/openmp_mpi.html). From c27753a434b6c84b949fe16d9189f4a7c60095af Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 14:58:28 +0000 Subject: [PATCH 6/9] Update 2.scaling-with-mpi.md --- docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md index c98960d..e74592e 100644 --- a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md +++ b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md @@ -82,10 +82,8 @@ Wrap the Python command with `mpirun` as follows: mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn ``` -- `-n 55` specifies the number of processes. -- `--mpi-no-spawn` is recommended according to the gprMax documentation to avoid MPI process spawning issues. -- -The `--mpi-no-spawn` flag is preferred to be used as stated in their documentation. +- `-n 55` specifies the number of processes +- `--mpi-no-spawn` is recommended according to the [gprMax documentation](https://docs.gprmax.com/en/latest/openmp_mpi.html#mpi) Here’s the Python script to run the case with MPI: From a7364bc89796e2666d43da3df616e3d92b29e4c0 Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 15:02:48 +0000 Subject: [PATCH 7/9] Update 2.scaling-with-mpi.md --- docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md index e74592e..db85c30 100644 --- a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md +++ b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md @@ -99,7 +99,7 @@ cloud_machine = inductiva.resources.MachineGroup( input_dir = "/Path/to/b-scan-case" # Initialize the Simulator -gprmax = inductiva.simulators.GprMax(version="3.1.7", use_dev=True) +gprmax = inductiva.simulators.GprMax(version="3.1.7") commands_mpi = [ "mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn", From e187c3e76edd8bf5b24b2e143dd10ad5cc07fe15 Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 15:37:27 +0000 Subject: [PATCH 8/9] Update 2.scaling-with-mpi.md --- docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md index db85c30..e2e032f 100644 --- a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md +++ b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md @@ -67,7 +67,7 @@ task_sequential.wait() cloud_machine.terminate() ``` -Running these 54 simulations sequentially took approximately **hours and minutes**. +Running these 54 simulations sequentially took approximately **1 hour and 55 minutes**. Next, we will explore MPI-based parallel execution, which will significantly speed up this case. @@ -82,7 +82,7 @@ Wrap the Python command with `mpirun` as follows: mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn ``` -- `-n 55` specifies the number of processes +- `-n 55` specifies the number of processes, which should be the number of runs -n 54 +1 - `--mpi-no-spawn` is recommended according to the [gprMax documentation](https://docs.gprmax.com/en/latest/openmp_mpi.html#mpi) Here’s the Python script to run the case with MPI: From 3de7d5ae8984d19dcc1dbe434c86306a2c9d2517 Mon Sep 17 00:00:00 2001 From: eunmoliveira Date: Thu, 18 Dec 2025 16:31:07 +0000 Subject: [PATCH 9/9] Update 2.scaling-with-mpi.md --- docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md index e2e032f..2936eb6 100644 --- a/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md +++ b/docs/14.gprmax/1.tutorials/2.scaling-with-mpi.md @@ -82,7 +82,7 @@ Wrap the Python command with `mpirun` as follows: mpirun -n 55 python -m gprMax cylinder_Bscan_GSSI_1500.in -n 54 --mpi-no-spawn ``` -- `-n 55` specifies the number of processes, which should be the number of runs -n 54 +1 +- `-n 55` specifies the number of processes, which should be one more than the number of runs (`-n 54 + 1`) to account for the master process - `--mpi-no-spawn` is recommended according to the [gprMax documentation](https://docs.gprmax.com/en/latest/openmp_mpi.html#mpi) Here’s the Python script to run the case with MPI: @@ -121,8 +121,14 @@ cloud_machine.terminate() This MPI-based simulation significantly reduces the runtime compared to sequential execution, taking approximately **23 minutes**. ## Results +The following table summarizes the performance and cost of sequential versus MPI-based execution for the `B-scan with a bowtie antenna model` case on Inductiva: +| Processing Type | Machine Type | Total Time | Estimated Cost (USD) | +|-----------------|-------------------|--------------|----------------------| +| Sequential | c2d-highcpu-16 | 1h, 55 min | 0.15 | +| MPI | c2d-highcpu-112 | 23 min | 0.21 | +Running the simulations on **Inductiva** using MPI-based parallel execution drastically reduces the runtime compared to sequential processing, from nearly **2 hours down to under 25 minutes**. Although the estimated cost for the larger machine is slightly higher, the time savings are significant, making MPI a highly efficient option for large-scale gprMax simulations. ::docsbannersmall ::