boundary_integral.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. #ifndef _SCTL_BOUNDARY_INTEGRAL_HPP_
  2. #define _SCTL_BOUNDARY_INTEGRAL_HPP_
  3. #include <sctl/common.hpp>
  4. #include SCTL_INCLUDE(comm.hpp)
  5. #include SCTL_INCLUDE(mem_mgr.hpp)
  6. #include SCTL_INCLUDE(vector.hpp)
  7. #include <map>
  8. #include <set>
  9. namespace SCTL_NAMESPACE {
  10. template <class ValueType> class Matrix;
  11. template <class Real, Integer DIM> class ParticleFMM;
  12. /**
  13. * Abstract base class for an element-list. In addition to the functions
  14. * declared in this base class, the derived class must be copy-constructible.
  15. */
  16. template <class Real> class ElementListBase {
  17. public:
  18. virtual ~ElementListBase() {}
  19. /**
  20. * Returns the position and normals of the surface nodal points for each
  21. * element.
  22. *
  23. * @param[out] X the position of the node points in array-of-struct
  24. * order: {x_1, y_1, z_1, x_2, ..., x_n, y_n, z_n}
  25. *
  26. * @param[out] Xn the normal vectors of the node points in
  27. * array-of-struct order: {nx_1, ny_1, nz_1, nx_2, ..., nx_n, ny_n, nz_n}
  28. *
  29. * @param[out] element_wise_node_cnt the number of node points
  30. * belonging to each element.
  31. */
  32. virtual void GetNodeCoord(Vector<Real>* X, Vector<Real>* Xn, Vector<Long>* element_wise_node_cnt) const = 0;
  33. /**
  34. * Given an accuracy tolerance, returns the quadrature node positions,
  35. * the normals at the nodes, the weights and the cut-off distance from
  36. * the nodes for computing the far-field potential from the surface (at
  37. * target points beyond the cut-off distance).
  38. *
  39. * @param[out] X the position of the quadrature node points in
  40. * array-of-struct order: {x_1, y_1, z_1, x_2, ..., x_n, y_n, z_n}
  41. *
  42. * @param[out] Xn the normal vectors at the quadrature node points in
  43. * array-of-struct order: {nx_1, ny_1, nz_1, nx_2, ..., nx_n, ny_n, nz_n}
  44. *
  45. * @param[out] wts the weights corresponding to each quadrature node.
  46. *
  47. * @param[out] dist_far the cut-off distance from each quadrature node
  48. * such that quadrature rule will be accurate to the specified tolerance
  49. * for target points further away than this distance.
  50. *
  51. * @param[out] element_wise_node_cnt the number of quadrature node
  52. * points belonging to each element.
  53. *
  54. * @param[in] tol the accuracy tolerance.
  55. */
  56. virtual void GetFarFieldNodes(Vector<Real>& X, Vector<Real>& Xn, Vector<Real>& wts, Vector<Real>& dist_far, Vector<Long>& element_wise_node_cnt, const Real tol) const = 0;
  57. /**
  58. * Interpolates the density from surface node points to far-field
  59. * quadrature node points.
  60. *
  61. * @param[out] Fout the interpolated density at far-field quadrature
  62. * nodes in array-of-struct order.
  63. *
  64. * @param[in] Fin the input density at surface node points in
  65. * array-of-struct order.
  66. */
  67. virtual void GetFarFieldDensity(Vector<Real>& Fout, const Vector<Real>& Fin) const = 0;
  68. /**
  69. * Apply the transpose of the GetFarFieldDensity() operator for a single
  70. * element applied to the column-vectors of Min and the result is
  71. * returned in Mout.
  72. *
  73. * @param[out] Mout the output matrix where the column-vectors are the
  74. * result of the application of the transpose operator.
  75. *
  76. * @param[in] Min the input matrix whose column-vectors are
  77. * multiplied by the transpose operator.
  78. *
  79. * @param[in] elem_idx the index of the element.
  80. */
  81. virtual void FarFieldDensityOperatorTranspose(Matrix<Real>& Mout, const Matrix<Real>& Min, const Long elem_idx) const = 0;
  82. /**
  83. * Compute self-interaction operator for each element.
  84. *
  85. * @param[out] M_lst the vector of all self-interaction matrices
  86. * (in row-major format).
  87. *
  88. * @param[in] ker the kernel object.
  89. *
  90. * @param[in] tol the accuracy tolerance.
  91. *
  92. * @param[in] trg_dot_prod whether to compute dot product of the potential with the target-normal vector.
  93. *
  94. * @param[in] self pointer to element-list object.
  95. */
  96. template <class Kernel> static void SelfInterac(Vector<Matrix<Real>>& M_lst, const Kernel& ker, Real tol, bool trg_dot_prod, const ElementListBase<Real>* self);
  97. /**
  98. * Compute near-interaction operator for a given element-idx and each each target.
  99. *
  100. * @param[out] M the near-interaction matrix (in row-major format).
  101. *
  102. * @param[in] Xt the position of the target points in array-of-structure
  103. * order: {x_1, y_1, z_1, x_2, ..., x_n, y_n, z_n}
  104. *
  105. * @param[in] normal_trg the normal at the target points in array-of-structure
  106. * order: {nx_1, ny_1, nz_1, nx_2, ..., nx_n, ny_n, nz_n}
  107. *
  108. * @param[in] ker the kernel object.
  109. *
  110. * @param[in] tol the accuracy tolerance.
  111. *
  112. * @param[in] elem_idx the index of the source element.
  113. *
  114. * @param[in] self pointer to element-list object.
  115. */
  116. template <class Kernel> static void NearInterac(Matrix<Real>& M, const Vector<Real>& Xt, const Vector<Real>& normal_trg, const Kernel& ker, Real tol, const Long elem_idx, const ElementListBase<Real>* self);
  117. };
  118. /**
  119. * Implements parallel computation of boundary integrals.
  120. */
  121. template <class Real, class Kernel> class BoundaryIntegralOp {
  122. static constexpr Integer KDIM0 = Kernel::SrcDim();
  123. static constexpr Integer KDIM1 = Kernel::TrgDim();
  124. static constexpr Integer COORD_DIM = 3;
  125. public:
  126. BoundaryIntegralOp() = delete;
  127. BoundaryIntegralOp(const BoundaryIntegralOp&) = delete;
  128. BoundaryIntegralOp& operator= (const BoundaryIntegralOp&) = delete;
  129. /**
  130. * Constructor
  131. *
  132. * @param[in] ker the kernel object.
  133. *
  134. * @param[in] comm the MPI communicator.
  135. */
  136. explicit BoundaryIntegralOp(const Kernel& ker, bool trg_normal_dot_prod = false, const Comm& comm = Comm::Self());
  137. /**
  138. * Destructor
  139. */
  140. ~BoundaryIntegralOp();
  141. /**
  142. * Specify accuracy tolerance.
  143. */
  144. void SetAccuracy(Real tol);
  145. /**
  146. * Set kernel functions for FMM translation operators
  147. */
  148. template <class KerS2M, class KerS2L, class KerS2T, class KerM2M, class KerM2L, class KerM2T, class KerL2L, class KerL2T> void SetFMMKer(const KerS2M& k_s2m, const KerS2L& k_s2l, const KerS2T& k_s2t, const KerM2M& k_m2m, const KerM2L& k_m2l, const KerM2T& k_m2t, const KerL2L& k_l2l, const KerL2T& k_l2t);
  149. /**
  150. * Add an element-list.
  151. */
  152. template <class ElemLstType> void AddElemList(const ElemLstType& elem_lst, const std::string& name = std::to_string(typeid(ElemLstType).hash_code()));
  153. /**
  154. * Get const reference to an element-list.
  155. */
  156. template <class ElemLstType> const ElemLstType& GetElemList(const std::string& name = std::to_string(typeid(ElemLstType).hash_code())) const;
  157. /**
  158. * Delete an element-list.
  159. */
  160. void DeleteElemList(const std::string& name);
  161. /**
  162. * Delete an element-list.
  163. */
  164. template <class ElemLstType> void DeleteElemList();
  165. /**
  166. * Set target point coordinates.
  167. *
  168. * @param[in] Xtrg the coordinates of target points in array-of-struct
  169. * order: {x_1, y_1, z_1, x_2, ..., x_n, y_n, z_n}
  170. */
  171. void SetTargetCoord(const Vector<Real>& Xtrg);
  172. /**
  173. * Set target point normals.
  174. *
  175. * @param[in] Xn_trg the coordinates of target points in array-of-struct
  176. * order: {nx_1, ny_1, nz_1, nx_2, ..., nx_n, ny_n, nz_n}
  177. */
  178. void SetTargetNormal(const Vector<Real>& Xn_trg);
  179. /**
  180. * Get dimension of the boundary integral operator. Dim(0) is the input
  181. * dimension and Dim(1) is the output dimension.
  182. */
  183. Long Dim(Integer k) const;
  184. /**
  185. * Setup the boundary integral operator.
  186. */
  187. void Setup() const;
  188. /**
  189. * Clear setup data.
  190. */
  191. void ClearSetup() const;
  192. /**
  193. * Evaluate the boundary integral operator.
  194. */
  195. void ComputePotential(Vector<Real>& U, const Vector<Real>& F) const;
  196. private:
  197. void SetupBasic() const;
  198. void SetupFar() const;
  199. void SetupSelf() const;
  200. void SetupNear() const;
  201. void ComputeFarField(Vector<Real>& U, const Vector<Real>& F) const;
  202. void ComputeNearInterac(Vector<Real>& U, const Vector<Real>& F) const;
  203. struct ElemLstData {
  204. void (*SelfInterac)(Vector<Matrix<Real>>&, const Kernel&, Real, bool, const ElementListBase<Real>*);
  205. void (*NearInterac)(Matrix<Real>&, const Vector<Real>&, const Vector<Real>&, const Kernel&, Real, const Long, const ElementListBase<Real>*);
  206. };
  207. std::map<std::string,ElementListBase<Real>*> elem_lst_map;
  208. std::map<std::string,ElemLstData> elem_data_map;
  209. Vector<Real> Xt; // User specified position of target points
  210. Vector<Real> Xnt; // User specified normal at target points
  211. Real tol_;
  212. Kernel ker_;
  213. bool trg_normal_dot_prod_;
  214. Comm comm_;
  215. mutable bool setup_flag;
  216. mutable Vector<std::string> elem_lst_name; // name of each element-list (size=Nlst)
  217. mutable Vector<Long> elem_lst_cnt, elem_lst_dsp; // cnt and dsp of elements for each elem_lst (size=Nlst)
  218. mutable Vector<Long> elem_nds_cnt, elem_nds_dsp; // cnt and dsp of nodes for each element (size=Nelem)
  219. mutable Vector<Real> Xsurf; // Position of surface node points (target points for on-surface evaluation)
  220. mutable Vector<Real> Xn_surf; // Normal at surface node points (normal vector for on-surface evaluation)
  221. mutable Vector<Real> Xtrg; // Position of target points
  222. mutable Vector<Real> Xn_trg; // Normal vector at target points
  223. mutable bool setup_far_flag;
  224. mutable ParticleFMM<Real,COORD_DIM> fmm;
  225. mutable Vector<Long> elem_nds_cnt_far, elem_nds_dsp_far; // cnt and dsp of far-nodes for each element (size=Nelem)
  226. mutable Vector<Real> X_far, Xn_far, wts_far; // position, normal and weights for far-field quadrature
  227. mutable Vector<Real> dist_far; // minimum distance of target points for far-field evaluation
  228. mutable Vector<Real> F_far; // pre-allocated memory for density in far-field evaluation
  229. mutable bool setup_near_flag;
  230. mutable Vector<Real> Xtrg_near; // position of near-interaction target points sorted by element (size=Nnear*COORD_DIM)
  231. mutable Vector<Real> Xn_trg_near; // normal at near-interaction target points sorted by element (size=Nnear*COORD_DIM)
  232. mutable Vector<Long> near_scatter_index; // prmutation vector that takes near-interactions sorted by elem-idx to sorted by trg-idx (size=Nnear)
  233. mutable Vector<Long> near_trg_cnt, near_trg_dsp; // cnt and dsp of near-interactions for each target (size=Ntrg)
  234. mutable Vector<Long> near_elem_cnt, near_elem_dsp; // cnt and dsp of near-interaction for each element (size=Nelem)
  235. mutable Vector<Long> K_near_cnt, K_near_dsp; // cnt and dsp of element wise near-interaction matrix (size=Nelem)
  236. mutable Vector<Real> K_near;
  237. mutable bool setup_self_flag;
  238. mutable Vector<Matrix<Real>> K_self;
  239. };
  240. }
  241. #include SCTL_INCLUDE(boundary_integral.txx)
  242. #endif //_SCTL_BOUNDARY_INTEGRAL_HPP_