Example #1
0
def computeVelocityField(mesh):
    Xh = dl.VectorFunctionSpace(mesh,'Lagrange', 2)
    Wh = dl.FunctionSpace(mesh, 'Lagrange', 1)
    if dlversion() <= (1,6,0):
        XW = dl.MixedFunctionSpace([Xh, Wh])
    else:
        mixed_element = dl.MixedElement([Xh.ufl_element(), Wh.ufl_element()])
        XW = dl.FunctionSpace(mesh, mixed_element)

    
    Re = 1e2
    
    g = dl.Expression(('0.0','(x[0] < 1e-14) - (x[0] > 1 - 1e-14)'), element=Xh.ufl_element())
    bc1 = dl.DirichletBC(XW.sub(0), g, v_boundary)
    bc2 = dl.DirichletBC(XW.sub(1), dl.Constant(0), q_boundary, 'pointwise')
    bcs = [bc1, bc2]
    
    vq = dl.Function(XW)
    (v,q) = dl.split(vq)
    (v_test, q_test) = dl.TestFunctions (XW)
    
    def strain(v):
        return dl.sym(dl.nabla_grad(v))
    
    F = ( (2./Re)*dl.inner(strain(v),strain(v_test))+ dl.inner (dl.nabla_grad(v)*v, v_test)
           - (q * dl.div(v_test)) + ( dl.div(v) * q_test) ) * dl.dx
           
    dl.solve(F == 0, vq, bcs, solver_parameters={"newton_solver":
                                         {"relative_tolerance":1e-4, "maximum_iterations":100,
                                          "linear_solver":"default"}})
        
    return v
def rhs(states, time, parameters, dy=None):
    """
    Compute right hand side
    """
    # Imports
    import ufl
    import dolfin

    # Assign states
    assert(isinstance(states, dolfin.Function))
    assert(states.function_space().depth() == 1)
    assert(states.function_space().num_sub_spaces() == 2)
    s, v = dolfin.split(states)

    # Assign parameters
    a, b, c_1, c_2, c_3, v_peak, v_rest = parameters
    v_amp = v_peak - v_rest
    v_th = v_rest + a*v_amp

    I = (v - v_rest)*(v - v_th)*(v_peak - v)*c_1/(v_amp*v_amp) - (v -\
        v_rest)*c_2*s/v_amp

    # Init test function
    _v = dolfin.TestFunction(states.function_space())

    # Derivative for state s
    dy = ((-c_3*s + v - v_rest)*b)*_v[0]

    # Derivative for state v
    dy += (I)*_v[1]

    dya = dolfin.assemble(dy*dolfin.dx)

    # Return dy
    return dy
Example #3
0
    def solve_system(self,rhs,factor,u0,t):
        """
        Dolfin's linear solver for (M-dtA)u = rhs

        Args:
            rhs: right-hand side for the nonlinear system
            factor: abbrev. for the node-to-node stepsize (or any other factor required)
            u0: initial guess for the iterative solver (not used here so far)

        Returns:
            solution as mesh
        """

        sol = fenics_mesh(self.V)

        # self.g.t = t
        self.w.assign(sol.values)

        q1,q2 = df.TestFunctions(self.V)
        w1,w2 = df.split(self.w)
        r1,r2 = df.split(rhs.values)
        F1 = w1*q1*df.dx - factor*self.F1 - r1*q1*df.dx
        F2 = w2*q2*df.dx - factor*self.F2 - r2*q2*df.dx
        F = F1+F2
        du = df.TrialFunction(self.V)
        J  = df.derivative(F, self.w, du)

        problem = df.NonlinearVariationalProblem(F, self.w, [], J)
        solver  = df.NonlinearVariationalSolver(problem)

        prm = solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-09
        prm['newton_solver']['relative_tolerance'] = 1E-08
        prm['newton_solver']['maximum_iterations'] = 100
        prm['newton_solver']['relaxation_parameter'] = 1.0

        # df.set_log_level(df.PROGRESS)

        solver.solve()

        sol.values.assign(self.w)

        return sol
Example #4
0
    def __init__(
            self, WPQ,
            kappa, rho, rho_const, mu, cp,
            g, extra_force,
            heat_source,
            u_bcs, p_bcs,
            theta_dirichlet_bcs=None,
            theta_neumann_bcs=None,
            theta_robin_bcs=None,
            my_dx=dx,
            my_ds=ds
            ):
        super(StokesHeat, self).__init__()

        theta_dirichlet_bcs = theta_dirichlet_bcs or {}
        theta_neumann_bcs = theta_neumann_bcs or {}
        theta_robin_bcs = theta_robin_bcs or {}

        # Translate the Dirichlet boundary conditions into the product space.
        self.dirichlet_bcs = helpers.dbcs_to_productspace(
            WPQ,
            [u_bcs, p_bcs, theta_dirichlet_bcs]
            )

        self.uptheta = Function(WPQ)
        u, p, theta = split(self.uptheta)
        v, q, zeta = TestFunctions(WPQ)

        mesh = WPQ.mesh()
        r = SpatialCoordinate(mesh)[0]

        # Right-hand side for momentum equation.
        f = rho(theta) * g  # coupling
        if extra_force is not None:
            f += as_vector((extra_force[0], extra_force[1], 0.0))
        self.stokes_F = stokes.F(
            u, p, v, q, f, r, mu, my_dx
            )

        self.heat_F = heat.F(
                theta, zeta,
                kappa=kappa, rho=rho_const, cp=cp,
                convection=u,  # coupling
                source=heat_source,
                r=r,
                neumann_bcs=theta_neumann_bcs,
                robin_bcs=theta_robin_bcs,
                my_dx=my_dx,
                my_ds=my_ds
                )

        self.F0 = self.stokes_F + self.heat_F
        self.jacobian = derivative(self.F0, self.uptheta)
        return
Example #5
0
  def solve(self, it=0):
    if self.group_GS:
      self.solve_group_GS(it)
    else:
      super(EllipticSNFluxModule, self).solve(it)
      self.slns_mg = split(self.sln)

    i,p,q,k1,k2 = ufl.indices(5)

    sol_timer = Timer("-- Complete solution")
    aux_timer = Timer("---- SOL: Computing angular flux + adjoint")

    # TODO: Move to Discretization
    V11 = FunctionSpace(self.DD.mesh, "CG", self.DD.parameters["p"])

    for gto in range(self.DD.G):
      self.PD.get_xs('D', self.D, gto)

      form = self.D * ufl.diag_vector(ufl.as_matrix(self.DD.ordinates_matrix[i,p]*self.slns_mg[gto][q].dx(i), (p,q)))

      for gfrom in range(self.DD.G):
        pres_Ss = False

        # TODO: Enlarge self.S and self.C to (L+1)^2 (or 1./2.*(L+1)*(L+2) in 2D) to accomodate for anisotropic
        # scattering (lines below using CC, SS are correct only for L = 0, when the following inner loop runs only
        # once.
        for l in range(self.L+1):
          for m in range(-l, l+1):
            if self.DD.angular_quad.get_D() == 2 and divmod(l+m, 2)[1] == 0:
              continue

            pres_Ss |= self.PD.get_xs('Ss', self.S[l], gto, gfrom, l)
            self.PD.get_xs('C', self.C[l], gto, gfrom, l)

        if pres_Ss:
          Cd = ufl.diag(self.C)
          CC = self.tensors.Y[p,k1] * Cd[k1,k2] * self.tensors.Qt[k2,q,i]

          form += ufl.as_vector(CC[p,q,i] * self.slns_mg[gfrom][q].dx(i), p)

      # project(form, self.DD.Vpsi1, function=self.aux_slng, preconditioner_type="petsc_amg")
      # FASTER, but requires form compilation for each dir.:
      for pp in range(self.DD.M):
        assign(self.aux_slng.sub(pp), project(form[pp], V11, preconditioner_type="petsc_amg"))

      self.psi_mg[gto].assign(self.slns_mg[gto] + self.aux_slng)
      self.adj_psi_mg[gto].assign(self.slns_mg[gto] - self.aux_slng)
Example #6
0
def numerical_test(
    user_parameters,
    ell=0.05,
    nu=0.,
):
    time_data = []
    time_data_pd = []
    spacetime = []
    lmbda_min_prev = 1e-6
    bifurcated = False
    bifurcation_loads = []
    save_current_bifurcation = False
    bifurc_i = 0
    bifurcation_loads = []

    # Create mesh and define function space
    geometry_parameters = {'Lx': 1., 'n': 5}

    # Define Dirichlet boundaries
    outdir = '../test/output/test_1dcheck'
    Path(outdir).mkdir(parents=True, exist_ok=True)


    with open('../parameters/form_compiler.yml') as f:
        form_compiler_parameters = yaml.load(f, Loader=yaml.FullLoader)

    with open('../parameters/solvers_default.yml') as f:
        solver_parameters = yaml.load(f, Loader=yaml.FullLoader)

    with open('../parameters/model1d.yaml') as f:
        material_parameters = yaml.load(f, Loader=yaml.FullLoader)['material']

    with open('../parameters/loading.yaml') as f:
        loading_parameters = yaml.load(f, Loader=yaml.FullLoader)['loading']

    with open('../parameters/stability.yaml') as f:
        stability_parameters = yaml.load(f, Loader=yaml.FullLoader)['stability']

    Path(outdir).mkdir(parents=True, exist_ok=True)

    print('Outdir is: '+outdir)

    default_parameters = {
        'code': {**code_parameters},
        'compiler': {**form_compiler_parameters},
        'geometry': {**geometry_parameters},
        'loading': {**loading_parameters},
        'material': {**material_parameters},
        'solver':{**solver_parameters},
        'stability': {**stability_parameters},
        }

    default_parameters.update(user_parameters)
    # FIXME: Not nice
    parameters = default_parameters

    with open(os.path.join(outdir, 'parameters.yaml'), "w") as f:
        yaml.dump(parameters, f, default_flow_style=False)

    Lx = parameters['geometry']['Lx']; 
    # Ly = parameters['geometry']['Ly']
    ell =  parameters['material']['ell']
    # comm = MPI.comm_world
    # geom = mshr.Rectangle(dolfin.Point(0, -Ly/2.), dolfin.Point(Lx, Ly/2.))
    # import pdb; pdb.set_trace()
    # resolution = max(geometry_parameters['n'] * Lx / ell, 1/(Ly*10))
    # resolution = max(geometry_parameters['n'] * Lx / ell, 5/(Ly*10))
    resolution = 50
    mesh = dolfin.IntervalMesh(3, 0, Lx)
    # mesh = dolfin.IntervalMesh(int(float(geometry_parameters['n'] * Lx / ell)), 0, Lx)
    meshf = dolfin.File(os.path.join(outdir, "mesh.xml"))
    meshf << mesh
    plot(mesh)
    plt.savefig(os.path.join(outdir, "mesh.pdf"), bbox_inches='tight')

    savelag = 1
    left = dolfin.CompiledSubDomain("near(x[0], 0)", Lx=Lx)
    right = dolfin.CompiledSubDomain("near(x[0], Lx)", Lx=Lx)
    # left_bottom_pt = dolfin.CompiledSubDomain("near(x[0],0) && near(x[1],-Ly/2.)", Lx=Lx, Ly=Ly)

    mf = dolfin.MeshFunction("size_t", mesh, 1, 0)
    right.mark(mf, 1)
    left.mark(mf, 2)

    ds = dolfin.Measure("ds", subdomain_data=mf)
    dx = dolfin.Measure("dx", metadata=form_compiler_parameters, domain=mesh)

    # Function Spaces
    V_u = dolfin.FunctionSpace(mesh, "CG", 1)
    V_alpha = dolfin.FunctionSpace(mesh, "CG", 1)
    u = dolfin.Function(V_u, name="Total displacement")
    alpha = Function(V_alpha)
    dalpha = TrialFunction(V_alpha)
    alpha_old = dolfin.Function(V_alpha)
    alpha_bif = dolfin.Function(V_alpha)
    alpha_bif_old = dolfin.Function(V_alpha)


    state = {'u': u, 'alpha': alpha}
    Z = dolfin.FunctionSpace(mesh, 
            dolfin.MixedElement([u.ufl_element(),alpha.ufl_element()]))
    z = dolfin.Function(Z)
    z2 = dolfin.Function(Z)
    dz = dolfin.TestFunction(Z)
    v, beta = dolfin.split(z)

    ut = dolfin.Expression("t", t=0.0, degree=0)
    bcs_u = [dolfin.DirichletBC(V_u, dolfin.Constant(0), left),
             dolfin.DirichletBC(V_u, ut, right),
             # dolfin.DirichletBC(V_u, (0, 0), left_bottom_pt, method="pointwise")
             ]

    # bcs_alpha_l = DirichletBC(V_alpha,  Constant(0.0), left)
    # bcs_alpha_r = DirichletBC(V_alpha, Constant(0.0), right)
    # bcs_alpha =[bcs_alpha_l, bcs_alpha_r]
    bcs_alpha = []

    bcs = {"damage": bcs_alpha, "elastic": bcs_u}

    # import pdb; pdb.set_trace()

    ell = parameters['material']['ell']

    # Problem definition
    # Problem definition
    k_res = parameters['material']['k_res']
    a = (1 - alpha) ** 2. + k_res
    w_1 = parameters['material']['sigma_D0'] ** 2 / parameters['material']['E']
    w = w_1 * alpha
    eps = u.dx(0)
    # lmbda0 = parameters['material']['E'] * parameters['material']['nu'] /(1. - parameters['material']['nu'])**2.
    mu0 = parameters['material']['E']/ 2.
    Wu = mu0 * inner(eps, eps)

    energy = a * Wu * dx + w_1 *( alpha + \
            parameters['material']['ell']** 2.* alpha.dx(0)**2.)*dx

    eps_ = variable(eps)
    sigma = diff(a * Wu, eps_)

    file_out = dolfin.XDMFFile(os.path.join(outdir, "output.xdmf"))
    file_out.parameters["functions_share_mesh"] = True
    file_out.parameters["flush_output"] = True
    file_postproc = dolfin.XDMFFile(os.path.join(outdir, "output_postproc.xdmf"))
    file_postproc.parameters["functions_share_mesh"] = True
    file_postproc.parameters["flush_output"] = True
    file_eig = dolfin.XDMFFile(os.path.join(outdir, "modes.xdmf"))
    file_eig.parameters["functions_share_mesh"] = True
    file_eig.parameters["flush_output"] = True
    file_bif = dolfin.XDMFFile(os.path.join(outdir, "bifurcation.xdmf"))
    file_bif.parameters["functions_share_mesh"] = True
    file_bif.parameters["flush_output"] = True
    file_bif_postproc = dolfin.XDMFFile(os.path.join(outdir, "bifurcation_postproc.xdmf"))
    file_bif_postproc.parameters["functions_share_mesh"] = True
    file_bif_postproc.parameters["flush_output"] = True


    solver = EquilibriumAM(energy, state, bcs, parameters=parameters['solver'])
    stability = StabilitySolver(energy, state, bcs, parameters = parameters['stability'])
    linesearch = LineSearch(energy, state)

    # load_steps = np.linspace(parameters['loading']['load_min'],
    #     parameters['loading']['load_max'],
    #     parameters['loading']['n_steps'])

    load_steps = [0.0, 1.0, 1.1]

    xs = np.linspace(0, parameters['geometry']['Lx'], 50)

    log(LogLevel.INFO, '====================== EVO ==========================')
    log(LogLevel.INFO, '{}'.format(parameters))

    for it, load in enumerate(load_steps):
        alpha_old.assign(alpha)
        log(LogLevel.CRITICAL, '====================== STEPPING ==========================')
        log(LogLevel.CRITICAL, 'CRITICAL: Solving load t = {:.2f}'.format(load))
        ut.t = load
        (time_data_i, am_iter) = solver.solve()

        # Second order stability conditions

        (stable, negev) = stability.solve(solver.damage.problem.lb)
        log(LogLevel.CRITICAL, 'Current state is{}stable'.format(' ' if stable else ' un'))

        # we postpone the update after the stability check
        solver.update()
        # if stable:
            # solver.update()
        # else:
            # perturbation_v    = stability.perturbation_v
            # perturbation_beta = stability.perturbation_beta
            # import pdb; pdb.set_trace()

            # h_opt, (hmin, hmax), energy_perturbations = linesearch.search(
            #     {'u': u, 'alpha':alpha, 'alpha_old':alpha_old},
            #     perturbation_v, perturbation_beta)

            # if h_opt != 0:
            #     save_current_bifurcation = True
            #     alpha_bif.assign(alpha)
            #     alpha_bif_old.assign(alpha_old)
            #     # admissible
            #     uval = u.vector()[:]     + h_opt * perturbation_v.vector()[:]
            #     aval = alpha.vector()[:] + h_opt * perturbation_beta.vector()[:]

            #     u.vector()[:] = uval
            #     alpha.vector()[:] = aval

            #     u.vector().vec().ghostUpdate()
            #     alpha.vector().vec().ghostUpdate()

            #     # import pdb; pdb.set_trace()
            #     (time_data_i, am_iter) = solver.solve()
            #     (stable, negev) = stability.solve(alpha_old)
            #     ColorPrint.print_pass('    Continuation iteration {}, current state is{}stable'.format(iteration, ' ' if stable else ' un'))
            #     iteration += 1

            # else:
            #     # warn
            #     ColorPrint.print_warn('WARNING: Found zero increment, we are stuck in the matrix')
                # log(LogLevel.WARNING, 'WARNING: Continuing load program')
                # break

        mineig = stability.mineig if hasattr(stability, 'mineig') else 0.0
        Deltav = (mineig-lmbda_min_prev) if hasattr(stability, 'eigs') else 0

        if (mineig + Deltav)*(lmbda_min_prev+dolfin.DOLFIN_EPS) < 0 and not bifurcated:
            bifurcated = True

            # save 3 bif modes
            log(LogLevel.CRITICAL, 'About to bifurcate load {} step {}'.format(load, it))
            bifurcation_loads.append(load)
            modes = np.where(stability.eigs < 0)[0]

            with dolfin.XDMFFile(os.path.join(outdir, "postproc.xdmf")) as file:
                leneigs = len(modes)
                maxmodes = min(3, leneigs)
                for n in range(maxmodes):
                    mode = dolfin.project(stability.linsearch[n]['beta_n'], V_alpha)
                    modename = 'beta-%d'%n
                    print(modename)
                    file.write_checkpoint(mode, modename, 0, append=True)

            bifurc_i += 1

        lmbda_min_prev = mineig if hasattr(stability, 'mineig') else 0.


        time_data_i["load"] = load
        time_data_i["alpha_max"] = max(alpha.vector()[:])
        time_data_i["elastic_energy"] = dolfin.assemble(
            1./2.* material_parameters['E']*a*eps**2. *dx)
        time_data_i["dissipated_energy"] = dolfin.assemble(
    # e1 = dolfin.Constant([1, 0])
            (w + w_1 * material_parameters['ell'] ** 2. * alpha.dx(0)**2.)*dx)
        time_data_i["stable"] = stability.stable
        time_data_i["# neg ev"] = stability.negev
        time_data_i["eigs"] = stability.eigs if hasattr(stability, 'eigs') else np.inf

        # snn = dolfin.dot(dolfin.dot(sigma, e1), e1)
        time_data_i["sigma"] = dolfin.assemble(a*mu0*eps*ds(1))

        log(LogLevel.INFO,
            "Load/time step {:.4g}: iteration: {:3d}, err_alpha={:.4g}".format(
                time_data_i["load"],
                time_data_i["iterations"][0],
                time_data_i["alpha_error"][0]))

        time_data.append(time_data_i)
        time_data_pd = pd.DataFrame(time_data)

        if np.mod(it, savelag) == 0:
            with file_out as f:
                f.write(alpha, load)
                f.write(u, load)
            with file_postproc as f:
                f.write_checkpoint(alpha, "alpha-{}".format(it), 0, append = True)
                log(LogLevel.PROGRESS, 'PROGRESS: written step {}'.format(it))

        if save_current_bifurcation == True:
            with file_eig as f:
                _v = dolfin.project(dolfin.Constant(h_opt)*perturbation_v, V_u)
                _beta = dolfin.project(dolfin.Constant(h_opt)*perturbation_beta, V_alpha)
                _v.rename('perturbation displacement', 'perturbation displacement')
                _beta.rename('perturbation damage', 'perturbation damage')
                # import pdb; pdb.set_trace()
                f.write(_v, load)
                f.write(_beta, load)
                f.write_checkpoint(_v, 'perturbation_v', 0, append=True)
                f.write_checkpoint(_beta, 'perturbation_beta', 0, append=True)

            time_data_pd.to_json(os.path.join(outdir, "time_data.json"))

        spacetime.append([alpha(x) for x in xs])


        if save_current_bifurcation:
            # modes = np.where(stability.eigs < 0)[0]

            time_data_i['h_opt'] = h_opt
            time_data_i['max_h'] = hmax
            time_data_i['min_h'] = hmin

            with file_bif_postproc as file:
                # leneigs = len(modes)
                # maxmodes = min(3, leneigs)
                beta0v = dolfin.project(stability.perturbation_beta, V_alpha)
                log(LogLevel.DEBUG, 'DEBUG: irrev {}'.format(alpha.vector()-alpha_old.vector()))
                file.write_checkpoint(beta0v, 'beta0', 0, append = True)
                file.write_checkpoint(alpha_bif_old, 'alpha-old', 0, append=True)
                file.write_checkpoint(alpha_bif, 'alpha-bif', 0, append=True)
                file.write_checkpoint(alpha, 'alpha', 0, append=True)

                np.save(os.path.join(outdir, 'energy_perturbations'), energy_perturbations, allow_pickle=True, fix_imports=True)

            with file_eig as file:
                _v = dolfin.project(dolfin.Constant(h_opt)*perturbation_v, V_u)
                _beta = dolfin.project(dolfin.Constant(h_opt)*perturbation_beta, V_alpha)
                _v.rename('perturbation displacement', 'perturbation displacement')
                _beta.rename('perturbation damage', 'perturbation damage')
                # import pdb; pdb.set_trace()
                f.write(_v, load)
                f.write(_beta, load)

    _spacetime = pd.DataFrame(spacetime)
    spacetime = _spacetime.fillna(0)
    mat = np.matrix(spacetime)
    plt.imshow(mat, cmap = 'Greys', vmin = 0., vmax = 1., aspect=.1)
    plt.colorbar()

    def format_space(x, pos, xresol = 100):
        return '$%1.1f$'%((-x+xresol/2)/xresol)

    def format_time(t, pos, xresol = 100):
        return '$%1.1f$'%((t-parameters['loading']['load_min'])/parameters['loading']['n_steps']*parameters['loading']['load_max'])

    from matplotlib.ticker import FuncFormatter, MaxNLocator

    ax = plt.gca()

    ax.yaxis.set_major_formatter(FuncFormatter(format_space))
    ax.xaxis.set_major_formatter(FuncFormatter(format_time))

    plt.xlabel('$x$')
    plt.ylabel('$t$')
    plt.savefig(os.path.join(outdir, "spacetime.pdf".format(load)), bbox_inches="tight")

    spacetime.to_json(os.path.join(outdir + "/spacetime.json"))

    from matplotlib.ticker import FuncFormatter, MaxNLocator
    plot(alpha)
    plt.savefig(os.path.join(outdir, 'alpha.pdf'))
    log(LogLevel.INFO, "Saved figure: {}".format(os.path.join(outdir, 'alpha.pdf')))


    xs = np.linspace(0, Lx, 100)
    profile = np.array([alpha(x) for x in xs])
    plt.figure()
    plt.plot(xs, profile, marker='o')
    plt.plot(xs, np.array([u(x) for x in xs]))
    # plt.ylim(0., 1.)
    plt.savefig(os.path.join(outdir, 'profile.pdf'))

    return time_data_pd, outdir
def RunJob(Tb, mu_value, path):
    runtimeInit = clock()

    tfile = File(path + '/t6t.pvd')
    mufile = File(path + "/mu.pvd")
    ufile = File(path + '/velocity.pvd')
    gradpfile = File(path + '/gradp.pvd')
    pfile = File(path + '/pstar.pvd')
    parameters = open(path + '/parameters', 'w', 0)
    vmeltfile = File(path + '/vmelt.pvd')
    rhofile = File(path + '/rhosolid.pvd')

    for name in dir():
        ev = str(eval(name))
        if name[0] != '_' and ev[0] != '<':
            parameters.write(name + ' = ' + ev + '\n')

    temp_values = [27. + 273, Tb + 273, 1300. + 273, 1305. + 273]
    dTemp = temp_values[3] - temp_values[0]
    temp_values = [x / dTemp for x in temp_values]  # non dimensionalising temp

    mu_a = mu_value  # this was taken from the blankenbach paper, can change..
    
    Ep = b / dTemp

    mu_bot = exp(-Ep * (temp_values[3] * dTemp - 1573) + cc) * mu_a

    Ra = rho_0 * alpha * g * dTemp * h**3 / (kappa_0 * mu_a)
    w0 = rho_0 * alpha * g * dTemp * h**2 / mu_a
    tau = h / w0
    p0 = mu_a * w0 / h

    print(mu_a, mu_bot, Ra, w0, p0)

    vslipx = 1.6e-09 / w0
    vslip = Constant((vslipx, 0.0))  # nondimensional
    noslip = Constant((0.0, 0.0))

    dt = 3.E11 / tau
    tEnd = 3.E13 / tau  # non-dimensionalising times

    class PeriodicBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return left(x, on_boundary)

        def map(self, x, y):
            y[0] = x[0] - MeshWidth
            y[1] = x[1]

    pbc = PeriodicBoundary()

    class TempExp(Expression):
        def eval(self, value, x):
            if x[1] >= LAB(x):
                value[0] = temp_values[0] + (temp_values[1] - temp_values[0]) * (MeshHeight - x[1]) / (MeshHeight - LAB(x))
            else:
                value[0] = temp_values[3] - (temp_values[3] - temp_values[2]) * (x[1]) / (LAB(x))

    class FluidTemp(Expression):
        def eval(self, value, x):
            if value[0] < 1295:
                value[0] = 1295

    mesh = RectangleMesh(Point(0.0, 0.0), Point(MeshWidth, MeshHeight), nx, ny)

    Svel = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc)
    Spre = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Stemp = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Smu = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    Sgradp = VectorFunctionSpace(mesh, 'CG', 2, constrained_domain=pbc)
    Srho = FunctionSpace(mesh, 'CG', 1, constrained_domain=pbc)
    S0 = MixedFunctionSpace([Svel, Spre, Stemp])

    u = Function(S0)
    v, p, T = split(u)
    v_t, p_t, T_t = TestFunctions(S0)

    T0 = interpolate(TempExp(), Stemp)

    muExp = Expression('exp(-Ep * (T_val * dTemp - 1573) + cc * x[2] / meshHeight)', Smu.ufl_element(),
                        Ep=Ep, dTemp=dTemp, cc=cc, meshHeight=MeshHeight, T_val=T0)

    mu = interpolate(muExp, Smu)

    rhosolid = Function(Srho)
    deltarho = Function(Srho)

    v0 = Function(Svel)
    vmelt = Function(Svel)

    v_theta = (1. - theta)*v0 + theta*v

    T_theta = (1. - theta)*T + theta*T0

    r_v = (inner(sym(grad(v_t)), 2.*mu*sym(grad(v))) \
        - div(v_t)*p \
        - T*v_t[1] )*dx

    r_p = p_t*div(v)*dx

    r_T = (T_t*((T - T0) \
        + dt*inner(v_theta, grad(T_theta))) \
        + (dt/Ra)*inner(grad(T_t), grad(T_theta)) )*dx
#           + k_s*(Tf-T_theta)*dt

    Tf = T0.interpolate(FluidTemp())
    # Tf = T0.interpolate(Expression('value[0] >= 1295.0 ? value[0] : 1295.0'))

    # Tf.interpolate(Expression('value[0] >= 1295 ? value[0] : 1295'))
    # project(Expression('value[0] >= 1295 ? value[0] : 1295'), Tf)
# Alex, a question for you:
# can you see if there is a way to set Tf = T in regions where T >=1295 celsius
#
# 1295 celsius is my arbitrary choice for the LAB isotherm.  In regions
# where T < 1295 C, set Tf to be some constant for now, such as 1295 C.
# Once we do this, then we can add in a term like that last line above where
# it will only be non-zero when the solid temperature, T, is cooler than 1295
# can you do this? After this is done, we will then worry about a calculation
# where we solve for Tf as a function of time in the regions cooler than 1295 C
# Makes sense?  If not, we can skype soon -- email me with questions
# 3/19/16
    r = r_v + r_p + r_T

    bcv0 = DirichletBC(S0.sub(0), noslip, top)
    bcv1 = DirichletBC(S0.sub(0), vslip, bottom)
    bcp0 = DirichletBC(S0.sub(1), Constant(0.0), bottom)
    bct0 = DirichletBC(S0.sub(2), Constant(temp_values[0]), top)
    bct1 = DirichletBC(S0.sub(2), Constant(temp_values[3]), bottom)

    bcs = [bcv0, bcv1, bcp0, bct0, bct1]

    t = 0
    count = 0
    while (t < tEnd):
        solve(r == 0, u, bcs)
        t += dt
        nV, nP, nT = u.split()
        gp = grad(nP)
        rhosolid = rho_0 * (1 - alpha * (nT * dTemp - 1573))
        deltarho = rhosolid - rhomelt
        yvec = Constant((0.0, 1.0))
        vmelt = nV * w0 - darcy * (gp * p0 / h - deltarho * yvec * g)
        if (count % 100 == 0):
            pfile << nP
            ufile << nV
            tfile << nT
            mufile << mu
            gradpfile << project(grad(nP), Sgradp)
            mufile << project(mu * mu_a, Smu)
            rhofile << project(rhosolid, Srho)
            vmeltfile << project(vmelt, Svel)
        count += 1
        assign(T0, nT)
        assign(v0, nV)
        mu.interpolate(muExp)

    print('Case mu=%g, Tb=%g complete.' % (mu_a, Tb), ' Run time =', clock() - runtimeInit, 's')
Example #8
0
def main():

    pulse.annotation.annotate = True

    # Set up problem
    problem, material_control, activation_control = create_problem()

    disp_file = dolfin.XDMFFile("displacement.xdmf")
    (U, P) = problem.state.split(deepcopy=True)
    disp_file.write_checkpoint(U, "displacement", 0,
                               dolfin.XDMFFile.Encoding.HDF5, False)

    computed_volumes = [problem.geometry.cavity_volume()]

    # Create volume observersion
    endo = problem.geometry.markers["ENDO"][0]
    volume_model = pulse_adjoint.model_observations.VolumeObservation(
        problem.geometry.mesh, problem.geometry.ds(endo))

    passive_volume_data = [2.511304019359619, 2.8]
    active_volume_data = [2.8, 1.5, 1.2, 1.2, 2.8]
    volume_data = passive_volume_data + active_volume_data

    passive_pressure_data = [0, 0.1]
    active_pressure_data = [1.0, 1.2, 1.0, 0.05, 0.1]
    pressure_data = passive_pressure_data + active_pressure_data

    if 0:
        fig, ax = plt.subplots()
        ax.plot(volume_data, pressure_data)
        ax.set_xlabel("Volume [ml]")
        ax.set_ylabel("Pressure [kPa]")
        plt.show()

    # ------------- Passive phase ----------------

    volume_target = pulse_adjoint.OptimizationTarget(passive_volume_data[1:],
                                                     volume_model)

    material_regularization = pulse_adjoint.Regularization(material_control,
                                                           weight=1e-4,
                                                           reg_type="L2")

    pressure_obs = pulse_adjoint.model_observations.BoundaryObservation(
        problem.bcs.neumann[0],
        passive_pressure_data[1:],
        start_value=passive_pressure_data[0],
    )

    assimilator = pulse_adjoint.Assimilator(
        problem,
        targets=[volume_target],
        bcs=pressure_obs,
        control=material_control,
        regularization=material_regularization,
    )

    optimal_control = assimilator.assimilate(min_value=0.1,
                                             max_value=10.0,
                                             tol=1e-6)

    material_control.vector()[:] = optimal_control.optimal_control
    dolfin.File("material.pvd") << material_control
    optimzed_material_paramter = optimal_control.optimal_control

    problem.solve()
    u, p = dolfin.split(problem.state)
    computed_volume = problem.geometry.cavity_volume(u=u)
    computed_volumes.append(computed_volume)
    print(f"Target volume: {passive_volume_data[-1]}")
    print(f"Model volume: {computed_volume}")
    print(f"Estimated activation parameters {optimzed_material_paramter}")

    (U, P) = problem.state.split(deepcopy=True)
    disp_file.write_checkpoint(U, "displacement", 1,
                               dolfin.XDMFFile.Encoding.HDF5, True)

    prev_pressure = passive_pressure_data[-1]
    activation_parameters = [0] * len(passive_pressure_data)

    # ------------- Active phase ----------------

    gamma_regularization = pulse_adjoint.Regularization(activation_control,
                                                        weight=1e-4,
                                                        reg_type="L2")

    gamma_file = dolfin.XDMFFile("activation.xdmf")
    gamma_file.write_checkpoint(activation_control, "gamma", 0,
                                dolfin.XDMFFile.Encoding.HDF5, False)

    for i, (volume, pressure) in enumerate(
            zip(active_volume_data, active_pressure_data), ):
        print(f"Try to fit volume : {volume} with pressure {pressure}")

        volume_target = pulse_adjoint.OptimizationTarget([volume],
                                                         volume_model)

        pressure_obs = pulse_adjoint.model_observations.BoundaryObservation(
            problem.bcs.neumann[0], [pressure], start_value=prev_pressure)

        assimilator = pulse_adjoint.Assimilator(
            problem,
            targets=[volume_target],
            bcs=pressure_obs,
            control=activation_control,
            regularization=gamma_regularization,
        )

        optimal_control = assimilator.assimilate(min_value=0.0,
                                                 max_value=0.3,
                                                 tol=0.01)

        activation_control.vector()[:] = optimal_control.optimal_control
        gamma_file.write_checkpoint(activation_control, "gamma", i + 1,
                                    dolfin.XDMFFile.Encoding.HDF5, True)
        problem.solve()
        u, p = dolfin.split(problem.state)
        computed_volume = problem.geometry.cavity_volume(u=u)
        computed_volumes.append(computed_volume)
        activation_parameters.append(optimal_control.optimal_control)

        print(f"Target volume: {volume}")
        print(f"Model volume: {computed_volume}")
        print(
            f"Estimated activation parameters {optimal_control.optimal_control}"
        )

        prev_pressure = pressure

        (U, P) = problem.state.split(deepcopy=True)
        disp_file.write_checkpoint(U, "displacement", i + 2,
                                   dolfin.XDMFFile.Encoding.HDF5, True)

    fig, ax = plt.subplots()
    ax.plot(volume_data, pressure_data, label="Data")
    ax.plot(computed_volumes, pressure_data, label="Model")
    ax.set_xlabel("Volume")
    ax.set_xlabel("Pressure")
    ax.legend()
    fig.savefig("results.png")
def rhs(states, time, parameters, dy=None):
    """
    Compute right hand side
    """
    # Imports
    import ufl
    import dolfin

    # Assign states
    assert(isinstance(states, dolfin.Function))
    assert(states.function_space().depth() == 1)
    assert(states.function_space().num_sub_spaces() == 17)
    Xr1, Xr2, Xs, m, h, j, d, f, fCa, s, r, Ca_SR, Ca_i, g, Na_i, V, K_i =\
        dolfin.split(states)

    # Assign parameters
    assert(isinstance(parameters, (dolfin.Function, dolfin.Constant)))
    if isinstance(parameters, dolfin.Function):
        assert(parameters.function_space().depth() == 1)
        assert(parameters.function_space().num_sub_spaces() == 45)
    else:
        assert(parameters.value_size() == 45)
    P_kna, g_K1, g_Kr, g_Ks, g_Na, g_bna, g_CaL, g_bca, g_to, K_mNa, K_mk,\
        P_NaK, K_NaCa, K_sat, Km_Ca, Km_Nai, alpha, gamma, K_pCa, g_pCa,\
        g_pK, Buf_c, Buf_sr, Ca_o, K_buf_c, K_buf_sr, K_up, V_leak, V_sr,\
        Vmax_up, a_rel, b_rel, c_rel, tau_g, Na_o, Cm, F, R, T, V_c,\
        stim_amplitude, stim_duration, stim_period, stim_start, K_o =\
        dolfin.split(parameters)

    # Reversal potentials
    E_Na = R*T*ufl.ln(Na_o/Na_i)/F
    E_K = R*T*ufl.ln(K_o/K_i)/F
    E_Ks = R*T*ufl.ln((Na_o*P_kna + K_o)/(Na_i*P_kna + K_i))/F
    E_Ca = 0.5*R*T*ufl.ln(Ca_o/Ca_i)/F

    # Inward rectifier potassium current
    alpha_K1 = 0.1/(1.0 + 6.14421235332821e-6*ufl.exp(0.06*V - 0.06*E_K))
    beta_K1 = (3.06060402008027*ufl.exp(0.0002*V - 0.0002*E_K) +\
        0.367879441171442*ufl.exp(0.1*V - 0.1*E_K))/(1.0 + ufl.exp(0.5*E_K -\
        0.5*V))
    xK1_inf = alpha_K1/(alpha_K1 + beta_K1)
    i_K1 = 0.430331482911935*ufl.sqrt(K_o)*(-E_K + V)*g_K1*xK1_inf

    # Rapid time dependent potassium current
    i_Kr = 0.430331482911935*ufl.sqrt(K_o)*(-E_K + V)*Xr1*Xr2*g_Kr

    # Rapid time dependent potassium current xr1 gate
    xr1_inf = 1.0/(1.0 + 0.0243728440732796*ufl.exp(-0.142857142857143*V))
    alpha_xr1 = 450.0/(1.0 + ufl.exp(-9/2 - V/10.0))
    beta_xr1 = 6.0/(1.0 + 13.5813245225782*ufl.exp(0.0869565217391304*V))
    tau_xr1 = alpha_xr1*beta_xr1

    # Rapid time dependent potassium current xr2 gate
    xr2_inf = 1.0/(1.0 + 39.1212839981532*ufl.exp(0.0416666666666667*V))
    alpha_xr2 = 3.0/(1.0 + 0.0497870683678639*ufl.exp(-0.05*V))
    beta_xr2 = 1.12/(1.0 + 0.0497870683678639*ufl.exp(0.05*V))
    tau_xr2 = alpha_xr2*beta_xr2

    # Slow time dependent potassium current
    i_Ks = (Xs*Xs)*(V - E_Ks)*g_Ks

    # Slow time dependent potassium current xs gate
    xs_inf = 1.0/(1.0 + 0.69967253737513*ufl.exp(-0.0714285714285714*V))
    alpha_xs = 1100.0/ufl.sqrt(1.0 +\
        0.188875602837562*ufl.exp(-0.166666666666667*V))
    beta_xs = 1.0/(1.0 + 0.0497870683678639*ufl.exp(0.05*V))
    tau_xs = alpha_xs*beta_xs

    # Fast sodium current
    i_Na = (m*m*m)*(-E_Na + V)*g_Na*h*j

    # Fast sodium current m gate
    m_inf = 1.0/((1.0 +\
        0.00184221158116513*ufl.exp(-0.110741971207087*V))*(1.0 +\
        0.00184221158116513*ufl.exp(-0.110741971207087*V)))
    alpha_m = 1.0/(1.0 + ufl.exp(-12.0 - V/5.0))
    beta_m = 0.1/(1.0 + 0.778800783071405*ufl.exp(0.005*V)) + 0.1/(1.0 +\
        ufl.exp(7.0 + V/5.0))
    tau_m = alpha_m*beta_m

    # Fast sodium current h gate
    h_inf = 1.0/((1.0 + 15212.5932856544*ufl.exp(0.134589502018843*V))*(1.0 +\
        15212.5932856544*ufl.exp(0.134589502018843*V)))
    alpha_h = 4.43126792958051e-7*ufl.exp(-0.147058823529412*V)/(1.0 +\
        2.3538526683702e+17*ufl.exp(1.0*V))
    beta_h = (310000.0*ufl.exp(0.3485*V) + 2.7*ufl.exp(0.079*V))/(1.0 +\
        2.3538526683702e+17*ufl.exp(1.0*V)) + 0.77*(1.0 - 1.0/(1.0 +\
        2.3538526683702e+17*ufl.exp(1.0*V)))/(0.13 +\
        0.0497581410839387*ufl.exp(-0.0900900900900901*V))
    tau_h = 1.0/(alpha_h + beta_h)

    # Fast sodium current j gate
    j_inf = 1.0/((1.0 + 15212.5932856544*ufl.exp(0.134589502018843*V))*(1.0 +\
        15212.5932856544*ufl.exp(0.134589502018843*V)))
    alpha_j = (37.78 + V)*(-6.948e-6*ufl.exp(-0.04391*V) -\
        25428.0*ufl.exp(0.2444*V))/((1.0 +\
        2.3538526683702e+17*ufl.exp(1.0*V))*(1.0 +\
        50262745825.954*ufl.exp(0.311*V)))
    beta_j = 0.6*(1.0 - 1.0/(1.0 +\
        2.3538526683702e+17*ufl.exp(1.0*V)))*ufl.exp(0.057*V)/(1.0 +\
        0.0407622039783662*ufl.exp(-0.1*V)) +\
        0.02424*ufl.exp(-0.01052*V)/((1.0 +\
        2.3538526683702e+17*ufl.exp(1.0*V))*(1.0 +\
        0.00396086833990426*ufl.exp(-0.1378*V)))
    tau_j = 1.0/(alpha_j + beta_j)

    # Sodium background current
    i_b_Na = (-E_Na + V)*g_bna

    # L type ca current
    i_CaL = 4.0*(F*F)*(-0.341*Ca_o +\
        Ca_i*ufl.exp(2.0*F*V/(R*T)))*V*d*f*fCa*g_CaL/((-1.0 +\
        ufl.exp(2.0*F*V/(R*T)))*R*T)

    # L type ca current d gate
    d_inf = 1.0/(1.0 + 0.513417119032592*ufl.exp(-0.133333333333333*V))
    alpha_d = 0.25 + 1.4/(1.0 +\
        0.0677244716592409*ufl.exp(-0.0769230769230769*V))
    beta_d = 1.4/(1.0 + ufl.exp(1.0 + V/5.0))
    gamma_d = 1.0/(1.0 + 12.1824939607035*ufl.exp(-0.05*V))
    tau_d = gamma_d + alpha_d*beta_d

    # L type ca current f gate
    f_inf = 1.0/(1.0 + 17.4117080633276*ufl.exp(0.142857142857143*V))
    tau_f = 80.0 + 165.0/(1.0 + ufl.exp(5/2 - V/10.0)) +\
        1125.0*ufl.exp(-0.00416666666666667*((27.0 + V)*(27.0 + V)))

    # L type ca current fca gate
    alpha_fCa = 1.0/(1.0 + 8.03402376701711e+27*ufl.elem_pow(Ca_i, 8.0))
    beta_fCa = 0.1/(1.0 + 0.00673794699908547*ufl.exp(10000.0*Ca_i))
    gama_fCa = 0.2/(1.0 + 0.391605626676799*ufl.exp(1250.0*Ca_i))
    fCa_inf = 0.157534246575342 + 0.684931506849315*gama_fCa +\
        0.684931506849315*beta_fCa + 0.684931506849315*alpha_fCa
    tau_fCa = 2.0
    d_fCa = (-fCa + fCa_inf)/tau_fCa

    # Calcium background current
    i_b_Ca = (V - E_Ca)*g_bca

    # Transient outward current
    i_to = (-E_K + V)*g_to*r*s

    # Transient outward current s gate
    s_inf = 1.0/(1.0 + ufl.exp(4.0 + V/5.0))
    tau_s = 3.0 + 85.0*ufl.exp(-0.003125*((45.0 + V)*(45.0 + V))) + 5.0/(1.0 +\
        ufl.exp(-4.0 + V/5.0))

    # Transient outward current r gate
    r_inf = 1.0/(1.0 + 28.0316248945261*ufl.exp(-0.166666666666667*V))
    tau_r = 0.8 + 9.5*ufl.exp(-0.000555555555555556*((40.0 + V)*(40.0 + V)))

    # Sodium potassium pump current
    i_NaK = K_o*Na_i*P_NaK/((K_mk + K_o)*(Na_i + K_mNa)*(1.0 +\
        0.0353*ufl.exp(-F*V/(R*T)) + 0.1245*ufl.exp(-0.1*F*V/(R*T))))

    # Sodium calcium exchanger current
    i_NaCa = (-(Na_o*Na_o*Na_o)*Ca_i*alpha*ufl.exp((-1.0 + gamma)*F*V/(R*T))\
        + (Na_i*Na_i*Na_i)*Ca_o*ufl.exp(F*V*gamma/(R*T)))*K_NaCa/((1.0 +\
        K_sat*ufl.exp((-1.0 + gamma)*F*V/(R*T)))*((Na_o*Na_o*Na_o) +\
        (Km_Nai*Km_Nai*Km_Nai))*(Km_Ca + Ca_o))

    # Calcium pump current
    i_p_Ca = Ca_i*g_pCa/(K_pCa + Ca_i)

    # Potassium pump current
    i_p_K = (-E_K + V)*g_pK/(1.0 +\
        65.4052157419383*ufl.exp(-0.167224080267559*V))

    # Calcium dynamics
    i_rel = ((Ca_SR*Ca_SR)*a_rel/((Ca_SR*Ca_SR) + (b_rel*b_rel)) + c_rel)*d*g
    i_up = Vmax_up/(1.0 + (K_up*K_up)/(Ca_i*Ca_i))
    i_leak = (-Ca_i + Ca_SR)*V_leak
    g_inf = (1.0 - 1.0/(1.0 + 0.0301973834223185*ufl.exp(10000.0*Ca_i)))/(1.0 +\
        1.97201988740492e+55*ufl.elem_pow(Ca_i, 16.0)) + 1.0/((1.0 +\
        0.0301973834223185*ufl.exp(10000.0*Ca_i))*(1.0 +\
        5.43991024148102e+20*ufl.elem_pow(Ca_i, 6.0)))
    d_g = (-g + g_inf)/tau_g
    Ca_i_bufc = 1.0/(1.0 + Buf_c*K_buf_c/((K_buf_c + Ca_i)*(K_buf_c + Ca_i)))
    Ca_sr_bufsr = 1.0/(1.0 + Buf_sr*K_buf_sr/((K_buf_sr + Ca_SR)*(K_buf_sr +\
        Ca_SR)))

    # Sodium dynamics

    # Membrane
    i_Stim = -(1.0 - 1.0/(1.0 + ufl.exp(-5.0*stim_start +\
        5.0*time)))*stim_amplitude/(1.0 + ufl.exp(-5.0*stim_start + 5.0*time\
        - 5.0*stim_duration))

    # Potassium dynamics

    # The ODE system: 17 states

    # Init test function
    _v = dolfin.TestFunction(states.function_space())

    # Derivative for state Xr1
    dy = ((-Xr1 + xr1_inf)/tau_xr1)*_v[0]

    # Derivative for state Xr2
    dy += ((-Xr2 + xr2_inf)/tau_xr2)*_v[1]

    # Derivative for state Xs
    dy += ((-Xs + xs_inf)/tau_xs)*_v[2]

    # Derivative for state m
    dy += ((-m + m_inf)/tau_m)*_v[3]

    # Derivative for state h
    dy += ((-h + h_inf)/tau_h)*_v[4]

    # Derivative for state j
    dy += ((j_inf - j)/tau_j)*_v[5]

    # Derivative for state d
    dy += ((d_inf - d)/tau_d)*_v[6]

    # Derivative for state f
    dy += ((-f + f_inf)/tau_f)*_v[7]

    # Derivative for state fCa
    dy += ((1.0 - 1.0/((1.0 + ufl.exp(60.0 + V))*(1.0 + ufl.exp(-10.0*fCa +\
        10.0*fCa_inf))))*d_fCa)*_v[8]

    # Derivative for state s
    dy += ((-s + s_inf)/tau_s)*_v[9]

    # Derivative for state r
    dy += ((-r + r_inf)/tau_r)*_v[10]

    # Derivative for state Ca_SR
    dy += ((-i_leak + i_up - i_rel)*Ca_sr_bufsr*V_c/V_sr)*_v[11]

    # Derivative for state Ca_i
    dy += ((-i_up - (i_CaL + i_p_Ca + i_b_Ca - 2.0*i_NaCa)*Cm/(2.0*F*V_c) +\
        i_leak + i_rel)*Ca_i_bufc)*_v[12]

    # Derivative for state g
    dy += ((1.0 - 1.0/((1.0 + ufl.exp(60.0 + V))*(1.0 + ufl.exp(-10.0*g +\
        10.0*g_inf))))*d_g)*_v[13]

    # Derivative for state Na_i
    dy += ((-3.0*i_NaK - 3.0*i_NaCa - i_Na - i_b_Na)*Cm/(F*V_c))*_v[14]

    # Derivative for state V
    dy += (-i_Ks - i_to - i_Kr - i_p_K - i_NaK - i_NaCa - i_Na - i_p_Ca -\
        i_b_Na - i_CaL - i_Stim - i_K1 - i_b_Ca)*_v[15]

    # Derivative for state K_i
    dy += ((-i_Ks - i_to - i_Kr - i_p_K - i_Stim - i_K1 +\
        2.0*i_NaK)*Cm/(F*V_c))*_v[16]

    # Return dy
    return dy
Example #10
0
import dolfin as dl

mesh = dl.UnitCubeMesh(1,1,1)

vectorP2Element = dl.VectorElement("P", mesh.ufl_cell(), 2) 
scalarP1Element = dl.FiniteElement("P", mesh.ufl_cell(), 1)
TaylorHoodV  = dl.FunctionSpace(mesh, dl.MixedElement([vectorP2Element,scalarP1Element]))
parameterV = dl.VectorFunctionSpace(mesh,"R",0,7)  

y = dl.Function(TaylorHoodV)
ytest = dl.TestFunction(TaylorHoodV)
ytrial = dl.TrialFunction(TaylorHoodV)
u,p = dl.split(y)

a = dl.Function(parameterV)
atest = dl.TestFunction(parameterV)
atrial = dl.TrialFunction(parameterV)
#Model Parameters
m0 = 543.09
m1 = 4.73
m2 = 4.57
m3 = 5.27
m4 = 4.49
m5 = 4.49
m6 = 12.02 
m = (m0,m1,m2,m3,m4,m5,m6)
parameters = dl.interpolate(dl.Constant(m),parameterV)

#Model
d    = len(u)
I    = dl.Identity(d)            # Identity tensor
Example #11
0
  def initialize_eqs(self):
    """
    """


    # initial height
    h = self.initial_h(120+0.0003*self.L, self.c, 0.4*self.L, self.L)

    self.h_old = d.project(h, self.V)
    # initial guess of velocity
    u = d.project(d.Expression('x[0]/L', L=1000*self.L), self.V)     
    self.h_u_dhdx = d.project(d.as_vector((h,u,h.dx(0))), self.V3)
    self.h,self.u,self.dhdx = d.split(self.h_u_dhdx)

    # initialize floating conditional
    class FloatBoolean(Expression):
      """
      creates boolean function over length of ice, true when ice is floating.
      """
      def eval(s,value,x):
        if self.h_u_dhdx(x[0])[0] <= -h_b(x[0])*(self.rho_w/self.rho-1):
          value[0] = 1
        else:
          value[0] = 0

    # floating conditional
    fc = self.smooth_step_conditional(FloatBoolean())

    # A useful expression for the effective pressure term
    reduction = fc*(self.rho_w/self.rho)*self.h_b
    
    # H (ice thickness) conditional on floating
    if self.floating:
      # archimedes principle, H (ice thickness)
      self.H = fc * (h/(1-self.rho/self.rho_w)) + (1-fc) * (self.h-self.h_b) 
    else:
      # ice thickness = surface elevation - bed elevation
      self.H = self.h - self.h_b  

    H = self.H
    h = self.h
    W = self.W
    u = self.u
    n = self.n

    # basal drag
    self.basal_drag = self.mu*self.A_s*(self.H+reduction)**self.p*u**(1/n)

    if self.floating:
      self.basal_drag = (1-fc) * self.basal_drag

    # define variational problem
    testFunction  = TestFunction(self.V3)
    trialFunction = TrialFunction(self.V3)
    phi1, phi2, phi3 = split(testFunction)

    self.driving_stress = self.rho*self.g*H*self.dhdx
    self.lateral_drag = (self.B_s*H/W)*((n+2)*u/(2*W))**(1/n)
    
    force_balance = (self.driving_stress+self.basal_drag+self.lateral_drag)*phi2 
    
    ####????####################################################################
    mass_conservation = ((h-self.h_old)/self.dt + (H*u*W).dx(0)/W - M)*phi1
    ####????####################################################################
    
    F = (mass_conservation + force_balance)*d.dx
    
    ###????#####################################################################
    invariant_squared = ((n+2.)/(n+1.)*u/W)**2+u.dx(0)**2
    self.longitudinal_stress = \
            2*self.B_s*H*invariant_squared**((1-n)/(2*n))*u.dx(0)
    
    F += self.longitudinal_stress * phi2.dx(0) * d.dx
    F -= self.longitudinal_stress * phi2 * self.ds(self.TERMINUS)
    F += (self.h.dx(0)-self.dhdx)*phi3*d.dx
    ###????#####################################################################


    J = derivative(F, self.h_u_dhdx, trialFunction)
    problem =\
    NonlinearVariationalProblem(F, self.h_u_dhdx, self.boundary_conditions, J)
    self.solver  = NonlinearVariationalSolver(problem)
Example #12
0
    def linear_solver(self, u_k):
        r"""
        Solves the (linear) Newton iteration Eq. :eq:`Eq_linear_solver` for the IR theory.

        For the IR theory, the form of the Newton iterations is:

        .. math:: & - \int \hat{\nabla}\hat{\pi} \cdot \hat{\nabla} v_1 \hat{r}^2 d\hat{r}
                   - \int \hat{Y} v_1 \hat{r}^2 d\hat{r} +

                  & + \int \hat{W} v_2 \hat{r}^2 d\hat{r} -n \int {\hat{Y}_k}^{n-1} \hat{Y} v_2 \hat{r}^2 d\hat{r} +

                  & + \int \hat{Y} v_3 \hat{r}^2 d\hat{r} 
                  - \int \left( \frac{m}{M_n} \right)^2 \hat{\pi} v_3 \hat{r}^2 d\hat{r}
                  + \epsilon \left( \frac{M_n}{\Lambda} \right)^{3n-1} \left( \frac{M_{f1}}{M_n} \right)^{n-1}
                  \int \nabla\hat{W} \cdot \nabla v_3 \hat{r}^2 d\hat{r}

                  & = (1-n) \int {\hat{Y}_k}^n v_2 \hat{r}^2 d\hat{r}
                  + \int \frac{\hat{\rho}}{M_P} \frac{M_n}{M_{f1}} v_3 \hat{r}^2 d\hat{r}

        *Arguments*
            u_k  
                solution at the previous iteration

        """

        # get the boundary conditions
        Dirichlet_bc = self.get_Dirichlet_bc()

        # create a vector (pi,w,y) with the three trial functions for the fields
        u = d.TrialFunction(self.V)
        # ... and split it into pi, w, y
        pi, w, y = d.split(u)

        # define test functions over the function space
        v1, v2, v3 = d.TestFunctions(self.V)

        # split solution at current iteration into pi_k, w_k, y_k - this is only really useful for y_k
        pi_k, w_k, y_k = d.split(u_k)

        # cast params as constant functions so that, if they are set to 0, FEniCS still understand
        # what is being integrated
        m, Lambda, Mp = Constant(self.fields.m), Constant(
            self.fields.Lambda), Constant(self.fields.Mp)
        epsilon = Constant(self.fields.epsilon)
        Mn, Mf1 = Constant(self.Mn), Constant(self.Mf1)
        n = self.fields.n

        # r^2
        r2 = Expression('pow(x[0],2)', degree=self.fem.func_degree)

        # define bilinear form
        a1 = -inner(grad(pi), grad(v1)) * r2 * dx - y * v1 * r2 * dx
        a2 = w * v2 * r2 * dx - n * y_k**(n - 1) * y * v2 * r2 * dx
        a3 = y * v3 * r2 * dx - ( m / Mn )**2 * pi * v3 * r2 * dx + \
             epsilon * ( Mn / Lambda )**(3*n-1) * ( Mf1 / Mn )**(n-1) * inner( grad(w), grad(v3) ) * r2 * dx

        a = a1 + a2 + a3

        # define linear form
        # we have L1 = 0.
        L2 = (1 - n) * y_k**n * v2 * r2 * dx
        L3 = self.source.rho / Mp * Mn / Mf1 * v3 * r2 * dx

        L = L2 + L3

        # define a vector with the solution
        sol = d.Function(self.V)

        # solve linearised system
        pde = d.LinearVariationalProblem(a, L, sol, Dirichlet_bc)
        solver = d.LinearVariationalSolver(pde)
        solver.solve()

        return sol
Example #13
0
def main():

    pulse.annotation.annotate = True

    # Set up problem
    problem, material_control, activation_control = create_problem()
    computed_volumes = [problem.geometry.cavity_volume()]

    # Create volume observersion
    endo = problem.geometry.markers["ENDO"][0]
    volume_model = pulse_adjoint.model_observations.VolumeObservation(
        problem.geometry.mesh, problem.geometry.ds(endo)
    )

    passive_volume_data = [2.511304019359619, 2.8]
    active_volume_data = [2.8, 1.5, 1.2, 1.2, 2.8]
    volume_data = passive_volume_data + active_volume_data

    passive_pressure_data = [0, 0.1]
    active_pressure_data = [1.0, 1.2, 1.0, 0.05, 0.1]
    pressure_data = passive_pressure_data + active_pressure_data

    if 0:
        fig, ax = plt.subplots()
        ax.plot(volume_data, pressure_data)
        ax.set_xlabel("Volume [ml]")
        ax.set_ylabel("Pressure [kPa]")
        plt.show()

    # ------------- Passive phase ----------------

    volume_target = pulse_adjoint.OptimizationTarget(
        passive_volume_data[1:], volume_model
    )

    pressure_obs = pulse_adjoint.model_observations.BoundaryObservation(
        problem.bcs.neumann[0],
        passive_pressure_data[1:],
        start_value=passive_pressure_data[0],
    )

    assimilator = pulse_adjoint.Assimilator(
        problem, targets=[volume_target], bcs=pressure_obs, control=material_control
    )

    optimal_control = assimilator.assimilate(min_value=0.1, max_value=10.0, tol=0.01)

    material_control.assign(dolfin.Constant(optimal_control.optimal_control))
    optimzed_material_paramter = optimal_control.optimal_control

    problem.solve()
    u, p = dolfin.split(problem.state)
    computed_volume = problem.geometry.cavity_volume(u=u)
    computed_volumes.append(computed_volume)
    print(f"Target volume: {passive_volume_data[-1]}")
    print(f"Model volume: {computed_volume}")
    print(f"Estimated activation parameters {optimzed_material_paramter}")

    prev_pressure = passive_pressure_data[-1]
    activation_parameters = [0] * len(passive_pressure_data)
    # ------------- Active phase ----------------

    for volume, pressure in zip(active_volume_data, active_pressure_data):
        print(f"Try to fit volume : {volume} with pressure {pressure}")

        volume_target = pulse_adjoint.OptimizationTarget([volume], volume_model)

        pressure_obs = pulse_adjoint.model_observations.BoundaryObservation(
            problem.bcs.neumann[0], [pressure], start_value=prev_pressure
        )

        assimilator = pulse_adjoint.Assimilator(
            problem,
            targets=[volume_target],
            bcs=pressure_obs,
            control=activation_control,
        )

        optimal_control = assimilator.assimilate(min_value=0.0, max_value=0.3, tol=0.01)

        activation_control.assign(dolfin.Constant(optimal_control.optimal_control))
        problem.solve()
        u, p = dolfin.split(problem.state)
        computed_volume = problem.geometry.cavity_volume(u=u)
        computed_volumes.append(computed_volume)
        activation_parameters.append(optimal_control.optimal_control)

        print(f"Target volume: {volume}")
        print(f"Model volume: {computed_volume}")
        print(f"Estimated activation parameters {optimal_control.optimal_control}")

        prev_pressure = pressure

    fig, ax = plt.subplots(2, 1)
    ax[0].plot(volume_data, pressure_data, label="Data")
    ax[0].plot(computed_volumes, pressure_data, label="Model")
    ax[0].set_title(f"Material parameter {optimzed_material_paramter:.2f}")
    ax[1].plot(activation_parameters, marker="o")
    ax[1].set_title("Active strain")
    fig.savefig("results.png")
Example #14
0
    def strong_residual_form(self, sol, units):
        r"""
        Computes the residual with respect to the strong form of the equations.

        The total residual is obtained by summing the residuals of all equations:

        .. math:: F = F_1 + F_2 + F_3

        where, in dimensionless in-code units (`units='rescaled'`):

        .. math:: & F_1(\hat{\pi},\hat{W},\hat{Y}) = \hat{\nabla}^2 \hat{\pi} - \hat{Y}

                  & F_2(\hat{\pi},\hat{W},\hat{Y}) = \hat{W} - \hat{Y}^n

                  & F_3(\hat{\pi},\hat{W},\hat{Y}) = \hat{Y} - \left( \frac{m}{M_n} \right)^2 \hat{\pi}
                  - \epsilon \left( \frac{M_n}{\Lambda} \right)^{3n-1}
                  \left(\frac{M_{f1}}{M_n}\right)^{n-1} \hat{\nabla}^2 \hat{W}
                  - \frac{\hat{\rho}}{M_P} \frac{M_n}{M_{f1}}


        and in physical units (`units='physical'`):

        .. math:: & F_1(\pi,W,Y) = \nabla^2\pi - Y

                  & F_2(\pi,W,Y) = W - Y^n

                  & F_3(\pi,W,Y) = Y - m^2 \pi - \frac{\epsilon}{\Lambda^{3n-1}} \nabla^2 W - \frac{\rho}{M_P}



        .. note:: In this function, the Laplacian :math:`\hat{\nabla}^2` is obtained by projecting
                  :math:`\frac{\partial^2}{\partial\hat{r}^2} + 2\frac{\partial}{\partial\hat{r}}`.
                  As such, it should not be used with interpolating polynomials of degree less than 2.

        Note that the weak residual in :func:`weak_residual_form` is just the scalar product
        of the strong residuals by test functions.

        *Parameters*
            sol
                the solution with respect to which the weak residual is computed.
            units
                `'rescaled'` (for the rescaled units used inside the code) or `'physical'`, for physical units

        """

        if units == 'rescaled':
            resc_1, resc_2, resc_3 = 1., 1., 1.
        elif units == 'physical':
            resc_1 = self.Mn**2 * self.Mf1
            resc_2 = (self.Mn**2 * self.Mf1)**self.fields.n
            resc_3 = self.Mn**2 * self.Mf1
        else:
            message = "Invalid choice of units: valid choices are 'physical' or 'rescaled'."
            raise ValueError(message)

        # cast params as constant functions so that, if they are set to 0, FEniCS still understand
        # what is being integrated
        m, Lambda, Mp = Constant(self.fields.m), Constant(
            self.fields.Lambda), Constant(self.fields.Mp)
        epsilon = Constant(self.fields.epsilon)
        Mn, Mf1 = Constant(self.Mn), Constant(self.Mf1)
        n = self.fields.n

        # split solution into pi, w, y
        pi, w, y = d.split(sol)

        # initialise residual function
        F = d.Function(self.dV)

        # define r for use in the computation of the Laplacian
        r = Expression('x[0]', degree=self.fem.func_degree)

        # equation 1
        f1 = pi.dx(0).dx(0) + Constant(2.) / r * pi.dx(0) - y
        f1 *= Constant(resc_1)
        F1 = project(f1, self.fem.dS, self.fem.func_degree)
        # equation 2
        f2 = w - y**n
        f2 *= Constant(resc_2)
        F2 = project(f2, self.fem.dS, self.fem.func_degree)
        # equation 3
        f3 = y - ( m/Mn )**2 * pi \
             - epsilon * ( Mn / Lambda )**(3*n-1) * ( Mf1 / Mn )**(n-1) * (  w.dx(0).dx(0) + Constant(2.)/r * w.dx(0) ) \
             - self.source.rho / Mp * Mn / Mf1
        f3 *= Constant(resc_3)
        F3 = project(f3, self.fem.dS, self.fem.func_degree)

        # combine equations
        fa = d.FunctionAssigner(self.dV,
                                [self.fem.dS, self.fem.dS, self.fem.dS])
        fa.assign(F, [F1, F2, F3])

        return F
Example #15
0
    def KG_initial_guess(self):
        r"""
        Obtains an initial guess for the Galileon equation of motion by assuming the nonlinear term is
        subdominant, i.e.:

        .. math:: \Box\pi - m^2\pi \approx \frac{\rho}{Mp}

        The initial guess is computed by first solving the system of equations:

        .. math:: & \hat{\nabla}^2\hat{\pi} = \hat{Y} \\
                  & \hat{Y} - \left( \frac{m}{M_n} \right)^2\pi = \frac{\hat{\rho}}{M_p}

        and then obtaining :math:`\hat{W}=\hat{Y}^n` by projection.

        """

        # define a function space for (pi, y) only
        piy_E = d.MixedElement([self.fem.Pn, self.fem.Pn])
        piy_V = d.FunctionSpace(self.fem.mesh.mesh, piy_E)

        # get the boundary conditions for pi and y only
        piD, yD = Constant(0.), Constant(0.)

        def boundary(x):
            return self.fem.mesh.r_max - x[0] < d.DOLFIN_EPS

        bc_pi = d.DirichletBC(piy_V.sub(0), piD, boundary, method='pointwise')
        bc_y = d.DirichletBC(piy_V.sub(1), yD, boundary, method='pointwise')
        Dirichlet_bc = [bc_pi, bc_y]

        # Trial functions for pi and y
        u = d.TrialFunction(piy_V)
        pi, y = d.split(u)

        # test functions for the two equations
        v1, v3 = d.TestFunctions(piy_V)

        # cast params as constant functions so that, if they are set to 0, FEniCS still understand
        # what is being integrated
        m, Mp, Mn, Mf1 = Constant(self.fields.m), Constant(
            self.fields.Mp), Constant(self.Mn), Constant(self.Mf1)
        n = self.fields.n

        # r^2
        r2 = Expression('pow(x[0],2)', degree=self.fem.func_degree)

        # bilinear form
        a1 = -inner(grad(pi), grad(v1)) * r2 * dx - y * v1 * r2 * dx
        a3 = y * v3 * r2 * dx - (m / Mn)**2 * pi * v3 * r2 * dx
        a = a1 + a3

        # linear form (L1=0)
        L3 = self.source.rho / Mp * Mn / Mf1 * v3 * r2 * dx
        L = L3

        # solve system
        sol = d.Function(piy_V)
        pde = d.LinearVariationalProblem(a, L, sol, Dirichlet_bc)
        solver = d.LinearVariationalSolver(pde)
        print('Getting KG initial guess...')
        solver.solve()

        # split solution into pi and y - cast as independent functions, not components of a vector function
        pi, y = sol.split(deepcopy=True)

        # obtain w by projecting y**n
        w = y**n
        w = project(w, self.fem.S, self.fem.func_degree)

        # and now pack pi, w, y into one function...
        guess = d.Function(self.V)
        # this syntax is because, even though pi and y are effectively defined on fem.S, from fenics point
        # of view, they are obtained as splits of a function
        fa = d.FunctionAssigner(
            self.V, [pi.function_space(), self.fem.S,
                     y.function_space()])
        fa.assign(guess, [pi, w, y])

        return guess
Example #16
0
def traction_test(
    ell=0.1,
    degree=1,
    n=3,
    nu=0.0,
    load_min=0,
    load_max=2,
    loads=None,
    nsteps=20,
    Lx=1,
    Ly=0.1,
    outdir="outdir",
    savelag=1,
):
    # constants
    ell = ell
    Lx = Lx
    Ly = Ly
    load_min = load_min
    load_max = load_max
    nsteps = nsteps
    loads=loads

    savelag = 1
    nu = dolfin.Constant(nu)
    ell = dolfin.Constant(ell)
    E0 = dolfin.Constant(1.0)
    sigma_D0 = E0
    n = n


    params =  { 
    'material': {
        "ell":   ell.values()[0],
        "E": E0.values()[0],
        "nu": nu.values()[0],
        "sigma_D0": sigma_D0.values()[0]},
    'geometry': {
        'Lx': Lx,
        'Ly': Ly,
        'n': n,
        },
    'load':{
        'min': load_min,
        'max': load_max,
        'nsteps':  nsteps
    } }

    print(params)
    geom = mshr.Rectangle(dolfin.Point(-Lx/2., -Ly/2.), dolfin.Point(Lx/2., Ly/2.))

    nel = max(int(n * float(Lx / ell)), int(Ly/3.))
    mesh = mshr.generate_mesh(geom, nel)

    left = dolfin.CompiledSubDomain("near(x[0], -Lx/2.)", Lx=Lx)
    right = dolfin.CompiledSubDomain("near(x[0], Lx/2.)", Lx=Lx)
    right_bottom_pt = dolfin.CompiledSubDomain("near(x[1], Lx/2.) && near(x[0],-Ly/2.)", Lx=Lx, Ly=Ly)

    mf = dolfin.MeshFunction("size_t", mesh, 1, 0)
    right.mark(mf, 1)
    left.mark(mf, 2)
    ds = dolfin.Measure("ds", subdomain_data=mf)
    dx = dolfin.Measure("dx", metadata=form_compiler_parameters, domain=mesh)

    V_u = dolfin.VectorFunctionSpace(mesh, "CG", 1)
    V_alpha = dolfin.FunctionSpace(mesh, "CG", 1)
    u = dolfin.Function(V_u, name="Total displacement")
    alpha = dolfin.Function(V_alpha, name="Damage")
    state = {'u': u, 'alpha':alpha}

    Z = dolfin.FunctionSpace(mesh, dolfin.MixedElement([u.ufl_element(),alpha.ufl_element()]))
    z = dolfin.Function(Z)

    v, beta = dolfin.split(z)

    ut = dolfin.Expression("t", t=0.0, degree=0)
    bcs_u = [dolfin.DirichletBC(V_u.sub(0), dolfin.Constant(0), left),
             dolfin.DirichletBC(V_u.sub(0), ut, right),
             dolfin.DirichletBC(V_u, (0, 0), right_bottom_pt, method="pointwise")]

    bcs_alpha = []

    # Problem definition
    model = DamageElasticityModel(state, E0, nu, ell, sigma_D0)
    energy = model.total_energy_density(u, alpha)*dx

    # Alternate minimization solver
    solver = solvers.EquilibriumAM(
        energy, {'u':u, 'alpha':alpha}, {'elastic':bcs_u, 'damage':bcs_alpha}, parameters = alt_min_parameters)

    rP = model.rP(u, alpha, v, beta)*dx
    rN = model.rN(u, alpha, beta)

    stability = StabilitySolver(mesh, energy,
        {'u':u, 'alpha':alpha}, {'elastic':bcs_u, 'damage':bcs_alpha}, z, parameters = stability_parameters)

    # Time iterations
    time_data = []
    load_steps = np.linspace(load_min, load_max, nsteps)
    alpha_old = dolfin.Function(V_alpha)

    for it, load in enumerate(load_steps):
        stable = None; negev = 0; mineig = np.inf; iteration = 0
        ut.t = load
        ColorPrint.print_pass('load: {:4f} step {:d} ell {:f}'.format(load, it, ell.values()[0]))
        alpha_old.assign(alpha)
        time_data_i, am_iter = solver.solve()
        solver.update()
        (stable, negev) = stability.solve(alpha_old)

        time_data_i["load"] = load
        time_data_i["stable"] = stable
        time_data_i["# neg ev"] = negev
        time_data_i["elastic_energy"] = dolfin.assemble(
            model.elastic_energy_density(model.eps(u), alpha)*dx)
        time_data_i["dissipated_energy"] = dolfin.assemble(
            model.damage_dissipation_density(alpha)*dx)
        time_data_i["eigs"] = stability.eigs if hasattr(stability, 'eigs') else np.inf
        time_data_i["max alpha"] = np.max(alpha.vector()[:])
        time_data.append(time_data_i)
        time_data_pd = pd.DataFrame(time_data)

        if stable == False:
            break

    return time_data_pd
Example #17
0
    def __init__(self, fileName, timeEnd, timeStep):

        self.times = []
        self.BB = []
        self.HH = []
        self.TD = []
        self.TB = []
        self.TX = []
        self.TY = []
        self.TZ = []
        self.us = []
        self.ub = []

        ##########################################################
        ################           MESH          #################
        ##########################################################
        # TODO: Probably do not have to save then open mesh
        self.mesh = df.Mesh()
        self.inFile = fc.HDF5File(self.mesh.mpi_comm(), fileName, "r")
        self.inFile.read(self.mesh, "/mesh", False)

        #########################################################
        #################  FUNCTION SPACES  #####################
        #########################################################
        self.E_Q = df.FiniteElement("CG", self.mesh.ufl_cell(), 1)
        self.Q = df.FunctionSpace(self.mesh, self.E_Q)
        self.E_V = df.MixedElement(self.E_Q, self.E_Q, self.E_Q)
        self.V = df.FunctionSpace(self.mesh, self.E_V)

        self.assigner_inv = fc.FunctionAssigner([self.Q, self.Q, self.Q],
                                                self.V)
        self.assigner = fc.FunctionAssigner(self.V, [self.Q, self.Q, self.Q])

        self.U = df.Function(self.V)
        self.dU = df.TrialFunction(self.V)
        self.Phi = df.TestFunction(self.V)
        self.u, self.u2, self.H = df.split(self.U)
        self.phi, self.phi1, self.xsi = df.split(self.Phi)

        self.un = df.Function(self.Q)
        self.u2n = df.Function(self.Q)

        self.zero_sol = df.Function(self.Q)

        self.S0 = df.Function(self.Q)
        self.B = df.Function(self.Q)
        self.H0 = df.Function(self.Q)
        self.A = df.Function(self.Q)

        self.inFile.read(self.S0.vector(), "/surface", True)
        self.inFile.read(self.B.vector(), "/bed", True)
        self.inFile.read(self.A.vector(), "/smb", True)

        self.H0.assign(self.S0 - self.B)

        self.Hmid = theta * self.H + (1 - theta) * self.H0

        self.S = self.B + self.Hmid

        self.width = df.interpolate(Width(degree=2), self.Q)

        self.strs = Stresses(self.U, self.Hmid, self.H0, self.H, self.width,
                             self.B, self.S, self.Phi)

        self.R = -(self.strs.tau_xx + self.strs.tau_xz + self.strs.tau_b +
                   self.strs.tau_d + self.strs.tau_xy) * df.dx

        #############################################################################
        ########################  MASS CONSERVATION  ################################
        #############################################################################
        self.h = df.CellSize(self.mesh)
        self.D = self.h * abs(self.U[0]) / 2.
        self.area = self.Hmid * self.width

        self.mesh_min = self.mesh.coordinates().min()
        self.mesh_max = self.mesh.coordinates().max()

        # Define boundaries
        self.ocean = df.FacetFunctionSizet(self.mesh, 0)
        self.ds = fc.ds(subdomain_data=self.ocean
                        )  # THIS DS IS FROM FENICS! border integral

        for f in df.facets(self.mesh):
            if df.near(f.midpoint().x(), self.mesh_max):
                self.ocean[f] = 1
            if df.near(f.midpoint().x(), self.mesh_min):
                self.ocean[f] = 2

        self.R += ((self.H - self.H0) / dt * self.xsi \
                   - self.xsi.dx(0) * self.U[0] * self.Hmid \
                   + self.D * self.xsi.dx(0) * self.Hmid.dx(0) \
                   - (self.A - self.U[0] * self.H / self.width * self.width.dx(0)) \
                   * self.xsi) * df.dx + self.U[0] * self.area * self.xsi * self.ds(1) \
                  - self.U[0] * self.area * self.xsi * self.ds(0)

        #####################################################################
        #########################  SOLVER SETUP   ###########################
        #####################################################################

        # Bounds
        self.l_thick_bound = df.project(Constant(thklim), self.Q)
        self.u_thick_bound = df.project(Constant(1e4), self.Q)

        self.l_v_bound = df.project(-10000.0, self.Q)
        self.u_v_bound = df.project(10000.0, self.Q)

        self.l_bound = df.Function(self.V)
        self.u_bound = df.Function(self.V)

        self.assigner.assign(self.l_bound,
                             [self.l_v_bound] * 2 + [self.l_thick_bound])
        self.assigner.assign(self.u_bound,
                             [self.u_v_bound] * 2 + [self.u_thick_bound])

        # This should set the velocity at the divide (left) to zero
        self.dbc0 = df.DirichletBC(
            self.V.sub(0), 0, lambda x, o: df.near(x[0], self.mesh_min) and o)
        # Set the velocity on the right terminus to zero
        self.dbc1 = df.DirichletBC(
            self.V.sub(0), 0, lambda x, o: df.near(x[0], self.mesh_max) and o)
        # overkill?
        self.dbc2 = df.DirichletBC(
            self.V.sub(1), 0, lambda x, o: df.near(x[0], self.mesh_max) and o)
        # set the thickness on the right edge to thklim
        self.dbc3 = df.DirichletBC(
            self.V.sub(2), thklim,
            lambda x, o: df.near(x[0], self.mesh_max) and o)

        # Define variational solver for the mass-momentum coupled problem
        self.J = df.derivative(self.R, self.U, self.dU)

        self.coupled_problem = df.NonlinearVariationalProblem(self.R, self.U, bcs=[self.dbc0, self.dbc1, self.dbc3], \
                                                              J=self.J)

        self.coupled_problem.set_bounds(self.l_bound, self.u_bound)

        self.coupled_solver = df.NonlinearVariationalSolver(
            self.coupled_problem)

        # Accquire the optimizations in fenics_optimizations
        set_solver_options(self.coupled_solver)

        self.t = 0
        self.timeEnd = float(timeEnd)
        self.dtFloat = float(timeStep)

        self.inFile.close()
Example #18
0
    infile.read(mesh)
mvc = MeshValueCollection("size_t", mesh, 1)
with XDMFFile(pygmsh_facets) as infile:
    infile.read(mvc, "name_to_read")
mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)

# Define function spaces for PDEs variational formulation.
P1 = FiniteElement('P', mesh.ufl_cell(),
                   1)  # Lagrange 1-order polynomials family
element = MixedElement([P1, P1, P1, P1])
V = FunctionSpace(mesh, element)

# Splitting test and trial functions
v_A, v_B, v_C, v_T = TestFunctions(V)  # Test functions
u = Function(V)
u_A, u_B, u_C, u_T = split(u)  # Trial functions, time step = n+1
u_n = Function(V)  # Trial functions, time step = n
_3u_n = Function(V)

# Retrieve boundaries marks for Robin boundary conditions.
ds_in = Measure("ds",
                domain=mesh,
                subdomain_data=mf,
                subdomain_id=Inletboundary_id)
ds_wall = Measure("ds",
                  domain=mesh,
                  subdomain_data=mf,
                  subdomain_id=Wallboundary_id)
"""Initial values (t == 0.0)"""
CAo = Constant(0.0)  # Initial composition for A
CBo = Constant(0.0)  # Initial composition for A
    def ab2tr_step(W, P, dt0, dt_1,
                   mu, rho,
                   u0, u_1, u_bcs,
                   dudt0, dudt_1, dudt_bcs,
                   p_1, p_bcs,
                   f0, f1,
                   tol=1.0e-12,
                   verbose=True
                   ):
        # General AB2/TR step.
        #
        # Steps are labeled in the following way:
        #
        #   * u_1: previous step.
        #   * u0:  current step.
        #   * u1:  next step.
        #
        # The same scheme applies to all other entities.
        #
        WP = W * P

        # Make sure the boundary conditions fit with the space.
        u_bcs_new = []
        for u_bc in u_bcs:
            u_bcs_new.append(DirichletBC(WP.sub(0),
                                         u_bc.value(),
                                         u_bc.user_sub_domain()))
        p_bcs_new = []
        for p_bc in p_bcs:
            p_bcs_new.append(DirichletBC(WP.sub(1),
                                         p_bc.value(),
                                         p_bc.user_sub_domain()))

        # Predict velocity.
        if dudt_1:
            u_pred = u0 \
                + 0.5*dt0*((2 + dt0/dt_1) * dudt0 - (dt0/dt_1) * dudt_1)
        else:
            # Simple linear extrapolation.
            u_pred = u0 + dt0 * dudt0

        uu = TrialFunctions(WP)
        vv = TestFunctions(WP)

        # Assign up[1] with u_pred and up[1] with p_1.
        # As of now (2013/09/05), there is no proper subfunction assignment in
        # Dolfin, cf.
        # <https://bitbucket.org/fenics-project/dolfin/issue/84/subfunction-assignment>.
        # Hence, we need to be creative here.
        # TODO proper subfunction assignment
        #
        # up1.assign(0, u_pred)
        # up1.assign(1, p_1)
        #
        up1 = Function(WP)
        a = (dot(uu[0],  vv[0]) + uu[1] * vv[1]) * dx
        L = dot(u_pred, vv[0]) * dx
        if p_1:
            L += p_1 * vv[1] * dx
        solve(a == L, up1,
              bcs=u_bcs_new + p_bcs_new
              )

        # Split up1 for easier access.
        # This is not as easy as it may seem at first, see
        # <http://fenicsproject.org/qa/1123/nonlinear-solves-with-mixed-function-spaces>.
        # Note in particular that
        #     u1, p1 = up1.split()
        # doesn't work here.
        #
        u1, p1 = split(up1)

        # Form the nonlinear equation system (3.16-235) in Gresho/Sani.
        # Left-hand side of the nonlinear equation system.
        F = 2.0/dt0 * rho * dot(u1, vv[0]) * dx \
            + mu * inner(grad(u1), grad(vv[0])) * dx \
            + rho * 0.5 * (inner(grad(u1)*u1, vv[0])
                           - inner(grad(vv[0]) * u1, u1)) * dx \
            + dot(grad(p1), vv[0]) * dx \
            + div(u1) * vv[1] * dx

        # Subtract the right-hand side.
        F -= dot(rho*(2.0/dt0*u0 + dudt0) + f1, vv[0]) * dx

        #J = derivative(F, up1)

        # Solve nonlinear system for u1, p1.
        solve(
            F == 0, up1,
            bcs=u_bcs_new + p_bcs_new,
            #J = J,
            solver_parameters={
              #'nonlinear_solver': 'snes',
              'nonlinear_solver': 'newton',
              'newton_solver': {'maximum_iterations': 5,
                                'report': True,
                                'absolute_tolerance': tol,
                                'relative_tolerance': 0.0
                                },
              'linear_solver': 'direct',
              #'linear_solver': 'iterative',
              ## The nonlinear term makes the problem
              ## generally nonsymmetric.
              #'symmetric': False,
              ## If the nonsymmetry is too strong, e.g., if
              ## u_1 is large, then AMG preconditioning
              ## might not work very well.
              #'preconditioner': 'ilu',
              ##'preconditioner': 'hypre_amg',
              #'krylov_solver': {'relative_tolerance': tol,
              #                  'absolute_tolerance': 0.0,
              #                  'maximum_iterations': 100,
              #                  'monitor_convergence': verbose}
              })

        ## Simpler access to the solution.
        #u1, p1 = up1.split()

        # Invert trapezoidal rule for next du/dt.
        dudt1 = 2 * (u1 - u0)/dt0 - dudt0

        # Get next dt.
        if dt_1:
            # Compute local trunction error (LTE) estimate.
            d = (u1 - u_pred) / (3*(1.0 + dt_1 / dt))
            # There are other ways of estimating the LTE norm.
            norm_d = numpy.sqrt(inner(d, d) / u_max**2)
            # Get next step size.
            dt1 = dt0 * (eps / norm_d)**(1.0/3.0)
        else:
            dt1 = dt0
        return u1, p1, dudt1, dt1
Example #20
0
File: pcd.py Project: NREL/pfibs
    def initialize(self, pc):
        if 'vp_spaces' not in self.ctx:
            raise ValueError("Must provide vp_spaces (velocity and pressure subspaces) to ctx")
        else:    
            self.vp_spaces = self.ctx['vp_spaces']
            if not isinstance(self.vp_spaces,list):
                raise TypeError('vp_spaces must be of type list()')
        if 'nu' not in self.ctx:
            raise ValueError('Must provide nu (viscosity) to ctx')
        else:
            self.nu = self.ctx['nu']
        self.V = self.vbp.V
        p = df.TrialFunction(self.V)
        q = df.TestFunction(self.V)
        p = df.split(p)[self.vp_spaces[1]]
        q = df.split(q)[self.vp_spaces[1]]
        u = df.split(self.vbp.u)[self.vp_spaces[0]]

        ## Mass term ##
        self.mP = df.Constant(1.0/self.nu)*p*q*df.dx
        
        ## Advection term ##
        self.aP = df.Constant(1.0/self.nu)*df.dot(df.grad(p), u)*q*df.dx

        ## Stiffness term ##
        self.kP = df.inner(df.grad(p), df.grad(q))*df.dx

        ## Create PETSc Matrices ##
        self.M_p = df.PETScMatrix()
        self.A_p = df.PETScMatrix()
        self.K_p = df.PETScMatrix()
        df.assemble(self.mP, tensor=self.M_p)
        df.assemble(self.aP, tensor=self.A_p)
        df.assemble(self.kP, tensor=self.K_p)
        
        ## Optionally apply BCs ##
        if 'bcs_kP' in self.ctx:
            self.applyBCs(self.K_p,self.ctx['bcs_kP'])
            self.bc_dofs, self.bc_value = self.extractBCs(self.ctx['bcs_kP'])
        
        ## Extract sub matrices ##
        self.M_submat = self.M_p.mat().createSubMatrix(self.isset,self.isset)
        self.A_submat = self.A_p.mat().createSubMatrix(self.isset,self.isset)
        self.K_submat = self.K_p.mat().createSubMatrix(self.isset,self.isset)

        ## KSP solver for mass matrix ##
        self.M_ksp = PETSc.KSP().create(comm=pc.comm)
        self.M_ksp.setType(PETSc.KSP.Type.GMRES)        # Default solver, can change 
        self.M_ksp.pc.setType(PETSc.PC.Type.BJACOBI)    # Default solver, can change
        self.M_ksp.incrementTabLevel(1, parent=pc)
        self.M_ksp.setOperators(self.M_submat)
        self.M_ksp.setOptionsPrefix(self.options_prefix+'mP_')
        self.M_ksp.setFromOptions()
        self.M_ksp.setUp()

        ## KSP solver for stiffness matrix ##
        self.K_ksp = PETSc.KSP().create(comm=pc.comm)
        self.K_ksp.setType(PETSc.KSP.Type.GMRES)        # Default solver, can change 
        self.K_ksp.pc.setType(PETSc.PC.Type.HYPRE)      # Default solver, can change
        self.K_ksp.incrementTabLevel(1, parent=pc)
        self.K_ksp.setOperators(self.K_submat)
        self.K_ksp.setOptionsPrefix(self.options_prefix+'aP_')
        self.K_ksp.setFromOptions()
        self.K_ksp.setUp()
geo_map.initialize(res, restart_folder=parameters["restart_folder"])

W = geo_map.mixed_space(4)

# Define trial and test functions
du = df.TrialFunction(W)
chi, xi, eta, etahat = df.TestFunctions(W)

# Define functions
u = df.TrialFunction(W)
u_ = df.Function(W, name="u_")  # current solution
u_1 = df.Function(W, name="u_1")  # solution from previous converged step

# Split mixed functions
psi,  mu, nu, nuhat = df.split(u)
psi_, mu_, nu_, nuhat_ = df.split(u_)
psi_1, mu_1, nu_1, nuhat_1 = df.split(u_1)

# Create intial conditions
if parameters["restart_folder"] is None:
    init_mode = parameters["init_mode"]
    if init_mode == "random":
        u_init = RandomIC(u_, amplitude=1e-1, degree=1)
    elif init_mode == "striped":
        u_init = StripedIC(u_, alpha=parameters["alpha"]*np.pi/180.0, degree=1)
    else:
        exit("No init_mode set.")
    u_1.interpolate(u_init)
    u_.assign(u_1)
else:
#==============================================================================
# define auxiliary operators
def a_operator(phi, psi):
    return inner(grad(phi), grad(psi)) / Re * dV


def b_operator(phi, psi):
    return div(phi) * psi * dV


def c_operator(phi, psi):
    return inner(grad(phi) * phi, psi) * dV


#==============================================================================
sol_v, sol_p = dlfn.split(sol)
sol_v0, _ = dlfn.split(sol0)
half = dlfn.Constant(0.5)
F_CN = (inner(sol_v, del_v) - inner(sol_v0, del_v)) * dV \
        + half * dt * ( a_operator(sol_v, del_v) + a_operator(sol_v0, del_v) )\
        + half * dt * ( c_operator(sol_v, del_v) + c_operator(sol_v0, del_v) )\
        - dt * b_operator(sol_v, del_p) \
        - dt * b_operator(del_v, sol_p)
J_newton = dlfn.derivative(F_CN, sol)
problem = dlfn.NonlinearVariationalProblem(F_CN, sol, bcs=bcs, J=J_newton)
solver = dlfn.NonlinearVariationalSolver(problem)
#==============================================================================
pvd_velocity = dlfn.File("results_{1}/Re_{0:d}/solution_velocity_Re_{0:d}.pvd".\
                     format(int(reynolds), "FEniCS"))
pvd_pressure = dlfn.File("results_{1}/Re_{0:d}/solution_pressure_Re_{0:d}.pvd".\
                     format(int(reynolds), "FEniCS"))
Example #23
0
    def left_boundary(x, on_boundary):
        return on_boundary and abs(x[0]) < tol

    def right_boundary(x, on_boundary):
        return on_boundary and abs(x[0] - 1) < tol

    # Define function space
    V = df.FunctionSpace(mesh, "Lagrange", p)
    V2 = df.MixedFunctionSpace([V, V])

    u = df.Function(V2)
    du = df.TrialFunction(V2)
    v = df.TestFunction(V2)

    u1, u2 = df.split(u)
    v1, v2 = df.split(v)

    # Initial Guesses
    u1_i = df.Expression("x[0]")
    u2_i = df.Expression("1-x[0]")

    # Impose boundary conditions for the solution to the nonlinear system
    bc = [
        df.DirichletBC(V2.sub(0), df.Constant(0.0), left_boundary),
        df.DirichletBC(V2.sub(0), df.Constant(1.0), right_boundary),
        df.DirichletBC(V2.sub(1), df.Constant(1.0), left_boundary),
        df.DirichletBC(V2.sub(1), df.Constant(0.0), right_boundary),
    ]

    # Make homogeneous version of BCs for the update
Example #24
0
density_function = df.Function(density_function_space)
pde_problem.add_input('density', density_function)
'''
4. 2. Add states
'''
# Define mixed function space-split into temperature and displacement FS
d = mesh.geometry().dim()
cell = mesh.ufl_cell()
displacement_fe = df.VectorElement("CG", cell, 1)
temperature_fe = df.FiniteElement("CG", cell, 1)

mixed_fs = df.FunctionSpace(mesh,
                            df.MixedElement([displacement_fe, temperature_fe]))
mixed_fs.sub(1).dofmap().dofs()
mixed_function = df.Function(mixed_fs)
displacements_function, temperature_function = df.split(mixed_function)

v, T_hat = df.TestFunctions(mixed_fs)

residual_form = get_residual_form(displacements_function, v, density_function,
                                  temperature_function, T_hat, KAPPA, K, ALPHA)

residual_form -=  (df.dot(f_r, v) * dss(10) + df.dot(f_t, v) * dss(14)  + \
                    q*T_hat*dss(5) + q_half*T_hat*dss(6) + q_quart*T_hat*dss(7))
print("get residual_form-------")
pde_problem.add_state('mixed_states', mixed_function, residual_form, 'density')
'''
4. 3. Add outputs
'''

# Add output-avg_density to the PDE problem:
Example #25
0
    def __init__(self, cparams, dtype_u, dtype_f):
        """
        Initialization routine

        Args:
            cparams: custom parameters for the example
            dtype_u: particle data type (will be passed parent class)
            dtype_f: acceleration data type (will be passed parent class)
        """

        # define the Dirichlet boundary
        def Boundary(x, on_boundary):
            return on_boundary

        # these parameters will be used later, so assert their existence
        assert 'c_nvars' in cparams
        assert 't0' in cparams
        assert 'family' in cparams
        assert 'order' in cparams
        assert 'refinements' in cparams

        # add parameters as attributes for further reference
        for k,v in cparams.items():
            setattr(self,k,v)

        df.set_log_level(df.WARNING)

        df.parameters["form_compiler"]["optimize"]     = True
        df.parameters["form_compiler"]["cpp_optimize"] = True

        # set mesh and refinement (for multilevel)
        # mesh = df.UnitIntervalMesh(self.c_nvars)
        # mesh = df.UnitSquareMesh(self.c_nvars[0],self.c_nvars[1])
        mesh = df.IntervalMesh(self.c_nvars,0,100)
        # mesh = df.RectangleMesh(0.0,0.0,2.0,2.0,self.c_nvars[0],self.c_nvars[1])
        for i in range(self.refinements):
            mesh = df.refine(mesh)

        # self.mesh = mesh
        # define function space for future reference
        V = df.FunctionSpace(mesh, self.family, self.order)
        self.V = V*V

        # invoke super init, passing number of dofs, dtype_u and dtype_f
        super(fenics_grayscott,self).__init__(self.V,dtype_u,dtype_f)

        # rhs in weak form
        self.w = df.Function(self.V)
        q1,q2 = df.TestFunctions(self.V)

        self.w1,self.w2 = df.split(self.w)

        self.F1 = (-self.Du*df.inner(df.nabla_grad(self.w1), df.nabla_grad(q1)) - self.w1*(self.w2**2)*q1 + self.A*(1-self.w1)*q1)*df.dx
        self.F2 = (-self.Dv*df.inner(df.nabla_grad(self.w2), df.nabla_grad(q2)) + self.w1*(self.w2**2)*q2 - self.B*    self.w2*q2)*df.dx
        self.F = self.F1+self.F2

        # mass matrix
        u1,u2 = df.TrialFunctions(self.V)
        a_M = u1*q1*df.dx
        M1 = df.assemble(a_M)
        a_M = u2*q2*df.dx
        M2 = df.assemble(a_M)
        self.M = M1+M2
Example #26
0
    def __init__(self, Vh, gamma, delta, mean=None, rel_tol=1e-12, max_iter=100):
        """
        Construct the prior model.
        Input:

        - :code:`Vh`:              the finite element space for the parameter
        - :code:`gamma` and :code:`delta`: the coefficient in the PDE
        - :code:`Theta`:           the SPD tensor for anisotropic diffusion of the PDE
        - :code:`mean`:            the prior mean
        """        
        assert delta != 0., "Intrinsic Gaussian Prior are not supported"
        self.Vh = Vh
        
        trial = dl.TrialFunction(Vh)
        test  = dl.TestFunction(Vh)
        
        varfL = dl.inner(dl.nabla_grad(trial), dl.nabla_grad(test))*dl.dx
        varfM = dl.inner(trial,test)*dl.dx
        
        self.M = dl.assemble(varfM)
        self.R = dl.assemble(gamma*varfL + delta*varfM)
        
        if dlversion() <= (1,6,0):
            self.Rsolver = dl.PETScKrylovSolver("cg", amg_method())
        else:
            self.Rsolver = dl.PETScKrylovSolver(self.Vh.mesh().mpi_comm(), "cg", amg_method())
        self.Rsolver.set_operator(self.R)
        self.Rsolver.parameters["maximum_iterations"] = max_iter
        self.Rsolver.parameters["relative_tolerance"] = rel_tol
        self.Rsolver.parameters["error_on_nonconvergence"] = True
        self.Rsolver.parameters["nonzero_initial_guess"] = False
        
        if dlversion() <= (1,6,0):
            self.Msolver = dl.PETScKrylovSolver("cg", "jacobi")
        else:
            self.Msolver = dl.PETScKrylovSolver(self.Vh.mesh().mpi_comm(), "cg", "jacobi")
        self.Msolver.set_operator(self.M)
        self.Msolver.parameters["maximum_iterations"] = max_iter
        self.Msolver.parameters["relative_tolerance"] = rel_tol
        self.Msolver.parameters["error_on_nonconvergence"] = True
        self.Msolver.parameters["nonzero_initial_guess"] = False
        
        ndim = Vh.mesh().geometry().dim()
        old_qr = dl.parameters["form_compiler"]["quadrature_degree"]
        dl.parameters["form_compiler"]["quadrature_degree"] = -1
        qdegree = 2*Vh._ufl_element.degree()
        metadata = {"quadrature_degree" : qdegree}
        
        if dlversion() >= (2017,1,0):
            representation_old = dl.parameters["form_compiler"]["representation"]
            dl.parameters["form_compiler"]["representation"] = "quadrature"
            
        if dlversion() <= (1,6,0):
            Qh = dl.VectorFunctionSpace(Vh.mesh(), 'Quadrature', qdegree, dim=(ndim+1) )
        else:
            element = dl.VectorElement("Quadrature", Vh.mesh().ufl_cell(),
                                       qdegree, dim=(ndim+1), quad_scheme="default")
            Qh = dl.FunctionSpace(Vh.mesh(), element)
            
        ph = dl.TrialFunction(Qh)
        qh = dl.TestFunction(Qh)
        
        pph = dl.split(ph)
        
        Mqh = dl.assemble(dl.inner(ph, qh)*dl.dx(metadata = metadata))
        ones = dl.Vector(self.R.mpi_comm())
        Mqh.init_vector(ones,0)
        ones.set_local( np.ones(ones.get_local().shape, dtype =ones.get_local().dtype ) )
        dMqh = Mqh*ones
        dMqh.set_local( ones.get_local() / np.sqrt(dMqh.get_local() ) )
        Mqh.zero()
        Mqh.set_diagonal(dMqh)
        
        sqrtdelta = math.sqrt(delta)
        sqrtgamma = math.sqrt(gamma)
        varfGG = sqrtdelta*pph[0]*test*dl.dx(metadata = metadata)
        for i in range(ndim):
            varfGG = varfGG + sqrtgamma*pph[i+1]*test.dx(i)*dl.dx(metadata = metadata)
            
        GG = dl.assemble(varfGG)
        self.sqrtR = MatMatMult(GG, Mqh)
        
        dl.parameters["form_compiler"]["quadrature_degree"] = old_qr
        
        if dlversion() >= (2017,1,0):
            dl.parameters["form_compiler"]["representation"] = representation_old
                        
        self.mean = mean
        
        if self.mean is None:
            self.mean = dl.Vector(self.R.mpi_comm())
            self.init_vector(self.mean, 0)
    def assembleSystem(self):
        """Assemble the FEM system. This is only run a single time before time-stepping. The values of the coefficient
        fields need to be updated between time-steps
        """
        # Loop through the entire model and composite the system of equations
        self.diffusors = []  # [[compartment, species, diffusivity of species],[ ...],[...]]
        """
           Diffusors have source terms
        """
        self.electrostatic_compartments = [] # (compartment) where electrostatic equations reside
        """
           Has source term
        """
        self.potentials = [] # (membrane)
        """
            No spatial derivatives, just construct ODE
        """
        self.channelvars = [] #(membrane, channel, ...)

        for compartment in self.compartments:
            s = 0
            for species in compartment.species:
                if compartment.diffusivities[species] < 1e-10: continue
                self.diffusors.extend([ [compartment,species,compartment.diffusivities[species]] ])
                s+=compartment.diffusivities[species]*abs(species.z)
            if s>0:
                self.electrostatic_compartments.extend([compartment])
                # Otherwise, there are no mobile charges in the compartment


        # the number of potentials is the number of spatial potentials + number of membrane potentials
        self.numdiffusers = len(self.diffusors)
        self.numpoisson = len(self.electrostatic_compartments)

        # Functions
        # Reaction-diffusion type
        #   Diffusers    :numdiffusers
        #
        # Coefficient
        #   Diffusivities
        self.V_np = dolfin.MixedFunctionSpace([self.v]*(self.numdiffusers))
        self.V_poisson = dolfin.MixedFunctionSpace([self.v]*self.numpoisson)
        #self.V = self.V_diff*self.V_electro
        self.V = dolfin.MixedFunctionSpace([self.v]*(self.numdiffusers+self.numpoisson))

        self.dofs_is = [self.V.sub(j).dofmap().dofs() for j in range(self.numdiffusers+self.numpoisson)]
        self.N = len(self.dofs_is[0])

        self.diffusivities = [dolfin.Function(self.v) for j in range(self.numdiffusers)]

        self.trialfunctions = dolfin.TrialFunctions(self.V)  # Trial function
        self.testfunctions = dolfin.TestFunctions(self.V) # test functions, one for each field

        self.sourcefunctions = [dolfin.Function(self.v) for j in range(self.numpoisson+self.numdiffusers)]

        self.permitivities = [dolfin.Function(self.v) for j in range(self.numpoisson)]

        # index the compartments!

        self.functions__ = dolfin.Function(self.V)

        self.np_assigner = dolfin.FunctionAssigner(self.V_np,[self.v]*self.numdiffusers)
        self.poisson_assigner = dolfin.FunctionAssigner(self.V_poisson,[self.v]*self.numpoisson)
        self.full_assigner = dolfin.FunctionAssigner(self.V,[self.v]*(self.numdiffusers+self.numpoisson))

        self.prev_value__ = dolfin.Function(self.V)
        self.prev_value_ = dolfin.split(self.prev_value__)
        self.prev_value = [dolfin.Function(self.v) for j in range(self.numdiffusers+self.numpoisson)]

        self.vfractionfunctions = [dolfin.Function(self.v) for j in range(len(self.compartments))]
        # Each reaction diffusion eqn should be indexed to a single volume fraction function
        # Each reaction diffusion eqn should be indexed to a single potential function
        # Each reaction diffusion eqn should be indexed to a single valence
        self.dt = dolfin.Constant(0.1)
        self.eqs = []
        self.phi = dolfin.Constant(phi)

        for membrane in self.membranes:
            self.potentials.extend([membrane])
            membrane.phi_m = np.ones(self.N)*membrane.phi_m
        self.num_membrane_potentials = len(self.potentials) # improve this

        """
            Assemble the equations for the system
            Order of equations:
            for compartment in compartments:
                for species in compartment.species
                    diffusion (in order)
                volume
                potential for electrodiffusion
            Membrane potentials


        """
        for j,compartment in enumerate(self.compartments):
            self.vfractionfunctions[j].vector()[:] = self.volfrac[compartment]

        # Set the reaction-diffusion equations
        for j,(trial,old,test,source,D,diffusor) in enumerate(zip(self.trialfunctions[:self.numdiffusers],self.prev_value_[:self.numdiffusers] \
                ,self.testfunctions[:self.numdiffusers], self.sourcefunctions[:self.numdiffusers]\
                ,self.diffusivities,self.diffusors)):
            """
            This instance of the loop corresponds to a diffusion species in self.diffusors
            """
            compartment_index = self.compartments.index(diffusor[0]) # we are in this compartment

            try:
                phi_index = self.electrostatic_compartments.index(diffusor[0]) + self.numdiffusers
                self.eqs.extend([ trial*test*dx-test*old*dx+ \
                        self.dt*(inner(D*nabla_grad(trial),nabla_grad(test)) + \
                        dolfin.Constant(diffusor[1].z/phi)*inner(D*trial*nabla_grad(self.prev_value[phi_index]),nabla_grad(test)))*dx   ])

                """
                self.eqs.extend([ trial*test*dx-test*old*dx+ \
                        self.dt*(inner(D*nabla_grad(trial),nabla_grad(test)) + \
                        dolfin.Constant(diffusor[1].z/phi)*inner(D*trial*nabla_grad(self.prev_value[phi_index]),nabla_grad(test)) - source*test)*dx   ])
                """
                # electrodiffusion here

            except ValueError:
                # No electrodiffusion for this species
                self.eqs.extend([trial*test*dx-old*test*dx+self.dt*(inner(D*nabla_grad(trial),nabla_grad(test))- source*test)*dx ])

            self.prev_value[j].vector()[:] = diffusor[0].value(diffusor[1])
            self.diffusivities[j].vector()[:] = diffusor[2]
            #diffusor[0].setValue(diffusor[1],self.prev_value[j].vector().array()) # do this below instead


        self.full_assigner.assign(self.prev_value__,self.prev_value)
        self.full_assigner.assign(self.functions__,self.prev_value)  # Initial guess for Newton

        """
        Vectorize the values that aren't already vectorized
        """
        for compartment in self.compartments:
            for j,(species, val) in enumerate(compartment.values.items()):
                try:
                    length = len(val)
                    compartment.internalVars.extend([(species,self.N,j*self.N)])
                    compartment.species_internal_lookup[species] = j*self.N
                except:
                    compartment.values[species]= np.ones(self.N)*val
                    #compartment.internalVars.extend([(species,self.N,j*self.N)])
                    compartment.species_internal_lookup[species] = j*self.N


        # Set the electrostatic eqns
        # Each equation is associated with a single compartment as defined in

        for j,(trial, test, source, eps, compartment) in enumerate(zip(self.trialfunctions[self.numdiffusers:],self.testfunctions[self.numdiffusers:], \
                self.sourcefunctions[self.numdiffusers:], self.permitivities, self.electrostatic_compartments)):
            # set the permitivity for this equation
            eps.vector()[:] = F**2*self.volfrac[compartment]/R/T \
                *sum([compartment.diffusivities[species]*species.z**2*compartment.value(species)  for species in compartment.species],axis=0)
            self.eqs.extend( [inner(eps*nabla_grad(trial),nabla_grad(test))*dx - source*test*dx] )

        compartmentfluxes = self.updateSources()

        #


        """
        Set indices for the "internal variables"
        List of tuples
        (compartment/membrane, num of variables)

        Each compartment or membrane has method
        getInternalVars()
        get_dot_InternalVars(t,values)
        get_jacobian_InternalVars(t,values)
        setInternalVars(values)

        The internal variables for each object are stored starting in
        y[obj.system_state_offset]
        """
        self.internalVars = []
        index = 0
        for membrane in self.membranes:
            index2 = 0
            for channel in membrane.channels:
                channeltmp = channel.getInternalVars()
                if channeltmp is not None:
                    self.internalVars.extend([ (channel, len(channeltmp),index2)])
                    channel.system_state_offset = index+index2
                    channel.internalLength = len(channeltmp)
                    index2+=len(channeltmp)
            tmp = membrane.getInternalVars()
            if tmp is not None:
                self.internalVars.extend( [(membrane,len(tmp),index)] )
                membrane.system_state_offset = index
                index += len(tmp)
                membrane.points = self.N
        """
        Compartments at the end, so we may reuse some computations
        """

        for compartment in self.compartments:
            index2 = 0
            compartment.system_state_offset = index  # offset for this object in the overall state
            for species, value in compartment.values.items():
                compartment.internalVars.extend([(species,len(compartment.value(species)),index2)])
                index2 += len(value)
            tmp = compartment.getInternalVars()
            self.internalVars.extend( [(compartment,len(tmp),index)] )
            index += len(tmp)
            compartment.points = self.N

        for key, val in self.volfrac.items():
            self.volfrac[key] = val*np.ones(self.N)

        """
        Solver setup below
        self.pdewolver is the FEM solver for the concentrations
        self.ode is the ODE solver for the membrane and volume fraction
        The ODE solve uses LSODA
        """
        # Define the problem and the solver
        self.equation = sum(self.eqs)
        self.equation_ = dolfin.action(self.equation, self.functions__)
        self.J = dolfin.derivative(self.equation_,self.functions__)
        ffc_options = {"optimize": True, \
            "eliminate_zeros": True, \
            "precompute_basis_const": True, \
            "precompute_ip_const": True, \
            "quadrature_degree": 2}
        self.problem = dolfin.NonlinearVariationalProblem(self.equation_, self.functions__, None, self.J, form_compiler_parameters=ffc_options)
        self.pdesolver  = dolfin.NonlinearVariationalSolver(self.problem)
        self.pdesolver.parameters['newton_solver']['absolute_tolerance'] = 1e-9
        self.pdesolver.parameters['newton_solver']['relative_tolerance'] = 1e-9

        """
        ODE integrator here. Add ability to customize the parameters in the future
        """
        self.t = 0.0
        self.odesolver = ode(self.ode_rhs) #
        self.odesolver.set_integrator('lsoda', nsteps=3000, first_step=1e-6, max_step=5e-3 )
        self.odesolver.set_initial_value(self.getInternalVars(),self.t)

        self.isAssembled = True
Example #28
0
def run_with_params(Tb, mu_value, k_s, path):
    run_time_init = clock()

    mesh = BoxMesh(Point(0.0, 0.0, 0.0), Point(mesh_width, mesh_width, mesh_height), nx, ny, nz)

    pbc = PeriodicBoundary()

    WE = VectorElement('CG', mesh.ufl_cell(), 2)
    SE = FiniteElement('CG', mesh.ufl_cell(), 1)
    WSSS = FunctionSpace(mesh, MixedElement(WE, SE, SE, SE), constrained_domain=pbc)
    # W = FunctionSpace(mesh, WE, constrained_domain=pbc)
    # S = FunctionSpace(mesh, SE, constrained_domain=pbc)
    W = WSSS.sub(0).collapse()
    S = WSSS.sub(1).collapse()

    temperature_vals = [27.0 + 273, Tb + 273, 1300.0 + 273, 1305.0 + 273]
    temp_prof = TemperatureProfile(temperature_vals, element=S.ufl_element())

    mu_a = mu_value  # this was taken from the Blankenbach paper, can change

    Ep = b / temp_prof.delta

    mu_bot = exp(-Ep * (temp_prof.bottom * temp_prof.delta - 1573.0) + cc) * mu_a

    # TODO: verify exponentiation
    Ra = rho_0 * alpha * g * temp_prof.delta * h ** 3 / (kappa_0 * mu_a)
    w0 = rho_0 * alpha * g * temp_prof.delta * h ** 2 / mu_a
    tau = h / w0
    p0 = mu_a * w0 / h

    log(mu_a, mu_bot, Ra, w0, p0)

    slip_vx = 1.6E-09 / w0  # Non-dimensional
    slip_velocity = Constant((slip_vx, 0.0, 0.0))
    zero_slip = Constant((0.0, 0.0, 0.0))

    time_step = 3.0E11 / tau * 2

    dt = Constant(time_step)
    t_end = 3.0E15 / tau / 5.0  # Non-dimensional times

    u = Function(WSSS)

    # Instead of TrialFunctions, we use split(u) for our non-linear problem
    v, p, T, Tf = split(u)
    v_t, p_t, T_t, Tf_t = TestFunctions(WSSS)

    T0 = interpolate(temp_prof, S)

    mu_exp = Expression('exp(-Ep * (T_val * dTemp - 1573.0) + cc * x[2] / mesh_height)',
                       Ep=Ep, dTemp=temp_prof.delta, cc=cc, mesh_height=mesh_height, T_val=T0,
                       element=S.ufl_element())

    Tf0 = interpolate(temp_prof, S)

    mu = Function(S)
    v0 = Function(W)

    v_theta = (1.0 - theta) * v0 + theta * v

    T_theta = (1.0 - theta) * T0 + theta * T

    Tf_theta = (1.0 - theta) * Tf0 + theta * Tf

    # TODO: Verify forms

    r_v = (inner(sym(grad(v_t)), 2.0 * mu * sym(grad(v)))
           - div(v_t) * p
           - T * v_t[2]) * dx

    r_p = p_t * div(v) * dx

    heat_transfer = Constant(k_s) * (Tf_theta - T_theta) * dt

    r_T = (T_t * ((T - T0) + dt * inner(v_theta, grad(T_theta)))  # TODO: Inner vs dot
           + (dt / Ra) * inner(grad(T_t), grad(T_theta))
           - T_t * heat_transfer) * dx

    v_melt = Function(W)
    z_hat = Constant((0.0, 0.0, 1.0))

    # TODO: inner -> dot, take out Tf_t
    r_Tf = (Tf_t * ((Tf - Tf0) + dt * inner(v_melt, grad(Tf_theta)))
            + Tf_t * heat_transfer) * dx

    r = r_v + r_p + r_T + r_Tf

    bcv0 = DirichletBC(WSSS.sub(0), zero_slip, top)
    bcv1 = DirichletBC(WSSS.sub(0), slip_velocity, bottom)
    bcv2 = DirichletBC(WSSS.sub(0).sub(1), Constant(0.0), back)
    bcv3 = DirichletBC(WSSS.sub(0).sub(1), Constant(0.0), front)

    bcp0 = DirichletBC(WSSS.sub(1), Constant(0.0), bottom)
    bct0 = DirichletBC(WSSS.sub(2), Constant(temp_prof.surface), top)
    bct1 = DirichletBC(WSSS.sub(2), Constant(temp_prof.bottom), bottom)
    bctf1 = DirichletBC(WSSS.sub(3), Constant(temp_prof.bottom), bottom)

    bcs = [bcv0, bcv1, bcv2, bcv3, bcp0, bct0, bct1, bctf1]

    t = 0
    count = 0
    files = DefaultDictByKey(partial(create_xdmf, path))

    while t < t_end:
        mu.interpolate(mu_exp)
        rhosolid = rho_0 * (1.0 - alpha * (T0 * temp_prof.delta - 1573.0))
        deltarho = rhosolid - rho_melt
        # TODO: project (accuracy) vs interpolate
        assign(v_melt, project(v0 - darcy * (grad(p) * p0 / h - deltarho * z_hat * g) / w0, W))
        # TODO: Written out one step later?
        # v_melt.assign(v0 - darcy * (grad(p) * p0 / h - deltarho * yvec * g) / w0)
        # TODO: use nP after to avoid projection?

        solve(r == 0, u, bcs)
        nV, nP, nT, nTf = u.split()  # TODO: write with Tf, ... etc

        if count % output_every == 0:
            time_left(count, t_end / time_step, run_time_init)  # TODO: timestep vs dt

            # TODO: Make sure all writes are to the same function for each time step
            files['T_fluid'].write(nTf, t)
            files['p'].write(nP, t)
            files['v_solid'].write(nV, t)
            files['T_solid'].write(nT, t)
            files['mu'].write(mu, t)
            files['v_melt'].write(v_melt, t)
            files['gradp'].write(project(grad(nP), W), t)
            files['rho'].write(project(rhosolid, S), t)
            files['Tf_grad'].write(project(grad(Tf), W), t)
            files['advect'].write(project(dt * dot(v_melt, grad(nTf))), t)
            files['ht'].write(project(heat_transfer, S), t)

        assign(T0, nT)
        assign(v0, nV)
        assign(Tf0, nTf)

        t += time_step
        count += 1

    log('Case mu={}, Tb={}, k={} complete. Run time = {:.2f} minutes'.format(mu_a, Tb, k_s, (clock() - run_time_init) / 60.0))
Example #29
0
  def __init__(self, PD, DD, verbosity):
    """
    Constructor
    :param ProblemData PD: Problem information and various mesh-region <-> xs-material mappings
    :param SNDiscretization DD: Discretization data
    :param int verbosity: Verbosity level.
    """

    self.max_group_GS_it = parameters["flux_module"]["group_GS"]["max_niter"]
    self.group_GS = self.max_group_GS_it > 0  

    try:
      PD.eigenproblem
    except AttributeError:
      PD.distribute_material_data(DD.cell_regions, DD.M)

    if PD.eigenproblem and self.group_GS:
      print "Group Gauss-Seidel for eigenproblem not yet supported - switching to all-group coupled solution method."
      self.group_GS = False

    if DD.G == 1:
      self.group_GS = True
      self.max_group_GS_it = 1

    DD.init_solution_spaces(self.group_GS)

    super(EllipticSNFluxModule, self).__init__(PD, DD, verbosity)

    if PD.fixed_source_problem:
      self.vals_Q = numpy.empty(self.DD.ndof,dtype='float64')

    if self.verb > 1: print0("Defining coefficient functions and tensors")

    if self.DD.V is self.DD.Vpsi1 or DD.G == 1:
      # shallow copies of trial/test functions - allows unified treatment of both mixed/single versions
      self.u = [self.u]*self.DD.G
      self.v = [self.v]*self.DD.G

      self.slns_mg = [self.sln]
      for g in range(1, self.DD.G):
        self.slns_mg.append(Function(self.DD.Vpsi1))

    else:
      self.u = split(self.u)
      self.v = split(self.v)

      # self.group_assigner = []
      # for g in range(self.DD.G):
      #   self.group_assigner.append(FunctionAssigner(self.DD.V.sub(g), self.DD.Vpsi1))

    # auxiliary single-group angular fluxes (used for monitoring convergence of the group GS iteration and computing
    # the true forward/adjoint angular fluxes)
    self.aux_slng = Function(self.DD.Vpsi1)

    # multigroup angular fluxes
    self.psi_mg = []
    for g in range(self.DD.G):
      self.psi_mg.append(Function(self.DD.Vpsi1))

    # multigroup adjoint angular fluxes
    self.adj_psi_mg = []
    for g in range(self.DD.G):
      self.adj_psi_mg.append(Function(self.DD.Vpsi1))

    self.D = Function(self.DD.V0)

    self.L = PD.scattering_order-1
    self.tensors = self.AngularTensors(self.DD.angular_quad, self.L)

    self.C = numpy.empty(self.L+1, Function)
    self.S = numpy.empty(self.L+1, Function)
    for l in range(self.L+1):
      self.C[l] = Function(self.DD.V0)
      self.S[l] = Function(self.DD.V0)

    for var in {"angular_flux", "adjoint_angular_flux"}:
      self.vis_files[var] = \
      [
        [
          File(os.path.join(self.vis_folder, "{}_g{}_m{}.pvd".format(var,g,m)), "compressed") for m in range(self.DD.M)
        ]
        for g in range(self.DD.G)
      ]

    self.__define_boundary_terms()
    def define_incompressible_functions(self):
        """
        Define mixed functions necessary to formulate an incompressible
        fluid mechanics problem. The mixed function is also split using
        dolfin.split (for use in UFL variational forms) and u.split(),
        where u is a mixed function (for saving solutions separately).
        The names of the member data added to the instance of the
        SolidMechanicsProblem class are:

        - :code:`sys_v`: mixed function
        - :code:`ufl_velocity`: sub component corresponding to velocity
        - :code:`velocity`: copy of sub component for writing and assigning
          values
        - :code:`ufl_pressure`: sub component corresponding to pressure
        - :code:`pressure`: copy of sub component for writing and assigning values
        - :code:`sys_du`: mixed trial function
        - :code:`trial_vector`: sub component of mixed trial function
        - :code:`trial_scalar`: sub component of mixed trial function
        - :code:`test_vector`: sub component of mixed test function
        - :code:`test_scalar`: sub component of mixed test function

        If problem is unsteady, the following are also added:

        - :code:`sys_v0`: mixed function at previous time step
        - :code:`ufl_velocity0`: sub component corresponding to velocity
        - :code:`velocity0`: copy of sub component for writing and assigning values
        - :code:`ufl_pressure0`: sub component at previous time step
        - :code:`pressure0`: copy of sub component at previous time step


        """

        self.sys_v = dlf.Function(self.functionSpace)
        self.ufl_velocity, self.ufl_pressure = dlf.split(self.sys_v)

        init = self.config['formulation']['initial_condition']
        types_for_assign = (dlf.Constant, dlf.Expression)
        if init['velocity'] is not None \
           and init['pressure'] is not None:
            if isinstance(init['velocity'], types_for_assign):
                self.velocity = dlf.Function(
                    self.functionSpace.sub(0).collapse())
                self.velocity.assign(init['velocity'])
            else:
                self.velocity = dlf.project(
                    init['velocity'],
                    self.functionSpace.sub(0).collapse())
            if isinstance(init['pressure'], types_for_assign):
                self.pressure = dlf.Function(
                    self.functionSpace.sub(1).collapse())
                self.pressure.assign(init['pressure'])
            else:
                self.pressure = dlf.project(
                    init['pressure'],
                    self.functionSpace.sub(1).collapse())
        elif init['velocity'] is not None:
            _, self.pressure = self.sys_v.split(deepcopy=True)
            if isinstance(init['velocity'], types_for_assign):
                self.velocity = dlf.Function(
                    self.functionSpace.sub(0).collapse())
                self.velocity.assign(init['velocity'])
            else:
                self.velocity = dlf.project(
                    init['velocity'],
                    self.functionSpace.sub(0).collapse())
        elif init['pressure'] is not None:
            self.velocity, _ = self.sys_v.split(deepcopy=True)
            if isinstance(init['pressure'], types_for_assign):
                self.pressure = dlf.Function(
                    self.functionSpace.sub(1).collapse())
                self.pressure.assign(init['pressure'])
            else:
                self.pressure = dlf.project(
                    init['pressure'],
                    self.functionSpace.sub(1).collapse())
        else:
            print("No initial conditions were provided")
            self.velocity, self.pressure = self.sys_v.split(deepcopy=True)

        self.velocity.rename("v", "velocity")
        self.pressure.rename("p", "pressure")

        self.sys_dv = dlf.TrialFunction(self.functionSpace)
        self.trial_vector, self.trial_scalar = dlf.split(self.sys_dv)
        self.test_vector, self.test_scalar = dlf.TestFunctions(
            self.functionSpace)

        if self.config['formulation']['time']['unsteady']:
            self.sys_v0 = self.sys_v.copy(deepcopy=True)

            self.ufl_velocity0, self.ufl_pressure0 = dlf.split(self.sys_v0)
            self.velocity0, self.pressure0 = self.sys_v0.split(deepcopy=True)
            self.velocity0.rename("v0", "velocity0")
            self.pressure0.rename("p0", "pressure0")

            self.define_ufl_acceleration()

        self.define_function_assigners()
        self.assigner_v2sys.assign(self.sys_v, [self.velocity, self.pressure])

        return None