NDDEM
|
Classes | |
class | Cell |
Individual cell for contact detection. More... | |
class | Cells< d > |
All the cells making the space, with related function for creating the cell array, neighbour arrays etc. Currently non implemented TODO: no pbc handling, no handling of moving boundaries. More... | |
class | Action< d > |
Handle force and torque contact information. More... | |
class | SpecificAction< d > |
Action on a specific particle for a specific duration. More... | |
class | cp< d > |
Contact properties class. More... | |
class | cpm< d > |
Contact properties for mesh contacts (mainly), including contact point location, specialising cp. More... | |
class | ContactList< d > |
Handles lists of contacts. More... | |
class | ContactListMesh< d > |
Handles lists of contacts with meshes. More... | |
class | Contacts< d > |
Calculate contact forces. More... | |
class | Simulation< d > |
struct | CLp_it_t< d > |
Simple packing structure for the iterators to the contact list regions per particle. More... | |
class | Multiproc< d > |
Manual multiprocessor handling for OpenMP, for max efficiency & avoiding bugs & race conditions, hopefully. More... | |
class | number_gen< T > |
Small class to handle number generator (ie. first:step:last syntax) More... | |
class | Parameters< d > |
Generic class to handle the simulation set up. More... | |
class | TensorInfos |
Limited use: used to transfer data to the VTK writer. More... | |
class | Tools_2D |
Dimension specific mathematics. More... | |
class | Tools< d > |
Static class to handle multi-dimensional mathematics, and more. It gets specialised for speed with template parameter d:dimension. More... | |
Macros | |
#define | CONTACTLIST |
#define | MAXDIM 4 |
#define | MACRO(r, state) case BOOST_PP_TUPLE_ELEM(2, 0, state): templatedmain<BOOST_PP_TUPLE_ELEM(2, 0, state)>(argv);break; |
#define | STR_PROTECT(s) s |
#define | MAXDEFDIM 30 |
For larger number of dimension, be taken in particular for periodic boundary conditions. More... | |
Typedefs | |
using | json = nddem::json |
using | uint = unsigned int |
using | v1d = vector< double > |
using | v2d = vector< vector< double > > |
using | v3d = vector< vector< vector< double > >> |
using | v1f = vector< float > |
using | cv1d = const vector< double > |
using | cv2d = const vector< vector< double > > |
using | cv3d = const vector< vector< vector< double > >> |
using | cv1f = const vector< float > |
using | bitdim = unsigned int |
using | v1i = vector< int > |
Functions | |
template<int d> | |
bool | operator< (const cp< d > &a, const cp< d > &b) |
The contact list is order in increasing order of index i, and for two identical i in increasing order of j. More... | |
template<int d> | |
bool | operator== (const cp< d > &a, const cp< d > &b) |
Contact equivalence is based solely on the index of objects in contact i and j. More... | |
void | sig_handler (int p) |
Function handling signal reception for clean closing on SIGINT for example. More... | |
template<int d> | |
int | templatedmain (char *argv[]) |
Main simulation run. All the simulation is handled by this function. More... | |
int | main (int argc, char *argv[]) |
Calls the appropriate templatedmain() function. Templated function are used to allow compiler optimisation for speed. Only a handful of dimension are compiled on the base code to limit compilation time and memory. If you need dimensions that are not cmpiled by default, have a look at the code it's pretty straightforward to activate the needed dimension. If the compilation failed with low meomry, in particular on older system, head to the code and comment the dimensions which are unused. More... | |
ExportType & | operator|= (ExportType &a, const ExportType b) |
ExportData & | operator|= (ExportData &a, const ExportData b) |
ExportData | operator| (ExportData a, ExportData b) |
ExportData | operator~ (ExportData a) |
ExportData & | operator&= (ExportData &a, const ExportData b) |
ExportData & | operator>>= (ExportData &w, int u) |
ExportData & | operator<<= (ExportData &w, int u) |
bool | operator& (ExportType &a, ExportType b) |
bool | operator& (ExportData &a, ExportData b) |
template<typename T > | |
std::istream & | operator>> (std::istream &in, number_gen< T > &n) |
v1d | operator* (v1d a, double b) |
v1f | operator* (v1f a, float b) |
v1d | operator* (v1d a, cv1d &b) |
v1f | operator* (v1f a, cv1f &b) |
v1d | operator+ (v1d a, double b) |
v1d | operator+ (v1d a, cv1d &b) |
v1f | operator+ (v1f a, cv1f &b) |
v1d | operator- (v1d a, double &b) |
v1d | operator- (v1d a, cv1d &b) |
v1d | operator- (v1d a, const double *b) |
v1d | operator- (const double *a, v1d b) |
v1d | operator- (v1d a) |
v1f | operator- (v1f a, cv1f &b) |
v1d | operator/ (v1d a, double b) |
v1d & | operator-= (v1d &a, cv1d &b) |
v1d & | operator*= (v1d &a, double b) |
v1f & | operator*= (v1f &a, double b) |
v1d & | operator+= (v1d &a, cv1d &b) |
v1f & | operator+= (v1f &a, cv1f &b) |
v1f & | operator/= (v1f &a, cv1f &b) |
v1d & | operator/= (v1d &a, double b) |
v1f & | operator/= (v1f &a, double b) |
v1d | operator- (v1d a, double b) |
int | ContactList< d >::insert (const cp< d > &a) |
Insert a contact, maintaining sorting with increasing i, and removing missing contacts on traversal. More... | |
int | ContactListMesh< d >::insert (const cpm< d > &a) |
Insert a contact, maintaining sorting with increasing i, and removing missing contacts on traversal. More... | |
bool | ContactList< d >::check_ghost_regular (bitdim gst, const Parameters< d > &P, cv1d &X1, cv1d &X2, double r1, double r2, cp< d > &tmpcp, int startd=0, double partialsum=0, bitdim mask=0) |
Find ghost-particle contact, going though pbc recursively. A beautiful piece of optimised algorithm if I may say so myself. More... | |
bool | ContactList< d >::check_ghost_LE (bitdim gst, const Parameters< d > &P, cv1d &X1, cv1d &X2, double r1, double r2, cp< d > &tmpcp, int startd=0, double partialsum=0, bitdim mask=0) |
void | ContactList< d >::check_ghost_dst (uint32_t gst, int n, double partialsum, uint32_t mask, const Parameters< d > &P, cv1d &X1, cv1d &X2, cp< d > &contact) |
void | ContactList< d >::coordinance (v1d &Z) |
Calculate and store coordination number in Z. More... | |
Contacts< d >::Contacts (Parameters< d > &PP) | |
void | Contacts< d >::particle_particle (cv1d &Xi, cv1d &Vi, cv1d &Omegai, double ri, double mi, cv1d &Xj, cv1d &Vj, cv1d &Omegaj, double rj, double mj, cp< d > &Contact, bool isdumptime) |
Force & torque between 2 particles. More... | |
void | Contacts< d >::particle_wall (cv1d &Vi, cv1d &Omegai, double ri, double mi, cv1d &cn, cp< d > &Contact) |
Force & torque between a particle and a wall. More... | |
void | Contacts< d >::particle_movingwall (cv1d &Vi, cv1d &Omegai, double ri, double mi, cv1d &cn, cv1d &Vj, cp< d > &Contact) |
Force & torque between a particle and a moving wall. Vj is the velocity of the wall at the contact point. More... | |
void | Contacts< d >::particle_mesh (cv1d &Xi, cv1d &Vi, cv1d &Omegai, double ri, double mi, cpm< d > &Contact) |
Force & torque between particle and mesh. More... | |
void | Multiproc< d >::disp_share () |
Display the # of particle on each thread. More... | |
void | Multiproc< d >::split (int N, int P) |
Function to allocate the grains to threads taking into account the load balance in the contact detection. load_balance() takes over after a few iteration have run, and is usually more efficient. More... | |
void | Multiproc< d >::splitcells (int C) |
void | Multiproc< d >::delaying (int ID, int j, Action< d > &act) |
Record the action to be added later to the relevent atom in sequencial settings, avoid potential race condition if an action was added to an atom that is not owned by the thread. This is for a particle-particle contact. More... | |
void | Multiproc< d >::delayingwall (int ID, int j, Action< d > &act) |
Record the action on the wall. Only usefull if the force on the wall needs to be calculated. More... | |
void | Multiproc< d >::delayed_clean () |
Clean the record list. More... | |
void | Multiproc< d >::delayedwall_clean () |
Clean the record of the force on the wal. More... | |
void | Multiproc< d >::load_balance (ContactStrategies contactstrategy) |
Modify the atom share between threads to achieve better load balance between the threads based on the current speed of each one during the previous iterations. More... | |
auto | Multiproc< d >::contacts2array (ExportData exp, cv2d &X, Parameters< d > &P) |
pack the contact data in a 2d array More... | |
Variables | |
vector< std::pair< ExportType, ExportData > > * | toclean |
XMLWriter * | xmlout |
vector< std::pair< ExportType, ExportData > > * | toclean |
XMLWriter * | xmlout |
static vector< vector< int > > | Tools< d >::MSigns |
For skew symetric matrix. -1 below the diagonal, 0 on the diagonal, +1 above the diagnal. More... | |
static vector< vector< int > > | Tools< d >::MIndexAS |
For skew symmetric matrix, make the correspondance between linear index of a full matrix with the linear index of the skew-symetric storage. More... | |
static vector< pair< int, int > > | Tools< d >::MASIndex |
For skew symmetric matrix, make the correspondance between linear index and (row,column) index. More... | |
static v1d | Tools< d >::Eye |
The identity matrix in dimension <d> More... | |
static vector< FILE * > | Tools< d >::outs |
Store the output file descriptors. More... | |
static boost::random::mt19937 | Tools< d >::rng |
Random number generator. More... | |
static boost::random::uniform_01< boost::mt19937 > | Tools< d >::rand |
Returns a random number between 0 and 1. More... | |
General functions | |
static void | Tools< d >::initialise () |
Initialise the member variables, in particular the variables to handle skew-symmetric flattened matrix, cf. the class detailed description. More... | |
static void | Tools< d >::clear () |
Get the class ready for a different dimension. More... | |
static std::pair< double, double > | Tools< d >::two_max_element (cv1d &v) |
Return the two largest elements of v. More... | |
static bool | Tools< d >::check_initialised (int dd) |
static int | Tools< d >::sgn (uint8_t a) |
Sign function. More... | |
static int | Tools< d >::sgn (double a) |
Sign function. More... | |
Saving and writing functions | |
static int | Tools< d >::savetxt (char path[], const v2d &table, char const header[]) |
static int | Tools< d >::write1D (char path[], v1d table) |
static void | Tools< d >::savecsv (char path[], cv2d &X, cv1d &r, const vector< uint32_t > &PBCFlags, cv1d &Vmag, cv1d &OmegaMag, [[maybe_unused]] cv1d &Z) |
Save the location and a few more informations in a CSV file. More... | |
static void | Tools< d >::savecsv (char path[], cv2d &X, cv2d &V, cv1d &r, const vector< uint32_t > &PBCFlags, cv1d &Vmag, cv1d &OmegaMag, [[maybe_unused]] cv1d &Z) |
Save the location and a few more informations in a CSV file. More... | |
static void | Tools< d >::savecsv (char path[], cv2d &A) |
Save the orientation in a CSV file. More... | |
static void | Tools< d >::savevtk (char path[], int N, cv2d &Boundaries, cv2d &X, cv1d &r, vector< TensorInfos > data) |
Save as a vtk file. Dimensions higher than 3 are stored as additional scalars. Additional informations can be passed as a vector of TensorInfos. More... | |
static int | Tools< d >::writeinline (initializer_list< v1d >) |
static int | Tools< d >::writeinline_close (void) |
static void | Tools< d >::print (cv1d M) |
Vector and matrix initialisation and normalisation | |
static v1d | Tools< d >::randomize_vec (cv1d v) |
Produce a random vector. More... | |
static void | Tools< d >::unitvec (vector< double > &v, int n) |
Construct a unit vector in place. More... | |
static void | Tools< d >::orthonormalise (v1d &A) |
Orthonormalise A using the Gram-Shmidt process, in place. More... | |
static v1d | Tools< d >::unitvec (int n) |
Construct & return a unit vector. More... | |
static void | Tools< d >::setzero (v2d &a) |
Set a matrix to zero in-place. More... | |
static void | Tools< d >::setzero (v1d &a) |
Set a vector to zero in-place. More... | |
static double | Tools< d >::norm (const vector< double > &a) |
Norm of a vector. More... | |
static void | Tools< d >::norm (v1d &res, cv2d &a) |
Norm of a 2D-matrix, returns a 1D vector with the norms of the individual vectors. More... | |
static double | Tools< d >::normdiff (cv1d &a, cv1d &b) |
Norm of a vector difference ![]() | |
static double | Tools< d >::normsq (const vector< double > &a) |
Norm squared. More... | |
static double | Tools< d >::normdiffsq (cv1d &a, cv1d &b) |
Norm squared of a vector difference ![]() | |
static double | Tools< d >::skewnorm (cv1d &a) |
Norm of a skew-symetric matrix. More... | |
static double | Tools< d >::skewnormsq (cv1d &a) |
Norm squared of a skew-symetrix matrix. More... | |
static double | Tools< d >::dot (cv1d &a, cv1d &b) |
Dot product. More... | |
static v1f | Tools< d >::vsqrt (cv1f &a) |
Component-wise square root. More... | |
static v1f | Tools< d >::vsq (cv1f &a) |
Component-wise squaring. More... | |
static void | Tools< d >::surfacevelocity (v1d &res, cv1d &p, double *com, double *vel_com, double *omega_com) |
static void | Tools< d >::setgravity (v2d &a, v1d &g, v1d &m) |
Set the gravity. ![]() | |
Matrix operations, usually operating on flattened matrices, cf. the description for more information on matrix storage | |
static v1d | Tools< d >::skewmatvecmult (cv1d &M, cv1d &v) |
Multiply the skew symetric matrix M with vector v. More... | |
static v1d | Tools< d >::skewmatvecmult (const double *M, cv1d &v) |
Multiply the skew symetric matrix M with vector v. More... | |
static void | Tools< d >::skewmatvecmult (v1d &r, cv1d &M, cv1d &v) |
Multiply the skew symetric matrix M with vector v in place. More... | |
static void | Tools< d >::skewmatvecmult (v1d &r, const double *M, cv1d &v) |
Multiply the skew symetric matrix M with vector v in place (overload) More... | |
static v1d | Tools< d >::skewmatsquare (cv1d &A) |
Square the skew symetric matrix M. More... | |
static void | Tools< d >::skewmatsquare (v1d &r, cv1d &A) |
Square the skew symetric matrix M in place. More... | |
static v1d | Tools< d >::skewexpand (cv1d &A) |
Return the skew symetrix matrix M stored on d(d-1)/2 component as a full flattened matrix with d^2 components. More... | |
static void | Tools< d >::skewexpand (v1d &r, cv1d &A) |
Return the skew symetrix matrix M stored on d(d-1)/2 component as a full flattened matrix with d^2 components in place. More... | |
static v1d | Tools< d >::matmult (cv1d &A, cv1d &B) |
Multiply 2 matrix together. More... | |
static void | Tools< d >::matmult (v1d &r, cv1d &A, cv1d &B) |
Multiply 2 matrix together in place. More... | |
static void | Tools< d >::matvecmult (v1d &res, cv1d &A, cv1d &B) |
Multiply a matrix with a vector, in place. More... | |
static v1d | Tools< d >::wedgeproduct (cv1d &a, cv1d &b) |
Wedge product of vectors. More... | |
static void | Tools< d >::wedgeproduct (v1d &res, cv1d &a, cv1d &b) |
Wedge product in-place. More... | |
static double | Tools< d >::det (cv2d &M) |
compute the matrix determinant (probably quite slow, but doesn't really really matters for the usage) More... | |
static double | Tools< d >::det (cv1d &M) |
compute the matrix determinant (probably quite slow, but shouldn't really really matters for the usage) More... | |
static double | Tools< d >::det (double M[d][d]) |
compute the matrix determinant using array on the stack (avoids malloc/free) More... | |
static v1d | Tools< d >::inverse (cv1d &M) |
compute the matrix inverse (very slow and redundant calculation of the determinant for the comatrix, but shouldn't really really matters for the usage) More... | |
static v1d | Tools< d >::transpose (cv1d &a) |
Transposition. More... | |
static void | Tools< d >::transpose_inplace (v1d &a) |
Transpose in-place. More... | |
Special physics computation | |
static double | Tools< d >::Volume (double R) |
Compute the hypersphere volume. More... | |
static double | Tools< d >::InertiaMomentum (double R, double rho) |
Compute the hypersphere moment of inertia. More... | |
Coordinate system change | |
static double | Tools< d >::hyperspherical_xtophi (cv1d &x, v1d &phi) |
Convert from cartesian to hyperspherical coordinates. More... | |
static void | Tools< d >::hyperspherical_phitox (double r, cv1d &phi, v1d &x) |
Convert from hyperspherical to cartesian coordinates. More... | |
This module handles the Discrete Element Simulations.
#define CONTACTLIST |
#define MACRO | ( | r, | |
state | |||
) | case BOOST_PP_TUPLE_ELEM(2, 0, state): templatedmain<BOOST_PP_TUPLE_ELEM(2, 0, state)>(argv);break; |
#define MAXDEFDIM 30 |
For larger number of dimension, be taken in particular for periodic boundary conditions.
#define MAXDIM 4 |
#define STR_PROTECT | ( | s | ) | s |
using bitdim = unsigned int |
using json = nddem::json |
using uint = unsigned int |
using v1d = vector < double > |
using v1f = vector <float> |
using v1i = vector <int> |
using v2d = vector < vector <double> > |
using v3d = vector<vector<vector<double> >> |
enum ContactModels |
enum ContactStrategies |
enum DataValue |
|
strong |
|
strong |
|
strong |
|
strong |
void ContactList< d >::check_ghost_dst | ( | uint32_t | gst, |
int | n, | ||
double | partialsum, | ||
uint32_t | mask, | ||
const Parameters< d > & | P, | ||
cv1d & | X1, | ||
cv1d & | X2, | ||
cp< d > & | contact | ||
) |
bool ContactList< d >::check_ghost_LE | ( | bitdim | gst, |
const Parameters< d > & | P, | ||
cv1d & | X1, | ||
cv1d & | X2, | ||
double | r1, | ||
double | r2, | ||
cp< d > & | tmpcp, | ||
int | startd = 0 , |
||
double | partialsum = 0 , |
||
bitdim | mask = 0 |
||
) |
bool ContactList< d >::check_ghost_regular | ( | bitdim | gst, |
const Parameters< d > & | P, | ||
cv1d & | X1, | ||
cv1d & | X2, | ||
double | r1, | ||
double | r2, | ||
cp< d > & | tmpcp, | ||
int | startd = 0 , |
||
double | partialsum = 0 , |
||
bitdim | mask = 0 |
||
) |
Find ghost-particle contact, going though pbc recursively. A beautiful piece of optimised algorithm if I may say so myself.
Contacts< d >::Contacts | ( | Parameters< d > & | PP | ) |
auto Multiproc< d >::contacts2array | ( | ExportData | exp, |
cv2d & | X, | ||
Parameters< d > & | P | ||
) |
pack the contact data in a 2d array
void ContactList< d >::coordinance | ( | v1d & | Z | ) |
Calculate and store coordination number in Z.
Record the action to be added later to the relevent atom in sequencial settings, avoid potential race condition if an action was added to an atom that is not owned by the thread. This is for a particle-particle contact.
Record the action on the wall. Only usefull if the force on the wall needs to be calculated.
compute the matrix determinant (probably quite slow, but shouldn't really really matters for the usage)
compute the matrix determinant (probably quite slow, but doesn't really really matters for the usage)
compute the matrix determinant using array on the stack (avoids malloc/free)
Convert from hyperspherical to cartesian coordinates.
Convert from cartesian to hyperspherical coordinates.
Compute the hypersphere moment of inertia.
Initialise the member variables, in particular the variables to handle skew-symmetric flattened matrix, cf. the class detailed description.
int ContactList< d >::insert | ( | const cp< d > & | a | ) |
Insert a contact, maintaining sorting with increasing i, and removing missing contacts on traversal.
int ContactListMesh< d >::insert | ( | const cpm< d > & | a | ) |
Insert a contact, maintaining sorting with increasing i, and removing missing contacts on traversal.
compute the matrix inverse (very slow and redundant calculation of the determinant for the comatrix, but shouldn't really really matters for the usage)
void Multiproc< d >::load_balance | ( | ContactStrategies | contactstrategy | ) |
Modify the atom share between threads to achieve better load balance between the threads based on the current speed of each one during the previous iterations.
int main | ( | int | argc, |
char * | argv[] | ||
) |
Calls the appropriate templatedmain() function. Templated function are used to allow compiler optimisation for speed. Only a handful of dimension are compiled on the base code to limit compilation time and memory. If you need dimensions that are not cmpiled by default, have a look at the code it's pretty straightforward to activate the needed dimension. If the compilation failed with low meomry, in particular on older system, head to the code and comment the dimensions which are unused.
Multiply 2 matrix together in place.
Multiply a matrix with a vector, in place.
Norm of a vector.
Norm of a 2D-matrix, returns a 1D vector with the norms of the individual vectors.
Norm of a vector difference .
Norm squared of a vector difference .
Norm squared.
|
inline |
|
inline |
|
inline |
The contact list is order in increasing order of index i, and for two identical i in increasing order of j.
|
inline |
Contact equivalence is based solely on the index of objects in contact i and j.
std::istream& operator>> | ( | std::istream & | in, |
number_gen< T > & | n | ||
) |
|
inline |
|
inline |
|
inline |
|
inline |
|
inline |
Orthonormalise A using the Gram-Shmidt process, in place.
void Contacts< d >::particle_mesh | ( | cv1d & | Xi, |
cv1d & | Vi, | ||
cv1d & | Omegai, | ||
double | ri, | ||
double | mi, | ||
cpm< d > & | Contact | ||
) |
Force & torque between particle and mesh.
void Contacts< d >::particle_movingwall | ( | cv1d & | Vi, |
cv1d & | Omegai, | ||
double | ri, | ||
double | mi, | ||
cv1d & | cn, | ||
cv1d & | Vj, | ||
cp< d > & | Contact | ||
) |
Force & torque between a particle and a moving wall. Vj is the velocity of the wall at the contact point.
void Contacts< d >::particle_particle | ( | cv1d & | Xi, |
cv1d & | Vi, | ||
cv1d & | Omegai, | ||
double | ri, | ||
double | mi, | ||
cv1d & | Xj, | ||
cv1d & | Vj, | ||
cv1d & | Omegaj, | ||
double | rj, | ||
double | mj, | ||
cp< d > & | Contact, | ||
bool | isdumptime | ||
) |
Force & torque between 2 particles.
void Contacts< d >::particle_wall | ( | cv1d & | Vi, |
cv1d & | Omegai, | ||
double | ri, | ||
double | mi, | ||
cv1d & | cn, | ||
cp< d > & | Contact | ||
) |
Force & torque between a particle and a wall.
Save the orientation in a CSV file.
|
static |
Save the location and a few more informations in a CSV file.
|
static |
Save the location and a few more informations in a CSV file.
|
static |
|
static |
Save as a vtk file. Dimensions higher than 3 are stored as additional scalars. Additional informations can be passed as a vector of TensorInfos.
Set the gravity. .
Set a vector to zero in-place.
Set a matrix to zero in-place.
void sig_handler | ( | int | p | ) |
Function handling signal reception for clean closing on SIGINT for example.
Return the skew symetrix matrix M stored on d(d-1)/2 component as a full flattened matrix with d^2 components.
Return the skew symetrix matrix M stored on d(d-1)/2 component as a full flattened matrix with d^2 components in place.
Square the skew symetric matrix M in place.
Multiply the skew symetric matrix M with vector v.
Multiply the skew symetric matrix M with vector v.
Multiply the skew symetric matrix M with vector v in place (overload)
Multiply the skew symetric matrix M with vector v in place.
Norm of a skew-symetric matrix.
Norm squared of a skew-symetrix matrix.
Function to allocate the grains to threads taking into account the load balance in the contact detection. load_balance() takes over after a few iteration have run, and is usually more efficient.
|
inlinestatic |
int templatedmain | ( | char * | argv[] | ) |
Main simulation run. All the simulation is handled by this function.
Transpose in-place.
Return the two largest elements of v.
Construct & return a unit vector.
Construct a unit vector in place.
Wedge product of vectors.
Wedge product in-place.
For skew symmetric matrix, make the correspondance between linear index and (row,column) index.
For skew symmetric matrix, make the correspondance between linear index of a full matrix with the linear index of the skew-symetric storage.
For skew symetric matrix. -1 below the diagonal, 0 on the diagonal, +1 above the diagnal.
Returns a random number between 0 and 1.
vector<std::pair<ExportType,ExportData> >* toclean |
|
extern |
XMLWriter* xmlout |
|
extern |