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); }