Commit efa5ea566f0bf64aca32f7e22a66761cbccf2f80

Authored by ellisowen
1 parent 6b0f4241

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