summaryrefslogtreecommitdiff
path: root/lpic/src/diagnostic_poisson.C
diff options
context:
space:
mode:
Diffstat (limited to 'lpic/src/diagnostic_poisson.C')
-rw-r--r--lpic/src/diagnostic_poisson.C315
1 files changed, 315 insertions, 0 deletions
diff --git a/lpic/src/diagnostic_poisson.C b/lpic/src/diagnostic_poisson.C
new file mode 100644
index 0000000..1994db6
--- /dev/null
+++ b/lpic/src/diagnostic_poisson.C
@@ -0,0 +1,315 @@
+/*
+ This file is part of LPIC++, a particle-in-cell code for
+ simulating the interaction of laser light with plasma.
+
+ Copyright (C) 1994-1997 Roland Lichters
+
+ LPIC++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <diagnostic_poisson.h>
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+poisson::poisson( parameter &p, domain* grid )
+ : rf(),
+ input(p),
+ stepper( input.stepper, p )
+{
+ sprintf( errname, "%s/error-%d", p.path, p.domain_number );
+ static error_handler bob("poisson::Constructor",errname);
+
+ double nach, vor;
+ int n = grid->n_cells; // number of grid points
+
+ spp = p.spp;
+ domain_number = p.domain_number;
+ output_path = new char [filename_size];
+
+ strcpy(output_path,p.path);
+
+ if (input.n_domains>1) {
+ stepper.Q = 0;
+ bob.message( "parallel processing -> no fft" );
+ }
+ else {
+ if ( (nach=modf(log(n)/log(2),&vor)) > TINY ) {
+ stepper.Q = 0;
+ bob.message( "# cells not a power of 2 -> no fft" );
+ }
+ else {
+ stepper.Q = 1;
+
+ ex = new( double [grid->n_cells] );
+ rhok = new( double [2*grid->n_cells + 1] );
+ phik = new( double [2*grid->n_cells + 1] );
+
+ name = new( char [filename_size] );
+ }
+ }
+
+ if( input.Q_restart == 1 ) {
+ char fname[ filename_size ];
+ sprintf( fname, "%s/%s-%d-data1", p.path, input.restart_file, p.domain_number );
+ rf.openinput(fname);
+ stepper.t_count = atoi( rf.getinput( "poi.stepper.t_count" ) );
+ rf.closeinput();
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+input_poisson::input_poisson( parameter &p )
+ : rf()
+{
+ sprintf( errname, "%s/error-%d", p.path, p.domain_number );
+ static error_handler bob("input_poisson::Constructor",errname);
+
+ rf.openinput( p.input_file_name );
+
+ n_domains = p.n_domains;
+
+ stepper.Q = 1; // not needed
+ stepper.t_start = atof( rf.setget( "&propagate", "prop_start" ) );
+ stepper.t_stop = atof( rf.setget( "&propagate", "prop_stop" ) );
+ stepper.t_step = 1; // once per cycle
+ stepper.x_start = -1; // not needed
+ stepper.x_stop = -1; // not needed
+ stepper.x_step = -1; // not needed
+
+ Q_restart = atoi( rf.setget( "&restart", "Q" ) );
+ strcpy( restart_file, rf.setget( "&restart", "file" ) );
+
+ rf.closeinput();
+
+ bob.message("parameter read");
+
+ if (p.domain_number==1) save(p);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+void input_poisson::save( parameter &p )
+{
+ static error_handler bob("input_poisson::save",errname);
+ ofstream outfile;
+
+ outfile.open(p.outname,ios::app);
+
+ outfile << "diagnostic poisson" << endl;
+ outfile << "------------------------------------------------------------------" << endl;
+ outfile << "Q : " << stepper.Q << endl;
+ outfile << "t_start : " << stepper.t_start << endl;
+ outfile << "t_stop : " << stepper.t_stop << endl;
+ outfile << "t_step : " << stepper.t_step << endl;
+ outfile << "Q_restart : " << Q_restart << endl;
+ outfile << "restart_file : " << restart_file << endl << endl << endl;
+
+ outfile.close();
+
+ bob.message("parameter written");
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+void poisson::write( double time, domain *grid )
+{
+ static error_handler bob("diagnostic::write_poisson",errname);
+
+ struct cell *cell;
+ int i;
+
+ sprintf(name,"%s/poisson-%d-%.3f", output_path, domain_number, time);
+
+ file.open(name);
+ if (!file) bob.error("cannot open snapshot file", name );
+
+ file.precision( 3 );
+ file.setf( ios::showpoint | ios::scientific );
+
+ file << "#" << setw(11) << "x"
+ << setw(12) << "Ex-Current"
+ << setw(12) << "Ex-Poisson" << endl;
+
+ for( i=0, cell=grid->left; cell!=grid->rbuf; cell=cell->next, i++ )
+ {
+ file << setw(12) << cell->x
+ << setw(12) << cell->ex
+ << setw(12) << ex[i] << endl;
+ }
+
+ file.close();
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+void poisson::solve( domain* grid )
+// n_cells = power of 2 is assumed
+// solves Poisson equation to obtain electric field Ex'
+// compares Ex' with Ex obtained from Jx during simulation
+// can be used to initialize Ex from an initial charge distribution
+{
+ static error_handler bob("diagnostic::solve_poisson",errname);
+
+ int n = grid->n_cells;
+ double dx = grid->dx; // grid constant
+ double dk = 2*PI/(dx*n); // grid constant
+ double kn, Kn; // slitfunction
+ double b; // homogeneous solution
+ int i;
+ struct cell *cell;
+
+ // fourier transform of the charge density
+
+ for( i=1, cell=grid->left; cell!=grid->rbuf; cell=cell->next, i++ )
+ {
+ rhok[2*i-1] = cell->charge; // real part
+ rhok[2*i] = 0; // imaginary part
+ }
+ fft(rhok,n,1); // transform
+
+ for( i=1; i<n; i++ ) // potential in k-space
+ { // smooth at large k
+ if (i<=0.5*n) kn=dk*i;
+ else kn=dk*(i-n);
+
+ Kn=kn*dif(kn*dx/2); // LOCAL differences
+ // new units: 1/eps -> (2pi)^2 in Poisson's equation!
+ phik[2*i+1] = sqr(2*PI/Kn) * rhok[2*i+1] * smooth(kn*dx/2);
+ phik[2*i+2] = sqr(2*PI/Kn) * rhok[2*i+2] * smooth(kn*dx/2);
+ }
+ phik[1] = phik[2] = 0; // FT_phi(k=0):=0
+
+ fft(phik,n,-1);
+
+ // take real part and add homogeneous solution --> potential
+ // calculate electric field and electrostatic energy density
+
+ // new units: E = - div phi --> E = - 1/2pi div phi
+
+ b = ( phik[1] - phik[3] ) / (2*PI*dx*n);
+ ex[0] = - (double) ( phik[3] - phik[1] ) / (2*PI*dx*n) - b;
+
+ for(i=1;i<=n-2;i++)
+ ex[i] = - ( phik[2*i+3] - phik[2*i-1] ) / (4*PI*dx*n) - b;
+
+ ex[n-1] = - ( phik[2*n-3] - phik[2*n-5] ) / (2*PI*dx*n) - b;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+double poisson::dif( double in )
+{
+ double out;
+
+ if (in==0) out=1;
+ else out=sin(in)/in;
+ return out;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+double poisson::smooth( double in )
+/*
+ cutoff at short wavelengths : a2
+ corrects omega_p(k) to order (kdx)^4 : a1
+*/
+{
+ double out;
+ double a1=0.5;
+ double a2=0.1; /* vorher a2=0.01 */
+
+ if (in==0) out=1;
+ else
+ {
+ out = a1 * pow( sin(in),2 ) - a2 * pow( sin(in)/cos(in), 4 );
+ out = exp( 2 * out );
+ }
+ return out;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
+
+void poisson::fft( double* data, int nn, int isign)
+// numerical recipies routine "four1.c"
+// changed data[], tempr, tempi from float to double
+{
+ int n,mmax,m,j,istep,i;
+ double wtemp,wr,wpr,wpi,wi,theta;
+ double tempr,tempi;
+
+ n=nn << 1;
+ j=1;
+ for (i=1;i<n;i+=2) {
+ if (j > i) {
+ SWAP(data[j],data[i]);
+ SWAP(data[j+1],data[i+1]);
+ }
+ m=n >> 1;
+ while (m >= 2 && j > m) {
+ j -= m;
+ m >>= 1;
+ }
+ j += m;
+ }
+ mmax=2;
+ while (n > mmax) {
+ istep=2*mmax;
+ theta=6.28318530717959/(isign*mmax);
+ wtemp=sin(0.5*theta);
+ wpr = -2.0*wtemp*wtemp;
+ wpi=sin(theta);
+ wr=1.0;
+ wi=0.0;
+ for (m=1;m<mmax;m+=2) {
+ for (i=m;i<=n;i+=istep) {
+ j=i+mmax;
+ tempr=wr*data[j]-wi*data[j+1];
+ tempi=wr*data[j+1]+wi*data[j];
+ data[j]=data[i]-tempr;
+ data[j+1]=data[i+1]-tempi;
+ data[i] += tempr;
+ data[i+1] += tempi;
+ }
+ wr=(wtemp=wr)*wpr-wi*wpi+wr;
+ wi=wi*wpr+wtemp*wpi+wi;
+ }
+ mmax=istep;
+ }
+}
+
+#undef SWAP
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//eof