diff --git a/lib/README b/lib/README
new file mode 100644
index 000000000..540c05137
--- /dev/null
+++ b/lib/README
@@ -0,0 +1,12 @@
+This directory contains libraries that can be linked with when
+building LAMMPS.  The library itself must be built first, so that a
+lib*.a file exists for LAMMPS to link against.
+
+Each library directory contains a README with additional info.  You
+will need to copy one of the Makefile.* files to Makefile before
+building a library.  If a Makefile.* suitable for your machine does
+not exist, you will need to edit one of the existing Makefiles.
+
+The libraries included with LAMMPS are the following:
+
+poems	      POEMS rigid-body integration package from RPI
diff --git a/lib/poems/Authors_List.txt b/lib/poems/Authors_List.txt
new file mode 100644
index 000000000..0a468fa2f
--- /dev/null
+++ b/lib/poems/Authors_List.txt
@@ -0,0 +1,28 @@
+ /*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: AUTHORS LIST                                           *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2004 by Authors as listed in Author's List          *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *_________________________________________________________________________*/
+ 
+ 
+ 
+ POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE, contains
+ contributions from the following authors.
+  
+KURT S ANDERSON (anderk5@rpi.edu)
+RUDRANARAYAN M MUKHERJEE (mukher@rpi.edu)
+JAMES H CRITCHLEY 
+JOHN L ZIEGLER
+SCOTT LIPTON
+GEOFFREY BASORE
+JOHN EVANS
diff --git a/lib/poems/Copyright_Notice b/lib/poems/Copyright_Notice
new file mode 100644
index 000000000..7c87c7fa3
--- /dev/null
+++ b/lib/poems/Copyright_Notice
@@ -0,0 +1,10 @@
+				   Copyright (C) 2006
+Authors as indicated in Author List and Rensselaer Polytechnic Institute
+
+Parallelizable Open source Efficient Multibody Software (POEMS) is written and maintained by the authors as indicated in Author's List as a part of Scientific Computation Research Center (SCOREC) at Rensselaer Polytechnic Intitute, Troy, NY, USA.
+
+This program is free software; you can redistribute it and/or modify it under the terms of the license as found in POEMS_License.txt distributed with the source code.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the license text for more details.
+   
+A copy of the license file POEMS_License.txt, Authors List and Grants List files should be distributed along with this program. 
\ No newline at end of file
diff --git a/lib/poems/Grants_List.txt b/lib/poems/Grants_List.txt
new file mode 100644
index 000000000..0fabf51ca
--- /dev/null
+++ b/lib/poems/Grants_List.txt
@@ -0,0 +1,28 @@
+ /*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: GRANTS LIST                                            *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2004 by Authors as listed in Author's List          *
+ *      DOWNLOAD: www.rpi.edu/~anderk5/POEMS                               *
+ *_________________________________________________________________________*/
+ 
+ 
+ 
+ 
+ POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE, 
+ has been supported in part by the following grants. Their support is
+ highly appreciated.
+
+ NSF Nanoscale Interdisciplinary Research Team 0303902
+ NSF State Time 0219734
+ NSF Faculty Early Career Development (CAREER)  9733684
+ Sandia National Laboratories LDRD project 67017
+ 
\ No newline at end of file
diff --git a/lib/poems/Makefile b/lib/poems/Makefile
new file mode 100644
index 000000000..ed50802ff
--- /dev/null
+++ b/lib/poems/Makefile
@@ -0,0 +1,101 @@
+# *
+# *_________________________________________________________________________*
+# *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+# *      DESCRIPTION: SEE READ-ME                                           *
+# *      FILE NAME: Makefile                                                *
+# *      AUTHORS: See Author List                                           * 
+# *      GRANTS: See Grants List                                            *
+# *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+# *      LICENSE: Please see License Agreement                              *
+# *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+# *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+# *                     Computational Dynamics Lab                          *
+# *                     Rensselaer Polytechnic Institute                    *
+# *                     110 8th St. Troy NY 12180                           * 
+# *      CONTACT:        anderk5@rpi.edu                                    *
+# *_________________________________________________________________________*/
+
+
+
+SHELL = /bin/sh
+
+
+# ------ FILES ------
+
+SRC_MAIN = workspace.cpp system.cpp poemsobject.cpp 
+INC_MAIN = workspace.h system.h poemsobject.h
+
+SRC_BODY =      body.cpp rigidbody.cpp particle.cpp inertialframe.cpp
+INC_BODY =      bodies.h body.h rigidbody.h particle.h inertialframe.h
+
+
+SRC_JOINT =     joint.cpp revolutejoint.cpp prismaticjoint.cpp sphericaljoint.cpp \
+    freebodyjoint.cpp body23joint.cpp mixedjoint.cpp
+INC_JOINT =     joints.h joint.h revolutejoint.h prismaticjoint.h sphericaljoint.h \
+    freebodyjoint.h body23joint.h mixedjoint.h
+
+SRC_POINT =     point.cpp fixedpoint.cpp
+INC_POINT =     points.h point.h fixedpoint.h
+
+SRC_SOLVE = solver.cpp  
+INC_SOLVE = solver.h  
+
+SRC_ORDERN = onsolver.cpp onfunctions.cpp onbody.cpp
+INC_ORDERN = onsolver.h onfunctions.h onbody.h
+
+SRC_MAT =       virtualmatrix.cpp matrix.cpp matrixfun.cpp mat3x3.cpp virtualcolmatrix.cpp \
+    colmatrix.cpp vect3.cpp virtualrowmatrix.cpp rowmatrix.cpp mat6x6.cpp vect6.cpp \
+    fastmatrixops.cpp colmatmap.cpp eulerparameters.cpp vect4.cpp norm.cpp mat4x4.cpp \
+    
+INC_MAT =       matrices.h virtualmatrix.h matrix.h matrixfun.h mat3x3.h virtualcolmatrix.h \
+    colmatrix.h vect3.h virtualrowmatrix.h rowmatrix.h mat6x6.h vect6.h \
+    fastmatrixops.h colmatmap.h eulerparameters.h vect4.h norm.h mat4x4.h 
+
+SRC_MISC = poemstreenode.cpp
+INC_MISC = poemslist.h poemstreenode.h poemstree.h poemsnodelib.h SystemProcessor.h defines.h POEMSChain.h
+
+SRC = $(SRC_MAIN) $(SRC_BODY) $(SRC_JOINT) $(SRC_POINT) $(SRC_SOLVE) $(SRC_ORDERN) $(SRC_MAT) $(SRC_MISC) 
+INC = $(INC_MAIN) $(INC_BODY) $(INC_JOINT) $(INC_POINT) $(INC_SOLVE) $(INC_ORDERN) $(INC_MAT) $(INC_MISC) 
+
+FILES = $(SRC) $(INC) Makefile Authors_List.txt Grants_List.txt POEMS_License.txt README Copyright_Notice
+
+# ------ DEFINITIONS ------
+
+LIB = libpoems.a
+OBJ =   $(SRC:.cpp=.o)
+
+# ------ SETTINGS ------
+
+CC =	        g++
+CCFLAGS =       -O -g -Wall #-Wno-deprecated
+ARCHIVE =	ar
+ARCHFLAG =	-rc
+DEPFLAGS =      -M
+LINK =         	g++
+LINKFLAGS =	-O
+USRLIB =
+SYSLIB =
+
+# ------ MAKE PROCEDURE ------
+
+lib: 	$(OBJ)
+	$(ARCHIVE) $(ARFLAGS) $(LIB) $(OBJ)
+
+# ------ COMPILE RULES ------
+
+%.o:%.cpp
+	$(CC) $(CCFLAGS) -c $<
+%.d:%.cpp
+	$(CC) $(CCFLAGS) $(DEPFLAGS) $< > $@		
+
+# ------ DEPENDENCIES ------
+
+DEPENDS = $(OBJ:.o=.d)
+
+# ------ CLEAN ------
+
+clean:
+	-rm *.o *.d *~ $(LIB)
+
+tar:
+	-tar -cvf ../POEMS.tar $(FILES)
\ No newline at end of file
diff --git a/lib/poems/Makefile.icc b/lib/poems/Makefile.icc
new file mode 100644
index 000000000..833a2f1d5
--- /dev/null
+++ b/lib/poems/Makefile.icc
@@ -0,0 +1,101 @@
+# *
+# *_________________________________________________________________________*
+# *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+# *      DESCRIPTION: SEE READ-ME                                           *
+# *      FILE NAME: Makefile                                                *
+# *      AUTHORS: See Author List                                           * 
+# *      GRANTS: See Grants List                                            *
+# *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+# *      LICENSE: Please see License Agreement                              *
+# *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+# *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+# *                     Computational Dynamics Lab                          *
+# *                     Rensselaer Polytechnic Institute                    *
+# *                     110 8th St. Troy NY 12180                           * 
+# *      CONTACT:        anderk5@rpi.edu                                    *
+# *_________________________________________________________________________*/
+
+
+
+SHELL = /bin/sh
+
+
+# ------ FILES ------
+
+SRC_MAIN = workspace.cpp system.cpp poemsobject.cpp 
+INC_MAIN = workspace.h system.h poemsobject.h
+
+SRC_BODY =      body.cpp rigidbody.cpp particle.cpp inertialframe.cpp
+INC_BODY =      bodies.h body.h rigidbody.h particle.h inertialframe.h
+
+
+SRC_JOINT =     joint.cpp revolutejoint.cpp prismaticjoint.cpp sphericaljoint.cpp \
+    freebodyjoint.cpp body23joint.cpp mixedjoint.cpp
+INC_JOINT =     joints.h joint.h revolutejoint.h prismaticjoint.h sphericaljoint.h \
+    freebodyjoint.h body23joint.h mixedjoint.h
+
+SRC_POINT =     point.cpp fixedpoint.cpp
+INC_POINT =     points.h point.h fixedpoint.h
+
+SRC_SOLVE = solver.cpp  
+INC_SOLVE = solver.h  
+
+SRC_ORDERN = onsolver.cpp onfunctions.cpp onbody.cpp
+INC_ORDERN = onsolver.h onfunctions.h onbody.h
+
+SRC_MAT =       virtualmatrix.cpp matrix.cpp matrixfun.cpp mat3x3.cpp virtualcolmatrix.cpp \
+    colmatrix.cpp vect3.cpp virtualrowmatrix.cpp rowmatrix.cpp mat6x6.cpp vect6.cpp \
+    fastmatrixops.cpp colmatmap.cpp eulerparameters.cpp vect4.cpp norm.cpp mat4x4.cpp \
+    
+INC_MAT =       matrices.h virtualmatrix.h matrix.h matrixfun.h mat3x3.h virtualcolmatrix.h \
+    colmatrix.h vect3.h virtualrowmatrix.h rowmatrix.h mat6x6.h vect6.h \
+    fastmatrixops.h colmatmap.h eulerparameters.h vect4.h norm.h mat4x4.h 
+
+SRC_MISC = poemstreenode.cpp
+INC_MISC = poemslist.h poemstreenode.h poemstree.h poemsnodelib.h SystemProcessor.h defines.h POEMSChain.h
+
+SRC = $(SRC_MAIN) $(SRC_BODY) $(SRC_JOINT) $(SRC_POINT) $(SRC_SOLVE) $(SRC_ORDERN) $(SRC_MAT) $(SRC_MISC) 
+INC = $(INC_MAIN) $(INC_BODY) $(INC_JOINT) $(INC_POINT) $(INC_SOLVE) $(INC_ORDERN) $(INC_MAT) $(INC_MISC) 
+
+FILES = $(SRC) $(INC) Makefile Authors_List.txt Grants_List.txt POEMS_License.txt README Copyright_Notice
+
+# ------ DEFINITIONS ------
+
+LIB = libpoems.a
+OBJ =   $(SRC:.cpp=.o)
+
+# ------ SETTINGS ------
+
+CC =		icc
+CCFLAGS =       -O -Wall -Wcheck -wd869,981,1572
+ARCHIVE =	ar
+ARCHFLAG =	-rc
+DEPFLAGS =      -M
+LINK =		icc
+LINKFLAGS =	-O
+USRLIB =
+SYSLIB =
+
+# ------ MAKE PROCEDURE ------
+
+lib: 	$(OBJ)
+	$(ARCHIVE) $(ARFLAGS) $(LIB) $(OBJ)
+
+# ------ COMPILE RULES ------
+
+%.o:%.cpp
+	$(CC) $(CCFLAGS) -c $<
+%.d:%.cpp
+	$(CC) $(CCFLAGS) $(DEPFLAGS) $< > $@		
+
+# ------ DEPENDENCIES ------
+
+DEPENDS = $(OBJ:.o=.d)
+
+# ------ CLEAN ------
+
+clean:
+	-rm *.o *.d *~ $(LIB)
+
+tar:	
+	-tar -cvf ../POEMS.tar $(FILES)
diff --git a/lib/poems/Makefile.storm b/lib/poems/Makefile.storm
new file mode 100644
index 000000000..8a3e01d36
--- /dev/null
+++ b/lib/poems/Makefile.storm
@@ -0,0 +1,101 @@
+# *
+# *_________________________________________________________________________*
+# *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+# *      DESCRIPTION: SEE READ-ME                                           *
+# *      FILE NAME: Makefile                                                *
+# *      AUTHORS: See Author List                                           * 
+# *      GRANTS: See Grants List                                            *
+# *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+# *      LICENSE: Please see License Agreement                              *
+# *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+# *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+# *                     Computational Dynamics Lab                          *
+# *                     Rensselaer Polytechnic Institute                    *
+# *                     110 8th St. Troy NY 12180                           * 
+# *      CONTACT:        anderk5@rpi.edu                                    *
+# *_________________________________________________________________________*/
+
+
+
+SHELL = /bin/sh
+
+
+# ------ FILES ------
+
+SRC_MAIN = workspace.cpp system.cpp poemsobject.cpp 
+INC_MAIN = workspace.h system.h poemsobject.h
+
+SRC_BODY =      body.cpp rigidbody.cpp particle.cpp inertialframe.cpp
+INC_BODY =      bodies.h body.h rigidbody.h particle.h inertialframe.h
+
+
+SRC_JOINT =     joint.cpp revolutejoint.cpp prismaticjoint.cpp sphericaljoint.cpp \
+    freebodyjoint.cpp body23joint.cpp mixedjoint.cpp
+INC_JOINT =     joints.h joint.h revolutejoint.h prismaticjoint.h sphericaljoint.h \
+    freebodyjoint.h body23joint.h mixedjoint.h
+
+SRC_POINT =     point.cpp fixedpoint.cpp
+INC_POINT =     points.h point.h fixedpoint.h
+
+SRC_SOLVE = solver.cpp  
+INC_SOLVE = solver.h  
+
+SRC_ORDERN = onsolver.cpp onfunctions.cpp onbody.cpp
+INC_ORDERN = onsolver.h onfunctions.h onbody.h
+
+SRC_MAT =       virtualmatrix.cpp matrix.cpp matrixfun.cpp mat3x3.cpp virtualcolmatrix.cpp \
+    colmatrix.cpp vect3.cpp virtualrowmatrix.cpp rowmatrix.cpp mat6x6.cpp vect6.cpp \
+    fastmatrixops.cpp colmatmap.cpp eulerparameters.cpp vect4.cpp norm.cpp mat4x4.cpp \
+    
+INC_MAT =       matrices.h virtualmatrix.h matrix.h matrixfun.h mat3x3.h virtualcolmatrix.h \
+    colmatrix.h vect3.h virtualrowmatrix.h rowmatrix.h mat6x6.h vect6.h \
+    fastmatrixops.h colmatmap.h eulerparameters.h vect4.h norm.h mat4x4.h 
+
+SRC_MISC = poemstreenode.cpp
+INC_MISC = poemslist.h poemstreenode.h poemstree.h poemsnodelib.h SystemProcessor.h defines.h POEMSChain.h
+
+SRC = $(SRC_MAIN) $(SRC_BODY) $(SRC_JOINT) $(SRC_POINT) $(SRC_SOLVE) $(SRC_ORDERN) $(SRC_MAT) $(SRC_MISC) 
+INC = $(INC_MAIN) $(INC_BODY) $(INC_JOINT) $(INC_POINT) $(INC_SOLVE) $(INC_ORDERN) $(INC_MAT) $(INC_MISC) 
+
+FILES = $(SRC) $(INC) Makefile Authors_List.txt Grants_List.txt POEMS_License.txt README Copyright_Notice
+
+# ------ DEFINITIONS ------
+
+LIB = libpoems.a
+OBJ =   $(SRC:.cpp=.o)
+
+# ------ SETTINGS ------
+
+CC =	        CC
+CCFLAGS =       -O -g -Wall #-Wno-deprecated
+ARCHIVE =	ar
+ARCHFLAG =	-rc
+DEPFLAGS =      -M
+LINK =         	CC
+LINKFLAGS =	-O
+USRLIB =
+SYSLIB =
+
+# ------ MAKE PROCEDURE ------
+
+lib: 	$(OBJ)
+	$(ARCHIVE) $(ARFLAGS) $(LIB) $(OBJ)
+
+# ------ COMPILE RULES ------
+
+%.o:%.cpp
+	$(CC) $(CCFLAGS) -c $<
+%.d:%.cpp
+	$(CC) $(CCFLAGS) $(DEPFLAGS) $< > $@		
+
+# ------ DEPENDENCIES ------
+
+DEPENDS = $(OBJ:.o=.d)
+
+# ------ CLEAN ------
+
+clean:
+	-rm *.o *.d *~ $(LIB)
+
+tar:
+	-tar -cvf ../POEMS.tar $(FILES)
\ No newline at end of file
diff --git a/lib/poems/POEMSChain.h b/lib/poems/POEMSChain.h
new file mode 100644
index 000000000..cc17952d0
--- /dev/null
+++ b/lib/poems/POEMSChain.h
@@ -0,0 +1,73 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: PoemsChain.h                                            *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef POEMSCHAIN_H_
+#define POEMSCHAIN_H_
+
+#include "poemslist.h"
+
+struct ChildRingData {
+	List<int> * childRing;
+	int entranceNodeId;
+};
+
+struct POEMSChain{
+	~POEMSChain(){
+		for(int i = 0; i < childChains.GetNumElements(); i++)
+		{
+			delete childChains(i);
+		}
+	}
+	//void printTreeStructure(int tabs);
+	//void getTreeAsList(List<int> * temp);
+	List<int> listOfNodes;
+	List<POEMSChain> childChains;
+	POEMSChain * parentChain;
+	List<ChildRingData> childRings;
+	
+	
+	void printTreeStructure(int tabs){
+		for(int i = 0; i < tabs; i++)
+		{
+			cout << "\t";
+		}
+		cout << "Chain: ";
+		for(int i = 0; i < listOfNodes.GetNumElements(); i++)
+		{
+			cout << *(listOfNodes(i)) << " ";
+		}
+		cout << endl;
+		for(int i = 0; i < childChains.GetNumElements(); i++)
+		{
+			childChains(i)->printTreeStructure(tabs + 1);
+		}
+	}
+	void getTreeAsList(List<int> * temp)
+	{
+		for(int i = 0; i < listOfNodes.GetNumElements(); i++)
+		{
+			int * integer = new int;
+			*integer = *(listOfNodes(i));
+			temp->Append(integer);
+		}
+		for(int i = 0; i < childChains.GetNumElements(); i++)
+		{
+			childChains(i)->getTreeAsList(temp);
+		}
+	}
+};
+#endif
diff --git a/lib/poems/POEMS_License.txt b/lib/poems/POEMS_License.txt
new file mode 100644
index 000000000..9b54d2316
--- /dev/null
+++ b/lib/poems/POEMS_License.txt
@@ -0,0 +1,64 @@
+   Copyright (C) 2005
+   Authors as indicated in Author List and Rensselaer Polytechnic Institute
+
+   Parallelizable Open source Efficient Multibody Software (POEMS) is written and maintained by the
+   authors as indicated in Author's List as a part of Scientific Computation Research Center (SCOREC)
+   at Rensselaer Polytechnic Intitute, Troy, NY, USA.
+   
+   This License Agreement applies to any software library or other program which contains a notice
+   placed by the copyright holder saying it may be distributed under the terms of this Rensselaer 
+   Public License (also called "this License"). Each licensee is addressed as "you".
+
+   A "library" means a collection of software functions and/or data prepared so as to be conveniently
+   linked with application programs (which use some of those functions and data) to form executables.
+   The "Library", below, refers to any such software library or work which has been distributed under
+   these terms.  A "work based on the Library" means either the Library/code or any derivative work
+   under copyright law.
+
+   "Source code" for a work means the preferred form of the work for making modifications to it including
+   any associated interface definition files, and scripts used to control compilation  and installation
+   of the library.
+
+   This library is free software; Redistribution and use in source code and binary forms, with or
+   without modification, are permitted provided that the following conditions are met: 
+   
+1. Redistributions of source code must retain the above copyright notice, this list of conditions, 
+   the authors list, the grants list, and the following disclaimer without any modifications and in
+   its current form. 
+   
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions,
+   the authors list, the grants list, and the following disclaimer in the documentation and/or other
+   materials provided with the distribution. 
+   
+3. You must cause the files modified to carry prominent notices stating that you changed the files
+   and dates of the change.  
+   
+4. At your discretion, you may submit the differences between the program and your work based on the 
+   program for inclusion in the source code repository maintained by Rensselaer Polytechnic Institute.
+   The mechanics of the submission are explained in the file named CONTRIBUTE distributed with the
+   Library. Should you decide to submit the changes, you agree to provide Rensselaer Polytechnic
+   Institute with a joint copyright assignment of the changes, and you agree to sign such a copyright
+   assignment form at the request of Rensselaer Polytechnic Institute. Changes will then made as 
+   appropriate to the authors list at the Resselaer repository. 
+   
+5. The authors as listed in "Authors_List" reserve the right to distribute the software or any modified
+   work in any other license form if they so choose to without infringing on any previous or concurrent
+   license agreement.   
+       
+6. The name of the authors or their employer(s), Rensselaer Polytechnic Institute, the Computational
+   Dynamics Laboratory,  the Scientific Computation Research Center (SCoReC), nor the names of any
+   of the software distributors may not be used to endorse or promote products derived
+   from this software without specific prior written permission.
+
+
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
+BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR THE SCIENTIFIC COMPUTATION RESEARCH CENTER BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+ 
\ No newline at end of file
diff --git a/lib/poems/README b/lib/poems/README
new file mode 100644
index 000000000..f4043db58
--- /dev/null
+++ b/lib/poems/README
@@ -0,0 +1,28 @@
+ POEMS 1.0 README
+
+
+The Parallelizable Open source Efficient Multibody Software (POEMS) is general purpose distributed multibody dynamics software, which is able to simulate the dynamics of articulated body systems.
+
+This work is supported by the funding agencies listed in the Grants' List. POEMS is an open source program distributed under the Rensselaer Scorec License.
+
+The Authors as listed in Authors' List reserve the right to reject the request on technical supports of the POEMS freely obtained.
+
+
+We are open to hear from you about bugs, an idea for improvement, and suggestions, etc. We keep improving the POEMS. Check the POEMS web site (www.rpi.edu/~anderk5/POEMS) for the recent changes.
+
+
+All correspondence regarding the POEMS should be sent to:
+
+By email: (preferred)
+Prof. Kurt Anderson (anderk5@rpi.edu) or Rudranarayan Mukherjee (mukher@rpi.edu) - include "[POEMS]" in the subject
+
+or by mail:
+Prof. Kurt S. Anderson
+4006 Jonsson Engineering Center 	
+Rensselaer Polytechnic Institute
+110 8th Street,
+Troy, NY 12180-3510, U.S.A.
+
+	
+
+Created: June 6, 2006
diff --git a/lib/poems/SystemProcessor.h b/lib/poems/SystemProcessor.h
new file mode 100644
index 000000000..fa43386a1
--- /dev/null
+++ b/lib/poems/SystemProcessor.h
@@ -0,0 +1,283 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: SystemProcessor.h                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef _SYS_PROCESSOR_H_
+#define _SYS_PROCESSOR_H_
+#include "poemslist.h"
+#include "poemstree.h"
+#include "POEMSChain.h"
+
+
+struct POEMSNode {
+	List<POEMSNode> links;
+	List<bool> taken;
+	int idNumber;
+	bool visited;
+	
+	~POEMSNode(){
+		for(int i = 0; i < taken.GetNumElements(); i++)
+		{
+			delete taken(i);
+		}
+	};	
+};
+
+
+class SystemProcessor{
+private:
+	Tree nodes;
+//	List<POEMSNode> forDeletion;
+	List<POEMSChain> headsOfSystems;
+	List<List<int> > ringsInSystem;
+	POEMSNode * findSingleLink(TreeNode * aNode);
+	POEMSChain * AddNewChain(POEMSNode * currentNode);
+	bool setLinkVisited(POEMSNode * firstNode, POEMSNode * secondNode);
+public:
+	SystemProcessor(void);
+	
+	~SystemProcessor(void)	{
+		headsOfSystems.DeleteValues();
+		for(int i = 0; i < ringsInSystem.GetNumElements(); i++)
+		{
+			for(int k = 0; k < ringsInSystem(i)->GetNumElements(); i++)
+			{
+				delete (*ringsInSystem(i))(k);
+			}
+		}
+	};
+	void processArray(int** links, int numLinks);
+	List<POEMSChain> * getSystemData();
+	int getNumberOfHeadChains();
+};
+
+SystemProcessor::SystemProcessor(void){
+}
+
+void SystemProcessor::processArray(int** links, int numLinks)
+{
+	bool * false_var;					//holds the value false; needed because a constant cannot be put into a list; the list requires a
+										//reference.
+	for(int i = 0; i < numLinks; i++)	//go through all the links in the input array
+	{
+		if(!nodes.Find(links[i][0]))	//if the first node in the pair is not found in the storage tree
+		{
+			POEMSNode * newNode = new POEMSNode;	//make a new node
+//			forDeletion.Append(newNode);
+			newNode->idNumber = links[i][0];		//set its ID to the value
+			newNode->visited = false;				//set it to be unvisited
+			nodes.Insert(links[i][0], links[i][0], (void *) newNode);	//and add it to the tree storage structure
+		}
+		if(!nodes.Find(links[i][1]))				//repeat process for the other half of each link
+		{
+			POEMSNode * newNode = new POEMSNode;
+//			forDeletion.Append(newNode);
+			newNode->idNumber = links[i][1];
+			newNode->visited = false;
+			nodes.Insert(links[i][1], links[i][1], (void *) newNode);
+		}
+		POEMSNode * firstNode = (POEMSNode *)nodes.Find(links[i][0]);	//now that we are sure both nodes exist,
+		POEMSNode * secondNode = (POEMSNode *)nodes.Find(links[i][1]);	//we can get both of them out of the tree
+		firstNode->links.Append(secondNode);							//and add the link from the first to the second...
+		false_var = new bool;
+		*false_var = false;												//make a new false boolean to note that the link between these two
+		firstNode->taken.Append(false_var);								//has not already been taken, and append it to the taken list
+		secondNode->links.Append(firstNode);							//repeat process for link from second node to first
+		false_var = new bool;
+		*false_var = false;
+		secondNode->taken.Append(false_var);
+	}	
+	
+	TreeNode * temp = nodes.GetRoot();							//get the root node of the node storage tree
+	POEMSNode * currentNode;
+	do
+	{
+		currentNode = findSingleLink(temp);						//find the start of the next available chain
+		if(currentNode != NULL)
+		{
+			headsOfSystems.Append(AddNewChain(currentNode));							//and add it to the headsOfSystems list of chains
+		}
+	} 
+	while(currentNode != NULL);									//repeat this until all chains have been added		
+}
+
+POEMSChain * SystemProcessor::AddNewChain(POEMSNode * currentNode){
+	if(currentNode == NULL)	//Termination condition; if the currentNode is null, then return null
+	{
+		return NULL;
+	}
+	int * tmp;
+	POEMSNode * nextNode = NULL;	//nextNode stores the proposed next node to add to the chain.  this will be checked to make sure no backtracking is occuring before being assigned as the current node.
+	POEMSChain * newChain = new POEMSChain;	//make a new POEMSChain object.  This will be the object returned
+
+	if(currentNode->links.GetNumElements() == 0)	//if we have no links from this node, then the whole chain is only one node.  Add this node to the chain and return it; mark node as visited for future reference
+	{
+		currentNode->visited = true;
+		tmp = new int;
+		*tmp = currentNode->idNumber;
+		newChain->listOfNodes.Append(tmp);
+		return newChain;
+	}
+	while(currentNode->links.GetNumElements() <= 2)	//we go until we get to a node that branches, or both branches have already been taken both branches can already be taken if a loop with no spurs is found in the input data
+	{
+		currentNode->visited = true;
+		tmp = new int;
+		*tmp = currentNode->idNumber;
+		newChain->listOfNodes.Append(tmp);	//append the current node to the chain & mark as visited
+		//cout << "Appending node " << currentNode->idNumber << " to chain" << endl;
+		nextNode = currentNode->links.GetHeadElement()->value;	//the next node is the first or second value stored in the links array
+																//of the current node.  We get the first value...
+		if(!setLinkVisited(currentNode, nextNode))					//...and see if it points back to where we came from. If it does...
+		{														//either way, we set this link as visited
+			if(currentNode->links.GetNumElements() == 1)		//if it does, then if that is the only link to this node, we're done with the chain, so append the chain to the list and return the newly created chain
+			{
+//				headsOfSystems.Append(newChain);
+				return newChain;
+			}
+			nextNode = currentNode->links.GetHeadElement()->next->value;//follow the other link if there is one, so we go down the chain
+			if(!setLinkVisited(currentNode, nextNode))				//mark link as followed, so we know not to backtrack			
+			{
+	//			headsOfSystems.Append(newChain);
+				return newChain;								//This condition, where no branches have occurred but both links have already
+																//been taken can only occur in a loop with no spurs; add this loop to the
+																//system (currently added as a chain for consistency), and return.
+			}
+		}
+		currentNode = nextNode;									//set the current node to be the next node in the chain
+	}
+	currentNode->visited = true;
+	tmp = new int;
+	*tmp = currentNode->idNumber;
+	newChain->listOfNodes.Append(tmp);		//append the last node before branch (node shared jointly with branch chains)
+																//re-mark as visited, just to make sure
+	ListElement<POEMSNode> * tempNode = currentNode->links.GetHeadElement();	//go through all of the links, one at a time that branch
+	POEMSChain * tempChain = NULL;								//temporary variable to hold data 
+	while(tempNode != NULL)										//when we have followed all links, stop
+	{
+		if(setLinkVisited(tempNode->value, currentNode))		//dont backtrack, or create closed loops
+		{
+			tempChain = AddNewChain(tempNode->value);			//Add a new chain created out of the next node down that link
+			tempChain->parentChain = newChain;					//set the parent to be this chain
+			newChain->childChains.Append(tempChain);			//append the chain to this chain's list of child chains
+		}
+		tempNode = tempNode->next;								//go to process the next chain
+	}
+	//headsOfSystems.Append(newChain);							//append this chain to the system list		
+	return newChain;	
+}
+
+POEMSNode * SystemProcessor::findSingleLink(TreeNode * aNode)
+//This function takes the root of a search tree containing POEMSNodes and returns a POEMSNode corresponding to the start of a chain in the
+//system.  It finds a node that has not been visited before, and only has one link; this node will be used as the head of the chain.
+{
+	if(aNode == NULL)	
+	{
+		return NULL;
+	}
+	POEMSNode * returnVal =  (POEMSNode *)aNode->GetAuxData();	//get the poemsnode data out of the treenode
+	POEMSNode * detectLoneLoops = NULL;							//is used to handle a loop that has no protruding chains
+	if(returnVal->visited == false)
+	{
+		detectLoneLoops = returnVal;							//if we find any node that has not been visited yet, save it
+	}
+	if(returnVal->links.GetNumElements() == 1 && returnVal->visited == false)	//see if it has one element and hasnt been visited already
+	{
+		return returnVal;														//return the node is it meets this criteria
+	}
+	returnVal = findSingleLink(aNode->Left());									//otherwise, check the left subtree
+	if(returnVal == NULL)														//and if we find nothing...
+	{
+		returnVal = findSingleLink(aNode->Right());								//check the right subtree
+	}
+	if(returnVal == NULL)														//if we could not find any chains
+	{
+		returnVal = detectLoneLoops;											//see if we found any nodes at all that havent been processed
+	}
+	return returnVal;															//return what we find (will be NULL if no new chains are 
+																				//found)
+}
+
+bool SystemProcessor::setLinkVisited(POEMSNode * firstNode, POEMSNode * secondNode)
+//setLinkVisited sets the links between these two nodes as visited. If they are already visited, it returns false.  Otherwise, it sets
+//them as visited and returns true.  This function is used to see whether a certain path has been taken already in the graph structure.
+//If it has been, then we need to know so we dont follow it again; this prevents infinite recursion when there is a loop, and prevents
+//backtracking up a chain that has already been made.  The list of booleans denoting if a link has been visited is called 'taken' and is
+//part of the POEMSNode struct.  The list is the same size as the list of pointers to other nodes, and stores the boolean visited/unvisited
+//value for that particular link.  Because each link is represented twice, (once at each node in the link), both of the boolean values need
+//to be set in the event that the link has to be set as visited.
+{
+	//cout << "Checking link between nodes " << firstNode->idNumber << " and " << secondNode->idNumber << "... ";
+	ListElement<POEMSNode> * tmp = firstNode->links.GetHeadElement();	//get the head element of the list of pointers for node 1
+	ListElement<bool> * tmp2 = firstNode->taken.GetHeadElement();		//get the head element of the list of bool isVisited flags for node 1
+	while(tmp->value != NULL || tmp2->value != NULL)					//go through untill we reach the end of the lists
+	{
+		if(tmp->value == secondNode)							//if we find the link to the other node
+		{
+			if(*(tmp2->value) == true)							//if the link has already been visited
+			{
+				 //cout << "visited already" << endl;
+				return false;									//return false to indicate that the link has been visited before this attempt
+			}
+			else												//otherwise, visit it
+			{
+				*tmp2->value = true;
+			}
+			break;
+		}
+		tmp = tmp->next;										//go check next link
+		tmp2 = tmp2->next;
+	}
+
+	tmp = secondNode->links.GetHeadElement();			//now, if the link was unvisited, we need to go set the other node's list such that
+														//it also knows this link is being visited
+	tmp2 = secondNode->taken.GetHeadElement();
+	while(tmp->value != NULL || tmp2->value != NULL)	//go through the list
+	{
+		if(tmp->value == firstNode)						//if we find the link
+		{
+			if(*(tmp2->value) == true)					//and it has already been visited, then signal an error; this shouldnt ever happen
+			{
+				cout << "Error in parsing structure! Should never reach this condition! \n" << 
+						"Record of visited links out of synch between two adjacent nodes.\n";
+				return false;
+			}
+			else
+			{
+				*tmp2->value = true;					//set the appropriate value to true to indicate this link has been visited
+			}
+			break;
+		}
+		tmp = tmp->next;
+		tmp2 = tmp2->next;
+	}
+	//cout << "not visited" << endl;
+	return true;										//return true to indicate that this is the first time the link has been visited
+}
+
+List<POEMSChain> * SystemProcessor::getSystemData(void)	//Gets the list of POEMSChains that comprise the system.  Might eventually only
+														//return chains linked to the reference plane, but currently returns every chain
+														//in the system.
+{
+	return &headsOfSystems;
+}
+
+int SystemProcessor::getNumberOfHeadChains(void) //This function isnt implemented yet, and might be taken out entirely; this was a holdover
+												//from when I intended to return an array of chain pointers, rather than a list of chains
+												//It will probably be deleted once I finish figuring out exactly what needs to be returned
+{
+	return 0;
+}
+#endif
diff --git a/lib/poems/bodies.h b/lib/poems/bodies.h
new file mode 100644
index 000000000..e47a4c80e
--- /dev/null
+++ b/lib/poems/bodies.h
@@ -0,0 +1,27 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: bodies.h                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef BODIES_H
+#define BODIES_H
+
+#include "body.h"
+#include "inertialframe.h"
+#include "rigidbody.h"
+#include "particle.h"
+
+#endif
diff --git a/lib/poems/body.cpp b/lib/poems/body.cpp
new file mode 100644
index 000000000..4ef05dd1e
--- /dev/null
+++ b/lib/poems/body.cpp
@@ -0,0 +1,137 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: body.cpp                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+#include "bodies.h"
+#include "point.h"
+
+using namespace std;
+
+Body::Body()
+{
+  inertia.Zeros();
+  mass = 0;
+  a_t.Zeros();
+}
+
+Body::~Body()
+{
+  points.DeleteValues();
+}
+
+bool Body::ReadIn(istream& in){
+  return (ReadInBodyData(in) && ReadInPoints(in));
+}
+
+void Body::WriteOut(ostream& out){
+  // write out header <type> <name>
+  out << GetType() << ' ' << GetName() << endl;
+
+  // write out body specific data
+  WriteOutBodyData(out);
+
+  // write out points
+  WriteOutPoints(out);
+
+}
+
+bool Body::ReadInPoints(istream& in){
+  // get numfixed points
+  int numpoints;
+  int index;
+  Point* point;
+  int pointtype;
+  char pointname[256];
+
+  in >> numpoints;
+
+  for(int i=points.GetNumElements();i<numpoints;i++){
+    // error check
+    in >> index;
+    if(index != i){
+      cerr << "Invalid file format" << endl;
+      return false;
+    }
+
+    in >> pointtype >> pointname;
+    point = NewPoint(pointtype);
+
+    if(!point){
+      cerr << "Unrecognized point type '" << pointtype << endl;
+      return false;
+    }
+
+    // add the point
+    AddPoint(point);
+
+    // set generic point info
+    point->ChangeName(pointname);
+
+    // read in the rest of its data
+    if(!point->ReadIn(in)) return false;
+  }
+  return true;
+}
+
+void Body::WriteOutPoints(std::ostream& out){
+  int numpoints = points.GetNumElements();
+
+  out << numpoints << endl;
+
+  // list element pointer
+  ListElement<Point>* ele = points.GetHeadElement();
+
+  // set the ID of each point
+  for(int i=0;i<numpoints;i++){
+    ele->value->SetID(i);
+    out << i << ' ';
+    ele->value->WriteOut(out);
+
+    // increment list element pointer
+    ele = ele->next;
+  }
+  out << endl;
+}
+
+Point* Body::GetPoint(int p) {
+  return points(p);
+}
+
+void Body::AddJoint(Joint* joint){
+  joints.Append(joint);
+}
+
+void Body::AddPoint(Point* point){
+  points.Append(point);
+}
+
+//
+// global body functions
+//
+
+Body* NewBody(int type){
+  switch( BodyType(type) )
+    {
+      case INERTIALFRAME :  // The inertial reference frame
+        return new InertialFrame;
+      case RIGIDBODY :  // A Rigid Body
+        return new RigidBody;
+      case PARTICLE :  // A Particle
+        return new Particle;
+      default  :  // error
+        return 0;
+    }
+}
diff --git a/lib/poems/body.h b/lib/poems/body.h
new file mode 100644
index 000000000..f8e0f6a5a
--- /dev/null
+++ b/lib/poems/body.h
@@ -0,0 +1,81 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: body.h                                                  *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+
+#ifndef BODY_H
+#define BODY_H
+
+#include "poemslist.h"
+#include <iostream>
+#include "poemsobject.h"
+
+#include "matrices.h"
+
+
+
+// emumerated type
+enum BodyType {
+  INERTIALFRAME = 0,
+  PARTICLE = 1,
+  RIGIDBODY = 2
+};
+  
+class Point;
+class Joint;
+class CompBody;
+
+class Body : public POEMSObject {
+public:
+  double mass;
+  Mat3x3 inertia;
+  
+  Vect3 r;
+  Vect3 v;
+  Vect3 v_k;
+  Vect3 a;
+  Vect3 a_t;
+  Mat3x3 n_C_k;
+  Vect3 omega;
+  Vect3 omega_k;
+  Vect3 alpha;
+  Vect3 alpha_t;
+  double KE;
+  
+
+  List<Joint> joints;
+  List<Point> points;
+
+  Body();
+  
+  bool ReadIn(std::istream& in);
+  void WriteOut(std::ostream& out);
+  bool ReadInPoints(std::istream& in);
+  void WriteOutPoints(std::ostream& out);
+  Point* GetPoint(int p);
+  void AddJoint(Joint* joint);
+  void AddPoint(Point* point);
+  
+  virtual bool ReadInBodyData(std::istream& in) = 0;
+  virtual void WriteOutBodyData(std::ostream& out) = 0;
+  virtual ~Body();
+  virtual BodyType GetType() = 0;
+};
+
+// global body functions
+Body* NewBody(int type);
+
+#endif
diff --git a/lib/poems/body23joint.cpp b/lib/poems/body23joint.cpp
new file mode 100644
index 000000000..8cd0a95bc
--- /dev/null
+++ b/lib/poems/body23joint.cpp
@@ -0,0 +1,260 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: body23joint.cpp			                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+
+#include "body23joint.h"
+#include "point.h"
+#include "matrixfun.h"
+#include "body.h"
+#include "fastmatrixops.h"
+#include "norm.h"
+#include "eulerparameters.h"
+#include "matrices.h"
+#include <iomanip>
+
+
+Body23Joint::Body23Joint(){
+  DimQandU(4,2);
+}
+Body23Joint::~Body23Joint(){
+}
+
+JointType Body23Joint::GetType(){
+  return BODY23JOINT;
+}
+
+bool Body23Joint::ReadInJointData(std::istream& in){
+  return true;
+}
+
+void Body23Joint::WriteOutJointData(std::ostream& out){
+}
+
+Matrix Body23Joint::GetForward_sP(){
+	Vect3 temp = -(point2->position);  // This is vector from joint to CM
+	Matrix sP(6,2);
+	sP.Zeros();
+	
+	sP(2,1) =1.0;
+	sP(3,2) =1.0;	
+	sP(5,2) = temp(1);
+	sP(6,1) = -temp(1);	
+	return sP;    
+}
+
+void Body23Joint::UpdateForward_sP( Matrix& sP){
+    // sP is constant, do nothing.
+  // linear part is not constant
+}
+
+Matrix Body23Joint::GetBackward_sP(){
+	cout<<" -----------"<<endl;
+	cout<<"Am I here "<<endl;
+	cout<<" -----------"<<endl;	  
+	Vect3 temp = (point2->position);  // This is vector from CM to joint 
+	Matrix sP(6,2);
+	sP.Zeros();
+	sP(2,1) =1.0;
+	sP(3,2) =1.0;
+	
+	sP(5,2) = temp(1);
+	sP(6,1) = -temp(1);
+	
+	return sP;    
+}
+
+void Body23Joint::UpdateBackward_sP( Matrix& sP){  
+  // sP is constant, do nothing.
+}
+
+void Body23Joint::ComputeLocalTransform(){
+	Mat3x3 ko_C_k;
+	// Obtain the transformation matrix from euler parameters
+	EP_Transformation(q, ko_C_k);
+	FastMult(pk_C_ko,ko_C_k,pk_C_k);
+	}  
+
+
+void Body23Joint::ForwardKinematics(){
+  Vect3 result1,result2,result3,result4,result5;
+  Vect3 pk_w_k;
+  
+  
+  //cout<<"Check in spherical "<<q<<" "<<qdot<<endl;
+  EP_Normalize(q);
+  
+
+  // orientations
+  ComputeForwardTransforms();    
+  
+  
+  //----------------------------------//
+  // COMPUTE POSITION VECTOR R12 aka GAMMA    
+  
+  FastNegMult(pk_C_k,point2->position,result1); // parents basis      
+  FastAdd(result1,point1->position,r12);      
+  
+  // compute position vector r21 
+  FastNegMult(k_C_pk,r12,r21); 
+
+  
+  //----------------------------------//
+  // COMPUTE GLOBAL LOCATION  
+  FastMult(body1->n_C_k,(body1->GetPoint(2))->position,result1);    
+  FastAdd(result1,body1->r,result1);  
+  FastNegMult(body2->n_C_k,(body2->GetPoint(1))->position,result2);  
+  FastAdd(result1,result2,body2->r);  
+    
+  ColMatrix temp_u(3);
+  qdot_to_u(q, temp_u, qdot);  
+  
+  temp_u(1)=0.0; 
+  u(1) = temp_u(2);
+  u(2) = temp_u(3);
+  
+
+  //-----------------------------------  
+  // angular velocities  
+  
+  FastAssign(temp_u,pk_w_k);
+  FastTMult(pk_C_k,body1->omega_k,result1);        
+  FastAdd(result1,pk_w_k,body2->omega_k);
+  FastMult(body2->n_C_k,body2->omega_k,body2->omega);  // June 1 checked with Lammps       
+  //-----------------------------------  
+  
+  // compute velocities  
+  FastCross(body1->omega_k,(body1->GetPoint(2))->position,result1);  
+  FastAdd(body1->v_k,result1,result2);
+  FastTMult(pk_C_k,result2,result1); // In body basis  
+  
+  FastCross((body2->GetPoint(1))->position,body2->omega_k,result2);                   
+  FastAdd(result1,result2,body2->v_k);    // In body basis   
+  FastMult(body2->n_C_k,body2->v_k,body2->v); 
+  
+  //------------------------------------------
+  //Compute the KE   
+  Matrix tempke;
+  tempke = T(body2->v_k)*(body2->v_k);    
+  double ke = 0.0;
+  ke = body2->mass*tempke(1,1);    
+  FastMult(body2->inertia,body2->omega_k,result1);
+  tempke= T(body2->omega_k)*result1;  
+  ke = 0.5*ke + 0.5*tempke(1,1);
+  body2->KE=ke;
+  
+  //-----------------------------------  
+  // compute state explicit angular acceleration  // Has to be in body basis    
+  FastTMult(pk_C_k,body1->alpha_t,result2);  
+  FastCross(body2->omega_k,pk_w_k,result1);
+  FastAdd(result1,result2,body2->alpha_t); 
+   
+  //-----------------------------------  
+  // compute state explicit acceleration   
+  // NEED TO DO THIS COMPLETELY IN BODY BASIS 
+  
+  FastCross(body1->omega_k,(body1->GetPoint(2))->position,result1);
+  FastCross(body1->omega_k,result1,result2); 
+  FastTMult(pk_C_k,result2,result1); 
+  
+  //FastCross(body2->omega_k,-(body2->GetPoint(1))->position,result3);  
+  FastCross((body2->GetPoint(1))->position,body2->omega_k,result3);  
+  FastCross(body2->omega_k,result3,result2);    
+  FastAdd(result1,result2,result3); //wxwxr in body basis  
+  
+  FastCross(body1->alpha_t,(body1->GetPoint(2))->position,result4); 
+    
+  FastTMult(pk_C_k,result4,result5);  
+  FastAssign(result5,result4);
+  
+  FastCross((body2->GetPoint(1))->position,body2->alpha_t,result2);   
+  FastAdd(result2,result4,result1); //alphaxr in body basis  
+  
+  FastTMult(pk_C_k,body1->a_t,result2);
+  FastTripleSum(result3,result1,result2,body2->a_t);     // in body basis  
+  
+  
+  //-----------------------------------    
+}
+
+// NOTE: NOT USING BACKWARDKINEMATICS AT PRESENT
+void Body23Joint::BackwardKinematics(){
+  cout<<"what about here "<<endl;
+  Vect3 result1,result2,result3,result4,result5;
+  Vect3 k_w_pk;
+
+  // orientations
+  ComputeBackwardTransforms();
+  
+
+  // compute position vector r21
+  //r21 = point2->position - k_C_pk * point1->position;
+  FastMult(k_C_pk,point1->position,result1);
+  FastSubt(point2->position,result1,r21);
+  
+
+  // compute position vector r21
+  FastNegMult(pk_C_k,r21,r12);
+
+  // compute global location
+  // body1->r = body2->r + body2->n_C_k * r21;
+  FastMult(body2->n_C_k,r21,result1);
+  FastAdd(body2->r,result1,body1->r);
+
+  // compute qdot (for revolute joint qdot = u)
+  // qdot = u
+  ColMatrix us(3);
+  /*us(1)=0;
+  us(2)=u(1);
+  us(3)=u(2);*/
+  EP_Derivatives(q,u,qdot);
+
+  // angular velocities
+ 
+  FastMult(body2->n_C_k,u,result2);
+  FastAdd(body2->omega,result2,body1->omega);
+  FastAssign(u,k_w_pk);
+  FastMult(pk_C_k,body2->omega_k,result1);
+  FastSubt(result1,k_w_pk,body1->omega_k);
+  cout<<"The program was here"<<endl;
+
+  // compute velocities
+  FastCross(body2->omega_k,r21,result1);
+  FastCross(point1->position,k_w_pk,result2);
+  FastAdd(body2->v_k,result1,result3);
+  FastMult(pk_C_k,result3,result4);
+  FastAdd(result2,result4,body1->v_k);
+  FastMult(body1->n_C_k,body1->v_k,body1->v);
+
+  // compute state explicit angular acceleration
+  FastCross(body1->omega_k,k_w_pk,result1);
+  FastMult(pk_C_k,body2->alpha_t,result2);
+  FastAdd(result1,result2,body1->alpha_t);
+  
+  // compute state explicit acceleration
+  FastCross(body2->alpha_t,point2->position,result1);
+  FastCross(body2->omega_k,point2->position,result2);
+  FastCross(body2->omega_k,result2,result3);
+  FastTripleSum(body2->a_t,result1,result3,result4);
+  FastMult(pk_C_k,result4,result5);
+
+  FastCross(point1->position,body1->alpha_t,result1);
+  FastCross(point1->position,body1->omega_k,result2);
+  FastCross(body1->omega_k,result2,result3);
+
+  FastTripleSum(result5,result1,result3,body1->a_t);
+  
+}
diff --git a/lib/poems/body23joint.h b/lib/poems/body23joint.h
new file mode 100644
index 000000000..60253ac8a
--- /dev/null
+++ b/lib/poems/body23joint.h
@@ -0,0 +1,44 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: body23joint.h			                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef BODY23JOINT_H
+#define BODY23JOINT_H
+
+#include "joint.h"
+#include "vect3.h"
+#include "mat3x3.h"
+
+
+
+class Body23Joint : public Joint  {
+  Matrix const_sP;
+public:
+  Body23Joint();
+  ~Body23Joint();
+  JointType GetType();
+  bool ReadInJointData(std::istream& in);
+  void WriteOutJointData(std::ostream& out);
+  Matrix GetForward_sP();
+  Matrix GetBackward_sP();
+  void UpdateForward_sP( Matrix& sP);
+  void UpdateBackward_sP( Matrix& sP);
+  void ComputeLocalTransform();
+  void ForwardKinematics();
+  void BackwardKinematics();
+};
+
+#endif
diff --git a/lib/poems/colmatmap.cpp b/lib/poems/colmatmap.cpp
new file mode 100644
index 000000000..d2f631c20
--- /dev/null
+++ b/lib/poems/colmatmap.cpp
@@ -0,0 +1,197 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: colmatmap.cpp                                           *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "colmatmap.h"
+#include "colmatrix.h"
+#include <iostream>
+
+using namespace std;
+
+ColMatMap::ColMatMap(){
+	numrows = 0;
+	elements = 0;
+}
+
+ColMatMap::~ColMatMap(){
+	delete [] elements;
+}
+
+ColMatMap::ColMatMap(const ColMatMap& A){  // copy constructor
+	numrows = 0;
+	elements = 0;
+	Dim(A.numrows);
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.elements[i];
+}
+
+ColMatMap::ColMatMap(ColMatrix& A){  // copy constructor
+	numrows = 0;
+	elements = 0;
+	Dim(A.GetNumRows());
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.GetElementPointer(i);
+}
+
+/*
+ColMatrix::ColMatrix(const VirtualMatrix& A){  // copy constructor
+  if( A.GetNumCols() != 1 ){
+    cerr << "error trying to write a 2D matrix to a collumn" << endl;
+    exit(1);
+  }
+  numrows = 0;
+  elements = 0;
+  Dim(A.GetNumRows());
+  for(int i=0;i<numrows;i++)
+    elements[i] = A.BasicGet(i,0);
+}
+*/
+
+ColMatMap::ColMatMap(int m){  // size constructor
+	numrows = 0;
+	elements = 0;
+	Dim(m);
+}
+
+void ColMatMap::Dim(int m){
+	delete [] elements;
+	numrows = m;
+	elements = new double* [m];
+}
+
+void ColMatMap::Const(double value){
+	for(int i=0;i<numrows;i++)
+		*(elements[i]) = value;
+}
+
+MatrixType ColMatMap::GetType() const{
+	return COLMATMAP;
+}
+
+ostream& ColMatMap::WriteData(ostream& c) const{  //output
+	c << numrows << ' ';
+	for(int i=0;i<numrows;i++)
+		c << *(elements[i]) << ' ';
+	return c;
+}
+
+double& ColMatMap::operator_1int (int i){ // array access
+	if((i>numrows) || (i<1)){
+		cerr << "matrix index invalid in operator ()" << endl;
+		exit(1);
+	}
+	return *(elements[i-1]);
+}
+
+double ColMatMap::Get_1int(int i) const{
+	if((i>numrows) || (i<1)){
+		cerr << "matrix index exceeded in Get" << endl;
+		exit(1);
+	}
+	return *(elements[i-1]);
+}
+
+void ColMatMap::Set_1int(int i, double value){
+	if((i>numrows) || (i<1)){
+		cerr << "matrix index exceeded in Set" << endl;
+		exit(1);
+	}
+	*(elements[i-1]) = value;
+}
+
+double ColMatMap::BasicGet_1int(int i) const{
+	return *(elements[i]);
+}
+
+void ColMatMap::SetElementPointer(int i, double* p){
+	elements[i] = p;
+}
+
+double* ColMatMap::GetElementPointer(int i){
+	return elements[i];
+}
+
+void ColMatMap::BasicSet_1int(int i, double value){
+	*(elements[i]) = value;
+}
+
+void ColMatMap::BasicIncrement_1int(int i, double value){
+	*(elements[i]) += value;
+}
+
+void ColMatMap::AssignVM(const VirtualMatrix& A){
+	if(A.GetNumRows() != numrows){
+		cerr << "dimension mismatch in ColMatMap assignment" << endl;
+		exit(0);
+	}
+	if( A.GetNumCols() != 1 ){
+		cerr << "error trying to write a 2D matrix to a collumn" << endl;
+		exit(1);
+	}
+	for(int i=0;i<numrows;i++)
+		*(elements[i]) = A.BasicGet(i,0);
+}
+
+ColMatMap& ColMatMap::operator=(const ColMatMap& A){ // assignment operator
+	if(A.numrows != numrows){
+		cerr << "dimension mismatch in ColMatMap assignment" << endl;
+		exit(0);
+	}
+	for(int i=0;i<numrows;i++)
+		*(elements[i]) = *(A.elements[i]);
+	return *this;
+}
+
+ColMatMap& ColMatMap::operator=(const ColMatrix& A){ // assignment operator
+	if(A.GetNumRows() != numrows){
+		cerr << "dimension mismatch in ColMatMap assignment" << endl;
+		exit(0);
+	}
+	for(int i=0;i<numrows;i++)
+		*(elements[i]) = A.BasicGet(i);
+	return *this;
+}
+
+ColMatMap& ColMatMap::operator=(const VirtualColMatrix& A){ // overloaded =
+	if(A.GetNumRows() != numrows){
+		cerr << "dimension mismatch in ColMatMap assignment" << endl;
+		exit(0);
+	}
+	for(int i=0;i<numrows;i++)
+		*(elements[i]) = A.BasicGet(i);
+	return *this;
+}
+
+ColMatMap& ColMatMap::operator=(const VirtualMatrix& A){ // overloaded =
+	if(A.GetNumRows() != numrows){
+		cerr << "dimension mismatch in ColMatMap assignment" << endl;
+		exit(0);
+	}
+	if( A.GetNumCols() != 1 ){
+		cerr << "error trying to write a 2D matrix to a collumn" << endl;
+		exit(1);
+	}
+	for(int i=0;i<numrows;i++)
+		*(elements[i]) = A.BasicGet(i,0);
+	return *this;
+}
+
+ColMatMap& ColMatMap::operator*=(double b){
+	for(int i=0;i<numrows;i++)
+		*(elements[i]) *= b;
+	return *this;
+}
+
diff --git a/lib/poems/colmatmap.h b/lib/poems/colmatmap.h
new file mode 100644
index 000000000..3a6267a24
--- /dev/null
+++ b/lib/poems/colmatmap.h
@@ -0,0 +1,65 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: colmatmap.h                                             *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef COLMATMAP_H
+#define COLMATMAP_H
+
+#include "virtualcolmatrix.h"
+
+class ColMatrix;
+
+class ColMatMap : public VirtualColMatrix  {
+        double** elements;
+public:
+        ColMatMap();
+        ~ColMatMap();
+        ColMatMap(const ColMatMap& A);  // copy constructor
+        ColMatMap(ColMatrix& A);  // copy constructor
+        ColMatMap(int m);  // size constructor
+
+        double& operator_1int (int i); // array access
+        double Get_1int(int i) const;
+        void Set_1int(int i, double value);
+        double BasicGet_1int(int i) const;
+        void BasicSet_1int(int i, double value);
+        void BasicIncrement_1int(int i, double value);
+        void SetElementPointer(int i, double* p);
+        double* GetElementPointer(int i);
+        void Dim(int m);
+        void Const(double value);
+        MatrixType GetType() const;
+        std::ostream& WriteData(std::ostream& c) const;
+
+        void AssignVM(const VirtualMatrix& A);
+        ColMatMap& operator=(const ColMatMap& A); // assignment operator
+        ColMatMap& operator=(const ColMatrix& A); // overloaded =
+        ColMatMap& operator=(const VirtualColMatrix& A); // overloaded =
+        ColMatMap& operator=(const VirtualMatrix& A); // overloaded =
+        ColMatMap& operator*=(double b);
+
+        // Fast Matrix Operators
+        friend void FastAssign(ColMatMap& A, ColMatMap& C); //C = A
+        friend void FastAssign(ColMatMap& A, ColMatrix& C);  // C = A
+        friend void FastAssign(ColMatrix& A, ColMatMap& C);  // C = A
+        friend void FastForwardEuler(ColMatMap& X,ColMatMap& Xdot, double dt);
+        friend void FastForwardEuler(ColMatMap& X,ColMatrix& Xdot, double dt);
+        friend void FastCKRK5(ColMatMap& X, ColMatrix& Xi, ColMatrix* f, double* c, double dt);
+        friend void FastFRK5(ColMatMap& X, ColMatrix& Xi, ColMatrix* f, double* c, double dt);
+};
+
+#endif
diff --git a/lib/poems/colmatrix.cpp b/lib/poems/colmatrix.cpp
new file mode 100644
index 000000000..abbb0181c
--- /dev/null
+++ b/lib/poems/colmatrix.cpp
@@ -0,0 +1,204 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: colmatrix.cpp                                           *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "colmatrix.h"
+#include "rowmatrix.h"
+#include <iostream>
+#include <cmath>
+
+using namespace std;
+
+ColMatrix::ColMatrix(){
+	numrows = 0;
+	elements = 0;
+}
+
+ColMatrix::~ColMatrix(){
+	delete [] elements;
+}
+
+ColMatrix::ColMatrix(const ColMatrix& A){  // copy constructor
+	numrows = 0;
+	elements = 0;
+	Dim(A.numrows);
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.elements[i];
+}
+
+ColMatrix::ColMatrix(const VirtualColMatrix& A){  // copy constructor
+	numrows = 0;
+	elements = 0;
+	Dim(A.GetNumRows());
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.BasicGet(i);
+}
+
+ColMatrix::ColMatrix(const VirtualMatrix& A){  // copy constructor
+	if( A.GetNumCols() != 1 ){
+		cerr << "error trying to write a 2D matrix to a collumn" << endl;
+		exit(1);
+	}
+	numrows = 0;
+	elements = 0;
+	Dim(A.GetNumRows());
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.BasicGet(i,0);
+}
+
+ColMatrix::ColMatrix(int m){  // size constructor
+	numrows = 0;
+	elements = 0;
+	Dim(m);
+}
+
+void ColMatrix::Dim(int m){
+	delete [] elements;
+	numrows = m;
+	elements = new double [m];
+}
+
+void ColMatrix::Const(double value){
+	for(int i=0;i<numrows;i++)
+		elements[i] = value;
+}
+
+MatrixType ColMatrix::GetType() const{
+	return COLMATRIX;
+}
+
+istream& ColMatrix::ReadData(istream& c){
+	int n;
+	c >> n;
+	Dim(n);
+	for(int i=0;i<n;i++)
+		c >> elements[i];
+	return c;
+}
+
+ostream& ColMatrix::WriteData(ostream& c) const{  //output
+	c << numrows << ' ';
+	for(int i=0;i<numrows;i++)
+		c << elements[i] << ' ';
+	return c;
+}
+
+double& ColMatrix::operator_1int (int i){ // array access
+	if((i>numrows) || (i<1)){
+		cerr << "matrix index invalid in operator ()" << endl;
+		exit(1);
+	}
+	return elements[i-1];
+}
+
+double ColMatrix::Get_1int(int i) const{
+	if((i>numrows) || (i<1)){
+		cerr << "matrix index exceeded in Get" << endl;
+		exit(1);
+	}
+	return elements[i-1];
+}
+
+void ColMatrix::Set_1int(int i, double value){
+	if((i>numrows) || (i<1)){
+		cerr << "matrix index exceeded in Set" << endl;
+		exit(1);
+	}
+	elements[i-1] = value;
+}
+
+double ColMatrix::BasicGet_1int(int i) const{
+	return elements[i];
+}
+
+double* ColMatrix::GetElementPointer(int i){
+	return &(elements[i]);
+}
+
+void ColMatrix::BasicSet_1int(int i, double value){
+	elements[i] = value;
+}
+
+void ColMatrix::BasicIncrement_1int(int i, double value){
+	elements[i] += value;
+}
+
+void ColMatrix::AssignVM(const VirtualMatrix& A){
+	if( A.GetNumCols() != 1 ){
+		cerr << "error trying to write a 2D matrix to a collumn" << endl;
+		exit(1);
+	}
+	Dim( A.GetNumRows() );
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.BasicGet(i,0);
+}
+
+ColMatrix& ColMatrix::operator=(const ColMatrix& A){ // assignment operator
+	Dim(A.numrows);
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.elements[i];
+	return *this;
+}
+
+ColMatrix& ColMatrix::operator=(const VirtualColMatrix& A){ // overloaded =
+	Dim( A.GetNumRows() );
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.BasicGet(i);
+	return *this;
+}
+
+ColMatrix& ColMatrix::operator=(const VirtualMatrix& A){ // overloaded =
+	if( A.GetNumCols() != 1 ){
+		cerr << "error trying to write a 2D matrix to a collumn" << endl;
+		exit(1);
+	}
+	Dim( A.GetNumRows() );
+	for(int i=0;i<numrows;i++)
+		elements[i] = A.BasicGet(i,0);
+	return *this;
+}
+
+ColMatrix& ColMatrix::operator*=(double b){
+	for(int i=0;i<numrows;i++)
+		elements[i] *= b;
+	return *this;
+}
+
+void ColMatrix::Abs(){
+	for(int i=0;i<numrows;i++)
+		elements[i] = std::abs(elements[i]);
+}
+
+void ColMatrix::BasicMax(double& value, int& index){
+	value = elements[0];
+	index = 0;
+	for(int i=1;i<numrows;i++)
+		if(elements[i] > value){
+			value = elements[i];
+			index = i;
+		}
+}
+
+void ColMatrix::BasicMin(double& value, int& index){
+	value = elements[0];
+	index = 0;
+	for(int i=1;i<numrows;i++)
+		if(elements[i] < value){
+			value = elements[i];
+			index = i;
+		}
+}
+
diff --git a/lib/poems/colmatrix.h b/lib/poems/colmatrix.h
new file mode 100644
index 000000000..11fd85a92
--- /dev/null
+++ b/lib/poems/colmatrix.h
@@ -0,0 +1,84 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: colmatrix.h                                             *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef COLMATRIX_H
+#define COLMATRIX_H
+
+#include "virtualcolmatrix.h"
+#include "colmatmap.h"
+
+class Matrix;
+class Vect6;
+class Mat3x3;
+class Vect3;
+
+class ColMatrix : public VirtualColMatrix  {
+  double* elements;
+public:
+  ColMatrix();
+  ~ColMatrix();
+  ColMatrix(const ColMatrix& A);  // copy constructor
+  ColMatrix(const VirtualColMatrix& A);  // copy constructor
+  ColMatrix(const VirtualMatrix& A);  // copy constructor
+  ColMatrix(int m);  // size constructor
+
+  double& operator_1int (int i); // array access
+  double Get_1int(int i) const;
+  void Set_1int(int i, double value);
+  double BasicGet_1int(int i) const;
+  void BasicSet_1int(int i, double value);
+  void BasicIncrement_1int(int i, double value);
+
+  double* GetElementPointer(int i);
+  void Dim(int m);
+  void Const(double value);
+  MatrixType GetType() const;
+  std::istream& ReadData(std::istream& c);
+  std::ostream& WriteData(std::ostream& c) const;
+
+  void AssignVM(const VirtualMatrix& A);
+  ColMatrix& operator=(const ColMatrix& A); // assignment operator
+  ColMatrix& operator=(const VirtualColMatrix& A); // overloaded =
+  ColMatrix& operator=(const VirtualMatrix& A); // overloaded =
+  ColMatrix& operator*=(double b);
+
+        void Abs();
+        void BasicMax(double& value, int& index);
+        void BasicMin(double& value, int& index);
+
+  // fast matrix operations
+		  friend void FastQuaternions(ColMatrix& q, Mat3x3& C);
+		  friend void FastInvQuaternions(Mat3x3& C, ColMatrix& q);
+		  friend void FastQuaternionDerivatives(ColMatrix& q, ColMatrix& omega, ColMatrix& qdot);
+		  friend void FastTMult(Matrix& A, Vect6& B, ColMatrix& C);
+		  friend void FastMult(Matrix& A, ColMatrix& B, Vect6& C);
+		  friend void FastAssign(ColMatrix& A, ColMatrix& C);
+
+		  friend void FastMult(Mat3x3& A, ColMatrix& B, Vect3& C);
+		  friend void FastMult(Mat3x3& A, Vect3& B, ColMatrix& C);
+		  friend void FastAssign(ColMatrix&A, Vect3& C);
+  
+		  friend void EP_Derivatives(ColMatrix& q, ColMatrix& u, ColMatrix& qdot);
+		  friend void EP_Transformation(ColMatrix& q, Mat3x3& C);
+		  friend void EP_FromTransformation(ColMatrix& q, Mat3x3& C);
+		  friend void EP_Normalize(ColMatrix& q);
+		  friend void EPdotdot_udot(ColMatrix& Audot, ColMatrix& Aqdot, ColMatrix& Aq,ColMatrix& Aqddot);
+		  friend void qdot_to_u(ColMatrix& q, ColMatrix& u, ColMatrix& qdot);
+};
+
+#endif
diff --git a/lib/poems/defines.h b/lib/poems/defines.h
new file mode 100644
index 000000000..55f94283d
--- /dev/null
+++ b/lib/poems/defines.h
@@ -0,0 +1,27 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: defines.h		                                          *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef _DEFINES_H_
+#define _DEFINES_H_
+
+enum SolverType {
+  ONSOLVER = 0,
+  PARTICLESOLVER = 1
+};
+
+#endif
+
diff --git a/lib/poems/eulerparameters.cpp b/lib/poems/eulerparameters.cpp
new file mode 100644
index 000000000..61fcc5fcc
--- /dev/null
+++ b/lib/poems/eulerparameters.cpp
@@ -0,0 +1,163 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: eulerparameters.cpp                                     *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "eulerparameters.h"
+#include "math.h"
+
+using namespace std;
+
+void EP_Derivatives(ColMatrix& q, ColMatrix& u, ColMatrix& qdot){  
+  EP_Normalize(q);
+  int num=u.GetNumRows();
+  if (3<num){
+	  for (int i=4; i<=num; i++){
+		  qdot.elements[i]=u.elements[i-1];
+	  }
+  }
+  
+  qdot.elements[0] = 0.5 *(q.elements[3]*u.elements[0] - q.elements[2]*u.elements[1] + q.elements[1]*u.elements[2]);  
+  qdot.elements[1] = 0.5 *(q.elements[2]*u.elements[0] + q.elements[3]*u.elements[1] - q.elements[0]*u.elements[2]);
+  qdot.elements[2] = 0.5 *(-q.elements[1]*u.elements[0] + q.elements[0]*u.elements[1] + q.elements[3]*u.elements[2]);
+  qdot.elements[3] = -0.5 *(q.elements[0]*u.elements[0] + q.elements[1]*u.elements[1] + q.elements[2]*u.elements[2]);
+    
+  }
+
+void EP_Transformation(ColMatrix& q, Mat3x3& C){
+  EP_Normalize(q);
+  
+  double q11 = q.elements[0]*q.elements[0];
+  double q22 = q.elements[1]*q.elements[1];
+  double q33 = q.elements[2]*q.elements[2];
+  double q44 = q.elements[3]*q.elements[3];
+
+  double q12 = q.elements[0]*q.elements[1];
+  double q13 = q.elements[0]*q.elements[2];
+  double q14 = q.elements[0]*q.elements[3];
+  double q23 = q.elements[1]*q.elements[2];
+  double q24 = q.elements[1]*q.elements[3];
+  double q34 = q.elements[2]*q.elements[3];
+
+  C.elements[0][0] = q11 - q22 - q33 + q44;
+  C.elements[1][1] = -q11 + q22 - q33 + q44;
+  C.elements[2][2] = -q11 - q22 + q33 + q44;
+
+  C.elements[0][1] = 2*(q12 - q34);
+  C.elements[1][0] = 2*(q12 + q34);
+
+  C.elements[0][2] = 2*(q13 + q24);
+  C.elements[2][0] = 2*(q13 - q24);
+
+  C.elements[1][2] = 2*(q23 - q14);
+  C.elements[2][1] = 2*(q23 + q14);
+}
+
+void EP_FromTransformation(ColMatrix& q, Mat3x3& C){
+  double b[4];
+
+  // condition indicators
+  b[0] = C.elements[0][0] - C.elements[1][1] - C.elements[2][2] + 1;
+  b[1] = -C.elements[0][0] + C.elements[1][1] - C.elements[2][2] + 1;
+  b[2] = -C.elements[0][0] - C.elements[1][1] + C.elements[2][2] + 1;
+  b[3] = C.elements[0][0] + C.elements[1][1] + C.elements[2][2] + 1;
+
+  int max = 0;
+  for(int i=1;i<4;i++){
+    if( b[i] > b[max] ) max = i;
+  }
+
+  if( max == 3 ){
+    q.elements[3] = 0.5 * sqrt( b[3] );
+    q.elements[0] = ( C.elements[2][1] - C.elements[1][2] ) / ( 4 * q.elements[3] );
+    q.elements[1] = ( C.elements[0][2] - C.elements[2][0] ) / ( 4 * q.elements[3] );
+    q.elements[2] = ( C.elements[1][0] - C.elements[0][1] ) / ( 4 * q.elements[3] );
+    return;
+  }
+
+  if( max == 0 ){
+    q.elements[0] = 0.5 * sqrt( b[0] );
+    q.elements[1] = ( C.elements[0][1] + C.elements[1][0] ) / ( 4 * q.elements[0] );
+    q.elements[2] = ( C.elements[0][2] + C.elements[2][0] ) / ( 4 * q.elements[0] );
+    q.elements[3] = ( C.elements[2][1] - C.elements[1][2] ) / ( 4 * q.elements[0] );
+    return;
+  }
+
+  if( max == 1 ){
+    q.elements[1] = 0.5 * sqrt( b[1] );
+    q.elements[0] = ( C.elements[0][1] + C.elements[1][0] ) / ( 4 * q.elements[1] );
+    q.elements[2] = ( C.elements[1][2] + C.elements[2][1] ) / ( 4 * q.elements[1] );
+    q.elements[3] = ( C.elements[0][2] - C.elements[2][0] ) / ( 4 * q.elements[1] );
+    return;
+  }
+
+  if( max == 2 ){
+    q.elements[2] = 0.5 * sqrt( b[2] );
+    q.elements[0] = ( C.elements[0][2] + C.elements[2][0] ) / ( 4 * q.elements[2] );
+    q.elements[1] = ( C.elements[1][2] + C.elements[2][1] ) / ( 4 * q.elements[2] );
+    q.elements[3] = ( C.elements[1][0] - C.elements[0][1] ) / ( 4 * q.elements[2] );
+    return;
+  }
+  EP_Normalize(q);
+}
+
+void EP_Normalize(ColMatrix& q){
+  double one = 1.0/sqrt(q.elements[0]*q.elements[0] + q.elements[1]*q.elements[1] + q.elements[2]*q.elements[2] + q.elements[3]*q.elements[3]);  
+  q.elements[0] = one*q.elements[0];
+  q.elements[1] = one*q.elements[1];
+  q.elements[2] = one*q.elements[2];
+  q.elements[3] = one*q.elements[3];
+}
+
+
+
+
+void EPdotdot_udot(ColMatrix& Audot, ColMatrix& Aqdot, ColMatrix& Aq, ColMatrix& Aqddot){  
+  int num=Audot.GetNumRows();
+  if (3<num){
+	  for (int i=4; i<=num; i++){
+		  Aqddot.elements[i]=Audot.elements[i-1];
+	  }
+  }
+    
+  double AA;
+  AA=Aqdot.elements[0]*Aqdot.elements[0]+Aqdot.elements[1]*Aqdot.elements[1]+Aqdot.elements[2]*Aqdot.elements[2]+Aqdot.elements[3]*Aqdot.elements[3];
+  
+  Aqddot.elements[0] = 0.5 *(Aq.elements[3]*Audot.elements[0] - Aq.elements[2]*Audot.elements[1] + Aq.elements[1]*Audot.elements[2]-2*Aq.elements[0]*AA);
+  
+  Aqddot.elements[1] = 0.5 *(Aq.elements[2]*Audot.elements[0] + Aq.elements[3]*Audot.elements[1] - Aq.elements[0]*Audot.elements[2]-2*Aq.elements[1]*AA);
+  
+  Aqddot.elements[2] = 0.5 *(-Aq.elements[1]*Audot.elements[0] + Aq.elements[0]*Audot.elements[1] + Aq.elements[3]*Audot.elements[2]-2*Aq.elements[2]*AA);
+  
+  Aqddot.elements[3] = -0.5 *(Aq.elements[0]*Audot.elements[0] + Aq.elements[1]*Audot.elements[1] + Aq.elements[2]*Audot.elements[2]+2*Aq.elements[3]*AA);
+  
+}
+
+
+void qdot_to_u(ColMatrix& q, ColMatrix& u, ColMatrix& qdot){
+	EP_Normalize(q);
+	int num=qdot.GetNumRows();
+      	if (4<num){
+      		for (int i=5; i<=num; i++){
+      			u.elements[i-2]=qdot.elements[i-1];
+      		}
+      	}		
+      	u.elements[0]=2*(q.elements[3]*qdot.elements[0]+q.elements[2]*qdot.elements[1]-q.elements[1]*qdot.elements[2]-q.elements[0]*qdot.elements[3]);
+      	u.elements[1]=2*(-q.elements[2]*qdot.elements[0]+q.elements[3]*qdot.elements[1]+q.elements[0]*qdot.elements[2]-q.elements[1]*qdot.elements[3]);
+      	u.elements[2]=2*(q.elements[1]*qdot.elements[0]-q.elements[0]*qdot.elements[1]+q.elements[3]*qdot.elements[2]-q.elements[2]*qdot.elements[3]);
+  
+}
+
+
diff --git a/lib/poems/eulerparameters.h b/lib/poems/eulerparameters.h
new file mode 100644
index 000000000..029ade4b7
--- /dev/null
+++ b/lib/poems/eulerparameters.h
@@ -0,0 +1,37 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: eulerparameters.h                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+#ifndef EULERPARAMETERS_H
+#define EULERPARAMETERS_H
+
+#include "colmatrix.h"
+#include "mat3x3.h"
+
+void EP_Derivatives(ColMatrix& q, ColMatrix& u, ColMatrix& qdot);
+
+void EP_Transformation(ColMatrix& q, Mat3x3& C);
+
+void EP_FromTransformation(ColMatrix& q, Mat3x3& C);
+
+void EP_Normalize(ColMatrix& q);
+
+void EPdotdot_udot(ColMatrix& Audot, ColMatrix& Aqdot, ColMatrix& Aq,ColMatrix& Aqddot);
+
+void qdot_to_u(ColMatrix& q, ColMatrix& u, ColMatrix& qdot);
+
+#endif
+
diff --git a/lib/poems/fastmatrixops.cpp b/lib/poems/fastmatrixops.cpp
new file mode 100644
index 000000000..b887c9193
--- /dev/null
+++ b/lib/poems/fastmatrixops.cpp
@@ -0,0 +1,1033 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: fastmatrixops.cpp                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include <iostream>
+#include "fastmatrixops.h"
+#include <cmath>
+
+using namespace std;
+
+//
+// Cross Product (friend of Vect3)
+//
+
+void FastCross(Vect3& a, Vect3& b, Vect3& c){
+  c.elements[0] = a.elements[1]*b.elements[2] - a.elements[2]*b.elements[1];
+  c.elements[1] = a.elements[2]*b.elements[0] - a.elements[0]*b.elements[2];
+  c.elements[2] = a.elements[0]*b.elements[1] - a.elements[1]*b.elements[0];
+}
+
+//
+//  Simple Rotation (friend of Vect3 and Mat3x3)
+//
+
+void FastSimpleRotation(Vect3& v, double q, Mat3x3& C){
+  // intermediate quantities
+  double cq = cos(q);
+  double sq = sin(q);
+  double one_m_cq = 1-cq;
+  double l12 = v.elements[0]*v.elements[1]*one_m_cq;
+  double l13 = v.elements[0]*v.elements[2]*one_m_cq;
+  double l23 = v.elements[1]*v.elements[2]*one_m_cq;
+
+  // the transformation
+  C.elements[0][0] = v.elements[0]*v.elements[0]*one_m_cq+cq;
+  C.elements[0][1] = l12-v.elements[2]*sq;
+  C.elements[0][2] = l13+v.elements[1]*sq;
+  C.elements[1][0] = l12+v.elements[2]*sq;
+  C.elements[1][1] = v.elements[1]*v.elements[1]*one_m_cq+cq;
+  C.elements[1][2] = l23-v.elements[0]*sq;
+  C.elements[2][0] = l13-v.elements[1]*sq;
+  C.elements[2][1] = l23+v.elements[0]*sq;
+  C.elements[2][2] = v.elements[2]*v.elements[2]*one_m_cq+cq;
+}
+
+//
+// Quaternion Functions
+//
+
+void FastQuaternions(ColMatrix& q, Mat3x3& C){
+  double* e = q.elements;
+
+  // normalize the quaternions
+  double length = e[0]*e[0] + e[1]*e[1] + e[2]*e[2] + e[3]*e[3];
+  length = sqrt(length);
+  e[0] = e[0]/length;
+  e[1] = e[1]/length;
+  e[2] = e[2]/length;
+  e[3] = e[3]/length;
+
+  // compute the transformation
+  C.elements[0][0] = e[0]*e[0] + e[1]*e[1] - e[2]*e[2] - e[3]*e[3];
+  C.elements[1][1] = e[0]*e[0] - e[1]*e[1] + e[2]*e[2] - e[3]*e[3];
+  C.elements[2][2] = e[0]*e[0] - e[1]*e[1] - e[2]*e[2] + e[3]*e[3];
+
+  C.elements[0][1] = 2 * (e[1]*e[2] - e[0]*e[3]);
+  C.elements[0][2] = 2 * (e[1]*e[3] + e[0]*e[2]);
+  C.elements[1][2] = 2 * (e[2]*e[3] - e[0]*e[1]);
+
+  C.elements[1][0] = 2 * (e[1]*e[2] + e[0]*e[3]);
+  C.elements[2][0] = 2 * (e[1]*e[3] - e[0]*e[2]);
+  C.elements[2][1] = 2 * (e[2]*e[3] + e[0]*e[1]);
+}
+
+void FastQuaternionDerivatives(ColMatrix& q, ColMatrix& omega, ColMatrix& qdot){
+  double* w = omega.elements;
+  double* e = q.elements;
+
+  qdot.elements[0] = 0.5 * (-w[0]*e[1] - w[1]*e[2] - w[2]*e[3]);
+  qdot.elements[1] = 0.5 * ( w[0]*e[0] + w[2]*e[2] - w[1]*e[3]);
+  qdot.elements[2] = 0.5 * ( w[1]*e[0] - w[2]*e[1] + w[0]*e[3]);
+  qdot.elements[3] = 0.5 * ( w[2]*e[0] + w[1]*e[1] - w[0]*e[2]);
+}
+
+void FastInvQuaternions(Mat3x3& C, ColMatrix& q){
+}
+
+//
+// Inverse
+//
+
+// friend of Matrix
+//void FastInverse(Matrix& A, Matrix& C){ // C = A^(-1)
+//  C.rows[0][0] = 1/A.rows[0][0];
+//}
+
+//
+// LDL^T Decomposition (from Golub and Van Loan)
+//
+
+// friend of Matrix
+void FastLDLT(Matrix& A, Matrix& C){ // C is the LD of the LDL^T decomposition of A (SPD)
+  double Lv;
+  int n = A.numrows;
+
+  for(int j=0;j<n;j++){
+    Lv = 0.0;
+    for(int i=0;i<j;i++){
+      C.rows[i][j] = C.rows[j][i]*C.rows[i][i];
+      Lv += C.rows[j][i]*C.rows[i][j];
+    }
+
+    C.rows[j][j] = A.rows[j][j] - Lv;
+    for(int i=j+1;i<n;i++){
+      Lv = 0.0;
+      for(int k=0;k<j;k++) Lv += C.rows[i][k]*C.rows[k][j];
+      C.rows[i][j] = (A.rows[i][j] - Lv)/C.rows[j][j];
+    }
+  }
+}
+
+
+// friend of Mat6x6
+void FastLDLT(Mat6x6& A, Mat6x6& C){ // C is the LD of the LDL^T decomposition of A (SPD)
+  double v[6];
+  double Lv;
+
+  for(int j=0;j<6;j++){
+    Lv = 0.0;
+    for(int i=0;i<j;i++){
+      v[i] = C.elements[j][i]*C.elements[i][i];
+      Lv += C.elements[j][i]*v[i];
+    }
+
+    v[j] = A.elements[j][j] - Lv;
+    C.elements[j][j] = v[j];
+    for(int i=j+1;i<6;i++){
+      Lv = 0.0;
+      for(int k=0;k<j;k++) Lv += C.elements[i][k]*v[k];
+      C.elements[i][j] = (A.elements[i][j] - Lv)/v[j];
+    }
+  }
+}
+
+// friend of Matrix
+void FastLDLTSubs(Matrix& LD, Matrix& B, Matrix& C){
+  int n = B.numrows;
+  int c = B.numcols;
+  double temp;
+
+  for(int k=0;k<c;k++){
+    for(int i=0;i<n;i++){
+      temp = 0.0;
+      for(int j=0;j<i;j++){
+        temp += C.rows[j][k] * LD.rows[i][j];
+      }
+      C.rows[i][k] = B.rows[i][k] - temp;
+    }
+    for(int i=n-1;i>-1;i--){
+      C.rows[i][k] = C.rows[i][k] / LD.rows[i][i];
+      temp = 0.0;
+      for(int j=n-1;j>i;j--){
+        temp += C.rows[j][k] * LD.rows[j][i];
+      }
+      C.rows[i][k] = C.rows[i][k] - temp;
+    }
+  }
+}
+
+// friend of Matrix
+void FastLDLTSubsLH(Matrix& B, Matrix& LD, Matrix& C){
+  int n = B.numcols;
+  int c = B.numrows;
+  double temp;
+
+  for(int k=0;k<c;k++){
+    for(int i=0;i<n;i++){
+      temp = 0.0;
+      for(int j=0;j<i;j++){
+        temp += C.rows[k][j] * LD.rows[i][j];
+      }
+      C.rows[k][i] = B.rows[k][i] - temp;
+    }
+    for(int i=n-1;i>-1;i--){
+      C.rows[k][i] = C.rows[k][i] / LD.rows[i][i];
+      temp = 0.0;
+      for(int j=n-1;j>i;j--){
+        temp += C.rows[k][j] * LD.rows[j][i];
+      }
+      C.rows[k][i] = C.rows[k][i] - temp;
+    }
+  }
+}
+
+// friend of Mat6x6
+void FastLDLTSubs(Mat6x6& LD, Mat6x6& B, Mat6x6& C){
+  double temp;
+
+  for(int k=0;k<6;k++){
+    for(int i=0;i<6;i++){
+      temp = 0.0;
+      for(int j=0;j<i;j++){
+        temp += C.elements[j][k] * LD.elements[i][j];
+      }
+      C.elements[i][k] = B.elements[i][k] - temp;
+    }
+    for(int i=5;i>-1;i--){
+      C.elements[i][k] = C.elements[i][k] / LD.elements[i][i];
+      temp = 0.0;
+      for(int j=5;j>i;j--){
+        temp += C.elements[j][k] * LD.elements[j][i];
+      }
+      C.elements[i][k] = C.elements[i][k] - temp;
+    }
+  }
+}
+
+// friend of Mat6x6 & Vect6
+void FastLDLTSubs(Mat6x6& LD, Vect6& B, Vect6& C){
+  double temp;
+
+  for(int i=0;i<6;i++){
+    temp = 0.0;
+    for(int j=0;j<i;j++){
+      temp += C.elements[j] * LD.elements[i][j];
+    }
+    C.elements[i] = B.elements[i] - temp;
+  }
+  for(int i=5;i>-1;i--){
+    C.elements[i] = C.elements[i] / LD.elements[i][i];
+    temp = 0.0;
+    for(int j=5;j>i;j--){
+      temp += C.elements[j] * LD.elements[j][i];
+    }
+    C.elements[i] = C.elements[i] - temp;
+  }
+}
+
+// friend of Matrix
+void FastLU(Matrix& A, Matrix& LU, int *indx){ // LU is the LU decomposition of A
+  int i,imax=0,j,k;
+  int n = A.numrows;
+  double big, dum, sum, temp;
+  double vv[10000];
+
+  LU = A;
+  for (i=0;i<n;i++){
+    big=0.0;
+    for (j=0;j<n;j++){
+      temp=fabs(LU.rows[i][j]);
+      if (temp > big) big=temp;
+      }
+    vv[i]=1.0/big;
+  }
+  for (j=0;j<n;j++){
+    for (i=0;i<j;i++){
+      sum=LU.rows[i][j];
+      for (k=0;k<i;k++) sum -= LU.rows[i][k]*LU.rows[k][j];
+      LU.rows[i][j]=sum;
+    }
+    big=0.0;
+    for (i=j;i<n;i++){
+      sum=LU.rows[i][j];
+      for (k=0;k<j;k++)
+        sum -= LU.rows[i][k]*LU.rows[k][j];
+        LU.rows[i][j]=sum;
+        if ((dum=vv[i]*fabs(sum)) >= big) {
+        big=dum;
+        imax=i;
+      }
+    }
+    if (j != imax) {
+      for (k=0;k<n;k++) {
+        dum=LU.rows[imax][k];
+        LU.rows[imax][k]=LU.rows[j][k];
+        LU.rows[j][k]=dum;
+      }
+      vv[imax]=vv[j];
+    }
+    indx[j]=imax;
+    // if (LU.rows[j][j] == 0.0) LU.rows[j][j]=1.0e-20;
+    if (j != n-1) {
+      dum=1.0/(LU.rows[j][j]);
+      for (i=j+1;i<n;i++) LU.rows[i][j] *= dum;
+    }
+  }
+}
+
+// friend of Mat3x3
+void FastLU(Mat3x3& A, Mat3x3& LU, int *indx){ // LU is the LU decomposition of A
+  int i,imax=0,j,k;
+  double big, dum, sum, temp;
+  double vv[10000];
+
+  LU = A;
+  for (i=0;i<3;i++){
+    big=0.0;
+    for (j=0;j<3;j++){
+      temp=fabs(LU.BasicGet(i,j));
+      if (temp > big) big=temp;
+      }
+    vv[i]=1.0/big;
+  }
+  for (j=0;j<3;j++){
+    for (i=0;i<j;i++){
+      sum=LU.BasicGet(i,j);
+      for (k=0;k<i;k++) sum -= LU.BasicGet(i,k)*LU.BasicGet(k,j);
+      LU.BasicSet(i,j,sum);
+    }
+    big=0.0;
+    for (i=j;i<3;i++){
+      sum=LU.BasicGet(i,j);
+      for (k=0;k<j;k++)
+        sum -= LU.BasicGet(i,k)*LU.BasicGet(k,j);
+        LU.BasicSet(i,j,sum);
+        if ((dum=vv[i]*fabs(sum)) >= big) {
+        big=dum;
+        imax=i;
+      }
+    }
+    if (j != imax) {
+      for (k=0;k<3;k++) {
+        dum=LU.BasicGet(imax,k);
+        LU.BasicSet(imax,k,LU.BasicGet(j,k));
+        LU.BasicSet(j,k,dum);
+      }
+      vv[imax]=vv[j];
+    }
+    indx[j]=imax;
+    if (j != 3-1) {
+      dum=1.0/(LU.BasicGet(j,j));
+      for (i=j+1;i<3;i++) LU.BasicSet(i,j,LU.BasicGet(i,j)*dum);
+    }
+  }
+}
+
+// friend of Mat4x4
+void FastLU(Mat4x4& A, Mat4x4& LU, int *indx){ // LU is the LU decomposition of A
+  int i,imax=0,j,k;
+  double big, dum, sum, temp;
+  double vv[10000];
+
+  LU = A;
+  for (i=0;i<4;i++){
+    big=0.0;
+    for (j=0;j<4;j++){
+      temp=fabs(LU.BasicGet(i,j));
+      if (temp > big) big=temp;
+      }
+    vv[i]=1.0/big;
+  }
+  for (j=0;j<4;j++){
+    for (i=0;i<j;i++){
+      sum=LU.BasicGet(i,j);
+      for (k=0;k<i;k++) sum -= LU.BasicGet(i,k)*LU.BasicGet(k,j);
+      LU.BasicSet(i,j,sum);
+    }
+    big=0.0;
+    for (i=j;i<4;i++){
+      sum=LU.BasicGet(i,j);
+      for (k=0;k<j;k++)
+        sum -= LU.BasicGet(i,k)*LU.BasicGet(k,j);
+        LU.BasicSet(i,j,sum);
+        if ((dum=vv[i]*fabs(sum)) >= big) {
+        big=dum;
+        imax=i;
+      }
+    }
+    if (j != imax) {
+      for (k=0;k<4;k++) {
+        dum=LU.BasicGet(imax,k);
+        LU.BasicSet(imax,k,LU.BasicGet(j,k));
+        LU.BasicSet(j,k,dum);
+      }
+      vv[imax]=vv[j];
+    }
+    indx[j]=imax;
+    if (j != 4-1) {
+      dum=1.0/(LU.BasicGet(j,j));
+      for (i=j+1;i<4;i++) LU.BasicSet(i,j,LU.BasicGet(i,j)*dum);
+    }
+  }
+}
+
+// friend of Mat6x6
+void FastLU(Mat6x6& A, Mat6x6& LU, int *indx){ // LU is the LU decomposition of A
+  int i,imax=0,j,k;
+  double big, dum, sum, temp;
+  double vv[10000];
+
+  LU = A;
+  for (i=0;i<6;i++){
+    big=0.0;
+    for (j=0;j<6;j++){
+      temp=fabs(LU.BasicGet(i,j));
+      if (temp > big) big=temp;
+      }
+    vv[i]=1.0/big;
+  }
+  for (j=0;j<6;j++){
+    for (i=0;i<j;i++){
+      sum=LU.BasicGet(i,j);
+      for (k=0;k<i;k++) sum -= LU.BasicGet(i,k)*LU.BasicGet(k,j);
+      LU.BasicSet(i,j,sum);
+    }
+    big=0.0;
+    for (i=j;i<6;i++){
+      sum=LU.BasicGet(i,j);
+      for (k=0;k<j;k++)
+        sum -= LU.BasicGet(i,k)*LU.BasicGet(k,j);
+        LU.BasicSet(i,j,sum);
+        if ((dum=vv[i]*fabs(sum)) >= big) {
+        big=dum;
+        imax=i;
+      }
+    }
+    if (j != imax) {
+      for (k=0;k<6;k++) {
+        dum=LU.BasicGet(imax,k);
+        LU.BasicSet(imax,k,LU.BasicGet(j,k));
+        LU.BasicSet(j,k,dum);
+      }
+      vv[imax]=vv[j];
+    }
+    indx[j]=imax;
+    if (j != 6-1) {
+      dum=1.0/(LU.BasicGet(j,j));
+      for (i=j+1;i<6;i++) LU.BasicSet(i,j,LU.BasicGet(i,j)*dum);
+    }
+  }
+}
+
+// friend of Matrix
+void FastLUSubs(Matrix& LU, Matrix& B, Matrix& C, int *indx){ // Appropriate Forward and Back Substitution	
+  int i,ip,j,k;
+  int n = B.numrows;
+  int c = B.numcols;
+  double temp;
+  
+  C = B;
+  for (k=0;k<c;k++){
+	for (i=0;i<n;i++){
+		ip=indx[i];
+		temp=C.rows[ip][k];
+		C.rows[ip][k]=C.rows[i][k];
+		for (j=0;j<i;j++) temp -= LU.rows[i][j]*C.rows[j][k];
+		C.rows[i][k]=temp;
+	}
+	for (i=n-1;i>=0;i--){
+		temp=C.rows[i][k];
+		for (j=i+1;j<n;j++) temp -= LU.rows[i][j]*C.rows[j][k];
+		C.rows[i][k]=temp/LU.rows[i][i];
+	}
+  }
+}
+
+// friend of Matrix and Mat3x3
+void FastLUSubs(Mat3x3& LU, Matrix& B, Matrix& C, int *indx){ // Appropriate Forward and Back Substitution	
+  int i,ip,j,k;
+  int n = B.numrows;
+  int c = B.numcols;
+  double temp;
+  
+  C = B;
+  for (k=0;k<c;k++){
+	for (i=0;i<n;i++){
+		ip=indx[i];
+		temp=C.rows[ip][k];
+		C.rows[ip][k]=C.rows[i][k];
+		for (j=0;j<i;j++) temp -= LU.BasicGet(i,j)*C.rows[j][k];
+		C.rows[i][k]=temp;
+	}
+	for (i=n-1;i>=0;i--){
+		temp=C.rows[i][k];
+		for (j=i+1;j<n;j++) temp -= LU.BasicGet(i,j)*C.rows[j][k];
+		C.rows[i][k]=temp/LU.BasicGet(i,i);
+	}
+  }
+}
+
+// friend of Matrix and Mat4x4
+void FastLUSubs(Mat4x4& LU, Matrix& B, Matrix& C, int *indx){ // Appropriate Forward and Back Substitution
+  int i,ip,j,k;
+  int n = B.numrows;
+  int c = B.numcols;
+  double temp;
+  
+  C = B;
+  for (k=0;k<c;k++){
+	for (i=0;i<n;i++){
+		ip=indx[i];
+		temp=C.rows[ip][k];
+		C.rows[ip][k]=C.rows[i][k];
+		for (j=0;j<i;j++) temp -= LU.BasicGet(i,j)*C.rows[j][k];
+		C.rows[i][k]=temp;
+	}
+	for (i=n-1;i>=0;i--){
+		temp=C.rows[i][k];
+		for (j=i+1;j<n;j++) temp -= LU.BasicGet(i,j)*C.rows[j][k];
+		C.rows[i][k]=temp/LU.BasicGet(i,i);
+	}
+  }
+}
+
+// friend of Matrix and Mat6x6
+void FastLUSubs(Mat6x6& LU, Matrix& B, Matrix& C, int *indx){ // Appropriate Forward and Back Substitution	
+  int i,ip,j,k;
+  int n = B.numrows;
+  int c = B.numcols;
+  double temp;
+  
+  C = B;
+  for (k=0;k<c;k++){
+	for (i=0;i<n;i++){
+		ip=indx[i];
+		temp=C.rows[ip][k];
+		C.rows[ip][k]=C.rows[i][k];
+		for (j=0;j<i;j++) temp -= LU.BasicGet(i,j)*C.rows[j][k];
+		C.rows[i][k]=temp;
+	}
+	for (i=n-1;i>=0;i--){
+		temp=C.rows[i][k];
+		for (j=i+1;j<n;j++) temp -= LU.BasicGet(i,j)*C.rows[j][k];
+		C.rows[i][k]=temp/LU.BasicGet(i,i);
+	}
+  }
+}
+
+
+// The following LUSubsLH routine is incomplete at the moment.
+// friend of Matrix
+void FastLUSubsLH(Matrix& LU, Matrix& B, Matrix& C, int *indx){ // Appropriate Forward and Back Substitution	
+  int i,ip,j,k;
+  int n = B.numcols;
+  int c = B.numrows;
+  double temp;
+  Matrix C_temp;
+  
+  C_temp = B;
+  for (k=0;k<c;k++){
+	for (i=0;i<n;i++){
+		ip=indx[k];
+	    temp=C_temp.rows[ip][i];
+		C_temp.rows[ip][i]=C_temp.rows[k][i];
+		for (j=0;j<i;j++) temp -= LU.rows[i][j]*C_temp.rows[k][j];
+		C_temp.rows[k][i]=temp;
+	}
+	for (i=n-1;i>=0;i--){
+		temp=C_temp.rows[k][i];
+		for (j=i+1;j<n;j++) temp -= LU.rows[i][j]*C_temp.rows[k][j];
+		C_temp.rows[k][i]=temp/LU.rows[i][i];
+	}
+  }
+  C = C_temp;
+}
+
+
+
+//
+// Triple sum
+//
+
+void FastTripleSum(Vect3& a, Vect3& b, Vect3& c, Vect3& d){ // d = a+b+c
+  d.elements[0] = a.elements[0]+b.elements[0]+c.elements[0];
+  d.elements[1] = a.elements[1]+b.elements[1]+c.elements[1];
+  d.elements[2] = a.elements[2]+b.elements[2]+c.elements[2];
+}
+
+void FastTripleSumPPM(Vect3& a, Vect3& b, Vect3& c, Vect3& d){ // d = a+b-c
+  d.elements[0] = a.elements[0]+b.elements[0]-c.elements[0];
+  d.elements[1] = a.elements[1]+b.elements[1]-c.elements[1];
+  d.elements[2] = a.elements[2]+b.elements[2]-c.elements[2];
+}
+
+//
+// Multiplications
+//
+
+// friend of matrix
+void FastMult(Matrix& A, Matrix& B, Matrix& C){  // C = A*B
+  // assumes dimensions are already correct!
+  int r = A.numrows;
+  int ca = A.numcols;
+  int cb = B.numcols;
+
+  int i,j,k;
+  for(i=0;i<r;i++)
+    for(j=0;j<cb;j++){
+      C.rows[i][j] = 0.0;
+      for(k=0;k<ca;k++)
+        C.rows[i][j] += A.rows[i][k] * B.rows[k][j];
+    }
+}
+
+// friend of matrix
+void FastTMult(Matrix& A, Matrix& B, Matrix& C){  // C = A*B
+  // assumes dimensions are already correct!
+  int r = A.numcols;
+  int ca = A.numrows;
+  int cb = B.numcols;
+
+  int i,j,k;
+  for(i=0;i<r;i++)
+    for(j=0;j<cb;j++){
+      C.rows[i][j] = A.rows[0][i] * B.rows[0][j];
+      for(k=1;k<ca;k++)
+        C.rows[i][j] += A.rows[k][i] * B.rows[k][j];
+    }
+}
+
+// friend of Mat3x3 & Vect3
+void FastMult(Mat3x3& A, Vect3& B, Vect3& C){  // C = A*B
+  C.elements[0] = A.elements[0][0]*B.elements[0] + A.elements[0][1]*B.elements[1] + A.elements[0][2]*B.elements[2];
+  C.elements[1] = A.elements[1][0]*B.elements[0] + A.elements[1][1]*B.elements[1] + A.elements[1][2]*B.elements[2];
+  C.elements[2] = A.elements[2][0]*B.elements[0] + A.elements[2][1]*B.elements[1] + A.elements[2][2]*B.elements[2];
+}
+
+// friend of Mat3x3, ColMatrix, & Vect3
+void FastMult(Mat3x3& A, ColMatrix& B, Vect3& C){  // C = A*B
+  C.elements[0] = A.elements[0][0]*B.elements[0] + A.elements[0][1]*B.elements[1] + A.elements[0][2]*B.elements[2];
+  C.elements[1] = A.elements[1][0]*B.elements[0] + A.elements[1][1]*B.elements[1] + A.elements[1][2]*B.elements[2];
+  C.elements[2] = A.elements[2][0]*B.elements[0] + A.elements[2][1]*B.elements[1] + A.elements[2][2]*B.elements[2];
+}
+
+
+// friend of Mat3x3, ColMatrix, & Vect3
+void FastMult(Mat3x3& A, Vect3& B, ColMatrix& C){  // C = A*B
+  C.elements[0] = A.elements[0][0]*B.elements[0] + A.elements[0][1]*B.elements[1] + A.elements[0][2]*B.elements[2];
+  C.elements[1] = A.elements[1][0]*B.elements[0] + A.elements[1][1]*B.elements[1] + A.elements[1][2]*B.elements[2];
+  C.elements[2] = A.elements[2][0]*B.elements[0] + A.elements[2][1]*B.elements[1] + A.elements[2][2]*B.elements[2];
+}
+
+// friend of Mat3x3 & Vect3
+void FastTMult(Mat3x3& A, Vect3& B, Vect3& C){  // C = A^T*B
+  C.elements[0] = A.elements[0][0]*B.elements[0] + A.elements[1][0]*B.elements[1] + A.elements[2][0]*B.elements[2];
+  C.elements[1] = A.elements[0][1]*B.elements[0] + A.elements[1][1]*B.elements[1] + A.elements[2][1]*B.elements[2];
+  C.elements[2] = A.elements[0][2]*B.elements[0] + A.elements[1][2]*B.elements[1] + A.elements[2][2]*B.elements[2];
+}
+
+// friend of Mat3x3 & Vect3
+void FastNegMult(Mat3x3& A, Vect3& B, Vect3& C){  // C = -A*B
+  C.elements[0] = -A.elements[0][0]*B.elements[0] - A.elements[0][1]*B.elements[1] - A.elements[0][2]*B.elements[2];
+  C.elements[1] = -A.elements[1][0]*B.elements[0] - A.elements[1][1]*B.elements[1] - A.elements[1][2]*B.elements[2];
+  C.elements[2] = -A.elements[2][0]*B.elements[0] - A.elements[2][1]*B.elements[1] - A.elements[2][2]*B.elements[2];
+}
+
+// friend of Mat3x3 & Vect3
+void FastNegTMult(Mat3x3& A, Vect3& B, Vect3& C){  // C = -A^T*B
+  C.elements[0] = -A.elements[0][0]*B.elements[0] - A.elements[1][0]*B.elements[1] - A.elements[2][0]*B.elements[2];
+  C.elements[1] = -A.elements[0][1]*B.elements[0] - A.elements[1][1]*B.elements[1] - A.elements[2][1]*B.elements[2];
+  C.elements[2] = -A.elements[0][2]*B.elements[0] - A.elements[1][2]*B.elements[1] - A.elements[2][2]*B.elements[2];
+}
+
+// friend of Vect3
+void FastMult(double a, Vect3& B, Vect3& C){  // C = a*B
+  C.elements[0] = a*B.elements[0];
+  C.elements[1] = a*B.elements[1];
+  C.elements[2] = a*B.elements[2];
+}
+
+// friend of Mat4x4 & Vect4
+void FastMult(Mat4x4& A, Vect4& B, Vect4& C){  // C = A*B
+  C.elements[0] = A.elements[0][0]*B.elements[0] + A.elements[0][1]*B.elements[1] + A.elements[0][2]*B.elements[2] + A.elements[0][3]*B.elements[3];
+  C.elements[1] = A.elements[1][0]*B.elements[0] + A.elements[1][1]*B.elements[1] + A.elements[1][2]*B.elements[2] + A.elements[1][3]*B.elements[3];
+  C.elements[2] = A.elements[2][0]*B.elements[0] + A.elements[2][1]*B.elements[1] + A.elements[2][2]*B.elements[2] + A.elements[2][3]*B.elements[3];
+  C.elements[3] = A.elements[3][0]*B.elements[0] + A.elements[3][1]*B.elements[1] + A.elements[3][2]*B.elements[2] + A.elements[3][3]*B.elements[3];
+}
+
+// friend of Mat4x4 & Vect4
+void FastTMult(Mat4x4& A, Vect4& B, Vect4& C){  // C = A^T*B
+  C.elements[0] = A.elements[0][0]*B.elements[0] + A.elements[1][0]*B.elements[1] + A.elements[2][0]*B.elements[2] + A.elements[3][0]*B.elements[3];
+  C.elements[1] = A.elements[0][1]*B.elements[0] + A.elements[1][1]*B.elements[1] + A.elements[2][1]*B.elements[2] + A.elements[3][1]*B.elements[3];
+  C.elements[2] = A.elements[0][2]*B.elements[0] + A.elements[1][2]*B.elements[1] + A.elements[2][2]*B.elements[2] + A.elements[3][2]*B.elements[3];
+  C.elements[3] = A.elements[0][3]*B.elements[0] + A.elements[1][3]*B.elements[1] + A.elements[2][3]*B.elements[2] + A.elements[3][3]*B.elements[3];
+}
+
+// friend of Mat4x4 & Vect4
+void FastNegMult(Mat4x4& A, Vect4& B, Vect4& C){  // C = -A*B
+  C.elements[0] = -A.elements[0][0]*B.elements[0] - A.elements[0][1]*B.elements[1] - A.elements[0][2]*B.elements[2] - A.elements[0][3]*B.elements[3];
+  C.elements[1] = -A.elements[1][0]*B.elements[0] - A.elements[1][1]*B.elements[1] - A.elements[1][2]*B.elements[2] - A.elements[1][3]*B.elements[3];
+  C.elements[2] = -A.elements[2][0]*B.elements[0] - A.elements[2][1]*B.elements[1] - A.elements[2][2]*B.elements[2] - A.elements[2][3]*B.elements[3];
+  C.elements[3] = -A.elements[3][0]*B.elements[0] - A.elements[3][1]*B.elements[1] - A.elements[3][2]*B.elements[2] - A.elements[3][3]*B.elements[3];
+}
+
+// friend of Mat4x4 & Vect4
+void FastNegTMult(Mat4x4& A, Vect4& B, Vect4& C){  // C = -A^T*B
+  C.elements[0] = -A.elements[0][0]*B.elements[0] - A.elements[1][0]*B.elements[1] - A.elements[2][0]*B.elements[2] - A.elements[3][0]*B.elements[3];
+  C.elements[1] = -A.elements[0][1]*B.elements[0] - A.elements[1][1]*B.elements[1] - A.elements[2][1]*B.elements[2] - A.elements[3][1]*B.elements[3];
+  C.elements[2] = -A.elements[0][2]*B.elements[0] - A.elements[1][2]*B.elements[1] - A.elements[2][2]*B.elements[2] - A.elements[3][2]*B.elements[3];
+  C.elements[3] = -A.elements[0][3]*B.elements[0] - A.elements[1][3]*B.elements[1] - A.elements[2][3]*B.elements[2] - A.elements[3][3]*B.elements[3];
+}
+
+// friend of Vect4
+void FastMult(double a, Vect4& B, Vect4& C){  // C = a*B
+  C.elements[0] = a*B.elements[0];
+  C.elements[1] = a*B.elements[1];
+  C.elements[2] = a*B.elements[2];
+  C.elements[3] = a*B.elements[3];
+}
+
+// friend of Matrix & Mat6x6
+void FastMultT(Matrix& A, Matrix& B, Mat6x6& C){  // C = A*B^T
+  int i,j,k,n;
+  n = A.numcols;
+
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++){
+      C.elements[i][j] = 0.0;
+      for(k=0;k<n;k++)
+        C.elements[i][j] += A.rows[i][k] * B.rows[j][k];
+    }
+}
+
+// friend Matrix, Vect6, ColMatrix
+void FastMult(Matrix& A, ColMatrix& B, Vect6& C){
+  int ca = A.numcols;
+
+  int i,k;
+  for(i=0;i<6;i++){
+    C.elements[i] = 0.0;
+    for(k=0;k<ca;k++)
+      C.elements[i] += A.rows[i][k] * B.elements[k];
+  }
+}
+
+// friend of Matrix & Mat6x6
+void FastMult(Mat6x6& A, Matrix& B, Matrix& C){  // C = A*B
+  // assumes dimensions are already correct!
+  int cb = B.numcols;
+
+  int i,j,k;
+  for(i=0;i<6;i++)
+    for(j=0;j<cb;j++){
+      C.rows[i][j] = 0.0;
+      for(k=0;k<6;k++)
+        C.rows[i][j] += A.elements[i][k] * B.rows[k][j];
+    }
+}
+
+// friend Matrix, Vect6, ColMatrix
+void FastTMult(Matrix& A, Vect6& B, ColMatrix& C){  // C = A^T*B
+  int n = C.numrows;
+  int i,k;
+  for(i=0;i<n;i++){
+    C.elements[i] = 0.0;
+    for(k=0;k<6;k++)
+      C.elements[i] += A.rows[k][i] * B.elements[k];
+  }
+}
+
+// friend of Mat3x3
+void FastMult(Mat3x3& A, Mat3x3& B, Mat3x3& C){  // C = A*B
+  C.elements[0][0] = A.elements[0][0]*B.elements[0][0] + A.elements[0][1]*B.elements[1][0] + A.elements[0][2]*B.elements[2][0];
+  C.elements[0][1] = A.elements[0][0]*B.elements[0][1] + A.elements[0][1]*B.elements[1][1] + A.elements[0][2]*B.elements[2][1];
+  C.elements[0][2] = A.elements[0][0]*B.elements[0][2] + A.elements[0][1]*B.elements[1][2] + A.elements[0][2]*B.elements[2][2];
+
+  C.elements[1][0] = A.elements[1][0]*B.elements[0][0] + A.elements[1][1]*B.elements[1][0] + A.elements[1][2]*B.elements[2][0];
+  C.elements[1][1] = A.elements[1][0]*B.elements[0][1] + A.elements[1][1]*B.elements[1][1] + A.elements[1][2]*B.elements[2][1];
+  C.elements[1][2] = A.elements[1][0]*B.elements[0][2] + A.elements[1][1]*B.elements[1][2] + A.elements[1][2]*B.elements[2][2];
+
+  C.elements[2][0] = A.elements[2][0]*B.elements[0][0] + A.elements[2][1]*B.elements[1][0] + A.elements[2][2]*B.elements[2][0];
+  C.elements[2][1] = A.elements[2][0]*B.elements[0][1] + A.elements[2][1]*B.elements[1][1] + A.elements[2][2]*B.elements[2][1];
+  C.elements[2][2] = A.elements[2][0]*B.elements[0][2] + A.elements[2][1]*B.elements[1][2] + A.elements[2][2]*B.elements[2][2];
+}
+
+// friend of Mat3x3
+void FastMultT(Mat3x3& A, Mat3x3& B, Mat3x3& C){  // C = A*B^T
+  C.elements[0][0] = A.elements[0][0]*B.elements[0][0] + A.elements[0][1]*B.elements[0][1] + A.elements[0][2]*B.elements[0][2];
+  C.elements[0][1] = A.elements[0][0]*B.elements[1][0] + A.elements[0][1]*B.elements[1][1] + A.elements[0][2]*B.elements[1][2];
+  C.elements[0][2] = A.elements[0][0]*B.elements[2][0] + A.elements[0][1]*B.elements[2][1] + A.elements[0][2]*B.elements[2][2];
+
+  C.elements[1][0] = A.elements[1][0]*B.elements[0][0] + A.elements[1][1]*B.elements[0][1] + A.elements[1][2]*B.elements[0][2];
+  C.elements[1][1] = A.elements[1][0]*B.elements[1][0] + A.elements[1][1]*B.elements[1][1] + A.elements[1][2]*B.elements[1][2];
+  C.elements[1][2] = A.elements[1][0]*B.elements[2][0] + A.elements[1][1]*B.elements[2][1] + A.elements[1][2]*B.elements[2][2];
+
+  C.elements[2][0] = A.elements[2][0]*B.elements[0][0] + A.elements[2][1]*B.elements[0][1] + A.elements[2][2]*B.elements[0][2];
+  C.elements[2][1] = A.elements[2][0]*B.elements[1][0] + A.elements[2][1]*B.elements[1][1] + A.elements[2][2]*B.elements[1][2];
+  C.elements[2][2] = A.elements[2][0]*B.elements[2][0] + A.elements[2][1]*B.elements[2][1] + A.elements[2][2]*B.elements[2][2];
+}
+
+// friend of Mat4x4
+void FastMult(Mat4x4& A, Mat4x4& B, Mat4x4& C){  // C = A*B
+  C.elements[0][0] = A.elements[0][0]*B.elements[0][0] + A.elements[0][1]*B.elements[1][0] + A.elements[0][2]*B.elements[2][0] + A.elements[0][3]*B.elements[3][0];
+  C.elements[0][1] = A.elements[0][0]*B.elements[0][1] + A.elements[0][1]*B.elements[1][1] + A.elements[0][2]*B.elements[2][1] + A.elements[0][3]*B.elements[3][1];
+  C.elements[0][2] = A.elements[0][0]*B.elements[0][2] + A.elements[0][1]*B.elements[1][2] + A.elements[0][2]*B.elements[2][2] + A.elements[0][3]*B.elements[3][2];
+  C.elements[0][3] = A.elements[0][0]*B.elements[0][3] + A.elements[0][1]*B.elements[1][3] + A.elements[0][2]*B.elements[2][3] + A.elements[0][3]*B.elements[3][3];
+
+  C.elements[1][0] = A.elements[1][0]*B.elements[0][0] + A.elements[1][1]*B.elements[1][0] + A.elements[1][2]*B.elements[2][0] + A.elements[1][3]*B.elements[3][0];
+  C.elements[1][1] = A.elements[1][0]*B.elements[0][1] + A.elements[1][1]*B.elements[1][1] + A.elements[1][2]*B.elements[2][1] + A.elements[1][3]*B.elements[3][1];
+  C.elements[1][2] = A.elements[1][0]*B.elements[0][2] + A.elements[1][1]*B.elements[1][2] + A.elements[1][2]*B.elements[2][2] + A.elements[1][3]*B.elements[3][2];
+  C.elements[1][3] = A.elements[1][0]*B.elements[0][3] + A.elements[1][1]*B.elements[1][3] + A.elements[1][2]*B.elements[2][3] + A.elements[1][3]*B.elements[3][3];
+
+  C.elements[2][0] = A.elements[2][0]*B.elements[0][0] + A.elements[2][1]*B.elements[1][0] + A.elements[2][2]*B.elements[2][0] + A.elements[2][3]*B.elements[3][0];
+  C.elements[2][1] = A.elements[2][0]*B.elements[0][1] + A.elements[2][1]*B.elements[1][1] + A.elements[2][2]*B.elements[2][1] + A.elements[2][3]*B.elements[3][1];
+  C.elements[2][2] = A.elements[2][0]*B.elements[0][2] + A.elements[2][1]*B.elements[1][2] + A.elements[2][2]*B.elements[2][2] + A.elements[2][3]*B.elements[3][2];
+  C.elements[2][3] = A.elements[2][0]*B.elements[0][3] + A.elements[2][1]*B.elements[1][3] + A.elements[2][2]*B.elements[2][3] + A.elements[2][3]*B.elements[3][3];
+
+  C.elements[3][0] = A.elements[3][0]*B.elements[0][0] + A.elements[3][1]*B.elements[1][0] + A.elements[3][2]*B.elements[2][0] + A.elements[3][3]*B.elements[3][0];
+  C.elements[3][1] = A.elements[3][0]*B.elements[0][1] + A.elements[3][1]*B.elements[1][1] + A.elements[3][2]*B.elements[2][1] + A.elements[3][3]*B.elements[3][1];
+  C.elements[3][2] = A.elements[3][0]*B.elements[0][2] + A.elements[3][1]*B.elements[1][2] + A.elements[3][2]*B.elements[2][2] + A.elements[3][3]*B.elements[3][2];
+  C.elements[3][3] = A.elements[3][0]*B.elements[0][3] + A.elements[3][1]*B.elements[1][3] + A.elements[3][2]*B.elements[2][3] + A.elements[3][3]*B.elements[3][3];
+}
+
+// friend of Mat4x4
+void FastMultT(Mat4x4& A, Mat4x4& B, Mat4x4& C){  // C = A*B^T
+  C.elements[0][0] = A.elements[0][0]*B.elements[0][0] + A.elements[0][1]*B.elements[0][1] + A.elements[0][2]*B.elements[0][2] + A.elements[0][3]*B.elements[0][3];
+  C.elements[0][1] = A.elements[0][0]*B.elements[1][0] + A.elements[0][1]*B.elements[1][1] + A.elements[0][2]*B.elements[1][2] + A.elements[0][3]*B.elements[1][3];
+  C.elements[0][2] = A.elements[0][0]*B.elements[2][0] + A.elements[0][1]*B.elements[2][1] + A.elements[0][2]*B.elements[2][2] + A.elements[0][3]*B.elements[2][3];
+  C.elements[0][3] = A.elements[0][0]*B.elements[3][0] + A.elements[0][1]*B.elements[3][1] + A.elements[0][2]*B.elements[3][2] + A.elements[0][3]*B.elements[3][3];
+
+  C.elements[1][0] = A.elements[1][0]*B.elements[0][0] + A.elements[1][1]*B.elements[0][1] + A.elements[1][2]*B.elements[0][2] + A.elements[1][3]*B.elements[0][3];
+  C.elements[1][1] = A.elements[1][0]*B.elements[1][0] + A.elements[1][1]*B.elements[1][1] + A.elements[1][2]*B.elements[1][2] + A.elements[1][3]*B.elements[1][3];
+  C.elements[1][2] = A.elements[1][0]*B.elements[2][0] + A.elements[1][1]*B.elements[2][1] + A.elements[1][2]*B.elements[2][2] + A.elements[1][3]*B.elements[2][3];
+  C.elements[1][3] = A.elements[1][0]*B.elements[3][0] + A.elements[1][1]*B.elements[3][1] + A.elements[1][2]*B.elements[3][2] + A.elements[1][3]*B.elements[3][3];
+
+  C.elements[2][0] = A.elements[2][0]*B.elements[0][0] + A.elements[2][1]*B.elements[0][1] + A.elements[2][2]*B.elements[0][2] + A.elements[2][3]*B.elements[0][3];
+  C.elements[2][1] = A.elements[2][0]*B.elements[1][0] + A.elements[2][1]*B.elements[1][1] + A.elements[2][2]*B.elements[1][2] + A.elements[2][3]*B.elements[1][3];
+  C.elements[2][2] = A.elements[2][0]*B.elements[2][0] + A.elements[2][1]*B.elements[2][1] + A.elements[2][2]*B.elements[2][2] + A.elements[2][3]*B.elements[2][3];
+  C.elements[2][3] = A.elements[2][0]*B.elements[3][0] + A.elements[2][1]*B.elements[3][1] + A.elements[2][2]*B.elements[3][2] + A.elements[2][3]*B.elements[3][3];
+
+  C.elements[3][0] = A.elements[3][0]*B.elements[0][0] + A.elements[3][1]*B.elements[0][1] + A.elements[3][2]*B.elements[0][2] + A.elements[3][3]*B.elements[0][3];
+  C.elements[3][1] = A.elements[3][0]*B.elements[1][0] + A.elements[3][1]*B.elements[1][1] + A.elements[3][2]*B.elements[1][2] + A.elements[3][3]*B.elements[1][3];
+  C.elements[3][2] = A.elements[3][0]*B.elements[2][0] + A.elements[3][1]*B.elements[2][1] + A.elements[3][2]*B.elements[2][2] + A.elements[3][3]*B.elements[2][3];
+  C.elements[3][3] = A.elements[3][0]*B.elements[3][0] + A.elements[3][1]*B.elements[3][1] + A.elements[3][2]*B.elements[3][2] + A.elements[3][3]*B.elements[3][3];
+  C.elements[2][2] = A.elements[2][0]*B.elements[2][0] + A.elements[2][1]*B.elements[2][1] + A.elements[2][2]*B.elements[2][2];
+}
+
+// friend of Mat6x6
+void FastMult(Mat6x6& A, Mat6x6& B, Mat6x6& C){  // C = A*B
+  int i,j,k;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++){
+      C.elements[i][j] = 0.0;
+      for(k=0;k<6;k++)
+        C.elements[i][j] += A.elements[i][k]*B.elements[k][j];
+    }
+}
+
+// friend of Mat6x6
+void FastMultT(Mat6x6& A, Mat6x6& B, Mat6x6& C){  // C = A*B
+  int i,j,k;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++){
+      C.elements[i][j] = 0.0;
+      for(k=0;k<6;k++)
+        C.elements[i][j] += A.elements[i][k]*B.elements[j][k];
+    }
+}
+
+// friend of Mat6x6
+void FastTMult(Mat6x6& A, Mat6x6& B, Mat6x6& C){  // C = A^T*B
+  int i,j,k;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++){
+      C.elements[i][j] = 0.0;
+      for(k=0;k<6;k++)
+        C.elements[i][j] += A.elements[k][i]*B.elements[k][j];
+    }
+}
+
+// friend of Mat6x6 & Vect6
+void FastMult(Mat6x6& A, Vect6& B, Vect6& C){  // C = A*B
+  for(int i=0;i<6;i++)
+    C.elements[i] = A.elements[i][0]*B.elements[0] + A.elements[i][1]*B.elements[1] + A.elements[i][2]*B.elements[2] + A.elements[i][3]*B.elements[3] + A.elements[i][4]*B.elements[4] + A.elements[i][5]*B.elements[5];
+}
+
+// friend of Mat6x6 & Vect6
+void FastTMult(Mat6x6& A, Vect6& B, Vect6& C){  // C = A^T*B
+  for(int i=0;i<6;i++)
+    C.elements[i] = A.elements[0][i]*B.elements[0] + A.elements[1][i]*B.elements[1] + A.elements[2][i]*B.elements[2] + A.elements[3][i]*B.elements[3] + A.elements[4][i]*B.elements[4] + A.elements[5][i]*B.elements[5];
+}
+
+//
+// Additions
+//
+
+// friend of Vect3
+void FastAdd(Vect3& A, Vect3& B, Vect3& C){ // C = A+B
+  C.elements[0] = A.elements[0] + B.elements[0];
+  C.elements[1] = A.elements[1] + B.elements[1];
+  C.elements[2] = A.elements[2] + B.elements[2];
+}
+
+// friend of Vect4
+void FastAdd(Vect4& A, Vect4& B, Vect4& C){ // C = A+B
+  C.elements[0] = A.elements[0] + B.elements[0];
+  C.elements[1] = A.elements[1] + B.elements[1];
+  C.elements[2] = A.elements[2] + B.elements[2];
+  C.elements[3] = A.elements[3] + B.elements[3];
+}
+
+void FastAdd(Mat6x6& A, Mat6x6& B, Mat6x6& C){  // C = A+B
+  int i,j;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++)
+      C.elements[i][j] = A.elements[i][j] + B.elements[i][j];
+}
+
+// friend of Vect6
+void FastAdd(Vect6& A, Vect6& B, Vect6& C){ // C = A-B
+  C.elements[0] = A.elements[0] + B.elements[0];
+  C.elements[1] = A.elements[1] + B.elements[1];
+  C.elements[2] = A.elements[2] + B.elements[2];
+  C.elements[3] = A.elements[3] + B.elements[3];
+  C.elements[4] = A.elements[4] + B.elements[4];
+  C.elements[5] = A.elements[5] + B.elements[5];
+}
+
+//
+// Subtractions
+//
+
+// friend of Vect3
+void FastSubt(Vect3& A, Vect3& B, Vect3& C){ // C = A-B
+  C.elements[0] = A.elements[0] - B.elements[0];
+  C.elements[1] = A.elements[1] - B.elements[1];
+  C.elements[2] = A.elements[2] - B.elements[2];
+}
+
+// friend of Vect4
+void FastSubt(Vect4& A, Vect4& B, Vect4& C){ // C = A-B
+  C.elements[0] = A.elements[0] - B.elements[0];
+  C.elements[1] = A.elements[1] - B.elements[1];
+  C.elements[2] = A.elements[2] - B.elements[2];
+  C.elements[3] = A.elements[3] - B.elements[3];
+}
+
+void FastSubt(Mat6x6& A, Mat6x6& B, Mat6x6& C){  // C = A-B
+  int i,j;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++)
+      C.elements[i][j] = A.elements[i][j] - B.elements[i][j];
+}
+
+// friend of Vect6
+void FastSubt(Vect6& A, Vect6& B, Vect6& C){ // C = A-B
+  C.elements[0] = A.elements[0] - B.elements[0];
+  C.elements[1] = A.elements[1] - B.elements[1];
+  C.elements[2] = A.elements[2] - B.elements[2];
+  C.elements[3] = A.elements[3] - B.elements[3];
+  C.elements[4] = A.elements[4] - B.elements[4];
+  C.elements[5] = A.elements[5] - B.elements[5];
+}
+
+// friend of ColMatMap
+void FastAssign(ColMatMap& A, ColMatMap& C){
+  for(int i=0;i<C.numrows;i++)
+    *(C.elements[i]) = *(A.elements[i]);
+}
+
+// friend of ColMatrix
+void FastAssign(ColMatrix& A, ColMatrix& C){ //C = A
+  for(int i=0;i<C.numrows;i++)
+    C.elements[i] = A.elements[i];
+}
+
+// friend of Vect3
+void FastAssign(Vect3& A, Vect3& C){ //C = A
+    C.elements[0] = A.elements[0];
+    C.elements[1] = A.elements[1];
+    C.elements[2] = A.elements[2];
+}
+
+// friend of Vect3 & ColMatrix
+void FastAssign(ColMatrix& A, Vect3& C){ //C = A
+    C.elements[0] = A.elements[0];
+    C.elements[1] = A.elements[1];
+    C.elements[2] = A.elements[2];
+}
+
+// friend of Vect4
+void FastAssign(Vect4& A, Vect4& C){ //C = A
+    C.elements[0] = A.elements[0];
+    C.elements[1] = A.elements[1];
+    C.elements[2] = A.elements[2];
+    C.elements[3] = A.elements[3];
+}
+
+// friend of Mat3x3
+void FastAssignT(Mat3x3& A, Mat3x3& C){
+  C.elements[0][0] = A.elements[0][0];
+  C.elements[1][1] = A.elements[1][1];
+  C.elements[2][2] = A.elements[2][2];
+
+  C.elements[0][1] = A.elements[1][0];
+  C.elements[1][0] = A.elements[0][1];
+
+  C.elements[0][2] = A.elements[2][0];
+  C.elements[2][0] = A.elements[0][2];
+
+  C.elements[1][2] = A.elements[2][1];
+  C.elements[2][1] = A.elements[1][2];
+}
+
+// friend of Mat4x4
+void FastAssignT(Mat4x4& A, Mat4x4& C){
+  C.elements[0][0] = A.elements[0][0];
+  C.elements[1][1] = A.elements[1][1];
+  C.elements[2][2] = A.elements[2][2];
+  C.elements[3][3] = A.elements[3][3];
+
+  C.elements[0][1] = A.elements[1][0];
+  C.elements[1][0] = A.elements[0][1];
+
+  C.elements[0][2] = A.elements[2][0];
+  C.elements[2][0] = A.elements[0][2];
+
+  C.elements[0][3] = A.elements[3][0];
+  C.elements[3][0] = A.elements[0][3];
+
+  C.elements[1][2] = A.elements[2][1];
+  C.elements[2][1] = A.elements[1][2];
+
+  C.elements[1][3] = A.elements[3][1];
+  C.elements[3][1] = A.elements[1][3];
+
+  C.elements[2][3] = A.elements[3][2];
+  C.elements[3][2] = A.elements[2][3];
+}
+
diff --git a/lib/poems/fastmatrixops.h b/lib/poems/fastmatrixops.h
new file mode 100644
index 000000000..e7ccdbd0c
--- /dev/null
+++ b/lib/poems/fastmatrixops.h
@@ -0,0 +1,97 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: fastmatrixops.h                                         *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef FASTMATRIXOPS_H
+#define FASTMATRIXOPS_H
+#include "matrices.h"
+
+void FastCross(Vect3& a, Vect3& b, Vect3& c);
+void FastSimpleRotation(Vect3& v, double q, Mat3x3& C);
+void FastQuaternions(ColMatrix& q, Mat3x3& C);
+void FastQuaternionDerivatives(ColMatrix& q, ColMatrix& omega, ColMatrix& qdot);
+void FastLDLT(Matrix& A, Matrix& LD); // C is the LDL^T decomposition of A (SPD)
+void FastLDLT(Mat6x6& A, Mat6x6& LD); // C is the LDL^T decomposition of A (SPD)
+void FastLDLTSubs(Matrix& LD, Matrix& B, Matrix& C); // Appropriate Forward and Back Substitution
+void FastLDLTSubsLH(Matrix& B, Matrix& LD, Matrix& C); // Left handed Forward and Back Substitution
+void FastLDLTSubs(Mat6x6& LD, Mat6x6& B, Mat6x6& C); // Appropriate Forward and Back Substitution
+void FastLDLTSubs(Mat6x6& LD, Vect6& B, Vect6& C); // Appropriate Forward and Back Substitution
+void FastLU(Matrix& A, Matrix& LU, int *indx); // LU is the LU decomposition of A
+void FastLU(Mat3x3& A, Mat3x3& LU, int *indx); // LU is the LU decomposition of A
+void FastLU(Mat4x4& A, Mat4x4& LU, int *indx); // LU is the LU decomposition of A
+void FastLU(Mat6x6& A, Mat6x6& LU, int *indx); // LU is the LU decomposition of A
+void FastLUSubs(Matrix& LU, Matrix& B, Matrix& C, int *indx); // Appropriate Forward and Back Substitution
+void FastLUSubs(Mat3x3& LU, Matrix& B, Matrix& C, int *indx); // Appropriate Forward and Back Substitution
+void FastLUSubs(Mat4x4& LU, Matrix& B, Matrix& C, int *indx); // Appropriate Forward and Back Substitution
+void FastLUSubs(Mat6x6& LU, Matrix& B, Matrix& C, int *indx); // Appropriate Forward and Back Substitution
+// The following LUSubsLH routine is incomplete at the moment.
+void FastLUSubsLH(Matrix& B, Matrix& LU, Matrix& C, int *indx); // Appropriate Forward and Back Subsitution
+void FastTripleSum(Vect3& a, Vect3& b, Vect3& c, Vect3& d); // d = a+b+c
+void FastTripleSumPPM(Vect3& a, Vect3& b, Vect3& c, Vect3& d); // d = a+b-c
+
+void FastMult(Matrix& A, Matrix& B, Matrix& C);  // C = A*B
+void FastTMult(Matrix& A, Matrix& B, Matrix& C);  // C = A^T*B
+
+void FastMult(Mat3x3& A, Vect3& B, Vect3& C);  // C = A*B
+void FastMult(Mat3x3& A, ColMatrix& B, Vect3& C); // C = A*B
+void FastMult(Mat3x3& A, Vect3& B, ColMatrix& C); // C = A*B
+void FastMult(double a, Vect3& B, Vect3& C);  // C = a*B
+void FastNegMult(Mat3x3& A, Vect3& B, Vect3& C);  // C = A*B
+void FastNegTMult(Mat3x3& A, Vect3& B, Vect3& C);  // C = A*B
+
+void FastMult(Mat4x4& A, Vect4& B, Vect4& C);  // C = A*B
+void FastTMult(Mat4x4& A, Vect4& B, Vect4& C);  // C = A^T*B
+void FastMult(double a, Vect4& B, Vect4& C);  // C = a*B
+void FastNegMult(Mat4x4& A, Vect4& B, Vect4& C);  // C = A*B
+void FastNegTMult(Mat4x4& A, Vect4& B, Vect4& C);  // C = A*B
+
+void FastMultT(Matrix& A, Matrix& B, Mat6x6& C);  // C = A*B^T
+void FastMult(Mat6x6& A, Matrix& B, Matrix& C);   // C = A*B
+void FastTMult(Matrix& A, Vect6& B, ColMatrix& C);// C = A^T*B
+void FastMult(Matrix& A, ColMatrix& B, Vect6& C); // C = A*B
+
+void FastMult(Mat3x3& A, Mat3x3& B, Mat3x3& C);  // C = A*B
+void FastMultT(Mat3x3& A, Mat3x3& B, Mat3x3& C);  // C = A*B
+
+void FastMult(Mat4x4& A, Mat4x4& B, Mat4x4& C);  // C = A*B
+void FastMultT(Mat4x4& A, Mat4x4& B, Mat4x4& C);  // C = A*B
+
+void FastMult(Mat6x6& A, Mat6x6& B, Mat6x6& C);  // C = A*B
+void FastMultT(Mat6x6& A, Mat6x6& B, Mat6x6& C);  // C = A*B^T
+void FastTMult(Mat6x6& A, Mat6x6& B, Mat6x6& C);  // C = A^T*B
+
+void FastMult(Mat6x6& A, Vect6& B, Vect6& C);  // C = A*B
+void FastTMult(Mat6x6& A, Vect6& B, Vect6& C);  // C = A^T*B
+
+void FastAdd(Vect3& A, Vect3& B, Vect3& C);     // C = A+B
+void FastAdd(Vect4& A, Vect4& B, Vect3& C);     // C = A+B
+void FastAdd(Mat6x6& A, Mat6x6& B, Mat6x6& C);  // C = A+B
+void FastAdd(Vect6& A, Vect6& B, Vect6& C);     // C = A+B
+
+void FastSubt(Vect3& A, Vect3& B, Vect3& C);    // C = A-B
+void FastSubt(Vect4& A, Vect4& B, Vect4& C);    // C = A-B
+void FastSubt(Mat6x6& A, Mat6x6& B, Mat6x6& C); // C = A-B
+void FastSubt(Vect6& A, Vect6& B, Vect6& C);    // C = A-B
+
+void FastAssign(ColMatMap& A, ColMatMap& C);  // C = A
+void FastAssign(ColMatrix& A, ColMatrix& C);  // C = A
+void FastAssign(Vect3& A, Vect3& C);          // C = A
+void FastAssign(ColMatrix&A, Vect3& C);
+void FastAssign(Vect4& A, Vect4& C);          // C = A
+void FastAssignT(Mat3x3& A, Mat3x3& C);       // C = A^T
+void FastAssignT(Mat4x4& A, Mat4x4& C);       // C = A^T
+
+#endif
diff --git a/lib/poems/fixedpoint.cpp b/lib/poems/fixedpoint.cpp
new file mode 100644
index 000000000..860088239
--- /dev/null
+++ b/lib/poems/fixedpoint.cpp
@@ -0,0 +1,55 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: fixedpoint.cpp                                          *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "fixedpoint.h"
+#include <iostream>
+#include <iomanip>
+
+using namespace std;
+
+FixedPoint::FixedPoint(){
+}
+FixedPoint::~FixedPoint(){
+}
+
+FixedPoint::FixedPoint(double x, double y, double z){
+  position(1) = x;
+  position(2) = y;
+  position(3) = z;
+}
+
+FixedPoint::FixedPoint(Vect3& v){
+  position = v;
+}
+
+PointType FixedPoint::GetType(){
+  return FIXEDPOINT;
+}
+
+bool FixedPoint::ReadInPointData(std::istream& in){
+  in >> position;
+  return true;
+}
+
+void FixedPoint::WriteOutPointData(std::ostream& out){  
+  out << setprecision(16) << position;
+}
+
+Vect3 FixedPoint::GetPoint(){
+  return position;
+}
diff --git a/lib/poems/fixedpoint.h b/lib/poems/fixedpoint.h
new file mode 100644
index 000000000..b5ecb2390
--- /dev/null
+++ b/lib/poems/fixedpoint.h
@@ -0,0 +1,37 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: fixedpoint.h                                            *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef FIXEDPOINT_H
+#define FIXEDPOINT_H
+
+#include "point.h"
+#include "vect3.h"
+
+class FixedPoint : public Point  {
+public:
+  FixedPoint();
+  ~FixedPoint();
+  FixedPoint(double x, double y, double z);
+  FixedPoint(Vect3& v);
+  PointType GetType(); 
+  Vect3 GetPoint();
+  bool ReadInPointData(std::istream& in);
+  void WriteOutPointData(std::ostream& out);
+};
+
+#endif
diff --git a/lib/poems/freebodyjoint.cpp b/lib/poems/freebodyjoint.cpp
new file mode 100644
index 000000000..d00f0bdb9
--- /dev/null
+++ b/lib/poems/freebodyjoint.cpp
@@ -0,0 +1,156 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: freebodyjoint.cpp                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+#include "freebodyjoint.h"
+#include "point.h"
+#include "matrixfun.h"
+#include "body.h"
+#include "fastmatrixops.h"
+#include "norm.h"
+#include "eulerparameters.h"
+#include "matrices.h"
+#include <iomanip>
+   
+
+FreeBodyJoint::FreeBodyJoint(){
+  DimQandU(7,6);  
+}
+
+FreeBodyJoint::~FreeBodyJoint(){
+}
+
+JointType FreeBodyJoint::GetType(){
+  return FREEBODYJOINT;
+}
+
+bool FreeBodyJoint::ReadInJointData(std::istream& in){
+  return true;
+}
+
+void FreeBodyJoint::WriteOutJointData(std::ostream& out){
+}
+
+void FreeBodyJoint::ComputeLocalTransform(){
+  Mat3x3 ko_C_k;  
+  EP_Transformation(q, ko_C_k);   
+  FastMult(pk_C_ko,ko_C_k,pk_C_k);  
+}
+
+Matrix FreeBodyJoint::GetForward_sP(){
+  Mat6x6 sP;
+  //sP.Identity();      
+  
+  sP.Zeros();  
+  Mat3x3 temp0=T(pk_C_k);
+  for(int i=1;i<4;i++){
+	  sP(i,i)=1.0;
+	  for(int j=1;j<4;j++){
+		  sP(3+i,3+j)=temp0(i,j);
+		  }
+	  } 	  	  
+  return sP;    
+}
+
+Matrix FreeBodyJoint::GetBackward_sP(){
+  Mat6x6 sP;
+  sP.Identity();        
+  sP =-1.0*sP;
+  cout<<"Did I come here in "<<endl;
+  return sP;    
+}
+
+
+void FreeBodyJoint::UpdateForward_sP( Matrix& sP){
+  // do nothing
+}
+  
+void FreeBodyJoint::UpdateBackward_sP( Matrix& sP){
+  // do nothing
+}  
+  
+void FreeBodyJoint::ForwardKinematics(){
+ //cout<<"Check in freebody "<<q<<" "<<qdot<<endl;
+  EP_Normalize(q);
+
+  // COMMENT STEP1: CALCULATE ORIENTATIONS
+  ComputeForwardTransforms();  
+  
+    
+  //COMMENT STEP2: CALCULATE POSITION VECTORS
+  Vect3 result1, result2, result3, result4; 
+  
+  result1.BasicSet(0,q.BasicGet(4));
+  result1.BasicSet(1,q.BasicGet(5));
+  result1.BasicSet(2,q.BasicGet(6));
+  
+  FastAssign(result1,r12);    
+  FastNegMult(k_C_pk,r12,r21);
+  
+  FastAssign(r12,body2->r);  
+    
+  //COMMENT STEP3: CALCULATE QDOT  
+  qdot_to_u(q, u, qdot);
+  
+  
+  Vect3 WN;
+  WN.BasicSet(0,u.BasicGet(0));
+  WN.BasicSet(1,u.BasicGet(1));
+  WN.BasicSet(2,u.BasicGet(2));
+    
+  Vect3 VN; 
+  VN.BasicSet(0,u.BasicGet(3));
+  VN.BasicSet(1,u.BasicGet(4));
+  VN.BasicSet(2,u.BasicGet(5));  
+    
+  FastAssign(WN,body2->omega_k);  
+ 
+  Vect3 pk_w_k;
+  FastMult(body2->n_C_k,WN,pk_w_k);      
+  FastAssign(pk_w_k,body2->omega);
+  
+
+  
+  //COMMENT STEP5: CALCULATE VELOCITES        
+  FastAssign(VN,body2->v);    
+  FastTMult(body2->n_C_k,body2->v,body2->v_k);        
+  
+  
+  //CALCULATE KE          
+ 
+  Matrix tempke;
+  tempke = T(body2->v)*(body2->v);    
+  double ke = 0.0;
+  ke = body2->mass*tempke(1,1);  
+  FastMult(body2->inertia,body2->omega_k,result1);
+  tempke= T(body2->omega_k)*result1;  
+  ke = 0.5*ke + 0.5*tempke(1,1);
+  body2->KE=ke;
+ 
+  
+  //COMMENT STEP6: CALCULATE STATE EXPLICIT ANGULAR ACCELERATIONS
+  body2->alpha_t.Zeros();
+    
+    
+  //COMMENT STEP7: CALCULATE STATE EXPLICIT ACCELERATIONS
+  body2->a_t.Zeros();   
+  
+  }
+
+void FreeBodyJoint::BackwardKinematics(){
+cout<<"Did I come here "<<endl;
+         
+}
diff --git a/lib/poems/freebodyjoint.h b/lib/poems/freebodyjoint.h
new file mode 100644
index 000000000..27cacf7dc
--- /dev/null
+++ b/lib/poems/freebodyjoint.h
@@ -0,0 +1,41 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: freebodyjoint.cpp                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef FREEBODYJOINT_H
+#define FREEBODYJOINT_H
+
+#include "joint.h"
+
+
+class FreeBodyJoint : public Joint{
+public: 
+  FreeBodyJoint();
+  ~FreeBodyJoint();
+  
+  JointType GetType();
+  bool ReadInJointData(std::istream& in);
+  void WriteOutJointData(std::ostream& out);
+  void ComputeLocalTransform();
+  Matrix GetForward_sP();
+  Matrix GetBackward_sP();
+  void UpdateForward_sP( Matrix& sP);
+  void UpdateBackward_sP( Matrix& sP);
+  void ForwardKinematics();
+  void BackwardKinematics();
+};
+
+#endif
diff --git a/lib/poems/inertialframe.cpp b/lib/poems/inertialframe.cpp
new file mode 100644
index 000000000..6c97b2f58
--- /dev/null
+++ b/lib/poems/inertialframe.cpp
@@ -0,0 +1,58 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: inertialframe.cpp                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "inertialframe.h"
+#include "fixedpoint.h"
+
+using namespace std;
+
+InertialFrame::InertialFrame(){
+  gravity.Zeros();
+  n_C_k.Identity();
+
+  r.Zeros();
+  v.Zeros();
+  v_k.Zeros();
+  a.Zeros();
+  omega.Zeros();
+  omega_k.Zeros();
+  alpha.Zeros();
+  alpha_t.Zeros();
+}
+InertialFrame::~InertialFrame(){
+}
+
+BodyType InertialFrame::GetType(){
+  return INERTIALFRAME;
+}
+
+Vect3 InertialFrame::GetGravity(){
+  return gravity;
+}
+
+void InertialFrame::SetGravity(Vect3& g){
+  gravity = g;
+}
+
+bool InertialFrame::ReadInBodyData(istream& in){
+  in >> gravity;
+  return true;
+}
+
+void InertialFrame::WriteOutBodyData(ostream& out){
+  out << gravity;
+}
diff --git a/lib/poems/inertialframe.h b/lib/poems/inertialframe.h
new file mode 100644
index 000000000..08d0279a1
--- /dev/null
+++ b/lib/poems/inertialframe.h
@@ -0,0 +1,37 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: inertialframe.h                                         *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef INERTIALFRAME_H
+#define INERTIALFRAME_H
+
+#include "body.h"
+
+
+class InertialFrame : public Body  {
+  Vect3 gravity;
+public:
+  InertialFrame();
+  ~InertialFrame();
+  BodyType GetType();
+  Vect3 GetGravity();
+  void SetGravity(Vect3& g);
+  bool ReadInBodyData(std::istream& in);
+  void WriteOutBodyData(std::ostream& out);
+};
+
+#endif
diff --git a/lib/poems/joint.cpp b/lib/poems/joint.cpp
new file mode 100644
index 000000000..3bdd7b5fc
--- /dev/null
+++ b/lib/poems/joint.cpp
@@ -0,0 +1,248 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: joint.cpp                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "joints.h"
+#include "body.h"
+#include "point.h"
+#include <string>
+#include "matrixfun.h"
+#include "fastmatrixops.h"
+#include <iomanip>
+
+using namespace std;
+
+Joint::Joint(){
+  body1 = body2 = 0;
+  point1 = point2 = 0;
+  pk_C_ko.Identity();
+  pk_C_k.Identity();
+}
+
+Joint::~Joint(){
+}
+
+void Joint::SetBodies(Body* b1, Body* b2){
+  body1 = b1;
+  body2 = b2;
+}
+
+void Joint::SetPoints(Point* p1, Point* p2){
+  point1 = p1;
+  point2 = p2;
+}
+
+int Joint::GetBodyID1(){
+  return body1->GetID();
+}
+
+int Joint::GetBodyID2(){
+  return body2->GetID();
+}
+
+int Joint::GetPointID1(){
+  return point1->GetID();
+}
+
+int Joint::GetPointID2(){
+  return point2->GetID();
+}
+
+bool Joint::ReadIn(std::istream& in){
+  in >>setprecision(20)>> qo >> setprecision(20)>>qdoto >> setprecision(20)>>pk_C_ko; 
+  q = qo;
+  qdot = qdoto;
+  EP_Normalize(q);
+  
+  return ReadInJointData(in);
+}
+
+void Joint::ResetQdot(){
+  //EP_Derivatives(q,u,qdot);  
+  qdot_to_u(q,u,qdot);
+}
+
+void Joint::ResetQ(){
+  EP_Normalize(q); 
+}
+
+void Joint::SetInitialState(ColMatrix& a, ColMatrix& adot){
+  if( (qo.GetNumRows() != a.GetNumRows()) || (qdoto.GetNumRows() != adot.GetNumRows()) ){
+	  cout<<qo.GetNumRows()<<"	"<<a.GetNumRows()<<" "<<qdoto.GetNumRows()<<" "<<adot.GetNumRows()<<endl;	  
+    cerr << "ERROR::Illegal matrix size for initial condition" << endl;
+    exit(1);
+  }
+  qo = a;
+  qdoto = adot;
+  EP_Normalize(qo);
+  q=qo;           //////////////////////////Check this ...added May 14 2005
+  qdot=qdoto;     //////////////////////////Check this ...added May 14 2005  
+}
+
+void Joint::SetZeroOrientation(VirtualMatrix& C){
+  pk_C_ko = C;  
+}
+
+
+void Joint::WriteOut(std::ostream& out){  
+  out << GetType() << ' ' << GetName() << ' ';
+  out << GetBodyID1() << ' ' << GetBodyID2() << ' ';
+  out << GetPointID1() << ' ' << GetPointID2() << endl;
+  out <<setprecision(16)<< qo <<setprecision(16)<< qdoto <<setprecision(16)<< pk_C_ko;
+  WriteOutJointData(out);
+  out << endl;
+}
+
+ColMatrix* Joint::GetQ(){
+  return &q;
+}
+
+ColMatrix* Joint::GetU(){  
+  return &u;
+}
+
+ColMatrix* Joint::GetQdot(){  
+  return &qdot;
+}
+
+ColMatrix* Joint::GetUdot(){    
+  return &udot;
+}
+
+ColMatrix* Joint::GetQdotdot(){  
+  return &qdotdot;
+}
+
+
+void Joint::DimQandU(int i){
+  DimQandU(i,i);  
+}
+
+void Joint::DimQandU(int i, int j){
+  qo.Dim(i);
+  q.Dim(i);
+  qdot.Dim(i);
+  qdoto.Dim(i);
+  uo.Dim(j);
+  u.Dim(j);
+  udot.Dim(j);
+  qdotdot.Dim(i);  
+  
+  // zero them
+  qo.Zeros();
+  qdoto.Zeros();
+  q.Zeros();
+  qdot.Zeros();
+  uo.Zeros();
+  u.Zeros();  
+  udot.Zeros(); 
+  qdotdot.Zeros();
+  
+}
+
+Body* Joint::GetBody1(){
+  return body1;
+}
+
+Body* Joint::GetBody2(){
+  return body2;
+}
+
+Body* Joint::OtherBody(Body* body){
+  if(body1 == body) return body2;
+  if(body2 == body) return body1;
+  return 0;
+}
+
+Vect3* Joint::GetR12(){
+  return &r12; 
+}
+
+Vect3* Joint::GetR21(){
+  return &r21;
+}
+
+Mat3x3* Joint::Get_pkCk(){
+  return &pk_C_k;
+}
+
+
+Mat3x3* Joint::Get_kCpk(){
+  return &k_C_pk;
+}
+
+Matrix Joint::GetForward_sP(){
+  cerr << "ERROR: Forward Spatial Partial Velocity is not suported for joint type " << GetType() << endl;
+  exit(0);
+}
+
+Matrix Joint::GetBackward_sP(){
+  cerr << "ERROR: Backward Spatial Partial Velocity is not suported for joint type " << GetType() << endl;
+  exit(0);
+}
+
+void Joint::UpdateForward_sP(Matrix& sP){
+  cerr << "WARNING: Using default Update sP procedure" << endl;
+  sP = GetForward_sP();
+}
+
+void Joint::UpdateBackward_sP(Matrix& sP){
+  cerr << "WARNING: Using default Update sP procedure" << endl;
+  sP = GetBackward_sP();
+}
+
+void Joint::ComputeForwardTransforms(){
+  ComputeLocalTransform();
+//  k_C_pk = T(pk_C_k);
+  FastAssignT(pk_C_k, k_C_pk);
+  ComputeForwardGlobalTransform();  
+}
+
+void Joint::ComputeBackwardTransforms(){
+  ComputeLocalTransform();
+  // k_C_pk = pk_C_k^T
+  FastAssignT(pk_C_k, k_C_pk);
+  ComputeBackwardGlobalTransform();
+}
+
+void Joint::ComputeForwardGlobalTransform(){
+  // body2->n_C_k = body1->n_C_k * pk_C_k;
+  FastMult(body1->n_C_k,pk_C_k,body2->n_C_k);   
+  }
+
+void Joint::ComputeBackwardGlobalTransform(){
+  // body1->n_C_k = body2->n_C_k * T(pk_C_k);
+  FastMultT(body2->n_C_k,pk_C_k,body1->n_C_k);
+}
+
+
+//
+// global joint functions
+//
+
+Joint* NewJoint(int type){
+  switch( JointType(type) )
+  {
+    case FREEBODYJOINT : return new FreeBodyJoint;
+    case REVOLUTEJOINT : return new RevoluteJoint;
+    case PRISMATICJOINT : return new PrismaticJoint;
+    case SPHERICALJOINT : return new SphericalJoint;
+	 case BODY23JOINT : return new Body23Joint;
+	 case MIXEDJOINT : return new MixedJoint;
+    default : return 0; // error
+  }
+}
diff --git a/lib/poems/joint.h b/lib/poems/joint.h
new file mode 100644
index 000000000..17122af77
--- /dev/null
+++ b/lib/poems/joint.h
@@ -0,0 +1,123 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: joint.h                                                 *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef JOINT_H
+#define JOINT_H
+
+#include "poemsobject.h"
+#include <iostream>
+#include "matrices.h"
+
+enum JointType {
+  XYZJOINT = 0,
+  FREEBODYJOINT = 1,
+  REVOLUTEJOINT = 2,
+  PRISMATICJOINT = 3,
+  SPHERICALJOINT = 4,
+  BODY23JOINT = 5,
+  MIXEDJOINT = 6		  
+};
+
+class Body;
+class Point;
+
+class Joint : public POEMSObject {
+protected:
+  Body* body1;
+  Body* body2;
+  Point* point1;
+  Point* point2;
+
+  ColMatrix qo;     // generalized coordinates (initial value)
+  ColMatrix uo;     // generalized speeds (initial value)
+  ColMatrix qdoto;     // generalized speeds (initial value)
+
+  ColMatrix q;      // generalized coordinates
+  ColMatrix u;      // generalized speeds
+  ColMatrix qdot;   // generalized coordinate derivatives
+  ColMatrix udot;   // generalized speed derivatives
+  ColMatrix qdotdot;
+  
+  Mat3x3 pk_C_ko;   // transformation relationship for q = 0
+
+  Mat3x3 pk_C_k;  // local transform
+  Mat3x3 k_C_pk;
+
+  Vect3 r12;
+  Vect3 r21;
+
+public:
+
+  Joint();
+  virtual ~Joint();
+  virtual JointType GetType() = 0;
+
+  void SetBodies(Body* b1, Body* b2);
+  void SetPoints(Point* p1, Point* p2);
+
+  int GetBodyID1();
+  int GetBodyID2();
+  int GetPointID1();
+  int GetPointID2();
+
+  ColMatrix* GetQ();
+  ColMatrix* GetU();
+  ColMatrix* GetQdot();
+  ColMatrix* GetUdot();
+  ColMatrix* GetQdotdot();
+  /*ColMatrix* GetAcc();
+  ColMatrix* GetAng();*/
+
+  void DimQandU(int i);
+  void DimQandU(int i, int j);
+
+  Body* GetBody1();
+  Body* GetBody2();
+  Body* OtherBody(Body* body);
+
+  Vect3* GetR12();
+  Vect3* GetR21();
+  Mat3x3* Get_pkCk();
+  Mat3x3* Get_kCpk();
+
+  //void SetInitialState(VirtualMatrix& q, VirtualMatrix& u);  
+  void SetInitialState(ColMatrix& q, ColMatrix& u);  
+  void SetZeroOrientation(VirtualMatrix& C);
+  void ResetQdot();
+  void ResetQ();
+  bool ReadIn(std::istream& in);  
+  void WriteOut(std::ostream& out);
+  
+  virtual void WriteOutJointData(std::ostream& out) = 0;
+  virtual bool ReadInJointData(std::istream& in) = 0;
+  virtual Matrix GetForward_sP();
+  virtual Matrix GetBackward_sP();
+  virtual void UpdateForward_sP(Matrix& sP);
+  virtual void UpdateBackward_sP(Matrix& sP);
+  virtual void ComputeForwardTransforms();
+  virtual void ComputeBackwardTransforms();
+  virtual void ComputeLocalTransform()=0;
+  virtual void ComputeForwardGlobalTransform();
+  virtual void ComputeBackwardGlobalTransform();
+  virtual void ForwardKinematics()=0;
+  virtual void BackwardKinematics()=0;
+};
+
+// global joint functions
+Joint* NewJoint(int type);
+
+#endif
diff --git a/lib/poems/joints.h b/lib/poems/joints.h
new file mode 100644
index 000000000..240a272bd
--- /dev/null
+++ b/lib/poems/joints.h
@@ -0,0 +1,30 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: joints.h                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef JOINTS_H
+#define JOINTS_H
+
+#include "joint.h"
+#include "freebodyjoint.h"
+#include "revolutejoint.h"
+#include "prismaticjoint.h"
+#include "sphericaljoint.h"
+#include "body23joint.h"
+#include "mixedjoint.h"
+
+#endif
diff --git a/lib/poems/mat3x3.cpp b/lib/poems/mat3x3.cpp
new file mode 100644
index 000000000..56ff27035
--- /dev/null
+++ b/lib/poems/mat3x3.cpp
@@ -0,0 +1,152 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: mat3x3.cpp                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "mat3x3.h"
+
+using namespace std;
+
+Mat3x3::Mat3x3(){
+  numrows = numcols = 3;
+}
+Mat3x3::~Mat3x3(){
+}
+
+Mat3x3::Mat3x3(const Mat3x3& A){
+  numrows = numcols = 3;
+  elements[0][0] = A.elements[0][0];elements[0][1] = A.elements[0][1];elements[0][2] = A.elements[0][2];
+  elements[1][0] = A.elements[1][0];elements[1][1] = A.elements[1][1];elements[1][2] = A.elements[1][2];
+  elements[2][0] = A.elements[2][0];elements[2][1] = A.elements[2][1];elements[2][2] = A.elements[2][2];
+}
+
+Mat3x3::Mat3x3(const VirtualMatrix& A){
+  numrows = numcols = 3;
+
+  // error check
+  if( (A.GetNumRows() != 3) || (A.GetNumCols() != 3) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+  
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++)
+      elements[i][j] = A.BasicGet(i,j);
+}
+
+double& Mat3x3::operator_2int(int i, int j){ // array access
+  return elements[i-1][j-1];
+}
+
+double Mat3x3::Get_2int(int i, int j) const{
+  return elements[i-1][j-1];
+}
+
+void Mat3x3::Set_2int(int i, int j, double value){
+  elements[i-1][j-1] = value;
+}
+
+double Mat3x3::BasicGet_2int(int i, int j) const{
+  return elements[i][j];
+}
+
+void Mat3x3::BasicSet_2int(int i, int j, double value){
+  elements[i][j] = value;
+}
+
+void Mat3x3::BasicIncrement_2int(int i, int j, double value){
+  elements[i][j] += value;
+}
+
+void Mat3x3::Const(double value){
+  elements[0][0] = elements[0][1] = elements[0][2] = value;
+  elements[1][0] = elements[1][1] = elements[1][2] = value;
+  elements[2][0] = elements[2][1] = elements[2][2] = value;
+}
+
+MatrixType Mat3x3::GetType() const{
+  return MAT3X3;
+}
+
+istream& Mat3x3::ReadData(istream& c){  //input
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++)
+      c >> elements[i][j];
+  return c;
+}
+
+ostream& Mat3x3::WriteData(ostream& c) const{  //output
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++)
+      c << elements[i][j] << ' ';
+  return c;
+}
+
+void Mat3x3::AssignVM(const VirtualMatrix& A){
+  // error check
+  if( (A.GetNumRows() != 3) || (A.GetNumCols() != 3) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++)
+      elements[i][j] = A.BasicGet(i,j);
+}
+
+Mat3x3& Mat3x3::operator=(const Mat3x3& A){ // assignment operator
+  elements[0][0] = A.elements[0][0];elements[0][1] = A.elements[0][1];elements[0][2] = A.elements[0][2];
+  elements[1][0] = A.elements[1][0];elements[1][1] = A.elements[1][1];elements[1][2] = A.elements[1][2];
+  elements[2][0] = A.elements[2][0];elements[2][1] = A.elements[2][1];elements[2][2] = A.elements[2][2];
+  return *this;
+}
+
+Mat3x3& Mat3x3::operator=(const VirtualMatrix& A){ // overloaded =
+  // error check
+  if( (A.GetNumRows() != 3) || (A.GetNumCols() != 3) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++)
+      elements[i][j] = A.BasicGet(i,j);
+  return *this;
+}
+
+Mat3x3& Mat3x3::operator*=(double b){
+  elements[0][0] *= b; elements[0][1] *= b; elements[0][2] *= b;
+  elements[1][0] *= b; elements[1][1] *= b; elements[1][2] *= b;
+  elements[2][0] *= b; elements[2][1] *= b; elements[2][2] *= b;
+  return *this;
+}
+
+Mat3x3& Mat3x3::Identity(){
+  elements[0][0] = 1.0;
+  elements[0][1] = 0.0;
+  elements[0][2] = 0.0;
+
+  elements[1][0] = 0.0;
+  elements[1][1] = 1.0;
+  elements[1][2] = 0.0;
+
+  elements[2][0] = 0.0;
+  elements[2][1] = 0.0;
+  elements[2][2] = 1.0;
+
+  return *this;
+}
+
diff --git a/lib/poems/mat3x3.h b/lib/poems/mat3x3.h
new file mode 100644
index 000000000..4362b3ad9
--- /dev/null
+++ b/lib/poems/mat3x3.h
@@ -0,0 +1,83 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: mat3x3.h                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef MAT3X3_H
+#define MAT3X3_H
+
+#include "virtualmatrix.h"
+
+
+class Vect3;
+class Mat6x6;
+class Matrix;
+class ColMatrix;
+
+class Mat3x3 : public VirtualMatrix  {
+  double elements[3][3];
+public:
+  Mat3x3();
+  ~Mat3x3();
+  Mat3x3(const Mat3x3& A);  // copy constructor
+  Mat3x3(const VirtualMatrix& A);  // copy constructor
+
+  double& operator_2int (int i, int j); // array access
+  double Get_2int(int i, int j) const;
+  void Set_2int(int i, int j, double value);
+  double BasicGet_2int(int i, int j) const;
+  void BasicSet_2int(int i, int j, double value);
+  void BasicIncrement_2int(int i, int j, double value);
+
+  void Const(double value);
+  MatrixType GetType() const;
+  std::istream& ReadData(std::istream& c); // input
+  std::ostream& WriteData(std::ostream& c) const; // output
+
+  void AssignVM(const VirtualMatrix& A);
+  Mat3x3& operator=(const Mat3x3& A); // assignment operator
+  Mat3x3& operator=(const VirtualMatrix& A); // overloaded =
+  Mat3x3& operator*=(double b);
+
+  Mat3x3& Identity();
+
+  friend Mat3x3 T(const Mat3x3& A);  // a wasteful transpose
+  friend Mat3x3 CrossMat(Vect3& a);  // a wasteful cross matrix implementation
+
+  friend void FastSimpleRotation(Vect3& v, double q, Mat3x3& d);
+  friend void FastQuaternions(ColMatrix& q, Mat3x3& C);
+  friend void FastInvQuaternions(Mat3x3& C, ColMatrix& q);
+  friend void FastLU(Mat3x3& A, Mat3x3& LU, int *indx);
+  friend void FastLUSubs(Mat3x3& LU, Mat3x3& B, Mat3x3& C, int *indx);
+  friend void FastMult(Mat3x3& A, Vect3& B, Vect3& C);
+  friend void FastTMult(Mat3x3& A, Vect3& B, Vect3& C);
+  friend void FastNegMult(Mat3x3& A, Vect3& B, Vect3& C);
+  friend void FastNegTMult(Mat3x3& A, Vect3& B, Vect3& C);
+  friend void FastMult(Mat3x3& A, Mat3x3& B, Mat3x3& C);
+  friend void FastMultT(Mat3x3& A, Mat3x3& B, Mat3x3& C);
+  friend void FastAssignT(Mat3x3& A, Mat3x3& C);
+  friend void FastMult(Mat3x3& A, Vect3& B, ColMatrix& C);  
+  
+  friend void OnPopulateSC(Vect3& gamma, Mat3x3& C, Mat6x6& SC);
+  friend void OnPopulateSI(Mat3x3& inertia, double mass, Mat6x6& sI);
+
+  friend void FastMult(Mat3x3& A, ColMatrix& B, Vect3& C);
+  
+  friend void EP_Transformation(ColMatrix& q, Mat3x3& C);
+  friend void EP_FromTransformation(ColMatrix& q, Mat3x3& C);
+  
+};
+
+#endif
diff --git a/lib/poems/mat4x4.cpp b/lib/poems/mat4x4.cpp
new file mode 100644
index 000000000..a6a4a77fb
--- /dev/null
+++ b/lib/poems/mat4x4.cpp
@@ -0,0 +1,163 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: mat4x4.cpp                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "mat4x4.h"
+
+using namespace std;
+
+Mat4x4::Mat4x4(){
+  numrows = numcols = 4;
+}
+Mat4x4::~Mat4x4(){
+}
+
+Mat4x4::Mat4x4(const Mat4x4& A){
+  numrows = numcols = 4;
+  elements[0][0] = A.elements[0][0];elements[0][1] = A.elements[0][1];elements[0][2] = A.elements[0][2]; elements[0][3] = A.elements[0][3];
+  elements[1][0] = A.elements[1][0];elements[1][1] = A.elements[1][1];elements[1][2] = A.elements[1][2]; elements[1][3] = A.elements[1][3];
+  elements[2][0] = A.elements[2][0];elements[2][1] = A.elements[2][1];elements[2][2] = A.elements[2][2]; elements[2][3] = A.elements[2][3];
+  elements[3][0] = A.elements[3][0];elements[3][1] = A.elements[3][1];elements[3][2] = A.elements[3][2]; elements[3][3] = A.elements[3][3];
+}
+
+Mat4x4::Mat4x4(const VirtualMatrix& A){
+  numrows = numcols = 4;
+
+  // error check
+  if( (A.GetNumRows() != 4) || (A.GetNumCols() != 4) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+  
+  for(int i=0;i<4;i++)
+    for(int j=0;j<4;j++)
+      elements[i][j] = A.BasicGet(i,j);
+}
+
+double& Mat4x4::operator_2int(int i, int j){ // array access
+  return elements[i-1][j-1];
+}
+
+double Mat4x4::Get_2int(int i, int j) const{
+  return elements[i-1][j-1];
+}
+
+void Mat4x4::Set_2int(int i, int j, double value){
+  elements[i-1][j-1] = value;
+}
+
+double Mat4x4::BasicGet_2int(int i, int j) const{
+  return elements[i][j];
+}
+
+void Mat4x4::BasicSet_2int(int i, int j, double value){
+  elements[i][j] = value;
+}
+
+void Mat4x4::BasicIncrement_2int(int i, int j, double value){
+  elements[i][j] += value;
+}
+
+void Mat4x4::Const(double value){
+  elements[0][0] = elements[0][1] = elements[0][2] = elements[0][3] = value;
+  elements[1][0] = elements[1][1] = elements[1][2] = elements[1][3] = value;
+  elements[2][0] = elements[2][1] = elements[2][2] = elements[2][3] = value;
+  elements[3][0] = elements[3][1] = elements[3][2] = elements[3][3] = value;
+}
+
+MatrixType Mat4x4::GetType() const{
+  return MAT4X4;
+}
+
+istream& Mat4x4::ReadData(istream& c){  //input
+  for(int i=0;i<4;i++)
+    for(int j=0;j<4;j++)
+      c >> elements[i][j];
+  return c;
+}
+
+ostream& Mat4x4::WriteData(ostream& c) const{  //output
+  for(int i=0;i<4;i++)
+    for(int j=0;j<4;j++)
+      c << elements[i][j] << ' ';
+  return c;
+}
+
+void Mat4x4::AssignVM(const VirtualMatrix& A){
+  // error check
+  if( (A.GetNumRows() != 4) || (A.GetNumCols() != 4) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++)
+      elements[i][j] = A.BasicGet(i,j);
+}
+
+Mat4x4& Mat4x4::operator=(const Mat4x4& A){ // assignment operator
+  elements[0][0] = A.elements[0][0];elements[0][1] = A.elements[0][1];elements[0][2] = A.elements[0][2]; elements[0][3] = A.elements[0][3];
+  elements[1][0] = A.elements[1][0];elements[1][1] = A.elements[1][1];elements[1][2] = A.elements[1][2]; elements[1][3] = A.elements[1][3];
+  elements[2][0] = A.elements[2][0];elements[2][1] = A.elements[2][1];elements[2][2] = A.elements[2][2]; elements[2][3] = A.elements[2][3];
+  elements[3][0] = A.elements[3][0];elements[3][1] = A.elements[3][1];elements[3][2] = A.elements[3][2]; elements[3][3] = A.elements[3][3];
+  return *this;
+}
+
+Mat4x4& Mat4x4::operator=(const VirtualMatrix& A){ // overloaded =
+  // error check
+  if( (A.GetNumRows() != 4) || (A.GetNumCols() != 4) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++)
+      elements[i][j] = A.BasicGet(i,j);
+  return *this;
+}
+
+Mat4x4& Mat4x4::operator*=(double b){
+  elements[0][0] *= b; elements[0][1] *= b; elements[0][2] *= b; elements[0][3] *= b;
+  elements[1][0] *= b; elements[1][1] *= b; elements[1][2] *= b; elements[1][3] *= b;
+  elements[2][0] *= b; elements[2][1] *= b; elements[2][2] *= b; elements[2][3] *= b;
+  elements[3][0] *= b; elements[3][1] *= b; elements[3][2] *= b; elements[3][3] *= b;
+  return *this;
+}
+
+Mat4x4& Mat4x4::Identity(){
+  elements[0][0] = 1.0;
+  elements[0][1] = 0.0;
+  elements[0][2] = 0.0;
+  elements[0][3] = 0.0;
+
+  elements[1][0] = 0.0;
+  elements[1][1] = 1.0;
+  elements[1][2] = 0.0;
+  elements[1][3] = 0.0;
+
+  elements[2][0] = 0.0;
+  elements[2][1] = 0.0;
+  elements[2][2] = 1.0;
+  elements[2][3] = 0.0;
+
+  elements[3][0] = 0.0;
+  elements[3][1] = 0.0;
+  elements[3][2] = 0.0;
+  elements[3][3] = 1.0;
+
+  return *this;
+}
+
diff --git a/lib/poems/mat4x4.h b/lib/poems/mat4x4.h
new file mode 100644
index 000000000..03637646f
--- /dev/null
+++ b/lib/poems/mat4x4.h
@@ -0,0 +1,68 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: mat4x4.h                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef MAT4X4_H
+#define MAT4X4_H
+
+#include "virtualmatrix.h"
+#include "matrix.h"
+
+
+class Vect4;
+
+class Mat4x4 : public VirtualMatrix  {
+  double elements[4][4];
+public: 
+  Mat4x4();
+  ~Mat4x4();
+  Mat4x4(const Mat4x4& A);  // copy constructor
+  Mat4x4(const VirtualMatrix& A);  // copy constructor
+  
+  double& operator_2int (int i, int j); // array access
+  double Get_2int(int i, int j) const;
+  void Set_2int(int i, int j, double value);
+  double BasicGet_2int(int i, int j) const;
+  void BasicSet_2int(int i, int j, double value);
+  void BasicIncrement_2int(int i, int j, double value);
+
+  void Const(double value);
+  MatrixType GetType() const;
+  std::istream& ReadData(std::istream& c); // input
+  std::ostream& WriteData(std::ostream& c) const; // output
+
+  void AssignVM(const VirtualMatrix& A);
+  Mat4x4& operator=(const Mat4x4& A); // assignment operator
+  Mat4x4& operator=(const VirtualMatrix& A); // overloaded =
+  Mat4x4& operator*=(double b);
+
+  Mat4x4& Identity();
+
+  friend Mat4x4 T(const Mat4x4& A);  // a wasteful transpose
+  friend Mat4x4 CrossMat(Vect4& a);  // a wasteful cross matrix implementation
+
+  friend void FastLU(Mat4x4& A, Mat4x4& LU, int *indx);
+  friend void FastLUSubs(Mat4x4& LU, Matrix& B, Matrix& C, int *indx);
+  friend void FastMult(Mat4x4& A, Vect4& B, Vect4& C);
+  friend void FastTMult(Mat4x4& A, Vect4& B, Vect4& C);
+  friend void FastNegMult(Mat4x4& A, Vect4& B, Vect4& C);
+  friend void FastNegTMult(Mat4x4& A, Vect4& B, Vect4& C);
+  friend void FastMult(Mat4x4& A, Mat4x4& B, Mat4x4& C);
+  friend void FastMultT(Mat4x4& A, Mat4x4& B, Mat4x4& C);
+  friend void FastAssignT(Mat4x4& A, Mat4x4& C);
+};
+
+#endif
diff --git a/lib/poems/mat6x6.cpp b/lib/poems/mat6x6.cpp
new file mode 100644
index 000000000..84bda1faf
--- /dev/null
+++ b/lib/poems/mat6x6.cpp
@@ -0,0 +1,152 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: mat6x6.cpp                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "mat6x6.h"
+
+using namespace std;
+
+Mat6x6::Mat6x6(){
+  numrows = numcols = 6;
+}
+Mat6x6::~Mat6x6(){
+}
+
+Mat6x6::Mat6x6(const Mat6x6& A){
+  numrows = numcols = 6;
+  int i,j;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++)
+      elements[i][j] = A.elements[i][j];
+}
+
+Mat6x6::Mat6x6(const VirtualMatrix& A){
+  numrows = numcols = 6;
+
+  // error check
+  if( (A.GetNumRows() != 6) || (A.GetNumCols() != 6) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<6;i++)
+    for(int j=0;j<6;j++)
+      elements[i][j] = A.BasicGet(i,j);
+}
+
+double& Mat6x6::operator_2int(int i, int j){ // array access
+  return elements[i-1][j-1];
+}
+
+double Mat6x6::Get_2int(int i, int j) const{
+  return elements[i-1][j-1];
+}
+
+void Mat6x6::Set_2int(int i, int j, double value){
+  elements[i-1][j-1] = value;
+}
+
+double Mat6x6::BasicGet_2int(int i, int j) const{
+  return elements[i][j];
+}
+
+void Mat6x6::BasicSet_2int(int i, int j, double value){
+  elements[i][j] = value;
+}
+
+void Mat6x6::BasicIncrement_2int(int i, int j, double value){
+  elements[i][j] += value;
+}
+
+void Mat6x6::Const(double value){
+  int i,j;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++)
+      elements[i][j] = value;
+}
+
+MatrixType Mat6x6::GetType() const{
+  return MAT6X6;
+}
+
+istream& Mat6x6::ReadData(istream& c){  //input
+  for(int i=0;i<6;i++)
+    for(int j=0;j<6;j++)
+      c >> elements[i][j];
+  return c;
+}
+
+ostream& Mat6x6::WriteData(ostream& c) const{  //output
+  for(int i=0;i<6;i++)
+    for(int j=0;j<6;j++)
+      c << elements[i][j] << ' ';
+  return c;
+}
+
+void Mat6x6::AssignVM(const VirtualMatrix& A){
+  // error check
+  if( (A.GetNumRows() != 6) || (A.GetNumCols() != 6) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<6;i++)
+    for(int j=0;j<6;j++)
+      elements[i][j] = A.BasicGet(i,j);
+}
+
+Mat6x6& Mat6x6::operator=(const Mat6x6& A){ // assignment operator
+  int i,j;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++)
+      elements[i][j] = A.elements[i][j];
+  return *this;
+}
+
+Mat6x6& Mat6x6::operator=(const VirtualMatrix& A){ // overloaded =
+  // error check
+  if( (A.GetNumRows() != 6) || (A.GetNumCols() != 6) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<6;i++)
+    for(int j=0;j<6;j++)
+      elements[i][j] = A.BasicGet(i,j);
+  return *this;
+}
+
+Mat6x6& Mat6x6::operator*=(double b){
+  int i,j;
+  for(i=0;i<6;i++)
+    for(j=0;j<6;j++)
+      elements[i][j] *= b;
+  return *this;
+}
+
+Mat6x6& Mat6x6::Identity(){
+  int i,j;
+  for(i=0;i<5;i++){
+    elements[i][i] = 1.0;
+    for(j=i+1;j<6;j++){
+      elements[i][j] = 0.0;
+      elements[j][i] = 0.0;
+    }
+  }
+  elements[i][i] = 1.0;
+  return *this;
+}
+
diff --git a/lib/poems/mat6x6.h b/lib/poems/mat6x6.h
new file mode 100644
index 000000000..11951b044
--- /dev/null
+++ b/lib/poems/mat6x6.h
@@ -0,0 +1,76 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: mat6x6.h                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef MAT6X6_H
+#define MAT6X6_H
+#include "virtualmatrix.h"
+
+
+class Matrix;
+class Mat3x3;
+class Vect6;
+class Vect3;
+
+class Mat6x6 : public VirtualMatrix  {
+  double elements[6][6];
+public:
+  Mat6x6();
+  ~Mat6x6();
+  Mat6x6(const Mat6x6& A);  // copy constructor
+  Mat6x6(const VirtualMatrix& A);  // copy constructor
+
+  double& operator_2int(int i, int j); // array access
+  double Get_2int(int i, int j) const;
+  void Set_2int(int i, int j, double value);
+  double BasicGet_2int(int i, int j) const;
+  void BasicSet_2int(int i, int j, double value);
+  void BasicIncrement_2int(int i, int j, double value);
+
+  void Const(double value);
+  MatrixType GetType() const;
+
+  std::istream& ReadData(std::istream& c); // input
+  std::ostream& WriteData(std::ostream& c) const; // output
+
+  void AssignVM(const VirtualMatrix& A);
+  Mat6x6& operator=(const Mat6x6& A); // assignment operator
+  Mat6x6& operator=(const VirtualMatrix& A); // overloaded =
+  Mat6x6& operator*=(double b);
+
+  Mat6x6& Identity();
+
+  friend Mat6x6 T(const Mat6x6& A);  // a wasteful transpose
+
+  // fast matrix operations
+  friend void FastAdd(Mat6x6& A, Mat6x6& B, Mat6x6& C);
+  friend void FastSubt(Mat6x6& A, Mat6x6& B, Mat6x6& C);
+  friend void FastMultT(Matrix& A, Matrix& B, Mat6x6& C);
+  friend void FastMult(Mat6x6& A, Mat6x6& B, Mat6x6& C);  // C = A*B
+  friend void FastMult(Mat6x6& A, Matrix& B, Matrix& C);
+  friend void FastMultT(Mat6x6& A, Mat6x6& B, Mat6x6& C);  // C = A*B^T
+  friend void FastTMult(Mat6x6& A, Mat6x6& B, Mat6x6& C);  // C = A^T*B
+  friend void FastMult(Mat6x6& A, Vect6& B, Vect6& C);
+  friend void FastTMult(Mat6x6& A, Vect6& B, Vect6& C);
+  friend void FastLDLT(Mat6x6& A, Mat6x6& C);
+  friend void FastLDLTSubs(Mat6x6& LD, Mat6x6& B, Mat6x6& C);
+  friend void FastLDLTSubs(Mat6x6& LD, Vect6& B, Vect6& C);
+
+  friend void OnPopulateSC(Vect3& gamma, Mat3x3& C, Mat6x6& SC);
+  friend void OnPopulateSI(Mat3x3& inertia, double mass, Mat6x6& sI);
+};
+
+#endif
diff --git a/lib/poems/matrices.h b/lib/poems/matrices.h
new file mode 100644
index 000000000..934a21b4e
--- /dev/null
+++ b/lib/poems/matrices.h
@@ -0,0 +1,42 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: matrices.h                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef MATRICES_H
+#define MATRICES_H
+
+#include "matrix.h"
+
+#include "colmatrix.h"
+
+#include "rowmatrix.h"
+
+#include "mat3x3.h"
+
+#include "vect3.h"
+
+#include "mat4x4.h"
+
+#include "vect4.h"
+
+#include "mat6x6.h"
+
+#include "vect6.h"
+
+#include "colmatmap.h"
+
+#endif
diff --git a/lib/poems/matrix.cpp b/lib/poems/matrix.cpp
new file mode 100644
index 000000000..68275718f
--- /dev/null
+++ b/lib/poems/matrix.cpp
@@ -0,0 +1,166 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: matrix.cpp                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "matrix.h"
+#include <iostream>
+
+using namespace std;
+
+Matrix::Matrix(){
+  numrows = numcols = 0;
+  rows = 0;
+  elements = 0;
+}
+
+Matrix::~Matrix(){
+  delete [] rows;
+  delete [] elements;
+}
+
+Matrix::Matrix(const Matrix& A){
+  numrows = numcols = 0;
+  rows = 0;
+  elements = 0;
+  Dim(A.numrows,A.numcols);
+  for(int i=0;i<numrows*numcols;i++)
+    elements[i] = A.elements[i];
+}
+
+Matrix::Matrix(const VirtualMatrix& A){
+  numrows = numcols = 0;
+  rows = 0;
+  elements = 0;
+  Dim(A.GetNumRows(),A.GetNumCols());
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++)
+      rows[i][j] = A.BasicGet(i,j);
+}
+
+Matrix::Matrix(int m, int n){
+  numrows = numcols = 0;
+  rows = 0;
+  elements = 0;
+  this->Dim(m,n);
+}
+
+double& Matrix::operator_2int(int i, int j){
+  if((i>numrows) || (j>numcols) || (i*j==0)){
+    cerr << "matrix index exceeded in operator ()" << endl;
+    exit(1);
+  }
+  return rows[i-1][j-1];
+}
+
+double Matrix::Get_2int(int i, int j) const {
+  if((i>numrows) || (j>numcols) || (i*j==0)){
+    cerr << "matrix index exceeded in Get" << endl;
+    exit(1);
+  }
+  return rows[i-1][j-1];
+}
+
+void Matrix::Set_2int(int i, int j, double value){
+  if((i>numrows) || (j>numcols) || (i*j==0)){
+    cerr << "matrix index exceeded in Set" << endl;
+    exit(1);
+  }
+  rows[i-1][j-1] = value;
+}
+
+double Matrix::BasicGet_2int(int i, int j) const {
+  return rows[i][j];
+}
+
+void Matrix::BasicSet_2int(int i, int j, double value){
+  rows[i][j] = value;
+}
+
+void Matrix::BasicIncrement_2int(int i, int j, double value){
+  rows[i][j] += value;
+}
+
+void Matrix::Const(double value){
+  int num = numrows*numcols;
+  for(int i=0;i<num;i++) elements[i] = value;
+}
+
+MatrixType Matrix::GetType() const{
+  return MATRIX;
+}
+
+istream& Matrix::ReadData(istream& c){
+  int n,m;
+  c >> n >> m;
+  Dim(n,m);
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++){
+      c >> rows[i][j];
+    }
+  return c;
+}
+
+ostream& Matrix::WriteData(ostream& c) const{  //output
+  c << numrows << ' ' << numcols << ' ';
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++){
+      c << rows[i][j] << ' ';
+    }
+  return c;
+}
+
+Matrix& Matrix::Dim(int m, int n){  // allocate size
+  numrows = m;
+  numcols = n;
+  delete [] rows;
+  delete [] elements;
+  elements = new double[n*m];
+  rows = new double*[m];
+  for(int i=0;i<m;i++)
+    rows[i] = &elements[i*numcols];
+  return *this;
+}
+
+void Matrix::AssignVM(const VirtualMatrix& A){
+  Dim( A.GetNumRows(), A.GetNumCols() );
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++)
+      rows[i][j] = A.BasicGet(i,j);
+}
+
+Matrix& Matrix::operator=(const Matrix& A){
+  Dim(A.numrows,A.numcols);
+  for(int i=0;i<numrows*numcols;i++)
+    elements[i] = A.elements[i];
+  return *this;
+}
+
+Matrix& Matrix::operator=(const VirtualMatrix& A){
+  Dim( A.GetNumRows(), A.GetNumCols() );
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++)
+      rows[i][j] = A.BasicGet(i,j);
+  return *this;
+}
+
+Matrix& Matrix::operator*=(double b){
+  for(int i=0;i<numrows;i++)
+    for(int j=0;j<numcols;j++)
+      rows[i][j] *= b;
+  return *this;
+}
+
diff --git a/lib/poems/matrix.h b/lib/poems/matrix.h
new file mode 100644
index 000000000..63699b983
--- /dev/null
+++ b/lib/poems/matrix.h
@@ -0,0 +1,77 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: matrix.h                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef MATRIX_H
+#define MATRIX_H
+
+#include "virtualmatrix.h"
+
+class Mat3x3;
+class Mat4x4;
+class Mat6x6;
+class Vect6;
+class ColMatrix;
+
+
+class Matrix : public VirtualMatrix {
+  double **rows;          // row pointer
+  double *elements;
+public:
+  Matrix();
+  ~Matrix();
+  Matrix(const Matrix& A);  // copy constructor
+  Matrix(const VirtualMatrix& A);  // copy constructor
+  Matrix(int m, int n);  // size constructor
+
+  double& operator_2int (int i, int j); // array access
+  double Get_2int(int i, int j) const;
+  void Set_2int(int i, int j, double value);
+  double BasicGet_2int(int i, int j) const;
+  void BasicSet_2int(int i, int j, double value);
+  void BasicIncrement_2int(int i, int j, double value);
+
+  void Const(double value);
+  MatrixType GetType() const;
+  std::istream& ReadData(std::istream& c);
+  std::ostream& WriteData(std::ostream& c) const;
+
+  Matrix& Dim(int m, int n);    // allocate size
+
+  void AssignVM(const VirtualMatrix& A);
+  Matrix& operator=(const Matrix& A); // assignment operator
+  Matrix& operator=(const VirtualMatrix& A); // overloaded =
+  Matrix& operator*=(double b);
+
+  friend void FastLDLT(Matrix& A, Matrix& C);
+  friend void FastLDLTSubs(Matrix& LD, Matrix& B, Matrix& C);
+  friend void FastLDLTSubsLH(Matrix& B, Matrix& LD, Matrix& C);
+  friend void FastLU(Matrix& A, Matrix& LU, int *indx);
+  friend void FastLUSubs(Matrix& LU, Matrix& B, Matrix& C, int *indx);
+  friend void FastLUSubs(Mat3x3& LU, Matrix& B, Matrix& C, int *indx);
+  friend void FastLUSubs(Mat4x4& LU, Matrix& B, Matrix& C, int *indx);
+  friend void FastLUSubs(Mat6x6& LU, Matrix& B, Matrix& C, int *indx);
+  friend void FastLUSubsLH(Matrix& B, Matrix& LU, Matrix& C, int *indx);
+  friend void FastMult(Matrix& A, Matrix& B, Matrix& C);
+  friend void FastTMult(Matrix& A, Matrix& B, Matrix& C);
+  friend void FastTMult(Matrix& A, Vect6& B, ColMatrix& C);
+  friend void FastMult(Mat6x6& A, Matrix& B, Matrix& C);
+  friend void FastMult(Matrix& A, ColMatrix& B, Vect6& C);
+  friend void FastMultT(Matrix& A, Matrix& B, Mat6x6& C);
+  
+};
+
+#endif
diff --git a/lib/poems/matrixfun.cpp b/lib/poems/matrixfun.cpp
new file mode 100644
index 000000000..80a9450bf
--- /dev/null
+++ b/lib/poems/matrixfun.cpp
@@ -0,0 +1,407 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: matrixfun.cpp                                           *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "matrixfun.h"
+#include <math.h>
+#include "fastmatrixops.h"
+
+using namespace std;
+
+//
+//  Create a new matrix
+//
+
+VirtualMatrix* NewMatrix(int type){
+  switch( MatrixType(type) )
+    {
+      case MATRIX : return new Matrix;
+      case COLMATRIX : return new ColMatrix;
+      case ROWMATRIX : return new RowMatrix;		
+      case MAT3X3 : return new Mat3x3;
+		case MAT4X4 : return new Mat4x4;
+      case VECT3 : return new Vect3;
+		case VECT4 : return new Vect4;
+      default  : return 0; // error!
+    }
+}
+
+//
+// Transpose
+//
+
+Matrix T(const VirtualMatrix& A){
+	int numrows = A.GetNumRows();
+	int numcols = A.GetNumCols();
+	Matrix C(numcols,numrows);
+	for(int i=0;i<numcols;i++)
+		for(int j=0;j<numrows;j++)
+			C.BasicSet(i,j,A.BasicGet(j,i));
+	return C;
+}
+
+Mat3x3 T(const Mat3x3& A){
+	Mat3x3 C;
+	C.elements[0][0] = A.elements[0][0];
+	C.elements[1][1] = A.elements[1][1];
+	C.elements[2][2] = A.elements[2][2];
+
+	C.elements[0][1] = A.elements[1][0];
+	C.elements[0][2] = A.elements[2][0];
+	C.elements[1][2] = A.elements[2][1];
+
+	C.elements[1][0] = A.elements[0][1];
+	C.elements[2][0] = A.elements[0][2];
+	C.elements[2][1] = A.elements[1][2];
+	return C;
+}
+
+Mat6x6 T(const Mat6x6& A){
+	Mat6x6 C;
+	int i,j;
+	for(i=0;i<6;i++)
+		for(j=0;j<6;j++)
+			C.elements[i][j] = A.elements[j][i];
+
+	return C;
+}
+
+Matrix T(const Vect3& A){
+	Matrix C(1,3);
+	C.BasicSet(0,0,A.elements[0]);
+	C.BasicSet(0,1,A.elements[1]);
+	C.BasicSet(0,2,A.elements[2]);
+
+	return C;
+}
+
+Matrix T(const Vect6& A){
+	Matrix C(1,6);
+	C.BasicSet(0,0,A.elements[0]);
+	C.BasicSet(0,1,A.elements[1]);
+	C.BasicSet(0,2,A.elements[2]);
+	C.BasicSet(0,3,A.elements[3]);
+	C.BasicSet(0,4,A.elements[4]);
+	C.BasicSet(0,5,A.elements[5]);
+
+	return C;
+}
+
+RowMatrix T(const VirtualColMatrix &A){
+	int numele = A.GetNumRows();
+	RowMatrix C(numele);
+	for(int i=0;i<numele;i++)
+		C.BasicSet(i,A.BasicGet(i));
+	return C;
+}
+
+ColMatrix T(const VirtualRowMatrix &A){
+	int numele = A.GetNumCols();
+	ColMatrix C(numele);
+	for(int i=0;i<numele;i++)
+		C.BasicSet(i,A.BasicGet(i));
+	return C;
+}
+
+//
+// Symmetric Inverse
+//
+
+Matrix SymInverse(Matrix &A){
+	int r = A.GetNumRows();
+	Matrix C(r,r);
+	Matrix LD(r,r);
+	Matrix I(r,r);
+	I.Zeros();
+	for(int i=0;i<r;i++) I.BasicSet(i,i,1.0);
+	FastLDLT(A,LD);
+	FastLDLTSubs(LD,I,C);
+	return C;
+}
+
+Mat6x6 SymInverse(Mat6x6 &A){
+	Mat6x6 C;
+	Mat6x6 LD;
+	Mat6x6 I;
+	I.Zeros();
+	for(int i=0;i<6;i++) I.BasicSet(i,i,1.0);
+	FastLDLT(A,LD);
+	FastLDLTSubs(LD,I,C);
+	return C;
+}
+
+//
+// Inverse
+//
+
+Matrix Inverse(Matrix& A){
+	int r = A.GetNumRows();
+	int indx[10000];
+	Matrix LU(r,r);
+	Matrix I(r,r);
+	Matrix C(r,r);
+	I.Zeros();
+	for(int i=0;i<r;i++) I.BasicSet(i,i,1.0);
+	FastLU(A,LU,indx);
+	FastLUSubs(LU,I,C,indx);
+	return C;
+}
+
+Mat3x3 Inverse(Mat3x3& A){
+	int indx[10000];
+	Mat3x3 LU;
+	Matrix I(3,3);
+	Matrix C(3,3);
+	I.Zeros();
+	for(int i=0;i<3;i++) I.BasicSet(i,i,1.0);
+	FastLU(A,LU,indx);
+	FastLUSubs(LU,I,C,indx);
+	return C;
+}
+
+Mat4x4 Inverse(Mat4x4& A){
+	int indx[10000];
+	Mat4x4 LU;
+	Matrix I(4,4);
+	Matrix C(4,4);
+	I.Zeros();
+	for(int i=0;i<4;i++) I.BasicSet(i,i,1.0);
+	FastLU(A,LU,indx);
+	FastLUSubs(LU,I,C,indx);
+	return C;
+}
+
+Mat6x6 Inverse(Mat6x6& A){
+	int indx[10000];
+	Mat6x6 LU;
+	Matrix I(6,6);
+	Matrix C(6,6);
+	I.Zeros();
+	for(int i=0;i<6;i++) I.BasicSet(i,i,1.0);
+	FastLU(A,LU,indx);
+	FastLUSubs(LU,I,C,indx);
+	return C;
+}
+
+//
+// overloaded addition
+//
+
+Matrix operator+ (const VirtualMatrix &A, const VirtualMatrix &B){      // addition
+	int Arows,Acols,Brows,Bcols;
+	Arows = A.GetNumRows();
+	Acols = A.GetNumCols();
+	Brows = B.GetNumRows();
+	Bcols = B.GetNumCols();
+
+	if( !((Arows == Brows) && (Acols == Bcols)) ){
+		cerr << "Dimesion mismatch in matrix addition" << endl;
+		exit(1);
+	}
+
+	Matrix C(Arows,Acols);
+
+	for(int i=0;i<Arows;i++)
+		for(int j=0;j<Acols;j++)
+			C.BasicSet(i,j,A.BasicGet(i,j) + B.BasicGet(i,j));
+
+	return C;
+}
+
+//
+// overloaded subtraction
+//
+
+Matrix operator- (const VirtualMatrix &A, const VirtualMatrix &B){      // subtraction
+	int Arows,Acols,Brows,Bcols;
+	Arows = A.GetNumRows();
+	Acols = A.GetNumCols();
+	Brows = B.GetNumRows();
+	Bcols = B.GetNumCols();
+
+	if( !((Arows == Brows) && (Acols == Bcols)) ){
+		cerr << "Dimesion mismatch in matrix addition" << endl;
+		exit(1);
+	}
+
+	Matrix C(Arows,Acols);
+
+	for(int i=0;i<Arows;i++)
+		for(int j=0;j<Acols;j++)
+			C.BasicSet(i,j,A.BasicGet(i,j) - B.BasicGet(i,j));
+
+	return C;
+}
+
+//
+// overloaded matrix multiplication
+//
+
+Matrix operator* (const VirtualMatrix &A, const VirtualMatrix &B){      // multiplication
+	int Arows,Acols,Brows,Bcols;
+	Arows = A.GetNumRows();
+	Acols = A.GetNumCols();
+	Brows = B.GetNumRows();
+	Bcols = B.GetNumCols();
+
+	if(Acols != Brows){
+		cerr << "Dimesion mismatch in matrix multiplication" << endl;
+		exit(1);
+	}
+
+	Matrix C(Arows,Bcols);
+	C.Zeros();
+
+	for(int i=0;i<Arows;i++)
+		for(int j=0;j<Bcols;j++)
+			for(int k=0;k<Brows;k++)
+				C.BasicIncrement(i,j, A.BasicGet(i,k) * B.BasicGet(k,j) );
+
+	return C;
+}
+
+//
+// overloaded scalar multiplication
+//
+
+Matrix operator* (const VirtualMatrix &A, double b){    // multiplication
+	Matrix C = A;
+	C *= b;
+	return C;
+}
+
+Matrix operator* (double b, const VirtualMatrix &A){    // multiplication
+	Matrix C = A;  
+	C *= b;
+	return C;
+}
+
+//
+// overloaded negative
+//
+
+Matrix operator- (const VirtualMatrix& A){  // negative
+	int r = A.GetNumRows();
+	int c = A.GetNumCols();
+	Matrix C(r,c);
+
+	for(int i=0;i<r;i++)
+		for(int j=0;j<c;j++)
+			C.BasicSet(i,j,-A.BasicGet(i,j));
+
+	return C;
+}
+
+//
+// Cross product (friend of Vect3)
+//
+
+Vect3 Cross(Vect3& a, Vect3& b){
+	return CrossMat(a)*b;
+}
+
+//
+// Cross Matrix (friend of Vect3 & Mat3x3)
+//
+
+Mat3x3 CrossMat(Vect3& a){
+	Mat3x3 C;
+	C.Zeros();
+	C.elements[0][1] = -a.elements[2];
+	C.elements[1][0] = a.elements[2];
+	C.elements[0][2] = a.elements[1];
+	C.elements[2][0] = -a.elements[1];
+	C.elements[1][2] = -a.elements[0];
+	C.elements[2][1] = a.elements[0];
+
+	return C;
+}
+
+//
+// Stack
+//
+
+Matrix Stack(VirtualMatrix& A, VirtualMatrix& B){
+	int m,na,nb;
+	m = A.GetNumCols();
+	if( m != B.GetNumCols()){
+		cerr << "Error: cannot stack matrices of differing column dimension" << endl;
+		exit(0);
+	}
+	na = A.GetNumRows();
+	nb = B.GetNumRows();
+
+	Matrix C(na+nb,m);
+
+	for(int i=0;i<na;i++){
+		for(int j=0;j<m;j++){
+			C.BasicSet(i,j,A.BasicGet(i,j));
+		}
+	}
+
+	for(int i=0;i<nb;i++){
+		for(int j=0;j<m;j++){
+			C.BasicSet(i+na,j,B.BasicGet(i,j));
+		}
+	}
+
+	return C;
+}
+
+//Hstack
+
+Matrix HStack(VirtualMatrix& A, VirtualMatrix& B){
+	int m,na,nb;
+	m = A.GetNumRows();
+	if( m != B.GetNumRows()){
+		cerr << "Error: cannot stack matrices of differing row dimension" << endl;
+		exit(0);
+	}
+	na = A.GetNumCols();
+	nb = B.GetNumCols();
+
+	Matrix C(m,na+nb);
+
+	for(int i=0;i<m;i++){
+		for(int j=0;j<na;j++){
+			C.BasicSet(i,j,A.BasicGet(i,j));
+		}
+	}
+
+	for(int i=0;i<m;i++){
+		for(int j=0;j<nb;j++){
+			C.BasicSet(i,j+na,B.BasicGet(i,j));
+		}
+	}
+
+	return C;
+}
+
+//
+//
+
+void Set6DAngularVector(Vect6& v6, Vect3& v3){
+	v6.elements[0] = v3.elements[0];
+	v6.elements[1] = v3.elements[1];
+	v6.elements[2] = v3.elements[2];
+}
+
+void Set6DLinearVector(Vect6& v6, Vect3& v3){
+	v6.elements[3] = v3.elements[0];
+	v6.elements[4] = v3.elements[1];
+	v6.elements[5] = v3.elements[2];
+}
+
diff --git a/lib/poems/matrixfun.h b/lib/poems/matrixfun.h
new file mode 100644
index 000000000..600b608ad
--- /dev/null
+++ b/lib/poems/matrixfun.h
@@ -0,0 +1,76 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: matrixfun.h                                           *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+#ifndef MATRIXFUN_H
+#define MATRIXFUN_H
+
+#include "matrices.h"
+
+// Create a Matrix
+VirtualMatrix* NewMatrix(int type);
+
+// Transpose
+Matrix T(const VirtualMatrix& A);
+Mat3x3 T(const Mat3x3& A);
+Mat6x6 T(const Mat6x6& A);
+Matrix T(const Vect3& A);
+Matrix T(const Vect6& A);
+RowMatrix T(const VirtualColMatrix& A);
+ColMatrix T(const VirtualRowMatrix& A);
+
+// Symmetric Inverse
+
+Matrix SymInverse(Matrix& A);
+Mat6x6 SymInverse(Mat6x6& A);
+
+// Inverse
+Matrix Inverse(Matrix& A);
+Mat3x3 Inverse(Mat3x3& A);
+Mat4x4 Inverse(Mat4x4& A);
+Mat6x6 Inverse(Mat6x6& A);
+
+// overloaded addition
+Matrix operator+ (const VirtualMatrix &A, const VirtualMatrix &B);	// addition
+//Mat3x3 operator+ (const Mat3x3 &A, const Mat3x3 &B);	// addition
+//Matrix operator+ (const VirtualMatrix &A, const VirtualMatrix &B);	// addition
+
+// overloaded subtraction
+Matrix operator- (const VirtualMatrix &A, const VirtualMatrix &B);	// subtraction
+
+// overloaded matrix multiplication
+Matrix operator* (const VirtualMatrix &A, const VirtualMatrix &B);  // multiplication
+
+// overloaded scalar-matrix multiplication
+Matrix operator* (const VirtualMatrix &A, double b);			// overloaded *
+Matrix operator* (double b, const VirtualMatrix &A);			// overloaded *
+
+// overloaded negative
+Matrix operator- (const VirtualMatrix &A);	// negative
+
+Vect3 Cross(Vect3& a, Vect3& b);
+Mat3x3 CrossMat(Vect3& a);
+
+Matrix Stack(VirtualMatrix& A, VirtualMatrix& B);
+Matrix HStack(VirtualMatrix& A, VirtualMatrix& B);
+
+void Set6DAngularVector(Vect6& v6, Vect3& v3);
+void Set6DLinearVector(Vect6& v6, Vect3& v3);
+
+
+
+
+#endif
diff --git a/lib/poems/mixedjoint.cpp b/lib/poems/mixedjoint.cpp
new file mode 100644
index 000000000..c834ef621
--- /dev/null
+++ b/lib/poems/mixedjoint.cpp
@@ -0,0 +1,196 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: mixedjoint.cpp 	                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+#include "mixedjoint.h"
+#include "point.h"
+#include "matrixfun.h"
+#include "body.h"
+#include "fastmatrixops.h"
+#include "norm.h"
+#include "eulerparameters.h"
+#include "matrices.h"
+
+   
+
+MixedJoint::MixedJoint(){		 
+}
+
+MixedJoint::~MixedJoint(){
+}
+
+JointType MixedJoint::GetType(){
+  return MIXEDJOINT;
+}
+
+bool MixedJoint::ReadInJointData(std::istream& in){
+  return true;
+}
+
+void MixedJoint::WriteOutJointData(std::ostream& out){
+}
+
+void MixedJoint::SetsP(Matrix& sPr, Vect6& temp_dofs, int i, int j){
+	const_sP = sPr;
+	dofs = temp_dofs;
+	numrots = i;
+	numtrans = j;
+	if (numrots < 2)
+		DimQandU(numrots+numtrans,numrots+numtrans);  
+	else 
+		DimQandU((4+numtrans),(numrots+numtrans)); 
+	cout<<"Check "<<4+numtrans<<" "<<numrots+numtrans<<" "<<i<<" "<<j<<endl;
+}
+
+void MixedJoint::ComputeLocalTransform(){
+  Mat3x3 ko_C_k;  
+  EP_Transformation(q, ko_C_k);   
+  FastMult(pk_C_ko,ko_C_k,pk_C_k);  
+}
+
+Matrix MixedJoint::GetForward_sP(){
+  Mat6x6 temp_sP;
+  Matrix sP;
+    
+  temp_sP.Zeros();  
+  Mat3x3 temp0=T(pk_C_k);
+  for(int i=1;i<4;i++){
+	  temp_sP(i,i)=1.0;
+	  for(int j=1;j<4;j++){
+		  temp_sP(3+i,3+j)=temp0(i,j);
+	  }
+  }
+  sP = temp_sP*const_sP;  
+  return sP;    
+}
+
+Matrix MixedJoint::GetBackward_sP(){
+  Mat6x6 sP;
+  sP.Identity();        
+  sP =-1.0*sP;
+  cout<<"Did I come here in "<<endl;
+  return sP;    
+}
+
+
+void MixedJoint::UpdateForward_sP( Matrix& sP){
+  // do nothing
+}
+  
+void MixedJoint::UpdateBackward_sP( Matrix& sP){
+  // do nothing
+}  
+  
+void MixedJoint::ForwardKinematics(){	
+	if(numrots > 1)
+		EP_Normalize(q);
+
+  // COMMENT STEP1: CALCULATE ORIENTATIONS
+  ComputeForwardTransforms();  
+  
+    
+  //COMMENT STEP2: CALCULATE POSITION VECTORS
+  Vect3 result1, result2, result3, result4;   
+  result1.Zeros();
+  for (int k=0; k<3; k++){
+	  if( dofs(3+k) != 0.0 ){
+		  if (numrots > 1)
+			  result1.BasicSet(k,q.BasicGet(4 + k));
+		  else
+			  result1.BasicSet(k,q.BasicGet(numrots + k));
+	  }  
+  }
+    
+  
+  
+  FastAssign(result1,r12);     // r12 in parents basis  i.e. Newtonian  
+  FastNegMult(k_C_pk,r12,r21);	    // r21 in body basis           
+  
+  FastAssign(r12,body2->r);  // This is right     
+    
+  //COMMENT STEP3: CALCULATE QDOT  
+  int pp = 0;
+  if (numrots > 1){
+	  ColMatrix temp_u(3+numtrans);
+	  qdot_to_u(q,temp_u,qdot);
+	  for (int k=1;k<=6;k++){
+		  if(dofs(k) != 0.0){
+			  u.BasicSet(pp,temp_u.BasicGet(k-1));			  
+			  pp = pp+1;
+		  }		  
+	  }
+  }
+  else u = qdot;
+
+  
+  
+  Vect3 WN; WN.Zeros();
+  int p = 0;
+  for (int k=0;k<3;k++){
+	  if(dofs(k+1) != 0.0){
+		  WN.BasicSet(k,u.BasicGet(p));
+		  p=p+1;
+	  }
+  }// WN is in body basis
+
+  
+  Vect3 VN; VN.Zeros();  
+  for (int k=0;k<3;k++){
+	  if( dofs(3+k+1) != 0.0 ) {
+		  VN.BasicSet(k,u.BasicGet(p));
+		  p=p+1;
+	  }
+  }// VN is the vector of translational velocities in Newtonian basis
+    
+  FastAssign(WN,body2->omega_k);  
+
+  // cout<<"Angular Velocity "<<WN<<endl;  
+  Vect3 pk_w_k;
+  FastMult(body2->n_C_k,WN,pk_w_k);      
+  FastAssign(pk_w_k,body2->omega);
+  
+  
+  
+  //COMMENT STEP5: CALCULATE VELOCITES        
+  FastAssign(VN,body2->v);    
+  FastTMult(body2->n_C_k,body2->v,body2->v_k);        
+  
+  
+  //CALCULATE KE          
+ 
+  Matrix tempke;
+  tempke = T(body2->v)*(body2->v);    
+  double ke = 0.0;
+  ke = body2->mass*tempke(1,1);    
+  FastMult(body2->inertia,body2->omega_k,result1);
+  tempke= T(body2->omega_k)*result1;  
+  ke = 0.5*ke + 0.5*tempke(1,1);
+  body2->KE=ke;
+  
+  
+  //COMMENT STEP6: CALCULATE STATE EXPLICIT ANGULAR ACCELERATIONS
+  body2->alpha_t.Zeros();
+      
+    
+  //COMMENT STEP7: CALCULATE STATE EXPLICIT ACCELERATIONS
+  body2->a_t.Zeros();   
+  
+  }
+
+void MixedJoint::BackwardKinematics(){
+cout<<"Did I come here "<<endl;
+         
+}
diff --git a/lib/poems/mixedjoint.h b/lib/poems/mixedjoint.h
new file mode 100644
index 000000000..5f59b95f0
--- /dev/null
+++ b/lib/poems/mixedjoint.h
@@ -0,0 +1,46 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: mixedjoint.h		                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef MIXEDJOINT_H
+#define MIXEDJOINT_H
+
+#include "joint.h"
+
+
+class MixedJoint : public Joint{
+  Matrix const_sP;
+  int numrots;
+  int numtrans;
+  Vect6 dofs;
+public: 
+  MixedJoint();
+  ~MixedJoint();
+  
+  JointType GetType();
+  bool ReadInJointData(std::istream& in);
+  void WriteOutJointData(std::ostream& out);
+  void ComputeLocalTransform();
+  void SetsP(Matrix& sPr, Vect6& temp_dofs, int i, int j);
+  Matrix GetForward_sP();
+  Matrix GetBackward_sP();
+  void UpdateForward_sP( Matrix& sP);
+  void UpdateBackward_sP( Matrix& sP);
+  void ForwardKinematics();
+  void BackwardKinematics();
+};
+
+#endif
diff --git a/lib/poems/norm.cpp b/lib/poems/norm.cpp
new file mode 100644
index 000000000..0118476e8
--- /dev/null
+++ b/lib/poems/norm.cpp
@@ -0,0 +1,59 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: nrom.cpp                                               *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include <cmath>
+#include "norm.h"
+
+double Magnitude(ColMatrix& A){
+	double G;
+	G = 0;
+	for (int i=1;i<=A.GetNumRows();i++) G += A.Get(i)*A.Get(i);
+	G = sqrt(G);
+	return G;
+}
+
+double Magnitude(RowMatrix& A){
+	double G;
+	G = 0;
+	for (int i=1;i<=A.GetNumCols();i++) G += A.Get(i)*A.Get(i);
+	G = sqrt(G);
+	return G;
+}
+
+double Magnitude(Vect3& A){
+	double G;
+	G = 0;
+	for (int i=1;i<=3;i++) G += A.Get(i)*A.Get(i);
+	G = sqrt(G);
+	return G;
+}
+
+double Magnitude(Vect4& A){
+	double G;
+	G = 0;
+	for (int i=1;i<=4;i++) G += A.Get(i)*A.Get(i);
+	G = sqrt(G);
+	return G;
+}
+
+double Magnitude(Vect6& A){
+	double G;
+	G = 0;
+	for (int i=1;i<=6;i++) G += A.Get(i)*A.Get(i);
+	G = sqrt(G);
+	return G;
+}
diff --git a/lib/poems/norm.h b/lib/poems/norm.h
new file mode 100644
index 000000000..974c1768a
--- /dev/null
+++ b/lib/poems/norm.h
@@ -0,0 +1,30 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: norm.h                                                  *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef NORM_H
+#define NORM_H
+
+#include "matrices.h"
+
+
+double Magnitude(ColMatrix& A);
+double Magnitude(RowMatrix& A);
+double Magnitude(Vect3& A);
+double Magnitude(Vect4& A);
+double Magnitude(Vect6& A);
+
+#endif
diff --git a/lib/poems/onbody.cpp b/lib/poems/onbody.cpp
new file mode 100644
index 000000000..102900df8
--- /dev/null
+++ b/lib/poems/onbody.cpp
@@ -0,0 +1,401 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: onbody.cpp                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "onbody.h"
+#include "body.h"
+#include "inertialframe.h"
+#include "joint.h"
+#include "onfunctions.h"
+#include "virtualmatrix.h"
+#include "matrixfun.h"
+#include <iostream>
+#include "norm.h"
+#include "eulerparameters.h"
+
+using namespace std;
+
+
+OnBody::OnBody(){
+  system_body = 0;
+  system_joint = 0;
+  parent = 0;
+
+  // these terms have zeros which are NEVER overwritten
+  sI.Zeros();
+  sSC.Zeros();
+}
+
+OnBody::~OnBody(){
+  children.DeleteValues();
+}
+
+int OnBody::RecursiveSetup (InertialFrame* basebody){
+  int ID = 0;
+  system_body = basebody;
+
+  // record that the traversal algorithm has been here
+  if( system_body->GetID() ) return 0;
+  ID++;
+  system_body->SetID(ID);  
+
+  // setup inertial frame
+  SetupInertialFrame();
+
+  Joint* joint;
+  OnBody* child;
+  int tempID;
+
+  // loop through children calling the recursive setup function
+  ListElement<Joint>* ele = system_body->joints.GetHeadElement();
+  while(ele){
+    joint = ele->value;
+    child = new OnBody;
+
+    tempID = child->RecursiveSetup(ID,this,joint);
+    if( tempID ){
+      children.Append(child);
+      ID = tempID;      
+    }
+    else delete child;
+
+    ele = ele->next;
+  }
+
+  return ID;
+}
+
+int OnBody::RecursiveSetup(int ID, OnBody* parentbody, Joint* sys_joint){
+  // initialize the topology and system analogs
+  parent = parentbody;  
+  system_joint = sys_joint;
+  system_body = system_joint->OtherBody(parentbody->system_body);
+  
+    
+  // record that the traversal algorithm has been here
+  if( system_body->GetID() ) return 0;
+  ID++;  
+
+  // perform the local setup operations
+  Setup();
+
+  Joint* joint;
+  OnBody* child;
+  int tempID;
+
+  // loop through children calling the recursive setup function
+  ListElement<Joint>* ele = system_body->joints.GetHeadElement();
+  while(ele){
+    joint = ele->value;
+    if(joint != sys_joint){
+      child = new OnBody;
+
+      tempID = child->RecursiveSetup(ID,this,joint);
+      if( tempID ){
+        children.Append(child);
+        ID = tempID;
+      }
+      else delete child;
+    }
+
+    ele = ele->next;
+  }
+
+  return ID;  
+}
+
+void OnBody::SetupInertialFrame(){
+  // error check
+  if(system_body->GetType() != INERTIALFRAME){
+    cerr << "ERROR: attempting to setup inertial frame for non-inertial body" << endl;
+    exit(1);
+  }
+  
+  // setup gravity
+  Vect3 neg_gravity = -((InertialFrame*) system_body)->GetGravity();  
+  sAhat.Zeros();
+  Set6DLinearVector(sAhat,neg_gravity);
+  
+}
+
+
+void OnBody::Setup(){  
+  
+  // get the direction of the joint
+  if( system_joint->GetBody2() == system_body ) joint_dir = FORWARD;
+  else joint_dir = BACKWARD;
+
+  // set the function pointers for the joint direction
+  if( joint_dir == FORWARD ){    
+    kinfun = &Joint::ForwardKinematics;
+    updatesP = &Joint::UpdateForward_sP;
+    gamma = system_joint->GetR12(); 
+    pk_C_k = system_joint->Get_pkCk();
+  } else {
+    kinfun = &Joint::BackwardKinematics;
+    updatesP = &Joint::UpdateBackward_sP;
+    gamma = system_joint->GetR21();
+    pk_C_k = system_joint->Get_kCpk();
+  }
+
+  // initialize variables and dimensions
+
+  // sI
+  OnPopulateSI(system_body->inertia, system_body->mass, sI);
+	
+  // sP
+  if( joint_dir == FORWARD )
+    sP = system_joint->GetForward_sP();
+  else
+    sP = system_joint->GetBackward_sP();
+
+  // dimension these quantities
+  sM = T(sP)*sP;
+  sMinv = sM;
+  sPsMinv = sP;
+  sIhatsP = sP;
+  
+
+  // get the state and state derivative column matrix pointers
+  q = system_joint->GetQ();
+  u = system_joint->GetU();
+  qdot = system_joint->GetQdot();  
+  udot = system_joint->GetUdot();
+  qdotdot = system_joint->GetQdotdot();
+  }
+
+void OnBody::RecursiveKinematics(){
+  OnBody* child;
+  // Perform local kinematics recursively outward
+  ListElement<OnBody>* ele = children.GetHeadElement();
+  while(ele){
+    child = ele->value;    
+    child->LocalKinematics();
+    child->RecursiveKinematics();
+    Mat3x3 result=*child->pk_C_k;           
+    ele = ele->next;
+  }
+  
+}
+
+void OnBody::RecursiveTriangularization(){
+  OnBody* child;
+
+  // Perform local triangularization recursively inward
+  ListElement<OnBody>* ele = children.GetHeadElement();
+  while(ele){
+    child = ele->value;
+    child->RecursiveTriangularization();
+    //child->LocalTriangularization();
+    ele = ele->next;
+  }
+
+}
+
+void OnBody::RecursiveForwardSubstitution(){
+  OnBody* child;
+  // Perform local forward substitution recursively outward
+  ListElement<OnBody>* ele = children.GetHeadElement();
+  while(ele){
+    child = ele->value;
+   // child->LocalForwardSubstitution();
+    child->RecursiveForwardSubstitution();
+    ele = ele->next;
+  }
+}
+
+void OnBody::LocalKinematics(){
+  // do the directional kinematics
+  (system_joint->*kinfun)();
+  (system_joint->*updatesP)( sP );
+  OnPopulateSC( *gamma, *pk_C_k, sSC );      
+}
+
+Mat3x3 OnBody::GetN_C_K(){
+Mat3x3 nck=system_body->n_C_k;
+return nck;
+}
+
+ 
+int OnBody::GetBodyID(){
+int ID=system_body->GetID();
+return ID;
+}
+
+Vect3 OnBody::LocalCart(){  
+  (system_joint->*kinfun)();  
+  Vect3 RR=system_body->r;  
+  return RR;
+}
+
+  
+  
+void OnBody::LocalTriangularization(Vect3& Torque, Vect3& Force){	  
+
+	Vect3 Iw,wIw,Ialpha,wIwIalpha,ma,Bforce,Bforce_ma,Btorque,Btorque_wIwIalpha;
+  Iw.Zeros();wIw.Zeros();wIwIalpha.Zeros();ma.Zeros();
+	Bforce.Zeros();Bforce_ma.Zeros();Btorque.Zeros();Btorque_wIwIalpha.Zeros();
+     
+	FastMult(system_body->inertia,system_body->omega_k,Iw);  
+	FastCross(Iw,system_body->omega_k,wIw);  
+  
+	FastMult(system_body->inertia, system_body->alpha_t, Ialpha);    
+	FastSubt(wIw,Ialpha,wIwIalpha); 
+	FastMult(-system_body->mass,system_body->a_t,ma);    
+	
+	
+	Mat3x3 k_C_n=T(system_body->n_C_k);      
+	Bforce=k_C_n*Force;
+	Btorque=k_C_n*Torque;  
+	
+	FastAdd(Bforce,ma,Bforce_ma);       
+	FastAdd(Btorque,wIwIalpha,Btorque_wIwIalpha);	  
+	OnPopulateSVect(Btorque_wIwIalpha,Bforce_ma,sF);
+  
+  
+	sIhat = sI;    
+	sFhat = sF;     
+	Mat6x6 sPsMinvsPT;
+	Mat6x6 sIhatsPsMsPT;
+	Mat6x6 sUsIhatsPsMsPT;
+	Mat6x6 sTsIhat;
+	Mat6x6 sTsIhatsSCT;
+	Vect6 sTsFhat;
+	Mat6x6 sU;
+	sU.Identity();  
+  
+	OnBody* child;
+	ListElement<OnBody>* ele = children.GetHeadElement();
+  
+	while(ele){
+		child = ele->value;
+    
+		FastMultT(child->sIhatsP,child->sPsMinv,sIhatsPsMsPT); 
+		FastSubt(sU,sIhatsPsMsPT,sUsIhatsPsMsPT);              
+		FastMult(child->sSC,sUsIhatsPsMsPT,child->sT);         
+        
+		FastMult(child->sT,child->sIhat,sTsIhat);
+		FastMultT(sTsIhat,child->sSC,sTsIhatsSCT); 
+		FastAdd(sIhat,sTsIhatsSCT,sIhat);
+    
+		FastMult(child->sT,child->sFhat,sTsFhat);
+		FastAdd(sFhat,sTsFhat,sFhat);            
+		ele = ele->next;
+	}  
+  
+	FastMult(sIhat,sP,sIhatsP);   
+	FastTMult(sP,sIhatsP,sM);       
+	sMinv=SymInverse(sM);    
+	FastMult(sP,sMinv,sPsMinv);	
+}
+
+void OnBody::LocalForwardSubstitution(){  
+	Vect6 sSCTsAhat;
+	Vect6 sIhatsSCTsAhat;
+	Vect6 sFsIhatsSCTsAhat;
+	Vect6 sPudot;
+	int type = system_joint->GetType();
+	if(type == 1){
+		FastTMult(sSC,parent->sAhat,sSCTsAhat);
+		FastMult(sIhat,sSCTsAhat,sIhatsSCTsAhat);       
+		FastSubt(sFhat,sIhatsSCTsAhat,sFsIhatsSCTsAhat);
+		FastTMult(sPsMinv,sFsIhatsSCTsAhat,*udot);		
+  
+		ColMatrix result1=*udot;      
+		ColMatrix result2=*qdot;
+		ColMatrix result3=*q;
+		int num=result1.GetNumRows();
+		ColMatrix result4(num+1);
+		result4.Zeros();		
+		EPdotdot_udot(result1, result2, result3, result4);
+		FastAssign(result4, *qdotdot);    
+		FastMult(sP,*udot,sPudot);      
+		FastAdd(sSCTsAhat,sPudot,sAhat);		
+	}
+	else if (type == 4){		
+		FastTMult(sSC,parent->sAhat,sSCTsAhat);
+		FastMult(sIhat,sSCTsAhat,sIhatsSCTsAhat);       
+		FastSubt(sFhat,sIhatsSCTsAhat,sFsIhatsSCTsAhat);
+		FastTMult(sPsMinv,sFsIhatsSCTsAhat,*udot);
+		
+		ColMatrix result1=*udot;      		
+		ColMatrix result2=*qdot;
+		ColMatrix result3=*q;
+		int num=result1.GetNumRows();
+		ColMatrix result4(num+1);
+		result4.Zeros();
+		
+		EPdotdot_udot(result1, result2, result3, result4);
+		FastAssign(result4, *qdotdot);    
+		FastMult(sP,*udot,sPudot);      
+		FastAdd(sSCTsAhat,sPudot,sAhat);
+	}	
+	else if (type == 5){		
+		FastTMult(sSC,parent->sAhat,sSCTsAhat);
+		FastMult(sIhat,sSCTsAhat,sIhatsSCTsAhat);       
+		FastSubt(sFhat,sIhatsSCTsAhat,sFsIhatsSCTsAhat);
+		FastTMult(sPsMinv,sFsIhatsSCTsAhat,*udot);				
+		ColMatrix temp_u = *udot;
+		
+		ColMatrix result1(3);		
+		result1(1)=0.0;
+		result1(2)=temp_u(1);      		
+		result1(3)=temp_u(2); 		
+		ColMatrix result2=*qdot;
+		ColMatrix result3=*q;
+		int num=result1.GetNumRows();
+		ColMatrix result4(num+1);
+		result4.Zeros();
+		
+		EPdotdot_udot(result1, result2, result3, result4);		
+		FastAssign(result4, *qdotdot);    
+		FastMult(sP,*udot,sPudot);      
+		FastAdd(sSCTsAhat,sPudot,sAhat);
+	}
+	else if (type == 6){		
+		FastTMult(sSC,parent->sAhat,sSCTsAhat);
+		FastMult(sIhat,sSCTsAhat,sIhatsSCTsAhat);       
+		FastSubt(sFhat,sIhatsSCTsAhat,sFsIhatsSCTsAhat);
+		FastTMult(sPsMinv,sFsIhatsSCTsAhat,*udot);				
+		ColMatrix temp_u = *udot;
+		int tt = temp_u.GetNumRows() + 1;
+		ColMatrix result1(tt);				
+		result1(1)=0.0;
+		for (int k =2; k<=tt; k++){
+			result1(k)=temp_u(k-1);      				
+		}			
+		ColMatrix result2=*qdot;
+		ColMatrix result3=*q;
+		int num=result1.GetNumRows();
+		ColMatrix result4(num+1);
+		result4.Zeros();
+		
+		EPdotdot_udot(result1, result2, result3, result4);		
+		FastAssign(result4, *qdotdot);    
+		FastMult(sP,*udot,sPudot);      
+		FastAdd(sSCTsAhat,sPudot,sAhat);
+	}		
+	else{
+		cout<<"Joint type not recognized in onbody.cpp LocalForwardSubsitution() "<<type<<endl;
+		exit(-1);
+	}
+	CalculateAcceleration();
+	
+}
+
+
+void OnBody::CalculateAcceleration(){
+}
diff --git a/lib/poems/onbody.h b/lib/poems/onbody.h
new file mode 100644
index 000000000..d9923773c
--- /dev/null
+++ b/lib/poems/onbody.h
@@ -0,0 +1,99 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: onbody.h                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef ONBODY_H
+#define ONBODY_H
+
+#include "poemslist.h"
+#include "matrix.h"
+#include "vect6.h"
+#include "mat6x6.h"
+
+// emumerated type
+enum Direction {
+  BACKWARD = 0,
+  FORWARD= 1
+};
+
+class Body;
+class InertialFrame;
+class Joint;
+class OnSolver;
+
+class OnBody {
+       Body* system_body;
+       Joint* system_joint;
+       OnBody* parent;
+       List<OnBody> children;
+
+       Direction joint_dir;
+       void (Joint::*kinfun)();          // kinematics function
+       void (Joint::*updatesP)(Matrix&); // sP update function
+       Vect3* gamma;                     // pointer to gamma vector
+       Mat3x3* pk_C_k;                   // pointer to transformation
+
+  
+       Mat6x6 sI;      // spatial inertias
+       Mat6x6 sIhat;   // recursive spatial inertias
+       Mat6x6 sSC;     // spatial shift
+       Mat6x6 sT;      // spatial triangularization
+
+       Vect6 sF;       // spatial forces
+       Vect6 sFhat;    // recursive spatial forces
+       Vect6 sAhat;    // recursive spatial acceleration
+
+       Matrix sP;      // spatial partial velocities
+       Matrix sM;      // triangularized mass matrix diagonal elements
+       Matrix sMinv;   // inverse of sM
+       Matrix sPsMinv;
+       Matrix sIhatsP;
+
+       // states and state derivatives
+       ColMatrix* q;
+       ColMatrix* u;
+       ColMatrix* qdot;
+       ColMatrix* udot;
+       ColMatrix* qdotdot;
+	  
+       ColMatrix* r;       
+       ColMatrix* acc;
+       ColMatrix* ang;
+
+  // friend classes
+  friend class OnSolver;
+  
+
+public: 
+       OnBody();
+       ~OnBody();
+       int RecursiveSetup(InertialFrame* basebody);
+       int RecursiveSetup(int ID, OnBody* parentbody, Joint* sys_joint);
+       void RecursiveKinematics();
+       void RecursiveTriangularization();
+       void RecursiveForwardSubstitution();
+       Mat3x3 GetN_C_K();
+       Vect3 LocalCart();
+       int GetBodyID();
+       void CalculateAcceleration();       
+       void Setup();
+       void SetupInertialFrame();
+       void LocalKinematics();       
+		 void LocalTriangularization(Vect3& Torque, Vect3& Force);
+       void LocalForwardSubstitution();
+};
+
+#endif
diff --git a/lib/poems/onfunctions.cpp b/lib/poems/onfunctions.cpp
new file mode 100644
index 000000000..582ab8cf8
--- /dev/null
+++ b/lib/poems/onfunctions.cpp
@@ -0,0 +1,69 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: onfunction.cpp                                          *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+
+#include "onfunctions.h"
+#include "matrixfun.h"
+#include <iostream>
+using namespace std;
+
+// friend of Vect3 & Vect6
+void OnPopulateSVect(Vect3& angular, Vect3& linear, Vect6& sV){
+  sV.elements[0] = angular.elements[0];
+  sV.elements[1] = angular.elements[1];
+  sV.elements[2] = angular.elements[2];
+  sV.elements[3] = linear.elements[0];
+  sV.elements[4] = linear.elements[1];
+  sV.elements[5] = linear.elements[2];
+}
+
+// friend of Vect3, Mat3x3, & Mat6x6
+void OnPopulateSC(Vect3& gamma, Mat3x3& C, Mat6x6& SC){
+  // the block diagonals
+  
+  // the gamma cross with transform
+  Mat3x3 temp; Mat3x3 temp2;
+  SC.Zeros();
+  temp.Zeros();  
+  temp2.Zeros();
+  //FastTMult(C,gamma,temp);     
+  temp(1,2)= -gamma(3); temp(1,3)= gamma(2); temp(2,1)= gamma(3);
+  temp(2,3)= -gamma(1); temp(3,1)= -gamma(2); temp(3,2)= gamma(1);  
+  FastMult(temp,C,temp2);
+  
+  SC(1,4)=temp2(1,1);   SC(2,4)=temp2(2,1);   SC(3,4)=temp2(3,1);
+  SC(1,5)=temp2(1,2);   SC(2,5)=temp2(2,2);   SC(3,5)=temp2(3,2);
+  SC(1,6)=temp2(1,3);   SC(2,6)=temp2(2,3);   SC(3,6)=temp2(3,3);
+  
+  SC(1,1)=C(1,1);   SC(2,1)=C(2,1);   SC(3,1)=C(3,1);
+  SC(1,2)=C(1,2);   SC(2,2)=C(2,2);   SC(3,2)=C(3,2);
+  SC(1,3)=C(1,3);   SC(2,3)=C(2,3);   SC(3,3)=C(3,3);
+
+  SC(4,4)=C(1,1);   SC(5,4)=C(2,1);   SC(6,4)=C(3,1);
+  SC(4,5)=C(1,2);   SC(5,5)=C(2,2);   SC(6,5)=C(3,2);
+  SC(4,6)=C(1,3);   SC(5,6)=C(2,3);   SC(6,6)=C(3,3);  
+  
+  }
+
+// friend of Mat3x3 & Mat6x6
+void OnPopulateSI(Mat3x3& inertia, double mass, Mat6x6& sI){
+  
+	sI(4,4)=mass; sI(5,5)=mass; sI(6,6)=mass;
+	sI(1,1)=inertia(1,1); sI(1,2)=inertia(1,2); sI(1,3)=inertia(1,3);
+	sI(2,1)=inertia(2,1); sI(2,2)=inertia(2,2); sI(2,3)=inertia(2,3);
+	sI(3,1)=inertia(3,1); sI(3,2)=inertia(3,2); sI(3,3)=inertia(3,3);	
+}
diff --git a/lib/poems/onfunctions.h b/lib/poems/onfunctions.h
new file mode 100644
index 000000000..8a6969409
--- /dev/null
+++ b/lib/poems/onfunctions.h
@@ -0,0 +1,31 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: onfunction.h                                            *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef ONFUNCTIONS_H
+#define ONFUNCTIONS_H
+
+#include "matrices.h"
+
+void OnPopulateSVect(Vect3& angular, Vect3& linear, Vect6& sV);
+void OnPopulateSC(Vect3& gamma, Mat3x3& C, Mat6x6& SC);
+void OnPopulateSI(Mat3x3& inertia, double mass, Mat6x6& sI);
+
+
+void Create_Map(int MM);
+int ICELL(int IX,int IY,int IZ, int MM);
+
+#endif
diff --git a/lib/poems/onsolver.cpp b/lib/poems/onsolver.cpp
new file mode 100644
index 000000000..ad04d7e9e
--- /dev/null
+++ b/lib/poems/onsolver.cpp
@@ -0,0 +1,148 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: onsolver.cpp                                            *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "onsolver.h"
+#include "system.h"
+#include "onbody.h"
+#include "body.h"
+#include "matrixfun.h"
+#include <fstream>
+
+
+using namespace std;
+
+OnSolver::OnSolver(){
+  numbodies = 0;
+  bodyarray = 0;
+  q=0;u=0; qdot=0; udot=0; qdotdot=0;  
+  type = ONSOLVER;
+}
+
+OnSolver::~OnSolver(){
+  DeleteModel();
+}
+
+void OnSolver::DeleteModel(){
+  delete [] bodyarray;
+
+  delete [] q;
+  delete [] u;
+
+  delete [] qdot;
+  delete [] udot; 
+  
+  delete [] qdotdot;
+  
+  numbodies = 0;
+}
+
+void OnSolver::CreateModel(){
+  // delete old model
+  DeleteModel();
+
+  // clear system body IDs (primer for traversal algorithm)
+  system->ClearBodyIDs();
+  
+
+  // error check for inertial frame
+  Body* sysbasebody = system->bodies.GetHeadElement()->value;
+  if( sysbasebody->GetType() != INERTIALFRAME ){
+    cerr << "ERROR: inertial frame not at head of bodies list" << endl;
+    exit(1);
+  }
+
+  // setup the O(n) spanning tree
+  numbodies = inertialframe.RecursiveSetup( (InertialFrame*) sysbasebody );
+  if(!numbodies){
+    cerr << "ERROR: unable to create O(n) model" << endl;
+    exit(1);
+  }
+  
+  
+  
+  bodyarray = new OnBody* [numbodies];
+  
+  CreateTopologyArray(0,&inertialframe);	  
+  
+  CreateStateMatrixMaps();  
+}
+
+int OnSolver::CreateTopologyArray(int num, OnBody* body){
+  int i = num;
+  bodyarray[i] = body;    
+  i++;
+
+  
+  OnBody* child;
+  ListElement<OnBody>* ele = body->children.GetHeadElement();    
+  
+  while(ele){
+    child = ele->value;    
+    i = CreateTopologyArray(i,child);
+    ele = ele->next;        
+  }  
+  return i;  
+}
+
+void OnSolver::CreateStateMatrixMaps(){
+  
+	
+  int numstates=0;
+  for(int i=1;i<numbodies;i++)    
+    numstates += bodyarray[i]->q->GetNumRows();       
+  
+  state.Dim(numstates);
+  statedot.Dim(numstates);
+  statedoubledot.Dim(numstates); 
+
+  
+  int count=0;
+  
+  for(int i=1;i<numbodies;i++){
+	  for(int j=0;j<bodyarray[i]->q->GetNumRows();j++){
+		  state.SetElementPointer(count,bodyarray[i]->q->GetElementPointer(j));      
+		  statedot.SetElementPointer(count,bodyarray[i]->qdot->GetElementPointer(j));        	
+		  statedoubledot.SetElementPointer(count,bodyarray[i]->qdotdot->GetElementPointer(j));       
+		  count++;      
+	  }        
+  }
+}
+
+
+void OnSolver::Solve(double time, Matrix& FF){
+	system->SetTime(time);
+	for(int i=1;i<numbodies;i++)
+		bodyarray[i]->LocalKinematics();
+	
+	Vect3 Torque; Torque.Zeros();
+	Vect3 Force; Force.Zeros();
+	
+	for(int i=numbodies-1;i>0;i--){
+		Torque(1)=FF(1,i);     
+		Torque(2)=FF(2,i);
+		Torque(3)=FF(3,i);		
+		Force(1)=FF(4,i);     
+		Force(2)=FF(5,i);
+		Force(3)=FF(6,i);   
+		bodyarray[i]->LocalTriangularization(Torque,Force);
+	}
+   	
+	for(int i=1;i<numbodies;i++){
+		bodyarray[i]->LocalForwardSubstitution();
+	}  
+}
diff --git a/lib/poems/onsolver.h b/lib/poems/onsolver.h
new file mode 100644
index 000000000..f32b5880a
--- /dev/null
+++ b/lib/poems/onsolver.h
@@ -0,0 +1,51 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: onsolver.h                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef ONSOLVER_H
+#define ONSOLVER_H
+
+#include "solver.h"
+#include "onbody.h"
+#include <fstream>
+
+
+  
+class OnSolver : public Solver {
+       OnBody inertialframe;   
+       int numbodies;
+       OnBody** bodyarray;  
+       ColMatrix** q;		 
+       ColMatrix** qdot;
+		 ColMatrix** qdotdot;
+       ColMatrix** u;
+       ColMatrix** udot;
+       
+       
+       
+       void DeleteModel();
+       int CreateTopologyArray(int i, OnBody* body);
+       void CreateStateMatrixMaps();
+	    void GetType();
+public: 
+       OnSolver();
+       ~OnSolver();
+       void CreateModel();
+       void Solve(double time, Matrix& FF);       
+};
+
+#endif
diff --git a/lib/poems/particle.cpp b/lib/poems/particle.cpp
new file mode 100644
index 000000000..3496bc190
--- /dev/null
+++ b/lib/poems/particle.cpp
@@ -0,0 +1,40 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: particle.cpp                                            *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "particle.h"
+#include "fixedpoint.h"
+
+Particle::Particle(){
+}
+
+Particle::~Particle(){
+}
+
+BodyType Particle::GetType(){
+  return PARTICLE;
+}
+
+bool Particle::ReadInBodyData(std::istream& in){
+  in >> mass;
+  return true;
+}
+
+void Particle::WriteOutBodyData(std::ostream& out){
+  out << mass;
+}
+
diff --git a/lib/poems/particle.h b/lib/poems/particle.h
new file mode 100644
index 000000000..20aa4831e
--- /dev/null
+++ b/lib/poems/particle.h
@@ -0,0 +1,34 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: particle.h                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef PARTICLE_H
+#define PARTICLE_H
+
+#include "body.h"
+
+
+class Particle : public Body  {
+public: 
+  Particle();
+  ~Particle();
+  BodyType GetType();
+  bool ReadInBodyData(std::istream& in);
+  void WriteOutBodyData(std::ostream& out);
+};
+
+#endif
diff --git a/lib/poems/poemslist.h b/lib/poems/poemslist.h
new file mode 100644
index 000000000..28e345a22
--- /dev/null
+++ b/lib/poems/poemslist.h
@@ -0,0 +1,228 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: poemslist.h                                             *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef _POEMSLIST_H_
+#define _POEMSLIST_H_
+
+#include <iostream>
+
+using namespace std;
+
+template<class T> class ListElement{
+public:
+  ListElement<T>* prev;
+  ListElement<T>* next;
+  T* value;
+
+  ListElement();
+  ListElement(T* v);
+  ~ListElement();
+};
+
+template<class S> class List {
+  int numelements;
+  ListElement<S>* head;
+  ListElement<S>* tail;
+public:
+  List();
+  ~List();
+  int GetNumElements();
+  ListElement<S>* GetHeadElement();
+  ListElement<S>* GetTailElement();
+  void Remove(ListElement<S>* ele);
+  ListElement<S>* Append(S* v);
+  ListElement<S>* Prepend(S* v);
+  S** CreateArray();
+  S* operator()(int id);
+  void Append(List<S> * listToAppend);
+  void DeleteValues();
+  void RemoveElementAndDeleteValue(ListElement<S>* ele);  
+  void PrintList();
+};
+
+//
+// ListElement
+//
+
+template<class T> ListElement<T>::ListElement(){
+  next = prev = 0;
+  value = 0;
+};
+
+template<class T> ListElement<T>::ListElement(T* v){
+  next = prev = 0;
+  value = v;
+};
+
+template<class T> ListElement<T>::~ListElement(){
+};
+
+//
+// List
+//
+
+template<class S> List<S>::List(){
+  head = tail = 0;
+  numelements = 0;
+};
+
+template<class S> List<S>::~List(){
+  // delete all list elements
+
+  while(numelements)
+    Remove(tail);
+};
+
+template<class S> void List<S>::Append(List<S> * listToAppend)
+{
+	tail->next = listToAppend->head;
+	listToAppend->head->prev = tail;
+	tail = listToAppend->tail;
+};
+
+template<class S> int List<S>::GetNumElements(){
+  return numelements;
+};
+
+template<class S> ListElement<S>* List<S>::GetHeadElement(){
+  return head;
+};
+
+template<class S> ListElement<S>* List<S>::GetTailElement(){
+	return tail;
+};
+
+
+template<class S> void List<S>::Remove(ListElement<S>* ele){
+  if(!ele){
+    cerr << "ERROR: ListElement to be removed not defined" << endl;
+    exit(0);
+  }
+  if(!numelements){
+    cerr << "ERROR: List is empty" << endl;
+    exit(0);
+  }
+
+  if(ele != head)
+    ele->prev->next = ele->next;
+  else
+    head = ele->next;
+
+  if(ele != tail)
+    ele->next->prev = ele->prev;
+  else
+    tail = ele->prev;
+
+  numelements--;
+  if(ele)
+  delete ele;
+};
+
+template<class S> ListElement<S>* List<S>::Append(S* v){
+  if(!v){
+    cerr << "ERROR: cannot add null Body to list" << endl;
+    exit(0);
+  }
+
+  numelements++;
+  ListElement<S>* ele = new ListElement<S>(v);
+
+  if(numelements==1)
+    head = tail = ele;
+  else{
+	  /*
+    tail->next = ele;
+    ele->prev = tail;
+	 tail = ele;*/
+	  
+	  ele->prev = tail;
+	  tail = ele;	  
+	  ele->prev->next = ele;	  
+	  
+  }    
+  return ele;
+};
+
+template<class S> ListElement<S>* List<S>::Prepend(S* v){
+  if(!v){
+    cerr << "ERROR: cannot add null Body to list" << endl;
+    exit(0);
+  }
+
+  numelements++;
+  ListElement<S>* ele = new ListElement<S>(v);
+
+  if(numelements==1)
+    head = tail = ele;
+  else{
+	  ele->next = head;
+	  head = ele;
+	  ele->next->prev = ele;
+  }
+  return ele;
+};
+
+template<class S> S** List<S>::CreateArray(){
+  S** array = new S* [numelements];
+
+  ListElement<S>* ele = head;
+  for(int i=0;ele != 0;i++){
+    array[i] = ele->value;
+    ele = ele->next;
+  }
+  return array;
+};
+
+template<class S> S* List<S>::operator()(int id){
+  if(id >= numelements){
+    cerr << "ERROR: subscript out of bounds" << endl;
+    exit(0);
+  }
+  
+  ListElement<S>* ele = head;
+  for(int i=0;i<id;i++){
+    ele = ele->next;
+  }
+  
+  return ele->value;
+};
+
+template<class S> void List<S>::DeleteValues(){
+  while(numelements)
+    RemoveElementAndDeleteValue(tail);
+};
+
+template<class S> void List<S>::RemoveElementAndDeleteValue(ListElement<S>* ele){
+  S* v = ele->value;
+  Remove(ele);
+  delete v;
+};
+
+template<class S> void List<S>::PrintList(){
+	cout<<"Printing List "<<endl;
+	ListElement<S>* ele = head;
+	cout<<*(ele->value)<<" ";
+	ele = ele->next;
+	for(int k =2; k<numelements; k++){
+		cout<<*(ele->value)<<" ";	
+		ele = ele->next;
+	}
+	cout<<*(ele->value)<<endl;
+};
+
+
+#endif
diff --git a/lib/poems/poemsnodelib.h b/lib/poems/poemsnodelib.h
new file mode 100644
index 000000000..e1bc4d624
--- /dev/null
+++ b/lib/poems/poemsnodelib.h
@@ -0,0 +1,162 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: poemsnodelib.h                                          *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef NODELIB_H
+#define NODELIB_H
+
+#include <iostream>
+
+using namespace std;
+
+
+TreeNode *GetTreeNode(int item,TreeNode *lptr = NULL,TreeNode *rptr =NULL); 
+
+void FreeTreeNode(TreeNode *p);
+
+void Postorder(TreeNode *t, void visit(TreeNode* &t));
+
+void Preorder (TreeNode *t, void visit(TreeNode* &t));
+
+void CountLeaf (TreeNode *t, int& count);
+
+int Depth (TreeNode *t);
+
+void IndentBlanks(int num);
+
+void PrintTree (TreeNode *t, int level);
+
+
+// ---------------- Global functions-----------------//
+
+// postorder recursive scan of the nodes in a tree
+void Postorder (TreeNode *t, void visit(TreeNode* &t))
+{
+	// the recursive scan terminates on a empty subtree
+	if (t != NULL)
+	{
+		Postorder(t->Left(), visit);	// descend left
+		Postorder(t->Right(), visit);	// descend right
+		visit(t);					// visit the node
+	}
+}
+
+
+// preorder recursive scan of the nodes in a tree
+void Preorder (TreeNode *t, void visit(TreeNode* &t))
+{
+	// the recursive scan terminates on a empty subtree
+	if (t != NULL)
+	{
+		visit(t);				// visit the node
+		Preorder(t->Left(), visit);		// descend left
+		Preorder(t->Right(), visit);	// descend right			
+	}
+}
+
+
+//create TreeNode object with pointer fields lptr and rptr
+// The pointers have default value NULL
+TreeNode *GetTreeNode(int item,TreeNode *lptr,TreeNode *rptr)
+{
+	TreeNode *p;
+
+	// call new to allocate the new node
+	// pass parameters lptr and rptr to the function
+	p = new TreeNode(item, lptr, rptr);
+
+	// if insufficient memory, terminatewith an error message
+	if (p == NULL)
+	{
+		cerr << "Memory allocation failure!\n";
+		exit(1);
+	}
+
+	// return the pointer to the system generated memory
+	return p;
+}
+
+
+// deallocate dynamic memory associated with the node
+
+void FreeTreeNode(TreeNode *p)
+{
+	delete p;
+}
+
+
+// the function uses the postorder scan. a visit
+// tests whether the node is a leaf node
+void CountLeaf (TreeNode *t, int& count)
+{
+	//use postorder descent
+	if(t !=NULL)
+	{
+		CountLeaf(t->Left(), count); // descend left
+		CountLeaf(t->Right(), count); // descend right
+
+		// check if node t is a leaf node (no descendants)
+		// if so, increment the variable count
+		if (t->Left() == NULL && t->Right() == NULL)
+			count++;
+	}
+}
+
+
+// the function uses the postorder scan. it computes the
+// depth of the left and right subtrees of a node and 
+// returns the depth as 1 + max(depthLeft,depthRight).
+// the depth of an empty tree is -1
+int Depth (TreeNode *t)
+{
+	int depthLeft, depthRight, depthval;
+
+	if (t == NULL)
+		depthval = -1;
+	else
+	{
+		depthLeft = Depth(t->Left());
+		depthRight = Depth(t->Right());
+		depthval = 1+(depthLeft > depthRight?depthLeft:depthRight);
+	}
+	return depthval;
+}
+
+void IndentBlanks(int num)
+{
+//	const int indentblock = 6;
+
+	for(int i = 0; i < num; i++)
+		cout << " ";
+}
+
+void PrintTree (TreeNode *t, int level)
+{
+	//print tree with root t, as long as t!=NULL
+	if (t != NULL)
+	{
+		int indentUnit = 5;
+		// print right branch of tree t
+		PrintTree(t->Right(),level + 1);
+		// indent to current level; output node data
+		IndentBlanks(indentUnit*level);
+		cout << t->GetData() << endl;
+		// print left branch of tree t
+		PrintTree(t->Left(),level + 1);
+	}
+}
+#endif
+
diff --git a/lib/poems/poemsobject.cpp b/lib/poems/poemsobject.cpp
new file mode 100644
index 000000000..6db3598f1
--- /dev/null
+++ b/lib/poems/poemsobject.cpp
@@ -0,0 +1,48 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: poemsobject.cpp                                         *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+
+#include "poemsobject.h"
+#include <string>
+
+POEMSObject::POEMSObject(){
+  name = 0;
+  ChangeName("unnamed");
+  ID = -1;
+}
+
+POEMSObject::~POEMSObject(){
+  delete [] name;
+}
+
+void POEMSObject::ChangeName(char* newname){
+  delete [] name;
+  name = new char[strlen(newname)+1];
+  strcpy(name,newname);
+}
+
+char* POEMSObject::GetName(){
+  return name;
+}
+
+int POEMSObject::GetID(){
+  return ID;
+}
+
+void POEMSObject::SetID(int id){
+  ID = id;
+}
diff --git a/lib/poems/poemsobject.h b/lib/poems/poemsobject.h
new file mode 100644
index 000000000..d898ab3c6
--- /dev/null
+++ b/lib/poems/poemsobject.h
@@ -0,0 +1,35 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: poemsobject.cpp                                         *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+
+#ifndef POEMSOBJECT_H
+#define POEMSOBJECT_H
+
+
+class POEMSObject {
+  char* name;
+  int ID;
+public: 
+  POEMSObject();
+  virtual ~POEMSObject();
+  void ChangeName(char* newname);
+  char* GetName();
+  int GetID();
+  void SetID(int id);
+};
+
+#endif
diff --git a/lib/poems/poemstree.h b/lib/poems/poemstree.h
new file mode 100644
index 000000000..e200ed048
--- /dev/null
+++ b/lib/poems/poemstree.h
@@ -0,0 +1,651 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: poemstree.h                                             *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef TREE_H
+#define TREE_H
+
+#include "poemstreenode.h"
+#include "poemsnodelib.h"
+
+//tree.h
+//***********
+//***********
+// constants to indicate the balance factor of a node
+const int leftheavy = -1;
+const int balanced = 0;
+const int rightheavy = 1;
+
+
+
+class Tree{
+protected:
+	// pointer to tree root and node most recently accessed
+	TreeNode *root;
+	TreeNode *current;
+
+	// number of elements in the tree
+	int size;
+
+	//?????? the below are acuatually global functions right now
+	//memory allocation/deallocation
+	//TreeNode *GetTreeNode(const int& item,
+	//				TreeNode *lptr,TreeNode *rptr);
+	//void FreeTreeNode(TreeNode *p);
+
+	// used by the copy constructor and assignment operator
+	TreeNode *CopyTree(TreeNode *t);
+
+	// used by insert and delete method to re-establish
+	// the avl conditions after a node is added or deleted
+	// from a subtree
+	void SingleRotateLeft (TreeNode* &p);
+	void SingleRotateRight (TreeNode* &p);
+	void DoubleRotateLeft (TreeNode* &p);
+	void DoubleRotateRight (TreeNode* &p);
+	void UpdateLeftTree (TreeNode* &p, int &reviseBalanceFactor);
+	void UpdateRightTree (TreeNode* &p, int &reviseBalanceFactor);
+
+
+	// used by destructor, assignment operator and ClearList
+	void DeleteTree(TreeNode *t);
+	void ClearTree(TreeNode * &t);
+
+	// locate a node with data item and its parent in tree
+	// used by Find and Delete
+	TreeNode *FindNode(const int& item, TreeNode* & parent) const;
+
+public:
+	// constructor, destructor
+	Tree(void);
+	//Tree(const Tree& tree);  //????????need to write this
+	~Tree(void)
+	{
+		ClearTree(root);
+	}; //?????????????need to write this
+
+	// assignment operator
+	Tree& operator= (const Tree& rhs);
+
+	// standard list handling methods
+	int Find(int& item);
+	void * GetAuxData(int item) { return (void *)(FindNode(item, root)->GetAuxData());}
+	void Insert(const int& item, const int& data, void * AuxData = NULL);
+	void Delete(const int& item);
+	void AVLInsert(TreeNode* &tree, TreeNode* newNode, int &reviseBalanceFactor);
+	//void AVLDelete(TreeNode* &tree, TreeNode* newNode, int &reviseBalanceFactor);
+	void ClearList(void);
+	//int ListEmpty(void) const;
+	//int ListSize(void) const;
+
+	// tree specific methods
+	void Update(const int& item);
+	TreeNode *GetRoot(void) const;
+
+	//friend class DCASolver;
+};
+
+
+// constructor
+Tree::Tree(void)
+{
+	root = 0; // was NULL
+	current = 0; // was NULL
+	size = 0;
+}
+
+
+
+// return root pointer
+TreeNode *Tree::GetRoot(void) const
+{
+	return root;
+}
+
+
+// assignment operator
+Tree& Tree::operator = (const Tree& rhs)
+{
+	// can't copy a tree to itself
+	if (this == &rhs)
+		return *this;
+
+	// clear current tree. copy new tree into current object
+	ClearList();
+	root = CopyTree(rhs.root);
+
+	// assign current to root and set the tree size
+	current = root;
+	size = rhs.size;
+
+	// return reference to current object
+	return *this;
+}
+
+// search for data item in the tree. if found, return its node
+// address and a pointer to its parent; otherwise, return NULL
+TreeNode *Tree::FindNode(const int& item,
+								   TreeNode* & parent) const
+{
+	// cycle t through the tree starting with root
+	TreeNode *t = root;
+
+	// the parent of the root is NULL
+	parent = NULL;
+
+	// terminate on empty subtree
+	while(t != NULL)
+	{
+		// stop on a match
+		if (item == t->data)
+			break;
+		else
+		{
+			// update the parent pointer and move right of left
+			parent = t;
+			if (item < t->data)
+				t = t->left;
+			else
+				t = t->right;
+		}
+	}
+
+	// return pointer to node; NULL if not found
+	return t;
+}
+
+// search for item. if found, assign the node data to item
+int Tree::Find(int& item)
+{
+	// we use FindNode, which requires a parent parameter
+	TreeNode *parent;
+
+	// search tree for item. assign matching node to current
+	current = FindNode (item, parent);
+
+	// if item found, assign data to item and return True
+	if (current != NULL)
+	{
+		item = current->data;
+		return (int)current->GetAuxData();
+	}
+	else
+		// item not found in the tree. return False
+		return 0;
+}
+
+
+void Tree::Insert(const int& item, const int& data, void * AuxData)
+{
+	// declare AVL tree node pointer; using base class method
+	// GetRoot. cast to larger node and assign root pointer
+	TreeNode *treeRoot, *newNode;
+	 treeRoot = GetRoot();
+
+	// flag used by AVLInsert to rebalance nodes
+	int reviseBalanceFactor = 0;
+
+	// get a new AVL tree node with empty pointer fields
+	newNode = GetTreeNode(item,NULL,NULL);
+	newNode->data = data;
+	newNode->SetAuxData(AuxData);
+	// call recursive routine to actually insert the element
+	AVLInsert(treeRoot, newNode, reviseBalanceFactor);
+
+	// assign new values to data members in the base class
+	root = treeRoot;
+	current = newNode;
+	size++;
+
+
+
+
+
+	////the below is for an unbalance insert algorithm
+	/*
+	// t is the current node in transversal, parent the pervios node
+	TreeNode *t = root, *parent = NULL, *newNode;
+
+	// terminate on empty subtree
+	while(t != NULL)
+	{
+		// update the parent pointer. then go left or right
+		parent = t;
+		if (item < t->data)
+			t = t->left;
+		else
+			t = t->right;
+	}
+
+	// create the new leaf node
+	newNode = GetTreeNode(item,NULL,NULL);
+
+	// if parent is NULL, insert as a root node
+	if (parent == NULL)
+		root = newNode;
+
+	// if item < parent->data. insert as left child
+	else if  (item < parent->data)
+		parent->left = newNode;
+
+	else
+	// if item >= parent->data. insert as right child
+	parent->right = newNode;
+	// assign current as address of new node and increment size
+	current = newNode;
+	size++;
+	*/
+}
+
+void Tree::AVLInsert(TreeNode *&tree, TreeNode *newNode, int &reviseBalanceFactor)
+{
+	// flag indicates change node's balanceFactor will occur
+	int rebalanceCurrNode;
+
+	// scan reaches an empty tree; time to insert the new node
+	if (tree == NULL)
+	{
+		// update the parent to point at newNode
+		tree = newNode;
+
+		// assign balanceFactor = 0 to new node
+		tree->balanceFactor = balanced;
+		// broadcast message; balanceFactor value is modified
+		reviseBalanceFactor = 1;
+	}
+	// recursively move left if new data < current data
+	else if (newNode->data < tree->data)
+	{
+		AVLInsert(tree->left,newNode,rebalanceCurrNode);
+		// check if balanceFactor must be updated.
+		if (rebalanceCurrNode)
+		{
+			// went left from node that is left heavy. will
+			// violate AVL condition; use rotation (case 3)
+			if (tree->balanceFactor == leftheavy)
+				UpdateLeftTree(tree,reviseBalanceFactor);
+
+			// went left from balanced node. will create
+			// node left on the left. AVL condition OK (case 1)
+			else if (tree->balanceFactor == balanced)
+			{
+				tree->balanceFactor = leftheavy;
+				reviseBalanceFactor = 1;
+			}
+			// went left from node that is right heavy. will
+			// balance the node. AVL condition OK (case 2)
+			else
+			{
+				tree->balanceFactor = balanced;
+				reviseBalanceFactor = 0;
+			}
+		}
+        else 
+            // no balancing occurs; do not ask previous nodes
+			reviseBalanceFactor = 0;
+	}
+    // otherwise recursively move right
+    else
+	{
+		AVLInsert(tree->right, newNode, rebalanceCurrNode);
+		// check if balanceFactor must be updated.
+		if (rebalanceCurrNode)
+		{
+			// went right from node that is left heavy. wil;
+			// balance the node. AVL condition OK (case 2)
+			if (tree->balanceFactor == leftheavy)
+			{
+				// scanning right subtree. node heavy on left.
+				// the node will become balanced
+				tree->balanceFactor = balanced;
+				reviseBalanceFactor = 0;
+			}
+			// went right from balanced node. will create
+			// node heavy on the right. AVL condition OK (case 1)
+			else if (tree->balanceFactor == balanced)
+			{
+				// node is balanced; will become heavy on right
+				tree->balanceFactor = rightheavy;
+				reviseBalanceFactor = 1;
+			}
+			// went right from node that is right heavy. will
+			// violate AVL condition; use rotation (case 3)
+			else
+				UpdateRightTree(tree, reviseBalanceFactor);
+		}
+		else
+			reviseBalanceFactor = 0;
+	}
+}
+
+
+void Tree::UpdateLeftTree (TreeNode* &p, int &reviseBalanceFactor)
+{
+	TreeNode *lc;
+
+	lc = p->Left();			// left subtree is also heavy
+	if (lc->balanceFactor == leftheavy)
+	{
+		SingleRotateRight(p);
+		reviseBalanceFactor = 0;
+	}
+	// is right subtree heavy?
+	else if (lc->balanceFactor == rightheavy)
+	{
+		// make a double rotation
+		DoubleRotateRight(p);
+		// root is now balance
+		reviseBalanceFactor = 0;
+	}
+}
+
+void Tree::UpdateRightTree (TreeNode* &p, int &reviseBalanceFactor)
+{
+	TreeNode *lc;
+
+	lc = p->Right();			// right subtree is also heavy
+	if (lc->balanceFactor == rightheavy)
+	{
+		SingleRotateLeft(p);
+		reviseBalanceFactor = 0;
+	}
+	// is left subtree heavy?
+	else if (lc->balanceFactor == leftheavy)
+	{
+		// make a double rotation
+		DoubleRotateLeft(p);
+		// root is now balance
+		reviseBalanceFactor = 0;
+	}
+}
+
+void Tree::SingleRotateRight (TreeNode* &p)
+{
+	// the left subtree of p is heavy
+	TreeNode *lc;
+
+	// assign the left subtree to lc
+	lc = p->Left();
+
+	// update the balance factor for parent and left child
+	p->balanceFactor = balanced;
+	lc->balanceFactor = balanced;
+
+	// any right subtree st of lc must continue as right
+	// subtree of lc. do by making it a left subtree of p
+	p->left = lc->Right();
+
+	// rotate p (larger node) into right subtree of lc
+	// make lc the pivot node
+	lc->right = p;
+	p = lc;
+}
+
+void Tree::SingleRotateLeft (TreeNode* &p)
+{
+	// the right subtree of p is heavy
+	TreeNode *lc;
+
+	// assign the left subtree to lc
+	lc = p->Right();
+
+	// update the balance factor for parent and left child
+	p->balanceFactor = balanced;
+	lc->balanceFactor = balanced;
+
+	// any right subtree st of lc must continue as right
+	// subtree of lc. do by making it a left subtree of p
+	p->right = lc->Left();
+
+	// rotate p (larger node) into right subtree of lc
+	// make lc the pivot node
+	lc->left = p;
+	p = lc;
+}
+
+// double rotation right about node p
+void Tree::DoubleRotateRight (TreeNode* &p)
+{
+	// two subtrees that are rotated
+	TreeNode *lc, *np;
+
+	// in the tree, node(lc) <= node(np) < node(p)
+	lc = p->Left();			// lc is left child of parent
+	np = lc->Right();		// np is right child of lc
+	
+	// update balance factors for p, lc, and np
+	if (np->balanceFactor == rightheavy)
+	{
+		p->balanceFactor = balanced;
+		lc->balanceFactor = rightheavy;
+	}
+	else if (np->balanceFactor == balanced)
+	{
+		p->balanceFactor = balanced;
+		lc->balanceFactor = balanced;
+	}
+	else
+	{
+		p->balanceFactor = rightheavy;
+		lc->balanceFactor = balanced;
+	}	
+	np->balanceFactor = balanced;
+
+	// before np replaces the parent p, take care of subtrees
+	// detach old children and attach new children
+	lc->right = np->Left();
+	np->left = lc;
+	p->left = np->Right();
+	np->right = p;
+	p = np;
+}
+
+void Tree::DoubleRotateLeft (TreeNode* &p)
+{
+	// two subtrees that are rotated
+	TreeNode *lc, *np;
+
+	// in the tree, node(lc) <= node(np) < node(p)
+	lc = p->Right();			// lc is right child of parent
+	np = lc->Left();		// np is left child of lc
+	
+	// update balance factors for p, lc, and np
+	if (np->balanceFactor == leftheavy)
+	{
+		p->balanceFactor = balanced;
+		lc->balanceFactor = leftheavy;
+	}
+	else if (np->balanceFactor == balanced)
+	{
+		p->balanceFactor = balanced;
+		lc->balanceFactor = balanced;
+	}
+	else
+	{
+		p->balanceFactor = leftheavy;
+		lc->balanceFactor = balanced;
+	}	
+	np->balanceFactor = balanced;
+
+	// before np replaces the parent p, take care of subtrees
+	// detach old children and attach new children
+	lc->left = np->Right();
+	np->right = lc;
+	p->right = np->Left();
+	np->left = p;
+	p = np;
+}
+
+// if item is in the tree, delete it
+void Tree::Delete(const int& item)
+{
+	// DNodePtr = pointer to node D that is deleted
+	// PNodePtr = pointer to parent P of node D
+	// RNodePtr = pointer to node R that replaces D
+	TreeNode *DNodePtr, *PNodePtr, *RNodePtr;
+
+	// search for a node containing data value item. obtain its
+	// node adress and that of its parent
+	if ((DNodePtr = FindNode (item, PNodePtr)) == NULL)
+		return;
+
+	// If D has NULL pointer, the 
+	// replacement node is the one on the other branch
+	if (DNodePtr->right == NULL)
+		RNodePtr = DNodePtr->left;
+	else if (DNodePtr->left == NULL)
+		RNodePtr = DNodePtr->right;
+	// Both pointers of DNodePtr are non-NULL
+	else
+	{
+		// Find and unlink replacement node for D
+		// Starting on the left branch of node D,
+		// find node whose data value is the largest of all
+		// nodes whose values are less than the value in D
+		// Unlink the node from the tree
+
+		// PofRNodePtr = pointer to parent of replacement node
+		TreeNode *PofRNodePtr = DNodePtr;
+
+		// frist possible replacement is left child D
+		RNodePtr = DNodePtr->left;
+
+		// descend down right subtree of the left child of D
+		// keeping a record of current node and its parent.
+		// when we stop, we have found the replacement
+		while (RNodePtr->right != NULL)
+		{
+			PofRNodePtr = RNodePtr;
+			RNodePtr = RNodePtr;
+		}
+
+		if (PofRNodePtr == DNodePtr)
+			// left child of deleted node is the replacement
+			// assign right subtree of D to R
+			RNodePtr->right =  DNodePtr->right;
+		else
+		{
+			// we moved at least one node down a right brance
+			// delete replacement node from tree by assigning
+			// its left branc to its parent
+			PofRNodePtr->right = RNodePtr->left;
+
+			// put replacement node in place of DNodePtr.
+			RNodePtr->left = DNodePtr->left;
+			RNodePtr->right = DNodePtr->right;
+		}
+	}
+
+	// complete the link to the parent node
+	// deleting the root node. assign new root
+	if (PNodePtr == NULL)
+		root = RNodePtr;
+	// attach R to the correct branch of P
+	else if (DNodePtr->data < PNodePtr->data)
+		PNodePtr->left = RNodePtr;
+	else
+		PNodePtr->right = RNodePtr;
+
+	// delete the node from memory and decrement list size
+	FreeTreeNode(DNodePtr);  // this says FirstTreeNode in the book, should be a typo
+	size--;
+}
+
+
+
+
+
+// if current node is defined and its data value matches item,
+// assign node value to item; otherwise, insert item in tree
+void Tree::Update(const int& item)
+{
+	if (current !=NULL && current->data == item)
+		current->data = item;
+	else
+		Insert(item, item);
+}
+
+// create duplicate of tree t; return the new root
+TreeNode *Tree::CopyTree(TreeNode *t)
+{
+	// variable newnode points at each new node that is
+	// created by a call to GetTreeNode and later attached to
+	// the new tree. newlptr and newrptr point to the child of
+	// newnode and are passed as parameters to GetTreeNode
+	TreeNode *newlptr, *newrptr, *newnode;
+
+	// stop the recursive scan when we arrive at an empty tree
+	if (t == NULL)
+		return NULL;
+
+	// CopyTree builds a new tree by scanning the nodes of t.
+	// At each node in t, CopyTree checks for a left child. if
+	// present it makes a copy of left child or returns NULL.
+	// the algorithm similarly checks for a right child.
+	// CopyTree builds a copy of node using GetTreeNode and
+	// appends copy of left and right children to node.
+
+	if (t->Left() !=NULL)
+		newlptr = CopyTree(t->Left());
+	else
+		newlptr = NULL;
+
+	if (t->Right() !=NULL)
+		newrptr = CopyTree(t->Right());
+	else
+		newrptr = NULL;
+
+
+	// Build new tree from the bottom up by building the two
+	// children and then building the parent
+	newnode = GetTreeNode(t->data, newlptr, newrptr);
+
+	// return a pointer to the newly created node
+	return newnode;
+}
+
+
+// us the postorder scanning algorithm to traverse the nodes in
+// the tree and delete each node as the vist operation
+void Tree::DeleteTree(TreeNode *t)
+{
+	if (t != NULL)
+	{
+		DeleteTree(t->Left());
+		DeleteTree(t->Right());
+		if (t->GetAuxData() != NULL)
+					delete t->GetAuxData();
+		FreeTreeNode(t);
+	}
+}
+
+// call the function DeleteTree to deallocate the nodes. then
+// set the root pointer back to NULL
+void Tree::ClearTree(TreeNode * &t)
+{
+	DeleteTree(t);
+	t = NULL;		// root now NULL
+}
+
+// delete all nodes in list
+void Tree::ClearList(void)
+{
+	delete root;
+	delete current;
+	size = 0;
+}
+
+#endif
diff --git a/lib/poems/poemstreenode.cpp b/lib/poems/poemstreenode.cpp
new file mode 100644
index 000000000..051e13d6e
--- /dev/null
+++ b/lib/poems/poemstreenode.cpp
@@ -0,0 +1,49 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: poemstreenode.cpp                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "poemstreenode.h"
+
+// constructor; initialize the data and pointer fields
+// The pointer value NULL assigns a empty subtree
+TreeNode::TreeNode (const int & item, TreeNode *lptr,TreeNode *rptr,
+					int balfac):data(item), left(lptr), right(rptr), balanceFactor(balfac)
+{
+}
+
+
+
+// return left
+TreeNode* TreeNode::Left(void)
+{
+	return left;
+}
+
+// return right
+TreeNode* TreeNode::Right(void)
+{
+	return right;
+}
+
+int TreeNode::GetBalanceFactor(void)
+{
+	return balanceFactor;
+}
+
+int TreeNode::GetData(void)
+{
+	return data;
+}
diff --git a/lib/poems/poemstreenode.h b/lib/poems/poemstreenode.h
new file mode 100644
index 000000000..b8f46031a
--- /dev/null
+++ b/lib/poems/poemstreenode.h
@@ -0,0 +1,52 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: poemstreenode.h                                         *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef TREENODE_H
+#define TREENODE_H
+
+//#define NULL 0
+
+
+//Tree depends on TreeNode
+class Tree;
+
+// declares a tree node object for a binary tree
+class TreeNode{
+
+private:
+// points to the left and right children of the node
+	TreeNode *left;
+	TreeNode *right;
+
+	int balanceFactor;
+	int data;
+	void * aux_data;
+public:	
+	// make Tree a friend because it needs access to left and right pointer fields of a node
+	friend class Tree;
+	TreeNode * Left();
+	TreeNode * Right();
+	int GetData();
+	void * GetAuxData() {return aux_data;};
+	void SetAuxData(void * AuxData) {aux_data = AuxData;};
+	int GetBalanceFactor();
+	TreeNode(const int &item, TreeNode *lptr, TreeNode *rptr, int balfac = 0);
+	//friend class DCASolver;
+};
+
+#endif
+
diff --git a/lib/poems/point.cpp b/lib/poems/point.cpp
new file mode 100644
index 000000000..438384473
--- /dev/null
+++ b/lib/poems/point.cpp
@@ -0,0 +1,44 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: point.cpp                                                  *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "points.h"
+
+Point::Point(){
+  position.Zeros();
+}
+Point::~Point(){
+}
+
+bool Point::ReadIn(std::istream& in){
+  return ReadInPointData(in);
+}
+
+void Point::WriteOut(std::ostream& out){
+  out << GetType() << ' ' << GetName() << ' ';
+  WriteOutPointData(out);
+}
+
+Point* NewPoint(int type){
+  switch( PointType(type) )
+  {
+    case FIXEDPOINT :  // A Fixed Point
+      return new FixedPoint();
+    default  :  // error
+      return 0;
+  }
+}
diff --git a/lib/poems/point.h b/lib/poems/point.h
new file mode 100644
index 000000000..746a527cd
--- /dev/null
+++ b/lib/poems/point.h
@@ -0,0 +1,49 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: point.h                                                  *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef POINT_H
+#define POINT_H
+
+#include <iostream>
+#include "poemsobject.h"
+#include "vect3.h"
+
+
+// emumerated type
+enum PointType {
+  FIXEDPOINT = 0
+};
+
+class Point : public POEMSObject {
+public: 
+  Vect3 position;
+
+  Point();   
+  bool ReadIn(std::istream& in);  
+  void WriteOut(std::ostream& out);
+  
+  virtual ~Point();  
+  virtual PointType GetType() = 0;
+  virtual Vect3 GetPoint() = 0;
+  virtual bool ReadInPointData(std::istream& in) = 0;
+  virtual void WriteOutPointData(std::ostream& out) = 0;
+};
+
+// global point functions
+Point* NewPoint(int type);
+
+#endif
diff --git a/lib/poems/points.h b/lib/poems/points.h
new file mode 100644
index 000000000..f8b95c738
--- /dev/null
+++ b/lib/poems/points.h
@@ -0,0 +1,24 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: points.h		                                          *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef POINTS_H
+#define POINTS_H
+
+#include "point.h"
+#include "fixedpoint.h"
+
+#endif
diff --git a/lib/poems/prismaticjoint.cpp b/lib/poems/prismaticjoint.cpp
new file mode 100644
index 000000000..7c01667a8
--- /dev/null
+++ b/lib/poems/prismaticjoint.cpp
@@ -0,0 +1,194 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: prismaticjoint.cpp                                      *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "prismaticjoint.h"
+#include "point.h"
+#include "matrixfun.h"
+#include "body.h"
+#include "fastmatrixops.h"
+
+PrismaticJoint::PrismaticJoint(){
+  q.Dim(1);
+  qdot.Dim(1);
+  u.Dim(1);
+  udot.Dim(1);
+}
+PrismaticJoint::~PrismaticJoint(){
+}
+
+JointType PrismaticJoint::GetType(){
+  return PRISMATICJOINT;
+}
+
+bool PrismaticJoint::ReadInJointData(std::istream& in){
+  in >> axis_pk;
+  axis_k = T(pk_C_ko)*axis_pk;
+
+  // init the constant transforms
+  pk_C_k = pk_C_ko;
+  k_C_pk = T(pk_C_k);
+    
+  return true;
+}
+
+void PrismaticJoint::WriteOutJointData(std::ostream& out){
+  out << axis_pk;
+}
+
+Matrix PrismaticJoint::GetForward_sP(){
+  Vect3 zero;
+  zero.Zeros();
+
+  // sP = [zero;axis]
+  return Stack(zero,axis_k);
+}
+
+void PrismaticJoint::UpdateForward_sP( Matrix& sP){
+  // sP is constant, do nothing.
+}
+
+Matrix PrismaticJoint::GetBackward_sP(){
+  Vect3 zero;
+  zero.Zeros();
+
+  // sP = [zero;axis]
+  return -Stack(zero,axis_pk);
+}
+
+void PrismaticJoint::UpdateBackward_sP( Matrix& sP){
+  // sP is constant, do nothing.
+}
+
+void PrismaticJoint::ComputeForwardTransforms(){
+  ComputeForwardGlobalTransform();
+}
+
+void PrismaticJoint::ComputeBackwardTransforms(){
+  ComputeBackwardGlobalTransform();
+}
+
+void PrismaticJoint::ComputeLocalTransform(){
+  // the transform is constant, do nothing
+}
+
+void PrismaticJoint::ForwardKinematics(){
+  Vect3 result1,result2,result3;
+  Vect3 d_pk;
+
+  // orientations
+  ComputeForwardTransforms();
+
+  // compute position vector r12
+  //r12 = point1->position + axis_pk * q - pk_C_k * point2->position;
+  FastMult(pk_C_k,point2->position,result1);
+  FastMult(q.BasicGet(0),axis_pk,d_pk);
+  FastTripleSumPPM(point1->position,d_pk,result1,r12);
+
+  // compute position vector r21
+  FastNegMult(k_C_pk,r12,r21);
+  
+  // compute global location
+  // body2->r = body1->r + body1->n_C_k * r12;
+  FastMult(body1->n_C_k,r12,result1);
+  FastAdd(body1->r,result1,body2->r);
+
+  // compute qdot (for Prismatic joint qdot = u)
+  // qdot = u
+  FastAssign(u,qdot);
+
+  // angular velocities
+  //body2->omega = body1->omega;
+  //body2->omega_k = T(pk_C_k) * body1->omega_k;
+  FastAssign(body1->omega,body2->omega);
+  FastMult(k_C_pk,body1->omega_k,body2->omega_k);
+  
+  // compute velocities
+  Vect3 pk_v_k;
+  Vect3 wxgamma;
+  FastMult(u.BasicGet(0),axis_k,pk_v_k);
+  FastMult(k_C_pk,body1->v_k,result1);
+  FastCross(body2->omega_k,r12,wxgamma);
+  FastTripleSum(result1,pk_v_k,wxgamma,body2->v_k);
+  FastMult(body2->n_C_k,body2->v_k,body2->v);
+
+  // compute state explicit angular acceleration
+  FastMult(k_C_pk,body1->alpha_t,body2->alpha_t);
+
+  // compute state explicit acceleration
+  FastCross(r21,body1->alpha_t,result1);
+  FastAdd(body1->a_t,result1,result2);
+  FastMult(k_C_pk,result2,result1);
+
+  FastCross(body2->omega_k,pk_v_k,result2);
+  FastMult(2.0,result2,result3);
+  FastCross(body2->omega_k,wxgamma,result2);
+  FastTripleSum(result1,result2,result3,body2->a_t);
+}
+
+void PrismaticJoint::BackwardKinematics(){
+  Vect3 result1,result2,result3;
+  Vect3 d_k;
+
+  // orientations
+  ComputeBackwardTransforms();
+
+  // compute position vector r21
+  //r21 = point2->position + axis_k * q - k_C_pk * point1->position;
+  FastMult(k_C_pk,point1->position,result1);
+  FastMult(-q.BasicGet(0),axis_k,d_k);
+  FastTripleSumPPM(point2->position,d_k,result1,r21);
+
+  // compute position vector r12
+  FastNegMult(pk_C_k,r21,r12);
+
+  // compute global location
+  // body1->r = body2->r + body2->n_C_k * r21;
+  FastMult(body2->n_C_k,r21,result1);
+  FastAdd(body2->r,result1,body1->r);
+
+  // compute qdot (for Prismatic joint qdot = u)
+  // qdot = u
+  FastAssign(u,qdot);
+
+  // angular velocities
+  //body1->omega = body2->omega;
+  //body1->omega_k = pk_C_k * body2->omega_k;
+  FastAssign(body2->omega,body1->omega);
+  FastMult(pk_C_k,body2->omega_k,body1->omega_k);
+
+  // compute velocities
+  Vect3 k_v_pk;
+  Vect3 wxgamma;
+  FastMult(-u.BasicGet(0),axis_pk,k_v_pk);
+  FastMult(pk_C_k,body2->v_k,result1);
+  FastCross(body1->omega_k,r21,wxgamma);
+  FastTripleSum(result1,k_v_pk,wxgamma,body1->v_k);
+  FastMult(body1->n_C_k,body1->v_k,body1->v);
+
+  // compute state explicit angular acceleration
+  FastMult(pk_C_k,body2->alpha_t,body1->alpha_t);
+
+  // compute state explicit acceleration
+  FastCross(r12,body2->alpha_t,result1);
+  FastAdd(body2->a_t,result1,result2);
+  FastMult(pk_C_k,result2,result1);
+
+  FastCross(body1->omega_k,k_v_pk,result2);
+  FastMult(2.0,result2,result3);
+  FastCross(body1->omega_k,wxgamma,result2);
+  FastTripleSum(result1,result2,result3,body1->a_t);
+}
diff --git a/lib/poems/prismaticjoint.h b/lib/poems/prismaticjoint.h
new file mode 100644
index 000000000..17cf050a7
--- /dev/null
+++ b/lib/poems/prismaticjoint.h
@@ -0,0 +1,47 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: prismaticjoint.cpp                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef PRISMATICJOINT_H
+#define PRISMATICJOINT_H
+
+#include "joint.h"
+#include "vect3.h"
+#include "mat3x3.h"
+
+
+
+class PrismaticJoint : public Joint  {
+  Vect3 axis_pk; // unit vector in body1 basis
+  Vect3 axis_k;  // unit vector in body2 basis
+public:
+  PrismaticJoint();
+  ~PrismaticJoint();
+  JointType GetType();
+  bool ReadInJointData(std::istream& in);
+  void WriteOutJointData(std::ostream& out);
+  Matrix GetForward_sP();
+  Matrix GetBackward_sP();
+  void UpdateForward_sP( Matrix& sP);
+  void UpdateBackward_sP( Matrix& sP);
+  void ComputeForwardTransforms();
+  void ComputeBackwardTransforms();
+  void ComputeLocalTransform();
+  void ForwardKinematics();
+  void BackwardKinematics();
+};
+
+#endif
diff --git a/lib/poems/revolutejoint.cpp b/lib/poems/revolutejoint.cpp
new file mode 100644
index 000000000..ec5b1bec0
--- /dev/null
+++ b/lib/poems/revolutejoint.cpp
@@ -0,0 +1,219 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: revolutejoint.cpp                                        *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "revolutejoint.h"
+#include "point.h"
+#include "matrixfun.h"
+#include "body.h"
+#include "fastmatrixops.h"
+
+RevoluteJoint::RevoluteJoint(){
+  DimQandU(1);
+  Vect3 axis;
+  axis.Zeros();
+  axis(3) = 1;
+  SetAxisPK(axis);
+}
+
+RevoluteJoint::~RevoluteJoint(){
+}
+
+JointType RevoluteJoint::GetType(){
+  return REVOLUTEJOINT;
+}
+
+void RevoluteJoint::SetAxisK(VirtualMatrix& axis){
+  axis_k = axis;
+  axis_pk = pk_C_ko*axis_k;
+}
+
+void RevoluteJoint::SetAxisPK(VirtualMatrix& axis){
+  axis_pk = axis;
+  axis_k = T(pk_C_ko)*axis_pk;
+}
+
+bool RevoluteJoint::ReadInJointData(std::istream& in){
+  Vect3 axis;
+  in >> axis;
+  SetAxisPK(axis);
+  return true;
+}
+
+void RevoluteJoint::WriteOutJointData(std::ostream& out){
+  out << axis_pk;
+}
+
+Matrix RevoluteJoint::GetForward_sP(){
+  Vect3 v_kk;
+
+  // v_kk = axis x r
+  FastCross(point2->position,axis_k,v_kk);
+
+  // sP = [axis;v_kk]
+  return Stack(axis_k,v_kk);
+}
+
+void RevoluteJoint::UpdateForward_sP( Matrix& sP){
+  // sP is constant, do nothing.
+}
+
+Matrix RevoluteJoint::GetBackward_sP(){
+  Vect3 v_kk;
+
+  // v_kk = axis x r
+  FastCross(point1->position,axis_pk,v_kk);
+
+  // sP = [axis;v_kk]
+  return -Stack(axis_pk,v_kk);;
+}
+
+void RevoluteJoint::UpdateBackward_sP( Matrix& sP){
+  // sP is constant, do nothing.
+}
+
+void RevoluteJoint::ComputeLocalTransform(){
+  Mat3x3 ko_C_k;
+  FastSimpleRotation(axis_k,q.BasicGet(0),ko_C_k);
+  // pk_C_k = pk_C_ko * ko_C_k;
+  FastMult(pk_C_ko,ko_C_k,pk_C_k);
+}
+
+void RevoluteJoint::ForwardKinematics(){
+  Vect3 result1,result2,result3,result4,result5;
+  Vect3 pk_w_k;
+
+  // orientations
+  ComputeForwardTransforms();
+
+  // compute position vector r12
+  //r12 = point1->position - pk_C_k * point2->position;
+  FastMult(pk_C_k,point2->position,result1); 
+  FastSubt(point1->position,result1,r12);// Jacks comment: needs flipping!!!
+
+  // compute position vector r21
+  FastNegMult(k_C_pk,r12,r21);
+
+  // compute global location
+  // body2->r = body1->r + body1->n_C_k * r12;
+  FastMult(body1->n_C_k,r12,result1);
+  FastAdd(body1->r,result1,body2->r);
+
+  // compute qdot (for revolute joint qdot = u)
+  // qdot = u
+  FastAssign(u,qdot);
+
+  // angular velocities
+  //body2->omega = body1->omega + body1->n_C_k * axis_pk * u;
+  //pk_w_k = axis_k * u;
+  //body2->omega_k = T(pk_C_k) * body1->omega_k + pk_w_k;
+  double u_double = u.BasicGet(0);
+  FastMult(u_double,axis_pk,result1);
+  FastMult(body1->n_C_k,result1,result2);
+  FastAdd(body1->omega,result2,body2->omega);
+  FastMult(u_double,axis_k,pk_w_k);
+  FastTMult(pk_C_k,body1->omega_k,result1);
+  FastAdd(result1,pk_w_k,body2->omega_k);
+
+  // compute velocities
+  FastCross(body1->omega_k,r12,result1);
+  FastCross(point2->position,pk_w_k,result2);
+  FastAdd(body1->v_k,result1,result3);
+  FastTMult(pk_C_k,result3,result4);
+  FastAdd(result2,result4,body2->v_k);
+  FastMult(body2->n_C_k,body2->v_k,body2->v);
+
+  // compute state explicit angular acceleration
+  FastCross(body2->omega_k,pk_w_k,result1);
+  FastTMult(pk_C_k,body1->alpha_t,result2);
+  FastAdd(result1,result2,body2->alpha_t);
+
+  // compute state explicit acceleration
+  FastCross(body1->alpha_t,point1->position,result1);
+  FastCross(body1->omega_k,point1->position,result2);
+  FastCross(body1->omega_k,result2,result3);
+  FastTripleSum(body1->a_t,result1,result3,result4);
+  FastTMult(pk_C_k,result4,result5);
+
+  FastCross(point2->position,body2->alpha_t,result1);
+  FastCross(point2->position,body2->omega_k,result2);
+  FastCross(body2->omega_k,result2,result3);
+
+  FastTripleSum(result5,result1,result3,body2->a_t);
+}
+
+void RevoluteJoint::BackwardKinematics(){
+  Vect3 result1,result2,result3,result4,result5;
+  Vect3 k_w_pk;
+
+  // orientations
+  ComputeBackwardTransforms();
+
+  // compute position vector r21
+  //r21 = point2->position - k_C_pk * point1->position;
+  FastMult(k_C_pk,point1->position,result1);
+  FastSubt(point2->position,result1,r21);
+
+  // compute position vector r21
+  FastNegMult(pk_C_k,r21,r12);
+
+  // compute global location
+  // body1->r = body2->r + body2->n_C_k * r21;
+  FastMult(body2->n_C_k,r21,result1);
+  FastAdd(body2->r,result1,body1->r);
+
+  // compute qdot (for revolute joint qdot = u)
+  // qdot = u
+  FastAssign(u,qdot);
+
+  // angular velocities
+  //body1->omega = body2->omega - body2->n_C_k * axis_k * u;
+  //k_w_pk = - axis_pk * u;
+  //body1->omega_k = pk_C_k * body2->omega_k + k_w_pk;
+  double u_double = u.BasicGet(0);
+  FastMult(-u_double,axis_k,result1);
+  FastMult(body2->n_C_k,result1,result2);
+  FastAdd(body2->omega,result2,body1->omega);
+  FastMult(-u_double,axis_pk,k_w_pk);
+  FastMult(pk_C_k,body2->omega_k,result1);
+  FastAdd(result1,k_w_pk,body1->omega_k);
+
+  // compute velocities
+  FastCross(body2->omega_k,r21,result1);
+  FastCross(point1->position,k_w_pk,result2);
+  FastAdd(body2->v_k,result1,result3);
+  FastMult(pk_C_k,result3,result4);
+  FastAdd(result2,result4,body1->v_k);
+  FastMult(body1->n_C_k,body1->v_k,body1->v);
+
+  // compute state explicit angular acceleration
+  FastCross(body1->omega_k,k_w_pk,result1);
+  FastMult(pk_C_k,body2->alpha_t,result2);
+  FastAdd(result1,result2,body1->alpha_t);
+
+  // compute state explicit acceleration
+  FastCross(body2->alpha_t,point2->position,result1);
+  FastCross(body2->omega_k,point2->position,result2);
+  FastCross(body2->omega_k,result2,result3);
+  FastTripleSum(body2->a_t,result1,result3,result4);
+  FastMult(pk_C_k,result4,result5);
+
+  FastCross(point1->position,body1->alpha_t,result1);
+  FastCross(point1->position,body1->omega_k,result2);
+  FastCross(body1->omega_k,result2,result3);
+
+  FastTripleSum(result5,result1,result3,body1->a_t);
+}
diff --git a/lib/poems/revolutejoint.h b/lib/poems/revolutejoint.h
new file mode 100644
index 000000000..478d48dbb
--- /dev/null
+++ b/lib/poems/revolutejoint.h
@@ -0,0 +1,47 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: revolutejoint.h                                         *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef REVOLUTEJOINT_H
+#define REVOLUTEJOINT_H
+
+#include "joint.h"
+#include "vect3.h"
+#include "mat3x3.h"
+
+
+
+class RevoluteJoint : public Joint  {
+  Vect3 axis_pk; // unit vector in body1 basis
+  Vect3 axis_k;  // unit vector in body2 basis
+public: 
+  RevoluteJoint();
+  ~RevoluteJoint();
+  JointType GetType();
+  void SetAxisK(VirtualMatrix& axis);
+  void SetAxisPK(VirtualMatrix& axis);
+  bool ReadInJointData(std::istream& in);
+  void WriteOutJointData(std::ostream& out);
+  Matrix GetForward_sP();
+  Matrix GetBackward_sP();
+  void UpdateForward_sP( Matrix& sP);
+  void UpdateBackward_sP( Matrix& sP);
+  void ComputeLocalTransform();
+  void ForwardKinematics();
+  void BackwardKinematics();
+};
+
+#endif
diff --git a/lib/poems/rigidbody.cpp b/lib/poems/rigidbody.cpp
new file mode 100644
index 000000000..3ac424f9e
--- /dev/null
+++ b/lib/poems/rigidbody.cpp
@@ -0,0 +1,39 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: rigidbody.cpp                                           *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "rigidbody.h"
+#include "fixedpoint.h"
+
+using namespace std;
+
+RigidBody::RigidBody(){
+}
+RigidBody::~RigidBody(){
+}
+
+BodyType RigidBody::GetType(){
+  return RIGIDBODY;
+}
+
+bool RigidBody::ReadInBodyData(istream& in){
+  in >> mass >> inertia;
+  return true;
+}
+
+void RigidBody::WriteOutBodyData(ostream& out){
+  out << mass << ' ' << inertia;
+}
diff --git a/lib/poems/rigidbody.h b/lib/poems/rigidbody.h
new file mode 100644
index 000000000..0bb2a3ece
--- /dev/null
+++ b/lib/poems/rigidbody.h
@@ -0,0 +1,32 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: rigidbody.h                                             *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef RIGIDBODY_H
+#define RIGIDBODY_H
+
+#include "body.h"
+
+class RigidBody : public Body  {
+public: 
+  RigidBody();
+  ~RigidBody();
+  BodyType GetType();
+  bool ReadInBodyData(std::istream& in);
+  void WriteOutBodyData(std::ostream& out);
+};
+
+#endif
diff --git a/lib/poems/rowmatrix.cpp b/lib/poems/rowmatrix.cpp
new file mode 100644
index 000000000..f44313765
--- /dev/null
+++ b/lib/poems/rowmatrix.cpp
@@ -0,0 +1,175 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: rowmatrix.cpp                                           *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "rowmatrix.h"
+#include "colmatrix.h"
+#include <iostream>
+
+using namespace std;
+
+RowMatrix::RowMatrix(){
+  numcols = 0;
+  elements = 0;
+}
+
+RowMatrix::~RowMatrix(){
+  delete [] elements;
+}
+
+RowMatrix::RowMatrix(const RowMatrix& A){  // copy constructor
+  numcols = 0;
+  elements = 0;
+  Dim(A.numcols);
+  for(int i=0;i<numcols;i++)
+    elements[i] = A.elements[i];
+}
+
+RowMatrix::RowMatrix(const VirtualRowMatrix& A){  // copy constructor
+  numcols = 0;
+  elements = 0;
+  Dim(A.GetNumCols());
+  for(int i=0;i<numcols;i++)
+    elements[i] = A.BasicGet(i);
+}
+
+RowMatrix::RowMatrix(const VirtualMatrix& A){  // copy constructor
+  if( A.GetNumRows() != 1 ){
+    cerr << "error trying to write a 2D matrix to a collumn" << endl;
+    exit(1);
+  }
+  numcols = 0;
+  elements = 0;
+  Dim(A.GetNumCols());
+  for(int i=0;i<numcols;i++)
+    elements[i] = A.BasicGet(i,0);
+}
+
+RowMatrix::RowMatrix(int n){  // size constructor
+  numcols = 0;
+  elements = 0;
+  Dim(n);
+}
+
+void RowMatrix::Dim(int n){
+  delete [] elements;
+  numcols = n;
+  elements = new double [n];
+}
+
+void RowMatrix::Const(double value){
+  for(int i=0;i<numcols;i++)
+    elements[i] = value;
+}
+
+double& RowMatrix::operator_1int (int i){ // array access
+  if((i>numcols) || (i<1)){
+    cerr << "matrix index invalid in operator ()" << endl;
+    exit(1);
+  }
+  return elements[i-1];
+}
+
+double RowMatrix::Get_1int(int i) const{
+  if((i>numcols) || (i<1)){
+    cerr << "matrix index exceeded in Get" << endl;
+    exit(1);
+  }
+  return elements[i-1];
+}
+
+void RowMatrix::Set_1int(int i, double value){
+  if((i>numcols) || (i<1)){
+    cerr << "matrix index exceeded in Set" << endl;
+    exit(1);
+  }
+  elements[i-1] = value;
+}
+
+double RowMatrix::BasicGet_1int(int i) const{
+  return elements[i];
+}
+
+void RowMatrix::BasicSet_1int(int i, double value){
+  elements[i] = value;
+}
+
+void RowMatrix::BasicIncrement_1int(int i, double value){
+  elements[i] += value;
+}
+
+MatrixType RowMatrix::GetType() const{
+  return ROWMATRIX;
+}
+
+istream& RowMatrix::ReadData(istream& c){
+  int n;
+  c >> n;
+  Dim(n);
+  for(int i=0;i<n;i++)
+    c >> elements[i];
+
+  return c;
+}
+
+ostream& RowMatrix::WriteData(ostream& c) const{  //output
+  c << numcols << ' ';
+  for(int i=0;i<numcols;i++)
+    c << elements[i] << ' ';
+  return c;
+}
+
+void RowMatrix::AssignVM(const VirtualMatrix& A){
+  if( A.GetNumRows() != 1 ){
+    cerr << "error trying to write a 2D matrix to a collumn" << endl;
+    exit(1);
+  }
+  Dim( A.GetNumCols() );
+  for(int i=0;i<numcols;i++)
+    elements[i] = A.BasicGet(0,i);
+}
+
+RowMatrix& RowMatrix::operator=(const RowMatrix& A){ // assignment operator
+  Dim(A.numcols);
+  for(int i=0;i<numcols;i++)
+    elements[i] = A.elements[i];
+  return *this;
+}
+
+RowMatrix& RowMatrix::operator=(const VirtualRowMatrix& A){ // overloaded =
+  Dim( A.GetNumCols() );
+  for(int i=0;i<numcols;i++)
+    elements[i] = A.BasicGet(i);
+  return *this;
+}
+
+RowMatrix& RowMatrix::operator=(const VirtualMatrix& A){ // overloaded =
+  if( A.GetNumRows() != 1 ){
+    cerr << "error trying to write a 2D matrix to a collumn" << endl;
+    exit(1);
+  }
+  Dim( A.GetNumCols() );
+  for(int i=0;i<numcols;i++)
+    elements[i] = A.BasicGet(0,i);
+  return *this;
+}
+
+RowMatrix& RowMatrix::operator*=(double b){
+  for(int i=0;i<numcols;i++)
+    elements[i] *= b;
+  return *this;
+}
+
diff --git a/lib/poems/rowmatrix.h b/lib/poems/rowmatrix.h
new file mode 100644
index 000000000..b04113e8e
--- /dev/null
+++ b/lib/poems/rowmatrix.h
@@ -0,0 +1,53 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: rowmatrix.h                                             *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef ROWMATRIX_H
+#define ROWMATRIX_H
+
+#include "virtualrowmatrix.h"
+
+class RowMatrix : public VirtualRowMatrix  {
+  double* elements;
+public:
+  RowMatrix();
+  ~RowMatrix();
+  RowMatrix(const RowMatrix& A);  // copy constructor
+  RowMatrix(const VirtualRowMatrix& A);  // copy constructor
+  RowMatrix(const VirtualMatrix& A);  // copy constructor
+  RowMatrix(int n);  // size constructor
+
+  void Const(double value);
+  double& operator_1int (int i); // array access
+  double Get_1int(int i) const;
+  void Set_1int(int i, double value);
+  double BasicGet_1int(int i) const;
+  void BasicSet_1int(int i, double value);
+  void BasicIncrement_1int(int i, double value);
+  void Dim(int n);
+  MatrixType GetType() const;
+  std::istream& ReadData(std::istream& c);
+  std::ostream& WriteData(std::ostream& c) const;
+
+  void AssignVM(const VirtualMatrix& A);
+  RowMatrix& operator=(const RowMatrix& A); // assignment operator
+  RowMatrix& operator=(const VirtualRowMatrix& A); // overloaded =
+  RowMatrix& operator=(const VirtualMatrix& A); // overloaded =
+  RowMatrix& operator*=(double b);
+};
+
+#endif
diff --git a/lib/poems/solver.cpp b/lib/poems/solver.cpp
new file mode 100644
index 000000000..67f5b607e
--- /dev/null
+++ b/lib/poems/solver.cpp
@@ -0,0 +1,62 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: solver.cpp                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "solver.h"
+#include "system.h"
+#include "matrices.h"
+
+Solver::Solver(){
+
+}
+
+Solver::~Solver(){
+}
+
+void Solver::SetSystem(System* s){
+  system = s;
+  CreateModel();
+}
+
+void Solver::ComputeForces(){
+system->ComputeForces();
+}
+
+SolverType Solver::GetSolverType()
+{
+	return type;
+}
+
+Solver * Solver::GetSolver(SolverType solverToMake) //returning a pointer to a new Solver object of the appropriate type
+{
+	switch((int)solverToMake)
+	{
+		case ONSOLVER: return new OnSolver();
+		default: return NULL;
+	}
+}
+
+ColMatMap* Solver::GetState(){
+  return &state;
+}
+
+ColMatMap* Solver::GetStateDerivative(){
+  return &statedot;
+}
+
+ColMatMap* Solver::GetStateDerivativeDerivative(){
+  return &statedoubledot;
+}
diff --git a/lib/poems/solver.h b/lib/poems/solver.h
new file mode 100644
index 000000000..45564dd1e
--- /dev/null
+++ b/lib/poems/solver.h
@@ -0,0 +1,59 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: solver.h                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:       anderk5@rpi.edu                                     *
+ *_________________________________________________________________________*/
+
+#ifndef SOLVER_H
+#define SOLVER_H
+#include <fstream>
+#include "colmatmap.h"
+#include "matrices.h"
+#include "defines.h"
+
+class System;
+
+class Solver{
+protected:
+  System* system;
+
+  
+  double time;
+  ColMatMap state;
+  ColMatMap statedot;
+  ColMatMap statedoubledot;  
+
+  SolverType type;
+
+virtual void ComputeForces();
+
+public:
+  Solver();
+  virtual ~Solver();
+  void SetSystem(System* s);
+  SolverType GetSolverType();
+  static Solver * GetSolver(SolverType solverToMake);
+
+  virtual void DeleteModel() = 0;
+  virtual void CreateModel() = 0;
+  virtual void Solve(double time, Matrix& FF) = 0;  
+  
+    
+    
+  ColMatMap* GetState();
+  ColMatMap* GetStateDerivative();
+  ColMatMap* GetStateDerivativeDerivative();
+};
+
+#endif
diff --git a/lib/poems/sphericaljoint.cpp b/lib/poems/sphericaljoint.cpp
new file mode 100644
index 000000000..fb5330db1
--- /dev/null
+++ b/lib/poems/sphericaljoint.cpp
@@ -0,0 +1,264 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: sphericaljoint.cpp                                      *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+ 
+
+#include "sphericaljoint.h"
+#include "point.h"
+#include "matrixfun.h"
+#include "body.h"
+#include "fastmatrixops.h"
+#include "norm.h"
+#include "eulerparameters.h"
+#include "matrices.h"
+#include <iomanip>
+
+
+SphericalJoint::SphericalJoint(){
+  DimQandU(4,3);
+}
+SphericalJoint::~SphericalJoint(){
+}
+
+JointType SphericalJoint::GetType(){
+  return SPHERICALJOINT;
+}
+
+bool SphericalJoint::ReadInJointData(std::istream& in){
+  return true;
+}
+
+void SphericalJoint::WriteOutJointData(std::ostream& out){
+}
+
+Matrix SphericalJoint::GetForward_sP(){  
+  Mat3x3 sPa,sPl;
+  Matrix sP(6,3);
+  sPa.Identity();    
+  sPl.Zeros();
+  Vect3 temp = -(point2->position);  
+  
+  sPl(1,2) = temp(3);
+  sPl(1,3) = -temp(2);
+  
+  sPl(2,1) = -temp(3);
+  sPl(2,3) = temp(1);
+  
+  sPl(3,1) = temp(2);  
+  sPl(3,2) = -temp(1);
+         
+  sP=Stack(sPa,sPl);  
+  return sP;    
+}
+
+void SphericalJoint::UpdateForward_sP( Matrix& sP){
+    // sP is constant, do nothing.
+  // linear part is not constant
+}
+
+Matrix SphericalJoint::GetBackward_sP(){
+	cout<<" -----------"<<endl;
+	cout<<"Am I coming here "<<endl;
+	cout<<" -----------"<<endl;	
+  Mat3x3 sPa,sPl;
+  Matrix sP;
+  sPa.Identity();    
+  sPl.Zeros();          
+  sPl(3,2)=(point2->position(1));  
+  sPl(2,3)=-(point2->position(1));   
+  sP=Stack(sPa,sPl);
+  return sP;    
+}
+
+void SphericalJoint::UpdateBackward_sP( Matrix& sP){  
+  // sP is constant, do nothing.
+}
+
+void SphericalJoint::ComputeLocalTransform(){
+	Mat3x3 ko_C_k;
+	// Obtain the transformation matrix from euler parameters
+	EP_Transformation(q, ko_C_k);
+	FastMult(pk_C_ko,ko_C_k,pk_C_k);
+	}  
+
+
+void SphericalJoint::ForwardKinematics(){
+  Vect3 result1,result2,result3,result4,result5;
+  Vect3 pk_w_k;
+  
+  //cout<<"Check in spherical "<<q<<" "<<qdot<<endl;
+  EP_Normalize(q);
+
+
+  // orientations
+  ComputeForwardTransforms();    
+
+  
+  //----------------------------------//
+  // COMPUTE POSITION VECTOR R12 aka GAMMA    
+  
+  FastNegMult(pk_C_k,point2->position,result1); // parents basis      
+  FastAdd(result1,point1->position,r12);      
+  
+  // compute position vector r21 
+  FastNegMult(k_C_pk,r12,r21); 
+
+  
+  
+  //----------------------------------//
+  // COMPUTE GLOBAL LOCATION  
+  FastMult(body1->n_C_k,(body1->GetPoint(2))->position,result1);    
+  FastAdd(result1,body1->r,result1);  
+  FastNegMult(body2->n_C_k,(body2->GetPoint(1))->position,result2);  
+  FastAdd(result1,result2,body2->r);  
+  
+  qdot_to_u(q, u, qdot);  
+  
+
+  //-----------------------------------  
+  // angular velocities  
+  
+  FastAssign(u,pk_w_k);
+  FastTMult(pk_C_k,body1->omega_k,result1);        
+  FastAdd(result1,pk_w_k,body2->omega_k);
+  FastMult(body2->n_C_k,body2->omega_k,body2->omega); 
+
+  
+  
+  //-----------------------------------  
+  
+  // compute velocities  
+  FastCross(body1->omega_k,(body1->GetPoint(2))->position,result1);  
+  FastAdd(body1->v_k,result1,result2);
+  FastTMult(pk_C_k,result2,result1); // In body basis  
+  
+  FastCross((body2->GetPoint(1))->position,body2->omega_k,result2);                 
+  FastAdd(result1,result2,body2->v_k);    // In body basis     
+  FastMult(body2->n_C_k,body2->v_k,body2->v); 
+  
+  
+  //------------------------------------------
+  //Compute the KE   
+  Matrix tempke;
+  tempke = T(body2->v)*(body2->v);    
+  double ke = 0.0;
+  ke = body2->mass*tempke(1,1);  
+  FastMult(body2->inertia,body2->omega_k,result1);
+  tempke= T(body2->omega_k)*result1;  
+  ke = 0.5*ke + 0.5*tempke(1,1);
+  body2->KE=ke;
+
+  //-----------------------------------  
+  // compute state explicit angular acceleration  // Has to be in body basis    
+  FastTMult(pk_C_k,body1->alpha_t,result2);  
+  FastCross(body2->omega_k,pk_w_k,result1);
+  FastAdd(result1,result2,body2->alpha_t); 
+   
+  //-----------------------------------  
+  // compute state explicit acceleration   
+  // NEED TO DO THIS COMPLETELY IN BODY BASIS 
+  
+  FastCross(body1->omega_k,(body1->GetPoint(2))->position,result1);
+  FastCross(body1->omega_k,result1,result2); 
+  FastTMult(pk_C_k,result2,result1); 
+  
+  //FastCross(body2->omega_k,-(body2->GetPoint(1))->position,result3);  
+  FastCross((body2->GetPoint(1))->position,body2->omega_k,result3);  
+  FastCross(body2->omega_k,result3,result2);    
+  FastAdd(result1,result2,result3); //wxwxr in body basis  
+  
+  FastCross(body1->alpha_t,(body1->GetPoint(2))->position,result4); 
+  FastTMult(pk_C_k,result4,result5);  
+  FastAssign(result5,result4);
+  
+  FastCross((body2->GetPoint(1))->position,body2->alpha_t,result2);   
+  FastAdd(result2,result4,result1); //alphaxr in body basis  
+  
+  FastTMult(pk_C_k,body1->a_t,result2);
+  FastTripleSum(result3,result1,result2,body2->a_t);     // in body basis  
+  
+  
+  //-----------------------------------    
+}
+
+// NOTE: NOT USING BACKWARDKINEMATICS AT PRESENT
+void SphericalJoint::BackwardKinematics(){
+  cout<<"what about here "<<endl;
+  Vect3 result1,result2,result3,result4,result5;
+  Vect3 k_w_pk;
+
+  // orientations
+  ComputeBackwardTransforms();
+  
+
+  // compute position vector r21
+  //r21 = point2->position - k_C_pk * point1->position;
+  FastMult(k_C_pk,point1->position,result1);
+  FastSubt(point2->position,result1,r21);
+  
+
+  // compute position vector r21
+  FastNegMult(pk_C_k,r21,r12);
+
+  // compute global location
+  // body1->r = body2->r + body2->n_C_k * r21;
+  FastMult(body2->n_C_k,r21,result1);
+  FastAdd(body2->r,result1,body1->r);
+
+  // compute qdot (for revolute joint qdot = u)
+  // qdot = u
+  ColMatrix us(3);
+  /*us(1)=0;
+  us(2)=u(1);
+  us(3)=u(2);*/
+  EP_Derivatives(q,u,qdot);
+
+  // angular velocities
+ 
+  FastMult(body2->n_C_k,u,result2);
+  FastAdd(body2->omega,result2,body1->omega);
+  FastAssign(u,k_w_pk);
+  FastMult(pk_C_k,body2->omega_k,result1);
+  FastSubt(result1,k_w_pk,body1->omega_k);
+  cout<<"The program was here"<<endl;
+
+  // compute velocities
+  FastCross(body2->omega_k,r21,result1);
+  FastCross(point1->position,k_w_pk,result2);
+  FastAdd(body2->v_k,result1,result3);
+  FastMult(pk_C_k,result3,result4);
+  FastAdd(result2,result4,body1->v_k);
+  FastMult(body1->n_C_k,body1->v_k,body1->v);
+
+  // compute state explicit angular acceleration
+  FastCross(body1->omega_k,k_w_pk,result1);
+  FastMult(pk_C_k,body2->alpha_t,result2);
+  FastAdd(result1,result2,body1->alpha_t);
+  
+  // compute state explicit acceleration
+  FastCross(body2->alpha_t,point2->position,result1);
+  FastCross(body2->omega_k,point2->position,result2);
+  FastCross(body2->omega_k,result2,result3);
+  FastTripleSum(body2->a_t,result1,result3,result4);
+  FastMult(pk_C_k,result4,result5);
+
+  FastCross(point1->position,body1->alpha_t,result1);
+  FastCross(point1->position,body1->omega_k,result2);
+  FastCross(body1->omega_k,result2,result3);
+
+  FastTripleSum(result5,result1,result3,body1->a_t);
+  
+}
diff --git a/lib/poems/sphericaljoint.h b/lib/poems/sphericaljoint.h
new file mode 100644
index 000000000..ef29f8e38
--- /dev/null
+++ b/lib/poems/sphericaljoint.h
@@ -0,0 +1,44 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: sphericaljoint.h                                        *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef SPHERICALJOINT_H
+#define SPHERICALJOINT_H
+
+#include "joint.h"
+#include "vect3.h"
+#include "mat3x3.h"
+
+
+
+class SphericalJoint : public Joint  {
+  Matrix const_sP;
+public:
+  SphericalJoint();
+  ~SphericalJoint();
+  JointType GetType();
+  bool ReadInJointData(std::istream& in);
+  void WriteOutJointData(std::ostream& out);
+  Matrix GetForward_sP();
+  Matrix GetBackward_sP();
+  void UpdateForward_sP( Matrix& sP);
+  void UpdateBackward_sP( Matrix& sP);
+  void ComputeLocalTransform();
+  void ForwardKinematics();
+  void BackwardKinematics();
+};
+
+#endif
diff --git a/lib/poems/system.cpp b/lib/poems/system.cpp
new file mode 100644
index 000000000..25e84c2b8
--- /dev/null
+++ b/lib/poems/system.cpp
@@ -0,0 +1,596 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: system.cpp                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "system.h"
+#include "body.h"
+#include "joint.h"
+#include <math.h>
+
+
+System::System(){
+	mappings = NULL;
+}
+
+System::~System(){
+  Delete();
+}
+
+void System::Delete(){
+  delete [] mappings;
+  bodies.DeleteValues();
+  joints.DeleteValues();
+}
+
+int System::GetNumBodies(){
+  return bodies.GetNumElements();
+}
+
+int * System::GetMappings()
+{
+	return mappings;
+}
+
+void System::AddBody(Body* body){
+  bodies.Append(body);
+}
+
+void System::AddJoint(Joint* joint){
+  joints.Append(joint);
+}
+
+void System::SetTime(double t){
+  time = t;
+}
+
+double System::GetTime(){
+  return time;
+}
+
+void System::ComputeForces(){	
+	// NOT DOING ANYTHING AT THIS TIME
+  }  
+  
+bool System::ReadIn(istream& in){
+  int numbodies;
+  Body* body;
+  int bodytype;
+  char bodyname[256];
+  int index;  
+
+  // get number of bodies
+  in >> numbodies;
+
+  // bodies loop
+  for(int i=0;i<numbodies;i++){
+
+    // error check
+    in >> index;
+    if(index != i){
+      cerr << "Error reading bodies" << endl;
+      return false;
+    }
+
+    in >> bodytype >> bodyname;
+    body = NewBody(bodytype);
+
+    // type check
+    if(!body){
+      cerr << "Unrecognized body type '" << bodytype << "'" << endl;
+      return false;
+    }
+
+    // add the body
+    AddBody(body);
+
+    // set generic body info
+    body->ChangeName(bodyname);
+
+    // read in the rest of its data
+    if(!body->ReadIn(in)) return false;
+  }
+
+  // create a temporary array for fast indexed access
+  Body** bodyarray = bodies.CreateArray();
+
+  int numjoints;
+  int jointtype;
+  char jointname[256];
+  Joint* joint;
+  int body1, body2;
+  int point1, point2;
+
+  // get number of joints
+  in >> numjoints;
+
+  // joints loop
+  for(int i=0;i<numjoints;i++){
+
+    // error check
+    in >> index;
+    if(index != i){
+      cerr << "Error reading joints" << endl;
+      return false;
+    }
+
+    in >> jointtype >> jointname;
+    joint = NewJoint(jointtype);
+
+    // joint type check
+    if(!joint){
+      cerr << "Unrecognized joint type '" << jointtype << "'" << endl;
+      return false;
+    }
+
+    // add the joint
+    AddJoint(joint);
+
+    // set the generic joint info
+    joint->ChangeName(jointname);
+
+    in >> body1 >> body2;
+    if( !(body1<numbodies) || !(body2<numbodies) ){
+      cerr << "Body index out of range" << endl;
+      return false;
+    }
+    
+    joint->SetBodies(bodyarray[body1], bodyarray[body2]);
+
+    bodyarray[body1]->AddJoint(joint);
+    bodyarray[body2]->AddJoint(joint);
+    
+    in >> point1 >> point2;
+
+    joint->SetPoints(bodyarray[body1]->GetPoint(point1),bodyarray[body2]->GetPoint(point2));
+
+    // read in the rest of its data
+    if(!joint->ReadIn(in)){
+      return false;
+    }
+  }
+
+  // delete the temporary array
+  delete [] bodyarray;
+
+  return true;
+}
+
+void System::WriteOut(ostream& out){
+  // number of bodies
+  out << bodies.GetNumElements() << endl;
+
+  // bodies loop
+  int i = 0;
+  Body* body;
+  ListElement<Body>* b_ele = bodies.GetHeadElement();
+  while(b_ele !=0){
+    out << i << ' ';
+
+    body = b_ele->value;
+
+    // set the body ID for later identification
+    body->SetID(i);
+    
+    // write out the data
+    body->WriteOut(out);
+
+    i++; b_ele = b_ele->next;
+  }
+
+  // number of joints
+  out << joints.GetNumElements() << endl;  
+
+  // joints loop
+  i = 0;
+  Joint* joint;
+  ListElement<Joint>* j_ele = joints.GetHeadElement();
+  while(j_ele !=0){
+    out << i << ' ';
+    joint = j_ele->value;
+
+    // set the joint ID for later identification
+    joint->SetID(i);
+
+    // write out the data
+    joint->WriteOut(out);
+    
+    i++; j_ele = j_ele->next;
+  }
+}
+
+void System::ClearBodyIDs(){
+  ListElement<Body>* current = bodies.GetHeadElement();
+
+  while(current){
+    current->value->SetID(0);
+    current = current->next;
+  }
+}
+
+void System::ClearJointIDs(){
+  ListElement<Joint>* current = joints.GetHeadElement();
+
+  while(current){
+    current->value->SetID(0);
+    current = current->next;
+  }
+}
+
+
+void System::Create_DegenerateSystem(int& nfree, int*freelist, double *&masstotal, double **&inertia, double **&xcm, double **&vcm, double **&omega, double **&ex_space, double **&ey_space, double **&ez_space){
+
+ //-------------------------------------------------------------------------//    
+  // Declaring Temporary Entities 
+  //-------------------------------------------------------------------------//   
+     Body* body = NULL;
+     Body* prev;
+     Body* Inertial;
+     Point* origin;
+     Joint* joint;
+     Point* point_CM; 
+     Point* point_p;  
+     Point* point_k;  
+     Point* point_ch = NULL;
+     Vect3 r1,r2,r3,v1,v2,v3; 
+     Mat3x3 IM, N, PKCK,PKCN ;
+     ColMatrix qo, uo, q, qdot,w;
+     
+	 mappings = new int[nfree];
+	 for(int i = 0; i < nfree; i++)
+	 {
+		 mappings[i] = freelist[i];		 
+	 }
+     qo.Dim(4);
+     uo.Dim(3);
+     q.Dim(4);
+     qdot.Dim(4);     
+     PKCN.Identity();
+     PKCK.Identity();
+     w.Dim(3);
+	
+//-------------------------------------------------------------------------//    
+  // Setting up Inertial Frame, gravity and Origin  
+  //-------------------------------------------------------------------------//
+     Inertial= new InertialFrame;  
+     AddBody(Inertial);
+     
+     Vect3 temp1;  
+     temp1.Zeros();  
+     ((InertialFrame*) Inertial)->SetGravity(temp1);    
+     origin= new FixedPoint(temp1);
+     Inertial->AddPoint(origin);    
+//-------------------------------------------------------------------------//
+	double ** xh1 = new double*[nfree];
+	double ** xh2 = new double*[nfree];
+	
+	for (int i=0; i<nfree; i++){		
+ 		xh1[i] = new double[3];
+		xh2[i] = new double[3];
+	}	
+	for (int i=0; i<nfree; i++){		
+		for (int j=0; j<3; j++){
+			xh1[i][j] = xcm[mappings[i]-1][j];
+		}
+	}
+	
+//-------------------------------------------------------------------------//    
+// Begin looping over each body for recursive kinematics
+//-------------------------------------------------------------------------//
+    for(int i=0;i<nfree;i++){
+	    prev=Inertial;
+	    point_p=origin;               
+      
+     body = new RigidBody;   
+     body->mass=masstotal[mappings[i]-1];
+     IM(1,1)=inertia[mappings[i]-1][0];
+     IM(2,2)=inertia[mappings[i]-1][1];
+     IM(3,3)=inertia[mappings[i]-1][2];
+     IM(1,2)=0.0;
+     IM(1,3)=0.0;
+     IM(2,3)=0.0;
+     IM(2,1)=IM(1,2);
+     IM(3,1)=IM(1,3);
+     IM(3,2)=IM(2,3);
+     body->inertia = IM;   
+
+//-------------------------------------------------------//                  
+    
+    
+	    for (int k=0;k<3;k++){ 
+          r1(k+1)=xh1[i][k]-xcm[mappings[i]-1][k];     
+			 r3(k+1) = xcm[mappings[i]-1][k];
+			 r3(k+1)=xh2[i][k]-xcm[mappings[i]-1][k]; 	  
+	    }
+	  
+     r2.Zeros(); 
+     
+     for (int k=1;k<=3;k++){     
+          N(k,1)=ex_space[mappings[i]-1][k-1];              
+          N(k,2)=ey_space[mappings[i]-1][k-1];              
+          N(k,3)=ez_space[mappings[i]-1][k-1];              
+         }                  
+     
+     PKCK=T(N);
+     PKCN=T(N);
+    
+     q.Zeros();     
+     EP_FromTransformation(q,N);
+                    
+     r1=PKCN*r1;
+     r3=PKCN*r3;
+     
+     for (int k=1;k<=3;k++){
+     w(k)=omega[mappings[i]-1][k-1];                                   
+     }     
+     
+     Vect3 cart_r, cart_v;
+     for (int k=1;k<=3;k++){
+	     cart_r(k)=xcm[mappings[i]-1][k-1];	     
+	     cart_v(k)=vcm[mappings[i]-1][k-1];
+	     }
+	     	     
+	     w=PKCN*w;     
+	     EP_Derivatives(q,w,qdot);
+	     
+     
+//-------------------------------------------------------------------------//    
+// Create bodies and joints with associated properties for POEMS
+//-------------------------------------------------------------------------//
+
+     point_CM = new FixedPoint(r2);
+     point_k = new FixedPoint(r1);
+     point_ch = new FixedPoint(r3);
+     body->AddPoint(point_CM);
+     body->AddPoint(point_k);
+     body->AddPoint(point_ch);
+     AddBody(body);    
+   
+     Mat3x3 One;
+     One.Identity();	
+	  ColMatrix qq=Stack(q,cart_r);
+          ColMatrix vv=Stack(qdot,cart_v);          
+          joint=new FreeBodyJoint;
+          AddJoint(joint);
+          joint->SetBodies(prev,body);
+          body->AddJoint(joint);
+          prev->AddJoint(joint);
+          joint->SetPoints(point_p,point_k);
+          joint->SetZeroOrientation(One);
+          joint->DimQandU(7,6);
+          joint->SetInitialState(qq,vv);
+          joint->ForwardKinematics();                             
+  }
+  for(int i = 0; i < nfree; i++) {
+	  delete [] xh1[i];
+	  delete [] xh2[i];
+  }
+  delete xh1;
+  delete xh2;  
+}
+
+
+void System::Create_System_LAMMPS(int numbodies, double *mass,double **inertia, double ** xcm, double ** xjoint,double **vcm,double **omega,double **ex_space, double **ey_space, double **ez_space, int b, int * mapping, int count){
+
+	//-------------------------------------------------------------------------//    
+  // Declaring Temporary Entities 
+	//-------------------------------------------------------------------------//   
+  	
+	Body* body = NULL;
+	Body* prev;
+	Body* Inertial;
+	Point* origin;
+	Joint* joint;
+	Point* point_CM;   
+	Point* point_p;    
+	Point* point_k;    
+	Point* point_ch = NULL;  
+	Vect3 r1,r2,r3,v1,v2,v3; 
+	Mat3x3 IM, N, PKCK,PKCN ;
+	ColMatrix qo, uo, q, qdot,w;
+	Vect3 cart_r, cart_v;
+	mappings = new int[b];
+	for(int i = 0; i < b; i++){
+		mappings[i] = mapping[i];		 
+	}	 
+	 
+     
+	qo.Dim(4);
+	uo.Dim(3);
+	q.Dim(4);
+	qdot.Dim(4);     
+	PKCN.Identity();
+	PKCK.Identity();
+	w.Dim(3);
+	
+	//-------------------------------------------------------------------------//    
+  // Setting up Inertial Frame, gravity and Origin  
+	//-------------------------------------------------------------------------//
+	Inertial= new InertialFrame;  
+	AddBody(Inertial);
+     
+	Vect3 temp1;  
+	temp1.Zeros();  
+	((InertialFrame*) Inertial)->SetGravity(temp1);    
+	origin= new FixedPoint(temp1);
+	Inertial->AddPoint(origin);    
+	//-------------------------------------------------------------------------//
+
+	double ** xh1;
+	double ** xh2;
+		  
+	xh1 = new double*[b];		  
+	xh2 = new double*[b];
+		  
+	
+	for (int i=0; i<b; i++){			
+		xh1[i] = new double[3];
+		xh2[i] = new double[3];			
+	}	
+		  
+		  
+		  
+	for (int j=0; j<3; j++){
+		xh1[0][j] = xcm[mapping[0]-1][j];
+		xh2[b-1][j] = xcm[mapping[b-1]-1][j];
+	}
+	
+	for (int i=0; i<b-1; i++){
+		for (int j=0; j<3; j++){
+			xh1[i+1][j] = xjoint[mapping[i]-count-1][j];
+		}
+	}		  
+	
+	for (int i=0; i<b-1; i++){
+		for (int j=0; j<3; j++){
+			xh2[i][j] = xjoint[mapping[i]-count-1][j];
+		}
+	}
+
+	
+	//-------------------------------------------------------------------------//    
+// Begin looping over each body for recursive kinematics
+	//-------------------------------------------------------------------------//
+	for(int i=0;i<b;i++){	    
+		if (i == 0){
+			prev=Inertial;
+			point_p=origin;
+		}    
+		else{
+			prev = body;            
+			point_p = point_ch;     
+		}   
+    
+  	  
+		body = new RigidBody;  
+		body->mass=mass[mapping[i]-1];
+		IM(1,1)=inertia[mapping[i]-1][0];
+		IM(2,2)=inertia[mapping[i]-1][1];
+		IM(3,3)=inertia[mapping[i]-1][2];
+		IM(1,2)=0.0;
+		IM(1,3)=0.0;
+		IM(2,3)=0.0;
+		IM(2,1)=IM(1,2);
+		IM(3,1)=IM(1,3);
+		IM(3,2)=IM(2,3);
+		body->inertia = IM;   
+     
+		//-------------------------------------------------------//
+             
+		for (int k=0;k<3;k++){
+			r1(k+1)=xh1[i][k]-xcm[mapping[i]-1][k]; 
+			r3(k+1)=xh2[i][k]-xcm[mapping[i]-1][k]; 
+		}
+		r2.Zeros();   
+     
+		for (int k=1;k<=3;k++){     
+			N(k,1)=ex_space[mapping[i]-1][k-1];              
+			N(k,2)=ey_space[mapping[i]-1][k-1];              
+			N(k,3)=ez_space[mapping[i]-1][k-1];              
+		}
+	 
+         
+		if (i==0){
+			PKCK=T(N);     
+			PKCN=T(N);     
+	     
+			q.Zeros();	     
+			EP_FromTransformation(q,N);
+	     
+			r1=PKCN*r1;
+			r3=PKCN*r3;
+	     
+			for (int k=1;k<=3;k++){     
+				w(k)=omega[mappings[i]-1][k-1];
+			}	     
+	     
+			for (int k=1;k<=3;k++){
+				cart_r(k)=xcm[mappings[i]-1][k-1];		     
+				cart_v(k)=vcm[mappings[i]-1][k-1];
+			}
+			w=PKCN*w;     
+			EP_Derivatives(q,w,qdot);    
+		 
+		}                 
+		else{	     
+			PKCK=PKCN*N;   
+			PKCN=T(N);     
+    
+			q.Zeros();
+			EP_FromTransformation(q,PKCK);
+               
+			r1=PKCN*r1;
+			r3=PKCN*r3;
+     
+			for (int k=1;k<=3;k++){     
+				w(k)=omega[mapping[i]-1][k-1]-omega[mapping[i-1]-1][k-1];                         
+			}
+    	
+			w=PKCN*w; 
+			EP_Derivatives(q, w, qdot);        
+		}  
+        
+	
+		//-------------------------------------------------------------------------//    
+// Create bodies and joints with associated properties for POEMS
+		//-------------------------------------------------------------------------//
+
+		point_CM = new FixedPoint(r2);
+		point_k = new FixedPoint(r1);
+		point_ch = new FixedPoint(r3);
+		body->AddPoint(point_CM);
+		body->AddPoint(point_k);
+		body->AddPoint(point_ch);
+		AddBody(body);    
+   
+		Mat3x3 One;
+		One.Identity();	
+		if (i==0){	  
+			ColMatrix qq=Stack(q,cart_r);
+			ColMatrix vv=Stack(qdot,cart_v);          
+			joint=new FreeBodyJoint;
+			AddJoint(joint);
+			joint->SetBodies(prev,body);
+			body->AddJoint(joint);
+			prev->AddJoint(joint);
+			joint->SetPoints(point_p,point_k);
+			joint->SetZeroOrientation(One);
+			joint->DimQandU(7,6);
+			joint->SetInitialState(qq,vv);  	  
+			joint->ForwardKinematics();  
+		}    
+		else{	     
+			joint= new SphericalJoint;
+			AddJoint(joint);
+			joint->SetBodies(prev,body);
+			body->AddJoint(joint);
+			prev->AddJoint(joint);
+			joint->SetPoints(point_p,point_k);          
+			joint->SetZeroOrientation(One);
+			joint->DimQandU(4,3);
+			joint->SetInitialState(q,qdot);
+			joint->ForwardKinematics();  
+		}
+	}
+	for(int i = 0; i < b; i++)
+	{
+		delete [] xh1[i];
+		delete [] xh2[i];
+	}
+	delete [] xh1;
+	delete [] xh2;
+  
+}
diff --git a/lib/poems/system.h b/lib/poems/system.h
new file mode 100644
index 000000000..39c1f518b
--- /dev/null
+++ b/lib/poems/system.h
@@ -0,0 +1,92 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: system.h                                                *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+ 
+#ifndef SYSTEM_H
+#define SYSTEM_H
+
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <stdio.h>   
+#include <iomanip>  
+
+#include "poemslist.h"
+#include "matrices.h"
+#include "workspace.h"
+#include "matrixfun.h"
+#include "onsolver.h"
+#include "system.h"
+#include "inertialframe.h"
+#include "rigidbody.h"
+#include "revolutejoint.h"
+#include "fixedpoint.h"
+#include "freebodyjoint.h"
+#include "sphericaljoint.h"
+#include "body23joint.h"
+#include "mixedjoint.h"
+#include "eulerparameters.h"
+#include "matrices.h"
+#include "norm.h"
+
+
+     class Body;
+     class Joint;
+
+     class System{
+	 private:
+		int * mappings;
+		
+     public:
+       double time;
+       List<Body> bodies;
+       List<Joint> joints;
+  
+       System();
+       ~System();
+       void Delete();
+       
+       int GetNumBodies();
+       
+	   int * GetMappings();
+
+       void AddBody(Body* body);
+       
+       void AddJoint(Joint* joint);
+       
+       void SetTime(double t);
+       
+       double GetTime();
+       
+       void ComputeForces();
+       
+       bool ReadIn(std::istream& in);
+       
+       void WriteOut(std::ostream& out);
+       
+       void ClearBodyIDs();
+       
+       void ClearJointIDs();              
+
+       void Create_System_LAMMPS(int numbodies, double *mass,double **inertia, double ** xcm, double ** xjoint,double **vh1,double **omega,double **ex_space, double **ey_space, double **ez_space, int b, int * mapping, int count);
+       
+       void Create_DegenerateSystem(int& nfree, int*freelist, double *&masstotal, double **&inertia, double **&xcm, double **&vcm, double **&omega, double **&ex_space, double **&ey_space, double **&ez_space);
+
+};
+
+#endif
diff --git a/lib/poems/vect3.cpp b/lib/poems/vect3.cpp
new file mode 100644
index 000000000..f0e677b6e
--- /dev/null
+++ b/lib/poems/vect3.cpp
@@ -0,0 +1,148 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: vect3.cpp                                               *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "vect3.h"
+
+using namespace std;
+
+Vect3::Vect3(){
+  numrows = 3; numcols = 1;
+}
+Vect3::~Vect3(){
+}
+
+Vect3::Vect3(const Vect3& A){  // copy constructor
+  numrows = 3; numcols = 1;
+
+  elements[0] = A.elements[0];
+  elements[1] = A.elements[1];
+  elements[2] = A.elements[2];
+}
+
+Vect3::Vect3(const VirtualMatrix& A){  // copy constructor
+  numrows = 3; numcols = 1;
+
+  // error check
+  if( (A.GetNumRows() != 3) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<3;i++)
+    elements[i] = A.BasicGet(i,0);
+}
+
+double& Vect3::operator_1int (int i){ // array access
+	if(i<1 || i>3){
+		cerr << "matrix index invalid in operator ()" << endl;
+		exit(1);
+	}
+  return elements[i-1];
+}
+
+double Vect3::Get_1int(int i) const{
+  return elements[i-1];
+}
+
+void Vect3::Set_1int(int i, double value){
+  elements[i-1] = value;
+}
+
+double Vect3::BasicGet_1int(int i) const{
+  return elements[i];
+}
+
+void Vect3::BasicSet_1int(int i, double value){
+  elements[i] = value;
+}
+
+void Vect3::BasicIncrement_1int(int i, double value){
+  elements[i] += value;
+}
+
+void Vect3::Const(double value){
+  elements[0] = value;
+  elements[1] = value;
+  elements[2] = value;
+}
+
+MatrixType Vect3::GetType() const{
+  return VECT3;
+}
+
+istream& Vect3::ReadData(istream& c){  //input
+  for(int i=0;i<3;i++)
+    c >> elements[i];
+  return c;
+}
+
+ostream& Vect3::WriteData(ostream& c) const{  //output
+  for(int i=0;i<3;i++)
+    c << elements[i] << ' ';
+  return c;
+}
+
+void Vect3::AssignVM(const VirtualMatrix& A){
+  // error check
+  if( (A.GetNumRows() != 3) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    elements[i] = A.BasicGet(i,0);
+}
+
+Vect3& Vect3::operator=(const Vect3& A){ // assignment operator
+  elements[0] = A.elements[0];
+  elements[1] = A.elements[1];
+  elements[2] = A.elements[2];
+  return *this;
+}
+
+Vect3& Vect3::operator=(const VirtualMatrix& A){ // overloaded =
+  // error check
+  if( (A.GetNumRows() != 3) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    elements[i] = A.BasicGet(i,0);
+  return *this;
+}
+
+Vect3& Vect3::operator*=(double b){
+  elements[0] *= b;
+  elements[1] *= b;
+  elements[2] *= b;
+  return *this;
+}
+
+Vect3& Vect3::operator+=(const Vect3& A){
+  elements[0] += A.elements[0];
+  elements[1] += A.elements[1];
+  elements[2] += A.elements[2];
+  return *this;
+}
+
+Vect3& Vect3::operator-=(const Vect3& A){
+  elements[0] -= A.elements[0];
+  elements[1] -= A.elements[1];
+  elements[2] -= A.elements[2];
+  return *this;
+}
diff --git a/lib/poems/vect3.h b/lib/poems/vect3.h
new file mode 100644
index 000000000..ababe18e5
--- /dev/null
+++ b/lib/poems/vect3.h
@@ -0,0 +1,84 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: vect3.h                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef VECT3_H
+#define VECT3_H
+
+#include "virtualcolmatrix.h"
+
+class Matrix;
+class Mat3x3;
+class Mat6x6;
+class Vect6;
+class ColMatrix;
+
+class Vect3 : public VirtualColMatrix  {
+  double elements[3];
+public:
+  Vect3();
+  ~Vect3();
+  Vect3(const Vect3& A);  // copy constructor
+  Vect3(const VirtualMatrix& A);  // copy constructor
+
+  double& operator_1int(int i); // array access
+  double Get_1int(int i) const;
+  void Set_1int(int i, double value);
+  double BasicGet_1int(int i) const;
+  void BasicSet_1int(int i, double value);
+  void BasicIncrement_1int(int i, double value);
+
+  void Const(double value);
+  MatrixType GetType() const;
+  std::ostream& WriteData(std::ostream& c) const;
+  std::istream& ReadData(std::istream& c);
+
+  void AssignVM(const VirtualMatrix& A);
+  Vect3& operator=(const Vect3& A); // assignment operator
+  Vect3& operator=(const VirtualMatrix& A); // overloaded =
+  Vect3& operator*=(double b);
+  Vect3& operator+=(const Vect3& A);
+  Vect3& operator-=(const Vect3& A);
+
+  friend Matrix T(const Vect3& A);  // a wasteful transpose
+  friend Mat3x3 CrossMat(Vect3& a);  // a wasteful cross matrix implementation
+
+  friend void Set6DAngularVector(Vect6& v6, Vect3& v3);
+  friend void Set6DLinearVector(Vect6& v6, Vect3& v3);
+
+  // fast matrix functions
+  friend void FastAssign(Vect3& a, Vect3& c);
+  friend void FastSimpleRotation(Vect3& v, double q, Mat3x3& d);
+  friend void FastCross(Vect3& a, Vect3& b, Vect3& c); // cross product axb = c
+  friend void FastTripleSum(Vect3& a, Vect3& b, Vect3& c, Vect3& d);
+  friend void FastTripleSumPPM(Vect3& a, Vect3& b, Vect3& c, Vect3& d);
+  friend void FastMult(Mat3x3& A, Vect3& B, Vect3& C);
+  friend void FastTMult(Mat3x3& A, Vect3& B, Vect3& C);
+  friend void FastNegMult(Mat3x3& A, Vect3& B, Vect3& C);
+  friend void FastNegTMult(Mat3x3& A, Vect3& B, Vect3& C);
+  friend void FastMult(double a, Vect3& B, Vect3& C);
+  friend void FastAdd(Vect3& A, Vect3& B, Vect3& C);
+  friend void FastSubt(Vect3& A, Vect3& B, Vect3& C);
+  friend void OnPopulateSVect(Vect3& angular, Vect3& linear, Vect6& sV);
+  friend void OnPopulateSC(Vect3& gamma, Mat3x3& C, Mat6x6& SC);
+
+  friend void FastMult(Mat3x3& A, ColMatrix& B, Vect3& C);
+  friend void FastAssign(ColMatrix&A, Vect3& C);
+  friend void FastMult(Mat3x3& A, Vect3& B, ColMatrix& C);
+  
+};
+
+#endif
diff --git a/lib/poems/vect4.cpp b/lib/poems/vect4.cpp
new file mode 100644
index 000000000..4824f2883
--- /dev/null
+++ b/lib/poems/vect4.cpp
@@ -0,0 +1,135 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: vect4.cpp                                               *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "vect4.h"
+
+using namespace std;
+
+Vect4::Vect4(){
+  numrows = 4; numcols = 1;
+}
+Vect4::~Vect4(){
+}
+
+Vect4::Vect4(const Vect4& A){  // copy constructor
+  numrows = 4; numcols = 1;
+
+  elements[0] = A.elements[0];
+  elements[1] = A.elements[1];
+  elements[2] = A.elements[2];
+  elements[3] = A.elements[3];
+}
+
+Vect4::Vect4(const VirtualMatrix& A){  // copy constructor
+  numrows = 4; numcols = 1;
+
+  // error check
+  if( (A.GetNumRows() != 4) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<4;i++)
+    elements[i] = A.BasicGet(i,0);
+}
+
+double& Vect4::operator_1int (int i){ // array access
+  return elements[i-1];
+}
+
+double Vect4::Get_1int(int i) const{
+  return elements[i-1];
+}
+
+void Vect4::Set_1int(int i, double value){
+  elements[i-1] = value;
+}
+
+double Vect4::BasicGet_1int(int i) const{
+  return elements[i];
+}
+
+void Vect4::BasicSet_1int(int i, double value){
+  elements[i] = value;
+}
+
+void Vect4::BasicIncrement_1int(int i, double value){
+  elements[i] += value;
+}
+
+void Vect4::Const(double value){
+  elements[0] = value;
+  elements[1] = value;
+  elements[2] = value;
+  elements[3] = value;
+}
+
+MatrixType Vect4::GetType() const{
+  return VECT4;
+}
+
+istream& Vect4::ReadData(istream& c){  //input
+  for(int i=0;i<4;i++)
+    c >> elements[i];
+  return c;
+}
+
+ostream& Vect4::WriteData(ostream& c) const{  //output
+  for(int i=0;i<4;i++)
+    c << elements[i] << ' ';
+  return c;
+}
+
+void Vect4::AssignVM(const VirtualMatrix& A){
+  // error check
+  if( (A.GetNumRows() != 4) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    elements[i] = A.BasicGet(i,0);
+}
+
+Vect4& Vect4::operator=(const Vect4& A){ // assignment operator
+  elements[0] = A.elements[0];
+  elements[1] = A.elements[1];
+  elements[2] = A.elements[2];
+  elements[3] = A.elements[3];
+  return *this;
+}
+
+Vect4& Vect4::operator=(const VirtualMatrix& A){ // overloaded =
+  // error check
+  if( (A.GetNumRows() != 4) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    elements[i] = A.BasicGet(i,0);
+  return *this;
+}
+
+Vect4& Vect4::operator*=(double b){
+  elements[0] *= b;
+  elements[1] *= b;
+  elements[2] *= b;
+  elements[3] *= b;
+  return *this;
+}
+
diff --git a/lib/poems/vect4.h b/lib/poems/vect4.h
new file mode 100644
index 000000000..e9aee2719
--- /dev/null
+++ b/lib/poems/vect4.h
@@ -0,0 +1,71 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: vect4.h                                                 *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef VECT4_H
+#define VECT4_H
+
+#include "virtualcolmatrix.h"
+
+
+class Matrix;
+class Mat4x4;
+
+class Vect4 : public VirtualColMatrix  {
+  double elements[4];
+public:
+  Vect4();
+  ~Vect4();
+  Vect4(const Vect4& A);  // copy constructor
+  Vect4(const VirtualMatrix& A);  // copy constructor
+
+  double& operator_1int(int i); // array access
+  double Get_1int(int i) const;
+  void Set_1int(int i, double value);
+  double BasicGet_1int(int i) const;
+  void BasicSet_1int(int i, double value);
+  void BasicIncrement_1int(int i, double value);
+
+  
+  void Const(double value);
+  MatrixType GetType() const;
+  std::ostream& WriteData(std::ostream& c) const;
+  std::istream& ReadData(std::istream& c);
+
+  void AssignVM(const VirtualMatrix& A);
+  Vect4& operator=(const Vect4& A); // assignment operator
+  Vect4& operator=(const VirtualMatrix& A); // overloaded =
+  Vect4& operator*=(double b);
+
+  friend Matrix T(const Vect4& A);  // a wasteful transpose
+  friend Mat4x4 CrossMat(Vect4& a);  // a wasteful cross matrix implementation
+
+  // fast matrix functions
+  friend void FastAssign(Vect4& a, Vect4& c);
+  friend void FastSimpleRotation(Vect4& v, double q, Mat4x4& d);
+  friend void FastCross(Vect4& a, Vect4& b, Vect4& c); // cross product axb = c
+  friend void FastTripleSum(Vect4& a, Vect4& b, Vect4& c, Vect4& d);
+  friend void FastTripleSumPPM(Vect4& a, Vect4& b, Vect4& c, Vect4& d);
+  friend void FastMult(Mat4x4& A, Vect4& B, Vect4& C);
+  friend void FastTMult(Mat4x4& A, Vect4& B, Vect4& C);
+  friend void FastNegMult(Mat4x4& A, Vect4& B, Vect4& C);
+  friend void FastNegTMult(Mat4x4& A, Vect4& B, Vect4& C);
+  friend void FastMult(double a, Vect4& B, Vect4& C);
+  friend void FastAdd(Vect4& A, Vect4& B, Vect4& C);
+  friend void FastSubt(Vect4& A, Vect4& B, Vect4& C);
+};
+
+#endif
diff --git a/lib/poems/vect6.cpp b/lib/poems/vect6.cpp
new file mode 100644
index 000000000..a98d171d3
--- /dev/null
+++ b/lib/poems/vect6.cpp
@@ -0,0 +1,147 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: vect6.cpp                                               *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "vect6.h"
+
+using namespace std;
+
+Vect6::Vect6(){
+  numrows = 6; numcols = 1;
+}
+Vect6::~Vect6(){
+}
+
+Vect6::Vect6(const Vect6& A){  // copy constructor
+  numrows = 6; numcols = 1;
+
+  elements[0] = A.elements[0];
+  elements[1] = A.elements[1];
+  elements[2] = A.elements[2];
+  elements[3] = A.elements[3];
+  elements[4] = A.elements[4];
+  elements[5] = A.elements[5];
+}
+
+Vect6::Vect6(const VirtualMatrix& A){  // copy constructor
+  numrows = 6; numcols = 1;
+
+  // error check
+  if( (A.GetNumRows() != 6) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<6;i++)
+    elements[i] = A.BasicGet(i,0);
+}
+
+double& Vect6::operator_1int (int i){ // array access
+	if(i<1 || i>6){
+		cerr << "matrix index invalid in operator ()" << endl;
+		exit(1);
+	}
+	return elements[i-1];
+}
+
+double Vect6::Get_1int(int i) const{
+  return elements[i-1];
+}
+
+void Vect6::Set_1int(int i, double value){
+  elements[i-1] = value;
+}
+
+double Vect6::BasicGet_1int(int i) const{
+  return elements[i];
+}
+
+void Vect6::BasicSet_1int(int i, double value){
+  elements[i] = value;
+}
+
+void Vect6::BasicIncrement_1int(int i, double value){
+  elements[i] += value;
+}
+
+void Vect6::Const(double value){
+  elements[0] = value;
+  elements[1] = value;
+  elements[2] = value;
+  elements[3] = value;
+  elements[4] = value;
+  elements[5] = value;
+}
+
+MatrixType Vect6::GetType() const{
+  return VECT6;
+}
+
+istream& Vect6::ReadData(istream& c){  //input
+  for(int i=0;i<6;i++)
+    c >> elements[i];
+  return c;
+}
+
+ostream& Vect6::WriteData(ostream& c) const{  //output
+  for(int i=0;i<6;i++)
+    c << elements[i] << ' ';
+  return c;
+}
+
+void Vect6::AssignVM(const VirtualMatrix& A){
+  // error check
+  if( (A.GetNumRows() != 6) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    elements[i] = A.BasicGet(i,0);
+}
+
+Vect6& Vect6::operator=(const Vect6& A){ // assignment operator
+  elements[0] = A.elements[0];
+  elements[1] = A.elements[1];
+  elements[2] = A.elements[2];
+  elements[3] = A.elements[3];
+  elements[4] = A.elements[4];
+  elements[5] = A.elements[5];
+  return *this;
+}
+
+Vect6& Vect6::operator=(const VirtualMatrix& A){ // overloaded =
+  // error check
+  if( (A.GetNumRows() != 6) || (A.GetNumCols() != 1) ){
+    cerr << "illegal matrix size" << endl;
+    exit(0);
+  }
+
+  for(int i=0;i<numrows;i++)
+    elements[i] = A.BasicGet(i,0);
+  return *this;
+}
+
+Vect6& Vect6::operator*=(double b){
+  elements[0] *= b;
+  elements[1] *= b;
+  elements[2] *= b;
+  elements[3] *= b;
+  elements[4] *= b;
+  elements[5] *= b;
+  return *this;
+}
+
diff --git a/lib/poems/vect6.h b/lib/poems/vect6.h
new file mode 100644
index 000000000..c346c852e
--- /dev/null
+++ b/lib/poems/vect6.h
@@ -0,0 +1,70 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: vect6.h                                                 *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#ifndef VECT6_H
+#define VECT6_H
+
+#include "virtualcolmatrix.h"
+
+class Matrix;
+class Mat6x6;
+class ColMatrix;
+class Vect3;
+
+class Vect6 : public VirtualColMatrix  {
+  double elements[6];
+public:
+  Vect6();
+  ~Vect6();
+  Vect6(const Vect6& A);  // copy constructor
+  Vect6(const VirtualMatrix& A);  // copy constructor
+
+  double& operator_1int (int i); // array access
+  double Get_1int(int i) const;
+  void Set_1int(int i, double value);
+  double BasicGet_1int(int i) const;
+  void BasicSet_1int(int i, double value);
+  void BasicIncrement_1int(int i, double value);
+
+  void Const(double value);
+  MatrixType GetType() const;
+  std::ostream& WriteData(std::ostream& c) const;
+  std::istream& ReadData(std::istream& c);
+
+  void AssignVM(const VirtualMatrix& A);
+  Vect6& operator=(const Vect6& A); // assignment operator
+  Vect6& operator=(const VirtualMatrix& A); // overloaded =
+  Vect6& operator*=(double b);
+
+  friend Matrix T(const Vect6& A);  // a wasteful transpose
+
+  friend void Set6DAngularVector(Vect6& v6, Vect3& v3);
+  friend void Set6DLinearVector(Vect6& v6, Vect3& v3);
+
+  // fast matrix operations
+  friend void FastAdd(Vect6& A, Vect6& B, Vect6& C);
+  friend void FastSubt(Vect6& A, Vect6& B, Vect6& C);
+  friend void FastMult(Mat6x6& A, Vect6& B, Vect6& C);
+  friend void FastMult(Matrix& A, ColMatrix& B, Vect6& C);
+  friend void FastTMult(Mat6x6& A, Vect6& B, Vect6& C);
+  friend void FastTMult(Matrix& A, Vect6& B, ColMatrix& C);
+  friend void FastLDLTSubs(Mat6x6& LD, Vect6& B, Vect6& C);
+
+  friend void OnPopulateSVect(Vect3& angular, Vect3& linear, Vect6& sV);
+};
+
+#endif
diff --git a/lib/poems/virtualcolmatrix.cpp b/lib/poems/virtualcolmatrix.cpp
new file mode 100644
index 000000000..05f33e793
--- /dev/null
+++ b/lib/poems/virtualcolmatrix.cpp
@@ -0,0 +1,65 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: virtualcolmatrix.cpp                                    *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+#include "virtualcolmatrix.h"
+#include <iostream>
+
+using namespace std;
+
+VirtualColMatrix::VirtualColMatrix(){
+  numcols = 1;
+}
+
+VirtualColMatrix::~VirtualColMatrix(){
+}
+
+double& VirtualColMatrix::operator_2int(int i, int j){
+	if(j!=1){
+		cerr << "matrix index invalid in operator ()" << endl;
+		exit(1);
+	}
+	return (*this).operator_1int(i);
+}
+
+double VirtualColMatrix::Get_2int(int i, int j) const{
+  if(j!=1){
+    cerr << "Subscript out of bounds for collumn matrix" << endl;
+    exit(1);
+  }
+  return Get_1int(i);
+}
+
+void VirtualColMatrix::Set_2int(int i, int j, double value){
+  if(j!=1){
+    cerr << "Subscript out of bounds for collumn matrix" << endl;
+    exit(1);
+  }
+  Set_1int(i,value);
+}
+
+double VirtualColMatrix::BasicGet_2int(int i, int j) const{
+  return BasicGet_1int(i);
+}
+
+void VirtualColMatrix::BasicSet_2int(int i, int j, double value){
+  BasicSet_1int(i,value);
+}
+
+void VirtualColMatrix::BasicIncrement_2int(int i, int j, double value){
+  BasicIncrement_1int(i,value);
+}
+
diff --git a/lib/poems/virtualcolmatrix.h b/lib/poems/virtualcolmatrix.h
new file mode 100644
index 000000000..1548794ca
--- /dev/null
+++ b/lib/poems/virtualcolmatrix.h
@@ -0,0 +1,45 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: virtualcolmatrix.h                                      *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef VIRTUALCOLMATRIX_H
+#define VIRTUALCOLMATRIX_H
+
+#include "virtualmatrix.h"
+
+
+class VirtualColMatrix : public VirtualMatrix  {
+public: 
+	VirtualColMatrix();
+	~VirtualColMatrix();
+	double& operator_2int (int i, int j); // array access
+	double Get_2int (int i, int j) const;
+	void Set_2int (int i, int j, double value);
+	double BasicGet_2int(int i, int j) const;
+	void BasicSet_2int(int i, int j, double value);
+	void BasicIncrement_2int(int i, int j, double value);
+
+	virtual double& operator_1int (int i) = 0; // array access
+	virtual double Get_1int(int i) const = 0;
+	virtual void Set_1int(int i, double value) = 0;
+	virtual double BasicGet_1int(int i) const = 0;
+	virtual void BasicSet_1int(int i, double value) = 0;
+	virtual void BasicIncrement_1int(int i, double value) = 0;
+
+};
+
+#endif
diff --git a/lib/poems/virtualmatrix.cpp b/lib/poems/virtualmatrix.cpp
new file mode 100644
index 000000000..dc9fa6049
--- /dev/null
+++ b/lib/poems/virtualmatrix.cpp
@@ -0,0 +1,170 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: virtualmatrix.cpp                                       *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "virtualmatrix.h"
+#include "matrixfun.h"
+
+using namespace std;
+
+VirtualMatrix::VirtualMatrix(){
+  numrows = numcols = 0;
+}
+
+VirtualMatrix::~VirtualMatrix(){
+}
+
+int VirtualMatrix::GetNumRows() const {
+  return numrows;
+}
+
+int VirtualMatrix::GetNumCols() const {
+  return numcols;
+}
+
+double& VirtualMatrix::operator() (int i, int j){ // array access
+	return operator_2int(i,j);
+}
+
+double VirtualMatrix::Get(int i, int j) const{
+	return Get_2int(i,j);
+}
+
+void VirtualMatrix::Set(int i, int j, double value){
+	Set_2int(i,j,value);
+}
+
+double VirtualMatrix::BasicGet(int i, int j) const{
+	return BasicGet_2int(i,j);
+}
+
+void VirtualMatrix::BasicSet(int i, int j, double value){
+	BasicSet_2int(i,j,value);
+}
+
+void VirtualMatrix::BasicIncrement(int i, int j, double value){
+	BasicIncrement_2int(i,j,value);
+}
+
+double& VirtualMatrix::operator() (int i){
+	return operator_1int(i);
+}
+
+double VirtualMatrix::Get(int i) const{
+	return Get_1int(i);
+}
+
+void VirtualMatrix::Set(int i, double value){
+	Set_1int(i, value);
+}
+
+double VirtualMatrix::BasicGet(int i) const{
+	return BasicGet_1int(i);
+}
+
+void VirtualMatrix::BasicSet(int i, double value){
+	BasicSet_1int(i, value);
+}
+
+void VirtualMatrix::BasicIncrement(int i, double value){
+	BasicIncrement_1int(i, value);
+}
+
+double& VirtualMatrix::operator_1int (int i) {
+	cerr << "Error: single dimensional access is not defined for matrices of type " << GetType() << endl;
+	exit(0);
+	return *(new double);
+}
+
+double VirtualMatrix::Get_1int(int i) const {
+	cerr << "Error: single dimensional access is not defined for matrices of type " << GetType() << endl;
+	exit(0);
+	return 0.0;
+}
+
+void VirtualMatrix::Set_1int(int i, double value){
+	cerr << "Error: single dimensional access is not defined for matrices of type " << GetType() << endl;
+	exit(0);
+}
+
+double VirtualMatrix::BasicGet_1int(int i) const {
+	cerr << "Error: single dimensional access is not defined for matrices of type " << GetType() << endl;
+	exit(0);
+	return 0.0;
+}
+
+void VirtualMatrix::BasicSet_1int(int i, double value) {
+	cerr << "Error: single dimensional access is not defined for matrices of type " << GetType() << endl;
+	exit(0);
+}
+
+void VirtualMatrix::BasicIncrement_1int(int i, double value){
+	cerr << "Error: single dimensional access is not defined for matrices of type " << GetType() << endl;
+	exit(0);
+}
+
+void VirtualMatrix::Zeros(){
+  Const(0.0);
+}
+
+void VirtualMatrix::Ones(){
+  Const(1.0);
+}
+
+ostream& VirtualMatrix::WriteData(ostream& c) const {
+  cerr << "Error: no output definition for matrices of type " << GetType() << endl;
+  exit(0);
+}
+
+istream& VirtualMatrix::ReadData(istream& c){
+	cerr << "Error: no input definition for matrices of type " << GetType() << endl;
+	exit(0);
+}
+
+//
+// operators and functions
+//
+
+ostream& operator<< (ostream& c, const VirtualMatrix& A){  //output
+  c << A.GetType() << ' ';
+  A.WriteData(c);
+  c << endl;
+  return c;
+}
+
+istream& operator>> (istream& c, VirtualMatrix& A){  //input
+  VirtualMatrix* vm;
+  int matrixtype;
+  c >> matrixtype;
+
+  if( MatrixType(matrixtype) == A.GetType() ) A.ReadData(c);
+  else{
+    // issue a warning?
+    cerr << "Warning: During matrix read expected type " << A.GetType() << " and got type " << matrixtype << endl;
+    vm = NewMatrix(matrixtype);
+    if(!vm){
+      cerr << "Error: unable to instantiate matrix of type " << matrixtype << endl;
+      exit(0);
+    }
+    vm->ReadData(c);
+    A.AssignVM(*vm);
+    delete vm;
+  }
+
+  return c;
+}
+
diff --git a/lib/poems/virtualmatrix.h b/lib/poems/virtualmatrix.h
new file mode 100644
index 000000000..a27c7de04
--- /dev/null
+++ b/lib/poems/virtualmatrix.h
@@ -0,0 +1,87 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: virtualmatrix.h                                              *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef VIRTUALMATRIX_H
+#define VIRTUALMATRIX_H
+#include <iostream>
+
+enum MatrixType {
+	MATRIX = 0,
+	COLMATRIX = 1,
+	ROWMATRIX = 2,
+	MAT3X3 = 3,
+	VECT3 = 4,
+	MAT6X6 = 5,
+	VECT6 = 6,
+	COLMATMAP = 7,
+	VECT4 = 8,
+	MAT4X4 = 9
+};
+
+class VirtualMatrix {
+protected:
+	int numrows, numcols;
+public:
+	VirtualMatrix();
+	virtual ~VirtualMatrix();
+	int GetNumRows() const;
+	int GetNumCols() const;
+
+	double& operator() (int i, int j); // array access
+	double Get(int i, int j) const;
+	void Set(int i, int j, double value);
+	double BasicGet(int i, int j) const;
+	void BasicSet(int i, int j, double value);
+	void BasicIncrement(int i, int j, double value);
+
+	double& operator() (int i); // array access
+	double Get(int i) const;
+	void Set(int i, double value);
+	double BasicGet(int i) const;
+	void BasicSet(int i, double value);
+	void BasicIncrement(int i, double value);
+
+	virtual void Const(double value) = 0;
+	virtual MatrixType GetType() const = 0;
+	virtual void AssignVM(const VirtualMatrix& A) = 0;
+	void Zeros();
+	void Ones();
+	virtual std::ostream& WriteData(std::ostream& c) const;
+	virtual std::istream& ReadData(std::istream& c);
+
+protected:
+	virtual double& operator_2int(int i, int j) = 0;
+	virtual double& operator_1int(int i);
+	virtual double Get_2int(int i, int j) const = 0;
+	virtual double Get_1int(int i) const ;
+	virtual void Set_2int(int i, int j, double value) = 0;
+	virtual void Set_1int(int i, double value);
+	virtual double BasicGet_2int(int i, int j) const = 0;
+	virtual double BasicGet_1int(int i) const ;
+	virtual void BasicSet_2int(int i, int j, double value) = 0;
+	virtual void BasicSet_1int(int i, double value);
+	virtual void BasicIncrement_2int(int i, int j, double value) = 0;
+	virtual void BasicIncrement_1int(int i, double value);
+
+};
+
+// overloaded operators
+std::ostream& operator<< (std::ostream& c, const VirtualMatrix& A); // output
+std::istream& operator>> (std::istream& c, VirtualMatrix& A); // input
+
+#endif
diff --git a/lib/poems/virtualrowmatrix.cpp b/lib/poems/virtualrowmatrix.cpp
new file mode 100644
index 000000000..f57e94d23
--- /dev/null
+++ b/lib/poems/virtualrowmatrix.cpp
@@ -0,0 +1,67 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: virtualrowmatrix.cpp                                    *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "virtualrowmatrix.h"
+#include <iostream>
+
+using namespace std;
+
+VirtualRowMatrix::VirtualRowMatrix(){
+  numrows = 1;
+}
+
+VirtualRowMatrix::~VirtualRowMatrix(){
+}
+
+double& VirtualRowMatrix::operator_2int (int i, int j){
+	if(i!=1){
+		cerr << "matrix index invalid in operator ()" << endl;
+		exit(1);
+	}
+  return (*this).operator_1int(j);
+}
+
+double VirtualRowMatrix::Get_2int(int i, int j) const{
+  if(i!=1){
+    cerr << "Subscript out of bounds for row matrix" << endl;
+    exit(1);
+  }
+  return Get_1int(j);
+}
+
+void VirtualRowMatrix::Set_2int(int i, int j, double value){
+  if(i!=1){
+    cerr << "Subscript out of bounds for row matrix" << endl;
+    exit(1);
+  }
+  Set_1int(j,value);
+}
+
+double VirtualRowMatrix::BasicGet_2int(int i, int j) const{
+  return BasicGet_1int(j);
+}
+
+void VirtualRowMatrix::BasicSet_2int(int i, int j, double value){
+  BasicSet_1int(j,value);
+}
+
+void VirtualRowMatrix::BasicIncrement_2int(int i, int j, double value){
+  BasicIncrement_1int(j,value);
+}
+
+
diff --git a/lib/poems/virtualrowmatrix.h b/lib/poems/virtualrowmatrix.h
new file mode 100644
index 000000000..68b39f137
--- /dev/null
+++ b/lib/poems/virtualrowmatrix.h
@@ -0,0 +1,43 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: virtualrowmatrix.h                                      *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef VIRTUALROWMATRIX_H
+#define VIRTUALROWMATRIX_H
+
+#include "virtualmatrix.h"
+
+class VirtualRowMatrix : public VirtualMatrix  {
+public: 
+  VirtualRowMatrix();
+  ~VirtualRowMatrix();
+  double& operator_2int (int i, int j); // array access
+  double Get_2int(int i, int j) const;
+  void Set_2int(int i, int j, double value);
+  double BasicGet_2int(int i, int j) const;
+  void BasicSet_2int(int i, int j, double value);
+  void BasicIncrement_2int(int i, int j, double value);
+  
+  virtual double& operator_1int (int i) = 0; // array access
+  virtual double Get_1int(int i) const = 0;
+  virtual void Set_1int(int i, double value) = 0;
+  virtual double BasicGet_1int(int i) const = 0;
+  virtual void BasicSet_1int(int i, double value) = 0;
+  virtual void BasicIncrement_1int(int i, double value) = 0;
+};
+
+#endif
diff --git a/lib/poems/workspace.cpp b/lib/poems/workspace.cpp
new file mode 100644
index 000000000..54a32c124
--- /dev/null
+++ b/lib/poems/workspace.cpp
@@ -0,0 +1,489 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: workspace.cpp                                           *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#include "workspace.h"
+#include "system.h"
+#include "solver.h"
+#include "SystemProcessor.h"
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <cmath>
+
+
+using namespace std;
+
+void Workspace::allocateNewSystem() {
+  currentIndex++;
+  if(currentIndex < maxAlloc)
+  {
+	  system[currentIndex].system = new System;
+  }
+  else
+  {
+	  maxAlloc = (maxAlloc + 1) * 2; 
+									 
+	  SysData * tempPtrSys = new SysData[maxAlloc];
+	  for(int i = 0; i < currentIndex; i++)
+	  {
+		  tempPtrSys[i] = system[i];
+	  }
+	  delete [] system;				  
+	  system = tempPtrSys;
+	  system[currentIndex].system = new System; 
+  }
+}
+
+Workspace::Workspace(){
+	currentIndex = -1; 
+	maxAlloc = 0;		
+	system = NULL;		
+}
+
+Workspace::~Workspace(){
+  for(int i = 0; i <= currentIndex; i++){
+	  delete system[i].system;
+  }
+  delete [] system;						
+}
+
+
+bool Workspace::LoadFile(char* filename){
+  bool ans;
+  ifstream file;
+  file.open(filename, ifstream::in);
+  if( !file.is_open() ){
+    cerr << "File '" << filename << "' not found." << endl;
+    return false;
+  }
+  allocateNewSystem();
+  ans = system[currentIndex].system->ReadIn(file);
+  file.close();
+
+  return ans;
+}
+
+void Workspace::SetLammpsValues(double dtv, double dthalf, double tempcon){
+	Thalf = dthalf;
+	Tfull = dtv;
+	ConFac = tempcon;	
+}
+
+
+bool Workspace::MakeSystem(int& nbody, double *&masstotal, double **&inertia, double **&xcm, double **&vcm, double **&omega, double **&ex_space, double **&ey_space, double **&ez_space, int &njoint, int **&jointbody, double **&xjoint, int& nfree, int*freelist, double dthalf, double dtv, double tempcon, double KE){
+	
+	SetLammpsValues(dtv, dthalf, tempcon);		
+	
+if(njoint){		
+	SystemProcessor sys;	
+	sys.processArray(jointbody, njoint);  	
+	List<POEMSChain> * results = sys.getSystemData();		
+
+	int numsyschains = results->GetNumElements();	
+	int headvalue = 0;
+	List<POEMSChain> * newresults = results;	
+	ListElement<POEMSChain> * tempNode = results->GetHeadElement();			
+	int stop = 1;
+	int counter = 1;
+	for(int n = 1; n<=numsyschains; n++){						
+		while(stop){			
+			if ( (*(tempNode->value->listOfNodes.GetHeadElement()->value) == (headvalue+1) ) || (*(tempNode->value->listOfNodes.GetTailElement()->value) == (headvalue+1) ) ) {			
+			newresults->Append(tempNode->value);								
+			headvalue = headvalue + tempNode->value->listOfNodes.GetNumElements();						
+			tempNode = results->GetHeadElement();					
+			stop = 0;			
+			counter ++;						
+		}		
+		else{						
+			tempNode = tempNode->next;						
+		}				
+		}
+		stop=1;			
+	}		
+	
+	ListElement<POEMSChain> * TNode = newresults->GetHeadElement();
+	ListElement<POEMSChain> * TTNode = newresults->GetHeadElement();
+	for(int kk=1; kk<=numsyschains; kk++){		
+		if(kk!=numsyschains)
+			TTNode = TNode->next;
+		newresults->Remove(TNode);			
+		if(kk!=numsyschains)
+			TNode = TTNode;		
+	}
+	ListElement<POEMSChain> * NodeValue = newresults->GetHeadElement();
+	int count = 0; 	
+	int * array;
+	int ** arrayFromChain;
+	int numElementsInSystem;
+	int ttk = 0;
+	
+		
+	while(NodeValue != NULL) {
+		array = new int[NodeValue->value->listOfNodes.GetNumElements()];
+		arrayFromChain = NodeValue->value->listOfNodes.CreateArray();
+		numElementsInSystem = NodeValue->value->listOfNodes.GetNumElements();								
+		for(int counter = 0; counter < numElementsInSystem; counter++){
+			array[counter] = *arrayFromChain[counter];
+		}
+				
+		SetKE(1,KE);
+		allocateNewSystem();			
+		system[currentIndex].system->Create_System_LAMMPS(nbody,masstotal,inertia,xcm,xjoint,vcm,omega,ex_space,ey_space,ez_space, numElementsInSystem, array, count);					
+		
+		system[currentIndex].solver = ONSOLVER;
+		ttk = ttk + 1;		
+		count = ttk;
+		delete [] array;
+		delete [] arrayFromChain;
+		NodeValue= NodeValue->next;						
+	}
+}
+if(nfree){
+	MakeDegenerateSystem(nfree,freelist,masstotal,inertia,xcm,vcm,omega,ex_space,ey_space,ez_space);
+}
+	return true;
+}
+
+
+bool Workspace::MakeDegenerateSystem(int& nfree, int*freelist, double *&masstotal, double **&inertia, double **&xcm, double **&vcm, double **&omega, double **&ex_space, double **&ey_space, double **&ez_space){
+	allocateNewSystem();
+	system[currentIndex].system->Create_DegenerateSystem(nfree,freelist,masstotal,inertia,xcm,vcm,omega,ex_space,ey_space,ez_space);
+	system[currentIndex].solver = ONSOLVER;
+	return true;			
+} 
+
+bool Workspace::SaveFile(char* filename, int index){ 
+  if(index < 0){
+	  index = currentIndex; 
+  }
+  ofstream file;
+
+  file.open(filename, ofstream::out);
+  
+  if( !file.is_open() ){
+    cerr << "File '" << filename << "' could not be opened." << endl;
+    return false;
+  }
+  if(index >= 0 && index <= currentIndex){
+	  system[index].system->WriteOut(file);
+  }
+  else {
+	  cerr << "Error, requested system index " << index << ", minimum index 0 and maximum index " << currentIndex << endl;
+  }
+  file.close();
+  return true;
+}
+
+
+System* Workspace::GetSystem(int index){
+	if(index <= currentIndex){
+		if(index >= 0){
+			return system[index].system;			
+		}
+		else{
+			return system[currentIndex].system; 
+		}
+	}
+	else{
+		return NULL;
+	}
+}
+
+void Workspace::AddSolver(Solver* s, int index){
+	if(currentIndex >= index){
+		if(index >= 0){
+			system[index].solver = (int)s->GetSolverType();
+		}
+		else{
+			system[currentIndex].solver = (int)s->GetSolverType();
+		}
+	}
+	else{
+		cout << "Error adding solver to index " << index << endl;
+	}
+}
+
+int Workspace::getNumberOfSystems(){
+	return currentIndex + 1;
+}
+
+
+
+void Workspace::SetKE(int temp, double SysKE){	
+KE_val = SysKE;
+FirstTime =temp;
+}
+    
+
+void Workspace::LobattoOne(double **&xcm, double **&vcm,double **&omega,double **&torque, double **&fcm, double **&ex_space, double **&ey_space, double **&ez_space){
+	
+	int numsys = currentIndex;
+	int numbodies;
+	double time = 0.0;
+	int * mappings;
+	double SysKE=0.0;
+		
+	for (int i = 0; i <= numsys; i++){
+		mappings = system[i].system->GetMappings();
+		numbodies = system[i].system->GetNumBodies() - 1;
+		Matrix FF(6,numbodies);
+		FF.Zeros();
+		for (int j=1; j<=numbodies; j++){
+			FF(1,j)  = torque[mappings[j - 1]-1][0]*ConFac;
+			FF(2,j)  = torque[mappings[j - 1]-1][1]*ConFac;
+			FF(3,j)  = torque[mappings[j - 1]-1][2]*ConFac;
+			
+			FF(4,j)  = fcm[mappings[j - 1]-1][0]*ConFac;
+			FF(5,j)  = fcm[mappings[j - 1]-1][1]*ConFac;
+			FF(6,j)  = fcm[mappings[j - 1]-1][2]*ConFac;
+		}
+		
+		//------------------------------------//
+		// Get a solver and solve that system.
+		Solver * theSolver = Solver::GetSolver((SolverType)system[i].solver);				
+		theSolver->SetSystem(system[i].system);	
+		theSolver->Solve(time, FF);	
+		
+		
+		theSolver->Solve(time, FF);		
+		ColMatrix tempx = *((*theSolver).GetState());
+		ColMatrix tempv = *((*theSolver).GetStateDerivative());
+		ColMatrix tempa = *((*theSolver).GetStateDerivativeDerivative());
+		
+		
+		for(int numint =0 ; numint<3; numint++){
+			theSolver->Solve(time, FF);
+			tempa = *((*theSolver).GetStateDerivativeDerivative());
+			*((*theSolver).GetStateDerivative())= tempv + Thalf*tempa;
+		}
+		
+		ColMatrix TempV= *((*theSolver).GetStateDerivative());
+		*((*theSolver).GetState())= tempx + Tfull*TempV;
+				
+		int numjoints = system[i].system->joints.GetNumElements();
+		for(int k = 0; k < numjoints; k++){
+			system[i].system->joints(k)->ForwardKinematics();
+		}		
+		
+		for(int k = 0; k < numbodies; k++){
+			Vect3 temp1 =system[i].system->bodies(k+1)->r;
+			Vect3 temp2 =system[i].system->bodies(k+1)->v;
+			Vect3 temp3 =system[i].system->bodies(k+1)->omega;
+			Mat3x3 temp4 =system[i].system->bodies(k+1)->n_C_k;			
+			for(int m = 0; m < 3; m++){
+				xcm[mappings[k]-1][m]   = temp1(m+1);
+				vcm[mappings[k]-1][m]   = temp2(m+1);
+				omega[mappings[k]-1][m] = temp3(m+1);				
+				ex_space[mappings[k]-1][m] = temp4(m+1,1);				
+				ey_space[mappings[k]-1][m] = temp4(m+1,2);
+				ez_space[mappings[k]-1][m] = temp4(m+1,3);				
+			}			
+			SysKE = SysKE + system[i].system->bodies(k+1)->KE;
+		} 		
+		delete theSolver;		      
+	}	
+}
+
+void Workspace::LobattoTwo(double **&vcm,double **&omega,double **&torque, double **&fcm){
+	int numsys = currentIndex;
+	int numbodies;				
+	double time = 0.0;   
+	int * mappings;
+	double SysKE =0.0;		
+	for (int i = 0; i <= numsys; i++){
+		mappings = system[i].system->GetMappings();
+		numbodies = system[i].system->GetNumBodies() - 1;
+		Matrix FF(6,numbodies);				
+				
+		for (int j=1; j<=numbodies; j++){
+			FF(1,j)  = torque[mappings[j - 1]-1][0]*ConFac;
+			FF(2,j)  = torque[mappings[j - 1]-1][1]*ConFac;
+			FF(3,j)  = torque[mappings[j - 1]-1][2]*ConFac;
+			FF(4,j)  = fcm[mappings[j - 1]-1][0]*ConFac;
+			FF(5,j)  = fcm[mappings[j - 1]-1][1]*ConFac;
+			FF(6,j)  = fcm[mappings[j - 1]-1][2]*ConFac;
+		}			
+		
+		//------------------------------------//
+		// Get a solver and solve that system.		
+		Solver * theSolver = Solver::GetSolver((SolverType)system[i].solver);		
+		theSolver->SetSystem(system[i].system);    			
+		theSolver->Solve(time, FF);		
+		ColMatrix tempv = *((*theSolver).GetStateDerivative());
+		ColMatrix tempa = *((*theSolver).GetStateDerivativeDerivative());
+		*((*theSolver).GetStateDerivative()) = tempv + Thalf*tempa;
+		
+						
+		int numjoints = system[i].system->joints.GetNumElements();
+		for(int k = 0; k < numjoints; k++){
+			system[i].system->joints(k)->ForwardKinematics(); 
+		}				
+		    		
+		for(int k = 0; k < numbodies; k++){
+			Vect3 temp1 =system[i].system->bodies(k+1)->r;			
+			Vect3 temp2 =system[i].system->bodies(k+1)->v;	    	
+			Vect3 temp3 =system[i].system->bodies(k+1)->omega;
+			SysKE = SysKE + system[i].system->bodies(k+1)->KE;
+			for(int m = 0; m < 3; m++){
+				vcm[mappings[k]-1][m]   = temp2(m+1);
+				omega[mappings[k]-1][m] = temp3(m+1);
+			}			
+		}
+		delete theSolver;
+	}	
+}
+
+    
+ 
+  void Workspace::RKStep(double **&xcm, double **&vcm,double **&omega,double **&torque, double **&fcm, double **&ex_space, double **&ey_space, double **&ez_space){
+	
+	  double a[6];
+	  double b[6][6];
+	  double c[6];
+	  //double e[6];
+	 
+	  a[1] = 0.2;
+	  a[2] = 0.3;
+	  a[3] = 0.6;
+	  a[4] = 1.0;
+	  a[5] = 0.875;
+
+	  b[1][0] = 0.2;
+	  b[2][0] = 0.075;           b[2][1] = 0.225;
+	  b[3][0] = 0.3;             b[3][1] = -0.9;        b[3][2] = 1.2;
+	  b[4][0] = -11.0/54.0;      b[4][1] = 2.5;         b[4][2] = -70.0/27.0;    b[4][3] = 35.0/27.0;
+	  b[5][0] = 1631.0/55296.0; b[5][1] = 175.0/512.0; b[5][2] = 575.0/13824.0; b[5][3] = 44275.0/110592.0; b[5][4] = 253.0/4096.0;
+
+	  c[0] = 37.0/378.0;
+	  c[1] = 0.0;
+	  c[2] = 250.0/621.0;
+	  c[3] = 125.0/594.0;
+	  c[4] = 0.0;
+	  c[5] = 512.0/1771.0;
+
+	  int numsys = currentIndex; 
+	  int numbodies;				
+	  double time = 0.0;   
+	  int * mappings;
+	  double SysKE =0.0;
+
+	  
+	  for (int i = 0; i <= numsys; i++){
+		  mappings = system[i].system->GetMappings();  
+
+		  numbodies = system[i].system->GetNumBodies() - 1;
+		  Matrix FF(6,numbodies);
+		  for (int j=1; j<=numbodies; j++){
+			  FF(1,j)  = ConFac*torque[mappings[j - 1]-1][0];
+			  FF(2,j)  = ConFac*torque[mappings[j - 1]-1][1];
+			  FF(3,j)  = ConFac*torque[mappings[j - 1]-1][2];            			   
+
+			  FF(4,j)  = ConFac*fcm[mappings[j - 1]-1][0];
+			  FF(5,j)  = ConFac*fcm[mappings[j - 1]-1][1];
+			  FF(6,j)  = ConFac*fcm[mappings[j - 1]-1][2];
+		  }					  
+		
+		
+		  //------------------------------------//
+		// Get a solver and solve that system.		
+		  Solver * theSolver = Solver::GetSolver((SolverType)system[i].solver);		
+		  theSolver->SetSystem(system[i].system);    			
+		  theSolver->Solve(time, FF);	
+	
+		  ColMatrix initial_x;  
+		  ColMatrix initial_xdot;
+		  ColMatMap* x;
+		  ColMatMap* xdot;
+		  ColMatMap* xdotdot;
+	
+		  x = theSolver->GetState();  
+		  xdot = theSolver->GetStateDerivative();
+		  xdotdot=theSolver->GetStateDerivativeDerivative(); 
+	
+		  initial_x = *x;  
+		  initial_xdot = *xdot;  
+		  ColMatrix f[6];
+		  ColMatrix ff[6];
+	
+		  ff[0] = initial_xdot; 
+		  f[0] = *xdotdot; 
+	
+		  for(int ii=1;ii<6;ii++){
+			  time = a[ii] * Tfull;		
+			  (*x) = initial_x;		
+			  (*xdot) = initial_xdot;		
+			  for(int j=0;j<ii;j++){
+				  (*x) = (*x) + (b[ii][j]*Tfull)*ff[j];      		
+				  (*xdot) = (*xdot) + (b[ii][j]*Tfull)*f[j];      		
+			  }			
+			  theSolver->Solve(time,FF);    
+			  f[ii] = (*xdotdot);
+			  ff[ii] = (*xdot);
+		  }  	
+  
+	
+		  (*x) = initial_x + (c[0]*Tfull)*ff[0] + (c[2]*Tfull)*ff[2] + (c[3]*Tfull)*ff[3] + (c[5]*Tfull)*ff[5];  
+	
+		  (*xdot) = initial_xdot + (c[0]*Tfull)*f[0] + (c[2]*Tfull)*f[2] + (c[3]*Tfull)*f[3] + (c[5]*Tfull)*f[5];  
+	
+	
+		  int numjoints = system[i].system->joints.GetNumElements();
+		  for(int k = 0; k < numjoints; k++){
+			  system[i].system->joints(k)->ForwardKinematics();
+		  }		      
+						      	
+		
+		  for(int k = 0; k < numbodies; k++){
+			  Vect3 temp1 =system[i].system->bodies(k+1)->r;
+			  Vect3 temp2 =system[i].system->bodies(k+1)->v;
+			  Vect3 temp3 =system[i].system->bodies(k+1)->omega;
+			  Mat3x3 temp4 =system[i].system->bodies(k+1)->n_C_k;
+			  SysKE = SysKE + system[i].system->bodies(k+1)->KE;			  
+			  for(int m = 0; m < 3; m++){
+				  xcm[mappings[k]-1][m]   = temp1(m+1);
+				  vcm[mappings[k]-1][m]   = temp2(m+1);
+				  omega[mappings[k]-1][m] = temp3(m+1);
+				
+				  ex_space[mappings[k]-1][m] = temp4(m+1,1);				
+				  ey_space[mappings[k]-1][m] = temp4(m+1,2);
+				  ez_space[mappings[k]-1][m] = temp4(m+1,3);
+			  }         
+		  } 		
+		  delete theSolver;		      
+	  }	 	
+  }
+
+
+void Workspace::WriteFile(char * filename){
+	int numsys = currentIndex; 
+	int numbodies;				
+		  
+	
+	for (int i = 0; i <= numsys; i++){
+		numbodies = system[i].system->GetNumBodies() - 1;  	
+		ofstream outfile;
+		outfile.open(filename,ofstream::out | ios::app);		
+		outfile << numbodies<<endl;
+		outfile << "Atoms "<<endl;
+		for(int k = 0; k < numbodies; k++){
+			Vect3 temp1 =system[i].system->bodies(k+1)->r;
+			outfile<<1<<"\t"<<temp1(1)<<"\t"<<temp1(2)<<"\t"<<temp1(3)<<endl;
+		}
+		outfile.close();
+	}	
+  }
diff --git a/lib/poems/workspace.h b/lib/poems/workspace.h
new file mode 100644
index 000000000..83af07783
--- /dev/null
+++ b/lib/poems/workspace.h
@@ -0,0 +1,88 @@
+/*
+ *_________________________________________________________________________*
+ *      POEMS: PARALLELIZABLE OPEN SOURCE EFFICIENT MULTIBODY SOFTWARE     *
+ *      DESCRIPTION: SEE READ-ME                                           *
+ *      FILE NAME: workspace.h                                             *
+ *      AUTHORS: See Author List                                           * 
+ *      GRANTS: See Grants List                                            *
+ *      COPYRIGHT: (C) 2005 by Authors as listed in Author's List          *
+ *      LICENSE: Please see License Agreement                              *
+ *      DOWNLOAD: Free at www.rpi.edu/~anderk5                             *
+ *      ADMINISTRATOR: Prof. Kurt Anderson                                 *
+ *                     Computational Dynamics Lab                          *
+ *                     Rensselaer Polytechnic Institute                    *
+ *                     110 8th St. Troy NY 12180                           * 
+ *      CONTACT:        anderk5@rpi.edu                                    *
+ *_________________________________________________________________________*/
+
+
+#ifndef WORKSPACE_H
+#define WORKSPACE_H
+
+#include "matrices.h"
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <stdio.h>   
+#include <iomanip>  
+#include <vector>
+
+
+class System;
+class Solver;
+
+struct SysData{
+	System * system;
+	int solver;
+	int integrator;
+};
+
+class Workspace {
+	SysData * system; // the multibody systems data
+	int currentIndex;
+	int maxAlloc;
+	
+public:
+     Workspace();
+     ~Workspace();
+     
+     double Thalf;
+     double Tfull;
+     double ConFac;
+     double KE_val;
+	  int FirstTime;
+     
+     bool LoadFile(char* filename);
+     
+     bool SaveFile(char* filename, int index = -1);
+
+     System* GetSystem(int index = -1);
+     
+     void AddSolver(Solver* s, int index = -1);        
+    
+
+     void LobattoOne(double **&xcm, double **&vcm,double **&omega,double **&torque, double **&fcm, double **&ex_space, double **&ey_space, double **&ez_space);	
+     
+     void LobattoTwo(double **&vcm,double **&omega,double **&torque, double **&fcm);	 
+     
+ 
+     bool MakeSystem(int& nbody, double *&masstotal, double **&inertia, double **&xcm, double **&vcm, double **&omega, double **&ex_space, double **&ey_space, double **&ez_space, int &njoint, int **&jointbody, double **&xjoint, int& nfree, int*freelist, double dthalf, double dtv, double tempcon, double KE);
+     																																							
+	  
+	  bool SaveSystem(int& nbody, double *&masstotal, double **&inertia, double **&xcm, double **&xjoint, double **&vcm, double **&omega, double **&ex_space, double **&ey_space, double **&ez_space, double **&acm, double **&alpha, double **&torque, double **&fcm, int **&jointbody, int &njoint);
+	  																		
+	 bool MakeDegenerateSystem(int& nfree, int*freelist, double *&masstotal, double **&inertia, double **&xcm, double **&vcm, double **&omega, double **&ex_space, double **&ey_space, double **&ez_space);
+     int getNumberOfSystems();
+     
+     void SetLammpsValues(double dtv, double dthalf, double tempcon);
+     void SetKE(int temp, double SysKE);
+	  
+	  void RKStep(double **&xcm, double **&vcm,double **&omega,double **&torque, double **&fcm, double **&ex_space, double **&ey_space, double **&ez_space);	
+	  
+	  void WriteFile(char* filename);
+
+private:
+	void allocateNewSystem(); //helper function to handle vector resizing and such for the array of system pointers
+};
+
+#endif