Skip to content

mors.cluster

cluster

Module holding the Cluster class and related functions.

log = logging.getLogger('fwl.' + __name__) module-attribute

Cluster(Mstar=None, Age=None, Omega=None, OmegaEnv=None, OmegaCore=None, AgesOut=None, starEvoDir=None, evoModels=None, params=params.paramsDefault, verbose=False)

A class for star objects that hold all information about a star.

This is the main function that is run when creating an instance of the Cluster class and it sets up all the things needed including calculating evolutionary tracks for each of the stars star. The function requires that an array of stellar masses (in Msun) and initial rotation rates (in OmegaSun=2.67e-6 rad s^-1) are input. using the Mstar and Omega keyword arguments. Alternatively, OmegaEnv and OmegaCore can be set, in which case Omega does not need to be specified. If the argument Age (in Myr) is also specified, then the code will find the evolutionary tracks for each star that passes through this rotation rate at this age, otherwise if Age is not set then it will calculate evolutionary tracks assuming this Omega as the initial (1 Myr) rotation rate. The user should not specify OmegaCore and Age simultaneously, and if Age is set then either Omega or OmegaEnv can be used to specify the surface rotation rate. Age can also be set as an array giving different ages for each star.

Source code in src/mors/cluster.py
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def __init__(self,Mstar=None,Age=None,Omega=None,OmegaEnv=None,OmegaCore=None,AgesOut=None,starEvoDir=None,evoModels=None,params=params.paramsDefault,verbose=False):
    """Initialises instance of Cluster class.

    This is the main function that is run when creating an instance of the Cluster class and it sets up all
    the things needed including calculating evolutionary tracks for each of the stars star. The function requires
    that an array of stellar masses (in Msun) and initial rotation rates (in OmegaSun=2.67e-6 rad s^-1) are input.
    using the Mstar and Omega keyword arguments. Alternatively, OmegaEnv and OmegaCore can be set, in which case
    Omega does not need to be specified. If the argument Age (in Myr) is also specified, then the code will find
    the evolutionary tracks for each star that passes through this rotation rate at this age, otherwise if Age is
    not set then it will calculate evolutionary tracks assuming this Omega as the initial (1 Myr) rotation rate.
    The user should not specify OmegaCore and Age simultaneously, and if Age is set then either Omega or OmegaEnv
    can be used to specify the surface rotation rate. Age can also be set as an array giving different ages for
    each star.

    """

    # Make sure Mstar was set
    if Mstar is None:
        raise Exception("Mstar keyword argument not set")

    # Make sure Omega, OmegaEnv, and OmegaCore are well set
    # (if Omega is set, OmegaEnv and OmegaCore will both be set to that value)
    Omega , OmegaEnv , OmegaCore = _CheckInputRotation(Age,Omega,OmegaEnv,OmegaCore)

    # Make sure arrays all same length
    if not ( len(Mstar) == len(Omega) ):
        raise Exception("Mstar and Omega have different lengths")
    if not ( len(Mstar) == len(OmegaEnv) ):
        raise Exception("Mstar and OmegaEnv have different lengths")
    if not ( len(Mstar) == len(OmegaCore) ):
        raise Exception("Mstar and OmegaCore have different lengths")

    # Set number of stars
    self.nStars = len(Mstar)

    # Set parameters
    self.params = params

    # Set the ExtendedTracks parameter to True so we get all parameters
    self.params['ExtendedTracks'] = True

    # Set Mstar arrays
    self.Mstar = Mstar

    # Set AgesOut
    self.AgesOut = AgesOut

    # Set stellar evo model
    self.starEvoDir = starEvoDir
    self.evoModels = evoModels

    # Get evolutionary tracks
    self._LoadEvoTracks(Age,OmegaEnv,OmegaCore,verbose)

    # Get HZ boundaries
    self.aOrbHZ = phys.aOrbHZ(Mstar=self.Mstar,params=self.params)

    return

ActivityLifetime(Quantity=None, Threshold=None, AgeMax=None)

Takes threshold value, returns ages at which each star last drops below this threshold.

This function can be used to determine when each star's emission crosses a given threshold value for a few activity quantities. These are Lx, Fx, Rx, and FxHZ for X-rays, and similar values for EUV1, EUV2, EUV, XUV, and Ly-alpha. If the star crosses the threshold (from above it to below it) multiple times, this will find the final time it will cross the threshold. If the user wants to set a maximum age so that the code only looks for crossings of the threshold below this age then this can be done using the AgeMax keyword argument.

Parameters:

Name Type Description Default
Quantity str

Gives which quantity to consider (e.g. 'Lx').

None
Threshold float or str

Value for threshold in units of quantity or string of 'sat'.

None
AgeMax float

End age of track to consider in Myr.

None

Returns:

Name Type Description
AgeActive float

Activity lifetime in Myr.

Source code in src/mors/cluster.py
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
def ActivityLifetime(self,Quantity=None,Threshold=None,AgeMax=None):
    """Takes threshold value, returns ages at which each star last drops below this threshold.

    This function can be used to determine when each star's emission crosses a given threshold value for a few
    activity quantities. These are Lx, Fx, Rx, and FxHZ for X-rays, and similar values for EUV1, EUV2, EUV,
    XUV, and Ly-alpha. If the star crosses the threshold (from above it to below it) multiple times, this
    will find the final time it will cross the threshold. If the user wants to set a maximum age so that the
    code only looks for crossings of the threshold below this age then this can be done using the AgeMax
    keyword argument.

    Parameters
    ----------
    Quantity : str
        Gives which quantity to consider (e.g. 'Lx').
    Threshold : float or str
        Value for threshold in units of quantity or string of 'sat'.
    AgeMax : float , optional
        End age of track to consider in Myr.

    Returns
    ----------
    AgeActive : float
        Activity lifetime in Myr.

    """

    # Make sure Quantity is set
    if Quantity is None:
        raise Exception("Quantity not set in call to function")

    # Make sure Quantity is string
    if not isinstance(Quantity,str):
        raise Exception("Quantity must be string")

    # Make array
    AgeActive = np.zeros(self.nStars)

    # Loop over stars and get each
    for iStar in range(self.nStars):
        AgeActive[iStar] = self.stars[iStar].ActivityLifetime(Quantity=Quantity,Threshold=Threshold,AgeMax=AgeMax)

    return AgeActive

IntegrateEmission(AgeMin=None, AgeMax=None, Band=None, aOrb=None)

Takes age range, returns integrated emission in band within that range for each star.

This code can be used to the luminosities of the stars between two ages. This can be applied to any wavelength band and the result is a total energy emitted in this time in erg. If the user also specifies an orbital distance using the aOrb keyword argument, the code integrates the flux at this obital distance returns a fluence in erg cm^-2. The user can specify aOrb as a string to get the fluences at various habitable zone boundaries (using the HZ calculated at the age defined in params when creating this cluster). Options are 'RecentVenus', 'RunawayGreenhouse', 'MoistGreenhouse', 'MaximumGreenhouse', 'EarlyMars', and 'HZ'.

Parameters:

Name Type Description Default
AgeMin float

Start of time period to integrate in Myr.

None
AgeMax float

End of time period to integrate in Myr.

None
Band str

Gives which wavelength band to consider (options are 'XUV', 'Xray', 'EUV1', 'EUV2', 'EUV', 'Lyman', 'bol').

None
aOrb float or str

Orbital distance to get fluence at in AU or string identifying HZ boundary.

None

Returns:

Name Type Description
Energy ndarray

Integrated luminosity or flux in erg or erg cm^-2.

Source code in src/mors/cluster.py
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
def IntegrateEmission(self,AgeMin=None,AgeMax=None,Band=None,aOrb=None):
    """Takes age range, returns integrated emission in band within that range for each star.

    This code can be used to the luminosities of the stars between two ages. This can be applied to any wavelength band
    and the result is a total energy emitted in this time in erg. If the user also specifies an orbital distance using
    the aOrb keyword argument, the code integrates the flux at this obital distance returns a fluence in erg cm^-2. The
    user can specify aOrb as a string to get the fluences at various habitable zone boundaries (using the HZ calculated
    at the age defined in params when creating this cluster). Options are 'RecentVenus', 'RunawayGreenhouse', 'MoistGreenhouse',
    'MaximumGreenhouse', 'EarlyMars', and 'HZ'.

    Parameters
    ----------
    AgeMin : float
        Start of time period to integrate in Myr.
    AgeMax : float
        End of time period to integrate in Myr.
    Band : str
        Gives which wavelength band to consider (options are 'XUV', 'Xray', 'EUV1', 'EUV2', 'EUV', 'Lyman', 'bol').
    aOrb : float or str, optional
        Orbital distance to get fluence at in AU or string identifying HZ boundary.

    Returns
    ----------
    Energy : numpy.ndarray
        Integrated luminosity or flux in erg or erg cm^-2.

    """

    # Make array
    Energy = np.zeros(self.nStars)

    # Loop over stars and get each
    for iStar in range(self.nStars):
        Energy[iStar] = self.stars[iStar].IntegrateEmission(AgeMin=AgeMin,AgeMax=AgeMax,Band=Band,aOrb=aOrb)

    return Energy

Percentile(Mstar=None, Age=None, Omega=None, Prot=None, percentile=None)

Gets rotation rate of percentile or percentile of rotation rate in the rotation distribution at given age.

This function can be used for two purposes 1. to determine the percentile in a rotation distribution of a star given its mass, rotation rate, and age 2. to determine the rotation rate of a star in a rotation distribution given its mass, percentile, and age In the first case, the user should specify the rotation rate using either the Omega or Prot keyword arguments (given in OmegaSun and days respectively) and the mass. In the second case, the user should specify the percentile using the percentile keyword argument (in the range 0 to 100) and the mass. The mass should be specified in Msun using the Mstar keyword argument and the age in Myr using the Age keyword argument. These should only be given as floats.

Parameters:

Name Type Description Default
Mstar float

Stellar mass in Msun.

None
Age float

Age of star in Myr.

None
Omega float

Rotation rate of star in OmegaSun.

None
Prot float

Rotation period of star in days.

None
percentile float

percentile in distribution (between 0 and 100).

None

Returns:

Name Type Description
result float

Either rotation rate for percentile or percentile for rotation rate.

Source code in src/mors/cluster.py
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
def Percentile(self,Mstar=None,Age=None,Omega=None,Prot=None,percentile=None):
    """Gets rotation rate of percentile or percentile of rotation rate in the rotation distribution at given age.

    This function can be used for two purposes
    1. to determine the percentile in a rotation distribution of a star given its mass, rotation rate, and age
    2. to determine the rotation rate of a star in a rotation distribution given its mass, percentile, and age
    In the first case, the user should specify the rotation rate using either the Omega or Prot keyword arguments (given
    in OmegaSun and days respectively) and the mass. In the second case, the user should specify the percentile using the
    percentile keyword argument (in the range 0 to 100) and the mass. The mass should be specified in Msun using the Mstar
    keyword argument and the age in Myr using the Age keyword argument. These should only be given as floats.

    Parameters
    ----------
    Mstar : float
        Stellar mass in Msun.
    Age : float
        Age of star in Myr.
    Omega : float , optional
        Rotation rate of star in OmegaSun.
    Prot : float , optional
        Rotation period of star in days.
    percentile : float , optional
        percentile in distribution (between 0 and 100).

    Returns
    ----------
    result : float
        Either rotation rate for percentile or percentile for rotation rate.

    """

    # Make sure the age is specified
    if Age is None:
        raise Exception("keyword parameter Age not set in call to function")

    # If percentile was set to a string, get float version
    if isinstance(percentile,str):
        if ( percentile == 'slow' ):
            percentile = 5.0
        elif ( percentile == 'medium' ):
            percentile = 50.0
        elif ( percentile == 'fast' ):
            percentile = 95.0
        else:
            raise Exception( "invalid percentile string (options are 'slow', 'medium', or 'fast')" )

    # Get the rotation distribution at this age
    OmegaDist = self.Values( Age=Age , Quantity='OmegaEnv' )

    # Get the result
    result = star.Percentile( Mstar=Mstar , Omega=Omega , Prot=Prot , percentile=percentile ,
                            MstarDist=self.Mstar , OmegaDist=OmegaDist , params=self.params )

    return result

PrintStars()

Prints list of stars in cluster to screen.

Source code in src/mors/cluster.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
def PrintStars(self):
    """Prints list of stars in cluster to screen."""

    # Header
    log.info("The following is a list of masses for stars in this cluster.")

    # Loop over each star and print basic parameters
    for iStar in range(0,self.nStars):
        log.info("   "+str(iStar)+". "+str(self.Mstar[iStar])+" Msun")

    # Total number of stars
    log.info("Number of stars in cluster = "+str(self.nStars))

    return

Save(filename='cluster.pickle')

Takes filename (default is 'cluster.pickle'), saves cluster to this file using pickle.

Source code in src/mors/cluster.py
183
184
185
186
187
188
189
def Save(self,filename='cluster.pickle'):
    """Takes filename (default is 'cluster.pickle'), saves cluster to this file using pickle."""

    with open(filename,'wb') as f:
        pickle.dump(self,f)

    return

Values(Age=None, Quantity=None)

Takes age in Myr and a string with name of quantity to output, returns value of that quantity at specified age for all stars.

Parameters:

Name Type Description Default
Age float

Age of cluster.

None
Quantity str

String holding name of parameter to get.

None

Returns:

Name Type Description
values ndarray

Set of extended quantities.

Source code in src/mors/cluster.py
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
def Values(self,Age=None,Quantity=None):
    """Takes age in Myr and a string with name of quantity to output, returns value of that quantity at specified age for all stars.

    Parameters
    ----------
    Age : float
        Age of cluster.
    Quantity : str
        String holding name of parameter to get.

    Returns
    ----------
    values : numpy.ndarray
        Set of extended quantities.

    """

    # Make sure input parameters are set
    if Age is None:
        raise Exception("keyword parameter Age not set in call to function")
    if Quantity is None:
        raise Exception("keyword parameter Quantity not set in call to function")

    # Make array to hold values
    values = np.zeros(self.nStars)

    # Loop over stars and get values for each
    for iStar in range(0,self.nStars):
        values[iStar] = self.stars[iStar].Value(Age=Age,Quantity=Quantity)

    return values

save(filename='cluster.pickle')

Same as Save().

Source code in src/mors/cluster.py
191
192
193
194
def save(self,filename='cluster.pickle'):
    """Same as Save()."""
    self.Save(filename=filename)
    return

_CheckInputRotation(Age, Omega, OmegaEnv, OmegaCore)

Takes input rotation, checks if values are setup correctly.

Source code in src/mors/cluster.py
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
def _CheckInputRotation(Age,Omega,OmegaEnv,OmegaCore):
  """Takes input rotation, checks if values are setup correctly."""

  # Make sure if Age is set that OmegaCore is not set
  if ( not Age is None ) and ( not OmegaCore is None ):
    raise Exception( "cannot set both Age and OmegaCore as arguments of Cluster" )

  # Make sure at least one rotation rate is set
  if ( Omega is None ):

    # Since Omega is not set, make sure both OmegaEnv and OmegaCore are set
    if ( OmegaEnv is None ) or ( OmegaCore is None ):
      raise Exception( "must set either Omega or both OmegaEnv and OmegaCore as arugment of Star" )

  else:

    # Since Omega is set, make sure both OmegaEnv and OmegaCore are not set
    if not ( ( OmegaEnv is None ) and ( OmegaCore is None ) ):
      raise Exception( "cannot set OmegaEnv and OmegaCore when Omega is set as arugment of Star" )

    # Set both OmegaEnv and OmegaCore to Omega
    OmegaEnv = Omega
    OmegaCore = Omega

  return Omega , OmegaEnv , OmegaCore