Commit d81007d0e77d4f4c5710c6b1e74cacbe6a5c4fe0

Authored by ellisowen
1 parent b64bc218

Begins to implement gradients in GModelSpectralGauss::eval_gradients

include/GModelSpectralGauss.hpp
... ... @@ -183,7 +183,7 @@ GEnergy GModelSpectralGauss::mean(void) const
183 183 /***********************************************************************//**
184 184 * @brief Set mean energy
185 185 *
186   - * @param[in] Mean energy.
  186 + * @param[in] mean Mean energy.
187 187 ***************************************************************************/
188 188 inline
189 189 void GModelSpectralGauss::mean(const GEnergy& mean)
... ... @@ -209,7 +209,7 @@ GEnergy GModelSpectralGauss::sigma(void) const
209 209 /***********************************************************************//**
210 210 * @brief Set energy width
211 211 *
212   - * @param[in] Energy width
  212 + * @param[in] sigma Energy width
213 213 ***************************************************************************/
214 214 inline
215 215 void GModelSpectralGauss::sigma(const GEnergy& sigma)
... ...
src/model/GModelSpectralGauss.cpp
... ... @@ -271,12 +271,59 @@ double GModelSpectralGauss::eval(const GEnergy& srcEng,
271 271 *
272 272 * This method simply calls the eval() method as no analytical gradients will
273 273 * be computed. See the eval() method for details.
  274 + *
  275 + * TODO: Implement this
274 276 ***************************************************************************/
275 277 double GModelSpectralGauss::eval_gradients(const GEnergy& srcEng,
276 278 const GTime& srcTime)
277 279 {
278   - // Return
279   - return eval(srcEng, srcTime);
  280 + double energy = srcEng.MeV();
  281 + double norm = m_norm.value();
  282 + double mean = m_mean.value();
  283 + double sigma = m_sigma.value();
  284 +
  285 + // Update the evaluation cache
  286 + update_eval_cache(srcEng);
  287 +
  288 + // Compute function value
  289 + double term1 = (norm / sigma) * gammalib::inv_sqrt2pi;
  290 + double term2 = (energy - mean) * (energy - mean) / (2 * sigma * sigma);
  291 + double value = term1 * std::exp(- term2);
  292 +
  293 + // Compute partial derivatives with respect to the parameter factor
  294 + // values. The partial derivatives with respect to the parameter
  295 + // values are obtained by division by the scale factor.
  296 + double g_norm = (m_norm.is_free())
  297 + ? m_norm.scale() * m_last_power : 0.0;
  298 + double g_mean = (m_index.is_free())
  299 + ? value * m_index.scale() * std::log(m_last_e_norm) : 0.0;
  300 + double g_sigma = (m_ecut.is_free())
  301 + ? value * m_last_e_cut / m_ecut.factor_value() : 0.0;
  302 +
  303 + // Set gradients
  304 + m_norm.factor_gradient(g_norm);
  305 + m_mean.factor_gradient(g_mean);
  306 + m_sigma.factor_gradient(g_sigma);
  307 +
  308 + // Compile option: Check for NaN/Inf
  309 + #if defined(G_NAN_CHECK)
  310 + if (gammalib::is_notanumber(value) || gammalib::is_infinite(value)) {
  311 + std::cout << "*** ERROR: GModelSpectralExpPlaw::eval_gradients";
  312 + std::cout << "(srcEng=" << srcEng;
  313 + std::cout << ", srcTime=" << srcTime << "):";
  314 + std::cout << " NaN/Inf encountered";
  315 + std::cout << " (value=" << value;
  316 + std::cout << ", e_norm=" << m_last_e_norm;
  317 + std::cout << ", e_cut=" << m_last_e_cut;
  318 + std::cout << ", power=" << m_last_power;
  319 + std::cout << ")" << std::endl;
  320 + }
  321 + #endif
  322 +
  323 + // Return
  324 + return value;
  325 + }
  326 +
280 327 }
281 328  
282 329  
... ... @@ -730,3 +777,48 @@ double GModelSpectralGauss::eflux_kernel::eval(const double&amp; energy)
730 777 // Return value
731 778 return value;
732 779 }
  780 +
  781 +/***********************************************************************//**
  782 + * @brief Update eval precomputation cache
  783 + *
  784 + * @param[in] energy Energy.
  785 + *
  786 + * Updates the precomputation cache for eval() and eval_gradients() methods.
  787 + *
  788 + * TODO integrate this to correct form
  789 + ***************************************************************************/
  790 +void GModelSpectralGauss::update_eval_cache(const GEnergy& energy) const
  791 +{
  792 + // Get parameter values (takes 3 multiplications which are difficult
  793 + // to avoid)
  794 + double index = m_index.value();
  795 + double ecut = m_ecut.value();
  796 + double pivot = m_pivot.value();
  797 +
  798 + // If the energy or one of the parameters index, cut-off or pivot
  799 + // energy has changed then recompute the cache
  800 + if ((m_last_energy != energy) ||
  801 + (m_last_index != index) ||
  802 + (m_last_ecut != ecut) ||
  803 + (m_last_pivot != pivot)) {
  804 +
  805 + // Store actual energy and parameter values
  806 + m_last_energy = energy;
  807 + m_last_index = index;
  808 + m_last_ecut = ecut;
  809 + m_last_pivot = pivot;
  810 +
  811 + // Compute and store value
  812 + double eng = energy.MeV();
  813 + m_last_e_norm = eng / m_last_pivot;
  814 + m_last_e_cut = eng / m_last_ecut;
  815 + m_last_power = std::pow(m_last_e_norm, m_last_index) *
  816 + std::exp(-m_last_e_cut);
  817 +
  818 + } // endif: recomputation was required
  819 +
  820 + // Return
  821 + return;
  822 +}
  823 +
  824 +
... ...