Index: sansmodels/src/sans/models/BroadPeakModel.py
===================================================================
--- sansmodels/src/sans/models/BroadPeakModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
+++ sansmodels/src/sans/models/BroadPeakModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+""" 
+BroadPeakModel function as a BaseComponent model
+"""
+
+from sans.models.BaseComponent import BaseComponent
+from math import pow, fabs
+
+class BroadPeakModel(BaseComponent):
+    """ 
+    Class that evaluates a BroadPeakModel.
+    I(q) = I(q) = scale_p/pow(qval,exponent)+scale_l/
+    (1.0 + pow((qval*length_l),exponent_l) )+ background
+    """
+        
+    def __init__(self):
+        """ Initialization """
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        
+        ## Name of the model
+        self.name = "BroadPeak"
+        self.description="""I(q) = scale_p/pow(q,exponent)+scale_l/
+        (1.0 + pow((fabs(q-q_peak)*length_l),exponent_l) )+ background
+             List of default parameters:
+             scale_p = Porod term scaling
+             exponent_p = Porod exponent
+             scale_l = Lorentzian term scaling
+             length_l = Lorentzian screening length [A]
+             q_peak = peak location [1/A]
+             exponent_l = Lorentzian exponent
+             background = Incoherent background
+        """
+        ## Define parameters
+        self.params = {}
+        self.params['scale_p']  = 1.0e-05
+        self.params['exponent_p']     = 3.0
+        self.params['scale_l']  = 10.0
+        self.params['length_l']     = 50.0
+        self.params['q_peak']     = 0.1
+        self.params['exponent_l']     = 2.0
+        self.params['background']     = 0.1
+        ## Parameter details [units, min, max]
+        self.details = {}
+        self.details['scale_p'] = ['', None, None]
+        self.details['exponent_p'] =  ['', None, None]
+        self.details['scale_l']  =  ['', None, None]
+        self.details['length_l']  =   ['A', None, None]
+        self.details['q_peak']  =  ['1/A', None, None]
+        self.details['exponent_l']  =   ['', None, None]
+        self.details['background']   =  ['[1/cm]', None, None]
+
+        #list of parameter that cannot be fitted
+        self.fixed= []  
+    def _broadpeak(self, x):
+        """
+        Model definition
+        """
+        inten = self.params['scale_p']/pow(x,self.params['exponent_p'])
+        inten += self.params['scale_l']/(1.0 + \
+                pow((fabs(x-self.params['q_peak'])*self.params['length_l']),self.params['exponent_l']))
+        inten += self.params['background']
+
+        return inten  
+   
+    def run(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        param x: input q-value (float or [float, float] as [r, theta])
+        return: (scattering value)
+        """
+        if x.__class__.__name__ == 'list':
+            return self._broadpeak(x[0])
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._broadpeak(x)
+   
+    def runXY(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        param x: input q-value (float or [float, float] as [qx, qy])
+        return: scattering value
+        """
+        if x.__class__.__name__ == 'list':
+            q = math.sqrt(x[0]**2 + x[1]**2)
+            return self._broadpeak(q)
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._broadpeak(x)
+        
+        
Index: sansmodels/src/sans/models/CorrLengthModel.py
===================================================================
--- sansmodels/src/sans/models/CorrLengthModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
+++ sansmodels/src/sans/models/CorrLengthModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+""" 
+CorrLengthModel function as a BaseComponent model
+"""
+
+from sans.models.BaseComponent import BaseComponent
+from math import pow
+
+class CorrLengthModel(BaseComponent):
+    """ 
+    Class that evaluates a CorrLengthModel.
+    I(q) = I(q) = scale_p/pow(q,exponent)+scale_l/
+    (1.0 + pow((q*length_l),exponent_l) )+ background
+    """
+        
+    def __init__(self):
+        """ Initialization """
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        
+        ## Name of the model
+        self.name = "CorrLength"
+        self.description="""I(q) = scale_p/pow(q,exponent)+scale_l/
+            (1.0 + pow((q*length_l),exponent_l) )+ background
+             List of default parameters:
+             scale_p = Porod term scaling
+             exponent_p = Porod exponent
+             scale_l = Lorentzian term scaling
+             length_l = Lorentzian screening length [A]
+             exponent_l = Lorentzian exponent
+             background = Incoherent background
+        """
+        ## Define parameters
+        self.params = {}
+        self.params['scale_p']  = 1.0e-06
+        self.params['exponent_p']     = 3.0
+        self.params['scale_l']  = 10.0
+        self.params['length_l']     = 50.0
+        self.params['exponent_l']     = 2.0
+        self.params['background']     = 0.1
+        ## Parameter details [units, min, max]
+        self.details = {}
+        self.details['scale_p'] = ['', None, None]
+        self.details['exponent_p'] =  ['', None, None]
+        self.details['scale_l']  =  ['', None, None]
+        self.details['length_l']  =   ['A', None, None]
+        self.details['exponent_l']  =   ['', None, None]
+        self.details['background']   =  ['[1/cm]', None, None]
+
+        #list of parameter that cannot be fitted
+        self.fixed= []  
+    def _corrlength(self, x):
+        """
+        Model definition
+        """
+        inten = self.params['scale_p']/pow(x,self.params['exponent_p'])
+        inten += self.params['scale_l']/(1.0 + \
+                pow((x*self.params['length_l']),self.params['exponent_l']))
+        inten += self.params['background']
+
+        return inten  
+   
+    def run(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        param x: input q-value (float or [float, float] as [r, theta])
+        return: (scattering value)
+        """
+        if x.__class__.__name__ == 'list':
+            return self._corrlength(x[0])
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._corrlength(x)
+   
+    def runXY(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        param x: input q-value (float or [float, float] as [qx, qy])
+        return: scattering value
+        """
+        if x.__class__.__name__ == 'list':
+            q = math.sqrt(x[0]**2 + x[1]**2)
+            return self._corrlength(q)
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._corrlength(x)
Index: sansmodels/src/sans/models/FractalCoreShellModel.py
===================================================================
--- sansmodels/src/sans/models/FractalCoreShellModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
+++ sansmodels/src/sans/models/FractalCoreShellModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -0,0 +1,241 @@
+   
+from sans.models.BaseComponent import BaseComponent
+from sans.models.CoreShellModel import CoreShellModel
+from scipy.special import gammaln
+from math import exp, pow, sin, atan
+from copy import deepcopy
+
+class FractalCoreShellModel(BaseComponent):
+    """
+    Class that evaluates a FractalCoreShellModel
+    List of default parameters:
+    volfraction     = 0.05
+    radius          = 20.0 [A]
+    thickness       = 5.0 [A]
+    frac_dim        = 2.0
+    cor_length      = 100 [A]
+    core_sld        = 3.5e-006 [1/A^(2)]
+    shell_sld       = 1.0e-006 [1/A^(2)]
+    solvent_sld     = 6.35e-006 [1/A^(2)]
+    background      = 0.0 [1/cm]
+    """
+    def __init__(self):
+        BaseComponent.__init__(self)
+
+        ## Setting  model name model description
+        model = CoreShellModel()
+        self.description=model
+        
+        self.model = model
+        self.name = "FractalCoreShell"
+        self.description="""Scattering  from a fractal structure 
+        with a primary building block of a spherical particle 
+        with particle with a core-shell structure.
+        Note: Setting the (core) radius polydispersion with a Schulz 
+        distribution is equivalent to the FractalPolyCore function 
+        in NIST/Igor Package.
+        List of parameters:
+        volfraction: volume fraction of building block spheres
+        radius: radius of building block
+        thickness: shell thickness
+        frac_dim:  fractal dimension
+        cor_length: correlation length of fractal-like aggregates
+        core_sld: SLD of building block
+        shell_sld: SLD of shell
+        solvent_sld: SLD of matrix or solution
+        background: flat background"""
+        
+        ## Define parameters
+        self.params = {}
+
+        ## Parameter details [units, min, max]
+        self.details = {}
+        
+        # non-fittable parameters
+        self.non_fittable = model.non_fittable
+        
+        ## dispersion
+        self._set_dispersion()
+        ## Define parameters
+        self._set_params()
+        
+        ## Parameter details [units, min, max]
+        self._set_details()
+
+        ## parameters with orientation: can be removed since there is no orientational params
+        for item in self.model.orientation_params:
+            self.orientation_params.append(item)
+                
+    def _fractalcore(self,x):
+        """
+        Define model function
+        
+        return S(q): Fractal Structure 
+        """
+        # set local variables
+        Df = self.params['frac_dim']
+        corr = self.params['cor_length']
+        r0 = self.params['radius']
+        #calculate S(q)
+        sq = Df*exp(gammaln(Df-1.0))*sin((Df-1.0)*atan(x*corr))
+        sq /= pow((x*r0),Df) * pow((1.0 + 1.0/(x*corr*x*corr)),((Df-1)/2))
+        sq += 1.0
+        return sq
+
+    def _clone(self, obj):
+        """
+        Internal utility function to copy the internal
+        data members to a fresh copy.
+        """
+        obj.params     = deepcopy(self.params)
+        obj.description     = deepcopy(self.description)
+        obj.details    = deepcopy(self.details)
+        obj.dispersion = deepcopy(self.dispersion)
+        obj.model  = self.model.clone()
+
+        return obj 
+    
+    def _set_dispersion(self):
+        """
+        model dispersions
+        """ 
+        ##set dispersion from model 
+        for name , value in self.model.dispersion.iteritems():      
+            self.dispersion[name]= value
+                              
+    def _set_params(self):
+        """
+        Concatenate the parameters of the model to create
+        this model parameters 
+        """
+        # rearrange the parameters for the given # of shells
+        for name , value in self.model.params.iteritems():
+            if name == 'scale':
+                value = 0.05   
+            elif name == 'radius':
+                value = 20.0
+            elif name == 'thickness':
+                value = 5.0
+            elif name == 'core_sld':
+                value = 3.5e-06
+            elif name == 'shell_sld':
+                value = 1.0e-06
+            elif name == 'solvent_sld':
+                value = 6.35e-06
+            elif name == 'background':
+                value = 0.0
+            self.model.params[name]= value
+            if name  == 'scale':
+                name = 'volfraction'
+            self.params[name]= value
+        self.params['frac_dim'] = 2.0
+        self.params['cor_length'] = 100.0  
+  
+    def _set_details(self):
+        """
+        Concatenate details of the original model to create
+        this model details 
+        """
+        for name ,detail in self.model.details.iteritems():
+            if name in self.params.iterkeys():
+                if name == 'scale':
+                    name = 'volfraction'
+                self.details[name]= detail
+        self.details['frac_dim']   = ['', None, None]
+        self.details['cor_length'] = ['[A]', None, None]  
+
+
+    def setParam(self, name, value):
+        """ 
+        Set the value of a model parameter
+    
+        : param name: name of the parameter
+        : param value: value of the parameter
+        """
+        # set param to new model
+        self._setParamHelper(name, value)
+
+        if name == 'volfraction':
+            name = 'scale'
+        # model.setParam except the two names below
+        if name != 'frac_dim' and name != 'cor_length':
+            # background is always 0.0 in the coreshellmodel
+            if name == 'background':
+                value = 0.0
+            self.model.setParam(name, value)
+
+    def _setParamHelper(self, name, value):
+        """
+        Helper function to setParam
+        """
+        #look for dispersion parameters
+        toks = name.split('.')
+        if len(toks)==2:
+            for item in self.dispersion.keys():
+                if item.lower()==toks[0].lower():
+                    for par in self.dispersion[item]:
+                        if par.lower() == toks[1].lower():
+                            self.dispersion[item][par] = value
+                            return
+        # Look for standard parameter
+        for item in self.params.keys():
+            if item.lower()==name.lower():
+                self.params[item] = value
+                return
+        
+        raise ValueError, "Model does not contain parameter %s" % name
+             
+     
+                
+    def run(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        : param x: input q-value (float or [float, float] as [r, theta])
+        : return: (DAB value)
+        """
+        if x.__class__.__name__ == 'list':
+            # Take absolute value of Q, since this model is really meant to
+            # be defined in 1D for a given length of Q
+            #qx = math.fabs(x[0]*math.cos(x[1]))
+            #qy = math.fabs(x[0]*math.sin(x[1]))
+            return self.params['background']+self._fractalcore(x[0])*self.model.run(x)
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self.params['background']+self._fractalcore(x)*self.model.run(x)
+
+
+        return self.params['background']+self._fractalcore(x)*self.model.run(x)
+
+    def runXY(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        : param x: input q-value (float or [float, float] as [qx, qy])
+        : return: DAB value
+        """  
+        if x.__class__.__name__ == 'list':
+            q = math.sqrt(x[0]**2 + x[1]**2)
+            return self.params['background']+self._fractalcore(q)*self.model.runXY(x)
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self.params['background']+self._fractalcore(x)*self.model.runXY(x)
+
+
+    def set_dispersion(self, parameter, dispersion):
+        """
+        Set the dispersion object for a model parameter
+        
+        : param parameter: name of the parameter [string]
+        :dispersion: dispersion object of type DispersionModel
+        """
+        value= None
+        try:
+            if parameter in self.model.dispersion.keys():
+                value= self.model.set_dispersion(parameter, dispersion)
+            self._set_dispersion()
+            return value
+        except:
+            raise 
Index: sansmodels/src/sans/models/GaussLorentzGelModel.py
===================================================================
--- sansmodels/src/sans/models/GaussLorentzGelModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
+++ sansmodels/src/sans/models/GaussLorentzGelModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -0,0 +1,91 @@
+#!/usr/bin/env python
+""" 
+Provide I(q) = I_0 exp ( - R_g^2 q^2 / 3.0)
+GaussLorentzGel function as a BaseComponent model
+"""
+
+from sans.models.BaseComponent import BaseComponent
+from math import exp
+
+class GaussLorentzGelModel(BaseComponent):
+    """ 
+    Class that evaluates a GaussLorentzGel model.
+
+    I(q) = scale_g*exp(- q^2*Z^2 / 2)+scale_l/(1+q^2*z^2)
+            + background
+    List of default parameters:
+     scale_g = Gauss scale factor
+     Z = Static correlation length
+     scale_l = Lorentzian scale factor
+     z = Dynamic correlation length
+     background = Incoherent background
+    """
+        
+    def __init__(self):
+        """ Initialization """
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        
+        ## Name of the model
+        self.name = "GaussLorentzGel"
+        self.description="""I(q)=scale_g*exp(-q^2*Z^2/2)+scale_l/(1+q^2*z^2)
+            + background
+            List of default parameters:
+             scale_g = Gauss scale factor
+             stat_colength = Static correlation length
+             scale_l = Lorentzian scale factor
+             dyn_colength = Dynamic correlation length
+             background = Incoherent background
+"""
+        ## Define parameters
+        self.params = {}
+        self.params['scale_g']  = 100.0
+        self.params['stat_colength']     = 100.0
+        self.params['scale_l']  = 50.0
+        self.params['dyn_colength']     = 20.0
+        self.params['background']     = 0.0
+        ## Parameter details [units, min, max]
+        self.details = {}
+        self.details['scale_g'] = ['', None, None]
+        self.details['stat_colength'] =  ['A', None, None]
+        self.details['scale_l']  =  ['', None, None]
+        self.details['dyn_colength']  =   ['A', None, None]
+        self.details['background']   =  ['[1/cm]', None, None]
+
+        #list of parameter that cannot be fitted
+        self.fixed= []  
+    def _gausslorentzgel(self, x):
+        """
+        Model definition
+        """
+        inten = self.params['scale_g']*exp(-1.0*x*x*self.params['stat_colength']* \
+                self.params['stat_colength']/2.0) + self.params['scale_l']/ \
+                (1.0 + (x*self.params['dyn_colength'])* \
+                 (x*self.params['dyn_colength'])) + self.params['background']
+        return inten  
+   
+    def run(self, x = 0.0):
+        """ Evaluate the model
+            @param x: input q-value (float or [float, float] as [r, theta])
+            @return: (guinier value)
+        """
+        if x.__class__.__name__ == 'list':
+            return self._gausslorentzgel(x[0])
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._gausslorentzgel(x)
+   
+    def runXY(self, x = 0.0):
+        """ Evaluate the model
+            @param x: input q-value (float or [float, float] as [qx, qy])
+            @return: guinier value
+        """
+        if x.__class__.__name__ == 'list':
+            q = math.sqrt(x[0]**2 + x[1]**2)
+            return self._gausslorentzgel(q)
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._gausslorentzgel(x)
Index: sansmodels/src/sans/models/GuinierPorodModel.py
===================================================================
--- sansmodels/src/sans/models/GuinierPorodModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
+++ sansmodels/src/sans/models/GuinierPorodModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -0,0 +1,100 @@
+#!/usr/bin/env python
+""" 
+I(q) = scale/q^s* exp ( - R_g^2 q^2 / (3-s) ) for q<= ql
+    = scale/q^m*exp((-ql^2*Rg^2)/(3-s))*ql^(m-s) for q>=ql
+Guinier function as a BaseComponent model
+"""
+
+from sans.models.BaseComponent import BaseComponent
+from math import sqrt,exp
+
+class GuinierPorodModel(BaseComponent):
+    """ 
+    Class that evaluates a GuinierPorod model.
+
+    I(q) = scale/q^s* exp ( - R_g^2 q^2 / (3-s) ) for q<= ql
+        = scale/q^m*exp((-ql^2*Rg^2)/(3-s))*ql^(m-s) for q>=ql
+    """
+    def __init__(self):
+        """ Initialization """
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        
+        ## Name of the model
+        self.name = "GuinierPorod"
+        self.description=""" I(q) = scale/q^s* exp ( - R_g^2 q^2 / (3-s) ) for q<= ql
+         = scale/q^m*exp((-ql^2*Rg^2)/(3-s))*ql^(m-s) for q>=ql
+                        where ql = sqrt((m-s)(3-s)/2)/Rg.
+                        List of parameters:
+                        scale = Guinier Scale
+                        s = Dimension Variable
+                        Rg = Radius of Gyration [A] 
+                        m = Porod Exponent
+                        background  = Background [1/cm]"""
+        ## Define parameters
+        self.params = {}
+        self.params['scale']  = 1.0
+        self.params['dim']  = 1.0
+        self.params['rg']     = 100.0
+        self.params['m']     = 3.0
+        self.params['background']     = 0.1
+        ## Parameter details [units, min, max]
+        self.details = {}
+        self.details['scale'] = ['', None, None]
+        self.details['dim']  = ['', None, None]
+        self.details['rg']    = ['[A]', None, None]
+        self.details['m']     = ['', None, None]
+        self.details['background']     = ['[1/cm]', None, None]
+
+        #list of parameter that cannot be fitted
+        self.fixed= []  
+        
+    def _guinier_porod(self, x):
+        """
+        Guinier-Porod Model
+        """
+        # parameters
+        G = self.params['scale']
+        s = self.params['dim']
+        Rg = self.params['rg']
+        m = self.params['m']
+        bgd = self.params['background']
+        n = 3.0 - s
+        qval = x
+        
+        #do the calculation and return the function value
+        q1=sqrt((n-3.0+m)*n/2.0)/Rg
+        if qval < q1:
+            F = (G/pow(qval,(3.0-n)))*exp((-qval*qval*Rg*Rg)/n) 
+        else:
+            F = (G/pow(qval,m))*exp(-(n-3.0+m)/2.0)*pow(((n-3.0+m)*n/2.0),
+                                        ((n-3.0+m)/2.0))/pow(Rg,(n-3.0+m))
+        inten = F + bgd
+    
+        return inten
+   
+    def run(self, x = 0.0):
+        """ Evaluate the model
+            @param x: input q-value (float or [float, float] as [r, theta])
+            @return: (guinier value)
+        """
+        if x.__class__.__name__ == 'list':
+            return self._guinier_porod(x[0])
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._guinier_porod(x)
+   
+    def runXY(self, x = 0.0):
+        """ Evaluate the model
+            @param x: input q-value (float or [float, float] as [qx, qy])
+            @return: guinier value
+        """
+        if x.__class__.__name__ == 'list':
+            q = sqrt(x[0]**2 + x[1]**2)
+            return self._guinier_porod(q)
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._guinier_porod(x)
Index: sansmodels/src/sans/models/ReflectivityModel.py
===================================================================
--- sansmodels/src/sans/models/ReflectivityModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
+++ sansmodels/src/sans/models/ReflectivityModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -0,0 +1,367 @@
+   
+from sans.models.BaseComponent import BaseComponent
+from sans.models.ReflModel import ReflModel
+from copy import deepcopy
+from math import floor
+from scipy.special import erf
+func_list = {'Erf':0, 'Linear':1, 'RParabolic':2, \
+                     'LParabola':3, 'RCubic':4, 'LCubic':5}
+max_nshells = 10
+class ReflectivityModel(BaseComponent):
+    """
+    This multi-model is based on Parratt formalism and provides the capability
+    of changing the number of layers between 0 and 10.
+    """
+    def __init__(self, multfactor=1):
+        BaseComponent.__init__(self)
+        """
+        :param multfactor: number of layers in the model, assumes 0<= n_shells <=10.
+        """
+
+        ## Setting  model name model description
+        self.description=""
+        model = ReflModel()
+        self.model = model
+        self.name = "ReflectivityModel"
+        self.description=model.description
+        self.n_layers = multfactor
+        ## Define parameters
+        self.params = {}
+
+        ## Parameter details [units, min, max]
+        self.details = {}
+        
+        # non-fittable parameters
+        self.non_fittable = model.non_fittable
+        
+        # list of function in order of the function number 
+        self.fun_list = self._get_func_list()
+        ## dispersion
+        self._set_dispersion()
+        ## Define parameters
+        self._set_params()
+        
+        ## Parameter details [units, min, max]
+        self._set_details()
+        
+        #list of parameter that can be fitted
+        self._set_fixed_params()  
+        self.model.params['n_layers'] = self.n_layers
+        
+        ## functional multiplicity info of the model
+        # [int(maximum no. of functionality),"str(Titl),
+        # [str(name of function0),...], [str(x-asix name of sld),...]]
+        self.multiplicity_info = [max_nshells,"No. of Layers:",[],['Depth']]
+
+    
+    def _clone(self, obj):
+        """
+        Internal utility function to copy the internal
+        data members to a fresh copy.
+        """
+        obj.params     = deepcopy(self.params)
+        obj.non_fittable     = deepcopy(self.non_fittable)
+        obj.description     = deepcopy(self.description)
+        obj.details    = deepcopy(self.details)
+        obj.dispersion = deepcopy(self.dispersion)
+        obj.model  = self.model.clone()
+
+        return obj
+    
+    
+    def _set_dispersion(self):
+        """
+        model dispersions
+        """ 
+        ##set dispersion from model 
+        self.dispersion = {}
+                    
+
+    def _set_params(self):
+        """
+        Concatenate the parameters of the model to create
+        this model parameters 
+        """
+        # rearrange the parameters for the given # of shells
+        for name , value in self.model.params.iteritems():
+            n = 0
+            pos = len(name.split('_'))-1
+            if name.split('_')[0] == 'sldIM':
+                continue
+            elif name.split('_')[0] == 'func':
+                n= -1
+                while n<self.n_layers:
+                    n += 1
+                    if name.split('_')[pos] == 'inter%s' % str(n):
+                        self.params[name]=value
+                        continue
+                #continue
+            elif name.split('_')[pos][0:5] == 'inter':
+                n= -1
+                while n<self.n_layers:
+                    n += 1
+                    if name.split('_')[pos] == 'inter%s' % str(n):
+                        self.params[name]= value
+                        continue
+            elif name.split('_')[pos][0:4] == 'flat':
+                while n<self.n_layers:
+                    n += 1
+                    if name.split('_')[pos] == 'flat%s' % str(n):
+                        self.params[name]= value
+                        continue
+            elif name == 'n_layers':
+                continue
+            else:
+                self.params[name]= value
+               
+        self.model.params['n_layers'] = self.n_layers    
+
+        # set constrained values for the original model params
+        self._set_xtra_model_param()       
+
+    def _set_details(self):
+        """
+        Concatenate details of the original model to create
+        this model details 
+        """
+        for name ,detail in self.model.details.iteritems():
+            if name in self.params.iterkeys():
+                self.details[name]= detail
+            
+    
+    def _set_xtra_model_param(self):
+        """
+        Set params of original model that are hidden from this model
+        """
+        # look for the model parameters that are not in param list
+        for key in self.model.params.iterkeys():
+            if key not in self.params.keys():
+                if  key.split('_')[0] == 'thick':
+                    self.model.setParam(key, 0)
+                    continue
+                if  key.split('_')[0] == 'func':
+                    self.model.setParam(key, 0)
+                    continue
+                for nshell in range(self.n_layers,max_nshells):
+                    if key.split('_')[1] == 'flat%s' % str(nshell+1):
+                        try:
+                            if key.split('_')[0] == 'sld':
+                                value = self.model.params['sld_medium']
+                            elif key.split('_')[0] == 'sldIM':
+                                value = self.model.params['sldIM_medium']
+                            self.model.setParam(key, value)
+                        except: pass
+    
+    def _get_func_list(self):
+        """
+        Get the list of functions in each layer (shell) 
+        """
+        #func_list = {}
+        return func_list
+        
+    def getProfile(self):
+        """
+        Get SLD profile 
+        
+        : return: (z, beta) where z is a list of depth of the transition points
+                beta is a list of the corresponding SLD values 
+        """
+        # max_pts for each layers
+        n_sub = 21
+        z = []
+        beta = []
+        sub_range = floor(n_sub/2.0)
+        z.append(0)
+        beta.append(self.params['sld_sub0']) 
+       
+        z0 = 0
+        # for layers from the top
+        for n in range(1,self.n_layers+2):
+            i = n
+
+            for j in range(0,2):
+                for n_s in range(-sub_range,sub_range+1):
+                    if j==1:
+                        if i==self.n_layers+1:
+                            break
+                        # shift half sub thickness for the first point
+                        z0 += dz/2.0
+                        z.append(z0)
+                        #z0 -= dz/2.0
+                        z0 += self.params['thick_flat%s'% str(i)]
+                        
+                        sld_i = self.params['sld_flat%s'% str(i)]
+                        beta.append(self.params['sld_flat%s'% str(i)])
+                    else:
+                        
+                        dz = self.params['thick_inter%s'% str(i-1)]/n_sub
+                        
+                        if n_s == -sub_range:
+                            # shift half sub thickness for the first point
+                            z0 -= dz/2.0
+                        #exec "dz = self.params['thick_inter[%s-1]'% str(i)]/9"
+                        #print "%d = %g \n"% (i,self.params['thick_inter3'])
+                        z0 += dz
+
+                        if i == 1:
+                            sld_l = self.params['sld_sub0']
+                        else:
+                            sld_l = self.params['sld_flat%s'% str(i-1)]
+                        if i == self.n_layers+1:
+                            sld_r = self.params['sld_medium']
+                        else:
+                            sld_r = self.params['sld_flat%s'% str(i)]
+                        func_idx = self.params['func_inter%s'% str(i-1)]
+                        func = self._get_func(n_s, n_sub, func_idx)
+                        if sld_r>sld_l:
+                            sld_i = (sld_r-sld_l)*func+sld_l
+                        elif sld_r<sld_l:
+                            sld_i = (sld_l-sld_r)*(1-func)+sld_r
+                        else:
+                             sld_i = sld_r
+                    z.append(z0)
+                    beta.append(sld_i)
+                    if j==1: break
+        # put substrate and superstrate profile
+        # shift half sub thickness for the first point
+        z0 += dz/2.0
+        z.append(z0)
+        beta.append(self.params['sld_medium'])  
+        z_ext = z0/6.0
+        
+        # put the extra points for the substrate 
+        # and superstrate
+        z.append(z0+z_ext)
+        beta.append(self.params['sld_medium']) 
+        z.insert(0,-z_ext)
+        beta.insert(0,self.params['sld_sub0']) 
+        z = [z0 - x for x in z]
+        z.reverse()
+        beta.reverse()  
+        return z, beta
+    
+    def _get_func(self, index, n_sub, func_idx):
+        """
+        Get the function asked to buil sld profile
+        : param index: index of sub_layer
+        : param n_sub: total number of sub_layer
+        : param func_idx: an integer to identify a function
+        
+        : return out: the output from the function, float
+        """
+        # cal bin_size
+        bin_size = 1.0/n_sub
+        # erf
+        if func_idx == 0:
+            out = erf(index/(n_sub/5.0))/2.0 + 0.5
+            return out
+        else:
+            index += 0.5
+        # linear
+        if func_idx == 1:
+            out = ((index + floor(n_sub/2.0))*bin_size)
+        # r_parabolic
+        elif func_idx == 2:
+            out = ((index + floor(n_sub/2.0))*bin_size)* \
+                    ((index + floor(n_sub/2.0))*bin_size)
+        # l_parabolic
+        elif func_idx == 3:
+            out = 1.0-(((index + floor(n_sub/2.0))*bin_size) - 1.0) *\
+                    (((index + floor(n_sub/2.0))*bin_size) - 1.0)
+        # r_cubic
+        elif func_idx == 4:
+            out = ((index + floor(n_sub/2.0))*bin_size)* \
+                    ((index + floor(n_sub/2.0))*bin_size)* \
+                    ((index + floor(n_sub/2.0))*bin_size)
+        # l_cubic
+        elif func_idx == 5:
+            out = 1.0+(((index + floor(n_sub/2.0)))*bin_size - 1.0) *\
+                    (((index + floor(n_sub/2.0)))*bin_size - 1.0) *\
+                    (((index + floor(n_sub/2.0)))*bin_size - 1.0)
+        # return output
+        return out
+    
+    def setParam(self, name, value):
+        """ 
+        Set the value of a model parameter
+    
+        : param name: name of the parameter
+        : param value: value of the parameter
+        """
+        # set param to new model
+        self._setParamHelper( name, value)
+        
+        ## setParam to model 
+        if name=='sld_medium':
+            # the sld_*** model.params not in params must set to value of sld_solv
+            for key in self.model.params.iterkeys():
+                if key not in self.params.keys()and key.split('_')[0] == 'sld':
+                        self.model.setParam(key, value)
+            
+        self.model.setParam( name, value)
+
+    def _setParamHelper(self, name, value):
+        """
+        Helper function to setParam
+        """
+
+        # Look for standard parameter
+        for item in self.params.keys():
+            if item.lower()==name.lower():
+                self.params[item] = value
+                return
+        
+        raise ValueError, "Model does not contain parameter %s" % name
+             
+   
+    def _set_fixed_params(self):
+        """
+        Fill the self.fixed list with the model fixed list
+        """
+        pass         
+
+    def run(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        :param x: input q, or [q,phi]
+        
+        :return: scattering function P(q)
+        
+        """
+
+        return self.model.run(x)
+
+    def runXY(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        : param x: input q-value (float or [float, float] as [qx, qy])
+        : return: scattering function value
+        """  
+
+        return self.model.runXY(x)
+    
+    ## Now (May27,10) directly uses the model eval function 
+    ## instead of the for-loop in Base Component.
+    def evalDistribution(self, x = []):
+        """ 
+        Evaluate the model in cartesian coordinates
+        
+        : param x: input q[], or [qx[], qy[]]
+        : return: scattering function P(q[])
+        """
+        # set effective radius and scaling factor before run
+        return self.model.evalDistribution(x)
+    def calculate_ER(self):
+        """
+        """
+        return self.model.calculate_ER()
+    def set_dispersion(self, parameter, dispersion):
+        """
+        Set the dispersion object for a model parameter
+        
+        : param parameter: name of the parameter [string]
+        :dispersion: dispersion object of type DispersionModel
+        """
+        pass
Index: sansmodels/src/sans/models/TwoLorentzianModel.py
===================================================================
--- sansmodels/src/sans/models/TwoLorentzianModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
+++ sansmodels/src/sans/models/TwoLorentzianModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+""" 
+TwoLorentzianModel function as a BaseComponent model
+"""
+
+from sans.models.BaseComponent import BaseComponent
+from math import pow
+
+class TwoLorentzianModel(BaseComponent):
+    """ 
+    Class that evaluates a TwoLorentzianModel.
+    I(q) = II(q) = scale_1/(1.0 + pow((q*length_1),exponent_1))
+    + scale_2/(1.0 + pow((q*length_2),exponent_2) )+ background
+    """
+        
+    def __init__(self):
+        """ Initialization """
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        
+        ## Name of the model
+        self.name = "TwoLorentzian"
+        self.description="""I(q) = scale_1/(1.0 + pow((q*length_1),exponent_1))
+             + scale_2/(1.0 + pow((q*length_2),exponent_2) )+ background
+             List of default parameters:
+             scale_1 = Lorentzian term scaling #1
+             length_1 = Lorentzian screening length #1 [A]
+             exponent_1 = Lorentzian exponent #1
+             scale_2 = Lorentzian term scaling #2
+             length_2 = Lorentzian screening length #2 [A]
+             exponent_2 = Lorentzian exponent #2
+             background = Incoherent background
+        """
+        ## Define parameters
+        self.params = {}
+        self.params['scale_1']  = 10.0
+        self.params['length_1']     = 100.0
+        self.params['exponent_1']     = 3.0
+        self.params['scale_2']  = 1.0
+        self.params['length_2']     = 10.0
+        self.params['exponent_2']     = 2.0
+        self.params['background']     = 0.1
+        ## Parameter details [units, min, max]
+        self.details = {}
+        self.details['scale_1'] = ['', None, None]
+        self.details['length_1'] = ['A', None, None]
+        self.details['exponent_1'] =  ['', None, None]
+        self.details['scale_2']  =  ['', None, None]
+        self.details['length_2']  =   ['A', None, None]
+        self.details['exponent_2']  =   ['', None, None]
+        self.details['background']   =  ['[1/cm]', None, None]
+
+        #list of parameter that cannot be fitted
+        self.fixed= []  
+    def _twolorentzian(self, x):
+        """
+        Model definition
+        """
+        inten = self.params['scale_1']/(1.0 + \
+                pow((x*self.params['length_1']),self.params['exponent_1']))
+        inten += self.params['scale_2']/(1.0 + \
+                pow((x*self.params['length_2']),self.params['exponent_2']))
+        inten += self.params['background']
+
+        return inten  
+   
+    def run(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        param x: input q-value (float or [float, float] as [r, theta])
+        return: (scattering value)
+        """
+        if x.__class__.__name__ == 'list':
+            return self._twolorentzian(x[0])
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._twolorentzian(x)
+   
+    def runXY(self, x = 0.0):
+        """ 
+        Evaluate the model
+        
+        param x: input q-value (float or [float, float] as [qx, qy])
+        return: scattering value
+        """
+        if x.__class__.__name__ == 'list':
+            q = math.sqrt(x[0]**2 + x[1]**2)
+            return self._twolorentzian(q)
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._twolorentzian(x)
Index: sansmodels/src/sans/models/TwoPowerLawModel.py
===================================================================
--- sansmodels/src/sans/models/TwoPowerLawModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
+++ sansmodels/src/sans/models/TwoPowerLawModel.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -0,0 +1,99 @@
+#!/usr/bin/env python
+""" 
+Provide I(q) = A*pow(qval,-1.0*m1) for q<=qc
+    =scale*pow(qval,-1.0*m2) for q>qc
+TwoPowerLaw function as a BaseComponent model
+"""
+
+from sans.models.BaseComponent import BaseComponent
+from math import pow
+
+class TwoPowerLawModel(BaseComponent):
+    """ 
+    Class that evaluates a TwoPowerLawModel.
+
+    I(q) = coef_A*pow(qval,-1.0*power1) for q<=qc
+        =C*pow(qval,-1.0*power2) for q>qc
+    where C=coef_A*pow(qc,-1.0*power1)/pow(qc,-1.0*power2).
+    List of default parameters:
+     coef_A = coefficient
+     power1 = (-) Power @ low Q
+     power2 = (-) Power @ high Q
+     qc = crossover Q-value
+     background = incoherent background
+    """
+        
+    def __init__(self):
+        """ Initialization """
+        
+        # Initialize BaseComponent first, then sphere
+        BaseComponent.__init__(self)
+        
+        ## Name of the model
+        self.name = "TwoPowerLaw"
+        self.description="""I(q) = coef_A*pow(qval,-1.0*power1) for q<=qc
+            =C*pow(qval,-1.0*power2) for q>qc
+            where C=coef_A*pow(qc,-1.0*power1)/pow(qc,-1.0*power2).
+             List of default parameters:
+             coef_A = coefficient
+             power1 = (-) Power @ low Q
+             power2 = (-) Power @ high Q
+             qc = crossover Q-value
+             background = incoherent background
+        """
+        ## Define parameters
+        self.params = {}
+        self.params['coef_A']  = 1.0
+        self.params['power1']     = 1.0
+        self.params['power2']  = 4.0
+        self.params['qc']     = 0.04
+        self.params['background']     = 0.0
+        ## Parameter details [units, min, max]
+        self.details = {}
+        self.details['coef_A'] = ['', None, None]
+        self.details['power1'] =  ['', None, None]
+        self.details['power2']  =  ['', None, None]
+        self.details['qc']  =   ['1/A', None, None]
+        self.details['background']   =  ['[1/cm]', None, None]
+
+        #list of parameter that cannot be fitted
+        self.fixed= []  
+    def _twopowerlaw(self, x):
+        """
+        Model definition
+        """
+        qc= self.params['qc']
+        if(x<=qc):
+            inten = self.params['coef_A']*pow(x,-1.0*self.params['power1'])
+        else:
+            scale = self.params['coef_A']*pow(qc,-1.0*self.params['power1']) \
+                                    / pow(qc,-1.0*self.params['power2'])
+            inten = scale*pow(x,-1.0*self.params['power2'])
+        inten += self.params['background']
+
+        return inten  
+   
+    def run(self, x = 0.0):
+        """ Evaluate the model
+            @param x: input q-value (float or [float, float] as [r, theta])
+            @return: (guinier value)
+        """
+        if x.__class__.__name__ == 'list':
+            return self._twopowerlaw(x[0])
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._twopowerlaw(x)
+   
+    def runXY(self, x = 0.0):
+        """ Evaluate the model
+            @param x: input q-value (float or [float, float] as [qx, qy])
+            @return: guinier value
+        """
+        if x.__class__.__name__ == 'list':
+            q = math.sqrt(x[0]**2 + x[1]**2)
+            return self._twopowerlaw(q)
+        elif x.__class__.__name__ == 'tuple':
+            raise ValueError, "Tuples are not allowed as input to BaseComponent models"
+        else:
+            return self._twopowerlaw(x)
Index: sansmodels/src/sans/models/c_extensions/bcc.c
===================================================================
--- sansmodels/src/sans/models/c_extensions/bcc.c	(revision d5b6a9d7cd9e26b5f9e28e55e8cf848a40de6ae9)
+++ sansmodels/src/sans/models/c_extensions/bcc.c	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -91,6 +91,6 @@
     b1_y = cos(pars->psi);
     // b2 axis orientation
-    b2_x = sqrt(1-sin(pars->theta)*cos(pars->phi))*cos(pars->psi);
-    b2_y = sqrt(1-sin(pars->theta)*cos(pars->phi))*sin(pars->psi);
+    b2_x = sqrt(1.0-sin(pars->theta)*cos(pars->phi))*cos(pars->psi);
+    b2_y = sqrt(1.0-sin(pars->theta)*cos(pars->phi))*sin(pars->psi);
 
     // a3 axis orientation
Index: sansmodels/src/sans/models/c_extensions/ellipsoid.c
===================================================================
--- sansmodels/src/sans/models/c_extensions/ellipsoid.c	(revision f10063e8f3c53d2be93abaea9c0d3d4f3061d444)
+++ sansmodels/src/sans/models/c_extensions/ellipsoid.c	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -32,5 +32,5 @@
 
 	// Spherical scattering ampliture, with modified length for ellipsoid
-	sph_func = 3*( sin(q*length) - q*length*cos(q*length) ) / (q*q*q*length*length*length);
+	sph_func = 3.0*( sin(q*length) - q*length*cos(q*length) ) / (q*q*q*length*length*length);
 
 	return sph_func*sph_func;
@@ -99,5 +99,5 @@
 
     // q vector
-    q_z = 0;
+    q_z = 0.0;
 
     // Compute the angle btw vector q and the
Index: sansmodels/src/sans/models/c_extensions/fcc.c
===================================================================
--- sansmodels/src/sans/models/c_extensions/fcc.c	(revision 339ce675656e3ab89eff7b84d8292a2e0ffe6109)
+++ sansmodels/src/sans/models/c_extensions/fcc.c	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -91,6 +91,6 @@
     b1_y = cos(pars->psi);
     // b2 axis orientation
-    b2_x = sqrt(1-sin(pars->theta)*cos(pars->phi))*cos(pars->psi);
-    b2_y = sqrt(1-sin(pars->theta)*cos(pars->phi))*sin(pars->psi);
+    b2_x = sqrt(1.0-sin(pars->theta)*cos(pars->phi))*cos(pars->psi);
+    b2_y = sqrt(1.0-sin(pars->theta)*cos(pars->phi))*sin(pars->psi);
 
     // a3 axis orientation
@@ -109,5 +109,5 @@
 
     // Compute the angle btw vector q and the a3 axis
-    cos_val_a3 = a3_x*q_x + a3_y*q_y + a3_z*q_z;
+    cos_val_a3 = a3_x*q_x + a3_y*q_y;// + a3_z*q_z;
     a3_dot_q = aa*q*cos_val_a3;
 
Index: sansmodels/src/sans/models/c_extensions/sc.c
===================================================================
--- sansmodels/src/sans/models/c_extensions/sc.c	(revision d5b6a9d7cd9e26b5f9e28e55e8cf848a40de6ae9)
+++ sansmodels/src/sans/models/c_extensions/sc.c	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -99,8 +99,8 @@
 
     // a2 axis orientation
-    a2_x = sqrt(1-sin(pars->theta)*cos(pars->phi))*cos(pars->psi);
-    a2_y = sqrt(1-sin(pars->theta)*cos(pars->phi))*sin(pars->psi);
+    a2_x = sqrt(1.0-sin(pars->theta)*cos(pars->phi))*cos(pars->psi);
+    a2_y = sqrt(1.0-sin(pars->theta)*cos(pars->phi))*sin(pars->psi);
     // a2 axis
-    cos_val_a2 = sin(acos(cos_val_a1)) ;
+    cos_val_a2 =  a2_x*q_x + a2_y*q_y;//sin(acos(cos_val_a1)) ;
     a2_dot_q = aa*q*cos_val_a2;
 
Index: sansmodels/src/sans/models/c_extensions/triaxial_ellipsoid.c
===================================================================
--- sansmodels/src/sans/models/c_extensions/triaxial_ellipsoid.c	(revision 13eb1c4b175eb150bd941382067266672545173d)
+++ sansmodels/src/sans/models/c_extensions/triaxial_ellipsoid.c	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -97,5 +97,5 @@
 
     // q vector
-    q_z = 0;
+    q_z = 0.0;
 
 	//dx = 1.0;
Index: sansmodels/src/sans/models/test/utest_extra_models.py
===================================================================
--- sansmodels/src/sans/models/test/utest_extra_models.py	(revision 339ce675656e3ab89eff7b84d8292a2e0ffe6109)
+++ sansmodels/src/sans/models/test/utest_extra_models.py	(revision 8f20419d5be1d467bd17c7dfade28c96f90656ca)
@@ -178,5 +178,115 @@
         self.assertAlmostEqual(self.model.run(0.215268), 0.00927739, 6)
         self.assertAlmostEqual(self.model.runXY(0.414467), 0.000406973, 6)
-                                                        
+                               
+
+class TestGuinierPorod(unittest.TestCase):
+    """
+    Unit tests for GuinierPorod Model function
+    """
+    def setUp(self):
+        from sans.models.GuinierPorodModel import GuinierPorodModel 
+        self.model= GuinierPorodModel()
+        
+    def test1D(self):        
+        # the values are from Igor pro calculation  
+        # the different digits are due to precision of q values  
+        self.assertAlmostEqual(self.model.run(0.001), 995.112, 3)
+        self.assertAlmostEqual(self.model.run(0.105363), 0.162904, 5)
+        self.assertAlmostEqual(self.model.runXY(0.441623), 0.100854, 6)
+
+class TestGaussLorentzGel(unittest.TestCase):
+    """
+    Unit tests for GuinierPorod Model function
+    """
+    def setUp(self):
+        from sans.models.GaussLorentzGelModel import GaussLorentzGelModel
+        self.model= GaussLorentzGelModel()
+        
+    def test1D(self):        
+        # the values are from Igor pro calculation  
+        # the different digits are due to precision of q values  
+        self.assertAlmostEqual(self.model.run(0.001), 149.481, 3)
+        self.assertAlmostEqual(self.model.run(0.105363), 9.1903, 4)
+        self.assertAlmostEqual(self.model.runXY(0.441623), 0.632811, 5)
+                                
+
+class TestTwoPowerLaw(unittest.TestCase):
+    """
+    Unit tests for TwoPowerLaw Model function
+    """
+    def setUp(self):
+        from sans.models.TwoPowerLawModel import TwoPowerLawModel
+        self.model= TwoPowerLawModel()
+        
+    def test1D(self):        
+        # the values are from Igor pro calculation  
+        # the different digits are due to precision of q values  
+        self.assertEqual(self.model.run(0.001), 1000)
+        self.assertAlmostEqual(self.model.run(0.150141), 0.125945, 5)
+        self.assertAlmostEqual(self.model.runXY(0.442528), 0.00166884, 7)
+                                
+class TestTwoLorentzian(unittest.TestCase):
+    """
+    Unit tests for TwoLorentzian Model function
+    """
+    def setUp(self):
+        from sans.models.TwoLorentzianModel import TwoLorentzianModel
+        self.model= TwoLorentzianModel()
+        
+    def test1D(self):        
+        # the values are from Igor pro calculation  
+        # the different digits are due to precision of q values  
+        self.assertAlmostEqual(self.model.run(0.001), 11.0899, 3)
+        self.assertAlmostEqual(self.model.run(0.150141), 0.410245, 5)
+        self.assertAlmostEqual(self.model.runXY(0.442528), 0.148699, 6)
+                                
+
+class TestCorrLengthLaw(unittest.TestCase):
+    """
+    Unit tests for CorrLength Model function
+    """
+    def setUp(self):
+        from sans.models.CorrLengthModel import CorrLengthModel
+        self.model= CorrLengthModel()
+        
+    def test1D(self):        
+        # the values are from Igor pro calculation  
+        # the different digits are due to precision of q values  
+        self.assertAlmostEqual(self.model.run(0.001), 1010.08, 1)
+        self.assertAlmostEqual(self.model.run(0.150141), 0.274645, 5)
+        self.assertAlmostEqual(self.model.runXY(0.442528), 0.120396, 6)
+                                
+
+class TestBroadPeak(unittest.TestCase):
+    """
+    Unit tests for BroadPeak Model function
+    """
+    def setUp(self):
+        from sans.models.BroadPeakModel import BroadPeakModel
+        self.model= BroadPeakModel()
+        
+    def test1D(self):        
+        # the values are from Igor pro calculation  
+        # the different digits are due to precision of q values  
+        self.assertAlmostEqual(self.model.run(0.001), 10000.5, 1)
+        self.assertAlmostEqual(self.model.run(0.1501412), 1.47557, 5)
+        self.assertAlmostEqual(self.model.runXY(0.4425284), 0.134093, 6)
+        
+class TestFractalCoreShell(unittest.TestCase):
+    """
+    Unit tests for FractalCoreShell Model function
+    """
+    def setUp(self):
+        from sans.models.FractalCoreShellModel import FractalCoreShellModel
+        self.model= FractalCoreShellModel()
+        
+    def test1D(self):        
+        #self.model.setParam('radius.width', 2.0)
+        # the values are from Igor pro calculation  
+        # the different digits are due to precision of q values  
+        self.assertAlmostEqual(self.model.run(0.001), 273.742, 3)
+        self.assertAlmostEqual(self.model.run(0.1501412), 0.040079, 6)
+        self.assertAlmostEqual(self.model.runXY(0.4425284), 0.00141167, 6)                             
+                                                                                                               
 if __name__ == '__main__':
     unittest.main()
