Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
TurTLE
TurTLE
Commits
d4227289
Commit
d4227289
authored
Feb 15, 2016
by
Cristian Lalescu
Browse files
Merge branch 'feature/distributed_particles' into develop
parents
c0894829
26a7a8cc
Changes
25
Expand all
Hide whitespace changes
Inline
Side-by-side
bfps/NavierStokes.py
View file @
d4227289
...
@@ -78,7 +78,6 @@ class NavierStokes(_fluid_particle_base):
...
@@ -78,7 +78,6 @@ class NavierStokes(_fluid_particle_base):
hsize_t dims[4];
hsize_t dims[4];
hid_t group;
hid_t group;
hid_t Cspace, Cdset;
hid_t Cspace, Cdset;
int ndims;
// store kspace information
// store kspace information
Cdset = H5Dopen(stat_file, "/kspace/kshell", H5P_DEFAULT);
Cdset = H5Dopen(stat_file, "/kspace/kshell", H5P_DEFAULT);
Cspace = H5Dget_space(Cdset);
Cspace = H5Dget_space(Cdset);
...
@@ -337,8 +336,7 @@ class NavierStokes(_fluid_particle_base):
...
@@ -337,8 +336,7 @@ class NavierStokes(_fluid_particle_base):
def
fill_up_fluid_code
(
self
):
def
fill_up_fluid_code
(
self
):
self
.
fluid_includes
+=
'#include <cstring>
\n
'
self
.
fluid_includes
+=
'#include <cstring>
\n
'
self
.
fluid_variables
+=
(
'fluid_solver<{0}> *fs;
\n
'
.
format
(
self
.
C_dtype
)
+
self
.
fluid_variables
+=
(
'fluid_solver<{0}> *fs;
\n
'
.
format
(
self
.
C_dtype
)
+
'hid_t particle_file;
\n
'
+
'hid_t particle_file;
\n
'
)
'hid_t H5T_field_complex;
\n
'
)
self
.
fluid_definitions
+=
"""
self
.
fluid_definitions
+=
"""
typedef struct {{
typedef struct {{
{0} re;
{0} re;
...
@@ -367,12 +365,6 @@ class NavierStokes(_fluid_particle_base):
...
@@ -367,12 +365,6 @@ class NavierStokes(_fluid_particle_base):
strncpy(fs->forcing_type, forcing_type, 128);
strncpy(fs->forcing_type, forcing_type, 128);
fs->iteration = iteration;
fs->iteration = iteration;
fs->read('v', 'c');
fs->read('v', 'c');
if (fs->cd->myrank == 0)
{{
H5T_field_complex = H5Tcreate(H5T_COMPOUND, sizeof(tmp_complex_type));
H5Tinsert(H5T_field_complex, "r", HOFFSET(tmp_complex_type, re), {2});
H5Tinsert(H5T_field_complex, "i", HOFFSET(tmp_complex_type, im), {2});
}}
//endcpp
//endcpp
"""
.
format
(
self
.
C_dtype
,
self
.
fftw_plan_rigor
,
field_H5T
)
"""
.
format
(
self
.
C_dtype
,
self
.
fftw_plan_rigor
,
field_H5T
)
if
self
.
parameters
[
'nparticles'
]
>
0
:
if
self
.
parameters
[
'nparticles'
]
>
0
:
...
@@ -395,13 +387,12 @@ class NavierStokes(_fluid_particle_base):
...
@@ -395,13 +387,12 @@ class NavierStokes(_fluid_particle_base):
self
.
fluid_output
+
'
\n
}
\n
'
)
self
.
fluid_output
+
'
\n
}
\n
'
)
self
.
fluid_end
=
(
'if (fs->iteration % niter_out != 0)
\n
{
\n
'
+
self
.
fluid_end
=
(
'if (fs->iteration % niter_out != 0)
\n
{
\n
'
+
self
.
fluid_output
+
'
\n
}
\n
'
+
self
.
fluid_output
+
'
\n
}
\n
'
+
'if (fs->cd->myrank == 0)
\n
'
+
'{
\n
'
+
'H5Tclose(H5T_field_complex);
\n
'
+
'}
\n
'
+
'delete fs;
\n
'
)
'delete fs;
\n
'
)
if
self
.
parameters
[
'nparticles'
]
>
0
:
if
self
.
parameters
[
'nparticles'
]
>
0
:
self
.
fluid_end
+=
'H5Fclose(particle_file);
\n
'
self
.
fluid_end
+=
(
'if (myrank == 0)
\n
'
+
'{
\n
'
+
'H5Fclose(particle_file);
\n
'
+
'}
\n
'
)
return
None
return
None
def
add_3D_rFFTW_field
(
def
add_3D_rFFTW_field
(
self
,
self
,
...
@@ -420,10 +411,11 @@ class NavierStokes(_fluid_particle_base):
...
@@ -420,10 +411,11 @@ class NavierStokes(_fluid_particle_base):
neighbours
=
1
,
neighbours
=
1
,
smoothness
=
1
,
smoothness
=
1
,
name
=
'field_interpolator'
,
name
=
'field_interpolator'
,
field_name
=
'fs->rvelocity'
):
field_name
=
'fs->rvelocity'
,
self
.
fluid_includes
+=
'#include "rFFTW_interpolator.hpp"
\n
'
class_name
=
'rFFTW_interpolator'
):
self
.
fluid_variables
+=
'rFFTW_interpolator <{0}, {1}> *{2};
\n
'
.
format
(
self
.
fluid_includes
+=
'#include "{0}.hpp"
\n
'
.
format
(
class_name
)
self
.
C_dtype
,
neighbours
,
name
)
self
.
fluid_variables
+=
'{0} <{1}, {2}> *{3};
\n
'
.
format
(
class_name
,
self
.
C_dtype
,
neighbours
,
name
)
self
.
parameters
[
name
+
'_type'
]
=
interp_type
self
.
parameters
[
name
+
'_type'
]
=
interp_type
self
.
parameters
[
name
+
'_neighbours'
]
=
neighbours
self
.
parameters
[
name
+
'_neighbours'
]
=
neighbours
if
interp_type
==
'spline'
:
if
interp_type
==
'spline'
:
...
@@ -431,8 +423,9 @@ class NavierStokes(_fluid_particle_base):
...
@@ -431,8 +423,9 @@ class NavierStokes(_fluid_particle_base):
beta_name
=
'beta_n{0}_m{1}'
.
format
(
neighbours
,
smoothness
)
beta_name
=
'beta_n{0}_m{1}'
.
format
(
neighbours
,
smoothness
)
elif
interp_type
==
'Lagrange'
:
elif
interp_type
==
'Lagrange'
:
beta_name
=
'beta_Lagrange_n{0}'
.
format
(
neighbours
)
beta_name
=
'beta_Lagrange_n{0}'
.
format
(
neighbours
)
self
.
fluid_start
+=
'{0} = new
rFFTW_interpolator
<{
1
}, {
2
}>(fs, {
3
}, {
4
});
\n
'
.
format
(
self
.
fluid_start
+=
'{0} = new
{1}
<{
2
}, {
3
}>(fs, {
4
}, {
5
});
\n
'
.
format
(
name
,
name
,
class_name
,
self
.
C_dtype
,
self
.
C_dtype
,
neighbours
,
neighbours
,
beta_name
,
beta_name
,
...
@@ -445,7 +438,8 @@ class NavierStokes(_fluid_particle_base):
...
@@ -445,7 +438,8 @@ class NavierStokes(_fluid_particle_base):
kcut
=
None
,
kcut
=
None
,
interpolator
=
'field_interpolator'
,
interpolator
=
'field_interpolator'
,
frozen_particles
=
False
,
frozen_particles
=
False
,
acc_name
=
None
):
acc_name
=
None
,
class_name
=
'particles'
):
"""Adds code for tracking a series of particle species, each
"""Adds code for tracking a series of particle species, each
consisting of `nparticles` particles.
consisting of `nparticles` particles.
...
@@ -493,7 +487,7 @@ class NavierStokes(_fluid_particle_base):
...
@@ -493,7 +487,7 @@ class NavierStokes(_fluid_particle_base):
self
.
parameters
[
'tracers{0}_integration_steps'
.
format
(
s0
+
s
)]
=
integration_steps
[
s
]
self
.
parameters
[
'tracers{0}_integration_steps'
.
format
(
s0
+
s
)]
=
integration_steps
[
s
]
self
.
file_datasets_grow
+=
"""
self
.
file_datasets_grow
+=
"""
//begincpp
//begincpp
group = H5Gopen(particle_file, ps{0}->name, H5P_DEFAULT);
group = H5Gopen(particle_file, ps{0}->
get_
name
()
, H5P_DEFAULT);
grow_particle_datasets(group, "", NULL, NULL);
grow_particle_datasets(group, "", NULL, NULL);
H5Gclose(group);
H5Gclose(group);
//endcpp
//endcpp
...
@@ -504,39 +498,26 @@ class NavierStokes(_fluid_particle_base):
...
@@ -504,39 +498,26 @@ class NavierStokes(_fluid_particle_base):
# array for putting sampled velocity in
# array for putting sampled velocity in
# must compute velocity, just in case it was messed up by some
# must compute velocity, just in case it was messed up by some
# other particle species before the stats
# other particle species before the stats
output_vel_acc
+=
(
'double *velocity = new double[3*nparticles];
\n
'
+
output_vel_acc
+=
'fs->compute_velocity(fs->cvorticity);
\n
'
'fs->compute_velocity(fs->cvorticity);
\n
'
)
if
not
type
(
kcut
)
==
list
:
if
not
type
(
kcut
)
==
list
:
output_vel_acc
+=
'fs->ift_velocity();
\n
'
output_vel_acc
+=
'fs->ift_velocity();
\n
'
if
not
type
(
acc_name
)
==
type
(
None
):
if
not
type
(
acc_name
)
==
type
(
None
):
# array for putting sampled acceleration in
# array for putting sampled acceleration in
# must compute acceleration
# must compute acceleration
output_vel_acc
+=
'double *acceleration = new double[3*nparticles];
\n
'
output_vel_acc
+=
'fs->compute_Lagrangian_acceleration({0});
\n
'
.
format
(
acc_name
)
output_vel_acc
+=
'fs->compute_Lagrangian_acceleration({0});
\n
'
.
format
(
acc_name
)
for
s
in
range
(
nspecies
):
for
s
in
range
(
nspecies
):
if
type
(
kcut
)
==
list
:
if
type
(
kcut
)
==
list
:
output_vel_acc
+=
'fs->low_pass_Fourier(fs->cvelocity, 3, {0});
\n
'
.
format
(
kcut
[
s
])
output_vel_acc
+=
'fs->low_pass_Fourier(fs->cvelocity, 3, {0});
\n
'
.
format
(
kcut
[
s
])
output_vel_acc
+=
'fs->ift_velocity();
\n
'
output_vel_acc
+=
'fs->ift_velocity();
\n
'
output_vel_acc
+=
"""
output_vel_acc
+=
"""
{0}->
field =
fs->rvelocity;
{0}->
read_rFFTW(
fs->rvelocity
)
;
ps{1}->sample
_vec_field
({0}, velocity);
ps{1}->sample({0},
"
velocity
"
);
"""
.
format
(
interpolator
[
s
],
s0
+
s
)
"""
.
format
(
interpolator
[
s
],
s0
+
s
)
if
not
type
(
acc_name
)
==
type
(
None
):
if
not
type
(
acc_name
)
==
type
(
None
):
output_vel_acc
+=
"""
output_vel_acc
+=
"""
{0}->
field =
{1};
{0}->
read_rFFTW(
{1}
)
;
ps{2}->sample
_vec_field
({0}, acceleration);
ps{2}->sample({0},
"
acceleration
"
);
"""
.
format
(
interpolator
[
s
],
acc_name
,
s0
+
s
)
"""
.
format
(
interpolator
[
s
],
acc_name
,
s0
+
s
)
output_vel_acc
+=
(
'if (myrank == 0)
\n
'
+
'{
\n
'
+
'ps{0}->write(particle_file, "velocity", velocity);
\n
'
.
format
(
s0
+
s
))
if
not
type
(
acc_name
)
==
type
(
None
):
output_vel_acc
+=
(
'ps{0}->write(particle_file, "acceleration", acceleration);
\n
'
.
format
(
s0
+
s
))
output_vel_acc
+=
'}
\n
'
output_vel_acc
+=
'delete[] velocity;
\n
'
if
not
type
(
acc_name
)
==
type
(
None
):
output_vel_acc
+=
'delete[] acceleration;
\n
'
output_vel_acc
+=
'}
\n
'
output_vel_acc
+=
'}
\n
'
#### initialize, stepping and finalize code
#### initialize, stepping and finalize code
...
@@ -547,38 +528,39 @@ class NavierStokes(_fluid_particle_base):
...
@@ -547,38 +528,39 @@ class NavierStokes(_fluid_particle_base):
self
.
particle_loop
+=
update_fields
self
.
particle_loop
+=
update_fields
else
:
else
:
self
.
particle_loop
+=
'fs->compute_velocity(fs->cvorticity);
\n
'
self
.
particle_loop
+=
'fs->compute_velocity(fs->cvorticity);
\n
'
self
.
particle_includes
+=
'#include "
rFFTW_particles.hpp"
\n
'
self
.
particle_includes
+=
'#include "
{0}.hpp"
\n
'
.
format
(
class_name
)
self
.
particle_stat_src
+=
(
self
.
particle_stat_src
+=
(
'if (ps0->iteration % niter_part == 0)
\n
'
+
'if (ps0->iteration % niter_part == 0)
\n
'
+
'{
\n
'
)
'{
\n
'
)
for
s
in
range
(
nspecies
):
for
s
in
range
(
nspecies
):
neighbours
=
self
.
parameters
[
interpolator
[
s
]
+
'_neighbours'
]
neighbours
=
self
.
parameters
[
interpolator
[
s
]
+
'_neighbours'
]
self
.
particle_start
+=
'sprintf(fname, "tracers{0}");
\n
'
.
format
(
s0
+
s
)
self
.
particle_start
+=
'sprintf(fname, "tracers{0}");
\n
'
.
format
(
s0
+
s
)
self
.
particle_end
+=
(
'ps{0}->write(
particle_file
);
\n
'
+
self
.
particle_end
+=
(
'ps{0}->write();
\n
'
+
'delete ps{0};
\n
'
).
format
(
s0
+
s
)
'delete ps{0};
\n
'
).
format
(
s0
+
s
)
self
.
particle_variables
+=
'rFFTW_particles<VELOCITY_TRACER, {0}, {1}> *ps{2};
\n
'
.
format
(
self
.
particle_variables
+=
'{0}<VELOCITY_TRACER, {1}, {2}> *ps{3};
\n
'
.
format
(
class_name
,
self
.
C_dtype
,
self
.
C_dtype
,
neighbours
,
neighbours
,
s0
+
s
)
s0
+
s
)
self
.
particle_start
+=
(
'ps{0} = new rFFTW_particles<VELOCITY_TRACER, {1}, {2}>(
\n
'
+
self
.
particle_start
+=
(
'ps{0} = new {1}<VELOCITY_TRACER, {2}, {3}>(
\n
'
+
'fname, {3},
\n
'
+
'fname, particle_file, {4},
\n
'
+
'nparticles,
\n
'
+
'niter_part, tracers{0}_integration_steps);
\n
'
).
format
(
'niter_part, tracers{0}_integration_steps);
\n
'
).
format
(
s0
+
s
,
s0
+
s
,
class_name
,
self
.
C_dtype
,
self
.
C_dtype
,
neighbours
,
neighbours
,
interpolator
[
s
])
interpolator
[
s
])
self
.
particle_start
+=
(
'ps{0}->dt = dt;
\n
'
+
self
.
particle_start
+=
(
'ps{0}->dt = dt;
\n
'
+
'ps{0}->iteration = iteration;
\n
'
+
'ps{0}->iteration = iteration;
\n
'
+
'ps{0}->read(
particle_file
);
\n
'
).
format
(
s0
+
s
)
'ps{0}->read();
\n
'
).
format
(
s0
+
s
)
if
not
frozen_particles
:
if
not
frozen_particles
:
if
type
(
kcut
)
==
list
:
if
type
(
kcut
)
==
list
:
update_field
=
(
'fs->low_pass_Fourier(fs->cvelocity, 3, {0});
\n
'
.
format
(
kcut
[
s
])
+
update_field
=
(
'fs->low_pass_Fourier(fs->cvelocity, 3, {0});
\n
'
.
format
(
kcut
[
s
])
+
'fs->ift_velocity();
\n
'
)
'fs->ift_velocity();
\n
'
)
self
.
particle_loop
+=
update_field
self
.
particle_loop
+=
update_field
self
.
particle_loop
+=
'{0}->
field =
fs->rvelocity;
\n
'
.
format
(
interpolator
[
s
])
self
.
particle_loop
+=
'{0}->
read_rFFTW(
fs->rvelocity
)
;
\n
'
.
format
(
interpolator
[
s
])
self
.
particle_loop
+=
'ps{0}->step();
\n
'
.
format
(
s0
+
s
)
self
.
particle_loop
+=
'ps{0}->step();
\n
'
.
format
(
s0
+
s
)
self
.
particle_stat_src
+=
'ps{0}->write(
particle_file,
false);
\n
'
.
format
(
s0
+
s
)
self
.
particle_stat_src
+=
'ps{0}->write(false);
\n
'
.
format
(
s0
+
s
)
self
.
particle_stat_src
+=
output_vel_acc
self
.
particle_stat_src
+=
output_vel_acc
self
.
particle_stat_src
+=
'}
\n
'
self
.
particle_stat_src
+=
'}
\n
'
self
.
particle_species
+=
nspecies
self
.
particle_species
+=
nspecies
...
@@ -898,9 +880,7 @@ class NavierStokes(_fluid_particle_base):
...
@@ -898,9 +880,7 @@ class NavierStokes(_fluid_particle_base):
with
h5py
.
File
(
self
.
get_particle_file_name
(),
'a'
)
as
ofile
:
with
h5py
.
File
(
self
.
get_particle_file_name
(),
'a'
)
as
ofile
:
for
s
in
range
(
self
.
particle_species
):
for
s
in
range
(
self
.
particle_species
):
ofile
.
create_group
(
'tracers{0}'
.
format
(
s
))
ofile
.
create_group
(
'tracers{0}'
.
format
(
s
))
time_chunk
=
2
**
20
//
(
8
*
3
*
time_chunk
=
2
**
20
//
(
8
*
3
*
self
.
parameters
[
'nparticles'
])
self
.
parameters
[
'nparticles'
]
*
self
.
parameters
[
'tracers{0}_integration_steps'
.
format
(
s
)])
time_chunk
=
max
(
time_chunk
,
1
)
time_chunk
=
max
(
time_chunk
,
1
)
dims
=
(
1
,
dims
=
(
1
,
self
.
parameters
[
'tracers{0}_integration_steps'
.
format
(
s
)],
self
.
parameters
[
'tracers{0}_integration_steps'
.
format
(
s
)],
...
@@ -911,15 +891,13 @@ class NavierStokes(_fluid_particle_base):
...
@@ -911,15 +891,13 @@ class NavierStokes(_fluid_particle_base):
self
.
parameters
[
'nparticles'
],
self
.
parameters
[
'nparticles'
],
3
)
3
)
chunks
=
(
time_chunk
,
chunks
=
(
time_chunk
,
self
.
parameters
[
'tracers{0}_integration_steps'
.
format
(
s
)]
,
1
,
self
.
parameters
[
'nparticles'
],
self
.
parameters
[
'nparticles'
],
3
)
3
)
create_particle_dataset
(
create_particle_dataset
(
ofile
,
ofile
,
'/tracers{0}/rhs'
.
format
(
s
),
'/tracers{0}/rhs'
.
format
(
s
),
dims
,
maxshape
,
chunks
)
dims
,
maxshape
,
chunks
)
time_chunk
=
2
**
20
//
(
8
*
3
*
self
.
parameters
[
'nparticles'
])
time_chunk
=
max
(
time_chunk
,
1
)
create_particle_dataset
(
create_particle_dataset
(
ofile
,
ofile
,
'/tracers{0}/state'
.
format
(
s
),
'/tracers{0}/state'
.
format
(
s
),
...
...
bfps/_fluid_base.py
View file @
d4227289
...
@@ -102,13 +102,15 @@ class _fluid_particle_base(_code):
...
@@ -102,13 +102,15 @@ class _fluid_particle_base(_code):
self
.
definitions
+=
self
.
particle_definitions
self
.
definitions
+=
self
.
particle_definitions
self
.
definitions
+=
(
'int grow_single_dataset(hid_t dset, int tincrement)
\n
{
\n
'
+
self
.
definitions
+=
(
'int grow_single_dataset(hid_t dset, int tincrement)
\n
{
\n
'
+
'int ndims;
\n
'
+
'int ndims;
\n
'
+
'hsize_t dims[5];
\n
'
+
'hsize_t space;
\n
'
+
'hsize_t space;
\n
'
+
'space = H5Dget_space(dset);
\n
'
+
'space = H5Dget_space(dset);
\n
'
+
'ndims = H5Sget_simple_extent_dims(space, dims, NULL);
\n
'
+
'ndims = H5Sget_simple_extent_ndims(space);
\n
'
+
'hsize_t *dims = new hsize_t[ndims];
\n
'
+
'H5Sget_simple_extent_dims(space, dims, NULL);
\n
'
+
'dims[0] += tincrement;
\n
'
+
'dims[0] += tincrement;
\n
'
+
'H5Dset_extent(dset, dims);
\n
'
+
'H5Dset_extent(dset, dims);
\n
'
+
'H5Sclose(space);
\n
'
+
'H5Sclose(space);
\n
'
+
'delete[] dims;
\n
'
+
'return EXIT_SUCCESS;
\n
}
\n
'
)
'return EXIT_SUCCESS;
\n
}
\n
'
)
self
.
definitions
+=
(
'herr_t grow_statistics_dataset(hid_t o_id, const char *name, const H5O_info_t *info, void *op_data)
\n
{
\n
'
+
self
.
definitions
+=
(
'herr_t grow_statistics_dataset(hid_t o_id, const char *name, const H5O_info_t *info, void *op_data)
\n
{
\n
'
+
'if (info->type == H5O_TYPE_DATASET)
\n
{
\n
'
+
'if (info->type == H5O_TYPE_DATASET)
\n
{
\n
'
+
...
...
bfps/cpp/distributed_particles.cpp
0 → 100644
View file @
d4227289
/**********************************************************************
* *
* Copyright 2015 Max Planck Institute *
* for Dynamics and Self-Organization *
* *
* This file is part of bfps. *
* *
* bfps 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 3 of the License, *
* or (at your option) any later version. *
* *
* bfps 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 bfps. If not, see <http://www.gnu.org/licenses/> *
* *
* Contact: Cristian.Lalescu@ds.mpg.de *
* *
**********************************************************************/
#define NDEBUG
#include <cmath>
#include <cassert>
#include <cstring>
#include <string>
#include <sstream>
#include "base.hpp"
#include "distributed_particles.hpp"
#include "fftw_tools.hpp"
extern
int
myrank
,
nprocs
;
template
<
int
particle_type
,
class
rnumber
,
int
interp_neighbours
>
distributed_particles
<
particle_type
,
rnumber
,
interp_neighbours
>::
distributed_particles
(
const
char
*
NAME
,
const
hid_t
data_file_id
,
interpolator
<
rnumber
,
interp_neighbours
>
*
FIELD
,
const
int
TRAJ_SKIP
,
const
int
INTEGRATION_STEPS
)
:
particles_io_base
<
particle_type
>
(
NAME
,
TRAJ_SKIP
,
data_file_id
,
FIELD
->
descriptor
->
comm
)
{
assert
((
INTEGRATION_STEPS
<=
6
)
&&
(
INTEGRATION_STEPS
>=
1
));
this
->
vel
=
FIELD
;
this
->
rhs
.
resize
(
INTEGRATION_STEPS
);
this
->
integration_steps
=
INTEGRATION_STEPS
;
}
template
<
int
particle_type
,
class
rnumber
,
int
interp_neighbours
>
distributed_particles
<
particle_type
,
rnumber
,
interp_neighbours
>::~
distributed_particles
()
{
}
template
<
int
particle_type
,
class
rnumber
,
int
interp_neighbours
>
void
distributed_particles
<
particle_type
,
rnumber
,
interp_neighbours
>::
sample
(
interpolator
<
rnumber
,
interp_neighbours
>
*
field
,
std
::
unordered_map
<
int
,
single_particle_state
<
POINT3D
>>
&
y
)
{
double
*
yy
=
new
double
[
3
];
y
.
clear
();
for
(
auto
&
pp
:
this
->
state
)
{
(
*
field
)(
pp
.
second
.
data
,
yy
);
y
[
pp
.
first
]
=
yy
;
}
delete
[]
yy
;
}
template
<
int
particle_type
,
class
rnumber
,
int
interp_neighbours
>
void
distributed_particles
<
particle_type
,
rnumber
,
interp_neighbours
>::
get_rhs
(
const
std
::
unordered_map
<
int
,
single_particle_state
<
particle_type
>>
&
x
,
std
::
unordered_map
<
int
,
single_particle_state
<
particle_type
>>
&
y
)
{
double
*
yy
=
new
double
[
this
->
ncomponents
];
y
.
clear
();
for
(
auto
&
pp
:
x
)
{
(
*
this
->
vel
)(
pp
.
second
.
data
,
yy
);
y
[
pp
.
first
]
=
yy
;
}
delete
[]
yy
;
}
template
<
int
particle_type
,
class
rnumber
,
int
interp_neighbours
>
void
distributed_particles
<
particle_type
,
rnumber
,
interp_neighbours
>::
sample
(
interpolator
<
rnumber
,
interp_neighbours
>
*
field
,
const
char
*
dset_name
)
{
std
::
unordered_map
<
int
,
single_particle_state
<
POINT3D
>>
y
;
this
->
sample
(
field
,
y
);
this
->
write
(
dset_name
,
y
);
}
template
<
int
particle_type
,
class
rnumber
,
int
interp_neighbours
>
void
distributed_particles
<
particle_type
,
rnumber
,
interp_neighbours
>::
roll_rhs
()
{
for
(
int
i
=
this
->
integration_steps
-
2
;
i
>=
0
;
i
--
)
rhs
[
i
+
1
]
=
rhs
[
i
];
}
template
<
int
particle_type
,
class
rnumber
,
int
interp_neighbours
>
void
distributed_particles
<
particle_type
,
rnumber
,
interp_neighbours
>::
redistribute
(
std
::
unordered_map
<
int
,
single_particle_state
<
particle_type
>>
&
x
,
std
::
vector
<
std
::
unordered_map
<
int
,
single_particle_state
<
particle_type
>>>
&
vals
)
{
//DEBUG_MSG("entered redistribute\n");
/* neighbouring rank offsets */
int
ro
[
2
];
ro
[
0
]
=
-
1
;
ro
[
1
]
=
1
;
/* neighbouring ranks */
int
nr
[
2
];
nr
[
0
]
=
MOD
(
this
->
myrank
+
ro
[
0
],
this
->
nprocs
);
nr
[
1
]
=
MOD
(
this
->
myrank
+
ro
[
1
],
this
->
nprocs
);
/* particles to send, particles to receive */
std
::
vector
<
int
>
ps
[
2
],
pr
[
2
];
/* number of particles to send, number of particles to receive */
int
nps
[
2
],
npr
[
2
];
int
rsrc
,
rdst
;
/* get list of id-s to send */
for
(
auto
&
pp
:
x
)
for
(
int
i
=
0
;
i
<
2
;
i
++
)
if
(
this
->
vel
->
get_rank
(
pp
.
second
.
data
[
2
])
==
nr
[
i
])
ps
[
i
].
push_back
(
pp
.
first
);
/* prepare data for send recv */
for
(
int
i
=
0
;
i
<
2
;
i
++
)
nps
[
i
]
=
ps
[
i
].
size
();
for
(
rsrc
=
0
;
rsrc
<
this
->
nprocs
;
rsrc
++
)
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
rdst
=
MOD
(
rsrc
+
ro
[
i
],
this
->
nprocs
);
if
(
this
->
myrank
==
rsrc
)
MPI_Send
(
nps
+
i
,
1
,
MPI_INTEGER
,
rdst
,
2
*
(
rsrc
*
this
->
nprocs
+
rdst
)
+
i
,
this
->
comm
);
if
(
this
->
myrank
==
rdst
)
MPI_Recv
(
npr
+
1
-
i
,
1
,
MPI_INTEGER
,
rsrc
,
2
*
(
rsrc
*
this
->
nprocs
+
rdst
)
+
i
,
this
->
comm
,
MPI_STATUS_IGNORE
);
}
//DEBUG_MSG("I have to send %d %d particles\n", nps[0], nps[1]);
//DEBUG_MSG("I have to recv %d %d particles\n", npr[0], npr[1]);
for
(
int
i
=
0
;
i
<
2
;
i
++
)
pr
[
i
].
resize
(
npr
[
i
]);
int
buffer_size
=
(
nps
[
0
]
>
nps
[
1
])
?
nps
[
0
]
:
nps
[
1
];
buffer_size
=
(
buffer_size
>
npr
[
0
])
?
buffer_size
:
npr
[
0
];
buffer_size
=
(
buffer_size
>
npr
[
1
])
?
buffer_size
:
npr
[
1
];
//DEBUG_MSG("buffer size is %d\n", buffer_size);
double
*
buffer
=
new
double
[
buffer_size
*
this
->
ncomponents
*
(
1
+
vals
.
size
())];
for
(
rsrc
=
0
;
rsrc
<
this
->
nprocs
;
rsrc
++
)
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
rdst
=
MOD
(
rsrc
+
ro
[
i
],
this
->
nprocs
);
if
(
this
->
myrank
==
rsrc
&&
nps
[
i
]
>
0
)
{
MPI_Send
(
&
ps
[
i
].
front
(),
nps
[
i
],
MPI_INTEGER
,
rdst
,
2
*
(
rsrc
*
this
->
nprocs
+
rdst
),
this
->
comm
);
int
pcounter
=
0
;
for
(
int
p
:
ps
[
i
])
{
std
::
copy
(
x
[
p
].
data
,
x
[
p
].
data
+
this
->
ncomponents
,
buffer
+
pcounter
*
(
1
+
vals
.
size
())
*
this
->
ncomponents
);
x
.
erase
(
p
);
for
(
int
tindex
=
0
;
tindex
<
vals
.
size
();
tindex
++
)
{
std
::
copy
(
vals
[
tindex
][
p
].
data
,
vals
[
tindex
][
p
].
data
+
this
->
ncomponents
,
buffer
+
(
pcounter
*
(
1
+
vals
.
size
())
+
tindex
+
1
)
*
this
->
ncomponents
);
vals
[
tindex
].
erase
(
p
);
}
pcounter
++
;
}
MPI_Send
(
buffer
,
nps
[
i
]
*
(
1
+
vals
.
size
())
*
this
->
ncomponents
,
MPI_DOUBLE
,
rdst
,
2
*
(
rsrc
*
this
->
nprocs
+
rdst
)
+
1
,
this
->
comm
);
}
if
(
this
->
myrank
==
rdst
&&
npr
[
1
-
i
]
>
0
)
{
MPI_Recv
(
&
pr
[
1
-
i
].
front
(),
npr
[
1
-
i
],
MPI_INTEGER
,
rsrc
,
2
*
(
rsrc
*
this
->
nprocs
+
rdst
),
this
->
comm
,
MPI_STATUS_IGNORE
);
MPI_Recv
(
buffer
,
npr
[
1
-
i
]
*
(
1
+
vals
.
size
())
*
this
->
ncomponents
,
MPI_DOUBLE
,
rsrc
,
2
*
(
rsrc
*
this
->
nprocs
+
rdst
)
+
1
,
this
->
comm
,
MPI_STATUS_IGNORE
);
int
pcounter
=
0
;
for
(
int
p
:
pr
[
1
-
i
])
{
x
[
p
]
=
buffer
+
(
pcounter
*
(
1
+
vals
.
size
()))
*
this
->
ncomponents
;
for
(
int
tindex
=
0
;
tindex
<
vals
.
size
();
tindex
++
)
{
vals
[
tindex
][
p
]
=
buffer
+
(
pcounter
*
(
1
+
vals
.
size
())
+
tindex
+
1
)
*
this
->
ncomponents
;
}
pcounter
++
;
}
}
}
delete
[]
buffer
;
#ifndef NDEBUG
/* check that all particles at x are local */
for
(
auto
&
pp
:
x
)
if
(
this
->
vel
->
get_rank
(
pp
.
second
.
data
[
2
])
!=
this
->
myrank
)
{
DEBUG_MSG
(
"found particle %d with rank %d
\n
"
,
pp
.
first
,
this
->
vel
->
get_rank
(
pp
.
second
.
data
[
2
]));
assert
(
false
);
}
#endif
//DEBUG_MSG("exiting redistribute\n");
}
template
<
int
particle_type
,
class
rnumber
,
int
interp_neighbours
>
void
distributed_particles
<
particle_type
,
rnumber
,
interp_neighbours
>::
AdamsBashforth
(
const
int
nsteps
)
{
this
->
get_rhs
(
this
->
state
,
this
->
rhs
[
0
]);
for
(
auto
&
pp
:
this
->
state
)
for
(
int
i
=
0
;
i
<
this
->
ncomponents
;
i
++
)
switch
(
nsteps
)
{