Index: sasmodels/compare.py
===================================================================
--- sasmodels/compare.py	(revision cf404cbf1344577110785a29f1390cbabc7969b2)
+++ sasmodels/compare.py	(revision 9a66e65e86a25933531cd1a795f3bed854e659a5)
@@ -20,5 +20,5 @@
 from .data import plot_theory, empty_data1D, empty_data2D
 from .direct_model import DirectModel
-from .convert import revert_model
+from .convert import revert_model, constrain_new_to_old
 kerneldll.ALLOW_SINGLE_PRECISION_DLLS = True
 
@@ -81,14 +81,7 @@
 
     for k,v in pars.items():
-        if k.startswith("num_pearls_") or k.startswith("thick_string_"):
-            continue
-        if k.endswith("_pd"):
-            model.dispersion[k[:-3]]['width'] = v
-        elif k.endswith("_pd_n"):
-            model.dispersion[k[:-5]]['npts'] = v
-        elif k.endswith("_pd_nsigma"):
-            model.dispersion[k[:-10]]['nsigmas'] = v
-        elif k.endswith("_pd_type"):
-            model.dispersion[k[:-8]]['type'] = v
+        parts = k.split('.')  # polydispersity components
+        if len(parts) == 2:
+            model.dispersion[parts[0]][parts[1]] = v
         else:
             model.setParam(k, v)
@@ -129,4 +122,7 @@
 
 def constrain_pars(model_definition, pars):
+    """
+    Restrict parameters to valid values.
+    """
     name = model_definition.name
     if name == 'capped_cylinder' and pars['cap_radius'] < pars['radius']:
@@ -141,13 +137,4 @@
         rg_max = np.sqrt(90*np.log(10) + 3*np.log(pars['scale']))/q_max
         pars['rg'] = min(pars['rg'],rg_max)
-
-    # These constraints are only needed for comparison to sasview
-    if name in ('teubner_strey','broad_peak'):
-        del pars['scale']
-    if name in ('guinier',):
-        del pars['background']
-    if getattr(model_definition, 'category', None) == 'structure-factor':
-        del pars['scale'], pars['background']
-
 
 def parlist(pars):
@@ -277,4 +264,5 @@
     pars.update(set_pars)  # set value after random to control value
     constrain_pars(model_definition, pars)
+    constrain_new_to_old(model_definition, pars)
 
     # parameter selection
Index: sasmodels/compare_many.py
===================================================================
--- sasmodels/compare_many.py	(revision 5d316e95135200b4ea93e182879b728131db199b)
+++ sasmodels/compare_many.py	(revision 9a66e65e86a25933531cd1a795f3bed854e659a5)
@@ -9,5 +9,5 @@
 from .compare import (MODELS, randomize_model, suppress_pd, eval_sasview,
                       eval_opencl, eval_ctypes, make_data, get_demo_pars,
-                      columnize, constrain_pars)
+                      columnize, constrain_pars, constrain_new_to_old)
 
 def calc_stats(target, value, index):
@@ -74,4 +74,5 @@
         pars_i, seed = randomize_model(pars)
         constrain_pars(model_definition, pars_i)
+        constrain_new_to_old(model_definition, pars_i)
         if mono: suppress_pd(pars_i)
 
Index: sasmodels/convert.py
===================================================================
--- sasmodels/convert.py	(revision aa4946b68cdcd8686f2c8386cafe8a9e446f0ed2)
+++ sasmodels/convert.py	(revision 9a66e65e86a25933531cd1a795f3bed854e659a5)
@@ -2,24 +2,25 @@
 Convert models to and from sasview.
 """
+import warnings
 
-def _rename_pars(pars, mapping):
+PD_DOT = [
+    ("", ""),
+    ("_pd", ".width"),
+    ("_pd_n", ".npts"),
+    ("_pd_nsigma", ".nsigmas"),
+    ("_pd_type", ".type"),
+    ]
+def _convert_pars(pars, mapping):
     """
     Rename the parameters and any associated polydispersity attributes.
     """
     newpars = pars.copy()
-    for old,new in mapping.items():
+    for new, old in mapping.items():
         if old == new: continue
-        # Bumps style parameter names
-        for variant in ("", "_pd", "_pd_n", "_pd_nsigma", "_pd_type"):
-            if old+variant in newpars:
+        for pd, dot in PD_DOT:
+            if old+dot in newpars:
                 if new is not None:
-                    newpars[new+variant] = pars[old+variant]
-                del newpars[old+variant]
-        # Sasview style parameter names
-        for variant in (".width", ".nsigmas", ".type", ".npts"):
-            if old+variant in newpars:
-                if new is not None:
-                    newpars[new+variant] = pars[old+variant]
-                del newpars[old+variant]
+                    newpars[new+pd] = pars[old+dot]
+                del newpars[old+dot]
     return newpars
 
@@ -51,4 +52,34 @@
                 for p,v in pars.items())
 
+def _remove_pd(pars, key, name):
+    """
+    Remove polydispersity from the parameter list.
+
+    Note: operates in place
+    """
+    # Bumps style parameter names
+    pd = pars.pop(key+".width", 0.0)
+    pd_n = pars.pop(key+".npts", 0)
+    if pd != 0.0 and pd_n != 0:
+        warnings.warn("parameter %s not polydisperse in sasview %s"%(key, name))
+    pars.pop(key+".nsigmas", None)
+    pars.pop(key+".type", None)
+    return pars
+
+def _revert_pars(pars, mapping):
+    """
+    Rename the parameters and any associated polydispersity attributes.
+    """
+    newpars = pars.copy()
+    for new, old in mapping.items():
+        for pd, dot in PD_DOT:
+            if old+pd == new+dot:
+                continue
+            if new+pd in newpars:
+                if old is not None:
+                    newpars[old+dot] = pars[new+pd]
+                del newpars[new+pd]
+    return newpars
+
 def revert_model(model_definition, pars):
     """
@@ -57,5 +88,39 @@
     mapping = model_definition.oldpars
     oldname = model_definition.oldname
-    oldpars = _rename_pars(_unscale_sld(pars), mapping)
+    oldpars = _revert_pars(_unscale_sld(pars), mapping)
+
+    # Note: update compare.constrain_pars to match
+    name = model_definition.name
+    if name in ('teubner_strey', 'broad_peak'):
+        if oldpars.pop('scale', 1.0) != 1.0:
+            warnings.warn("parameter scale not used in sasview %s"%name)
+    elif name in ('guinier',):
+        if oldpars.pop('background', 0.0) != 0.0:
+            warnings.warn("parameter background not used in sasview %s"%name)
+    elif getattr(model_definition, 'category', None) == 'structure-factor':
+        if oldpars.pop('scale', 1.0) != 1.0:
+            warnings.warn("parameter scale not used in sasview %s"%name)
+        if oldpars.pop('background', 0.0) != 0.0:
+            warnings.warn("parameter background not used in sasview %s"%name)
+    elif name == 'pearl_necklace':
+        _remove_pd(oldpars, 'num_pearls', name)
+        _remove_pd(oldpars, 'thick_string', name)
+
     return oldname, oldpars
 
+def constrain_new_to_old(model_definition, pars):
+    """
+    Restrict parameter values to those that will match sasview.
+    """
+    # Note: update convert.revert_model to match
+    name = model_definition.name
+    if name in ('teubner_strey','broad_peak'):
+        pars['scale'] = 1
+    elif name in ('guinier',):
+        pars['background'] = 0
+    elif name == 'pearl_necklace':
+        pars['string_thickness_pd_n'] = 0
+        pars['number_of_pearls_pd_n'] = 0
+    elif getattr(model_definition, 'category', None) == 'structure-factor':
+        pars['scale'], pars['background'] = 1, 0
+
