Molecular Dynamics Simulation  1.0
XSDToInternalTypeAdapter.cpp
Go to the documentation of this file.
2 
3 #include <variant>
4 
5 #include "io/logger/Logger.h"
23 
24 CuboidSpawner XSDToInternalTypeAdapter::convertToCuboidSpawner(const CuboidSpawnerType& cuboid, ThirdDimension third_dimension) {
25  auto lower_left_front_corner = convertToVector(cuboid.lower_left_front_corner());
26  auto grid_dimensions = convertToVector(cuboid.grid_dim());
27  auto initial_velocity = convertToVector(cuboid.velocity());
28 
29  auto grid_spacing = cuboid.grid_spacing();
30  auto mass = cuboid.mass();
31  auto type = cuboid.type();
32  auto epsilon = cuboid.epsilon();
33  auto sigma = cuboid.sigma();
34  auto temperature = cuboid.temperature();
35  LockState lock_state = cuboid.is_locked() ? LockState::LOCKED : LockState::UNLOCKED;
36 
37  if (grid_dimensions[0] <= 0 || grid_dimensions[1] <= 0 || grid_dimensions[2] <= 0) {
38  Logger::logger->error("Cuboid grid dimensions must be positive");
39  throw std::runtime_error("Cuboid grid dimensions must be positive");
40  }
41 
42  if (third_dimension == ThirdDimension::DISABLED && grid_dimensions[2] > 1) {
43  Logger::logger->error("Cuboid grid dimensions must be 1 in z direction if third dimension is disabled");
44  throw std::runtime_error("Cuboid grid dimensions must be 1 in z direction if third dimension is disabled");
45  }
46 
47  if (grid_spacing <= 0) {
48  Logger::logger->error("Cuboid grid spacing must be positive");
49  throw std::runtime_error("Cuboid grid spacing must be positive");
50  }
51 
52  if (mass <= 0) {
53  Logger::logger->error("Cuboid mass must be positive");
54  throw std::runtime_error("Cuboid mass must be positive");
55  }
56 
57  if (temperature < 0) {
58  Logger::logger->error("Cuboid temperature must be positive");
59  throw std::runtime_error("Cuboid temperature must be positive");
60  }
61 
62  return CuboidSpawner{
63  lower_left_front_corner, grid_dimensions, grid_spacing, mass, initial_velocity, static_cast<int>(type), epsilon, sigma, lock_state,
64  third_dimension, temperature};
65 }
66 
68  ThirdDimension third_dimension) {
69  auto lower_left_front_corner = convertToVector(soft_body_cuboid.lower_left_front_corner());
70  auto grid_dimensions = convertToVector(soft_body_cuboid.grid_dim());
71  auto initial_velocity = convertToVector(soft_body_cuboid.velocity());
72 
73  auto grid_spacing = soft_body_cuboid.grid_spacing();
74  auto mass = soft_body_cuboid.mass();
75  auto type = soft_body_cuboid.type();
76  auto spring_constant = soft_body_cuboid.spring_constant();
77  auto epsilon = soft_body_cuboid.epsilon();
78  auto sigma = soft_body_cuboid.sigma();
79  auto temperature = soft_body_cuboid.temperature();
80 
81  if (grid_dimensions[0] <= 0 || grid_dimensions[1] <= 0 || grid_dimensions[2] <= 0) {
82  Logger::logger->error("Cuboid grid dimensions must be positive");
83  throw std::runtime_error("Cuboid grid dimensions must be positive");
84  }
85 
86  if (third_dimension == ThirdDimension::DISABLED && grid_dimensions[2] > 1) {
87  Logger::logger->error("Cuboid grid dimensions must be 1 in z direction if third dimension is disabled");
88  throw std::runtime_error("Cuboid grid dimensions must be 1 in z direction if third dimension is disabled");
89  }
90 
91  if (grid_spacing <= 0) {
92  Logger::logger->error("Cuboid grid spacing must be positive");
93  throw std::runtime_error("Cuboid grid spacing must be positive");
94  }
95 
96  if (mass <= 0) {
97  Logger::logger->error("Cuboid mass must be positive");
98  throw std::runtime_error("Cuboid mass must be positive");
99  }
100 
101  if (temperature < 0) {
102  Logger::logger->error("Cuboid temperature must be positive");
103  throw std::runtime_error("Cuboid temperature must be positive");
104  }
105 
106  return SoftBodyCuboidSpawner{lower_left_front_corner, grid_dimensions, grid_spacing, mass,
107  initial_velocity, static_cast<int>(type), epsilon, sigma,
108  spring_constant, third_dimension, temperature};
109 }
110 
111 SphereSpawner XSDToInternalTypeAdapter::convertToSphereSpawner(const SphereSpawnerType& sphere, ThirdDimension third_dimension) {
112  auto center = convertToVector(sphere.center());
113  auto initial_velocity = convertToVector(sphere.velocity());
114 
115  auto radius = sphere.radius();
116  auto grid_spacing = sphere.grid_spacing();
117  auto mass = sphere.mass();
118  auto type = sphere.type();
119  auto epsilon = sphere.epsilon();
120  auto sigma = sphere.sigma();
121  auto temperature = sphere.temperature();
122  LockState lock_state = sphere.is_locked() ? LockState::LOCKED : LockState::UNLOCKED;
123 
124  if (radius <= 0) {
125  Logger::logger->error("Sphere radius must be positive");
126  throw std::runtime_error("Sphere radius must be positive");
127  }
128 
129  if (grid_spacing <= 0) {
130  Logger::logger->error("Sphere grid spacing must be positive");
131  throw std::runtime_error("Sphere grid spacing must be positive");
132  }
133 
134  if (mass <= 0) {
135  Logger::logger->error("Sphere mass must be positive");
136  throw std::runtime_error("Sphere mass must be positive");
137  }
138 
139  if (temperature < 0) {
140  Logger::logger->error("Sphere temperature must be positive");
141  throw std::runtime_error("Sphere temperature must be positive");
142  }
143 
144  return SphereSpawner{center, static_cast<int>(radius), grid_spacing, mass, initial_velocity, static_cast<int>(type), epsilon, sigma,
145  lock_state, third_dimension, temperature};
146 }
147 
149  ThirdDimension third_dimension) {
150  auto position = convertToVector(particle.position());
151  auto initial_velocity = convertToVector(particle.velocity());
152 
153  auto mass = particle.mass();
154  auto type = particle.type();
155  auto epsilon = particle.epsilon();
156  auto sigma = particle.sigma();
157  LockState lock_state = particle.is_locked() ? LockState::LOCKED : LockState::UNLOCKED;
158 
159  return CuboidSpawner{position,
160  {1, 1, 1},
161  0,
162  mass,
163  initial_velocity,
164  static_cast<int>(type),
165  epsilon,
166  sigma,
167  lock_state,
168  third_dimension,
169  particle.temperature()};
170 }
171 
172 std::vector<std::shared_ptr<SimulationInterceptor>> XSDToInternalTypeAdapter::convertToSimulationInterceptors(
173  const SimulationInterceptorsType& interceptors, ThirdDimension third_dimension,
174  std::variant<SimulationParams::DirectSumType, SimulationParams::LinkedCellsType> container_type) {
175  std::vector<std::shared_ptr<SimulationInterceptor>> simulation_interceptors;
176 
177  for (auto frame_writer : interceptors.FrameWriter()) {
178  auto fps = frame_writer.fps();
179  auto video_length = frame_writer.video_length_s();
180  auto output_format = convertToOutputFormat(frame_writer.output_format());
181 
182  simulation_interceptors.push_back(std::make_shared<FrameWriterInterceptor>(output_format, fps, video_length));
183  }
184 
185  for (auto xsd_thermostat : interceptors.Thermostat()) {
186  auto target_temperature = xsd_thermostat.target_temperature();
187  auto max_temperature_change = xsd_thermostat.max_temperature_change();
188  auto application_interval = xsd_thermostat.application_interval();
189 
190  std::shared_ptr<Thermostat> thermostat;
191 
192  if (xsd_thermostat.type() == ThermostatType::value::absolute) {
193  thermostat = std::make_shared<AbsoluteThermostat>(target_temperature, max_temperature_change, third_dimension);
194  } else if (xsd_thermostat.type() == ThermostatType::value::relative_motion) {
195  thermostat = std::make_shared<RelativeThermostat>(target_temperature, max_temperature_change, third_dimension);
196  } else {
197  Logger::logger->error("Thermostat type not implemented");
198  throw std::runtime_error("Thermostat type not implemented");
199  }
200 
201  simulation_interceptors.push_back(std::make_shared<ThermostatInterceptor>(thermostat, application_interval));
202 
203  if (xsd_thermostat.temperature_sensor()) {
204  auto temperature_sensor = *xsd_thermostat.temperature_sensor();
205  auto sample_every_x_percent = temperature_sensor.sample_every_x_percent();
206 
207  simulation_interceptors.push_back(std::make_shared<TemperatureSensorInterceptor>(thermostat, sample_every_x_percent));
208  }
209  }
210 
211  if (interceptors.ParticleUpdatesPerSecond().size() > 0) {
212  simulation_interceptors.push_back(std::make_shared<ParticleUpdateCounterInterceptor>());
213  }
214 
215  for (auto diffusion_function : interceptors.DiffusionFunction()) {
216  auto sample_every_x_percent = diffusion_function.sample_every_x_percent();
217  simulation_interceptors.push_back(std::make_shared<DiffusionFunctionInterceptor>(sample_every_x_percent));
218  }
219 
220  for (auto xsd_rdf : interceptors.RadialDistributionFunction()) {
221  auto bin_width = xsd_rdf.bin_width();
222  auto sample_every_x_percent = xsd_rdf.sample_every_x_percent();
223 
224  simulation_interceptors.push_back(std::make_shared<RadialDistributionFunctionInterceptor>(bin_width, sample_every_x_percent));
225  }
226 
227  for (auto xsd_vp : interceptors.VelocityProfile()) {
228  auto num_bins = xsd_vp.num_bins();
229  auto sample_every_x_percent = xsd_vp.sample_every_x_percent();
230 
231  auto box_xsd = xsd_vp.box();
232 
233  std::pair<std::array<double, 3>, std::array<double, 3>> box;
234 
235  if (box_xsd.present()) {
236  auto box_data = *box_xsd;
237 
238  auto bottom_left = convertToVector(box_data.lower_left_front_corner());
239  auto top_right = convertToVector(box_data.upper_right_back_corner());
240 
241  box = std::make_pair(bottom_left, top_right);
242  } else {
243  std::visit(
244  [&box](auto&& container) {
245  if constexpr (std::is_same_v<std::decay_t<decltype(container)>, SimulationParams::DirectSumType>) {
246  Logger::logger->error("Box must be specified if direct sum is used");
247  throw std::runtime_error("Box must be specified if direct sum is used");
248  } else if constexpr (std::is_same_v<std::decay_t<decltype(container)>, SimulationParams::LinkedCellsType>) {
249  auto bottom_left = std::array<double, 3>{0, 0, 0};
250  auto top_right = container.domain_size;
251 
252  box = std::make_pair(bottom_left, top_right);
253  } else {
254  Logger::logger->error("Container type not implemented");
255  throw std::runtime_error("Container type not implemented");
256  }
257  },
258  container_type);
259  }
260 
261  simulation_interceptors.push_back(std::make_shared<VelocityProfileInterceptor>(box, num_bins, sample_every_x_percent));
262  }
263 
264  simulation_interceptors.push_back(std::make_shared<ProgressBarInterceptor>());
265 
266  return simulation_interceptors;
267 }
268 
269 std::variant<SimulationParams::DirectSumType, SimulationParams::LinkedCellsType> XSDToInternalTypeAdapter::convertToParticleContainer(
270  const ParticleContainerType& particle_container) {
271  std::variant<SimulationParams::DirectSumType, SimulationParams::LinkedCellsType> container;
272 
273  if (particle_container.linkedcells_container().present()) {
274  auto container_data = *particle_container.linkedcells_container();
275 
276  auto domain_size = XSDToInternalTypeAdapter::convertToVector(container_data.domain_size());
277  auto cutoff_radius = container_data.cutoff_radius();
278  auto boundary_conditions = XSDToInternalTypeAdapter::convertToBoundaryConditionsArray(container_data.boundary_conditions());
279 
280  container = SimulationParams::LinkedCellsType(domain_size, cutoff_radius, boundary_conditions);
281  } else if (particle_container.directsum_container().present()) {
282  container = SimulationParams::DirectSumType();
283  } else {
284  Logger::logger->error("Container type not implemented");
285  throw std::runtime_error("Container type not implemented");
286  }
287 
288  return container;
289 }
290 
291 std::array<LinkedCellsContainer::BoundaryCondition, 6> XSDToInternalTypeAdapter::convertToBoundaryConditionsArray(
292  const BoundaryConditionsType& boundary) {
293  std::array<LinkedCellsContainer::BoundaryCondition, 6> boundary_conditions;
294 
295  boundary_conditions[0] = convertToBoundaryCondition(boundary.left());
296  boundary_conditions[1] = convertToBoundaryCondition(boundary.right());
297  boundary_conditions[2] = convertToBoundaryCondition(boundary.bottom());
298  boundary_conditions[3] = convertToBoundaryCondition(boundary.top());
299  boundary_conditions[4] = convertToBoundaryCondition(boundary.back());
300  boundary_conditions[5] = convertToBoundaryCondition(boundary.front());
301 
302  return boundary_conditions;
303 }
304 
306  switch (boundary) {
307  case BoundaryType::value::Outflow:
309  case BoundaryType::value::Reflective:
311  case BoundaryType::value::Periodic:
313  default:
314  Logger::logger->error("Boundary condition not implemented");
315  throw std::runtime_error("Boundary condition not implemented");
316  }
317 }
318 
320  auto position = XSDToInternalTypeAdapter::convertToVector(particle.position());
321  auto velocity = XSDToInternalTypeAdapter::convertToVector(particle.velocity());
322  auto force = XSDToInternalTypeAdapter::convertToVector(particle.force());
323  auto old_force = XSDToInternalTypeAdapter::convertToVector(particle.old_force());
324  auto type = particle.type();
325  auto mass = particle.mass();
326  auto epsilon = particle.epsilon();
327  auto sigma = particle.sigma();
328  LockState lock_state = particle.is_locked() ? LockState::LOCKED : LockState::UNLOCKED;
329 
330  if (mass <= 0) {
331  Logger::logger->error("Particle mass must be positive");
332  throw std::runtime_error("Particle mass must be positive");
333  }
334 
335  Particle output_particle{position, velocity, force, old_force, mass, static_cast<int>(type), epsilon, sigma, lock_state};
336 
337  for (const auto& entry : particle.connected_particles().entries()) {
338  output_particle.addConnectedParticle(entry.pointer_diff(), entry.rest_length(), entry.spring_constant());
339  }
340 
341  return output_particle;
342 }
343 
344 std::tuple<std::vector<std::shared_ptr<SimpleForceSource>>, std::vector<std::shared_ptr<PairwiseForceSource>>,
345  std::vector<std::shared_ptr<TargettedForceSource>>>
347  const ForcesType& forces, const std::variant<SimulationParams::DirectSumType, SimulationParams::LinkedCellsType>& container_data) {
348  std::vector<std::shared_ptr<SimpleForceSource>> simple_force_sources;
349  std::vector<std::shared_ptr<PairwiseForceSource>> pairwise_force_sources;
350  std::vector<std::shared_ptr<TargettedForceSource>> targetted_force_sources;
351 
352  // Simple Forces
353  if (forces.GlobalDownwardsGravity()) {
354  auto g = (*forces.GlobalDownwardsGravity()).g();
355  simple_force_sources.push_back(std::make_shared<GlobalDownwardsGravity>(g));
356  }
357  if (forces.HarmonicPotential()) {
358  simple_force_sources.push_back(std::make_shared<HarmonicForce>(container_data));
359  }
360 
361  // Pairwise Forces
362  if (forces.LennardJones()) {
363  pairwise_force_sources.push_back(std::make_shared<LennardJonesForce>());
364  }
365  if (forces.LennardJonesRepulsive()) {
366  pairwise_force_sources.push_back(std::make_shared<LennardJonesRepulsiveForce>());
367  }
368  if (forces.SmoothedLennardJones()) {
369  double r_c = (*forces.SmoothedLennardJones()).r_c();
370  double r_l = (*forces.SmoothedLennardJones()).r_l();
371  pairwise_force_sources.push_back(std::make_shared<SmoothedLennardJonesForce>(r_c, r_l));
372  }
373  if (forces.Gravitational()) {
374  pairwise_force_sources.push_back(std::make_shared<GravitationalForce>());
375  }
376 
377  // Targetted Forces
378  if (forces.TargettedTemporaryConstant()) {
379  auto indices_list = forces.TargettedTemporaryConstant()->indices();
380  std::vector<size_t> indices_vector;
381  for (auto& index : indices_list) {
382  indices_vector.push_back(index);
383  }
384  auto force = convertToVector(forces.TargettedTemporaryConstant()->force());
385  auto start_time = forces.TargettedTemporaryConstant()->start_time();
386  auto end_time = forces.TargettedTemporaryConstant()->end_time();
387 
388  targetted_force_sources.push_back(std::make_shared<TargettedTemporaryConstantForce>(indices_vector, force, start_time, end_time));
389  }
390 
391  return {simple_force_sources, pairwise_force_sources, targetted_force_sources};
392 }
393 
394 std::array<double, 3> XSDToInternalTypeAdapter::convertToVector(const DoubleVec3Type& vector) {
395  return {vector.x(), vector.y(), vector.z()};
396 }
397 
398 std::array<int, 3> XSDToInternalTypeAdapter::convertToVector(const IntVec3Type& vector) { return {vector.x(), vector.y(), vector.z()}; }
ThirdDimension
Enum class to define the dimension count of the simulation (2D or 3D). Affects primarily the dimensio...
Definition: Enums.h:7
LockState
Enum class to define the lockstate of particles. Locked particles are not allowed to move.
Definition: Enums.h:12
OutputFormat convertToOutputFormat(const std::string &output_format)
Converts a string to an OutputFormat.
Class to spawn particles in a cuboid. Implements the interface ParticleSpawner.
Definition: CuboidSpawner.h:15
BoundaryCondition
Boundary type enum for labeling the sides of the domain.
static std::shared_ptr< spdlog::logger > logger
Publically accessible shared pointer to the logger.
Definition: Logger.h:35
Class to represent a particle.
Definition: Particle.h:26
void addConnectedParticle(long ptr_diff, double l_0, double k)
Adds a connected particle.
Definition: Particle.cpp:74
Class to spawn particles of a soft body in a cuboid. Implements the interface ParticleSpawner.
Class to spawn particles in a Sphere. Implements the interface ParticleSpawner.
Definition: SphereSpawner.h:15
static SoftBodyCuboidSpawner convertToSoftBodyCuboidSpawner(const SoftBodySpawnerType &soft_body_cuboid, ThirdDimension third_dimension)
Converts a soft body cuboid from the XSD format to the internal format.
static SphereSpawner convertToSphereSpawner(const SphereSpawnerType &sphere, ThirdDimension third_dimension)
Converts a sphere from the XSD format to the internal format.
static std::tuple< std::vector< std::shared_ptr< SimpleForceSource > >, std::vector< std::shared_ptr< PairwiseForceSource > >, std::vector< std::shared_ptr< TargettedForceSource > > > convertToForces(const ForcesType &forces, const std::variant< SimulationParams::DirectSumType, SimulationParams::LinkedCellsType > &container_data)
Converts a force type from the XSD format to the internal format.
static LinkedCellsContainer::BoundaryCondition convertToBoundaryCondition(const BoundaryType &boundary)
Converts a boundary type from the XSD format to the internal format.
static std::variant< SimulationParams::DirectSumType, SimulationParams::LinkedCellsType > convertToParticleContainer(const ParticleContainerType &container_type)
Converts a container type from the XSD format to the internal format.
static std::array< LinkedCellsContainer::BoundaryCondition, 6 > convertToBoundaryConditionsArray(const BoundaryConditionsType &boundary)
Converts a boundary conditions type from the XSD format to the internal format.
static Particle convertToParticle(const ParticleType &particle)
Converts a particle type from the XSD format to the internal format.
static CuboidSpawner convertToSingleParticleSpawner(const SingleParticleSpawnerType &particle, ThirdDimension third_dimension)
Converts a particle from the XSD format to the internal format.
static std::array< double, 3 > convertToVector(const DoubleVec3Type &vector)
Converts a double vector from the XSD format to the internal format.
static std::vector< std::shared_ptr< SimulationInterceptor > > convertToSimulationInterceptors(const SimulationInterceptorsType &interceptors, ThirdDimension third_dimension, std::variant< SimulationParams::DirectSumType, SimulationParams::LinkedCellsType > container_type)
Converts the simulation interceptors from the XSD format to the internal format.
static CuboidSpawner convertToCuboidSpawner(const CuboidSpawnerType &cuboid, ThirdDimension third_dimension)
Converts a cuboid from the XSD format to the internal format.
Struct to specify the type of the particle container as DirectSumType.
Struct to specify the type of the particle container as LinkedCellsType (needs domain_size and cutoff...