"""
A collection of density physical property definitions.
"""
from propertyestimator.datasets.plugins import register_thermoml_property
from propertyestimator.properties import PhysicalProperty, PropertyPhase
from propertyestimator.properties.plugins import register_estimable_property
from propertyestimator.protocols import analysis, reweighting
from propertyestimator.protocols.utils import generate_base_simulation_protocols, generate_base_reweighting_protocols, \
generate_gradient_protocol_group
from propertyestimator.storage import StoredSimulationData
from propertyestimator.utils.statistics import ObservableType
from propertyestimator.workflow.schemas import WorkflowSchema
from propertyestimator.workflow.utils import ProtocolPath
[docs]@register_estimable_property()
@register_thermoml_property(thermoml_string='Mass density, kg/m3', supported_phases=PropertyPhase.Liquid)
class Density(PhysicalProperty):
"""A class representation of a density property"""
@property
def multi_component_property(self):
return False
@property
def required_data_class(self):
return StoredSimulationData
[docs] @staticmethod
def get_default_workflow_schema(calculation_layer, options=None):
if calculation_layer == 'SimulationLayer':
return Density.get_default_simulation_workflow_schema(options)
elif calculation_layer == 'ReweightingLayer':
return Density.get_default_reweighting_workflow_schema(options)
return None
[docs] @staticmethod
def get_default_simulation_workflow_schema(options=None):
"""Returns the default workflow to use when estimating this property
from direct simulations.
Parameters
----------
options: WorkflowOptions
The default options to use when setting up the estimation workflow.
Returns
-------
WorkflowSchema
The schema to follow when estimating this property.
"""
# Define the protocol which will extract the average density from
# the results of a simulation.
extract_density = analysis.ExtractAverageStatistic('extract_density')
extract_density.statistics_type = ObservableType.Density
# Define the protocols which will run the simulation itself.
protocols, value_source, output_to_store = generate_base_simulation_protocols(extract_density,
options)
# Set up the gradient calculations
reweight_density_template = reweighting.ReweightStatistics('')
reweight_density_template.statistics_type = ObservableType.Density
reweight_density_template.statistics_paths = [ProtocolPath('statistics_file_path',
protocols.converge_uncertainty.id,
protocols.production_simulation.id)]
coordinate_source = ProtocolPath('output_coordinate_file', protocols.equilibration_simulation.id)
trajectory_source = ProtocolPath('trajectory_file_path', protocols.converge_uncertainty.id,
protocols.production_simulation.id)
statistics_source = ProtocolPath('statistics_file_path', protocols.converge_uncertainty.id,
protocols.production_simulation.id)
gradient_group, gradient_replicator, gradient_source = \
generate_gradient_protocol_group(reweight_density_template,
[ProtocolPath('force_field_path', 'global')],
ProtocolPath('force_field_path', 'global'),
coordinate_source,
trajectory_source,
statistics_source)
# Build the workflow schema.
schema = WorkflowSchema(property_type=Density.__name__)
schema.id = '{}{}'.format(Density.__name__, 'Schema')
schema.protocols = {
protocols.build_coordinates.id: protocols.build_coordinates.schema,
protocols.assign_parameters.id: protocols.assign_parameters.schema,
protocols.energy_minimisation.id: protocols.energy_minimisation.schema,
protocols.equilibration_simulation.id: protocols.equilibration_simulation.schema,
protocols.converge_uncertainty.id: protocols.converge_uncertainty.schema,
protocols.extract_uncorrelated_trajectory.id: protocols.extract_uncorrelated_trajectory.schema,
protocols.extract_uncorrelated_statistics.id: protocols.extract_uncorrelated_statistics.schema,
gradient_group.id: gradient_group.schema
}
schema.replicators = [gradient_replicator]
schema.outputs_to_store = {'full_system': output_to_store}
schema.gradients_sources = [gradient_source]
schema.final_value_source = value_source
return schema
[docs] @staticmethod
def get_default_reweighting_workflow_schema(options):
"""Returns the default workflow to use when estimating this property
by reweighting existing data.
Parameters
----------
options: WorkflowOptions
The default options to use when setting up the estimation workflow.
Returns
-------
WorkflowSchema
The schema to follow when estimating this property.
"""
data_replicator_id = 'data_replicator'
# The protocol which will be used to calculate the densities from
# the existing data.
density_calculation = analysis.ExtractAverageStatistic(f'calc_density_$({data_replicator_id})')
density_calculation.statistics_type = ObservableType.Density
reweight_density = reweighting.ReweightStatistics(f'reweight_density')
reweight_density.statistics_type = ObservableType.Density
reweighting_protocols, data_replicator = generate_base_reweighting_protocols(density_calculation,
reweight_density,
options,
data_replicator_id)
# Set up the gradient calculations
coordinate_path = ProtocolPath('output_coordinate_path', reweighting_protocols.concatenate_trajectories.id)
trajectory_path = ProtocolPath('output_trajectory_path', reweighting_protocols.concatenate_trajectories.id)
reweight_density_template = reweighting.ReweightStatistics('')
reweight_density_template.statistics_type = ObservableType.Density
reweight_density_template.statistics_paths = ProtocolPath('statistics_file_path',
reweighting_protocols.unpack_stored_data.id)
gradient_group, gradient_replicator, gradient_source = \
generate_gradient_protocol_group(reweight_density_template,
ProtocolPath('force_field_path',
reweighting_protocols.unpack_stored_data.id),
ProtocolPath('force_field_path', 'global'),
coordinate_path,
trajectory_path,
replicator_id='grad',
use_subset_of_force_field=False,
effective_sample_indices=ProtocolPath('effective_sample_indices',
reweighting_protocols.
mbar_protocol.id))
schema = WorkflowSchema(property_type=Density.__name__)
schema.id = '{}{}'.format(Density.__name__, 'Schema')
schema.protocols = {protocol.id: protocol.schema for protocol in reweighting_protocols}
schema.protocols[gradient_group.id] = gradient_group.schema
schema.replicators = [data_replicator, gradient_replicator]
schema.gradients_sources = [gradient_source]
schema.final_value_source = ProtocolPath('value', reweighting_protocols.mbar_protocol.id)
return schema