Index: sasmodels/models/hollow_cylinder.c
===================================================================
--- sasmodels/models/hollow_cylinder.c	(revision aea2e2ab3f11c42b7fc1a72a02b6784076c41d3a)
+++ sasmodels/models/hollow_cylinder.c	(revision aea2e2ab3f11c42b7fc1a72a02b6784076c41d3a)
@@ -0,0 +1,115 @@
+double form_volume(double radius, double thickness, double length);
+
+double Iq(double q, double radius, double thickness, double length, double sld,
+	double solvent_sld);
+double Iqxy(double qx, double qy, double radius, double thickness, double length, double sld,
+	double solvent_sld, double theta, double phi);
+
+//#define INVALID(v) (v.radius_core >= v.radius)
+
+// From Igor library
+static double hollow_cylinder_scaling(
+    double integrand, double delrho, double volume)
+{
+    double answer;
+    // Multiply by contrast^2
+    answer = integrand*delrho*delrho;
+
+    //normalize by cylinder volume
+    answer *= volume*volume;
+
+    //convert to [cm-1]
+    answer *= 1.0e-4;
+
+    return answer;
+}
+
+
+static double _hollow_cylinder_kernel(
+    double q, double radius, double thickness, double length, double dum)
+{
+    const double qs = q*sqrt(1.0-dum*dum);
+    const double lam1 = sas_J1c((radius+thickness)*qs);
+    const double lam2 = sas_J1c(radius*qs);
+    const double gamma_sq = square(radius/(radius+thickness));
+    //Note: lim_{r -> r_c} psi = J0(radius_core*qs)
+    const double psi = (lam1 - gamma_sq*lam2)/(1.0 - gamma_sq);	//SRK 10/19/00
+    const double t2 = sinc(q*length*dum/2.0);
+    return square(psi*t2);
+}
+
+
+static double hollow_cylinder_analytical_2D_scaled(
+    double q, double q_x, double q_y, double radius, double thickness,
+    double length, double sld, double solvent_sld, double theta, double phi)
+{
+    double cyl_x, cyl_y; //, cyl_z
+    //double q_z;
+    double vol, cos_val, delrho;
+    double answer;
+    //convert angle degree to radian
+    theta = theta * M_PI_180;
+    phi = phi * M_PI_180;
+    delrho = solvent_sld - sld;
+
+    // Cylinder orientation
+    cyl_x = cos(theta) * cos(phi);
+    cyl_y = sin(theta);
+    //cyl_z = -cos(theta) * sin(phi);
+
+    // q vector
+    //q_z = 0;
+
+    // Compute the angle btw vector q and the
+    // axis of the cylinder
+    cos_val = cyl_x*q_x + cyl_y*q_y;// + cyl_z*q_z;
+
+    answer = _hollow_cylinder_kernel(q, radius, thickness, length, cos_val);
+
+    vol = form_volume(radius, thickness, length);
+    answer = hollow_cylinder_scaling(answer, delrho, vol);
+
+    return answer;
+}
+
+
+double form_volume(double radius, double thickness, double length)
+{
+    double v_shell = M_PI*length*((radius+thickness)*(radius+thickness)-radius*radius);
+    return(v_shell);
+}
+
+
+double Iq(double q, double radius, double thickness, double length,
+    double sld, double solvent_sld)
+{
+    int i;
+    double lower,upper,zi, inter;		//upper and lower integration limits
+    double summ,answer,delrho;			//running tally of integration
+    double norm,volume;	//final calculation variables
+
+    lower = 0.0;
+    upper = 1.0;		//limits of numerical integral
+
+    summ = 0.0;			//initialize intergral
+    for (i=0;i<76;i++) {
+        zi = ( Gauss76Z[i] * (upper-lower) + lower + upper )/2.0;
+        inter = Gauss76Wt[i] * _hollow_cylinder_kernel(q, radius, thickness, length, zi);
+        summ += inter;
+    }
+
+    norm = summ*(upper-lower)/2.0;
+    volume = form_volume(radius, thickness, length);
+    delrho = solvent_sld - sld;
+    answer = hollow_cylinder_scaling(norm, delrho, volume);
+
+    return(answer);
+}
+
+
+double Iqxy(double qx, double qy, double radius, double thickness,
+    double length, double sld, double solvent_sld, double theta, double phi)
+{
+    const double q = sqrt(qx*qx+qy*qy);
+    return hollow_cylinder_analytical_2D_scaled(q, qx/q, qy/q, radius, thickness, length, sld, solvent_sld, theta, phi);
+}
Index: sasmodels/models/hollow_cylinder.py
===================================================================
--- sasmodels/models/hollow_cylinder.py	(revision aea2e2ab3f11c42b7fc1a72a02b6784076c41d3a)
+++ sasmodels/models/hollow_cylinder.py	(revision aea2e2ab3f11c42b7fc1a72a02b6784076c41d3a)
@@ -0,0 +1,137 @@
+r"""
+This model provides the form factor, $P(q)$, for a monodisperse hollow right
+angle circular cylinder (rigid tube) where the form factor is normalized by the
+volume of the tube (i.e. not by the external volume).
+
+.. math::
+
+    P(q) = \text{scale} \left<F^2\right>/V_\text{shell} + \text{background}
+
+where the averaging $\left<\ldots\right>$ is applied only for the 1D calculation.
+
+The inside and outside of the hollow cylinder are assumed have the same SLD.
+
+Definition
+----------
+
+The 1D scattering intensity is calculated in the following way (Guinier, 1955)
+
+.. math::
+
+    P(q)           &= (\text{scale})V_\text{shell}\Delta\rho^2
+            \int_0^{1}\Psi^2
+            \left[q_z, R_\text{outer}(1-x^2)^{1/2},
+                       R_\text{core}(1-x^2)^{1/2}\right]
+            \left[\frac{\sin(qHx)}{qHx}\right]^2 dx \\
+    \Psi[q,y,z]    &= \frac{1}{1-\gamma^2}
+            \left[ \Lambda(qy) - \gamma^2\Lambda(qz) \right] \\
+    \Lambda(a)     &= 2 J_1(a) / a \\
+    \gamma         &= R_\text{core} / R_\text{outer} \\
+    V_\text{shell} &= \pi \left(R_\text{outer}^2 - R_\text{core}^2 \right)L \\
+    J_1(x)         &= (\sin(x)-x\cdot \cos(x)) / x^2
+
+where *scale* is a scale factor, $H = L/2$ and $J_1$ is the 1st order
+Bessel function.
+
+**NB**: The 2nd virial coefficient of the cylinder is calculated
+based on the outer radius and full length, which give an the effective radius
+for structure factor $S(q)$ when $P(q) \cdot S(q)$ is applied.
+
+In the parameters,the *radius* is $R_\text{core}$ while *thickness* is $R_\text{outer} - R_\text{core}$.
+
+To provide easy access to the orientation of the core-shell cylinder, we define
+the axis of the cylinder using two angles $\theta$ and $\phi$
+(see :ref:`cylinder model <cylinder-angle-definition>`).
+
+References
+----------
+
+L A Feigin and D I Svergun, *Structure Analysis by Small-Angle X-Ray and
+Neutron Scattering*, Plenum Press, New York, (1987)
+
+Authorship and Verification
+----------------------------
+
+* **Author:** NIST IGOR/DANSE **Date:** pre 2010
+* **Last Modified by:** Richard Heenan **Date:** October 06, 2016 
+   (reparametrised to use thickness, not outer radius)
+* **Last Reviewed by:** Richard Heenan **Date:** October 06, 2016
+
+"""
+
+from numpy import pi, inf
+
+name = "hollow_cylinder"
+title = ""
+description = """
+P(q) = scale*<f*f>/Vol + background, where f is the scattering amplitude.
+radius = the radius of core
+thickness = the thickness of shell
+length = the total length of the cylinder
+sld = SLD of the shell
+sld_solvent = SLD of the solvent
+background = incoherent background
+"""
+category = "shape:cylinder"
+# pylint: disable=bad-whitespace, line-too-long
+#   ["name", "units", default, [lower, upper], "type","description"],
+parameters = [
+    ["radius",      "Ang",     20.0, [0, inf],    "volume",      "Cylinder core radius"],
+    ["thickness",   "Ang",     10.0, [0, inf],    "volume",      "Cylinder wall thickness"],
+    ["length",      "Ang",    400.0, [0, inf],    "volume",      "Cylinder total length"],
+    ["sld",         "1/Ang^2",  6.3, [-inf, inf], "sld",         "Cylinder sld"],
+    ["sld_solvent", "1/Ang^2",  1,   [-inf, inf], "sld",         "Solvent sld"],
+    ["theta",       "degrees", 90,   [-360, 360], "orientation", "Theta angle"],
+    ["phi",         "degrees",  0,   [-360, 360], "orientation", "Phi angle"],
+    ]
+# pylint: enable=bad-whitespace, line-too-long
+
+source = ["lib/polevl.c", "lib/sas_J1.c", "lib/gauss76.c", "hollow_cylinder.c"]
+
+# pylint: disable=W0613
+def ER(radius, thickness, length):
+    """
+    :param radius:      Cylinder core radius
+    :param thickness:   Cylinder wall thickness
+    :param length:      Cylinder length
+    :return:            Effective radius
+    """
+    router = radius + thickness
+    if router == 0 or length == 0:
+        return 0.0
+    len1 = router
+    len2 = length/2.0
+    term1 = len1*len1*2.0*len2/2.0
+    term2 = 1.0 + (len2/len1)*(1.0 + 1/len2/2.0)*(1.0 + pi*len1/len2/2.0)
+    ddd = 3.0*term1*term2
+    diam = pow(ddd, (1.0/3.0))
+    return diam
+
+def VR(radius, thickness, length):
+    """
+    :param radius:      Cylinder radius
+    :param thickness:   Cylinder wall thickness
+    :param length:      Cylinder length
+    :return:            Volf ratio for P(q)*S(q)
+    """
+    router = radius + thickness
+    vol_core = pi*radius*radius*length
+    vol_total = pi*router*router*length
+    vol_shell = vol_total - vol_core
+    return vol_shell, vol_total
+
+# parameters for demo
+demo = dict(scale=1.0, background=0.0, length=400.0, radius=20.0,
+            thickness=10, sld=6.3, sld_solvent=1, theta=90, phi=0,
+            thickness_pd=0.2, thickness_pd_n=9,
+            length_pd=.2, length_pd_n=10,
+            radius_pd=.2, radius_pd_n=9,
+            theta_pd=10, theta_pd_n=5,
+           )
+
+# Parameters for unit tests
+tests = [
+    [{}, 0.00005, 1764.926],
+    [{}, 'VR', 1.8],
+    [{}, 0.001, 1756.76]
+    ]
