Index: src/xtalopt/xtalopt.cpp
===================================================================
--- src/xtalopt/xtalopt.cpp	(revision 364d7157c1b4363ccb37a2c39e7e8579d62163d3)
+++ src/xtalopt/xtalopt.cpp	(revision 06f244abd607a7c31b6ed64e2a2c378638e727d2)
@@ -26,4 +26,5 @@
 #include <xtalopt/ui/dialog.h>
 #include <xtalopt/genetic.h>
+#include <xtalopt/molecularxtaloptimizer.h>
 
 #include <xtalopt/mxtaloptgenetic.h>
@@ -726,5 +727,7 @@
   void XtalOpt::initializeAndAddXtal(Xtal *xtal, uint generation,
                                      const QString &parents)
-    {
+  {
+    MolecularXtal *mxtal = qobject_cast<MolecularXtal*>(xtal);
+
     xtalInitMutex->lock();
     QList<Structure*> allStructures = m_queue->lockForNaming();
@@ -776,8 +779,17 @@
     }
     xtal->findSpaceGroup(tol_spg);
+
+    // If this is a molecular xtal, flag it for preoptimization
+    if (mxtal != NULL) {
+      if (this->usePreopt) {
+        mxtal->setNeedsPreoptimization(true);
+      }
+    }
+
     xtalLocker.unlock();
     xtal->update();
     m_queue->unlockForNaming(xtal);
     xtalInitMutex->unlock();
+
   }
 
@@ -800,4 +812,68 @@
                            newXtal->getParents());
     }
+  }
+
+  void XtalOpt::preoptimizeStructure(Structure *s)
+  {
+    if (s == NULL) {
+      qWarning() << Q_FUNC_INFO << "NULL argument.";
+      return;
+    }
+
+    MolecularXtal *mxtal = qobject_cast<MolecularXtal*>(s);
+    if (mxtal == NULL) {
+      qWarning() << "No preoptimization method implemented for"
+                 << s->metaObject()->className();
+      return;
+    }
+
+    QtConcurrent::run(this, &XtalOpt::preoptimizeMXtal, mxtal);
+  }
+
+  void XtalOpt::preoptimizeMXtal(MolecularXtal *mxtal)
+  {
+    QWriteLocker locker (mxtal->lock());
+
+    if (!mxtal->needsPreoptimization())
+      return;
+
+    mxtal->emitPreoptimizationStarted();
+
+    mxtal->setNeedsPreoptimization(false);
+
+    mxtal->wrapAtomsToCell();
+
+    // Rough preoptimization
+    MolecularXtalOptimizer mxtalOpt (this, sOBMutex);
+    mxtalOpt.setDebug(this->mpo_debug);
+    mxtalOpt.setMXtal(mxtal);
+    mxtalOpt.setEnergyConvergence(this->mpo_econv);
+    mxtalOpt.setNumberOfGeometrySteps(this->mpo_maxSteps);
+    mxtalOpt.setSuperCellUpdateInterval(this->mpo_sCUpdateInterval);
+    mxtalOpt.setVDWCutoff(this->mpo_vdwCut);
+    mxtalOpt.setElectrostaticCutoff(this->mpo_eleCut);
+    mxtalOpt.setCutoffUpdateInterval(this->mpo_cutoffUpdateInterval);
+    mxtalOpt.setup();
+
+    mxtal->startOptTimer();
+    locker.unlock();
+    mxtalOpt.run();
+    locker.relock();
+    mxtal->stopOptTimer();
+
+    mxtal->setStatus(MolecularXtal::Updating);
+
+    if (mxtalOpt.isConverged() || mxtalOpt.reachedStepLimit()) {
+      mxtalOpt.updateMXtalCoords();
+      mxtal->wrapAtomsToCell();
+    }
+    else {
+      qWarning() << "Preoptimization failed for" << mxtal->getIDString()
+                 << ". Continuing with full optimization.";
+    }
+
+    mxtalOpt.releaseMXtal(); // Under writelock on mxtal->lock(), ok to call
+
+    mxtal->emitPreoptimizationFinished();
   }
 
