├── data └── .gitignore ├── docs ├── _static │ └── .gitignore ├── analysis │ ├── analysis.rst │ ├── pythonanalysis.rst │ └── matlabanalysis.rst ├── input │ ├── python │ │ ├── block.rst │ │ ├── domain.rst │ │ ├── fields.rst │ │ ├── front.rst │ │ ├── output.rst │ │ ├── problem.rst │ │ ├── material.rst │ │ ├── interface.rst │ │ ├── slipweak.rst │ │ ├── friction.rst │ │ ├── stz.rst │ │ ├── surface.rst │ │ └── python.rst │ ├── text │ │ ├── operator.rst │ │ ├── cartesian.rst │ │ ├── problem.rst │ │ ├── text.rst │ │ ├── slipweak.rst │ │ ├── stz.rst │ │ ├── interface.rst │ │ ├── domain.rst │ │ ├── frontlist.rst │ │ ├── fields.rst │ │ ├── block.rst │ │ └── friction.rst │ └── input.rst ├── examples │ ├── examples.rst │ ├── test2d.tex │ ├── input_example.tex │ ├── tpv4.tex │ ├── input_example.rst │ ├── tpv5.tex │ ├── tpv5.rst │ ├── tpv4.rst │ └── test2d.rst ├── index.rst ├── installation.rst ├── make.bat └── Makefile ├── .gitignore ├── src ├── utilities.h ├── readinput.hpp ├── frontlist.hpp ├── outputlist.hpp ├── rk.hpp ├── problem.hpp ├── surface.hpp ├── load.hpp ├── pert.hpp ├── fd.hpp ├── front.hpp ├── material.hpp ├── cartesian.hpp ├── slipweak.hpp ├── coord.hpp ├── swparam.hpp ├── load.cpp ├── outputunit.hpp ├── stz.hpp ├── domain.hpp ├── stzparam.hpp ├── boundary.hpp ├── main.cpp ├── fields.hpp ├── swparam.cpp ├── friction.hpp ├── interface.hpp ├── readinput.cpp ├── stzparam.cpp ├── frontlist.cpp ├── coord.cpp ├── Makefile ├── material.cpp ├── outputlist.cpp ├── pert.cpp ├── block.hpp ├── rk.cpp ├── utilities.cpp ├── problem.cpp ├── surface.cpp └── cartesian.cpp ├── python ├── setup.py ├── python_example.py └── fdfault │ ├── analysis │ ├── __init__.py │ ├── front.py │ └── output.py │ ├── __init__.py │ └── front.py ├── matlab ├── matlab_example.m ├── load_front.m └── load_output.m ├── LICENSE ├── problems ├── tpv4.in ├── test2d.in ├── input_example.py └── tpv5.py └── README /data/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore all files in data directory as they are large, predominantly binary files 2 | * 3 | # except .gitignore, which is needed as a placeholder to add keep this directory in place 4 | !.gitignore -------------------------------------------------------------------------------- /docs/_static/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore all files in directory, which will be automatically generated 2 | * 3 | # except .gitignore, which is needed as a placeholder to add keep this directory in place 4 | !.gitignore -------------------------------------------------------------------------------- /docs/analysis/analysis.rst: -------------------------------------------------------------------------------- 1 | .. _analysis: 2 | 3 | ********************************** 4 | Analyzing Simulation Results 5 | ********************************** 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | pythonanalysis 11 | matlabanalysis -------------------------------------------------------------------------------- /docs/input/python/block.rst: -------------------------------------------------------------------------------- 1 | .. _block: 2 | 3 | ********************************** 4 | The ``block`` Class 5 | ********************************** 6 | 7 | .. automodule:: fdfault.block 8 | :noindex: 9 | 10 | .. autoclass:: fdfault.block 11 | :members: 12 | 13 | .. automethod:: __init__ -------------------------------------------------------------------------------- /docs/input/python/domain.rst: -------------------------------------------------------------------------------- 1 | .. _domain: 2 | 3 | ********************************** 4 | The ``domain`` Class 5 | ********************************** 6 | 7 | .. automodule:: fdfault.domain 8 | :noindex: 9 | 10 | .. autoclass:: fdfault.domain 11 | :members: 12 | 13 | .. automethod:: __init__ -------------------------------------------------------------------------------- /docs/input/python/fields.rst: -------------------------------------------------------------------------------- 1 | .. _fields: 2 | 3 | ********************************** 4 | The ``fields`` Class 5 | ********************************** 6 | 7 | .. automodule:: fdfault.fields 8 | :noindex: 9 | 10 | .. autoclass:: fdfault.fields 11 | :members: 12 | 13 | .. automethod:: __init__ -------------------------------------------------------------------------------- /docs/input/python/front.rst: -------------------------------------------------------------------------------- 1 | .. _front: 2 | 3 | ********************************** 4 | The ``front`` Class 5 | ********************************** 6 | 7 | .. automodule:: fdfault.front 8 | :noindex: 9 | 10 | .. autoclass:: fdfault.front 11 | :members: 12 | 13 | .. automethod:: __init__ 14 | -------------------------------------------------------------------------------- /docs/input/python/output.rst: -------------------------------------------------------------------------------- 1 | .. _output: 2 | 3 | ********************************** 4 | The ``output`` Class 5 | ********************************** 6 | 7 | .. automodule:: fdfault.output 8 | :noindex: 9 | 10 | .. autoclass:: fdfault.output 11 | :members: 12 | 13 | .. automethod:: __init__ 14 | -------------------------------------------------------------------------------- /docs/input/python/problem.rst: -------------------------------------------------------------------------------- 1 | .. _problem: 2 | 3 | ********************************** 4 | The ``problem`` Class 5 | ********************************** 6 | 7 | .. automodule:: fdfault.problem 8 | :noindex: 9 | 10 | .. autoclass:: fdfault.problem 11 | :members: 12 | 13 | .. automethod:: __init__ 14 | -------------------------------------------------------------------------------- /docs/input/python/material.rst: -------------------------------------------------------------------------------- 1 | .. _material: 2 | 3 | ********************************** 4 | The ``material`` Class 5 | ********************************** 6 | 7 | .. automodule:: fdfault.material 8 | :noindex: 9 | 10 | .. autoclass:: fdfault.material 11 | :members: 12 | 13 | .. automethod:: __init__ 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.dat 2 | *.o 3 | *.pyc 4 | *.load 5 | *.mat 6 | *.sw 7 | *.stz 8 | *.surf 9 | *.csv 10 | *.png 11 | *.pdf 12 | *.aux 13 | *.log 14 | *~ 15 | /problems/*.in 16 | !/problems/test2d.in 17 | /problems/*.py 18 | !/problems/input_example.py 19 | /problems/*.tar.gz 20 | /problems/ 21 | /fdfault 22 | .DS_Store 23 | /docs/_build/ -------------------------------------------------------------------------------- /docs/input/python/interface.rst: -------------------------------------------------------------------------------- 1 | .. _interface: 2 | 3 | ********************************** 4 | The ``interface`` Class 5 | ********************************** 6 | 7 | .. automodule:: fdfault.interface 8 | :noindex: 9 | 10 | .. autoclass:: fdfault.interface 11 | :members: 12 | 13 | .. automethod:: fdfault.interface.__init__ 14 | -------------------------------------------------------------------------------- /docs/examples/examples.rst: -------------------------------------------------------------------------------- 1 | .. _examples: 2 | 3 | ********************************** 4 | Included Example Problems 5 | ********************************** 6 | 7 | 2D problems: 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | test2d 13 | input_example 14 | 15 | 3D Problems: 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | 20 | 21 | tpv4 22 | tpv5 -------------------------------------------------------------------------------- /src/utilities.h: -------------------------------------------------------------------------------- 1 | #ifndef _utilities_h 2 | #define _utilities_h 3 | 4 | #include "domain.hpp" 5 | #include 6 | 7 | char get_endian(); 8 | 9 | MPI_Comm create_comm(const bool no_data); 10 | 11 | double solve_newton(const double xmin, const double xmax, double* params, double (*f)(const double, double*), double (*df)(const double, double*)); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/readinput.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROBLEMHEADERDEF 2 | #define PROBLEMHEADERDEF 3 | 4 | #include 5 | #include "rk.hpp" 6 | #include 7 | 8 | class problem 9 | { 10 | public: 11 | problem(const std::string filename); 12 | int nt; 13 | rk_type rk; 14 | private: 15 | std::map readinput_problem(const std::string file); 16 | }; 17 | 18 | #endif -------------------------------------------------------------------------------- /python/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup(name='fdfault', 4 | version='1.0', 5 | description='Tools made to go with fdfault rupture code', 6 | url='https://github.com/egdaub/fdfault', 7 | author='Eric Daub', 8 | author_email='egdaub@memphis.edu', 9 | packages=['fdfault', 'fdfault.analysis'], 10 | install_requires=['numpy']) 11 | -------------------------------------------------------------------------------- /src/frontlist.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FRONTLISTCLASSHEADERDEF 2 | #define FRONTLISTCLASSHEADERDEF 3 | 4 | #include 5 | #include "front.hpp" 6 | #include "domain.hpp" 7 | 8 | class frontlist 9 | { 10 | public: 11 | frontlist(const char* filename, const std::string probname, const std::string datadir, const domain& d); 12 | ~frontlist(); 13 | void set_front(const double t, const domain& d); 14 | void write_list(const domain& d); 15 | private: 16 | front* rootunit; 17 | }; 18 | 19 | #endif -------------------------------------------------------------------------------- /src/outputlist.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OUTPUTLISTCLASSHEADERDEF 2 | #define OUTPUTLISTCLASSHEADERDEF 3 | 4 | #include 5 | #include "outputunit.hpp" 6 | 7 | class outputlist 8 | { 9 | public: 10 | outputlist(const char* filename, const std::string probname, const std::string datadir, const int nt, const domain& d); 11 | ~outputlist(); 12 | void write_list(const int tstep, const double dt, const domain& d); 13 | void close_list(); 14 | private: 15 | outputunit* rootunit; 16 | }; 17 | 18 | #endif -------------------------------------------------------------------------------- /docs/input/text/operator.rst: -------------------------------------------------------------------------------- 1 | .. _operator: 2 | 3 | ********************************** 4 | Operator Input 5 | ********************************** 6 | 7 | Optionally, the code uses artificial dissipation to damp out spurious oscillations arising from the finite difference method. To use artificial dissipation, include a ``[fdfault.operator]`` section with a single floating point number to designate the the artificial dissipation coefficient. Correct selection of the dissipation coefficient is up to the user, and too large a value can result in numerical instabilities. -------------------------------------------------------------------------------- /src/rk.hpp: -------------------------------------------------------------------------------- 1 | #ifndef RK_TYPECLASSHEADERDEF 2 | #define RK_TYPECLASSHEADERDEF 3 | 4 | class rk_type 5 | { 6 | public: 7 | rk_type(const int order); 8 | // rk_type(const rk_type& otherrk); 9 | ~rk_type(); 10 | // rk_type& operator=(const rk_type& assignrk); 11 | int get_rkorder() const; 12 | int get_nstages() const; 13 | double get_A(const int stage) const; 14 | double get_B(const int stage) const; 15 | double get_C(const int stage) const; 16 | private: 17 | int rkorder; 18 | int nstages; 19 | double* A; 20 | double* B; 21 | double* C; 22 | }; 23 | 24 | #endif -------------------------------------------------------------------------------- /matlab/matlab_example.m: -------------------------------------------------------------------------------- 1 | % example using load_output function in MATLAB 2 | 3 | % required arguments are problem name and output unit name 4 | % data directory is optional, if no argument provided assumes it is the current working directory 5 | 6 | vybody = load_output('hpctest','vybody'); 7 | 8 | % loads data structure containing information 9 | 10 | vybody 11 | 12 | % because of differences in how MATLAB and C++ order arrays, field arrays are indexed by (z,y,x,t) 13 | % any singleton dimensions are removed 14 | 15 | % plot velocity 16 | 17 | pcolor(vybody.x, vybody.y, vybody.vy(:,:,4)); 18 | shading flat; 19 | axis image; 20 | colorbar; 21 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. fdfault_docs documentation master file, created by 2 | sphinx-quickstart on Thu Nov 17 14:51:08 2016. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to the user manual for ``fdfault`` 7 | ========================================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 3 13 | 14 | intro 15 | installation 16 | input/input 17 | examples/examples 18 | analysis/analysis 19 | 20 | 21 | Indices and tables 22 | ================== 23 | 24 | * :ref:`genindex` 25 | * :ref:`modindex` 26 | * :ref:`search` 27 | 28 | -------------------------------------------------------------------------------- /src/problem.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROBLEMHEADERDEF 2 | #define PROBLEMHEADERDEF 3 | 4 | #include 5 | #include "domain.hpp" 6 | #include "frontlist.hpp" 7 | #include "outputlist.hpp" 8 | #include "rk.hpp" 9 | 10 | class problem 11 | { 12 | public: 13 | problem(const char* filename); 14 | ~problem(); 15 | int get_nt() const; 16 | void solve(); 17 | private: 18 | std::string name; 19 | std::string datadir; 20 | int nt; 21 | int ninfo; 22 | double dt; 23 | double ttot; 24 | double cfl; 25 | domain* d; 26 | rk_type* rk; 27 | outputlist* out; 28 | frontlist* front; 29 | void set_time_step(); 30 | }; 31 | 32 | #endif -------------------------------------------------------------------------------- /src/surface.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SURFACECLASSHEADERDEF 2 | #define SURFACECLASSHEADERDEF 3 | 4 | #include 5 | #include "coord.hpp" 6 | 7 | class surface 8 | { 9 | public: 10 | surface(const int ndim_in, const coord c, const int direction, const std::string filename); 11 | surface(const int ndim_in, const coord c, const int direction, const double x_in[3], const double l_in[2]); 12 | ~surface(); 13 | int get_n(const int index) const; 14 | double get_x(const int index, const int i, const int j) const; 15 | bool has_same_edge(const int edge1, const int edge2, const surface& othersurf) const; 16 | private: 17 | int ndim; 18 | int n[2]; 19 | double* x; 20 | }; 21 | 22 | #endif -------------------------------------------------------------------------------- /docs/input/python/slipweak.rst: -------------------------------------------------------------------------------- 1 | .. _pythonslipweak: 2 | 3 | ********************************** 4 | The ``slipweak`` Class 5 | ********************************** 6 | 7 | The main class used for creating slip weakening interfaces is the ``slipweak`` class. 8 | 9 | .. autoclass:: fdfault.slipweak 10 | :members: 11 | :inherited-members: 12 | 13 | .. automethod:: fdfault.interface.slipweak.__init__ 14 | 15 | .. autoclass:: fdfault.swparam 16 | :members: 17 | :inherited-members: 18 | 19 | .. automethod:: fdfault.swparam.__init__ 20 | 21 | .. autoclass:: fdfault.swparamfile 22 | :members: 23 | :inherited-members: 24 | 25 | .. automethod:: fdfault.swparamfile.__init__ -------------------------------------------------------------------------------- /docs/input/python/friction.rst: -------------------------------------------------------------------------------- 1 | .. _friction: 2 | 3 | ********************************** 4 | The ``friction`` Class 5 | ********************************** 6 | 7 | The ``friction`` class is the parent class of all frictional interfaces. Information on setting load perturbations is provided here, as this is common to all friction laws. 8 | 9 | .. autoclass:: fdfault.friction 10 | :members: 11 | :inherited-members: 12 | 13 | .. automethod:: fdfault.friction.__init__ 14 | 15 | .. autoclass:: fdfault.load 16 | :members: 17 | :inherited-members: 18 | 19 | .. automethod:: fdfault.load.__init__ 20 | 21 | .. autoclass:: fdfault.loadfile 22 | :members: 23 | :inherited-members: 24 | 25 | .. automethod:: fdfault.loadfile.__init__ -------------------------------------------------------------------------------- /docs/input/text/cartesian.rst: -------------------------------------------------------------------------------- 1 | .. _cartesian: 2 | 3 | ********************************** 4 | Cartesian Input 5 | ********************************** 6 | 7 | The code automatically handles domain decomposition into a Cartesian grid based on the dimensionality of the problem and the number of processors specified when running the executable. However, you may also specify the number of processes manually by including ``[fdfault.cartesian]`` in the input file. This section must contain a list of three integers specifying the desired number of processes in each of the three spatial dimensions (if a 2D problem is run, the number of processes in the :math:`{z}` direction is automatically set to one). It is up to the user to ensure that the numbers set here match the total number of processes set when launching the executable. 8 | -------------------------------------------------------------------------------- /src/load.hpp: -------------------------------------------------------------------------------- 1 | #ifndef LOADCLASSHEADERDEF 2 | #define LOADCLASSHEADERDEF 3 | 4 | #include 5 | #include "pert.hpp" 6 | 7 | class load: public pert 8 | { 9 | public: 10 | load(const std::string type_in, const double t0_in, const double x0_in, const double dx_in, 11 | const double y0_in, const double dy_in, const int n[2], const int xm[2], const int xm_loc[2], 12 | const double x[2], const double l[2], const double sn_in, const double s2_in, 13 | const double s3_in); 14 | double get_sn(const int i, const int j, const double t) const; 15 | double get_s2(const int i, const int j, const double t) const; 16 | double get_s3(const int i, const int j, const double t) const; 17 | protected: 18 | double sn; 19 | double s2; 20 | double s3; 21 | }; 22 | 23 | #endif -------------------------------------------------------------------------------- /src/pert.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PERTCLASSHEADERDEF 2 | #define PERTCLASSHEADERDEF 3 | 4 | #include 5 | 6 | class pert 7 | { 8 | public: 9 | pert(const std::string type_in, const double t0_in, const double x0_in, const double dx_in, 10 | const double y0_in, const double dy_in, const int n[2], const int xm[2], const int xm_loc[2], 11 | const double x[2], const double l[2]); 12 | protected: 13 | int type; 14 | int direction; 15 | int mlb[3]; 16 | double t0; 17 | double x0; 18 | double y0; 19 | double dx; 20 | double dy; 21 | double a; 22 | double b; 23 | double c; 24 | double d; 25 | double xyfunc(const int i, const int j) const; 26 | double tfunc(const double t) const; 27 | double x(const int i) const; 28 | double y(const int j) const; 29 | }; 30 | 31 | #endif -------------------------------------------------------------------------------- /python/python_example.py: -------------------------------------------------------------------------------- 1 | # example using output class in python 2 | 3 | # required arguments are problem name and output unit name 4 | # data directory is optional, if no argument provided assumes it is the current working directory 5 | 6 | from __future__ import print_function 7 | import numpy as np 8 | import matplotlib.pyplot as plt 9 | from fdfault.analysis import output 10 | 11 | vybody = output('testprob', 'vybody') 12 | 13 | # load data structure containing information 14 | 15 | vybody.load() 16 | 17 | # field arrays are indexed by (t,x,y,z), with any singleton dimensions removed 18 | # print statement prints basic information 19 | 20 | print(vybody) 21 | 22 | # can also access fields directly 23 | 24 | print(vybody.vy) 25 | 26 | # plot velocity 27 | 28 | plt.figure() 29 | plt.pcolor(vybody.x, vybody.y, vybody.vy[0,:,:]) 30 | plt.colorbar() 31 | plt.show() 32 | -------------------------------------------------------------------------------- /src/fd.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FD_TYPECLASSHEADERDEF 2 | #define FD_TYPECLASSHEADERDEF 3 | 4 | #include "coord.hpp" 5 | 6 | class fd_type 7 | { 8 | friend class block; 9 | public: 10 | fd_type(const fd_type& copyfd_type); 11 | fd_type(int order); 12 | ~fd_type(); 13 | fd_type& operator=(const fd_type& assignfd_type); 14 | int get_sbporder() const; 15 | double get_h0() const; 16 | double cons_s(double**** f, double**** m, double*** jac, const int i, const int j, const int k, const coord c, const int dir, const int index, const int ndim, const int mode) const; 17 | double nonc(double*** f, const int i, const int j, const int k, const coord c, const int dir) const; 18 | double diss(double*** f, const int i, const int j, const int k, const coord c, const int dir) const; 19 | private: 20 | double h0; 21 | double** fdcoeff; 22 | double** disscoeff; 23 | int sbporder; 24 | }; 25 | 26 | #endif -------------------------------------------------------------------------------- /docs/input/python/stz.rst: -------------------------------------------------------------------------------- 1 | .. _stz: 2 | 3 | ********************************** 4 | The ``stz`` Class 5 | ********************************** 6 | 7 | The main class used for creating STZ interfaces is the ``stz`` class. This also includes setting the STZ parameters through perturbations and files, as well as setting the initial state variable. 8 | 9 | .. autoclass:: fdfault.stz 10 | :members: 11 | :inherited-members: 12 | 13 | .. automethod:: fdfault.interface.stz.__init__ 14 | 15 | .. autoclass:: fdfault.stzparam 16 | :members: 17 | :inherited-members: 18 | 19 | .. automethod:: fdfault.stzparam.__init__ 20 | 21 | .. autoclass:: fdfault.stzparamfile 22 | :members: 23 | :inherited-members: 24 | 25 | .. automethod:: fdfault.stzparamfile.__init__ 26 | 27 | .. autoclass:: fdfault.statefile 28 | :members: 29 | 30 | .. automethod:: fdfault.statefile.__init__ -------------------------------------------------------------------------------- /src/front.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FRONTCLASSHEADERDEF 2 | #define FRONTCLASSHEADERDEF 3 | 4 | #include 5 | #include "domain.hpp" 6 | #include 7 | 8 | class front 9 | { 10 | public: 11 | front(const std::string probname_in, const std::string datadir_in, 12 | std::string field_in, const double value_in, const int niface_in, const domain& d); 13 | ~front(); 14 | front* get_next_unit() const; 15 | void set_next_unit(front* nextunit); 16 | void set_front(const double t, const domain& d); 17 | void write_front(const domain& d) const; 18 | private: 19 | std::string probname; 20 | std::string datadir; 21 | bool no_data; 22 | int ndim; 23 | int xm[3]; 24 | int xm_loc[3]; 25 | int xp[3]; 26 | int xp_loc[3]; 27 | int nx[2]; 28 | int nx_loc[2]; 29 | int field; 30 | int direction; 31 | int niface; 32 | double value; 33 | double* tvals; 34 | front* next; 35 | }; 36 | 37 | #endif -------------------------------------------------------------------------------- /src/material.hpp: -------------------------------------------------------------------------------- 1 | #ifndef MATERIALCLASSHEADERDEF 2 | #define MATERIALCLASSHEADERDEF 3 | 4 | class material 5 | { 6 | public: 7 | material(); 8 | void set_rho(const double newrho); 9 | void set_lambda(const double newlambda); 10 | void set_g(const double newg); 11 | void set_mu(const double newmu); 12 | void set_beta(const double newbeta); 13 | void set_eta(const double neweta); 14 | void set_c(const double newc); 15 | double get_rho() const; 16 | double get_lambda() const; 17 | double get_g() const; 18 | double get_mu() const; 19 | double get_beta() const; 20 | double get_eta() const; 21 | double get_c() const; 22 | double get_cs() const; 23 | double get_cp() const; 24 | double get_zs() const; 25 | double get_zp() const; 26 | private: 27 | double lambda; 28 | double g; 29 | double rho; 30 | double mu; 31 | double beta; 32 | double eta; 33 | double c; 34 | }; 35 | 36 | #endif -------------------------------------------------------------------------------- /docs/input/python/surface.rst: -------------------------------------------------------------------------------- 1 | .. _surface: 2 | 3 | *************************************** 4 | The ``surface`` and ``curve`` Classes 5 | *************************************** 6 | 7 | The main classes used for handling complex geometries are the ``surface`` and ``curve`` classes. ``surface`` is used in 3D problems, while ``curve`` is used in 2D problems. The only differences in the classes are the number of dimensions; otherwise they are identical. There is an additional class ``curve3d`` which is used to create surfaces from bounding curves with the ``curves_to_surf`` function 8 | 9 | .. autoclass:: fdfault.surface 10 | :members: 11 | 12 | .. automethod:: fdfault.surface.__init__ 13 | 14 | .. autoclass:: fdfault.curve3d 15 | :members: 16 | :inherited-members: 17 | 18 | .. automethod:: fdfault.curve3d.__init__ 19 | 20 | .. autofunction:: fdfault.curves_to_surf 21 | 22 | .. autoclass:: fdfault.curve 23 | :members: 24 | :inherited-members: 25 | 26 | .. automethod:: fdfault.curve.__init__ -------------------------------------------------------------------------------- /src/cartesian.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CARTESIANCLASSHEADERDEF 2 | #define CARTESIANCLASSHEADERDEF 3 | 4 | #include "coord.hpp" 5 | #include 6 | 7 | class cartesian 8 | { friend class fields; 9 | public: 10 | cartesian(const char* filename, const int ndim_in, const int nx_in[3], const int nblocks[3], int** nx_block, int** xm_block, const int sbporder); 11 | int get_nproc(const int direction) const; 12 | int get_coords(const int direction) const; 13 | int get_nx(const int index) const; 14 | int get_nx_loc(const int index) const; 15 | int get_xm_loc(const int index) const; 16 | int get_xp_loc(const int index) const; 17 | int get_nx_tot(const int index) const; 18 | int get_xm_ghost(const int index) const; 19 | int get_xp_ghost(const int index) const; 20 | int get_min_loc(const int index) const; 21 | int get_max_loc(const int index) const; 22 | private: 23 | int np; 24 | int id; 25 | int ndim; 26 | coord c; 27 | int nproc[3]; 28 | int coords[3]; 29 | MPI_Comm comm; 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/slipweak.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SLIPWEAKCLASSHEADERDEF 2 | #define SLIPWEAKCLASSHEADERDEF 3 | 4 | #include 5 | #include "friction.hpp" 6 | #include "interface.hpp" 7 | #include "swparam.hpp" 8 | 9 | class slipweak: public friction 10 | { friend class outputunit; 11 | friend class front; 12 | public: 13 | slipweak(const char* filename, const int ndim_in, const int mode_in,const std::string material_in, 14 | const int niface, block**** blocks, const fields& f, const cartesian& cart, const fd_type& fd); 15 | ~slipweak(); 16 | protected: 17 | swparam** perts; 18 | double* dc; 19 | double* mus; 20 | double* mud; 21 | double* c0; 22 | double* trup; 23 | double* tc; 24 | virtual void read_params(const std::string paramfile, const bool data_proc); 25 | virtual boundchar solve_fs(const double phi, const double eta, const double snc, const int i, const int j, const double t); 26 | virtual double calc_mu(const double phi, const double eta, const double snc, const int i, const int j, const double t) const; 27 | }; 28 | 29 | #endif -------------------------------------------------------------------------------- /docs/input/text/problem.rst: -------------------------------------------------------------------------------- 1 | .. _problem: 2 | 3 | ********************************** 4 | Problem Input 5 | ********************************** 6 | 7 | A problem is specified under ``[fdfault.problem]``. The entries under this section are as follows: :: 8 | 9 | Problem Name 10 | Data where simulation output will be saved 11 | Number of time steps 12 | Time step size 13 | Total time 14 | Courant ratio 15 | Frequency at which status information is written to the terminal 16 | Runge-Kutta Integration Order (integer 1-4) 17 | 18 | Most of these are straightforward. The main tricky part in this section is that you typically will only specify two of the four options for determining the time step. You are free to specify any two of these, with the exception of the time step and Courant ratio (the ratio between the grid spacing and the distance a wave travels in one time step). If you specify both the time step and Courant ratio, the code defaults to the given time step. If you specify more than two parameters, the code defaults to the total time and either the time step or the Courant ratio. -------------------------------------------------------------------------------- /src/coord.hpp: -------------------------------------------------------------------------------- 1 | #ifndef COORDCLASSHEADERDEF 2 | #define COORDCLASSHEADERDEF 3 | 4 | class coord 5 | { 6 | public: 7 | coord(); 8 | int get_nx(const int index) const; 9 | int get_xm(const int index) const; 10 | int get_xp(const int index) const; 11 | int get_nx_loc(const int index) const; 12 | int get_nx_tot(const int index) const; 13 | int get_xm_loc(const int index) const; 14 | int get_xp_loc(const int index) const; 15 | int get_xm_ghost(const int index) const; 16 | int get_xp_ghost(const int index) const; 17 | int get_min_loc(const int index) const; 18 | int get_max_loc(const int index) const; 19 | void set_nx(const int index, const int new_nx); 20 | void set_xm(const int index, const int new_xm); 21 | void set_nx_loc(const int index, const int new_nx); 22 | void set_xm_loc(const int index, const int new_xm); 23 | void set_xm_ghost(const int index, const int new_xm); 24 | void set_xp_ghost(const int index, const int new_xp); 25 | private: 26 | int nx[3]; 27 | int xm[3]; 28 | int nx_loc[3]; 29 | int xm_loc[3]; 30 | int xm_ghost[3]; 31 | int xp_ghost[3]; 32 | }; 33 | 34 | #endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Eric G. Daub 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/analysis/pythonanalysis.rst: -------------------------------------------------------------------------------- 1 | .. _pythonanalysis: 2 | 3 | ********************************** 4 | Analysis With Python 5 | ********************************** 6 | 7 | .. automodule:: fdfault.analysis 8 | 9 | .. autoclass:: fdfault.analysis.output 10 | :members: 11 | 12 | .. autoclass:: fdfault.analysis.front 13 | :members: 14 | 15 | =============================== 16 | The ``write_scec`` submodule 17 | =============================== 18 | 19 | .. automodule:: fdfault.analysis.write_scec 20 | 21 | .. autofunction:: fdfault.analysis.write_scec.write_off_fault 22 | 23 | .. autofunction:: fdfault.analysis.write_scec.write_off_fault_2d 24 | 25 | .. autofunction:: fdfault.analysis.write_scec.write_on_fault 26 | 27 | .. autofunction:: fdfault.analysis.write_scec.write_on_fault_2d 28 | 29 | .. autofunction:: fdfault.analysis.write_scec.write_front 30 | 31 | ========================== 32 | Example 33 | ========================== 34 | 35 | An example of how to use the included classes for analysis is included in the file ``python_example.py``, included in the ``python`` directory. 36 | 37 | .. literalinclude:: ../../python/python_example.py -------------------------------------------------------------------------------- /src/swparam.hpp: -------------------------------------------------------------------------------- 1 | #ifndef SWPARAMCLASSHEADERDEF 2 | #define SWPARAMCLASSHEADERDEF 3 | 4 | #include 5 | #include "pert.hpp" 6 | 7 | class swparam: public pert 8 | { 9 | public: 10 | swparam(const std::string type_in, const double t0_in, const double x0_in, const double dx_in, 11 | const double y0_in, const double dy_in, const int n[2], const int xm[2], const int xm_loc[2], 12 | const double x[2], const double l[2], const double dc_in, const double mus_in, 13 | const double mud_in, const double c0_in, const double trup_in, const double tc_in); 14 | double get_dc(const int i, const int j, const double t) const; 15 | double get_mus(const int i, const int j, const double t) const; 16 | double get_mud(const int i, const int j, const double t) const; 17 | double get_c0(const int i, const int j, const double t) const; 18 | double get_trup(const int i, const int j, const double t) const; 19 | double get_tc(const int i, const int j, const double t) const; 20 | protected: 21 | double dc; 22 | double mus; 23 | double mud; 24 | double c0; 25 | double trup; 26 | double tc; 27 | }; 28 | 29 | #endif -------------------------------------------------------------------------------- /src/load.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "load.hpp" 6 | #include "pert.hpp" 7 | 8 | load::load(const std::string type_in, const double t0_in, const double x0_in, const double dx_in, 9 | const double y0_in, const double dy_in, const int n[2], const int xm[2], const int xm_loc[2], 10 | const double x[2], const double l[2], const double sn_in, const double s2_in, 11 | const double s3_in) : pert(type_in, t0_in, x0_in, dx_in, y0_in, dy_in, n, xm, xm_loc, x, l) { 12 | // constructor 13 | 14 | sn = sn_in; 15 | s2 = s2_in; 16 | s3 = s3_in; 17 | 18 | } 19 | 20 | double load::get_s2(const int i, const int j, const double t) const { 21 | // returns shear load perturbation 22 | 23 | return s2*xyfunc(i,j)*tfunc(t); 24 | } 25 | 26 | double load::get_s3(const int i, const int j, const double t) const { 27 | // returns shear load perturbation 28 | 29 | return s3*xyfunc(i,j)*tfunc(t); 30 | } 31 | 32 | double load::get_sn(const int i, const int j, const double t) const { 33 | // returns normal load perturbation 34 | 35 | return sn*xyfunc(i,j)*tfunc(t); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/outputunit.hpp: -------------------------------------------------------------------------------- 1 | #ifndef OUTPUTUNITCLASSHEADERDEF 2 | #define OUTPUTUNITCLASSHEADERDEF 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class outputunit 9 | { 10 | public: 11 | outputunit(const std::string probname, const std::string datadir, const int nt, const int tm_in, const int tp_in, 12 | const int ts_in, const int xm_in[3], const int xp_in[3], const int xs_in[3], 13 | std::string field_in, std::string name, const domain& d); 14 | outputunit* get_next_unit() const ; 15 | void set_next_unit(outputunit* nextunit); 16 | void write_unit(const int tstep, const double dt, const domain& d) const; 17 | void close_file(); 18 | private: 19 | int ndim; 20 | int mode; 21 | bool master; 22 | bool no_data; 23 | int xm[3]; 24 | int xp[3]; 25 | int xs[3]; 26 | int xm_loc[3]; 27 | int xp_loc[3]; 28 | int nx[3]; 29 | int nx_loc[3]; 30 | int tm; 31 | int tp; 32 | int ts; 33 | int field; 34 | int location; 35 | int iface; 36 | int start; 37 | outputunit* next; 38 | std::ofstream* tfile; 39 | MPI_File outfile; 40 | MPI_File xfile; 41 | MPI_Datatype dataarray; 42 | MPI_Datatype filearray; 43 | MPI_Comm comm; 44 | }; 45 | 46 | #endif -------------------------------------------------------------------------------- /python/fdfault/analysis/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ``fdfault.analysis`` is a python module for analyzing dynamic rupture problems for use with the 3 | C++ code. 4 | 5 | It contains classes corresponding to the two types of outputs from the code 6 | 7 | The module contains the following classes: 8 | 9 | * ``fdfault.analysis.output`` -- output unit for grid or fault data 10 | * ``fdfault.analysis.front`` -- rupture front output for fault surfaces 11 | 12 | The output units can hold a variety of different fields. See the documentation for the output 13 | units for more details. 14 | 15 | The rupture front holds rupture time values for all points on the fault. This can be used to examine 16 | rupture speeds and determine the areas of the fault that slip. 17 | 18 | Details on the data structures in each class can be found in the documentation. 19 | 20 | The module also contains several functions for converting binary output files to text files for the 21 | SCEC Rupture Code Verification Group. It contains functions for on- and off-fault stations, and 22 | 2D and 3D problems, as well as rupture front times. See the details of each individual function. 23 | These are not imported by default when loading the analysis submodule 24 | """ 25 | 26 | from .output import output 27 | from .front import front 28 | -------------------------------------------------------------------------------- /src/stz.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STZCLASSHEADERDEF 2 | #define STZCLASSHEADERDEF 3 | 4 | #include 5 | #include "friction.hpp" 6 | #include "stzparam.hpp" 7 | 8 | class stz: public friction 9 | { friend class outputunit; 10 | friend class front; 11 | public: 12 | stz(const char* filename, const int ndim_in, const int mode_in,const std::string material_in, 13 | const int niface, block**** blocks, const fields& f, const cartesian& cart, const fd_type& fd); 14 | ~stz(); 15 | protected: 16 | stzparam** perts; 17 | double* v0; 18 | double* f0; 19 | double* a; 20 | double* muy; 21 | double* c0; 22 | double* R; 23 | double* beta; 24 | double* chiw; 25 | double* v1; 26 | virtual void read_params(const std::string paramfile, const bool data_proc); 27 | virtual double calc_mu(const double phi, const double eta, const double snc, const int i, const int j, const double t) const; 28 | virtual double calc_dstatedt(const double vhat, const double shat, const int i, const int j, const double t) const; 29 | double chihat(const double vt, const double chiwt, const double v1t) const; 30 | }; 31 | 32 | double stz_func(const double mu, double* params); 33 | double stz_der(const double mu, double* params); 34 | double calc_vpl(const double mu, double* params); 35 | double calc_dvpldmu(const double mu, double* params); 36 | 37 | #endif -------------------------------------------------------------------------------- /docs/input/python/python.rst: -------------------------------------------------------------------------------- 1 | .. _python: 2 | 3 | ********************************** 4 | Input Using the Python Module 5 | ********************************** 6 | 7 | .. automodule:: fdfault 8 | 9 | ==================== 10 | Main Classes 11 | ==================== 12 | 13 | The Python module is set up as a collection of classes. Most of them operate under the hood and correspond to an equivalent class in the C++ code and are not directly modified by the user. Instead, the ``problem`` class is used, which contains a series of interfaces for modifying the underlying classes. Additional classes that are directly instantiated by the user include load and friction perturbations and output units. 14 | 15 | .. toctree:: 16 | :maxdepth: 2 17 | 18 | problem 19 | material 20 | surface 21 | friction 22 | slipweak 23 | stz 24 | output 25 | 26 | 27 | ===================== 28 | Additional Classes 29 | ===================== 30 | 31 | The classes below are not normally accessed by the user. Instead, use the interfaces provided in the ``problem`` class, which modify the underlying classes in a more robust way and prevent you from setting up a problem incorrectly. However, full documentation for the additional classes are included here for completeness. 32 | 33 | .. toctree:: 34 | :maxdepth: 2 35 | 36 | block 37 | domain 38 | fields 39 | front 40 | interface -------------------------------------------------------------------------------- /src/domain.hpp: -------------------------------------------------------------------------------- 1 | #ifndef DOMAINCLASSHEADERDEF 2 | #define DOMAINCLASSHEADERDEF 3 | 4 | #include 5 | #include "block.hpp" 6 | #include "cartesian.hpp" 7 | #include "fd.hpp" 8 | #include "fields.hpp" 9 | #include "friction.hpp" 10 | #include "interface.hpp" 11 | #include "rk.hpp" 12 | 13 | class domain 14 | { friend class outputunit; 15 | friend class frontlist; 16 | friend class front; 17 | public: 18 | domain(const char* filename); 19 | ~domain(); 20 | int get_ndim() const; 21 | int get_mode() const; 22 | int get_nblocks(const int index) const; 23 | int get_nblockstot() const; 24 | int get_nifaces() const; 25 | double get_min_dx() const; 26 | void do_rk_stage(const double dt, const int stage, const double t, rk_type& rk); 27 | void free_exchange(); 28 | void set_stress(); 29 | void remove_stress(); 30 | private: 31 | int ndim; 32 | int mode; 33 | std::string material; 34 | bool is_plastic; 35 | int nx[3]; 36 | int nblockstot; 37 | int nblocks[3]; 38 | int nifaces; 39 | block**** blocks; 40 | interface** interfaces; 41 | fd_type* fd; 42 | cartesian* cart; 43 | fields* f; 44 | void allocate_blocks(const char* filename, int** nx_block, int** xm_block); 45 | void allocate_interfaces(const char* filename, std::string* iftype); 46 | void deallocate_blocks(); 47 | void deallocate_interfaces(); 48 | }; 49 | 50 | #endif -------------------------------------------------------------------------------- /problems/tpv4.in: -------------------------------------------------------------------------------- 1 | [fdfault.problem] 2 | tpv4 3 | data/ 4 | 701 5 | 0.0 6 | 0.0 7 | 0.3 8 | 100 9 | 4 10 | 11 | [fdfault.domain] 12 | 3 13 | 2 14 | 201 202 101 15 | 1 2 1 16 | 201 17 | 101 101 18 | 101 19 | 1 20 | slipweak 21 | 4 22 | elastic 23 | 24 | [fdfault.fields] 25 | 0.0 0.0 0.0 0.0 0.0 0.0 26 | none 27 | none 28 | 0 29 | 30 | [fdfault.block000] 31 | 2.67 32.04 32.04 32 | 0.0 0.0 0.0 33 | 40.0 20.0 20.0 34 | absorbing 35 | absorbing 36 | absorbing 37 | none 38 | absorbing 39 | free 40 | none 41 | none 42 | none 43 | none 44 | none 45 | none 46 | 47 | [fdfault.block010] 48 | 2.67 32.04 32.04 49 | 0.0 20.0 0.0 50 | 40.0 20.0 20.0 51 | absorbing 52 | absorbing 53 | none 54 | absorbing 55 | absorbing 56 | free 57 | none 58 | none 59 | none 60 | none 61 | none 62 | none 63 | 64 | [fdfault.interface0] 65 | y 66 | 0 0 0 67 | 0 1 0 68 | 69 | [fdfault.friction] 70 | 2 71 | constant 0.0 0.0 0.0 0.0 0.0 -120.0 70.0 0.0 72 | boxcar 0.0 20.0 1.5 12.5 1.5 0.0 11.6 0.0 73 | none 74 | 75 | [fdfault.slipweak] 76 | 4 77 | constant 0.0 0.0 0.0 0.0 0.0 0.4 0.677 0.525 0.0 0.0 0.0 78 | boxcar 0.0 20.0 20.0 2.5 2.5 0.0 10000.0 0.0 0.0 0.0 0.0 79 | boxcar 0.0 2.5 2.5 12.5 7.5 0.0 10000.0 0.0 0.0 0.0 0.0 80 | boxcar 0.0 37.5 2.5 12.5 7.5 0.0 10000.0 0.0 0.0 0.0 0.0 81 | none 82 | 83 | [fdfault.outputlist] 84 | vf 85 | V 86 | 0 700 10 87 | 0 200 1 88 | 101 101 1 89 | 0 100 1 90 | 91 | 92 | [fdfault.frontlist] 93 | 1 94 | V 95 | 0.001 96 | 97 | -------------------------------------------------------------------------------- /problems/test2d.in: -------------------------------------------------------------------------------- 1 | [fdfault.problem] 2 | test2d 3 | data/ 4 | 1000 5 | 0 6 | 0 7 | 0.3 8 | 50 9 | 4 10 | 11 | [fdfault.domain] 12 | 2 13 | 2 14 | 801 802 1 15 | 1 2 1 16 | 801 17 | 401 401 18 | 1 19 | 1 20 | slipweak 21 | 4 22 | elastic 23 | 24 | [fdfault.fields] 25 | 0. 0. 0. 0. 0. 0. 26 | none 27 | none 28 | 0 29 | 30 | [fdfault.block000] 31 | 2.67 32.04 32.04 32 | 0. 0. 33 | 40. 20. 34 | absorbing 35 | absorbing 36 | absorbing 37 | none 38 | none 39 | none 40 | none 41 | none 42 | 43 | [fdfault.block010] 44 | 2.67 32.04 32.04 45 | 0. 20. 46 | 40. 20. 47 | absorbing 48 | absorbing 49 | none 50 | absorbing 51 | none 52 | none 53 | none 54 | none 55 | 56 | [fdfault.operator] 57 | 0. 58 | 59 | [fdfault.interface0] 60 | y 61 | 0 0 0 62 | 0 1 0 63 | 64 | [fdfault.friction] 65 | 2 66 | constant 0. 0. 0. 0. 0. -120. 70. 0. 67 | boxcar 0. 20. 1.5 0. 0. 0. 11.6 0. 68 | none 69 | 70 | [fdfault.slipweak] 71 | 3 72 | constant 0. 0. 0. 0. 0. 0.4 0.677 0.525 0. 0. 0. 73 | boxcar 0. 2.5 2.5 0. 0. 0. 10000. 0. 0. 0. 0. 74 | boxcar 0. 37.5 2.5 0. 0. 0. 10000. 0. 0. 0. 0. 75 | none 76 | 77 | [fdfault.outputlist] 78 | vx 79 | vx 80 | 0 1000 100 81 | 0 800 1 82 | 0 801 1 83 | 0 0 1 84 | V 85 | V 86 | 0 1000 10 87 | 0 800 1 88 | 401 401 1 89 | 0 0 1 90 | sxy 91 | sxy 92 | 0 1000 1 93 | 600 600 1 94 | 501 501 1 95 | 0 0 1 96 | 97 | 98 | [fdfault.frontlist] 99 | 0 100 | -------------------------------------------------------------------------------- /docs/examples/test2d.tex: -------------------------------------------------------------------------------- 1 | \documentclass{standalone} 2 | \usepackage{tikz} 3 | \begin{document} 4 | \begin{tikzpicture}[line width=1pt] 5 | \draw (0,0) rectangle (5,5); 6 | \draw (0, 2.5) -- (5, 2.5); 7 | \draw[line width=1pt,<->] (0,-0.25) -- (2.5,-0.25) node[anchor=north]{40 km} -- (5, -0.25); 8 | \draw[line width=1pt,<->] (5.25,0) -- (5.25,1.25) node[anchor=west]{20 km} -- (5.25, 2.5); 9 | \draw[line width=1pt,<->] (5.25,2.5) -- (5.25,3.75) node[anchor=west]{20 km} -- (5.25, 5); 10 | \draw[line width=2pt, color=darkgray] (0, 2.5) -- (0.625, 2.5); 11 | \draw[line width=1pt,<->] (0,2.25) -- (0.4,2.25) node[anchor=north]{5 km} -- (0.625, 2.25); 12 | \draw[line width=2pt, color=darkgray] (4.375, 2.5) -- (5, 2.5); 13 | \draw[line width=1pt,<->] (4.375,2.25) -- (4.6,2.25) node[anchor=north]{5 km} -- (5, 2.25); 14 | \draw[line width=2pt, color=gray] (2.3125, 2.5) -- (2.5,2.5) node[anchor=south]{Nucleation Patch} -- (2.6875, 2.5); 15 | \draw[line width=1pt,<->] (2.3125,2.25) -- (2.5,2.25) node[anchor=north]{3 km} -- (2.6875, 2.25); 16 | \draw[line width=1pt,<->] (0,1.5) -- (1.25,1.5) node[anchor=north]{20 km} -- (2.5, 1.5); 17 | \draw[line width=1pt,->] (0,5.25) -- (0.5,5.25) node[anchor=west]{$x$}; 18 | \draw[line width=1pt,->] (0,5.25) -- (0,5.75) node[anchor=south]{$y$}; 19 | \draw[line width=1pt, color=darkgray,->] (1.27,4) node[anchor=west]{Strong Barrier} -- (0.3125,2.75); 20 | \draw[line width=1pt, color=darkgray,->] (3.73,4) -- (4.6875,2.75); 21 | \end{tikzpicture} 22 | \end{document} -------------------------------------------------------------------------------- /src/stzparam.hpp: -------------------------------------------------------------------------------- 1 | #ifndef STZPARAMCLASSHEADERDEF 2 | #define STZPARAMCLASSHEADERDEF 3 | 4 | #include 5 | #include "pert.hpp" 6 | 7 | class stzparam: public pert 8 | { 9 | public: 10 | stzparam(const std::string type_in, const double t0_in, const double x0_in, const double dx_in, 11 | const double y0_in, const double dy_in, const int n[2], const int xm[2], const int xm_loc[2], 12 | const double x[2], const double l[2], const double v0_in, const double f0_in, 13 | const double a_in, const double muy_in, const double c0_in, const double R_in, 14 | const double beta_in, const double chiw_in, const double v1_in); 15 | double get_v0(const int i, const int j, const double t) const; 16 | double get_f0(const int i, const int j, const double t) const; 17 | double get_a(const int i, const int j, const double t) const; 18 | double get_muy(const int i, const int j, const double t) const; 19 | double get_c0(const int i, const int j, const double t) const; 20 | double get_R(const int i, const int j, const double t) const; 21 | double get_beta(const int i, const int j, const double t) const; 22 | double get_chiw(const int i, const int j, const double t) const; 23 | double get_v1(const int i, const int j, const double t) const; 24 | protected: 25 | double v0; 26 | double f0; 27 | double a; 28 | double muy; 29 | double c0; 30 | double R; 31 | double beta; 32 | double chiw; 33 | double v1; 34 | }; 35 | 36 | #endif -------------------------------------------------------------------------------- /src/boundary.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BOUNDARYCLASSHEADERDEF 2 | #define BOUNDARYCLASSHEADERDEF 3 | 4 | #include 5 | #include "cartesian.hpp" 6 | #include "coord.hpp" 7 | #include "fields.hpp" 8 | #include "fd.hpp" 9 | #include "material.hpp" 10 | #include "surface.hpp" 11 | 12 | struct boundfields { 13 | double v1, v2, v3, s11, s12, s13, s22, s23, s33; 14 | }; 15 | 16 | struct boundchar { 17 | double v, s; 18 | }; 19 | 20 | boundfields rotate_xy_nt(const boundfields b, const double nn[3], const double t1[3], const double t2[3]); 21 | 22 | boundfields rotate_nt_xy(const boundfields b, const double nn[3], const double t1[3], const double t2[3]); 23 | 24 | class boundary 25 | { 26 | public: 27 | boundary(const int ndim_in, const int mode_in, const std::string material_in, const int location_in, const std::string boundtype_in, 28 | const coord c, const double dx[3], fields& f, material& m, const cartesian& cart, const fd_type& fd); 29 | ~boundary(); 30 | virtual void apply_bcs(const double dt, fields& f); 31 | private: 32 | std::string boundtype; 33 | int ndim; 34 | int mode; 35 | int location; 36 | int n[2]; 37 | int n_loc[2]; 38 | int nxd[3]; 39 | int mlb[3]; 40 | int prb[3]; 41 | bool no_data; 42 | bool is_plastic; 43 | double cp; 44 | double cs; 45 | double zp; 46 | double zs; 47 | double gamma; 48 | double*** nx; 49 | double** dl; 50 | double r; 51 | double alpha; 52 | double theta; 53 | void allocate_normals(const double dx[3], fields& f, const fd_type& fd); 54 | void deallocate_normals(); 55 | boundchar calc_hat(const boundchar b, const double z); 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "problem.hpp" 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main(int argc, char* argv[]) { 9 | 10 | int np, id, rc; 11 | time_t rawtime; 12 | struct tm* timeinfo; 13 | 14 | // start MPI 15 | 16 | MPI_Init(&argc, &argv); 17 | 18 | MPI_Comm_size(MPI_COMM_WORLD, &np); 19 | 20 | MPI_Comm_rank(MPI_COMM_WORLD, &id); 21 | 22 | // write process info 23 | 24 | if (id==0) { 25 | cout << "fdfault called with " << np << " processes\n"; 26 | } 27 | 28 | // get input file from command line 29 | 30 | const char* inputfile = argv[1]; 31 | 32 | if (id==0) { 33 | cout << "Reading from input file " << inputfile << "\n"; 34 | } 35 | 36 | // initialize problem 37 | 38 | problem prob(inputfile); 39 | 40 | // Barrier to wait for all processes to finish initialization 41 | 42 | MPI_Barrier(MPI_COMM_WORLD); 43 | 44 | // initialization finished 45 | 46 | if (id==0) { 47 | time (&rawtime); 48 | timeinfo = localtime (&rawtime); 49 | cout << "Initialization finished " << asctime(timeinfo); 50 | } 51 | 52 | // solve problem 53 | 54 | prob.solve(); 55 | 56 | // finished with problem setup 57 | // Barrier to wait for all processes to finish running 58 | 59 | MPI_Barrier(MPI_COMM_WORLD); 60 | 61 | if (id==0) { 62 | time (&rawtime); 63 | timeinfo = localtime (&rawtime); 64 | cout << "Problem finished " << asctime(timeinfo); 65 | } 66 | 67 | // finalize MPI 68 | 69 | MPI_Finalize( ); 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /docs/input/text/text.rst: -------------------------------------------------------------------------------- 1 | .. _text: 2 | 3 | ********************************** 4 | Text Input Files 5 | ********************************** 6 | 7 | Text input files contain multiple sections. With one exception, the order of the sections is not important -- the file is read multiple times by various parts of the code, and each time the file is read the code starts from the beginning and scans through to find the appropriate section. Each section is designated by a text string ``[fdfault.]``, where ```` refers to which part of the code will be reading this section. If the code expects to find a certain section and it reaches the end of the text file without finding it, the code will abort. At minimum, the following sections are required to fully specify a problem: :: 8 | 9 | [fdfault.problem] 10 | [fdfault.domain] 11 | [fdfault.fields] 12 | [fdfault.blockXYZ] 13 | [fdfault.outputlist] 14 | [fdfault.frontlist] 15 | 16 | In addition to these sections, optional sections describe additional blocks and interfaces, as well as other parameter settings. These include the following sections: :: 17 | 18 | [fdfault.cartesian] 19 | [fdfault.operator] 20 | [fdfault.interfaceN] 21 | [fdfault.friction] 22 | [fdfault.slipweak] 23 | [fdfault.stz] 24 | 25 | If the problem has more than one block or more than one interface, the sections are designated with the numeric value in place of ``XYZ`` or ``N`` included in the section header. 26 | 27 | .. toctree:: 28 | :maxdepth: 1 29 | 30 | problem 31 | domain 32 | cartesian 33 | fields 34 | operator 35 | block 36 | interface 37 | friction 38 | slipweak 39 | stz 40 | outputlist 41 | frontlist -------------------------------------------------------------------------------- /docs/input/text/slipweak.rst: -------------------------------------------------------------------------------- 1 | .. _slipweak: 2 | 3 | ********************************** 4 | Slip Weakening Input 5 | ********************************** 6 | 7 | The basic format for slip-weakening interaces is analogous to those for setting the surface tractions: :: 8 | 9 | Number of parameter perturbations 10 | List of parameter perturbations 11 | Parameter perturbation filename 12 | 13 | Each item in the list requires the same basic six parameters to describe the shape as for the load perturbations (type t0 x0 dx y0 dy), interpreted in the same way as described above. For slip weakening laws, there are six additional parameters that must be specified: :: 14 | 15 | dc mus mud c0 tc trup 16 | 17 | ``dc`` is the slip weakening distance, ``mus`` is the static friction coefficient, ``mud`` is the dynamic friction coefficient, ``c0`` is the frictional cohesion, ``tc`` is the characteristic weakening time, and ``trup`` is the forced rupture time. The first four parameters are fairly standard, while the final two parameters are used to impose kinematic forcing on the rupture front: ``tc`` is the time scale over which the friction weakens from static to dynamic, and ``trup`` is the time at which this process initiates. If ``trup`` is 0, then no kinematic forcing is used. 18 | 19 | As with load perturbations, heterogeneous perturbations using an input file are also allowed. The format is the same as with load perturbations (C order double precision floats, with parameters given in the order listed above), and the ordering of the arrays is the same as for the perturbations listed above. The Python module can help with generating the appropriate files. If no file is used, the code must include ``none`` in place of the filename. -------------------------------------------------------------------------------- /docs/examples/input_example.tex: -------------------------------------------------------------------------------- 1 | \documentclass{standalone} 2 | \usepackage{tikz} 3 | \begin{document} 4 | \begin{tikzpicture}[line width=1pt] 5 | \draw (0,0) rectangle (5,5); 6 | \draw plot[domain=0:5,smooth] (\x,{sin(\x * pi/5 r)/4.+2.5}); 7 | \draw[line width=1pt,<->] (0,-0.25) -- (2.5,-0.25) node[anchor=north]{40 km} -- (5, -0.25); 8 | \draw[line width=1pt,<->] (5.25,0) -- (5.25,1.25) node[anchor=west]{20 km} -- (5.25, 2.5); 9 | \draw[line width=1pt,<->] (5.25,2.5) -- (5.25,3.75) node[anchor=west]{20 km} -- (5.25, 5); 10 | \draw[line width=2pt, color=darkgray] plot[domain=0:0.625,smooth] (\x,{sin(\x * pi/5 r)/4.+2.5}); 11 | \draw[line width=1pt,<->] (0,2.25) -- (0.4,2.25) node[anchor=north]{5 km} -- (0.625, 2.25); 12 | \draw[line width=2pt, color=darkgray] plot[domain=4.375:5,smooth] (\x,{sin(\x * pi/5 r)/4.+2.5}); 13 | \draw[line width=1pt,<->] (4.375,2.25) -- (4.6,2.25) node[anchor=north]{5 km} -- (5, 2.25); 14 | \draw[line width=2pt, color=gray] plot[domain=2.3125:2.6875,smooth] (\x,{sin(\x * pi/5 r)/4.+2.5}); 15 | \draw[color=gray] (2.5,2.75) node[anchor=south]{Nucleation Patch}; 16 | \draw[line width=1pt,<->] (-0.1,2.5) -- (-0.1,2.625) node[anchor=east]{0.5 km} -- (-0.1, 2.75); 17 | \draw[line width=1pt,<->] (2.3125,2.55) -- (2.5,2.55) node[anchor=north]{3 km} -- (2.6875, 2.55); 18 | \draw[line width=1pt,<->] (0,1.5) -- (1.25,1.5) node[anchor=north]{20 km} -- (2.5, 1.5); 19 | \draw[line width=1pt,->] (0,5.25) -- (0.5,5.25) node[anchor=west]{$x$}; 20 | \draw[line width=1pt,->] (0,5.25) -- (0,5.75) node[anchor=south]{$y$}; 21 | \draw[line width=1pt, color=darkgray,->] (1.27,4) node[anchor=west]{Strong Barrier} -- (0.3125,2.75); 22 | \draw[line width=1pt, color=darkgray,->] (3.73,4) -- (4.6875,2.75); 23 | \end{tikzpicture} 24 | \end{document} -------------------------------------------------------------------------------- /docs/input/input.rst: -------------------------------------------------------------------------------- 1 | .. _input: 2 | 3 | ********************************** 4 | Specifying Simulation Parameters 5 | ********************************** 6 | 7 | Parameters for simulations are set with input files. These are text files that are formatted to be understood by the C++ code. They mostly consist of section headers followed by raw numbers, strings, or file names. They are manageable for small, simple problems, but to really use the full power of the code it is suggested to take advantage of the Python module. Either way, parameters are set through an input file ``problemname.in``, though the problem name is actually set in the input file itself so the input file name and problem name need not be the same. 8 | 9 | Once the input file is written to disk, you can launch a simulation. From the main ``fdfault`` directory, simply enter: :: 10 | 11 | > mpirun -n 4 fdfault problems/problemname.in 12 | 13 | This should run the problem on 4 processors, printing out information to the console as it progresses. If you wish to use a different number of processors, modify the 4 (some versions of MPI may require you to use the option flag ``-np 4`` to set the number of processors, and some versions of MPI may require that you use ``mpiexec`` to run a simulation). If you are running the code on a cluster, you should follow your normal procedure for submitting jobs. 14 | 15 | The code assumes you will be running everything in the main code directory, and by default uses relative paths to that main directory to write the simulation files to disk. You are welcome to run the code from another directory, but you should either have a ``data`` directory already created or use the full path to the location where you wish to write data. 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | 20 | text/text 21 | python/python -------------------------------------------------------------------------------- /src/fields.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FIELDSCLASSHEADERDEF 2 | #define FIELDSCLASSHEADERDEF 3 | 4 | #include 5 | #include "cartesian.hpp" 6 | #include "coord.hpp" 7 | #include 8 | 9 | class fields 10 | { 11 | friend class block; 12 | friend class boundary; 13 | friend class interface; 14 | friend class load; 15 | friend class outputunit; 16 | friend class front; 17 | public: 18 | fields(const char* filename, const int ndim_in, const int mode, const std::string material_in, const cartesian& cart); 19 | ~fields(); 20 | void scale_df(const double A); 21 | void update(const double B); 22 | void set_stress(); 23 | void remove_stress(); 24 | void exchange_neighbors(); 25 | void exchange_grid(); 26 | void free_exchange(); 27 | private: 28 | int ndim; 29 | int mode; 30 | std::string material; 31 | bool hetstress; 32 | bool hetmat; 33 | bool plastic_tensor; 34 | int nv; 35 | int ns; 36 | int nmat; 37 | int nxyz; 38 | int index[6]; 39 | int nfields; 40 | int nfieldsp; 41 | int ndataf; 42 | int ndatadf; 43 | int ndatax; 44 | int ndatametric; 45 | int ndatajac; 46 | int shiftp_source[3]; 47 | int shiftp_dest[3]; 48 | int shiftm_source[3]; 49 | int shiftm_dest[3]; 50 | int shiftp_source_index[3]; 51 | int shiftp_dest_index[3]; 52 | int shiftm_source_index[3]; 53 | int shiftm_dest_index[3]; 54 | coord c; 55 | double s0[6]; 56 | double* s; 57 | double* mat; 58 | double* f; 59 | double* df; 60 | double* x; 61 | double* metric; 62 | double* jac; 63 | MPI_Comm comm; 64 | MPI_Datatype slicep[3]; 65 | MPI_Datatype slicem[3]; 66 | void init_exchange(const cartesian& cart); 67 | void read_load(const std::string loadfile); 68 | void read_mat(const std::string matfile); 69 | }; 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /problems/input_example.py: -------------------------------------------------------------------------------- 1 | import fdfault 2 | import numpy as np 3 | 4 | # create problem 5 | 6 | p = fdfault.problem('input_example') 7 | 8 | # set rk and fd order 9 | 10 | p.set_rkorder(4) 11 | p.set_sbporder(4) 12 | 13 | # set time step info 14 | 15 | p.set_nt(1601) 16 | p.set_cfl(0.3) 17 | p.set_ninfo(50) 18 | 19 | # set number of blocks and coordinate information 20 | 21 | p.set_nblocks((1,2,1)) 22 | p.set_nx_block(([1601], [801, 801], [1])) 23 | 24 | # set block dimensions 25 | 26 | p.set_block_lx((0,0,0),(40.,20.)) 27 | p.set_block_lx((0,1,0),(40.,20.)) 28 | 29 | # set block boundary conditions 30 | 31 | p.set_bounds((0,0,0),['absorbing', 'absorbing', 'absorbing', 'none']) 32 | p.set_bounds((0,1,0),['absorbing', 'absorbing', 'none', 'absorbing']) 33 | 34 | # set block surface 35 | 36 | x = np.linspace(0., 40., 1601) 37 | y = 20.*np.ones(1601)+0.5*np.sin(np.pi*x/40.) 38 | 39 | surf = fdfault.curve(1601, 'y', x, y) 40 | 41 | p.set_block_surf((0,0,0), 3, surf) 42 | p.set_block_surf((0,1,0), 2, surf) 43 | 44 | # set initial fields 45 | 46 | p.set_stress((-100., 70., 0., -120., 0., 0.)) 47 | 48 | # set interface type 49 | 50 | p.set_iftype(0,'slipweak') 51 | 52 | # set slip weakening parameters 53 | 54 | p.add_pert(fdfault.swparam('constant', dc = 0.4, mus = 0.676, mud = 0.525),0) 55 | p.add_pert(fdfault.swparam('boxcar', x0 = 2.5, dx = 2.5, mus = 10000.),0) 56 | p.add_pert(fdfault.swparam('boxcar', x0 = 37.5, dx = 2.5, mus = 10000.),0) 57 | 58 | # add load perturbations 59 | 60 | p.add_load(fdfault.load('boxcar',0., 20., 1.5, 0., 0., 0., 11.6, 0.)) 61 | 62 | # add output unit 63 | 64 | p.add_output(fdfault.output('vxbody','vx',0, 1600, 50, 0, 1600, 2, 0, 1600, 2, 0, 0, 1)) 65 | p.add_output(fdfault.output('vybody','vy',0, 1600, 50, 0, 1600, 2, 0, 1600, 2, 0, 0, 1)) 66 | p.add_output(fdfault.output('vfault','V',0, 1600, 10, 0, 1600, 1, 801, 801, 1, 0, 0, 1)) 67 | 68 | p.write_input() 69 | -------------------------------------------------------------------------------- /src/swparam.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "swparam.hpp" 6 | #include "pert.hpp" 7 | 8 | swparam::swparam(const std::string type_in, const double t0_in, const double x0_in, const double dx_in, 9 | const double y0_in, const double dy_in, const int n[2], const int xm[2], const int xm_loc[2], 10 | const double x[2], const double l[2], const double dc_in, const double mus_in, 11 | const double mud_in, const double c0_in, const double trup_in, const double tc_in) : pert(type_in, t0_in, x0_in, dx_in, y0_in, dy_in, n, xm, xm_loc, x, l) { 12 | // constructor 13 | 14 | dc = dc_in; 15 | mus = mus_in; 16 | mud = mud_in; 17 | c0 = c0_in; 18 | trup = trup_in; 19 | tc = tc_in; 20 | 21 | } 22 | 23 | double swparam::get_dc(const int i, const int j, const double t) const { 24 | // returns slip weakening distance perturbation 25 | 26 | return dc*xyfunc(i,j)*tfunc(t); 27 | } 28 | 29 | double swparam::get_mus(const int i, const int j, const double t) const { 30 | // returns static friction perturbation 31 | 32 | return mus*xyfunc(i,j)*tfunc(t); 33 | } 34 | 35 | double swparam::get_mud(const int i, const int j, const double t) const { 36 | // returns dynamic friction perturbation 37 | 38 | return mud*xyfunc(i,j)*tfunc(t); 39 | 40 | } 41 | 42 | double swparam::get_c0(const int i, const int j, const double t) const { 43 | // returns cohesion perturbation 44 | 45 | return c0*xyfunc(i,j)*tfunc(t); 46 | } 47 | 48 | double swparam::get_trup(const int i, const int j, const double t) const { 49 | // returns forced rupture time perturbation 50 | 51 | return trup*xyfunc(i,j)*tfunc(t); 52 | } 53 | 54 | double swparam::get_tc(const int i, const int j, const double t) const { 55 | // returns time weakening scale perturbation 56 | 57 | return tc*xyfunc(i,j)*tfunc(t); 58 | 59 | } 60 | -------------------------------------------------------------------------------- /docs/input/text/stz.rst: -------------------------------------------------------------------------------- 1 | .. _stz: 2 | 3 | ********************************** 4 | STZ Friction Input 5 | ********************************** 6 | 7 | The basic format for STZ interaces is analogous to those for setting the surface tractions, with the main difference being that additional parameters are needed to set the initial value of the state variable: :: 8 | 9 | Initial effective temperature 10 | Filename for heterogeneous initial effective temperature 11 | Number of parameter perturbations 12 | List of parameter perturbations 13 | Parameter perturbation filename 14 | 15 | First is the (uniform) initial value of the effective temperature, which is simply a floating point number. Next is a file holding double precision floating point numbers in C order for all points on the interface that set the initial value for the effective temperature (the sum of the grid-based values and the overall constant determines the initial value). Endianness should be the same as the computer where the simulations will be run. If no file is used, ``none`` should be entered in its place. 16 | 17 | Next, the friction parameters are set, which uses both perturbations analogous to the load perturbations. Each item in the perturbation list requires the same basic six parameters to describe the shape as for the load perturbations (type t0 x0 dx y0 dy), interpreted in the same way as described in the load section. For STZ friction laws, there are nine additional parameters that must be specified: :: 18 | 19 | V0 f0 a muy c0 R beta chiw V1 20 | 21 | See the introduction for more details on the meaning of these parameters. 22 | 23 | Fully heterogeneous parameter values can be set using a file holding grid-based data (again double precision in C order, with endinanness corresponding to the machine where the simulation will be run). The full arrays for all 9 parmeters must be given in the same order as the parameters in the perturbation. If no file is used, ``none`` must be used as a placeholder. -------------------------------------------------------------------------------- /src/friction.hpp: -------------------------------------------------------------------------------- 1 | #ifndef FRICTIONCLASSHEADERDEF 2 | #define FRICTIONCLASSHEADERDEF 3 | 4 | #include 5 | #include "block.hpp" 6 | #include "cartesian.hpp" 7 | #include "fd.hpp" 8 | #include "fields.hpp" 9 | #include "interface.hpp" 10 | #include "load.hpp" 11 | 12 | class friction: public interface 13 | { friend class outputunit; 14 | friend class front; 15 | public: 16 | friction(const char* filename, const int ndim_in, const int mode_in, const std::string material_in, 17 | const int niface, block**** blocks, const fields& f, const cartesian& cart, const fd_type& fd); 18 | ~friction(); 19 | virtual void scale_df(const double A); 20 | virtual void calc_df(const double dt); 21 | virtual void update(const double B); 22 | protected: 23 | double* du; 24 | double* dux; 25 | double* dstate; 26 | double* dstatedt; 27 | bool load_file; 28 | bool param_file; 29 | int nperts; 30 | int nloads; 31 | load** loads; 32 | double* s1; 33 | double* s2; 34 | double* s3; 35 | void read_load(const std::string loadfile, const bool data_proc); 36 | void read_state(const std::string statefile, const bool data_proc); 37 | virtual void read_params(const std::string paramfile, const bool data_proc); 38 | virtual iffields solve_interface(const boundfields b1, const boundfields b2, const double zp1, const double zs1, const double zp2, const double zs2, const int i, const int j, const double t); 39 | virtual iffields solve_friction(iffields iffin, double snc, const double z1, const double z2, const int i, const int j, const double t); 40 | virtual boundchar solve_fs(const double phi, const double eta, const double snc, const int i, const int j, const double t); 41 | virtual double calc_mu(const double phi, const double eta, const double snc, const int i, const int j, const double t) const; 42 | virtual double calc_dstatedt(const double vhat, const double shat, const int i, const int j, const double t) const; 43 | }; 44 | 45 | #endif -------------------------------------------------------------------------------- /docs/input/text/interface.rst: -------------------------------------------------------------------------------- 1 | .. _interface: 2 | 3 | ********************************** 4 | Interface Input 5 | ********************************** 6 | 7 | All interfaces are specified by a header with the form ``[fdfault.interfaceN]``, where ``N`` determines the interface number (zero indexed). For problems with :math:`{n}` interfaces, the input file must contain an interface header for all :math:`{n}` interfaces, or you will get an error. Interface headers are followed by the following arguments: :: 8 | 9 | Approximate normal direction 10 | Minus block indices 11 | Plus block indices 12 | 13 | First, the list defines the approximate normal direction of the interface in the simulation based on the simulation geometry. For rectangular blocks, this is the true normal direction of the block, while if the block has boundaries specified through a file the normal direction may not be precisely in this direction, or the normal direction may not be uniform across the entire block. The direction is set by a string ``x``, ``y``, or ``z``. 14 | 15 | Following the direction specification, you must set the indices of the block on the "minus" side of the interface (a list of 3 integers). This can be any block in the simulation, but must be the block with the lowest set of indices that are joined by this interface. Order is not important for setting up the interfaces -- interface 0 can join any pair of neighboring blocks in the simulation -- and the lists can appear in the input file in any order. 16 | 17 | Next, the block on the "plus" side of the interface is given by its indices. Because the blocks in the simulation must form a regular grid, the "plus" block must differ in only one index from the "minus" block, and the index that is different must be the same as the direction specified above (this is checked by the code when initializing). For instance, if the minus block is :math:`{(0,0,0)}`, and the direction is ``x``, then the plus block must have the index :math:`{(1,0,0)}`. Line breaks are ignored when reading in the indices. 18 | -------------------------------------------------------------------------------- /docs/examples/tpv4.tex: -------------------------------------------------------------------------------- 1 | \documentclass{standalone} 2 | \usepackage{tikz} 3 | \begin{document} 4 | \begin{tikzpicture}[line width=1pt] 5 | \draw (2, 2) rectangle (12, 7); 6 | \draw (4, 4) rectangle (14, 9); 7 | \draw[line width=1pt,<->] (0,-0.25) -- (5,-0.25) node[anchor=north]{40 km} -- (10, -0.25); 8 | \draw[line width=1pt,<->] (-0.25,0) -- (-0.25,2.5) node[anchor=east]{20 km} -- (-0.25, 5); 9 | \draw[line width=1pt,<->] (10.25,0) -- (11.25,1) node[anchor=north west]{20 km} -- (12.25, 2); 10 | \draw[line width=1pt,<->] (12.25,2) -- (13.25,3) node[anchor=north west]{20 km} -- (14.25, 4); 11 | \fill[color=darkgray] (2,2) -- (12, 2) -- (12, 7) -- (10.75, 7) -- (10.75, 3.25) -- (3.25, 3.25) -- (3.25, 7) -- (2, 7) -- (2,2); 12 | \draw[line width=1pt,<->] (2,1.75) -- (2.625,1.75) node[anchor=north]{5 km} -- (3.25, 1.75); 13 | \draw[line width=1pt,<->] (10.75,7.25) -- (11.4375, 7.25) node[anchor=south]{5 km} -- (12, 7.25); 14 | \draw[line width=1pt,<->] (1.75,2) -- (1.75,2.625) node[anchor=east]{5 km} -- (1.75, 3.25); 15 | \fill[color=gray] (6.625,4.6875) rectangle (7.375, 5.4375); 16 | \draw[color=gray] (7,5.4375) node[anchor=south]{Nucleation Patch}; 17 | \draw[line width=1pt,<->] (6.625,4.5) -- (7,4.5) node[anchor=north]{3 km} -- (7.375, 4.5); 18 | \draw[line width=1pt,<->] (6.4375,4.6875) -- (6.4375,5.2) node[anchor=east]{3 km} -- (6.4375, 5.4375); 19 | \draw[line width=1pt,<->] (2,6.25) -- (5,6.25) node[anchor=south]{20 km} -- (7, 6.25); 20 | \draw[line width=1pt,<->] (9,5.125) -- (9,6) node[anchor=west]{7.5 km} -- (9, 7); 21 | \draw[line width=1pt,->] (0.5,7) -- (1.5,7) node[anchor=west]{$x$}; 22 | \draw[line width=1pt,->] (0.5,7) -- (1.207,7.707) node[anchor=south west]{$y$}; 23 | \draw[line width=1pt,->] (0.5,7) -- (0.5,8) node[anchor=south]{$z$}; 24 | \draw[line width=1pt, color=darkgray,->] (7,1.5) node[anchor=north]{Strong Barrier} -- (7,2); 25 | \draw (7,8) node{Free Surface}; 26 | \draw (0,0) rectangle (10,5); 27 | \draw (0, 0) -- (4, 4); 28 | \draw (0, 5) -- (4, 9); 29 | \draw (10, 0) -- (14, 4); 30 | \draw (10, 5) -- (14, 9); 31 | \end{tikzpicture} 32 | \end{document} -------------------------------------------------------------------------------- /matlab/load_front.m: -------------------------------------------------------------------------------- 1 | function front = load_front(probname, iface, datadir) 2 | 3 | % load_front is a function to load rupture front time data from simulation data 4 | % function returns a data structure holding the following information: 5 | % endian (string) = byte-ordering of the binary data 6 | % nx (integer) = number of x grid points 7 | % ny (integer) = number of y grid points 8 | % nz (integer) = number of z grid points 9 | % x (array) = x grid values (shape nz*ny*nx) 10 | % y (array) = y grid values (shape nz*ny*nx) 11 | % z (array) = z grid values (shape nz*ny*nx) 12 | % t (array) = rupture time array (shape nz*ny*nx*nt) 13 | % 14 | % If the point in question never satisfies the condition for rupture, the array 15 | % value for the rupture time is -1. 16 | 17 | [result currentdir] = system('pwd'); 18 | 19 | if nargin == 2 20 | datadir = [deblank(currentdir) '/']; 21 | end 22 | 23 | if datadir(end) ~= '/' 24 | datadir = [ datadir '/']; 25 | end 26 | 27 | cd(datadir); 28 | system(['cp ' probname '_front_' num2str(iface) '.m tmpfile.m']); 29 | eval('tmpfile'); 30 | system(['rm -f tmpfile.m']); 31 | cd(deblank(currentdir)); 32 | 33 | front.endian = endian; 34 | front.nx = nx; 35 | front.ny = ny; 36 | 37 | f = fopen([ datadir probname '_front_' num2str(iface) '_x.dat'], 'rb'); 38 | front.x = squeeze(reshape(fread(f,nx*ny,'float64',endian),[ny nx])); 39 | fclose(f); 40 | f = fopen([ datadir probname '_front_' num2str(iface) '_y.dat'], 'rb'); 41 | front.y = squeeze(reshape(fread(f,nx*ny,'float64',endian), [ny nx])); 42 | fclose(f); 43 | try 44 | f = fopen([ datadir probname '_front_' num2str(iface) '_z.dat'], 'rb'); 45 | front.z = squeeze(reshape(fread(f,nx*ny,'float64',endian),[ny nx])); 46 | fclose(f); 47 | end 48 | 49 | f = fopen([ datadir probname '_front_' num2str(iface) '_t.dat'], 'rb'); 50 | front.t = squeeze(reshape(fread(f,nx*ny,'float64',endian),[ny nx])); 51 | fclose(f); 52 | 53 | end -------------------------------------------------------------------------------- /docs/input/text/domain.rst: -------------------------------------------------------------------------------- 1 | .. _domain: 2 | 3 | ********************************** 4 | Domain Input 5 | ********************************** 6 | 7 | Details of the spatial domain are determined by the ``[fdfault.domain]`` header. The following arguments are required: :: 8 | 9 | Number of dimensions (2 or 3) 10 | Rupture mode (only meaningful for 2D problems, but necessary for 3D problems) 11 | Number of grid points (3 integers, if 2D problem the third will be reset to 1) 12 | Number of blocks (3 integers, if 2D problem the third will be reset to 1) 13 | Number of grid points for each block in x-direction 14 | Number of grid points for each block in y-direction 15 | Number of grid points for each block in z-direction 16 | Number of interfaces 17 | Type of each interface (list of strings) 18 | Finite difference order (integer 2-4) 19 | Material type (elastic or plastic) 20 | 21 | For this section, the trickiest part is understanding how the blocks and sizes are set up. First, the number of grid points is specified (which must have a length of 3), and then the number of blocks in each dimension is specified (also must of of length 3). If the problem is 2D, then the third entry in each list will be reset to 1 if it is not already 1. Depending on these entries, the code expects the integers that follow to conform to a specific order. First comes the length of each block along the x-direction. The code expects the number of entries to match the number of blocks, and the sum of all entries must equal the total number of grid points along the x-direction. Similarly, the y and z directions are specified in the subsequent entries. While it is recommended that the entries for each direction are on separate lines, the spacing between entries, as well as the line spacing, are ignored when reading the input file. 22 | 23 | After the block dimensions are set, the code reads the number of interfaces, followed by the interface types (it expects a number of strings corresponding to the number of interfaces). Again, line breaks are ignored. The type of each interface must be one of the following: ``locked``, ``frictionless``, ``slipweak``, or ``stz``. 24 | 25 | The final two entries are fairly self explanatory, and determine the finite difference order (integer 2-4) and the material response (elastic or plastic). -------------------------------------------------------------------------------- /docs/input/text/frontlist.rst: -------------------------------------------------------------------------------- 1 | .. _frontlist: 2 | 3 | ********************************** 4 | Rupture Front Times Input 5 | ********************************** 6 | 7 | In addition to the extensive set of options for saving field data from the simulation, the code can also save rupture times (useful for determining rupture front contours). The rupture time is defined as the earliest time when a particular interface field first exceeds a threshold. If rupture front output is selected, the code will save a file for each interface that indicates the earliest time at which the chosen field exceeds the threshold value. If the particular point never ruptures, a value of ``-1.`` is saved. Additionally, the spatial grid information for each interface is saved. Front output only applies to frictional interfaces, and the code will automatically set up output for any frictional interface in the simulation while ignoring others. For more details on interpreting the results of rupture front output, see the analysis section. 8 | 9 | The front output is set using the ``[fdfault.frontlist]`` section of the input file. This section of the input file has the following format: :: 10 | 11 | Boolean indicating if front output is desired 12 | Field used to determine rupture time (required only if front output is turned on) 13 | Field value used to determine rupture time (required only if front output is turned on) 14 | 15 | The ``frontlist`` section requires one argument indicating whether or not rupture time output is desired (``0`` means no output, ``1`` indicates that rupture times for all frictional interfaces should be saved). If output is turned on, two additional arguments are needed: first, a field must be indicated to be used to determine the rupture time, and a value for that field. 16 | 17 | The field can be one of two strings: ``U`` if a slip threshold will be used to determine the rupture time, or ``V`` if a slip rate threshold is desired for determining the rupture time. The field value must be a numeric value, and the rupture time will be the earliest time at which the chosen field exceeds the threshold value. 18 | 19 | Rupture front output is optional, and can be disabled by simply giving ``0`` as the only argument in the list (the ``0`` indicates "false" for front output). If this option is chosen, the remaining two arguments can be omitted. 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/interface.hpp: -------------------------------------------------------------------------------- 1 | #ifndef INTERFACECLASSHEADERDEF 2 | #define INTERFACECLASSHEADERDEF 3 | 4 | #include "block.hpp" 5 | #include "boundary.hpp" 6 | #include "cartesian.hpp" 7 | #include "fields.hpp" 8 | 9 | struct iffields { 10 | double v11, v12, v13, s11, s12, s13; 11 | double v21, v22, v23, s21, s22, s23; 12 | }; 13 | 14 | struct ifchar { 15 | double v1, v2, s1, s2; 16 | }; 17 | 18 | class interface 19 | { friend class outputunit; 20 | friend class frontlist; 21 | friend class front; 22 | public: 23 | interface(const char* filename, const int ndim_in, const int mode_in, const std::string material_in, 24 | const int niface, block**** blocks, const fields& f, const cartesian& cart, const fd_type& fd); 25 | ~interface(); 26 | void apply_bcs(const double dt, const double t, fields& f, const bool no_sat); 27 | virtual void scale_df(const double A); 28 | virtual void calc_df(const double dt); 29 | virtual void update(const double B); 30 | virtual void write_fields(); 31 | protected: 32 | int ndim; 33 | int mode; 34 | int direction; 35 | int n[2]; 36 | int n_loc[2]; 37 | int xm[3]; 38 | int xm_loc[3]; 39 | int xp[3]; 40 | int xp_loc[3]; 41 | double x[3]; 42 | double l[3]; 43 | double cp1; 44 | double cs1; 45 | double zp1; 46 | double zs1; 47 | double cp2; 48 | double cs2; 49 | double zp2; 50 | double zs2; 51 | double gamma1; 52 | double gamma2; 53 | double*** nx; 54 | double** dl1; 55 | double** dl2; 56 | int nxd[3]; 57 | int mlb[3]; 58 | int prb[3]; 59 | int delta[3]; 60 | bool no_data; 61 | bool data1; 62 | bool data2; 63 | bool is_friction; 64 | bool has_state; 65 | bool is_plastic; 66 | double* u; 67 | double* v; 68 | double* ux; 69 | double* vx; 70 | double* sx; 71 | double* s; 72 | double* sn; 73 | double* state; 74 | void allocate_normals(const double dx1[3], const double dx2[3], const fields& f, const fd_type& fd); 75 | void deallocate_normals(); 76 | virtual iffields solve_interface(const boundfields b1, const boundfields b2, const double zp1, const double zs1, const double zp2, const double zs2, const int i, const int j, const double t); 77 | ifchar solve_locked(const ifchar ifc, const double z1, const double z2); 78 | }; 79 | 80 | #endif -------------------------------------------------------------------------------- /matlab/load_output.m: -------------------------------------------------------------------------------- 1 | function output = load_output(probname, name, datadir) 2 | % load_output is a function to load output data from simulation data 3 | % function returns a data structure holding the following information: 4 | % field (string) = field that was saved from the simulation 5 | % endian (string) = byte-ordering of the binary data 6 | % nt (integer) = number of time steps 7 | % nx (integer) = number of x grid points 8 | % ny (integer) = number of y grid points 9 | % nz (integer) = number of z grid points 10 | % x (array) = x grid values (shape nz*ny*nx) 11 | % y (array) = y grid values (shape nz*ny*nx) 12 | % z (array) = z grid values (shape nz*ny*nx) 13 | % the field data is stored in an array with the name given by the string 14 | % in the field attribute (shape nz*ny*nx*nt) 15 | % 16 | % All singleton dimensions are flattened in the resulting arrays for the 17 | % grid points and field data 18 | 19 | [result currentdir] = system('pwd'); 20 | 21 | if nargin == 2 22 | datadir = [deblank(currentdir) '/']; 23 | end 24 | 25 | if datadir(end) ~= '/' 26 | datadir = [ datadir '/']; 27 | end 28 | 29 | cd(datadir); 30 | system(['cp ' probname '_' name '.m tmpfile.m']); 31 | eval('tmpfile'); 32 | system(['rm -f tmpfile.m']); 33 | cd(deblank(currentdir)); 34 | 35 | output.field = field; 36 | output.endian = endian; 37 | output.nt = nt; 38 | output.nx = nx; 39 | output.ny = ny; 40 | output.nz = nz; 41 | 42 | if nt > 1 43 | f = fopen([ datadir probname '_' name '_t.dat'], 'rb'); 44 | output.t = fread(f,[nt],'float64',endian); 45 | fclose(f); 46 | end 47 | f = fopen([ datadir probname '_' name '_x.dat'], 'rb'); 48 | output.x = squeeze(reshape(fread(f,nx*ny*nz,'float64',endian),[nz ny nx])); 49 | fclose(f); 50 | f = fopen([ datadir probname '_' name '_y.dat'], 'rb'); 51 | output.y = squeeze(reshape(fread(f,nx*ny*nz,'float64',endian), [nz ny nx])); 52 | fclose(f); 53 | try 54 | f = fopen([ datadir probname '_' name '_z.dat'], 'rb'); 55 | output.z = squeeze(reshape(fread(f,nx*ny*nz,'float64',endian),[nz ny nx])); 56 | fclose(f); 57 | end 58 | 59 | f = fopen([ datadir probname '_' name '_' field '.dat'], 'rb'); 60 | eval(['output.' field ' = squeeze(reshape(fread(f,nt*nx*ny*nz,''float64'',endian),[nz ny nx nt]))']); 61 | fclose(f); 62 | 63 | end -------------------------------------------------------------------------------- /src/readinput.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "problem.hpp" 7 | #include "rk.hpp" 8 | #include "mpi.h" 9 | 10 | using namespace std; 11 | 12 | // constructor given input file 13 | 14 | problem::problem(const string filename) { 15 | 16 | // set default values 17 | 18 | nt = 0; 19 | 20 | int rkorder; 21 | rkorder = 1; 22 | 23 | // put parameters into map to assign values to variables 24 | 25 | map inputmap; 26 | 27 | inputmap = readinput_problem(filename); 28 | 29 | // change default values to those in input file if necessary 30 | 31 | if (inputmap.count("nt") == 1) nt = atoi(inputmap["mode"].c_str()); 32 | if (inputmap.count("rkorder") == 1) rkorder = atoi(inputmap["rkorder"].c_str()); 33 | 34 | rk = rk_type(rkorder); 35 | 36 | } 37 | 38 | map problem::readinput_problem(const string file) { 39 | 40 | // reads and parses input file 41 | 42 | bool inputstart; 43 | string line, key, word; 44 | stringstream linestream; 45 | map inputmap; 46 | int rc; 47 | 48 | // open input file, find appropriate place, ignore empty and commented lines, read in parameters and store in inputmap 49 | 50 | ifstream paramfile(file, ios::in); 51 | if (paramfile.is_open()) { 52 | inputstart = false; 53 | while (getline(paramfile,line)) { 54 | if (line == "[fdfault.problem]") { 55 | inputstart = true; 56 | continue; 57 | } else if (line[0] == '[') { 58 | inputstart = false; 59 | continue; 60 | } 61 | if ((inputstart && line.length() > 0) && line[0] != '#') { 62 | linestream.clear(); 63 | linestream.str(""); 64 | linestream << line; 65 | getline(linestream,key,'='); 66 | key.erase( remove_if( key.begin(), key.end(), ::isspace ), key.end() ); 67 | getline(linestream,word,';'); 68 | word.erase( remove_if( word.begin(), word.end(), ::isspace ), word.end() ); 69 | inputmap[key] = word; 70 | } 71 | } 72 | } 73 | else { 74 | cerr << "Error reading input file\n"; 75 | MPI_Abort(MPI_COMM_WORLD, rc); 76 | } 77 | paramfile.close(); 78 | 79 | return inputmap; 80 | } -------------------------------------------------------------------------------- /python/fdfault/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | ``fdfault`` is a python module for setting up dynamic rupture problems for use with the C++ code. 3 | 4 | ================ 5 | Overview 6 | ================ 7 | 8 | The Python module closely resembles the structure of the text input files and hence the structure 9 | of the C++ code, and has an interface for specifying all simulation parameters through the 10 | ``problem`` class. The module is particularly useful for handling situations where inputs must be 11 | written to file in binary format. The module also includes functions that facilitate finding coordinate 12 | values nearest certain spatial locations for choosing indices for creating output units. 13 | 14 | One benefit in using the Python module is that the code performs an extensive series of checks 15 | prior to writing the simulation data to file. This, plus using the interfaces that are part of the 16 | ``problem`` class, grealy improves the likelihood that the simulation will be set up correctly, and 17 | is highly recommended if you will be using the code to simulate complex problems. 18 | 19 | While the module contains all classes (and you can set up simulations yourself using them), 20 | mostly you will be using the wrappers provided through the ``problem`` class, plus the constructors 21 | for ``surface``, ``curve``, ``material``, ``load``, ``loadfile``, ``swparam``, ``swparamfile``, ``stzparam``, 22 | ``stzparamfile``, ``statefile``, and ``output``. 23 | 24 | Details on the methods are provided in the documentation for the individual classes. 25 | 26 | =================== 27 | Requirements 28 | =================== 29 | 30 | The only external package required to use the Python module is NumPy, which uses numerical 31 | arrays to hold parameter values and writes them to file in binary format. The code has been tested 32 | starting with Numpy 1.9 and subsequent releases, though it will probably also work with some 33 | older versions. The code supports both Python 2 and Python 3 and has been tested on both 34 | versions of Python. 35 | """ 36 | 37 | from .block import block 38 | from .domain import domain 39 | from .fields import fields 40 | from .front import front 41 | from .interface import interface, friction, slipweak, stz 42 | from .pert import load, swparam, stzparam, loadfile, swparamfile, stzparamfile, statefile 43 | from .problem import problem 44 | from .material import material 45 | from .output import output 46 | from .surface import surface, curve, curve3d, points_to_curve, curves_to_surf, points_to_surf 47 | -------------------------------------------------------------------------------- /docs/examples/input_example.rst: -------------------------------------------------------------------------------- 1 | .. _input_example: 2 | 3 | ********************************** 4 | Example 2D Problem in Python 5 | ********************************** 6 | 7 | .. literalinclude:: ../../problems/input_example.py 8 | 9 | ``input_example.py`` illustrates how to set up a 2D problem with an irregular fault geometry and a uniform regional stress tensor. The diagram below shows the setup of the problem: 10 | 11 | .. image:: input_example.* 12 | :width: 6in 13 | 14 | Note that this illustration is not to scale when representing the height of the nonplanar fault surface (in the picture, the height of the fault curve is exaggerated). 15 | 16 | The problem is very similar to ``test2d.in``, but uses a Python file to handle the irregular coordinate geometry in order to automatically generate the files needed for the fault surface. In the python code, the surface is generated using numpy arrays and combined into a ``curve`` object. The ``curve`` object is then assigned to form the upper edge of the lower block and the lower edge of the upper block. The C++ code automatically handles grid generation once this boundary is specified for each block, so no additional information is require to set the mesh for the problem. However, if you attempt to set the two neighboring surfaces representing the fault to have different coordinates, the Python and C++ codes will give you an error message. 17 | 18 | Because this problem uses an irregular surface, the initial stress is set using a uniform background stress tensor, rather than by specifying tractions on the fault surface. When the stress tensor is resolved onto the irregular fault surface, the shear and normal tractions become spatially variable and the rupture will not propagate uniformly in both spatial directions. In particular, slip is easier to the right of the hypocenter due to the fact that the right side is a releasing bend, while to the left of the hypocenter, the fault constitutes a restraining bend such that slip is slightly inhibited. 19 | 20 | Other than these two differences, the problem setup is identical. This serves as an example of how to use the various classes in the Python module for creating a problem. In particular, the script uses the ``problem``, ``curve``, and ``output`` classes to handle the problem, curves representing block boundaries, and output units, respectively. In addition to these classes, the main additional class that is frequently used in creating problems is the ``material`` class, which sets the off-fault material properties in a given block. -------------------------------------------------------------------------------- /docs/examples/tpv5.tex: -------------------------------------------------------------------------------- 1 | \documentclass{standalone} 2 | \usepackage{tikz} 3 | \begin{document} 4 | \begin{tikzpicture}[line width=1pt] 5 | \draw (2, 2) rectangle (12, 7); 6 | \draw (4, 4) rectangle (14, 9); 7 | \draw[line width=1pt,<->] (0,-0.25) -- (5,-0.25) node[anchor=north]{40 km} -- (10, -0.25); 8 | \draw[line width=1pt,<->] (-0.25,0) -- (-0.25,2.5) node[anchor=east]{20 km} -- (-0.25, 5); 9 | \draw[line width=1pt,<->] (10.25,0) -- (11.25,1) node[anchor=north west]{20 km} -- (12.25, 2); 10 | \draw[line width=1pt,<->] (12.25,2) -- (13.25,3) node[anchor=north west]{20 km} -- (14.25, 4); 11 | \fill[color=darkgray] (2,2) -- (12, 2) -- (12, 7) -- (10.75, 7) -- (10.75, 3.25) -- (3.25, 3.25) -- (3.25, 7) -- (2, 7) -- (2,2); 12 | \draw[line width=1pt,<->] (2,1.75) -- (2.625,1.75) node[anchor=north]{5 km} -- (3.25, 1.75); 13 | \draw[line width=1pt,<->] (10.75,7.25) -- (11.4375, 7.25) node[anchor=south]{5 km} -- (12, 7.25); 14 | \draw[line width=1pt,<->] (1.75,2) -- (1.75,2.625) node[anchor=east]{5 km} -- (1.75, 3.25); 15 | \fill[color=gray] (6.625,4.6875) rectangle (7.375, 5.4375); 16 | \draw[color=gray] (7,5.4375) node[anchor=south]{Nucleation}; 17 | \fill[color=lightgray] (8.5,4.6875) rectangle (9.25, 5.4375); 18 | \draw[color=lightgray] (8.875,5.4375) node[anchor=south]{Reduced}; 19 | \fill[color=lightgray] (4.75,4.6875) rectangle (5.5, 5.4375); 20 | \draw[color=lightgray] (5.125,5.4375) node[anchor=south]{Elevated}; 21 | \draw[line width=1pt,<->] (6.625,4.5) -- (7,4.5) node[anchor=north]{3 km} -- (7.375, 4.5); 22 | \draw[line width=1pt,<->] (8.5,4.5) -- (8.875,4.5) node[anchor=north]{3 km} -- (9.25, 4.5); 23 | \draw[line width=1pt,<->] (4.75,4.5) -- (5.125,4.5) node[anchor=north]{3 km} -- (5.5, 4.5); 24 | \draw[line width=1pt,<->] (9.59,5.125) -- (9.59,6) node[anchor=west]{7.5 km} -- (9.59, 7); 25 | \draw[line width=1pt,<->] (4.5625,4.6875) -- (4.5625,5.2) node[anchor=east]{3 km} -- (4.5625, 5.4375); 26 | \draw[line width=1pt,<->] (2,6) -- (5,6) node[anchor=south]{20 km} -- (7, 6); 27 | \draw[line width=1pt,<->] (2,3.75) -- (4.25,3.75) node[anchor=north]{12.5 km} -- (5.125, 3.75); 28 | \draw[line width=1pt,<->] (2,6.75) -- (7,6.75) node[anchor=north]{27.5 km} -- (8.875, 6.75); 29 | \draw[line width=1pt,->] (0.5,7) -- (1.5,7) node[anchor=west]{$x$}; 30 | \draw[line width=1pt,->] (0.5,7) -- (1.207,7.707) node[anchor=south west]{$y$}; 31 | \draw[line width=1pt,->] (0.5,7) -- (0.5,8) node[anchor=south]{$z$}; 32 | \draw[line width=1pt, color=darkgray,->] (7,1.5) node[anchor=north]{Strong Barrier} -- (7,2); 33 | \draw (7,8) node{Free Surface}; 34 | \draw (0,0) rectangle (10,5); 35 | \draw (0, 0) -- (4, 4); 36 | \draw (0, 5) -- (4, 9); 37 | \draw (10, 0) -- (14, 4); 38 | \draw (10, 5) -- (14, 9); 39 | \end{tikzpicture} 40 | \end{document} -------------------------------------------------------------------------------- /src/stzparam.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "stzparam.hpp" 6 | #include "pert.hpp" 7 | 8 | stzparam::stzparam(const std::string type_in, const double t0_in, const double x0_in, const double dx_in, 9 | const double y0_in, const double dy_in, const int n[2], const int xm[2], const int xm_loc[2], 10 | const double x[2], const double l[2], const double v0_in, const double f0_in, 11 | const double a_in, const double muy_in, const double c0_in, const double R_in, 12 | const double beta_in, const double chiw_in, const double v1_in) : pert(type_in, t0_in, x0_in, dx_in, y0_in, dy_in, n, xm, xm_loc, x, l) { 13 | // constructor 14 | 15 | v0 = v0_in; 16 | f0 = f0_in; 17 | a = a_in; 18 | muy = muy_in; 19 | c0 = c0_in; 20 | R = R_in; 21 | beta = beta_in; 22 | chiw = chiw_in; 23 | v1 = v1_in; 24 | 25 | } 26 | 27 | double stzparam::get_v0(const int i, const int j, const double t) const { 28 | // returns reference velocity perturbation 29 | 30 | return v0*xyfunc(i,j)*tfunc(t); 31 | } 32 | 33 | double stzparam::get_f0(const int i, const int j, const double t) const { 34 | // returns reference activation barrier perturbation 35 | 36 | return f0*xyfunc(i,j)*tfunc(t); 37 | } 38 | 39 | double stzparam::get_a(const int i, const int j, const double t) const { 40 | // returns direct effect perturbation 41 | 42 | return a*xyfunc(i,j)*tfunc(t); 43 | } 44 | 45 | double stzparam::get_muy(const int i, const int j, const double t) const { 46 | // returns reference velocity perturbation 47 | 48 | return muy*xyfunc(i,j)*tfunc(t); 49 | } 50 | 51 | double stzparam::get_c0(const int i, const int j, const double t) const { 52 | // returns specific heat perturbation 53 | 54 | return c0*xyfunc(i,j)*tfunc(t); 55 | } 56 | 57 | double stzparam::get_R(const int i, const int j, const double t) const { 58 | // returns relaxation rate perturbation 59 | 60 | return R*xyfunc(i,j)*tfunc(t); 61 | } 62 | 63 | double stzparam::get_beta(const int i, const int j, const double t) const { 64 | // returns stz relaxation barrier perturbation 65 | 66 | return beta*xyfunc(i,j)*tfunc(t); 67 | } 68 | 69 | double stzparam::get_chiw(const int i, const int j, const double t) const { 70 | // returns effective temperature activation barrier perturbation 71 | 72 | return chiw*xyfunc(i,j)*tfunc(t); 73 | } 74 | 75 | double stzparam::get_v1(const int i, const int j, const double t) const { 76 | // returns effective temperature melting velocity perturbation 77 | 78 | return v1*xyfunc(i,j)*tfunc(t); 79 | } 80 | -------------------------------------------------------------------------------- /docs/examples/tpv5.rst: -------------------------------------------------------------------------------- 1 | .. _tpv5: 2 | 3 | ********************************** 4 | The Problem, Version 5 5 | ********************************** 6 | 7 | This example illustrates use of a Python input file for a 3D problem. The problem is similar to ``tpv4.in``, but includes additional stress heterogeneity on the fault. Additionally, this example illustrates how the Python module can be used to query the grid for a problem in order to find grid indices that correspond to a particular spatial location in order to choose output locations. 8 | 9 | .. literalinclude:: ../../problems/tpv5.py 10 | 11 | The following shows the model geometry: 12 | 13 | .. image:: tpv5.* 14 | :width: 6in 15 | 16 | The problem uses the same block setup as ``tpv4.in``, with two patches on the fault with different initial shear stresses on the fault. To the right of the hypocenter, there is a patch with reduced shear stress, and to the left of the hypocenter, there is a patch with increased shear stress. These patches are implemented using the ``load`` class, which is used to specify the various traction perturbations in the problem. Each one of the stress heterogeneities is implemented with the ``'boxcar'`` perturbation, which is a rectangular patch with a constant stress inside that falls to zero outside the rectangular patch. Otherwise, the setup is identical to ``tpv4.in``. 17 | 18 | One additional capability illustrated in this example is the use of the ``find_nearest_point`` method of a problem. Once the simulation geometry has been specified, this method generates a grid on the fly in order to query the grid and find the closest point to the location specified. ``find_nearest_point`` can be used to find points in the 3D volume (the case where ``find_nearest_point`` is called with a tuple of length 3 of floats representing spatial coordinates), or along a 2D slice in order to find points on an interface such as a fault (the case where ``find_nearest_point`` is called with the ``known`` and ``knownloc`` arguments). For the 3D version, the method simply finds the nearest point to the given coordinates. For the 2D version, the search is only carried out in 2 directions while the coordinate specified by ``known`` is held constant with the index given by ``knownloc``. Once the nearest indices to the point in question are found, that point is added to the output list using the ``output`` class. 19 | 20 | **A note to users:** as with ``tpv4.in``, the standard resolution for this problem is such that the problem will run on a powerful desktop system with multiple processors. However, this is not sufficient for simulations for publication in a scientific jounral or other practical application, and simulations of those magnitudes will likely require a multi-node computer cluster to run the simulation in a reasonable amount of time. -------------------------------------------------------------------------------- /docs/input/text/fields.rst: -------------------------------------------------------------------------------- 1 | .. _fields: 2 | 3 | ********************************** 4 | Fields Input 5 | ********************************** 6 | 7 | The initial stress fields are set with the ``[fdfault.fields]`` header. This section has four entries: :: 8 | 9 | Uniform initial stress tensor 10 | Filename for spatially heterogeneous initial stress tensor 11 | Filename for spatially heterogeneous elastic properties 12 | Boolean indicating if full plastic strain tensor is calculated 13 | 14 | The uniform initial stress tensor is a list of 6 numbers, and the order is :math:`{\sigma_{xx}}`, :math:`{\sigma_{xy}}`, :math:`{\sigma_{xz}}`, :math:`{\sigma_{yy}}`, :math:`{\sigma_{yz}}`, :math:`{\sigma_{zz}}`). Components not involved in a 2D problem are in some cases used in the problem, particularly for anti-plane (mode 3) problems, where the in-plane normal stress components determine the compressive normal stresses acting on the fault. Line breaks are ignored. 15 | 16 | If a heterogeneous stress tensor will be used, it is specified with a filename here. If no heterogeneous file is to be read, this entry should be ``none``. The file should contain a sequence of double precision binary floating point numbers (endianness should match the processor where the code will be run). Components are entered one at a time, with the number of entries matching the grid size using row major order (C order). For 2D mode 3 problems, the order is :math:`{\sigma_{xz}}`, :math:`{\sigma_{yz}}`. For 2D mode 2 problems, the order is :math:`{\sigma_{xx}}`, :math:`{\sigma_{xy}}`, :math:`{\sigma_{yy}}` (and for plasticity problems, :math:`{\sigma_{zz}}`). For 3D problems, the order is the same as for the uniform stress tensor. Entering heterogeneous stresses is greatly simplified if you use the Python module. Also note that entering the full heterogeneous stress tensor required additional memory. 17 | 18 | Similarly, if a heterogeneous elastic properties will be used, it is specified with a filename here. If no heterogeneous file is to be read, this entry should be ``none``. The format is the same as the stress tensor, but with three entries: density, first Lamé parameter, and shear modulus. Creation of these files is simplified with the Python module. 19 | 20 | **Note:** for large 3D problems, the arrays for a heterogeneous stress field or elastic property may be too large to be handles by the Python module (Numpy seems to be limited to arrays that are 2 or 4 GB, depending on the version of Python that you use). In that case, you may need to generate these files manually. 21 | 22 | The final a boolean (0 or 1) indicates whether or not the full plastic strain tensor is computed for plastic problems. This is an option because saving the full tensor requires significant additional memory. To turn it on, 0 should be entered here. This entry is ignored for elastic problems. 23 | -------------------------------------------------------------------------------- /docs/examples/tpv4.rst: -------------------------------------------------------------------------------- 1 | .. _tpv4: 2 | 3 | ********************************** 4 | The Problem, Version 4 5 | ********************************** 6 | 7 | This problem is an example of how to set up a 3D problem using a text input file. 8 | 9 | .. literalinclude:: ../../problems/tpv4.in 10 | 11 | As with the 2D example using a text file, the problem setup is relatively simple. The following shows the model geometry: 12 | 13 | .. image:: tpv4.* 14 | :width: 6in 15 | 16 | The setup is analogous to ``test2d.in``, with a few modifications necessary to define a 3D problem. Mainly, this involves specifying the simulation in the 3rd spatial dimension, so that each block needs an additional set of input parameters to describe its location, length, boundary conditions, and bounding surfaces. Because the 3D simulation includes the earth's surface, the external boundary condition in the :math:`{z}` direction is a traction free surface, which is specified by setting the appropriate boundary condition to ``free`` for each block. Otherwise, the simulation is analogous to the 2D test problem that is also included. 17 | 18 | While the remainder of the simulation closely parallels that of ``test2d.in``, one important difference is in regards to the output that is saved. In this 3D problem, in addition to a few output units on the fault, the rupture front times are saved to disk. This falls under the ``frontlist`` portion of the input file. The ``front`` will automatically save the earliest time for which a chosen field (``U`` for slip and ``V`` for slip rate) exceeds a threshold value on all frictional interfaces in the problem. For this particular case, we choose ``V`` for the field and ``0.001`` for the threshold, meaning that the rupture time is defined to be the first time point where the slip rate exceeds this threshold. If a point does not rupture, then the rupture time is ``-1.`` and this value is written to disk for the point in question. The code keeps track of this information and then saves the information to disk, which can be loaded into a ``front`` object defined in the ``analysis`` portion of the Python module. 19 | 20 | **A note to users:** the problem resolution specified here uses a grid spacing of 200 m. This is not likely to result in a well-resolved solution appropriate for a scientific publication or any other technical application. Rather, this number is chosen as it results in a problem that will run on a high powered desktop computer in a reasonable amount of time (on an 8 core Mac Pro desktop, this is about 1 hour when using all processors). In general, 3D problems are highly computationally intensive, and running simulations that are adequetely resolved typicaly require much more significant computational resources such as a multi-node cluster. A resolution of 100 m or 50 m with this size of problem gives much better results, though many users may not have easy access to a cluster of the size needed to simulate such problems. (Note that for 3D problems, increasing the resolution increases the computational load by a factor of 16, as the number of grid points in each of three spatial dimensions doubles and the number of time steps also doubles.) -------------------------------------------------------------------------------- /docs/input/text/block.rst: -------------------------------------------------------------------------------- 1 | .. _block: 2 | 3 | ********************************** 4 | Block Input 5 | ********************************** 6 | 7 | Each block has its own section in the input file, designated by ``[fdfault.blockXYZ]`` for the block with indices :math:`{(X,Y,Z)}` (the code assumes zero indexing). For each block, the input file entries set the material properties, boundary conditions, and geometry. The input file must contain a header for each block in the simulation, and other block headers that do not match a block in the simulation are ignored. Order is not important. Specific entries are as follows: :: 8 | 9 | Material properties 10 | Block lower left coordinate 11 | Block side lengths 12 | Block boundary conditions 13 | Block boundary filenames 14 | 15 | The number of entries expected in each item depends on the type of problem being solved, and are explained below. 16 | 17 | The material properties are the density :math:`{\rho}`, Lamé constant :math:`{\lambda}`, and shear modulus :math:`{G}`, and for plasticity problems the parameters defined in the yield function and flow rule. Order for the plasticity parameters is internal friction :math:`{\mu}`, cohesion :math:`{c}`, dilatancy :math:`{\beta}`, and viscosity :math:`{\eta}`. 18 | 19 | The lower left coordinate of the block determines its location in space, and requires 2 numbers for 2D problems and 3 numbers for 3D problems. Similarly, the block side lengths require the same number of entries for 2D and 3D problems. These coordinate values are used to create any boundary surfaces that are not set through a file by creating rectangular surfaces (in 3D) and straight lines (in 2D) for the appropriate block sides. If all sides are given as a file, these entries are ignored in creating the grid, though they are still used in adding surface tractions to frictional faults and modifying friction parameters. 20 | 21 | The block boundary conditions is a list of 4 boundary conditions for 2D problems, and 6 boundary conditions for 3D problems. Order is left, right, front, back, top, bottom (where top and bottom are only for 3D problems). Each boundary condition must be one of the following strings: ``absorbing`` (no waves enter the domain), ``free`` (traction free surface), ``rigid`` (zero velocity), or ``none`` (do not apply a boundary condition, used if block is coupled to another through an interface). 22 | 23 | Boundaries that are defined via a filename derive their data from files that contain binary data, rather than assuming a rectangular block edge. This method can be used to create non-planar block surfaces. The number of entries and order is the same as for the boundary conditions. Each file must contain double precision floating point binary data, with all :math:`{x}` coordinates in row major (C) order, followed by all :math:`{y}` coordinates, and if a 3D problem, all :math:`{z}` coordinates. Endianness is set by the computer where the simulation will be run. When setting nonplanar boundaries, the surfaces must conform at their edges, and the code checks this during initialization. While you can easily create your own files for defining nonplanar boundaries, this is made much simpler with the Python module. -------------------------------------------------------------------------------- /src/frontlist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "domain.hpp" 5 | #include "frontlist.hpp" 6 | #include "front.hpp" 7 | #include 8 | 9 | using namespace std; 10 | 11 | frontlist::frontlist(const char* filename, const string probname, const string datadir, const domain& d) { 12 | // constructor 13 | 14 | rootunit = 0; 15 | 16 | front* cunit = rootunit; 17 | front* nunit; 18 | 19 | // reads input from outlist in input file 20 | 21 | bool has_front; 22 | string line, field; 23 | double value; 24 | 25 | // open input file, find appropriate place and read in parameters 26 | 27 | ifstream paramfile(filename, ifstream::in); 28 | if (paramfile.is_open()) { 29 | // scan to start of outputlist 30 | while (getline(paramfile,line)) { 31 | if (line == "[fdfault.frontlist]") { 32 | break; 33 | } 34 | } 35 | if (paramfile.eof()) { 36 | cerr << "Error reading frontlist from input file\n"; 37 | MPI_Abort(MPI_COMM_WORLD,-1); 38 | } else { 39 | // read front values from file 40 | paramfile >> has_front; 41 | if (has_front) { 42 | paramfile >> field; 43 | paramfile >> value; 44 | } 45 | } 46 | } else { 47 | cerr << "Error opening input file in frontlist.cpp\n"; 48 | MPI_Abort(MPI_COMM_WORLD,-1); 49 | } 50 | paramfile.close(); 51 | 52 | // if front output desired, create fronts for all frictional interfaces 53 | 54 | if (!has_front) { return; } 55 | 56 | int nifaces = d.get_nifaces(); 57 | 58 | for (int i = 0; iis_friction) { 60 | cunit = new front(probname, datadir, field, value, i, d); 61 | if (!rootunit) { 62 | rootunit = cunit; 63 | nunit = rootunit; 64 | } else { 65 | nunit->set_next_unit(cunit); 66 | nunit = nunit->get_next_unit(); 67 | } 68 | } 69 | } 70 | 71 | } 72 | 73 | frontlist::~frontlist() { 74 | 75 | front* ounit = rootunit; 76 | front* cunit = rootunit; 77 | 78 | while (ounit) { 79 | cunit = cunit->get_next_unit(); 80 | delete ounit; 81 | ounit = cunit; 82 | } 83 | } 84 | 85 | void frontlist::set_front(const double t, const domain& d) { 86 | // writes fronts 87 | 88 | front* cunit = rootunit; 89 | 90 | // traverse list, calling write_front for each 91 | 92 | while (cunit) { 93 | cunit->set_front(t, d); 94 | cunit = cunit->get_next_unit(); 95 | } 96 | 97 | } 98 | 99 | void frontlist::write_list(const domain& d) { 100 | // sets fronts 101 | 102 | front* cunit = rootunit; 103 | 104 | // traverse list, calling set_front for each 105 | 106 | while (cunit) { 107 | cunit->write_front(d); 108 | cunit = cunit->get_next_unit(); 109 | } 110 | } -------------------------------------------------------------------------------- /src/coord.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "coord.hpp" 4 | 5 | coord::coord() { 6 | // constructor 7 | 8 | for (int i=0; i<3; i++) { 9 | nx[i] = 1; 10 | xm[i] = 0; 11 | nx_loc[i] = 1; 12 | xm_loc[i] = 0; 13 | xm_ghost[i] = 0; 14 | xp_ghost[i] = 0; 15 | } 16 | } 17 | 18 | int coord::get_nx(const int index) const { 19 | assert(index >=0 && index < 3); 20 | return nx[index]; 21 | } 22 | 23 | int coord::get_xm(const int index) const { 24 | assert(index >=0 && index < 3); 25 | return xm[index]; 26 | } 27 | 28 | int coord::get_xp(const int index) const { 29 | assert(index >=0 && index < 3); 30 | return xm[index] + nx[index] - 1; 31 | } 32 | 33 | int coord::get_nx_loc(const int index) const { 34 | assert(index >=0 && index < 3); 35 | return nx_loc[index]; 36 | } 37 | 38 | int coord::get_nx_tot(const int index) const { 39 | assert(index >=0 && index < 3); 40 | return xm_ghost[index] + nx_loc[index] + xp_ghost[index]; 41 | } 42 | 43 | int coord::get_xm_loc(const int index) const { 44 | assert(index >=0 && index < 3); 45 | return xm_loc[index]; 46 | } 47 | 48 | int coord::get_xp_loc(const int index) const { 49 | assert(index >=0 && index < 3); 50 | return xm_loc[index] + nx_loc[index] - 1; 51 | } 52 | 53 | int coord::get_xm_ghost(const int index) const { 54 | assert(index >=0 && index < 3); 55 | return xm_ghost[index]; 56 | } 57 | 58 | int coord::get_xp_ghost(const int index) const { 59 | assert(index >=0 && index < 3); 60 | return xp_ghost[index]; 61 | } 62 | 63 | int coord::get_min_loc(const int index) const { 64 | assert(index >=0 && index < 3); 65 | return xm_ghost[index]; 66 | } 67 | 68 | int coord::get_max_loc(const int index) const { 69 | assert(index >=0 && index < 3); 70 | return xm_ghost[index] + nx_loc[index]; 71 | } 72 | 73 | void coord::set_nx(const int index, const int new_nx) { 74 | assert(index >=0 && index < 3); 75 | assert(new_nx >= 0); 76 | 77 | nx[index] = new_nx; 78 | } 79 | 80 | void coord::set_xm(const int index, const int new_xm) { 81 | assert(index >=0 && index < 3); 82 | assert(new_xm >= 0); 83 | 84 | xm[index] = new_xm; 85 | } 86 | 87 | void coord::set_nx_loc(const int index, const int new_nx) { 88 | assert(index >=0 && index < 3); 89 | assert(new_nx >= 0); 90 | assert(new_nx <= nx[index]); 91 | 92 | nx_loc[index] = new_nx; 93 | } 94 | 95 | void coord::set_xm_loc(const int index, const int new_xm) { 96 | assert(index >=0 && index < 3); 97 | assert(new_xm >= 0); 98 | assert(new_xm >= xm[index]); 99 | assert(new_xm + nx_loc[index] <= xm[index] + nx[index]); 100 | 101 | xm_loc[index] = new_xm; 102 | } 103 | 104 | void coord::set_xm_ghost(const int index, const int new_xm) { 105 | assert(index >=0 && index < 3); 106 | assert(new_xm >= 0); 107 | assert(new_xm + nx_loc[index] + xp_ghost[index] <= nx[index]); 108 | 109 | xm_ghost[index] = new_xm; 110 | } 111 | 112 | void coord::set_xp_ghost(const int index, const int new_xp) { 113 | assert(index >=0 && index < 3); 114 | assert(new_xp >= 0); 115 | assert(xm_ghost[index] + nx_loc[index] + new_xp <= nx[index]); 116 | 117 | xp_ghost[index] = new_xp; 118 | } 119 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | CC=mpic++ 2 | CFLAGS=-c -O3 3 | EFLAGS=-O3 4 | EXEC=../fdfault 5 | 6 | fdfault : block.o boundary.o cartesian.o coord.o domain.o fd.o fields.o friction.o front.o frontlist.o interface.o load.o main.o material.o outputlist.o outputunit.o pert.o problem.o rk.o slipweak.o swparam.o stz.o stzparam.o surface.o utilities.o 7 | $(CC) $(EFLAGS) -o $(EXEC) block.o boundary.o cartesian.o coord.o domain.o \ 8 | fd.o fields.o friction.o front.o frontlist.o interface.o load.o main.o material.o \ 9 | outputlist.o outputunit.o pert.o problem.o rk.o slipweak.o swparam.o stz.o stzparam.o surface.o utilities.o 10 | 11 | block.o : block.hpp boundary.hpp cartesian.hpp coord.hpp fd.hpp material.hpp surface.hpp block.cpp 12 | $(CC) $(CFLAGS) block.cpp 13 | 14 | boundary.o : boundary.hpp cartesian.hpp coord.hpp fd.hpp fields.hpp material.hpp boundary.cpp 15 | $(CC) $(CFLAGS) boundary.cpp 16 | 17 | cartesian.o : cartesian.hpp coord.hpp cartesian.cpp 18 | $(CC) $(CFLAGS) cartesian.cpp 19 | 20 | coord.o : coord.hpp coord.cpp 21 | $(CC) $(CFLAGS) coord.cpp 22 | 23 | domain.o : block.hpp cartesian.hpp domain.hpp fd.hpp fields.hpp friction.hpp interface.hpp rk.hpp slipweak.hpp stz.hpp domain.cpp 24 | $(CC) $(CFLAGS) domain.cpp 25 | 26 | fd.o : fd.hpp coord.hpp fd.cpp 27 | $(CC) $(CFLAGS) fd.cpp 28 | 29 | fields.o : fields.hpp coord.hpp cartesian.hpp fields.cpp 30 | $(CC) $(CFLAGS) fields.cpp 31 | 32 | friction.o : block.hpp cartesian.hpp fd.hpp fields.hpp friction.hpp interface.hpp load.hpp utilities.h friction.cpp 33 | $(CC) $(CFLAGS) friction.cpp 34 | 35 | front.o : cartesian.hpp domain.hpp fields.hpp front.hpp interface.hpp utilities.h front.cpp 36 | $(CC) $(CFLAGS) front.cpp 37 | 38 | frontlist.o : domain.hpp front.hpp frontlist.hpp frontlist.cpp 39 | $(CC) $(CFLAGS) frontlist.cpp 40 | 41 | interface.o : block.hpp boundary.hpp cartesian.hpp coord.hpp fields.hpp interface.hpp interface.cpp 42 | $(CC) $(CFLAGS) interface.cpp 43 | 44 | load.o : load.hpp pert.hpp load.cpp 45 | $(CC) $(CFLAGS) load.cpp 46 | 47 | main.o : problem.hpp main.cpp 48 | $(CC) $(CFLAGS) main.cpp 49 | 50 | material.o : material.hpp material.cpp 51 | $(CC) $(CFLAGS) material.cpp 52 | 53 | outputlist.o : domain.hpp outputlist.hpp outputunit.hpp outputlist.cpp 54 | $(CC) $(CFLAGS) outputlist.cpp 55 | 56 | outputunit.o : cartesian.hpp domain.hpp outputunit.hpp utilities.h outputunit.cpp 57 | $(CC) $(CFLAGS) outputunit.cpp 58 | 59 | pert.o : pert.hpp pert.cpp 60 | $(CC) $(CFLAGS) pert.cpp 61 | 62 | problem.o : domain.hpp outputlist.hpp frontlist.hpp problem.hpp rk.hpp problem.cpp 63 | $(CC) $(CFLAGS) problem.cpp 64 | 65 | rk.o : rk.hpp rk.cpp 66 | $(CC) $(CFLAGS) rk.cpp 67 | 68 | slipweak.o : block.hpp cartesian.hpp fd.hpp fields.hpp friction.hpp interface.hpp swparam.hpp slipweak.hpp utilities.h slipweak.cpp 69 | $(CC) $(CFLAGS) slipweak.cpp 70 | 71 | swparam.o : pert.hpp swparam.hpp swparam.cpp 72 | $(CC) $(CFLAGS) swparam.cpp 73 | 74 | stz.o : block.hpp cartesian.hpp fd.hpp fields.hpp friction.hpp interface.hpp stzparam.hpp stz.hpp utilities.h stz.cpp 75 | $(CC) $(CFLAGS) stz.cpp 76 | 77 | stzparam.o : pert.hpp stzparam.hpp stzparam.cpp 78 | $(CC) $(CFLAGS) stzparam.cpp 79 | 80 | surface.o : coord.hpp surface.hpp surface.cpp 81 | $(CC) $(CFLAGS) surface.cpp 82 | 83 | utilities.o : utilities.h utilities.cpp 84 | $(CC) $(CFLAGS) utilities.cpp 85 | 86 | clean: 87 | rm *.o $(EXEC) -------------------------------------------------------------------------------- /src/material.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "material.hpp" 4 | 5 | material::material() { 6 | // constructor 7 | 8 | // set all properties to default values 9 | // units can be set to any desired units, however the default values have one thing 10 | // of note: default density has funny units of MPa s^2 / km / m such that measuring 11 | // velocity in m/s, stress in MPa, and distance in km will lead to correct unit scaling 12 | // similarly, with these choices, measuring moduli in GPa (= MPa km / m) will give 13 | // correct values 14 | 15 | rho = 2.67; 16 | lambda = 32.04; 17 | g = 32.04; 18 | mu = 0.5735; 19 | beta = 0.2867; 20 | eta = 0.2775; 21 | c = 0.; 22 | } 23 | 24 | void material::set_rho(const double newrho) { 25 | // sets density 26 | assert(newrho > 0.); 27 | 28 | rho = newrho; 29 | } 30 | 31 | void material::set_lambda(const double newlambda) { 32 | // sets first lame parameter 33 | 34 | assert(newlambda > 0.); 35 | 36 | lambda = newlambda; 37 | } 38 | 39 | void material::set_g(const double newg) { 40 | // sets shear modulus 41 | 42 | assert(newg > 0.); 43 | 44 | g = newg; 45 | } 46 | 47 | void material::set_mu(const double newmu) { 48 | // sets plasticity internal friction 49 | 50 | assert(newmu > 0.); 51 | 52 | mu = newmu; 53 | } 54 | 55 | void material::set_beta(const double newbeta) { 56 | // sets plasticity dilatancy 57 | 58 | assert(newbeta >= 0.); 59 | 60 | beta = newbeta; 61 | } 62 | 63 | 64 | void material::set_eta(const double neweta) { 65 | // sets plasticity viscosity 66 | 67 | assert(neweta >= 0.); 68 | 69 | eta = neweta; 70 | } 71 | 72 | void material::set_c(const double newc) { 73 | // sets material cohesion 74 | 75 | assert(newc >= 0.); 76 | 77 | c = newc; 78 | } 79 | 80 | double material::get_rho() const { 81 | // returns density 82 | 83 | return rho; 84 | } 85 | 86 | double material::get_lambda() const { 87 | // returns first lame parameter 88 | 89 | return lambda; 90 | } 91 | 92 | double material::get_g() const { 93 | // returns shear modulus 94 | 95 | return g; 96 | } 97 | 98 | double material::get_mu() const { 99 | // returns plasticity internal friction 100 | 101 | return mu; 102 | } 103 | 104 | double material::get_beta() const { 105 | // returns plastic dilatancy 106 | 107 | return beta; 108 | } 109 | 110 | double material::get_eta() const { 111 | // returns plastic viscosity 112 | 113 | return eta; 114 | } 115 | 116 | double material::get_c() const { 117 | // returns cohesion 118 | 119 | return c; 120 | } 121 | 122 | double material::get_cs() const { 123 | // returns shear wave speed 124 | 125 | return sqrt(g/rho); 126 | } 127 | 128 | double material::get_cp() const { 129 | // returns dilatational wave speed 130 | 131 | return sqrt((lambda+2.*g)/rho); 132 | } 133 | 134 | double material::get_zs() const { 135 | // returns shear wave speed 136 | 137 | return rho*get_cs(); 138 | } 139 | 140 | double material::get_zp() const { 141 | // returns dilatational wave speed 142 | 143 | return rho*get_cp(); 144 | } 145 | -------------------------------------------------------------------------------- /src/outputlist.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "domain.hpp" 5 | #include "outputlist.hpp" 6 | #include "outputunit.hpp" 7 | #include 8 | 9 | using namespace std; 10 | 11 | outputlist::outputlist(const char* filename, const string probname, const string datadir, const int nt, const domain& d) { 12 | // constructor 13 | 14 | rootunit = 0; 15 | 16 | outputunit* cunit = rootunit; 17 | outputunit* nunit; 18 | 19 | // reads input from outlist in input file 20 | 21 | bool inputstart; 22 | string line, name, field; 23 | int tm, tp, ts, xm[3], xp[3], xs[3]; 24 | 25 | // open input file, find appropriate place and read in parameters 26 | 27 | ifstream paramfile(filename, ifstream::in); 28 | if (paramfile.is_open()) { 29 | // scan to start of outputlist 30 | while (getline(paramfile,line)) { 31 | if (line == "[fdfault.outputlist]") { 32 | break; 33 | } 34 | } 35 | if (paramfile.eof()) { 36 | cerr << "Error reading outputlist from input file\n"; 37 | MPI_Abort(MPI_COMM_WORLD,-1); 38 | } else { 39 | // read next output unit 40 | while (getline(paramfile, line)) { 41 | if (line.empty()) { 42 | break; 43 | } else { 44 | // read in next item 45 | name = line; 46 | paramfile >> field; 47 | paramfile >> tm; 48 | paramfile >> tp; 49 | paramfile >> ts; 50 | for (int i=0; i<3; i++) { 51 | paramfile >> xm[i]; 52 | paramfile >> xp[i]; 53 | paramfile >> xs[i]; 54 | } 55 | // skip over newline 56 | getline(paramfile, line); 57 | // traverse list and add onto end 58 | cunit = new outputunit(probname, datadir, nt, tm, tp, ts, xm, xp, xs, field, name, d); 59 | if (!rootunit) { 60 | rootunit = cunit; 61 | nunit = rootunit; 62 | } else { 63 | nunit->set_next_unit(cunit); 64 | nunit = nunit->get_next_unit(); 65 | } 66 | } 67 | } 68 | } 69 | } else { 70 | cerr << "Error opening input file in outputlist.cpp\n"; 71 | MPI_Abort(MPI_COMM_WORLD,-1); 72 | } 73 | paramfile.close(); 74 | 75 | } 76 | 77 | outputlist::~outputlist() { 78 | 79 | outputunit* ounit = rootunit; 80 | outputunit* cunit = rootunit; 81 | 82 | while (ounit) { 83 | cunit = cunit->get_next_unit(); 84 | delete ounit; 85 | ounit = cunit; 86 | } 87 | } 88 | 89 | void outputlist::write_list(const int tstep, const double dt, const domain& d) { 90 | // writes outputlist units 91 | 92 | outputunit* cunit = rootunit; 93 | 94 | // traverse list, calling write_unit for each 95 | 96 | while (cunit) { 97 | cunit->write_unit(tstep,dt,d); 98 | cunit = cunit->get_next_unit(); 99 | } 100 | 101 | } 102 | 103 | void outputlist::close_list() { 104 | // writes outputlist units 105 | 106 | outputunit* cunit = rootunit; 107 | 108 | // traverse list, calling close_file for each 109 | 110 | while (cunit) { 111 | cunit->close_file(); 112 | cunit = cunit->get_next_unit(); 113 | } 114 | } -------------------------------------------------------------------------------- /problems/tpv5.py: -------------------------------------------------------------------------------- 1 | import fdfault 2 | import numpy as np 3 | 4 | # create problem 5 | 6 | p = fdfault.problem('tpv5') 7 | 8 | # set rk and fd order 9 | 10 | p.set_rkorder(4) 11 | p.set_sbporder(4) 12 | 13 | # set time step info 14 | 15 | refine = 1 16 | nt = 700*refine 17 | 18 | p.set_nt(nt) 19 | p.set_cfl(0.3) 20 | p.set_ninfo(50*refine) 21 | 22 | p.set_ndim(3) 23 | 24 | # set number of blocks and coordinate information 25 | 26 | nx = 200*refine+1 27 | ny = 100*refine+1 28 | nz = 100*refine+1 29 | 30 | p.set_nblocks((1,2,1)) 31 | p.set_nx_block(([nx], [ny, ny], [nz])) 32 | 33 | # set block dimensions 34 | 35 | p.set_block_lx((0,0,0),(40.,20., 20.)) 36 | p.set_block_lx((0,1,0),(40.,20., 20.)) 37 | 38 | p.set_domain_xm((-20., -20., -20.)) 39 | 40 | # set block boundary conditions 41 | 42 | p.set_bounds((0,0,0),['absorbing', 'absorbing', 'absorbing', 'none', 'absorbing', 'free']) 43 | p.set_bounds((0,1,0),['absorbing', 'absorbing', 'none', 'absorbing', 'absorbing', 'free']) 44 | 45 | # turn on artificial dissipation 46 | 47 | #p.set_cdiss(0.1) 48 | 49 | # set material 50 | 51 | cs = 3.464 52 | cp = 6. 53 | rho = 2.67 54 | 55 | p.set_material(fdfault.material('elastic', rho, rho*(cp**2-2.*cs**2), rho*cs**2)) 56 | 57 | # set interface type 58 | 59 | p.set_iftype(0,'slipweak') 60 | 61 | # set slip weakening parameters 62 | 63 | p.add_pert(fdfault.swparam('constant',0., 0., 0., 0., 0., 0.4, 0.677, 0.525)) 64 | p.add_pert(fdfault.swparam('boxcar',0., 0., 20., -17.55, 2.5, 0., 10000., 0., 10.)) 65 | p.add_pert(fdfault.swparam('boxcar',0., -17.55, 2.5, -7.5, 7.5, 0., 10000., 0., 10.)) 66 | p.add_pert(fdfault.swparam('boxcar',0., 17.55, 2.5, -7.5, 7.5, 0., 10000., 0., 10.)) 67 | 68 | # add load perturbations 69 | 70 | p.add_load(fdfault.load('constant',0., 0., 0., 0., 0., -120., 70., 0.)) 71 | p.add_load(fdfault.load('boxcar',0., 0., 1.5, -7.5, 1.5, 0., 11.6, 0.)) 72 | p.add_load(fdfault.load('boxcar',0., -7.5, 1.5, -7.5, 1.5, 0., 8., 0.)) 73 | p.add_load(fdfault.load('boxcar',0., 7.5, 1.5, -7.5, 1.5, 0., -8., 0.)) 74 | 75 | # add output unit 76 | 77 | #p.add_output(fdfault.output('vf','V',0, nt, 5*refine, 0, nx-1, refine, ny, ny, 1, 0, nz-1, refine)) 78 | 79 | # on fault stations 80 | 81 | onfault = [('-120', '000'), ('-075', '000'), ('-045', '000'), ('000', '000'), ('045', '000'), ('075', '000'), ('120', '000'), 82 | ('000', '030'), ('-120', '075'), ('-075', '075'), ('-045', '075'), ('000', '075'), ('045', '075'), ('075', '075'), ('120', '075'), 83 | ('000', '120')] 84 | fields = ['h-slip', 'h-slip-rate', 'h-shear-stress', 'v-slip', 'v-slip-rate', 'v-shear-stress'] 85 | fname = ['Ux', 'Vx', 'Sx', 'Uz', 'Vz', 'Sz'] 86 | for station in onfault: 87 | xcoord = float(station[0])/10. 88 | zcoord = -float(station[1])/10. 89 | xpt, ypt, zpt = p.find_nearest_point((xcoord, 0., zcoord), known='y', knownloc=ny) 90 | for fld, fn in zip(fields, fname): 91 | p.add_output(fdfault.output('faultst'+station[0]+'dp'+station[1]+'-'+fld, fn, 0, nt, 1, xpt, xpt, 1, 92 | ypt, ypt, 1, zpt, zpt, 1)) 93 | 94 | 95 | # off fault stations 96 | 97 | offfault = [('030', '-120', '000'), ('030', '120', '000'), ('030', '-120', '075'), ('030', '120', '075')] 98 | fields = ['h-vel', 'v-vel', 'n-vel'] 99 | fname = ['vx', 'vz', 'vy'] 100 | 101 | for station in offfault: 102 | xcoord = float(station[1])/10. 103 | ycoord = float(station[0])/10. 104 | zcoord = -float(station[2])/10. 105 | xpt, ypt, zpt = p.find_nearest_point((xcoord, ycoord, zcoord)) 106 | for fld, fn in zip(fields, fname): 107 | p.add_output(fdfault.output('body'+station[0]+'st'+station[1]+'dp'+station[2]+'-'+fld, fn, 0, nt, 1, xpt, xpt, 1, 108 | ypt, ypt, 1, zpt, zpt, 1)) 109 | 110 | p.set_front_output(True) 111 | 112 | p.write_input() 113 | -------------------------------------------------------------------------------- /python/fdfault/analysis/front.py: -------------------------------------------------------------------------------- 1 | """ 2 | ``analysis.front`` is a class used for holding rupture time data for analysis with Python. The class 3 | contains information on the problem, the interface that was output, number of grid points, and 4 | byte-ordering of the output data. Once the class instance is initialized and the rupture time data 5 | is loaded, the class is designed to be used as a basic data structure in analysis routines and for 6 | plotting and visualizing data. 7 | """ 8 | 9 | import numpy as np 10 | from os import getcwd 11 | from os.path import join 12 | from sys import path 13 | 14 | class front(object): 15 | """ 16 | Class for rupture front objects 17 | 18 | Object describing a rupture front, with the following attributes: 19 | 20 | :ivar problem: Name of problem 21 | :type problem: str 22 | :ivar iface: Interface that was output 23 | :type name: int 24 | :ivar datadir: Directory where simulation data is held, if ``None`` (default) this is the current directory 25 | :type datadir: str 26 | :ivar nx: Number of x grid points (or number of y grid points if the target interface has an x normal) 27 | :type nx: int 28 | :ivar ny: Number of y grid points (or number of z grid points if the target interface has an x or y normal) 29 | :type ny: int 30 | :ivar endian: Byte-ordering of simulation data (``'='`` for native, ``'>'`` for big endian, ``'<'`` for little endian) 31 | :type endian: str 32 | :ivar t: Numpy array holding rupture time data 33 | :type t: ndarray 34 | """ 35 | def __init__(self, problem, iface, datadir = None): 36 | "initializes output object with simulation information" 37 | 38 | self.problem = problem 39 | self.iface = int(iface) 40 | if datadir is None: 41 | self.datadir = getcwd() 42 | else: 43 | self.datadir = datadir 44 | 45 | path.append(datadir) 46 | 47 | self._temp = __import__(problem+'_front_'+str(iface)) 48 | 49 | self.nx = self._temp.nx 50 | self.ny = self._temp.ny 51 | self.endian = self._temp.endian 52 | 53 | def load(self): 54 | """ 55 | Load data from data file for rupture front 56 | 57 | Method loads the data from file into the ``t`` attribute. If you have an existing instance of 58 | an front class whose simulation data has changed, ``load`` can be run more than once 59 | and will refresh the contents of the simulation output. 60 | 61 | Method takes no inputs and has no outputs. Class is modified by running this method 62 | as the simulation data will be reloaded from file if it already exists. 63 | 64 | :returns: None 65 | """ 66 | 67 | # check if simulation data has changed 68 | 69 | try: 70 | from importlib import reload 71 | except ImportError: 72 | from imp import reload 73 | 74 | reload(self._temp) 75 | 76 | self.nx = self._temp.nx 77 | self.ny = self._temp.ny 78 | self.endian = self._temp.endian 79 | 80 | self.x = np.squeeze(np.fromfile(join(self.datadir,self.problem+'_front_'+str(self.iface)+'_x.dat'), self.endian+'f8').reshape(self.nx, self.ny)) 81 | self.y = np.squeeze(np.fromfile(join(self.datadir,self.problem+'_front_'+str(self.iface)+'_y.dat'), self.endian+'f8').reshape(self.nx, self.ny)) 82 | try: 83 | self.z = np.squeeze(np.fromfile(join(self.datadir,self.problem+'_front_'+str(self.iface)+'_z.dat'), self.endian+'f8').reshape(self.nx,self.ny)) 84 | except: 85 | pass 86 | 87 | self.t = np.squeeze(np.fromfile(join(self.datadir, self.problem+'_front_'+str(self.iface)+'_t.dat'), self.endian+'f8').reshape(self.nx,self.ny)) 88 | 89 | def __str__(self): 90 | "Returns a string representation of the rupture front" 91 | return ('Problem '+self.problem+', Front from interface '+str(self.iface)+'\nnx = '+str(self.nx) 92 | +'\nny = '+str(self.ny)) 93 | -------------------------------------------------------------------------------- /src/pert.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "pert.hpp" 6 | 7 | pert::pert(const std::string type_in, const double t0_in, const double x0_in, const double dx_in, 8 | const double y0_in, const double dy_in, const int n[2], const int xm[2], const int xm_loc[2], 9 | const double x[2], const double l[2]) { 10 | // constructor 11 | 12 | assert(type_in == "constant" || type_in == "gaussian" || type_in == "ellipse" || type_in == "boxcar" 13 | || type_in == "linear"); 14 | assert(t0_in >= 0.); 15 | assert(dx_in >= 0.); 16 | assert(dy_in >= 0.); 17 | 18 | t0 = t0_in; 19 | x0 = x0_in; 20 | y0 = y0_in; 21 | dx = dx_in; 22 | dy = dy_in; 23 | 24 | if (type_in == "constant") { 25 | type = 0; 26 | } else if (type_in == "gaussian") { 27 | type = 1; 28 | } else if (type_in == "ellipse") { 29 | type = 2; 30 | } else if (type_in == "linear") { 31 | type = 3; 32 | } else { // boxcar 33 | type = 4; 34 | } 35 | 36 | // calculate parameters 37 | 38 | a = (double)(xm_loc[0]-xm[0])/(double)(n[0]-1)*l[0]+x[0]; 39 | b = l[0]/(double)(n[0]-1); 40 | c = (double)(xm_loc[1]-xm[1])/(double)(n[1]-1)*l[1]+x[1]; 41 | d = l[1]/(double)(n[1]-1); 42 | 43 | } 44 | 45 | double pert::tfunc(const double t) const { 46 | // load time ramp 47 | 48 | double tval; 49 | 50 | if (t >= t0) { 51 | tval = 1.; 52 | } else { 53 | tval = t/t0; 54 | } 55 | 56 | return tval; 57 | } 58 | 59 | double pert::xyfunc(const int i, const int j) const { 60 | // calculates spatial dependence of perturbation 61 | 62 | double xyval = 0., xval, yval, epsilon = 1.e-14; 63 | 64 | switch (type) { 65 | case 0: 66 | xyval = 1.; 67 | break; 68 | case 1: 69 | if (dx < epsilon) { 70 | xval = 0.; 71 | } else { 72 | xval = pow((x(i)-x0)/dx,2); 73 | } 74 | if (dy < epsilon) { 75 | yval = 0.; 76 | } else { 77 | yval = pow((y(j)-y0)/dy,2); 78 | } 79 | xyval = exp(-xval-yval); 80 | break; 81 | case 2: 82 | if (dx < epsilon) { 83 | xval = 0.; 84 | } else { 85 | xval = pow((x(i)-x0)/dx,2); 86 | } 87 | if (dy < epsilon) { 88 | yval = 0.; 89 | } else { 90 | yval = pow((y(j)-y0)/dy,2); 91 | } 92 | if (xval+yval <= 1.) { 93 | xyval = 1.; 94 | } 95 | break; 96 | case 3: 97 | if (dx < epsilon) { 98 | xval = 1; 99 | } else { 100 | xval = x(i)/dx+x0; 101 | } 102 | if (dy < epsilon) { 103 | yval = 1; 104 | } else { 105 | yval = y(j)/dy+y0; 106 | } 107 | xyval = xval*yval; 108 | break; 109 | case 4: 110 | if (dx < epsilon) { 111 | xval = 1.; 112 | } else { 113 | if (fabs(fabs(x(i)-x0)-dx) < epsilon) { 114 | xval = 0.5; 115 | } else if (fabs(x(i)-x0) < dx) { 116 | xval = 1.; 117 | } else { 118 | xval = 0.; 119 | } 120 | } 121 | if (dy < epsilon) { 122 | yval = 1.; 123 | } else { 124 | if (fabs(fabs(y(j)-y0)-dy) < epsilon) { 125 | yval = 0.5; 126 | } else if (fabs(y(j)-y0) < dy) { 127 | yval = 1.; 128 | } else { 129 | yval = 0.; 130 | } 131 | } 132 | xyval = xval*yval; 133 | } 134 | 135 | return xyval; 136 | } 137 | 138 | double pert::x(const int i) const { 139 | // calculates x value given index i 140 | 141 | return b*(double)i+a; 142 | } 143 | 144 | double pert::y(const int j) const { 145 | // calculates y value given index j 146 | 147 | return d*(double)j+c; 148 | } 149 | 150 | -------------------------------------------------------------------------------- /src/block.hpp: -------------------------------------------------------------------------------- 1 | #ifndef BLOCKCLASSHEADERDEF 2 | #define BLOCKCLASSHEADERDEF 3 | 4 | #include 5 | #include "boundary.hpp" 6 | #include "cartesian.hpp" 7 | #include "coord.hpp" 8 | #include "fd.hpp" 9 | #include "fields.hpp" 10 | #include "material.hpp" 11 | 12 | struct plastp { 13 | double sxx, sxy, sxz, syy, syz, szz, gammap, lambda, epxx, epxy, epxz, epyy, epyz, epzz; 14 | }; 15 | 16 | class block 17 | { 18 | public: 19 | block(const char* filename, const int ndim_in, const int mode_in, const std::string material_in, const int coords[3], const int nx_in[3], const int xm_in[3], 20 | const cartesian& cart, fields& f, const fd_type& fd); 21 | ~block(); 22 | int get_nx(const int index) const; 23 | int get_nx_loc(const int index) const; 24 | int get_xm(const int index) const; 25 | int get_xm_loc(const int index) const; 26 | int get_xp(const int index) const; 27 | int get_xp_loc(const int index) const; 28 | int get_xm_ghost(const int index) const; 29 | int get_xp_ghost(const int index) const; 30 | double get_cp() const; 31 | double get_cs() const; 32 | double get_zp() const; 33 | double get_zs() const; 34 | double get_dx(const int index) const; 35 | double get_x(const int index) const; 36 | double get_l(const int index) const; 37 | double get_min_dx(fields& f) const; 38 | void calc_df(const double dt, fields& f, const fd_type& fd); 39 | void set_boundaries(const double dt, fields& f); 40 | void set_mms(const double dt, const double t, fields& f); 41 | void calc_plastic(const double dt, fields& f); 42 | private: 43 | int ndim; 44 | int mode; 45 | int mlb[3]; 46 | int mc[3]; 47 | int mrb[3]; 48 | int prb[3]; 49 | int nxd[3]; 50 | double dx[3]; 51 | double x_block[3]; 52 | double l_block[3]; 53 | bool no_data; 54 | bool is_plastic; 55 | bool plastic_tensor; 56 | coord c; 57 | int nbound; 58 | boundary** bound; 59 | material mat; 60 | double xfact; 61 | bool dissipation; 62 | double cdiss; 63 | void calc_process_info(const cartesian& cart, const int sbporder); 64 | void set_grid(surface** surf, fields& f, const cartesian& cart, const fd_type& fd); 65 | void calc_df_mode2(const double dt, fields& f, const fd_type& fd); 66 | void calc_df_mode3(const double dt, fields& f, const fd_type& fd); 67 | void calc_df_3d(const double dt, fields& f, const fd_type& fd); 68 | void calc_df_szz(const double dt, fields&f, const fd_type& fd); 69 | plastp plastic_flow(const double dt, const plastp s_in, const double k, const double g) const; 70 | double calc_tau(const plastp s) const; 71 | double calc_sigma(const plastp s) const; 72 | double yield(const double tau, const double sigma) const; 73 | void calc_mms_mode3(const double dt, const double t, fields& f); 74 | void calc_mms_mode2(const double dt, const double t, fields& f); 75 | void calc_mms_3d(const double dt, const double t, fields& f); 76 | double mms_vz_mode3(const double t, const double x, const double y) const; 77 | double mms_sxz_mode3(const double t, const double x, const double y) const; 78 | double mms_syz_mode3(const double t, const double x, const double y) const; 79 | double mms_vx_mode2(const double t, const double x, const double y) const; 80 | double mms_vy_mode2(const double t, const double x, const double y) const; 81 | double mms_sxx_mode2(const double t, const double x, const double y) const; 82 | double mms_sxy_mode2(const double t, const double x, const double y) const; 83 | double mms_syy_mode2(const double t, const double x, const double y) const; 84 | double mms_szz_mode2(const double t, const double x, const double y) const; 85 | double mms_vx_3d(const double t, const double x, const double y, const double z) const; 86 | double mms_vy_3d(const double t, const double x, const double y, const double z) const; 87 | double mms_vz_3d(const double t, const double x, const double y, const double z) const; 88 | double mms_sxx_3d(const double t, const double x, const double y, const double z) const; 89 | double mms_sxy_3d(const double t, const double x, const double y, const double z) const; 90 | double mms_sxz_3d(const double t, const double x, const double y, const double z) const; 91 | double mms_syy_3d(const double t, const double x, const double y, const double z) const; 92 | double mms_syz_3d(const double t, const double x, const double y, const double z) const; 93 | double mms_szz_3d(const double t, const double x, const double y, const double z) const; 94 | }; 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /src/rk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "rk.hpp" 4 | #include 5 | 6 | using namespace std; 7 | 8 | rk_type::rk_type(const int order) { 9 | // constructor to initialize coefficients based on order 10 | 11 | int rc; 12 | 13 | rkorder = order; 14 | 15 | // determine number of RK stages 16 | 17 | switch (rkorder) { 18 | case 1: 19 | nstages = 1; 20 | break; 21 | case 2: 22 | nstages = 2; 23 | break; 24 | case 3: 25 | nstages = 3; 26 | break; 27 | case 4: 28 | nstages = 5; 29 | break; 30 | default: 31 | cerr << "Error in initializing RK method\n"; 32 | MPI_Abort(MPI_COMM_WORLD, rc); 33 | break; 34 | } 35 | 36 | A = new double [nstages]; 37 | B = new double [nstages]; 38 | C = new double [nstages+1]; 39 | 40 | // initialize RK coefficients 41 | 42 | switch (rkorder) { 43 | case 1: 44 | // Euler 45 | A[0] = 0.; 46 | B[0] = 1.; 47 | C[0] = 0.; 48 | C[1] = 1.; 49 | break; 50 | case 2: 51 | // Heun's method 52 | A[0] = 0.; 53 | A[1] = -1.; 54 | B[0] = 1.; 55 | B[1] = 0.5; 56 | C[0] = 0.; 57 | C[1] = 1.; 58 | C[2] = 1.; 59 | break; 60 | case 3: 61 | // Williamson 3,3 62 | A[0] = 0.; 63 | A[1] = -5./9.; 64 | A[2] = -153./128.; 65 | B[0] = 1./3.; 66 | B[1] = 15./16.; 67 | B[2] = 8./15.; 68 | C[0] = 0.; 69 | C[1] = 1./3.; 70 | C[2] = 3./4.; 71 | C[3] = 1.; 72 | break; 73 | case 4: 74 | // Carpenter Kennedy 5,4 75 | A[0] = 0.; 76 | A[1] = -567301805773./1357537059087.; 77 | A[2] = -2404267990393./2016746695238.; 78 | A[3] = -3550918686646./2091501179385.; 79 | A[4] = -1275806237668./842570457699.; 80 | B[0] = 1432997174477./9575080441755.; 81 | B[1] = 5161836677717./13612068292357.; 82 | B[2] = 1720146321549./2090206949498.; 83 | B[3] = 3134564353537./4481467310338.; 84 | B[4] = 2277821191437./14882151754819.; 85 | C[0] = 0.; 86 | C[1] = 1432997174477./9575080441755.; 87 | C[2] = 2526269341429./6820363962896.; 88 | C[3] = 2006345519317./3224310063776.; 89 | C[4] = 2802321613138./2924317926251.; 90 | C[5] = 1.; 91 | break; 92 | default: 93 | cerr << "Error in initializing RK method\n"; 94 | MPI_Abort(MPI_COMM_WORLD, rc); 95 | break; 96 | } 97 | 98 | } 99 | 100 | /*rk_type::rk_type(const rk_type& otherrk) { 101 | // constructor to copy another rk_type 102 | 103 | rkorder = otherrk.get_rkorder(); 104 | nstages = otherrk.nstages; 105 | 106 | // allocate memory for coefficients 107 | 108 | A = new double [nstages]; 109 | B = new double [nstages]; 110 | C = new double [nstages+1]; 111 | 112 | // set coefficients to appropriate values 113 | 114 | for (int i=0; i unzip fdfault-1.0.zip 28 | 29 | Depending on which version you downloaded, the filename for the zipped archive might 30 | be different. Or clone the git repository using 31 | 32 | > git clone https://github.com/egdaub/fdfault.git 33 | 34 | For most users, building the source code should simply require 35 | 36 | > cd fdfault/src 37 | > make 38 | 39 | assuming you have Make and an appropriate C++ compiler with an MPI Library. You may 40 | need to change some of the compiler flags -- I have mostly tested the code using the 41 | GNU Compilers and OpenMPI on both Linux and Mac OS X. This will create the fdfault 42 | executable in the main fdfault directory. 43 | 44 | You will also need to configure the python module. There are several ways to do this: 45 | 46 | 1. Install the Python module system-wide. To make the Python tools available system-wide, 47 | change to the python directory and run setup.py (you must have setuptools installed): 48 | 49 | > cd fdfault/python 50 | > python setup.py install 51 | 52 | You may also use Python 3 without any modifications. Depending on your setup, you might 53 | need administrative privileges to do the installation step. If you obtained the code by 54 | cloning the Git repository, installation in this manner will not update automatically 55 | if any of the source code files are updated. If you want to keep up to date without 56 | having to reinstall, install a development version: 57 | 58 | > cd fdfault/python 59 | > python setup.py develop 60 | 61 | This will simply place a link to the fdfault python directory in the system Python 62 | libraries, so any updates will automatically be available. 63 | 64 | 2. If you would like the Python module available in any directory without installing for 65 | other users, you can simply modify your PYTHONPATH environment variable to include the 66 | full path to fdfault/python. This will only effect the current user. 67 | 68 | 3. Some users prefer to only have the Python tools available in certain directories. 69 | The tools for setting up problems are most often used in the problems directory, and the 70 | analysis tools are most often used in the data directory. 71 | 72 | To make these tools available in these directories only, make a symbolic link to the 73 | python/fdfault directory in the problems directory: 74 | 75 | > cd fdfault/problems 76 | > ln -s ../python/fdfault/ fdfault 77 | 78 | This will allow you to simply type "import fdfault" in python from within the problems 79 | directory. Similarly, to make the analysis features available in the data directory: 80 | 81 | > cd fdfault/data 82 | > ln -s ../python/fdfault/analysis fdfault 83 | 84 | This allows you to type "import fdfault" from within the data directory and have the 85 | analysis tools at your disposal. 86 | 87 | Finally you will need to build the User's Guide. The user's guide requires Sphinx and 88 | MathJax (or an internet connection to access MathJax online) for the HTML version and 89 | a LaTeX distribution for the PDF version. 90 | 91 | > cd fdfault/docs/ 92 | > make html && make latexpdf 93 | 94 | This should build the notes in the fdfault/docs/_build/html or fdfault/docs/_build/latex 95 | directories. If you wish to build only the html or pdf version, use the appropriate 96 | command. If you do not have Sphinx or LaTeX on your machine, both versions of the 97 | documentation are available on the web, though these are only periodially updated: 98 | 99 | http://www.ceri.memphis.edu/people/egdaub/fdfault/_build/html/index.html (html) 100 | http://www.ceri.memphis.edu/people/egdaub/fdfault/_build/latex/fdfault_docs.pdf (pdf) 101 | -------------------------------------------------------------------------------- /src/utilities.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | 9 | char get_endian() { 10 | // checks for endian type for reading data output 11 | 12 | char endian; 13 | union { 14 | uint32_t i; 15 | char c[4]; 16 | } bigint = {0x01020304}; 17 | 18 | if (bigint.c[0] == 1 && bigint.c[1] == 2 && bigint.c[2] == 3 && bigint.c[3] == 4) { 19 | endian = '>'; 20 | } 21 | else if (bigint.c[0] == 4 && bigint.c[1] == 3 && bigint.c[2] == 2 && bigint.c[3] == 1) { 22 | endian = '<'; 23 | } else { 24 | cout << "Endian test failed, setting to native\n"; 25 | endian = '='; 26 | } 27 | 28 | return endian; 29 | 30 | } 31 | 32 | MPI_Comm create_comm(const bool no_data) { 33 | // create communicator involving only processes that have data 34 | 35 | // determine which processes have data to create new communicator 36 | 37 | int np, np_out, part, id, count; 38 | int* incl_tot; 39 | 40 | MPI_Comm_size(MPI_COMM_WORLD, &np); 41 | MPI_Comm_rank(MPI_COMM_WORLD, &id); 42 | 43 | incl_tot = new int [np]; 44 | 45 | if (no_data) { 46 | part = -1; 47 | } else { 48 | part = id; 49 | } 50 | 51 | MPI_Allgather(&part, 1, MPI_INT, incl_tot, 1, MPI_INT, MPI_COMM_WORLD); 52 | 53 | np_out = 0; 54 | 55 | for (int i=0; i 0.) { 111 | xh = x; 112 | break; 113 | } else { 114 | xl = x; 115 | } 116 | } else { 117 | xh = x; 118 | } 119 | x = 0.5*(xh+xl); 120 | func = f(x, params); 121 | } 122 | 123 | } 124 | 125 | x = 0.5*(xh+xl); 126 | func = f(x, params); 127 | der = df(x, params); 128 | 129 | dx = fabs(xh-xl); 130 | dxold = dx; 131 | 132 | while (i < nmax) { 133 | 134 | if (der == 0.) { 135 | cerr << "zero derivative in Newton's method in utilities.cpp\n"; 136 | MPI_Abort(MPI_COMM_WORLD, -1); 137 | } 138 | 139 | if ((((x-xh)*der-func)*((x-xl)*der-func) > 0.) || fabs(2.*func) > fabs(dxold*der)) { 140 | dxold = dx; 141 | dx = 0.5*(xh-xl); 142 | x = xl+dx; 143 | if (xl == x) { 144 | break; 145 | } 146 | } else { 147 | dxold = dx; 148 | dx = func/der; 149 | temp = x; 150 | x = x-dx; 151 | if (temp == x) { 152 | break; 153 | } 154 | } 155 | 156 | if (fabs(dx) < tol) { 157 | break; 158 | } 159 | 160 | func = f(x, params); 161 | der = df(x, params); 162 | 163 | if (func < 0.) { 164 | xl = x; 165 | } else { 166 | xh = x; 167 | } 168 | 169 | i++; 170 | 171 | } 172 | 173 | if (i == nmax) { 174 | cerr << "Newton's method failed to converge in utilities.cpp\n"; 175 | MPI_Abort(MPI_COMM_WORLD, -1); 176 | } 177 | 178 | return x; 179 | 180 | } -------------------------------------------------------------------------------- /python/fdfault/front.py: -------------------------------------------------------------------------------- 1 | """ 2 | The ``front`` class holds information about rupture time output. Rupture times are found by 3 | recording the earliest time at which a given field (slip or slip rate) exceeds a threshold value. 4 | 5 | An instance of ``front`` is automatically generated for all problems, so the user should not 6 | use this directly, but rather modify the front for the problem using the provided interfaces in 7 | the ``problem`` class. 8 | """ 9 | 10 | from __future__ import division, print_function 11 | 12 | class front(object): 13 | """ 14 | Class holding information regarding rupture front output. 15 | 16 | Relevant internal variables include: 17 | 18 | :ivar out: Boolean indicating if front output is on/off (Default ``False``) 19 | :type out: bool 20 | :ivar field: Field to use for determining rupture time (rupture time is earliest time this field 21 | exceeds the threshold). Default is ``'V'`` (scalar slip velocity), can also be 22 | ``'U'`` (slip). 23 | :type field: str 24 | :ivar value: Threshold value (default is 0.001) 25 | :type value: float 26 | """ 27 | def __init__(self): 28 | """ 29 | Initializes rupture front 30 | 31 | Create a new instance of the ``front`` class with default properties (output is ``False``, 32 | output field is ``'V'``, and output threshold value is ``0.001``). 33 | 34 | :returns: New rupture front class: 35 | :rtype: ~fdfault.front 36 | """ 37 | 38 | self.outputstatus = False 39 | self.field = 'V' 40 | self.value = 0.001 41 | 42 | def get_output(self): 43 | """ 44 | Returns status of front output (boolean) 45 | 46 | :returns: Status of front output 47 | :rtype: bool 48 | """ 49 | return self.outputstatus 50 | 51 | def set_output(self, newoutput): 52 | """ 53 | Sets front output to be on or off 54 | 55 | Sets rupture front output to be the specified value (boolean). Will raise an error 56 | if the provided value cannot be converted into a boolean. 57 | 58 | :param newoutput: New value of output 59 | :type newoutput: bool 60 | :returns: None 61 | """ 62 | assert type(newoutput) is bool, "front output must be a boolean" 63 | self.outputstatus = newoutput 64 | 65 | def get_field(self): 66 | """ 67 | Returns front field 68 | 69 | :returns: Rupture front field (string, "U" denotes slip and "V" denotes slip velocity) 70 | :rtype: str 71 | """ 72 | return self.field 73 | 74 | def set_field(self, field): 75 | """ 76 | Sets rupture front field 77 | 78 | Sets new value of rupture front field ``field``. ``field`` must be a string (slip (``'U'``) 79 | or slip velocity (``'V'``)). Other choices will raise an error. 80 | 81 | :param field: New rupture front field 82 | :type field: str 83 | :returns: None 84 | """ 85 | assert (field == "U" or field == "V"), "Incorrect field name" 86 | self.field = field 87 | 88 | def get_value(self): 89 | """ 90 | Returns front threshold value. 91 | Front output is the earliest time at which the given field exceeds this value 92 | 93 | :returns: Threshold value for rupture front output 94 | :rtype: float 95 | """ 96 | return self.value 97 | 98 | def set_value(self, value): 99 | """ 100 | Sets front threshold value 101 | 102 | Changes value of rupture front threshold. The rupture time is the earliest time at which 103 | the chosen field exceeds this value. ``value`` is the new value (must be a positive number). 104 | 105 | :param value: New values of the threshold for rupture front times. 106 | :type value: float 107 | :returns: None 108 | """ 109 | assert (value > 0.), "Front threshhold must be positive" 110 | self.value = value 111 | 112 | def write_input(self,f): 113 | """ 114 | Writes front information to input file 115 | 116 | Method writes the current state of a front to an input file. 117 | 118 | Input argument the input file ``f`` (file handle). 119 | 120 | :param f: file handle for text input file 121 | :type f: file 122 | :returns: None 123 | """ 124 | f.write("[fdfault.frontlist]\n") 125 | f.write(str(int(self.outputstatus))+"\n") 126 | if self.outputstatus: 127 | f.write(self.field+"\n") 128 | f.write(repr(self.value)+"\n") 129 | 130 | def __str__(self): 131 | "Returns string representation of front" 132 | outstr = "Front: output = "+str(self.outputstatus) 133 | if self.outputstatus: 134 | outstr += ", field = "+self.field+", value = "+str(self.value) 135 | return outstr 136 | -------------------------------------------------------------------------------- /src/problem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "problem.hpp" 8 | #include "domain.hpp" 9 | #include "frontlist.hpp" 10 | #include "outputlist.hpp" 11 | #include "rk.hpp" 12 | #include 13 | 14 | using namespace std; 15 | 16 | problem::problem(const char* filename) { 17 | // constructor 18 | 19 | int rkorder; 20 | 21 | // open input file, find appropriate place and read in parameters 22 | 23 | string line; 24 | ifstream paramfile(filename, ifstream::in); 25 | if (paramfile.is_open()) { 26 | // scan to start of problem list 27 | while (getline(paramfile,line)) { 28 | if (line == "[fdfault.problem]") { 29 | break; 30 | } 31 | } 32 | if (paramfile.eof()) { 33 | cerr << "Error reading problem from input file\n"; 34 | MPI_Abort(MPI_COMM_WORLD,-1); 35 | } else { 36 | // read problem variables 37 | paramfile >> name; 38 | paramfile >> datadir; 39 | paramfile >> nt; 40 | paramfile >> dt; 41 | paramfile >> ttot; 42 | paramfile >> cfl; 43 | paramfile >> ninfo; 44 | paramfile >> rkorder; 45 | } 46 | } else { 47 | cerr << "Error opening input file in problem.cpp\n"; 48 | MPI_Abort(MPI_COMM_WORLD,-1); 49 | } 50 | paramfile.close(); 51 | 52 | // initiailize rk class 53 | 54 | rk = new rk_type(rkorder); 55 | 56 | // set up problem 57 | 58 | d = new domain(filename); 59 | 60 | // set time step 61 | 62 | set_time_step(); 63 | 64 | // create output list 65 | 66 | out = new outputlist(filename, name, datadir, nt, *d); 67 | 68 | // create front list 69 | 70 | front = new frontlist(filename, name, datadir, *d); 71 | 72 | // write initial output data (uses absolute stress values) 73 | 74 | d->set_stress(); 75 | 76 | out->write_list(0, dt, *d); 77 | 78 | d->remove_stress(); 79 | 80 | // set initial values of rupture front 81 | 82 | front->set_front(0., *d); 83 | 84 | } 85 | 86 | problem::~problem() { 87 | // destructor, deallocates memory 88 | delete rk; 89 | delete d; 90 | delete out; 91 | delete front; 92 | } 93 | 94 | void problem::set_time_step() { 95 | // sets time step 96 | // must specify two of nt, dt, cfl, and ttot (except cannot specify both dt and cfl) 97 | 98 | // get minimum grid spacing/wave speed 99 | 100 | int id; 101 | 102 | MPI_Comm_rank(MPI_COMM_WORLD, &id); 103 | 104 | double dx = d->get_min_dx(); 105 | 106 | if ((ttot > 0. && nt > 0) && (dt == 0 && cfl == 0.)) { 107 | // if supplied ttot, nt but not dt, cfl, use ttot and nt 108 | dt = ttot/(double)nt; 109 | cfl = dt/dx; 110 | } else { // use one of ttot/nt and one of dt/cfl 111 | if (dt > 0.) { 112 | if (cfl > 0. && id == 0) { 113 | cout << "Cannot specify both dt and cfl, defaulting to dt\n"; 114 | } 115 | cfl = dt/dx; 116 | } else { 117 | dt = cfl*dx; 118 | } 119 | if (ttot > 0.) { 120 | if (nt > 0 && id == 0 ) { 121 | cout << "Cannot specify both ttot and nt with one of cfl or dt, defaulting to ttot\n"; 122 | } 123 | nt = ceil(ttot/dt); 124 | ttot = (double)nt*dt; 125 | } else { 126 | ttot = (double)nt*dt; 127 | } 128 | } 129 | 130 | if (cfl > 1. && id == 0) { 131 | cout << "Warning: CFL ratio > 1, numerical instability is likely\n"; 132 | } 133 | 134 | } 135 | 136 | void problem::solve() { 137 | // solves a dynamic rupture problem 138 | 139 | int id, nstages; 140 | time_t rawtime; 141 | struct tm* timeinfo; 142 | 143 | // get process id 144 | 145 | MPI_Comm_rank(MPI_COMM_WORLD, &id); 146 | 147 | // loop over time steps 148 | 149 | nstages = rk->get_nstages(); 150 | 151 | for (int i=0; ido_rk_stage(dt,stage,(double)i*dt,*rk); 156 | } 157 | 158 | // output data (uses absolute stress values) 159 | 160 | d->set_stress(); 161 | 162 | out->write_list(i+1, dt, *d); 163 | 164 | d->remove_stress(); 165 | 166 | // update front 167 | 168 | front->set_front((double)(i+1)*dt, *d); 169 | 170 | // update status 171 | 172 | if (id == 0 && (i+1)%ninfo == 0) { 173 | time (&rawtime); 174 | timeinfo = localtime (&rawtime); 175 | std::cout << "Timestep " << i+1 << " of " << nt << " " << asctime(timeinfo); 176 | } 177 | 178 | } 179 | 180 | // close output files 181 | 182 | out->close_list(); 183 | 184 | // write fronts 185 | 186 | front->write_list(*d); 187 | 188 | // free MPI data types for boundary exchange 189 | 190 | d->free_exchange(); 191 | 192 | } 193 | -------------------------------------------------------------------------------- /python/fdfault/analysis/output.py: -------------------------------------------------------------------------------- 1 | """ 2 | ``analysis.output`` is a class used for holding simulation data for analysis with Python. The class 3 | contains information on the problem, field, number of grid and time points, and byte-ordering 4 | of the output data. Once the class instance is initialized and the simulation data is loaded, 5 | the class is designed to be used as a basic data structure in analysis routines and for plotting 6 | and visualizing data. 7 | 8 | The field data itself is loaded into the ``fielddata`` attribute, a numpy array with the shape 9 | ``(nt, nx, ny, nz)`` holding the simulation data. The ``load`` routine also creates an alias to 10 | ``fielddata`` using the field name itself. This allows for flexibility writing routines that can 11 | operate on the ``output`` class generically, while also preserving code legibility for routines that 12 | operate on ``output`` classes with a certain field associated with it. Thus, if the ``field`` attribute 13 | on the output unit ``vx_body`` is ``vx``, then the x particle velocities can be accessed with either 14 | ``vx_body.vx`` or ``vx_body.fielddata``. 15 | """ 16 | 17 | import numpy as np 18 | from os import getcwd 19 | from os.path import join 20 | from sys import path 21 | 22 | class output(object): 23 | """ 24 | Class representing an output object 25 | 26 | Output objects contain the following attributes: 27 | 28 | :ivar problem: Name of problem 29 | :type problem: str 30 | :ivar name: Name of output unit 31 | :type name: str 32 | :ivar datadir: Directory where simulation data is held, if ``None`` (default) this is the current directory 33 | :type datadir: str 34 | :ivar field: Field that was saved to file 35 | :type field: str 36 | :ivar nt: Number of time steps 37 | :type nt: int 38 | :ivar nx: Number of x grid points 39 | :type nx: int 40 | :ivar ny: Number of y grid points 41 | :type ny: int 42 | :ivar nz: Number of z grid points 43 | :type nz: int 44 | :ivar endian: Byte-ordering of simulation data (``'='`` for native, ``'>'`` for big endian, ``'<'`` for little endian) 45 | :type endian: str 46 | :ivar fielddata: Numpy array holding simulation data (also aliased using the field name itself) 47 | :type fielddata: ndarray 48 | """ 49 | def __init__(self, problem, name, datadir = None): 50 | """ 51 | Initializes output object with simulation information 52 | """ 53 | 54 | self.name = name 55 | self.problem = problem 56 | if datadir is None: 57 | self.datadir = getcwd() 58 | else: 59 | self.datadir = datadir 60 | 61 | path.append(datadir) 62 | 63 | self._temp = __import__(problem+'_'+name) 64 | 65 | self.field = self._temp.field 66 | self.nt = self._temp.nt 67 | self.nx = self._temp.nx 68 | self.ny = self._temp.ny 69 | self.nz = self._temp.nz 70 | self.endian = self._temp.endian 71 | 72 | def load(self): 73 | """ 74 | Load data from data file for output item 75 | 76 | Method loads the data from file into the ``fielddata`` attribute, a Numpy array, and also 77 | creates an alias with the ``field`` attribute itself. If you have an existing instance of 78 | an output class whose simulation data has changed, ``load`` can be run more than once 79 | and will refresh the contents of the simulation output. 80 | 81 | Method takes no inputs and has no outputs. Class is modified by running this method 82 | as the simulation data will be reloaded from file if it already exists. 83 | 84 | :returns: None 85 | """ 86 | 87 | # check if simulation data has changed 88 | 89 | try: 90 | from importlib import reload 91 | except ImportError: 92 | from imp import reload 93 | 94 | reload(self._temp) 95 | 96 | self.field = self._temp.field 97 | self.nt = self._temp.nt 98 | self.nx = self._temp.nx 99 | self.ny = self._temp.ny 100 | self.nz = self._temp.nz 101 | self.endian = self._temp.endian 102 | 103 | if (self.nt > 1): 104 | self.t = np.fromfile(join(self.datadir,self.problem+'_'+self.name+'_t.dat'), self.endian+'f8') 105 | self.x = np.squeeze(np.fromfile(join(self.datadir,self.problem+'_'+self.name+'_x.dat'), self.endian+'f8').reshape(self.nx, self.ny, self.nz)) 106 | self.y = np.squeeze(np.fromfile(join(self.datadir,self.problem+'_'+self.name+'_y.dat'), self.endian+'f8').reshape(self.nx, self.ny, self.nz)) 107 | try: 108 | self.z = np.squeeze(np.fromfile(join(self.datadir,self.problem+'_'+self.name+'_z.dat'), self.endian+'f8').reshape(self.nx, self.ny, self.nz)) 109 | except: 110 | pass 111 | 112 | # store data in fielddata (makes it easier to write field agnostic analysis routines) 113 | 114 | self.fielddata = np.squeeze(np.fromfile(join(self.datadir,self.problem+'_'+self.name+'_'+self.field+'.dat'), self.endian+'f8').reshape(self.nt, self.nx, self.ny, self.nz)) 115 | 116 | # create shortcut for more informative attribute name 117 | 118 | setattr(self, self.field, self.fielddata) 119 | 120 | def __str__(self): 121 | "Feturns a string representation of the output unit" 122 | return ('Problem '+self.problem+', Output '+self.name+'\nfield = '+self.field+'\nnt = '+str(self.nt)+'\nnx = '+str(self.nx) 123 | +'\nny = '+str(self.ny)+'\nnz = '+str(self.nz)) 124 | -------------------------------------------------------------------------------- /docs/input/text/friction.rst: -------------------------------------------------------------------------------- 1 | .. _friction: 2 | 3 | ********************************** 4 | Friction Input 5 | ********************************** 6 | 7 | The information above is all that is required for locked interfaces. For frictional interfaces, additional information must be provided. All frictional interfaces must include a ``[fdfault.friction]`` header somewhere *after* the interface header. Note that the friction header does not include an interface number -- the code scans through the input file to find the interface header for the interface in question, and then continues scanning until it finds the next friction header. This trick lets you easily set multiple frictional interfaces to have the same specifications. 8 | 9 | Friction headers contain the following information: :: 10 | 11 | Number of load perturbations 12 | List of load perturbations 13 | Load perturbation filename 14 | 15 | First is an integer that determines the number of surface traction perturbations that will be applied to the interface during the simulation. Next is a list of perturbations, followed by a file containing additional perturbations to the load. 16 | 17 | ==================== 18 | Load Perturbations 19 | ==================== 20 | 21 | Load perturbations have the following format: :: 22 | 23 | type t0 x0 dx y0 dy s1 s2 s3 24 | 25 | ``type`` is a string that determines the spatial characteristics of the perturbation. Options are ``constant`` (spatially uniform), ``boxcar`` (spatially uniform inside a rectangular area, zero outside), ``ellipse`` (spatially uniform inside an elliptical area, zero outside), and ``linear`` (linear function in each direction). 26 | 27 | ``t0`` determines the time scale over which the perturbation is added, with a linear ramp from zero over the given time scale. If the perturbation is to be added from the start of the simulation, give 0. 28 | 29 | ``x0 dx`` are constants determining the shape of the perturbation along first coordinate direction of the interface (:math:`{x}` for ``y`` and ``z`` interfaces, :math:`{y}` for ``x`` interfaces). For constant perturbations, these parameters are ignored. For boxcar and ellipse perturbations, ``x0`` is the center of the perturbation and ``dx`` is the half width. If you want the width to span the entire interface width, enter 0 for ``dx``. For linear perturbations, ``x0`` is the intercept and ``dx`` is the slope. If you want the linear gradient to only extend in one spatial direction, enter 0 for ``dx`` in the direction where you want the perturbation to be constant. Similarly, ``y0 dy`` set the same values for the other coordinate direction (:math:`{y}` for ``z`` interfaces and :math:`{z}` for ``x`` and ``y`` interfaces). For 2D problems, the second set of indices is ignored, but still must be present in the input file. 30 | 31 | In the simulations, the values of ``x0 dx y0 dy`` are only interpreted literally for rectangular blocks. For non-rectangular blocks, these values are interpreted assuming the interface follows a rectangular block on the minus side, using the values given under the block header. This means that the values may not be interpreted exactly as you expect! 32 | 33 | Finally, a trio of numbers set the vector surface traction applied to the interface. The first component is the normal traction, and the next two numbers are the two shear tractions. For 2D problems, the first shear component is the in-plane shear traction (only valid for mode 2 problems), and the second is the out of plane shear traction (always in the :math:`{z}`-direction and only valid for mode 3 problems). The code sets the unused shear traction component to zero. For 3D problems, the exact meaning of the shear traction components are determined by the surface normal direction, described as follows. 34 | 35 | The different interface components do not truly correspond to the corresponding coordinate directions. The code handles complex boundary conditions by rotating the fields into a coordinate system defined by three mutually orthogonal unit vectors. The normal direction is defined to always point into the "positive" block and is uniquely defined by the boundary geometry. The two tangential components are defined as follows for each different type of interface: 36 | 37 | * Depending on the orientation of the interface in the computational space, a different convention is used to set the first tangent vector. 38 | For ``'x'`` or ``'y'`` oriented interfaces, the :math:`{z}` component of the first tangent vector is set to zero. This is done to ensure 39 | that for 2D problems, the second tangent vector points in the :math:`{z}`-direction. For ``'z'`` oriented interfaces, the :math:`{y}` 40 | component of the first tangent vector is set to zero. 41 | 42 | * With one component of the first tangent vector defined, the other two components can be uniquely determined to make the tangent vector 43 | orthogonal up to a sign. The sign is chosen such that the tangent vector points in the direction where the grid points are increasing. 44 | 45 | * The second tangent vector is defined by taking the right-handed cross product of the normal and first tangent vectors, except for 46 | ``'y'`` interfaces, where the left-handed cross product is used. This is done to ensure that for 2D problems, the vertical component 47 | always points in the :math:`{+z}`-direction. 48 | 49 | ==================== 50 | File Perturbations 51 | ==================== 52 | 53 | After all of the surface traction perturbations, the code takes a filename of a file that adds additional tractions to the surface. The file contains a series of double precision floating point binary numbers of length :math:`{3\times n1 \times n2}`, where :math:`{n1}` and :math:`{n2}` are the number of grid points along the interface. The first block of :math:`{n1\times n2}` is for the normal traction (in row major order), then the in-plane shear traction component, and finally the out of plane shear traction component, with the same convention described above for setting the tangential directions. Endianness is assumed to match the computer where the simulation is being run. 54 | 55 | ============================================== 56 | Additional Friction Parameter Specifications 57 | ============================================== 58 | 59 | There are several specific types of frictional interfaces, two of which require additional parameters be specified: 60 | 61 | 1. **Frictionless** interfaces do not support shear tractions. No additional parameters are required when specifying frictionless interfaces. 62 | 63 | 2. **Slip-Weakening** interfaces require additional parameter specifications 64 | 65 | 3. **STZ** interfaces also require additional parameter specifications 66 | 67 | For more information on how to set slip-weakening and STZ parameter values, consult the following pages. -------------------------------------------------------------------------------- /src/surface.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "coord.hpp" 6 | #include "surface.hpp" 7 | #include 8 | 9 | using namespace std; 10 | 11 | surface::surface(const int ndim_in, const coord c, const int direction, const string filename) { 12 | // constructor, reads data from input file 13 | 14 | assert(direction >= 0 && direction < ndim_in); 15 | 16 | int index[2]; 17 | 18 | if (direction == 0) { 19 | index[0] = 1; 20 | index[1] = 2; 21 | } else if (direction == 1) { 22 | index[0] = 0; 23 | index[1] = 2; 24 | } else { 25 | index[0] = 0; 26 | index[1] = 1; 27 | } 28 | 29 | ndim = ndim_in; 30 | 31 | for (int i=0; i<2; i++) { 32 | n[i] = c.get_nx(index[i]); 33 | } 34 | 35 | // allocate memory for arrays 36 | 37 | x = new double [ndim*n[0]*n[1]]; 38 | 39 | // read data from file 40 | 41 | ifstream surffile (filename.c_str(), ios::in | ios::binary); 42 | 43 | if (!surffile.read((char*) x, sizeof(double)*ndim*n[0]*n[1])) { 44 | cerr << "Error reading surface from file " << filename << "\n"; 45 | MPI_Abort(MPI_COMM_WORLD,-1); 46 | } 47 | 48 | surffile.close(); 49 | 50 | } 51 | 52 | surface::surface(const int ndim_in, const coord c, const int direction, const double x_in[3], const double l_in[2]) { 53 | // constructor for a flat surface in a given normal direction with lower left coordinate x_in and lengths l_in 54 | 55 | assert(l_in[0] >= 0.); 56 | assert(l_in[1] >= 0.); 57 | assert(direction >= 0 && direction < ndim_in); 58 | 59 | int index[2]; 60 | 61 | if (direction == 0) { 62 | index[0] = 1; 63 | index[1] = 2; 64 | } else if (direction == 1) { 65 | index[0] = 0; 66 | index[1] = 2; 67 | } else { 68 | index[0] = 0; 69 | index[1] = 1; 70 | } 71 | 72 | ndim = ndim_in; 73 | 74 | for (int i=0; i<2; i++) { 75 | n[i] = c.get_nx(index[i]); 76 | } 77 | 78 | // allocate memory for arrays 79 | 80 | x = new double [ndim*n[0]*n[1]]; 81 | 82 | // set values for normal direction 83 | 84 | for (int j=0; j= 0 && index < ndim); 114 | 115 | return n[index]; 116 | } 117 | 118 | 119 | double surface::get_x(const int index, const int i, const int j) const { 120 | // returns value of x for given indices 121 | 122 | assert(index >= 0 && index < ndim); 123 | assert(i >= 0 && i < n[0]); 124 | assert(j >= 0 && j < n[1]); 125 | 126 | return x[index*n[0]*n[1]+i*n[1]+j]; 127 | } 128 | 129 | bool surface::has_same_edge(const int edge1, const int edge2, const surface& othersurf) const { 130 | // checks if two surfaces share the specified edges 131 | 132 | assert(edge1 >= 0 && edge1 < 4); 133 | assert(edge2 >= 0 && edge2 < 4); 134 | 135 | // edges are referred to by integers 0-3: 136 | // 0 means edge where second index is 0 137 | // 1 means edge where first index is 0 138 | // 2 means edge where second index is n2-1 139 | // 3 means edge where first index is n1-1 140 | 141 | int edge1index, edge2index; 142 | double abtol = 1.e-8; 143 | double reltol = 1.e-5; 144 | double a, b; 145 | 146 | if (edge1%2 == 1) { 147 | // fixed first index for this surface 148 | if (edge1 == 1) { 149 | edge1index = 0; 150 | } else { 151 | edge1index = n[0]-1; 152 | } 153 | if (edge2%2 == 1) { 154 | // fixed first index for othersurf 155 | if (edge2 == 1) { 156 | edge2index = 0; 157 | } else { 158 | edge2index = othersurf.get_n(0)-1; 159 | } 160 | if (n[1] != othersurf.get_n(1)) { 161 | return false; 162 | } else { 163 | for (int i=0; i (abtol + reltol*fabs(b))) { 168 | return false; 169 | } 170 | } 171 | } 172 | return true; 173 | } 174 | } else { 175 | // fixed second index for othersurf 176 | if (edge2 == 0) { 177 | edge2index = 0; 178 | } else { 179 | edge2index = othersurf.get_n(1)-1; 180 | } 181 | if (n[1] != othersurf.get_n(0)) { 182 | return false; 183 | } else { 184 | for (int i=0; i (abtol + reltol*fabs(b))) { 189 | return false; 190 | } 191 | } 192 | } 193 | return true; 194 | } 195 | } 196 | } else { 197 | // fixed second index for this surface 198 | if (edge1 == 0) { 199 | edge1index = 0; 200 | } else { 201 | edge1index = n[1]-1; 202 | } 203 | if (edge2%2 == 1) { 204 | // fixed first index for othersurf 205 | if (edge2 == 1) { 206 | edge2index = 0; 207 | } else { 208 | edge2index = othersurf.get_n(0)-1; 209 | } 210 | if (n[0] != othersurf.get_n(1)) { 211 | return false; 212 | } else { 213 | for (int i=0; i (abtol + reltol*fabs(b))) { 218 | return false; 219 | } 220 | } 221 | } 222 | return true; 223 | } 224 | } else { 225 | // fixed second index for othersurf 226 | if (edge2 == 0) { 227 | edge2index = 0; 228 | } else { 229 | edge2index = othersurf.get_n(1)-1; 230 | } 231 | if (n[0] != othersurf.get_n(0)) { 232 | return false; 233 | } else { 234 | for (int i=0; i (abtol + reltol*fabs(b))) { 239 | return false; 240 | } 241 | } 242 | } 243 | return true; 244 | } 245 | } 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/cartesian.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "cartesian.hpp" 6 | #include "coord.hpp" 7 | #include 8 | 9 | using namespace std; 10 | 11 | cartesian::cartesian(const char* filename, const int ndim_in, const int nx_in[3], const int nblocks[3], int** nx_block, int** xm_block, const int sbporder) { 12 | // constructor 13 | // sets up domain decomposition and holds process-specific information 14 | 15 | ndim = ndim_in; 16 | for (int i=0; i> nproc[i]; 38 | if (i == ndim) { 39 | nproc[i] = 1; 40 | } 41 | } 42 | } else { 43 | nproc[0] = 0; 44 | nproc[1] = 0; 45 | nproc[2] = 0; 46 | } 47 | } else { 48 | cout << "Error opening input file in cartesian.cpp. Defaulting to automatic domain decomposition\n"; 49 | nproc[0] = 0; 50 | nproc[1] = 0; 51 | nproc[2] = 0; 52 | } 53 | paramfile.close(); 54 | 55 | // allocate memory for process and coordinate information 56 | 57 | // allow process topology to be reordered 58 | 59 | reorder = true; 60 | 61 | // get process size and rank 62 | 63 | MPI_Comm_size(MPI_COMM_WORLD,&np); 64 | MPI_Comm_rank(MPI_COMM_WORLD,&id); 65 | 66 | // if manual decomposition does not agree with total number of processes, default to automatic decomposition 67 | 68 | if (nproc[0]*nproc[1]*nproc[2] != 0 && nproc[0]*nproc[1]*nproc[2] != np) { 69 | cout << "Number of processes does not match manual decomposition. Defaulting to automatic domain decomposition\n"; 70 | nproc[0] = 0; 71 | nproc[1] = 0; 72 | nproc[2] = 0; 73 | } 74 | 75 | // set up arrays for process info 76 | 77 | for (int i=0; i<3; i++) { 78 | if (i == ndim) { 79 | nproc[i] = 1; 80 | } 81 | if (nproc[i] < 0) { 82 | cout << "Number of processes cannot be negative. Defaulting to automatic decomposition\n"; 83 | nproc[i] = 0; 84 | } 85 | periods[i] = false; 86 | } 87 | 88 | // determine domain decomposition size 89 | 90 | MPI_Dims_create(np,ndim,nproc); 91 | 92 | // create cartesian communicator 93 | 94 | MPI_Cart_create(MPI_COMM_WORLD, ndim, nproc, periods, reorder, &comm); 95 | 96 | // get individual coordinates for this specific process 97 | 98 | MPI_Cart_coords(comm, id, ndim, coords); 99 | 100 | // now perform domain decomposition 101 | 102 | // determine how to distribute grid points 103 | 104 | for (int i=0; i xm_block[i][j] && c.get_xm_loc(i) < xm_block[i][j]+nx_block[i][j]-1) { 147 | c.set_xm_ghost(i,sbporder-1); 148 | } else if (c.get_xm_loc(i) == xm_block[i][j]+nx_block[i][j]) { 149 | c.set_xm_ghost(i,1); 150 | } 151 | 152 | if (c.get_xp_loc(i) > xm_block[i][j] && c.get_xp_loc(i) < xm_block[i][j]+nx_block[i][j]-1) { 153 | c.set_xp_ghost(i,sbporder-1); 154 | } else if (c.get_xp_loc(i) == xm_block[i][j]-1) { 155 | c.set_xp_ghost(i,1); 156 | } 157 | } 158 | } 159 | 160 | for (int i=0; i= 0 && direction < 3); 172 | 173 | return nproc[direction]; 174 | } 175 | 176 | int cartesian::get_coords(const int direction) const { 177 | // returns number of processes in specific direction 178 | assert(direction >= 0 && direction < 3); 179 | 180 | return coords[direction]; 181 | } 182 | 183 | int cartesian::get_nx(const int index) const { 184 | // returns number of x grid points 185 | assert(index >= 0 && index < 3); 186 | 187 | return c.get_nx(index); 188 | } 189 | 190 | int cartesian::get_nx_loc(const int index) const { 191 | // returns minimum x index for local process 192 | assert(index >= 0 && index < 3); 193 | 194 | return c.get_nx_loc(index); 195 | } 196 | 197 | 198 | int cartesian::get_xm_loc(const int index) const { 199 | // returns minimum x coordinate for local process 200 | assert(index >= 0 && index < 3); 201 | 202 | return c.get_xm_loc(index); 203 | } 204 | 205 | int cartesian::get_xp_loc(const int index) const { 206 | // returns minimum x coordinate for local process 207 | assert(index >= 0 && index < 3); 208 | 209 | return c.get_xp_loc(index); 210 | } 211 | 212 | int cartesian::get_xm_ghost(const int index) const { 213 | // returns number of ghost cells in minus direction for local process 214 | assert(index >= 0 && index < 3); 215 | 216 | return c.get_xm_ghost(index); 217 | } 218 | 219 | int cartesian::get_xp_ghost(const int index) const { 220 | // returns number of ghost cells in plus direction for local process 221 | assert(index >= 0 && index < 3); 222 | 223 | return c.get_xp_ghost(index); 224 | } 225 | 226 | int cartesian::get_nx_tot(const int index) const { 227 | // returns total number of local points (nx_loc + ghost points) in process 228 | assert(index >= 0 && index < 3); 229 | 230 | return c.get_nx_tot(index); 231 | } 232 | 233 | int cartesian::get_min_loc(const int index) const { 234 | // returns initial grid index for local process 235 | 236 | assert(index >= 0 && index < 3); 237 | 238 | return c.get_min_loc(index); 239 | } 240 | 241 | int cartesian::get_max_loc(const int index) const { 242 | //return max grid index for local process 243 | 244 | assert(index >= 0 && index < 3); 245 | 246 | return c.get_max_loc(index); 247 | } 248 | -------------------------------------------------------------------------------- /docs/examples/test2d.rst: -------------------------------------------------------------------------------- 1 | .. _test2d: 2 | 3 | ********************************** 4 | Example Problem in 2D 5 | ********************************** 6 | 7 | To illustrate how to specify parameters in a text file, here is an example problem ``test2d.in`` (included in the ``problems`` directory). This example illustrates a simple 2D rupture problem based on the SCEC Rupture Code Verification Group TPV3 (this is a horizontal slice of the 3D simulation at hypocentral depth). The initial stress and friction parameters are homogeneous, with the exception of a nucleation patch at the center of the fault and strong frictional barriers at the external boundaries of the fault. The simulation saves several fields, both on-fault and off-fault. 8 | 9 | .. literalinclude:: ../../problems/test2d.in 10 | 11 | This model is fairly simple, so use of a text input file rather than a python script is a reasonable choice. The following shows the model geometry: 12 | 13 | .. image:: test2d.* 14 | :width: 6in 15 | 16 | The input file first sets the problem variables. The simulation and output directories are named, then the time stepping information is set up. The simulation will take 1000 time steps, and use a CFL ratio of 0.3. Output will be written to the console every 50 time steps, and the integration order is 4th order. 17 | 18 | Next, the simulation domain is set up. The problem will be a 2D mode 2 fracture. The total domain will have 801 grid points in the :math:`{x}`-direction (along strike) and 802 grid points in the :math:`{y}`-direction (across the fault). Note that the extra grid point in the :math:`{y}`-direction accounts for the shared grid point along the fault; this will maintain the same grid resolution in both directions. We will use 2 blocks in the :math:`{y}`-direction, so since this is a 2D problem the number of blocks in each cartesian direction is ``1 2 1``. Following this, the exact number of grid points in each block along each direction is entered. Since there is one block in the :math:`{x}`-direction, we must give one number (801) for the :math:`{x}` grid length. Since there are two blocks in the :math:`{y}`-direction, we give two numbers (401 401). The :math:`{z}`-direction just has a ``1`` to signify that there is only one grid point in that direction. 19 | 20 | Next in the domain, we specify the interfaces. There is a single slip-weakening frictional interface in this simulation, so we give ``1`` for the number of interfaces and ``slipweak`` for the interface type. Finally, we set the finite difference order to be 4, and set the material properties to ``elastic`` (this is needed to correctly set up the blocks, fields, and simulation output). 21 | 22 | Information on the fields comes in the following section. This contains information on data stored at every grid point: the initial stress fields, heterogeneous material properties (located here because of how the code stores the heterogeneous field values), and whether or not the code will save the full plastic strain tensor for plasticity problems. Because this particular simulation chooses not to use any of these capabilities, all of these are set to zero, none, or false. For more information on how these are used, see the sections on code input. 23 | 24 | The simulation blocks are set up in the next section. The simulation has two blocks: ``block000`` and ``block010``. The three digit indicies are the x/y/z coordinates of each block, so ``000`` is the first block in the :math:`{y}` direction, and ``010`` is the second block in the :math:`{y}` direction. This sets the material properties, geometry, and boundary conditions on each of the blocks. The blocks both have the same material properties: :math:`{\rho = 2.67}` MPa s^2 / km / m (note the funny units, which are used to allow slips to be measured in meters while lengths are measured in kilometers, and the elastic moduli to be measured in GPa while the stresses are in MPa for calculational convenience), :math:`{\lambda = 32.04}` GPa, and :math:`{G = 23.04}` GPa. The blocks are each 40 km x 20 km, and they align at :math:`{y = 20}` km on the fault plane. All external boundaries (the input order is left, right, front, back) are absorbing, while the shared boundary at the fault has boundary conditions ``none`` (back for the ``000`` block, front for the ``010`` block), since the friction law will set these boundary conditions. This problem does not use any non-rectangular grids, so the section where filenames would be given for external curves/surfaces all give values of ``none``. 25 | 26 | This simulation does not use artificial dissipation, though it includes the operator section for completeness. 27 | 28 | The three lists that follow describe the fault friction. The problem has a single interface (``interface0``), with a normal direction in computational space in the :math:`{y}`-direction, and it joins together blocks ``000`` and ``010``. All of this is specified in the interface section. Next come the information on interface stresses and friction parameters, which are in the ``friction`` and ``slipweak`` sections. Note that no number is required for these section -- the code simply finds the first occurrence of ``friction`` and ``slipweak`` following the ``interface0`` section. 29 | 30 | Under the friction section, the traction on the fault is modified with two "perturbations." The first sets the constant initial background stress to be :math:`{\sigma_n = -120}` MPa and :math:`{\tau_h = 70}` MPa. Since this is a 2D problem, the vertical interface traction is ignored. Next is a boxcar function to nucleate the rupture by overstressing a fault patch. The boxcar is centered at :math:`{x=20}` km and has a half width of 1.5 km, and the patch includes an additional 11.6 MPa of horizontal traction (this ensures that the initial stress, which is the sum of all perturbations, exceeds the static friction level). No file is used to further modify the initial tractions, so ``none`` is given for the load file entry. 31 | 32 | The friction parameters are changed in the ``slipweak`` section using three perturbations. The first entry sets the constant background values to :math:`{d_c = 0.4}` m, :math:`{\mu_s = 0.677}`, and :math:`{\mu_d = 0.525}`. The simulation has no cohesion or forced rupture. The other two perturbations increase the initial static friction to be high enough to be unbreakable barriers for the outer 5 km at each end of the domain; these prevent the rupture from hitting the edge of the simulation domain. No parameter files is used to further modify the friction parameters. 33 | 34 | The final sections set up simulation output. The simulation saves three output units to disk. These output units illustrate the different ways that output can be saved to disk. 35 | 36 | The first ouput unit saves the full 2D grid values of :math:`{v_x}` (the horizontal particle velocity) every 100 time steps. The first entry gives a name for the output unit (used to keep track of the different output units, so each one should have a unique name), and the second entry is the field to be saved (``vx`` here, to denote the particle velocity, and note that this is case sensitive). Next are three numbers describing time output: start end stride. The simulation will start saving data at the 0 time step, stop saving at the 1000 time step (i.e. the end of the simulation), and save every 100 time steps (chosen to be large as the files can be quite large if we save every grid point). The next three sets of numbers are the start, end, and stride for the x, y, and z directions. Thus, we start at grid point 0, end at grid point 800, and take every point for x; start at 0, end at 801, and take every point for y; and start and end at 0 for z (since this is a 2D simulation). 37 | 38 | The second output unit saves the slip velocity on the fault. The name and field are both ``V``, and since the slip velocity is only defined on the fault, you will get an error if you try to choose values that are not on the fault interface. Here I pick values on the fault using y indices of 401 for both the start and end values. The x indices go from 0 to 800, and the time values go from 0 to 1000, saving every 10 points. 39 | 40 | Finally, we save the shear stress at a single grid point for all time steps. The field ``sxy`` indicates which stress tensor value we want, and the time values go from 0 to 1000, saving every time step. Note that the spatial indices have the same starting and ending values, ensuring that only a single grid point is saved. 41 | 42 | The output list must end with a blank line before any additional sections may be specified on the input file. The only one that comes afterwards is the frontlist, which determines the time that all grid points on the fault rupture. This is turned off for this simulation. 43 | 44 | This shows all of the different sections that need to be set up to specify a rupture problem. This is a simple 2D simulation with homoeneous properties (save the nucleation point and the barriers to rupture), so it can easily be written as a single text file. More complicated problems are better handled using the Python module, which is described in the next example. -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. epub3 to make an epub3 31 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 32 | echo. text to make text files 33 | echo. man to make manual pages 34 | echo. texinfo to make Texinfo files 35 | echo. gettext to make PO message catalogs 36 | echo. changes to make an overview over all changed/added/deprecated items 37 | echo. xml to make Docutils-native XML files 38 | echo. pseudoxml to make pseudoxml-XML files for display purposes 39 | echo. linkcheck to check all external links for integrity 40 | echo. doctest to run all doctests embedded in the documentation if enabled 41 | echo. coverage to run coverage check of the documentation if enabled 42 | echo. dummy to check syntax errors of document sources 43 | goto end 44 | ) 45 | 46 | if "%1" == "clean" ( 47 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 48 | del /q /s %BUILDDIR%\* 49 | goto end 50 | ) 51 | 52 | 53 | REM Check if sphinx-build is available and fallback to Python version if any 54 | %SPHINXBUILD% 1>NUL 2>NUL 55 | if errorlevel 9009 goto sphinx_python 56 | goto sphinx_ok 57 | 58 | :sphinx_python 59 | 60 | set SPHINXBUILD=python -m sphinx.__init__ 61 | %SPHINXBUILD% 2> nul 62 | if errorlevel 9009 ( 63 | echo. 64 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 65 | echo.installed, then set the SPHINXBUILD environment variable to point 66 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 67 | echo.may add the Sphinx directory to PATH. 68 | echo. 69 | echo.If you don't have Sphinx installed, grab it from 70 | echo.http://sphinx-doc.org/ 71 | exit /b 1 72 | ) 73 | 74 | :sphinx_ok 75 | 76 | 77 | if "%1" == "html" ( 78 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 79 | if errorlevel 1 exit /b 1 80 | echo. 81 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 82 | goto end 83 | ) 84 | 85 | if "%1" == "dirhtml" ( 86 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 87 | if errorlevel 1 exit /b 1 88 | echo. 89 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 90 | goto end 91 | ) 92 | 93 | if "%1" == "singlehtml" ( 94 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 95 | if errorlevel 1 exit /b 1 96 | echo. 97 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 98 | goto end 99 | ) 100 | 101 | if "%1" == "pickle" ( 102 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 103 | if errorlevel 1 exit /b 1 104 | echo. 105 | echo.Build finished; now you can process the pickle files. 106 | goto end 107 | ) 108 | 109 | if "%1" == "json" ( 110 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 111 | if errorlevel 1 exit /b 1 112 | echo. 113 | echo.Build finished; now you can process the JSON files. 114 | goto end 115 | ) 116 | 117 | if "%1" == "htmlhelp" ( 118 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 119 | if errorlevel 1 exit /b 1 120 | echo. 121 | echo.Build finished; now you can run HTML Help Workshop with the ^ 122 | .hhp project file in %BUILDDIR%/htmlhelp. 123 | goto end 124 | ) 125 | 126 | if "%1" == "qthelp" ( 127 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 128 | if errorlevel 1 exit /b 1 129 | echo. 130 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 131 | .qhcp project file in %BUILDDIR%/qthelp, like this: 132 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\fdfault_docs.qhcp 133 | echo.To view the help file: 134 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\fdfault_docs.ghc 135 | goto end 136 | ) 137 | 138 | if "%1" == "devhelp" ( 139 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 140 | if errorlevel 1 exit /b 1 141 | echo. 142 | echo.Build finished. 143 | goto end 144 | ) 145 | 146 | if "%1" == "epub" ( 147 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 148 | if errorlevel 1 exit /b 1 149 | echo. 150 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 151 | goto end 152 | ) 153 | 154 | if "%1" == "epub3" ( 155 | %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3 156 | if errorlevel 1 exit /b 1 157 | echo. 158 | echo.Build finished. The epub3 file is in %BUILDDIR%/epub3. 159 | goto end 160 | ) 161 | 162 | if "%1" == "latex" ( 163 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 164 | if errorlevel 1 exit /b 1 165 | echo. 166 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 167 | goto end 168 | ) 169 | 170 | if "%1" == "latexpdf" ( 171 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 172 | cd %BUILDDIR%/latex 173 | make all-pdf 174 | cd %~dp0 175 | echo. 176 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 177 | goto end 178 | ) 179 | 180 | if "%1" == "latexpdfja" ( 181 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 182 | cd %BUILDDIR%/latex 183 | make all-pdf-ja 184 | cd %~dp0 185 | echo. 186 | echo.Build finished; the PDF files are in %BUILDDIR%/latex. 187 | goto end 188 | ) 189 | 190 | if "%1" == "text" ( 191 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 192 | if errorlevel 1 exit /b 1 193 | echo. 194 | echo.Build finished. The text files are in %BUILDDIR%/text. 195 | goto end 196 | ) 197 | 198 | if "%1" == "man" ( 199 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 200 | if errorlevel 1 exit /b 1 201 | echo. 202 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 203 | goto end 204 | ) 205 | 206 | if "%1" == "texinfo" ( 207 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 208 | if errorlevel 1 exit /b 1 209 | echo. 210 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 211 | goto end 212 | ) 213 | 214 | if "%1" == "gettext" ( 215 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 216 | if errorlevel 1 exit /b 1 217 | echo. 218 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 219 | goto end 220 | ) 221 | 222 | if "%1" == "changes" ( 223 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 224 | if errorlevel 1 exit /b 1 225 | echo. 226 | echo.The overview file is in %BUILDDIR%/changes. 227 | goto end 228 | ) 229 | 230 | if "%1" == "linkcheck" ( 231 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 232 | if errorlevel 1 exit /b 1 233 | echo. 234 | echo.Link check complete; look for any errors in the above output ^ 235 | or in %BUILDDIR%/linkcheck/output.txt. 236 | goto end 237 | ) 238 | 239 | if "%1" == "doctest" ( 240 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 241 | if errorlevel 1 exit /b 1 242 | echo. 243 | echo.Testing of doctests in the sources finished, look at the ^ 244 | results in %BUILDDIR%/doctest/output.txt. 245 | goto end 246 | ) 247 | 248 | if "%1" == "coverage" ( 249 | %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage 250 | if errorlevel 1 exit /b 1 251 | echo. 252 | echo.Testing of coverage in the sources finished, look at the ^ 253 | results in %BUILDDIR%/coverage/python.txt. 254 | goto end 255 | ) 256 | 257 | if "%1" == "xml" ( 258 | %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml 259 | if errorlevel 1 exit /b 1 260 | echo. 261 | echo.Build finished. The XML files are in %BUILDDIR%/xml. 262 | goto end 263 | ) 264 | 265 | if "%1" == "pseudoxml" ( 266 | %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml 267 | if errorlevel 1 exit /b 1 268 | echo. 269 | echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. 270 | goto end 271 | ) 272 | 273 | if "%1" == "dummy" ( 274 | %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy 275 | if errorlevel 1 exit /b 1 276 | echo. 277 | echo.Build finished. Dummy builder generates no files. 278 | goto end 279 | ) 280 | 281 | :end 282 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 16 | 17 | ANTIALIAS = -dGraphicsAlphaBits=4 -dTextAlphaBits=4 18 | GSOPTIONS = -q -dNOPAUSE -dSAFER 19 | 20 | IMAGESTEX := $(wildcard examples/*.tex) 21 | IMAGESPDF := $(IMAGESTEX:.tex=.pdf) 22 | IMAGESPNG := $(IMAGESTEX:.tex=.png) 23 | IMAGESAUX := $(IMAGESTEX:.tex=.aux) 24 | IMAGESLOG := $(IMAGESTEX:.tex=.log) 25 | 26 | GSDEVICE = -sDEVICE=pnggray 27 | GSRES = -r200 28 | 29 | .PHONY: help 30 | help: 31 | @echo "Please use \`make ' where is one of" 32 | @echo " html to make standalone HTML files" 33 | @echo " dirhtml to make HTML files named index.html in directories" 34 | @echo " singlehtml to make a single large HTML file" 35 | @echo " pickle to make pickle files" 36 | @echo " json to make JSON files" 37 | @echo " htmlhelp to make HTML files and a HTML help project" 38 | @echo " qthelp to make HTML files and a qthelp project" 39 | @echo " applehelp to make an Apple Help Book" 40 | @echo " devhelp to make HTML files and a Devhelp project" 41 | @echo " epub to make an epub" 42 | @echo " epub3 to make an epub3" 43 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 44 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 45 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 46 | @echo " text to make text files" 47 | @echo " man to make manual pages" 48 | @echo " texinfo to make Texinfo files" 49 | @echo " info to make Texinfo files and run them through makeinfo" 50 | @echo " gettext to make PO message catalogs" 51 | @echo " changes to make an overview of all changed/added/deprecated items" 52 | @echo " xml to make Docutils-native XML files" 53 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 54 | @echo " linkcheck to check all external links for integrity" 55 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 56 | @echo " coverage to run coverage check of the documentation (if enabled)" 57 | @echo " dummy to check syntax errors of document sources" 58 | 59 | .PHONY: clean 60 | clean: 61 | rm -rf $(BUILDDIR)/* 62 | 63 | .PHONY: html 64 | html: $(IMAGESPNG) 65 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 66 | @echo 67 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 68 | 69 | .PHONY: dirhtml 70 | dirhtml: 71 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 72 | @echo 73 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 74 | 75 | .PHONY: singlehtml 76 | singlehtml: $(IMAGESPNG) 77 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 78 | @echo 79 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 80 | 81 | .PHONY: pickle 82 | pickle: 83 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 84 | @echo 85 | @echo "Build finished; now you can process the pickle files." 86 | 87 | .PHONY: json 88 | json: 89 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 90 | @echo 91 | @echo "Build finished; now you can process the JSON files." 92 | 93 | .PHONY: htmlhelp 94 | htmlhelp: 95 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 96 | @echo 97 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 98 | ".hhp project file in $(BUILDDIR)/htmlhelp." 99 | 100 | .PHONY: qthelp 101 | qthelp: 102 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 103 | @echo 104 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 105 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 106 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/fdfault_docs.qhcp" 107 | @echo "To view the help file:" 108 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/fdfault_docs.qhc" 109 | 110 | .PHONY: applehelp 111 | applehelp: 112 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 113 | @echo 114 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 115 | @echo "N.B. You won't be able to view it unless you put it in" \ 116 | "~/Library/Documentation/Help or install it in your application" \ 117 | "bundle." 118 | 119 | .PHONY: devhelp 120 | devhelp: 121 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 122 | @echo 123 | @echo "Build finished." 124 | @echo "To view the help file:" 125 | @echo "# mkdir -p $$HOME/.local/share/devhelp/fdfault_docs" 126 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/fdfault_docs" 127 | @echo "# devhelp" 128 | 129 | .PHONY: epub 130 | epub: 131 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 132 | @echo 133 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 134 | 135 | .PHONY: epub3 136 | epub3: 137 | $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 138 | @echo 139 | @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." 140 | 141 | .PHONY: latex 142 | latex: $(IMAGESPDF) 143 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 144 | @echo 145 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 146 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 147 | "(use \`make latexpdf' here to do that automatically)." 148 | 149 | .PHONY: latexpdf 150 | latexpdf: $(IMAGESPDF) 151 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 152 | @echo "Running LaTeX files through pdflatex..." 153 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 154 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 155 | 156 | .PHONY: latexpdfja 157 | latexpdfja: $(IMAGESPDF) 158 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 159 | @echo "Running LaTeX files through platex and dvipdfmx..." 160 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 161 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 162 | 163 | .PHONY: text 164 | text: 165 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 166 | @echo 167 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 168 | 169 | .PHONY: man 170 | man: 171 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 172 | @echo 173 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 174 | 175 | .PHONY: texinfo 176 | texinfo: 177 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 178 | @echo 179 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 180 | @echo "Run \`make' in that directory to run these through makeinfo" \ 181 | "(use \`make info' here to do that automatically)." 182 | 183 | .PHONY: info 184 | info: 185 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 186 | @echo "Running Texinfo files through makeinfo..." 187 | make -C $(BUILDDIR)/texinfo info 188 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 189 | 190 | .PHONY: gettext 191 | gettext: 192 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 193 | @echo 194 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 195 | 196 | .PHONY: changes 197 | changes: 198 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 199 | @echo 200 | @echo "The overview file is in $(BUILDDIR)/changes." 201 | 202 | .PHONY: linkcheck 203 | linkcheck: 204 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 205 | @echo 206 | @echo "Link check complete; look for any errors in the above output " \ 207 | "or in $(BUILDDIR)/linkcheck/output.txt." 208 | 209 | .PHONY: doctest 210 | doctest: 211 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 212 | @echo "Testing of doctests in the sources finished, look at the " \ 213 | "results in $(BUILDDIR)/doctest/output.txt." 214 | 215 | .PHONY: coverage 216 | coverage: 217 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 218 | @echo "Testing of coverage in the sources finished, look at the " \ 219 | "results in $(BUILDDIR)/coverage/python.txt." 220 | 221 | .PHONY: xml 222 | xml: 223 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 224 | @echo 225 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 226 | 227 | .PHONY: pseudoxml 228 | pseudoxml: 229 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 230 | @echo 231 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 232 | 233 | .PHONY: dummy 234 | dummy: 235 | $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy 236 | @echo 237 | @echo "Build finished. Dummy builder generates no files." 238 | 239 | %.pdf: %.tex 240 | pdflatex -output-directory examples $< 241 | rm -f $(IMAGESLOG) 242 | rm -f $(IMAGESAUX) 243 | 244 | %.png: %.pdf 245 | gs $(GSOPTIONS) $(GSDEVICE) $(ANTIALIAS) $(GSRES) -o $@ $< 246 | --------------------------------------------------------------------------------