#ifndef _SGM_ESL_H
#define _SGM_ESL_H
#include "head_func.h"

/**
 * @brief      利用等效源对重磁场进行区域场与剩余场的分离
 * 
 * 通过对等效源进行分区，迭代反演并正演不同分区的等效源对重磁场的区域与剩余场的分离。
 */
class SGM_ESL
{
public:
	SGM_ESL(){}
	~SGM_ESL(){}
	/**
	 * @brief      运行流程函数
	 *
	 * @param      <unnamed>  参数配置文件
	 *
	 * @return     返回运行状态，正确0、错误-1。
	 */
	int Routine(char*);
	/**
	 * @brief      初始化观测点数据
	 * 
	 * @warning    规则网格数据如果给定数据范围与间距则函数会将观测点插值至等效源块体的中心位置。
	 *
	 * @param      <unnamed>  观测点读入参数
	 * 
	 * 参数形式：<filename>[+r<xmin>/<xmax>/<ymin>/<ymax>+i<dx>/<dy>]
	 *
	 * @return     返回运行状态，正确0、错误-1。
	 */
	int InitObsPoints(char*);
	/**
	 * @brief      输出观测点数据
	 *
	 * @param      <unnamed>  输出文件名
	 * @param      <unnamed>  需要输出的数据
	 *
	 * @return     返回运行状态，正确0、错误-1。
	 */
	int OutObsPoints(const char*,_1dArray);
	/**
	 * @brief      输出观测点数据
	 *
	 * @param      <unnamed>  输出文件名
	 * @param      <unnamed>  需要输出的数据
	 * @param      <unnamed>  需要输出的数据
	 * @param      <unnamed>  需要输出的数据
	 *
	 * @return     返回运行状态，正确0、错误-1。
	 */
	int OutObsPoints(const char*,_1dArray,_1dArray,_1dArray);
	/**
	 * @brief      初始化等效源块体
	 *
	 * @param      <unnamed>  输入文件名
	 * @param      <unnamed>  区域场对应的等效源块体的物理分组代码
	 * @param      <unnamed>  等效源层的上顶面
	 * @param      <unnamed>  等效源层的下底面
	 *
	 * @return     返回运行状态，正确0、错误-1。
	 */
	int InitModBlocks(char*,int,double,double);
	/**
	 * @brief      输出等效源模型块体的框架信息
	 *
	 * @param      <unnamed>  输出文件名
	 *
	 * @return     返回运行状态，正确0、错误-1。
	 */
	int OutModBlocks(char*);
	/**
	 * @brief      输出等效源模型块体的模型参数信息
	 *
	 * @param      <unnamed>  输出文件名
	 * @param[in]  <unnamed>  输出的模型参数的名称
	 * @param.     <unnamed>..输出模型参数的数组
	 *
	 * @return     返回运行状态，正确0、错误-1。
	 */
	int OutModEleData(char*,string,_1dArray);
	/**
	 * @brief      计算重力计算核函数
	 */
	void CalGKernel();
	/**
	 * @brief      计算磁场DeltaT核函数
	 */
	void CalDeltaTKernel();
	/**
	 * @brief      计算等效源体积与深度加权矩阵
	 */
	void CalWvWz();
	/**
	 * @brief      计算反演预优矩阵
	 *
	 * @param[in]  <unnamed>  预优因子，一般为1.0
	 */
	void CalWp(double);
	/**
	 * @brief      计算模型拟合差矩阵
	 *
	 * @param[in]  <unnamed>  数据不确定度参数，一般为1.0
	 */
	void CalWd(double);
	/**
	 * @brief      计算共轭梯度目标矩阵
	 *
	 * @param[in]  <unnamed>  观测值数组
	 */
	void CalPartB(_1dArray);
	/**
	 * @brief      计算部分等效源重力数据
	 *
	 * @param      <unnamed>  输出观测数据数组
	 */
	void CalPartialModel(_1dArray&);
	/**
	 * @brief      计算部分等效源重力数据
	 *
	 * @param      <unnamed>  输出观测数据数组
	 * @param      <unnamed>  等效源分组信息数据（可选）
	 */
	void CalPartialModel(_1dArray&,_1dArray);
	/**
	 * @brief      预优共轭梯度求解函数
	 *
	 * @param[in]  <unnamed>  观测值数组
	 */
	void OptimizeCG_Precondition(_1dArray);
private:
	//观测点数组
	int obs_points_num_;
	obspointArray obs_points_;
	_1dArray total_field_;
	_1dArray regional_field_;
	_1dArray object_field_;
	_1dArray regional_regional_field_;
	_1dArray regional_object_field_;
	_1dArray object_regional_field_;
	_1dArray object_object_field_;
	//模型块体数组
	int mod_vertice_num_;
	int mod_blocks_num_;
	cpointArray mod_vertice_;
	blockArray mod_blocks_;
	_2dArray mod_elements_;
	_1sArray mod_elements_names_;
	//模型属性数组
	_1dArray init_model_; char init_model_name_[1024];
	_1dArray invert_model_;
	_1dArray regional_model_list_;
	_1dArray object_model_list_;
	_2dArray GM_kernel_;
	//反演参数
	_1dArray WvTWv,WzTWz,WdTWd,Wp,PartB;
	int iter_times_;
	double alpha_, beta_;
	//double D0_, I0_, D_, I_; ///< 地磁参数与磁化参数
	// 假设局部与区域磁化参数不一样
	double D0_, I0_, loc_D_, loc_I_, reg_D_, reg_I_;
};
#endif //_SGM_ESL_H