#ifndef _SCTL_SLENDER_ELEMENT_HPP_ #define _SCTL_SLENDER_ELEMENT_HPP_ #include #include SCTL_INCLUDE(mem_mgr.hpp) #include SCTL_INCLUDE(vector.hpp) namespace SCTL_NAMESPACE { class Comm; struct VTUData; template class FFT; template class Vector; template class Matrix; template class ElementListBase; template class BoundaryIntegralOp; template class ToroidalGreensFn { static constexpr Integer COORD_DIM = 3; static constexpr Real min_dist = 0.0; static constexpr Real max_dist = 0.2; public: /** * Constructor */ ToroidalGreensFn() {} /** * Precompute tables for modal Green's funcation */ template void Setup(const Kernel& ker, Real R0); /** * Build modal Green's function operator for a given target point * (x0,x1,x2). */ template void BuildOperatorModal(Matrix& M, const Real x0, const Real x1, const Real x2, const Kernel& ker) const; private: /** * Basis functions in which to represent the potential. */ template class BasisFn { // p(x) log(x) + q(x) + 1/x public: static ValueType Eval(const Vector& coeff, ValueType x); static void EvalBasis(Vector& f, ValueType x); static const Vector& nds(Integer ORDER); }; /** * Precompute tables for modal Green's funcation */ template void PrecompToroidalGreensFn(const Kernel& ker, ValueType R0); /** * Compute reference potential using adaptive integration. */ template static void ComputePotential(Vector& U, const Vector& Xtrg, ValueType R0, const Vector& F_, const Kernel& ker, ValueType tol = 1e-18); /** * Compute modal Green's function operator using trapezoidal quadrature * rule (for distant target points). */ template void BuildOperatorModalDirect(Matrix& M, const Real x0, const Real x1, const Real x2, const Kernel& ker) const; Real R0_; FFT fft_Nm_R2C, fft_Nm_C2R; Matrix Mnds2coeff0, Mnds2coeff1; Vector U; // KDIM0*Nmm*KDIM1*Nr*Ntt Vector Ut; // Nr*Ntt*KDIM0*Nmm*KDIM1 }; /** * Implements the abstract class ElementListBase for slender boundary * elements with circular cross-section. * * @see ElementListBase */ template class SlenderElemList : public ElementListBase { static constexpr Integer FARFIELD_UPSAMPLE = 1; static constexpr Integer COORD_DIM = 3; static constexpr Integer ModalUpsample = 1; // toroidal quadrature order is FourierModes+ModalUpsample public: /** * Constructor */ SlenderElemList() {} /** * Constructor */ SlenderElemList(const Vector& cheb_order0, const Vector& fourier_order0, const Vector& coord0, const Vector& radius0, const Vector& orientation0 = Vector()); /** * Initialize list of elements */ void Init(const Vector& cheb_order0, const Vector& fourier_order0, const Vector& coord0, const Vector& radius0, const Vector& orientation0 = Vector()); /** * Destructor */ virtual ~SlenderElemList() {} /** * Return the number of elements in the list. */ Long Size() const; /** * Returns the position and normals of the surface nodal points for each * element. * * @see ElementListBase::GetNodeCoord() */ void GetNodeCoord(Vector* X, Vector* Xn, Vector* element_wise_node_cnt) const override; /** * Given an accuracy tolerance, returns the quadrature node positions, * the normals at the nodes, the weights and the cut-off distance from * the nodes for computing the far-field potential from the surface (at * target points beyond the cut-off distance). * * @see ElementListBase::GetFarFieldNodes() */ void GetFarFieldNodes(Vector& X, Vector& Xn, Vector& wts, Vector& dist_far, Vector& element_wise_node_cnt, const Real tol) const override; /** * Interpolates the density from surface node points to far-field * quadrature node points. * * @see ElementListBase::GetFarFieldDensity() */ void GetFarFieldDensity(Vector& Fout, const Vector& Fin) const override; /** * Apply the transpose of the GetFarFieldDensity() operator applied to * the column-vectors of Min and the result is returned in Mout. * * @see ElementListBase::FarFieldDensityOperatorTranspose() */ void FarFieldDensityOperatorTranspose(Matrix& Mout, const Matrix& Min, const Long elem_idx) const override; /** * Compute self-interaction operator for each element. * * @see ElementListBase::SelfInterac() */ template static void SelfInterac(Vector>& M_lst, const Kernel& ker, Real tol, bool trg_dot_prod, const ElementListBase* self); /** * Compute near-interaction operator for a given element-idx and each each target. * * @see ElementListBase::NearInterac() */ template static void NearInterac(Matrix& M, const Vector& Xtrg, const Vector& normal_trg, const Kernel& ker, Real tol, const Long elem_idx, const ElementListBase* self); /** * Returns the Chebyshev node points for a given order. */ static const Vector& CenterlineNodes(const Integer Order); /** * Write elements to file. */ void Write(const std::string& fname, const Comm& comm = Comm::Self()) const; /** * Read elements from file. */ void Read(const std::string& fname, const Comm& comm = Comm::Self()); /** * Get geometry data for an element. */ void GetGeom(Vector* X, Vector* Xn, Vector* Xa, Vector* dX_ds, Vector* dX_dt, const Vector& s_param, const Vector& sin_theta_, const Vector& cos_theta_, const Long elem_idx) const; /** * Get the VTU (Visualization Toolkit for Unstructured grids) data for * one or all elements. */ void GetVTUData(VTUData& vtu_data, const Vector& F = Vector(), const Long elem_idx = -1) const; /** * Write VTU data to file. */ void WriteVTK(const std::string& fname, const Vector& F = Vector(), const Comm& comm = Comm::Self()) const; /** * Test example for Laplace double-layer kernel. */ template static void test(const Comm& comm = Comm::Self(), Real tol = 1e-10); /** * Test example for Green's identity with Laplace kernel. */ static void test_greens_identity(const Comm& comm = Comm::Self(), Real tol = 1e-10); template void Copy(SlenderElemList& elem_lst) const; private: template Matrix SelfInteracHelper_(const Kernel& ker, const Long elem_idx, const Real tol) const; // constant radius template Matrix SelfInteracHelper(const Kernel& ker, const Long elem_idx) const; template void NearInteracHelper(Matrix& M, const Vector& Xtrg, const Vector& normal_trg, const Kernel& ker, const Long elem_idx) const; Vector radius, coord, e1; Vector cheb_order, fourier_order, elem_dsp; Vector dr, dx, d2x; // derived quantities }; } #include SCTL_INCLUDE(slender_element.txx) #endif //_SCTL_SLENDER_ELEMENT_HPP_