diff --git a/sdpm/_src/sdpmw.i b/sdpm/_src/sdpmw.i
index f6b5062cf82a3d915a2f320f63024731e88522a6..b27441a228f732ce52aa2a230dbc9b2b332019ee 100644
--- a/sdpm/_src/sdpmw.i
+++ b/sdpm/_src/sdpmw.i
@@ -91,6 +91,9 @@ threads="1"
 
 // SDPM typemaps
 %include "sdpm_def.h" // needed to access USE_CODI in SWIG interface
+#ifndef USE_CODI
+typedef double sdpmDouble; // needed so that SWIG does not convert sdpmDouble to double
+#endif
 %typemap(out) sdpmDouble {
 #ifndef USE_CODI
     $result = PyFloat_FromDouble($1);
@@ -107,6 +110,14 @@ threads="1"
 %template(std_vector_Elementp) std::vector<sdpm::Element *>;
 %template(std_vector_Tagp) std::vector<sdpm::Tag *>;
 %template(std_map_string_Tagp) std::map<std::string, sdpm::Tag *>;
+%template(std_vector_vector3d) std::vector<sdpmVector3d>;
+#ifndef USE_CODI
+%rename(std_vector_double) std::vector<sdpmDouble>;
+%rename(std_vector_vector_double) std::vector<std::vector<sdpmDouble>>;
+#else
+%template(std_vector_sdpmdouble) std::vector<sdpmDouble>;
+%template(std_vector_vector_sdpmdouble) std::vector<std::vector<sdpmDouble>>;
+#endif
 
 // SDPM
 %include "sdpm.h"
@@ -136,26 +147,40 @@ threads="1"
 
 // Interface to SDPM types
 class sdpmVector3d {};
-
 %extend sdpmVector3d {
-    double getitem(int i)
+    double __getitem__(int i)
     {
+        if (i > 2)
+            throw std::runtime_error("sdpmVector3d: index out of range (size 3)!\n");
 #ifndef USE_CODI
         return (*self)(i);
 #else
         return (*self)(i).getValue();
 #endif
     }
-    std::string __str__()
+    // use repr instead of str so that iterables also print nicely
+    std::string __repr__()
     {
-        std::ostringstream out; out << *self;  return out.str();
+        std::ostringstream out; out << *self;
+        return out.str();
     }
+}
 
-    %pythoncode {
-def __getitem__(self, idx): 
-    return self.getitem(idx)
+#ifdef USE_CODI
+class sdpmDouble {};
+%extend sdpmDouble {
+    double __float__()
+    {
+        return (*self).getValue();
+    }
+    // use repr instead of str so that iterables also print nicely
+    std::string __repr__()
+    {
+        std::ostringstream out; out << *self;
+        return out.str();
     }
 }
+#endif
 
 // Interface to SDPM classes
 namespace sdpm {
diff --git a/sdpm/api/om.py b/sdpm/api/om.py
index e052755b954b14a03eac0835fdce327ab701265a..4e75025d5620f735bb256089324ef9a9e3247dfe 100644
--- a/sdpm/api/om.py
+++ b/sdpm/api/om.py
@@ -80,8 +80,8 @@ class SdpmSolver(om.ExplicitComponent):
             self.adj.solve()
         # Set outputs
         for i in range(self.nf):
-            outputs['Q_re'][i, :, :] = np.array(self.sol.getGafMatrixRe(i))
-            outputs['Q_im'][i, :, :] = np.array(self.sol.getGafMatrixIm(i))
+            outputs['Q_re'][i, :, :] = np.array(self.sol.getGafMatrixRe(i), dtype=float)
+            outputs['Q_im'][i, :, :] = np.array(self.sol.getGafMatrixIm(i), dtype=float)
 
 class SdpmBuilder(Builder):
     """SDPM builder for OpenMDAO
diff --git a/sdpm/src/sdpm.h b/sdpm/src/sdpm.h
index e2bb57f7c7e1dc24c4a4f8b1a58b37ee3861c447..0fa95980af2d93c94b558621de308d04a43c3003 100644
--- a/sdpm/src/sdpm.h
+++ b/sdpm/src/sdpm.h
@@ -35,6 +35,7 @@
 #include <Eigen/Dense>
 #include <complex>
 
+#ifndef SWIG
 #ifndef USE_CODI
 using sdpmDouble = double;
 #else // USE_CODI
@@ -51,6 +52,7 @@ using sdpmVector3d = Eigen::Matrix<sdpmDouble, 3, 1>;
 using sdpmMatrixXcd = Eigen::Matrix<sdpmComplex, Eigen::Dynamic, Eigen::Dynamic>;
 using sdpmVectorXcd = Eigen::Matrix<sdpmComplex, Eigen::Dynamic, 1>;
 using sdpmVector3cd = Eigen::Matrix<sdpmComplex, 3, 1>;
+#endif // SWIG
 
 namespace sdpm
 {