driver_mesh_swarm_mesh.h
Go to the documentation of this file.
1 /*
2 This file is part of the Ristra portage project.
3 Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/portage/blob/master/LICENSE
5 */
6 
7 #ifndef SRC_DRIVER_MESH_SWARM_MESH_H_
8 #define SRC_DRIVER_MESH_SWARM_MESH_H_
9 
10 //#include <sys/time.h>
11 
12 #include <algorithm>
13 #include <vector>
14 #include <iterator>
15 #include <string>
16 #include <utility>
17 #include <iostream>
18 #include <type_traits>
19 #include <string>
20 #include <limits>
21 
22 // portage includes
23 #include "portage/support/timer.h"
25 #include "portage/support/basis.h"
26 #include "portage/support/weight.h"
29 #include "portage/swarm/swarm.h"
34 
35 #ifdef PORTAGE_ENABLE_MPI
37 #endif
38 
48 namespace Portage {
49 
66 template <template <int, class, class> class Search,
67  template<int, class, class> class Accumulate,
68  template<int, class> class Estimate,
69  int dim,
70  class SourceMesh_Wrapper,
71  class SourceState_Wrapper,
72  class TargetMesh_Wrapper = SourceMesh_Wrapper,
73  class TargetState_Wrapper = SourceState_Wrapper>
74 class MSM_Driver {
75 public:
92  MSM_Driver(SourceMesh_Wrapper const& source_mesh,
93  SourceState_Wrapper const& source_state,
94  TargetMesh_Wrapper const& target_mesh,
95  TargetState_Wrapper& target_state,
96  double smoothing_factor = 1.25,
97  double boundary_factor = 0.5,
100  Meshfree::WeightCenter center = Meshfree::Gather,
101  std::string part_field = "NONE",
102  double part_tolerance = std::numeric_limits<double>::infinity())
103 
104  : source_mesh_(source_mesh),
105  target_mesh_(target_mesh),
106  source_state_(source_state),
107  target_state_(target_state),
108  smoothing_factor_(smoothing_factor),
109  boundary_factor_(boundary_factor),
110  kernel_(kernel),
111  geometry_(geometry),
112  center_(center),
113  part_field_(part_field),
114  part_tolerance_(part_tolerance),
115  dim_(source_mesh.space_dimension()) {
116 
117  assert(source_mesh.space_dimension() == target_mesh.space_dimension());
118  assert(source_mesh.space_dimension() == dim);
119  if (geometry == Meshfree::Weight::FACETED) {
121  }
122  }
123 
125  MSM_Driver(const MSM_Driver &) = delete;
126 
128  MSM_Driver& operator = (const MSM_Driver &) = delete;
129 
131  ~MSM_Driver() = default;
132 
139  void set_remap_var_names(std::vector<std::string> const& remap_var_names) {
140  // remap variable names same in source and target mesh
141  set_remap_var_names(remap_var_names, remap_var_names);
142  }
143 
157  void set_remap_var_names(std::vector<std::string> const& source_vars,
158  std::vector<std::string> const& target_vars,
159  Meshfree::EstimateType const& estimator_type = Meshfree::LocalRegression,
162  Portage::vector<Meshfree::oper::Domain> const& operator_domains = {},
163  Portage::vector<std::vector<Point<dim>>> const& operator_data = {}) {
164 #ifdef DEBUG
165  assert(source_vars.size() == target_vars.size());
166 
167  int nvars = source_vars.size();
168  for (int i = 0; i < nvars; ++i) {
169  auto const& source_entity = source_state_.get_entity(source_vars[i]);
170  auto const& target_entity = target_state_.get_entity(target_vars[i]);
171  assert(source_entity == target_entity);
172  }
173 #endif
174 
175  source_vars_ = source_vars;
176  target_vars_ = target_vars;
177  estimate_ = estimator_type;
178  basis_ = basis_type;
179  operator_spec_ = operator_spec;
180  operator_domains_ = operator_domains;
181  operator_data_ = operator_data;
182  }
183 
189  std::vector<std::string> source_vars() const { return source_vars_; }
190 
196  std::vector<std::string> target_vars() const { return target_vars_; }
197 
202  int dimension() const { return dim_; }
203 
207  void run(Wonton::Executor_type const *executor = nullptr) {
208 
209  using namespace Meshfree;
210  // useful aliases
211  using SwarmRemap = SwarmDriver<Search, Accumulate, Estimate, dim,
212  Swarm<dim>, SwarmState<dim>>;
213 
214  int rank = 0;
215  int nprocs = 1;
216 
217 #ifdef PORTAGE_ENABLE_MPI
218  MPI_Comm mycomm = MPI_COMM_NULL;
219  auto mpiexecutor = dynamic_cast<Wonton::MPIExecutor_type const *>(executor);
220  if (mpiexecutor && mpiexecutor->mpicomm != MPI_COMM_NULL) {
221  mycomm = mpiexecutor->mpicomm;
222  MPI_Comm_rank(mycomm, &rank);
223  MPI_Comm_size(mycomm, &nprocs);
224  if (nprocs > 1) {
225  std::cerr << "Cannot run Mesh-Swarm-Mesh driver in distributed mode yet";
226  std::cerr << std::endl;
227  return;
228  }
229  }
230 #endif
231 #ifdef ENABLE_DEBUG
232  if (rank == 0)
233  std::cout << "in MSM_Driver::run() ... " << std::endl;
234 
235  int ncells = target_mesh_.num_owned_cells();
236  std::cout << "Number of owned target cells on rank "<< rank <<": "<< ncells;
237  std::cout << std::endl;
238 
239  auto tic = timer::now();
240 #endif
241  int nvars = source_vars_.size();
242 
243  // Wonton::CELL VARIABLE SECTION ---------------------------------------------------
244 
245  // get cell variable names
246  std::vector<std::string> source_cellvar_names;
247  std::vector<std::string> target_cellvar_names;
248 
249  for (int i = 0; i < nvars; ++i) {
250  auto onwhat = source_state_.get_entity(source_vars_[i]);
251  if (onwhat == Wonton::CELL) {
252  source_cellvar_names.emplace_back(source_vars_[i]);
253  target_cellvar_names.emplace_back(target_vars_[i]);
254  }
255  }
256 
257  // Collect all cell based variables and remap them
258  if (not source_cellvar_names.empty()) {
259  // convert mesh and state wrappers to swarm ones
260  Swarm<dim> source_swarm(source_mesh_, Wonton::CELL);
261  Swarm<dim> target_swarm(target_mesh_, Wonton::CELL);
262  SwarmState<dim> source_swarm_state(source_state_, Wonton::CELL);
263  SwarmState<dim> target_swarm_state(target_state_, Wonton::CELL);
264 
265  // set up smoothing lengths and extents
267  std::vector<std::vector<double>> default_lengths(1, std::vector<double>(dim));
268  Portage::vector<Wonton::Point<dim>> weight_extents, other_extents;
269  Portage::vector<std::vector<std::vector<double>>> part_smoothing; // only for faceted,scatter,parts
270 
271  if (geometry_ == Weight::FACETED) {
272  using Weight::faceted_setup_cell;
273 
274  if (part_field_ == "NONE") {
275  switch (center_) {
276  case Scatter: faceted_setup_cell<dim>(source_mesh_,
277  smoothing_lengths,
278  weight_extents,
279  smoothing_factor_,
280  boundary_factor_); break;
281  case Gather: faceted_setup_cell<dim>(target_mesh_,
282  smoothing_lengths,
283  weight_extents,
284  smoothing_factor_,
285  boundary_factor_); break;
286  default: break;
287  }
288  } else {
289  Portage::vector<Wonton::Point<dim>> dummy_extents;
290  switch (center_) {
291  case Scatter:
292  // Set smoothing_factor to 1/4 to make weight support exactly equal to cell volume.
293  // Store these smoothing lengths off on the side for later use in the swarm driver.
294  faceted_setup_cell<dim>(source_mesh_, part_smoothing,
295  dummy_extents, 0.25, 0.25);
296  // Get usual smoothing lengths and extents
297  faceted_setup_cell<dim>(source_mesh_,
298  smoothing_lengths, weight_extents,
299  smoothing_factor_, boundary_factor_);
300  break;
301  case Gather: faceted_setup_cell<dim>(target_mesh_, target_state_,
302  part_field_, part_tolerance_,
303  smoothing_lengths, weight_extents,
304  smoothing_factor_, boundary_factor_);
305  break;
306  default: break;
307  }
308  }
309  } else /* part_field_ != NONE */ {
310  int ncells = (center_ == Scatter ? source_mesh_.num_owned_cells()
311  : target_mesh_.num_owned_cells());
312 
313  smoothing_lengths.resize(ncells, default_lengths);
314 
315  for (int i = 0; i < ncells; i++) {
316  double radius = 0.0;
317  switch (center_) {
318  case Scatter: Wonton::cell_radius<dim>(source_mesh_, i, &radius); break;
319  case Gather: Wonton::cell_radius<dim>(target_mesh_, i, &radius); break;
320  default: break;
321  }
322 
323  std::vector<std::vector<double>> h = smoothing_lengths[i];
324  h[0] = std::vector<double>(dim, 2. * radius * smoothing_factor_);
325  smoothing_lengths[i] = h;
326  }
327  }
328 
329  // create swarm remap driver
330  SwarmRemap* swarm_remap_ptr = nullptr;
331 
332  if (geometry_ == Weight::FACETED) {
333  if (center_ == Scatter) {
334  swarm_remap_ptr = new SwarmRemap(source_swarm, source_swarm_state,
335  target_swarm, target_swarm_state,
336  smoothing_lengths,
337  weight_extents, other_extents,
338  center_);
339  } else if (center_ == Gather) {
340  swarm_remap_ptr = new SwarmRemap(source_swarm, source_swarm_state,
341  target_swarm, target_swarm_state,
342  smoothing_lengths,
343  other_extents, weight_extents,
344  center_);
345  }
346  } else {
347  swarm_remap_ptr = new SwarmRemap(source_swarm, source_swarm_state,
348  target_swarm, target_swarm_state,
349  smoothing_lengths,
350  kernel_, geometry_, center_);
351  }
352 
353  assert(swarm_remap_ptr != nullptr);
354  SwarmRemap& swarm_remap(*swarm_remap_ptr);
355  swarm_remap.set_remap_var_names(source_cellvar_names, target_cellvar_names,
356  estimate_, basis_, operator_spec_,
357  operator_domains_, operator_data_,
358  part_field_, part_tolerance_, part_smoothing);
359  // do the remap
360  swarm_remap.run(executor, true);
361 
362  // transfer data back to target mesh
363  for (auto&& name : target_cellvar_names) {
364  auto& swarm_field = target_swarm_state.get_field(name);
365  double* mesh_field;
366  target_state_.mesh_get_data(Wonton::CELL, name, &mesh_field);
367  for (int i = 0; i < target_swarm_state.get_size(); i++)
368  mesh_field[i] = swarm_field[i];
369  }
370 
371  delete swarm_remap_ptr;
372  }
373 
374  // Wonton::NODE VARIABLE SECTION ---------------------------------------------------
375 
376  // get node variable names
377  std::vector<std::string> source_nodevar_names;
378  std::vector<std::string> target_nodevar_names;
379  for (int i = 0; i < nvars; ++i) {
380  auto onwhat = source_state_.get_entity(source_vars_[i]);
381  if (onwhat == Wonton::NODE) {
382  source_nodevar_names.emplace_back(source_vars_[i]);
383  target_nodevar_names.emplace_back(target_vars_[i]);
384  }
385  }
386 
387  if (not source_nodevar_names.empty()) {
388  // convert mesh and state wrappers to swarm ones
389  Swarm<dim> source_swarm(source_mesh_, Wonton::NODE);
390  Swarm<dim> target_swarm(target_mesh_, Wonton::NODE);
391  SwarmState<dim> source_swarm_state(source_state_, Wonton::NODE);
392  SwarmState<dim> target_swarm_state(target_state_, Wonton::NODE);
393 
394  // create smoothing lengths
396  std::vector<std::vector<double>> default_lengths(1, std::vector<double>(dim));
397 
398  if (geometry_ == Weight::FACETED) {
399  std::cerr << "Cannot do FACETED weights for nodal variables yet." << std::endl;
400  return;
401  }
402 
403  int nnodes = (center_ == Scatter ? source_mesh_.num_owned_nodes()
404  : target_mesh_.num_owned_nodes());
405 
406  smoothing_lengths.resize(nnodes, default_lengths);
407 
408  for (int i = 0; i < nnodes; i++) {
409  double radius = 0.0;
410  switch (center_) {
411  case Scatter: Wonton::node_radius<dim>(source_mesh_, i, &radius); break;
412  case Gather: Wonton::node_radius<dim>(target_mesh_, i, &radius); break;
413  default: break;
414  }
415 
416  std::vector<std::vector<double>> h = smoothing_lengths[i];
417  h[0] = std::vector<double>(dim, radius * smoothing_factor_);
418  smoothing_lengths[i] = h;
419  }
420 
421  // create swarm remap driver
422  SwarmRemap swarm_remap(source_swarm, source_swarm_state,
423  target_swarm, target_swarm_state,
424  smoothing_lengths, kernel_,
425  geometry_, center_);
426 
427  swarm_remap.set_remap_var_names(source_nodevar_names, target_nodevar_names,
428  LocalRegression, basis_);
429 
430  // do the remap
431  swarm_remap.run(executor, true);
432 
433  // transfer data back to target mesh
434  for (auto&& name : target_nodevar_names) {
435  auto& swarm_field = target_swarm_state.get_field(name);
436  double* mesh_field;
437  target_state_.mesh_get_data(Wonton::NODE, name, &mesh_field);
438  for (int i = 0; i < target_swarm_state.get_size(); i++)
439  mesh_field[i] = swarm_field[i];
440  }
441  }
442 
443 #if ENABLE_DEBUG
444  float elapsed = timer::elapsed(tic);
445  std::cout << "Mesh-Swarm-Mesh Time for Rank " << rank << " (s): " << elapsed << std::endl;
446 #endif
447  }
448 
449 private:
450  SourceMesh_Wrapper const& source_mesh_;
451  TargetMesh_Wrapper const& target_mesh_;
452  SourceState_Wrapper const& source_state_;
453  TargetState_Wrapper& target_state_;
454  std::vector<std::string> source_vars_;
455  std::vector<std::string> target_vars_;
456  double smoothing_factor_ = 0.0;
457  double boundary_factor_ = 0.0;
458  Meshfree::Weight::Kernel kernel_ {};
459  Meshfree::Weight::Geometry geometry_ {};
460  Meshfree::WeightCenter center_ {};
461  std::string part_field_;
462  double part_tolerance_ = 0.0;
463  Meshfree::EstimateType estimate_ {};
464  Meshfree::basis::Type basis_ {};
465  Meshfree::oper::Type operator_spec_ {};
466  Portage::vector<Meshfree::oper::Domain> operator_domains_ {};
467  Portage::vector<std::vector<Point<dim>>> operator_data_ {};
468  int dim_ = 2;
469 }; // class MSM_Driver
470 
471 } // namespace Portage
472 
473 #endif // SRC_DRIVER_MESH_SWARM_MESH_H_
std::chrono::high_resolution_clock::time_point now()
Get current time.
Definition: timer.h:19
Definition: weight.h:304
std::vector< T > vector
Definition: portage.h:238
MSM_Driver(SourceMesh_Wrapper const &source_mesh, SourceState_Wrapper const &source_state, TargetMesh_Wrapper const &target_mesh, TargetState_Wrapper &target_state, double smoothing_factor=1.25, double boundary_factor=0.5, Meshfree::Weight::Geometry geometry=Meshfree::Weight::TENSOR, Meshfree::Weight::Kernel kernel=Meshfree::Weight::B4, Meshfree::WeightCenter center=Meshfree::Gather, std::string part_field="NONE", double part_tolerance=std::numeric_limits< double >::infinity())
Constructor for running the interpolation driver.
Definition: driver_mesh_swarm_mesh.h:92
float elapsed(std::chrono::high_resolution_clock::time_point &tic, bool reset=false)
Get elapsed time in seconds.
Definition: timer.h:27
MSM_Driver & operator=(const MSM_Driver &)=delete
Assignment operator (disabled)
~MSM_Driver()=default
Destructor.
MSM_Driver provides the API to mapping from one mesh to another using particles.
Definition: driver_mesh_swarm_mesh.h:74
std::vector< std::string > target_vars() const
Get the names of the variables to be remapped to the target mesh.
Definition: driver_mesh_swarm_mesh.h:196
Definition: operator.h:30
Definition: weight.h:333
Type
Definition: basis.h:20
Definition: basis.h:20
std::vector< std::string > source_vars() const
Get the names of the variables to be remapped from the source mesh.
Definition: driver_mesh_swarm_mesh.h:189
void run(Wonton::Executor_type const *executor=nullptr)
Execute the remapping process.
Definition: driver_mesh_swarm_mesh.h:207
Geometry
Geometry types.
Definition: weight.h:333
Type
Definition: operator.h:30
void set_remap_var_names(std::vector< std::string > const &remap_var_names)
Specify the names of the variables to be interpolated.
Definition: driver_mesh_swarm_mesh.h:139
Definition: coredriver.h:42
double kernel(const Kernel kern, double x)
General kernel function.
Definition: weight.h:313
Definition: weight.h:333
int dimension() const
Get the dimensionality of the meshes.
Definition: driver_mesh_swarm_mesh.h:202
void set_remap_var_names(std::vector< std::string > const &source_vars, std::vector< std::string > const &target_vars, Meshfree::EstimateType const &estimator_type=Meshfree::LocalRegression, Meshfree::basis::Type const &basis_type=Meshfree::basis::Unitary, Meshfree::oper::Type operator_spec=Meshfree::oper::LastOperator, Portage::vector< Meshfree::oper::Domain > const &operator_domains={}, Portage::vector< std::vector< Point< dim >>> const &operator_data={})
Specify the names of the variables to be interpolated.
Definition: driver_mesh_swarm_mesh.h:157
Kernel
Kernel types.
Definition: weight.h:304
Definition: weight.h:304