double cumulative_spectrum::get_area_flux(double cutoff_rig, double sol_mod_par, double cth_min, double cth_max, double en_min, double en_max)
{
	double en, incr = 1.001, flux = 0.;
	
	for (en = en_min; en < en_max/(0.5+0.5*incr); en *= incr) 
	{
		flux += get_flux(cutoff_rig, sol_mod_par, en*(0.5+0.5*incr)) *en*(incr-1);
	}
	return M_PI*(cth_max*cth_max - cth_min*cth_min) *flux;
}
void calc_jacobian(MeshCTX* meshctx, PropCTX* propctx) {

	int myid = propctx->myid, numprocs = propctx->numproc;

	HashTable* El_Table = meshctx->el_table;
	HashTable* NodeTable = meshctx->nd_table;

	TimeProps* timeprops_ptr = propctx->timeprops;
	MapNames* mapname_ptr = propctx->mapnames;
	MatProps* matprops_ptr = propctx->matprops;

	HashEntryPtr* buck = El_Table->getbucketptr();
	HashEntryPtr currentPtr;
	DualElem* Curr_El = NULL;

	int iter = timeprops_ptr->iter;
	double tiny = GEOFLOW_TINY;

#ifdef DEBUGFILE
	ofstream myfile;
	myfile.open("debug.txt",ios::app);
#endif

	for (int i = 0; i < El_Table->get_no_of_buckets(); i++) {
		if (*(buck + i)) {
			currentPtr = *(buck + i);
			while (currentPtr) {
				Curr_El = (DualElem*) (currentPtr->value);

				if (Curr_El->get_adapted_flag() > 0) {

					double *prev_state_vars = Curr_El->get_prev_state_vars();
					double *state_vars = Curr_El->get_state_vars();
					double *d_state_vars = Curr_El->get_d_state_vars();
					double *gravity = Curr_El->get_gravity();
					double *d_gravity = Curr_El->get_d_gravity();
					double *curvature = Curr_El->get_curvature();
					Curr_El->calc_stop_crit(matprops_ptr); //this function updates bedfric properties
					double bedfrict = Curr_El->get_effect_bedfrict();
					double *dx = Curr_El->get_dx();

					if (timeprops_ptr->iter < 51)
						matprops_ptr->frict_tiny = 0.1;
					else
						matprops_ptr->frict_tiny = 0.000000001;

					double flux[4][NUM_STATE_VARS];
					get_flux(El_Table, NodeTable, Curr_El->pass_key(), matprops_ptr, myid, flux);

					double dt = timeprops_ptr->dt.at(iter - 1);	//at final time step we do not need the computation of adjoint and we always compute it for the previouse time so we need iter.
					double dtdx = dt / dx[0];
					double dtdy = dt / dx[1];

					int stop[DIMENSION] = { 0, 0 };
					double orgSrcSgn[4] = { 0., 0., 0., 0. };

					update_states(state_vars, prev_state_vars, flux[0], flux[1], flux[2], flux[3], dtdx, dtdy,
					    dt, d_state_vars, (d_state_vars + NUM_STATE_VARS), curvature, matprops_ptr->intfrict,
					    bedfrict, gravity, d_gravity, *(Curr_El->get_kactxy()), matprops_ptr->frict_tiny,
					    stop, orgSrcSgn);

					Vec_Mat<9>& jacobian = Curr_El->get_jacobian();

					for (int effelement = 0; effelement < EFF_ELL; effelement++) { //0 for the element itself, and the rest id for neighbour elements

#ifdef DEBUG
						char filename[] = "jacobian";
						int bb = 1, aa = 0;

						if (fabs(*(Curr_El->get_coord()) - 161.3) < .04
								&& fabs(*(Curr_El->get_coord() + 1) - 539.58) < .04 && (iter == 545 || iter == 546))
						bb = aa;

						/*Curr_El->get_ithelem() == 8255 && effelement == 0) {/**(Curr_El->pass_key()) == KEY0
						 && *(Curr_El->pass_key() + 1) == KEY1 && iter == ITER
						 && effelement == EFFELL
						 Curr_El->write_elem_info(NodeTable, filename, timeprops_ptr->iter, dt);*/

#endif

						if ((effelement == 0 && prev_state_vars[0] == 0.) || //this is a void element so the residual vector does not change by changing it's values
						    (effelement > 4 && *(Curr_El->get_neigh_proc() + (effelement - 1)) == -2) || //one neighbor in this side
						    (effelement != 0 && void_neigh_elem(El_Table, Curr_El, effelement)) || //this is a void neighbor element so the residual of the curr_el does not depend on this neighbor
						    (effelement > 0 && *(Curr_El->get_neigh_proc() + (effelement - 1)) == INIT)) {

							Curr_El->set_jacobianMat_zero(effelement);

						} else {
							const Mat3x3 *jac_flux_n_x, *jac_flux_p_x, *jac_flux_n_y, *jac_flux_p_y;
							double dh_sens[2];

							set_fluxes_hsens(Curr_El, jac_flux_n_x, jac_flux_p_x, jac_flux_n_y, jac_flux_p_y,
							    dh_sens, effelement);

							calc_jacobian_elem(jacobian(effelement), *jac_flux_n_x, *jac_flux_p_x, *jac_flux_n_y,
							    *jac_flux_p_y, prev_state_vars, d_state_vars, (d_state_vars + NUM_STATE_VARS),
							    curvature, gravity, d_gravity, dh_sens, matprops_ptr->intfrict, bedfrict,
							    *(Curr_El->get_kactxy()), effelement, dtdx, dtdy, dt, stop, orgSrcSgn);

						}
					}
				}
				currentPtr = currentPtr->next;
			}
		}
	}

//	cout<<"max jacobian:  "<<max_jac<<endl;

#ifdef DEBUGFILE
	myfile.close();
#endif

}
void BinaryStar::compute_flow_off() {
    const Real da = get_dx() * get_dx();
    int k, j, i;
    static State this_DFO;
    this_DFO = Vector<Real, STATE_NF>(0.0);
    for (k = BW; k < GNX - BW; k++) {
        for (j = BW; j < GNX - BW; j++) {
            for (i = BW; i < GNX - BW; i++) {
                if (!zone_is_refined(i, j, k)) {
                    if (is_phys_bound(XL) && i == BW) {
                        this_DFO -= (get_flux(0, i, j, k)) * da;
                    }
                    if (is_phys_bound(XU) && i == GNX - BW - 1) {
                        this_DFO += (get_flux(0, i + 1, j, k)) * da;
                    }
                    if (is_phys_bound(YL) && j == BW) {
                        this_DFO -= (get_flux(1, i, j, k)) * da;
                    }
                    if (is_phys_bound(YU) && j == GNX - BW - 1) {
                        this_DFO += (get_flux(1, i, j + 1, k)) * da;
                    }
                    if (is_phys_bound(ZL) && k == BW) {
                        this_DFO -= (get_flux(2, i, j, k)) * da;
                    }
                    if (is_phys_bound(ZU) && k == GNX - BW - 1) {
                        this_DFO += (get_flux(2, i, j, k + 1)) * da;
                    }
                    if (!State::cylindrical) {
                        const int lx = State::sx_index;
                        const int ly = State::sy_index;
                        this_DFO[ly] = 0.0;
                        if (is_phys_bound(XL) && i == BW) {
                            this_DFO[ly] -= (get_flux(0, i, j, k))[ly] * da * HydroGrid::xf(i);
                            this_DFO[ly] += (get_flux(0, i, j, k))[lx] * da * HydroGrid::yc(j);
                        }
                        if (is_phys_bound(XU) && i == GNX - BW - 1) {
                            this_DFO[ly] += (get_flux(0, i + 1, j, k))[ly] * da * HydroGrid::xf(i + 1);
                            this_DFO[ly] -= (get_flux(0, i + 1, j, k))[lx] * da * HydroGrid::yc(j + 1);
                        }
                        if (is_phys_bound(YL) && j == BW) {
                            this_DFO[ly] -= (get_flux(1, i, j, k))[ly] * da * HydroGrid::xc(i);
                            this_DFO[ly] += (get_flux(1, i, j, k))[lx] * da * HydroGrid::yc(j);
                        }
                        if (is_phys_bound(YU) && j == GNX - BW - 1) {
                            this_DFO[ly] += (get_flux(1, i, j + 1, k))[ly] * da * HydroGrid::xc(i);
                            this_DFO[ly] -= (get_flux(1, i, j + 1, k))[lx] * da * HydroGrid::yc(j);
                        }
                        if (is_phys_bound(ZL) && k == BW) {
                            this_DFO[ly] -= (get_flux(2, i, j, k))[ly] * da * HydroGrid::xc(i);
                            this_DFO[ly] += (get_flux(2, i, j, k))[lx] * da * HydroGrid::yc(j);
                        }
                        if (is_phys_bound(ZU) && k == GNX - BW - 1) {
                            this_DFO[ly] += (get_flux(2, i, j, k + 1))[ly] * da * HydroGrid::xc(i);
                            this_DFO[ly] -= (get_flux(2, i, j, k + 1))[lx] * da * HydroGrid::yc(j);
                        }
                    }
                }
            }
        }
    }
    DFO += this_DFO;
}