lib/src/Workshop/NormalDerivative.cpp
// Expand and evaluate the multi-index partial derivative of a
// PartialDerivativeTerm recursively.  If the multi-index is zero (i.e., no
// further derivatives) then simply evaluate the PartialDerivateTerm at
// "a_point" using the implicit function.  If the multi-index isn't zerom,
// explicitly compute one partial derivative which is a sum of
// PartialDerivativeTerm's and call "expand" with each of these terms and a
// reduced multi-index (which will eventually be zero).  The sum the results
// and return that sum.
Expand and evaluate the multi-index partial derivative of a
PartialDerivativeTerm recursively.  If the multi-index is zero  then simply evaluate the PartialDerivateTerm at
"a_point" using the implicit function.  If the multi-index isn't zerom,
explicitly compute one partial derivative which is a sum of
PartialDerivativeTerm's and call "expand" with each of these terms and a
reduced multi-index (which will eventually be zero).  The sum the results
and return that sum.
Expand and evaluate the multi - index partial derivative of a PartialDerivativeTerm recursively . If the multi - index is zero then simply evaluate the PartialDerivateTerm at " a_point " using the implicit function . If the multi - index isn ' t zerom explicitly compute one partial derivative which is a sum of PartialDerivativeTerm ' s and call " expand " with each of these terms and a reduced multi - index ( which will eventually be zero ) . The sum the results and return that sum .
Real NormalDerivative<GLOBALDIM>::expand(const IvDim                 & a_multiIndex,
                                         const PartialDerivativeTerm & a_term,
                                         const RvDim                 & a_point,
                                         const IFSlicer<GLOBALDIM>   * a_implicitFunction) const
{
  Real value;
  int firstNonZero;
  for (firstNonZero = 0; firstNonZero < GLOBALDIM; firstNonZero++)
  {
    if (a_multiIndex[firstNonZero] != 0)
    {
      break;
    }
  }
  if (firstNonZero == GLOBALDIM)
  {
    value = 1.0;
    const DerivativeProduct& curDerivativeProduct = a_term.first;
    for (DerivativeProduct::const_iterator it=curDerivativeProduct.begin();
         it != curDerivativeProduct.end();
         ++it)
    {
      const IvDim& curMultiIndex = it->first;
      const int&   curExponent   = it->second;
      Real curValue = pow(a_implicitFunction->value(curMultiIndex,a_point),curExponent);
      value *= curValue;
    }
    if (m_magnitudeOfGradient != 0.0)
    {
      int curExponent = a_term.second;
      value /= pow(m_magnitudeOfGradient,curExponent);
    }
  }
  else
  {
    value = 0.0;
    IvDim curPartialDerivative = BASISV_TM<int,GLOBALDIM>(firstNonZero);
    IvDim reducedMultiIndex = a_multiIndex;
    reducedMultiIndex[firstNonZero]--;
    const DerivativeProduct& curDerivativeProduct = a_term.first;
    int curExponentOfMagnitudeOfGradient = a_term.second;
    for (DerivativeProduct::const_iterator it=curDerivativeProduct.begin();
         it != curDerivativeProduct.end();
         ++it)
    {
      const IvDim& curMultiIndex = it->first;
      const int&   curExponent   = it->second;
      DerivativeProduct newDerivativeProduct = curDerivativeProduct;
      Real multiplier = curExponent;
      if (curExponent == 1)
      {
        newDerivativeProduct.erase(curMultiIndex);
      }
      else
      {
        newDerivativeProduct[curMultiIndex] -= 1;
      }
      IvDim newMultiIndex = curMultiIndex;
      newMultiIndex += curPartialDerivative;
      newDerivativeProduct[newMultiIndex] += 1;
      PartialDerivativeTerm newTerm(newDerivativeProduct,
                                    curExponentOfMagnitudeOfGradient);
      Real curValue = multiplier * expand(reducedMultiIndex,
                                          newTerm,
                                          a_point,
                                          a_implicitFunction);
      value += curValue;
    }
    for (int idir = 0; idir < GLOBALDIM; idir++)
    {
      DerivativeProduct newDerivativeProduct = curDerivativeProduct;
      IvDim firstPartial = BASISV_TM<int,GLOBALDIM>(idir);
      IvDim secondPartial = firstPartial + curPartialDerivative;
      newDerivativeProduct[firstPartial] += 1;
      newDerivativeProduct[secondPartial] += 1;
      int newExponentOfMagnitudeOfGradient = curExponentOfMagnitudeOfGradient + 2;
      Real multiplier = -curExponentOfMagnitudeOfGradient;
      PartialDerivativeTerm newTerm(newDerivativeProduct,
                                    newExponentOfMagnitudeOfGradient);
      Real curValue = multiplier * expand(reducedMultiIndex,
                                          newTerm,
                                          a_point,
                                          a_implicitFunction);
      value += curValue;
    }
  }
  return value;
}
Real NormalDerivative < GLOBALDIM > :: expand ( const IvDim & a_multiIndex , const PartialDerivativeTerm & a_term , const RvDim & a_point , const IFSlicer < GLOBALDIM > * a_implicitFunction ) const { Real value ; int firstNonZero ; for ( firstNonZero = 0 ; firstNonZero < GLOBALDIM ; firstNonZero ++ ) { if ( a_multiIndex [ firstNonZero ] != 0 ) { break ; } } if ( firstNonZero == GLOBALDIM ) { value = 1.0 ; const DerivativeProduct & curDerivativeProduct = a_term . first ; for ( DerivativeProduct :: const_iterator it = curDerivativeProduct . begin ( ) ; it != curDerivativeProduct . end ( ) ; ++ it ) { const IvDim & curMultiIndex = it -> first ; const int & curExponent = it -> second ; Real curValue = pow ( a_implicitFunction -> value ( curMultiIndex , a_point ) , curExponent ) ; value *= curValue ; } if ( m_magnitudeOfGradient != 0.0 ) { int curExponent = a_term . second ; value /= pow ( m_magnitudeOfGradient , curExponent ) ; } } else { value = 0.0 ; IvDim curPartialDerivative = BASISV_TM < int , GLOBALDIM > ( firstNonZero ) ; IvDim reducedMultiIndex = a_multiIndex ; reducedMultiIndex [ firstNonZero ] -- ; const DerivativeProduct & curDerivativeProduct = a_term . first ; int curExponentOfMagnitudeOfGradient = a_term . second ; for ( DerivativeProduct :: const_iterator it = curDerivativeProduct . begin ( ) ; it != curDerivativeProduct . end ( ) ; ++ it ) { const IvDim & curMultiIndex = it -> first ; const int & curExponent = it -> second ; DerivativeProduct newDerivativeProduct = curDerivativeProduct ; Real multiplier = curExponent ; if ( curExponent == 1 ) { newDerivativeProduct . erase ( curMultiIndex ) ; } else { newDerivativeProduct [ curMultiIndex ] -= 1 ; } IvDim newMultiIndex = curMultiIndex ; newMultiIndex += curPartialDerivative ; newDerivativeProduct [ newMultiIndex ] += 1 ; PartialDerivativeTerm newTerm ( newDerivativeProduct , curExponentOfMagnitudeOfGradient ) ; Real curValue = multiplier * expand ( reducedMultiIndex , newTerm , a_point , a_implicitFunction ) ; value += curValue ; } for ( int idir = 0 ; idir < GLOBALDIM ; idir ++ ) { DerivativeProduct newDerivativeProduct = curDerivativeProduct ; IvDim firstPartial = BASISV_TM < int , GLOBALDIM > ( idir ) ; IvDim secondPartial = firstPartial + curPartialDerivative ; newDerivativeProduct [ firstPartial ] += 1 ; newDerivativeProduct [ secondPartial ] += 1 ; int newExponentOfMagnitudeOfGradient = curExponentOfMagnitudeOfGradient + 2 ; Real multiplier = - curExponentOfMagnitudeOfGradient ; PartialDerivativeTerm newTerm ( newDerivativeProduct , newExponentOfMagnitudeOfGradient ) ; Real curValue = multiplier * expand ( reducedMultiIndex , newTerm , a_point , a_implicitFunction ) ; value += curValue ; } } return value ; }
Expand and evaluate the multi-index partial derivative of a
PartialDerivativeTerm recursively.
Expand and evaluate the multi - index partial derivative of a PartialDerivativeTerm recursively .
// No more derivatives, evaluate the current term // Evalute the needed partial derivatives and take the product of the // specified powers // Evaluate a single partial derivative to its power // Divide by the magnitude of the gradient including the exponent // This is the (current) partial derivative we are going to apply to the // current product of partial derivatives // This is the remaining multi-index that we haven't applied // Distribute the current partial derivative over the product of // derivatives using the product rule // Loop through each term in the product // Get the current derivative multi-index and exponent // Create the next term in the product rule by copying the current // product and take the current partial derivative of the current // product term (including the exponent). // Handle the exponent of the current product term // Erase the current product term if its current exponent is one // Otherwise, decrement the exponent by one // Generate the new product term // Put it into the product // Put the new product together with magnitude of the gradient term // Evaluate this term in the product rule (recursively) // Add the result into the overall product rule sum // Now handle the last term in the overall product (and product rule) // which is the inverse of the magnitude of the gradient with an exponent. // The derivative of the magnitude of the gradient results in a sum which // has to be handled term by term // Copy the current overall product // Create the two new terms in the product // Put them in the new overall product // Generate the new exponent for the magnitude of the gradient // The multiplier due to the exponent // Put the new product together with magnitude of the gradient term // Evaluate this term in the product rule (recursively) // Add the result into the overall product rule sum