void GravityColumnSolver<Model>::solve(const std::vector<std::vector<int> >& columns,
					   const double dt,
					   std::vector<double>& s)
    {
	// Initialize model. These things are done for the whole grid!
	StateWithZeroFlux state(s); // This holds s by reference.
	JacSys sys(grid_.number_of_cells);
	std::vector<double> increment(grid_.number_of_cells, 0.0);
	model_.initStep(state, grid_, sys);

	int iter = 0;
	double max_delta = 1e100;

	while (iter < maxit_) {
	    model_.initIteration(state, grid_, sys);
            //   std::map<int, std::vector<int> >::const_iterator it;
            //for (it = columns.begin(); it != columns.end(); ++it) {
            int size = columns.size();

            #pragma omp parallel for schedule(dynamic)
            for(int i = 0; i < size; ++i) {
		solveSingleColumn(columns[i], dt, s, increment);
	    }

	    for (int cell = 0; cell < grid_.number_of_cells; ++cell) {
		sys.vector().writableSolution()[cell] += increment[cell];
	    }

	    const double maxelem = *std::max_element(increment.begin(), increment.end());
	    const double minelem = *std::min_element(increment.begin(), increment.end());
	    max_delta = std::max(maxelem, -minelem);
	    std::cout << "Gravity column solver iteration " << iter << "   max_delta = " << max_delta << std::endl;
	    if (max_delta < tol_) {
		break;
	    }
	    ++iter;
	}
	if (max_delta >= tol_) {
	    THROW("Failed to converge!");
	}
	// Finalize.
	// model_.finishIteration(); // Doesn't do anything in th 2p model.
	// finishStep() writes to state, which holds s by reference.
	// This will update the entire grid's state...
	model_.finishStep(grid_, sys.vector().solution(), state);
    }
    void GravityColumnSolverPolymer<FluxModel, Model>::solve(const std::vector<std::vector<int> >& columns,
						  const double dt,
						  std::vector<double>& s,
						  std::vector<double>& c,
                                                  std::vector<double>& cmax
						  )
    {
	// Initialize model. These things are done for the whole grid!
	StateWithZeroFlux state(s, c, cmax); // This holds s, c and cmax by reference.
	JacSys sys(2*grid_.number_of_cells);
	std::vector<double> increment(2*grid_.number_of_cells, 0.0);
	fmodel_.initStep(state, grid_, sys);

	int iter = 0;
	double max_delta = 1e100;
        const double cmax_cell = 2.0*model_.cMax();
        const double tol_c_cell = 1e-2*cmax_cell; 
	while (iter < maxit_) {
	    fmodel_.initIteration(state, grid_, sys);
            int size = columns.size();
            for(int i = 0; i < size; ++i) {
		solveSingleColumn(columns[i], dt, s, c, cmax, increment);
	    }
	    for (int cell = 0; cell < grid_.number_of_cells; ++cell) {
                double& s_cell = sys.vector().writableSolution()[2*cell + 0];
                double& c_cell = sys.vector().writableSolution()[2*cell + 1];
		s_cell += increment[2*cell + 0];
		c_cell += increment[2*cell + 1];
                if (s_cell < 0.) {
                    double& incr = increment[2*cell + 0];
                    s_cell -=  incr;
                    if (std::fabs(incr) < 1e-2) {
                        incr = -s_cell;
                        s_cell = 0.;
                    } else {
                        incr = -s_cell/2.0;
                        s_cell = s_cell/2.0;
                    }
                }
                if (s_cell > 1.) {
                    double& incr = increment[2*cell + 0];
                    s_cell -=  incr;
                    if (std::fabs(incr) < 1e-2) {
                        incr = 1. - s_cell;
                        s_cell = 1.;
                    } else {
                        incr = (1 - s_cell)/2.0;
                        s_cell = (1 + s_cell)/2.0;
                    }
                }
                if (c_cell < 0.) {
                    double& incr = increment[2*cell + 1];
                    c_cell -=  incr;
                    if (std::fabs(incr) < tol_c_cell) {
                        incr = -c_cell;
                        c_cell = 0.;
                    } else {
                        incr = -c_cell/2.0;
                        c_cell = c_cell/2.0;
                    }
                }
                if (c_cell > cmax_cell) {
                    double& incr = increment[2*cell + 1];
                    c_cell -=  incr;
                    if (std::fabs(incr) < tol_c_cell) {
                        incr = cmax_cell - c_cell;
                        c_cell = cmax_cell;
                    } else {
                        incr = (cmax_cell - c_cell)/2.0;
                        c_cell = (cmax_cell + c_cell)/2.0;
                    }
                }
                
                // if (s_cell < 0.) {
                //     increment[2*cell + 0] = increment[2*cell + 0] - s_cell;
                //     s_cell = 0.;
                // } else if (s_cell > 1.) {
                //     increment[2*cell + 0] = increment[2*cell + 0] - s_cell + 1.;
                //     s_cell = 1.;
                // }
                // if (c_cell < 0) {
                //     increment[2*cell + 1] = increment[2*cell + 1] - c_cell;
                //     c_cell = 0.;
                // } else if (c_cell > cmax_cell) {
                //     increment[2*cell + 1] = increment[2*cell + 1] - c_cell + cmax_cell;
                //     c_cell = cmax_cell;
                // }
	    } 
	    const double maxelem = *std::max_element(increment.begin(), increment.end());
	    const double minelem = *std::min_element(increment.begin(), increment.end());
	    max_delta = std::max(maxelem, -minelem);
	    std::cout << "Iteration " << iter << "   max_delta = " << max_delta << std::endl;
	    if (max_delta < tol_) {
		break;
	    }
	    ++iter;
	}
	if (max_delta >= tol_) {
	    THROW("Failed to converge!");
	}
	// Finalize.
	// fmodel_.finishIteration(); //
	// finishStep() writes to state, which holds s by reference.
	// This will update the entire grid's state... cmax is updated here.
	fmodel_.finishStep(grid_, sys.vector().solution(), state);
    }