LCOV - code coverage report
Current view: top level - src/utils - PolyatomicDisplacementDerivativeFunction.C (source / functions) Hit Total Coverage
Test: idaholab/magpie: 5710af Lines: 68 69 98.6 %
Date: 2025-07-21 23:34:39 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /**********************************************************************/
       2             : /*                     DO NOT MODIFY THIS HEADER                      */
       3             : /* MAGPIE - Mesoscale Atomistic Glue Program for Integrated Execution */
       4             : /*                                                                    */
       5             : /*            Copyright 2017 Battelle Energy Alliance, LLC            */
       6             : /*                        ALL RIGHTS RESERVED                         */
       7             : /**********************************************************************/
       8             : #ifdef GSL_ENABLED
       9             : 
      10             : #include "PolyatomicDisplacementDerivativeFunction.h"
      11             : 
      12             : // mytrim includes
      13             : #include <mytrim/simconf.h>
      14             : #include <mytrim/ion.h>
      15             : #include <mytrim/element.h>
      16             : 
      17             : // general includes
      18             : #include <assert.h>
      19             : #include <limits>
      20             : #include <exception>
      21             : 
      22             : // gsl includes
      23             : #include "gsl/gsl_sf_legendre.h"
      24             : #include "gsl/gsl_integration.h"
      25             : 
      26          25 : PolyatomicDisplacementDerivativeFunction::PolyatomicDisplacementDerivativeFunction(
      27             :     std::vector<MyTRIM_NS::Element> polyatomic_material,
      28             :     nrt_type damage_function_type,
      29             :     const PolyatomicDisplacementFunction * net_disp,
      30          25 :     std::vector<std::vector<Real>> Ecap)
      31             :   : PolyatomicDisplacementFunctionBase(polyatomic_material, damage_function_type, Ecap),
      32          50 :     _net_displacement_function(net_disp)
      33             : {
      34          25 :   if (damage_function_type != NET_DERIVATIVE)
      35           0 :     throw std::exception();
      36             : 
      37             :   // set the number of indices
      38          25 :   _n_indices = 3;
      39             : 
      40             :   Real Edisp_min = std::numeric_limits<Real>::max();
      41          60 :   for (unsigned int j = 0; j < _n_species; ++j)
      42          35 :     if (_material->_element[j]._Edisp < Edisp_min)
      43             :       Edisp_min = _material->_element[j]._Edisp;
      44          25 :   _energy_history[0] = Edisp_min;
      45             : 
      46             :   // note that initial conditions are 0s for theta_ijl
      47          25 : }
      48             : 
      49             : std::vector<Real>
      50       24940 : PolyatomicDisplacementDerivativeFunction::getRHS(Real energy)
      51             : {
      52       24940 :   std::vector<Real> f(_problem_size);
      53       65730 :   for (unsigned int i = 0; i < nSpecies(); ++i)
      54             :   {
      55       40790 :     Real stopping_power = stoppingPower(i, energy);
      56      113280 :     for (unsigned int j = 0; j < nSpecies(); ++j)
      57      208380 :       for (unsigned int l = 0; l < nSpecies(); ++l)
      58             :       {
      59             :         // working on the right hand side for theta_ijl
      60      135890 :         unsigned int n = mapIndex(i, j, l);
      61      135890 :         f[n] = 0;
      62             : 
      63      398580 :         for (unsigned int k = 0; k < nSpecies(); ++k)
      64      262690 :           f[n] += numberFraction(k) *
      65      262690 :                   (integralTypeI(energy, i, j, l, k) + integralTypeII(energy, i, j, l, k)) /
      66             :                   stopping_power;
      67      135890 :         f[n] += source(energy, i, j, l) / stopping_power;
      68             :       }
      69             :   }
      70       24940 :   return f;
      71             : }
      72             : 
      73             : Real
      74      262690 : PolyatomicDisplacementDerivativeFunction::integralTypeI(
      75             :     Real energy, unsigned int i, unsigned int j, unsigned int l, unsigned int k) const
      76             : {
      77      262690 :   Real upper_integration_limit = energy * _lambda[i][k];
      78             :   Real integral = 0;
      79      262690 :   Real Ebind = _material->_element[k]._Elbind;
      80             : 
      81             :   // the integration follows the already existing energies
      82     4320963 :   for (unsigned int n = 1; n < _energy_history.size(); ++n)
      83             :   {
      84             :     // adjust integration limits to be within E_{l-1} ... min(E_l, upper_integration_limit)
      85     4058273 :     Real lower = _energy_history[n - 1];
      86     4058273 :     Real upper = std::min(_energy_history[n], upper_integration_limit);
      87             : 
      88             :     // nothing to integrate
      89     4058273 :     if (lower > upper)
      90      770224 :       continue;
      91             : 
      92             :     // now integrate from lower to upper
      93     3288049 :     Real f = 0.5 * (upper - lower);
      94    16440245 :     for (unsigned int qp = 0; qp < _quad_order; ++qp)
      95             :     {
      96    13152196 :       Real recoil_energy = f * (_quad_points[qp] + 1) + lower;
      97    13152196 :       integral += f * _quad_weights[qp] * scatteringCrossSection(i, k, energy, recoil_energy) *
      98    26304392 :                   displacementProbability(k, recoil_energy) *
      99    13152196 :                   linearInterpolation(recoil_energy - Ebind, k, j, l);
     100             :     }
     101             :   }
     102      262690 :   return integral;
     103             : }
     104             : 
     105             : Real
     106      262690 : PolyatomicDisplacementDerivativeFunction::integralTypeII(
     107             :     Real energy, unsigned int i, unsigned int j, unsigned int l, unsigned int k) const
     108             : {
     109      262690 :   Real upper_integration_limit = energy * _lambda[i][k];
     110      262690 :   Real threshold = std::min(_asymptotic_threshold, energy * _lambda[i][k]);
     111             : 
     112             :   // store the current displacement function value
     113      262690 :   Real current_value = linearInterpolation(energy, i, j, l);
     114             : 
     115             :   // estimate the derivative d(nu_i) / dE:
     116      262690 :   Real dE = _energy_history.back() - _energy_history[_energy_history.size() - 2];
     117      262690 :   Real derivative = (current_value - linearInterpolation(energy - dE, i, j, l)) / dE;
     118             : 
     119             :   // integrate up to threshold and multiply by estimate of the derivative
     120      262690 :   Real integral = -weightedScatteringIntegral(energy, threshold, i, k) * derivative;
     121             : 
     122      262690 :   if (energy * _lambda[i][k] <= _asymptotic_threshold)
     123             :     return integral;
     124             : 
     125             :   // the integration follows the already existing energies
     126     4583653 :   for (unsigned int n = 0; n < _energy_history.size(); ++n)
     127             :   {
     128             :     // adjust integration limits to be within
     129             :     Real lower;
     130     4320963 :     if (n == 0)
     131      262690 :       lower = _asymptotic_threshold;
     132             :     else
     133     4058273 :       lower = std::max(_energy_history[n - 1], _asymptotic_threshold);
     134             : 
     135     4320963 :     Real upper = std::min(_energy_history[n], upper_integration_limit);
     136             : 
     137             :     // nothing to integrate
     138     4320963 :     if (lower > upper)
     139      770224 :       continue;
     140             : 
     141             :     // now integrate from lower to upper
     142     3550739 :     Real f = 0.5 * (upper - lower);
     143    17753695 :     for (unsigned int qp = 0; qp < _quad_order; ++qp)
     144             :     {
     145    14202956 :       Real recoil_energy = f * (_quad_points[qp] + 1) + lower;
     146    14202956 :       integral += f * _quad_weights[qp] * scatteringCrossSection(i, k, energy, recoil_energy) *
     147    14202956 :                   (nonCaptureProbability(i, k, energy, recoil_energy) *
     148    14202956 :                        linearInterpolation(energy - recoil_energy, i, j, l) -
     149             :                    current_value);
     150             :     }
     151             :   }
     152             :   return integral;
     153             : }
     154             : 
     155             : Real
     156      135890 : PolyatomicDisplacementDerivativeFunction::source(Real energy,
     157             :                                                  unsigned int i,
     158             :                                                  unsigned int j,
     159             :                                                  unsigned int l)
     160             : {
     161             :   // compute the derivative of the net displacement function at E
     162      135890 :   unsigned int index = _net_displacement_function->energyIndex(energy);
     163             :   Real d_net_dE = 0;
     164             :   // if energy == Emin => index = 0, the net displacement rate is constant below that value
     165      135890 :   if (index != 0)
     166             :   {
     167      135890 :     Real e1 = _net_displacement_function->energyPoint(index - 1);
     168             :     Real e2 = _net_displacement_function->energyPoint(index);
     169      135890 :     Real v1 = _net_displacement_function->linearInterpolation(e1, i, j);
     170      135890 :     Real v2 = _net_displacement_function->linearInterpolation(e2, i, j);
     171      135890 :     d_net_dE = (v2 - v1) / (e2 - e1);
     172             :   }
     173      135890 :   return _net_displacement_function->integralTypeI(energy, i, j, l) +
     174      135890 :          _net_displacement_function->integralTypeII(energy, i, j, l) -
     175      135890 :          d_net_dE * stoppingPowerDerivative(i, l, energy);
     176             : }
     177             : 
     178             : #endif

Generated by: LCOV version 1.14