vector<double> GradientDescent::maximize(const vector<double> &start_point) { return extremum(start_point, EType::Maximun); }
vector<double> GradientDescent::minimize(const vector<double> &start_point, const vector<vector<double>> &c, const vector<double> &d) { return extremum(start_point, c, d, EType::Minimum); }
std::vector<NSEProperties> EOSNSE::GetExteriorProtonDensity(double ne, double nno, double T) { OneDimensionalRoot rootFinder1D(1.e-8, 100); double np_min = 1.e-300; double np_max = 1.2*ne; // Find a good interval auto nse_func = [nno, ne, T, this](double xx)->double{ double npo = exp(xx); EOSData eosOut = mpEos->FromNAndT(EOSData::InputFromTNnNp(T, nno, npo)); auto nucleiProps = GetNucleiScalars(eosOut, ne); double yy = 1.0 - (nucleiProps.np + (1.0 - nucleiProps.uNuc)*npo)/ne; return yy; }; // Try finding the maximum of nse_func //double npmax = exp(minimize(nse_func, log(0.8*ne), log(1.e-300), log(ne))); //double npmax2 = exp(minimize(nse_func, log(0.8*ne), log(0.7*ne), log(ne))); // //if (nse_func(log(npmax))*nse_func(log(np_low)) < 0.0) np_high = npmax; //else if (nse_func(log(npmax))*nse_func(log(np_high)) < 0.0) np_low = npmax; double two, one, zero; double ntwo, none, nzero; double nstart = 1.e-5; ntwo = nstart; none = nstart; nzero = nstart; two = nse_func(log(nstart)); one = nse_func(log(nstart)); zero = nse_func(log(nstart)); std::vector<double> extremum(1, 1.e-300); // The 1.1 seems to be critical, increasing it's value makes things not work for (double npt = nstart; npt<=np_max; npt*=1.05) { ntwo = none; two = one; none = nzero; one = zero; nzero = std::min(npt, ne); zero = nse_func(log(nzero)); double npmax2 = -1.0; if (one>=two && one>=zero) { OneDimensionalMinimization minimize(1.e-7, 25); npmax2 = exp(minimize(nse_func, log(none), log(ntwo), log(nzero), true)); extremum.push_back(npmax2); //std::cerr << " Should be local maximum " << ntwo << " " << npmax2 << " " // << nzero; } if (one<=two && one<=zero) { OneDimensionalMinimization minimize(1.e-7, 25); npmax2 = exp(minimize(nse_func, log(none), log(ntwo), log(nzero))); extremum.push_back(npmax2); //std::cerr << " Should be local minimum " << ntwo << " " << npmax2 << " " // << nzero; } if (npt >= ne) { OneDimensionalMinimization minimize(1.e-7, 25); npmax2 = exp(minimize(nse_func, log(none), log(ntwo), log(nzero), true)); if (npmax2>ntwo*(1.0+1.e-6) && npmax2<nzero*(1.0-1.e-6)) { extremum.push_back(npmax2); } else { npmax2 = -1.0; } } } //extremum.push_back(ne); extremum.push_back(np_max); std::sort(extremum.begin(), extremum.end(), [](double a, double b) { return b>a; }); std::vector<double> npsol; std::vector<NSEProperties> output; for (int i=0; i<extremum.size()-1; i++) { double np_low = extremum[i]; double np_high = extremum[i+1]; if (nse_func(log(np_high))*nse_func(log(np_low))>0.0) continue; try { double npo = exp(rootFinder1D(nse_func, log(np_low), log(np_high))); // Make sure we don't have two solutions that are the same //for (auto npt : npsol) { // if (fabs(npo/npt - 1.0)<1.e-2) continue; //} npsol.push_back(npo); EOSData eosOut = mpEos->FromNAndT(EOSData::InputFromTNnNp(T, nno, npo)); auto nucleiProps = GetNucleiScalars(eosOut, ne); output.push_back(NSEProperties( nucleiProps.nn + eosOut.Nn()*(1.0 - nucleiProps.uNuc), nucleiProps.np + eosOut.Np()*(1.0 - nucleiProps.uNuc), T, eosOut, nucleiProps.uNuc)); } catch (...) { std::cout << "Did not find root " << np_low << " " << np_high << std::endl;} } return output; }