Ejemplo n.º 1
0
def calc_torqueCPU(CME):
    sp = np.sin(CME.p_angs)
    cp = np.cos(CME.p_angs)
    st = np.sin(CME.t_angs)
    ct = np.cos(CME.t_angs)

    # determine distance along x-axis, will subtract from xyz to get lever arm
    toraxx = [CME.cone[1, 0] + (CME.Lr + CME.rr * cp) * ct, 0. * cp, 0. * cp]

    toraxx = np.transpose(np.array(toraxx))
    tempvec = [toraxx[:, 0], toraxx[:, 1], toraxx[:, 2]]
    tempvec = FC.rotx(tempvec, -(90. - CME.tilt))
    tempvec = FC.roty(tempvec, -CME.cone[1, 1])
    tempvec = FC.rotz(tempvec, CME.cone[1, 2])
    toraxx = np.transpose(np.array(tempvec))
    # lever arm
    LA = [CME.xs - toraxx[:, 0], CME.ys - toraxx[:, 1], CME.zs - toraxx[:, 2]]
    LA = np.transpose(np.array(LA))

    # sum forces
    totF = CME.Ftens + CME.Fpgrad

    # torque is cross product of lever arm and def force
    FcrossLA = [
        LA[:, 1] * totF[:, 2] - LA[:, 2] * totF[:, 1],
        LA[:, 2] * totF[:, 0] - LA[:, 0] * totF[:, 2],
        LA[:, 0] * totF[:, 1] - LA[:, 1] * totF[:, 0]
    ]
    FcrossLA = np.transpose(np.array(FcrossLA))

    # dot with rhat to take radial component
    tottor = FcrossLA[:, 0] * CME.rhat[0] + FcrossLA[:, 1] * CME.rhat[
        1] + FcrossLA[:, 2] * CME.rhat[2]

    return np.sum(tottor) * rsun
Ejemplo n.º 2
0
def initForeCAT(input_values, skipPkl=False):
    #---------------------------------------------------------------------------------------|
    # Read in the filename from the command line and load the parameters -------------------|
    #---------------------------------------------------------------------------------------|
    global tprint, Ntor, Npol
    ipos, rmax, tprint, Ntor, Npol = FC.getInps(input_values, flagDate=skipPkl)
    #---------------------------------------------------------------------------------------|
    # Simulation set up --------------------------------------------------------------------|
    #---------------------------------------------------------------------------------------|
    if not skipPkl:  # option to skip this part if just using getInps for FIDO only
        # Initialize magnetic field data
        FF.init_CPU(FC.CR, Ntor, Npol)

        # Initialize magnetic field and distance pickles
        FC.initdefpickle(FC.CR)
    return ipos, rmax
Ejemplo n.º 3
0
 def calc_lens(self):
     self.rp = np.tan(self.AWp) / (
         1 + self.deltaCS * np.tan(self.AWp)) * self.points[idcent][1, 0]
     self.rr = self.deltaCS * self.rp
     self.Lp = (np.tan(self.AW) * (self.points[idcent][1, 0] - self.rr) -
                self.rr) / (1 + self.deltaAx * np.tan(self.AW))
     self.Lr = self.deltaAx * self.Lp
     self.cone[1, :] = self.points[idcent][1, :]
     self.cone[1, 0] += -self.Lr - self.rr  # new version
     self.cone[0, :] = FC.SPH2CART(self.cone[1, :])
Ejemplo n.º 4
0
    def update_CME(self, user_vr, user_exp, user_mass):
        # Determines the forces and updates the CME accordingly.

        # Calculate the drag acting on the CME
        self.Fdrag = FC.calc_drag(self)

        # Calculate the deflection forces on the CME
        FF.calc_forcesCPU(self)

        # convert forces to accelerations
        self.get_center_acc()

        # calculate magnitude of vr
        vrmag = np.sqrt(np.sum(self.vels[0, :]**2))

        self.addDefDrag(vrmag)
        # account for solar rotation -> slips toward lower Carrington lon
        self.points[idcent][1, 2] -= dt * radeg * FC.rotrate  # add in degrees
        # make sure doesn't go above 360
        self.points[idcent][1, 2] = self.points[idcent][1, 2] % 360.
        # move forward radially
        self.points[idcent][1, 0] += vrmag * dt / rsun

        # rotate the CME using angular velocity
        #just need to change tilt before calc'ing the new points
        self.tilt += self.angvel * dt

        # Update the angular width using user_exp from ForeCAT.py
        # could eventually replace this forces updating CME lens
        self.AW = user_exp(self.points[idcent][1, 0]) * dtor
        self.AWp = self.AWratio(self.points[idcent][1, 0]) * self.AW
        #self.deltaCSAx = self.AWp / self.AW / self.deltaCS
        self.calc_lens()
        self.deltaCSAx = self.rr / self.Lp

        # determine new mass
        self.M = user_mass(self.points[idcent][1, 0])

        # determine new density
        self.calc_rho()

        # determine new position of grid points with updated AW and cone pos
        self.calc_points()  # this also updates GPU shape and position

        # get radial velocity at new distance
        vmag, self.vels[0, :] = user_vr(self.points[idcent][1, 0], self.rhat)
        self.getvs(vmag)
        # update time (in minutes)
        self.t += self.dt

        # check if abs(lat) greater than 89.5 since ForeCAT gets wonky at poles
        if np.abs(self.cone[1, 1]) > 89.5:
            self.points[idcent][1, 0] = 999999  # stop simulation
            print("Hit pole, stopped simulation")
            print(self.cone[1, :])
Ejemplo n.º 5
0
def calc_posCPU(CME):
    # new hybrid shape version
    xAx = CME.deltaAx * CME.Lp * np.cos(CME.t_angs)
    zAx = 0.5 * CME.Lp * np.sign(CME.t_angs) * (
        np.sin(np.abs(CME.t_angs)) + np.sqrt(1 - np.cos(np.abs(CME.t_angs))))
    xCS = CME.deltaCS * CME.rp * np.cos(CME.p_angs)
    yCS = CME.rp * np.sin(CME.p_angs)
    sinTheta = 4 * CME.deltaAx * np.sin(CME.t_angs) / np.sqrt(
        (2 * np.cos(CME.t_angs) + np.sqrt(1 + np.cos(CME.t_angs)))**2 +
        16 * CME.deltaAx**2 * np.sin(CME.t_angs)**2)
    cosTheta = np.sqrt(1 - sinTheta**2)
    xs = CME.cone[1, 0] + xAx + xCS * cosTheta
    ys = yCS
    zs = zAx + xCS * sinTheta

    RLLT = [
        CME.cone[1, 0], CME.cone[1, 1] * dtor, CME.cone[1, 2] * dtor,
        CME.tilt * dtor
    ]
    # make a vector for position in CME coordinates
    CCvec = [xs, ys, zs]
    CCvec1 = FC.rotx(CCvec, -(90 - CME.tilt))
    CCvec2 = FC.roty(CCvec1, -CME.cone[1, 1])
    xyzpos = FC.rotz(CCvec2, CME.cone[1, 2])
    CMErs = np.sqrt(xyzpos[0]**2 + xyzpos[1]**2 + xyzpos[2]**2)
    CMElats = 90. - np.arccos(xyzpos[2] / CMErs) / dtor
    CMElons = np.arctan(xyzpos[1] / xyzpos[0]) / dtor
    negxs = np.where(xyzpos[0] < 0)
    CMElons[negxs] += 180.
    CMElons[np.where(CMElons < 0)] += 360.
    SPHpos = [CMErs, CMElats, CMElons]
    for i in range(CC.Npoints):
        CME.points[i][0, :] = [xyzpos[0][i], xyzpos[1][i], xyzpos[2][i]]
        CME.points[i][1, :] = [SPHpos[0][i], SPHpos[1][i], SPHpos[2][i]]
    # convenient to store these in class as arrays for serial version
    CME.rs = CMErs
    CME.lats = CMElats
    CME.lons = CMElons
    CME.xs = xyzpos[0][:]
    CME.ys = xyzpos[1][:]
    CME.zs = xyzpos[2][:]
Ejemplo n.º 6
0
def runForeCAT(CME, rmax, silent=False, path=False):
    #---------------------------------------------------------------------------------------|
    # Simulation Main Loop -----------------------------------------------------------------|
    #---------------------------------------------------------------------------------------|

    dtprint = CME.dt  # initiate print counter

    # Set up empty arrays if output path
    if path:
        outts, outRs, outlats, outlons, outtilts, outvs, outAWs, outAWps, outvdefs, outdeltaAxs, outdeltaCSs, outdeltaCAs = [], [], [], [], [], [], [], [], [], [], [], []

    # Run until nose hits rmax
    while CME.points[CC.idcent][1, 0] <= rmax:
        if CME.points[CC.idcent][1, 0] < 2.:
            critT = tprint / 2.
        else:
            critT = tprint
        # Check if time to print to screen and/or path
        if (dtprint > critT) or (CME.t == 0):
            if not silent:
                FC.printstep(CME)
            if path:
                outts.append(CME.t)
                outRs.append(CME.points[CC.idcent][1, 0])
                outlats.append(CME.points[CC.idcent][1, 1])
                outtilts.append(CME.tilt)
                # Need to apply lon and tilt corrections done in printstep
                thislon = CME.points[CC.idcent][1, 2]
                # FC.lon0 <-998 flags that we want to keep effects of solar rotation in
                # ie. the CME lon would slip toward lower Carrington lons
                # This is probably not going to be used in many cases so the if part is
                # mostly unnecessary since will always want to adjust
                # lon0 = 0 means run in Carrington coords without including solar rot
                # lon0 = initial CME lon will give relative change (without solar rot)
                if FC.lon0 > -998:
                    newlon = thislon - FC.lon0 + FC.rotrate * 60. * FC.radeg * CME.t
                outlons.append(newlon)
                #vCME = np.sqrt(np.sum(CME.vels[0,:]**2))/1e5
                vdef = np.sqrt(np.sum((CME.vdefLL + CME.vdragLL)**2)) / 1e5
                vs = np.copy(CME.vs) / 1e5
                outvs.append(vs)
                outvdefs.append(vdef)
                outAWs.append(CME.AW * FC.radeg)
                outAWps.append(CME.AWp * FC.radeg)
                outdeltaAxs.append(CME.deltaAx)
                outdeltaCSs.append(CME.deltaCS)
                outdeltaCAs.append(CME.deltaCSAx)
            # Reset print counter
            dtprint = CME.dt

        # Advance a step
        CME.update_CME(FC.user_vr, FC.user_exp, FC.user_mass)
        dtprint += CME.dt

    # Print final step if tprint not equal to time resolution so that we
    # include the last point that actually crosses rmax
    if not silent:
        if tprint != CME.dt:
            FC.printstep(CME)
    if path:
        if tprint != CME.dt:
            outts.append(CME.t)
            outRs.append(CME.points[CC.idcent][1, 0])
            outlats.append(CME.points[CC.idcent][1, 1])
            outtilts.append(CME.tilt)
            thislon = CME.points[CC.idcent][1, 2]
            if FC.lon0 > -998:
                newlon = thislon - FC.lon0 + FC.rotrate * 60. * FC.radeg * CME.t
            outlons.append(newlon)
            #vCME = np.sqrt(np.sum(CME.vels[0,:]**2))/1e5
            vdef = np.sqrt(np.sum((CME.vdefLL + CME.vdragLL)**2)) / 1e5
            vs = CME.vs / 1e5
            outvs.append(vs)
            outvdefs.append(vdef)
            outAWs.append(CME.AW * FC.radeg)
            outAWps.append(CME.AWp * FC.radeg)
            outdeltaAxs.append(CME.deltaAx)
            outdeltaCSs.append(CME.deltaCS)
            outdeltaCAs.append(CME.deltaCSAx)

    # Clean up things
    if FC.saveData: FC.outfile.close()  # close the output files

    # Correct the nose lon of the CME (take out solar rotation)
    # and recalculate the CME points
    if FC.lon0 > -998:
        newlon = CME.cone[1, 2] - FC.lon0 + FC.rotrate * 60. * FC.radeg * CME.t
        CME.cone[1, 2] = newlon
        CME.calc_points()

    # Return the path data if needed, else just return final CME
    if path:
        return CME, np.array([
            outts, outRs, outlats, outlons, outtilts, outAWs, outAWps, outvs,
            outvdefs, outdeltaAxs, outdeltaCSs, outdeltaCAs
        ])
    else:
        return CME
Ejemplo n.º 7
0
            outAWps.append(CME.AWp * FC.radeg)
            outdeltaAxs.append(CME.deltaAx)
            outdeltaCSs.append(CME.deltaCS)
            outdeltaCAs.append(CME.deltaCSAx)

    # Clean up things
    if FC.saveData: FC.outfile.close()  # close the output files

    # Correct the nose lon of the CME (take out solar rotation)
    # and recalculate the CME points
    if FC.lon0 > -998:
        newlon = CME.cone[1, 2] - FC.lon0 + FC.rotrate * 60. * FC.radeg * CME.t
        CME.cone[1, 2] = newlon
        CME.calc_points()

    # Return the path data if needed, else just return final CME
    if path:
        return CME, np.array([
            outts, outRs, outlats, outlons, outtilts, outAWs, outAWps, outvs,
            outvdefs, outdeltaAxs, outdeltaCSs, outdeltaCAs
        ])
    else:
        return CME


if __name__ == '__main__':
    input_values, allinputs = FC.readinputfile()
    ipos, rmax = initForeCAT(input_values)
    CME = initCME([FC.deltaAx, FC.deltaCS, FC.rstart], ipos)
    CME = runForeCAT(CME, rmax, path=True)
Ejemplo n.º 8
0
def calc_forcesCPU(CME):
    # will repeatedly need sin/cos of lon/colat -> calc once here
    sc = np.sin((90. - CME.lats) * dtor)
    cc = np.cos((90. - CME.lats) * dtor)
    sl = np.sin(CME.lons * dtor)
    cl = np.cos(CME.lons * dtor)
    scangs = [sc, cc, sl, cl]
    # unit vec in radial direction
    rhat = np.transpose(np.array([sc * cl, sc * sl, cc]))

    # calculate mag field at CME points
    BCME = getBCPU(CME.rs, CME.lats, CME.lons, scangs)
    Bhat = BCME[:, :3] / (BCME[:, 3].reshape([-1, 1]))

    # calculate mag field at adjacent points for gradients
    # really only need magnitude...
    Blat1 = getBCPU(CME.rs, CME.lats + 0.5, CME.lons, scangs)
    Blat2 = getBCPU(CME.rs, CME.lats - 0.5, CME.lons, scangs)
    dB2dlat = (Blat1[:, 3]**2 - Blat2[:, 3]**2) / 2. / (0.5 * dtor * RsR *
                                                        7e10 * CME.rs)
    Blon1 = getBCPU(CME.rs, CME.lats, CME.lons + 0.5, scangs)
    Blon2 = getBCPU(CME.rs, CME.lats, CME.lons - 0.5, scangs)
    dB2dlon = (Blon1[:, 3]**2 - Blon2[:, 3]**2) / 2. / (0.5 * dtor * RsR *
                                                        7e10 * CME.rs * sc)
    dB2 = np.transpose(
        np.array([
            cc * cl * dB2dlat + sl * dB2dlon, cc * sl * dB2dlat - cl * dB2dlon,
            -sc * dB2dlat
        ]))

    # calculate tension force----------------------------------------
    sp = np.sin(CME.p_angs)
    cp = np.cos(CME.p_angs)
    st = np.sin(CME.t_angs)
    ct = np.cos(CME.t_angs)

    # good to here w/o shape

    # for convenience make short shape names
    a, b, c = CME.Lr, CME.rp, CME.Lp

    # toroidal tangent vector
    xt = np.transpose(np.array([-(a + b * cp) * st, 0 * sp,
                                (c + b * cp) * ct]))
    xtmag = np.sqrt(xt[:, 0]**2 + xt[:, 1]**2 + xt[:, 2]**2)
    tgt_t = xt / xtmag.reshape([-1, 1])

    # poloidal tangent vector
    xp = np.transpose(np.array([-b * sp * ct, b * cp, -b * sp * st]))
    xpmag = np.sqrt(xp[:, 0]**2 + xp[:, 1]**2 + xp[:, 2]**2)
    tgt_p = xp / xpmag.reshape([-1, 1])

    # normal vector = cross product
    norm = np.cross(tgt_p, tgt_t)

    # calculate second derivatives
    xpp = np.transpose(np.array([-b * cp * ct, -b * sp, -b * cp * st]))
    xtt = np.transpose(
        np.array([-(a + b * cp) * ct, 0 * sp, -(c + b * cp) * st]))
    xpt = np.transpose(np.array([b * sp * st, 0 * sp, -b * sp * ct]))

    # coefficients of the first fundamental form
    E1FF = xp[:, 0]**2 + xp[:, 1]**2 + xp[:, 2]**2
    F1FF = xp[:, 0] * xt[:, 0] + xp[:, 1] * xt[:, 1] + xp[:, 2] * xt[:, 2]
    G1FF = xt[:, 0]**2 + xt[:, 1]**2 + xt[:, 2]**2

    # coefficients of second fundamental form
    e2FF = norm[:, 0] * xpp[:, 0] + norm[:, 1] * xpp[:, 1] + norm[:,
                                                                  2] * xpp[:,
                                                                           2]
    f2FF = norm[:, 0] * xpt[:, 0] + norm[:, 1] * xpt[:, 1] + norm[:,
                                                                  2] * xpt[:,
                                                                           2]
    g2FF = norm[:, 0] * xtt[:, 0] + norm[:, 1] * xtt[:, 1] + norm[:,
                                                                  2] * xtt[:,
                                                                           2]

    # rotate vectors to sun frame
    tempvec = [tgt_t[:, 0], tgt_t[:, 1], tgt_t[:, 2]]
    tempvec = FC.rotx(tempvec, -(90. - CME.tilt))
    tempvec = FC.roty(tempvec, -CME.cone[1, 1])
    tempvec = FC.rotz(tempvec, CME.cone[1, 2])
    tgt_t = np.transpose(np.array(tempvec))
    tempvec = [tgt_p[:, 0], tgt_p[:, 1], tgt_p[:, 2]]
    tempvec = FC.rotx(tempvec, -(90. - CME.tilt))
    tempvec = FC.roty(tempvec, -CME.cone[1, 1])
    tempvec = FC.rotz(tempvec, CME.cone[1, 2])
    tgt_p = np.transpose(np.array(tempvec))
    tempvec = [norm[:, 0], norm[:, 1], norm[:, 2]]
    tempvec = FC.rotx(tempvec, -(90. - CME.tilt))
    tempvec = FC.roty(tempvec, -CME.cone[1, 1])
    tempvec = FC.rotz(tempvec, CME.cone[1, 2])
    norm = np.transpose(np.array(tempvec))

    # solar B in pol/tor components
    Bt_u = Bhat[:, 0] * tgt_t[:, 0] + Bhat[:,
                                           1] * tgt_t[:,
                                                      1] + Bhat[:,
                                                                2] * tgt_t[:,
                                                                           2]
    Bp_u = Bhat[:, 0] * tgt_p[:, 0] + Bhat[:,
                                           1] * tgt_p[:,
                                                      1] + Bhat[:,
                                                                2] * tgt_p[:,
                                                                           2]

    # unit tangent vec for projected direction of draping on surface
    DD = np.transpose(np.array([np.sign(Bp_u) * np.sqrt(1 - Bt_u**2), Bt_u]))

    # determine geodesic curvature and tension force
    k = (e2FF * DD[:, 0]**2 + f2FF * DD[:, 0] * DD[:, 1] +
         g2FF * DD[:, 1]**2) / (E1FF * DD[:, 0]**2 + F1FF * DD[:, 0] * DD[:, 1]
                                + G1FF * DD[:, 1]**2)
    Ft_mag = np.abs(k) * BCME[:, 3]**2 / 4. / 3.14159 / (RsR * 7e10)

    # remove radial component
    ndr = norm[:, 0] * rhat[:, 0] + norm[:, 1] * rhat[:, 1] + norm[:,
                                                                   2] * rhat[:,
                                                                             2]
    n_nr = np.transpose(
        np.array([
            norm[:, 0] - ndr * rhat[:, 0], norm[:, 1] - ndr * rhat[:, 1],
            norm[:, 2] - ndr * rhat[:, 2]
        ]))
    Ftens = np.transpose(
        np.array(
            [-Ft_mag * n_nr[:, 0], -Ft_mag * n_nr[:, 1],
             -Ft_mag * n_nr[:, 2]]))

    # determine mag pressure force
    # first remove component of pressure gradients parallel to draped B
    drBhat = np.transpose(
        np.array([
            DD[:, 0] * tgt_p[:, 0] + DD[:, 1] * tgt_t[:, 0],
            DD[:, 0] * tgt_p[:, 1] + DD[:, 1] * tgt_t[:, 1],
            DD[:, 0] * tgt_p[:, 2] + DD[:, 1] * tgt_t[:, 2]
        ]))
    dB2parmag = dB2[:, 0] * drBhat[:,
                                   0] + dB2[:,
                                            1] * drBhat[:,
                                                        1] + dB2[:,
                                                                 2] * drBhat[:,
                                                                             2]
    dB2perp = np.transpose(
        np.array([
            dB2[:, 0] - dB2parmag * drBhat[:, 0],
            dB2[:, 1] - dB2parmag * drBhat[:, 1],
            dB2[:, 2] - dB2parmag * drBhat[:, 2]
        ]))
    Fpgrad = dB2perp / 8 / 3.14159

    # clean out any NaNs
    Ftens[np.where(np.isnan(Ftens) == True)] = 0
    Fpgrad[np.where(np.isnan(Fpgrad) == True)] = 0

    # put in CME object
    for i in range(CC.Npoints):
        CME.defforces[i][0, :] = Ftens[i, :]
        CME.defforces[i][1, :] = Fpgrad[i, :]
    CME.Ftens = Ftens
    CME.Fpgrad = Fpgrad
Ejemplo n.º 9
0
def cart2cart(x_in, lat, lon, tilt):
    # take in an xyz coordinate in frame where FR parallel to z axis and nose along x axis
    xyz = [x_in[0], x_in[1], x_in[2]]
    newxyz = FC.rotz(FC.roty(FC.rotx(xyz, -(90 - tilt)), -lat), lon)
    return newxyz