Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core collapse supernovae #3485

Merged
merged 8 commits into from
Oct 9, 2020
43 changes: 43 additions & 0 deletions pycbc/distributions/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@
This modules provides classes for evaluating multi-dimensional constraints.
"""

import scipy.spatial
import numpy
import h5py
from pycbc import transforms
from pycbc.io import record


class Constraint(object):
"""Creates a constraint that evaluates to True if parameters obey
the constraint and False if they do not.
Expand Down Expand Up @@ -60,7 +64,46 @@ def _constraint(self, params):
return params[self.constraint_arg]


class SupernovaeConvexHull(Constraint):
"""Pre defined constraint for core-collapse waveforms that checks
whether a given set of coefficients lie within the convex hull of
the coefficients of the principal component basis vectors.
"""
name = "supernovae_convex_hull"
required_parameters = ["coeff_0", "coeff_1"]
cdcapano marked this conversation as resolved.
Show resolved Hide resolved

def __init__(self, constraint_arg, transforms=None, **kwargs):
super(SupernovaeConvexHull,
self).__init__(constraint_arg, transforms=transforms, **kwargs)

if 'principal_components_file' in kwargs:
pc_filename = kwargs['principal_components_file']
hull_dimention = numpy.array(kwargs['hull_dimention'])
self.hull_dimention = int(hull_dimention)
pc_file = h5py.File(pc_filename, 'r')
pc_coefficients = numpy.array(pc_file.get('coefficients'))
pc_file.close()
hull_points = []
for dim in range(self.hull_dimention):
hull_points.append(pc_coefficients[:, dim])
hull_points = numpy.array(hull_points).T
pc_coeffs_hull = scipy.spatial.Delaunay(hull_points)
self._hull = pc_coeffs_hull

def _constraint(self, params):

output_array = []
points = numpy.array([params["coeff_0"],
params["coeff_1"],
params["coeff_2"]])
for coeff_index in range(len(params["coeff_0"])):
point = points[:, coeff_index][:self.hull_dimention]
output_array.append(self._hull.find_simplex(point) >= 0)
return numpy.array(output_array)


# list of all constraints
constraints = {
Constraint.name : Constraint,
SupernovaeConvexHull.name : SupernovaeConvexHull,
}
16 changes: 16 additions & 0 deletions pycbc/waveform/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from . import waveform
from .waveform import (NoWaveformError, FailedWaveformError)
from . import ringdown
from . import supernovae
from pycbc import filter
from pycbc import transforms
from pycbc.types import TimeSeries
Expand Down Expand Up @@ -631,6 +632,16 @@ def generate(self, **kwargs):
return h


class TDomainSupernovaeGenerator(BaseGenerator):
"""Uses supernovae.py to create time domain core-collapse supernovae waveforms
using a set of Principal Components provided in a .hdf file.
"""
def __init__(self, variable_args=(), **frozen_params):
super(TDomainSupernovaeGenerator,
self).__init__(supernovae.get_corecollapse_bounce,
variable_args=variable_args, **frozen_params)


class FDomainDetFrameGenerator(object):
"""Generates frequency-domain waveform in a specific frame.

Expand Down Expand Up @@ -869,6 +880,11 @@ def select_waveform_generator(approximant):
elif approximant == 'TdQNMfromFreqTau':
return TDomainFreqTauRingdownGenerator

# check if supernovae waveform:
elif approximant in supernovae.supernovae_td_approximants:
if approximant == 'CoreCollapseBounce':
return TDomainSupernovaeGenerator

# otherwise waveform approximant is not supported
else:
raise ValueError("%s is not a valid approximant." % approximant)
52 changes: 52 additions & 0 deletions pycbc/waveform/supernovae.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Generate core-collapse supernovae waveform for core bounce and
subsequent postbounce oscillations.
"""

import numpy
import h5py
from pycbc.types import TimeSeries

_pc_dict = {}


def get_corecollapse_bounce(**kwargs):
""" Generates core bounce and postbounce waveform by using principal
component basis vectors from a .hdf file. The waveform parameters are the
coefficients of the principal components and the distance. The number of
principal components used can also be varied.
"""

try:
principal_components = _pc_dict['principal_components']
except KeyError:
with h5py.File(kwargs['principal_components_file'], 'r') as pc_file:
principal_components = numpy.array(pc_file['principal_components'])
_pc_dict['principal_components'] = principal_components

if 'coefficients_array' in kwargs:
coefficients_array = kwargs['coefficients_array']
else:
coeffs_keys = [x for x in kwargs if x.startswith('coeff_')]
coeffs_keys = numpy.sort(numpy.array(coeffs_keys))
coefficients_array = numpy.array([kwargs[x] for x in coeffs_keys])

no_of_pcs = int(kwargs['no_of_pcs'])
coefficients_array = coefficients_array[:no_of_pcs]
principal_components = principal_components[:no_of_pcs]

pc_len = len(principal_components)
assert len(coefficients_array) == pc_len

distance = kwargs['distance']
mpc_conversion = 3.08567758128e+22
distance *= mpc_conversion

strain = numpy.dot(coefficients_array, principal_components) / distance
delta_t = kwargs['delta_t']
outhp = TimeSeries(strain, delta_t=delta_t)
outhc = TimeSeries(numpy.zeros(len(strain)), delta_t=delta_t)
return outhp, outhc


# Approximant names ###########################################################
supernovae_td_approximants = {'CoreCollapseBounce': get_corecollapse_bounce}