--- trunk/tengDissertation/Appendix.tex 2006/06/07 18:34:05 2815 +++ trunk/tengDissertation/Appendix.tex 2006/06/08 21:02:53 2831 @@ -118,41 +118,187 @@ The Singleton pattern ensures that only one instance o OOPSE}. \subsection{\label{appendixSection:singleton}Singleton} -The Singleton pattern ensures that only one instance of a class is -created. All objects that use an instance of that class use the same -instance. +The Singleton pattern not only provides a mechanism to restrict +instantiation of a class to one object, but also provides a global +point of access to the object. Currently implemented as a global +variable, the logging utility which reports error and warning +messages to the console in {\sc OOPSE} is a good candidate for +applying the Singleton pattern to avoid the global namespace +pollution.Although the singleton pattern can be implemented in +various ways to account for different aspects of the software +designs, such as lifespan control \textit{etc}, we only use the +static data approach in {\sc OOPSE}. {\tt IntegratorFactory} class +is declared as +\begin{lstlisting}[float,caption={[A classic Singleton design pattern implementation(I)] Declaration of {\tt IntegratorFactory} class.},label={appendixScheme:singletonDeclaration}] +class IntegratorFactory { + public: + static IntegratorFactory* getInstance(); + protected: + IntegratorFactory(); + private: + static IntegratorFactory* instance_; +}; + +\end{lstlisting} +The corresponding implementation is +\begin{lstlisting}[float,caption={[A classic implementation of Singleton design pattern (II)] Implementation of {\tt IntegratorFactory} class.},label={appendixScheme:singletonImplementation}] + +IntegratorFactory::instance_ = NULL; + +IntegratorFactory* getInstance() { + if (instance_ == NULL){ + instance_ = new IntegratorFactory; + } + return instance_; +} + +\end{lstlisting} +Since constructor is declared as {\tt protected}, a client can not +instantiate {\tt IntegratorFactory} directly. Moreover, since the +member function {\tt getInstance} serves as the only entry of access +to {\tt IntegratorFactory}, this approach fulfills the basic +requirement, a single instance. Another consequence of this approach +is the automatic destruction since static data are destroyed upon +program termination. + \subsection{\label{appendixSection:factoryMethod}Factory Method} -The Factory Method pattern is a creational pattern which deals with -the problem of creating objects without specifying the exact class -of object that will be created. Factory Method solves this problem -by defining a separate method for creating the objects, which -subclasses can then override to specify the derived type of product -that will be created. +Categoried as a creational pattern, the Factory Method pattern deals +with the problem of creating objects without specifying the exact +class of object that will be created. Factory Method is typically +implemented by delegating the creation operation to the subclasses. + +Registers a creator with a type identifier. Looks up the type +identifier in the internal map. If it is found, it invokes the +corresponding creator for the type identifier and returns its +result. +\begin{lstlisting}[float,caption={[The implementation of Factory pattern (I)].},label={appendixScheme:factoryDeclaration}] + +class IntegratorFactory { + public: + typedef std::map CreatorMapType; + + bool registerIntegrator(IntegratorCreator* creator) { + return creatorMap_.insert(creator->getIdent(), creator).second; + } + + Integrator* createIntegrator(const string& id, SimInfo* info) { + Integrator* result = NULL; + CreatorMapType::iterator i = creatorMap_.find(id); + if (i != creatorMap_.end()) { + result = (i->second)->create(info); + } + return result; + } + + private: + CreatorMapType creatorMap_; +}; +\end{lstlisting} +\begin{lstlisting}[float,caption={[The implementation of Factory pattern (III)]Souce code of creator classes.},label={appendixScheme:integratorCreator}] + +class IntegratorCreator { + public: + IntegratorCreator(const string& ident) : ident_(ident) {} + + const string& getIdent() const { return ident_; } + + virtual Integrator* create(SimInfo* info) const = 0; + + private: + string ident_; +}; + +template +class IntegratorBuilder : public IntegratorCreator { + public: + IntegratorBuilder(const string& ident) : IntegratorCreator(ident) {} + virtual Integrator* create(SimInfo* info) const { + return new ConcreteIntegrator(info); + } +}; +\end{lstlisting} + \subsection{\label{appendixSection:visitorPattern}Visitor} + The purpose of the Visitor Pattern is to encapsulate an operation -that you want to perform on the elements of a data structure. In -this way, you can change the operation being performed on a -structure without the need of changing the classes of the elements -that you are operating on. +that you want to perform on the elements. The operation being +performed on a structure can be switched without changing the +interfaces of the elements. In other words, one can add virtual +functions into a set of classes without modifying their interfaces. +The UML class diagram of Visitor patten is shown in +Fig.~\ref{appendixFig:visitorUML}. {\tt Dump2XYZ} program in +Sec.~\ref{appendixSection:Dump2XYZ} uses Visitor pattern +extensively. + +\begin{figure} +\centering +\includegraphics[width=\linewidth]{visitor.eps} +\caption[The architecture of {\sc OOPSE}] {Overview of the structure +of {\sc OOPSE}} \label{appendixFig:visitorUML} +\end{figure} +\begin{lstlisting}[float,caption={[The implementation of Visitor pattern (I)]Source code of the visitor classes.},label={appendixScheme:visitor}] + +class BaseVisitor{ + public: + virtual void visit(Atom* atom); + virtual void visit(DirectionalAtom* datom); + virtual void visit(RigidBody* rb); +}; + +\end{lstlisting} + +\begin{lstlisting}[float,caption={[The implementation of Visitor pattern (II)]Source code of the element classes.},label={appendixScheme:element}] + +class StuntDouble { + public: + virtual void accept(BaseVisitor* v) = 0; +}; + +class Atom: public StuntDouble { + public: + virtual void accept{BaseVisitor* v*} { + v->visit(this); + } +}; + +class DirectionalAtom: public Atom { + public: + virtual void accept{BaseVisitor* v*} { + v->visit(this); + } +}; + +class RigidBody: public StuntDouble { + public: + virtual void accept{BaseVisitor* v*} { + v->visit(this); + } +}; + +\end{lstlisting} + \section{\label{appendixSection:concepts}Concepts} OOPSE manipulates both traditional atoms as well as some objects that {\it behave like atoms}. These objects can be rigid collections of atoms or atoms which have orientational degrees of -freedom. Here is a diagram of the class heirarchy: - -%\begin{figure} -%\centering -%\includegraphics[width=3in]{heirarchy.eps} -%\caption[Class heirarchy for StuntDoubles in {\sc oopse}-3.0]{ \\ -%The class heirarchy of StuntDoubles in {\sc oopse}-3.0. The -%selection syntax allows the user to select any of the objects that -%are descended from a StuntDouble.} \label{oopseFig:heirarchy} -%\end{figure} - +freedom. A diagram of the class heirarchy is illustrated in +Fig.~\ref{oopseFig:heirarchy}. Every Molecule, Atom and +DirectionalAtom in {\sc OOPSE} have their own names which are +specified in the {\tt .md} file. In contrast, RigidBodies are +denoted by their membership and index inside a particular molecule: +[MoleculeName]\_RB\_[index] (the contents inside the brackets depend +on the specifics of the simulation). The names of rigid bodies are +generated automatically. For example, the name of the first rigid +body in a DMPC molecule is DMPC\_RB\_0. +\begin{figure} +\centering +\includegraphics[width=\linewidth]{heirarchy.eps} +\caption[Class heirarchy for ojects in {\sc OOPSE}]{ A diagram of +the class heirarchy. \begin{itemize} \item A {\bf StuntDouble} is {\it any} object that can be manipulated by the integrators and minimizers. @@ -161,15 +307,9 @@ DirectionalAtom}s which behaves as a single unit. \item A {\bf RigidBody} is a collection of {\bf Atom}s or {\bf DirectionalAtom}s which behaves as a single unit. \end{itemize} +} \label{oopseFig:heirarchy} +\end{figure} -Every Molecule, Atom and DirectionalAtom in {\sc OOPSE} have their -own names which are specified in the {\tt .md} file. In contrast, -RigidBodies are denoted by their membership and index inside a -particular molecule: [MoleculeName]\_RB\_[index] (the contents -inside the brackets depend on the specifics of the simulation). The -names of rigid bodies are generated automatically. For example, the -name of the first rigid body in a DMPC molecule is DMPC\_RB\_0. - \section{\label{appendixSection:syntax}Syntax of the Select Command} The most general form of the select command is: {\tt select {\it @@ -377,14 +517,14 @@ Fig.~\ref{oopseFig:staticPropsProcess}. \centering \includegraphics[width=\linewidth]{staticPropsProcess.eps} \caption[A representation of the three-stage correlations in -\texttt{StaticProps}]{Three-stage processing in -\texttt{StaticProps}. $S_1$ and $S_2$ are the numbers of selected -stuntdobules from {\tt -{}-sele1} and {\tt -{}-sele2} respectively, -while $C$ is the number of stuntdobules appearing at both sets. The -first stage($S_1-C$ and $S_2$) and second stages ($S_1$ and $S_2-C$) -are completely non-overlapping. On the contrary, the third stage($C$ -and $C$) are completely overlapping} -\label{oopseFig:staticPropsProcess} +\texttt{StaticProps}]{This diagram illustrates three-stage +processing used by \texttt{StaticProps}. $S_1$ and $S_2$ are the +numbers of selected stuntdobules from {\tt -{}-sele1} and {\tt +-{}-sele2} respectively, while $C$ is the number of stuntdobules +appearing at both sets. The first stage($S_1-C$ and $S_2$) and +second stages ($S_1$ and $S_2-C$) are completely non-overlapping. On +the contrary, the third stage($C$ and $C$) are completely +overlapping} \label{oopseFig:staticPropsProcess} \end{figure} The options available for {\tt StaticProps} are as follows: @@ -462,7 +602,20 @@ incremented, until all frame pairs have been correlate incremented and the process repeated until the end of the trajectory. Once the end is reached, the first block is freed then incremented, until all frame pairs have been correlated in time. +This process is illustrated in +Fig.~\ref{oopseFig:dynamicPropsProcess}. +\begin{figure} +\centering +\includegraphics[width=\linewidth]{dynamicPropsProcess.eps} +\caption[A representation of the block correlations in +\texttt{dynamicProps}]{This diagram illustrates block correlations +processing in \texttt{dynamicProps}. The shaded region represents +the self correlation of the block, and the open blocks are read one +at a time and the cross correlations between blocks are calculated.} +\label{oopseFig:dynamicPropsProcess} +\end{figure} + The options available for DynamicProps are as follows: \begin{longtable}[c]{|EFG|} \caption{DynamicProps Command-line Options} @@ -489,10 +642,10 @@ Dump2XYZ can transform an OOPSE dump file into a xyz f \subsection{\label{appendixSection:Dump2XYZ}Dump2XYZ} -Dump2XYZ can transform an OOPSE dump file into a xyz file which can -be opened by other molecular dynamics viewers such as Jmol and -VMD\cite{Humphrey1996}. The options available for Dump2XYZ are as -follows: +{\tt Dump2XYZ} can transform an OOPSE dump file into a xyz file +which can be opened by other molecular dynamics viewers such as Jmol +and VMD\cite{Humphrey1996}. The options available for Dump2XYZ are +as follows: \begin{longtable}[c]{|EFG|} @@ -523,7 +676,12 @@ The options available for Hydro are as follows: \end{longtable} \subsection{\label{appendixSection:hydrodynamics}Hydro} -The options available for Hydro are as follows: + +{\tt Hydro} can calculate resistance and diffusion tensors at the +center of resistance. Both tensors at the center of diffusion can +also be reported from the program, as well as the coordinates for +the beads which are used to approximate the arbitrary shapes. The +options available for Hydro are as follows: \begin{longtable}[c]{|EFG|} \caption{Hydrodynamics Command-line Options} \\ \hline