Index: sasmodels/compare.py
===================================================================
--- sasmodels/compare.py	(revision 7ae2b7f85895f1eddd6ef18f37ff501467a34961)
+++ sasmodels/compare.py	(revision e78edc4f23715c806091d73f1ccdb92ca14b3832)
@@ -57,4 +57,5 @@
     -lowq*/-midq/-highq/-exq use q values up to 0.05, 0.2, 1.0, 10.0
     -nq=128 sets the number of Q points in the data set
+    -zero indicates that q=0 should be included
     -1d*/-2d computes 1d or 2d data
     -preset*/-random[=seed] preset or random parameters
@@ -482,9 +483,11 @@
         index = ~data.mask
     else:
-        if opts['view'] == 'log':
+        if opts['view'] == 'log' and not opts['zero']:
             qmax = math.log10(qmax)
             q = np.logspace(qmax-3, qmax, nq)
         else:
             q = np.linspace(0.001*qmax, qmax, nq)
+        if opts['zero']:
+            q = np.hstack((0, q))
         data = empty_data1D(q, resolution=res)
         index = slice(None, None)
@@ -505,4 +508,13 @@
         return eval_opencl(model_info, data, dtype=dtype, cutoff=cutoff)
 
+def _show_invalid(data, theory):
+    if not theory.mask.any():
+        return
+
+    if hasattr(data, 'x'):
+        bad = zip(data.x[theory.mask], theory[theory.mask])
+        print("   *** ", ", ".join("I(%g)=%g"%(x, y) for x,y in bad))
+
+
 def compare(opts, limits=None):
     """
@@ -525,6 +537,8 @@
         try:
             base_value, base_time = time_calculation(base, pars, Nbase)
+            base_value = np.ma.masked_invalid(base_value)
             print("%s t=%.2f ms, intensity=%.0f"
-                  % (base.engine, base_time, sum(base_value)))
+                  % (base.engine, base_time, base_value.sum()))
+            _show_invalid(data, base_value)
         except ImportError:
             traceback.print_exc()
@@ -536,6 +550,8 @@
         try:
             comp_value, comp_time = time_calculation(comp, pars, Ncomp)
+            comp_value = np.ma.masked_invalid(comp_value)
             print("%s t=%.2f ms, intensity=%.0f"
-                  % (comp.engine, comp_time, sum(comp_value)))
+                  % (comp.engine, comp_time, comp_value.sum()))
+            _show_invalid(data, comp_value)
         except ImportError:
             traceback.print_exc()
@@ -560,9 +576,9 @@
         vmin, vmax = np.Inf, -np.Inf
         if Nbase > 0:
-            vmin = min(vmin, min(base_value))
-            vmax = max(vmax, max(base_value))
+            vmin = min(vmin, base_value.min())
+            vmax = max(vmax, base_value.max())
         if Ncomp > 0:
-            vmin = min(vmin, min(comp_value))
-            vmax = max(vmax, max(comp_value))
+            vmin = min(vmin, comp_value.min())
+            vmax = max(vmax, comp_value.max())
         limits = vmin, vmax
 
@@ -587,5 +603,5 @@
         if view == 'linear':
             plt.xscale('linear')
-        plt.title("max %s = %.3g"%(errstr, max(abs(err))))
+        plt.title("max %s = %.3g"%(errstr, abs(err).max()))
         #cbar_title = errstr if errview=="linear" else "log "+errstr
     #if is2D:
@@ -609,5 +625,5 @@
 
 def _print_stats(label, err):
-    sorted_err = np.sort(abs(err))
+    sorted_err = np.sort(abs(err.compressed()))
     p50 = int((len(err)-1)*0.50)
     p98 = int((len(err)-1)*0.98)
@@ -629,5 +645,5 @@
     'half', 'fast', 'single', 'double',
     'single!', 'double!', 'quad!', 'sasview',
-    'lowq', 'midq', 'highq', 'exq',
+    'lowq', 'midq', 'highq', 'exq', 'zero',
     '2d', '1d',
     'preset', 'random',
@@ -755,4 +771,5 @@
         elif arg == '-midq':    opts['qmax'] = 0.2
         elif arg == '-lowq':    opts['qmax'] = 0.05
+        elif arg == '-zero':    opts['zero'] = True
         elif arg.startswith('-nq='):       opts['nq'] = int(arg[4:])
         elif arg.startswith('-res='):      opts['res'] = float(arg[5:])
Index: sasmodels/data.py
===================================================================
--- sasmodels/data.py	(revision a5b8477c53695e7df03ecec7346f0c1bd770d3f7)
+++ sasmodels/data.py	(revision e78edc4f23715c806091d73f1ccdb92ca14b3832)
@@ -410,5 +410,5 @@
     use_calc = use_theory and Iq_calc is not None
     num_plots = (use_data or use_theory) + use_calc + use_resid
-
+    non_positive_x = (data.x<=0.0).any()
 
     scale = data.x**4 if view == 'q4' else 1.0
@@ -432,4 +432,6 @@
 
         if use_theory:
+            # Note: masks merge, so any masked theory points will stay masked,
+            # and the data mask will be added to it.
             mtheory = masked_array(theory, data.mask.copy())
             mtheory[~np.isfinite(mtheory)] = masked
@@ -443,5 +445,5 @@
             plt.ylim(*limits)
 
-        plt.xscale('linear' if not some_present else view)
+        plt.xscale('linear' if not some_present or non_positive_x  else view)
         plt.yscale('linear'
                    if view == 'q4' or not some_present or not all_positive
@@ -471,5 +473,5 @@
         plt.xlabel("$q$/A$^{-1}$")
         plt.ylabel('residuals')
-        plt.xscale('linear' if not some_present else view)
+        plt.xscale('linear' if not some_present or non_positive_x else view)
 
 
Index: sasmodels/model_test.py
===================================================================
--- sasmodels/model_test.py	(revision 7ae2b7f85895f1eddd6ef18f37ff501467a34961)
+++ sasmodels/model_test.py	(revision e78edc4f23715c806091d73f1ccdb92ca14b3832)
@@ -43,6 +43,4 @@
 Precision defaults to 5 digits (relative).
 """
-#TODO: rename to tests so that tab completion works better for models directory
-
 from __future__ import print_function
 
@@ -197,6 +195,11 @@
             # type: () -> None
             smoke_tests = [
+                # test validity at reasonable values
                 ({}, 0.1, None),
                 ({}, (0.1, 0.1), None),
+                # test validity at q = 0
+                #({}, 0.0, None),
+                #({}, (0.0, 0.0), None),
+                # test that ER/VR will run if they exist
                 ({}, 'ER', None),
                 ({}, 'VR', None),
Index: sasmodels/models/adsorbed_layer.py
===================================================================
--- sasmodels/models/adsorbed_layer.py	(revision 62cf9151309608397d1ac884bc374a8b77e1d0de)
+++ sasmodels/models/adsorbed_layer.py	(revision 7abcc596313e08b6c824ee3bd2debd8197b00f66)
@@ -65,5 +65,5 @@
 
 # pylint: disable=bad-whitespace, line-too-long
-#             ["name", "units", default, [lower, upper], "type", "description"],
+#   ["name", "units", default, [lower, upper], "type", "description"],
 parameters = [
     ["second_moment", "Ang", 23.0, [0.0, inf], "", "Second moment of polymer distribution"],
@@ -75,5 +75,5 @@
     ["sld_solvent", "1e-6/Ang^2", 6.3, [-inf, inf], "sld", "Solvent SLD"],
 ]
-# pylint: disable=bad-whitespace, line-too-long
+# pylint: enable=bad-whitespace, line-too-long
 
 # NB: Scale and Background are implicit parameters on every model
