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