Exemple #1
0
def test_Probes_vectorfunctionspace_3D(VF3, dirpath):
    u0 = interpolate(Expression(('x[0]', 'x[1]', 'x[2]'), degree=1), VF3)
    x = array([[0.5, 0.5, 0.5], [0.4, 0.4, 0.4], [0.3, 0.3, 0.3]])

    p = Probes(x.flatten(), VF3)
    # Probe twice
    p(u0)
    p(u0)

    # Check both snapshots
    p0 = p.array(N=0)

    if MPI.rank(MPI.comm_world) == 0:
        assert round(p0[0, 0] - 0.5, 7) == 0
        assert round(p0[1, 1] - 0.4, 7) == 0
        assert round(p0[2, 2] - 0.3, 7) == 0
    p0 = p.array(N=1)
    if MPI.rank(MPI.comm_world) == 0:
        assert round(p0[0, 0] - 0.5, 7) == 0
        assert round(p0[1, 1] - 0.4, 7) == 0
        assert round(p0[2, 2] - 0.3, 7) == 0

    p0 = p.array(filename=dirpath+'dumpvector3D')
    if MPI.rank(MPI.comm_world) == 0:
        assert round(p0[0, 0, 0] - 0.5, 7) == 0
        assert round(p0[1, 1, 0] - 0.4, 7) == 0
        assert round(p0[2, 1, 0] - 0.3, 7) == 0

        p1 = load(dirpath+'dumpvector3D_all.npy')
        assert round(p1[0, 0, 0] - 0.5, 7) == 0
        assert round(p1[1, 1, 0] - 0.4, 7) == 0
        assert round(p1[2, 1, 1] - 0.3, 7) == 0
Exemple #2
0
def test_Probes_vectorfunctionspace_2D(VF2, dirpath):
    u0 = interpolate(Expression(('x[0]', 'x[1]'), degree=1), VF2)
    x = array([[0.5, 0.5], [0.4, 0.4], [0.3, 0.3]])

    p = Probes(x.flatten(), VF2)

    # Probe twice
    p(u0)
    p(u0)

    # Check both snapshots
    p0 = p.array(N=0)
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0, 0] - 0.5, 7) == 0
        assert round(p0[1, 1] - 0.4, 7) == 0
        assert round(p0[2, 1] - 0.3, 7) == 0
    p0 = p.array(N=1)
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0, 0] - 0.5, 7) == 0
        assert round(p0[1, 0] - 0.4, 7) == 0
        assert round(p0[2, 1] - 0.3, 7) == 0

    p0 = p.array(filename=dirpath + 'dumpvector2D')
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0, 0, 0] - 0.5, 7) == 0
        assert round(p0[1, 1, 1] - 0.4, 7) == 0
        assert round(p0[2, 0, 1] - 0.3, 7) == 0

        f = open(dirpath + 'dumpvector2D_all.probes', 'r')
        p1 = load(f)
        assert round(p1[0, 0, 0] - 0.5, 7) == 0
        assert round(p1[1, 1, 0] - 0.4, 7) == 0
        assert round(p1[2, 1, 1] - 0.3, 7) == 0
Exemple #3
0
def theend_hook(q_, u_, p_, uv, mesh, ds, V, nu, Umean, D, **NS_namespace):
    uv()
    plot(uv, title='Velocity')
    plot(p_, title='Pressure')
    plot(q_['alfa'], title='alfa')
    R = VectorFunctionSpace(mesh, 'R', 0)
    c = TestFunction(R)
    tau = -p_*Identity(2)+nu*(grad(u_)+grad(u_).T)
    ff = FacetFunction("size_t", mesh, 0)
    Cyl.mark(ff, 1)
    n = FacetNormal(mesh)
    ds = ds[ff]
    forces = assemble(dot(dot(tau, n), c)*ds(1)).array()*2/Umean**2/D
    
    print "Cd = {}, CL = {}".format(*forces)

    from fenicstools import Probes
    from numpy import linspace, repeat, where, resize
    xx = linspace(0, L, 10000)
    x = resize(repeat(xx, 2), (10000, 2))
    x[:, 1] = 0.2
    probes = Probes(x.flatten(), V)
    probes(u_[0])
    nmax = where(probes.array() < 0)[0][-1]
    print "L = ", x[nmax, 0]-0.25
    print "dP = ", p_(Point(0.15, 0.2)) - p_(Point(0.25, 0.2))
def test_Probes_vectorfunctionspace_2D(VF2, dirpath):
    u0 = interpolate(Expression(('x[0]', 'x[1]')), VF2)
    x = array([[0.5, 0.5], [0.4, 0.4], [0.3, 0.3]])
    
    p = Probes(x.flatten(), VF2)

    # Probe twice
    p(u0)
    p(u0)
    
    # Check both snapshots
    p0 = p.array(N=0)
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0, 0] - 0.5, 7) == 0
        assert round(p0[1, 1] - 0.4, 7) == 0
        assert round(p0[2, 1] - 0.3, 7) == 0
    p0 = p.array(N=1)
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0, 0] - 0.5, 7) == 0
        assert round(p0[1, 0] - 0.4, 7) == 0
        assert round(p0[2, 1] - 0.3, 7) == 0

    p0 = p.array(filename=dirpath+'dumpvector2D')
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0, 0, 0] - 0.5, 7) == 0
        assert round(p0[1, 1, 1] - 0.4, 7) == 0
        assert round(p0[2, 0, 1] - 0.3, 7) == 0
        
        f = open(dirpath+'dumpvector2D_all.probes', 'r')
        p1 = load(f)
        assert round(p1[0, 0, 0] - 0.5, 7) == 0
        assert round(p1[1, 1, 0] - 0.4, 7) == 0
        assert round(p1[2, 1, 1] - 0.3, 7) == 0
Exemple #5
0
def theend_hook(u_, p_, up_, mesh, ds, VQ, nu, Umean, c_, testing, **NS_namespace):
    if not testing:
        plot(u_, title='Velocity')
        plot(p_, title='Pressure')
        plot(c_, title='Scalar')

    R = VectorFunctionSpace(mesh, 'R', 0)
    c = TestFunction(R)
    tau = -p_*Identity(2)+nu*(grad(u_)+grad(u_).T)
    ff = FacetFunction("size_t", mesh, 0)
    Cyl.mark(ff, 1)
    n = FacetNormal(mesh)
    ds = ds(subdomain_data=ff)
    forces = assemble(dot(dot(tau, n), c)*ds(1)).array()*2/Umean**2/D
    
    try:
        print "Cd = {0:2.6e}, CL = {1:2.6e}".format(*forces)
        
    except IndexError:
        pass

    if not testing:
        from fenicstools import Probes
        from numpy import linspace, repeat, where, resize
        xx = linspace(0, L, 10000)
        x = resize(repeat(xx, 2), (10000, 2))
        x[:, 1] = 0.2
        probes = Probes(x.flatten(), VQ)
        probes(up_)
        nmax = where(probes.array()[:, 0] < 0)[0][-1]
        print "L = ", x[nmax, 0]-0.25
        print "dP = ", up_(Point(0.15, 0.2))[2] - up_(Point(0.25, 0.2))[2]
        print "Global divergence error ", assemble(dot(u_, n)*ds()), assemble(div(u_)*div(u_)*dx())
Exemple #6
0
def theend_hook(q_, u_, p_, uv, mesh, ds, V, nu, Umean, D, **NS_namespace):
    uv()
    plot(uv, title='Velocity')
    plot(p_, title='Pressure')
    plot(q_['alfa'], title='alfa')
    R = VectorFunctionSpace(mesh, 'R', 0)
    c = TestFunction(R)
    tau = -p_*Identity(2)+nu*(grad(u_)+grad(u_).T)
    ff = FacetFunction("size_t", mesh, 0)
    Cyl.mark(ff, 1)
    n = FacetNormal(mesh)
    ds = ds[ff]
    forces = assemble(dot(dot(tau, n), c)*ds(1)).array()*2/(Umean**2*D)

    print "Cd = {}, CL = {}".format(*forces)

    from fenicstools import Probes
    from numpy import linspace, repeat, where, resize
    xx = linspace(0, L, 10000)
    x = resize(repeat(xx, 2), (10000, 2))
    x[:, 1] = 0.2
    probes = Probes(x.flatten(), V)
    probes(u_[0])
    nmax = where(probes.array() < 0)[0][-1]
    print "L = ", x[nmax, 0]-0.25
    print "dP = ", p_(Point(0.15, 0.2)) - p_(Point(0.25, 0.2))
Exemple #7
0
def test_Probes_functionspace_2D(V2):
    u0 = interpolate(Expression('x[0]', degree=1), V2)
    x = array([[0.5, 0.5], [0.4, 0.4], [0.3, 0.3]])

    p = Probes(x.flatten(), V2)
    # Probe twice
    p(u0)
    p(u0)

    # Check both snapshots
    p0 = p.array(N=0)
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0] - 0.5, 7) == 0
        assert round(p0[1] - 0.4, 7) == 0
        assert round(p0[2] - 0.3, 7) == 0
    p0 = p.array(N=1)
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0] - 0.5, 7) == 0
        assert round(p0[1] - 0.4, 7) == 0
        assert round(p0[2] - 0.3, 7) == 0
def test_Probes_functionspace_2D(V2):
    u0 = interpolate(Expression('x[0]'), V2)
    x = array([[0.5, 0.5], [0.4, 0.4], [0.3, 0.3]])

    p = Probes(x.flatten(), V2)
    # Probe twice
    p(u0)
    p(u0)
    
    # Check both snapshots
    p0 = p.array(N=0)
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0] - 0.5, 7) == 0
        assert round(p0[1] - 0.4, 7) == 0
        assert round(p0[2] - 0.3, 7) == 0
    p0 = p.array(N=1)
    if MPI.rank(mpi_comm_world()) == 0:
        assert round(p0[0] - 0.5, 7) == 0
        assert round(p0[1] - 0.4, 7) == 0
        assert round(p0[2] - 0.3, 7) == 0
Exemple #9
0
# BCs
bc1 = DirichletBC(VV.sub(0), ((0, 0)), boundaries, 1)
bc2 = DirichletBC(VV.sub(1), ((0, 0)), boundaries, 1)
bcs = [bc1, bc2]

# Parameters:
rho_s = 1.0e3
mu_s = 0.5e6
nu_s = 0.4
E_1 = 1.4e6
lambda_ = nu_s * 2. * mu_s / (1. - 2. * nu_s)
f = Constant((0, -2.))
beta = Constant(0.25)

probe = Probes(coord, V)


def action(wd_, t):
    time.append(t)
    probe(wd_["n"].sub(1))


# Set up different numerical schemes
# TODO: Add options to chose solver and change solver parameters
common = {
    "space": "mixedspace",
    "E": None,  # Full implicte, not energy conservative
    "T": 1,  # End time
    "dt": 0.001,  # Time step
    "coupling": "CN",  # Coupling between d and w
Exemple #10
0
def main():
    parser = argparse.ArgumentParser(description="Average various files")
    parser.add_argument("-l",
                        "--list",
                        nargs="+",
                        help="List of folders",
                        required=True)
    parser.add_argument("-f",
                        "--fields",
                        nargs="+",
                        default=None,
                        help="Sought fields")
    parser.add_argument("-t", "--time", type=float, default=0, help="Time")
    parser.add_argument("--show", action="store_true", help="Show")
    parser.add_argument("-R",
                        "--radius",
                        type=float,
                        default=None,
                        help="Radial distance")
    args = parser.parse_args()

    tss = []
    for folder in args.list:
        ts = InterpolatedTimeSeries(folder, sought_fields=args.fields)
        tss.append(ts)
    Ntss = len(tss)

    all_fields_ = []
    for ts in tss:
        all_fields_.append(set(ts.fields))
    all_fields = list(set.intersection(*all_fields_))
    if args.fields is None:
        fields = all_fields
    else:
        fields = list(set.intersection(set(args.fields), set(all_fields)))

    f_in = []
    for ts in tss:
        f_in.append(ts.functions())

    # Using the first timeseries to define the spaces
    # Could be redone to e.g. a finer, structured mesh.
    # ref_mesh = tss[0].mesh
    ref_spaces = dict([(field, f.function_space())
                       for field, f in f_in[0].items()])

    if "psi" not in fields:
        exit("No psi")

    var_names = ["t", "s"]
    index_names = ["tt", "st", "ss"]
    index_numbers = [0, 1, 4]
    dim_names = ["x", "y", "z"]

    # Loading geometry
    rad_t = []
    rad_s = []
    g_ab = []
    gab = []
    for ts in tss:
        # Should compute these from the curvature tensor
        rad_t.append(
            df.interpolate(df.Expression("x[0]", degree=2), ts.function_space))
        rad_s.append(
            df.interpolate(df.Expression("x[1]", degree=2), ts.function_space))

        # g_loc = [ts.function(name) for name in ["gtt", "gst", "gss"]]
        # g_inv_loc = [ts.function(name) for name in ["g_tt", "g_st", "g_ss"]]

        gab_loc = dict([(idx, ts.function("g{}".format(idx)))
                        for idx in index_names])
        g_ab_loc = dict([(idx, ts.function("g_{}".format(idx)))
                         for idx in index_names])

        for idx, ij in zip(index_names, index_numbers):
            # for ij in range(3):
            # ts.set_val(g_loc[ij], ts.g[:, ij])
            # ts.set_val(g_inv_loc[ij], ts.g_inv[:, ij])
            ts.set_val(g_ab_loc[idx], ts.g_ab[:, ij])
            # Could compute the gab locally instead of loading
            ts.set_val(gab_loc[idx], ts.gab[:, ij])

        g_ab_loc["ts"] = g_ab_loc["st"]
        gab_loc["ts"] = gab_loc["st"]

        g_ab.append(g_ab_loc)
        gab.append(gab_loc)

    costheta = df.Function(ref_spaces["psi"], name="costheta")
    for its, (ts, g_ab_loc, gab_loc) in enumerate(zip(tss, g_ab, gab)):
        if args.time is not None:
            step, time = get_step_and_info(ts, args.time)
        g_ab_ = to_vector(g_ab_loc)
        gab_ = to_vector(gab_loc)

        ts.update(f_in[its]["psi"], "psi", step)
        psi = f_in[its]["psi"]
        psi_t = df.project(psi.dx(0), ts.function_space)
        psi_s = df.project(psi.dx(1), ts.function_space)

        gp_t = psi_t.vector().get_local()
        gp_s = psi_s.vector().get_local()
        # gtt, gst, gss = [g_ij.vector().get_local() for g_ij in g[its]]
        # g_tt, g_st, g_ss = [g_ij.vector().get_local() for g_ij in g_inv[its]]
        gtt = gab_["tt"]
        gst = gab_["ts"]
        gss = gab_["ss"]
        g_tt = g_ab_["tt"]
        g_st = g_ab_["ts"]
        g_ss = g_ab_["ss"]

        rht = rad_t[its].vector().get_local()
        rhs = rad_s[its].vector().get_local()
        rh_norm = np.sqrt(g_tt * rht**2 + g_ss * rhs**2 + 2 * g_st * rht * rhs)
        gp_norm = np.sqrt(gtt * gp_t**2 + gss * gp_s**2 +
                          2 * gst * gp_t * gp_s)

        costheta_loc = ts.function("costheta")
        # abs(cos(theta)):
        costheta_loc.vector()[:] = abs(
            (rht * gp_t + rhs * gp_s) / (rh_norm * gp_norm + 1e-8))
        # cos(theta)**2:
        #costheta_loc.vector()[:] = ((rht*gp_t + rhs*gp_s)/(rh_norm*gp_norm+1e-8))**2
        # sin(theta):
        #costheta_loc.vector()[:] = np.sin(np.arccos((rht*gp_t + rhs*gp_s)/(rh_norm*gp_norm+1e-8)))
        # sin(theta)**2:
        # costheta_loc.vector()[:] = np.sin(np.arccos((rht*gp_t + rhs*gp_s)/(rh_norm*gp_norm+1e-8)))**2
        # abs(theta):
        #costheta_loc.vector()[:] = abs(np.arccos((rht*gp_t + rhs*gp_s)/(rh_norm*gp_norm+1e-8)))

        costheta_intp = interpolate_nonmatching_mesh(costheta_loc,
                                                     ref_spaces["psi"])

        costheta.vector()[:] += costheta_intp.vector().get_local() / Ntss

    dump_xdmf(costheta)

    if args.show:
        JET = plt.get_cmap('jet')
        RYB = plt.get_cmap('RdYlBu')
        RYB_r = plt.get_cmap('RdYlBu_r')
        mgm = plt.get_cmap('magma')
        fig, ax = plt.subplots()
        fig.set_size_inches(4.7, 4.7)
        rc('text', usetex=True)
        rc('font', **{'family': 'serif', 'serif': ['Palatino']})
        # First, dump a hires PNG version of the data:
        plot = df.plot(costheta, cmap=mgm)
        plt.axis('off')
        plt.savefig('anglogram_hires.png',
                    format="png",
                    bbox_inches='tight',
                    pad_inches=0,
                    dpi=500)
        mainfs = 10  # Fontsize
        titlefs = 12  # Fontsize
        #plt.set_cmap('jet')
        #cbar = fig.colorbar(plot, ticks=[0, 0.5, 1], orientation='vertical')
        #cbar.ax.set_yticklabels(['Radial', 'Intermediate', 'Azimuthal'])
        #cbar = fig.colorbar(plot, ticks=[0, 0.5, 0.95], orientation='horizontal', fraction=0.046, pad=0.04)
        #cbar = fig.colorbar(plot, ticks=[0, 0.5, 0.995], orientation='horizontal', fraction=0.046, pad=0.04)
        cbar = fig.colorbar(plot,
                            ticks=[0, 0.5, 0.9995],
                            orientation='horizontal',
                            fraction=0.046,
                            pad=0.04)
        cbar.ax.set_xticklabels(['Radial', 'Intermediate', 'Azimuthal'])
        #ax.set_title('Stripe orientation -- $\\cos^2(\\theta)$', fontsize=mainfs)
        #ax.set_title(r'Stripe orientation -- $\cos^2(\theta)$')
        plt.text(0.5,
                 1.05,
                 r'Stripe orientation -- $\left\vert\cos(\theta)\right\vert$',
                 fontsize=titlefs,
                 horizontalalignment='center',
                 transform=ax.transAxes)
        #ax.set_title('Stripe orientation', fontsize=mainfs)
        #plt.text(0.2, 0.2, '$\\textcolor{red}{\\mathbf{p}(u,w,\\xi)}=\\textcolor{blue}{\\tilde{\\mathbf{p}}(u,w)}  + \\xi \\tilde{\\mathbf{n}}(u,w)$', fontsize=mainfs)
        ax.get_xaxis().set_visible(False)
        ax.get_yaxis().set_visible(False)
        #plt.show()
        plt.savefig('anglogram.pdf',
                    format="pdf",
                    bbox_inches='tight',
                    pad_inches=0)
        #plt.axis('on')
        #ax.get_xaxis().set_visible(True)
        #ax.get_yaxis().set_visible(True)
        #plt.colorbar(plot)
        #plt.show()

    if args.radius is not None and args.radius > 0:
        Nr, Nphi = 256, 256
        r_lin = np.linspace(0., args.radius, Nr)
        phi_lin = np.linspace(0, 2 * np.pi, Nphi, endpoint=False)
        R, Phi = np.meshgrid(r_lin, phi_lin)
        r = R.reshape((Nr * Nphi, 1))
        phi = Phi.reshape((Nr * Nphi, 1))

        xy = np.hstack((r * np.cos(phi), r * np.sin(phi)))

        pts = xy.flatten()
        probes = Probes(pts, ref_spaces["psi"])
        probes(costheta)

        ct = probes.array()
        CT = ct.reshape(R.shape)

        g_r = CT.mean(axis=0)
        g_phi = CT.mean(axis=1)

        plt.figure()
        plt.plot(r_lin, g_r)
        plt.ylabel("g(r)")
        plt.xlabel("r")

        plt.figure()
        plt.plot(phi_lin, g_phi)
        plt.xlabel("phi")
        plt.ylabel("g(phi)")
        plt.show()
def method(ts,
           dx=0.1,
           line="[0.,0.]--[1.,1.]",
           time=None,
           dt=None,
           skip=0,
           **kwargs):
    """ Probe along a line. """
    info_cyan("Probe along a line.")
    try:
        x_a, x_b = [tuple(eval(pt)) for pt in line.split("--")]
        assert (len(x_a) == ts.dim)
        assert (len(x_b) == ts.dim)
        assert (all([
            bool(isinstance(xd, float) or isinstance(xd, int))
            for xd in list(x_a) + list(x_b)
        ]))
    except:
        info_on_red("Faulty line format. Use 'line=[x1,y1]--[x2,y2]'.")
        exit()

    x = np.array(line_points(x_a, x_b, dx))

    info("Probes {num} points from {a} to {b}".format(num=len(x), a=x_a,
                                                      b=x_b))

    if rank == 0:
        plot_probes(ts.nodes, ts.elems, x, colorbar=False, title="Probes")

    f = ts.functions()
    probes = dict()
    from fenicstools import Probes
    for field, func in f.iteritems():
        probes[field] = Probes(x.flatten(), func.function_space())

    steps = get_steps(ts, dt, time)

    for step in steps:
        info("Step " + str(step) + " of " + str(len(ts)))
        ts.update_all(f, step)
        for field, probe in probes.iteritems():
            probe(f[field])

    probe_arr = dict()
    for field, probe in probes.iteritems():
        probe_arr[field] = probe.array()

    if rank == 0:
        for i, step in enumerate(steps):
            chunks = [x]
            header_list = [index2letter(d) for d in range(ts.dim)]
            for field, chunk in probe_arr.iteritems():
                if chunk.ndim == 1:
                    header_list.append(field)
                    chunk = chunk[:].reshape(-1, 1)
                elif chunk.ndim == 2:
                    header_list.append(field)
                    chunk = chunk[:, i].reshape(-1, 1)
                elif chunk.ndim > 2:
                    header_list.extend(
                        [field + "_" + index2letter(d) for d in range(ts.dim)])
                    chunk = chunk[:, :, i]
                chunks.append(chunk)

            data = np.hstack(chunks)
            header = "\t".join(header_list)
            makedirs_safe(os.path.join(ts.analysis_folder, "probes"))
            np.savetxt(os.path.join(ts.analysis_folder, "probes",
                                    "probes_{:06d}.dat".format(step)),
                       data,
                       header=header)
Exemple #12
0
def solve_ht():
    #  error for inf temperature field if all BC are HTC
    bcs = {
            "work": { 'boundary_id': work_htc_boundary_id, 'values': {
                                'temperature': {'variable': "temperature", 'type': 'HTC', 'value': htc_work, 'ambient': T_ambient } } },
            "cutter":  {'boundary_id': cutter_htc_boundary_id, 'values': {
                                #'temperature': {'variable': "temperature", 'type': 'Dirichlet', 'value': T_ambient + 200} } },
                                'temperature': {'variable': "temperature", 'type': 'HTC', 'value': htc_cutter, 'ambient': T_ambient } } },
            "holder":  {'boundary_id': holder_htc_boundary_id, 'values': {
                                'temperature': {'variable': "temperature", 'type': 'HTC', 'value': htc_holder, 'ambient': T_ambient} } },
                                #'temperature': {'variable': "temperature", 'type': 'Dirichlet', 'value': T_ambient + 20} } },
            "chip":  { 'boundary_id': chip_htc_boundary_id, 'values': {
                                'temperature': {'variable': "temperature", 'type': 'HTC', 'value': htc_chip, 'ambient': T_ambient } } },
            #other are zero heat flux
    }

    settings = {'solver_name': 'ScalarEquationSolver',
                    'mesh': mesh_file, 'function_space': None,  'fe_degree': element_degree, 'periodic_boundary': pbc,
                    'boundary_conditions': bcs,
                    'body_source': None,
                    'initial_values': {'temperature': T_ambient},
                    'material': material_work,
                    'solver_settings': {
                        'transient_settings': {'transient': False, 'starting_time': 0, 'time_step': 0.01, 'ending_time': 0.03},
                        'reference_values': {'temperature': T_ambient},
                        'solver_parameters': {"relative_tolerance": 1e-8,  # mapping to solver.parameters of Fenics
                                                        'absolute_tolerance': 1E-9,
                                                        "maximum_iterations": 500,
                                                        "relaxation_parameter": 0.3,  # case 6 , case 8 failed to converge
                                                        "monitor_convergence": True,  # print to console
                                                        },
                        },
                    # solver specific settings
                    'scalar_name': 'temperature',
                    "convective_velocity": None,
                    #'radiation_settings': {'ambient_temperature': T_ambient-20, 'emissivity': 0.9}
                    }
    if using_stab:  # stab is not necessary if mapping boundary is used
        settings['advection_settings'] = {'stabilization_method': 'IP', 'alpha': IP_alpha, 'Pe':  Pe/1000.0}
    if considering_radiation:
        settings['radiation_settings']= {'ambient_temperature': T_ambient, 'emissivity': emissivity}

    import time  # dolfin has time function
    ts_before_preprocessing = time.time()
    solver = ScalarTransportSolver.ScalarTransportSolver(settings)

    Q = solver.function_space
    vector_degree = element_degree+1
    V = VectorFunctionSpace(solver.mesh, 'CG', vector_degree)
    v_e = Expression(cppcode=velocity_code, degree=vector_degree)  # degree, must match function space
    v_e.subdomain_id = solver.subdomains
    velocity = Function(V)
    velocity.interpolate(v_e)  # does not work for MPI
    if has_convective_velocity:
        #solver.convective_velocity = Constant((1, 1, 0))
        solver.convective_velocity = velocity

    #DG for conductivity and heat source, save to hdf5?
    DG0 = FunctionSpace(solver.mesh, 'DG', 0)  # can not mixed higher order CG and DG?
    unity = Function(DG0)
    unity.vector()[:] = 1 #interpolate(Expression('1', element_degree), DG0)


    # Numerical simulations of advection-dominated scalar mixing with applications to spinal CSF flow and drug transport
    if not using_nonlinear_thermal_properties:
        k_f = get_material_function(DG0, solver.subdomains, material_k_list)
        solver.material['thermal_conductivity'] = k_f
        capacity_f = get_material_function(DG0, solver.subdomains, material_capacity_list)
        solver.material['capacity'] = capacity_f

    #################################################
    shear_heat, friction_heat = get_heat_source()
    shear_heat_density = shear_heat / shear_heat_volume  # W/m3
    friction_heat_density = friction_heat / nominal_friction_heat_volume
    print("heating volume and intensity; ", shear_heat_volume, friction_heat_volume, shear_heat_density, friction_heat_density)
    if True:  # test passed, non-uniform heat source can be implemented later
        class HeatSourceExpression(Expression):
            def eval_cell(self, values, x, ufc_cell):
                cindex = ufc_cell.index
                did = solver.subdomains[cindex]
                if did == shear_subdomain_id:
                    values[0] = shear_heat_density
                elif did == friction_subdomain_id:
                    if nonuniform_friction_heat:
                        distance = math.sqrt(x[0]*x[0] + x[1]*x[1])
                        _start = (friction_heat_start + uniform_friction_heat_length)
                        if distance <= _start:
                            values[0] = friction_heat_density * uniform_heat_ratio
                        else:
                            _ratio_l = (distance -_start)/(actual_friction_heat_distance - _start)
                            _ratio_h = uniform_heat_ratio * (1 - _ratio_l)
                            values[0] = friction_heat_density * _ratio_h
                    if nonuniform_friction_thickness:
                        distance = math.sqrt(x[0]*x[0] + x[1]*x[1])
                        _start = friction_heat_start
                        _ratio_l = (distance -_start)/actual_friction_heat_length
                        _ratio_h = 1.0 / ( 1.0 - _ratio_l * ( 1.0 - friction_end_thickness/friction_heat_thickness))
                        values[0] = friction_heat_density * _ratio_h
                    else:
                        values[0] = friction_heat_density
                else:
                    values[0] = 0
        # FIXME: cause error of UFLException: Discontinuous type Coefficient must be restricted.
        v_s = HeatSourceExpression(degree = element_degree)  # degree, must match function space
        heat_source = Function(DG0)
        heat_source.interpolate(v_s)  # does not work for MPI
        solver.body_source = heat_source
    else:
        heat_source_list = [0] * subdomain_number
        heat_source_list[shear_subdomain_id] = shear_heat_density
        heat_source_list[friction_subdomain_id] = friction_heat_density
        heat_source = get_material_function(DG0, solver.subdomains, heat_source_list)  # does not work for MPI
        solver.body_source =  heat_source
    '''
    solver.boundary_facets.set_all(0)
    for facet in facets(solver.mesh):
        for cell in cells(facet):
            #print(f.index(), c.index())
            if facet.exterior() and solver.subdomains[cell.index()] < 5:
                solver.boundary_facets[facet.index()] = solver.subdomains[cell.index()]
    '''

    if exporting_foam:
        #preset boundary value
        #DG vector space
        #v_e = Expression(cppcode=velocity_code, degree=vector_degree)  # degree, must match function space?
        #v_e.subdomain_id = solver.subdomains
        #print(velocity_code)

        DGV = VectorFunctionSpace(solver.mesh, 'DG', 0)
        velocity = Function(DGV)
        velocity.interpolate(v_e)  # does not work for MPI
        print(' chip volocity = ({}, {}, {})'.format(chip_sliding_vel_x, chip_sliding_vel_y, 0))
        print(' work volocity = ({}, {}, {})'.format(cutting_speed, 0, 0))

        sys.path.append('/media/sf_OneDrive/gitrepo/VTKToFoam')
        from VTKToFoam import set_internal_field, write_field
        foam_data_folder = '0/'
        #foam_data_folder = '0.origin/'

        #print('size of DG0 vector numpy array', velocity.vector().array().shape)  # correct 1D array
        #print('size of DG0 scalar numpy array', heat_source.vector().array().shape)
        # need to regerate mesh and transform mesh even if boundary, subdomain id changed.
        foam_velocity_data_file = foam_data_folder + foam_data_folder + 'U'
        set_internal_field(foam_velocity_data_file, velocity.vector().array(), 'vector',  foam_data_folder + '0.origin/U')

        # icoThermoFoam TEqn  accepts  power/capacity as source
        #set_internal_field(foam_data_folder + 'S', heat_source.vector().array()/metal_capacity_0, 'scalar', foam_base_folder + 'S')  # if not existing, write_field()
        print("set heat source density in system/")
        sys.exit()

    #
    holder_top_boundary = AutoSubDomain(lambda x, on_boundary: \
                                        near(x[1], holder_top_y) and on_boundary)
    holder_top_boundary.mark(solver.boundary_facets, holder_top_boundary_id)
    solver.boundary_conditions['holder_top'] = { 'boundary_id': holder_top_boundary_id, 'values': {
                    'temperature': {'variable': "temperature", 'type': 'Dirichlet', 'value': T_holder_top } } }
    #
    if is_straight_chip:
        chip_end_boundary = AutoSubDomain(lambda x, on_boundary: \
                    near(x[1], chip_top_y) and on_boundary)
    else:
        chip_end_boundary = AutoSubDomain(lambda x, on_boundary: \
                    near(x[0], chip_center_x) and (x[1]>0) and on_boundary)

    chip_end_boundary.mark(solver.boundary_facets, chip_end_boundary_id)
    if not has_convective_velocity:
        solver.boundary_conditions['chipend_htc'] = { 'boundary_id': chip_end_boundary_id, 'values': {
                    'temperature': {'variable': "temperature", 'type': 'HTC', 'value':  htc_chip, 'ambient':T_ambient } } }

    if has_convective_velocity:
        if using_mapping_bc: # test if bc is found
            # those are used in post-processing, PeriodicBoundary should be done in function space creation
            mapping_periodic_boundary = PeriodicBoundary()
            mapping_periodic_boundary.mark(solver.boundary_facets, mapping_boundary_id, check_midpoint = True)
            #
            shear_interface = TurningInterface()  # chip side
            shear_interface.mark(solver.boundary_facets, mapped_shear_boundary_id, check_midpoint = True)
            #
            if using_chip_cutter_mapping_bc:
                friction_interface = FrictionalInterface()  # cutter side
                friction_interface.mark(solver.boundary_facets, mapped_friction_boundary_id, check_midpoint = True)

        if workpiece_type_id == 0 or workpiece_type_id == 2:  # rect work shape
            work_bottom_boundary = AutoSubDomain(lambda x, on_boundary: near(x[1], work_bottom_y) and on_boundary)
            work_bottom_boundary.mark(solver.boundary_facets, work_bottom_boundary_id)
            #
            work_left_boundary_id = work_bottom_boundary_id+1
            work_left_boundary = AutoSubDomain(lambda x, on_boundary: near(x[0], work_left_x) and x[1]<feed_thickness+DOLFIN_EPS and on_boundary)
            work_left_boundary.mark(solver.boundary_facets, work_left_boundary_id)
            #
            work_right_boundary = AutoSubDomain(lambda x, on_boundary: near(x[0], work_right_x) and x[1]<feed_thickness+DOLFIN_EPS and on_boundary)
            work_right_boundary.mark(solver.boundary_facets, work_bottom_boundary_id+2)
            #right are natural boundary, zero gradient, or it does not mater
            solver.boundary_conditions['work_inlet'] = { 'boundary_id': work_left_boundary_id, 'values': {
                                        'temperature': {'variable': "temperature", 'type': 'Dirichlet', 'value': T_work_inlet } } }
            #solver.boundary_conditions['work_bottom'] = { 'boundary_id': work_bottom_boundary_id, 'values': {
            #                            'temperature': {'variable': "temperature", 'type': 'Dirichlet', 'value': T_ambient } } }
        elif workpiece_type_id == 1:
            disc_center_y = - disc_R
            work_clamp_boundary_id = 8
            work_clamp_boundary = AutoSubDomain(lambda x, on_boundary: \
                between(x[0], (-disc_R*0.05, disc_R*0.05)) \
                and between(x[1], (disc_center_y-disc_R*0.1, disc_center_y+disc_R*0.1)) and on_boundary)
            work_clamp_boundary.mark(solver.boundary_facets, work_clamp_boundary_id)
            solver.boundary_conditions['work_clamp'] = { 'boundary_id': work_clamp_boundary_id, 'values': {
                                        'temperature': {'variable': "temperature", 'type': 'Dirichlet', 'value': T_ambient } } }
        else:
            raise NotImplementedError('this work piece shape id is not supported')


    def update_material_property(DG0, subdomains, material_values, T_DG0, cutter_f, metal_f):
        # it takes very long time to complete if set individually
        did = np.asarray(subdomains.array(), dtype=np.int32)
        u = Function(DG0)
        u.vector()[:]  = metal_f(T_DG0.vector().get_local())  # return numpy.array
        #print(type(u_new), u_new.size, u.vector().array().size)

        u.vector()[did == cutter_subdomain_id]  = cutter_f(T_DG0.vector().get_local())[did == cutter_subdomain_id]
        #u.vector()[did == cutter_subdomain_id] = cutter_value
        """
        for i, v in enumerate(did):
            if (v == cutter_subdomain_id):
                u.vector()[i] = cutter_value
            else:
                u.vector()[i] = metal_f(T_DG0.vector().array()[i])
        """
        return u

    ts_after_preprocessing = time.time()
    # my own nonliner loop, updating material property in each iteration
    if using_nonlinear_loop:  # 3D looping is possible
        assert not using_MPI  # setting material property may not working in parallel
        loop_i = 0
        loop_N = 10
        T_old = Function(solver.function_space)  #default to zero, Yes
        while loop_i < loop_N:
            T = solver.solve()
            T_mean_diff = np.mean(T_old.vector()[:] - T.vector()[:])
            print("=== nonlinear loop ", loop_i, " ======= ", T_mean_diff)
            if  math.fabs(T_mean_diff) < 0.1:
                break
            T_DG0 = project(T, DG0)
            capacity_field = update_material_property(DG0, solver.subdomains, material_capacity_list, T_DG0, cutter_capacity_f, metal_capacity_f)
            solver.material['capacity'] = capacity_field
            k_field = update_material_property(DG0, solver.subdomains, material_k_list, T_DG0, cutter_k_f, metal_k_f)
            solver.material['thermal_conductivity'] = k_field
            #solver.solve() has considered dc/dT        ignore dk/dT
            #to trigger this condition: if 'dc_dT' in self.material:

            T_old.vector()[:] = T.vector()[:]
            loop_i += 1
            #ofile = File(result_folder + "k.pvd")  # not for parallel
            #ofile << solver.material['thermal_conductivity']
    else:
        T = solver.solve()

    ts_before_postprocessing = time.time()
    if using_MPI:
        mf = HDF5File(mpi_comm_world(),  result_folder + "metal_cutting_result" +'.h5', 'w')
        #mf = XDMFFile(mpi_comm_world(), result_name+'.xdmf')
        mf.write(T, "T")
        mf.write(V.mesh(), "mesh")
        #post processing is not possible in parallel?
        sys.exit()
    else:
        #interpolate the higher order solution onto a finer linear space
        T.rename("Temperature (C)", "temperature contour")
        ofile = File(result_folder + "T.pvd")  # not for parallel
        ofile << T
    
    ############################### post-processing#####################

    is_simulation_valid = True
    error_message = ''
    dx= Measure("dx", subdomain_data=solver.subdomains)
    print("================= summary =================")
    print("shear_heat, friction_heat by definition", shear_heat, friction_heat)
    volume_shear_zone = assemble(unity*dx(shear_subdomain_id))
    volume_friction_zone = assemble(unity*dx(friction_subdomain_id))
    print("volume_shear_zone, volume_friction_zone by integral:", volume_shear_zone, volume_friction_zone)

    heat_source = solver.body_source
    heat1 = assemble(heat_source*dx(shear_subdomain_id))
    heat2 = assemble(heat_source*dx(friction_subdomain_id))
    heat_chip = assemble(heat_source*dx(chip_subdomain_id))
    print("shear_heat, friction_heat, heating by chip (should be zero) by integration", heat1, heat2, heat_chip)
    total_heat = assemble(heat_source*dx)
    if using_3D:
        heat_ratio = total_heat/(shear_heat + friction_heat)
    else:
        #total_heat = total_heat*cutter_thickness
        heat_ratio = total_heat*cutter_thickness/(shear_heat + friction_heat)
    print("total_heat, ratio of heat integral to the defined", total_heat,  heat_ratio)
    if math.fabs(heat_ratio - 1) > validation_tol:
        error_message += "heat generation != heat source integration"
        is_simulation_valid = False

    print("========== heat loss from HTC =================")
    ds= Measure("ds", subdomain_data=solver.boundary_facets)
    # radiation is not added into cooling
    cooling_frictinal_zone = assemble(htc_work*(T-T_ambient)*ds(friction_subdomain_id))
    cooling_shear_zone = assemble(htc_work*(T-T_ambient)*ds(shear_subdomain_id))
    print("cooling from friction and shear zone surface",  cooling_frictinal_zone, cooling_shear_zone)
    cooling_work = assemble(htc_work*(T-T_ambient)*ds(work_htc_boundary_id))
    cooling_chip = assemble(htc_chip*(T-T_ambient)*ds(chip_htc_boundary_id))
    cooling_tool = assemble(htc_cutter*(T-T_ambient)*ds(cutter_htc_boundary_id) +
                                          htc_holder*(T-T_ambient)*ds(holder_htc_boundary_id))
    cooling_total_HTC = cooling_work + cooling_chip + cooling_tool + cooling_frictinal_zone + cooling_shear_zone 
    cooling_HTC_all = assemble(htc_work*(T-T_ambient)*ds)  # not all surface are HTC
    print("convective cooling_work, cooling_chip, cooling_tool and holder, cooling_HTC_all",\
                cooling_work, cooling_chip, cooling_tool, cooling_HTC_all)
    print("ratio of HTC loss to generation", cooling_total_HTC/total_heat)
    total_heat_loss = cooling_total_HTC

    if considering_radiation:
        Stefan_constant = 5.670367e-8  # W/m-2/K-4
        m_ = emissivity * Stefan_constant
        radiation_outflux = - m_*(T_ambient**4 - pow(T, 4))
        R_work = assemble(radiation_outflux*ds(work_htc_boundary_id))
        R_chip = assemble(radiation_outflux*ds(chip_htc_boundary_id))
        R_tool = assemble(radiation_outflux*ds(cutter_htc_boundary_id) +
                                              radiation_outflux*ds(holder_htc_boundary_id))
        R_total = R_work + R_chip + R_tool
        R_all_surfaces = assemble(radiation_outflux*ds)
        total_heat_loss += R_total
        print("radiative: cooling_work, cooling_chip, cooling_tool and holder", R_work, R_chip, R_tool, R_all_surfaces)
        if math.fabs(R_total / R_all_surfaces- 1) > 0.3:
            error_message += "radiation sum != radiation integration"
            is_simulation_valid = False
        print("ratio of heat generation radiative cooling",  R_total/total_heat, R_all_surfaces/total_heat)
    else:
        R_total = 0


    T_DG0 = interpolate(T, DG0)
    did = np.asarray(solver.subdomains.array(), dtype=np.int32)
    T_DG0.vector()[did != shear_subdomain_id] = 0.0
    Tmax_shear_zone = np.max(T_DG0.vector().array())
    # defined in salome_parameter.py, failed in 2D for v2017.2
    try:
        p_probe = Point(*point_shear_surface_center_coordinates)
        T_probe = T(p_probe)
    except:
        T_probe = 0

    Tmean_shear_zone = assemble(T*dx(shear_subdomain_id))/volume_shear_zone
    Tmean_friction_zone = assemble(T*dx(friction_subdomain_id))/volume_friction_zone
    Tmean_chip_zone = assemble(T*dx(chip_subdomain_id))/chip_volume
    Tmax_friction_zone = np.max(T.vector().array())

    T_analytical_shear_zone,  T_analytical_friction_zone = get_analytical_T()
    print('================ temperature prediction by FEA ==================')
    print('Tmean_shear_zone = ', Tmean_shear_zone)
    print('Tmax_shear_zone = ', Tmax_shear_zone, "T_probe = ", T_probe)
    print('Tmean_chip_zone = ', Tmean_chip_zone)
    print('Tmean_friction_zone = ', Tmean_friction_zone)
    print('Tmax_friction_zone = ', Tmax_friction_zone)


    if has_convective_velocity:
        #chip material flow taking away from system, how to get T_chip_end, (chip_cross_area*chip_velocity) is known
        #capacity = metal_density*metal_cp
        chip_speed = cutting_speed * (feed_thickness/chip_thickness)
        #QC = capacity * chip_speed* (cutter_thickness * chip_thickness)
        #print("outflow heat = %f * delta_T"%QC)
        #T_chip_end_center = T[p_chip_end_xyz]
        surface_normal = FacetNormal(solver.mesh)

        #area_shear_zone = assemble(unity*ds(shear_subdomain_id))
        #area_friction_zone = assemble(unity*ds(friction_subdomain_id))
        #print('area_shear_zone = ', area_shear_zone, "should ==", 2*l_AB * shear_heat_thickness + shear_heat_thickness*cutter_thickness)
        #print('area_friction_zone = ', area_friction_zone, "should ==", 2*actual_friction_heat_length * friction_heat_thickness)

        if using_nonlinear_loop:
            _capacity = solver.material['capacity']
            _conductivity = solver.material['thermal_conductivity']
        elif using_nonlinear_thermal_properties:  #CG, cutter has same material with metal,  no difference
            #T_DG0 = interpolate(T, DG0)
            #_capacity = update_material_property(DG0, solver.subdomains, material_capacity_list, T_DG0, material_cutter['capacity'], metal_capacity_f)
            #_conductivity = update_material_property(DG0, solver.subdomains, material_k_list, T_DG0, material_cutter['capacity'], metal_k_f)
            _capacity = metal_capacity_f(T)
            _conductivity = metal_k_f(T)
        else:
            _capacity = Constant(metal_density*metal_cp_0)
            _conductivity = metal_k_0
        _density = metal_density

        system_heat_capacity = assemble((T-Constant(T_reference)) * _capacity*_density*dx)
        print("characteristic time = ", system_heat_capacity/total_heat)  # too big not quite usful

        if using_mapping_bc:
            #validation
            print('============ mapping bc validation ================')
            if using_3D:
                _area_theory = l_AB*cutter_thickness
            else:
                _area_theory = l_AB
            area_mapping = assemble(unity*ds(mapping_boundary_id))
            print('area mapping bounadry and theroetical (should be equal): ', area_mapping, _area_theory)
            area_mapped_shear = assemble(unity*ds(mapped_shear_boundary_id))

            if using_workpiece_extra_extusion:
                if math.fabs(area_mapping / (_area_theory) - 1) > validation_tol:
                    error_message += "\n mapping interface area is not equal\n"
                    is_simulation_valid = False

            M_mapping = assemble(dot(surface_normal, velocity)*ds(mapping_boundary_id))  # not equal, why?
            print('mass flux from mapping bounadries vs in theory (should be equal): ', M_mapping, cutting_speed*cutter_thickness*feed_thickness)
            Q_mapping_bottom = assemble(dot(surface_normal, velocity) * (T-T_reference)*_capacity*ds(mapping_boundary_id))
            Q_mapping_top = assemble(dot(surface_normal, velocity) * (T-T_reference)*_capacity*ds(mapped_shear_boundary_id))
            print('heat flux from mapping bounadries (should be equal): ', Q_mapping_top, Q_mapping_bottom)
            if using_workpiece_extra_extusion:
                if math.fabs(math.fabs(Q_mapping_top / Q_mapping_bottom) - 1) > validation_tol:
                    error_message += "\n heat flux on mapping interfaces area is not equal\n"
                    is_simulation_valid = False

            Q_mapping_work = assemble(_conductivity*dot(grad(T), surface_normal) * ds(mapping_boundary_id)) * -1
            Q_mapping_chip = assemble(_conductivity*dot(grad(T), surface_normal) * ds(mapped_shear_boundary_id)) * -1
            print("conductive heat transfer, Q_mapping_work, Q_mapping_chip", Q_mapping_work, Q_mapping_chip)
            if using_chip_cutter_mapping_bc:
                area_mapped_friction = assemble(unity*ds(mapped_friction_boundary_id))
                print('area for a chip-cutter fricitonal interface  and theroetical value (should be equal): ', \
                        area_mapped_friction, actual_friction_heat_length*cutter_thickness)  # 2D has diff area
                print('total area for mapping (should be equal to), and sum of cutter and work', \
                        area_mapping, area_mapped_friction+area_mapped_shear)

        print('============ heat with mass flow ================')
        # heat loss due to mass flow, should be zero
        _tmp = dot(surface_normal, velocity) * (T-Constant(T_reference)) * _capacity
        Q_friction = assemble(_tmp*ds(friction_subdomain_id))
        print("heat flow with mass out of system from friction zone is:", Q_friction)
        Q_shearing = assemble(_tmp*ds(shear_subdomain_id))
        print("heat flow with mass out of system from sheairing zone is:", Q_shearing)

        Q_chip = assemble(_tmp*ds(chip_htc_boundary_id))
        print("heat flow with mass out of system from chip htc boundary is:", Q_chip)
        Q_work = assemble(_tmp*ds(work_htc_boundary_id))
        print("heat flow with mass out of system from work htc boundary (should be zero)is:", Q_work)
        Q_cutter = assemble(_tmp*ds(cutter_htc_boundary_id))
        print("heat flow with mass out of system from cutter htc is:", Q_cutter)
        Q_holder = assemble(_tmp*ds(holder_htc_boundary_id))
        print("heat flow with mass out of system from holder htc is:", Q_holder)
        Q_chipend = assemble(_tmp*ds(chip_end_boundary_id))
        print("heat flow with mass from  chipend", Q_chipend)
        if has_friction_transition_zone:  # no using mapping bc for friction contact
            Q_friction_transition_subdomain = assemble(_tmp*ds(friction_transition_subdomain_id))
            print("heat flow with mass from friction_transition_subdomain", Q_friction_transition_subdomain)
        Q_ds0 = assemble(_tmp*ds(0))
        print("heat flow with mass from  ds(0), should be zero", Q_ds0)
        total_heat_loss += Q_chipend  # Q_material_out_sum,  excluding the workpiece outlet

        """
        print('============ mass flow ================')
        M_shearing = assemble(dot(surface_normal, velocity)*ds(shear_subdomain_id))
        print("mass flow out of system from shearing zone boundary  is:", M_shearing)
        M_friction = assemble(dot(surface_normal, velocity)*ds(friction_subdomain_id))
        print("mass flow out of system from friction boundary is:", M_friction)
        M_work = assemble(dot(surface_normal, velocity)*ds(work_htc_boundary_id))
        print("mass flow out of system from work  is:", M_work)
        M_chip = assemble(dot(surface_normal, velocity)*ds(chip_htc_boundary_id))
        print("mass flow out of system from chip HTC boundary is:", M_chip)
        M_chipend = assemble(dot(surface_normal, velocity)*ds(chip_end_boundary_id))
        print("mass flow from chip end in theory VS integral at chipend", chip_speed * (cutter_thickness * chip_thickness), M_chipend)
        """

        Q_material_out = assemble(_tmp*ds)
        if workpiece_type_id == 0:  #rectangle
            #Q_bottom = cutting_speed * capacity *ds(work_bottom_boundary_id)
            Q_inflow = assemble( (T-Constant(T_reference))* cutting_speed * _capacity * ds(work_bottom_boundary_id + 1))
            #* cutter_thickness * (chip_start_y - work_bottom_y)
            Q_outflow = assemble( (T-Constant(T_reference))* cutting_speed * _capacity * ds(work_bottom_boundary_id + 2))
            print('inflow from left boundary and outflow from right bounadry is', Q_inflow, Q_outflow)

            Q_bottom = assemble(_conductivity*dot(grad(T), surface_normal)*ds(work_bottom_boundary_id)) * -1 #flow out

            if using_workpiece_extra_extusion:
                Q_flowing_out_work = (Q_material_out  - Q_chipend) + Q_bottom
            else:
                Q_flowing_out_work = (Q_outflow - Q_inflow) + Q_bottom
            print('heat flow out from work oulet and bottom is:', Q_flowing_out_work)
            total_heat_loss += Q_flowing_out_work
        else:  # disc clamping
            Q_clamp = assemble(_conductivity*dot(grad(T), surface_normal)*ds(work_clamp_boundary_id)) * -1 #flow out
            print('heat flux from clamp bounadry is', Q_clamp)
            Q_flowing_out_work = Q_clamp + cooling_work
            total_heat_loss += Q_flowing_out_work

        Q_material_out_sum = Q_chip + Q_work + Q_cutter + Q_holder + Q_chipend + Q_outflow + Q_inflow
        print("heat flow with mass out of system from all boundary byintegral (ds) and sum:",  Q_material_out, Q_material_out_sum)
        if math.fabs(Q_material_out_sum/Q_material_out - 1.0) > validation_tol*0.2:
            error_message += "\n heat flow with mass out of system from all boundary byintegral (ds) and sum is not equal\n"
            is_simulation_valid = False

        print('=============== conduction heat loss ===========')
        Q_conduction_all = assemble(_conductivity*dot(grad(T), surface_normal) * ds) * -1  # surface_normal pointing out
        Qk_chipend = assemble(_conductivity*dot(grad(T), surface_normal)*ds(chip_end_boundary_id)) * -1# flow out
        print('conductive heat flux from bottom and chipend bounadries', Q_bottom, Qk_chipend)   #should be set zero-flux
        Qk_holder_top = assemble(_conductivity*dot(grad(T), surface_normal) * ds(holder_top_boundary_id)) * -1 #flow out
        Q_conduction_work = assemble(_conductivity*dot(grad(T), surface_normal) * ds(work_subdomain_id)) * -1
        Q_conduction_chip = assemble(_conductivity*dot(grad(T), surface_normal) * ds(chip_subdomain_id)) * -1
        Q_conduction_tool = assemble(_conductivity*dot(grad(T), surface_normal) * ds(holder_subdomain_id)) * -1 +\
                                        assemble(_conductivity*dot(grad(T), surface_normal) * ds(cutter_subdomain_id)) * -1
        Qk_bottom = assemble(_conductivity*dot(grad(T), surface_normal) * ds(work_bottom_boundary_id)) * -1
        Qk_inlet= assemble(_conductivity*dot(grad(T), surface_normal) * ds(work_bottom_boundary_id + 1)) * -1
        Qk_outlet= assemble(_conductivity*dot(grad(T), surface_normal) * ds(work_bottom_boundary_id + 2)) * -1
        print('conductive heat at holder top, Qk_bottom, Qk_inlet, Qk_outlet, conduction all is',\
                    Qk_holder_top, Qk_bottom, Qk_inlet, Qk_outlet, Q_conduction_all)
        print('Q_conduction_tool, Q_conduction_work, Q_conduction_chip',\
                  Q_conduction_tool, Q_conduction_work, Q_conduction_chip)
        total_heat_loss += Qk_holder_top

        print('=============== heat loss ratios ===========')
        Q_baseline = total_heat_loss
        print("convection, radiation, Q_flowing_out_work, Q_bottom, Q_chipend, Q_holder_top")
        _ratios = np.array([cooling_total_HTC, R_total, Q_flowing_out_work, Q_bottom, Q_chipend, Qk_holder_top])/Q_baseline
        print(_ratios)

        Q_total_passing_friction_interface = (Qk_holder_top + cooling_tool)
        partition_coeff_shear = 1.0 -  Q_flowing_out_work/ shear_heat
        partition_coeff_friction = 1.0 -  Q_total_passing_friction_interface/ friction_heat
        print("partition_coeff_shear, partition_coeff_friction = ", partition_coeff_shear, partition_coeff_friction)

    print("ratio of total heat loss {}, heat generation {}, ratio {}"\
            .format(total_heat_loss, total_heat, total_heat_loss/total_heat))
    if math.fabs(total_heat_loss/total_heat - 1.0) > validation_tol:
        error_message += "\n heat generaton and heat loss are not equal\n"
        is_simulation_valid = False

    ts_after_post_processing = time.time()
    print('=============== time consumption ===========')
    print('preprocessing time', ts_after_preprocessing - ts_before_preprocessing)
    print('assembling and LA solving time', ts_before_postprocessing - ts_after_preprocessing)

    if using_debug:
        #plot(solver.boundary_facets)
        bfile = File(result_folder + "boundary.pvd")  # not working for parallel
        bfile << solver.boundary_facets
    if using_debug:
        ofile = File(result_folder + "HeatSource.pvd")  # not for parallel
        ofile << solver.body_source   #it is possible to save DG0 data

    if has_convective_velocity and using_debug:
        ofile = File(result_folder + "U.pvd")  # not for parallel, using hdf5 for parallel
        ofile << velocity

    if not is_batch_mode:
        if using_VTK:
            plot(solver.boundary_facets, title = "boundary id")
            plot(solver.subdomains, title = "subdomain id")
            plot(heat_source, title = "heat source density (W/m3)")
            #plot(solver.material['specific_heat_capacity'], title = "specific_heat_capacity")  # can not plot DG
            plot(velocity, title = "pseudo convective velocity")
            interactive()
            solver.plot()  # plt.legend() does not work: warnings.warn("No labelled objects found. "
        else:
            import matplotlib.pyplot as plt
            solver.plot()
            plt.show()
            #`paraview --data=T.pvd`

    if is_simulation_valid == False:
        print("======== the simulation is INVALID ! ==================")
        print(error_message)
        #if not using_workpiece_extra_extusion:
        #    sys.exit()
    else:
        print("======== the simulation is completed sucessfully ==================")


    thermal_number = metal_density * metal_cp_f(T_analytical_shear_zone) * cutting_speed * feed_thickness / metal_k_f(T_analytical_shear_zone)
    partition_coeff_eq = get_heat_partition(thermal_number)
    #also save thermal_number
    from datetime import datetime
    time_stamp  = datetime.utcnow().isoformat()
    parameters = [time_stamp, case_id, workpiece_type_id, 
        feed_thickness, chip_thickness, cutter_angle_v, shear_angle, cutting_speed, F_cutting, F_thrush,
        shear_heat_thickness, friction_heat_thickness, tool_chip_interface_length,
        T_ambient,  T_analytical_shear_zone, T_analytical_friction_zone,
        Tmean_shear_zone, Tmax_shear_zone, Tmean_friction_zone, Tmax_friction_zone,
        thermal_number, partition_coeff_eq, partition_coeff_shear, partition_coeff_friction, is_simulation_valid]

    output = ",".join([str(v) for v in parameters])
    with open(result_filename, 'a') as wf:
        wf.write(output)
        wf.write('\n')

    if extracting_data:
        #sys.path.append('/opt/fenicstools/')  # this package must be installed
        from fenicstools import Probes
        dist = np.linspace(0, tool_chip_interface_length, 20)
        probing_pts = np.array([(math.sin(cutter_angle_v*pi/180)*l, math.cos(cutter_angle_v*pi/180)*l, 0) for l in dist])
        probes = Probes(probing_pts.flatten(), solver.function_space)
        probes(T)  # evaluate f at all probing points
        extracted_datafile = result_folder + datafile_root + '__' + param_name + '__' + str(param_value) + '.csv'
        np.savetxt(probes.array(), extracted_datafile)
        print(probes.array())
Exemple #13
0
    # Make probe points
    probe_list = [-30, -25] + range(-20, 0, 2) + range(46) + range(50, 100, 2)
    probe_points = []
    for j in range(2, -3, -1):
        probe_points += [[r_1 * j, 0, r_1 * 2 * i] for i in probe_list]
    probe_points = array(probe_points)
    probe_points.dump(path.join(newfolder, "Stats", "Probes", "points"))

    eval_dict["senterline_u"] = StatisticsProbes(eval_senter.flatten(), Pv,
                                                 True)
    eval_dict["senterline_p"] = StatisticsProbes(eval_senter.flatten(), Pv,
                                                 True)
    eval_dict["initial_u"] = StatisticsProbes(eval_senter.flatten(), Pv, True)
    eval_dict["wall_p"] = StatisticsProbes(eval_wall.flatten(), Pv, True)
    eval_dict["senterline_u_probes"] = Probes(probe_points.flatten(), Vv)
    eval_dict["senterline_p_probes"] = Probes(probe_points.flatten(), Pv)

    # Finding the mean velocity
    u_mean = {"u": Function(Vv), "num": 0}

    if restart_folder is None:
        # Print header
        if MPI.rank(mpi_comm_world()) == 0:
            print_header(dt, mesh.hmax(), mesh.hmin(), case, start, stop,
                         inlet_string, mesh.num_cells(), newfolder, mesh_path)

    else:
        # Restart stats
        files = listdir(path.join(newfolder, "Stats"))
        files = [
Exemple #14
0
def main():
    parser = argparse.ArgumentParser(description="Average various files")
    parser.add_argument("-l",
                        "--list",
                        nargs="+",
                        help="List of folders",
                        required=True)
    parser.add_argument("-f",
                        "--fields",
                        nargs="+",
                        default=None,
                        help="Sought fields")
    parser.add_argument("-t", "--time", type=float, default=0, help="Time")
    parser.add_argument("--show", action="store_true", help="Show")
    parser.add_argument("-R",
                        "--radius",
                        type=float,
                        default=None,
                        help="Radial distance")
    args = parser.parse_args()

    tss = []
    for folder in args.list:
        ts = InterpolatedTimeSeries(folder, sought_fields=args.fields)
        tss.append(ts)
    Ntss = len(tss)

    all_fields_ = []
    for ts in tss:
        all_fields_.append(set(ts.fields))
    all_fields = list(set.intersection(*all_fields_))
    if args.fields is None:
        fields = all_fields
    else:
        fields = list(set.intersection(set(args.fields), set(all_fields)))

    f_in = []
    for ts in tss:
        f_in.append(ts.functions())

    # Using the first timeseries to define the spaces
    # Could be redone to e.g. a finer, structured mesh.
    # ref_mesh = tss[0].mesh
    ref_spaces = dict([(field, f.function_space())
                       for field, f in f_in[0].items()])

    if "psi" not in fields:
        exit("No psi")

    # Loading geometry
    rad_t = []
    rad_s = []
    g = []
    g_inv = []
    for ts in tss:
        # Should compute these from the curvature tensor
        rad_t.append(
            df.interpolate(df.Expression("x[0]", degree=2), ts.function_space))
        rad_s.append(
            df.interpolate(df.Expression("x[1]", degree=2), ts.function_space))

        g_loc = [ts.function(name) for name in ["gtt", "gst", "gss"]]
        g_inv_loc = [ts.function(name) for name in ["g_tt", "g_st", "g_ss"]]

        for ij in range(3):
            ts.set_val(g_loc[ij], ts.g[:, ij])
            # Could compute the following locally instead of loading
            ts.set_val(g_inv_loc[ij], ts.g_inv[:, ij])

        g.append(g_loc)
        g_inv.append(g_inv_loc)

    costheta = df.Function(ref_spaces["psi"], name="costheta")
    for its, ts in enumerate(tss):
        if args.time is not None:
            step, time = get_step_and_info(ts, args.time)

        ts.update(f_in[its]["psi"], "psi", step)
        psi = f_in[its]["psi"]
        psi_t = df.project(psi.dx(0), ts.function_space)
        psi_s = df.project(psi.dx(1), ts.function_space)

        gp_t = psi_t.vector().get_local()
        gp_s = psi_s.vector().get_local()
        gtt, gst, gss = [g_ij.vector().get_local() for g_ij in g[its]]
        g_tt, g_st, g_ss = [g_ij.vector().get_local() for g_ij in g_inv[its]]
        rht = rad_t[its].vector().get_local()
        rhs = rad_s[its].vector().get_local()
        rh_norm = np.sqrt(g_tt * rht**2 + g_ss * rhs**2 + 2 * g_st * rht * rhs)
        gp_norm = np.sqrt(gtt * gp_t**2 + gss * gp_s**2 +
                          2 * gst * gp_t * gp_s)

        costheta_loc = df.Function(ts.function_space)
        costheta_loc.vector()[:] = abs(
            (rht * gp_t + rhs * gp_s) / (rh_norm * gp_norm + 1e-8))

        costheta_intp = interpolate_nonmatching_mesh(costheta_loc,
                                                     ref_spaces["psi"])
        costheta.vector()[:] += costheta_intp.vector().get_local() / Ntss

    dump_xdmf(costheta)

    if args.show:
        fig = df.plot(costheta)
        plt.colorbar(fig)
        plt.show()

    if args.radius is not None and args.radius > 0:
        Nr, Nphi = 256, 256
        r_lin = np.linspace(0., args.radius, Nr)
        phi_lin = np.linspace(0, 2 * np.pi, Nphi, endpoint=False)
        R, Phi = np.meshgrid(r_lin, phi_lin)
        r = R.reshape((Nr * Nphi, 1))
        phi = Phi.reshape((Nr * Nphi, 1))

        xy = np.hstack((r * np.cos(phi), r * np.sin(phi)))

        pts = xy.flatten()
        probes = Probes(pts, ref_spaces["psi"])
        probes(costheta)

        ct = probes.array()
        CT = ct.reshape(R.shape)

        g_r = CT.mean(axis=0)
        g_phi = CT.mean(axis=1)

        plt.figure()
        plt.plot(r_lin, g_r)
        plt.ylabel("g(r)")
        plt.xlabel("r")

        plt.figure()
        plt.plot(phi_lin, g_phi)
        plt.xlabel("phi")
        plt.ylabel("g(phi)")
        plt.show()