et_rot_mag_mag.C

00001 /*
00002  * Computes magnetic fields and derived quantities for rotating equilibrium
00003  *
00004  * (see file et_rot_mag.h for documentation)
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2002 Emmanuel Marcq
00010  *   Copyright (c) 2002 Jerome Novak
00011  *
00012  *   This file is part of LORENE.
00013  *
00014  *   LORENE is free software; you can redistribute it and/or modify
00015  *   it under the terms of the GNU General Public License as published by
00016  *   the Free Software Foundation; either version 2 of the License, or
00017  *   (at your option) any later version.
00018  *
00019  *   LORENE is distributed in the hope that it will be useful,
00020  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  *   GNU General Public License for more details.
00023  *
00024  *   You should have received a copy of the GNU General Public License
00025  *   along with LORENE; if not, write to the Free Software
00026  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00027  *
00028  */
00029 
00030 char et_rot_mag_mag_C[] = "$Header: /cvsroot/Lorene/C++/Source/Etoile/et_rot_mag_mag.C,v 1.14 2005/06/03 15:31:56 j_novak Exp $" ;
00031 
00032 /*
00033  * $Id: et_rot_mag_mag.C,v 1.14 2005/06/03 15:31:56 j_novak Exp $
00034  * $Log: et_rot_mag_mag.C,v $
00035  * Revision 1.14  2005/06/03 15:31:56  j_novak
00036  * Better computation when more than one point in phi.
00037  *
00038  * Revision 1.13  2003/10/03 15:58:47  j_novak
00039  * Cleaning of some headers
00040  *
00041  * Revision 1.12  2002/09/09 13:00:39  e_gourgoulhon
00042  * Modification of declaration of Fortran 77 prototypes for
00043  * a better portability (in particular on IBM AIX systems):
00044  * All Fortran subroutine names are now written F77_* and are
00045  * defined in the new file C++/Include/proto_f77.h.
00046  *
00047  * Revision 1.11  2002/06/05 15:15:59  j_novak
00048  * The case of non-adapted mapping is treated.
00049  * parmag.d and parrot.d have been merged.
00050  *
00051  * Revision 1.10  2002/06/03 13:23:16  j_novak
00052  * The case when the mapping is not adapted is now treated
00053  *
00054  * Revision 1.9  2002/06/03 13:00:45  e_marcq
00055  *
00056  * conduc parameter read in parmag.d
00057  *
00058  * Revision 1.7  2002/05/20 10:31:59  j_novak
00059  * *** empty log message ***
00060  *
00061  * Revision 1.6  2002/05/17 15:08:01  e_marcq
00062  *
00063  * Rotation progressive plug-in, units corrected, Q and a_j new member data
00064  *
00065  * Revision 1.5  2002/05/16 10:02:09  j_novak
00066  * Errors in stress energy tensor corrected
00067  *
00068  * Revision 1.4  2002/05/15 09:54:00  j_novak
00069  * First operational version
00070  *
00071  * Revision 1.3  2002/05/14 13:38:36  e_marcq
00072  *
00073  *
00074  * Unit update, new outputs
00075  *
00076  * Revision 1.1  2002/05/10 09:26:52  j_novak
00077  * Added new class Et_rot_mag for magnetized rotating neutron stars (under development)
00078  *
00079  *
00080  * $Header: /cvsroot/Lorene/C++/Source/Etoile/et_rot_mag_mag.C,v 1.14 2005/06/03 15:31:56 j_novak Exp $
00081  *
00082  */
00083 
00084 // Headers C
00085 #include <stdlib.h>
00086 #include <math.h>
00087 
00088 // Headers Lorene
00089 #include "et_rot_mag.h"
00090 #include "utilitaires.h"
00091 #include "param.h"
00092 #include "proto_f77.h"
00093 
00094 // Algo du papier de 1995
00095 
00096 void Et_rot_mag::magnet_comput(const int adapt_flag,
00097                    Cmp (*f_j)(const Cmp&, const double), 
00098                    Param& par_poisson_At, 
00099                    Param& par_poisson_Avect){
00100   double relax_mag = 0.5 ;
00101 
00102   int Z = mp.get_mg()->get_nzone();
00103 
00104   if(is_conduct()) {
00105     bool adapt(adapt_flag) ;
00106     /****************************************************************
00107      *  Assertion that all zones have same number of points in theta
00108      ****************************************************************/
00109     int nt = mp.get_mg()->get_nt(nzet-1) ; 
00110     for (int l=0; l<Z; l++) assert(mp.get_mg()->get_nt(l) == nt) ;
00111 
00112     Tbl Rsurf(nt) ;
00113     Rsurf.set_etat_qcq() ;
00114     mp.r.fait() ;
00115     mp.tet.fait() ;
00116     Mtbl* theta = mp.tet.c ;
00117     const Map_radial* mpr = dynamic_cast<const Map_radial*>(&mp) ;
00118     assert (mpr != 0x0) ;
00119     for (int j=0; j<nt; j++) 
00120       Rsurf.set(j) = mpr->val_r_jk(l_surf()(0,j), xi_surf()(0,j), j, 0) ;
00121 
00122 
00123     // Calcul de A_0t dans l'etoile (conducteur parfait)
00124 
00125     Cmp A_0t(- omega * A_phi) ;
00126     A_0t.annule(nzet,Z-1) ;
00127  
00128     Tenseur ATTENS(A_t) ; 
00129     Tenseur APTENS(A_phi) ;
00130     Tenseur BMN(-logn) ;
00131     BMN =  BMN + log(bbb) ;
00132     BMN.set_std_base() ;
00133 
00134 
00135     Cmp grad1(flat_scalar_prod_desal(ATTENS.gradient_spher(),
00136                      nphi.gradient_spher())());
00137     Cmp grad2(flat_scalar_prod_desal(APTENS.gradient_spher(),
00138                      nphi.gradient_spher())()) ;
00139     Cmp grad3(flat_scalar_prod_desal(ATTENS.gradient_spher(),
00140                      BMN.gradient_spher())()
00141           + 2*nphi()*flat_scalar_prod_desal(APTENS.gradient_spher(),
00142                         BMN.gradient_spher())()) ;
00143 
00144     Cmp ATANT(A_phi.srdsdt()); // Constrction par copie pour mapping
00145 
00146     ATANT.va = ATANT.va.mult_ct().ssint() ;
00147 
00148     Cmp ttnphi(tnphi()) ;
00149     ttnphi.mult_rsint() ;
00150     Cmp BLAH(- b_car()/(nnn()*nnn())*ttnphi*grad1)  ;
00151     BLAH -= (1+b_car()/(nnn()*nnn())*tnphi()*tnphi())*grad2  ;
00152     Cmp nphisr(nphi()) ;
00153     nphisr.div_r() ;
00154     Cmp npgrada(2*nphisr*(A_phi.dsdr()+ATANT )) ;
00155     npgrada.inc2_dzpuis() ;
00156     BLAH -=  grad3 + npgrada ;
00157     Cmp gtt(-nnn()*nnn()+b_car()*tnphi()*tnphi()) ;
00158     Cmp gtphi( - b_car()*ttnphi) ;
00159 
00160     // Calcul de j_t grace a Maxwell-Gauss
00161     Cmp tmp(((BLAH - A_0t.laplacien())/a_car() - gtphi*j_phi)
00162         / gtt);
00163     tmp.annule(nzet, Z-1) ;
00164     if (adapt) {
00165       j_t = tmp ;
00166     }
00167     else {
00168       j_t.allocate_all() ;
00169       for (int j=0; j<nt; j++) 
00170     for (int l=0; l<nzet; l++) 
00171       for (int i=0; i<mp.get_mg()->get_nr(l); i++) 
00172         j_t.set(l,0,j,i) = ( (*mp.r.c)(l,0,j,i) > Rsurf(j) ?
00173                  0. : tmp(l,0,j,i) ) ;
00174       j_t.annule(nzet,Z-1) ;
00175     }
00176     j_t.std_base_scal() ;
00177 
00178     // Calcul du courant j_phi
00179     j_phi = omega * j_t + (ener() + press())*f_j(A_phi, a_j) ;
00180     j_phi.std_base_scal() ;
00181 
00182     // Resolution de Maxwell Ampere (-> A_phi)
00183     // Calcul des termes sources avec A-t du pas precedent.
00184 
00185     Cmp grad4(flat_scalar_prod_desal(APTENS.gradient_spher(),
00186                      BMN.gradient_spher())());
00187 
00188     Tenseur source_tAphi(mp, 1, CON, mp.get_bvect_spher()) ;
00189 
00190     source_tAphi.set_etat_qcq() ;
00191     Cmp tjphi(j_phi) ;
00192     tjphi.mult_rsint() ;
00193     Cmp tgrad1(grad1) ;
00194     tgrad1.mult_rsint() ;
00195     Cmp d_grad4(grad4) ;
00196     d_grad4.div_rsint() ;
00197     source_tAphi.set(0)=0 ;
00198     source_tAphi.set(1)=0 ;
00199     source_tAphi.set(2)= -b_car()*a_car()*(tjphi-tnphi()*j_t)
00200       + b_car()/(nnn()*nnn())*(tgrad1+tnphi()*grad2)+d_grad4 ;
00201 
00202     source_tAphi.change_triad(mp.get_bvect_cart());
00203 
00204     Tenseur WORK_VECT(mp, 1, CON, mp.get_bvect_cart()) ;
00205     WORK_VECT.set_etat_qcq() ;
00206     for (int i=0; i<3; i++) {
00207       WORK_VECT.set(i) = 0 ; 
00208     }
00209     Tenseur WORK_SCAL(mp) ;
00210     WORK_SCAL.set_etat_qcq() ;
00211     WORK_SCAL.set() = 0 ;
00212   
00213     double lambda_mag = 0. ; // No 3D version !
00214 
00215     Tenseur AVECT(source_tAphi) ;
00216     if (source_tAphi.get_etat() != ETATZERO) {
00217     
00218       for (int i=0; i<3; i++) {
00219     if(source_tAphi(i).dz_nonzero()) {
00220       assert( source_tAphi(i).get_dzpuis() == 4 ) ; 
00221     }
00222     else{
00223       (source_tAphi.set(i)).set_dzpuis(4) ; 
00224     }
00225       }
00226     
00227     }
00228     source_tAphi.poisson_vect(lambda_mag, par_poisson_Avect, AVECT, WORK_VECT,
00229                   WORK_SCAL) ;
00230     AVECT.change_triad(mp.get_bvect_spher());
00231     Cmp A_phi_n(AVECT(2));
00232     A_phi_n.mult_rsint() ;
00233 
00234     // Resolution de Maxwell-Ampere : A_1
00235 
00236     Cmp source_A_1t(-a_car()*(j_t*gtt + j_phi*gtphi) + BLAH);
00237 
00238     Cmp A_1t(mp);
00239     A_1t = 0 ;
00240     source_A_1t.poisson(par_poisson_At, A_1t) ;
00241 
00242     int L = mp.get_mg()->get_nt(0);
00243 
00244     Tbl MAT(L,L) ;
00245     Tbl MAT_PHI(L,L);
00246     Tbl VEC(L) ;
00247 
00248     MAT.set_etat_qcq() ;
00249     VEC.set_etat_qcq() ;
00250     MAT_PHI.set_etat_qcq() ;
00251 
00252     Tbl leg(L,2*L) ;
00253     leg.set_etat_qcq() ;
00254 
00255     Cmp psi(mp);
00256     Cmp psi2(mp);
00257     psi.allocate_all() ;
00258     psi2.allocate_all() ;
00259 
00260     for (int p=0; p<mp.get_mg()->get_np(0); p++) {
00261     // leg[k,l] : legendre_l(cos(theta_k))
00262     // Construction par recurrence de degre 2
00263     for(int k=0;k<L;k++){
00264         for(int l=0;l<2*L;l++){
00265         
00266         if(l==0) leg.set(k,l)=1. ;
00267         if(l==1) leg.set(k,l)=cos((*theta)(l_surf()(p,k),p,k,0)) ;
00268         if(l>=2) leg.set(k,l) = double(2*l-1)/double(l)  
00269                  * cos((*theta)(l_surf()(p,k),p,k,0))
00270                  * leg(k,l-1)-double(l-1)/double(l)*leg(k,l-2) ;
00271         }
00272     }
00273   
00274     for(int k=0;k<L;k++){
00275         
00276         // Valeurs a la surface trouvees via va.val_point_jk(l,xisurf,k,p)
00277         
00278         VEC.set(k) = A_0t.va.val_point_jk(l_surf()(p,k), xi_surf()(p,k), k, p)
00279         -A_1t.va.val_point_jk(l_surf()(p,k), xi_surf()(p,k), k, p);
00280   
00281         for(int l=0;l<L;l++) MAT.set(l,k) = leg(k,2*l)/pow(Rsurf(k),2*l+1);
00282     
00283     }
00284     // appel fortran : 
00285 
00286     int* IPIV=new int[L] ;
00287     int INFO ;
00288     
00289     Tbl MAT_SAVE(MAT) ;
00290     Tbl VEC2(L) ;
00291     VEC2.set_etat_qcq() ;
00292     int un = 1 ;
00293 
00294     F77_dgesv(&L, &un, MAT.t, &L, IPIV, VEC.t, &L, &INFO) ; 
00295 
00296     // coeffs a_l dans VEC
00297 
00298     for(int k=0;k<L;k++) {VEC2.set(k)=1. ; }
00299 
00300     F77_dgesv(&L, &un, MAT_SAVE.t, &L, IPIV, VEC2.t, &L, &INFO) ;
00301     
00302     delete [] IPIV ;
00303 
00304     for(int nz=0;nz < Z; nz++){
00305         for(int i=0;i< mp.get_mg()->get_nr(nz);i++){
00306         for(int k=0;k<L;k++){
00307             psi.set(nz,p,k,i) = 0. ;
00308             psi2.set(nz,p,k,i) = 0. ;
00309             for(int l=0;l<L;l++){
00310             psi.set(nz,p,k,i) += VEC(l)*leg(k,2*l) / 
00311                 pow((*mp.r.c)(nz,p,k,i),2*l+1);
00312             psi2.set(nz,p,k,i) += VEC2(l)*leg(k,2*l)/
00313                 pow((*mp.r.c)(nz, p, k,i),2*l+1);
00314             }
00315         }
00316         }
00317     }
00318     }
00319     psi.std_base_scal() ;
00320     psi2.std_base_scal() ;
00321   
00322     assert(psi.get_dzpuis() == 0) ;
00323     int dif = A_1t.get_dzpuis() ;
00324     if (dif > 0) {
00325       for (int d=0; d<dif; d++) A_1t.dec_dzpuis() ;
00326     }
00327 
00328     if (adapt) {
00329       Cmp A_t_ext(A_1t + psi) ;
00330       A_t_ext.annule(0,nzet-1) ;
00331       A_0t += A_t_ext ;
00332     }
00333     else {
00334       tmp = A_0t ;
00335       A_0t.allocate_all() ;
00336       for (int j=0; j<nt; j++) 
00337     for (int l=0; l<Z; l++) 
00338       for (int i=0; i<mp.get_mg()->get_nr(l); i++) 
00339         A_0t.set(l,0,j,i) = ( (*mp.r.c)(l,0,j,i) > Rsurf(j) ?
00340                   A_1t(l,0,j,i) + psi(l,0,j,i) : tmp(l,0,j,i) ) ;
00341     } 
00342     A_0t.std_base_scal() ;
00343 
00344     Valeur** asymp = A_0t.asymptot(1) ;
00345 
00346     double Q_0 = -4*M_PI*(*asymp[1])(Z-1,0,0,0) ; // utilise A_0t plutot que E
00347     delete asymp[0] ;
00348     delete asymp[1] ;
00349 
00350     delete [] asymp ;
00351 
00352     asymp = psi2.asymptot(1) ;
00353 
00354     double Q_2 = -4*M_PI*(*asymp[1])(Z-1,0,0,0)  ; // A_2t = psi2 a l'infini
00355     delete asymp[0] ;
00356     delete asymp[1] ;
00357 
00358     delete [] asymp ;
00359 
00360     // solution definitive de A_t:
00361 
00362     double C = (Q-Q_0)/Q_2 ;
00363 
00364     assert(psi2.get_dzpuis() == 0) ;
00365     dif = A_0t.get_dzpuis() ;
00366     if (dif > 0) {
00367       for (int d=0; d<dif; d++) A_0t.dec_dzpuis() ;
00368     }
00369     Cmp A_t_n(mp) ;
00370     if (adapt) {
00371       A_t_n = A_0t + C ;
00372       Cmp A_t_ext(A_0t + C*psi2) ;
00373       A_t_ext.annule(0,nzet-1) ;
00374       A_t_n.annule(nzet,Z-1) ;
00375       A_t_n += A_t_ext ;
00376     }
00377     else {
00378       A_t_n.allocate_all() ;
00379       for (int j=0; j<nt; j++) 
00380     for (int l=0; l<Z; l++) 
00381       for (int i=0; i<mp.get_mg()->get_nr(l); i++) 
00382         A_t_n.set(l,0,j,i) = ( (*mp.r.c)(l,0,j,i) > Rsurf(j) ?
00383                    A_0t(l,0,j,i) + C*psi2(l,0,j,i) : 
00384                    A_0t(l,0,j,i) + C ) ;    
00385     }
00386     A_t_n.std_base_scal() ;
00387 
00388     asymp = A_t_n.asymptot(1) ;
00389 
00390     delete asymp[0] ;
00391     delete asymp[1] ;
00392 
00393     delete [] asymp ;
00394     A_t = relax_mag*A_t_n + (1.-relax_mag)*A_t ;
00395     A_phi = relax_mag*A_phi_n + (1. - relax_mag)*A_phi ;
00396 
00397 
00398   }else{
00399     
00400     /***************
00401      * CAS ISOLANT *
00402      ***************/                                   
00403     // Calcul de j_t
00404     j_t = Q*nbar() + (ener()+press())*f_j(omega* A_phi - A_t,a_j) ;
00405     j_t.annule(nzet,Z-1) ;
00406     j_t.std_base_scal() ;
00407     
00408     // Calcul de j_phi
00409     j_phi = omega * j_t ;
00410     j_phi.std_base_scal() ;
00411     
00412     // Resolution de A_t
00413     
00414     Tenseur ATTENS(A_t) ; 
00415     Tenseur APTENS(A_phi) ;
00416     Tenseur BMN(-logn) ;
00417     BMN =  BMN + log(bbb) ;
00418     BMN.set_std_base() ;
00419 
00420 
00421     Cmp grad1(flat_scalar_prod_desal(ATTENS.gradient_spher(),
00422                      nphi.gradient_spher())());
00423     Cmp grad2(flat_scalar_prod_desal(APTENS.gradient_spher(),
00424                      nphi.gradient_spher())()) ;
00425     Cmp grad3(flat_scalar_prod_desal(ATTENS.gradient_spher(),
00426                      BMN.gradient_spher())()
00427           + 2*nphi()*flat_scalar_prod_desal(APTENS.gradient_spher(),
00428                         BMN.gradient_spher())()) ;
00429 
00430     Cmp ATANT(A_phi.srdsdt());
00431 
00432     ATANT.va = ATANT.va.mult_ct().ssint() ;
00433 
00434     Cmp ttnphi(tnphi()) ;
00435     ttnphi.mult_rsint() ;
00436     Cmp BLAH(- b_car()/(nnn()*nnn())*ttnphi*grad1)  ;
00437     BLAH -= (1+b_car()/(nnn()*nnn())*tnphi()*tnphi())*grad2  ;
00438     Cmp nphisr(nphi()) ;
00439     nphisr.div_r() ;
00440     Cmp npgrada(2*nphisr*(A_phi.dsdr()+ATANT )) ;
00441     npgrada.inc2_dzpuis() ;
00442     BLAH -=  grad3 + npgrada ;
00443     Cmp gtt(-nnn()*nnn()+b_car()*tnphi()*tnphi()) ;
00444     Cmp gtphi( - b_car()*ttnphi) ;
00445 
00446     Cmp source_A_t_n(mp);
00447     if (relativistic) {
00448       source_A_t_n = (-a_car()*(j_t*gtt + j_phi*gtphi) + BLAH);
00449       source_A_t_n.std_base_scal();}
00450     else{
00451       source_A_t_n = j_t;}
00452 
00453     Cmp A_t_n(A_t) ;
00454     A_t_n = 0 ;
00455     A_t_n.std_base_scal() ;
00456 
00457     source_A_t_n.poisson(par_poisson_At, A_t_n) ;
00458 
00459     // Resolution de A_phi
00460 
00461     Cmp grad4(flat_scalar_prod_desal(APTENS.gradient_spher(),
00462                      BMN.gradient_spher())());
00463 
00464     Tenseur source_tAphi(mp, 1, CON, mp.get_bvect_spher()) ;
00465 
00466     source_tAphi.set_etat_qcq() ;
00467 
00468     Cmp tjphi(j_phi) ;
00469     tjphi.mult_rsint() ;
00470     Cmp tgrad1(grad1) ;
00471     tgrad1.mult_rsint() ;
00472     Cmp d_grad4(grad4) ;
00473     d_grad4.div_rsint() ;
00474     source_tAphi.set(0)=0 ;
00475     source_tAphi.set(1)=0 ;
00476 
00477     if (relativistic) {
00478       source_tAphi.set(2)= -b_car()*a_car()*(tjphi-tnphi()*j_t)
00479     + b_car()/(nnn()*nnn())*(tgrad1+tnphi()*grad2)+d_grad4 ;}
00480     else{
00481       source_tAphi.set(2)= - tjphi ;}
00482 
00483     source_tAphi.change_triad(mp.get_bvect_cart());
00484 
00485     Tenseur WORK_VECT(mp, 1, CON, mp.get_bvect_cart()) ;
00486     WORK_VECT.set_etat_qcq() ;
00487     for (int i=0; i<3; i++) {
00488       WORK_VECT.set(i) = 0 ; 
00489     }
00490     Tenseur WORK_SCAL(mp) ;
00491     WORK_SCAL.set_etat_qcq() ;
00492     WORK_SCAL.set() = 0 ;
00493   
00494     double lambda_mag = 0. ; // No 3D version !
00495 
00496     Tenseur AVECT(source_tAphi) ;
00497     if (source_tAphi.get_etat() != ETATZERO) {
00498     
00499       for (int i=0; i<3; i++) {
00500     if(source_tAphi(i).dz_nonzero()) {
00501       assert( source_tAphi(i).get_dzpuis() == 4 ) ; 
00502     }
00503     else{
00504       (source_tAphi.set(i)).set_dzpuis(4) ; 
00505     }
00506       }
00507     
00508     }
00509     source_tAphi.poisson_vect(lambda_mag, par_poisson_Avect, AVECT, WORK_VECT,
00510                   WORK_SCAL) ;
00511     AVECT.change_triad(mp.get_bvect_spher());
00512     Cmp A_phi_n(AVECT(2));
00513     A_phi_n.mult_rsint() ;
00514 
00515   // Relaxation
00516 
00517     A_t = relax_mag*A_t_n + (1.-relax_mag)*A_t ;
00518     A_phi = relax_mag*A_phi_n + (1. - relax_mag)*A_phi ;
00519 
00520   }
00521 
00522 
00523 }
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 

Generated on Tue Feb 7 01:35:17 2012 for LORENE by  doxygen 1.4.6