aboutsummaryrefslogtreecommitdiff
path: root/Exec/test_particle_injection/inject_particles.cpp
blob: 56d12fef47e59f8698b766845f635dd07273c866 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

#include <random>
#include <algorithm>

#include <WarpX.H>
#include <WarpXWrappers.h>

using namespace amrex;

namespace {
    void make_particles (Array<Real>& x, Array<Real>& y, Array<Real>& z,
			 Array<Real>& vx, Array<Real>& vy, Array<Real>& vz,
			 Array<Real>& w);
}

void inject_particles ()
{
    Array<Real> x, y, z, vx, vy, vz, w;
    make_particles(x, y, z, vx, vy, vz, w);

    int nattr = 1;
    int uniqueparticles = 1;

    addNParticles(0, x.size(), x.data(), y.data(), z.data(), vx.data(), vy.data(), vz.data(),
		  nattr, w.data(), uniqueparticles);
}

namespace
{
    void make_particles (Array<Real>& x, Array<Real>& y, Array<Real>& z,
			 Array<Real>& vx, Array<Real>& vy, Array<Real>& vz,
			 Array<Real>& w)
    {
	static std::mt19937 rand_eng(42+ParallelDescriptor::MyProc());
	static std::uniform_real_distribution<Real> rand_real(0.0,1.0);
	static std::poisson_distribution<> rand_int(0.5);
	
	auto& warpx = WarpX::GetInstance();

	static bool first = true;
	static BoxArray ba;
	static Array<int> procmap;

	const Real weight = 1.57;

	if (first)
	{
	    first = false;

	    const Geometry& geom = warpx.Geom(0);
	    const Box& domain = geom.Domain();
	    
	    ba = BoxArray{domain};
	    const int nprocs = ParallelDescriptor::NProcs();
	    // chopping grids into at least nprocs pieces
	    IntVect chunk(domain.size());
	    while (ba.size() < nprocs)
	    {
		for (int j = BL_SPACEDIM-1; j >= 0 ; j--)
		{
		    chunk[j] /= 2;
		    
		    if (ba.size() < nprocs) {
			ba.maxSize(chunk);
		    }
		}
	    }
	
	    DistributionMapping dm {ba, nprocs};
	    procmap.assign(dm.ProcessorMap().begin(), dm.ProcessorMap().begin()+ba.size());
	}

	// To make things more interesting, let's permutate it everytime;.
	std::next_permutation(procmap.begin(), procmap.end());

	const int myproc = ParallelDescriptor::MyProc();

	const Geometry& geom = warpx.Geom(0);
	const Real* problo = geom.ProbLo();
	const Real* dx = geom.CellSize();

	for (int i = 0, n = ba.size(); i < n; ++i)
	{
	    if (procmap[i] == myproc)
	    {
		const Box& bx = ba[i];
		for (IntVect cell = bx.smallEnd(); cell <= bx.bigEnd(); bx.next(cell))
		{
		    Real x0 = problo[0] + cell[0]*dx[0];
		    Real y0 = problo[1] + cell[1]*dx[1];
		    Real z0 = problo[2] + cell[2]*dx[2];
		    // number of particles to add to this cell
		    int np = rand_int(rand_eng);
		    for (int ip = 0; ip < np; ++ip)
		    {
			x.push_back(x0 + dx[0]*rand_real(rand_eng));
			y.push_back(x0 + dx[1]*rand_real(rand_eng));
			z.push_back(x0 + dx[2]*rand_real(rand_eng));
			Real vxt,vyt,vzt,v2;
			do {
			    vxt = rand_real(rand_eng);
			    vyt = rand_real(rand_eng);
			    vzt = rand_real(rand_eng);
			    v2 = vxt*vxt + vyt*vyt + vzt*vzt;
			} while(v2 >= 0.999999);
			Real gam = 1.0/sqrt(1.0-v2);
			vx.push_back(vxt*gam);
			vy.push_back(vyt*gam);
			vz.push_back(vzt*gam);
			w.push_back(weight);
		    }
		}
	    }
	}
    }
}