Commit 4feaaf8b authored by Cristian Lalescu's avatar Cristian Lalescu
Browse files

Merge branch 'feature/collisions' into develop

parents 75c2c631 2fba4801
Pipeline #70816 passed with stage
in 8 minutes and 14 seconds
...@@ -364,6 +364,7 @@ set(hpp_for_lib ...@@ -364,6 +364,7 @@ set(hpp_for_lib
${PROJECT_SOURCE_DIR}/cpp/particles/lock_free_bool_array.hpp ${PROJECT_SOURCE_DIR}/cpp/particles/lock_free_bool_array.hpp
${PROJECT_SOURCE_DIR}/cpp/particles/p2p_computer_empty.hpp ${PROJECT_SOURCE_DIR}/cpp/particles/p2p_computer_empty.hpp
${PROJECT_SOURCE_DIR}/cpp/particles/p2p_computer.hpp ${PROJECT_SOURCE_DIR}/cpp/particles/p2p_computer.hpp
${PROJECT_SOURCE_DIR}/cpp/particles/p2p_ghost_collision_base.hpp
${PROJECT_SOURCE_DIR}/cpp/particles/p2p_ghost_collisions.hpp ${PROJECT_SOURCE_DIR}/cpp/particles/p2p_ghost_collisions.hpp
${PROJECT_SOURCE_DIR}/cpp/particles/p2p_cylinder_collisions.hpp ${PROJECT_SOURCE_DIR}/cpp/particles/p2p_cylinder_collisions.hpp
${PROJECT_SOURCE_DIR}/cpp/particles/p2p_distr_mpi.hpp ${PROJECT_SOURCE_DIR}/cpp/particles/p2p_distr_mpi.hpp
......
...@@ -257,7 +257,7 @@ Afterwards, please run variations of the following command: ...@@ -257,7 +257,7 @@ Afterwards, please run variations of the following command:
.. code:: bash .. code:: bash
python ${TURTLE REPOSITORY}/tests/DNS/test_scaling.py D \ python ${TURTLE_REPOSITORY}/tests/DNS/test_scaling.py D \
-n 128 \ -n 128 \
--nprocesses 4 \ --nprocesses 4 \
--ncores 1 \ --ncores 1 \
......
...@@ -445,6 +445,7 @@ class DNS(_code): ...@@ -445,6 +445,7 @@ class DNS(_code):
'NSVE_Stokes_particles', 'NSVE_Stokes_particles',
'NSVEparticles', 'NSVEparticles',
'static_field', 'static_field',
'static_field_with_ghost_collisions',
'kraichnan_field']: 'kraichnan_field']:
assert (self.parameters['niter_todo'] % self.parameters['niter_part'] == 0) assert (self.parameters['niter_todo'] % self.parameters['niter_part'] == 0)
assert (self.parameters['niter_out'] % self.parameters['niter_part'] == 0) assert (self.parameters['niter_out'] % self.parameters['niter_part'] == 0)
...@@ -488,6 +489,8 @@ class DNS(_code): ...@@ -488,6 +489,8 @@ class DNS(_code):
4), 4),
dtype = np.int64) dtype = np.int64)
ofile['checkpoint'] = int(0) ofile['checkpoint'] = int(0)
if self.dns_type in ['static_field_with_ghost_collisions']:
ofile.create_group('statistics/collisions')
if (self.dns_type in ['NSVE', 'NSVE_no_output']): if (self.dns_type in ['NSVE', 'NSVE_no_output']):
return None return None
return None return None
...@@ -646,6 +649,10 @@ class DNS(_code): ...@@ -646,6 +649,10 @@ class DNS(_code):
'static_field', 'static_field',
help = 'static field with basic fluid tracers') help = 'static field with basic fluid tracers')
parser_static_field_with_ghost_collisions = subparsers.add_parser(
'static_field_with_ghost_collisions',
help = 'static field with basic fluid tracers and ghost collisions')
parser_kraichnan_field = subparsers.add_parser( parser_kraichnan_field = subparsers.add_parser(
'kraichnan_field', 'kraichnan_field',
help = 'Kraichnan field with basic fluid tracers') help = 'Kraichnan field with basic fluid tracers')
...@@ -673,6 +680,7 @@ class DNS(_code): ...@@ -673,6 +680,7 @@ class DNS(_code):
'NSVE_Stokes_particles', 'NSVE_Stokes_particles',
'NSVEp_extra', 'NSVEp_extra',
'static_field', 'static_field',
'static_field_with_ghost_collisions',
'kraichnan_field']: 'kraichnan_field']:
eval('self.simulation_parser_arguments({0})'.format('parser_' + pp)) eval('self.simulation_parser_arguments({0})'.format('parser_' + pp))
eval('self.job_parser_arguments({0})'.format('parser_' + pp)) eval('self.job_parser_arguments({0})'.format('parser_' + pp))
...@@ -749,6 +757,7 @@ class DNS(_code): ...@@ -749,6 +757,7 @@ class DNS(_code):
'NSVEparticles_no_output', 'NSVEparticles_no_output',
'NSVEp_extra_sampling', 'NSVEp_extra_sampling',
'static_field', 'static_field',
'static_field_with_ghost_collisions',
'kraichnan_field']: 'kraichnan_field']:
for k in self.NSVEp_extra_parameters.keys(): for k in self.NSVEp_extra_parameters.keys():
self.parameters[k] = self.NSVEp_extra_parameters[k] self.parameters[k] = self.NSVEp_extra_parameters[k]
...@@ -823,6 +832,7 @@ class DNS(_code): ...@@ -823,6 +832,7 @@ class DNS(_code):
if self.dns_type in [ if self.dns_type in [
'kraichnan_field', 'kraichnan_field',
'static_field', 'static_field',
'static_field_with_ghost_collisions',
'NSVEparticles', 'NSVEparticles',
'NSVEcomplex_particles', 'NSVEcomplex_particles',
'NSVE_Stokes_particles', 'NSVE_Stokes_particles',
...@@ -1138,6 +1148,7 @@ class DNS(_code): ...@@ -1138,6 +1148,7 @@ class DNS(_code):
if self.dns_type in [ if self.dns_type in [
'kraichnan_field', 'kraichnan_field',
'static_field', 'static_field',
'static_field_with_ghost_collisions',
'NSVEparticles', 'NSVEparticles',
'NSVEcomplex_particles', 'NSVEcomplex_particles',
'NSVE_Stokes_particles', 'NSVE_Stokes_particles',
......
...@@ -43,6 +43,11 @@ inline int MOD(int a, int n) ...@@ -43,6 +43,11 @@ inline int MOD(int a, int n)
return ((a%n) + n) % n; return ((a%n) + n) % n;
} }
template <typename T> int sgn(T val)
{
return (T(0) < val) - (val < T(0));
}
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
......
...@@ -64,19 +64,24 @@ int static_field<rnumber>::initialize(void) ...@@ -64,19 +64,24 @@ int static_field<rnumber>::initialize(void)
this->vorticity = new field<rnumber, FFTW, THREE>( this->vorticity = new field<rnumber, FFTW, THREE>(
nx, ny, nz, nx, ny, nz,
this->comm, this->comm,
fftw_planner_string_to_flag[this->fftw_plan_rigor]); fftw_planner_string_to_flag[this->fftw_plan_rigor]);
this->vorticity->real_space_representation = false; this->vorticity->real_space_representation = false;
this->velocity = new field<rnumber, FFTW, THREE>( this->velocity = new field<rnumber, FFTW, THREE>(
nx, ny, nz, nx, ny, nz,
this->comm, this->comm,
fftw_planner_string_to_flag[this->fftw_plan_rigor]); fftw_planner_string_to_flag[this->fftw_plan_rigor]);
this->velocity->real_space_representation = false; this->velocity->real_space_representation = false;
//read vorticity field //read static vorticity field from iteration 0
std::string checkpoint_fname = (
std::string(this->simname) +
std::string("_checkpoint_") +
std::to_string(0) +
std::string(".h5"));
this->vorticity->io( this->vorticity->io(
this->get_current_fname(), checkpoint_fname,
"vorticity", "vorticity",
this->iteration, 0,
true); true);
this->kk = new kspace<FFTW, SMOOTH>( this->kk = new kspace<FFTW, SMOOTH>(
this->vorticity->clayout, this->dkx, this->dky, this->dkz); this->vorticity->clayout, this->dkx, this->dky, this->dkz);
...@@ -96,7 +101,7 @@ int static_field<rnumber>::initialize(void) ...@@ -96,7 +101,7 @@ int static_field<rnumber>::initialize(void)
this->kk, // (kspace object, contains dkx, dky, dkz) this->kk, // (kspace object, contains dkx, dky, dkz)
tracers0_integration_steps, // to check coherency between parameters and hdf input file (nb rhs) tracers0_integration_steps, // to check coherency between parameters and hdf input file (nb rhs)
(long long int)nparticles, // to check coherency between parameters and hdf input file (long long int)nparticles, // to check coherency between parameters and hdf input file
this->get_current_fname(), // particles input filename this->get_current_fname(), // particles input filename
std::string("/tracers0/state/") + std::to_string(this->iteration), // dataset name for initial input std::string("/tracers0/state/") + std::to_string(this->iteration), // dataset name for initial input
std::string("/tracers0/rhs/") + std::to_string(this->iteration), // dataset name for initial input std::string("/tracers0/rhs/") + std::to_string(this->iteration), // dataset name for initial input
tracers0_neighbours, // parameter (interpolation no neighbours) tracers0_neighbours, // parameter (interpolation no neighbours)
...@@ -144,6 +149,7 @@ int static_field<rnumber>::write_checkpoint(void) ...@@ -144,6 +149,7 @@ int static_field<rnumber>::write_checkpoint(void)
this->ps->getLocalNbParticles(), this->ps->getLocalNbParticles(),
this->iteration); this->iteration);
this->particles_output_writer_mpi->close_file(); this->particles_output_writer_mpi->close_file();
this->write_iteration();
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
......
...@@ -3,6 +3,63 @@ ...@@ -3,6 +3,63 @@
#include <cfloat> #include <cfloat>
#include <climits> #include <climits>
template <> hid_t hdf5_tools::hdf5_type_id<char>()
{
return H5T_NATIVE_CHAR;
}
template <> hid_t hdf5_tools::hdf5_type_id<signed char>()
{
return H5T_NATIVE_SCHAR;
}
template <> hid_t hdf5_tools::hdf5_type_id<unsigned char>()
{
return H5T_NATIVE_UCHAR;
}
template <> hid_t hdf5_tools::hdf5_type_id<short>()
{
return H5T_NATIVE_SHORT;
}
template <> hid_t hdf5_tools::hdf5_type_id<unsigned short>()
{
return H5T_NATIVE_USHORT;
}
template <> hid_t hdf5_tools::hdf5_type_id<int>()
{
return H5T_NATIVE_INT;
}
template <> hid_t hdf5_tools::hdf5_type_id<unsigned>()
{
return H5T_NATIVE_UINT;
}
template <> hid_t hdf5_tools::hdf5_type_id<long>()
{
return H5T_NATIVE_LONG;
}
template <> hid_t hdf5_tools::hdf5_type_id<unsigned long>()
{
return H5T_NATIVE_ULONG;
}
template <> hid_t hdf5_tools::hdf5_type_id<long long>()
{
return H5T_NATIVE_LLONG;
}
template <> hid_t hdf5_tools::hdf5_type_id<unsigned long long>()
{
return H5T_NATIVE_ULLONG;
}
template <> hid_t hdf5_tools::hdf5_type_id<float>()
{
return H5T_NATIVE_FLOAT;
}
template <> hid_t hdf5_tools::hdf5_type_id<double>()
{
return H5T_NATIVE_DOUBLE;
}
template <> hid_t hdf5_tools::hdf5_type_id<long double>()
{
return H5T_NATIVE_LDOUBLE;
}
int hdf5_tools::require_size_single_dataset(hid_t dset, int tsize) int hdf5_tools::require_size_single_dataset(hid_t dset, int tsize)
{ {
TIMEZONE("hdf5_tools::require_size_single_dataset"); TIMEZONE("hdf5_tools::require_size_single_dataset");
...@@ -178,6 +235,36 @@ number hdf5_tools::read_value( ...@@ -178,6 +235,36 @@ number hdf5_tools::read_value(
return result; return result;
} }
template <typename number>
int hdf5_tools::write_value_with_single_rank(
const hid_t group,
const std::string dset_name,
const number value)
{
hid_t dset, mem_dtype;
if (typeid(number) == typeid(int))
mem_dtype = H5Tcopy(H5T_NATIVE_INT);
else if (typeid(number) == typeid(double))
mem_dtype = H5Tcopy(H5T_NATIVE_DOUBLE);
if (H5Lexists(group, dset_name.c_str(), H5P_DEFAULT))
{
dset = H5Dopen(group, dset_name.c_str(), H5P_DEFAULT);
}
else
{
hid_t fspace;
hsize_t count[1];
count[0] = 1;
fspace = H5Screate_simple(1, count, NULL);
dset = H5Dcreate(group, dset_name.c_str(), mem_dtype, fspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
H5Sclose(fspace);
}
H5Dwrite(dset, mem_dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, &value);
H5Dclose(dset);
H5Tclose(mem_dtype);
return EXIT_SUCCESS;
}
template <typename dtype> template <typename dtype>
std::vector<dtype> hdf5_tools::read_vector_with_single_rank( std::vector<dtype> hdf5_tools::read_vector_with_single_rank(
const int myrank, const int myrank,
...@@ -244,6 +331,44 @@ std::string hdf5_tools::read_string( ...@@ -244,6 +331,44 @@ std::string hdf5_tools::read_string(
} }
} }
template <class partsize_t>
int hdf5_tools::write_particle_ID_pairs_with_single_rank(
const std::vector<partsize_t> v,
const hid_t group,
const std::string dset_name)
{
TIMEZONE("hdf5_tools::write_particle_ID_pairs_with_single_rank");
// the vector contains pair information, so its size must be a multiple of 2
assert((v.size() % 2) == 0);
// file space creation
hid_t fspace;
hsize_t dims[2];
dims[0] = v.size()/2;
dims[1] = 2;
fspace = H5Screate_simple(2, dims, NULL);
// create dataset
hsize_t dset_id = H5Dcreate(
group,
dset_name.c_str(),
hdf5_tools::hdf5_type_id<partsize_t>(),
fspace,
H5P_DEFAULT,
H5P_DEFAULT,
H5P_DEFAULT);
// write data
H5Dwrite(
dset_id,
hdf5_tools::hdf5_type_id<partsize_t>(),
H5S_ALL,
H5S_ALL,
H5P_DEFAULT,
&v.front());
// clean up
H5Dclose(dset_id);
H5Sclose(fspace);
return EXIT_SUCCESS;
}
template template
std::vector<int> hdf5_tools::read_vector<int>( std::vector<int> hdf5_tools::read_vector<int>(
const hid_t, const hid_t,
...@@ -280,3 +405,21 @@ double hdf5_tools::read_value<double>( ...@@ -280,3 +405,21 @@ double hdf5_tools::read_value<double>(
const hid_t, const hid_t,
const std::string); const std::string);
template
int hdf5_tools::write_value_with_single_rank<int>(
const hid_t group,
const std::string dset_name,
const int value);
template
int hdf5_tools::write_value_with_single_rank<double>(
const hid_t group,
const std::string dset_name,
const double value);
template
int hdf5_tools::write_particle_ID_pairs_with_single_rank(
const std::vector<long long> v,
const hid_t group,
const std::string dset_name);
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
namespace hdf5_tools namespace hdf5_tools
{ {
// see https://support.hdfgroup.org/HDF5/doc/H5.user/Datatypes.html
template <typename data_type> hid_t hdf5_type_id();
int grow_single_dataset( int grow_single_dataset(
hid_t dset, hid_t dset,
int tincrement); int tincrement);
...@@ -84,6 +87,18 @@ namespace hdf5_tools ...@@ -84,6 +87,18 @@ namespace hdf5_tools
number read_value( number read_value(
const hid_t group, const hid_t group,
const std::string dset_name); const std::string dset_name);
template <typename number>
int write_value_with_single_rank(
const hid_t group,
const std::string dset_name,
const number value);
template <class partsize_t>
int write_particle_ID_pairs_with_single_rank(
const std::vector<partsize_t> v,
const hid_t group,
const std::string dset_name);
} }
#endif//HDF5_TOOLS_HPP #endif//HDF5_TOOLS_HPP
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#define ABSTRACT_PARTICLES_SYSTEM_HPP #define ABSTRACT_PARTICLES_SYSTEM_HPP
#include <memory> #include <memory>
#include <vector>
//- Not generic to enable sampling begin //- Not generic to enable sampling begin
#include "field.hpp" #include "field.hpp"
...@@ -39,6 +40,8 @@ class abstract_particles_system { ...@@ -39,6 +40,8 @@ class abstract_particles_system {
public: public:
virtual ~abstract_particles_system(){} virtual ~abstract_particles_system(){}
virtual void delete_particles_from_indexes(const std::vector<partsize_t>& inIndexToDelete) = 0;
virtual void compute() = 0; virtual void compute() = 0;
virtual void compute_p2p() = 0; virtual void compute_p2p() = 0;
......
...@@ -70,7 +70,9 @@ public: ...@@ -70,7 +70,9 @@ public:
} }
template <int size_particle_positions, int size_particle_rhs> template <int size_particle_positions, int size_particle_rhs>
void compute_interaction(const real_number pos_part1[], real_number rhs_part1[], void compute_interaction(const partsize_t /*idx_part1*/,
const real_number pos_part1[], real_number rhs_part1[],
const partsize_t /*idx_part2*/,
const real_number pos_part2[], real_number rhs_part2[], const real_number pos_part2[], real_number rhs_part2[],
const real_number dist_pow2, const real_number cutoff, const real_number dist_pow2, const real_number cutoff,
const real_number /*xshift_coef*/, const real_number /*yshift_coef*/, const real_number /*zshift_coef*/) const{ const real_number /*xshift_coef*/, const real_number /*yshift_coef*/, const real_number /*zshift_coef*/) const{
......
...@@ -40,7 +40,9 @@ public: ...@@ -40,7 +40,9 @@ public:
} }
template <int size_particle_positions, int size_particle_rhs> template <int size_particle_positions, int size_particle_rhs>
void compute_interaction(const real_number /*pos_part1*/[], real_number /*rhs_part1*/[], void compute_interaction(const partsize_t /*idx_part1*/,
const real_number /*pos_part1*/[], real_number /*rhs_part1*/[],
const partsize_t /*idx_part2*/,
const real_number /*pos_part2*/[], real_number /*rhs_part2*/[], const real_number /*pos_part2*/[], real_number /*rhs_part2*/[],
const real_number /*dist_pow2*/, const real_number /*cutoff*/, const real_number /*dist_pow2*/, const real_number /*cutoff*/,
const real_number /*xshift_coef*/, const real_number /*yshift_coef*/, const real_number /*zshift_coef*/) const{ const real_number /*xshift_coef*/, const real_number /*yshift_coef*/, const real_number /*zshift_coef*/) const{
......
...@@ -24,54 +24,138 @@ ...@@ -24,54 +24,138 @@
#define P2P_CYLINDER_GHOST_COLLISIONS_HPP #define P2P_CYLINDER_GHOST_COLLISIONS_HPP
#include <cstring> #include <cstring>
#include <math.h> /* for sqrt, abs */
#include <set>
#include <utility>
#include <vector>
#include "particles/p2p_ghost_collision_base.hpp"
template <class real_number, class partsize_t> template <class real_number, class partsize_t>
class p2p_cylinder_ghost_collisions{ class p2p_cylinder_ghost_collisions: public p2p_ghost_collision_base<real_number, partsize_t>
long int collision_counter; {
private:
// Following doubles are needed for the collision computation
double width;
double length;
public: public:
p2p_cylinder_ghost_collisions() : collision_counter(0){} p2p_cylinder_ghost_collisions() : width(1.),length(1.){}
// Copy constructor use a counter set to zero // Copy constructor use a counter set to zero
p2p_cylinder_ghost_collisions(const p2p_cylinder_ghost_collisions&) : collision_counter(0){} p2p_cylinder_ghost_collisions(const p2p_cylinder_ghost_collisions&){}
template <int size_particle_rhs>
void init_result_array(real_number /*rhs*/[], const partsize_t /*nbParticles*/) const{
}
template <int size_particle_rhs>
void reduce_particles_rhs(real_number /*rhs_dst*/[], const real_number /*rhs_src*/[], const partsize_t /*nbParticles*/) const{
}
template <int size_particle_positions, int size_particle_rhs> template <int size_particle_positions, int size_particle_rhs>
void compute_interaction(const real_number /*pos_part1*/[], real_number /*rhs_part1*/[], void compute_interaction(const partsize_t idx_part1,
const real_number /*pos_part2*/[], real_number /*rhs_part2*/[], const real_number pos_part1[], real_number /*rhs_part1*/[],
const partsize_t idx_part2,
const real_number pos_part2[], real_number /*rhs_part2*/[],
const real_number /*dist_pow2*/, const real_number /*cutoff*/, const real_number /*dist_pow2*/, const real_number /*cutoff*/,
const real_number /*xshift_coef*/, const real_number /*yshift_coef*/, const real_number /*zshift_coef*/){ const real_number /*xshift_coef*/, const real_number /*yshift_coef*/, const real_number /*zshift_coef*/){
bool cylinders_overlap = false; double x, y, z, pq, xp, xq, t, s, x_dist, y_dist, z_dist ,min_distance, pi, pi2;
/* TODO: check if cylinders overlap or not, set `cylinders_overlap` accordingly */ pi2 = atan(1.0)*8.0;
pi = atan(1.0)*4.0;
if(cylinders_overlap) /* Relative position vector of the two particles (x,y,z)^T */
collision_counter += 1; /* complicated usage of fmod, fabs and sgn because C++ fmod does not do what it should. */
x = std::fmod(pos_part2[0],pi2)-std::fmod(pos_part1[0],pi2);
y = std::fmod(pos_part2[1],pi2)-std::fmod(pos_part1[1],pi2);
z = std::fmod(pos_part2[2],pi2)-std::fmod(pos_part1[2],pi2);
x = ( std::fmod( std::fabs(x) +pi ,pi2) - pi ) * sgn(x) ;
y = ( std::fmod( std::fabs(y) +pi ,pi2) - pi ) * sgn(y) ;
z = ( std::fmod( std::fabs(z) +pi ,pi2) - pi ) * sgn(z) ;
if( sqrt(x*x+y*y+z*z) <= length )
{
/* p and q are the orientation vectors of the first and second particles. */
/* pq, xp, xq are scalar products of these vectors with x, relative position */
pq = pos_part1[3] * pos_part2[3] + pos_part1[4] * pos_part2[4] + pos_part1[5] * pos_part2[5];
xp = x * pos_part1[3] + y * pos_part1[4] + z * pos_part1[5];
xq = x * pos_part2[3] + y * pos_part2[4] + z * pos_part2[5];
/* t and s parametrize the two rods. Find min distance: */
assert(this->length > 0);
t = 2.0/(this->length*(pq*pq-1.0))*(-xp+pq*xq);
s = 2.0/(this->length*(pq*pq-1.0))*(-pq*xp+xq);
/* Test if -1<s<1 and -1<t<1 */
if( abs(t)<=1.0 and abs(s)<=1.0 ) {
/* Get minimal distance in case of both t and s in {-1,1}. Else: check edges */
x_dist = this->length*0.5*t*pos_part1[3]-this->length*0.5*s*pos_part2[3]-x;
y_dist = this->length*0.5*t*pos_part1[4]-this->length*0.5*s*pos_part2[4]-y;
z_dist = this->length*0.5*t*pos_part1[5]-this->length*0.5*s*pos_part2[5]-z;
min_distance = sqrt(x_dist*x_dist+y_dist*y_dist+z_dist*z_dist);
}
else
{
min_distance = this->length;
/* t fixed at 1, find min along s */
t = 1.0;
s = t*pq-2.0/this->length*xq;
if( abs(s)>1.0 ) { s = s / abs(s) ;}
x_dist = this->length*0.5*t*pos_part1[3]-this->length*0.5*s*pos_part2[3]-x;
y_dist = this->length*0.5*t*pos_part1[4]-this->length*0.5*s*pos_part2[4]-y;
z_dist = this->length*0.5*t*pos_part1[5]-this->length*0.5*s*pos_part2[5]-z;
min_distance = fmin( sqrt(x_dist*x_dist+y_dist*y_dist+z_dist*z_dist), min_distance );
/* t fixed at -1, find min along s */
t = -1.0;
s = t*pq-2.0/this->length*xq;
if( abs(s)>1.0 ) { s = s / abs(s) ;}
x_dist = this->length*0.5*t*pos_part1[3]-this->length*0.5*s*pos_part2[3]-x;
y_dist = this->length*0.5*t*pos_part1[4]-this->length*0.5*s*pos_part2[4]-y;
z_dist = this->length*0.5*t*pos_part1[5]-this->length*0.5*s*pos_part2[5]-z;
min_distance = fmin( sqrt(x_dist*x_dist+y_dist*y_dist+z_dist*z_dist), min_distance );
/* s fixed at 1, find min along t */
s = 1.0;
t = s*pq+2.0/this->length*xp;