Getting Started¶
Directory Structure¶
The following files and sub-directories will be found:
COPYRIGHT - Please get familiar with the Copyright before using this code!
README.md - Explains how to obtain, install and update the code.
doc/ - Provides additional documentation, including this user guide.
f90/ - The code base, makefiles and configuration scripts.
Compiling ModEM¶
The build system for ModEM uses a ModEM configure script and the fmkmf.pl
Perl script:
configure script (
./f90/config/configure) - Callsfmkmf.plwith various argumentsfmkmf.pl- Called by Configure scripts and automatically generates a ModEM makefile.
Once you have run configure, you’ll be able to run make on the generated
Makefile.
In the f90 directory there are some prototype Makefiles which can be used
to compile ModEM without having to run the configure script; however, these
Makefiles only create the Matrix-Free version of ModEM and you may want to
compile the other two version SP/SP2. To do this you will need to run the
configure script, which is explained below.
ModEM Dependencies¶
ModEM requires two libraries, the BLAS Library and the LAPACK library and optionally the MPI library.
Often BLAS and LAPACK are already available on your system and are linked automatically, but occasionally you might need to install or link them yourself. For instructions on building ModEM dependencies see Installing ModEM Dependencies.
Configure Scripts¶
There are a number of configure scripts inside ./f90/CONFIG in the form of
Configure.***, Configure.SP.***, Configure.3D_MT.**, etc. These
configure files are considered deprecated, and the configure script inside
f90/CONFIG should be used instead; however, the deprecated configure
scripts are left for backwards compatibility.
Creating Makefiles from configure¶
Note
By default, configure, with no optional arguments will generate an MPI
Makefile with the SP2 forward solver.
To create a Makefile, run the configure script found in the f90 with
arguments that match your system and the version of ModEM you want to use.
Currently, ModEM has three different forwards ‘flavors’:
MF - Matrix Free - Original/classic ModEM
SP - Hao’s Sparse Matrix
- SP2 - (DEFAULT) - Hao’s Second Sparse Matrix - Fastest and has Hao’s
fine-grained capability
$ cd f90/
$ # By default ./CONFIG/configure creates a SP2 Makefile with MPI
$ ./CONFIG/configure Makefile gfortran
The Configure scripts has the following usage:
$ Usage: ./CONFIG/Configure [-h] [-u] [-g release|debug] [-m mpi|serial] [-l solver] [-f] makefile-name compiler
-h Display full help message
-u Display this usage message
-g <release | debug> Specify whether to build with debug symbols or not
release - Default - Create Makefile with full optimizations (i.e. -O3)
debug - Create Makefile with debug symbols (i.e. -g) and no optimizations
-m <mpi* | serial> Specify MPI or serial
mpi - Default - Builds with MPI
serial - Builds Serially
-l <MF | SP | SP2> Specify solver
MF - Builds with MF
SP - Builds with SP
SP2 - Default - Builds with SP2
-f Build with Fined-Grained -DFG on SP2
Only able to build with SP2
-s Build spherical version of ModEM
Running configure will create a Makefile that you specify in the first
argument. In the above case the Makefile will be named Makefile. We can
then call make on that Makefile
$ make
Examples Using Configure¶
A few examples using Configure
$ ./CONFIG/configure Makefile gfortran
$ # Generates a Makefile with GFortran options using MPI
$ ./CONFIG/configure -d debug Makefile ifort
$ # Generates an MPI Makefile with ifort debugging options
$ ./CONFIG/configure -m serial -l MF Makefile gfortran
$ # Generates a serial Makefile with GFortran with the MF solver
$ FC=ftn LDFLAGS=-L/home/username/install/lib ./CONFIG/configure Makefile gfortran
$ # Generates an SP2, MPI capabile makefile, adding LDFLAGS to the link step and
$ # specifies the compiler to be `ftn`.
$ FFLAGS='-mSSE2' ./CONFIG/configure Makefile ifort
$ # Create a SP2, MPI capabile makefile, with ifort/intel compiler options and add
$ # the '-mSSE2' to all compiling steps.
$ LDFLAGS="-L/path/to/install/lib/" ./CONFIG/configure Makefile gfortran
$ # Generates a Makefile with GFortran options using MPI and passes
$ # the location of /path/to/install/lib to the linker step
Configuring on Cray Systems¶
If you are running on a Cray system, you will need to use Cray’s Fortran
compiler wrapper: ftn. You can easily specify the name of the compiler
by setting the FC environment variable:
$ FC=ftn ./CONFIG/configure Makefile gfortran
$ # Or for intel:
$ FC=ftn ./CONFIG/configure Makefile ifort
Ensure BLAS and LAPACK are linked¶
If you get errors that you are not able to find -lblas or -llapack, but
have them installed, you can use the LDFLAGS environment variable to tell
the linker where to find them. You can specify this when you run configure:
$ LDFLAGS="-L/path/to/install/lib/" ./CONFIG/configure Makefile gfortran
If you have already created your makefile, you can also add the -L
specification to the LIBS_PATH of the Macro-Def section of your Makefile:
# ------------------Macro-Defs---------------------
include Makefile.local
OBJDIR = ./objs/3D_MT/csemBuild
F90 = mpifort
FFLAGS = -cpp -DMPI -DCSEM_Dipole1D -O3 -ffree-line-length-none -dI -fallow-argument-mismatch
MPIFLAGS = -cpp -DMPI -DCSEM_Dipole1D
MODULE = -J $(OBJDIR)
LIBS_PATH = -L/path/to/install/lib
LIBS = -lblas -llapack
Compiling¶
Once you have generated your own makefile, or decided to use one of the defaults, you can compile ModEM by renaming that makefile to Makefile and then run make
$ cp Makefile.3D.MF.gnu Makefile
$ make clean # Not necessary from a fresh clone
$ make
Compiling with MPI¶
If you have MPI installed, and already have a serial makefile generated you can easily compile the MPI version of ModEM by altering the makefile. This is sometimes easier then creating a new makefile from the configuration scripts.
To compile an MPI version, change the F90 variable in your makefile to be
an MPI compiler (e.g. mpifort) and add -DMPI to the MPIFLAGGS
variable:
F90 = mpifort
MPIFLAGS = -DMPI ... omitting other flags
However, you can also generate an MPI makefile by running the configuration scripts and passing it MPI as the type.
Important
When running ModEM with MPI you must use at least 2 tasks and a max of (2 x nTransmitters) + 1 tasks (except for the SP2 version compiled with -DFG).
Running ModEM: The basics¶
Running the compiled program with no command line arguments will print a brief summary of usage
Output information to files, and progress report to screen (default).
Usage: Mod3DMT -[job] [args]
[READ_WRITE]
-R rFile_Model rFile_Data [wFile_Model wFile_Data]
Reads your input files and checks them for validity;
optionally also writes them out
[FORWARD]
-F rFile_Model rFile_Data wFile_Data [wFile_EMsoln rFile_fwdCtrl]
Calculates the predicted data and saves the EM solution
[COMPUTE_J]
-J rFile_Model rFile_Data wFile_Sens [rFile_fwdCtrl]
Calculates and saves the full J(acobian)
[MULT_BY_J]
-M rFile_Model rFile_dModel rFile_Data wFile_Data [rFile_fwdCtrl]
Multiplies a model by J to create a data vector
[MULT_BY_J_T]
-T rFile_Model rFile_Data wFile_dModel [rFile_fwdCtrl]
Multiplies a data vector by J^T to create a model
[INVERSE]
-I NLCG rFile_Model rFile_Data [lambda eps]
Here, lambda = the initial damping parameter for inversion
eps = misfit tolerance for the forward solver
OR
-I NLCG rFile_Model rFile_Data [rFile_invCtrl rFile_fwdCtrl]
Optionally, may also supply
the model covariance configuration file [rFile_Cov]
the starting model parameter perturbation [rFile_dModel]
Runs an inverse search to yield an inverse model at every iteration
[TEST_COV]
-C rFile_Model wFile_Model [rFile_Cov]
Applies the model covariance to produce a smooth model output
[TEST_ADJ]
-A J rFile_Model rFile_dModel rFile_Data [wFile_Model wFile_Data]
Tests the equality d^T J m = m^T J^T d for any model and data.
Optionally, outputs J m and J^T d.
[TEST_SENS]
-S rFile_Model rFile_dModel rFile_Data wFile_Data [wFile_Sens]
Multiplies by the full Jacobian, row by row, to get d = J m.
Compare to the output of [MULT_BY_J] to test [COMPUTE_J]
Optional final argument -v [debug|full|regular|compact|result|none]
indicates the desired level of output to screen and to files.
The -F [FORWARD] and -I [INVERSE] options will suffice for simple applications.
For some of the more advanced applications discussed below the -C [TEST_COV] option is
also needed. The -R [READ_WRITE] option can be useful for testing whether your input
files are in the correct format. The -v option controls the level of program output;
the default is “regular”; if you want to reduce outputs (“none” is not recommended!) you
can experiment with other output levels; “full ” and “debug” would be primarily useful for
developers. All of the other options (-J, -M, etc.) are primarily useful for
development, testing, and some specialized applications that are beyond the scope of this
basic documentation.
Sub-directory examples/ contains some sample input files with instructions for simple
cases. These should be sufficient to test your installation, and also will provide a
template for your own initial use. The doc/ sub-directory contains some further
information on the ModEM system, beyond the summary of usage provided here.
All of the various options have a required set of arguments, which define input and output
file names (rFile, and wFile in the usage summary, respectively). There are also
optional arguments, mostly also specifying additional input or output file names. In all
cases the order of arguments must be exactly as indicated in the “Usage” block, so to give
an optional argument at the end of the list, all previous optional arguments must also be
provided. Thus, for example, with the -F option, if you want to specify the input
rFile_fwdCtrl file, you must also specify the output wFile_EMsoln file, even if
you do not specifically want the full set of output EM fields, which this option will
result in. Before providing a more detailed discussion of the various options, we consider
file formats.
Using Docker to Compile and Run ModEM¶
Note
For more information on Docker, please see: https://www.docker.com/resources/what-container/.
For convenience, a Dockerfile has been provided which will automatically build ModEM once it is built. Once built, you can use the docker container to run ModEM. To run the ModEM docker container, first ensure you have docker installed and running (Either have the docker daemon docker running, or Docker Desktop Running.
The Dockerfile builds an Ubuntu instance with GFortran, MPI, and all the other tools needed to compile and run ModEM and it will compile MF, SP, and SP2 versions of ModEM automatically.
Building¶
Warning
Before running docker build or docker run the docker daemon
or Docker Desktop must be running!
After you install Docker, and have either the docker deamon running (linux) or
docker desktop running (Mac/Windows) you can build the docker container using
the Dockerfile. Inside the ModEM directory (where the Dockerfile
resides), run the following:
$ cd ModEM
$ docker build . -t modem:latest
After running the above command Docker will create an image that is taged with:
modem:latest which can you run; it will have all necessary libraries and
compilers to compile and run ModEM.
As well, the Dockerfile will copy the ModEM code that it is in and place it into /home/modem/ModEM in the Docker container and will build MF, SP and SP2 executables.
Note
Building the ModEM Dockerfile the first time takes 2-4 minutes. After building once, Docker will cache the installed programs and later builds will take substantially less time.
Running ModEM in Docker¶
Now that we have built the docker container above, we can use docker run to
run the container and mount our local code:
$ docker run --mount=type=bind,source=/absolute/path/to/ModEM,target=/home/modem/ModEM -it modem:latest
Normally, when running a docker container, the data created inside the container will be deleted when the container terminates. To prevent this, we can use a mount.
Mounting will allow your local ModEM code directory to be mounted into the docker container. That way any change you make in one will be reflected on the other.
After you terminate that container, and wish to start it again, you will need to specify your run command with the same arguments as above to set the same mount.
The docker run command will run the image modem:latest and create a
container for us to use The -it argument will tell Docker to start an
interactive tty session and will drop you inside a bash shell inside the
running container.
Now, inside the docker container, we can move into ~/ModEM/f90 where we will
see three compiled ModEM executables:
Mod3DMT_MF- matrix free versionMod3DMT_SP- SP versionMod3DMT_SP2- SP2 version
You can use these executables to run a ModEM example (which you will need to mount into the Dockerfile yourself, see Specifying mounts points). Or, if you wish, you an compile your own executable:
$ cd ~/ModEM/f90
$
$ # Compile with MPI, SP2 solver:
$ ./CONFIG/configure Makefile gfortran
$ make
$
$ # or compile serial, SP2 solver
$ ./CONFIG/configure -m serial Makefile gfortran
$ make clean
$ make
$
$ # Run ModEM serially or with MPI:
$ mpiexec -n 2 ./Mod3DMT ...
$ # Or if you compiled serial:
$ ./Mod3DMT ...
You can terminate this docker session by logging out by typing exit or you
can use Ctrl-D.
Important
Again, if you want to re-run docker and reuse the files/folders/data you created before you will need to specify the volume that you used before
$ docker run --mount=type=bind,source=/absolute/path/to/ModEM,target=/home/modem/ModEM -it modem:latest
Warning
f you want to save data you will need to specify additional volumes or mounts. See Specifying mounts points.
For more information on persistent data inside a container see:
https://docs.docker.com/get-started/docker-concepts/running-containers/persisting-container-data/
Specifying mounts points¶
Note
For more information on Docker mounts see: https://docs.docker.com/engine/storage/bind-mounts/.
You may want to add additional mounts in your docker container. For example, you might want to include the ModEM-Examples directory:
$ docker run --mount=type=bind,source=/absolute/path/to/ModEM,target=/home/modem/ModEM \
--mount=type=bind,source=/absolute/path/to/ModEM-Examples,target=/home/modem/ModEM-Examples \
-it modem
Important
Again, each time you run your modem container, you will need to specify volume and mount points.