WaveBEM: Unsteady Nonlinear Potential Flow Solver for Ship-Wave Interaction.
multipole_expansion.cc
Go to the documentation of this file.
1 #include <iostream>
2 
3 #include "multipole_expansion.h"
4 #include <deal.II/base/point.h>
5 
6 #define GSL_SIGN(x) (x<0 ? -1: (x>0 ? 1: 0))
7 
9 
11 
12 {
13 
14  this->p = 0;
15  this->center = Point<3>(0,0,0);
16  this->assLegFunction = NULL;
17  this->_M_n_m = NULL;
18  this->is_zero = true;
19 }
20 
21 
22 MultipoleExpansion::MultipoleExpansion(const unsigned int order, const dealii::Point<3> &center, const AssLegFunction *assLegFunction)
23 
24 {
25 
26  this->p = order;
27  this->center = center;
28  this->assLegFunction = assLegFunction;
29  this->_M_n_m= new std::complex <double>[(this->p+1)*(this->p+2)/2];
30  for (unsigned int i=0; i<(this->p+1)*(this->p+2)/2; ++i)
31  this->_M_n_m[i] = std::complex <double>(0.0,0.0);
32  this->is_zero = true;
33 
34 }
35 
37 {
38  this->p=other.p;
39  this->assLegFunction = other.assLegFunction;
40  this->center = other.center;
41  this->_M_n_m = new std::complex <double>[(this->p+1)*(this->p+2)/2];
42  memcpy(this->_M_n_m, other.GetCoeffs(), sizeof(std::complex <double>)*(this->p+1)*(this->p+2)/2);
43  this->is_zero = other.is_zero;
44 }
45 
46 
47 
49 {
50  this->p=other.p;
51  this->assLegFunction = other.assLegFunction;
52  this->center = other.center;
53  if (_M_n_m != NULL)
54  delete [] _M_n_m;
55  this->_M_n_m = new std::complex <double>[(this->p+1)*(this->p+2)/2];
56  memcpy(this->_M_n_m, other.GetCoeffs(), sizeof(std::complex <double>)*(this->p+1)*(this->p+2)/2);
57  this->is_zero = other.is_zero;
58  return *this;
59 }
60 
61 
63 {
64  if (_M_n_m != NULL)
65  delete [] _M_n_m;
66 }
67 
68 void MultipoleExpansion::Add(const MultipoleExpansion &multipole,const double sol)
69 
70 {
71  if (multipole.is_zero || sol==0)
72  {
73  }
74  else
75  {
76  this->is_zero = false;
77  for (int n = 0; n < int(this->p)+1 ; n++)
78  for (int m = 0; m < n + 1 ; m++)
79  {
80  std::complex <double> a = multipole.GetCoeff(n,m)*sol;
81  this->AddToCoeff(n,m,a);
82  }
83  }
84 
85 }
86 
87 void MultipoleExpansion::Add(const double strength, const dealii::Point<3> &point)
88 
89 {
90 
91  if (strength == 0)
92  {
93  }
94  else
95  {
96  this->is_zero = false;
97 
98  dealii::Point<3> pointRelPos = point + (-1.0*this->center);
99  double rho = sqrt(pointRelPos.square());
100  double cos_alpha_ = pointRelPos(2)/rho;
101  double beta = atan2(pointRelPos(1),pointRelPos(0));
102  double P_n_m;
103  for (int n = 0; n < int(this->p) + 1 ; n++)
104  {
105  for (int m = 0; m < n + 1 ; m++)
106  {
107  P_n_m = this->assLegFunction->GetAssLegFunSph(n,abs(m),cos_alpha_);
108  double realFact = P_n_m * pow(rho,double(n)) * strength;
109  std::complex <double> a = exp(std::complex<double>(0.,-m*beta))*realFact;
110  this->AddToCoeff(n,m,a);
111  }
112  }
113  }
114 
115 }
116 
117 void MultipoleExpansion::AddNormDer(const double strength, const dealii::Point<3> &point, const dealii::Tensor<1, 3> &normal)
118 
119 {
120  if (strength == 0)
121  {
122  }
123  else
124  {
125  this->is_zero = false;
126 
127  dealii::Point<3> pointRelPos = point + (-1.0*this->center);
128  dealii::Tensor<1,3> normVersor = normal/sqrt(normal[0]*normal[0]+normal[1]*normal[1]+normal[2]*normal[2]);//normal.square());
129  double rho = sqrt(pointRelPos.square());
130  double dRhodN = (pointRelPos/rho)*normVersor;
131  double beta = atan2(pointRelPos(1),pointRelPos(0));
132  double dBetadN = (dealii::Point<3>( -pointRelPos(1), pointRelPos(0), 0.)/(pow(pointRelPos(0),2.)+pow(pointRelPos(1),2.)))*normVersor;
133 
134  double cos_alpha_ = pointRelPos(2)/rho;
135  double dAlphadN = (dealii::Point<3>( cos_alpha_*cos(beta),cos_alpha_*sin(beta),-sqrt(1.-pow(cos_alpha_,2.)))/rho) * normVersor;
136 
137 
138  double P_n_m;
139  double dP_n_m_sin;
140  for (int n = 0; n < int(this->p) + 1 ; n++)
141  {
142  for (int m = 0; m < n + 1 ; m++)
143  {
144  P_n_m = this->assLegFunction->GetAssLegFunSph(n,abs(m),cos_alpha_);
145  dP_n_m_sin = this->assLegFunction->GetAssLegFunSphDeriv(n,abs(m),cos_alpha_)*sqrt(1-pow(cos_alpha_,2.));
146  std::complex <double> z = exp(std::complex <double>(0.,-double(m)*beta));
147  z *= std::complex <double> (double(n)*pow(rho,double(n)-1.)*P_n_m*dRhodN -
148  pow(rho,double(n))*dP_n_m_sin*dAlphadN, -double(m)*pow(rho,double(n))*P_n_m*dBetadN);
149  z*=strength;
150 
151  this->AddToCoeff(n,m,z);
152  }
153  }
154  }
155 
156 }
157 
158 
159 void MultipoleExpansion::Add(const MultipoleExpansion &other) //translation of a multipole to its parent center
160 
161 {
162  if (other.is_zero)
163  {
164  this->is_zero = this->is_zero & other.is_zero;
165  }
166  else
167  {
168  this->is_zero = false;
169  FullMatrix<double> &A_n_m = this->GetA_n_m();
170  if (other.center.distance(this->center) > 1e-7)
171  {
172 
173  dealii::Point<3> blockRelPos = other.center + (-1.0*this->center);
174  double rho = sqrt(blockRelPos.square());
175  double cos_alpha_ = blockRelPos(2)/rho;
176  double beta = atan2(blockRelPos(1),blockRelPos(0));
177 
178  std::complex <double> imUnit(0.,1.);
179 
180  double P_nn_mm;
181 
182  for (int n = 0; n < int(this->p)+1 ; n++)
183  {
184  for (int m = 0; m < n+1 ; m++)
185  {
186  std::complex <double> z(0.,0.);
187  for (int nn = 0; nn < n+1 ; nn++)
188  {
189  for (int mm = -1*nn; mm < nn+1 ; mm++)
190  {
191  if (abs(m-mm) > n-nn)
192  {
193  }
194  else
195  {
196  std::complex <double> a = std::complex<double>((other.GetCoeff(abs(n-nn),abs(m-mm))).real(),GSL_SIGN(m-mm)*
197  (other.GetCoeff(abs(n-nn),abs(m-mm))).imag());
198  P_nn_mm = this->assLegFunction->GetAssLegFunSph(nn,abs(mm),cos_alpha_);
199  double realFact = P_nn_mm * pow(rho,double(nn)) * A_n_m(abs(nn),abs(mm)) *
200  A_n_m(abs(n-nn),abs(m-mm)) / A_n_m(abs(n),abs(m));
201  realFact *= (pow(imUnit, double(abs(m)-abs(mm)-abs(m-mm)))).real();
202  z += realFact*(a*exp(std::complex <double>(0.,-mm*beta)));
203  }
204  }
205  }
206  this->AddToCoeff(n,m,z);
207  }
208  }
209  }
210  else
211  {
212  for (int n = 0; n < int(this->p)+1 ; n++)
213  {
214  for (int m = 0; m < n+1 ; m++)
215  {
216  this->AddToCoeff(n,m,other.GetCoeff(n,m));
217  }
218  }
219  }
220  }
221 }
222 
223 
224 double MultipoleExpansion::Evaluate(const dealii::Point<3> &evalPoint)
225 
226 {
227  std::complex <double> fieldValue(0.,0.);
228  if (this->is_zero)
229  {
230  }
231  else
232  {
233  dealii::Point<3> blockRelPos = evalPoint + (-1.0*this->center);
234  double rho = sqrt(blockRelPos.square());
235  double cos_alpha_ = blockRelPos(2)/rho;
236  double beta = atan2(blockRelPos(1),blockRelPos(0));
237 
238  double P_n_m;
239 
240  for (int n = 0; n < int(this->p)+1 ; n++)
241  {
242  P_n_m = this->assLegFunction->GetAssLegFunSph(n,0,cos_alpha_);
243  double realFact = P_n_m * pow(rho,double(-n-1));
244  fieldValue += this->GetCoeff(n, 0)*realFact;
245  for (int m = 1; m < n + 1 ; m++)
246  {
247  P_n_m = this->assLegFunction->GetAssLegFunSph(n,abs(m),cos_alpha_);
248  double realFact = P_n_m * pow(rho,double(-n-1));
249  fieldValue += this->GetCoeff(n, m)*exp(std::complex <double>(0., m*beta))*2.*realFact;
250  }
251  }
252  }
253  return fieldValue.real();
254 
255 }
#define GSL_SIGN(x)
double GetAssLegFunSphDeriv(const unsigned int n, const unsigned int m, double x) const
std::complex< double > & GetCoeff(unsigned int n, unsigned int m) const
FullMatrix< double > & GetA_n_m() const
MultipoleExpansion & operator=(const MultipoleExpansion &other)
void AddToCoeff(unsigned int n, unsigned int m, std::complex< double > &value) const
std::complex< double > * GetCoeffs() const
double GetAssLegFunSph(const unsigned int n, const unsigned int m, double x) const
dealii::Point< 3 > center
void Add(const MultipoleExpansion &multipole, const double sol)
const AssLegFunction * assLegFunction
std::complex< double > * _M_n_m
void AddNormDer(const double strength, const dealii::Point< 3 > &point, const dealii::Tensor< 1, 3 > &normal)
static FullMatrix< double > A_n_m_Matrix(unsigned int dim)
double Evaluate(const dealii::Point< 3 > &evalPoint)
static FullMatrix< double > A_n_m