In addition, the forward and adjoint functions have several optional arguments. The add is used in to signify that the output of the operation should be added to an existing vector. The restart can be used to signify that we are restarting the operator. When the operator is being used an inversion problem, two additional arguments will be passed. The iter argument corresponds to the current iteration. The status argument is a SEP.status_sep.status object used to keep track of the progress of the inversion. If passed in, the starting and finishing of the operation will be recorded in the status file. The forward and adjoint functions only deal with keeping track of the progress of the inversion. The real work is done by the adjoint_op and forward_op functions. These two functions must be overridden by its children. The SEP.oc_base.operator defines a function dot_test which tests to make sure the operator passes the dot product test. The init_op(restart) function is defined to perform operations needed before the operator is initialized for the first time. The restart argument is used to signify whether the job is being restarted.
The simplest operator that is derived from the SEP.op_base.operator class is the SEP.op_scale.operator operator. This operator is simply a diagonal operator where elements along the diagonal are constant. It uses the SEP.vec_base.vector vector operations to run the forward and adjoint. It is used by the solver to apply when doing regularized or preconditioned inversion.
Two classes for combining operator are also derived. The first SEP.op_combo.chain class chains two or more operators together (eg. ) , where and are both operators. When initialized, it checks to make sure that the domain of and the range of are the same space. The init_op function is overridden to create the temporary vector of the shared space. The SEP.op_combo.array class is used to define an array of operators. The number of columns and rows, along with the operators, are passed in during initialization. It can be useful for regularized problems and building complex inversion operators. The range and domain vectors are constructed from the SEP.op_super.vector vector class.
The current operator tree can be seen in Figure . An out-of-core operator class, SEP.op_oc.operator, is also derived from the SEP.op_base.operator class. This class expects its inputs and outputs will be stored on disk. The SEP.op_oc_serial.operator is used for operators that are applied by a serial code. The class is derived from both the SEP.op_oc.operator and SEP.opt_par_group.par_group. It is initialized by the location of the serial code prog and optionally the name, a description of the operator (defaulting to the program name), a verbosity flag (verb), and the message to print when applying the operator (msg). Other operator's parameters are set using the SEP.opt_par_group.par_group parameter methodology.
Figure 3 The inheritance class for operators
The final two operator classes, SEP.op_oc_par.operator and SEP.op_oc_par_split.operator, are for parallel jobs. They are derived from the SEP.pj_base.par_job and SEP.pj_split.par_job class along with the SEP.op_oc.operator class. The SEP.op_oc_par.operator class is designed for jobs where the domain and range vectors will be distributed and collected before and after the parallel job. The SEP.op_oc_par_split.operator class is useful for problems where distributing and collecting the files after every operation is not practical. All of the initialization and parameters are generally handled the same as for the SEP.op_oc_serial.operator. The domain and range vectors are either SEP.pv_copy.vector or SEP.pv_split.vector in the case of SEP.op_oc_par.operator operator. In the case of the SEP.op_oc_par_split.operator object, the vectors must be of the SEP.pv_always_split.vector type. To run the operator, a parallel job is executed rather than running a serial code.