wave_utilities.C

00001 /*
00002  *  Miscellaneous functions for the wave equation
00003  *
00004  */
00005 
00006 /*
00007  *   Copyright (c) 2008 Jerome Novak
00008  *
00009  *   This file is part of LORENE.
00010  *
00011  *   LORENE is free software; you can redistribute it and/or modify
00012  *   it under the terms of the GNU General Public License version 2
00013  *   as published by the Free Software Foundation.
00014  *
00015  *   LORENE is distributed in the hope that it will be useful,
00016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *   GNU General Public License for more details.
00019  *
00020  *   You should have received a copy of the GNU General Public License
00021  *   along with LORENE; if not, write to the Free Software
00022  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  */
00025 
00026 char wave_utilities_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/wave_utilities.C,v 1.10 2008/12/05 13:09:10 j_novak Exp $" ;
00027 
00028 /*
00029  * $Id: wave_utilities.C,v 1.10 2008/12/05 13:09:10 j_novak Exp $
00030  * $Log: wave_utilities.C,v $
00031  * Revision 1.10  2008/12/05 13:09:10  j_novak
00032  * Minor change in tilde_laplacian.
00033  *
00034  * Revision 1.9  2008/12/04 18:20:41  j_novak
00035  * Better treatment of the case ETATZERO in BC initialization, and of dzpuis for
00036  * evolution.
00037  *
00038  * Revision 1.8  2008/11/27 12:12:38  j_novak
00039  * New function to initialize parameters for wave equation.
00040  *
00041  * Revision 1.7  2008/10/29 08:22:58  jl_cornou
00042  * Compatibility conditions in the vector wave-equation case added
00043  *
00044  * Revision 1.6  2008/10/14 13:10:58  j_novak
00045  * New function Dirichlet_BC_AtB, to compute Dirichlet boundary conditions on A and B potentials knowing them on the tensor h^{ij}.
00046  *
00047  * Revision 1.5  2008/08/27 08:11:47  j_novak
00048  * Correction of a mistake in the index in evolve_outgoing_BC.
00049  *
00050  * Revision 1.4  2008/08/19 06:42:00  j_novak
00051  * Minor modifications to avoid warnings with gcc 4.3. Most of them concern
00052  * cast-type operations, and constant strings that must be defined as const char*
00053  *
00054  * Revision 1.3  2008/07/18 12:28:41  j_novak
00055  * Corrected some mistakes.
00056  *
00057  * Revision 1.2  2008/07/18 09:17:35  j_novak
00058  * New function tilde_laplacian().
00059  *
00060  * Revision 1.1  2008/07/11 13:20:54  j_novak
00061  * Miscellaneous functions for the wave equation.
00062  *
00063  *
00064  * $Header $
00065  *
00066  */
00067 
00068 #include"tensor.h"
00069 #include"evolution.h"
00070 
00071 void tilde_laplacian(const Scalar& B_in, Scalar& tilde_lap, int dl) {
00072     
00073     if (B_in.get_etat() == ETATZERO) {
00074     tilde_lap.set_etat_zero() ;
00075     return ;
00076     }
00077     assert(B_in.check_dzpuis(0)) ; ;
00078     if (dl == 0) {
00079     tilde_lap = B_in.laplacian(0) ;
00080     return ;
00081     }
00082     assert(B_in.get_etat() != ETATNONDEF) ;
00083     const Map_af* map =dynamic_cast<const Map_af*>(&B_in.get_mp()) ;
00084     assert(map != 0x0) ;
00085     
00086     tilde_lap = 2*B_in.dsdr() ;
00087     tilde_lap.div_r_dzpuis(3) ;
00088     tilde_lap += B_in.dsdr().dsdr() ;
00089     tilde_lap.dec_dzpuis() ;
00090     tilde_lap.set_spectral_va().ylm() ;
00091     Scalar B_over_r2 = B_in ;
00092     B_over_r2.div_r_dzpuis(1) ;
00093     B_over_r2.div_r_dzpuis(2) ;
00094     B_over_r2.set_spectral_va().ylm() ;
00095 
00096     const Base_val& base = B_in.get_spectral_base() ;
00097     const Mg3d& mg = *map->get_mg() ;
00098     int nz = mg.get_nzone() ;
00099     int l_q, m_q, base_r ;
00100     for (int lz=0; lz<nz; lz++) {
00101     if (B_in.domain(lz).get_etat() == ETATZERO) {
00102         tilde_lap.set_spectral_va().c_cf->set(lz).set_etat_zero() ;
00103     }
00104     else {
00105         for (int k=0; k<mg.get_np(lz)+2; k++)
00106         for (int j=0; j<mg.get_nt(lz); j++) {
00107             base.give_quant_numbers(lz, k, j, m_q, l_q, base_r) ;
00108             if (l_q > 1) {
00109             l_q += dl ;
00110             for (int i=0; i<mg.get_nr(lz); i++)
00111                 tilde_lap.set_spectral_va().c_cf->set(lz, k, j, i)
00112                 -= l_q*(l_q+1)*
00113                 (*B_over_r2.get_spectral_va().c_cf)(lz, k, j, i) ;
00114             }
00115         }
00116     }
00117     }
00118     if (tilde_lap.get_spectral_va().c != 0x0) {
00119     delete tilde_lap.set_spectral_va().c ;
00120     tilde_lap.set_spectral_va().c = 0x0 ;
00121     }
00122     tilde_lap.dec_dzpuis(2) ;
00123     return ;
00124 }
00125 
00126 /* Performs one time-step integration of the wave equation, using
00127  * a third-order Runge-Kutta scheme.
00128  * phi = d fff / dt
00129  * \Delta fff = d phi / dt
00130  * Inputs are dt, fff, phi; outputs fnext, phinext.
00131  */
00132 void runge_kutta3_wave_sys(double dt, const Scalar& fff, const Scalar& phi,
00133                Scalar& fnext, Scalar& phinext, int dl) {
00134 
00135     const Map& map = fff.get_mp() ;
00136     Scalar k1 = phi ;
00137     Scalar dk1(map) ; tilde_laplacian(fff, dk1, dl) ;
00138     Scalar y1 = fff + 0.5*dt*k1 ;
00139     Scalar dy1 = phi + 0.5*dt*dk1 ;
00140     Scalar k2 = dy1 ; Scalar dk2(map) ; tilde_laplacian(y1, dk2, dl) ;
00141     Scalar y2 = fff - dt*k1 + 2*dt*k2 ;
00142     Scalar dy2 = phi - dt*dk1 + 2*dt*dk2 ;
00143     Scalar k3 = dy2 ;
00144     Scalar dk3(map) ; tilde_laplacian(y2, dk3, dl) ;
00145     fnext = fff + dt*(k1 + 4*k2 + k3)/6. ;
00146     phinext = phi + dt*(dk1 + 4*dk2 + dk3)/6. ;
00147     
00148     return ;
00149 }
00150 
00151 void initialize_outgoing_BC(int nz_bound, const Scalar& phi, const Scalar& dphi, 
00152                 Tbl& xij)
00153 {
00154     Scalar source_xi = phi ;
00155     source_xi.div_r_dzpuis(2) ;
00156     source_xi += phi.dsdr() ;
00157     source_xi.dec_dzpuis(2) ;
00158     source_xi += dphi ;
00159     if (source_xi.get_etat() == ETATZERO)
00160     xij.annule_hard() ;
00161     else {
00162     source_xi.set_spectral_va().ylm() ;
00163 
00164     const Base_val& base_x = source_xi.get_spectral_base() ;
00165     int np2 = xij.get_dim(1) ;
00166     int nt = xij.get_dim(0) ;
00167     assert (source_xi.get_mp().get_mg()->get_np(nz_bound) + 2 == np2 ) ;
00168     assert (source_xi.get_mp().get_mg()->get_nt(nz_bound) == nt ) ;
00169     
00170     int l_q, m_q, base_r ;
00171     for (int k=0; k<np2; k++)
00172         for (int j=0; j<nt; j++) {      
00173         base_x.give_quant_numbers(nz_bound, k, j, m_q, l_q, base_r) ;
00174         xij.set(k, j) 
00175             = source_xi.get_spectral_va().c_cf->val_out_bound_jk(nz_bound, j, k) ;
00176         if (l_q == 0)
00177             xij.set(k,j) = 0 ;
00178         }
00179     }
00180 }
00181 
00182 
00183 /* Performs one time-step integration of the quantities needed for the
00184  * enhanced outgoing-wave boundary condition. It DOES NOT impose the BC
00185  * d phi / dr + d phi / dt + phi / r = xi(theta, varphi).
00186  * nz_bound: index of the domain on which to impose the BC
00187  * phi: the field that should leave the grid
00188  * sphi: source of the Robin BC, without xi : a phi + b d phi / dr = sphi + xi
00189  * ccc: (output) total source of the Robin BC
00190  */ 
00191 void evolve_outgoing_BC(double dt, int nz_bound, const Scalar& phi, Scalar& sphi, 
00192             Tbl& xij, Tbl& xijm1, Tbl& ccc, int dl) {
00193     
00194     const Map* map = &phi.get_mp() ;
00195     const Map_af* mp_aff = dynamic_cast<const Map_af*>(map) ;
00196     assert(mp_aff != 0x0) ;
00197 
00198     const Mg3d& grid = *mp_aff->get_mg() ;
00199 #ifndef NDEBUG
00200     int nz = grid.get_nzone() ;
00201     assert(nz_bound < nz) ;
00202     assert(phi.get_etat() != ETATZERO) ;
00203     assert(sphi.get_etat() != ETATZERO) ;
00204 #endif
00205     int np2 = grid.get_np(nz_bound) + 2 ;
00206     int nt = grid.get_nt(nz_bound) ;
00207     assert(xij.get_ndim() == 2) ;
00208     assert(xijm1.get_ndim() == 2) ;
00209     assert(ccc.get_ndim() == 2) ;
00210     assert(xij.get_dim(0) == nt) ;
00211     assert(xij.get_dim(1) == np2) ;
00212     assert(xijm1.get_dim(0) == nt) ;
00213     assert(xijm1.get_dim(1) == np2) ;
00214     assert(ccc.get_dim(0) == nt) ;
00215     assert(ccc.get_dim(1) == np2) ;
00216     
00217     double Rmax = mp_aff->get_alpha()[nz_bound] + mp_aff->get_beta()[nz_bound] ;
00218     
00219     Scalar source_xi = phi ;
00220     int dzp = ( source_xi.get_dzpuis() == 0 ? 2 : source_xi.get_dzpuis()+1 ) ;
00221     source_xi.div_r_dzpuis(dzp) ;
00222     source_xi -= phi.dsdr() ;
00223     source_xi.set_spectral_va().ylm() ;
00224     sphi.set_spectral_va().ylm() ;
00225     const Base_val& base = sphi.get_spectral_base() ;
00226     int l_q, m_q, base_r ;
00227     for (int k=0; k<np2; k++) 
00228     for (int j=0; j<nt; j++) {
00229         base.give_quant_numbers(nz_bound, k, j, m_q, l_q, base_r) ;
00230         if (l_q > 1) {
00231         l_q += dl ;
00232         double fact = 8*Rmax*Rmax + dt*dt*(6+3*l_q*(l_q+1)) + 12*Rmax*dt ;
00233         double souphi = -4*dt*dt*l_q*(l_q+1)*
00234             source_xi.get_spectral_va().c_cf->val_out_bound_jk(nz_bound, j, k) ;
00235         double xijp1 = ( 16*Rmax*Rmax*xij(k,j) -
00236                  (fact - 24*Rmax*dt)*xijm1(k,j) 
00237                  + souphi) / fact  ;
00238         ccc.set(k, j) = xijp1 
00239             + sphi.get_spectral_va().c_cf->val_out_bound_jk(nz_bound, j, k) ;
00240         xijm1.set(k,j) = xij(k,j) ;
00241         xij.set(k,j) = xijp1 ;
00242         }
00243     }
00244 
00245 }
00246 
00247 void Dirichlet_BC_AtB(const Evolution_std<Sym_tensor>& hb_evol, 
00248               const Evolution_std<Sym_tensor>& dhb_evol, Tbl& ccA, Tbl& ccB) {
00249 
00250     int iter = hb_evol.j_max() ;
00251     assert(dhb_evol.j_max() == iter) ;
00252 
00253     Scalar mu_ddot = dhb_evol.time_derive(iter,3).mu() ;
00254 
00255     Tbl ddmu = mu_ddot.tbl_out_bound(0, true) ;
00256     int nt = ddmu.get_dim(0) ;
00257     int np2 = ddmu.get_dim(1) ;
00258     const Base_val& base = mu_ddot.get_spectral_base() ;
00259      int l_q, m_q, base_r ;
00260      ccA.annule_hard() ;
00261      for (int k=0; k<np2; k++) {
00262      for (int j=0; j<nt; j++) {
00263          base.give_quant_numbers(0, k, j, m_q, l_q, base_r) ;
00264          if (l_q>1)
00265          ccA.set(k,j) = ddmu(k,j) / double(l_q*(l_q+1)-2) ;
00266      }
00267      }
00268 
00269      Scalar hrr_ddot = dhb_evol.time_derive(iter,3)(1,1) ;
00270      Tbl ddhrr = hrr_ddot.tbl_out_bound(0, true) ;
00271      Scalar eta_ddot = dhb_evol.time_derive(iter,3).eta() ;
00272      Tbl ddeta = eta_ddot.tbl_out_bound(0, true) ;
00273      const Base_val& base2 = hrr_ddot.get_spectral_base() ;
00274 
00275      const Map& map = hrr_ddot.get_mp() ;
00276      const Map_radial* mp_rad = dynamic_cast<const Map_radial*>(&map) ;
00277      assert(mp_rad != 0x0) ;
00278      for (int k=0; k<np2; k++) {
00279      for (int j=0; j<nt; j++) {
00280          base2.give_quant_numbers(0, k, j, m_q, l_q, base_r) ;
00281          if (l_q>1) {
00282          ccB.set(k,j) = (double(l_q+1)*ddeta(k,j) 
00283                  + ddhrr(k,j)*mp_rad->val_r_jk(0, 1., j, k))
00284              / double((l_q+1)*(l_q-1)) ;
00285          }
00286      }
00287      }
00288 
00289 }
00290               
00291 
00292 void Dirichlet_BC_Amu(const Evolution_std<Vector>& vb_evol, 
00293               const Evolution_std<Vector>& dvb_evol, Tbl& ccA, Tbl& ccmu) {
00294 
00295     int iter = vb_evol.j_max() ;
00296     assert(dvb_evol.j_max() == iter) ;
00297 
00298     Scalar vr_ddot = dvb_evol.time_derive(iter,3)(1) ;
00299 
00300     Tbl ddvr = vr_ddot.tbl_out_bound(0, true) ;
00301     int nt = ddvr.get_dim(0) ;
00302     int np2 = ddvr.get_dim(1) ;
00303     const Base_val& base = vr_ddot.get_spectral_base() ;
00304     int l_q, m_q, base_r ;
00305     ccA.annule_hard() ;
00306     ccmu.annule_hard() ;
00307     Scalar mu_b = vb_evol[iter].mu();
00308     ccmu = mu_b.tbl_out_bound(0,true);
00309     const Map& map = vr_ddot.get_mp();
00310     const Map_radial* mp_rad = dynamic_cast<const Map_radial*>(&map);
00311     assert(mp_rad != 0x0) ;
00312      for (int k=0; k<np2; k++) {
00313      for (int j=0; j<nt; j++) {
00314          base.give_quant_numbers(0, k, j, m_q, l_q, base_r) ;
00315          if (l_q>0) {
00316          ccA.set(k,j) = ddvr(k,j)*mp_rad->val_r_jk(0, 1., j, k) / double(l_q*(l_q+1)) ;
00317         }
00318         }
00319      }
00320      }
00321 
00322 
00323 
00324 
00325 

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