Mentions légales du service

Skip to content
Snippets Groups Projects
fedic.py 41.4 KiB
Newer Older
Martin Genet's avatar
Martin Genet committed
#coding=utf8

################################################################################
###                                                                          ###
### Created by Martin Genet, 2016-2017                                       ###
###                                                                          ###
### École Polytechnique, Palaiseau, France                                   ###
###                                                                          ###
################################################################################
Martin Genet's avatar
Martin Genet committed

import dolfin
import glob
Martin Genet's avatar
Martin Genet committed
import numpy
import os
Martin Genet's avatar
Martin Genet committed

import myPythonLibrary as mypy
import myVTKPythonLibrary as myvtk
Martin Genet's avatar
Martin Genet committed

################################################################################
Martin Genet's avatar
Martin Genet committed

#dolfin.set_log_level(dolfin.CRITICAL)
#dolfin.set_log_level(dolfin.ERROR)
#dolfin.set_log_level(dolfin.WARNING)
#dolfin.set_log_level(dolfin.INFO)
#dolfin.set_log_level(dolfin.PROGRESS)
#dolfin.set_log_level(dolfin.TRACE)
#dolfin.set_log_level(dolfin.DBG)

dolfin.parameters["form_compiler"]["representation"] = "uflacs"
dolfin.parameters["form_compiler"]["optimize"] = True
#dolfin.parameters["form_compiler"]["cpp_optimize"] = False
#dolfin.parameters["form_compiler"]["cpp_optimize_flags"] = '-O0'

dolfin.parameters['allow_extrapolation'] = True # 2017-04-10: why do I need to do that?

# dolfin.parameters["num_threads"] = 8 # 2016-07-07: doesn't seem to work…
linear_solver = "default"
#linear_solver = "mumps"
Martin Genet's avatar
Martin Genet committed
#linear_solver = "petsc"
#linear_solver = "umfpack"

################################################################################
Martin Genet's avatar
Martin Genet committed

Martin Genet's avatar
Martin Genet committed
def fedic(
        working_folder,
        working_basename,
        images_folder,
        images_basename,
        images_ext="vti", # vti, vtk
        images_n_frames=None,
        images_ref_frame=0,
        images_quadrature_from="points_count", # points_count, integral
        images_expressions_type="cpp", # cpp, py
        images_dynamic_scaling=0,
        mesh=None,
        mesh_folder=None,
        mesh_basename=None,
Martin Genet's avatar
Martin Genet committed
        mesh_degree=1,
        regul_type="equilibrated", # hyperelastic, equilibrated
        regul_model="neohookean", # linear, kirchhoff, neohookean, mooneyrivlin
        regul_quadrature=None,
        regul_level=0.1,
        regul_poisson=0.0,
        tangent_type="Idef", # Idef, Idef-wHess, Iold, Iref
        residual_type="Iref", # Iref, Iold, Iref-then-Iold
Martin Genet's avatar
Martin Genet committed
        relax_type="gss", # constant, aitken, gss
Martin Genet's avatar
Martin Genet committed
        relax_init=1.0,
Martin Genet's avatar
Martin Genet committed
        tol_res=None,
Martin Genet's avatar
Martin Genet committed
        n_iter_max=100,
        print_refined_mesh=0,
Martin Genet's avatar
Martin Genet committed

Martin Genet's avatar
Martin Genet committed
    tab = 0
Martin Genet's avatar
Martin Genet committed

Martin Genet's avatar
Martin Genet committed
    if not os.path.exists(working_folder):
        os.mkdir(working_folder)

    mypy.print_str("Checking number of frames…",tab)
    image_filenames = glob.glob(images_folder+"/"+images_basename+"_[0-9]*"+"."+images_ext)
    images_zfill = len(image_filenames[0].rsplit("_",1)[-1].split(".",1)[0])
    #mypy.print_var("images_zfill",images_zfill,tab+1)
    if (images_n_frames is None):
        images_n_frames = len(image_filenames)
    assert (images_n_frames > 1),\
        "images_n_frames = "+str(images_n_frames)+" <= 1. Aborting."
    mypy.print_var("images_n_frames",images_n_frames,tab+1)
    assert (abs(images_ref_frame) < images_n_frames),\
        "abs(images_ref_frame) = "+str(images_ref_frame)+" >= images_n_frames. Aborting."
    images_ref_frame = images_ref_frame%images_n_frames
    mypy.print_var("images_ref_frame",images_ref_frame,tab+1)
    mypy.print_str("Loading mesh…",tab)
    assert ((mesh is not None) or ((mesh_folder is not None) and (mesh_basename is not None))),\
        "Must provide a mesh (mesh = "+str(mesh)+") or a mesh file (mesh_folder = "+str(mesh_folder)+", mesh_basename = "+str(mesh_basename)+"). Aborting."
    if (mesh is None):
        mesh_filebasename = mesh_folder+"/"+mesh_basename
        mesh_filename = mesh_filebasename+"."+"xml"
        assert (os.path.exists(mesh_filename)),\
            "No mesh in "+mesh_filename+". Aborting."
        mesh = dolfin.Mesh(mesh_filename)
    mypy.print_var("mesh_n_cells",len(mesh.cells()),tab+1)
    dV = dolfin.Measure(
        "dx",
        domain=mesh)
    dS = dolfin.Measure(
        "ds",
        domain=mesh)
    dF = dolfin.Measure(
        "dS",
        domain=mesh)
    mesh_V0 = dolfin.assemble(dolfin.Constant(1) * dV)
    mypy.print_sci("mesh_V0",mesh_V0,tab+1)
    if (print_refined_mesh):
        mesh_for_plot = dolfin.refine(mesh)
        function_space_for_plot = dolfin.VectorFunctionSpace(mesh_for_plot, "Lagrange", 1)
    mypy.print_str("Computing quadrature degree for images…",tab)
    ref_image_filename = images_folder+"/"+images_basename+"_"+str(images_ref_frame).zfill(images_zfill)+"."+images_ext
        if (images_quadrature_from == "points_count"):
            images_quadrature = ddic.compute_quadrature_degree_from_points_count(
                image_filename=ref_image_filename,
                mesh_filebasename=mesh_filebasename,
                verbose=1)
        elif (images_quadrature_from == "integral"):
            images_quadrature = ddic.compute_quadrature_degree_from_integral(
                image_filename=ref_image_filename,
                mesh=mesh,
                deg_min=1,
                deg_max=10,
                tol=1e-2,
                verbose=1)
    mypy.print_var("images_quadrature",images_quadrature,tab+1)
    form_compiler_parameters_for_images = {}
    form_compiler_parameters_for_images["quadrature_degree"] = images_quadrature

    mypy.print_str("Loading reference image…",tab)
    ref_image = myvtk.readImage(
        filename=ref_image_filename,
Martin Genet's avatar
Martin Genet committed
        verbose=0)
    images_dimension = myvtk.getImageDimensionality(
        image=ref_image,
Martin Genet's avatar
Martin Genet committed
        verbose=0)
    mypy.print_var("images_dimension",images_dimension,tab+1)
    assert (images_dimension in (2,3)),\
        "images_dimension must be 2 or 3. Aborting."
Martin Genet's avatar
Martin Genet committed
    fe = dolfin.FiniteElement(
        family="Quadrature",
Martin Genet's avatar
Martin Genet committed
        degree=images_quadrature,
        quad_scheme="default")
    ve = dolfin.VectorElement(
        family="Quadrature",
        cell=mesh.ufl_cell(),
Martin Genet's avatar
Martin Genet committed
        degree=images_quadrature,
    te = dolfin.TensorElement(
        family="Quadrature",
        cell=mesh.ufl_cell(),
        degree=images_quadrature,
        quad_scheme="default")
    te._quad_scheme = "default"                       # should not be needed
    for k in xrange(images_dimension**2):             # should not be needed
        te.sub_elements()[k]._quad_scheme = "default" # should not be needed
    if (images_expressions_type == "cpp"):
        Iref = dolfin.Expression(
                im_dim=images_dimension,
                im_type="im",
                im_is_def=0),
Martin Genet's avatar
Martin Genet committed
            element=fe)
        Iref.init_image(ref_image_filename)
        DIref = dolfin.Expression(
                im_dim=images_dimension,
                im_type="grad",
                im_is_def=0),
        DIref.init_image(ref_image_filename)
    elif (images_expressions_type == "py"):
        if (images_dimension == 2):
                filename=ref_image_filename,
                element=fe)
                filename=ref_image_filename,
                element=ve)
        elif (images_dimension == 3):
                filename=ref_image_filename,
                element=fe)
                filename=ref_image_filename,
                element=ve)
    else:
        assert (0), "\"images_expressions_type\" (="+str(images_expressions_type)+") must be \"cpp\" or \"py\". Aborting."
    Iref_int = dolfin.assemble(Iref * dV, form_compiler_parameters=form_compiler_parameters_for_images)/mesh_V0
    Iref_norm = (dolfin.assemble(Iref**2 * dV, form_compiler_parameters=form_compiler_parameters_for_images)/mesh_V0)**(1./2)
    assert (Iref_norm > 0.),\
        "Iref_norm = "+str(Iref_norm)+" <= 0. Aborting."
    mypy.print_var("Iref_int",Iref_int,tab+1)
    mypy.print_var("Iref_norm",Iref_norm,tab+1)

    file_error_basename = working_folder+"/"+working_basename+"-error"
    file_error = open(file_error_basename+".dat", "w")
    file_error.write("#k_frame err_im"+"\n")
    file_error.write(" ".join([str(val) for val in [images_ref_frame, 0.]])+"\n")
Martin Genet's avatar
Martin Genet committed

    mypy.print_str("Defining functions…",tab)
    function_space = dolfin.VectorFunctionSpace(
Martin Genet's avatar
Martin Genet committed
        mesh=mesh,
        family="Lagrange",
        degree=mesh_degree)
Martin Genet's avatar
Martin Genet committed
    U = dolfin.Function(
        function_space,
Martin Genet's avatar
Martin Genet committed
        name="displacement")
    U.vector().zero()
        function_space,
Martin Genet's avatar
Martin Genet committed
        name="previous displacement")
    Uold.vector().zero()
        function_space,
        name="previous displacement increment")
Martin Genet's avatar
Martin Genet committed
    dU = dolfin.Function(
        function_space,
Martin Genet's avatar
Martin Genet committed
        name="displacement correction")
    dU_trial = dolfin.TrialFunction(function_space)
    dU_test = dolfin.TestFunction(function_space)
Martin Genet's avatar
Martin Genet committed

    mypy.print_str("Printing initial solution…",tab)
    if not os.path.exists(working_folder):
        os.mkdir(working_folder)
    pvd_basename = working_folder+"/"+working_basename
    for vtu_filename in glob.glob(pvd_basename+"_[0-9]*.vtu"):
    file_pvd = dolfin.File(pvd_basename+"__.pvd")
    file_pvd << (U, float(images_ref_frame))
    os.remove(
        pvd_basename+"__.pvd")
    shutil.move(
        pvd_basename+"__"+"".zfill(6)+".vtu",
        pvd_basename+"_"+str(images_ref_frame).zfill(6)+".vtu")

    if (print_refined_mesh):
        U.set_allow_extrapolation(True)
        U_for_plot = dolfin.interpolate(U, function_space_for_plot)
        U_for_plot.rename("displacement", "a Function")
        file_pvd = dolfin.File(pvd_basename+"-refined__.pvd")
        file_pvd << (U_for_plot, float(images_ref_frame))
        os.remove(
            pvd_basename+"-refined__.pvd")
        shutil.move(
            pvd_basename+"-refined__"+"".zfill(6)+".vtu",
            pvd_basename+"-refined_"+str(images_ref_frame).zfill(6)+".vtu")

    if (print_iterations):
        for filename in glob.glob(working_folder+"/"+working_basename+"-frame=[0-9]*.*"):
            os.remove(filename)

    mypy.print_str("Defining regularization energy…",tab)
    E     = dolfin.Constant(1.0)
    nu    = dolfin.Constant(regul_poisson)
    kappa = E/3/(1-2*nu)                            # = E/3 if nu = 0
    lmbda = E*nu/(1+nu)/(1-(images_dimension-1)*nu) # = 0   if nu = 0
    mu    = E/2/(1+nu)                              # = E/2 if nu = 0
    C1    = mu/2                                    # = E/4 if nu = 0
    C2    = mu/2                                    # = E/4 if nu = 0
    D1    = kappa/2                                 # = E/6 if nu = 0
Martin Genet's avatar
Martin Genet committed
    I = dolfin.Identity(images_dimension)
    F = I + dolfin.grad(U)
    J = dolfin.det(F)
    if (regul_model == "linear"): # <- super bad
        e     = dolfin.sym(dolfin.grad(U))
        psi_m = (lmbda * dolfin.tr(e)**2 + 2*mu * dolfin.tr(e*e))/2
        if (int(dolfin.dolfin_version().split('.')[0]) >= 2017):
            e   = dolfin.variable(e)
            S_m = dolfin.diff(psi_m, e)
        else:
            S_m = lmbda * dolfin.tr(e) * I + 2*mu * e
    elif (regul_model in ("kirchhoff", "neohookean", "mooneyrivlin")):
        C = F.T * F
        E = (C - I)/2
        if (regul_model == "kirchhoff"): # <- pretty bad too
            psi_m = (lmbda * dolfin.tr(E)**2 + 2*mu * dolfin.tr(E*E))/2
            if (int(dolfin.dolfin_version().split('.')[0]) < 2017):
                S_m = lmbda * dolfin.tr(E) * I + 2*mu * E
        elif (regul_model in ("neohookean", "mooneyrivlin")):
            Ic    = dolfin.tr(C)
            Ic0   = dolfin.tr(I)
            if (int(dolfin.dolfin_version().split('.')[0]) < 2017):
                Cinv = dolfin.inv(C)
            if (regul_model == "neohookean"):
                psi_m = D1 * (J**2 - 1 - 2*dolfin.ln(J)) + C1 * (Ic - Ic0 - 2*dolfin.ln(J))
                if (int(dolfin.dolfin_version().split('.')[0]) < 2017):
                    S_m = 2*D1 * (J**2 - 1) * Cinv + 2*C1 * (I - Cinv)
            elif (regul_model == "mooneyrivlin"):
                IIc   = (dolfin.tr(C)**2 - dolfin.tr(C*C))/2
                IIc0  = (dolfin.tr(I)**2 - dolfin.tr(I*I))/2
                psi_m = D1 * (J**2 - 1 - 2*dolfin.ln(J)) + C1 * (Ic - Ic0 - 2*dolfin.ln(J)) + C2 * (IIc - IIc0 - 4*dolfin.ln(J))
                if (int(dolfin.dolfin_version().split('.')[0]) < 2017):
                    S_m = 2*D1 * (J**2 - 1) * Cinv + 2*C1 * (I - Cinv) + 2*C2 * (Ic * I - C - 2*Cinv)
        if (int(dolfin.dolfin_version().split('.')[0]) >= 2017):
            E   = dolfin.variable(E)
            S_m = dolfin.diff(psi_m, E)
        else:

        P_m   = F * S_m
        assert (0), "\"regul_model\" must be \"linear\", \"kirchhoff\", \"neohookean\", or \"mooneyrivlin\". Aborting."

    if (regul_type == "hyperelastic"):
        psi_m_V = psi_m
        psi_m_F = dolfin.Constant(0)
        psi_m_S = dolfin.Constant(0)
    elif (regul_type == "equilibrated"):
        Div_P = dolfin.div(P_m)
        psi_m_V = dolfin.dot(Div_P,
                             Div_P)
        N = dolfin.FacetNormal(mesh)
        Jump_P_N = dolfin.jump(P_m, N)
        psi_m_F = dolfin.dot(Jump_P_N,
                             Jump_P_N)/h
        #P_N = P_m * N
        #P_N_N = dolfin.dot(N, P_N)
        #P_N_T = P_N - P_N_N * N
        #psi_m_S  = dolfin.dot(P_N_T,
                              #P_N_T)/h
        #psi_m_S  = dolfin.dot(P_N,
                              #P_N)/h
        psi_m_S = dolfin.Constant(0)
    else:
        assert (0), "\"regul_type\" must be \"hyperelastic\" or \"equilibrated\". Aborting."
    Dpsi_m_V  = dolfin.derivative( psi_m_V, U, dU_test)
    DDpsi_m_V = dolfin.derivative(Dpsi_m_V, U, dU_trial)
    Dpsi_m_F  = dolfin.derivative( psi_m_F, U, dU_test)
    DDpsi_m_F = dolfin.derivative(Dpsi_m_F, U, dU_trial)
    Dpsi_m_S  = dolfin.derivative( psi_m_S, U, dU_test)
    DDpsi_m_S = dolfin.derivative(Dpsi_m_S, U, dU_trial)
    mesh_V = dolfin.assemble(J * dV)
    mypy.print_sci("mesh_V",mesh_V,tab+1)
    #regul_quadrature = 2*mesh_degree+1
    #regul_quadrature = 2*mesh_degree
    #regul_quadrature = mesh_degree+1
    #regul_quadrature = mesh_degree
    #regul_quadrature = 1
    regul_quadrature = None

    form_compiler_parameters_for_regul = {}
    form_compiler_parameters_for_regul["representation"] = "uflacs"
    if (regul_quadrature is not None):
        form_compiler_parameters_for_regul["quadrature_degree"] = regul_quadrature
    file_volume_basename = working_folder+"/"+working_basename+"-volume"
    file_volume = open(file_volume_basename+".dat","w")
Martin Genet's avatar
Martin Genet committed
    file_volume.write("#k_frame mesh_V"+"\n")
    file_volume.write(" ".join([str(val) for val in [images_ref_frame, mesh_V]])+"\n")

    mypy.print_str("Defining deformed image…",tab)
    scaling = numpy.array([1.,0.])
    if (images_expressions_type == "cpp"):
        Idef = dolfin.Expression(
                im_dim=images_dimension,
                im_type="im",
                im_is_def=1),
Martin Genet's avatar
Martin Genet committed
            element=fe)
        Idef.init_dynamic_scaling(scaling)
        DIdef = dolfin.Expression(
                im_dim=images_dimension,
                im_type="grad",
                im_is_def=1),
        Idef.init_dynamic_scaling(scaling)
        DIdef.init_disp(U)
            assert (0), "ToDo"
        Iold = dolfin.Expression(
                im_dim=images_dimension,
                im_type="im",
                im_is_def=1),
        Iold.init_dynamic_scaling(scaling) # 2016/07/25: ok, same scaling must apply to Idef & Iold…
        Iold.init_disp(Uold)
        DIold = dolfin.Expression(
                im_dim=images_dimension,
                im_type="grad",
                im_is_def=1),
        DIold.init_dynamic_scaling(scaling) # 2016/07/25: ok, same scaling must apply to Idef & Iold…
        DIold.init_disp(Uold)
    elif (images_expressions_type == "py"):
        if (images_dimension == 2):
                scaling=scaling,
                element=fe)
                U=U,
                scaling=scaling,
                element=ve)
            if ("-wHess" in tangent_type):
                    U=U,
                    scaling=scaling,
                    element=te)
                scaling=scaling, # 2016/07/25: ok, same scaling must apply to Idef & Iold…
                element=fe)
                scaling=scaling, # 2016/07/25: ok, same scaling must apply to Idef & Iold…
                element=ve)
        elif (images_dimension == 3):
                U=U,
                scaling=scaling,
                element=fe)
                U=U,
                scaling=scaling,
                element=ve)
            if ("-wHess" in tangent_type):
                    scaling=scaling, # 2016/07/25: ok, same scaling must apply to Idef & Iold…
                    element=te)
                U=Uold,
                scaling=scaling,
                element=fe)
                scaling=scaling, # 2016/07/25: ok, same scaling must apply to Idef & Iold…
                element=ve)
    else:
        assert (0), "\"images_expressions_type\" (="+str(images_expressions_type)+") must be \"cpp\" or \"py\". Aborting."

    mypy.print_str("Defining correlation energy…",tab)
    phi_Iref = dolfin.Expression(
        cppcode=ddic.get_ExprCharFuncIm_cpp(
            im_dim=images_dimension),
        element=fe)
    phi_Iref.init_image(ref_image_filename)
    psi_c   = phi_Iref * (Idef - Iref)**2/2
    Dpsi_c  = phi_Iref * (Idef - Iref) * dolfin.dot(DIdef, dU_test)
    DDpsi_c = phi_Iref * dolfin.dot(DIdef, dU_trial) * dolfin.dot(DIdef, dU_test)
    if ("-wHess" in tangent_type):
        DDpsi_c += (Idef - Iref) * dolfin.inner(dolfin.dot(DDIdef, dU_trial), dU_test)
    psi_c_old  = (Idef - Iold)**2/2
    Dpsi_c_old = (Idef - Iold) * dolfin.dot(DIdef, dU_test)
    DDpsi_c_old = dolfin.dot(DIold, dU_trial) * dolfin.dot(DIold, dU_test)
    DDpsi_c_ref = dolfin.dot(DIref, dU_trial) * dolfin.dot(DIref, dU_test)
    b0 = Iref * dolfin.dot(DIref, dU_test)
    B0 = dolfin.assemble(b0 * dV, form_compiler_parameters=form_compiler_parameters_for_images)
    res_norm0 = B0.norm("l2")
    assert (res_norm0 > 0.),\
        "res_norm0 = "+str(res_norm0)+" <= 0. Aborting."
    mypy.print_var("res_norm0",res_norm0,tab+1)

    A_c = None
    A_m = None
    A   = None
    if (tangent_type.startswith("Iref")):
        mypy.print_str("Matrix assembly (image term)…",tab,newline=False)
        t = time.time()
        A_c = dolfin.assemble(DDpsi_c_ref * dV, tensor=A_c, form_compiler_parameters=form_compiler_parameters_for_images)
        t = time.time() - t
        mypy.print_str(" "+str(t)+" s")
    if (regul_model == "linear"):
        mypy.print_str("Matrix assembly (regularization term)…",tab,newline=False)
        t = time.time()
        A_m = dolfin.assemble(DDpsi_m_V * dV + DDpsi_m_F * dF + DDpsi_m_S * dS, tensor=A_m, form_compiler_parameters=form_compiler_parameters_for_regul)
        t = time.time() - t
        mypy.print_str(" "+str(t)+" s")
    if (tangent_type.startswith("Iref")) and (regul_model == "linear"):
        mypy.print_str("Matrix assembly (combination)…",tab,newline=False)
        t = time.time()
        A = (1.-regul_level) * A_c + regul_level * A_m
        t = time.time() - t
        mypy.print_str(" "+str(t)+" s")
    B_c = None
    B_m = None
    B   = None

    mypy.print_str("Looping over frames…",tab)
Martin Genet's avatar
Martin Genet committed
    n_iter_tot = 0
Martin Genet's avatar
Martin Genet committed
    global_success = True
    for forward_or_backward in ["forward", "backward"]:
        mypy.print_var("forward_or_backward",forward_or_backward,tab)
Martin Genet's avatar
Martin Genet committed

        if (forward_or_backward == "forward"):
            k_frames_old = range(images_ref_frame  , images_n_frames-1, +1)
            k_frames     = range(images_ref_frame+1, images_n_frames  , +1)
Martin Genet's avatar
Martin Genet committed
        elif (forward_or_backward == "backward"):
            k_frames_old = range(images_ref_frame  ,  0, -1)
            k_frames     = range(images_ref_frame-1, -1, -1)
        mypy.print_var("k_frames",k_frames,tab)
Martin Genet's avatar
Martin Genet committed

        if (forward_or_backward == "backward"):
            U.vector().zero()
            Uold.vector().zero()
            DUold.vector().zero()
            scaling[:] = [1.,0.]
Martin Genet's avatar
Martin Genet committed

Martin Genet's avatar
Martin Genet committed
        tab += 1
        success = True
        for (k_frame,k_frame_old) in zip(k_frames,k_frames_old):
            mypy.print_var("k_frame",k_frame,tab-1)
Martin Genet's avatar
Martin Genet committed

            if (print_iterations):
Martin Genet's avatar
Martin Genet committed
                frame_basename = working_folder+"/"+working_basename+"-frame="+str(k_frame).zfill(images_zfill)
                file_dat_frame = open(frame_basename+".dat", "w")
                file_dat_frame.write("#k_iter res_norm err_res err_res_rel relax dU_norm U_norm err_dU im_diff err_im\n")
Martin Genet's avatar
Martin Genet committed

                file_pvd_frame = dolfin.File(frame_basename+"_.pvd")
                file_pvd_frame << (U, 0.)

            mypy.print_str("Loading image, image gradient and image hessian…",tab)
            image_filename = images_folder+"/"+images_basename+"_"+str(k_frame).zfill(images_zfill)+"."+images_ext
            Idef.init_image(image_filename)
            DIdef.init_image(image_filename)
                DDIdef.init_image(image_filename)
            image_filename = images_folder+"/"+images_basename+"_"+str(k_frame_old).zfill(images_zfill)+"."+images_ext
            Iold.init_image(image_filename)
            DIold.init_image(image_filename)
Martin Genet's avatar
Martin Genet committed
            # linear system: matrix
            if (tangent_type.startswith("Iold")):
                mypy.print_str("Matrix assembly (image term)…",tab,newline=False)
                t = time.time()
                A_c = dolfin.assemble(DDpsi_c_old * dV, tensor=A_c, form_compiler_parameters=form_compiler_parameters_for_images)
                t = time.time() - t
                mypy.print_str(" "+str(t)+" s")
            if (tangent_type.startswith("Iold")) and (regul_model == "linear"):
                mypy.print_str("Matrix assembly (combination)…",tab,newline=False)
                t = time.time()
                if (A is None):
                    A = (1.-regul_level) * A_c + regul_level * A_m
                    A.zero()
                    A.axpy(1.-regul_level, A_c, False)
                    A.axpy(   regul_level, A_m, False)
                t = time.time() - t
                mypy.print_str(" "+str(t)+" s")
Martin Genet's avatar
Martin Genet committed

Martin Genet's avatar
Martin Genet committed
            if (print_iterations):
                U.vector().zero()
                im_diff = (dolfin.assemble(psi_c * dV, form_compiler_parameters=form_compiler_parameters_for_images)/mesh_V0)**(1./2)
                err_im = im_diff/Iref_norm
                file_dat_frame.write(" ".join([str(val) for val in [-2, None, None, None, None, None, None, im_diff, err_im, None]])+"\n")
                im_diff = (dolfin.assemble(psi_c * dV, form_compiler_parameters=form_compiler_parameters_for_images)/mesh_V0)**(1./2)
                err_im = im_diff/Iref_norm
                file_dat_frame.write(" ".join([str(val) for val in [-1, None, None, None, None, None, None, im_diff, err_im, None]])+"\n")
Martin Genet's avatar
Martin Genet committed

            if (initialize_DU_with_DUold):
                U.vector().axpy(1., DUold.vector())

            mypy.print_str("Running registration…",tab)
Martin Genet's avatar
Martin Genet committed
            tab += 1
Martin Genet's avatar
Martin Genet committed
            k_iter = 0
            if   (residual_type.startswith("Iref")):
                using_Iold_residual = False
            elif (residual_type.startswith("Iold")):
                using_Iold_residual = True
Martin Genet's avatar
Martin Genet committed
            while (True):
                mypy.print_var("k_iter",k_iter,tab-1)
Martin Genet's avatar
Martin Genet committed
                n_iter_tot += 1

Martin Genet's avatar
Martin Genet committed
                # linear system: matrix assembly
                    mypy.print_str("Matrix assembly (image term)…",tab,newline=False)
                    t = time.time()
                    A_c = dolfin.assemble(DDpsi_c * dV, tensor=A_c, form_compiler_parameters=form_compiler_parameters_for_images)
                    t = time.time() - t
                    mypy.print_str(" "+str(t)+" s")
                if (regul_model != "linear"):
                    mypy.print_str("Matrix assembly (regularization term)…",tab,newline=False)
                    t = time.time()
                    A_m = dolfin.assemble(DDpsi_m_V * dV + DDpsi_m_F * dF + DDpsi_m_S * dS, tensor=A_m, form_compiler_parameters=form_compiler_parameters_for_regul)
                    t = time.time() - t
                    mypy.print_str(" "+str(t)+" s")
                if (tangent_type.startswith("Idef")) or (regul_model != "linear"):
                    mypy.print_str("Matrix assembly (combination)…",tab,newline=False)
                    t = time.time()
                    if (A is None):
                        A = (1.-regul_level) * A_c + regul_level * A_m
                        A.zero()
                        A.axpy(1.-regul_level, A_c, False)
                        A.axpy(   regul_level, A_m, False)
                    t = time.time() - t
                    mypy.print_str(" "+str(t)+" s")
                # linear system: residual assembly
                if (k_iter > 0):
Martin Genet's avatar
Martin Genet committed
                    if (k_iter == 1):
                        B_old = B.copy()
                    elif (k_iter > 1):
                        B_old[:] = B[:]
                mypy.print_str("Residual assembly (image term)…",tab,newline=False)
                t = time.time()
                    B_c = dolfin.assemble(Dpsi_c_old * dV, tensor=B_c, form_compiler_parameters=form_compiler_parameters_for_images)
                    B_c = dolfin.assemble(Dpsi_c * dV, tensor=B_c, form_compiler_parameters=form_compiler_parameters_for_images)
                t = time.time() - t
                mypy.print_str(" "+str(t)+" s")
                mypy.print_str("Residual assembly (regularization term)…",tab,newline=False)
                t = time.time()
                B_m = dolfin.assemble(Dpsi_m_V * dV + Dpsi_m_F * dF + Dpsi_m_S * dS, tensor=B_m, form_compiler_parameters=form_compiler_parameters_for_regul)
                t = time.time() - t
                mypy.print_str(" "+str(t)+" s")
                mypy.print_str("Residual assembly (combination)…",tab,newline=False)
                t = time.time()
                if (B is None):
                    B = -(1.-regul_level) * B_c - regul_level * B_m
                else:
                    B.zero()
                    B.axpy(-(1.-regul_level), B_c)
                    B.axpy(-    regul_level , B_m)
                t = time.time() - t
                mypy.print_str(" "+str(t)+" s")
                #mypy.print_var("B",B.array(),tab)
                res_norm = B.norm("l2")
                #mypy.print_sci("res_norm",res_norm,tab)
                err_res = res_norm/res_norm0
                mypy.print_sci("err_res",err_res,tab)

                if (k_iter == 0):
                    err_res_rel = 1.
                else:
                    if (k_iter == 1):
                        dB = B - B_old
                    elif (k_iter > 1):
                        dB[:] = B[:] - B_old[:]
                    dres_norm = dB.norm("l2")
                    err_res_rel = dres_norm / res_old_norm
                    mypy.print_sci("err_res_rel",err_res_rel,tab)
Martin Genet's avatar
Martin Genet committed

                # linear system: solve
Martin Genet's avatar
Martin Genet committed
                mypy.print_str("Solve…",tab,newline=False)
                t = time.time()
Martin Genet's avatar
Martin Genet committed
                dolfin.solve(A, dU.vector(), B,
                             linear_solver)
Martin Genet's avatar
Martin Genet committed
                t = time.time() - t
                mypy.print_str(" "+str(t)+" s")
                #mypy.print_var("dU",dU.vector().array(),tab)
Martin Genet's avatar
Martin Genet committed

                # relaxation
Martin Genet's avatar
Martin Genet committed
                if (relax_type == "constant"):
                    if (k_iter == 0):
                        relax = relax_init
                elif (relax_type == "aitken"):
                    if (k_iter == 0):
                        relax = relax_init
                    else:
                        relax *= (-1.) * B_old.inner(dB) / dres_norm**2
                    mypy.print_sci("relax",relax,tab)
Martin Genet's avatar
Martin Genet committed
                elif (relax_type == "gss"):
                    phi = (1 + math.sqrt(5)) / 2
                    relax_a = (1-phi)/(2-phi)
                    relax_b = 1/(2-phi)
                    need_update_c = True
                    need_update_d = True
                    relax_cur = 0.
                    relax_list = []
                    relax_vals = []
Martin Genet's avatar
Martin Genet committed
                    tab += 1
Martin Genet's avatar
Martin Genet committed
                    relax_k = 0
                    while (True):
                        mypy.print_var("relax_k",relax_k,tab-1)
                        mypy.print_sci("relax_a",relax_a,tab)
                        mypy.print_sci("relax_b",relax_b,tab)
Martin Genet's avatar
Martin Genet committed
                        if (need_update_c):
                            relax_c = relax_b - (relax_b - relax_a) / phi
                            relax_list.append(relax_c)
                            mypy.print_sci("relax_c",relax_c,tab)
Martin Genet's avatar
Martin Genet committed
                            U.vector().axpy(relax_c-relax_cur, dU.vector())
                            relax_cur = relax_c
                            if (using_Iold_residual):
                                relax_fc  = (1.-regul_level) * dolfin.assemble(psi_c_old * dV, form_compiler_parameters=form_compiler_parameters_for_images)
                                relax_fc  = (1.-regul_level) * dolfin.assemble(psi_c * dV, form_compiler_parameters=form_compiler_parameters_for_images)
                            #mypy.print_sci("relax_fc",relax_fc,tab)
                            relax_fc += regul_level * dolfin.assemble(psi_m_V * dV + psi_m_F * dF + psi_m_S * dS, form_compiler_parameters=form_compiler_parameters_for_regul)
                            #mypy.print_sci("relax_fc",relax_fc,tab)
Martin Genet's avatar
Martin Genet committed
                            if (numpy.isnan(relax_fc)):
                                relax_fc = float('+inf')
                                #mypy.print_sci("relax_fc",relax_fc,tab)
                            mypy.print_sci("relax_fc",relax_fc,tab)
Martin Genet's avatar
Martin Genet committed
                            relax_vals.append(relax_fc)
                            #mypy.print_var("relax_list",relax_list,tab)
                            #mypy.print_var("relax_vals",relax_vals,tab)
Martin Genet's avatar
Martin Genet committed
                        if (need_update_d):
                            relax_d = relax_a + (relax_b - relax_a) / phi
                            relax_list.append(relax_d)
                            mypy.print_sci("relax_d",relax_d,tab)
Martin Genet's avatar
Martin Genet committed
                            U.vector().axpy(relax_d-relax_cur, dU.vector())
                            relax_cur = relax_d
                            if (using_Iold_residual):
                                relax_fd  = (1.-regul_level) * dolfin.assemble(psi_c_old * dV, form_compiler_parameters=form_compiler_parameters_for_images)
                                relax_fd  = (1.-regul_level) * dolfin.assemble(psi_c * dV, form_compiler_parameters=form_compiler_parameters_for_images)
                            #mypy.print_sci("relax_fd",relax_fd,tab)
                            relax_fd += regul_level * dolfin.assemble(psi_m_V * dV + psi_m_F * dF + psi_m_S * dS, form_compiler_parameters=form_compiler_parameters_for_regul)
                            #mypy.print_sci("relax_fd",relax_fd,tab)
Martin Genet's avatar
Martin Genet committed
                            if (numpy.isnan(relax_fd)):
                                relax_fd = float('+inf')
                                #mypy.print_sci("relax_fd",relax_fd,tab)
                            #mypy.print_sci("relax_fd",relax_fd,tab)
Martin Genet's avatar
Martin Genet committed
                            relax_vals.append(relax_fd)
                            #mypy.print_var("relax_list",relax_list,tab)
                            #mypy.print_var("relax_vals",relax_vals,tab)
Martin Genet's avatar
Martin Genet committed
                        if (relax_fc < relax_fd):
                            relax_b = relax_d
                            relax_d = relax_c
                            relax_fd = relax_fc
                            need_update_c = True
                            need_update_d = False
                        elif (relax_fc > relax_fd):
                            relax_a = relax_c
                            relax_c = relax_d
                            relax_fc = relax_fd
                            need_update_c = False
                            need_update_d = True
                        else: assert(0)
                        if (relax_k >= 5) and (numpy.argmin(relax_vals) > 0):
                            break
                        relax_k += 1
Martin Genet's avatar
Martin Genet committed
                    U.vector().axpy(-relax_cur, dU.vector())
                    #mypy.print_var("relax_vals",relax_vals,tab)
                    if (print_iterations):
Martin Genet's avatar
Martin Genet committed
                        iter_basename = frame_basename+"-iter="+str(k_iter).zfill(3)
                        file_dat_iter = open(iter_basename+".dat","w")
                        file_dat_iter.write("\n".join([" ".join([str(val) for val in [relax_list[relax_k], relax_vals[relax_k]]]) for relax_k in xrange(len(relax_list))]))
                        file_dat_iter.close()
                        os.system("gnuplot -e \"set terminal pdf; set output '"+iter_basename+".pdf'; plot '"+iter_basename+".dat' using 1:2 with points title 'psi_int'; plot '"+iter_basename+".dat' using (\$2=='inf'?\$1:1/0):(GPVAL_Y_MIN+(0.8)*(GPVAL_Y_MAX-GPVAL_Y_MIN)):(0):((0.2)*(GPVAL_Y_MAX-GPVAL_Y_MIN)) with vectors notitle, '"+iter_basename+".dat' u 1:2 with points title 'psi_int'\"")

                    relax = relax_list[numpy.argmin(relax_vals)]
                    mypy.print_sci("relax",relax,tab)
Martin Genet's avatar
Martin Genet committed
                else:
Martin Genet's avatar
Martin Genet committed
                    assert (0), "relax_type must be \"constant\", \"aitken\" or \"gss\". Aborting."
Martin Genet's avatar
Martin Genet committed

                # solution update
                U.vector().axpy(relax, dU.vector())
                U_norm = U.vector().norm("l2")
Martin Genet's avatar
Martin Genet committed

                if (print_iterations):
                    #mypy.print_var("U",U.vector().array(),tab)
Martin Genet's avatar
Martin Genet committed
                    file_pvd_frame << (U, float(k_iter+1))
Martin Genet's avatar
Martin Genet committed

                # displacement error
Martin Genet's avatar
Martin Genet committed
                dU_norm = abs(relax) * dU.vector().norm("l2")
                if (dU_norm == 0.) and (Uold_norm == 0.) and (U_norm == 0.):
                elif (Uold_norm == 0.):
                    err_dU = dU_norm/Uold_norm
                mypy.print_sci("err_dU",err_dU,tab)
Martin Genet's avatar
Martin Genet committed

                # image error
Martin Genet's avatar
Martin Genet committed
                if (k_iter > 0):
                im_diff = (dolfin.assemble(psi_c * dV, form_compiler_parameters=form_compiler_parameters_for_images)/mesh_V0)**(1./2)
                #mypy.print_sci("im_diff",im_diff,tab)
                err_im = im_diff/Iref_norm
                mypy.print_sci("err_im",err_im,tab)
Martin Genet's avatar
Martin Genet committed

                if (print_iterations):
                    file_dat_frame.write(" ".join([str(val) for val in [k_iter, res_norm, err_res, err_res_rel, relax, dU_norm, U_norm, err_dU, im_diff, err_im]])+"\n")
Martin Genet's avatar
Martin Genet committed

                # exit test
                if (tol_res is not None) and (err_res > tol_res):
                    success = False
                if (tol_res_rel is not None) and (err_res_rel > tol_res_rel):
                if (tol_dU is not None) and (err_dU > tol_dU):
                if (tol_im is not None) and (err_im > tol_im):
Martin Genet's avatar
Martin Genet committed
                if (success):
                    mypy.print_str("Nonlinear solver converged…",tab)
Martin Genet's avatar
Martin Genet committed
                    break

Martin Genet's avatar
Martin Genet committed
                if (k_iter == n_iter_max-1):
                    if (residual_type=="Iref-then-Iold") and not (using_Iold_residual):
                        mypy.print_str("Warning! Nonlinear solver failed to converge…using Iold instead of Iref. (k_frame = "+str(k_frame)+")",tab)
                        using_Iold_residual = True
                        U.vector()[:] = Uold.vector()[:]
                        U_norm = Uold_norm
                        k_iter = 0
                        continue
                    else:
                        mypy.print_str("Warning! Nonlinear solver failed to converge… (k_frame = "+str(k_frame)+")",tab)
Martin Genet's avatar
Martin Genet committed

                # increment counter
                k_iter += 1

Martin Genet's avatar
Martin Genet committed
            tab -= 1

Martin Genet's avatar
Martin Genet committed
            if (print_iterations):
                os.remove(frame_basename+"_.pvd")
Martin Genet's avatar
Martin Genet committed
                file_dat_frame.close()
                os.system("gnuplot -e \"set terminal pdf; set output '"+frame_basename+".pdf'; set key box textcolor variable; set grid; set logscale y; set yrange [1e-3:1e0]; plot '"+frame_basename+".dat' u 1:3 pt 1 lw 3 title 'err_res', '' u 1:8 pt 1 lw 3 title 'err_dU', '' using 1:10 pt 1 lw 3 title 'err_im', "+str(tol_res or tol_dU or tol_im)+" lt -1 notitle; unset logscale y; set yrange [*:*]; plot '' u 1:4 pt 1 lw 3 title 'relax'\"")
Martin Genet's avatar
Martin Genet committed

            if not (success) and not (continue_after_fail):
                break

            DUold.vector()[:] = U.vector()[:] - Uold.vector()[:]
            Uold.vector()[:] = U.vector()[:]
            Uold_norm = U_norm
            mesh_V = dolfin.assemble(J * dV)
            mypy.print_sci("mesh_V",mesh_V,tab+1)
Martin Genet's avatar
Martin Genet committed
            file_volume.write(" ".join([str(val) for val in [k_frame, mesh_V]])+"\n")

            mypy.print_str("Printing solution…",tab)
            file_pvd = dolfin.File(pvd_basename+"__.pvd")
Martin Genet's avatar
Martin Genet committed
            file_pvd << (U, float(k_frame))
            os.remove(
                pvd_basename+"__.pvd")
            shutil.move(
                pvd_basename+"__"+"".zfill(6)+".vtu",
                pvd_basename+"_"+str(k_frame).zfill(6)+".vtu")
Martin Genet's avatar
Martin Genet committed

            if (print_refined_mesh):
                U_for_plot = dolfin.interpolate(U, function_space_for_plot)
                U_for_plot.rename("displacement", "a Function")
                file_pvd = dolfin.File(pvd_basename+"-refined__.pvd")
                file_pvd << (U_for_plot, float(k_frame))
                os.remove(
                    pvd_basename+"-refined__.pvd")
                shutil.move(
                    pvd_basename+"-refined__"+"".zfill(6)+".vtu",
                    pvd_basename+"-refined_"+str(k_frame).zfill(6)+".vtu")

            if (images_dynamic_scaling):
                p = numpy.empty((2,2))
                q = numpy.empty(2)
                p[0,0] = dolfin.assemble(Idef**2 * dV, form_compiler_parameters=form_compiler_parameters_for_images)
                p[0,1] = dolfin.assemble(Idef * dV, form_compiler_parameters=form_compiler_parameters_for_images)
                p[1,0] = p[0,1]
                p[1,1] = 1.
                q[0] = dolfin.assemble(Idef*Iref * dV, form_compiler_parameters=form_compiler_parameters_for_images)
                q[1] = dolfin.assemble(Iref * dV, form_compiler_parameters=form_compiler_parameters_for_images)
                scaling[:] = numpy.linalg.solve(p,q)
                mypy.print_var("scaling",scaling,tab)

                if (images_expressions_type == "cpp"):         # should not be needed
                    Idef.update_dynamic_scaling(scaling)       # should not be needed
                    DIdef.update_dynamic_scaling(scaling)      # should not be needed
                    if ("-wHess" in tangent_type):             # should not be needed
                        DDIdef.update_dynamic_scaling(scaling) # should not be needed
                    Iold.update_dynamic_scaling(scaling)       # should not be needed
                    DIold.update_dynamic_scaling(scaling)      # should not be needed
                im_diff = (dolfin.assemble(psi_c * dV, form_compiler_parameters=form_compiler_parameters_for_images)/mesh_V0)**(1./2)
                err_im = im_diff/Iref_norm
                mypy.print_sci("err_im",err_im,tab)

            file_error.write(" ".join([str(val) for val in [k_frame, err_im]])+"\n")
Martin Genet's avatar
Martin Genet committed
        tab -= 1

Martin Genet's avatar
Martin Genet committed
        if not (success) and not (continue_after_fail):
            break

    mypy.print_var("n_iter_tot",n_iter_tot,tab)

    file_error.close()
    os.system("gnuplot -e \"set terminal pdf; set output '"+file_error_basename+".pdf'; set grid; set yrange [0:1]; plot '"+file_error_basename+".dat' u 1:2 lw 3 notitle\"")
Martin Genet's avatar
Martin Genet committed

Martin Genet's avatar
Martin Genet committed
    file_volume.close()
    os.system("gnuplot -e \"set terminal pdf; set output '"+file_volume_basename+".pdf'; set grid; set yrange [0:*]; plot '"+file_volume_basename+".dat' u 1:2 lw 3 notitle\"")
Martin Genet's avatar
Martin Genet committed

Martin Genet's avatar
Martin Genet committed
    return global_success