diff options
Diffstat (limited to 'lpic/src/domain.C')
-rw-r--r-- | lpic/src/domain.C | 1230 |
1 files changed, 1230 insertions, 0 deletions
diff --git a/lpic/src/domain.C b/lpic/src/domain.C new file mode 100644 index 0000000..727f1e7 --- /dev/null +++ b/lpic/src/domain.C @@ -0,0 +1,1230 @@ +/* + This file is part of LPIC++, a particle-in-cell code for + simulating the interaction of laser light with plasma. + + Copyright (C) 2002 Andreas Kemp + 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 <domain.h> +// exponential energy distribution introduced by A.Kemp, 04/02 +domain::domain( parameter &p ) + : input(p) +{ + sprintf( errname, "%s/error-%d", p.path, p.domain_number ); + static error_handler bob("domain::Constructor",errname); + + domain_number = p.domain_number; + n_domains = input.n_domains; + dx = input.dx; + + strcpy( path, p.path ); + + n_el = 0; // will be set in domain::chain_particles() + n_ion = 0; // '' + n_part = 0; // '' + + if(input.Q_restart == 0){ + // simulation box ----------------------- + + set_boundaries(); // determines boundaries from domain number + + // init data structure------------------- + + chain_cells(); // create chained list of cells + // set cell numbers + // set domain pointers to left and right cells + + init_cells(); // set fields equal to zero + // set normalized densities + + chain_particles(); // allocate and link particles to cells + // set number, species, cell, position + + // physical part ------------------------ + + init_particles(); // set charge, mass, velocities, gamma + + check(); // check and save + // particel numbers, positions, total charge + // plot cell, x, densities, part. per cell + } + else { + restart_configuration(); // set restart configuration + } + + bob.message( "sizeof(struct cell) =", sizeof(struct cell), "Byte" ); + bob.message( "sizeof(struct particle) =", sizeof(struct particle), "Byte" ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// + + +input_domain::input_domain( parameter &p ) + : rf() +{ + sprintf( errname, "%s/error-%d", p.path, p.domain_number ); + static error_handler bob("input_domain::Constructor",errname); + + rf.openinput(p.input_file_name); + + Q_restart = atoi( rf.setget( "&restart", "Q" ) ); + strcpy( restart_file, rf.setget( "&restart", "file" ) ); + Q_restart_save = atoi( rf.setget( "&restart", "Q_save" ) ); + + // read grid //////////////////////////////////////////////////// + + n_domains = p.n_domains; + cells = atoi( rf.setget( "&box", "cells" ) ); + cells_per_wl = atoi( rf.setget( "&box", "cells_per_wl" ) ); + cells_left = atoi( rf.setget( "&box", "cells_left" ) ); + lramp.length = atoi( rf.setget( "&lramp", "length") ); + lramp.form = atoi( rf.setget( "&lramp", "form") ); + lramp.length2 = atoi( rf.setget( "&lramp", "length2") ); + lramp.cutoff = atoi( rf.setget( "&lramp", "cutoff") ); + lramp.gluepos = atoi( rf.setget( "&lramp", "gluepos") ); + lramp.middens = atof( rf.setget( "&lramp", "middens") ); + rramp.length = atoi( rf.setget( "&rramp", "length") ); + rramp.form = atoi( rf.setget( "&rramp", "form") ); + rramp.length2 = atoi( rf.setget( "&rramp", "length2") ); + rramp.cutoff = atoi( rf.setget( "&rramp", "cutoff") ); + rramp.gluepos = atoi( rf.setget( "&rramp", "gluepos") ); + rramp.middens = atof( rf.setget( "&rramp", "middens") ); + cells_plasma = atoi( rf.setget( "&box", "cells_plasma" ) ); + n_ion_over_nc = atof( rf.setget( "&box", "n_ion_over_nc" ) ); + ux0 = atof( rf.setget( "&box", "ux0" ) ); + + dx = 1.0 / cells_per_wl; + + // read particles ///////////////////////////////////////////////// + + nsp = p.nsp; + + fix = new(int[nsp]); + z = new(double[nsp]); + m = new(double[nsp]); + ppc = new(int[nsp]); + vtherm = new(double[nsp]); + + // electrons ----------------------------------------------------- + + fix[0] = atoi( rf.setget( "&electrons", "fix" ) ); + z[0] = -1; // DEFAULT, SHOULD NOT BE CHANGED + m[0] = +1; // DEFAULT, SHOULD NOT BE CHANGED + ppc[0] = atoi( rf.setget( "&electrons", "ppc" ) ); + vtherm[0] = atof( rf.setget( "&electrons", "vtherm" ) ); + + // ions ---------------------------------------------------------- + + fix[1] = atoi( rf.setget( "&ions", "fix" ) ); + z[1] = atoi( rf.setget( "&ions", "z" ) ); + m[1] = atof( rf.setget( "&ions", "m" ) ); + ppc[1] = atoi( rf.setget( "&ions", "ppc" ) ); + vtherm[1] = atof( rf.setget( "&ions", "vtherm" ) ); + + if ( z[1] == 0 && ppc[0] > 0 ) { + cout << " WARNING : You selected neutral atoms and free electrons" << endl; + cout << " Setting # MacroElectrons := 0" << endl; + ppc[0] = 0; + } + + n_el_over_nc = 1.0 * z[1] * n_ion_over_nc; + + // read spp, adjusted angle, Beta and Gamma + + spp = p.spp; + angle = p.angle; + Beta = p.Beta; + Gamma = p.Gamma; + + rf.closeinput(); + + bob.message("parameter read"); + + if (p.domain_number==1) save(p); +} + + +////////////////////////////////////////////////////////////////////////////////////////// + + +void input_domain::save( parameter &p ) +{ + static error_handler bob("input_domain::save",errname); + ofstream outfile; + int i; + + outfile.open(p.outname,ios::app); + + outfile << "domain: plasma" << endl; + outfile << "------------------------------------------------------------------" << endl; + outfile << "Q_restart : " << Q_restart << endl; + outfile << "restart_file : " << restart_file << endl; + outfile << "Q_restart_save : " << Q_restart_save << endl; + outfile << "N_domains : " << n_domains << endl; + outfile << "cells : " << cells << endl; + outfile << "cells_per_wl : " << cells_per_wl << endl; + outfile << "cells_left : " << cells_left << endl; + outfile << "lramp.length : " << lramp.length << endl; + outfile << "lramp.form : " << lramp.form << endl; + outfile << "lramp.length2 : " << lramp.length2 << endl; + outfile << "lramp.cutoff : " << lramp.cutoff << endl; + outfile << "lramp.gluepos : " << lramp.gluepos << endl; + outfile << "lramp.middens : " << lramp.middens << endl; + outfile << "rramp.length : " << rramp.length << endl; + outfile << "rramp.form : " << rramp.form << endl; + outfile << "rramp.length2 : " << rramp.length2 << endl; + outfile << "rramp.cutoff : " << rramp.cutoff << endl; + outfile << "rramp.gluepos : " << rramp.gluepos << endl; + outfile << "rramp.middens : " << rramp.middens << endl; + outfile << "cells_plasma : " << cells_plasma << endl; + outfile << "dx : " << dx << endl << endl; + outfile << "n_ion_over_nc : " << n_ion_over_nc << endl; + outfile << "n_el_over_nc : " << n_el_over_nc << endl; + outfile << "ux0 : " << ux0 << endl << endl << endl; + + outfile << "domain: particles" << endl; + outfile << "------------------------------------------------------------------" << endl; + outfile << "nsp : " << setw(8) << nsp << endl; + outfile << "fix : "; + for(i=0;i<nsp;i++) outfile << setw(8) << fix[i]; + outfile << endl << "charge : "; + for(i=0;i<nsp;i++) outfile << setw(8) << z[i]; + outfile << endl << "mass : "; + for(i=0;i<nsp;i++) outfile << setw(8) << m[i]; + outfile << endl << "ppc : "; + for(i=0;i<nsp;i++) outfile << setw(8) << ppc[i]; + outfile << endl << "vtherm : "; + for(i=0;i<nsp;i++) outfile << setw(8) << vtherm[i]; + outfile << endl << endl << endl; + + outfile << "domain: Lorentz transformation" << endl; + outfile << "------------------------------------------------------------------" << endl; + outfile << "spp : " << spp << endl; + outfile << "adjusted angle : " << angle << endl; + outfile << "Beta : " << Beta << endl; + outfile << "Gamma : " << Gamma << endl << endl << endl; + + outfile.close(); + + bob.message("parameter written"); +} + + +////////////////////////////////////////////////////////////////////////////////////////// + + +void domain::set_boundaries() +// p.box.N domains of equal size +{ + error_handler bob("domain::set_boundaries",errname); + + int cells_per_domain = (int) floor( (double) input.cells / input.n_domains ); + + n_left = 1 + ( domain_number - 1 ) * cells_per_domain; + n_right = n_left + cells_per_domain - 1; + n_cells = cells_per_domain; + + if (domain_number==n_domains) + { + n_right = input.cells; + n_cells = n_right - n_left + 1; + } + + bob.message("n_left = ", n_left ); + bob.message("n_right = ", n_right ); + bob.message("n_cells = ", n_cells ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// + + +void domain::chain_cells( void ) +{ + error_handler bob("domain::chain_cells",errname); + struct cell *cell_old, *cell_new; + + Lbuf = new ( struct cell ); + if (!Lbuf) bob.error("allocation error: Lbuf"); + Lbuf->number = n_left - 2; + + lbuf = new ( struct cell ); + if (!lbuf) bob.error("allocation error: lbuf"); + lbuf->number = n_left - 1; + lbuf->prev = Lbuf; + + left = new ( struct cell ); + if (!left) bob.error("allocation error: left"); + left->number = n_left; + left->prev = lbuf; + cell_old = left; + + for( int i=n_left+1; i<=n_right; i++ ) + { + cell_new = new ( struct cell ); + if (!cell_new) bob.error("allocation error: cell_new"); + cell_new->prev = cell_old; + cell_old->next = cell_new; + cell_old = cell_new; + cell_new->number = i; + } + + right = cell_old; + + rbuf = new ( struct cell ); + if (!rbuf) bob.error("allocation error: rbuf"); + rbuf->prev = right; + rbuf->number = n_right + 1; + + Rbuf = new ( struct cell ); + if (!Rbuf) bob.error("allocation error: Rbuf"); + Rbuf->prev = rbuf; + Rbuf->number = n_right + 2; + + dummy = new ( struct cell ); + if (!dummy) bob.error("allocation error: dummy"); + dummy->prev = Rbuf; + dummy->number = n_right + 3; + + right->next = rbuf; + rbuf->next = Rbuf; + Rbuf->next = dummy; + dummy->next = Lbuf; + Lbuf->next = lbuf; + Lbuf->prev = dummy; + lbuf->next = left; + + // closed ring of cells with two buffer cells left and right and dummy cell + // connecting Rbuf and Lbuf +} + + +////////////////////////////////////////////////////////////////////////////////////////// + + +void domain::init_cells( void ) +{ + error_handler bob("domain::init_cells",errname); + struct cell *cell; + + for( cell=Lbuf; cell!=dummy; cell=cell->next ) + { + if (!cell) bob.error("allocation error"); + + cell->domain = domain_number; // domain number + cell->x = dx * ( cell->number - 1 ); // cell coordinate, left boundary + + // set up the normalized particle densities for a ramp profile + + if ( cell->number < input.cells_left ) + cell->dens[0] = cell->dens[1] = input.lramp.calculate_density( input.cells_left - cell->number ); + else + if ( cell->number > ( input.cells_left + input.cells_plasma ) ) + cell->dens[0] = cell->dens[1] = input.rramp.calculate_density( cell->number - ( input.cells_left + input.cells_plasma ) ); + else + cell->dens[0] = cell->dens[1] = 1.0; + + if (cell->number < n_left || cell->number > n_right) // initially empty buffers ! + cell->dens[0] = cell->dens[1] = 0; + + cell->charge = 0; + cell->jx = cell->jy = cell->jz = 0; + cell->ex = cell->ey = cell->ez = 0; + cell->bx = cell->by = cell->bz = 0; + cell->fp = cell->fm = cell->gp = cell->gm = 0; + + for( int j=0;j<input.nsp; j++ ) cell->np[j] = 0; + cell->npart = 0; + // will be set in domain::chain_particles() + } +} + +double ramp::calculate_density(int position) +{ + // I cleaned up some definitions to keep the code simple. + + if ( position < 0 ) // Now it's not valid to come here with (position<0) ! + return NAN; + if (( cutoff >= 0 ) && ( position > cutoff )) // beyond cutoff + return 0.0; + else + switch ( form ) + { + case 0: // linear ramp as described in original documentation + if ( position < length ) + return 1.0 - (double)position / length; + else + return 0.0; + case 1: // exponential ramp + return exp(-(double)position/length); + case 2: // double exponential ramp + if ( position > gluepos ) + return exp((double)( gluepos - position )/length2 - (double)(gluepos)/length); + else + return exp(-(double)position/length); + case 3: // lin - const - lin ramp + if ( position < length ) // inner linear ramp + return 1.0 - (1.0 - middens) * (double)position / length; + if ( position <= gluepos ) // constant region + return middens; + if ( position < length2+gluepos ) // outer linear ramp + return middens * (1.0 - (double)(position-gluepos) / length2); + else // vacuum + return 0.0; + } + return NAN; +} + +////////////////////////////////////////////////////////////////////////////////////////// + + +void domain::chain_particles( void ) + // particle numbers are set in each domain separately, beginning with 1 + // this is corrected in the box::Constructor using communicate_particle_numbers(...) + // in order to keep domain free of networking +{ + error_handler bob("domain::chain_particles",errname); + + int i; + int *number; // count particles for each species sperately + double delta; + struct cell *cell; + struct particle *pn, *po; + + number = new( int [input.nsp] ); + if (!number) bob.error("allocation error"); + + for ( i=0; i<input.nsp; i++ ) number[i] = 0; + + for( cell=Lbuf; cell!=dummy; cell=cell->next ) // for all cells including all buffers + { + cell->first = NULL; + cell->last = NULL; + + po = cell->first; + + for( int j=0; j<input.nsp; j++ ) // for all species + { + cell->np[j] = (int) floor( cell->dens[j] * input.ppc[j] + 0.5 ); + + if (j==0) n_el += cell->np[j]; // count particles by species + else n_ion += cell->np[j]; + cell->npart += cell->np[j]; // particles per cell + n_part += cell->np[j]; // particles per domain + + if (cell->np[j]!=0) // for occupied cells + { + delta = dx / cell->np[j]; + + for( i=1; i<=cell->np[j]; i++ ) // for all particles of + { // kind j in this cell + number[j]++; + + pn = new ( struct particle ); + if (!pn) bob.error("allocation error"); + + pn->prev = po; + if (po==NULL) cell->first = pn; + else po->next = pn; + pn->number = number[j]; + pn->species = j; + pn->cell = cell; + pn->x = cell->x + ((double)i-0.50000001) * delta; + + po = pn; + } + } + } + if (po!=NULL) { + po->next = NULL; + cell->last = po; + } + } + + if ( n_el != number[0] ) bob.error("# allocated electrons incorrect"); + + for( i=2; i<input.nsp; i++ ) number[1]+=number[i]; + if ( n_ion != number[1] ) bob.error("# allocated ions incorrect"); + + delete number; +} + +////////////////////////////////////////////////////////////////////////////////////////// + + +void domain::init_particles( void ) +{ + error_handler bob("domain::init_particles",errname); + + struct cell *cell; + struct particle *part; + double Gamma = input.Gamma; // gamma factor due to Lorentz transformation + double Beta = input.Beta; + double vx, vy, vz; + + for( cell=left; cell!=rbuf; cell=cell->next ) // for all cells + { + if (cell->npart!=0) // for occupied cells + { + for( part=cell->first; part!=NULL; part=part->next ) + { // for all particles in this cell + if (!part) bob.error("allocation: part"); + + part->fix = input.fix[part->species]; + part->z = input.z[part->species]; + part->m = input.m[part->species]; + part->zm = part->z / part->m; + + // part->n = density / critical density + // part->zn = charge state * density / critical density + // --------------------------------------------------------- + // Lorentz-Transformation: part->zn is scaled up with Gamma^3! + // L-Contraction in y-direction leads to n_M = Gamma n_L + // and Doppler shift leads to n_c_M = 1/Gamma^2 * n_c_L + // --------------------------------------------------------- + // part->zn is designed such that the sum of MacroParticle charges + // (electrons and ions) is zero in each cell initially + + + if (part->z == 0) { // neutral atoms + part->n = pow(Gamma,3) * input.n_ion_over_nc / input.ppc[part->species]; + part->zn = 0; + } + else { // electrons or ions + part->n = pow(Gamma,3) * fabs( 1.0 * input.z[1] / part->z ) + * input.n_ion_over_nc / input.ppc[part->species]; + part->zn = part->z * part->n; + } + // thermal velocities + do + { + vx = input.vtherm[part->species] * gauss_rand48(); + vy = input.vtherm[part->species] * gauss_rand48(); + vz = input.vtherm[part->species] * gauss_rand48(); + // vx = exponential_rand( input.vtherm[part->species] ); vy = vz = 0.0; + } + while( vx*vx + vy*vy + vz*vz >= 1.0); // make sure that |v| < c + + // L-transform to the M frame + + vx = vx * sqrt(1.0-Beta*Beta) / ( 1 - vy*Beta ); + vz = vz * sqrt(1.0-Beta*Beta) / ( 1 - vy*Beta ); + vy = ( vy - Beta ) / ( 1 - vy*Beta ); + + // determine gamma*v + + part->igamma = sqrt( 1.0 - vx*vx - vy*vy - vz*vz ); + part->ux = input.ux0 + vx / part->igamma; + part->uy = vy / part->igamma; + part->uz = vz / part->igamma; + } + } + } +} + + +////////////////////////////////////////////////////////////////////////////////////////// + + +double domain::exponential_rand( double tm ) +{ + // one dimensional exponential energy distribution ## + // tm == kT / Me + static error_handler bob( "domain::exponential_rand", errname ); + double r1; + + r1 = drand48(); + return sqrt( 1.0 - 1.0/ sqr( (1.0 - tm * log( 1.0 - r1)) )); +} +/////////////////////////////////////////////////////////////////////////// + +double domain::gauss_rand48( void ) +{ + double r1, r2; + + r1 = drand48(); + r2 = drand48(); + + return sqrt( -2.0 * log( 1.0 - r1 ) ) * sin( 2*PI*r2 ); +} + + +////////////////////////////////////////////////////////////////////////////////////////// + + +void domain::check( void ) +{ + error_handler bob("domain::check_and_save",errname); + struct cell *cell; + struct particle *part; + int count[2]; + double charge=0; + + for( cell=Lbuf; cell!=dummy; cell=cell->next ) + { + count[0] = count[1] = 0; + + if (cell->npart!=0) + { + for( part=cell->first; part!=NULL; part=part->next ) + { + if (!part) bob.error("allocation: part"); + if ( part->x < cell->x || part->x > cell->x+dx ) + bob.error("particle position"); + count[part->species]++; + charge += part->zn; + } + } + if (cell->np[0] != count[0]) bob.error("number of electrons"); + if (cell->np[1] != count[1]) bob.error("number of ions"); + } + + char fname[filename_size]; + sprintf(fname,"%s/domain-%d", path, domain_number); + + ofstream domain_file(fname); + if (!domain_file) bob.error("cannot open output file: ", fname ); + + domain_file.precision( 3 ); + domain_file.setf( ios::showpoint ); + domain_file.setf( ios::scientific ); + + domain_file << setw(6) << "# cell" + << setw(12) << "x" + << setw(12) << "rho_el." + << setw(12) << "rho_ion" + << setw(7) << "n_el" + << setw(7) << "n_ion" << endl; + + for( cell=Lbuf; cell!=dummy; cell=cell->next ) + { + domain_file << setw(6) << cell->number + << setw(12) << cell->x + << setw(12) << cell->dens[0] + << setw(12) << cell->dens[1] + << setw(7) << cell->np[0] + << setw(7) << cell->np[1] << endl; + } + + domain_file.close(); + + if ( fabs(charge)> 1e-6 ) bob.error("domain is charged"); + +} + + +////////////////////////////////////////////////////////////////////////////////////////// + + +void domain::count_particles() + // counts particles in domain -> n_el, n_ion, n_part +{ + static error_handler bob("domain::count_particles",errname); + + struct cell *cell; + struct particle *part; + + int nparts_1, nparts_2; + int n_el_old = n_el; // keep in mind the old numbers + int n_ion_old = n_ion; + int n_part_old = n_part; + + n_el = 0; + n_ion = 0; + n_part = 0; + + for( cell=Lbuf; cell!=dummy; cell=cell->next ) + { + nparts_1 = nparts_2 = 0; + + if (cell->npart != 0) { + + nparts_1 += cell->npart; + + for( part=cell->first; part!=NULL; part=part->next ) + { + nparts_2++; + + if (part->species==0) n_el ++; + else n_ion ++; + n_part ++; + } + + if (nparts_1 != nparts_2) { + bob.message( "particle numbers incorrect" ); + bob.message( " in cell:", cell->number ); + bob.message( " cell_parts =", nparts_1 ); + bob.message( " parts =", nparts_2 ); + + bob.error(""); + } + + } + } + + bob.message( "particle numbers", n_el, n_ion, n_part ); + + if (n_el!=n_el_old || n_ion!=n_ion_old || n_part!=n_part_old) + { + bob.message( "old particle numbers", n_el_old, n_ion_old, n_part_old ); + bob.error(""); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void domain::reo_to_prev( int request_prev, int *cells_to_prev, int *parts_to_prev ) +{ + static error_handler bob("domain::reo_to_prev",errname); + + struct cell *cell; + + cell = left; + *cells_to_prev = 1; + *parts_to_prev = cell->npart; + + while( *parts_to_prev < -request_prev && cell != right->prev ) // to make sure that at + { // at least one cell stays in the domain + cell = cell->next; + *cells_to_prev = *cells_to_prev + 1; + *parts_to_prev = *parts_to_prev + cell->npart; + } + + if ( ( -request_prev - (*parts_to_prev - cell->npart) ) / cell->npart < 0.5 ) + { + *cells_to_prev = *cells_to_prev - 1; + *parts_to_prev = *parts_to_prev - cell->npart; + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void domain::reo_to_next( int request_next, int *cells_to_next, int *parts_to_next ) +{ + static error_handler bob("domain::reo_to_next",errname); + + struct cell *cell; + + cell = right; + *cells_to_next = 1; + *parts_to_next = cell->npart; + + while( *parts_to_next < request_next && cell != left->next ) // to make sure that at + { // at least one cell stays in the domain + cell = cell->prev; + *cells_to_next = *cells_to_next + 1; + *parts_to_next = *parts_to_next + cell->npart; + } + + if ( ( request_next - (*parts_to_next - cell->npart) ) / cell->npart < 0.5 ) + { + *cells_to_next = *cells_to_next - 1; + *parts_to_next = *parts_to_next - cell->npart; + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void domain::reo_delete_to_prev( int cells_to_prev, int parts_to_prev ) +{ + static error_handler bob("domain::reo_delete_to_prev",errname); + + int i; + int partcount = 0; + int el_count = 0; + int ion_count = 0; + struct cell *cell,*dcell; + struct particle *part,*dpart; + + cell = left; + + for(i=0;i<cells_to_prev;i++) { + + if(i == cells_to_prev - 2){ + Lbuf->number = cell->number; + Lbuf->x = cell->x; + Lbuf->charge = cell->charge; + Lbuf->jx = cell->jx; + Lbuf->jy = cell->jy; + Lbuf->jz = cell->jz; + Lbuf->ex = cell->ex; + Lbuf->ey = cell->ey; + Lbuf->ez = cell->ez; + Lbuf->bx = cell->bx; + Lbuf->by = cell->by; + Lbuf->bz = cell->bz; + Lbuf->fp = cell->fp; + Lbuf->fm = cell->fm; + Lbuf->gp = cell->gp; + Lbuf->gm = cell->gm; + Lbuf->dens[0]= cell->dens[0]; + Lbuf->dens[1]= cell->dens[1]; + Lbuf->np[0] = 0; + Lbuf->np[1] = 0; + Lbuf->npart = 0; + } + + if(i == cells_to_prev - 1){ + lbuf->number = cell->number; + lbuf->x = cell->x; + lbuf->charge = cell->charge; + lbuf->jx = cell->jx; + lbuf->jy = cell->jy; + lbuf->jz = cell->jz; + lbuf->ex = cell->ex; + lbuf->ey = cell->ey; + lbuf->ez = cell->ez; + lbuf->bx = cell->bx; + lbuf->by = cell->by; + lbuf->bz = cell->bz; + lbuf->fp = cell->fp; + lbuf->fm = cell->fm; + lbuf->gp = cell->gp; + lbuf->gm = cell->gm; + lbuf->dens[0]= cell->dens[0]; + lbuf->dens[1]= cell->dens[1]; + lbuf->np[0] = 0; + lbuf->np[1] = 0; + lbuf->npart = 0; + } + + part = cell->first; + while(part != NULL) + { + switch (part->species){ + case 0: + el_count ++; + partcount ++; + break; + case 1: + ion_count ++; + partcount ++; + break; + } + dpart = part; + part = part->next; + delete dpart; + } + + dcell = cell; + cell = cell->next; + delete dcell; + } + + cell->prev = lbuf; + lbuf->next = cell; + + left = cell; + n_left += cells_to_prev; + n_cells -= cells_to_prev; + n_el -= el_count; + n_ion -= ion_count; + n_part -= partcount; + + if (partcount != parts_to_prev) { + bob.error( "number of particles deleted does NOT match intended number to delete" );} + +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void domain::reo_delete_to_next( int cells_to_next, int parts_to_next ) +{ + static error_handler bob("domain::reo_delete_to_next",errname); + + int i; + int partcount = 0; + int el_count = 0; + int ion_count = 0; + struct cell *cell,*dcell; + struct particle *part,*dpart; + + cell = right; + + for(i=0;i<cells_to_next;i++) { + + if(i == cells_to_next - 2){ + Rbuf->number = cell->number; + Rbuf->x = cell->x; + Rbuf->charge = cell->charge; + Rbuf->jx = cell->jx; + Rbuf->jy = cell->jy; + Rbuf->jz = cell->jz; + Rbuf->ex = cell->ex; + Rbuf->ey = cell->ey; + Rbuf->ez = cell->ez; + Rbuf->bx = cell->bx; + Rbuf->by = cell->by; + Rbuf->bz = cell->bz; + Rbuf->fp = cell->fp; + Rbuf->fm = cell->fm; + Rbuf->gp = cell->gp; + Rbuf->gm = cell->gm; + Rbuf->dens[0]= cell->dens[0]; + Rbuf->dens[1]= cell->dens[1]; + Rbuf->np[0] = 0; + Rbuf->np[1] = 0; + Rbuf->npart = 0; + } + if(i == cells_to_next - 1){ + rbuf->number = cell->number; + rbuf->x = cell->x; + rbuf->charge = cell->charge; + rbuf->jx = cell->jx; + rbuf->jy = cell->jy; + rbuf->jz = cell->jz; + rbuf->ex = cell->ex; + rbuf->ey = cell->ey; + rbuf->ez = cell->ez; + rbuf->bx = cell->bx; + rbuf->by = cell->by; + rbuf->bz = cell->bz; + rbuf->fp = cell->fp; + rbuf->fm = cell->fm; + rbuf->gp = cell->gp; + rbuf->gm = cell->gm; + rbuf->dens[0]= cell->dens[0]; + rbuf->dens[1]= cell->dens[1]; + rbuf->np[0] = 0; + rbuf->np[1] = 0; + rbuf->npart = 0; + } + + part = cell->first; + while(part != NULL) + { + switch (part->species){ + case 0: + el_count ++; + partcount ++; + break; + case 1: + ion_count ++; + partcount ++; + break; + } + dpart = part; + part = part->next; + delete dpart; + } + + dcell = cell; + cell = cell->prev; + delete dcell; + } + + cell->next = rbuf; + rbuf->prev = cell; + + right = cell; + n_right -= cells_to_next; + n_cells -= cells_to_next; + n_el -= el_count; + n_ion -= ion_count; + n_part -= partcount; + + if (partcount != parts_to_next) { + bob.error( "number of particles deleted does NOT match intended number to delete" );} + +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void domain::reo_alloc_from_prev( int cells_from_prev, int parts_from_prev ) +{ + static error_handler bob("domain::reo_alloc_from_prev",errname); + + int i,cell_number; + double cell_x; + struct cell *cell_new; + struct particle *part_new; + + cell_new = left; + cell_number = left->number; + cell_x = left->x; + + for(i=0;i<cells_from_prev;i++) { + cell_new = new ( struct cell ); + if (!cell_new) bob.error("allocation error: cell_new"); + cell_new->prev = lbuf; + cell_new->next = lbuf->next; + lbuf->next->prev = cell_new; + lbuf->next = cell_new; + cell_number --; + cell_new->number = cell_number; + cell_x -= dx; + cell_new->x = cell_x; + + cell_new->first = NULL; + cell_new->last = NULL; + } + + left = cell_new; + + n_left -= cells_from_prev; + n_cells += cells_from_prev; + n_part += parts_from_prev; + + for(i=0;i<parts_from_prev;i++) { + part_new = new ( struct particle ); + if (!(part_new)) bob.error("allocation error"); + part_new->prev = NULL; + part_new->next = left->first; + if (part_new->next!=NULL) left->first->prev = part_new; + else left->last = part_new; + left->first = part_new; + + part_new->cell = left; + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void domain::reo_alloc_from_next( int cells_from_next, int parts_from_next ) +{ + static error_handler bob("domain::reo_alloc_from_next",errname); + + int i,cell_number; + double cell_x; + struct cell *cell_new; + struct particle *part_new; + + cell_new = right; + cell_number = right->number; + cell_x = right->x; + + for(i=0;i<cells_from_next;i++) { + cell_new = new ( struct cell ); + if (!cell_new) bob.error("allocation error: cell_new"); + cell_new->next = rbuf; + cell_new->prev = rbuf->prev; + rbuf->prev->next = cell_new; + rbuf->prev = cell_new; + cell_number ++; + cell_new->number = cell_number; + cell_x += dx; + cell_new->x = cell_x; + + cell_new->first = NULL; + cell_new->last = NULL; + } + + right = cell_new; + + n_right += cells_from_next; + n_cells += cells_from_next; + n_part += parts_from_next; + + for(i=0;i<parts_from_next;i++) { + part_new = new ( struct particle ); + if (!(part_new)) bob.error("allocation error"); + part_new->prev = NULL; + part_new->next = right->first; + if (part_new->next!=NULL) right->first->prev = part_new; + else right->last = part_new; + right->first = part_new; + + part_new->cell = right; + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void domain::reo_update_n_el_n_ion( int el_count, int ion_count ) +{ + static error_handler bob("domain::reo_update_n_el_n_ion",errname); + + n_el += el_count; + n_ion += ion_count; + +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void domain::restart_configuration( void ) +{ + error_handler bob("domain::restart_configuration",errname); + + FILE *file; + char fname[ filename_size ]; + struct cell *cell_old, *cell_new, *cell; + struct particle *part; + int i,k; + int n_el_check, n_ion_check, n_part_check; + + sprintf( fname, "%s/%s-%d-data2", path, input.restart_file, domain_number ); + file = fopen( fname, "rb" ); + if (!file) bob.error( "cannot open file", fname ); + + fread( &n_cells, sizeof(int), 1, file ); + + // create chained list of cells: + + Lbuf = new ( struct cell ); + if (!Lbuf) bob.error("allocation error: Lbuf"); + Lbuf->first = NULL; + Lbuf->last = NULL; + + lbuf = new ( struct cell ); + if (!lbuf) bob.error("allocation error: lbuf"); + lbuf->prev = Lbuf; + lbuf->first = NULL; + lbuf->last = NULL; + + left = new ( struct cell ); + if (!left) bob.error("allocation error: left"); + left->prev = lbuf; + left->first = NULL; + left->last = NULL; + + cell_old = left; + + for( i=0; i<n_cells-1; i++ ) + { + cell_new = new ( struct cell ); + if (!cell_new) bob.error("allocation error: cell_new"); + cell_new->prev = cell_old; + cell_new->first = NULL; + cell_new->last = NULL; + cell_old->next = cell_new; + cell_old = cell_new; + } + + right = cell_old; + right->first = NULL; + right->last = NULL; + + rbuf = new ( struct cell ); + if (!rbuf) bob.error("allocation error: rbuf"); + rbuf->prev = right; + rbuf->first = NULL; + rbuf->last = NULL; + + Rbuf = new ( struct cell ); + if (!Rbuf) bob.error("allocation error: Rbuf"); + Rbuf->prev = rbuf; + Rbuf->first = NULL; + Rbuf->last = NULL; + + dummy = new ( struct cell ); + if (!dummy) bob.error("allocation error: dummy"); + dummy->prev = Rbuf; + + right->next = rbuf; + rbuf->next = Rbuf; + Rbuf->next = dummy; + dummy->next = Lbuf; + Lbuf->next = lbuf; + Lbuf->prev = dummy; + lbuf->next = left; + + // read cell information from restart file + // including particles: + + for( cell=Lbuf; cell!=dummy; cell=cell->next ) + { + fread( &cell->number , sizeof(int), 1, file ); + fread( &cell->x , sizeof(double), 1, file ); + fread( &cell->charge , sizeof(double), 1, file ); + fread( &cell->jx , sizeof(double), 1, file ); + fread( &cell->jy , sizeof(double), 1, file ); + fread( &cell->jz , sizeof(double), 1, file ); + fread( &cell->ex , sizeof(double), 1, file ); + fread( &cell->ey , sizeof(double), 1, file ); + fread( &cell->ez , sizeof(double), 1, file ); + fread( &cell->bx , sizeof(double), 1, file ); + fread( &cell->by , sizeof(double), 1, file ); + fread( &cell->bz , sizeof(double), 1, file ); + fread( &cell->fp , sizeof(double), 1, file ); + fread( &cell->fm , sizeof(double), 1, file ); + fread( &cell->gp , sizeof(double), 1, file ); + fread( &cell->gm , sizeof(double), 1, file ); + fread( &(cell->dens[0]), sizeof(double), 1, file ); + fread( &(cell->dens[1]), sizeof(double), 1, file ); + fread( &(cell->np[0]) , sizeof(int), 1, file ); + fread( &(cell->np[1]) , sizeof(int), 1, file ); + fread( &cell->npart , sizeof(int), 1, file ); + + cell->domain = domain_number; + + for(k=0;k<cell->npart;k++) { + + part = new ( struct particle ); + if (!part) bob.error("allocation error"); + + fread( &part->number , sizeof(int), 1, file ); + fread( &part->species, sizeof(int), 1, file ); + fread( &part->fix , sizeof(int), 1, file ); + fread( &part->z , sizeof(double), 1, file ); + fread( &part->m , sizeof(double), 1, file ); + fread( &part->zm , sizeof(double), 1, file ); + fread( &part->x , sizeof(double), 1, file ); + fread( &part->dx , sizeof(double), 1, file ); + fread( &part->igamma , sizeof(double), 1, file ); + fread( &part->ux , sizeof(double), 1, file ); + fread( &part->uy , sizeof(double), 1, file ); + fread( &part->uz , sizeof(double), 1, file ); + fread( &part->zn , sizeof(double), 1, file ); + + part->cell = cell; + part->next = NULL; + part->prev = cell->last; + if (part->prev==NULL) cell->first = part; + if (cell->last!=NULL) cell->last->next = part; + cell->last = part; + + switch (part->species){ + case 0: + n_el ++; + n_part ++; + break; + case 1: + n_ion ++; + n_part ++; + break; + } + + } + } + n_left = left->number; + n_right = right->number; + + fread( &n_el_check, sizeof(int), 1, file ); + fread( &n_ion_check, sizeof(int), 1, file ); + fread( &n_part_check, sizeof(int), 1, file ); + fclose( file ); + + bob.message("n_cells = ", n_cells); + bob.message("n_el = ", n_el); + bob.message("n_ion = ", n_ion); + bob.message("n_part = ", n_part); + + if( n_el_check!=n_el){ + bob.error("n_el incorrect", n_el); + } + if( n_ion_check!=n_ion){ + bob.error("n_ion incorrect"); + } + if( n_part_check!=n_part){ + bob.error("n_part incorrect"); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// +//eof |