Example #1
0
from sleep.fbb_DD.solid import solve_solid
from sleep.fbb_DD.fluid import solve_fluid
from sleep.fbb_DD.ale import solve_ale
from sleep.utils import EmbeddedMesh
from sleep.mesh import load_mesh2d
from dolfin import *

# We get the fluid domain mesh from the full PVS mesh
h5_filename = '../mesh/test/fbb_domain.h5'
# The mesh is typically generated by sleep/mesh/fbb_mesh.py
mesh, markers, lookup = load_mesh2d(h5_filename)
cell_f, facet_f = markers
cell_lookup, facet_lookup = lookup['cell'], lookup['facet']
# The mesh has 3 subdomains: corresponding to fluid and two Biot domain.
# We now split into fluid and solid meshes in order to keep only the fluid mesh
mesh_f = EmbeddedMesh(cell_f, cell_lookup['F'])
mesh_s = EmbeddedMesh(cell_f, (cell_lookup['S1'], cell_lookup['S2']))

# We get the boundary markers
fluid_markers = ('F_left', 'F_bottom', 'F_right', 'I_bottom')
fluid_markers = tuple(facet_lookup[k] for k in fluid_markers)
fluid_bdries = mesh_f.translate_markers(facet_f, fluid_markers)

# Parameters setup ------------------------------------------------ FIXME
mu_F = Constant(7e-3)
#-----------------------------------

fluid_parameters = {'mu': mu_F}

# Setup fem spaces ---------------------------------------------------
Vf_elm = VectorElement('Lagrange', triangle, 2)
Example #2
0
def transfer_DD(expr, V, interface, tol=1E-10):
    '''
    Let interface = (bdries-domain-1, bdries-domain-2, shared-bdry-index).
    Using space V defined on bdries-domain-1.mesh() we build a good enough 
    representation of it in V(bdiers-domain-2.mesh()).
    '''
    if len(interface) == 2:  # Same domain
        interface = (interface[0], interface[0], interface[1])
        return transfer_DD(expr, V, interface, tol)

    bdries1, bdries2, tag = interface
    # Share?
    assert tag in set(bdries1.array()) and tag in set(bdries2.array())
    # On first
    mesh1 = bdries1.mesh()
    assert V.mesh().id() == mesh1.id()
    same_mesh = mesh1.id() == bdries2.mesh().id()
    # We assume that the shared surface is on the boundary, duh :). So
    # the idea is to basically do an L^2 projection of expr onto the trace
    # space of V on the interface
    ds_ = Measure('ds', domain=mesh1, subdomain_data=bdries1)
    # Rhs of the projection problem that we will need to restrict
    v = TestFunction(V)
    b = assemble(inner(v, expr) * ds_(tag))
    b_norm = b.norm('l2')
    # The trace space is
    interface = EmbeddedMesh(bdries1, tag)
    not same_mesh and interface.compute_embedding(
        bdries2, tag, tol)  # Fails if the meshes are far apart
    # The trace space
    TV = trace_space(V, interface)

    Tb = Function(TV).vector()
    # Restrict
    Rmat = trace_matrix(V, TV, interface)
    Rmat.mult(b, Tb)
    Tb_norm = Tb.norm('l2')
    # Lhs of the projection problem
    u, v = TrialFunction(TV), TestFunction(TV)
    M = assemble(inner(u, v) * dx)
    # Project
    Texpr = Function(TV)  # Trace of the expression (sort of)
    solve(M, Texpr.vector(), Tb)
    # Finally we extend this to V(mesh2). NOTE: it is pretty much only
    # on the interface where the result makes some sense
    mesh2 = bdries2.mesh()

    if not same_mesh:
        V2 = FunctionSpace(mesh2,
                           V.ufl_element().reconstruct(cell=mesh2.ufl_cell()))
        Rmat = trace_matrix(V2, TV, interface)
    else:
        # Already have Rmat
        V2 = V
    u2 = Function(V2)
    # Extend
    Rmat.transpmult(Texpr.vector(), u2.vector())

    ds_ = Measure('ds', domain=mesh2, subdomain_data=bdries2)
    c = assemble(inner(TestFunction(V2), u2) * ds_(tag))
    c_norm = c.norm('l2')

    info('Transfer |b|->|Tb|->|ETb| = %g %g %g' % (b_norm, Tb_norm, c_norm))

    return u2
Example #3
0
# work is
#
#     us -> take is trace Tus -> extend to fluid -> compute the stress there
#
# You'll that this does not work and the work around is to take trace of
# stresses and extend those
from sleep.utils import EmbeddedMesh, trace_matrix
from dolfin import *

fs_domain = UnitSquareMesh(128, 128)
cell_f = MeshFunction('size_t', fs_domain, 2, 1)
CompiledSubDomain('x[0] > 0.5 - DOLFIN_EPS').mark(cell_f, 2)

dx_fs = Measure('dx', domain=fs_domain, subdomain_data=cell_f)

fluid = EmbeddedMesh(cell_f, 1)
solid = EmbeddedMesh(cell_f, 2)

# We take fluid domain and master and define interaface wrt to it
fluid_facets = MeshFunction('size_t', fluid, 1, 0)
CompiledSubDomain('near(x[0], 0.5)').mark(fluid_facets, 1)
# Corresponding suraface integral
dI_f = Measure('ds', domain=fluid, subdomain_data=fluid_facets, subdomain_id=1)
# Fluid is master
interface = EmbeddedMesh(fluid_facets, 1)

solid_facets = MeshFunction('size_t', solid, 1, 0)
CompiledSubDomain('near(x[0], 0.5)').mark(solid_facets, 2)
# Corresponding suraface integral
dI_s = Measure('ds', domain=solid, subdomain_data=solid_facets, subdomain_id=2)
Example #4
0
    u = Function(V)
    n = Constant((1, 0))

    subs = {u: sp.Matrix([sp.sin(x**2 + y**2), sp.cos(x**2 - 3 * y**2)])}
    displacement = ulfy.Expression(u, subs=subs, degree=2)
    stress = ulfy.Expression(sym(grad(u)), subs=subs, degree=2)
    traction = ulfy.Expression(dot(n, sym(grad(u))), subs=subs, degree=2)
    traction_n = ulfy.Expression(dot(n, dot(n, sym(grad(u)))),
                                 subs=subs,
                                 degree=2)
    displacement_n = ulfy.Expression(dot(u, n) * n, subs=subs, degree=2)

    cell_f = MeshFunction('size_t', mesh, 2, 2)
    CompiledSubDomain('x[0] < 0.5+DOLFIN_EPS').mark(cell_f, 1)

    left = EmbeddedMesh(cell_f, 1)
    left_bdries = MeshFunction('size_t', left, 1, 0)
    CompiledSubDomain('near(x[0], 0.5)').mark(left_bdries, 1)

    right = EmbeddedMesh(cell_f, 2)
    right_bdries = MeshFunction('size_t', right, 1, 0)
    CompiledSubDomain('near(x[0], 0.5)').mark(right_bdries, 1)

    # Visual inspection - collect interface midpoints
    _, f2v = (left.init(1, 0), left.topology()(1, 0))
    idx, = np.where(left_bdries.array() == 1)

    midpoints = np.mean(left.coordinates()[np.row_stack([f2v(i)
                                                         for i in idx])],
                        axis=1)
    midpoints = midpoints[np.argsort(midpoints[:, 1])]
Example #5
0
def foo(n):
    mesh = UnitSquareMesh(n, n)
    V = VectorFunctionSpace(mesh, 'CG', 2)

    x, y = sp.symbols('x y')
    u = Function(V)
    n = Constant((1, 0))

    subs = {u: sp.Matrix([sp.sin(x**2 + y**2), sp.cos(x**2 - 3 * y**2)])}
    displacement = ulfy.Expression(u, subs=subs, degree=2)
    stress = ulfy.Expression(sym(grad(u)), subs=subs, degree=2)
    traction = ulfy.Expression(dot(n, sym(grad(u))), subs=subs, degree=2)

    cell_f = MeshFunction('size_t', mesh, 2, 2)
    CompiledSubDomain('x[0] < 0.5+DOLFIN_EPS').mark(cell_f, 1)

    left = EmbeddedMesh(cell_f, 1)
    left_bdries = MeshFunction('size_t', left, 1, 0)
    CompiledSubDomain('near(x[0], 0.5)').mark(left_bdries, 1)

    interface = EmbeddedMesh(left_bdries, 1)

    right = EmbeddedMesh(cell_f, 2)
    right_bdries = MeshFunction('size_t', right, 1, 0)
    CompiledSubDomain('near(x[0], 0.5)').mark(right_bdries, 2)
    # Don't redefine!
    interface.compute_embedding(right_bdries, 2)

    # Okay so let's be on left with displacement
    V = VectorFunctionSpace(left, 'CG', 2)
    u = interpolate(displacement, V)
    # Is this a way to compute the stress?
    Q = VectorFunctionSpace(left, 'DG', 1)
    q = TestFunction(Q)  # Use DG1?
    n = FacetNormal(left)

    expr = dot(sym(grad(u)), n)
    ds_ = Measure('ds', domain=left, subdomain_data=left_bdries)
    b = assemble(inner(expr, q) * ds_(1))

    # This
    B = VectorFunctionSpace(interface, 'DG',
                            1)  # Match the test function of form
    MTb = Function(B)
    trace_matrix(Q, B, interface).mult(b, MTb.vector())
    # Now y is in the dual. we need it back
    x = Function(B)
    M = assemble(inner(TrialFunction(B), TestFunction(B)) * dx)
    solve(M, x.vector(), MTb.vector())
    # x is now expr|_interface

    print assemble(inner(x - traction, x - traction) * dx)

    # What I want to do next is to extend it to right domain so that
    # if I there perform surface integral over the interface I get close
    # to what the left boundary said

    R = VectorFunctionSpace(right, 'DG', 1)
    extend = Function(R)
    trace_matrix(R, B, interface).transpmult(x.vector(), extend.vector())

    import matplotlib.pyplot as plt

    xx = np.sort([cell.midpoint().array()[1] for cell in cells(interface)])

    yy = np.array([x(0.5, xxi)[0] for xxi in xx])
    zz = np.array([traction(0.5, xxi)[0] for xxi in xx])
    rr = np.array([extend(0.5, xxi)[0] for xxi in xx])

    plt.figure()
    plt.plot(xx, yy, label='num')
    plt.plot(xx, zz, label='true')
    plt.plot(xx, rr, label='rec')
    plt.legend()
    plt.show()
Example #6
0
    return df.PETScMatrix(mat)

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

if __name__ == '__main__':
    from sleep.utils import EmbeddedMesh
    from sleep.utils import transpose_matrix
    from dolfin import *
    
    fs_domain = UnitSquareMesh(32, 32)
    cell_f = MeshFunction('size_t', fs_domain, 2, 1)
    CompiledSubDomain('x[0] > 0.5 - DOLFIN_EPS').mark(cell_f, 2)

    dx_fs = Measure('dx', domain=fs_domain, subdomain_data=cell_f)
    
    fluid = EmbeddedMesh(cell_f, 1)
    solid = EmbeddedMesh(cell_f, 2)

    u = Expression('x[0]+2*x[1]', degree=1)
    # Test putting scalar to subdomain -------------------------------
    FS = FunctionSpace(fs_domain, 'CG', 1)
    u_fs = interpolate(u, FS)
    # The subdomain space
    F = FunctionSpace(fluid, 'CG', 1)

    R = restriction_matrix(FS, F, fluid)
    # Now we can tranport
    u_f = Function(F)
    R.mult(u_fs.vector(), u_f.vector())

    e = inner(u_f - u, u_f - u)*dx  # Implied, fluid
Example #7
0
from dolfin import *
import numpy as np


class Foo(Expression):
    def eval_cell(self, values, x, ufc_cell):
        values[0] = ufc_cell.index


f = Foo(degree=0)

mesh = UnitSquareMesh(32, 32)
facet_f = MeshFunction('size_t', mesh, 1, 0)

DomainBoundary().mark(facet_f, 1)
Tmesh = EmbeddedMesh(facet_f, 1)

V = FunctionSpace(mesh, 'DG', 1)
u = interpolate(f, V)

TV = FunctionSpace(Tmesh, 'DG', 1)
Tu = Function(TV)
trace_matrix(V, TV, Tmesh).mult(u.vector(), Tu.vector())

assert assemble(inner(f - Tu, f - Tu) * ds) < 1E-13


# What if it is discontinuous in vertices
class Foo(Expression):
    def eval_cell(self, values, x, ufc_cell):
        values[0] = ufc_cell.index + np.linalg.norm(x)
Example #8
0
def PVSbrain_simulation(args):
    """ Test case for simple diffusion from PVS to the brain. 
    Outputs :
    - a logfile with information about the simulation
    - .pvd files at specified args.toutput time period with the u, p and c fields in stokes domain and u, p , q, phi and c fields in Biot domain
    - .csv files of u, p, c 1D array of the u, p, c fields on the middle line of the PVS 
    - .csv files of the total mass in the domain, mass flux from the brain to sas, brain to PVS, PVS to SAS

    """

    # output folder name
    outputfolder = args.output_folder + '/' + args.job_name + '/'

    if not os.path.exists(outputfolder):
        os.makedirs(outputfolder)

    if not os.path.exists(outputfolder + '/fields'):
        os.makedirs(outputfolder + '/fields')

    # Create output files
    #pvd files
    c_out = File(outputfolder + 'fields' + '/c.pvd')

    facets_out_fluid = File(outputfolder + 'fields' + '/facets_fluid.pvd')
    facets_out_solid = File(outputfolder + 'fields' + '/facets_solid.pvd')

    # Create logger
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    # log to a file
    now = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = os.path.join(outputfolder + '/', 'PVSBrain_info.log')
    file_handler = logging.FileHandler(filename, mode='w')
    file_handler.setLevel(logging.INFO)
    #formatter = logging.Formatter("%(asctime)s %(filename)s, %(lineno)d, %(funcName)s: %(message)s")
    #file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    # log to the console
    console_handler = logging.StreamHandler()
    level = logging.INFO
    console_handler.setLevel(level)
    logger.addHandler(console_handler)

    # initialise logging

    logging.info(
        title1(
            "Test case of simple diffusion from PVS to the brain using the diffusion-advection solver"
        ))

    logging.info("Date and time:" +
                 datetime.now().strftime("%m/%d/%Y, %H:%M:%S"))

    logging.info('Job name : ' + args.job_name)

    logging.debug('logging initialized')

    # Set parameters

    logging.info(title1("Parameters"))

    # Geometry params
    logging.info('\n * Geometry')
    Rv = args.radius_vessel  # centimeters
    Rpvs = args.radius_pvs  # centimeters
    Rbrain = args.radius_brain  # centimeters
    L = args.length  # centimeters

    logging.info('Vessel radius : %e cm' % Rv)
    logging.info('PVS radius : %e cm' % Rpvs)
    logging.info('Brain radius : %e cm' % Rbrain)
    logging.info('length : %e cm' % L)

    #Mesh
    logging.info('\n * Mesh')
    #number of cells in the radial direction fluid domain
    Nr = args.N_radial_fluid
    #number of cells in the radial direction biot domain
    Nr_biot = args.N_radial_biot
    s_biot = args.biot_progression

    DR = (Rpvs - Rv) / Nr
    #number of cells in the axial direction
    if args.N_axial:
        Nl = args.N_axial
    else:
        Nl = round(L / DR)

    DY = L / Nl

    logging.info('N axial: %i' % Nl)
    logging.info('N radial PVS: %e' % Nr)
    logging.info('N radial Biot: %e' % Nr_biot)
    logging.info('progression parameter in biot: %e' % s_biot)

    #time parameters
    logging.info('\n * Time')
    toutput = args.toutput
    tfinal = args.tend
    dt = args.time_step

    logging.info('final time: %e s' % tfinal)
    logging.info('output period : %e s' % toutput)
    logging.info('time step : %e s' % dt)

    dt_advdiff = dt

    logging.info('\n* Tracer properties')
    D = args.diffusion_coef
    sigma_gauss = args.sigma
    logging.info('Free diffusion coef: %e cm2/s' % D)
    logging.info('STD of initial gaussian profile: %e ' % sigma_gauss)
    xi_gauss = args.initial_pos
    logging.info('Initial position: %e cm2' % xi_gauss)

    logging.info('\n * Porous medium properties')

    porosity_0 = args.biot_porosity
    tortuosity = args.biot_tortuosity

    dt_solid = dt

    logging.info('initial porosity: %e ' % porosity_0)
    logging.info('tortuosity: %e ' % tortuosity)

    ## The tracer is solver in the full domain, so it has two subdomains
    # 1 for solid
    # 0 for fluid

    tracer_parameters = {
        'kappa_0': D,
        'kappa_1': D * tortuosity,
        'dt': dt_advdiff,
        'nsteps': 1
    }

    # Mesh
    logging.info(title1('Meshing'))

    meshing = args.mesh_method

    ##### Meshing method : regular

    if meshing == 'regular':
        # Create a mesh using Rectangle mesh : all the cells are regulars but this means a lot of cells

        logging.info('cell size : %e cm' % (np.sqrt(DR**2 + DY**2)))

        # Create a rectangle mesh with Nr + Nsolid cells in the radias direction and Nl cells in the axial direction
        # the geometrical progression for the solid mesh is s

        #Creation of the uniform mesh
        Rext = 1 + Nr_biot / Nr
        mesh = RectangleMesh(Point(0, 0), Point(L, Rext), Nl, Nr + Nr_biot)
        x = mesh.coordinates()[:, 0]
        y = mesh.coordinates()[:, 1]

        #Deformation of the mesh

        def deform_mesh(x, y):
            transform_fluid = Rv + (Rpvs - Rv) * y
            transform_solid = Rpvs + (Rbrain - Rpvs) * ((y - 1) /
                                                        (Rext - 1))**s_biot
            yp = np.where(y <= 1, transform_fluid, transform_solid)
            return [x, yp]

        x_bar, y_bar = deform_mesh(x, y)
        xy_bar_coor = np.array([x_bar, y_bar]).transpose()
        mesh.coordinates()[:] = xy_bar_coor
        mesh.bounding_box_tree().build(mesh)

    else:

        ##### Meshing method : gmsh with box for refinement

        from sleep.mesh import mesh_model2d, load_mesh2d, set_mesh_size
        import sys

        gmsh.initialize(['', '-format', 'msh2'])

        model = gmsh.model

        import math
        Apvs0 = math.pi * Rpvs**2
        Av0 = math.pi * Rv**2
        A0 = Apvs0 - Av0

        # progressive mesh
        factory = model.occ
        a = factory.addPoint(0, Rv, 0)
        b = factory.addPoint(L, Rv, 0)
        c = factory.addPoint(L, Rpvs, 0)
        d = factory.addPoint(0, Rpvs, 0)
        e = factory.addPoint(L, Rbrain, 0)
        f = factory.addPoint(0, Rbrain, 0)

        fluid_lines = [
            factory.addLine(*p) for p in ((a, b), (b, c), (c, d), (d, a))
        ]
        named_lines = dict(
            zip(('bottom', 'pvs_right', 'interface', 'pvs_left'), fluid_lines))

        fluid_loop = factory.addCurveLoop(fluid_lines)
        fluid = factory.addPlaneSurface([fluid_loop])

        solid_lines = [
            factory.addLine(*p) for p in ((d, c), (c, e), (e, f), (f, d))
        ]
        named_lines.update(
            dict(
                zip(('interface', 'brain_right', 'brain_top', 'brain_left'),
                    solid_lines)))

        solid_loop = factory.addCurveLoop(solid_lines)
        solid = factory.addPlaneSurface([solid_loop])

        factory.synchronize()

        tags = {'cell': {'F': 1, 'S': 2}, 'facet': {}}

        model.addPhysicalGroup(2, [fluid], 1)
        model.addPhysicalGroup(2, [solid], 2)

        for name in named_lines:
            tag = named_lines[name]
            model.addPhysicalGroup(1, [tag], tag)

        # boxes for mesh refinement
        cell_size = DR * (Rpvs - Rv) / (Rpvs - Rv)
        boxes = []
        # add box on the PVS for mesh
        field = model.mesh.field

        fid = 1
        field.add('Box', fid)
        field.setNumber(fid, 'XMin', 0)
        field.setNumber(fid, 'XMax', L)
        field.setNumber(fid, 'YMin', Rv)
        field.setNumber(fid, 'YMax', Rpvs)
        field.setNumber(fid, 'VIn', cell_size * 2)
        field.setNumber(fid, 'VOut', DR * 50)
        field.setNumber(fid, 'Thickness', (Rpvs - Rv) / 4)

        boxes.append(fid)

        # Combine
        field.add('Min', fid + 1)
        field.setNumbers(fid + 1, 'FieldsList', boxes)
        field.setAsBackgroundMesh(fid + 1)

        model.occ.synchronize()

        h5_filename = outputfolder + '/mesh.h5'

        mesh_model2d(model, tags, h5_filename)

        mesh, markers, lookup = load_mesh2d(h5_filename)

        from IPython import embed
        embed()

        gmsh.finalize()

    ## Define subdomains

    x = mesh.coordinates()[:, 0]
    y = mesh.coordinates()[:, 1]

    tol = 1e-7

    class Omega_0(SubDomain):
        def inside(self, x, on_boundary):
            return x[1] < Rpvs + tol

    class Omega_1(SubDomain):
        def inside(self, x, on_boundary):
            return x[1] > Rpvs - tol

    subdomains = MeshFunction("size_t", mesh, mesh.topology().dim(), 0)

    subdomain_0 = Omega_0()
    subdomain_1 = Omega_1()
    subdomain_0.mark(subdomains, 0)
    subdomain_1.mark(subdomains, 1)

    mesh_f = EmbeddedMesh(subdomains, 0)
    mesh_s = EmbeddedMesh(subdomains, 1)

    ## Define boundaries
    solid_bdries = MeshFunction("size_t", mesh_s,
                                mesh_s.topology().dim() - 1, 0)
    fluid_bdries = MeshFunction("size_t", mesh_f,
                                mesh_f.topology().dim() - 1, 0)
    full_bdries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0)

    # Label facets

    class Boundary_left_fluid(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[0], 0, tol) and (x[1] <= Rpvs + tol
                                                           )  #left fluid

    class Boundary_right_fluid(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[0], L, tol) and (x[1] <= Rpvs + tol
                                                           )  # right fluid

    class Boundary_left_solid(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[0], 0, tol) and (x[1] >= Rpvs - tol
                                                           )  #left solid

    class Boundary_right_solid(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[0], L, tol) and (x[1] >= Rpvs - tol
                                                           )  # right solid

    class Boundary_bottom(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[1], Rv, tol)  #bottom

    class Boundary_top(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[1], Rbrain, tol)  #top

    class Boundary_interface(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and near(x[1], Rpvs, tol)  #interface

    #todo : keep separate F and S for right and left in the full bdries

    btop = Boundary_top()
    bbottom = Boundary_bottom()
    bleft_fluid = Boundary_left_fluid()
    bright_fluid = Boundary_right_fluid()
    bleft_solid = Boundary_left_solid()
    bright_solid = Boundary_right_solid()
    binterface = Boundary_interface()

    bbottom.mark(fluid_bdries, 2)
    binterface.mark(fluid_bdries, 4)
    bleft_fluid.mark(fluid_bdries, 1)
    bright_fluid.mark(fluid_bdries, 3)

    binterface.mark(solid_bdries, 4)
    bright_solid.mark(solid_bdries, 5)
    btop.mark(solid_bdries, 6)
    bleft_solid.mark(solid_bdries, 7)

    bleft_fluid.mark(full_bdries, 1)
    bleft_solid.mark(full_bdries, 7)
    bbottom.mark(full_bdries, 2)
    bright_fluid.mark(full_bdries, 3)
    bright_solid.mark(full_bdries, 5)
    btop.mark(full_bdries, 6)

    facet_lookup = {
        'F_left': 1,
        'F_bottom': 2,
        'F_right': 3,
        'Interface': 4,
        'S_left': 7,
        'S_top': 6,
        'S_right': 5
    }

    facets_out_fluid << fluid_bdries

    facets_out_solid << solid_bdries

    # define the domain specific parameters for the tracer
    # NOTE: Here we do P0 projection
    dx = Measure('dx', domain=mesh, subdomain_data=subdomains)
    CoefSpace = FunctionSpace(mesh, 'DG', 0)
    q = TestFunction(CoefSpace)

    # Remove
    coef = 'kappa'

    fluid_coef = tracer_parameters.pop('%s_0' % coef)
    solid_coef = tracer_parameters.pop('%s_1' % coef)

    form = ((1 / CellVolume(mesh)) * fluid_coef * q * dx(0) +
            (1 / CellVolume(mesh)) * solid_coef * q * dx(1))

    tracer_parameters[coef] = Function(CoefSpace, assemble(form))

    #FEM space

    logging.info(title1("Set FEM spaces"))

    logging.info('\n * Tracer')
    #### Todo : I would like to be able to have discontinuous concentration when we will have the membrane
    #### Beter to solve in two domains or one domain with discontinuous lagrange element ?
    Ct_elm = FiniteElement('Lagrange', triangle, 1)
    Ct = FunctionSpace(mesh, Ct_elm)
    logging.info('Concentration : "Lagrange", triangle, 1')

    #Advection velocity
    FS_advvel = VectorFunctionSpace(mesh, 'CG', 2)

    # Setup of boundary conditions
    logging.info(title1("Boundary conditions"))

    ## to do : allow zero concentration if fluid BC is free on the right
    logging.info('\n * Tracer concentration')

    bcs_tracer = {
        'concentration': [(facet_lookup['S_top'], Constant(0))],
        'flux': [
            (facet_lookup['S_left'], Constant(0)),
            (facet_lookup['S_right'], Constant(0)),
            (facet_lookup['F_right'], Constant(0)),
            (facet_lookup['F_left'], Constant(0)),
            (facet_lookup['F_bottom'], Constant(0)),
        ]
    }

    # Initialisation :

    # 1 in the PVS
    cf_0 = Expression('x[1]<= Rpvs ? 1 : 0 ',
                      degree=2,
                      a=1 / 2 / sigma_gauss**2,
                      b=xi_gauss,
                      Rv=Rv,
                      Rpvs=Rpvs)

    c_n = project(cf_0, Ct)  #

    File('initial_reg.pvd') << c_n
    exit()

    #Initial deformation of the fluid domain
    # We start at a time shift
    tshift = 0  #

    c_n.rename("c", "tmp")
    c_out << (c_n, 0)

    ############# RUN ############3

    logging.info(title1("Run"))

    # Time loop
    time = tshift
    timestep = 0

    # Here I dont know if there will be several dt for advdiff and fluid solver
    while time < tfinal + tshift:

        time += dt
        timestep += 1
        print('time', time - tshift)

        # Solve tracer problem

        tracer_parameters["T0"] = time

        advection_velocity = project(Constant((0, 0)), FS_advvel)

        c_, T0 = solve_adv_diff(Ct,
                                velocity=advection_velocity,
                                phi=Constant(0.2),
                                f=Constant(0),
                                c_0=c_n,
                                phi_0=Constant(0.2),
                                bdries=full_bdries,
                                bcs=bcs_tracer,
                                parameters=tracer_parameters)

        # Update current solution

        c_n.assign(c_)

        # Save output
        if (timestep % int(toutput / dt) == 0):

            logging.info("\n*** save output time %e s" % (time - tshift))
            logging.info("number of time steps %i" % timestep)

            # may report Courant number or other important values that indicate how is doing the run

            c_n.rename("c", "tmp")
            c_out << (c_n, time - tshift)

            advection_velocity.rename("adv_vel", "tmp")
            File(outputfolder + 'fields' +
                 '/adv_vel.pvd') << (advection_velocity, time - tshift)