KADATH
domain_nucleus_symphi_filter.cpp
1 /*
2  Copyright 2017 Philippe Grandclement
3 
4  This file is part of Kadath.
5 
6  Kadath is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Kadath is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Kadath. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "headcpp.hpp"
21 #include "spheric_symphi.hpp"
22 #include "array_math.hpp"
23 #include "scalar.hpp"
24 #include "tensor_impl.hpp"
25 #include "tensor.hpp"
26 namespace Kadath {
27 void Domain_nucleus_symphi::filter_val_domain (Val_domain& so, double threshold) const {
28 
29  so.coef() ;
30  Index pos_cf (nbr_coefs) ;
31 
32  // Positions of the Galerkin basis
33  Index pos_gal_t (nbr_coefs) ;
34  Index pos_gal_r (nbr_coefs) ;
35  Index pos_gal_rt (nbr_coefs) ;
36  double fact_t, fact_r, fact_rt ;
37 
38 
39  int kmin, kmax ;
40  // Base in phi
41  int basep = (*so.get_base().bases_1d[2]) (0) ;
42  switch (basep) {
43  case COS_EVEN:
44  kmin = 0 ;
45  kmax = nbr_coefs(2)-1 ;
46  break ;
47  case COS_ODD:
48  kmin = 0 ;
49  kmax = nbr_coefs(2)-2 ;
50  break ;
51  case SIN_EVEN:
52  kmin = 1 ;
53  kmax = nbr_coefs(2)-2 ;
54  break ;
55  case SIN_ODD:
56  kmin = 0 ;
57  kmax = nbr_coefs(2)-2 ;
58  break ;
59  default:
60  cerr << "Unknow phi basis in Domain_nucleus_symphi::filter_val_domain" << endl ;
61  abort() ;
62  }
63 
64 
65 
66  int lquant ;
67  // Loop on phi :
68  for (int k=kmin ; k<=kmax ; k++) {
69 
70  pos_cf.set(2) = k ;
71 
72  int mquant ;
73  switch (basep) {
74  case COS_EVEN:
75  mquant = 2*k ;
76  break ;
77  case COS_ODD:
78  mquant = 2*k+1 ;
79  break ;
80  case SIN_EVEN:
81  mquant = 2*k ;
82  break ;
83  case SIN_ODD:
84  mquant = 2*k+1 ;
85  break ;
86  default:
87  cerr << "Unknow phi basis in Domain_nucleus_symphi::filter_val_domain" << endl ;
88  abort() ;
89  }
90 
91  // Loop on theta
92  int baset = (*so.get_base().bases_1d[1]) (k) ;
93  for (int j=0 ; j<nbr_coefs(1) ; j++) {
94  int baser = (*so.get_base().bases_1d[0]) (j, k) ;
95  pos_cf.set(1) = j ;
96  // Loop on r :
97  for (int i=0 ; i<nbr_coefs(0) ; i++) {
98  pos_cf.set(0) = i ;
99  switch (baset) {
100  case COS_EVEN :
101  lquant = 2*j ;
102  // No galerkin :
103  if ((mquant==0) && (lquant==0)) {
104  if (fabs((*so.cf)(pos_cf)) < threshold)
105  so.cf->set(pos_cf) = 0. ;
106  }
107  else if (mquant==0) {
108  if (i!=0) {
109  // Galerkin base in r only
110  pos_gal_r = pos_cf ;
111  pos_gal_r.set(0) = 0 ;
112  switch (baser) {
113  case CHEB_EVEN :
114  fact_r = - pow(-1, i) ;
115  break ;
116  case LEG_EVEN : {
117  fact_r = -1. ;
118  for (int t=0 ; t<i ; t++)
119  fact_r *= -double(2*t+1)/double(2*t+2) ;
120  }
121  break ;
122  default :
123  cerr << "Strange base in Domain_nucleus_symphi::filter_val_domain" << endl ;
124  abort() ;
125  }
126 
127  if (fabs((*so.cf)(pos_cf)) < threshold) {
128  so.cf->set(pos_gal_r) -= fact_r*(*so.cf)(pos_cf) ;
129  so.cf->set(pos_cf) = 0 ;
130  }
131  }
132  }
133  else if ((j!=0) && (i!=0)) {
134  // Need to use two_dimensional Galerkin basis (aouch !)
135  pos_gal_r = pos_cf ;
136  pos_gal_r.set(0) = 0 ;
137  pos_gal_t = pos_cf ;
138  pos_gal_t.set(1) = 0 ;
139  pos_gal_rt = pos_cf ;
140  pos_gal_rt.set(0) = 0 ;
141  pos_gal_rt.set(1) = 0 ;
142  switch (baser) {
143  case CHEB_EVEN :
144  fact_r = -pow(-1, i) ;
145  fact_t = -1. ;
146  fact_rt = pow(-1, i) ;
147  break ;
148  case LEG_EVEN : {
149  double l0 = 1 ;
150  for (int t=0 ; t<i ; t++)
151  l0 *= -double(2*t+1)/double(2*t+2) ;
152  fact_r = - l0 ;
153  fact_t = -1. ;
154  fact_rt = l0 ;
155  }
156  break ;
157  default :
158  cerr << "Strange base in Domain_nucleus_symphi::filter_val_domain" << endl ;
159  abort() ;
160  }
161  if (fabs((*so.cf)(pos_cf)) < threshold) {
162  so.cf->set(pos_gal_r) -= fact_r*(*so.cf)(pos_cf) ;
163  so.cf->set(pos_gal_t) -= fact_t*(*so.cf)(pos_cf) ;
164  so.cf->set(pos_gal_rt) -= fact_rt*(*so.cf)(pos_cf) ;
165  so.cf->set(pos_cf) = 0 ;
166  }
167  }
168  break ;
169  case COS_ODD:
170  lquant = 2*j+1 ;
171  if ((j!=nbr_coefs(1)-1) && (i!=nbr_coefs(0)-1)) {
172  if ((k==0) && (lquant<=1)) {
173  if (fabs((*so.cf)(pos_cf)) < threshold)
174  so.cf->set(pos_cf) = 0. ;
175  }
176  else {
177  if ((mquant==0) && (i!=0)) {
178  pos_gal_r = pos_cf ;
179  pos_gal_r.set(0) = 0 ;
180  switch (baser) {
181  case CHEB_ODD :
182  fact_r = - (2*i+1) * pow(-1, i) ;
183  break ;
184  case LEG_ODD : {
185  fact_r = -1. ;
186  for (int t=0 ; t<i ; t++)
187  fact_r *= -double(2*t+3)/double(2*t+2) ;
188  }
189  break ;
190  default :
191  cerr << "Strange base in Domain_nucleus_symphi::filter_val_domain" << endl ;
192  abort() ;
193  }
194 
195  if (fabs((*so.cf)(pos_cf)) < threshold) {
196  so.cf->set(pos_gal_r) -= fact_r*(*so.cf)(pos_cf) ;
197  so.cf->set(pos_cf) = 0 ;
198  }
199  }
200  else if ((j!=0) && (i!=0)) {
201  // Need to use two_dimensional Galerkin basis (aouch !)
202  pos_gal_r = pos_cf ;
203  pos_gal_r.set(0) = 0 ;
204  pos_gal_t = pos_cf ;
205  pos_gal_t.set(1) = 0 ;
206  pos_gal_rt = pos_cf ;
207  pos_gal_rt.set(0) = 0 ;
208  pos_gal_rt.set(1) = 0 ;
209  switch (baser) {
210  case CHEB_ODD :
211  fact_r = -pow(-1, i)*(2*i+1) ;
212  fact_t = -1. ;
213  fact_rt = pow(-1, i)*(2*i+1) ;
214  break ;
215  case LEG_ODD : {
216  double l0 = 1 ;
217  for (int t=0 ; t<i ; t++)
218  l0 *= -double(2*t+3)/double(2*t+2) ;
219  fact_r = - l0 ;
220  fact_t = -1. ;
221  fact_rt = l0 ;
222  }
223  break ;
224  default :
225  cerr << "Strange base in Domain_nucleus_symphi::filter_val_domain" << endl ;
226  abort() ;
227  }
228  if (fabs((*so.cf)(pos_cf)) < threshold) {
229  so.cf->set(pos_gal_r) -= fact_r*(*so.cf)(pos_cf) ;
230  so.cf->set(pos_gal_t) -= fact_t*(*so.cf)(pos_cf) ;
231  so.cf->set(pos_gal_rt) -= fact_rt*(*so.cf)(pos_cf) ;
232  so.cf->set(pos_cf) = 0 ;
233  }
234  }
235  }
236  }
237  break ;
238  case SIN_EVEN:
239  lquant = 2*j ;
240  if ((j!=0) && (j!=nbr_coefs(1)-1)) {
241  if ((mquant<=1) && (lquant==0)) {
242  if (fabs((*so.cf)(pos_cf)) < threshold)
243  so.cf->set(pos_cf) = 0. ;
244  }
245  else {
246  if ((mquant<=1) && (i!=0)) {
247  // Galerkin base in r only
248  pos_gal_r = pos_cf ;
249  pos_gal_r.set(0) = 0 ;
250  switch (baser) {
251  case CHEB_EVEN :
252  fact_r = - pow(-1, i) ;
253  break ;
254  case LEG_EVEN : {
255  fact_r = -1. ;
256  for (int t=0 ; t<i ; t++)
257  fact_r *= -double(2*t+1)/double(2*t+2) ;
258  }
259  break ;
260  default :
261  cerr << "Strange base in Domain_nucleus_symphi::filter_val_domain" << endl ;
262  abort() ;
263  }
264  if (fabs((*so.cf)(pos_cf)) < threshold) {
265  so.cf->set(pos_gal_r) -= fact_r*(*so.cf)(pos_cf) ;
266  so.cf->set(pos_cf) = 0 ;
267  }
268  }
269 
270  else //Double Galerkin
271  if ((j!=1) && (i!=0)) {
272  // Need to use two_dimensional Galerkin basis (aouch !)
273  pos_gal_r = pos_cf ;
274  pos_gal_r.set(0) = 0 ;
275  pos_gal_t = pos_cf ;
276  pos_gal_t.set(1) = 1 ;
277  pos_gal_rt = pos_cf ;
278  pos_gal_rt.set(0) = 0 ;
279  pos_gal_rt.set(1) = 1 ;
280  switch (baser) {
281  case CHEB_EVEN :
282  fact_r = -pow(-1, i) ;
283  fact_t = -j ;
284  fact_rt = pow(-1, i)*j ;
285  break ;
286  case LEG_EVEN : {
287  double l0 = 1 ;
288  for (int t=0 ; t<i ; t++)
289  l0 *= -double(2*t+1)/double(2*t+2) ;
290  fact_r = - l0 ;
291  fact_t = -j ;
292  fact_rt = l0*j ;
293  }
294  break ;
295  default :
296  cerr << "Strange base in Domain_nucleus_symphi::filter_val_domain" << endl ;
297  abort() ;
298  }
299  if (fabs((*so.cf)(pos_cf)) < threshold) {
300  so.cf->set(pos_gal_r) -= fact_r*(*so.cf)(pos_cf) ;
301  so.cf->set(pos_gal_t) -= fact_t*(*so.cf)(pos_cf) ;
302  so.cf->set(pos_gal_rt) -= fact_rt*(*so.cf)(pos_cf) ;
303  so.cf->set(pos_cf) = 0 ;
304  }
305  }
306  }
307  }
308 
309  break ;
310  case SIN_ODD:
311  lquant = 2*j+1 ;
312  if ((j!=nbr_coefs(1)-1) && (i!=nbr_coefs(0)-1)) {
313  if ((mquant<=1) && (lquant<=1)) {
314  if (fabs((*so.cf)(pos_cf)) < threshold)
315  so.cf->set(pos_cf) = 0. ;
316  }
317  else {
318  if ((mquant<=1) && (i!=0)) {
319  pos_gal_r = pos_cf ;
320  pos_gal_r.set(0) = 0 ;
321  switch (baser) {
322  case CHEB_ODD :
323  fact_r = - (2*i+1) * pow(-1, i) ;
324  break ;
325  case LEG_ODD : {
326  fact_r = -1. ;
327  for (int t=0 ; t<i ; t++)
328  fact_r *= -double(2*t+3)/double(2*t+2) ;
329  }
330  break ;
331  default :
332  cerr << "Strange base in Domain_nucleus_symphi::filter_val_domain" << endl ;
333  abort() ;
334  }
335  if (fabs((*so.cf)(pos_cf)) < threshold) {
336  so.cf->set(pos_gal_r) -= fact_r*(*so.cf)(pos_cf) ;
337  so.cf->set(pos_cf) = 0 ;
338  }
339  }
340  else if ((j!=0) && (i!=0)) {
341  // Need to use two_dimensional Galerkin basis (aouch !)
342  pos_gal_r = pos_cf ;
343  pos_gal_r.set(0) = 0 ;
344  pos_gal_t = pos_cf ;
345  pos_gal_t.set(1) = 0 ;
346  pos_gal_rt = pos_cf ;
347  pos_gal_rt.set(0) = 0 ;
348  pos_gal_rt.set(1) = 0 ;
349  switch (baser) {
350  case CHEB_ODD :
351  fact_r = -pow(-1, i)*(2*i+1) ;
352  fact_t = -(2*j+1) ;
353  fact_rt = pow(-1, i)*(2*i+1)*(2*j+1) ;
354  break ;
355  case LEG_ODD : {
356  double l0 = 1 ;
357  for (int t=0 ; t<i ; t++)
358  l0 *= -double(2*t+3)/double(2*t+2) ;
359  fact_r = - l0 ;
360  fact_t = -(2*j+1) ;
361  fact_rt = l0*(2*j+1) ;
362  }
363  break ;
364  default :
365  cerr << "Strange base in Domain_nucleus_symphi::filter_val_domain" << endl ;
366  abort() ;
367  }
368  if (fabs((*so.cf)(pos_cf)) < threshold) {
369  so.cf->set(pos_gal_r) -= fact_r*(*so.cf)(pos_cf) ;
370  so.cf->set(pos_gal_t) -= fact_t*(*so.cf)(pos_cf) ;
371  so.cf->set(pos_gal_rt) -= fact_rt*(*so.cf)(pos_cf) ;
372  so.cf->set(pos_cf) = 0 ;
373  }
374  }
375  }
376  }
377  break ;
378  default:
379  cerr << "Unknow theta basis in Domain_nucleus_symphi::filter_val_domain" << endl ;
380  abort() ;
381  }
382  }
383  }
384  }
385 }
386 
387 void Domain_nucleus_symphi::filter (Tensor& tt, int dom, double threshold) const {
388 
389  // Check right domain
390  assert (tt.get_space().get_domain(dom)==this) ;
391 
392  int val = tt.get_valence() ;
393  switch (val) {
394  case 0 :
395  filter_val_domain (tt.set().set_domain(dom), threshold) ;
396  break ;
397  case 1 : {
398  bool found = false ;
399  // Cartesian basis
400  if (tt.get_basis().get_basis(dom)==CARTESIAN_BASIS) {
401  filter_val_domain (tt.set(1).set_domain(dom), threshold) ;
402  filter_val_domain (tt.set(2).set_domain(dom), threshold) ;
403  filter_val_domain (tt.set(3).set_domain(dom), threshold) ;
404  found = true ;
405  }
406 
407  if (!found) {
408  cerr << "Unknown type of vector Domain_nucleus_symphi::filter" << endl ;
409  abort() ;
410  }
411  }
412  break ;
413  case 2 : {
414  bool found = false ;
415  // Cartesian basis and symetric
416  if ((tt.get_basis().get_basis(dom)==CARTESIAN_BASIS) && (tt.get_n_comp()==6)) {
417  filter_val_domain (tt.set(1,1).set_domain(dom), threshold) ;
418  filter_val_domain (tt.set(1,2).set_domain(dom), threshold) ;
419  filter_val_domain (tt.set(1,3).set_domain(dom), threshold) ;
420  filter_val_domain (tt.set(2,2).set_domain(dom), threshold) ;
421  filter_val_domain (tt.set(2,3).set_domain(dom), threshold) ;
422  filter_val_domain (tt.set(3,3).set_domain(dom), threshold) ;
423  found = true ;
424  }
425  // Cartesian basis and not symetric
426  if ((tt.get_basis().get_basis(dom)==CARTESIAN_BASIS) && (tt.get_n_comp()==9)) {
427  filter_val_domain (tt.set(1,1).set_domain(dom), threshold) ;
428  filter_val_domain (tt.set(1,2).set_domain(dom), threshold) ;
429  filter_val_domain (tt.set(1,3).set_domain(dom), threshold) ;
430  filter_val_domain (tt.set(2,1).set_domain(dom), threshold) ;
431  filter_val_domain (tt.set(2,2).set_domain(dom), threshold) ;
432  filter_val_domain (tt.set(2,3).set_domain(dom), threshold) ;
433  filter_val_domain (tt.set(3,1).set_domain(dom), threshold) ;
434  filter_val_domain (tt.set(3,2).set_domain(dom), threshold) ;
435  filter_val_domain (tt.set(3,3).set_domain(dom), threshold) ;
436  found = true ;
437  }
438  if (!found) {
439  cerr << "Unknown type of 2-tensor Domain_nucleus_symphi::filter" << endl ;
440  abort() ;
441  }
442  }
443  break ;
444  default :
445  cerr << "Valence " << val << " not implemented in Domain_nucleus_symphi::filter" << endl ;
446  break ;
447  }
448 }}
reference set(const Index &pos)
Read/write of an element.
Definition: array.hpp:186
Bases_container bases_1d
Arrays containing the various basis of decomposition.
int get_basis(int nd) const
Read only the basis in a given domain.
Definition: base_tensor.hpp:93
void filter_val_domain(Val_domain &so, double threshold) const
Sets to zero all the coefficients smaller than a given treshold.
virtual void filter(Tensor &tt, int dom, double threshold) const
Puts to zero all the coefficients below a given treshold.
Dim_array nbr_coefs
Number of coefficients.
Definition: space.hpp:66
Class that gives the position inside a multi-dimensional Array.
Definition: index.hpp:38
int & set(int i)
Read/write of the position in a given dimension.
Definition: index.hpp:72
Val_domain & set_domain(int)
Read/write of a particular Val_domain.
Definition: scalar.hpp:555
const Domain * get_domain(int i) const
returns a pointer on the domain.
Definition: space.hpp:1385
Tensor handling.
Definition: tensor.hpp:149
Scalar & set(const Array< int > &ind)
Returns the value of a component (read/write version).
Definition: tensor_impl.hpp:91
const Base_tensor & get_basis() const
Returns the vectorial basis (triad) on which the components are defined.
Definition: tensor.hpp:504
int get_n_comp() const
Returns the number of stored components.
Definition: tensor.hpp:514
int get_valence() const
Returns the valence.
Definition: tensor.hpp:509
const Space & get_space() const
Returns the Space.
Definition: tensor.hpp:499
Class for storing the basis of decompositions of a field and its values on both the configuration and...
Definition: val_domain.hpp:69
Array< double > * cf
Pointer on the Array of the values in the coefficients space.
Definition: val_domain.hpp:77
void coef() const
Computes the coefficients.
Definition: val_domain.cpp:622
const Base_spectral & get_base() const
Returns the basis of decomposition.
Definition: val_domain.hpp:122