Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-28 09:20:49

0001 // Copyright (c) 2025 OPEN CASCADE SAS
0002 //
0003 // This file is part of Open CASCADE Technology software library.
0004 //
0005 // This library is free software; you can redistribute it and/or modify it under
0006 // the terms of the GNU Lesser General Public License version 2.1 as published
0007 // by the Free Software Foundation, with special exception defined in the file
0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0009 // distribution for complete text of the license and disclaimer of any warranty.
0010 //
0011 // Alternatively, this file may be used under the terms of Open CASCADE
0012 // commercial license or contractual agreement.
0013 
0014 #ifndef _MathInteg_Multiple_HeaderFile
0015 #define _MathInteg_Multiple_HeaderFile
0016 
0017 #include <MathUtils_Types.hxx>
0018 #include <MathUtils_Config.hxx>
0019 #include <math_Vector.hxx>
0020 #include <math_IntegerVector.hxx>
0021 #include <math_Matrix.hxx>
0022 #include <MathUtils_GaussKronrodWeights.hxx>
0023 
0024 #include <NCollection_DynamicArray.hxx>
0025 
0026 #include <cmath>
0027 #include <functional>
0028 
0029 namespace MathInteg
0030 {
0031 using namespace MathUtils;
0032 
0033 //! Configuration for multi-dimensional Gauss integration.
0034 struct MultipleConfig
0035 {
0036   int MaxOrder = 61; //!< Maximum integration order per dimension
0037 };
0038 
0039 //! Gauss-Legendre integration of a multi-variable function.
0040 //!
0041 //! Computes the N-dimensional integral using tensor product of 1D
0042 //! Gauss-Legendre quadrature:
0043 //! I = integral_{Lower}^{Upper} F(x1,...,xN) dx1...dxN
0044 //!
0045 //! Uses recursive summation over all Gauss points in each dimension.
0046 //!
0047 //! @tparam Func function type with bool Value(const math_Vector&, double&)
0048 //! @param theFunc N-dimensional function to integrate
0049 //! @param theNVars number of variables
0050 //! @param theLower lower bounds for each variable
0051 //! @param theUpper upper bounds for each variable
0052 //! @param theOrder integration order for each variable (max 61)
0053 //! @param theConfig optional configuration
0054 //! @return IntegResult containing the integral value
0055 template <typename Func>
0056 IntegResult GaussMultiple(Func&                     theFunc,
0057                           int                       theNVars,
0058                           const math_Vector&        theLower,
0059                           const math_Vector&        theUpper,
0060                           const math_IntegerVector& theOrder,
0061                           const MultipleConfig&     theConfig = MultipleConfig())
0062 {
0063   IntegResult aResult;
0064 
0065   // Validate inputs
0066   if (theNVars <= 0 || theLower.Length() != theNVars || theUpper.Length() != theNVars
0067       || theOrder.Length() != theNVars)
0068   {
0069     aResult.Status = Status::InvalidInput;
0070     return aResult;
0071   }
0072 
0073   const int aLowerL  = theLower.Lower();
0074   const int aLowerU  = theUpper.Lower();
0075   const int aLowerOr = theOrder.Lower();
0076 
0077   // Find maximum order and clamp orders
0078   math_IntegerVector aOrd(0, theNVars - 1);
0079   int                aMaxOrder = 0;
0080   for (int i = 0; i < theNVars; ++i)
0081   {
0082     aOrd(i) = std::min(theOrder(i + aLowerOr), theConfig.MaxOrder);
0083     aOrd(i) = std::max(aOrd(i), 1);
0084     if (aOrd(i) > aMaxOrder)
0085     {
0086       aMaxOrder = aOrd(i);
0087     }
0088   }
0089 
0090   // Compute midpoints and half-widths for coordinate transformation
0091   math_Vector aXm(0, theNVars - 1);
0092   math_Vector aXr(0, theNVars - 1);
0093   for (int i = 0; i < theNVars; ++i)
0094   {
0095     aXm(i) = 0.5 * (theLower(i + aLowerL) + theUpper(i + aLowerU));
0096     aXr(i) = 0.5 * (theUpper(i + aLowerU) - theLower(i + aLowerL));
0097   }
0098 
0099   // Get Gauss points and weights for each variable
0100   // Use NCollection_DynamicArray since math_Vector has no default constructor
0101   NCollection_DynamicArray<math_Vector> aGaussPoints;
0102   NCollection_DynamicArray<math_Vector> aGaussWeights;
0103 
0104   for (int i = 0; i < theNVars; ++i)
0105   {
0106     aGaussPoints.Append(math_Vector(0, aOrd(i) - 1));
0107     aGaussWeights.Append(math_Vector(0, aOrd(i) - 1));
0108 
0109     math_Vector aGP(1, aOrd(i));
0110     math_Vector aGW(1, aOrd(i));
0111     if (!GetOrderedGaussPointsAndWeights(aOrd(i), aGP, aGW))
0112     {
0113       aResult.Status = Status::InvalidInput;
0114       return aResult;
0115     }
0116 
0117     for (int k = 0; k < aOrd(i); ++k)
0118     {
0119       aGaussPoints.ChangeValue(i)(k)  = aGP(k + 1);
0120       aGaussWeights.ChangeValue(i)(k) = aGW(k + 1);
0121     }
0122   }
0123 
0124   // Recursive integration using lambda
0125   double      aVal = 0.0;
0126   math_Vector aX(1, theNVars);
0127   math_Vector aDx(1, theNVars);
0128 
0129   // Index array for iteration
0130   math_IntegerVector aInc(0, theNVars - 1, 0);
0131 
0132   // Iterative approach using index array
0133   std::function<bool(int)> aRecurse = [&](int theN) -> bool {
0134     if (theN == theNVars)
0135     {
0136       // Compute function value at current Gauss point
0137       for (int j = 0; j < theNVars; ++j)
0138       {
0139         aDx(j + 1) = aXr(j) * aGaussPoints.Value(j)(aInc(j));
0140         aX(j + 1)  = aXm(j) + aDx(j + 1);
0141       }
0142 
0143       double aF1;
0144       if (!theFunc.Value(aX, aF1))
0145       {
0146         return false;
0147       }
0148 
0149       // Compute product of weights
0150       double aWeight = 1.0;
0151       for (int j = 0; j < theNVars; ++j)
0152       {
0153         aWeight *= aGaussWeights.Value(j)(aInc(j));
0154       }
0155 
0156       aVal += aWeight * aF1;
0157       return true;
0158     }
0159 
0160     // Iterate over Gauss points for variable theN
0161     for (aInc(theN) = 0; aInc(theN) < aOrd(theN); ++aInc(theN))
0162     {
0163       if (!aRecurse(theN + 1))
0164       {
0165         return false;
0166       }
0167     }
0168     return true;
0169   };
0170 
0171   if (!aRecurse(0))
0172   {
0173     aResult.Status = Status::NotConverged;
0174     return aResult;
0175   }
0176 
0177   // Scale by half-widths
0178   for (int i = 0; i < theNVars; ++i)
0179   {
0180     aVal *= aXr(i);
0181   }
0182 
0183   aResult.Value  = aVal;
0184   aResult.Status = Status::OK;
0185   return aResult;
0186 }
0187 
0188 //! Gauss-Legendre integration with uniform order for all variables.
0189 //!
0190 //! @tparam Func function type with bool Value(const math_Vector&, double&)
0191 //! @param theFunc N-dimensional function to integrate
0192 //! @param theNVars number of variables
0193 //! @param theLower lower bounds for each variable
0194 //! @param theUpper upper bounds for each variable
0195 //! @param theOrder integration order for all variables
0196 //! @return IntegResult containing the integral value
0197 template <typename Func>
0198 IntegResult GaussMultipleUniform(Func&              theFunc,
0199                                  int                theNVars,
0200                                  const math_Vector& theLower,
0201                                  const math_Vector& theUpper,
0202                                  int                theOrder)
0203 {
0204   math_IntegerVector aOrders(0, theNVars - 1, theOrder);
0205   return GaussMultiple(theFunc, theNVars, theLower, theUpper, aOrders);
0206 }
0207 
0208 } // namespace MathInteg
0209 
0210 #endif // _MathInteg_Multiple_HeaderFile