Ejemplo n.º 1
0
class ApertureTEAPOT(NodeTEAPOT):
	"""
	Aperture TEAPOT element.
	"""
	def __init__(self, name = "aperture no name"):
		"""
		Constructor. Creates the aperutre element.
		"""
		NodeTEAPOT.__init__(self,name)
		self.setType("aperture")
		self.addParam("aperture", [])
		self.addParam("apertype", 0.0)
		
	def initialize(self):
	
		shape = self.getParam("apertype")
		dim = self.getParam("aperture")
		if len(dim) > 0:
			if shape == 1:
				self.aperture = Aperture(shape, dim[0], 0.0, 0.0, 0.0)
			if shape == 2:
				self.aperture = Aperture(shape, dim[0], dim[1], 0.0, 0.0)
			if shape == 3:
				self.aperture = Aperture(shape, dim[0], dim[1], 0.0, 0.0)

	def track(self, paramsDict):
		"""
		The aperture class implementation of the ApertueNode.
		"""
		bunch = paramsDict["bunch"]
		lostbunch = paramsDict["lostbunch"]
		self.aperture.checkBunch(bunch,lostbunch)
Ejemplo n.º 2
0
class ApertureTEAPOT(NodeTEAPOT):
    """
	Aperture TEAPOT element.
	"""
    def __init__(self, name="aperture no name"):
        """
		Constructor. Creates the aperutre element.
		"""
        NodeTEAPOT.__init__(self, name)
        self.setType("aperture")
        self.addParam("aperture", [])
        self.addParam("apertype", 0.0)

    def initialize(self):

        shape = self.getParam("apertype")
        dim = self.getParam("aperture")
        if len(dim) > 0:
            if shape == 1:
                self.aperture = Aperture(shape, dim[0], 0.0, 0.0, 0.0)
            if shape == 2:
                self.aperture = Aperture(shape, dim[0], dim[1], 0.0, 0.0)
            if shape == 3:
                self.aperture = Aperture(shape, dim[0], dim[1], 0.0, 0.0)

    def track(self, paramsDict):
        """
		The aperture class implementation of the ApertueNode.
		"""
        bunch = paramsDict["bunch"]
        lostbunch = paramsDict["lostbunch"]
        self.aperture.checkBunch(bunch, lostbunch)
Ejemplo n.º 3
0
 def __init__(self,
              aperture='slit',
              mass_profile='power_law',
              light_profile='Hernquist',
              anisotropy_type='r_ani',
              psf_fwhm=0.7,
              kwargs_cosmo={
                  'D_d': 1000,
                  'D_s': 2000,
                  'D_ds': 500
              }):
     """
     initializes the observation condition and masks
     :param aperture_type: string
     :param psf_fwhm: float
     """
     self._mass_profile = mass_profile
     self._fwhm = psf_fwhm
     self._kwargs_cosmo = kwargs_cosmo
     self.lightProfile = LightProfile_old(light_profile)
     self.aperture = Aperture(aperture)
     self.anisotropy = Anisotropy(anisotropy_type)
     self.FWHM = psf_fwhm
     self.jeans_solver = Jeans_solver(kwargs_cosmo, mass_profile,
                                      light_profile, anisotropy_type)
Ejemplo n.º 4
0
	def __init__(self, shape, a, b, pos = 0., c = 0., d = 0., name = "aperture"):
		BaseLinacNode.__init__(self,name)
		self.shape = shape
		self.a = a
		self.b = b
		self.c = c
		self.d = d
		self.aperture = Aperture(self.shape, self.a, self.b, self.c, self.d, pos)	
		self.setPosition(pos)
Ejemplo n.º 5
0
	def initialize(self):
	
		shape = self.getParam("apertype")
		dim = self.getParam("aperture")
		if len(dim) > 0:
			if shape == 1:
				self.aperture = Aperture(shape, dim[0], 0.0, 0.0, 0.0)
			if shape == 2:
				self.aperture = Aperture(shape, dim[0], dim[1], 0.0, 0.0)
			if shape == 3:
				self.aperture = Aperture(shape, dim[0], dim[1], 0.0, 0.0)
Ejemplo n.º 6
0
    def __init__(self, gb):
        self.gb = gb

        # -- flow -- #
        self.discr_flow = Flow(gb)

        shape = self.discr_flow.shape()
        self.flux_pressure = np.zeros(shape)

        # -- temperature -- #
        self.discr_temperature = Heat(gb)

        shape = self.discr_temperature.shape()
        self.temperature = np.zeros(shape)
        self.temperature_old = np.zeros(shape)

        # -- solute and precipitate -- #
        self.discr_solute_advection_diffusion = Transport(gb)
        self.discr_solute_precipitate_reaction = Reaction(gb)

        shape = self.discr_solute_advection_diffusion.shape()
        self.solute = np.zeros(shape)
        self.precipitate = np.zeros(shape)
        self.solute_old = np.zeros(shape)
        self.precipitate_old = np.zeros(shape)

        # -- porosity -- #
        self.discr_porosity = Porosity(gb)

        shape = self.discr_porosity.shape()
        self.porosity = np.zeros(shape)
        self.porosity_old = np.zeros(shape)
        self.porosity_star = np.zeros(shape)

        # -- aperture -- #
        self.discr_aperture = Aperture(gb)

        shape = self.discr_aperture.shape()
        self.aperture = np.zeros(shape)
        self.aperture_old = np.zeros(shape)
        self.aperture_star = np.zeros(shape)

        # -- composite variables -- #
        self.porosity_aperture_times_solute = np.zeros(shape)
        self.porosity_aperture_times_precipitate = np.zeros(shape)
Ejemplo n.º 7
0
	def __init__(self, shape, a, b, pos = 0., c = 0., d = 0., name = "aperture"):
		BaseLinacNode.__init__(self,name)
		self.shape = shape
		self.a = a
		self.b = b
		self.c = c
		self.d = d
		self.pos = pos
		self.aperture = Aperture(self.shape, self.a, self.b, self.c, self.d, self.pos)
Ejemplo n.º 8
0
	def __init__(self, a, b, pos = 0, c = 0, d = 0, name = "aperture"):
		DriftTEAPOT.__init__(self,name)
		self.shape = 3
		self.a = a
		self.b = b
		self.c = c
		self.d = d
		self.pos = pos
		self.Aperture = Aperture(self.shape, self.a, self.b, self.c, self.d, self.pos)
Ejemplo n.º 9
0
class RectangleApertureNode(DriftTEAPOT):
	def __init__(self, a, b, pos = 0, c = 0, d = 0, name = "aperture"):
		DriftTEAPOT.__init__(self,name)
		self.shape = 3
		self.a = a
		self.b = b
		self.c = c
		self.d = d
		self.pos = pos
		self.Aperture = Aperture(self.shape, self.a, self.b, self.c, self.d, self.pos)
	
	def track(self, paramsDict):
		bunch = paramsDict["bunch"]
		lostbunch = paramsDict["lostbunch"]
		self.Aperture.checkBunch(bunch, lostbunch)

	def setPosition(self,pos):
		self.pos = pos
		self.Aperture.setPosition(self.pos)
Ejemplo n.º 10
0
class LinacApertureNode(BaseLinacNode):
	"""
	The aperture classes removes particles from bunch and places them in the lostbunch
	if their coordinates are not inside the aperture:
	The shape variable could be:
	1 is circle (a is a radius)
	2 is elipse (a and b are a half-axises)
	3 is rectangle (a and b are a half-horizontal and vertical sizes)
	c and d parameters are x and y offsets of the center
	"""
	def __init__(self, shape, a, b, pos = 0., c = 0., d = 0., name = "aperture"):
		BaseLinacNode.__init__(self,name)
		self.shape = shape
		self.a = a
		self.b = b
		self.c = c
		self.d = d
		self.pos = pos
		self.aperture = Aperture(self.shape, self.a, self.b, self.c, self.d, self.pos)
	
	def track(self, paramsDict):
		bunch = paramsDict["bunch"]
		if(paramsDict.has_key("lostbunch")):
			lostbunch = paramsDict["lostbunch"]
			self.aperture.checkBunch(bunch, lostbunch)
		else:
			self.aperture.checkBunch(bunch)

	def trackDesign(self, paramsDict):
		"""
		This method does nothing for the aperture case.
		"""
		pass

	def setPosition(self, pos):
		self.pos = pos
		self.Aperture.setPosition(self.pos)

	def getPosition(self):
		return self.pos
Ejemplo n.º 11
0
 def __init__(self,
              mass_profile_list,
              light_profile_list,
              aperture_type='slit',
              anisotropy_model='isotropic',
              fwhm=0.7,
              kwargs_numerics={},
              kwargs_cosmo={
                  'D_d': 1000,
                  'D_s': 2000,
                  'D_ds': 500
              }):
     self.massProfile = MassProfile(mass_profile_list, kwargs_cosmo)
     self.lightProfile = LightProfile(light_profile_list)
     self.aperture = Aperture(aperture_type)
     self.anisotropy = MamonLokasAnisotropy(anisotropy_model)
     self.FWHM = fwhm
     self.cosmo = Cosmo(kwargs_cosmo)
     self._num_sampling = kwargs_numerics.get('sampling_number', 1000)
     self._interp_grid_num = kwargs_numerics.get('interpol_grid_num', 1000)
     self._log_int = kwargs_numerics.get('log_integration', False)
     self._max_integrate = kwargs_numerics.get(
         'max_integrate',
         100)  # maximal integration (and interpolation) in units of arcsecs
Ejemplo n.º 12
0
    def initialize(self):

        shape = self.getParam("apertype")
        dim = self.getParam("aperture")
        if len(dim) > 0:
            if shape == 1:
                self.aperture = Aperture(shape, dim[0], 0.0, 0.0, 0.0)
            if shape == 2:
                self.aperture = Aperture(shape, dim[0], dim[1], 0.0, 0.0)
            if shape == 3:
                self.aperture = Aperture(shape, dim[0], dim[1], 0.0, 0.0)
Ejemplo n.º 13
0
class LinacApertureNode(BaseLinacNode):
    """
	The aperture classes removes particles from bunch and places them in the lostbunch
	if their coordinates are not inside the aperture:
	The shape variable could be:
	1 is circle (a is a radius)
	2 is elipse (a and b are a half-axises)
	3 is rectangle (a and b are a half-horizontal and vertical sizes)
	c and d parameters are x and y offsets of the center
	"""
    def __init__(self, shape, a, b, pos=0., c=0., d=0., name="aperture"):
        BaseLinacNode.__init__(self, name)
        self.shape = shape
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.aperture = Aperture(self.shape, self.a, self.b, self.c, self.d,
                                 pos)
        self.setPosition(pos)
        self.lost_particles_n = 0

    def track(self, paramsDict):
        bunch = paramsDict["bunch"]
        n_parts = bunch.getSize()
        if (paramsDict.has_key("lostbunch")):
            lostbunch = paramsDict["lostbunch"]
            self.aperture.checkBunch(bunch, lostbunch)
        else:
            self.aperture.checkBunch(bunch)
        self.lost_particles_n = n_parts - bunch.getSize()

    def trackDesign(self, paramsDict):
        """
		This method does nothing for the aperture case.
		"""
        pass

    def setPosition(self, pos):
        BaseLinacNode.setPosition(self, pos)
        self.aperture.setPosition(self.getPosition())

    def getNumberOfLostParticles(self):
        return self.lost_particles_n
Ejemplo n.º 14
0
class Galkin(object):
    """
    major class to compute velocity dispersion measurements given light and mass models
    """
    def __init__(self,
                 mass_profile_list,
                 light_profile_list,
                 aperture_type='slit',
                 anisotropy_model='isotropic',
                 fwhm=0.7,
                 kwargs_numerics={},
                 kwargs_cosmo={
                     'D_d': 1000,
                     'D_s': 2000,
                     'D_ds': 500
                 }):
        self.massProfile = MassProfile(mass_profile_list, kwargs_cosmo)
        self.lightProfile = LightProfile(light_profile_list)
        self.aperture = Aperture(aperture_type)
        self.anisotropy = MamonLokasAnisotropy(anisotropy_model)
        self.FWHM = fwhm
        self.cosmo = Cosmo(kwargs_cosmo)
        self._num_sampling = kwargs_numerics.get('sampling_number', 1000)
        self._interp_grid_num = kwargs_numerics.get('interpol_grid_num', 1000)
        self._log_int = kwargs_numerics.get('log_integration', False)
        self._max_integrate = kwargs_numerics.get(
            'max_integrate',
            100)  # maximal integration (and interpolation) in units of arcsecs

    def vel_disp(self,
                 kwargs_mass,
                 kwargs_light,
                 kwargs_anisotropy,
                 kwargs_apertur,
                 r_eff=1.):
        """
        computes the averaged LOS velocity dispersion in the slit (convolved)
        :param gamma:
        :param phi_E:
        :param r_eff:
        :param r_ani:
        :param R_slit:
        :param FWHM:
        :return:
        """
        sigma2_R_sum = 0
        for i in range(0, self._num_sampling):
            sigma2_R = self.draw_one_sigma2(kwargs_mass,
                                            kwargs_light,
                                            kwargs_anisotropy,
                                            kwargs_apertur,
                                            r_eff=r_eff)
            sigma2_R_sum += sigma2_R
        sigma_s2_average = sigma2_R_sum / self._num_sampling
        # apply unit conversion from arc seconds and deflections to physical velocity disperison in (km/s)
        sigma_s2_average *= 2 * const.G  # correcting for integral prefactor
        return np.sqrt(sigma_s2_average /
                       (const.arcsec**2 * self.cosmo.D_d**2 *
                        const.Mpc)) / 1000.  # in units of km/s

    def draw_one_sigma2(self,
                        kwargs_mass,
                        kwargs_light,
                        kwargs_anisotropy,
                        kwargs_aperture,
                        r_eff=1.):
        """

        :param kwargs_mass:
        :param kwargs_light:
        :param kwargs_anisotropy:
        :param kwargs_aperture:
        :return:
        """
        while True:
            R = self.lightProfile.draw_light_2d(kwargs_light,
                                                r_eff=r_eff)  # draw r
            x, y = util.draw_xy(R)  # draw projected R
            x_, y_ = util.displace_PSF(x, y, self.FWHM)  # displace via PSF
            bool = self.aperture.aperture_select(x_, y_, kwargs_aperture)
            if bool is True:
                break
        sigma2_R = self.sigma2_R(R, kwargs_mass, kwargs_light,
                                 kwargs_anisotropy)
        return sigma2_R

    def sigma2_R(self, R, kwargs_mass, kwargs_light, kwargs_anisotropy):
        """
        returns unweighted los velocity dispersion
        :param R:
        :param kwargs_mass:
        :param kwargs_light:
        :param kwargs_anisotropy:
        :return:
        """
        I_R_sigma2 = self.I_R_simga2(R, kwargs_mass, kwargs_light,
                                     kwargs_anisotropy)
        I_R = self.lightProfile.light_2d(R, kwargs_light)
        #I_R = self.lightProfile._integrand_light(R, kwargs_light)
        return I_R_sigma2 / I_R

    def I_R_simga2(self, R, kwargs_mass, kwargs_light, kwargs_anisotropy):
        """
        equation A15 in Mamon&Lokas 2005 as a logarithmic numerical integral
        modulo pre-factor 2*G
        :param R:
        :param kwargs_mass:
        :param kwargs_light:
        :param kwargs_anisotropy:
        :return:
        """
        if self._log_int is True:
            min_log = np.log10(R + 0.0001)
            max_log = np.log10(self._max_integrate)
            r_array = np.logspace(min_log, max_log, self._interp_grid_num)
            dlog_r = (np.log10(r_array[1]) - np.log10(r_array[0])) * np.log(10)
            IR_sigma2_dr = self._integrand_A15(
                r_array, R, kwargs_mass, kwargs_light,
                kwargs_anisotropy) * dlog_r * r_array
        else:
            r_array = np.linspace(R + 0.0001, self._max_integrate,
                                  self._interp_grid_num)
            dr = r_array[1] - r_array[0]
            IR_sigma2_dr = self._integrand_A15(
                r_array, R, kwargs_mass, kwargs_light, kwargs_anisotropy) * dr
        IR_sigma2 = np.sum(IR_sigma2_dr)
        return IR_sigma2

    def _integrand_A15(self, r, R, kwargs_mass, kwargs_light,
                       kwargs_anisotropy):
        """
        integrand of A15 (in log space)
        :param r:
        :param kwargs_mass:
        :param kwargs_light:
        :param kwargs_anisotropy:
        :return:
        """
        k_r = self.anisotropy.K(r, R, kwargs_anisotropy)
        l_r = self.lightProfile.light_3d_interp(r, kwargs_light)
        m_r = self.massProfile.mass_3d_interp(r, kwargs_mass)
        out = k_r * l_r * m_r / r
        return out
Ejemplo n.º 15
0
class GalKin_old(object):
    """
    master class for all computations
    """
    def __init__(self,
                 aperture='slit',
                 mass_profile='power_law',
                 light_profile='Hernquist',
                 anisotropy_type='r_ani',
                 psf_fwhm=0.7,
                 kwargs_cosmo={
                     'D_d': 1000,
                     'D_s': 2000,
                     'D_ds': 500
                 }):
        """
        initializes the observation condition and masks
        :param aperture_type: string
        :param psf_fwhm: float
        """
        self._mass_profile = mass_profile
        self._fwhm = psf_fwhm
        self._kwargs_cosmo = kwargs_cosmo
        self.lightProfile = LightProfile_old(light_profile)
        self.aperture = Aperture(aperture)
        self.anisotropy = Anisotropy(anisotropy_type)
        self.FWHM = psf_fwhm
        self.jeans_solver = Jeans_solver(kwargs_cosmo, mass_profile,
                                         light_profile, anisotropy_type)

    def vel_disp(self,
                 kwargs_profile,
                 kwargs_aperture,
                 kwargs_light,
                 kwargs_anisotropy,
                 num=1000):
        """
        computes the averaged LOS velocity dispersion in the slit (convolved)
        :param gamma:
        :param phi_E:
        :param r_eff:
        :param r_ani:
        :param R_slit:
        :param FWHM:
        :return:
        """
        sigma_s2_sum = 0
        for i in range(0, num):
            sigma_s2_draw = self._vel_disp_one(kwargs_profile, kwargs_aperture,
                                               kwargs_light, kwargs_anisotropy)
            sigma_s2_sum += sigma_s2_draw
        sigma_s2_average = sigma_s2_sum / num
        return np.sqrt(sigma_s2_average)

    def _vel_disp_one(self, kwargs_profile, kwargs_aperture, kwargs_light,
                      kwargs_anisotropy):
        """
        computes one realisation of the velocity dispersion realized in the slit
        :param gamma:
        :param rho0_r0_gamma:
        :param r_eff:
        :param r_ani:
        :param R_slit:
        :param dR_slit:
        :param FWHM:
        :return:
        """

        while True:
            r = self.lightProfile.draw_light(kwargs_light)  # draw r
            R, x, y = util.R_r(r)  # draw projected R
            x_, y_ = util.displace_PSF(x, y, self.FWHM)  # displace via PSF
            bool = self.aperture.aperture_select(x_, y_, kwargs_aperture)
            if bool is True:
                break
        sigma_s2 = self.sigma_s2(r, R, kwargs_profile, kwargs_anisotropy,
                                 kwargs_light)
        return sigma_s2

    def sigma_s2(self, r, R, kwargs_profile, kwargs_anisotropy, kwargs_light):
        """
        projected velocity dispersion
        :param r:
        :param R:
        :param r_ani:
        :param a:
        :param gamma:
        :param phi_E:
        :return:
        """
        beta = self.anisotropy.beta_r(r, kwargs_anisotropy)
        return (1 - beta * R**2 / r**2) * self.sigma_r2(
            r, kwargs_profile, kwargs_anisotropy, kwargs_light)

    def sigma_r2(self, r, kwargs_profile, kwargs_anisotropy, kwargs_light):
        """
        computes radial velocity dispersion at radius r (solving the Jeans equation
        :param r:
        :return:
        """
        return self.jeans_solver.sigma_r2(r, kwargs_profile, kwargs_anisotropy,
                                          kwargs_light)
Ejemplo n.º 16
0
if __name__ == "__main__":
    def slowly_rotate(cls):
        old_update = cls.update

        def update(obj, dt):
            if old_update is not None:
                old_update(obj, dt)
            obj.orientation[:] += np.array([20, 50, 90]) * dt

        cls.update = update


    # cube = Cube()
    # cube.position[2] = -5.

    # torus = Torus(1, 0.3, 50, 30)
    # torus.position[2] = -4.

    aperture = Aperture()
    slowly_rotate(Aperture)

    aperture.position[2] = -10
    aperture.size[:] = [2., 2., 2.]
    aperture.hole.size[:2] = [1., 1.]
    aperture.lbox.size[0] = 3.
    aperture.tbox.size[1] = 2.5

    scene = Scene()
    scene._polygons = {'aperture': aperture}
    scene.exec_()
Ejemplo n.º 17
0
class Scheme(object):

    # ------------------------------------------------------------------------------#

    def __init__(self, gb):
        self.gb = gb

        # -- flow -- #
        self.discr_flow = Flow(gb)

        shape = self.discr_flow.shape()
        self.flux_pressure = np.zeros(shape)

        # -- temperature -- #
        self.discr_temperature = Heat(gb)

        shape = self.discr_temperature.shape()
        self.temperature = np.zeros(shape)
        self.temperature_old = np.zeros(shape)

        # -- solute and precipitate -- #
        self.discr_solute_advection_diffusion = Transport(gb)
        self.discr_solute_precipitate_reaction = Reaction(gb)

        shape = self.discr_solute_advection_diffusion.shape()
        self.solute = np.zeros(shape)
        self.precipitate = np.zeros(shape)
        self.solute_old = np.zeros(shape)
        self.precipitate_old = np.zeros(shape)

        # -- porosity -- #
        self.discr_porosity = Porosity(gb)

        shape = self.discr_porosity.shape()
        self.porosity = np.zeros(shape)
        self.porosity_old = np.zeros(shape)
        self.porosity_star = np.zeros(shape)

        # -- aperture -- #
        self.discr_aperture = Aperture(gb)

        shape = self.discr_aperture.shape()
        self.aperture = np.zeros(shape)
        self.aperture_old = np.zeros(shape)
        self.aperture_star = np.zeros(shape)

        # -- composite variables -- #
        self.porosity_aperture_times_solute = np.zeros(shape)
        self.porosity_aperture_times_precipitate = np.zeros(shape)

    # ------------------------------------------------------------------------------#

    def compute_flow(self):
        A, b = self.discr_flow.matrix_rhs()
        return sps.linalg.spsolve(A, b)

    # ------------------------------------------------------------------------------#

    def compute_temperature(self, porosity_star, aperture_star):
        # compute the matrices
        A, M, b = self.discr_temperature.matrix_rhs()

        # compute the effective thermal capacity, keeping in mind that the fracture
        # contains only water
        rc_w = self.discr_temperature.data["rc_w"]
        rc_s = self.discr_temperature.data["rc_s"]

        c_star = rc_w * (porosity_star + aperture_star) + rc_s * (1 - porosity_star)
        c_old = rc_w * (self.porosity_old + self.aperture_old) + rc_s * (1 - self.porosity_old)

        # the mass term which considers the contribution from the effective thermal capacity
        M_star = M * sps.diags(c_star, 0)
        M_old = M * sps.diags(c_old, 0)

        # compute the new temperature
        return sps.linalg.spsolve(M_star + A, M_old * self.temperature_old + b)

    # ------------------------------------------------------------------------------#

    def compute_solute_precipitate_advection_diffusion(self, porosity_star, aperture_star):
        # compute the matrices
        A, M, b = self.discr_solute_advection_diffusion.matrix_rhs()

        # the mass term which considers both the porosity and aperture contribution
        M_star = M * sps.diags(porosity_star + aperture_star, 0)
        M_old = M * sps.diags(self.porosity_old + self.aperture_old, 0)

        # compute the new solute
        return sps.linalg.spsolve(M_star + A, M_old * self.solute_old + b)

    # ------------------------------------------------------------------------------#

    def compute_solute_precipitate_rection(self, solute_half, precipitate_half):
        # the dof associated to the porous media and fractures, are the first
        dof = self.gb.num_cells()

        # temporary solution vectors
        solute = np.zeros(self.discr_solute_advection_diffusion.shape())
        precipitate = np.zeros(self.discr_solute_advection_diffusion.shape())

        # compute the new solute and precipitate
        solute[:dof], precipitate[:dof] = self.discr_solute_precipitate_reaction.step(
                                                                    solute_half[:dof],
                                                                    precipitate_half[:dof],
                                                                    self.temperature[:dof])
        return solute, precipitate

    # ------------------------------------------------------------------------------#

    def set_old_variables(self):
        self.temperature_old = self.temperature.copy()
        self.solute_old = self.solute.copy()
        self.precipitate_old = self.precipitate.copy()
        self.porosity_old = self.porosity.copy()
        self.aperture_old = self.aperture.copy()

    # ------------------------------------------------------------------------------#

    def set_data(self, param):

        # set the initial condition
        assembler = self.discr_solute_advection_diffusion.assembler
        dof = np.cumsum(np.append(0, np.asarray(assembler.full_dof)))
        for (g, _), bi in assembler.block_dof.items():
            #g = pair[0]
            if isinstance(g, pp.Grid):
                dof_loc = slice(dof[bi], dof[bi+1])

                data = param["temperature"]["initial"]
                self.temperature[dof_loc] = data(g, param, param["tol"])

                data = param["solute_advection_diffusion"]["initial_solute"]
                self.solute[dof_loc] = data(g, param, param["tol"])

                data = param["solute_advection_diffusion"]["initial_precipitate"]
                self.precipitate[dof_loc] = data(g, param, param["tol"])

                data = param["porosity"]["initial"]
                self.porosity[dof_loc] = data(g, param, param["tol"])

                data = param["aperture"]["initial"]
                self.aperture[dof_loc] = data(g, param, param["tol"])

        # set the old variables
        self.set_old_variables()

        # save the initial porosity and aperture
        self.discr_porosity.extract(self.porosity, "porosity_initial")
        self.discr_aperture.extract(self.aperture, "aperture_initial")

        # extract the initialized variables, useful for setting the data
        self.extract()

        # set now the data for each scheme
        self.discr_flow.set_data(param["flow"], param["time"])
        self.discr_temperature.set_data(param["temperature"], param["time"])
        self.discr_solute_advection_diffusion.set_data(param["solute_advection_diffusion"], param["time"])
        self.discr_solute_precipitate_reaction.set_data(param["solute_precipitate_reaction"], param["time"])
        self.discr_porosity.set_data(param["porosity"])
        self.discr_aperture.set_data(param["aperture"])

    # ------------------------------------------------------------------------------#

    def extract(self):

        self.discr_flow.extract(self.flux_pressure)
        self.discr_temperature.extract(self.temperature, "temperature")
        self.discr_solute_advection_diffusion.extract(self.solute, "solute")
        self.discr_solute_advection_diffusion.extract(self.precipitate, "precipitate")

        self.discr_porosity.extract(self.porosity, "porosity")
        self.discr_porosity.extract(self.porosity_old, "porosity_old")

        self.discr_aperture.extract(self.aperture, "aperture")
        self.discr_aperture.extract(self.aperture_old, "aperture_old")

        self.discr_solute_advection_diffusion.extract(self.porosity_aperture_times_solute,
            "porosity_aperture_times_solute")
        self.discr_solute_advection_diffusion.extract(self.porosity_aperture_times_precipitate,
            "porosity_aperture_times_precipitate")

    # ------------------------------------------------------------------------------#

    def vars_to_save(self):
        name = ["solute", "precipitate", "porosity", "aperture", "temperature"]
        name += ["porosity_aperture_times_solute", "porosity_aperture_times_precipitate"]
        return name + [self.discr_flow.pressure, self.discr_flow.P0_flux]

    # ------------------------------------------------------------------------------#


    def one_step_splitting_scheme(self):

        # the dof associated to the porous media and fractures, are the first
        dof = slice(0, self.gb.num_cells())

        # POINT 1) extrapolate the precipitate to get a better estimate of porosity
        precipitate_star = 2*self.precipitate - self.precipitate_old

        # POINT 2) compute the porosity and aperture star
        porosity_star = self.discr_porosity.step(self.porosity_old, precipitate_star, self.precipitate_old)
        self.discr_porosity.extract(porosity_star, "porosity_star")

        aperture_star = self.discr_aperture.step(self.aperture_old, precipitate_star, self.precipitate_old)
        self.discr_aperture.extract(aperture_star, "aperture_star")

        # -- DO THE FLOW PART -- #

        # POINT 3) update the data from the previous time step
        self.discr_flow.update_data()

        # POINT 4) solve the flow part
        self.flux_pressure = self.compute_flow()
        self.discr_flow.extract(self.flux_pressure)

        # -- DO THE HEAT PART -- #

        # POINT 5) set the flux and update the data from the previous time step
        self.discr_temperature.set_flux(self.discr_flow.flux, self.discr_flow.mortar)
        self.discr_temperature.update_data()

        # POINT 5) solve the temperature part
        self.temperature = self.compute_temperature(porosity_star, aperture_star)

        # -- DO THE TRANSPORT PART -- #

        # set the flux and update the data from the previous time step
        self.discr_solute_advection_diffusion.set_flux(self.discr_flow.flux, self.discr_flow.mortar)
        self.discr_solute_advection_diffusion.update_data()

        # POINT 6) solve the advection and diffusion part to get the intermediate solute solution
        solute_half = self.compute_solute_precipitate_advection_diffusion(porosity_star, aperture_star)

        # POINT 7) Since in the advection-diffusion step we have accounted for porosity changes using
        # phi_star, the new solute concentration accounts for the change in pore volume, thus, the
        # precipitate needs to be updated accordingly
        factor = np.zeros(self.porosity_old.size)
        factor[dof] = (self.porosity_old[dof] + self.aperture_old[dof]) / (porosity_star[dof] + aperture_star[dof])
        precipitate_half = self.precipitate_old * factor

        # POINT 8) solve the reaction part
        solute_star_star, precipitate_star_star = self.compute_solute_precipitate_rection(solute_half, precipitate_half)

        # -- DO THE POROSITY PART -- #

        # POINT 9) solve the porosity and aperture part with the true concentration of precipitate
        self.porosity = self.discr_porosity.step(self.porosity, precipitate_star_star, self.precipitate_old)
        self.aperture = self.discr_aperture.step(self.aperture, precipitate_star_star, self.precipitate_old)

        # POINT 10) finally, we correct the concentrations to account for the difference between the extrapolated
        # and "true" new porosity to ensure mass conservation
        factor = np.zeros(self.porosity_old.size)
        factor[dof] = (porosity_star[dof] + aperture_star[dof]) / (self.porosity[dof] + self.aperture[dof])
        self.solute = solute_star_star * factor
        self.precipitate = precipitate_star_star * factor

        # set the old variables
        self.set_old_variables()

        # compute composite variables
        factor = self.porosity + self.aperture
        self.porosity_aperture_times_solute = factor * self.solute
        self.porosity_aperture_times_precipitate = factor * self.precipitate

        # extract all the variables, useful for exporting
        self.extract()