LCOV - code coverage report
Current view: top level - src/Integrator - PhaseFieldMicrostructure.cpp (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 107 190 56.3 %
Date: 2024-11-18 05:28:54 Functions: 10 30 33.3 %

          Line data    Source code
       1             : 
       2             : #include <eigen3/Eigen/Eigenvalues>
       3             : 
       4             : #include <cmath>
       5             : 
       6             : #include <AMReX_SPACE.H>
       7             : 
       8             : #include "PhaseFieldMicrostructure.H"
       9             : #include "Integrator/Base/Mechanics.H"
      10             : #include "BC/Constant.H"
      11             : #include "BC/Step.H"
      12             : #include "Set/Set.H"
      13             : #include "Util/Util.H"
      14             : #include "IC/Random.H"
      15             : #include "IC/Trig.H"
      16             : #include "IC/Sphere.H"
      17             : #include "IC/Expression.H"
      18             : #include "Model/Interface/GB/SH.H"
      19             : #include "Numeric/Stencil.H"
      20             : #include "Solver/Nonlocal/Linear.H"
      21             : #include "Solver/Nonlocal/Newton.H"
      22             : #include "IC/Trig.H"
      23             : 
      24             : #include "Model/Solid/Affine/Cubic.H"
      25             : #include "Model/Solid/Affine/Hexagonal.H"
      26             : 
      27             : namespace Integrator
      28             : {
      29             : template<class model_type>
      30         324 : void PhaseFieldMicrostructure<model_type>::Advance(int lev, Set::Scalar time, Set::Scalar dt)
      31             : {
      32             :     BL_PROFILE("PhaseFieldMicrostructure::Advance");
      33         324 :     Base::Mechanics<model_type>::Advance(lev, time, dt);
      34             :     /// TODO Make this optional
      35             :     //if (lev != max_level) return;
      36             :     //std::swap(eta_old_mf[lev], eta_new_mf[lev]);
      37         324 :     const Set::Scalar* DX = this->geom[lev].CellSize();
      38             : 
      39             : 
      40         648 :     Model::Interface::GB::SH gbmodel(0.0, 0.0, anisotropy.sigma0, anisotropy.sigma1);
      41             : 
      42       30986 :     for (amrex::MFIter mfi(*eta_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
      43             :     {
      44       30662 :         amrex::Box bx = mfi.tilebox();
      45             :         //if (m_type == MechanicsBase<model_type>::Type::Static)
      46             :         //bx.grow(number_of_ghost_cells-1);
      47             :         //bx = bx & domain;
      48       30662 :         Set::Patch<Set::Scalar> eta = eta_mf.Patch(lev,mfi);
      49       30662 :         Set::Patch<Set::Scalar> driving_force = driving_force_mf.Patch(lev,mfi);
      50       30662 :         Set::Patch<Set::Scalar> driving_force_threshold = driving_force_threshold_mf.Patch(lev,mfi);// = (*driving_force_mf[lev]).array(mfi);
      51             : 
      52     2029062 :         amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
      53             :         {
      54    10005700 :             for (int m = 0; m < number_of_grains; m++)
      55             :             {
      56     8007300 :                 driving_force(i, j, k, m) = 0.0;
      57     8007300 :                 if (pf.threshold.on) driving_force_threshold(i, j, k, m) = 0.0;
      58     8007300 :                 Set::Scalar kappa = NAN, mu = NAN;
      59             : 
      60             :                 //
      61             :                 // BOUNDARY TERM and SECOND ORDER REGULARIZATION
      62             :                 //
      63             : 
      64     8007300 :                 Set::Vector Deta = Numeric::Gradient(eta, i, j, k, m, DX);
      65     8007300 :                 Set::Scalar normgrad = Deta.lpNorm<2>();
      66     8007300 :                 if (normgrad < 1E-4)
      67     5766470 :                     continue; // This ought to speed things up.
      68             : 
      69     2240830 :                 Set::Matrix DDeta = Numeric::Hessian(eta, i, j, k, m, DX);
      70     2240830 :                 Set::Scalar laplacian = DDeta.trace();
      71             : 
      72     2240830 :                 if (!anisotropy.on || time < anisotropy.tstart)
      73             :                 {
      74      877969 :                     kappa = pf.l_gb * 0.75 * pf.sigma0;
      75      877969 :                     mu = 0.75 * (1.0 / 0.23) * pf.sigma0 / pf.l_gb;
      76      877969 :                     if (pf.threshold.boundary)  driving_force_threshold(i, j, k, m) += -kappa * laplacian;
      77     1755940 :                     else                        driving_force(i, j, k, m) += -kappa * laplacian;
      78             :                 }
      79             :                 else
      80             :                 {
      81     1362860 :                     Set::Matrix4<AMREX_SPACEDIM, Set::Sym::Full> DDDDEta = Numeric::DoubleHessian<AMREX_SPACEDIM>(eta, i, j, k, m, DX);
      82     1362860 :                     auto anisotropic_df = boundary->DrivingForce(Deta, DDeta, DDDDEta);
      83     1362860 :                     if (pf.threshold.boundary) driving_force_threshold(i, j, k, m) += pf.l_gb * 0.75 * std::get<0>(anisotropic_df);
      84     2725720 :                     else                       driving_force(i, j, k, m) += pf.l_gb * 0.75 * std::get<0>(anisotropic_df);
      85     1362860 :                     if (std::isnan(std::get<0>(anisotropic_df))) Util::Abort(INFO);
      86     1362860 :                     if (pf.threshold.boundary) driving_force_threshold(i, j, k, m) += anisotropy.beta * std::get<1>(anisotropic_df);
      87     2725720 :                     else                       driving_force(i, j, k, m) += anisotropy.beta * std::get<1>(anisotropic_df);
      88     1362860 :                     if (std::isnan(std::get<1>(anisotropic_df))) Util::Abort(INFO);
      89     1362860 :                     mu = 0.75 * (1.0 / 0.23) * boundary->W(Deta) / pf.l_gb;
      90             :                 }
      91             : 
      92             :                 //
      93             :                 // CHEMICAL POTENTIAL
      94             :                 //
      95             : 
      96     2240830 :                 Set::Scalar sum_of_squares = 0.;
      97    13398500 :                 for (int n = 0; n < number_of_grains; n++)
      98             :                 {
      99    11157600 :                     if (m == n)
     100     2240830 :                         continue;
     101    26750400 :                     sum_of_squares += eta(i, j, k, n) * eta(i, j, k, n);
     102             :                 }
     103     2240830 :                 if (pf.threshold.chempot)
     104           0 :                     driving_force_threshold(i, j, k, m) += mu * (eta(i, j, k, m) * eta(i, j, k, m) - 1.0 + 2.0 * pf.gamma * sum_of_squares) * eta(i, j, k, m);
     105             :                 else
     106    11204100 :                     driving_force(i, j, k, m) += mu * (eta(i, j, k, m) * eta(i, j, k, m) - 1.0 + 2.0 * pf.gamma * sum_of_squares) * eta(i, j, k, m);
     107             : 
     108             :                 //
     109             :                 // LAGRANGE MULTIPLIER
     110             :                 //
     111     2240830 :                 if (lagrange.on && m == 0 && time > lagrange.tstart)
     112             :                 {
     113           0 :                     if (pf.threshold.lagrange)
     114           0 :                         driving_force_threshold(i, j, k, m) += lagrange.lambda * (volume - lagrange.vol0);
     115             :                     else
     116           0 :                         driving_force(i, j, k, m) += lagrange.lambda * (volume - lagrange.vol0);
     117             :                 }
     118             : 
     119             :                 //
     120             :                 // SYNTHETIC DRIVING FORCE
     121             :                 //
     122     2240830 :                 if (sdf.on && time > sdf.tstart)
     123             :                 {
     124           0 :                     if (pf.threshold.sdf)
     125           0 :                         driving_force_threshold(i, j, k, m) += sdf.val[m](time);
     126             :                     else
     127           0 :                         driving_force(i, j, k, m) += sdf.val[m](time);
     128             :                 }
     129             :             }
     130             :         });
     131             : 
     132             :         //
     133             :         // ELASTIC DRIVING FORCE
     134             :         //
     135       30662 :         if (pf.elastic_df)
     136             :         {
     137           0 :             amrex::Array4<const Set::Matrix> const& sigma = (*this->stress_mf[lev]).array(mfi);
     138             : 
     139           0 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     140             :             {
     141           0 :                 for (int m = 0; m < number_of_grains; m++)
     142             :                 {
     143           0 :                     Set::Matrix F0avg = Set::Matrix::Zero();
     144             : 
     145           0 :                     for (int n = 0; n < number_of_grains; n++)
     146             :                     {
     147           0 :                         F0avg += eta(i, j, k, n) * mechanics.model[n].F0;
     148             :                     }
     149             : 
     150           0 :                     Set::Matrix sig = Numeric::Interpolate::NodeToCellAverage(sigma, i, j, k, 0);
     151             : 
     152             :                     //Set::Matrix dF0deta = mechanics.model[m].F0;//(etasum * elastic.model[m].F0 - F0avg) / (etasum * etasum);
     153           0 :                     Set::Matrix dF0deta = Set::Matrix::Zero();
     154             : 
     155           0 :                     for (int n = 0; n < number_of_grains; n++)
     156             :                     {
     157           0 :                         if (n == m) continue;
     158           0 :                         Set::Scalar normsq = eta(i, j, k, m) * eta(i, j, k, m) + eta(i, j, k, n) * eta(i, j, k, n);
     159           0 :                         dF0deta += (2.0 * eta(i, j, k, m) * eta(i, j, k, n) * eta(i, j, k, n) * (mechanics.model[m].F0 - mechanics.model[n].F0))
     160             :                             / normsq / normsq;
     161             :                     }
     162             : 
     163           0 :                     Set::Scalar tmpdf = (dF0deta.transpose() * sig).trace();
     164             : 
     165           0 :                     if (pf.threshold.mechanics)
     166           0 :                         driving_force_threshold(i, j, k, m) -= pf.elastic_mult * tmpdf;
     167             :                     else
     168           0 :                         driving_force(i, j, k, m) -= pf.elastic_mult * tmpdf;
     169             :                 }
     170             :             });
     171             :         }
     172             : 
     173             : 
     174             :         //
     175             :         // Update eta
     176             :         // (if NOT using anisotropic kinetics)
     177             :         //
     178             :         
     179       30662 :         if (!anisotropic_kinetics.on || time < anisotropic_kinetics.tstart)
     180             :         {
     181    30047762 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     182             :             {
     183    10005700 :                 for (int m = 0; m < number_of_grains; m++)
     184             :                 {
     185     8007300 :                     if (pf.threshold.on)
     186             :                     {
     187           0 :                         if (driving_force_threshold(i, j, k, m) > pf.threshold.value)
     188             :                         {
     189           0 :                             if (pf.threshold.type == ThresholdType::Continuous)
     190           0 :                                 eta(i, j, k, m) -= pf.L * dt * (driving_force_threshold(i, j, k, m) - pf.threshold.value);
     191           0 :                             else if (pf.threshold.type == ThresholdType::Chop)
     192           0 :                                 eta(i, j, k, m) -= pf.L * dt * (driving_force_threshold(i, j, k, m));
     193             :                         }
     194           0 :                         else if (driving_force_threshold(i, j, k, m) < -pf.threshold.value)
     195             :                         {
     196           0 :                             if (pf.threshold.type == ThresholdType::Continuous)
     197           0 :                                 eta(i, j, k, m) -= pf.L * dt * (driving_force_threshold(i, j, k, m) + pf.threshold.value);
     198           0 :                             else if (pf.threshold.type == ThresholdType::Chop)
     199           0 :                                 eta(i, j, k, m) -= pf.L * dt * (driving_force_threshold(i, j, k, m));
     200             :                         }
     201             :                     }
     202             : 
     203    24021900 :                     eta(i, j, k, m) -= pf.L * dt * driving_force(i, j, k, m);
     204             :                 }
     205             :             });
     206             :         }
     207             :     }
     208             : 
     209             :     //
     210             :     // Update eta
     211             :     // (if we ARE using anisotropic kinetics)
     212             :     //
     213             :     
     214         324 :     if (anisotropic_kinetics.on && time >= anisotropic_kinetics.tstart)
     215             :     {
     216           0 :         for (amrex::MFIter mfi(*eta_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
     217             :         {
     218           0 :             amrex::Box bx = mfi.tilebox();
     219           0 :             amrex::Array4<const Set::Scalar> const& eta = (*eta_mf[lev]).array(mfi);
     220           0 :             amrex::Array4<Set::Scalar> const& L = (*anisotropic_kinetics.L_mf[lev]).array(mfi);
     221           0 :             amrex::Array4<Set::Scalar> const& threshold = (*anisotropic_kinetics.threshold_mf[lev]).array(mfi);
     222             : 
     223           0 :             for (int m = 0; m < number_of_grains; m++)
     224             :             {
     225           0 :                 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     226             :                 {
     227           0 :                     Set::Vector Deta = Numeric::Gradient(eta, i, j, k, m, DX);
     228           0 :                     Set::Scalar theta = atan2(Deta(1), Deta(0));
     229           0 :                     L(i, j, k, m) = (4. / 3.) * anisotropic_kinetics.mobility(theta) / pf.l_gb;
     230           0 :                     threshold(i, j, k, m) = anisotropic_kinetics.threshold(theta);
     231             :                 });
     232             :             }
     233             :         }
     234             :         
     235           0 :         for (amrex::MFIter mfi(*eta_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
     236             :         {
     237           0 :             amrex::Box bx = mfi.tilebox();
     238           0 :             Set::Patch<Set::Scalar>       eta = eta_mf.Patch(lev,mfi);
     239           0 :             Set::Patch<const Set::Scalar> driving_force = driving_force_mf.Patch(lev,mfi);
     240           0 :             Set::Patch<const Set::Scalar> driving_force_threshold = driving_force_threshold_mf.Patch(lev,mfi);
     241           0 :             Set::Patch<const Set::Scalar> L = anisotropic_kinetics.L_mf.Patch(lev,mfi);
     242           0 :             Set::Patch<const Set::Scalar> threshold = anisotropic_kinetics.threshold_mf.Patch(lev,mfi);
     243             : 
     244           0 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     245             :             {
     246           0 :                 for (int m = 0; m < number_of_grains; m++)
     247             :                 {
     248           0 :                     if (pf.threshold.on)
     249             :                     {
     250           0 :                         if (driving_force_threshold(i, j, k, m) > threshold(i,j,k,m))
     251             :                         {
     252           0 :                             if (pf.threshold.type == ThresholdType::Continuous)
     253           0 :                                 eta(i, j, k, m) -= L(i,j,k,m) * dt * (driving_force_threshold(i, j, k, m) - threshold(i,j,k,m));
     254           0 :                             else if (pf.threshold.type == ThresholdType::Chop)
     255           0 :                                 eta(i, j, k, m) -= L(i,j,k,m) * dt * (driving_force_threshold(i, j, k, m));
     256             :                         }
     257           0 :                         else if (driving_force_threshold(i, j, k, m) < -pf.threshold.value)
     258             :                         {
     259           0 :                             if (pf.threshold.type == ThresholdType::Continuous)
     260           0 :                                 eta(i, j, k, m) -= L(i,j,k,m) * dt * (driving_force_threshold(i, j, k, m) + threshold(i,j,k,m));
     261           0 :                             else if (pf.threshold.type == ThresholdType::Chop)
     262           0 :                                 eta(i, j, k, m) -= L(i,j,k,m) * dt * (driving_force_threshold(i, j, k, m));
     263             :                         }
     264             :                     }
     265             : 
     266           0 :                     eta(i, j, k, m) -= L(i,j,k,m) * dt * driving_force(i, j, k, m);
     267             :                 }
     268             :             });
     269             :         }        
     270             :     }
     271         324 : }
     272             : 
     273             : template<class model_type>
     274          23 : void PhaseFieldMicrostructure<model_type>::Initialize(int lev)
     275             : {
     276             :     BL_PROFILE("PhaseFieldMicrostructure::Initialize");
     277          23 :     Base::Mechanics<model_type>::Initialize(lev);
     278          23 :     ic->Initialize(lev, eta_mf);
     279          23 : }
     280             : 
     281             : template<class model_type>
     282          50 : void PhaseFieldMicrostructure<model_type>::TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar time, int ngrow)
     283             : {
     284             :     BL_PROFILE("PhaseFieldMicrostructure::TagCellsForRefinement");
     285          50 :     Base::Mechanics<model_type>::TagCellsForRefinement(lev, a_tags, time, ngrow);
     286          50 :     const amrex::Real* DX = this->geom[lev].CellSize();
     287          50 :     const Set::Vector dx(DX);
     288          50 :     const Set::Scalar dxnorm = dx.lpNorm<2>();
     289             : 
     290        3436 :     for (amrex::MFIter mfi(*eta_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
     291             :     {
     292        3386 :         const amrex::Box& bx = mfi.tilebox();
     293        3386 :         amrex::Array4<const amrex::Real> const& etanew = (*eta_mf[lev]).array(mfi);
     294        3386 :         amrex::Array4<char> const& tags = a_tags.array(mfi);
     295             : 
     296       18238 :         for (int n = 0; n < number_of_grains; n++)
     297     1199942 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k) {
     298     1185090 :             Set::Vector grad = Numeric::Gradient(etanew, i, j, k, n, DX);
     299             : 
     300     1185090 :             if (dxnorm * grad.lpNorm<2>() > ref_threshold)
     301      115862 :                 tags(i, j, k) = amrex::TagBox::SET;
     302             :         });
     303             :     }
     304          50 : }
     305             : 
     306             : template<class model_type>
     307          44 : void PhaseFieldMicrostructure<model_type>::TimeStepComplete(Set::Scalar /*time*/, int /*iter*/)
     308             : {
     309             :     // TODO: remove this function, it is no longer needed.
     310          44 : }
     311             : 
     312             : template<class model_type>
     313           0 : void PhaseFieldMicrostructure<model_type>::UpdateModel(int a_step, Set::Scalar /*a_time*/)
     314             : {
     315             :     BL_PROFILE("PhaseFieldMicrostructure::UpdateModel");
     316           0 :     if (a_step % this->m_interval) return;
     317             : 
     318           0 :     for (int lev = 0; lev <= this->finest_level; ++lev)
     319             :     {
     320           0 :         amrex::Box domain = this->geom[lev].Domain();
     321           0 :         domain.convert(amrex::IntVect::TheNodeVector());
     322             : 
     323           0 :         eta_mf[lev]->FillBoundary();
     324             : 
     325           0 :         for (MFIter mfi(*this->model_mf[lev], false); mfi.isValid(); ++mfi)
     326             :         {
     327           0 :             amrex::Box bx = mfi.grownnodaltilebox() & domain;
     328             : 
     329           0 :             amrex::Array4<model_type> const& model = this->model_mf[lev]->array(mfi);
     330           0 :             amrex::Array4<const Set::Scalar> const& eta = eta_mf[lev]->array(mfi);
     331             : 
     332           0 :             amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
     333             :             {
     334           0 :                 std::vector<Set::Scalar> etas(number_of_grains);
     335           0 :                 for (int n = 0; n < number_of_grains; n++)
     336           0 :                     etas[n] = Numeric::Interpolate::CellToNodeAverage(eta, i, j, k, n);
     337           0 :                 model(i, j, k) = model_type::Combine(mechanics.model, etas, 1);
     338             :             });
     339             :         }
     340             : 
     341           0 :         Util::RealFillBoundary(*this->model_mf[lev], this->geom[lev]);
     342             :     }
     343             : 
     344             : }
     345             : 
     346             : template<class model_type>
     347          44 : void PhaseFieldMicrostructure<model_type>::TimeStepBegin(Set::Scalar time, int iter)
     348             : {
     349             :     BL_PROFILE("PhaseFieldMicrostructure::TimeStepBegin");
     350          44 :     Base::Mechanics<model_type>::TimeStepBegin(time, iter);
     351             : 
     352          44 :     if (anisotropy.on && time >= anisotropy.tstart)
     353             :     {
     354          40 :         this->SetTimestep(anisotropy.timestep);
     355          40 :         if (anisotropy.elastic_int > 0)
     356           0 :             if (iter % anisotropy.elastic_int) return;
     357             :     }
     358             : }
     359             : 
     360             : template<class model_type>
     361       11898 : void PhaseFieldMicrostructure<model_type>::Integrate(int amrlev, Set::Scalar time, int step,
     362             :     const amrex::MFIter& mfi, const amrex::Box& box)
     363             : {
     364             :     BL_PROFILE("PhaseFieldMicrostructure::Integrate");
     365       11898 :     Base::Mechanics<model_type>::Integrate(amrlev, time, step, mfi, box);
     366             : 
     367       11898 :     Model::Interface::GB::SH gbmodel(0.0, 0.0, anisotropy.sigma0, anisotropy.sigma1);
     368       11898 :     const amrex::Real* DX = this->geom[amrlev].CellSize();
     369       11898 :     Set::Scalar dv = AMREX_D_TERM(DX[0], *DX[1], *DX[2]);
     370             : 
     371       11898 :     amrex::Array4<amrex::Real> const& eta = (*eta_mf[amrlev]).array(mfi);
     372      574826 :     amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k) {
     373             : #if AMREX_SPACEDIM == 2
     374      562928 :         auto sten = Numeric::GetStencil(i, j, k, box);
     375             : #endif
     376             : 
     377      562928 :         volume += eta(i, j, k, 0) * dv;
     378             : 
     379      562928 :         Set::Vector grad = Numeric::Gradient(eta, i, j, k, 0, DX);
     380      562928 :         Set::Scalar normgrad = grad.lpNorm<2>();
     381             : 
     382      562928 :         if (normgrad > 1E-8)
     383             :         {
     384      169690 :             Set::Vector normal = grad / normgrad;
     385             : 
     386      169690 :             Set::Scalar da = normgrad * dv;
     387      169690 :             area += da;
     388             : 
     389      169690 :             if (!anisotropy.on || time < anisotropy.tstart)
     390             :             {
     391        8562 :                 gbenergy += pf.sigma0 * da;
     392        8562 :                 Set::Scalar k = 0.75 * pf.sigma0 * pf.l_gb;
     393        8562 :                 realgbenergy += 0.5 * k * normgrad * normgrad * dv;
     394        8562 :                 regenergy = 0.0;
     395             :             }
     396             :             else
     397             :             {
     398             : #if AMREX_SPACEDIM == 2
     399      161128 :                 Set::Scalar theta = atan2(grad(1), grad(0));
     400      161128 :                 Set::Scalar sigma = boundary->W(theta);
     401      161128 :                 gbenergy += sigma * da;
     402             : 
     403      161128 :                 Set::Scalar k = 0.75 * sigma * pf.l_gb;
     404      161128 :                 realgbenergy += 0.5 * k * normgrad * normgrad * dv;
     405             : 
     406      161128 :                 Set::Matrix DDeta = Numeric::Hessian(eta, i, j, k, 0, DX, sten);
     407      161128 :                 Set::Vector tangent(normal[1], -normal[0]);
     408      161128 :                 Set::Scalar k2 = (DDeta * tangent).dot(tangent);
     409      161128 :                 regenergy += 0.5 * anisotropy.beta * k2 * k2;
     410             : #elif AMREX_SPACEDIM == 3
     411           0 :                 gbenergy += gbmodel.W(normal) * da;
     412             : #endif
     413             :             }
     414             :         }
     415             :     });
     416       11898 : }
     417             : 
     418             : template class PhaseFieldMicrostructure<Model::Solid::Affine::Cubic>;
     419             : template class PhaseFieldMicrostructure<Model::Solid::Affine::Hexagonal>;
     420             : 
     421             : 
     422             : } // namespace Integrator

Generated by: LCOV version 1.14