/******************************************************** * ██████╗ ██████╗████████╗██╗ * ██╔════╝ ██╔════╝╚══██╔══╝██║ * ██║ ███╗██║ ██║ ██║ * ██║ ██║██║ ██║ ██║ * ╚██████╔╝╚██████╗ ██║ ███████╗ * ╚═════╝ ╚═════╝ ╚═╝ ╚══════╝ * Geophysical Computational Tools & Library (GCTL) * * Copyright (c) 2023 Yi Zhang (yizhang-geo@zju.edu.cn) * * GCTL is distributed under a dual licensing scheme. You can redistribute * it and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either version 2 * of the License, or (at your option) any later version. You should have * received a copy of the GNU Lesser General Public License along with this * program. If not, see . * * If the terms and conditions of the LGPL v.2. would prevent you from using * the GCTL, please consider the option to obtain a commercial license for a * fee. These licenses are offered by the GCTL's original author. As a rule, * licenses are provided "as-is", unlimited in time for a one time fee. Please * send corresponding requests to: yizhang-geo@zju.edu.cn. Please do not forget * to include some description of your company and the realm of its activities. * Also add information on how to contact you by electronic and paper mail. ******************************************************/ #include "algorithm_func.h" double gctl::dist_inverse_weight(std::vector *dis_vec, std::vector *val_vec, int order) { if (dis_vec->size() != val_vec->size()) throw runtime_error("The arrays have different sizes. Thrown by gctl::dist_inverse_weight(...)"); double total_dist = 0; for (int i = 0; i < dis_vec->size(); i++) { dis_vec->at(i) = 1.0/(GCTL_ZERO + pow(dis_vec->at(i),order)); total_dist += dis_vec->at(i); } double ret = 0.0; for (int i = 0; i < dis_vec->size(); i++) { ret += val_vec->at(i)*dis_vec->at(i)/total_dist; } return ret; } int gctl::find_index(const double *in_array, int array_size, double in_val, int &index) { if (array_size <= 0) { index = -1; return -1; } else if (array_size == 1) { index = -1; return -1; } else if (in_val < in_array[0] || in_val > in_array[array_size-1]) { index = -1; return -1; } else if (array_size == 2) { index = 0; return 0; } else { int low_range = 0; int high_range = array_size - 1; int test_index; bool found = false; while (high_range - low_range >= 1) { test_index = floor(0.5*(low_range + high_range)); if (in_val >= in_array[test_index] && in_val <= in_array[test_index+1]) { index = test_index; found = true; break; } else if (in_val < in_array[test_index]) { high_range = test_index; } else if (in_val > in_array[test_index+1]) { low_range = test_index+1; } } if (found) return 0; else return -1; } } int gctl::find_index(array *in_array, double in_val, int &index) { return find_index(in_array->get(), in_array->size(), in_val, index); } void gctl::fractal_model_1d(array &out_arr, int out_size, double l_val, double r_val, double maxi_range, double smoothness) { if (out_size <= 0) throw invalid_argument("Negative output size. Thrown by gctl::fractal_model_1d(...)"); if (maxi_range <= 0) throw invalid_argument("Negative maximal range. Thrown by gctl::fractal_model_1d(...)"); if (smoothness <= 0) throw invalid_argument("Negative smoothness. Thrown by gctl::fractal_model_1d(...)"); out_arr.resize(out_size); int bigger_num = (int) pow(2, ceil(log(out_arr.size()-1)/log(2))) + 1; array tmp_arr(bigger_num); // 计算的长度必须为2的次方数 int step_size = (int) (bigger_num-1)/2; tmp_arr[0] = l_val; tmp_arr[bigger_num-1] = r_val; srand(time(0)); while (step_size >= 1) { for (int i = step_size; i < bigger_num; i += 2*step_size) { tmp_arr[i] = random(-1.0*maxi_range, maxi_range) + 0.5*(tmp_arr[i-step_size] + tmp_arr[i+step_size]); } maxi_range = pow(2.0, -1.0*smoothness)*maxi_range; step_size /= 2; } for (int i = 0; i < out_arr.size(); i++) { out_arr[i] = tmp_arr[i]; } return; } void gctl::fractal_model_2d(_2d_matrix &out_arr, int r_size, int c_size, double dl_val, double dr_val, double ul_val, double ur_val, double maxi_range, double smoothness, unsigned int seed) { if (r_size <= 0 || c_size <= 0) throw invalid_argument("Negative output size. Thrown by gctl::fractal_model_2d(...)"); if (maxi_range <= 0) throw invalid_argument("Negative maximal range. Thrown by gctl::fractal_model_2d(...)"); if (smoothness <= 0) throw invalid_argument("Negative smoothness. Thrown by gctl::fractal_model_2d(...)"); int i, j, m, n, R, jmax; double random_d; out_arr.resize(r_size, c_size); int xnum = out_arr.col_size(); int ynum = out_arr.row_size(); int order_x = ceil(log(xnum-1)/log(2)); int order_y = ceil(log(ynum-1)/log(2)); int imax = GCTL_MAX(order_x,order_y); int ntotal = (int) pow(2.0, imax) + 1; //总数据点数为2的imax次方加1 _2d_matrix topo(ntotal, ntotal, 0.0); for (i=0; i &in, array &diff, double spacing, int order) { if (order < 1 || order > 4) throw invalid_argument("The input order can only be 1 to 4. Thrown by gctl::difference_1d(...)"); if (spacing <= 0.0) throw invalid_argument("The input spacing can't be negative or zero. Thrown by void gctl::difference_1d(...)"); if (order == 1 && in.size() < 3) throw runtime_error("The input array size must be equal to or bigger than three for the first order derivative. Thrown by gctl::difference_1d(...)"); if (order == 2 && in.size() < 4) throw runtime_error("The input array size must be equal to or bigger than four for the second order derivative. Thrown by gctl::difference_1d(...)"); if (order == 3 && in.size() < 6) throw runtime_error("The input array size must be equal to or bigger than six for the third order derivative. Thrown by gctl::difference_1d(...)"); if (order == 4 && in.size() < 7) throw runtime_error("The input array size must be equal to or bigger than seven for the fourth order derivative. Thrown by gctl::difference_1d(...)"); int t_size = in.size(); diff.resize(t_size); // 利用向前或向后差分计算边缘元素的导数 if (order == 1) { diff[0] = (-3.0*in[0]+4.0*in[1]-in[2])/(2.0*spacing); diff[t_size-1] = (3.0*in[t_size-1]-4.0*in[t_size-2]+in[t_size-3])/(2.0*spacing); for (int i = 1; i < t_size-1; i++) { diff[i] = (in[i+1] - in[i-1])/(2.0*spacing); } } else if (order == 2) { diff[0] = (2.0*in[0]-5.0*in[1]+4.0*in[2]-in[3])/(spacing*spacing); diff[t_size-1] = (2.0*in[t_size-1]-5.0*in[t_size-2]+4.0*in[t_size-3]-in[t_size-4])/(spacing*spacing); for (int i = 1; i < t_size-1; i++) { diff[i] = (in[i-1]-2.0*in[i]+in[i+1])/(spacing*spacing); } } else if (order == 3) { diff[0] = (-5.0*in[0]+18.0*in[1]-24.0*in[2]+14.0*in[3]-3.0*in[4])/(2.0*spacing*spacing*spacing); diff[1] = (-5.0*in[1]+18.0*in[2]-24.0*in[3]+14.0*in[4]-3.0*in[5])/(2.0*spacing*spacing*spacing); diff[t_size-1] = (5.0*in[t_size-1]-18.0*in[t_size-2]+24.0*in[t_size-3]-14.0*in[t_size-4]+3.0*in[t_size-5])/(2.0*spacing*spacing*spacing); diff[t_size-2] = (5.0*in[t_size-2]-18.0*in[t_size-3]+24.0*in[t_size-4]-14.0*in[t_size-5]+3.0*in[t_size-6])/(2.0*spacing*spacing*spacing); for (int i = 2; i < t_size-2; i++) { diff[i] = (-1.0*in[i-2]+2.0*in[i-1]-2.0*in[i+1]+in[i+2])/(2.0*spacing*spacing*spacing); } } else { diff[0] = (3.0*in[0]-14.0*in[1]+26.0*in[2]-24.0*in[3]+11.0*in[4]-2.0*in[5])/(spacing*spacing*spacing*spacing); diff[1] = (3.0*in[1]-14.0*in[2]+26.0*in[3]-24.0*in[4]+11.0*in[5]-2.0*in[6])/(spacing*spacing*spacing*spacing); diff[t_size-1] = (3.0*in[t_size-1]-14.0*in[t_size-2]+26.0*in[t_size-3]-24.0*in[t_size-4]+11.0*in[t_size-5]-2.0*in[t_size-6])/(spacing*spacing*spacing*spacing); diff[t_size-2] = (3.0*in[t_size-2]-14.0*in[t_size-3]+26.0*in[t_size-4]-24.0*in[t_size-5]+11.0*in[t_size-6]-2.0*in[t_size-7])/(spacing*spacing*spacing*spacing); for (int i = 2; i < t_size-2; i++) { diff[i] = (in[i-2]-4.0*in[i-1]+6.0*in[i]-4.0*in[i+1]+in[i+2])/(spacing*spacing*spacing*spacing); } } return; } void gctl::difference_2d(const _2d_matrix &in, _2d_matrix &diff, double spacing, gradient_type_e d_type, int order) { std::string err_str; if (order < 1 || order > 4) throw invalid_argument("The input order can only be 1 to 4. Thrown by void gctl::difference_2d(...)"); if (spacing <= 0.0) throw invalid_argument("The input spacing can't be negative or zero. Thrown by void gctl::difference_2d(...)"); int t_size; if (d_type == Dx) { t_size = in.col_size(); } else if (d_type == Dy) { t_size = in.row_size(); } else { throw logic_error("The calculation type must be Dx or Dy. Thrown by gctl::difference_2d(...)"); } if (order == 1 && t_size < 3) throw runtime_error("The input array size must be equal to or bigger than 3x3 for the first order derivative. Thrown by void gctl::difference_2d(...)"); if (order == 2 && t_size < 4) throw runtime_error("The input array size must be equal to or bigger than 4x4 for the second order derivative. Thrown by gctl::difference_2d(...)"); if (order == 3 && t_size < 6) throw runtime_error("The input array size must be equal to or bigger than 6x6 for the third order derivative. Thrown by gctl::difference_2d(...)"); if (order == 4 && t_size < 7) throw runtime_error("The input array size must be equal to or bigger than 7x7 for the fourth order derivative. Thrown by void gctl::difference_2d(...)"); int tr_size = in.row_size(), tl_size = in.col_size(); diff.resize(tr_size, tl_size); if (d_type == Dx) { if (order == 1) { for (int i = 0; i < tr_size; i++) { diff[i][0] = (-3.0*in[i][0]+4.0*in[i][1]-in[i][2])/(2.0*spacing); diff[i][tl_size-1] = (3.0*in[i][tl_size-1]-4.0*in[i][tl_size-2]+in[i][tl_size-3])/(2.0*spacing); for (int j = 1; j < tl_size-1; j++) { diff[i][j] = (in[i][j+1] - in[i][j-1])/(2.0*spacing); } } } else if (order == 2) { for (int i = 0; i < tr_size; i++) { diff[i][0] = (2.0*in[i][0]-5.0*in[i][1]+4.0*in[i][2]-in[i][3])/(spacing*spacing); diff[i][tl_size-1] = (2.0*in[i][tl_size-1]-5.0*in[i][tl_size-2]+4.0*in[i][tl_size-3]-in[i][tl_size-4])/(spacing*spacing); for (int j = 1; j < tl_size-1; j++) { diff[i][j] = (in[i][j-1]-2.0*in[i][j]+in[i][j+1])/(spacing*spacing); } } } else if (order == 3) { for (int i = 0; i < tr_size; i++) { diff[i][0] = (-5.0*in[i][0]+18.0*in[i][1]-24.0*in[i][2]+14.0*in[i][3]-3.0*in[i][4])/(2.0*spacing*spacing*spacing); diff[i][1] = (-5.0*in[i][1]+18.0*in[i][2]-24.0*in[i][3]+14.0*in[i][4]-3.0*in[i][5])/(2.0*spacing*spacing*spacing); diff[i][tl_size-1] = (5.0*in[i][tl_size-1]-18.0*in[i][tl_size-2]+24.0*in[i][tl_size-3]-14.0*in[i][tl_size-4]+3.0*in[i][tl_size-5])/(2.0*spacing*spacing*spacing); diff[i][tl_size-2] = (5.0*in[i][tl_size-2]-18.0*in[i][tl_size-3]+24.0*in[i][tl_size-4]-14.0*in[i][tl_size-5]+3.0*in[i][tl_size-6])/(2.0*spacing*spacing*spacing); for (int j = 2; j < tl_size-2; j++) { diff[i][j] = (-1.0*in[i][j-2]+2.0*in[i][j-1]-2.0*in[i][j+1]+in[i][j+2])/(2.0*spacing*spacing*spacing); } } } else { for (int i = 0; i < tr_size; i++) { diff[i][0] = (3.0*in[i][0]-14.0*in[i][1]+26.0*in[i][2]-24.0*in[i][3]+11.0*in[i][4]-2.0*in[i][5])/(spacing*spacing*spacing*spacing); diff[i][1] = (3.0*in[i][1]-14.0*in[i][2]+26.0*in[i][3]-24.0*in[i][4]+11.0*in[i][5]-2.0*in[i][6])/(spacing*spacing*spacing*spacing); diff[i][tl_size-1] = (3.0*in[i][tl_size-1]-14.0*in[i][tl_size-2]+26.0*in[i][tl_size-3]-24.0*in[i][tl_size-4]+11.0*in[i][tl_size-5]-2.0*in[i][tl_size-6])/(spacing*spacing*spacing*spacing); diff[i][tl_size-2] = (3.0*in[i][tl_size-2]-14.0*in[i][tl_size-3]+26.0*in[i][tl_size-4]-24.0*in[i][tl_size-5]+11.0*in[i][tl_size-6]-2.0*in[i][tl_size-7])/(spacing*spacing*spacing*spacing); for (int j = 2; j < tl_size-2; j++) { diff[i][j] = (in[i][j-2]-4.0*in[i][j-1]+6.0*in[i][j]-4.0*in[i][j+1]+in[i][j+2])/(spacing*spacing*spacing*spacing); } } } } else { if (order == 1) { for (int j = 0; j < tl_size; j++) { diff[0][j] = (-3.0*in[0][j]+4.0*in[1][j]-in[2][j])/(2.0*spacing); diff[tr_size-1][j] = (3.0*in[tr_size-1][j]-4.0*in[tr_size-2][j]+in[tr_size-3][j])/(2.0*spacing); for (int i = 1; i < tr_size-1; i++) { diff[i][j] = (in[i+1][j] - in[i-1][j])/(2.0*spacing); } } } else if (order == 2) { for (int j = 0; j < tl_size; j++) { diff[0][j] = (2.0*in[0][j]-5.0*in[1][j]+4.0*in[2][j]-in[3][j])/(spacing*spacing); diff[tr_size-1][j] = (2.0*in[tr_size-1][j]-5.0*in[tr_size-2][j]+4.0*in[tr_size-3][j]-in[tr_size-4][j])/(spacing*spacing); for (int i = 1; i < tr_size-1; i++) { diff[i][j] = (in[i-1][j]-2.0*in[i][j]+in[i+1][j])/(spacing*spacing); } } } else if (order == 3) { for (int j = 0; j < tl_size; j++) { diff[0][j] = (-5.0*in[0][j]+18.0*in[1][j]-24.0*in[2][j]+14.0*in[3][j]-3.0*in[4][j])/(2.0*spacing*spacing*spacing); diff[1][j] = (-5.0*in[1][j]+18.0*in[2][j]-24.0*in[3][j]+14.0*in[4][j]-3.0*in[5][j])/(2.0*spacing*spacing*spacing); diff[tr_size-1][j] = (5.0*in[tr_size-1][j]-18.0*in[tr_size-2][j]+24.0*in[tr_size-3][j]-14.0*in[tr_size-4][j]+3.0*in[tr_size-5][j])/(2.0*spacing*spacing*spacing); diff[tr_size-2][j] = (5.0*in[tr_size-2][j]-18.0*in[tr_size-3][j]+24.0*in[tr_size-4][j]-14.0*in[tr_size-5][j]+3.0*in[tr_size-6][j])/(2.0*spacing*spacing*spacing); for (int i = 2; i < tr_size-2; i++) { diff[i][j] = (-1.0*in[i-2][j]+2.0*in[i-1][j]-2.0*in[i+1][j]+in[i+2][j])/(2.0*spacing*spacing*spacing); } } } else { for (int j = 0; j < tl_size; j++) { diff[0][j] = (3.0*in[0][j]-14.0*in[1][j]+26.0*in[2][j]-24.0*in[3][j]+11.0*in[4][j]-2.0*in[5][j])/(spacing*spacing*spacing*spacing); diff[1][j] = (3.0*in[1][j]-14.0*in[2][j]+26.0*in[3][j]-24.0*in[4][j]+11.0*in[5][j]-2.0*in[6][j])/(spacing*spacing*spacing*spacing); diff[tr_size-1][j] = (3.0*in[tr_size-1][j]-14.0*in[tr_size-2][j]+26.0*in[tr_size-3][j]-24.0*in[tr_size-4][j]+11.0*in[tr_size-5][j]-2.0*in[tr_size-6][j])/(spacing*spacing*spacing*spacing); diff[tr_size-2][j] = (3.0*in[tr_size-2][j]-14.0*in[tr_size-3][j]+26.0*in[tr_size-4][j]-24.0*in[tr_size-5][j]+11.0*in[tr_size-6][j]-2.0*in[tr_size-7][j])/(spacing*spacing*spacing*spacing); for (int i = 2; i < tr_size-2; i++) { diff[i][j] = (in[i-2][j]-4.0*in[i-1][j]+6.0*in[i][j]-4.0*in[i+1][j]+in[i+2][j])/(spacing*spacing*spacing*spacing); } } } } return; } void gctl::difference_2d(const array &in, array &diff, int row_size, int col_size, double spacing, gradient_type_e d_type, int order) { std::string err_str; if (order < 1 || order > 4) throw invalid_argument("The input order can only be 1 to 4. Thrown by void gctl::difference_2d(...)"); if (spacing <= 0.0) throw invalid_argument("The input spacing can't be negative or zero. Thrown by void gctl::difference_2d(...)"); if (row_size*col_size != in.size()) throw invalid_argument("The input array size does not match. Thrown by void gctl::difference_2d(...)"); int t_size; if (d_type == Dx) { t_size = col_size; } else if (d_type == Dy) { t_size = row_size; } else { throw logic_error("The calculation type must be Dx or Dy. Thrown by gctl::difference_2d(...)"); } if (order == 1 && t_size < 3) throw runtime_error("The input array size must be equal to or bigger than 3x3 for the first order derivative. Thrown by gctl::difference_2d(...)"); if (order == 2 && t_size < 4) throw runtime_error("The input array size must be equal to or bigger than 4x4 for the second order derivative. Thrown by gctl::difference_2d(...)"); if (order == 3 && t_size < 6) throw runtime_error("The input array size must be equal to or bigger than 6x6 for the third order derivative. Thrown by gctl::difference_2d(...)"); if (order == 4 && t_size < 7) throw runtime_error("The input array size must be equal to or bigger than 7x7 for the fourth order derivative. Thrown by gctl::difference_2d(...)"); int tr_size = row_size, tl_size = col_size; diff.resize(tr_size*tl_size); int idx; if (d_type == Dx) { if (order == 1) { for (int i = 0; i < tr_size; i++) { idx = i*tl_size; diff[idx] = (-3.0*in[idx]+4.0*in[idx+1]-in[idx+2])/(2.0*spacing); idx = i*tl_size + tl_size-1; diff[idx] = (3.0*in[idx]-4.0*in[idx-1]+in[idx-2])/(2.0*spacing); for (int j = 1; j < tl_size-1; j++) { idx = i*tl_size + j; diff[idx] = (in[idx+1] - in[idx-1])/(2.0*spacing); } } } else if (order == 2) { for (int i = 0; i < tr_size; i++) { idx = i*tl_size; diff[idx] = (2.0*in[idx]-5.0*in[idx+1]+4.0*in[idx+2]-in[idx+3])/(spacing*spacing); idx = i*tl_size + tl_size-1; diff[idx] = (2.0*in[idx]-5.0*in[idx-1]+4.0*in[idx-2]-in[idx-3])/(spacing*spacing); for (int j = 1; j < tl_size-1; j++) { idx = i*tl_size + j; diff[idx] = (in[idx-1]-2.0*in[idx]+in[idx+1])/(spacing*spacing); } } } else if (order == 3) { for (int i = 0; i < tr_size; i++) { idx = i*tl_size; diff[idx] = (-5.0*in[idx]+18.0*in[idx+1]-24.0*in[idx+2]+14.0*in[idx+3]-3.0*in[idx+4])/(2.0*spacing*spacing*spacing); idx = i*tl_size+1; diff[idx] = (-5.0*in[idx]+18.0*in[idx+1]-24.0*in[idx+2]+14.0*in[idx+3]-3.0*in[idx+4])/(2.0*spacing*spacing*spacing); idx = i*tl_size + tl_size-1; diff[idx] = (5.0*in[idx]-18.0*in[idx-1]+24.0*in[idx-2]-14.0*in[idx-3]+3.0*in[idx-4])/(2.0*spacing*spacing*spacing); idx = i*tl_size + tl_size-2; diff[idx] = (5.0*in[idx]-18.0*in[idx-1]+24.0*in[idx-2]-14.0*in[idx-3]+3.0*in[idx-4])/(2.0*spacing*spacing*spacing); for (int j = 2; j < tl_size-2; j++) { idx = i*tl_size + j; diff[idx] = (-1.0*in[idx-2]+2.0*in[idx-1]-2.0*in[idx+1]+in[idx+2])/(2.0*spacing*spacing*spacing); } } } else { for (int i = 0; i < tr_size; i++) { idx = i*tl_size; diff[idx] = (3.0*in[idx]-14.0*in[idx+1]+26.0*in[idx+2]-24.0*in[idx+3]+11.0*in[idx+4]-2.0*in[idx+5])/(spacing*spacing*spacing*spacing); idx = i*tl_size+1; diff[idx] = (3.0*in[idx]-14.0*in[idx+1]+26.0*in[idx+2]-24.0*in[idx+3]+11.0*in[idx+4]-2.0*in[idx+5])/(spacing*spacing*spacing*spacing); idx = i*tl_size + tl_size-1; diff[idx] = (3.0*in[idx]-14.0*in[idx-1]+26.0*in[idx-2]-24.0*in[idx-3]+11.0*in[idx-4]-2.0*in[idx-5])/(spacing*spacing*spacing*spacing); idx = i*tl_size + tl_size-2; diff[idx] = (3.0*in[idx]-14.0*in[idx-1]+26.0*in[idx-2]-24.0*in[idx-3]+11.0*in[idx-4]-2.0*in[idx-5])/(spacing*spacing*spacing*spacing); for (int j = 2; j < tl_size-2; j++) { idx = i*tl_size + j; diff[idx] = (in[idx-2]-4.0*in[idx-1]+6.0*in[idx]-4.0*in[idx+1]+in[idx+2])/(spacing*spacing*spacing*spacing); } } } } else { if (order == 1) { for (int j = 0; j < tl_size; j++) { idx = j; diff[idx] = (-3.0*in[idx]+4.0*in[idx+tl_size]-in[idx+2*tl_size])/(2.0*spacing); idx = (tr_size-1)*tl_size + j; diff[idx] = (3.0*in[idx]-4.0*in[idx-tl_size]+in[idx-2*tl_size])/(2.0*spacing); for (int i = 1; i < tr_size-1; i++) { idx = i*tl_size + j; diff[idx] = (in[idx+tl_size] - in[idx-tl_size])/(2.0*spacing); } } } else if (order == 2) { for (int j = 0; j < tl_size; j++) { idx = j; diff[idx] = (2.0*in[idx]-5.0*in[idx+tl_size]+4.0*in[idx+2*tl_size]-in[idx+3*tl_size])/(spacing*spacing); idx = (tr_size-1)*tl_size + j; diff[idx] = (2.0*in[idx]-5.0*in[idx-tl_size]+4.0*in[idx-2*tl_size]-in[idx-3*tl_size])/(spacing*spacing); for (int i = 1; i < tr_size-1; i++) { idx = i*tl_size + j; diff[idx] = (in[idx-tl_size]-2.0*in[idx]+in[idx+tl_size])/(spacing*spacing); } } } else if (order == 3) { for (int j = 0; j < tl_size; j++) { idx = j; diff[idx] = (-5.0*in[idx]+18.0*in[idx+tl_size]-24.0*in[idx+2*tl_size]+14.0*in[idx+3*tl_size]-3.0*in[idx+4*tl_size])/(2.0*spacing*spacing*spacing); idx = tl_size+j; diff[idx] = (-5.0*in[idx]+18.0*in[idx+tl_size]-24.0*in[idx+2*tl_size]+14.0*in[idx+3*tl_size]-3.0*in[idx+4*tl_size])/(2.0*spacing*spacing*spacing); idx = (tr_size-1)*tl_size + j; diff[idx] = (5.0*in[idx]-18.0*in[idx-tl_size]+24.0*in[idx-2*tl_size]-14.0*in[idx-3*tl_size]+3.0*in[idx-4*tl_size])/(2.0*spacing*spacing*spacing); idx = (tr_size-2)*tl_size + j; diff[idx] = (5.0*in[idx]-18.0*in[idx-tl_size]+24.0*in[idx-2*tl_size]-14.0*in[idx-3*tl_size]+3.0*in[idx-4*tl_size])/(2.0*spacing*spacing*spacing); for (int i = 2; i < tr_size-2; i++) { idx = i*tl_size + j; diff[idx] = (-1.0*in[idx-2*tl_size]+2.0*in[idx-tl_size]-2.0*in[idx+tl_size]+in[idx+2*tl_size])/(2.0*spacing*spacing*spacing); } } } else { for (int j = 0; j < tl_size; j++) { idx = j; diff[idx] = (3.0*in[idx]-14.0*in[idx+tl_size]+26.0*in[idx+2*tl_size]-24.0*in[idx+3*tl_size]+11.0*in[idx+4*tl_size]-2.0*in[idx+5*tl_size])/(spacing*spacing*spacing*spacing); idx = tl_size+j; diff[idx] = (3.0*in[idx]-14.0*in[idx+tl_size]+26.0*in[idx+2*tl_size]-24.0*in[idx+3*tl_size]+11.0*in[idx+4*tl_size]-2.0*in[idx+5*tl_size])/(spacing*spacing*spacing*spacing); idx = (tr_size-1)*tl_size + j; diff[idx] = (3.0*in[idx]-14.0*in[idx-tl_size]+26.0*in[idx-2*tl_size]-24.0*in[idx-3*tl_size]+11.0*in[idx-4*tl_size]-2.0*in[idx-5*tl_size])/(spacing*spacing*spacing*spacing); idx = (tr_size-2)*tl_size + j; diff[idx] = (3.0*in[idx]-14.0*in[idx-tl_size]+26.0*in[idx-2*tl_size]-24.0*in[idx-3*tl_size]+11.0*in[idx-4*tl_size]-2.0*in[idx-5*tl_size])/(spacing*spacing*spacing*spacing); for (int i = 2; i < tr_size-2; i++) { idx = i*tl_size + j; diff[idx] = (in[idx-2*tl_size]-4.0*in[idx-tl_size]+6.0*in[idx]-4.0*in[idx+tl_size]+in[idx+2*tl_size])/(spacing*spacing*spacing*spacing); } } } } return; }