6 #ifndef SRC_DRIVER_SWARM_H_ 7 #define SRC_DRIVER_SWARM_H_ 15 #include <type_traits> 27 #ifdef PORTAGE_ENABLE_MPI 47 template <
template <
int,
class,
class>
class Search,
48 template <
int,
class,
class>
class Accumulate,
49 template<
int,
class>
class Estimate,
51 class SourceSwarm,
class SourceState,
52 class TargetSwarm = SourceSwarm,
53 class TargetState = SourceState>
78 SourceState& source_state,
79 TargetSwarm
const& target_swarm,
80 TargetState& target_state,
84 WeightCenter
const center=Gather)
85 : source_swarm_(source_swarm),
86 target_swarm_(target_swarm),
87 source_state_(source_state),
88 target_state_(target_state),
89 smoothing_lengths_(smoothing_lengths) {
91 assert(dim == source_swarm.space_dimension());
92 assert(dim == target_swarm.space_dimension());
93 weight_center_ = center;
122 SourceState& source_state,
123 TargetSwarm
const& target_swarm,
124 TargetState& target_state,
128 WeightCenter
const center = Gather)
129 : source_swarm_(source_swarm),
130 target_swarm_(target_swarm),
131 source_state_(source_state),
132 target_state_(target_state),
133 smoothing_lengths_(smoothing_lengths),
134 kernel_types_(kernel_types),
135 geom_types_(geom_types) {
137 assert(dim == source_swarm.space_dimension());
138 assert(dim == target_swarm.space_dimension());
139 weight_center_ = center;
168 SourceState& source_state,
169 TargetSwarm
const& target_swarm,
170 TargetState& target_state,
174 WeightCenter
const center = Gather)
175 : source_swarm_(source_swarm),
176 target_swarm_(target_swarm),
177 source_state_(source_state),
178 target_state_(target_state),
179 smoothing_lengths_(smoothing_lengths) {
181 assert(dim == source_swarm.space_dimension());
182 assert(dim == target_swarm.space_dimension());
183 weight_center_ = center;
188 int const nb_source = source_swarm_.num_particles(Wonton::PARALLEL_OWNED);
189 int const nb_target = target_swarm_.num_particles(Wonton::PARALLEL_OWNED);
191 switch (weight_center_) {
192 case Gather: assert(target_extents.size() == unsigned(nb_target));
break;
193 case Scatter: assert(source_extents.size() == unsigned(nb_source));
break;
194 default:
throw std::runtime_error(
"invalid weight center type");
197 assert(smoothing_lengths.size() == unsigned(swarm_size));
202 source_extents_ = source_extents;
203 target_extents_ = target_extents;
248 EstimateType
const estimator_type = LocalRegression,
253 std::string part_field =
"NONE",
254 double part_tolerance = 0.0,
257 assert(source_vars.size() == target_vars.size());
263 estimator_type_ = estimator_type;
264 basis_type_ = basis_type;
265 operator_spec_ = operator_spec;
266 operator_domains_ = operator_domains;
267 operator_data_ = operator_data;
270 unsigned const num_target_particles = target_swarm_.num_owned_particles();
271 assert(operator_domains_.size() == num_target_particles);
272 assert(operator_data_.size() == num_target_particles);
276 part_field_ = part_field;
277 part_tolerance_ = part_tolerance;
278 part_smoothing_ = part_smoothing;
286 std::vector<std::string>
source_vars()
const {
return source_vars_; }
293 std::vector<std::string>
target_vars()
const {
return target_vars_; }
301 void run(Wonton::Executor_type
const* executor =
nullptr,
bool report_time =
true) {
305 bool distributed =
false;
307 #ifdef PORTAGE_ENABLE_MPI 308 MPI_Comm comm = MPI_COMM_NULL;
309 auto mpiexecutor =
dynamic_cast<Wonton::MPIExecutor_type const*
>(executor);
310 if (mpiexecutor && mpiexecutor->mpicomm != MPI_COMM_NULL) {
311 comm = mpiexecutor->mpicomm;
312 MPI_Comm_rank(comm, &rank);
313 MPI_Comm_size(comm, &nprocs);
314 distributed = nprocs > 1;
319 std::cout <<
"in SwarmDriver::run() ... " << std::endl;
322 using Searcher = Search<dim, SourceSwarm, TargetSwarm>;
323 using Accumulator = Accumulate<dim, SourceSwarm, TargetSwarm>;
324 using Estimator = Estimate<dim, SourceState>;
326 int nb_source = source_swarm_.num_particles(Wonton::PARALLEL_OWNED);
327 int nb_target = target_swarm_.num_particles(Wonton::PARALLEL_OWNED);
328 int nb_fields = source_vars_.size();
330 float tot_seconds = 0.0, tot_seconds_dist = 0.0,
331 tot_seconds_srch = 0.0, tot_seconds_xsect = 0.0,
332 tot_seconds_interp = 0.0;
342 #ifdef PORTAGE_ENABLE_MPI 344 MPI_Particle_Distribute<dim> distributor(mpiexecutor);
348 distributor.distribute(source_swarm_, source_state_,
349 target_swarm_, target_state_,
350 smoothing_lengths_, source_extents_, target_extents_,
351 kernel_types_, geom_types_, weight_center_);
362 Searcher search(source_swarm_, target_swarm_,
363 source_extents_, target_extents_, weight_center_);
366 target_swarm_.end(Wonton::PARTICLE, Wonton::PARALLEL_OWNED),
367 candidates.begin(), search);
376 if (geom_types_[0] ==
Weight::FACETED and weight_center_ == Scatter and part_field_!=
"NONE") {
380 nb_source = source_swarm_.num_particles(Wonton::PARALLEL_OWNED);
381 nb_target = target_swarm_.num_particles(Wonton::PARALLEL_OWNED);
384 auto source_field_part = source_state_.get_field_dbl(part_field_);
385 std::vector<double> target_field_part(nb_target);
389 Accumulator accumulator(source_swarm_, target_swarm_,
390 estimator_type_, weight_center_,
391 step_kern, geom_types_, part_smoothing_, basis_type_,
392 operator_spec_, operator_domains_, operator_data_);
396 for (
int i = 0; i < nb_target; i++) {
397 std::vector<int> possibles = candidates[i];
398 for (
auto&& neighbor : possibles) {
399 double weight = accumulator.weight(i, neighbor);
401 double part_val = source_field_part[neighbor];
402 target_field_part[i] = part_val;
406 auto p1 = source_swarm_.get_particle_coordinates(nbr);
407 auto p2 = target_swarm_.get_particle_coordinates(i);
408 double h = part_smoothing_[neighbor][0][2];
410 std::cout <<
"i=" << i <<
" " <<
" neighbor=" << neighbor <<
" ";
411 std::cout << std::abs(p2[0]-p1[0])/h <<
", "<< std::abs(p2[1]-p1[1])/h;
412 std::cout <<
" w= "<< weight <<
" part= "<< part_val << std::endl;
421 for (
int i = 0; i < nb_target; i++) {
422 std::vector<int> new_candidates;
423 std::vector<int> possibles = candidates[i];
424 for (
auto&& neighbor : possibles) {
425 if (std::abs(target_field_part[i] - source_field_part[neighbor]) < part_tolerance_) {
426 new_candidates.emplace_back(neighbor);
429 candidates[i] = new_candidates;
439 Accumulator accumulate(source_swarm_, target_swarm_,
440 estimator_type_, weight_center_, kernel_types_,
441 geom_types_, smoothing_lengths_, basis_type_,
442 operator_spec_, operator_domains_, operator_data_);
449 target_swarm_.end(Wonton::PARTICLE, Wonton::PARALLEL_OWNED),
450 candidates.begin(), source_points_and_multipliers.begin(),
456 nb_fields = source_vars_.size();
458 std::cout <<
"number of variables to remap is " << nb_fields << std::endl;
461 Estimator estimator(source_state_);
463 for (
int i = 0; i < nb_fields; ++i) {
466 std::cout <<
"Remap "<< source_vars_[i] <<
" to "<< target_vars_[i] << std::endl;
468 estimator.set_variable(source_vars_[i]);
483 auto& target_data = target_state_.get_field(target_vars_[i]);
486 Portage::transform(target_swarm_.begin(Entity_kind::PARTICLE, Entity_type::PARALLEL_OWNED),
487 target_swarm_.end(Entity_kind::PARTICLE, Entity_type::PARALLEL_OWNED),
488 source_points_and_multipliers.begin(),
489 target_field, estimator);
492 tot_seconds = tot_seconds_dist + tot_seconds_srch +
493 tot_seconds_xsect + tot_seconds_interp;
496 std::cout <<
"Swarm Transform Time Rank " << rank <<
" (s): " << tot_seconds << std::endl;
497 std::cout <<
" Swarm Distribution Time Rank " << rank <<
" (s): " << tot_seconds_dist << std::endl;
498 std::cout <<
" Swarm Search Time Rank " << rank <<
" (s): " << tot_seconds_srch << std::endl;
499 std::cout <<
" Swarm Accumulate Time Rank " << rank <<
" (s): " << tot_seconds_xsect << std::endl;
500 std::cout <<
" Swarm Estimate Time Rank " << rank <<
" (s): " << tot_seconds_interp << std::endl;
504 int nnbrmin = nb_target;
509 for (
int j=0; j < nb_target; j++) {
511 std::vector<Weights_t> wts = source_points_and_multipliers[j];
512 for (
auto&& wt : wts) {
513 if (std::abs(wt.weights[0]) > 0.0)
516 if (n > nnbrmax) nnbrmax = n;
517 if (n < nnbrmin) nnbrmin = n;
520 nnbravg = nnbrsum / nb_target;
522 for (
int j=0; j < nb_target; j++) {
524 std::vector<Weights_t> wts = source_points_and_multipliers[j];
525 for (
auto&& wt : wts) {
526 if (std::abs(wt.weights[0]) > 0.0)
529 nnbrsdev += std::pow(n - nnbravg, 2);
531 nnbrsdev = std::sqrt(nnbrsdev / nb_target);
533 std::cout <<
"Max number of neighbors: " << nnbrmax << std::endl;
534 std::cout <<
"Min number of neighbors: " << nnbrmin << std::endl;
535 std::cout <<
"Avg number of neighbors: " << nnbravg << std::endl;
536 std::cout <<
"Std Dev for number of neighbors: " << nnbrsdev << std::endl;
549 return (weight_center_ == Scatter
550 ? source_swarm_.num_particles(Wonton::PARALLEL_OWNED)
551 : target_swarm_.num_particles(Wonton::PARALLEL_OWNED));
562 assert(smoothing_lengths_.size() == swarm_size);
563 assert(kernel_types_.size() == swarm_size);
564 assert(geom_types_.size() == swarm_size);
579 assert(smoothing_lengths_.size() == unsigned(swarm_size));
580 kernel_types_.resize(swarm_size, kernel_type);
581 geom_types_.resize(swarm_size, support_geom_type);
589 if (weight_center_ == Gather) {
590 int const nb_target = target_swarm_.num_particles(Wonton::PARALLEL_OWNED);
591 assert(smoothing_lengths_.size() == unsigned(nb_target));
592 target_extents_.resize(nb_target);
594 for (
int i = 0; i < nb_target; i++) {
596 throw std::runtime_error(
"FACETED geometry is not available here");
598 std::vector<std::vector<double>> temp = smoothing_lengths_[i];
599 target_extents_[i] = Point<dim>(temp[0]);
601 }
else if (weight_center_ == Scatter) {
602 int const nb_source = source_swarm_.num_particles(Wonton::PARALLEL_OWNED);
603 assert(smoothing_lengths_.size() == unsigned(nb_source));
604 source_extents_.resize(nb_source);
606 for (
int i = 0; i < nb_source; i++) {
608 throw std::runtime_error(
"FACETED geometry is not available here");
610 std::vector<std::vector<double>> temp = smoothing_lengths_[i];
611 source_extents_[i] = Point<dim>(temp[0]);
617 SourceSwarm& source_swarm_;
618 TargetSwarm
const& target_swarm_;
619 SourceState& source_state_;
620 TargetState& target_state_;
621 std::vector<std::string> source_vars_ {};
622 std::vector<std::string> target_vars_ {};
623 WeightCenter weight_center_ = Gather;
629 EstimateType estimator_type_ {};
634 std::string part_field_ =
"";
635 double part_tolerance_ = 0.0;
641 #endif // SRC_DRIVER_SWARM_H_ std::chrono::high_resolution_clock::time_point now()
Get current time.
Definition: timer.h:19
void run(Wonton::Executor_type const *executor=nullptr, bool report_time=true)
Perform the remap.
Definition: driver_swarm.h:301
std::vector< T > vector
Definition: portage.h:238
OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op)
Definition: portage.h:250
~SwarmDriver()=default
Destructor.
void check_sizes_and_set_types(WeightCenter const weight_center, Weight::Kernel const kernel_type, Weight::Geometry const support_geom_type)
Check sizes according to weight center, set kernel and geometry.
Definition: driver_swarm.h:575
int get_swarm_size() const
Get swarm size according to weight center type.
Definition: driver_swarm.h:548
T * pointer
Definition: portage.h:241
float elapsed(std::chrono::high_resolution_clock::time_point &tic, bool reset=false)
Get elapsed time in seconds.
Definition: timer.h:27
SwarmDriver(SourceSwarm &source_swarm, SourceState &source_state, TargetSwarm const &target_swarm, TargetState &target_state, SmoothingLengths const &smoothing_lengths, Weight::Kernel const kernel_type=Weight::B4, Weight::Geometry const support_geom_type=Weight::ELLIPTIC, WeightCenter const center=Gather)
Constructor using a unique kernel_type and support geometry for all particles.
Definition: driver_swarm.h:77
Provides an interface to remap variables from one swarm to another.
Definition: driver_swarm.h:54
void set_extents_from_smoothing_lengths()
Setup search boxes around source and target points for non-faceted weights.
Definition: driver_swarm.h:588
std::vector< std::string > target_vars() const
Get all target swarm variables names.
Definition: driver_swarm.h:293
void set_remap_var_names(std::vector< std::string > const &remap_var_names)
Specify the names of the variables to be interpolated.
Definition: driver_swarm.h:227
Definition: operator.h:30
Type
Definition: basis.h:20
Geometry
Geometry types.
Definition: weight.h:333
void check_sizes(WeightCenter const weight_center)
Check sizes according to weight center type.
Definition: driver_swarm.h:559
Type
Definition: operator.h:30
Definition: coredriver.h:42
std::vector< std::string > source_vars() const
Get all source swarm variables names.
Definition: driver_swarm.h:286
SwarmDriver(SourceSwarm &source_swarm, SourceState &source_state, TargetSwarm const &target_swarm, TargetState &target_state, SmoothingLengths const &smoothing_lengths, Portage::vector< Weight::Kernel > const &kernel_types, Portage::vector< Weight::Geometry > const &geom_types, WeightCenter const center=Gather)
Constructor with search extents computed inline.
Definition: driver_swarm.h:121
Portage::vector< std::vector< std::vector< double > >> SmoothingLengths
Definition: driver_swarm.h:33
Kernel
Kernel types.
Definition: weight.h:304
SwarmDriver & operator=(const SwarmDriver &)=delete
Disabled assignment operator.
SwarmDriver(SourceSwarm &source_swarm, SourceState &source_state, TargetSwarm const &target_swarm, TargetState &target_state, SmoothingLengths const &smoothing_lengths, Portage::vector< Point< dim >> const &source_extents, Portage::vector< Point< dim >> const &target_extents, WeightCenter const center=Gather)
Constructor with search extents specified.
Definition: driver_swarm.h:167
void set_remap_var_names(std::vector< std::string > const &source_vars, std::vector< std::string > const &target_vars, EstimateType const estimator_type=LocalRegression, basis::Type const basis_type=basis::Unitary, oper::Type const operator_spec=oper::LastOperator, Portage::vector< oper::Domain > const &operator_domains={}, Portage::vector< std::vector< Point< dim >>> const &operator_data={}, std::string part_field="NONE", double part_tolerance=0.0, SmoothingLengths const &part_smoothing={})
Specify the names of the variables to be interpolated.
Definition: driver_swarm.h:246