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);
}
Ejemplo n.º 3
0
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;
}