LORENE
poisson_compact.C
1/*
2 * Copyright (c) 2000-2006 Philippe Grandclement
3 * Copyright (c) 2007 Michal Bejger
4 * Copyright (c) 2007 Eric Gourgoulhon
5 *
6 * This file is part of LORENE.
7 *
8 * LORENE is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * LORENE is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with LORENE; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24
25
26
27/*
28 * $Id: poisson_compact.C,v 1.8 2018/11/16 14:34:36 j_novak Exp $
29 * $Log: poisson_compact.C,v $
30 * Revision 1.8 2018/11/16 14:34:36 j_novak
31 * Changed minor points to avoid some compilation warnings.
32 *
33 * Revision 1.7 2016/12/05 16:18:09 j_novak
34 * Suppression of some global variables (file names, loch, ...) to prevent redefinitions
35 *
36 * Revision 1.6 2014/10/13 08:53:29 j_novak
37 * Lorene classes and functions now belong to the namespace Lorene.
38 *
39 * Revision 1.5 2014/10/06 15:16:09 j_novak
40 * Modified #include directives to use c++ syntax.
41 *
42 * Revision 1.4 2007/10/16 21:54:23 e_gourgoulhon
43 * Added new function sol_poisson_compact (multi-domain version).
44 *
45 * Revision 1.3 2006/09/05 13:39:46 p_grandclement
46 * update of the bin_ns_bh project
47 *
48 * Revision 1.2 2002/10/16 14:37:12 j_novak
49 * Reorganization of #include instructions of standard C++, in order to
50 * use experimental version 3 of gcc.
51 *
52 * Revision 1.1.1.1 2001/11/20 15:19:28 e_gourgoulhon
53 * LORENE
54 *
55 * Revision 2.2 2000/03/16 16:28:06 phil
56 * Version entirement revue et corrigee
57 *
58 * Revision 2.1 2000/03/09 13:51:55 phil
59 * *** empty log message ***
60 *
61 * Revision 2.0 2000/03/09 13:44:56 phil
62 * *** empty log message ***
63 *
64 *
65 * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_compact.C,v 1.8 2018/11/16 14:34:36 j_novak Exp $
66 *
67 */
68
69// Headers C
70#include <cstdlib>
71#include <cmath>
72#include <cassert>
73
74// Headers Lorene
75#include "map.h"
76#include "diff.h"
77#include "matrice.h"
78#include "type_parite.h"
79#include "proto.h"
80#include "base_val.h"
81#include "utilitaires.h"
82
84 // Single domain version //
86
87/*
88 * Cette fonction resout, dans le noyau :
89 * a*(1-xi^2)*lap(uu)+b*xi*duu/dxi = source
90 * avec a>0 et b<0 ;
91 * Pour le stokage des operateurs, il faut faire reamorce = true au
92 * debut d'un nouveau calcul.
93 */
94
95namespace Lorene {
96Mtbl_cf sol_poisson_compact(const Mtbl_cf& source, double a, double b,
97 bool reamorce) {
98
99 // Verifications :
100 assert (source.get_etat() != ETATNONDEF) ;
101
102 assert (a>0) ;
103 assert (b<0) ;
104
105 // Les tableaux de stockage :
106 const int nmax = 200 ;
107 static Matrice* tab_op[nmax] ;
108 static int nb_deja_fait = 0 ;
109 static int l_deja_fait[nmax] ;
110 static int n_deja_fait[nmax] ;
111
112 if (reamorce) {
113 for (int i=0 ; i<nb_deja_fait ; i++)
114 delete tab_op[i] ;
115 nb_deja_fait = 0 ;
116 }
117
118 int nz = source.get_mg()->get_nzone() ;
119
120 // Pour le confort (on ne travaille que dans le noyau) :
121 int nr = source.get_mg()->get_nr(0) ;
122 int nt = source.get_mg()->get_nt(0) ;
123 int np = source.get_mg()->get_np(0) ;
124
125 int l_quant ;
126 int m_quant ;
127 int base_r ;
128
129 // La solution ...
130 Mtbl_cf solution(source.get_mg(), source.base) ;
131 solution.set_etat_qcq() ;
132 solution.t[0]->set_etat_qcq() ;
133
134 for (int k=0 ; k<np+1 ; k++)
135 for (int j=0 ; j<nt ; j++)
136 if (nullite_plm(j, nt, k, np, source.base) == 1)
137 {
138 // calcul des nombres quantiques :
139 donne_lm(nz, 0, j, k, source.base, m_quant, l_quant, base_r) ;
140
141
142 //On gere le cas l_quant == 0 (c'est bien simple y'en a pas !)
143 if (l_quant == 0) {
144 for (int i=0 ; i<nr ; i++)
145 solution.set(0, k, j, i) = 0 ;
146 }
147
148 // cas l_quant != 0
149 else {
150 // On determine si la matrice a deja ete calculee :
151 int indice = -1 ;
152
153 // Le cas l==1 est non singulier : pas de base de Gelerkin
154 int taille = (l_quant == 1) ? nr : nr-1 ;
155
156 Matrice operateur (taille, taille) ;
157 for (int conte=0 ; conte<nb_deja_fait ; conte++)
158 if ((l_deja_fait[conte]== l_quant) && (n_deja_fait[conte] == nr))
159 indice = conte ;
160
161 if (indice == -1) {
162 if (nb_deja_fait >= nmax) {
163 cout << "sol_poisson_compact : trop de matrices ..." << endl;
164 abort() ;
165 }
166 // Calcul a faire :
167 operateur = a*lap_cpt_mat (nr, l_quant, base_r)
168 + b*xdsdx_mat(nr, l_quant, base_r) ;
169 operateur = combinaison_cpt (operateur, l_quant, base_r) ;
170
171 l_deja_fait[nb_deja_fait] = l_quant ;
172 n_deja_fait[nb_deja_fait] = nr ;
173 tab_op[nb_deja_fait] = new Matrice(operateur) ;
174
175 nb_deja_fait++ ;
176 }
177 else {
178 // rien a faire :
179 operateur = *tab_op[indice] ;
180 }
181
182 // La source :
183 Tbl so(taille) ;
184 so.set_etat_qcq() ;
185 for (int i=0 ; i<taille ; i++)
186 so.set(i) = source(0, k, j, i) ;
187 so = combinaison_cpt (so, base_r) ;
188
189 Tbl part (operateur.inverse(so)) ;
190
191 if (taille == nr)
192 for (int i=0 ; i<nr ; i++)
193 solution.set(0, k, j, i) = part(i) ; // cas l==1
194 else {
195 solution.set(0, k, j, nr-1) = 0 ;
196 for (int i=nr-2 ; i>=0 ; i--)
197 if (base_r == R_CHEBP) { //Gelerkin pair
198 solution.set(0, k, j, i) = part(i) ;
199 solution.set(0, k, j, i+1) += part(i) ;
200 }
201 else { //Gelerkin impaire
202 solution.set(0, k, j, i) = part(i)*(2*i+3) ;
203 solution.set(0, k, j, i+1) += part(i)*(2*i+1) ;
204 }
205 }
206 }
207 }
208 else // cas ou nullite_plm = 0 :
209 for (int i=0 ; i<nr ; i++)
210 solution.set(0, k, j, i) = 0 ;
211
212 // Mise a zero du coefficient (inusite) k=np+1
213 for (int j=0; j<nt; j++)
214 for(int i=0 ; i<nr ; i++)
215 solution.set(0, np+1, j, i) = 0 ;
216
217 for (int zone=1 ; zone<nz ; zone++)
218 solution.t[zone]->set_etat_zero() ;
219
220 return solution ;
221}
222
223
224
226 // Multi domain version //
228
229
230Mtbl_cf sol_poisson_compact(const Map_af& mapping, const Mtbl_cf& source,
231 const Tbl& ac, const Tbl& bc, bool ) {
232
233 // Number of domains inside the star :
234 int nzet = ac.get_dim(1) ;
235 assert(nzet<=source.get_mg()->get_nzone()) ;
236
237 // Some checks
238 assert (source.get_mg()->get_type_r(0) == RARE) ;
239 for (int l=1 ; l<nzet ; l++)
240 assert(source.get_mg()->get_type_r(l) == FIN) ;
241
242 // Spectral bases
243 const Base_val& base = source.base ;
244
245 // Result
246 Mtbl_cf resultat(source.get_mg(), base) ;
247 resultat.annule_hard() ;
248
249 // donnees sur la zone
250 int nr, nt, np ;
251 int base_r ;
252 double alpha, beta, echelle ;
253 int l_quant, m_quant;
254
255 // Determination of the size of the systeme :
256 int size = 0 ;
257 int max_nr = 0 ;
258 for (int l=0 ; l<nzet ; l++) {
259 nr = mapping.get_mg()->get_nr(l) ;
260 size += nr ;
261 if (nr > max_nr) max_nr = nr ;
262 }
263
264 Matrice systeme (size, size) ;
265 systeme.set_etat_qcq() ;
266 Tbl sec_membre (size) ;
267 Tbl soluce (size) ;
268 soluce.set_etat_qcq() ;
269
270 np = mapping.get_mg()->get_np(0) ;
271 nt = mapping.get_mg()->get_nt(0) ;
272 Matrice* work ;
273
274 // On bosse pour chaque l, m :
275 for (int k=0 ; k<np+1 ; k++)
276 for (int j=0 ; j<nt ; j++)
277 if (nullite_plm(j, nt, k, np, base) == 1) {
278
279 systeme.annule_hard() ;
280 sec_membre.annule_hard() ;
281
282 int column_courant = 0 ;
283 int ligne_courant = 0 ;
284
285 //--------------------------
286 // NUCLEUS
287 //--------------------------
288
289 nr = mapping.get_mg()->get_nr(0) ;
290 alpha = mapping.get_alpha()[0] ;
291 base.give_quant_numbers (0, k, j, m_quant, l_quant, base_r) ;
292
293 if (l_quant == 0) {
294 for (int i=0 ; i<size ; i++)
295 soluce.set(i) = 0 ;
296 }
297 else {
298
299 Diff_dsdx2 d2_n(base_r, nr) ; // suffix _n stands for "nucleus"
300 Diff_sxdsdx sxd_n(base_r, nr) ;
301 Diff_sx2 sx2_n(base_r, nr) ;
302 Diff_x2dsdx2 x2d2_n(base_r,nr) ;
303 Diff_xdsdx xd_n(base_r,nr) ;
304 Diff_id id_n(base_r,nr) ;
305
306 work = new Matrice( ac(0,0) * ( d2_n + 2.*sxd_n -l_quant*(l_quant+1)*sx2_n )
307 + ac(0,2) * ( x2d2_n + 2.*xd_n -l_quant*(l_quant+1)*id_n )
308 + alpha * bc(0,1) * xd_n ) ;
309
310 // cout << *work << endl ;
311 // arrete() ;
312
313 // regularity conditions :
314 int nbr_cl = 0 ;
315 if (l_quant > 1) {
316 nbr_cl = 1 ;
317 if (l_quant%2==0) {
318 //Even case
319 for (int col=0 ; col<nr ; col++)
320 if (col%2==0)
321 systeme.set(ligne_courant, col+column_courant) = 1 ;
322 else
323 systeme.set(ligne_courant, col+column_courant) = -1 ;
324 }
325 else {
326 //Odd case
327 for (int col=0 ; col<nr ; col++)
328 if (col%2==0)
329 systeme.set(ligne_courant, col+column_courant) = 2*col+1 ;
330 else
331 systeme.set(ligne_courant, col+column_courant) = -(2*col+1) ;
332 }
333 ligne_courant ++ ;
334 }
335
336 // L'operateur :
337 for (int lig=0 ; lig<nr-1-nbr_cl ; lig++) {
338 for (int col=0 ; col<nr ; col++)
339 systeme.set(lig+ligne_courant,col+column_courant) = (*work)(lig,col) ;
340 sec_membre.set(lig+ligne_courant) = alpha*alpha*source(0, k, j, lig) ;
341 }
342
343 delete work ;
344 ligne_courant += nr-1-nbr_cl ;
345
346 // Le raccord :
347 for (int col=0 ; col<nr ; col++) {
348 // La fonction
349 systeme.set(ligne_courant, col+column_courant) = 1 ;
350 // Sa dérivée :
351 if (l_quant%2==0)
352 systeme.set(ligne_courant+1, col+column_courant) = 4*col*col/alpha ;
353 else
354 systeme.set(ligne_courant+1, col+column_courant) = (2*col+1)*(2*col+1)/alpha ;
355 }
356 column_courant += nr ;
357
358 //--------------------------
359 // SHELLS
360 //--------------------------
361
362 for (int l=1 ; l<nzet ; l++) {
363
364 nr = mapping.get_mg()->get_nr(l) ;
365 alpha = mapping.get_alpha()[l] ;
366 beta = mapping.get_beta()[l] ;
367 echelle = beta/alpha ;
368 double bsa = echelle ;
369 double bsa2 = bsa*bsa ;
370
371 base.give_quant_numbers (l, k, j, m_quant, l_quant, base_r) ;
372
373 Diff_dsdx dx(base_r, nr) ;
374 Diff_xdsdx xdx(base_r, nr) ;
375 Diff_x2dsdx x2dx(base_r, nr) ;
376 Diff_x3dsdx x3dx(base_r, nr) ;
377 Diff_dsdx2 dx2(base_r, nr) ;
378 Diff_xdsdx2 xdx2(base_r, nr) ;
379 Diff_x2dsdx2 x2dx2(base_r, nr) ;
380 Diff_x3dsdx2 x3dx2(base_r, nr) ;
381 Diff_id id(base_r,nr) ;
382 Diff_mx mx(base_r,nr) ;
383
384 work = new Matrice ( ac(l,0) * ( x2dx2 + 2.*bsa*xdx2 + bsa2*dx2 + 2.*xdx
385 + 2.*bsa*dx - l_quant*(l_quant+1)*id )
386 + ac(l,1) * ( x3dx2 + 2.*bsa*x2dx2 + bsa2*xdx2 + 2.*x2dx
387 + 2.*bsa*xdx - l_quant*(l_quant+1) *mx )
388 + alpha * ( bc(l,0) * ( x2dx + 2.*bsa*xdx + bsa2*dx )
389 + bc(l,1) * ( x3dx + 2.*bsa*x2dx + bsa2*xdx ) ) ) ;
390
391 // matching with previous domain :
392 for (int col=0 ; col<nr ; col++) {
393 // La fonction
394 if (col%2==0)
395 systeme.set(ligne_courant, col+column_courant) = -1 ;
396 else
397 systeme.set(ligne_courant, col+column_courant) = 1 ;
398 // Sa dérivée :
399 if (col%2==0)
400 systeme.set(ligne_courant+1, col+column_courant) = col*col/alpha ;
401 else
402 systeme.set(ligne_courant+1, col+column_courant) = -col*col/alpha ;
403 }
404 ligne_courant += 2 ;
405
406 // source must be multiplied by (x+echelle)^2
407 Tbl source_aux(nr) ;
408 source_aux.set_etat_qcq() ;
409 for (int i=0 ; i<nr ; i++)
410 source_aux.set(i) = source(l,k,j,i)*alpha*alpha ;
411 Tbl xso(source_aux) ;
412 Tbl xxso(source_aux) ;
413 multx_1d(nr, &xso.t, R_CHEB) ;
414 multx_1d(nr, &xxso.t, R_CHEB) ;
415 multx_1d(nr, &xxso.t, R_CHEB) ;
416 source_aux = beta*beta/alpha/alpha*source_aux+2*beta/alpha*xso+xxso ;
417
418 // L'operateur :
419
420 for (int lig=0 ; lig<nr-1 ; lig++) {
421 for (int col=0 ; col<nr ; col++)
422 systeme.set(lig+ligne_courant,col+column_courant) = (*work)(lig,col) ;
423 sec_membre.set(lig+ligne_courant) = source_aux(lig) ;
424 }
425
426 // cout << *work << endl ;
427 // arrete() ;
428
429 delete work ;
430 ligne_courant += nr-2 ;
431
432 if (l<nzet-1) { // if this not the last shell
433 // matching with the next domain
434 for (int col=0 ; col<nr ; col++) {
435 // La fonction
436 systeme.set(ligne_courant, col+column_courant) = 1 ;
437 // Sa dérivée :
438 systeme.set(ligne_courant+1, col+column_courant) = col*col/alpha ;
439 }
440 }
441
442 column_courant += nr ;
443
444 } // end loop on the shells (index l)
445
446 // cout << "systeme : " << systeme << endl ;
447 // arrete() ;
448
449 // Solving the system:
450
451 systeme.set_band (size, size) ;
452 systeme.set_lu() ;
453
454 // cout << "Determinant: " << systeme.determinant() << endl ;
455 // cout << "Eigenvalues: " << systeme.val_propre() << endl ;
456
457 soluce = systeme.inverse(sec_membre) ;
458
459 } // end case l_quant != 0
460
461 // cout << "soluce: " << soluce << endl ;
462 // arrete() ;
463
464 // On range :
465 int conte = 0 ;
466 for (int l=0 ; l<nzet ; l++) {
467 nr = mapping.get_mg()->get_nr(l) ;
468 for (int i=0 ; i<nr ; i++) {
469 resultat.set(l,k,j,i) = soluce(conte) ;
470 conte++ ;
471 }
472 }
473
474 } // end case nullite_plm == 1
475
476 return resultat ;
477
478}
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494}
Bases of the spectral expansions.
Definition base_val.h:325
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:172
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:129
Class for the elementary differential operator Identity (see the base class Diff ).
Definition diff.h:210
Class for the elementary differential operator multiplication by (see the base class Diff ).
Definition diff.h:250
Class for the elementary differential operator division by (see the base class Diff ).
Definition diff.h:369
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:450
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:490
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:571
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:652
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:611
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:531
Class for the elementary differential operator (see the base class Diff ).
Definition diff.h:409
Affine radial mapping.
Definition map.h:2042
Matrix handling.
Definition matrice.h:152
Coefficients storage for the multi-domain spectral method.
Definition mtbl_cf.h:196
Basic array class.
Definition tbl.h:161
#define R_CHEB
base de Chebychev ordinaire (fin)
#define R_CHEBP
base de Cheb. paire (rare) seulement
Lorene prototypes.
Definition app_hor.h:67