示例#1
0
def main(myfile,
         startn=1,
         stopn=20,
         delim=None,
         period_hours=12.42,
         r_min=1000,
         inf_tol=1E-5,
         rel_tol=1E-12,
         abs_tol=1E-15,
         backend='dopri5',
         nstps=300,
         G=6.672E-11,
         file_out='wilms_nk.txt',
         kx=1,
         num_soln=1000,
         interp_emod=False,
         nmaxfull=1):
    # Print Status
    print(" ")
    print(":: Computing Love Numbers. Please Wait...")
    print(" ")
    # For SNREI Planet, Angular Frequency (omega) is Zero
    # Azimuthal order is only utilized for a rotating planet
    # The variables for each are included here as "place-holders" for future versions
    omega = 0
    order = 4

    # Prepare the planetary Model (read in, non-dimensionalize elastic parameters, etc.)
    r, mu, K, lmda, rho, g, tck_lnd, tck_mnd, tck_rnd, tck_gnd, s, lnd, mnd, rnd, gnd, s_min, small, \
    planet_radius, planet_mass, sic, soc, adim, gsdim, pi, piG, L_sc, R_sc, T_sc = \
        prepare_planet_model.main(myfile, G=G, r_min=r_min, kx=kx, file_delim=delim, emod_interp=interp_emod)
    # Define Forcing Period
    w = (1. / (period_hours * 3600.)) * (
        2. * pi)  # convert period to frequency (rad/sec)
    wnd = w * T_sc  # non-dimensionalize
    ond = omega * T_sc

    myn = np.linspace(startn, stopn, ((stopn - startn) + 1))
    n_sub = myn

    NK = []
    for ii in range(0, len(n_sub)):
        current_n = n_sub[ii]
        print('Working on Harmonic Degree: %7s | Number: %6d of %6d ' %
              (str(int(current_n)), (ii + 1), len(n_sub)))
        # Compute Integration Results for the Current Spherical Harmonic Degree, n

        nkprime = integrate_odes.main(current_n, s_min, tck_lnd, tck_mnd, tck_rnd, tck_gnd, wnd, ond, piG, sic, soc, small,
                            num_soln, backend, abs_tol, \
                            rel_tol, nstps, order, gnd, adim, gsdim, L_sc, T_sc, inf_tol, s, nmaxfull)

        NK.append(nkprime[0] / current_n)

    df = pd.DataFrame()
    df['nk'] = NK
    print(df)
    df.plot()
    plt.show()

    return
示例#2
0
all_iK = []
all_irho = []
all_ilmda = []

# Loop Through All Earth Models
for ii in range(0, len(earthmods)):

    # Current Model
    myfile = earthmods[ii]
    mycolor = colors[ii]
    mylabel = labels[ii]
    myweight = weights[ii]

    # Prepare Earth Model
    ir,imu,iK,ilmda,irho,ig,tck_lnd,tck_mnd,tck_rnd,tck_gnd,s,lnd,mnd,rnd,gnd,s_min,small,\
        earth_radius,earth_mass,sic,soc,adim,gsdim,pi,piG,L_sc,R_sc,T_sc = prepare_planet_model.main(myfile)

    # Compute P- and S-wave Velocities
    ivp = np.sqrt(np.divide(iK + (4. / 3.) * imu, irho))
    ivs = np.sqrt(np.divide(imu, irho))

    # Convert Radial Distances to km
    ir = ir / 1000.

    # Set Main Radial Vector (needed later for interpolation)
    if (ii == 0):
        main_ir = ir.copy()

    # Convert Other Parameters to Meaninful Units
    ivp = ivp / 1000.
    ivs = ivs / 1000.
示例#3
0
def main(myfile,rank,comm,size,startn=0,stopn=10000,delim=None,period_hours=12.42,r_min=1000.,inf_tol=1E-5,\
    rel_tol=1E-13,abs_tol=1E-13,backend='dop853',nstps=3000,G=6.672E-11,file_out='.txt',kx=1,num_soln=100,interp_emod=False,nmaxfull=None):

    # :: MPI ::
    # Determine the Chunk Sizes for LLN
    total_lln = stopn+1 - startn
    nominal_load = total_lln // size # Floor Divide
    # Final Chunk Might Have Fewer or More Jobs
    if rank == size - 1:
        procN = total_lln - rank * nominal_load
    else: # Otherwise, Chunks are Size of nominal_load
        procN = nominal_load

    # Only the Main Processor Will Do This:
    if (rank == 0):
    
        # Print Status
        print(" ")
        print(":: Computing Love Numbers. Please Wait...")
        print(" ")

        # For SNREI Planet, Angular Frequency (omega) is Zero 
        # Azimuthal order is only utilized for a rotating planet
        # The variables for each are included here as "place-holders" for future versions
        omega = 0
        order = 2

        # Prepare the planetary Model (read in, non-dimensionalize elastic parameters, etc.)
        r,mu,K,lmda,rho,g,tck_lnd,tck_mnd,tck_rnd,tck_gnd,s,lnd,mnd,rnd,gnd,s_min,small,\
            planet_radius,planet_mass,sic,soc,adim,gsdim,pi,piG,L_sc,R_sc,T_sc = \
            prepare_planet_model.main(myfile,G=G,r_min=r_min,kx=kx,file_delim=delim,emod_interp=interp_emod)

        # Define Forcing Period
        w = (1./(period_hours*3600.))*(2.*pi) # convert period to frequency (rad/sec)
        wnd = w*T_sc                         # non-dimensionalize
        ond = omega*T_sc

        # Surface Values (Used in Strain and Gravity Load Green's Function Computation)
        surface_idx = np.argmax(r)
        lmda_surface = lmda[surface_idx]
        mu_surface = mu[surface_idx]
        g_surface = g[surface_idx]

        # Optional: Plot Interpolated Values to Verify Interpolation
#        myrnd = interpolate.splev(s,tck_rnd,der=0)
#        mygnd = interpolate.splev(s,tck_gnd,der=0)
#        mymnd = interpolate.splev(s,tck_mnd,der=0)
#        mylnd = interpolate.splev(s,tck_lnd,der=0)
#        plt.subplot(2,2,1)
#        plt.plot(s,myrnd)
#        plt.title(r'$\rho$ Interpolated',size='x-small')
#        plt.subplot(2,2,2)
#        plt.plot(s,mymnd)
#        plt.title(r'$\mu$ Interpolated',size='x-small')
#        plt.subplot(2,2,3)
#        plt.plot(s,mygnd)
#        plt.title('Gravity Interpolated',size='x-small')
#        plt.subplot(2,2,4)
#        plt.plot(s,mylnd)
#        plt.title(r'$\lambda$ Interpolated',size='x-small')
#        plt.show()

        # Compute Asymptotic Load Love Numbers
        myn = np.linspace(startn,stopn,num=((stopn-startn)+1.),endpoint=True)
        hprime_asym,nkprime_asym,nlprime_asym,h_inf,h_inf_prime,l_inf,l_inf_prime, \
            k_inf,k_inf_prime = compute_asymptotic_LLN.main(myn,piG,lnd,mnd,gnd,rnd,adim,L_sc)

        # Shuffle the Degrees, Since Lower Degrees Take Longer to Compute
        myn_mix = myn.copy()
        np.random.shuffle(myn_mix)

        # Initialize Arrays
        hprime  = np.empty((len(myn),))
        nkprime = np.empty((len(myn),))
        nlprime = np.empty((len(myn),))
        hpot    = np.empty((len(myn),))
        nkpot   = np.empty((len(myn),))
        nlpot   = np.empty((len(myn),))
        hstr    = np.empty((len(myn),))
        nkstr   = np.empty((len(myn),))
        nlstr   = np.empty((len(myn),))
        hshr    = np.empty((len(myn),))
        nkshr   = np.empty((len(myn),))
        nlshr   = np.empty((len(myn),))
        sint_mt = np.empty((len(myn),num_soln))
        Yload   = np.empty((len(myn),num_soln*6))
        Ypot    = np.empty((len(myn),num_soln*6))
        Ystr    = np.empty((len(myn),num_soln*6))
        Yshr    = np.empty((len(myn),num_soln*6)) 
 
        # Load Love Number Output Filename
        lln_out      = ("lln_"+file_out)
        # Potential Love Number Output Filename
        pln_out      = ("pln_"+file_out)
        # Stress Love Number Output Filename
        str_out      = ("str_"+file_out)
        # Shear Love Number Output Filename
        shr_out      = ("shr_"+file_out)

    # If I'm a Worker, I Know Nothing About the Data
    else:
    
        myn = myn_mix = hprime = nlprime = nkprime = hpot = nlpot = nkpot = hstr = nlstr = nkstr = hshr = nlshr = nkshr = None
        s_min = tck_lnd = tck_mnd = tck_rnd = tck_gnd = wnd = ond = None
        piG = sic = soc = small = backend = abs_tol = rel_tol = nstps = None
        order = gnd = adim = gsdim = L_sc = T_sc = inf_tol = s = None
        sint_mt = Yload = Ypot = Ystr = Yshr = None
        lln_out = pln_out = str_out = shr_out = None

    # Create a Data Type for the Love Numbers
    lntype = MPI.DOUBLE.Create_contiguous(1)
    lntype.Commit()

    # Create a Data Type for Solution Radii
    stype = MPI.DOUBLE.Create_contiguous(num_soln)
    stype.Commit()

    # Create a Data Type for the Solutions (Ys)
    sol_vec_size = num_soln*6
    ytype = MPI.DOUBLE.Create_contiguous(sol_vec_size)
    ytype.Commit()

    # Gather the Processor Workloads for All Processors
    sendcounts = comm.gather(procN, root=0)

    # Scatter the Harmonic Degrees
    n_sub = np.empty((procN,))
    comm.Scatterv([myn_mix, (sendcounts, None), lntype], n_sub, root=0)

    # All Processors Get Certain Arrays and Parameters; Broadcast Them
    s_min = comm.bcast(s_min, root=0)
    tck_lnd = comm.bcast(tck_lnd, root=0)
    tck_mnd = comm.bcast(tck_mnd, root=0)
    tck_rnd = comm.bcast(tck_rnd, root=0)
    tck_gnd = comm.bcast(tck_gnd, root=0)
    wnd = comm.bcast(wnd, root=0)
    ond = comm.bcast(ond, root=0)
    piG = comm.bcast(piG, root=0)
    sic = comm.bcast(sic, root=0)
    soc = comm.bcast(soc, root=0)
    small = comm.bcast(small, root=0)
    num_soln = comm.bcast(num_soln, root=0)
    backend = comm.bcast(backend, root=0)
    abs_tol = comm.bcast(abs_tol, root=0)
    rel_tol = comm.bcast(rel_tol, root=0)
    nstps = comm.bcast(nstps, root=0)
    order = comm.bcast(order, root=0)
    gnd = comm.bcast(gnd, root=0)
    adim = comm.bcast(adim, root=0)
    gsdim = comm.bcast(gsdim, root=0)
    L_sc = comm.bcast(L_sc, root=0)
    T_sc = comm.bcast(T_sc, root=0)
    inf_tol = comm.bcast(inf_tol, root=0)
    s = comm.bcast(s, root=0)
    lln_out = comm.bcast(lln_out, root=0)
    pln_out = comm.bcast(pln_out, root=0)
    str_out = comm.bcast(str_out, root=0)
    shr_out = comm.bcast(shr_out, root=0)

    # Loop Through Spherical Harmonic Degrees
    hprime_sub = np.empty((len(n_sub),))
    nlprime_sub = np.empty((len(n_sub),))
    nkprime_sub = np.empty((len(n_sub),))
    hpot_sub = np.empty((len(n_sub),))
    nlpot_sub = np.empty((len(n_sub),))
    nkpot_sub = np.empty((len(n_sub),))
    hstr_sub = np.empty((len(n_sub),))
    nlstr_sub = np.empty((len(n_sub),))
    nkstr_sub = np.empty((len(n_sub),))
    hshr_sub = np.empty((len(n_sub),))
    nlshr_sub = np.empty((len(n_sub),))
    nkshr_sub = np.empty((len(n_sub),))
    sint_mt_sub = np.empty((len(n_sub),num_soln))
    Yload_sub = np.empty((len(n_sub),num_soln*6))
    Ypot_sub  = np.empty((len(n_sub),num_soln*6))
    Ystr_sub  = np.empty((len(n_sub),num_soln*6))
    Yshr_sub  = np.empty((len(n_sub),num_soln*6))
    for ii in range(0,len(n_sub)):
        current_n = n_sub[ii]
        print('Working on Harmonic Degree: %7s | Number: %6d of %6d | Rank: %6d' %(str(int(current_n)), (ii+1), len(n_sub), rank))
        # Compute Integration Results for the Current Spherical Harmonic Degree, n
        hprime_sub[ii],nlprime_sub[ii],nkprime_sub[ii],hpot_sub[ii],nlpot_sub[ii],nkpot_sub[ii],hstr_sub[ii],nlstr_sub[ii],nkstr_sub[ii],\
            hshr_sub[ii],nlshr_sub[ii],nkshr_sub[ii],sint_mt_sub[ii,:],Yload_sub[ii,:],Ypot_sub[ii,:],Ystr_sub[ii,:],Yshr_sub[ii,:] = \
            integrate_odes.main(current_n,s_min,tck_lnd,tck_mnd,tck_rnd,tck_gnd,wnd,ond,piG,sic,soc,small,num_soln,backend,abs_tol,\
                rel_tol,nstps,order,gnd,adim,gsdim,L_sc,T_sc,inf_tol,s,nmaxfull)

    # Gather Results 
    comm.Gatherv(hprime_sub, [hprime, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(nlprime_sub, [nlprime, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(nkprime_sub, [nkprime, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(hpot_sub, [hpot, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(nlpot_sub, [nlpot, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(nkpot_sub, [nkpot, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(hstr_sub, [hstr, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(nlstr_sub, [nlstr, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(nkstr_sub, [nkstr, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(hshr_sub, [hshr, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(nlshr_sub, [nlshr, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(nkshr_sub, [nkshr, (sendcounts, None), MPI.DOUBLE], root=0)
    comm.Gatherv(sint_mt_sub, [sint_mt, (sendcounts, None), stype], root=0)
    comm.Gatherv(Yload_sub, [Yload, (sendcounts, None), ytype], root=0)
    comm.Gatherv(Ypot_sub, [Ypot, (sendcounts, None), ytype], root=0)
    comm.Gatherv(Ystr_sub, [Ystr, (sendcounts, None), ytype], root=0)
    comm.Gatherv(Yshr_sub, [Yshr, (sendcounts, None), ytype], root=0)

    # Make Sure Everyone Has Reported Back Before Moving On
    comm.Barrier()

    # Free Data Types
    lntype.Free()
    stype.Free()
    ytype.Free()

    # Print Output to Files and Return Variables
    if (rank == 0):
 
        # Re-Organize Spherical Harmonic Degrees
        narr,nidx = np.unique(myn_mix,return_index=True)
        hprime = hprime[nidx]; nlprime = nlprime[nidx]; nkprime = nkprime[nidx]
        hpot = hpot[nidx]; nlpot = nlpot[nidx]; nkpot = nkpot[nidx]
        hstr = hstr[nidx]; nlstr = nlstr[nidx]; nkstr = nkstr[nidx]
        hshr = hshr[nidx]; nlshr = nlshr[nidx]; nkshr = nkshr[nidx]
        sint_mt = sint_mt[nidx,:]; Yload = Yload[nidx,:]; Ypot = Ypot[nidx,:]; Ystr = Ystr[nidx,:]; Yshr = Yshr[nidx,:]

        # Prepare Output Filenames (Random Integers Distinguish Files if Code is Being Run In Multiple Instances -- Body & Header Files Deleted After Writing)
        lln_file = ("../output/Love_Numbers/LLN/" + lln_out)
        pln_file = ("../output/Love_Numbers/PLN/" + pln_out)
        str_file = ("../output/Love_Numbers/STR/" + str_out)
        shr_file = ("../output/Love_Numbers/SHR/" + shr_out)
        lln_head = ("../output/Love_Numbers/LLN/" + str(np.random.randint(500)) + "header.txt")
        pln_head = ("../output/Love_Numbers/PLN/" + str(np.random.randint(500)) + "header.txt")
        str_head = ("../output/Love_Numbers/STR/" + str(np.random.randint(500)) + "header.txt")
        shr_head = ("../output/Love_Numbers/SHR/" + str(np.random.randint(500)) + "header.txt")
        lln_body = ("../output/Love_Numbers/LLN/" + str(np.random.randint(500)) + "body.txt")
        pln_body = ("../output/Love_Numbers/PLN/" + str(np.random.randint(500)) + "body.txt")
        str_body = ("../output/Love_Numbers/STR/" + str(np.random.randint(500)) + "body.txt")
        shr_body = ("../output/Love_Numbers/SHR/" + str(np.random.randint(500)) + "body.txt")

        # Prepare Data For Output
        all_lln_data = np.column_stack((myn,hprime,nlprime,nkprime,hprime_asym,nlprime_asym,nkprime_asym))
        all_pln_data = np.column_stack((myn,hpot,nlpot,nkpot))
        all_str_data = np.column_stack((myn,hstr,nlstr,nkstr))
        all_shr_data = np.column_stack((myn,hshr,nlshr,nkshr))

        # Universal Header
        uh1 = ('------------------------------------------------------ \n')
        uh2a = (':: Load Love Numbers (Load-Deformation Coefficients) \n')
        uh2b = (':: Potential Love Numbers \n')
        uh2c = (':: Stress Love Numbers \n')
        uh2d = (':: Shear Love Numbers \n')
        uh3 = (':: Computed at ' + datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y") + '\n')
        uh4 = ('------------------------------------------------------ \n')
        uh5 = (':: Material Parameters \n')
        uh6 = ('Planet-Radius (m) | Planet-Mass (kg) | Lambda-Surface (Pa) | Mu-Surface (Pa) | Gravity-Surface (m/s^2) \n')
        uh7 = (str(planet_radius) + ' ' + str(planet_mass) + ' ' + str(lmda_surface) + ' ' + str(mu_surface) + ' ' + str(g_surface) + '\n')
        uh8 = ('------------------------------------------------------ \n')
        uh9 = (':: Asymptotic Love Numbers \n')
        uh10 = ('hp     |     hpp     |     nlp     |     nlpp     |     nkp     |     nkpp \n')
        uh11 = (str(h_inf) + ' ' + str(h_inf_prime) + ' ' + str(l_inf) + ' ' + str(l_inf_prime) + ' ' + str(k_inf) + ' ' + str(k_inf_prime) + '\n')
        uh12 = ('------------------------------------------------------ \n')
        uh13 = ('******************   Love Numbers   ****************** \n')

        # Write Header Info to File
        hf = open(lln_head,'w')
        lln_str = 'n   |   h   |   nl   |   nk | h_asymptotic | nl_asymptotic | nk_asymptotic \n'
        hf.write(uh1); hf.write(uh2a); hf.write(uh3); hf.write(uh4); hf.write(uh5); hf.write(uh6)
        hf.write(uh7); hf.write(uh8); hf.write(uh9); hf.write(uh10); hf.write(uh11); hf.write(uh12); hf.write(uh13)
        hf.write(lln_str)
        hf.close()
        hf = open(pln_head,'w')
        pln_str = 'n   |   h   |   nl   |   nk \n'
        hf.write(uh1); hf.write(uh2b); hf.write(uh3); hf.write(uh4); hf.write(uh5); hf.write(uh6)
        hf.write(uh7); hf.write(uh8); hf.write(uh13)
        hf.write(pln_str)
        hf.close()
        hf = open(str_head,'w')
        str_str = 'n   |   h   |   nl   |   nk \n'
        hf.write(uh1); hf.write(uh2c); hf.write(uh3); hf.write(uh4); hf.write(uh5); hf.write(uh6)
        hf.write(uh7); hf.write(uh8); hf.write(uh13)
        hf.write(str_str)
        hf.close()
        hf = open(shr_head,'w')
        shr_str = 'n   |   h   |   nl   |   nk \n'
        hf.write(uh1); hf.write(uh2d); hf.write(uh3); hf.write(uh4); hf.write(uh5); hf.write(uh6)
        hf.write(uh7); hf.write(uh8); hf.write(uh13)
        hf.write(shr_str)
        hf.close()

        # Write Load Love Numbers to File
        np.savetxt(lln_body, all_lln_data, fmt='%7d %15.10f %15.10f %15.10f %15.10f %15.10f %15.10f')

        # Write Potential Love Numbers to File
        np.savetxt(pln_body, all_pln_data, fmt='%7d %15.10f %15.10f %15.10f')

        # Write Stress Love Numbers to File
        np.savetxt(str_body, all_str_data, fmt='%7d %15.10f %15.10f %15.10f')

        # Write Shear Love Numbers to File
        np.savetxt(shr_body, all_shr_data, fmt='%7d %15.10f %15.10f %15.10f')
 
        # Combine Header and Body Files
        filenames_lln = [lln_head, lln_body]
        with open(lln_file,'w') as outfile:
            for fname in filenames_lln:
                with open(fname) as infile:
                    outfile.write(infile.read())
        filenames_pln = [pln_head, pln_body]
        with open(pln_file,'w') as outfile:
            for fname in filenames_pln:
                with open(fname) as infile:
                    outfile.write(infile.read())
        filenames_str = [str_head, str_body]
        with open(str_file,'w') as outfile:
            for fname in filenames_str:
                with open(fname) as infile:
                    outfile.write(infile.read())
        filenames_shr = [shr_head, shr_body]
        with open(shr_file,'w') as outfile:
            for fname in filenames_shr:
                with open(fname) as infile:
                    outfile.write(infile.read())

        # Remove Header and Body Files
        os.remove(lln_head)
        os.remove(lln_body)
        os.remove(pln_head)
        os.remove(pln_body)
        os.remove(str_head)
        os.remove(str_body)
        os.remove(shr_head)
        os.remove(shr_body)

        # Re-Shape the Y Solution Arrays
        Yload = Yload.reshape(len(myn),int(len(Yload[0,:])/6),6)
        Ypot  = Ypot.reshape(len(myn), int(len( Ypot[0,:])/6),6)
        Ystr  = Ystr.reshape(len(myn), int(len( Ystr[0,:])/6),6)
        Yshr  = Yshr.reshape(len(myn), int(len( Yshr[0,:])/6),6)

        # Return Variables
        return myn,hprime,nlprime,nkprime,h_inf,l_inf,k_inf,h_inf_prime,l_inf_prime,k_inf_prime,hpot,nlpot,nkpot,\
            hstr,nlstr,nkstr,hshr,nlshr,nkshr,planet_radius,planet_mass,sint_mt,Yload,Ypot,Ystr,Yshr,lmda_surface,mu_surface
 
    else:

        # For Worker Ranks, Return Nothing
        return
def main(myn,sint,Yload,Ypot,Yshr,Ystr,hload,nlload,nkload,hpot,nlpot,nkpot,hshr,nlshr,nkshr,\
    hstr,nlstr,nkstr,emod_file,rank,comm,size,par_out='partials.txt',G=6.627E-11,r_min=1000.,kx=1,period_hours=12.42,delim=None,plot_figure=False):

    # Determine the Chunk Sizes for LLN
    total_lln = len(myn)
    nominal_load = total_lln // size # Floor Divide
    # Final Chunk Might Have Fewer or More Jobs
    if rank == size - 1:
        procN = total_lln - rank * nominal_load
    else: # Otherwise, Chunks are Size of nominal_load
        procN = nominal_load
 
    # Length of Radii Vector
    if (sint.size == sint.shape[0]):
        sys.exit("Error: Must have more than one radial distance.")
    else:  
        sint_length = sint.shape[1]

    if (rank == 0):

        # Print Update to Screen
        print(":: Computing Partial Derivatives. Please Wait..."); print("")

        # For SNREI Earth, Angular Frequency (omega) is Zero 
        # Azimuthal order is only utilized for a rotating Earth
        # The variables for each are included here as "place-holders" for future versions
        omega = 0
        order = 2

        # Prepare the Earth Model (read in, non-dimensionalize elastic parameters, etc.)
        r,mu,K,lmda,rho,g,tck_lnd,tck_mnd,tck_rnd,tck_gnd,s,lnd,mnd,rnd,gnd,s_min,small,\
            planet_radius,planet_mass,sic,soc,adim,gsdim,pi,piG,L_sc,R_sc,T_sc = \
            prepare_planet_model.main(emod_file,G,r_min,kx,file_delim=delim)

        # Define Forcing Period
        w = (1./(period_hours*3600.))*(2.*pi) # convert period to frequency (rad/sec)
        wnd = w*T_sc                         # non-dimensionalize
        ond = omega*T_sc

        # Initialize Arrays of Partial Derivatives
        dht_dmu  = np.empty((len(myn),sint_length))
        dlt_dmu  = np.empty((len(myn),sint_length))
        dkt_dmu  = np.empty((len(myn),sint_length))
        dht_dK   = np.empty((len(myn),sint_length))
        dlt_dK   = np.empty((len(myn),sint_length))
        dkt_dK   = np.empty((len(myn),sint_length))
        dht_drho = np.empty((len(myn),sint_length))
        dlt_drho = np.empty((len(myn),sint_length))
        dkt_drho = np.empty((len(myn),sint_length))
        dhl_dmu  = np.empty((len(myn),sint_length))
        dll_dmu  = np.empty((len(myn),sint_length))
        dkl_dmu  = np.empty((len(myn),sint_length))
        dhl_dK   = np.empty((len(myn),sint_length))
        dll_dK   = np.empty((len(myn),sint_length))
        dkl_dK   = np.empty((len(myn),sint_length))
        dhl_drho = np.empty((len(myn),sint_length))
        dll_drho = np.empty((len(myn),sint_length))
        dkl_drho = np.empty((len(myn),sint_length))
        dhs_dmu  = np.empty((len(myn),sint_length))
        dls_dmu  = np.empty((len(myn),sint_length))
        dks_dmu  = np.empty((len(myn),sint_length))
        dhs_dK   = np.empty((len(myn),sint_length))
        dls_dK   = np.empty((len(myn),sint_length))
        dks_dK   = np.empty((len(myn),sint_length))
        dhs_drho = np.empty((len(myn),sint_length))
        dls_drho = np.empty((len(myn),sint_length))
        dks_drho = np.empty((len(myn),sint_length))

    else: 

        # Workers Know Nothing About the Data
        dht_dmu = dlt_dmu = dkt_dmu = dht_dK = dlt_dK = dkt_dK = dht_drho = dlt_drho = dkt_drho = None
        dhl_dmu = dll_dmu = dkl_dmu = dhl_dK = dll_dK = dkl_dK = dhl_drho = dll_drho = dkl_drho = None
        dhs_dmu = dls_dmu = dks_dmu = dhs_dK = dls_dK = dks_dK = dhs_drho = dls_drho = dks_drho = None
        tck_lnd = tck_mnd = tck_rnd = tck_gnd = wnd = ond = piG = order = R_sc = T_sc = L_sc = None

    # Create a Data Type for the Harmonic Degrees
    lntype = MPI.DOUBLE.Create_contiguous(1)
    lntype.Commit() 

    # Create a Data Type for the Partials
    ptype = MPI.DOUBLE.Create_contiguous(sint_length)
    ptype.Commit()

    # Gather the Processor Workloads for All Processors
    sendcounts = comm.gather(procN, root=0)

    # Scatter the Harmonic Degrees
    n_sub = np.empty((procN,))
    comm.Scatterv([myn, (sendcounts, None), lntype], n_sub, root=0)

    # All Processors Get Certain Arrays and Parameters; Broadcast Them
    tck_lnd = comm.bcast(tck_lnd, root=0)
    tck_mnd = comm.bcast(tck_mnd, root=0)
    tck_rnd = comm.bcast(tck_rnd, root=0)
    tck_gnd = comm.bcast(tck_gnd, root=0)
    wnd = comm.bcast(wnd, root=0)
    ond = comm.bcast(ond, root=0)
    piG = comm.bcast(piG, root=0)
    order = comm.bcast(order, root=0)
    L_sc = comm.bcast(L_sc, root=0)
    T_sc = comm.bcast(T_sc, root=0)
    R_sc = comm.bcast(R_sc, root=0)

    # Loop Through Spherical Harmonic Degrees
    dht_dmu_sub  = np.empty((len(n_sub),sint_length))
    dlt_dmu_sub  = np.empty((len(n_sub),sint_length))
    dkt_dmu_sub  = np.empty((len(n_sub),sint_length))
    dht_dK_sub   = np.empty((len(n_sub),sint_length)) 
    dlt_dK_sub   = np.empty((len(n_sub),sint_length))
    dkt_dK_sub   = np.empty((len(n_sub),sint_length))
    dht_drho_sub = np.empty((len(n_sub),sint_length))
    dlt_drho_sub = np.empty((len(n_sub),sint_length))
    dkt_drho_sub = np.empty((len(n_sub),sint_length))
    dhl_dmu_sub  = np.empty((len(n_sub),sint_length))
    dll_dmu_sub  = np.empty((len(n_sub),sint_length))
    dkl_dmu_sub  = np.empty((len(n_sub),sint_length))
    dhl_dK_sub   = np.empty((len(n_sub),sint_length))
    dll_dK_sub   = np.empty((len(n_sub),sint_length))
    dkl_dK_sub   = np.empty((len(n_sub),sint_length))
    dhl_drho_sub = np.empty((len(n_sub),sint_length))
    dll_drho_sub = np.empty((len(n_sub),sint_length))
    dkl_drho_sub = np.empty((len(n_sub),sint_length))
    dhs_dmu_sub  = np.empty((len(n_sub),sint_length))
    dls_dmu_sub  = np.empty((len(n_sub),sint_length))
    dks_dmu_sub  = np.empty((len(n_sub),sint_length))
    dhs_dK_sub   = np.empty((len(n_sub),sint_length))
    dls_dK_sub   = np.empty((len(n_sub),sint_length))
    dks_dK_sub   = np.empty((len(n_sub),sint_length))
    dhs_drho_sub = np.empty((len(n_sub),sint_length))
    dls_drho_sub = np.empty((len(n_sub),sint_length))
    dks_drho_sub = np.empty((len(n_sub),sint_length))
    for ii in range(0,len(n_sub)):
        current_n = n_sub[ii]
        print('Partial Derivatives | Working on Harmonic Degree: %7s | Number: %6d of %6d | Rank: %6d' %(str(int(current_n)), (ii+1), len(n_sub), rank))
        nidx = int(current_n - min(myn)) # Determine Index (If the Range of 'n' Does Not Start at Zero)
        # Compute Integration Results for the Current Spherical Harmonic Degree, n
        dht_dmu_sub[ii,:],dlt_dmu_sub[ii,:],dkt_dmu_sub[ii,:],dht_dK_sub[ii,:],dlt_dK_sub[ii,:],dkt_dK_sub[ii,:],dht_drho_sub[ii,:],dlt_drho_sub[ii,:],dkt_drho_sub[ii,:],\
            dhl_dmu_sub[ii,:],dll_dmu_sub[ii,:],dkl_dmu_sub[ii,:],dhl_dK_sub[ii,:],dll_dK_sub[ii,:],dkl_dK_sub[ii,:],dhl_drho_sub[ii,:],dll_drho_sub[ii,:],dkl_drho_sub[ii,:],\
            dhs_dmu_sub[ii,:],dls_dmu_sub[ii,:],dks_dmu_sub[ii,:],dhs_dK_sub[ii,:],dls_dK_sub[ii,:],dks_dK_sub[ii,:],dhs_drho_sub[ii,:],dls_drho_sub[ii,:],dks_drho_sub[ii,:] = \
                ln_partials.main(current_n,sint[nidx,:],Yload[nidx,:,:],Ypot[nidx,:,:],Yshr[nidx,:,:],Ystr[nidx,:,:],hload[nidx],nlload[nidx],nkload[nidx],\
                hpot[nidx],nlpot[nidx],nkpot[nidx],hshr[nidx],nlshr[nidx],nkshr[nidx],hstr[nidx],nlstr[nidx],nkstr[nidx],\
                tck_lnd,tck_mnd,tck_rnd,tck_gnd,wnd,ond,piG,order,plot_figure)

    # Gather Results    
    comm.Gatherv(dht_dmu_sub, [dht_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dlt_dmu_sub, [dlt_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dkt_dmu_sub, [dkt_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dht_dK_sub, [dht_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dlt_dK_sub, [dlt_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dkt_dK_sub, [dkt_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dht_drho_sub, [dht_drho, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dlt_drho_sub, [dlt_drho, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dkt_drho_sub, [dkt_drho, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dhl_dmu_sub, [dhl_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dll_dmu_sub, [dll_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dkl_dmu_sub, [dkl_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dhl_dK_sub, [dhl_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dll_dK_sub, [dll_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dkl_dK_sub, [dkl_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dhl_drho_sub, [dhl_drho, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dll_drho_sub, [dll_drho, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dkl_drho_sub, [dkl_drho, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dhs_dmu_sub, [dhs_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dls_dmu_sub, [dls_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dks_dmu_sub, [dks_dmu, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dhs_dK_sub, [dhs_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dls_dK_sub, [dls_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dks_dK_sub, [dks_dK, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dhs_drho_sub, [dhs_drho, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dls_drho_sub, [dls_drho, (sendcounts, None), ptype], root=0)
    comm.Gatherv(dks_drho_sub, [dks_drho, (sendcounts, None), ptype], root=0)

    # Make Sure Everyone Has Reported Back Before Moving On
    comm.Barrier()

    # Free Data Types
    lntype.Free()
    ptype.Free()

    # Return Results and Print to File 
    if (rank == 0):
 
        # Loop through all Spherical Harmonic Degrees
        for jj in range(0,len(myn)):

            # Current Harmonic Degree
            cn = myn[jj]

            # Interpolate Parameters to 'sint' Locations
            imnd = interpolate.splev(sint[jj,:],tck_mnd)
            irnd = interpolate.splev(sint[jj,:],tck_rnd)
            ilnd = interpolate.splev(sint[jj,:],tck_lnd)
            iknd = ilnd + (2./3.)*imnd

            # Re-Dimensionalize
            ikappa = iknd*(R_sc*(L_sc**2)*(T_sc**(-2)))
            imu    = imnd*(R_sc*(L_sc**2)*(T_sc**(-2)))
            irho   = irnd*R_sc
            rint   = sint[jj,:]*L_sc/1000.

            # Print Info to File for Load Love Numbers
            out_head = ("../output/Love_Numbers/Partials/header_"+str(jj)+par_out)
            out_body = ("../output/Love_Numbers/Partials/body_"+str(jj)+par_out)
            out_name = ("../output/Love_Numbers/Partials/lln_n"+str(int(cn))+"_"+par_out)
            params = np.column_stack((rint,imnd,iknd,irnd,dhl_dmu[jj,:],dhl_dK[jj,:],dhl_drho[jj,:],dll_dmu[jj,:],dll_dK[jj,:],dll_drho[jj,:],\
                dkl_dmu[jj,:],dkl_dK[jj,:],dkl_drho[jj,:]))
            hf = open(out_head,'w')
            uh1 = ('------------------------------------------------------ \n')
            uh2 = (':: Load Love Number Partial Derivatives \n')
            uh3 = (':: Computed at ' + datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y") + '\n')
            uh4 = ('------------------------------------------------------ \n')
            hf.write(uh1); hf.write(uh2); hf.write(uh3); hf.write(uh4)
            out_str1 = ("n = "+str(int(cn))+" | Normalization: mu,kappa = (R_sc*(L_sc**2)*(T_sc**(-2))); rho = R_sc \n")
            out_str2 = ("    L_sc = "+str(L_sc)+ " | R_sc = "+str(R_sc)+ " | T_sc = "+str(T_sc)+ " | pi*G = "+str(piG)+ "\n")
            out_str3 = ' Radius(km)  Mu[non-dim]  Kappa[non-dim]  Rho[non-dim]  dhl_dmu  dhl_dK  dhl_drho  dll_dmu  dll_dK  dll_drho  dkl_dmu  dkl_dK  dkl_drho \n'
            out_str4 = ' ************************************************************************************************************************************** \n'
            hf.write(out_str1); hf.write(out_str2); hf.write(out_str3)
            hf.close()
            np.savetxt(out_body,params,fmt='%f %f %f %f %f %f %f %f %f %f %f %f %f')
            filenames_lln = [out_head, out_body]
            with open(out_name,'w') as outfile:
                for fname in filenames_lln:
                    with open(fname) as infile:
                        outfile.write(infile.read())
            os.remove(out_head)
            os.remove(out_body)

            # Print Info to File for Potential/Tide Love Numbers
            out_head = ("../output/Love_Numbers/Partials/header_"+str(jj)+par_out)
            out_body = ("../output/Love_Numbers/Partials/body_"+str(jj)+par_out)
            out_name = ("../output/Love_Numbers/Partials/pln_n"+str(int(cn))+"_"+par_out)
            params = np.column_stack((rint,imnd,iknd,irnd,dht_dmu[jj,:],dht_dK[jj,:],dht_drho[jj,:],dlt_dmu[jj,:],dlt_dK[jj,:],dlt_drho[jj,:],\
                dkt_dmu[jj,:],dkt_dK[jj,:],dkt_drho[jj,:]))
            hf = open(out_head,'w')
            uh1 = ('------------------------------------------------------ \n')
            uh2 = (':: Potential Love Number Partial Derivatives \n')
            uh3 = (':: Computed at ' + datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y") + '\n')
            uh4 = ('------------------------------------------------------ \n')
            hf.write(uh1); hf.write(uh2); hf.write(uh3); hf.write(uh4)
            out_str1 = ("n = "+str(int(cn))+" | Normalization: mu,kappa = (R_sc*(L_sc**2)*(T_sc**(-2))); rho = R_sc \n")
            out_str2 = ("    L_sc = "+str(L_sc)+ " | R_sc = "+str(R_sc)+ " | T_sc = "+str(T_sc)+ " | pi*G = "+str(piG)+ "\n")
            out_str3 = ' Radius(km)  Mu[non-dim]  Kappa[non-dim]  Rho[non-dim]  dhp_dmu  dhp_dK  dhp_drho  dlp_dmu  dlp_dK  dlp_drho  dkp_dmu  dkp_dK  dkp_drho \n'
            out_str4 = ' ************************************************************************************************************************************** \n'
            hf.write(out_str1); hf.write(out_str2); hf.write(out_str3)
            hf.close()
            np.savetxt(out_body,params,fmt='%f %f %f %f %f %f %f %f %f %f %f %f %f')
            filenames_lln = [out_head, out_body]
            with open(out_name,'w') as outfile:
                for fname in filenames_lln:
                    with open(fname) as infile:
                        outfile.write(infile.read())
            os.remove(out_head)
            os.remove(out_body)

            # Print Info to File for Shear Love Numbers (Stress Solution for n=1)
            out_head = ("../output/Love_Numbers/Partials/header_"+str(jj)+par_out)
            out_body = ("../output/Love_Numbers/Partials/body_"+str(jj)+par_out)
            out_name = ("../output/Love_Numbers/Partials/sln_n"+str(int(cn))+"_"+par_out)
            params = np.column_stack((rint,imnd,iknd,irnd,dhs_dmu[jj,:],dhs_dK[jj,:],dhs_drho[jj,:],dls_dmu[jj,:],dls_dK[jj,:],dls_drho[jj,:],\
                dks_dmu[jj,:],dks_dK[jj,:],dks_drho[jj,:]))
            hf = open(out_head,'w')
            uh1 = ('------------------------------------------------------ \n')
            uh2 = (':: Shear Love Number Partial Derivatives \n')
            uh3 = (':: Computed at ' + datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y") + '\n')
            uh4 = ('------------------------------------------------------ \n')
            hf.write(uh1); hf.write(uh2); hf.write(uh3); hf.write(uh4)
            if (cn == 1):
                out_str1 = ("n = "+str(int(cn))+" | STRESS SOLUTION | Normalization: mu,kappa = (R_sc*(L_sc**2)*(T_sc**(-2))); rho = R_sc \n")
            else:
                out_str1 = ("n = "+str(int(cn))+" | Normalization: mu,kappa = (R_sc*(L_sc**2)*(T_sc**(-2))); rho = R_sc \n")
            out_str2 = ("    L_sc = "+str(L_sc)+ " | R_sc = "+str(R_sc)+ " | T_sc = "+str(T_sc)+ " | pi*G = "+str(piG)+ "\n")
            out_str3 = ' Radius(km)  Mu[non-dim]  Kappa[non-dim]  Rho[non-dim]  dhs_dmu  dhs_dK  dhs_drho  dls_dmu  dls_dK  dls_drho  dks_dmu  dks_dK  dks_drho \n'
            out_str4 = ' ************************************************************************************************************************************** \n'
            hf.write(out_str1); hf.write(out_str2); hf.write(out_str3)
            hf.close()
            np.savetxt(out_body,params,fmt='%f %f %f %f %f %f %f %f %f %f %f %f %f')
            filenames_lln = [out_head, out_body]
            with open(out_name,'w') as outfile:
                for fname in filenames_lln:
                    with open(fname) as infile:
                        outfile.write(infile.read())
            os.remove(out_head)
            os.remove(out_body)

        # Return Results 
        return dht_dmu,dlt_dmu,dkt_dmu,dht_dK,dlt_dK,dkt_dK,dht_drho,dlt_drho,dkt_drho,dhl_dmu,dll_dmu,dkl_dmu,dhl_dK,dll_dK,dkl_dK,\
            dhl_drho,dll_drho,dkl_drho,dhs_dmu,dls_dmu,dks_dmu,dhs_dK,dls_dK,dks_dK,dhs_drho,dls_drho,dks_drho,\

    else:
 
        return