Пример #1
0
    def test_model_returns_complex(self):
        # This tests model failure with scalar complex.
        # Quantity class has other more thorough tests.

        A = Symbol('a', ['A'], ['A'], units='dimensionless', shape=1)
        B = Symbol('b', ['B'], ['B'], units='dimensionless', shape=1)
        get_config = {
            'name': 'add_complex_value',
            # 'connections': [{'inputs': ['b'], 'outputs': ['a']}],
            'equations': ['a = b + 1j'],
            # 'unit_map': {'a': "dimensionless", 'a': "dimensionless"}
            'symbol_property_map': {
                "a": A,
                "b": B
            }
        }
        model = EquationModel(**get_config)
        out = model.evaluate({'b': Quantity(B, 5)}, allow_failure=True)
        self.assertFalse(out['successful'])
        self.assertEqual(out['message'],
                         'Evaluation returned invalid values (complex)')

        out = model.evaluate({'b': Quantity(B, 5j)}, allow_failure=True)
        self.assertTrue(out['successful'])
        self.assertTrue(np.isclose(out['a'].magnitude, 6j))
Пример #2
0
    def test_unit_handling(self):
        """
        Tests unit handling with a simple model that calculates the area of a rectangle as the
        product of two lengths.

        In this case the input lengths are provided in centimeters and meters.
        Tests whether the input units are properly coerced into canonical types.
        Tests whether the output units are properly set.
        Tests whether the model returns as predicted.
        Returns:
            None
        """
        L = Symbol('l', ['L'], ['L'], units=[1.0, [['centimeter', 1.0]]], shape=[1])
        A = Symbol('a', ['A'], ['A'], units=[1.0, [['centimeter', 2.0]]], shape=[1])
        get_area_config = {
            'name': 'area',
            # 'connections': [{'inputs': ['l1', 'l2'], 'outputs': ['a']}],
            'equations': ['a = l1 * l2'],
            # 'unit_map': {'l1': "cm", "l2": "cm", 'a': "cm^2"}
            'symbol_property_map': {"a": A, "l1": L, "l2": L}
        }
        model = EquationModel(**get_area_config)
        out = model.evaluate({'l1': Quantity(L, 1, 'meter'),
                              'l2': Quantity(L, 2)}, allow_failure=False)

        self.assertTrue(math.isclose(out['a'].magnitude, 200.0))
        self.assertTrue(out['a'].units == A.units)
Пример #3
0
    def test(self, inputs, outputs):
        """
        Runs a test of the model to determine whether its operation
        is consistent with the specified inputs and outputs

        Args:
            inputs (dict): set of input names to values
            outputs (dict): set of output names to values

        Returns (bool): True if test succeeds
        """
        evaluate_inputs = self.map_symbols_to_properties(inputs)
        evaluate_inputs = {s: Quantity(s, v, self.unit_map.get(s))
                           for s, v in evaluate_inputs.items()}
        evaluate_outputs = self.evaluate(evaluate_inputs, allow_failure=False)
        evaluate_outputs = self.map_properties_to_symbols(evaluate_outputs)
        errmsg = "{} model test failed on ".format(self.name) + "{}\n"
        errmsg += "{}(test data) = {}\n"#.format(k, known_output)
        errmsg += "{}(model output) = {}"#.format(k, plug_in_output)
        for k, known_output in outputs.items():
            symbol = self.symbol_property_map[k]
            units = self.unit_map.get(k)
            known_quantity = Quantity(symbol, known_output, units)
            evaluate_output = evaluate_outputs[k]
            if known_quantity.is_pint or isinstance(known_quantity.value, list):
                if not np.allclose(known_quantity.value, evaluate_output.value):
                    errmsg = errmsg.format("evaluate", k, evaluate_output,
                                           k, known_quantity)
                    raise ModelEvaluationError(errmsg)
            elif known_quantity != evaluate_output:
                errmsg = errmsg.format("evaluate", k, evaluate_output,
                                       k, known_quantity)
                raise ModelEvaluationError(errmsg)

        return True
Пример #4
0
 def test_add_default_quantities(self):
     material = Material(add_default_quantities=True)
     self.assertEqual(
         list(material['temperature'])[0], Quantity("temperature", 300))
     self.assertEqual(
         list(material['relative_permeability'])[0],
         Quantity("relative_permeability", 1))
Пример #5
0
 def test_from_weighted_mean(self):
     qlist = [
         Quantity(self.custom_symbol, val)
         for val in np.arange(1, 2.01, 0.01)
     ]
     qagg = Quantity.from_weighted_mean(qlist)
     self.assertAlmostEqual(qagg.magnitude, 1.5)
     self.assertAlmostEqual(qagg.uncertainty, 0.2915475947422652)
Пример #6
0
    def process_item(self, item):
        # Define quantities corresponding to materials doc fields
        # Attach quantities to materials
        item = MontyDecoder().process_decoded(item)
        logger.info("Populating material for %s", item['task_id'])
        material = Material()
        for mkey, property_name in self.materials_symbol_map.items():
            value = get(item, mkey)
            if value:
                material.add_quantity(Quantity(property_name, value))

        # Add custom things, e. g. computed entry
        computed_entry = get_entry(item)
        material.add_quantity(Quantity("computed_entry", computed_entry))
        material.add_quantity(
            Quantity("external_identifier_mp", item['task_id']))

        input_quantities = material.get_quantities()

        # Use graph to generate expanded quantity pool
        logger.info("Evaluating graph for %s", item['task_id'])
        graph = Graph()
        graph.remove_models({
            "dimensionality_cheon":
            DEFAULT_MODEL_DICT['dimensionality_cheon'],
            "dimensionality_gorai":
            DEFAULT_MODEL_DICT['dimensionality_gorai']
        })
        new_material = graph.evaluate(material)

        # Format document and return
        logger.info("Creating doc for %s", item['task_id'])
        doc = {"inputs": [quantity.as_dict() for quantity in input_quantities]}
        for symbol, quantity in new_material.get_aggregated_quantities().items(
        ):
            all_qs = new_material._symbol_to_quantity[symbol]
            # Only add new quantities
            if len(all_qs) == 1 and list(all_qs)[0] in input_quantities:
                continue
            qs = [quantity.as_dict() for quantity in all_qs]
            sub_doc = {
                "quantities": qs,
                "mean": unumpy.nominal_values(quantity.value).tolist(),
                "std_dev": unumpy.std_devs(quantity.value).tolist(),
                "units": qs[0]['units'],
                "title": quantity._symbol_type.display_names[0]
            }
            doc[symbol.name] = sub_doc
        doc.update({
            "task_id": item["task_id"],
            "pretty_formula": item["pretty_formula"]
        })
        return jsanitize(doc, strict=True)
Пример #7
0
    def test_properties(self):
        # Test units, magnitude
        q = Quantity("bulk_modulus", 100)
        self.assertEqual(q.units, "gigapascal")
        self.assertEqual(q.magnitude, 100)

        # Ensure non-pint values raise error with units, magnitude
        structure = PymatgenTest.get_structure('Si')
        q = Quantity("structure", structure)
        with self.assertRaises(ValueError):
            print(q.units)
        with self.assertRaises(ValueError):
            print(q.magnitude)
Пример #8
0
 def setUp(self):
     # Create some test properties and a few base objects
     self.q1 = Quantity(
         DEFAULT_SYMBOLS['bulk_modulus'],
         ureg.Quantity.from_tuple([200, [['gigapascals', 1]]]))
     self.q2 = Quantity(
         DEFAULT_SYMBOLS['shear_modulus'],
         ureg.Quantity.from_tuple([100, [['gigapascals', 1]]]))
     self.q3 = Quantity(
         DEFAULT_SYMBOLS['bulk_modulus'],
         ureg.Quantity.from_tuple([300, [['gigapascals', 1]]]))
     self.material = Material()
     self.graph = Graph()
Пример #9
0
 def generate_canonical_material(c_symbols):
     """
     Generates a Material with appropriately attached Quantities.
     Args:
         c_symbols: (dict<str, Symbol>) dictionary of defined materials.
     Returns:
         (Material) material with properties loaded.
     """
     q1 = Quantity(c_symbols['A'], 19)
     q2 = Quantity(c_symbols['A'], 23)
     m = Material()
     m.add_quantity(q1)
     m.add_quantity(q2)
     return m
Пример #10
0
 def test_quantity_construction(self):
     # From custom symbol
     q = Quantity(self.custom_symbol, 5.0)
     self.assertEqual(q.value.magnitude, 5.0)
     self.assertIsInstance(q.value, ureg.Quantity)
     # From canonical symbol
     q = Quantity("bulk_modulus", 100)
     self.assertEqual(q.value.magnitude, 100)
     # From custom symbol with constraint
     with self.assertRaises(SymbolConstraintError):
         Quantity(self.constraint_symbol, -500)
     # From canonical symbol with constraint
     with self.assertRaises(SymbolConstraintError):
         Quantity("bulk_modulus", -500)
Пример #11
0
    def evaluate(input_rows):

        quantities = [
            Quantity(symbol_type=ROW_IDX_TO_SYMBOL_NAME[idx],
                     value=ureg.parse_expression(row['Value']))
            for idx, row in enumerate(input_rows) if row['Value']
        ]
        material = Material()

        for quantity in quantities:
            material.add_quantity(quantity)

        graph = Graph()
        output_material = graph.evaluate(material)

        output_quantities = output_material.get_aggregated_quantities()
        print(output_quantities)

        output_rows = [{
            'Property': symbol.display_names[0],
            'Value': str(quantity.value),
            'Provenance': None
        } for symbol, quantity in output_quantities.items()]

        return output_rows
Пример #12
0
 def iterate(self, nested_dict=None):
     """http://stackoverflow.com/questions/10756427/loop-through-all-nested-dictionary-values"""
     d = self if nested_dict is None else nested_dict
     if nested_dict is None:
         self.level = 0
     for key in list(d.keys()):
         value = d[key]
         if isinstance(value, _Mapping):
             if value.get('@class') == 'Structure':
                 from pymatgen import Structure
                 yield key, Structure.from_dict(value)
                 continue
             yield (self.level, key), None
             if value.get('@class') == 'Table':
                 from mpcontribs.io.core.components.tdata import Table
                 yield key, Table.from_dict(value)
                 continue
             if Quantity is not None and value.get('@class') == 'Quantity':
                 quantity = Quantity.from_dict(value)
                 yield key, quantity
                 continue
             self.level += 1
             for inner_key, inner_value in self.iterate(nested_dict=value):
                 yield inner_key, inner_value
             self.level -= 1
         else:
             yield (self.level, key), value
Пример #13
0
    def get_materials_for_mpids(self, mpids, filter_null_properties=True):
        """
        Retrieve a list of Materials from the materials
        Project for a given list of Materials Project IDs.

        Args:
            mpids: a list of Materials Project IDs

        Returns:

        """

        materials_properties = self.get_properties_for_mpids(
            mpids, filter_null_properties=filter_null_properties)
        materials = []

        for material_properties in materials_properties:
            material = Material()
            for property_name, property_value in material_properties.items():
                provenance = ProvenanceElement(source='Materials Project')
                quantity = Quantity(self.mapping[property_name],
                                    property_value,
                                    provenance=provenance)
                material.add_quantity(quantity)
            materials.append(material)

        return materials
Пример #14
0
 def test_get_provenance_graph(self):
     g = Graph()
     qs = [
         Quantity("bulk_modulus", 100),
         Quantity("shear_modulus", 50),
         Quantity("density", 8.96)
     ]
     mat = Material(qs)
     evaluated = g.evaluate(mat)
     # TODO: this should be tested more thoroughly
     out = list(evaluated['vickers_hardness'])[0]
     with tempfile.ScratchDir('.'):
         out.draw_provenance_graph("out.png")
     pgraph = out.get_provenance_graph()
     end = list(evaluated['vickers_hardness'])[0]
     shortest_lengths = nx.shortest_path_length(pgraph, qs[0])
     self.assertEqual(shortest_lengths[end], 4)
Пример #15
0
    def evaluate(input_rows, data, aggregate):


        quantities = [Quantity(symbol_type=ROW_IDX_TO_SYMBOL_NAME[idx],
                               value=ureg.parse_expression(row['Editable Value']))
                      for idx, row in enumerate(input_rows) if row['Editable Value']]

        if data and len(data) > 0:
            quantities += json.loads(data, cls=MontyDecoder).values()

        if not quantities:
            raise PreventUpdate

        material = Material()

        for quantity in quantities:
            material.add_quantity(quantity)

        graph = Graph()
        output_material = graph.evaluate(material)

        if aggregate:
            output_quantities = output_material.get_aggregated_quantities().values()
        else:
            output_quantities = output_material.get_quantities()

        output_rows = [{
            'Property': quantity.symbol.display_names[0],
            'Value': quantity.pretty_string(3)
        } for quantity in output_quantities]

        output_table = dt.DataTable(id='output-table',
                                    rows=output_rows,
                                    editable=False)

        # TODO: clean up

        input_quantity_names = [q.symbol.name for q in quantities]
        derived_quantity_names = set(
            [q.symbol.name for q in output_quantities]) - \
                                 set(input_quantity_names)
        material_graph_data = graph_conversion(
            graph.get_networkx_graph(), nodes_to_highlight_green=input_quantity_names,
            nodes_to_highlight_yellow=list(derived_quantity_names))
        options = AESTHETICS['global_options']
        options['edges']['color'] = '#000000'
        output_graph = html.Div(GraphComponent(
            id='material-graph',
            graph=material_graph_data,
            options=options
        ), style={'width': '100%', 'height': '400px'})

        return [
            output_graph,
            html.Br(),
            output_table
        ]
Пример #16
0
    def test_numpy_scalar_conversion(self):
        # From custom symbol
        q_int = Quantity(self.custom_symbol, np.int64(5))
        q_float = Quantity(self.custom_symbol, np.float64(5.0))
        q_complex = Quantity(self.custom_symbol, np.complex64(5.0 + 1.j))

        self.assertTrue(isinstance(q_int.magnitude, int))
        self.assertTrue(isinstance(q_float.magnitude, float))
        self.assertTrue(isinstance(q_complex.magnitude, complex))

        q_int_uncertainty = Quantity(self.custom_symbol,
                                     5,
                                     uncertainty=np.int64(1))
        q_float_uncertainty = Quantity(self.custom_symbol,
                                       5.0,
                                       uncertainty=np.float64(1.0))
        q_complex_uncertainty = Quantity(self.custom_symbol,
                                         5.0 + 1j,
                                         uncertainty=np.complex64(1.0 + 0.1j))

        self.assertTrue(
            isinstance(q_int_uncertainty.uncertainty.magnitude, int))
        self.assertTrue(
            isinstance(q_float_uncertainty.uncertainty.magnitude, float))
        self.assertTrue(
            isinstance(q_complex_uncertainty.uncertainty.magnitude, complex))
Пример #17
0
    def add_default_quantities(self):
        """
        Adds any default symbols which are not present in the graph

        Returns:
            None
        """
        new_syms = set(DEFAULT_SYMBOL_VALUES.keys())
        new_syms -= set(self._symbol_to_quantity.keys())
        for sym in new_syms:
            quantity = Quantity.from_default(sym)
            warnings.warn("Adding default {} quantity with value {}".format(
                sym, quantity))
            self.add_quantity(quantity)
Пример #18
0
    def get_aggregated_quantities(self):
        """
        Return mean values for all quantities for each symbol.

        Returns:
            (dict<Symbol, weighted_mean) mapping from a Symbol to
            an aggregated statistic.
        """
        # TODO: proper weighting system, and more flexibility in object handling
        aggregated = {}
        for symbol, quantities in self._symbol_to_quantity.items():
            if not symbol.category == 'object':
                aggregated[symbol] = Quantity.from_weighted_mean(
                    list(quantities))
        return aggregated
Пример #19
0
def aggregate_quantities(quantities, model_score_dict=None):
    """
    Simple method for aggregating a set of quantities

    Args:
        quantities:
        model_score_dict:

    Returns:

    """
    symbol = next(iter(quantities)).symbol
    if not all([q.symbol == symbol for q in quantities]):
        raise ValueError("Quantities passed to aggregate must be same symbol")
    weights = [get_weight(q, model_score_dict) for q in quantities]
    result_value = sum(
        [w * q.value for w, q in zip(weights, quantities)]) / sum(weights)
    return Quantity(symbol, result_value)
Пример #20
0
    def test_model_returns_nan(self):
        # This tests model failure with scalar nan.
        # Quantity class has other more thorough tests.

        A = Symbol('a', ['A'], ['A'], units='dimensionless', shape=1)
        B = Symbol('b', ['B'], ['B'], units='dimensionless', shape=1)
        get_config = {
            'name': 'equality',
            # 'connections': [{'inputs': ['b'], 'outputs': ['a']}],
            'equations': ['a = b'],
            # 'unit_map': {'a': "dimensionless", 'a': "dimensionless"}
            'symbol_property_map': {"a": A, "b": B}
        }
        model = EquationModel(**get_config)
        out = model.evaluate({'b': Quantity(B, float('nan'))},
                             allow_failure=True)
        self.assertFalse(out['successful'])
        self.assertEqual(out['message'], 'Evaluation returned invalid values (NaN)')
Пример #21
0
    def test_super_evaluate(self):
        """
        Tests the graph's composite material evaluation.
        """
        mpr = MPRester()
        m1 = mpr.get_material_for_mpid("mp-13")
        # Temporary hack for problem with zero band-gap materials
        m1.remove_symbol("band_gap_pbe")
        m1.add_quantity(Quantity("band_gap", 0.0))
        m2 = mpr.get_material_for_mpid("mp-24972")
        sm = CompositeMaterial([m1, m2])

        g = Graph()

        sm = g.super_evaluate(sm, allow_model_failure=False)

        self.assertTrue('pilling_bedworth_ratio' in sm._symbol_to_quantity.keys(),
                        "Super Evaluate failed to derive expected outputs.")
        self.assertTrue(len(sm._symbol_to_quantity['pilling_bedworth_ratio']) > 0,
                        "Super Evaluate failed to derive expected outputs.")
Пример #22
0
    def test_provenance(self):
        model4 = EquationModel(name="model4", equations=["D=B*C*11"], constraints=["G==0"])
        symbols = GraphTest.generate_canonical_symbols()
        models = GraphTest.generate_canonical_models()
        models['model4'] = model4
        del models['model6']
        material = GraphTest.generate_canonical_material(symbols)
        g = Graph(symbol_types=symbols, models=models, composite_models=dict())
        material_derived = g.evaluate(material)

        expected_quantities = [
            Quantity(symbols['A'], 19),
            Quantity(symbols['A'], 23),
            Quantity(symbols['B'], 38),
            Quantity(symbols['B'], 46),
            Quantity(symbols['C'], 57),
            Quantity(symbols['C'], 69),
            Quantity(symbols['G'], 95),
            Quantity(symbols['G'], 115),
            Quantity(symbols['F'], 266),
            Quantity(symbols['F'], 322),
            Quantity(symbols['D'], 70395),
            Quantity(symbols['D'], 85215),
            Quantity(symbols['D'], 103155)
        ]

        for q in material_derived._symbol_to_quantity[symbols['A']]:
            self.assertTrue(q._provenance is None)
        for q in material_derived._symbol_to_quantity[symbols['B']]:
            if q.value == 38:
                self.assertTrue(q._provenance.model is models['model1'].name,
                                "provenance improperly calculated")
                self.assertTrue(expected_quantities[0] in q._provenance.inputs,
                                "provenance improperly calculated")
            else:
                self.assertTrue(q._provenance.model is models['model1'].name,
                                "provenance improperly calculated")
                self.assertTrue(expected_quantities[1] in q._provenance.inputs,
                                "provenance improperly calculated")
        for q in material_derived._symbol_to_quantity[symbols['C']]:
            if q.value == 57:
                self.assertTrue(q._provenance.model is models['model1'].name,
                                "provenance improperly calculated")
                self.assertTrue(expected_quantities[0] in q._provenance.inputs,
                                "provenance improperly calculated")
            else:
                self.assertTrue(q._provenance.model is models['model1'].name,
                                "provenance improperly calculated")
                self.assertTrue(expected_quantities[1] in q._provenance.inputs,
                                "provenance improperly calculated")
        for q in material_derived._symbol_to_quantity[symbols['G']]:
            if q.value == 95:
                self.assertTrue(q._provenance.model is models['model2'].name,
                                "provenance improperly calculated")
                self.assertTrue(expected_quantities[0] in q._provenance.inputs,
                                "provenance improperly calculated")
            else:
                self.assertTrue(q._provenance.model is models['model2'].name,
                                "provenance improperly calculated")
                self.assertTrue(expected_quantities[1] in q._provenance.inputs,
                                "provenance improperly calculated")
        for q in material_derived._symbol_to_quantity[symbols['D']]:
            if q.value == 70395:
                self.assertTrue(q._provenance.model is models['model5'].name,
                                "provenance improperly calculated")
                self.assertTrue(expected_quantities[4] in q._provenance.inputs,
                                "provenance improperly calculated")
                self.assertTrue(expected_quantities[6] in q._provenance.inputs,
                                "provenance improperly calculated")
Пример #23
0
    def test_evaluate_single_material_degenerate_property(self):
        """
        Graph has one material on it: mat1
            mat1 has trivial degenerate properties relative permittivity and relative permeability
                2 experimental relative permittivity measurements
                2 experimental relative permeability measurements
        Determines if TestGraph1 is correctly evaluated using the evaluate method.
        We expect 4 refractive_index properties to be calculated as the following:
            sqrt(3), sqrt(5), sqrt(6), sqrt(10)
        """
        # Setup
        propnet = Graph()
        mat1 = Material()
        mat1.add_quantity(Quantity(DEFAULT_SYMBOLS['relative_permeability'], 1))
        mat1.add_quantity(Quantity(DEFAULT_SYMBOLS['relative_permeability'], 2))
        mat1.add_quantity(Quantity(DEFAULT_SYMBOLS['relative_permittivity'], 3))
        mat1.add_quantity(Quantity(DEFAULT_SYMBOLS['relative_permittivity'], 5))

        mat1_derived = propnet.evaluate(mat1)

        # Expected outputs
        s_outputs = []
        s_outputs.append(Quantity('relative_permeability', 1))
        s_outputs.append(Quantity('relative_permeability', 2))
        s_outputs.append(Quantity('relative_permittivity', 3))
        s_outputs.append(Quantity('relative_permittivity', 5))
        s_outputs.append(Quantity('refractive_index', 3 ** 0.5))
        s_outputs.append(Quantity('refractive_index', 5 ** 0.5))
        s_outputs.append(Quantity('refractive_index', 6 ** 0.5))
        s_outputs.append(Quantity('refractive_index', 10 ** 0.5))

        st_outputs = []
        st_outputs.append(DEFAULT_SYMBOLS['relative_permeability'])
        st_outputs.append(DEFAULT_SYMBOLS['relative_permittivity'])
        st_outputs.append(DEFAULT_SYMBOLS['refractive_index'])

        # Test
        for q_expected in s_outputs:
            q = None
            for q_derived in mat1_derived._symbol_to_quantity[q_expected.symbol]:
                if q_derived == q_expected:
                    q = q_derived
            self.assertTrue(q is not None,
                            "Quantity missing from evaluate.")
Пример #24
0
    def test_evaluate_constraints_cyclic(self):
        """
        Tests the evaluation algorithm on a cyclic graph involving constraints.
        The canonical graph and the canonical material are used for this test.
        """
        model4 = EquationModel(name="model4", equations=["D=B*C*11"], constraints=["G==0"])

        symbols = GraphTest.generate_canonical_symbols()
        models = GraphTest.generate_canonical_models()
        models['model4'] = model4
        material = GraphTest.generate_canonical_material(symbols)
        g = Graph(symbol_types=symbols, models=models, composite_models=dict())
        material_derived = g.evaluate(material)

        expected_quantities = [
            Quantity(symbols['A'], 19),
            Quantity(symbols['A'], 23),
            Quantity(symbols['B'], 38),
            Quantity(symbols['B'], 46),
            Quantity(symbols['C'], 57),
            Quantity(symbols['C'], 69),
            Quantity(symbols['G'], 95),
            Quantity(symbols['G'], 115),
            Quantity(symbols['F'], 266),
            Quantity(symbols['F'], 322),
            Quantity(symbols['D'], 70395),
            Quantity(symbols['D'], 85215),
            Quantity(symbols['D'], 103155),
        ]

        self.assertTrue(material == GraphTest.generate_canonical_material(symbols),
                        "evaluate() mutated the original material argument.")

        derived_quantities = material_derived.get_quantities()
        self.assertTrue(len(expected_quantities) == len(derived_quantities),
                        "Evaluate did not correctly derive outputs.")
        for q in expected_quantities:
            self.assertTrue(q in material_derived._symbol_to_quantity[q.symbol],
                            "Evaluate failed to derive all outputs.")
            self.assertTrue(q in derived_quantities)
Пример #25
0
 def test_from_default(self):
     default = Quantity.from_default('temperature')
     self.assertEqual(default, Quantity('temperature', 300))
     default = Quantity.from_default('relative_permeability')
     self.assertEqual(default, Quantity("relative_permeability", 1))
Пример #26
0
    def test_evaluate_cyclic(self):
        """
        Tests the evaluation algorithm on a cyclic graph.
        The canonical graph and the canonical material are used for this test.
        """
        symbols = GraphTest.generate_canonical_symbols()
        models = GraphTest.generate_canonical_models()
        material = GraphTest.generate_canonical_material(symbols)
        g = Graph(symbol_types=symbols, models=models, composite_models=dict())
        material_derived = g.evaluate(material)

        expected_quantities = [
            # Starting
            Quantity(symbols['A'], 19),
            Quantity(symbols['A'], 23),

            # Derives -1 (M1)
            Quantity(symbols['B'], 38),
            Quantity(symbols['B'], 46),
            Quantity(symbols['C'], 57),
            Quantity(symbols['C'], 69),
            # Derives -2 (M3, M1)
            Quantity(symbols['F'], 266),
            Quantity(symbols['F'], 322),
            # Derives -2 (M4, M1)
            Quantity(symbols['D'], 23826),
            Quantity(symbols['D'], 28842),
            Quantity(symbols['D'], 34914),

            # Derives -1 (M2)
            Quantity(symbols['G'], 95),
            Quantity(symbols['G'], 115),
            # Derives -2 (M5, M1, M2)
            Quantity(symbols['D'], 70395),
            Quantity(symbols['D'], 85215),
            Quantity(symbols['D'], 103155),
        ]

        self.assertTrue(material == GraphTest.generate_canonical_material(symbols),
                        "evaluate() mutated the original material argument.")

        derived_quantities = material_derived.get_quantities()
        self.assertTrue(len(expected_quantities) == len(derived_quantities),
                        "Evaluate did not correctly derive outputs.")
        for q in expected_quantities:
            self.assertTrue(q in material_derived._symbol_to_quantity[q.symbol],
                            "Evaluate failed to derive all outputs.")
            self.assertTrue(q in derived_quantities)
Пример #27
0
    def super_evaluate(self, material, allow_model_failure=True):
        """
        Given a SuperMaterial object as input, creates a new SuperMaterial
        object to include all derivable properties.  Returns a reference to
        the new, augmented SuperMaterial object.

        Args:
            material (SuperMaterial): material for which properties
                will be expanded.

        Returns:
            (Material) reference to the newly derived material object.
        """

        if not isinstance(material, CompositeMaterial):
            raise Exception("material provided is not a SuperMaterial: " +
                            str(type(material)))

        # Evaluate material's sub-materials
        evaluated_materials = list()
        for m in material.materials:
            logger.debug("Evaluating sub-material: " + str(id(m)))
            if isinstance(m, CompositeMaterial):
                evaluated_materials.append(self.super_evaluate(m))
            else:
                evaluated_materials.append(self.evaluate(m))

        # Run all SuperModels in the graph on this SuperMaterial if
        # a material mapping can be established.  Store any derived quantities.
        all_quantities = defaultdict(set)
        for (k, v) in material._symbol_to_quantity:
            all_quantities[k].add(v)

        to_return = CompositeMaterial(evaluated_materials)
        to_return._symbol_to_quantity = all_quantities

        logger.debug("Evaluating SuperMaterial")

        for model in self._composite_models.values():

            logger.debug("\tEvaluating Model: " + model.name)

            # Establish material mappings for the given input set.

            mat_mappings = model.gen_material_mappings(to_return.materials)

            # Avoid ambiguous or impossible mappings, at least for now.
            if len(mat_mappings) != 1:
                continue

            mat_mapping = mat_mappings[0]

            # Go through input sets

            for property_input_sets in model.evaluation_list:

                logger.debug("\t\tGenerating input sets for: " +
                             str(property_input_sets))

                # Create a quantity pool from the appropriate materials.
                # Modify inputs for use in generate_input_sets

                temp_pool = defaultdict(set)
                combined_list = []
                mat_list = []
                symbol_list = []
                for item in property_input_sets:
                    combined_list.append(item)
                    mat_list.append(CompositeModel.get_material(item))
                    symbol_list.append(CompositeModel.get_symbol(item))
                for i in range(0, len(mat_list)):
                    if mat_list[
                            i] == None:  # Draw symbol from the CompositeMaterial
                        mat = to_return
                    else:
                        mat = mat_mapping[mat_list[i]]
                    for q in mat._symbol_to_quantity[symbol_list[i]]:
                        temp_pool[combined_list[i]].add(q)
                input_sets = self.generate_input_sets(combined_list, temp_pool)

                for input_set in input_sets:

                    logger.debug("\t\t\tEvaluating input set: " +
                                 str(input_set))

                    # Check if input_set can be evaluated -- input_set must pass the necessary model constraints
                    if not model.check_constraints(input_set):
                        logger.debug(
                            "\t\t\tInput set failed -- did not pass model constraints."
                        )
                        continue

                    # Try to evaluate input_set:
                    evaluate_set = dict(zip(combined_list, input_set))
                    output = model.evaluate(evaluate_set,
                                            allow_failure=allow_model_failure)
                    success = output.pop('successful')
                    if not success:
                        logger.debug(
                            "\t\t\tInput set failed -- did not produce a successful output."
                        )
                        continue

                    # input_set led to output from the Model -- add output to the SuperMaterial

                    logger.debug("\t\t\tInput set produced successful output.")
                    for symbol, quantity in output.items():
                        st = self._symbol_types.get(symbol)
                        if not st:
                            raise ValueError(
                                "Symbol type {} not found".format(symbol))
                        q = Quantity(st, quantity)
                        to_return._symbol_to_quantity[st].add(q)
                        logger.debug("\t\t\tNew output: " + str(q))

        # Evaluate the SuperMaterial's quantities and return the result.
        mappings = self.evaluate(to_return)._symbol_to_quantity
        to_return._symbol_to_quantity = mappings
        return to_return
Пример #28
0
 def test_to(self):
     quantity = Quantity('band_gap', 3.0, 'eV')
     new = quantity.to('joules')
     self.assertEqual(new.magnitude, 4.80652959e-19)
     self.assertEqual(new.units, 'joule')
Пример #29
0
 def test_pretty_string(self):
     quantity = Quantity('bulk_modulus', 100)
     self.assertEqual(quantity.pretty_string(3), "100 GPa")
Пример #30
0
 def test_derive_quantities(self):
     # Simple one quantity test
     quantity = Quantity("band_gap", 3.2)
     graph = Graph()
     new, qpool = graph.derive_quantities([quantity])
     new_mat = graph.evaluate(Material([quantity]))