LCOV - code coverage report
Current view: top level - operators - FiniteDifferences.cpp (source / functions) Hit Total Coverage
Test: test_coverage.info.cleaned Lines: 0 89 0.0 %
Date: 2022-08-04 03:43:28 Functions: 0 36 0.0 %

          Line data    Source code
       1             : #include "FiniteDifferences.h"
       2             : #include "Timer.h"
       3             : #include "VolumeDescriptor.h"
       4             : #include "TypeCasts.hpp"
       5             : 
       6             : namespace elsa
       7             : {
       8             :     template <typename data_t>
       9           0 :     FiniteDifferences<data_t>::FiniteDifferences(const DataDescriptor& domainDescriptor,
      10             :                                                  DiffType type)
      11             :         : FiniteDifferences(domainDescriptor,
      12           0 :                             BooleanVector_t::Ones(domainDescriptor.getNumberOfDimensions()), type)
      13             :     {
      14           0 :     }
      15             : 
      16             :     template <typename data_t>
      17           0 :     FiniteDifferences<data_t>::FiniteDifferences(const DataDescriptor& domainDescriptor,
      18             :                                                  const BooleanVector_t& activeDims, DiffType type)
      19             :         : LinearOperator<data_t>(domainDescriptor,
      20             :                                  domainDescriptor), // setting range in body of constructor
      21           0 :           _type{type},
      22           0 :           _activeDims{activeDims},
      23           0 :           _coordDiff{activeDims.size()},
      24           0 :           _coordDelta{activeDims.size()},
      25           0 :           _dimCounter{activeDims.size()}
      26             :     {
      27             :         // build the range descriptor of appropriate size
      28           0 :         IndexVector_t coefficients(domainDescriptor.getNumberOfDimensions() + 1);
      29           0 :         coefficients << domainDescriptor.getNumberOfCoefficientsPerDimension(),
      30           0 :             activeDims.cast<index_t>().sum();
      31             : 
      32           0 :         RealVector_t spacing(domainDescriptor.getNumberOfDimensions() + 1);
      33           0 :         spacing << domainDescriptor.getSpacingPerDimension(), 1;
      34             : 
      35           0 :         this->_rangeDescriptor = std::make_unique<VolumeDescriptor>(coefficients, spacing);
      36             : 
      37           0 :         precomputeHelpers();
      38           0 :     }
      39             : 
      40             :     template <typename data_t>
      41           0 :     void FiniteDifferences<data_t>::precomputeHelpers()
      42             :     {
      43           0 :         IndexVector_t numberOfCoefficients =
      44             :             this->_rangeDescriptor->getNumberOfCoefficientsPerDimension();
      45             : 
      46           0 :         index_t deltaTmp = 1;
      47           0 :         int count = -1;
      48           0 :         for (index_t ic = 0; ic < this->getDomainDescriptor().getNumberOfDimensions(); ++ic) {
      49           0 :             _coordDiff[ic] = numberOfCoefficients.head(ic).prod();
      50             : 
      51           0 :             deltaTmp *= numberOfCoefficients[ic];
      52           0 :             _coordDelta[ic] = deltaTmp;
      53             : 
      54           0 :             if (_activeDims[ic])
      55           0 :                 ++count;
      56           0 :             _dimCounter[ic] = count;
      57             :         }
      58           0 :     }
      59             : 
      60             :     template <typename data_t>
      61           0 :     void FiniteDifferences<data_t>::applyImpl(const DataContainer<data_t>& x,
      62             :                                               DataContainer<data_t>& Ax) const
      63             :     {
      64           0 :         Timer timeguard("FiniteDifferences", "apply");
      65             : 
      66           0 :         Ax = 0;
      67             : 
      68           0 :         switch (_type) {
      69           0 :             case DiffType::FORWARD:
      70           0 :                 applyHelper(x, Ax, DiffType::FORWARD);
      71           0 :                 break;
      72           0 :             case DiffType::BACKWARD:
      73           0 :                 applyHelper(x, Ax, DiffType::BACKWARD);
      74           0 :                 break;
      75           0 :             case DiffType::CENTRAL:
      76           0 :                 applyHelper(x, Ax, DiffType::CENTRAL);
      77           0 :                 break;
      78           0 :             default:
      79           0 :                 throw LogicError("FiniteDifferences::apply: invalid DiffType");
      80             :         }
      81           0 :     }
      82             : 
      83             :     template <typename data_t>
      84           0 :     void FiniteDifferences<data_t>::applyAdjointImpl(const DataContainer<data_t>& y,
      85             :                                                      DataContainer<data_t>& Aty) const
      86             :     {
      87           0 :         Timer timeguard("FiniteDifferences", "applyAdjoint");
      88             : 
      89           0 :         Aty = 0;
      90             : 
      91           0 :         switch (_type) {
      92           0 :             case DiffType::FORWARD:
      93           0 :                 applyAdjointHelper(y, Aty, DiffType::FORWARD);
      94           0 :                 break;
      95           0 :             case DiffType::BACKWARD:
      96           0 :                 applyAdjointHelper(y, Aty, DiffType::BACKWARD);
      97           0 :                 break;
      98           0 :             case DiffType::CENTRAL:
      99           0 :                 applyAdjointHelper(y, Aty, DiffType::CENTRAL);
     100           0 :                 break;
     101           0 :             default:
     102           0 :                 throw LogicError("FiniteDifferences::applyAdjoint: invalid DiffType");
     103             :         }
     104           0 :     }
     105             : 
     106             :     template <typename data_t>
     107             :     template <typename FDtype>
     108           0 :     void FiniteDifferences<data_t>::applyHelper(const DataContainer<data_t>& x,
     109             :                                                 DataContainer<data_t>& Ax, FDtype type) const
     110             :     {
     111           0 :         index_t sizeOfDomain = this->getDomainDescriptor().getNumberOfCoefficients();
     112           0 :         index_t numDim = this->getDomainDescriptor().getNumberOfDimensions();
     113             : 
     114           0 :         IndexVector_t numberOfCoefficients =
     115           0 :             this->getRangeDescriptor().getNumberOfCoefficientsPerDimension();
     116           0 :         IndexVector_t decrementedCoefficients =
     117             :             numberOfCoefficients
     118           0 :             - IndexVector_t::Ones(this->getRangeDescriptor().getNumberOfDimensions());
     119             : 
     120           0 : #pragma omp parallel
     121             :         for (long currDim = 0; currDim < numDim; ++currDim) {
     122             :             if (!_activeDims[currDim])
     123             :                 continue;
     124             : 
     125             :             index_t modulus = numberOfCoefficients.head(currDim + 1).prod();
     126             :             index_t divisor = numberOfCoefficients.head(currDim).prod();
     127             : 
     128             : #pragma omp for nowait
     129             :             for (index_t id = 0; id < sizeOfDomain; ++id) {
     130             :                 index_t icCount = (id % modulus) / divisor; //_domainDescriptor.index(id, ic);
     131             :                 index_t ir = id + _dimCounter[currDim] * _coordDelta[currDim];
     132             : 
     133             :                 // store result depending on mode
     134             :                 switch (type) {
     135             :                     case DiffType::FORWARD:
     136             :                         Ax[ir] = -x[id];
     137             :                         if (icCount < decrementedCoefficients[currDim])
     138             :                             Ax[ir] += x[id + _coordDiff[currDim]];
     139             :                         break;
     140             :                     case DiffType::BACKWARD:
     141             :                         Ax[ir] = x[id];
     142             :                         if (icCount > 0)
     143             :                             Ax[ir] -= x[id - _coordDiff[currDim]];
     144             :                         break;
     145             :                     case DiffType::CENTRAL:
     146             :                         Ax[ir] = static_cast<data_t>(0.0);
     147             :                         if (icCount < decrementedCoefficients[currDim])
     148             :                             Ax[ir] += static_cast<data_t>(0.5) * x[id + _coordDiff[currDim]];
     149             :                         if (icCount > 0)
     150             :                             Ax[ir] -= static_cast<data_t>(0.5) * x[id - _coordDiff[currDim]];
     151             :                         break;
     152             :                 }
     153             :             }
     154             :         }
     155           0 :     }
     156             : 
     157             :     template <typename data_t>
     158             :     template <typename FDtype>
     159           0 :     void FiniteDifferences<data_t>::applyAdjointHelper(const DataContainer<data_t>& y,
     160             :                                                        DataContainer<data_t>& Aty,
     161             :                                                        FDtype type) const
     162             :     {
     163           0 :         index_t sizeOfDomain = this->getDomainDescriptor().getNumberOfCoefficients();
     164           0 :         index_t numDim = this->getDomainDescriptor().getNumberOfDimensions();
     165             : 
     166           0 :         IndexVector_t numberOfCoefficients =
     167           0 :             this->getDomainDescriptor().getNumberOfCoefficientsPerDimension();
     168           0 :         IndexVector_t decrementedCoefficients = numberOfCoefficients - IndexVector_t::Ones(numDim);
     169             : 
     170           0 : #pragma omp parallel
     171             :         for (long currDim = 0; currDim < numDim; ++currDim) {
     172             :             if (!_activeDims[currDim])
     173             :                 continue;
     174             : 
     175             :             index_t modulus = numberOfCoefficients.head(currDim + 1).prod();
     176             :             index_t divisor = numberOfCoefficients.head(currDim).prod();
     177             : 
     178             : #pragma omp for nowait
     179             :             for (index_t id = 0; id < sizeOfDomain; ++id) {
     180             :                 index_t icCount = (id % modulus) / divisor;
     181             :                 index_t ir = id + _dimCounter[currDim] * _coordDelta[currDim];
     182             : 
     183             :                 switch (type) {
     184             :                     case DiffType::FORWARD:
     185             :                         if (icCount > 0)
     186             :                             Aty[id] += y[ir - _coordDiff[currDim]];
     187             : 
     188             :                         Aty[id] -= y[ir];
     189             :                         break;
     190             :                     case DiffType::BACKWARD:
     191             :                         if (icCount < decrementedCoefficients(currDim))
     192             :                             Aty[id] -= y[ir + _coordDiff[currDim]];
     193             : 
     194             :                         Aty[id] += y[ir];
     195             :                         break;
     196             :                     case DiffType::CENTRAL:
     197             :                         if (icCount > 0)
     198             :                             Aty[ir] += static_cast<data_t>(0.5) * y[ir - _coordDiff[currDim]];
     199             : 
     200             :                         if (icCount < decrementedCoefficients(currDim))
     201             :                             Aty[ir] -= static_cast<data_t>(0.5) * y[ir + _coordDiff[currDim]];
     202             :                         break;
     203             :                 }
     204             :             }
     205             :         }
     206           0 :     }
     207             : 
     208             :     template <typename data_t>
     209           0 :     FiniteDifferences<data_t>* FiniteDifferences<data_t>::cloneImpl() const
     210             :     {
     211           0 :         return new FiniteDifferences(this->getDomainDescriptor(), _activeDims, _type);
     212             :     }
     213             : 
     214             :     template <typename data_t>
     215           0 :     bool FiniteDifferences<data_t>::isEqual(const LinearOperator<data_t>& other) const
     216             :     {
     217           0 :         if (!LinearOperator<data_t>::isEqual(other))
     218           0 :             return false;
     219             : 
     220           0 :         auto otherFD = downcast_safe<FiniteDifferences>(&other);
     221           0 :         if (!otherFD)
     222           0 :             return false;
     223             : 
     224           0 :         if (_type != otherFD->_type || _activeDims != otherFD->_activeDims)
     225           0 :             return false;
     226             : 
     227           0 :         return true;
     228             :     }
     229             : 
     230             :     // ------------------------------------------
     231             :     // explicit template instantiation
     232             :     template class FiniteDifferences<float>;
     233             :     template class FiniteDifferences<double>;
     234             :     template class FiniteDifferences<complex<float>>;
     235             :     template class FiniteDifferences<complex<double>>;
     236             : 
     237             : } // namespace elsa

Generated by: LCOV version 1.14