heatrapy

Heatrapy stands for HEAt TRAnsfer in PYthon. It simulates dynamic 1D and 2D heat transfer processes in solids using the finite difference method. Heatrapy includes both the modeling of caloric effects and the incorporation of phase transitions.

author: Daniel Silva (djsilva@gmx.com)
current version: v2.0.1

Installation

To install heatrapy use the pip package manager:

$ pip install heatrapy

To import the heatrapy module type in the python shell:

>>> import heatrapy as htp

Thermal object

Thermal objects are the building block of the heatrapy module. Each thermal object is defined by a range of discrete space, where each point incorporates thermal properties, power sources and temperature. Boundary conditions are also defined and can be changed at any time. Thermal objects can use several methods that change the sate of each point, materials properties, and power sources. The state of each point defines if a field is applied (if True) or not (if False). This is of paramount importance for caloric materials. Moreover, phase change transitions can be incorporated according to latent heat data. There are two different types of thermal object classes: SingleObject and SystemObjects. While the first only computes heat transfer processes of single thermal objects, the second can compute heat transfer processes of several thermal objects that can contact each other.

Database of materials

A builtin database of materials is provided in the database folder. This database is very limited. The use of customized data can be done by defining the material data absolute path variable file_name. The builtin database includes several standard materials and can be consulted here. Some folder names end with _mag. This means that the state of each point defines if a magnetic field is applied.

Visualization

Although the temperature data can be saved for each point and time in a csv file, the package also allows live visualization when using the SingleObject classes. By default, when initializing the related objects, the plotting of the temperature begins. The different live plot types are defined in the draw parameter. So far, one can plot the temperature, materials, heat power sources and state for SingleObject2D. Only the temperature can be plotted when using SingleObject1D.

Example

As an example, the code below computes 100 s of a Cu 2D solid with a water circle and a aluminum square.

>>> import heatrapy as htp
>>> example = htp.SingleObject2D(
...     293,
...     material='Cu',
...     boundaries=(300, 0, 0, 0),
...     size=(20, 20)
... )
>>> example.change_material(
...     material='Al',
...     shape='square',
...     initial_point=(5, 2),
...     length=(4, 4)
... )
>>> example.change_material(
...     material='water',
...     shape='circle',
...     initial_point=(5, 13),
...     length=4
... )
>>> example.compute(100, 10)

The output at the end of the computation is the following:

Changelog

The changelog can be consulted here.

License

Heatrapy is licensed under the terms of the MIT License (MIT).

Contributing

Any type of contributions are welcome. A road map for future releases can be consulted in the wiki pages. Besides contributing by coding, feel free to report bugs and suggest new features. When contributing, please first discuss the change you wish to make via issue or email (djsilva@gmx.com), and then test the new code according to the contributing file.

Citing Heatrapy

Please acknowledge heatrapy if it contributes to a project that leads to a publication by citing this paper.

View Source
"""
Heatrapy stands for HEAt TRAnsfer in PYthon. It simulates dynamic 1D and 2D heat transfer processes in solids using the finite difference method. Heatrapy includes both the modeling of caloric effects and the incorporation of phase transitions.

author: Daniel Silva (djsilva@gmx.com) <br> current version: v2.0.1

Installation
------------
To install heatrapy use the pip package manager:
```bash
$ pip install heatrapy
```
To import the heatrapy module type in the python shell:
```python
>>> import heatrapy as htp
```

Thermal object
--------------
Thermal objects are the building block of the heatrapy module. Each thermal object is defined by a range of discrete space, where each point incorporates thermal properties, power sources and temperature. Boundary conditions are also defined and can be changed at any time. Thermal objects can use several methods that change the sate of each point, materials properties, and power sources. The state of each point defines if a field is applied (if True) or not (if False). This is of paramount importance for caloric materials. Moreover, phase change transitions can be incorporated according to latent heat data. There are two different types of thermal object classes: SingleObject and SystemObjects. While the first only computes heat transfer processes of single thermal objects, the second can compute heat transfer processes of several thermal objects that can contact each other.

Database of materials
---------------------
A builtin database of materials is provided in the database folder. This database is very limited. The use of customized data can be done by defining the material data absolute path variable `file_name`. The builtin database includes several standard materials and can be consulted <a href='https://github.com/djsilva99/heatrapy/tree/master/heatrapy/database'>here</a>. Some folder names end with `_mag`. This means that the state of each point defines if a magnetic field is applied.

Visualization
-------------
Although the temperature data can be saved for each point and time in a csv file, the package also allows live visualization when using the SingleObject classes. By default, when initializing the related objects, the plotting of the temperature begins. The different live plot types are defined in the `draw` parameter. So far, one can plot the temperature, materials, heat power sources and state for SingleObject2D. Only the temperature can be plotted when using SingleObject1D.

Example
-------
As an example, the code below computes 100 s of a Cu 2D solid with a water circle and a aluminum square.
```python
>>> import heatrapy as htp
>>> example = htp.SingleObject2D(
...     293,
...     material='Cu',
...     boundaries=(300, 0, 0, 0),
...     size=(20, 20)
... )
>>> example.change_material(
...     material='Al',
...     shape='square',
...     initial_point=(5, 2),
...     length=(4, 4)
... )
>>> example.change_material(
...     material='water',
...     shape='circle',
...     initial_point=(5, 13),
...     length=4
... )
>>> example.compute(100, 10)
```
The output at the end of the computation will be the following:
<img src="https://github.com/danieljosesilva/heatrapy/blob/master/img/example.png">

Changelog
---------
The changelog can be consulted <a href='https://github.com/djsilva99/heatrapy/tree/master/CHANGELOG.md'>here</a>.

License
-------
Heatrapy is licensed under the terms of the <a href='https://github.com/djsilva99/heatrapy/tree/master/LICENSE'>MIT License (MIT)</a>.

Contributing
------------
Any type of contributions are welcome. A road map for future releases can be consulted in the <a href='https://github.com/djsilva99/heatrapy/wiki'>wiki pages</a>. Besides contributing by coding, feel free to report bugs and suggest new features. When contributing, please first discuss the change you wish to make via issue or email (djsilva@gmx.com), and then test the new code according to the <a href='https://github.com/djsilva99/heatrapy/tree/master/CONTRIBUTING.md'> contributing file</a>.

Citing Heatrapy
-----------------
Please acknowledge heatrapy if it contributes to a project that leads to a publication by citing <a href='https://github.com/djsilva99/heatrapy/wiki'>this paper</a>.

"""

from .dimension_1.objects import SystemObjects as SystemObjects1D
from .dimension_1.objects import SingleObject as SingleObject1D
from .dimension_2.objects import SystemObjects as SystemObjects2D
from .dimension_2.objects import SingleObject as SingleObject2D

__all__ = ['SystemObjects1D', 'SingleObject1D', 'SystemObjects2D',
           'SingleObject2D']
#   class SystemObjects1D:
View Source
class SystemObjects:
    """System_objects class.

    This class creates a system of unidimensional thermal objects, establishes
    contact between them and computes the respective thermal processes.

    """

    def __init__(self, number_objects=2, materials=('Cu', 'Cu'),
                 objects_length=(10, 10), amb_temperature=293, dx=0.01, dt=0.1,
                 file_name=None, initial_state=False,
                 boundaries=((2, 0), (3, 0)), materials_path=False):
        """System object initialization.

        `number_objects` is the integer number of thermal objects. `materials`
        is the list of strings of all the used materials present in
        `material_path`. `amb_temperature` is the ambient temperature of the
        whole system. `object_length` is the list of thermal object lengths
        (spacial steps). `dx` and `dt` are the space and time steps,
        respectively. `file_name` is the file name where the temperature is
        saved. `boundaries` is a list of tuples of length two that define each
        boundary condition for temperature. If 0 the boundary condition is
        insulation. `materials_path` is absolute path of the materials
        database. If false, then the materials database is the standard
        heatrapy database.

        """
        # check the validity of inputs
        materials = tuple(materials)
        objects_length = tuple(objects_length)
        boundaries = tuple(boundaries)
        cond01 = isinstance(amb_temperature, float)
        cond01 = cond01 or isinstance(amb_temperature, int)
        cond02 = isinstance(materials, tuple)
        cond03 = isinstance(number_objects, int)
        cond04 = isinstance(objects_length, tuple)
        cond05 = isinstance(dx, int) or isinstance(dx, float)
        cond06 = isinstance(dt, int) or isinstance(dt, float)
        cond07 = isinstance(file_name, str)
        cond07 = cond07 or (file_name is None)
        cond08 = isinstance(boundaries, tuple)
        cond09 = isinstance(initial_state, bool)
        condition = cond01 and cond02 and cond03 and cond04 and cond05
        condition = condition and cond06 and cond07 and cond08 and cond09
        if not condition:
            raise ValueError

        # initial definitions
        self.objects = []
        for i in range(number_objects):
            if file_name:
                file_name = file_name + '_' + str(i) + '.txt'

            self.objects.append(Object(amb_temperature,
                                materials=(materials[i],),
                                borders=(1, objects_length[i]+1),
                                materials_order=(0,), dx=dx, dt=dt,
                                file_name=file_name, boundaries=(0, 0),
                                Q=[], Q0=[], initial_state=initial_state,
                                materials_path=materials_path))

        self.contacts = set()
        self.boundaries = boundaries
        self.dt = dt
        self.q1 = 0.
        self.q2 = 0.

        for i in boundaries:
            if i[1] != 0:
                for j in range(len(self.objects[i[0]].temperature)):
                    self.objects[i[0]].temperature[j] = [i[1], i[1]]

    def contact_filter(self, object):
        """Filter self.contacts by thermal object id.

        object: thermal object id

        """
        # check the validity of inputs
        condition = object in range(len(self.objects))
        if not condition:
            raise ValueError

        filtered = [x for x in
                    self.contacts if (x[0][0] == object or x[1][0] == object)]
        return set(filtered)

    def contact_add(self, contact):
        """Add contact to self.contacts.

        The `contact` parameter is a tuple of length 3 (one element for thermal
        object A, one for thermal object B, and one for the heat transfer
        coefficient). Each thermal object element is a tuple of length 2 where
        the first element is the index of the thermal object and the second is
        the spatial point index.

        """
        # check the validity of inputs
        if isinstance(contact, list) or isinstance(contact, tuple):
            if len(contact) == 3:
                condition = True
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.contacts.add(contact)

    def contact_remove(self, object_one, object_two):
        """Contact removal.

        Removes all contacts between `object_one` id and `object_two` id.

        """
        # check the validity of inputs
        condition = isinstance(object_one, int)
        condition = condition and isinstance(object_two, int)
        if not condition:
            raise ValueError

        contact_list = list(self.contacts)
        for i in range(len(contact_list)):
            cond_1 = contact_list[i][0][0] == object_one
            cond_1 = cond_1 and contact_list[i][1][0] == object_two
            cond_2 = contact_list[i][0][0] == object_two
            cond_2 = cond_2 and contact_list[i][1][0] == object_one
            if cond_1 or cond_2:
                self.contacts.remove(contact_list[i])

    def change_boundaries(self, object_id, boundaries):
        """Change boundaries.

        Changes the `boundaries` of `object_id`.

        """
        # check the validity of inputs
        condition = isinstance(object_id, int)
        condition = condition and isinstance(boundaries, tuple)
        if condition:
            if len(boundaries) == 2:
                condition = True
            else:
                condition = False
        if not condition:
            raise ValueError

        self.objects[object_id].boundaries = boundaries

    def compute(self, time_interval, write_interval, solver='implicit_k(x)',
                verbose=True):
        """Compute the thermal process.

        Computes the system for `time_interval`, and writes into the
        `file_name` file every `write_interval` time steps. Four different
        solvers can be used: `'explicit_general'`, `'explicit_k(x)'`,
        `'implicit_general'`, and `'implicit_k(x)'`. If `verbose = True`, then
        the progress of the computation is shown.

        """
        # check the validity of inputs
        cond1 = isinstance(time_interval, float)
        cond1 = cond1 or isinstance(time_interval, int)
        cond2 = isinstance(write_interval, int)
        cond3 = isinstance(solver, str)
        cond4 = isinstance(verbose, bool)
        condition = cond1 and cond2 and cond3 and cond4
        if not condition:
            raise ValueError

        # number of time steps for the given timeInterval
        nt = int(time_interval / self.dt)

        # number of time steps counting from the last writing process
        nw = 0

        # computes
        for j in range(nt):
            for obj in self.objects:
                obj.Q0 = copy.copy(obj.Q0_ref)

            for contact in self.contacts:
                ind1 = int(contact[1][1])
                ind2 = int(contact[0][1])
                td1 = self.objects[contact[1][0]].temperature[ind1][0]
                td2 = self.objects[contact[0][0]].temperature[ind2][0]
                heat_contact_1 = contact[2] * (td1 - td2)
                heat_contact_2 = contact[2] * (td2 - td1)
                self.objects[contact[0][0]].Q0[ind2] = heat_contact_1
                self.objects[contact[1][0]].Q0[ind1] = heat_contact_2

            object_number = -1
            for obj in self.objects:
                object_number = object_number + 1
                obj.time_passed = obj.time_passed + obj.dt

                cond1 = object_number not in [l[0] for l in self.boundaries]
                if cond1 or (object_number, 0) in self.boundaries:

                    # defines the material properties
                    for i in range(1, obj.num_points - 1):
                        if obj.state[i] is True:
                            ind = obj.materials_index[i]
                            obj.rho[i] = obj.materials[ind].rhoa(
                                obj.temperature[i][0])
                            obj.Cp[i] = obj.materials[ind].cpa(
                                obj.temperature[i][0])
                            obj.k[i] = obj.materials[ind].ka(
                                obj.temperature[i][0])
                        if obj.state[i] is False:
                            ind = obj.materials_index[i]
                            obj.rho[i] = obj.materials[ind].rho0(
                                obj.temperature[i][0])
                            obj.Cp[i] = obj.materials[ind].cp0(
                                obj.temperature[i][0])
                            obj.k[i] = obj.materials[ind].k0(
                                obj.temperature[i][0])

                    # SOLVERS

                    # implicit k constant
                    if solver == 'implicit_general':
                        value = solvers.implicit_general(obj)
                        obj.temperature, obj.lheat = value

                    # implicit k dependent on x
                    if solver == 'implicit_k(x)':
                        obj.temperature, obj.lheat = solvers.implicit_k(obj)

                    # explicit k constant
                    if solver == 'explicit_general':
                        value = solvers.explicit_general(obj)
                        obj.temperature, obj.lheat = value

                    # explicit k dependent on x
                    if solver == 'explicit_k(x)':
                        obj.temperature, obj.lheat = solvers.explicit_k(obj)

                    # writes the temperature to file_name file ...
                    # if the number of time steps is verified
                    if obj.file_name:
                        if nw + 1 == write_interval or j == 0 or j == nt - 1:
                            line = '%f' % obj.time_passed
                            for i in obj.temperature:
                                new_line = ',%f' % i[1]
                                line = line + new_line
                            f = open(obj.file_name, 'a')
                            f.write(line+'\n')
                            f.close()

                else:

                    heat = [p*self.dt*obj.dx for p in obj.Q0 if p is not None]
                    heat = sum(heat)/(len(heat)*obj.dx)

                    if object_number == self.boundaries[0][0]:
                        self.q1 = self.q1 + heat
                        q = self.q1
                    else:
                        self.q2 = self.q2 + heat
                        q = self.q2

                    # writes the temperature to file_name file ...
                    # if the number of time steps is verified
                    if obj.file_name:
                        if nw + 1 == write_interval or j == 0 or j == nt - 1:
                            line = '%f' % obj.time_passed
                            for i in obj.temperature:
                                new_line = ',%f' % i[1]
                                line = line + new_line
                            new_line = ',%f' % q
                            line = line + new_line
                            f = open(obj.file_name, 'a')
                            f.write(line+'\n')
                            f.close()

            if nw == write_interval:
                nw = 0
                if verbose:
                    print('progress:', int(100*j/nt), '%', end='\r')
            else:
                nw = nw + 1

        if verbose:
            print('Finished simulation')

System_objects class.

This class creates a system of unidimensional thermal objects, establishes contact between them and computes the respective thermal processes.

#   SystemObjects1D( self, number_objects=2, materials=('Cu', 'Cu'), objects_length=(10, 10), amb_temperature=293, dx=0.01, dt=0.1, file_name=None, initial_state=False, boundaries=((2, 0), (3, 0)), materials_path=False )
View Source
    def __init__(self, number_objects=2, materials=('Cu', 'Cu'),
                 objects_length=(10, 10), amb_temperature=293, dx=0.01, dt=0.1,
                 file_name=None, initial_state=False,
                 boundaries=((2, 0), (3, 0)), materials_path=False):
        """System object initialization.

        `number_objects` is the integer number of thermal objects. `materials`
        is the list of strings of all the used materials present in
        `material_path`. `amb_temperature` is the ambient temperature of the
        whole system. `object_length` is the list of thermal object lengths
        (spacial steps). `dx` and `dt` are the space and time steps,
        respectively. `file_name` is the file name where the temperature is
        saved. `boundaries` is a list of tuples of length two that define each
        boundary condition for temperature. If 0 the boundary condition is
        insulation. `materials_path` is absolute path of the materials
        database. If false, then the materials database is the standard
        heatrapy database.

        """
        # check the validity of inputs
        materials = tuple(materials)
        objects_length = tuple(objects_length)
        boundaries = tuple(boundaries)
        cond01 = isinstance(amb_temperature, float)
        cond01 = cond01 or isinstance(amb_temperature, int)
        cond02 = isinstance(materials, tuple)
        cond03 = isinstance(number_objects, int)
        cond04 = isinstance(objects_length, tuple)
        cond05 = isinstance(dx, int) or isinstance(dx, float)
        cond06 = isinstance(dt, int) or isinstance(dt, float)
        cond07 = isinstance(file_name, str)
        cond07 = cond07 or (file_name is None)
        cond08 = isinstance(boundaries, tuple)
        cond09 = isinstance(initial_state, bool)
        condition = cond01 and cond02 and cond03 and cond04 and cond05
        condition = condition and cond06 and cond07 and cond08 and cond09
        if not condition:
            raise ValueError

        # initial definitions
        self.objects = []
        for i in range(number_objects):
            if file_name:
                file_name = file_name + '_' + str(i) + '.txt'

            self.objects.append(Object(amb_temperature,
                                materials=(materials[i],),
                                borders=(1, objects_length[i]+1),
                                materials_order=(0,), dx=dx, dt=dt,
                                file_name=file_name, boundaries=(0, 0),
                                Q=[], Q0=[], initial_state=initial_state,
                                materials_path=materials_path))

        self.contacts = set()
        self.boundaries = boundaries
        self.dt = dt
        self.q1 = 0.
        self.q2 = 0.

        for i in boundaries:
            if i[1] != 0:
                for j in range(len(self.objects[i[0]].temperature)):
                    self.objects[i[0]].temperature[j] = [i[1], i[1]]

System object initialization.

number_objects is the integer number of thermal objects. materials is the list of strings of all the used materials present in material_path. amb_temperature is the ambient temperature of the whole system. object_length is the list of thermal object lengths (spacial steps). dx and dt are the space and time steps, respectively. file_name is the file name where the temperature is saved. boundaries is a list of tuples of length two that define each boundary condition for temperature. If 0 the boundary condition is insulation. materials_path is absolute path of the materials database. If false, then the materials database is the standard heatrapy database.

#   def contact_filter(self, object):
View Source
    def contact_filter(self, object):
        """Filter self.contacts by thermal object id.

        object: thermal object id

        """
        # check the validity of inputs
        condition = object in range(len(self.objects))
        if not condition:
            raise ValueError

        filtered = [x for x in
                    self.contacts if (x[0][0] == object or x[1][0] == object)]
        return set(filtered)

Filter self.contacts by thermal object id.

object: thermal object id

#   def contact_add(self, contact):
View Source
    def contact_add(self, contact):
        """Add contact to self.contacts.

        The `contact` parameter is a tuple of length 3 (one element for thermal
        object A, one for thermal object B, and one for the heat transfer
        coefficient). Each thermal object element is a tuple of length 2 where
        the first element is the index of the thermal object and the second is
        the spatial point index.

        """
        # check the validity of inputs
        if isinstance(contact, list) or isinstance(contact, tuple):
            if len(contact) == 3:
                condition = True
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.contacts.add(contact)

Add contact to self.contacts.

The contact parameter is a tuple of length 3 (one element for thermal object A, one for thermal object B, and one for the heat transfer coefficient). Each thermal object element is a tuple of length 2 where the first element is the index of the thermal object and the second is the spatial point index.

#   def contact_remove(self, object_one, object_two):
View Source
    def contact_remove(self, object_one, object_two):
        """Contact removal.

        Removes all contacts between `object_one` id and `object_two` id.

        """
        # check the validity of inputs
        condition = isinstance(object_one, int)
        condition = condition and isinstance(object_two, int)
        if not condition:
            raise ValueError

        contact_list = list(self.contacts)
        for i in range(len(contact_list)):
            cond_1 = contact_list[i][0][0] == object_one
            cond_1 = cond_1 and contact_list[i][1][0] == object_two
            cond_2 = contact_list[i][0][0] == object_two
            cond_2 = cond_2 and contact_list[i][1][0] == object_one
            if cond_1 or cond_2:
                self.contacts.remove(contact_list[i])

Contact removal.

Removes all contacts between object_one id and object_two id.

#   def change_boundaries(self, object_id, boundaries):
View Source
    def change_boundaries(self, object_id, boundaries):
        """Change boundaries.

        Changes the `boundaries` of `object_id`.

        """
        # check the validity of inputs
        condition = isinstance(object_id, int)
        condition = condition and isinstance(boundaries, tuple)
        if condition:
            if len(boundaries) == 2:
                condition = True
            else:
                condition = False
        if not condition:
            raise ValueError

        self.objects[object_id].boundaries = boundaries

Change boundaries.

Changes the boundaries of object_id.

#   def compute( self, time_interval, write_interval, solver='implicit_k(x)', verbose=True ):
View Source
    def compute(self, time_interval, write_interval, solver='implicit_k(x)',
                verbose=True):
        """Compute the thermal process.

        Computes the system for `time_interval`, and writes into the
        `file_name` file every `write_interval` time steps. Four different
        solvers can be used: `'explicit_general'`, `'explicit_k(x)'`,
        `'implicit_general'`, and `'implicit_k(x)'`. If `verbose = True`, then
        the progress of the computation is shown.

        """
        # check the validity of inputs
        cond1 = isinstance(time_interval, float)
        cond1 = cond1 or isinstance(time_interval, int)
        cond2 = isinstance(write_interval, int)
        cond3 = isinstance(solver, str)
        cond4 = isinstance(verbose, bool)
        condition = cond1 and cond2 and cond3 and cond4
        if not condition:
            raise ValueError

        # number of time steps for the given timeInterval
        nt = int(time_interval / self.dt)

        # number of time steps counting from the last writing process
        nw = 0

        # computes
        for j in range(nt):
            for obj in self.objects:
                obj.Q0 = copy.copy(obj.Q0_ref)

            for contact in self.contacts:
                ind1 = int(contact[1][1])
                ind2 = int(contact[0][1])
                td1 = self.objects[contact[1][0]].temperature[ind1][0]
                td2 = self.objects[contact[0][0]].temperature[ind2][0]
                heat_contact_1 = contact[2] * (td1 - td2)
                heat_contact_2 = contact[2] * (td2 - td1)
                self.objects[contact[0][0]].Q0[ind2] = heat_contact_1
                self.objects[contact[1][0]].Q0[ind1] = heat_contact_2

            object_number = -1
            for obj in self.objects:
                object_number = object_number + 1
                obj.time_passed = obj.time_passed + obj.dt

                cond1 = object_number not in [l[0] for l in self.boundaries]
                if cond1 or (object_number, 0) in self.boundaries:

                    # defines the material properties
                    for i in range(1, obj.num_points - 1):
                        if obj.state[i] is True:
                            ind = obj.materials_index[i]
                            obj.rho[i] = obj.materials[ind].rhoa(
                                obj.temperature[i][0])
                            obj.Cp[i] = obj.materials[ind].cpa(
                                obj.temperature[i][0])
                            obj.k[i] = obj.materials[ind].ka(
                                obj.temperature[i][0])
                        if obj.state[i] is False:
                            ind = obj.materials_index[i]
                            obj.rho[i] = obj.materials[ind].rho0(
                                obj.temperature[i][0])
                            obj.Cp[i] = obj.materials[ind].cp0(
                                obj.temperature[i][0])
                            obj.k[i] = obj.materials[ind].k0(
                                obj.temperature[i][0])

                    # SOLVERS

                    # implicit k constant
                    if solver == 'implicit_general':
                        value = solvers.implicit_general(obj)
                        obj.temperature, obj.lheat = value

                    # implicit k dependent on x
                    if solver == 'implicit_k(x)':
                        obj.temperature, obj.lheat = solvers.implicit_k(obj)

                    # explicit k constant
                    if solver == 'explicit_general':
                        value = solvers.explicit_general(obj)
                        obj.temperature, obj.lheat = value

                    # explicit k dependent on x
                    if solver == 'explicit_k(x)':
                        obj.temperature, obj.lheat = solvers.explicit_k(obj)

                    # writes the temperature to file_name file ...
                    # if the number of time steps is verified
                    if obj.file_name:
                        if nw + 1 == write_interval or j == 0 or j == nt - 1:
                            line = '%f' % obj.time_passed
                            for i in obj.temperature:
                                new_line = ',%f' % i[1]
                                line = line + new_line
                            f = open(obj.file_name, 'a')
                            f.write(line+'\n')
                            f.close()

                else:

                    heat = [p*self.dt*obj.dx for p in obj.Q0 if p is not None]
                    heat = sum(heat)/(len(heat)*obj.dx)

                    if object_number == self.boundaries[0][0]:
                        self.q1 = self.q1 + heat
                        q = self.q1
                    else:
                        self.q2 = self.q2 + heat
                        q = self.q2

                    # writes the temperature to file_name file ...
                    # if the number of time steps is verified
                    if obj.file_name:
                        if nw + 1 == write_interval or j == 0 or j == nt - 1:
                            line = '%f' % obj.time_passed
                            for i in obj.temperature:
                                new_line = ',%f' % i[1]
                                line = line + new_line
                            new_line = ',%f' % q
                            line = line + new_line
                            f = open(obj.file_name, 'a')
                            f.write(line+'\n')
                            f.close()

            if nw == write_interval:
                nw = 0
                if verbose:
                    print('progress:', int(100*j/nt), '%', end='\r')
            else:
                nw = nw + 1

        if verbose:
            print('Finished simulation')

Compute the thermal process.

Computes the system for time_interval, and writes into the file_name file every write_interval time steps. Four different solvers can be used: 'explicit_general', 'explicit_k(x)', 'implicit_general', and 'implicit_k(x)'. If verbose = True, then the progress of the computation is shown.

#   class SingleObject1D:
View Source
class SingleObject:
    """Single_object class.

    This class solves numerically the heat conduction equation for 1 dimension
    of a single material(s). The class has 6 methods.

    """

    def __init__(self, amb_temperature, materials=('Cu',), borders=(1, 11),
                 materials_order=(0,), dx=0.01, dt=0.1, file_name=None,
                 boundaries=(0, 0), initial_state=False,
                 materials_path=False, draw=['temperature'], draw_scale=None):
        """Thermal object initialization.

        `amb_temperature` is the ambient temperature of the whole system.
        `materials` is the list of strings of all the used materials present in
        `material_path`. `borders` is a list of the points where there is a
        change of material. `materials_order` is a list of the materials list
        indexes that defines the material properties given by borders. `dx` and
        `dt` are the space and time steps, respectively. `file_name` is the
        file name where the temperature is saved. `boundaries` is a list of two
        entries that define the boundary condition for temperature. If 0 the
        boundary condition is insulation. `initial_state` is the initial state
        of the materials. True if there are an applied field and False if them
        field is absent. `materials_path` is absolute path of the materials
        database. If false, then the materials database is the standard
        heatrapy database. `draw` is a list of strings representing the online
        plots. In this version only `'temperature'` can be potted. If the list
        is empty, then no drawing is performed. `draw_scale` is a list of two
        values, representing the minimum and maximum temperature to be drawn.
        If None, there are no limits.

        """
        # check the validity of inputs
        materials = tuple(materials)
        borders = tuple(borders)
        materials_order = tuple(materials_order)
        boundaries = tuple(boundaries)
        cond01 = isinstance(amb_temperature, float)
        cond01 = cond01 or isinstance(amb_temperature, int)
        cond02 = isinstance(materials, tuple)
        cond03 = isinstance(borders, tuple)
        cond04 = isinstance(materials_order, tuple)
        cond05 = isinstance(dx, int) or isinstance(dx, float)
        cond06 = isinstance(dt, int) or isinstance(dt, float)
        cond07 = isinstance(file_name, str)
        cond07 = cond07 or (file_name is None)
        cond08 = isinstance(boundaries, tuple)
        cond10 = isinstance(initial_state, bool)
        if isinstance(draw, list):
            cond15 = True
        elif draw is None:
            cond15 = True
        else:
            cond15 = False
        if isinstance(draw_scale, list) or isinstance(draw_scale, tuple):
            cond16 = (len(draw_scale) == 2)
        elif draw_scale is None:
            cond16 = True
        else:
            cond16 = False
        condition = cond01 and cond02 and cond03 and cond04 and cond05
        condition = condition and cond06 and cond07 and cond08
        condition = condition and cond10
        condition = condition and cond15 and cond16
        if not condition:
            raise ValueError

        self.object = Object(amb_temperature, materials=materials,
                             borders=borders, materials_order=materials_order,
                             dx=dx, dt=dt, file_name=file_name,
                             boundaries=boundaries,
                             initial_state=initial_state,
                             materials_path=materials_path)

        # initializes the plotting
        self.draw = draw
        self.draw_scale = draw_scale
        for drawing in self.draw:
            if drawing == 'temperature':
                self.figure = plt.figure()
                self.ax = self.figure.add_subplot(111)
                temp = []
                for i in range(len(self.object.temperature)):
                    temp.append(self.object.temperature[i][0])
                if not self.draw_scale:
                    vmax = max(temp)
                    vmin = min(temp)
                    if vmax == vmin:
                        vmin = vmin - 0.1
                        vmax = vmax + 0.1
                    temp = np.array(temp)
                    x_plot = [self.object.dx*j for j in range(len(temp))]
                    self.online, = self.ax.plot(x_plot, temp)
                    self.ax.set_ylim([vmin, vmax])
                else:
                    temp = np.array(temp)
                    x_plot = [self.object.dx*j for j in range(len(temp))]
                    self.online, = self.ax.plot(x_plot, temp)
                    self.ax.set_ylim(self.draw_scale)
                self.ax.set_title('Temperature (K)')
                self.ax.set_xlabel('x axis (m)')
                self.ax.set_ylabel('temperature (K)')
                plt.show(block=False)

    def show_figure(self, figure_type, draw_scale=None):
        """Plotting.

        Initializes a specific live plotting. `figure_type` is a string
        identifying the plotting. This version only allows the plotting of the
        'temperature'. `draw_scale` defines the range of temperatures. If None,
        this range is found automatically for every frame.

        """
        # check the validity of inputs
        if isinstance(draw_scale, list) or isinstance(draw_scale, tuple):
            condition = (len(draw_scale) == 2)
        elif draw_scale is None:
            condition = True
        else:
            condition = False
        condition = condition and isinstance(figure_type, str)
        if not condition:
            raise ValueError

        self.draw_scale = draw_scale
        if figure_type == 'temperature':
            if figure_type not in self.draw:
                self.draw.append(figure_type)
            self.figure = plt.figure()
            self.ax = self.figure.add_subplot(111)
            temp = []
            for i in range(len(self.object.temperature)):
                temp.append(self.object.temperature[i][0])
            if not self.draw_scale:
                vmax = max(temp)
                vmin = min(temp)
                if vmax == vmin:
                    vmin = vmin - 0.1
                    vmax = vmax + 0.1
                temp = np.array(temp)
                x_plot = [self.object.dx*j for j in range(len(temp))]
                self.online, = self.ax.plot(x_plot, temp)
                self.ax.set_ylim([vmin, vmax])
            else:
                temp = np.array(temp)
                x_plot = [self.object.dx*j for j in range(len(temp))]
                self.online, = self.ax.plot(x_plot, temp)
                self.ax.set_ylim(self.draw_scale)
            self.ax.set_title('Temperature (K)')
            self.ax.set_xlabel('x axis (m)')
            self.ax.set_ylabel('temperature (K)')
            plt.show(block=False)

    def activate(self, initial_point, final_point):
        """Activation.

        Activates the thermal object between `initial_point` to `final_point`.
        """
        # check the validity of inputs
        condition = isinstance(initial_point, int)
        condition = condition and isinstance(final_point, int)
        if not condition:
            raise ValueError

        self.object.activate(initial_point, final_point)

        if self.draw:
            for drawing in self.draw:
                if drawing == 'temperature':
                    try:
                        temp = []
                        for i in range(len(self.object.temperature)):
                            temp.append(self.object.temperature[i][0])
                        if not self.draw_scale:
                            vmax = max(temp)
                            vmin = min(temp)
                            if vmax == vmin:
                                vmin = vmin - 0.1
                                vmax = vmax + 0.1
                            temp = np.array(temp)
                            self.online.set_ydata(temp)
                            self.ax.set_ylim([vmin, vmax])
                        else:
                            temp = np.array(temp)
                            self.online.set_ydata(temp)
                        self.figure.canvas.draw()
                    except:
                        pass

    def deactivate(self, initial_point, final_point):
        """Deactivation.

        Deactivates the thermal object between `initial_point` to
        `final_point`.
        """
        # check the validity of inputs
        condition = isinstance(initial_point, int)
        condition = condition and isinstance(final_point, int)
        if not condition:
            raise ValueError

        self.object.deactivate(initial_point, final_point)

        if self.draw:
            for drawing in self.draw:
                if drawing == 'temperature':
                    try:
                        temp = []
                        for i in range(len(self.object.temperature)):
                            temp.append(self.object.temperature[i][0])
                        if not self.draw_scale:
                            vmax = max(temp)
                            vmin = min(temp)
                            if vmax == vmin:
                                vmin = vmin - 0.1
                                vmax = vmax + 0.1
                            temp = np.array(temp)
                            self.online.set_ydata(temp)
                            self.ax.set_ylim([vmin, vmax])
                        else:
                            temp = np.array(temp)
                            self.online.set_ydata(temp)
                        self.figure.canvas.draw()
                    except:
                        pass

    def change_power(self, power_type, power, initial_point, final_point):
        """Heat power source change.

        Changes the coeficients for the heat power sources by a value of power
        from `initial_point` to `final_point`. `power_type` is a string that
        represents the type of coefficient, i.e. 'Q' or 'Q0'.

        """
        # check the validity of inputs
        value = isinstance(initial_point, int)
        if value and isinstance(final_point, int):
            cond1 = True
        else:
            cond1 = False
        cond2 = isinstance(power, int) or isinstance(power, float)
        if isinstance(power_type, str):
            if power_type == 'Q' or power_type == 'Q0':
                cond3 = True
            else:
                cond3 = False
        else:
            cond3 = False
        if not (cond1 and cond2 and cond3):
            raise ValueError

        if power_type == 'Q':
            for j in range(initial_point, final_point):
                self.object.Q[j] = power
        if power_type == 'Q0':
            for j in range(initial_point, final_point):
                self.object.Q0[j] = power

    def change_boundaries(self, boundaries):
        """Boundary change.

        Changes the `boundaries` variable.

        """
        # check the validity of inputs
        if isinstance(boundaries, tuple):
            if len(boundaries) == 2:
                condition = True
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.object.boundaries = boundaries

    def compute(self, time_interval, write_interval, solver='explicit_k(x)',
                verbose=True):
        """Compute the thermal process.

        Computes the system for time_interval seconds, and writes into the
        `file_name` file every `write_interval` time steps. Four different
        solvers can be used: `'explicit_general'`, `'explicit_k(x)'`,
        `'implicit_general'`, and `'implicit_k(x)'`. If `verbose = True`, then
        the progress of the computation progress is shown.

        """
        # check the validity of inputs
        cond1 = isinstance(time_interval, float)
        cond1 = cond1 or isinstance(time_interval, int)
        cond2 = isinstance(write_interval, int)
        if isinstance(solver, str):
            all_solvers = ['implicit_general', 'implicit_k(x)',
                           'explicit_k(x)', 'explicit_general']
            if solver in all_solvers:
                cond3 = True
            else:
                cond3 = False
        else:
            cond3 = False
        cond4 = isinstance(verbose, bool)
        condition = cond1 and cond2 and cond3 and cond4
        if not condition:
            raise ValueError

        # number of time steps for the given timeInterval
        nt = int(time_interval / self.object.dt)

        # number of time steps counting from the last writing process
        nw = 0

        # computes
        for j in range(nt):

            # updates the time_passed
            self.object.time_passed = self.object.time_passed + self.object.dt

            # defines the material properties accoring to the state list
            for i in range(1, self.object.num_points - 1):
                if self.object.state[i] is True:
                    value = self.object.materials_index[i]
                    self.object.rho[i] = self.object.materials[value].rhoa(
                        self.object.temperature[i][0])
                    self.object.Cp[i] = self.object.materials[value].cpa(
                        self.object.temperature[i][0])
                    self.object.k[i] = self.object.materials[value].ka(
                        self.object.temperature[i][0])
                if self.object.state[i] is False:
                    value = self.object.materials_index[i]
                    self.object.rho[i] = self.object.materials[value].rho0(
                        self.object.temperature[i][0])
                    self.object.Cp[i] = self.object.materials[value].cp0(
                        self.object.temperature[i][0])
                    self.object.k[i] = self.object.materials[value].k0(
                        self.object.temperature[i][0])

            # SOLVERS
            # implicit k constant
            if solver == 'implicit_general':
                value = solvers.implicit_general(self.object)
                self.object.temperature, self.object.lheat = value
            # implicit k dependent on x
            if solver == 'implicit_k(x)':
                value = solvers.implicit_k(self.object)
                self.object.temperature, self.object.lheat = value
            # explicit k constant
            if solver == 'explicit_general':
                value = solvers.explicit_general(self.object)
                self.object.temperature, self.object.lheat = value
            # explicit k dependent on x
            if solver == 'explicit_k(x)':
                value = solvers.explicit_k(self.object)
                self.object.temperature, self.object.lheat = value

            nw = nw + 1

            if self.draw:
                for drawing in self.draw:
                    if drawing == 'temperature':
                        try:
                            value = nw + 1 == write_interval
                            if value or j == 0 or j == nt - 1:
                                temp = []
                                for i in range(len(self.object.temperature)):
                                    temp.append(self.object.temperature[i][0])
                                if not self.draw_scale:
                                    vmax = max(temp)
                                    vmin = min(temp)
                                    if vmax == vmin:
                                        vmin = vmin - 0.1
                                        vmax = vmax + 0.1
                                    temp = np.array(temp)
                                    self.online.set_ydata(temp)
                                    self.ax.set_ylim([vmin, vmax])
                                else:
                                    temp = np.array(temp)
                                    self.online.set_ydata(temp)
                                self.figure.canvas.draw()
                        except:
                            pass

            # writes the temperature to file_name file ...
            # if the number of time steps is verified
            if self.object.file_name:
                if nw == write_interval or j == 0 or j == nt - 1:
                    line = '%f,' % self.object.time_passed
                    for i in self.object.temperature:
                        new_line = '%f,' % i[1]
                        line = line + new_line
                    line = line[:-1] + '\n'
                    f = open(self.object.file_name, 'a')
                    f.write(line)
                    f.close()

            if nw == write_interval:
                nw = 0
                if verbose:
                    print('pogress:', int(100*j/nt), '%', end="\r")

        if verbose:
            print('Finished simulation')

Single_object class.

This class solves numerically the heat conduction equation for 1 dimension of a single material(s). The class has 6 methods.

#   SingleObject1D( self, amb_temperature, materials=('Cu',), borders=(1, 11), materials_order=(0,), dx=0.01, dt=0.1, file_name=None, boundaries=(0, 0), initial_state=False, materials_path=False, draw=['temperature'], draw_scale=None )
View Source
    def __init__(self, amb_temperature, materials=('Cu',), borders=(1, 11),
                 materials_order=(0,), dx=0.01, dt=0.1, file_name=None,
                 boundaries=(0, 0), initial_state=False,
                 materials_path=False, draw=['temperature'], draw_scale=None):
        """Thermal object initialization.

        `amb_temperature` is the ambient temperature of the whole system.
        `materials` is the list of strings of all the used materials present in
        `material_path`. `borders` is a list of the points where there is a
        change of material. `materials_order` is a list of the materials list
        indexes that defines the material properties given by borders. `dx` and
        `dt` are the space and time steps, respectively. `file_name` is the
        file name where the temperature is saved. `boundaries` is a list of two
        entries that define the boundary condition for temperature. If 0 the
        boundary condition is insulation. `initial_state` is the initial state
        of the materials. True if there are an applied field and False if them
        field is absent. `materials_path` is absolute path of the materials
        database. If false, then the materials database is the standard
        heatrapy database. `draw` is a list of strings representing the online
        plots. In this version only `'temperature'` can be potted. If the list
        is empty, then no drawing is performed. `draw_scale` is a list of two
        values, representing the minimum and maximum temperature to be drawn.
        If None, there are no limits.

        """
        # check the validity of inputs
        materials = tuple(materials)
        borders = tuple(borders)
        materials_order = tuple(materials_order)
        boundaries = tuple(boundaries)
        cond01 = isinstance(amb_temperature, float)
        cond01 = cond01 or isinstance(amb_temperature, int)
        cond02 = isinstance(materials, tuple)
        cond03 = isinstance(borders, tuple)
        cond04 = isinstance(materials_order, tuple)
        cond05 = isinstance(dx, int) or isinstance(dx, float)
        cond06 = isinstance(dt, int) or isinstance(dt, float)
        cond07 = isinstance(file_name, str)
        cond07 = cond07 or (file_name is None)
        cond08 = isinstance(boundaries, tuple)
        cond10 = isinstance(initial_state, bool)
        if isinstance(draw, list):
            cond15 = True
        elif draw is None:
            cond15 = True
        else:
            cond15 = False
        if isinstance(draw_scale, list) or isinstance(draw_scale, tuple):
            cond16 = (len(draw_scale) == 2)
        elif draw_scale is None:
            cond16 = True
        else:
            cond16 = False
        condition = cond01 and cond02 and cond03 and cond04 and cond05
        condition = condition and cond06 and cond07 and cond08
        condition = condition and cond10
        condition = condition and cond15 and cond16
        if not condition:
            raise ValueError

        self.object = Object(amb_temperature, materials=materials,
                             borders=borders, materials_order=materials_order,
                             dx=dx, dt=dt, file_name=file_name,
                             boundaries=boundaries,
                             initial_state=initial_state,
                             materials_path=materials_path)

        # initializes the plotting
        self.draw = draw
        self.draw_scale = draw_scale
        for drawing in self.draw:
            if drawing == 'temperature':
                self.figure = plt.figure()
                self.ax = self.figure.add_subplot(111)
                temp = []
                for i in range(len(self.object.temperature)):
                    temp.append(self.object.temperature[i][0])
                if not self.draw_scale:
                    vmax = max(temp)
                    vmin = min(temp)
                    if vmax == vmin:
                        vmin = vmin - 0.1
                        vmax = vmax + 0.1
                    temp = np.array(temp)
                    x_plot = [self.object.dx*j for j in range(len(temp))]
                    self.online, = self.ax.plot(x_plot, temp)
                    self.ax.set_ylim([vmin, vmax])
                else:
                    temp = np.array(temp)
                    x_plot = [self.object.dx*j for j in range(len(temp))]
                    self.online, = self.ax.plot(x_plot, temp)
                    self.ax.set_ylim(self.draw_scale)
                self.ax.set_title('Temperature (K)')
                self.ax.set_xlabel('x axis (m)')
                self.ax.set_ylabel('temperature (K)')
                plt.show(block=False)

Thermal object initialization.

amb_temperature is the ambient temperature of the whole system. materials is the list of strings of all the used materials present in material_path. borders is a list of the points where there is a change of material. materials_order is a list of the materials list indexes that defines the material properties given by borders. dx and dt are the space and time steps, respectively. file_name is the file name where the temperature is saved. boundaries is a list of two entries that define the boundary condition for temperature. If 0 the boundary condition is insulation. initial_state is the initial state of the materials. True if there are an applied field and False if them field is absent. materials_path is absolute path of the materials database. If false, then the materials database is the standard heatrapy database. draw is a list of strings representing the online plots. In this version only 'temperature' can be potted. If the list is empty, then no drawing is performed. draw_scale is a list of two values, representing the minimum and maximum temperature to be drawn. If None, there are no limits.

#   def show_figure(self, figure_type, draw_scale=None):
View Source
    def show_figure(self, figure_type, draw_scale=None):
        """Plotting.

        Initializes a specific live plotting. `figure_type` is a string
        identifying the plotting. This version only allows the plotting of the
        'temperature'. `draw_scale` defines the range of temperatures. If None,
        this range is found automatically for every frame.

        """
        # check the validity of inputs
        if isinstance(draw_scale, list) or isinstance(draw_scale, tuple):
            condition = (len(draw_scale) == 2)
        elif draw_scale is None:
            condition = True
        else:
            condition = False
        condition = condition and isinstance(figure_type, str)
        if not condition:
            raise ValueError

        self.draw_scale = draw_scale
        if figure_type == 'temperature':
            if figure_type not in self.draw:
                self.draw.append(figure_type)
            self.figure = plt.figure()
            self.ax = self.figure.add_subplot(111)
            temp = []
            for i in range(len(self.object.temperature)):
                temp.append(self.object.temperature[i][0])
            if not self.draw_scale:
                vmax = max(temp)
                vmin = min(temp)
                if vmax == vmin:
                    vmin = vmin - 0.1
                    vmax = vmax + 0.1
                temp = np.array(temp)
                x_plot = [self.object.dx*j for j in range(len(temp))]
                self.online, = self.ax.plot(x_plot, temp)
                self.ax.set_ylim([vmin, vmax])
            else:
                temp = np.array(temp)
                x_plot = [self.object.dx*j for j in range(len(temp))]
                self.online, = self.ax.plot(x_plot, temp)
                self.ax.set_ylim(self.draw_scale)
            self.ax.set_title('Temperature (K)')
            self.ax.set_xlabel('x axis (m)')
            self.ax.set_ylabel('temperature (K)')
            plt.show(block=False)

Plotting.

Initializes a specific live plotting. figure_type is a string identifying the plotting. This version only allows the plotting of the 'temperature'. draw_scale defines the range of temperatures. If None, this range is found automatically for every frame.

#   def activate(self, initial_point, final_point):
View Source
    def activate(self, initial_point, final_point):
        """Activation.

        Activates the thermal object between `initial_point` to `final_point`.
        """
        # check the validity of inputs
        condition = isinstance(initial_point, int)
        condition = condition and isinstance(final_point, int)
        if not condition:
            raise ValueError

        self.object.activate(initial_point, final_point)

        if self.draw:
            for drawing in self.draw:
                if drawing == 'temperature':
                    try:
                        temp = []
                        for i in range(len(self.object.temperature)):
                            temp.append(self.object.temperature[i][0])
                        if not self.draw_scale:
                            vmax = max(temp)
                            vmin = min(temp)
                            if vmax == vmin:
                                vmin = vmin - 0.1
                                vmax = vmax + 0.1
                            temp = np.array(temp)
                            self.online.set_ydata(temp)
                            self.ax.set_ylim([vmin, vmax])
                        else:
                            temp = np.array(temp)
                            self.online.set_ydata(temp)
                        self.figure.canvas.draw()
                    except:
                        pass

Activation.

Activates the thermal object between initial_point to final_point.

#   def deactivate(self, initial_point, final_point):
View Source
    def deactivate(self, initial_point, final_point):
        """Deactivation.

        Deactivates the thermal object between `initial_point` to
        `final_point`.
        """
        # check the validity of inputs
        condition = isinstance(initial_point, int)
        condition = condition and isinstance(final_point, int)
        if not condition:
            raise ValueError

        self.object.deactivate(initial_point, final_point)

        if self.draw:
            for drawing in self.draw:
                if drawing == 'temperature':
                    try:
                        temp = []
                        for i in range(len(self.object.temperature)):
                            temp.append(self.object.temperature[i][0])
                        if not self.draw_scale:
                            vmax = max(temp)
                            vmin = min(temp)
                            if vmax == vmin:
                                vmin = vmin - 0.1
                                vmax = vmax + 0.1
                            temp = np.array(temp)
                            self.online.set_ydata(temp)
                            self.ax.set_ylim([vmin, vmax])
                        else:
                            temp = np.array(temp)
                            self.online.set_ydata(temp)
                        self.figure.canvas.draw()
                    except:
                        pass

Deactivation.

Deactivates the thermal object between initial_point to final_point.

#   def change_power(self, power_type, power, initial_point, final_point):
View Source
    def change_power(self, power_type, power, initial_point, final_point):
        """Heat power source change.

        Changes the coeficients for the heat power sources by a value of power
        from `initial_point` to `final_point`. `power_type` is a string that
        represents the type of coefficient, i.e. 'Q' or 'Q0'.

        """
        # check the validity of inputs
        value = isinstance(initial_point, int)
        if value and isinstance(final_point, int):
            cond1 = True
        else:
            cond1 = False
        cond2 = isinstance(power, int) or isinstance(power, float)
        if isinstance(power_type, str):
            if power_type == 'Q' or power_type == 'Q0':
                cond3 = True
            else:
                cond3 = False
        else:
            cond3 = False
        if not (cond1 and cond2 and cond3):
            raise ValueError

        if power_type == 'Q':
            for j in range(initial_point, final_point):
                self.object.Q[j] = power
        if power_type == 'Q0':
            for j in range(initial_point, final_point):
                self.object.Q0[j] = power

Heat power source change.

Changes the coeficients for the heat power sources by a value of power from initial_point to final_point. power_type is a string that represents the type of coefficient, i.e. 'Q' or 'Q0'.

#   def change_boundaries(self, boundaries):
View Source
    def change_boundaries(self, boundaries):
        """Boundary change.

        Changes the `boundaries` variable.

        """
        # check the validity of inputs
        if isinstance(boundaries, tuple):
            if len(boundaries) == 2:
                condition = True
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.object.boundaries = boundaries

Boundary change.

Changes the boundaries variable.

#   def compute( self, time_interval, write_interval, solver='explicit_k(x)', verbose=True ):
View Source
    def compute(self, time_interval, write_interval, solver='explicit_k(x)',
                verbose=True):
        """Compute the thermal process.

        Computes the system for time_interval seconds, and writes into the
        `file_name` file every `write_interval` time steps. Four different
        solvers can be used: `'explicit_general'`, `'explicit_k(x)'`,
        `'implicit_general'`, and `'implicit_k(x)'`. If `verbose = True`, then
        the progress of the computation progress is shown.

        """
        # check the validity of inputs
        cond1 = isinstance(time_interval, float)
        cond1 = cond1 or isinstance(time_interval, int)
        cond2 = isinstance(write_interval, int)
        if isinstance(solver, str):
            all_solvers = ['implicit_general', 'implicit_k(x)',
                           'explicit_k(x)', 'explicit_general']
            if solver in all_solvers:
                cond3 = True
            else:
                cond3 = False
        else:
            cond3 = False
        cond4 = isinstance(verbose, bool)
        condition = cond1 and cond2 and cond3 and cond4
        if not condition:
            raise ValueError

        # number of time steps for the given timeInterval
        nt = int(time_interval / self.object.dt)

        # number of time steps counting from the last writing process
        nw = 0

        # computes
        for j in range(nt):

            # updates the time_passed
            self.object.time_passed = self.object.time_passed + self.object.dt

            # defines the material properties accoring to the state list
            for i in range(1, self.object.num_points - 1):
                if self.object.state[i] is True:
                    value = self.object.materials_index[i]
                    self.object.rho[i] = self.object.materials[value].rhoa(
                        self.object.temperature[i][0])
                    self.object.Cp[i] = self.object.materials[value].cpa(
                        self.object.temperature[i][0])
                    self.object.k[i] = self.object.materials[value].ka(
                        self.object.temperature[i][0])
                if self.object.state[i] is False:
                    value = self.object.materials_index[i]
                    self.object.rho[i] = self.object.materials[value].rho0(
                        self.object.temperature[i][0])
                    self.object.Cp[i] = self.object.materials[value].cp0(
                        self.object.temperature[i][0])
                    self.object.k[i] = self.object.materials[value].k0(
                        self.object.temperature[i][0])

            # SOLVERS
            # implicit k constant
            if solver == 'implicit_general':
                value = solvers.implicit_general(self.object)
                self.object.temperature, self.object.lheat = value
            # implicit k dependent on x
            if solver == 'implicit_k(x)':
                value = solvers.implicit_k(self.object)
                self.object.temperature, self.object.lheat = value
            # explicit k constant
            if solver == 'explicit_general':
                value = solvers.explicit_general(self.object)
                self.object.temperature, self.object.lheat = value
            # explicit k dependent on x
            if solver == 'explicit_k(x)':
                value = solvers.explicit_k(self.object)
                self.object.temperature, self.object.lheat = value

            nw = nw + 1

            if self.draw:
                for drawing in self.draw:
                    if drawing == 'temperature':
                        try:
                            value = nw + 1 == write_interval
                            if value or j == 0 or j == nt - 1:
                                temp = []
                                for i in range(len(self.object.temperature)):
                                    temp.append(self.object.temperature[i][0])
                                if not self.draw_scale:
                                    vmax = max(temp)
                                    vmin = min(temp)
                                    if vmax == vmin:
                                        vmin = vmin - 0.1
                                        vmax = vmax + 0.1
                                    temp = np.array(temp)
                                    self.online.set_ydata(temp)
                                    self.ax.set_ylim([vmin, vmax])
                                else:
                                    temp = np.array(temp)
                                    self.online.set_ydata(temp)
                                self.figure.canvas.draw()
                        except:
                            pass

            # writes the temperature to file_name file ...
            # if the number of time steps is verified
            if self.object.file_name:
                if nw == write_interval or j == 0 or j == nt - 1:
                    line = '%f,' % self.object.time_passed
                    for i in self.object.temperature:
                        new_line = '%f,' % i[1]
                        line = line + new_line
                    line = line[:-1] + '\n'
                    f = open(self.object.file_name, 'a')
                    f.write(line)
                    f.close()

            if nw == write_interval:
                nw = 0
                if verbose:
                    print('pogress:', int(100*j/nt), '%', end="\r")

        if verbose:
            print('Finished simulation')

Compute the thermal process.

Computes the system for time_interval seconds, and writes into the file_name file every write_interval time steps. Four different solvers can be used: 'explicit_general', 'explicit_k(x)', 'implicit_general', and 'implicit_k(x)'. If verbose = True, then the progress of the computation progress is shown.

#   class SystemObjects2D:
View Source
class SystemObjects:
    """System_objects class.

    This class creates a system of 2D thermal objects, establishes contact
    between them and computes the respective thermal processes.

    """

    def __init__(self, number_objects=2, materials=('Cu', 'Cu'),
                 objects_length=((10, 10), (10, 10)), amb_temperature=293,
                 dx=0.01, dy=0.01, dt=0.1, file_name=None, initial_state=False,
                 boundaries=((0, 0, 0, 0), (0, 0, 0, 0)),
                 materials_path=False):
        """System object initialization.

        `number_objects` is the integer number of thermal objects. `materials`
        is the list of strings of all the used materials present in
        `material_path`. `amb_temperature` is the ambient temperature of the
        whole system. `object_length` is the list of thermal object lengths
        (tuple of spacial steps). `dx` and `dy` are the space steps along the
        x- and y-axis, respectively. dt is the time step. `file_name` is the
        file name where the temperature is saved. `boundaries` is a list of
        four entries that define the boundary condition for temperature (left,
        right, bottom, top). If 0, the boundary condition is insulation.
        `materials_path` is absolute path of the materials database. If false,
        then the materials database is the standard heatrapy database.

        """
        # check the validity of inputs
        materials = tuple(materials)
        objects_length = tuple(objects_length)
        boundaries = tuple(boundaries)
        cond01 = isinstance(amb_temperature, float)
        cond01 = cond01 or isinstance(amb_temperature, int)
        cond02 = isinstance(materials, tuple)
        cond03 = isinstance(number_objects, int)
        cond04 = isinstance(objects_length, tuple)
        cond05 = isinstance(dx, int) or isinstance(dx, float)
        cond06 = isinstance(dy, int) or isinstance(dy, float)
        cond07 = isinstance(dt, int) or isinstance(dt, float)
        cond08 = isinstance(file_name, str)
        cond08 = cond08 or (file_name is None)
        cond09 = isinstance(boundaries, tuple)
        cond10 = isinstance(initial_state, bool)
        condition = cond01 and cond02 and cond03 and cond04 and cond05
        condition = condition and cond06 and cond07 and cond08 and cond09
        condition = condition and cond10
        if not condition:
            raise ValueError

        # initial definitions
        self.objects = []
        file_name_obj = None
        for i in range(number_objects):

            if file_name:
                file_name_obj = file_name + '_' + str(i) + '.txt'

            self.objects.append(Object(amb_temperature, material=materials[i],
                                       dx=dx, dy=dy, dt=dt,
                                       file_name=file_name_obj,
                                       boundaries=boundaries[i], Q=[], Q0=[],
                                       initial_state=initial_state,
                                       materials_path=materials_path))
        self.contacts = set()
        self.boundaries = boundaries
        self.dt = dt
        self.q1 = 0.
        self.q2 = 0.

    def contact_filter(self, object_id):
        """Filter thermal contacts.

        Filter thermal contacts by `object_id`.

        """
        # check the validity of inputs
        condition = isinstance(object_id, int)
        if not condition:
            raise ValueError

        value = object_id
        filtered = [x for x in
                    self.contacts if (x[0][0] == value or x[1][0] == value)]
        return set(filtered)

    def contact_add(self, contact):
        """Add contact to self.contacts.

        `contact` is a thermal contact tuple of length 3, where the first and
        second entries correspond to tuples of the thermal objects and points
        (object_id, (x,y)), and the third entry is the heat transfer
        coefficient.

        """
        # check the validity of inputs
        if isinstance(contact, tuple):
            if len(contact) == 3:
                condition = True
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.contacts.add(contact)

    def contact_remove(self, object_one, object_two):
        """Contact removal.

        Removes all contacts between `object_one` id and `object_two` id.

        """
        # check the validity of inputs
        condition = isinstance(object_one, int)
        condition = condition and isinstance(object_two, int)
        if not condition:
            raise ValueError

        contact_list = list(self.contacts)
        for i in range(len(contact_list)):
            cond_1 = contact_list[i][0][0] == object_one
            cond_1 = cond_1 and contact_list[i][1][0] == object_two
            cond_2 = contact_list[i][0][0] == object_two
            cond_2 = cond_2 and contact_list[i][1][0] == object_one
            if cond_1 or cond_2:
                self.contacts.remove(contact_list[i])

    def change_boundaries(self, object_id, boundaries):
        """Change boundaries.

        Changes the `boundaries` variable of `object_id`.

        """
        # check the validity of inputs
        condition = isinstance(object_id, int)
        condition = condition and isinstance(boundaries, tuple)
        if condition:
            if len(boundaries) == 4:
                condition = True
            else:
                condition = False
        if not condition:
            raise ValueError

        self.objects[object_id].boundaries = boundaries

    def compute(self, time_interval, write_interval, solver='explicit_k(x)',
                verbose=True):
        """Compute the thermal process.

        Computes the system for `time_interval`, and writes into the
        `file_name` file every `write_interval` time steps. Two different
        solvers can be used: `'explicit_general'` and `'explicit_k(x)'`. If
        verbose = True, then the progress of the computation is shown.

        """
        # check the validity of inputs
        cond1 = isinstance(time_interval, float)
        cond1 = cond1 or isinstance(time_interval, int)
        cond2 = isinstance(write_interval, int)
        cond3 = isinstance(solver, str)
        cond4 = isinstance(verbose, bool)
        condition = cond1 and cond2 and cond3 and cond4
        if not condition:
            raise ValueError

        # number of time steps for the given time_interval
        nt = int(time_interval / self.dt)

        # number of time steps counting from the last writing process
        nw = 0

        # computes
        for k in range(nt):
            for obj in self.objects:
                obj.Q0 = copy.copy(obj.Q0_ref)

            for contact in self.contacts:
                in1_x = int(contact[1][1][0])
                in1_y = int(contact[1][1][1])
                in2_x = int(contact[0][1][0])
                in2_y = int(contact[0][1][1])
                td1 = self.objects[contact[1][0]].temperature[in1_x][in1_y][0]
                td2 = self.objects[contact[0][0]].temperature[in2_x][in2_y][0]
                heat_contact_1 = contact[2] * (td1 - td2)
                heat_contact_2 = contact[2] * (td2 - td1)
                self.objects[contact[0][0]].Q0[in2_x][in2_y] = heat_contact_1
                self.objects[contact[1][0]].Q0[in1_x][in2_y] = heat_contact_2

            for obj in self.objects:
                obj.time_passed = obj.time_passed + obj.dt

                # defines the material properties
                for i in range(obj.size[0]):
                    for j in range(obj.size[1]):
                        if obj.state[i][j] is True:
                            ind = obj.materials_index[i][j]
                            obj.rho[i][j] = obj.materials[ind].rhoa(
                                obj.temperature[i][j][0])
                            obj.Cp[i][j] = obj.materials[ind].cpa(
                                obj.temperature[i][j][0])
                            obj.k[i][j] = obj.materials[ind].ka(
                                obj.temperature[i][j][0])
                        if obj.state[i][j] is False:
                            ind = obj.materials_index[i][j]
                            obj.rho[i][j] = obj.materials[ind].rho0(
                                obj.temperature[i][j][0])
                            obj.Cp[i][j] = obj.materials[ind].cp0(
                                obj.temperature[i][j][0])
                            obj.k[i][j] = obj.materials[ind].k0(
                                obj.temperature[i][j][0])

                # explicit k constant
                if solver == 'explicit_general':
                    temp = []
                    for i in range(obj.size[0]):
                        temp.append([])
                        for j in range(obj.size[1]):
                            temp[-1].append(obj.temperature[i][j][0])
                    obj.temperature, obj.lheat = solvers.explicit_general(obj)
                    temp = []
                    for i in range(obj.size[0]):
                        temp.append([])
                        for j in range(obj.size[1]):
                            temp[-1].append(obj.temperature[i][j][0])

                # explicit k constant
                if solver == 'explicit_k(x)':
                    temp = []
                    for i in range(obj.size[0]):
                        temp.append([])
                        for j in range(obj.size[1]):
                            temp[-1].append(obj.temperature[i][j][0])
                    obj.temperature, obj.lheat = solvers.explicit_k(obj)
                    temp = []
                    for i in range(obj.size[0]):
                        temp.append([])
                        for j in range(obj.size[1]):
                            temp[-1].append(obj.temperature[i][j][0])

                if obj.file_name:
                    if nw + 1 == write_interval or k == 0 or k == nt - 1:
                        line = '%f' % obj.time_passed
                        for i in range(obj.size[0]):
                            for j in range(obj.size[1]):
                                new_line = ',%f' % obj.temperature[i][j][1]
                                line = line + new_line
                        f = open(obj.file_name, 'a')
                        f.write(line+'\n')
                        f.close()

            if nw == write_interval:
                nw = 0
                if verbose:
                    print('progress:', int(100*k/nt), '%', end='\r')
            else:
                nw = nw + 1

        if verbose:
            print('Finished simulation')

System_objects class.

This class creates a system of 2D thermal objects, establishes contact between them and computes the respective thermal processes.

#   SystemObjects2D( self, number_objects=2, materials=('Cu', 'Cu'), objects_length=((10, 10), (10, 10)), amb_temperature=293, dx=0.01, dy=0.01, dt=0.1, file_name=None, initial_state=False, boundaries=((0, 0, 0, 0), (0, 0, 0, 0)), materials_path=False )
View Source
    def __init__(self, number_objects=2, materials=('Cu', 'Cu'),
                 objects_length=((10, 10), (10, 10)), amb_temperature=293,
                 dx=0.01, dy=0.01, dt=0.1, file_name=None, initial_state=False,
                 boundaries=((0, 0, 0, 0), (0, 0, 0, 0)),
                 materials_path=False):
        """System object initialization.

        `number_objects` is the integer number of thermal objects. `materials`
        is the list of strings of all the used materials present in
        `material_path`. `amb_temperature` is the ambient temperature of the
        whole system. `object_length` is the list of thermal object lengths
        (tuple of spacial steps). `dx` and `dy` are the space steps along the
        x- and y-axis, respectively. dt is the time step. `file_name` is the
        file name where the temperature is saved. `boundaries` is a list of
        four entries that define the boundary condition for temperature (left,
        right, bottom, top). If 0, the boundary condition is insulation.
        `materials_path` is absolute path of the materials database. If false,
        then the materials database is the standard heatrapy database.

        """
        # check the validity of inputs
        materials = tuple(materials)
        objects_length = tuple(objects_length)
        boundaries = tuple(boundaries)
        cond01 = isinstance(amb_temperature, float)
        cond01 = cond01 or isinstance(amb_temperature, int)
        cond02 = isinstance(materials, tuple)
        cond03 = isinstance(number_objects, int)
        cond04 = isinstance(objects_length, tuple)
        cond05 = isinstance(dx, int) or isinstance(dx, float)
        cond06 = isinstance(dy, int) or isinstance(dy, float)
        cond07 = isinstance(dt, int) or isinstance(dt, float)
        cond08 = isinstance(file_name, str)
        cond08 = cond08 or (file_name is None)
        cond09 = isinstance(boundaries, tuple)
        cond10 = isinstance(initial_state, bool)
        condition = cond01 and cond02 and cond03 and cond04 and cond05
        condition = condition and cond06 and cond07 and cond08 and cond09
        condition = condition and cond10
        if not condition:
            raise ValueError

        # initial definitions
        self.objects = []
        file_name_obj = None
        for i in range(number_objects):

            if file_name:
                file_name_obj = file_name + '_' + str(i) + '.txt'

            self.objects.append(Object(amb_temperature, material=materials[i],
                                       dx=dx, dy=dy, dt=dt,
                                       file_name=file_name_obj,
                                       boundaries=boundaries[i], Q=[], Q0=[],
                                       initial_state=initial_state,
                                       materials_path=materials_path))
        self.contacts = set()
        self.boundaries = boundaries
        self.dt = dt
        self.q1 = 0.
        self.q2 = 0.

System object initialization.

number_objects is the integer number of thermal objects. materials is the list of strings of all the used materials present in material_path. amb_temperature is the ambient temperature of the whole system. object_length is the list of thermal object lengths (tuple of spacial steps). dx and dy are the space steps along the x- and y-axis, respectively. dt is the time step. file_name is the file name where the temperature is saved. boundaries is a list of four entries that define the boundary condition for temperature (left, right, bottom, top). If 0, the boundary condition is insulation. materials_path is absolute path of the materials database. If false, then the materials database is the standard heatrapy database.

#   def contact_filter(self, object_id):
View Source
    def contact_filter(self, object_id):
        """Filter thermal contacts.

        Filter thermal contacts by `object_id`.

        """
        # check the validity of inputs
        condition = isinstance(object_id, int)
        if not condition:
            raise ValueError

        value = object_id
        filtered = [x for x in
                    self.contacts if (x[0][0] == value or x[1][0] == value)]
        return set(filtered)

Filter thermal contacts.

Filter thermal contacts by object_id.

#   def contact_add(self, contact):
View Source
    def contact_add(self, contact):
        """Add contact to self.contacts.

        `contact` is a thermal contact tuple of length 3, where the first and
        second entries correspond to tuples of the thermal objects and points
        (object_id, (x,y)), and the third entry is the heat transfer
        coefficient.

        """
        # check the validity of inputs
        if isinstance(contact, tuple):
            if len(contact) == 3:
                condition = True
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.contacts.add(contact)

Add contact to self.contacts.

contact is a thermal contact tuple of length 3, where the first and second entries correspond to tuples of the thermal objects and points (object_id, (x,y)), and the third entry is the heat transfer coefficient.

#   def contact_remove(self, object_one, object_two):
View Source
    def contact_remove(self, object_one, object_two):
        """Contact removal.

        Removes all contacts between `object_one` id and `object_two` id.

        """
        # check the validity of inputs
        condition = isinstance(object_one, int)
        condition = condition and isinstance(object_two, int)
        if not condition:
            raise ValueError

        contact_list = list(self.contacts)
        for i in range(len(contact_list)):
            cond_1 = contact_list[i][0][0] == object_one
            cond_1 = cond_1 and contact_list[i][1][0] == object_two
            cond_2 = contact_list[i][0][0] == object_two
            cond_2 = cond_2 and contact_list[i][1][0] == object_one
            if cond_1 or cond_2:
                self.contacts.remove(contact_list[i])

Contact removal.

Removes all contacts between object_one id and object_two id.

#   def change_boundaries(self, object_id, boundaries):
View Source
    def change_boundaries(self, object_id, boundaries):
        """Change boundaries.

        Changes the `boundaries` variable of `object_id`.

        """
        # check the validity of inputs
        condition = isinstance(object_id, int)
        condition = condition and isinstance(boundaries, tuple)
        if condition:
            if len(boundaries) == 4:
                condition = True
            else:
                condition = False
        if not condition:
            raise ValueError

        self.objects[object_id].boundaries = boundaries

Change boundaries.

Changes the boundaries variable of object_id.

#   def compute( self, time_interval, write_interval, solver='explicit_k(x)', verbose=True ):
View Source
    def compute(self, time_interval, write_interval, solver='explicit_k(x)',
                verbose=True):
        """Compute the thermal process.

        Computes the system for `time_interval`, and writes into the
        `file_name` file every `write_interval` time steps. Two different
        solvers can be used: `'explicit_general'` and `'explicit_k(x)'`. If
        verbose = True, then the progress of the computation is shown.

        """
        # check the validity of inputs
        cond1 = isinstance(time_interval, float)
        cond1 = cond1 or isinstance(time_interval, int)
        cond2 = isinstance(write_interval, int)
        cond3 = isinstance(solver, str)
        cond4 = isinstance(verbose, bool)
        condition = cond1 and cond2 and cond3 and cond4
        if not condition:
            raise ValueError

        # number of time steps for the given time_interval
        nt = int(time_interval / self.dt)

        # number of time steps counting from the last writing process
        nw = 0

        # computes
        for k in range(nt):
            for obj in self.objects:
                obj.Q0 = copy.copy(obj.Q0_ref)

            for contact in self.contacts:
                in1_x = int(contact[1][1][0])
                in1_y = int(contact[1][1][1])
                in2_x = int(contact[0][1][0])
                in2_y = int(contact[0][1][1])
                td1 = self.objects[contact[1][0]].temperature[in1_x][in1_y][0]
                td2 = self.objects[contact[0][0]].temperature[in2_x][in2_y][0]
                heat_contact_1 = contact[2] * (td1 - td2)
                heat_contact_2 = contact[2] * (td2 - td1)
                self.objects[contact[0][0]].Q0[in2_x][in2_y] = heat_contact_1
                self.objects[contact[1][0]].Q0[in1_x][in2_y] = heat_contact_2

            for obj in self.objects:
                obj.time_passed = obj.time_passed + obj.dt

                # defines the material properties
                for i in range(obj.size[0]):
                    for j in range(obj.size[1]):
                        if obj.state[i][j] is True:
                            ind = obj.materials_index[i][j]
                            obj.rho[i][j] = obj.materials[ind].rhoa(
                                obj.temperature[i][j][0])
                            obj.Cp[i][j] = obj.materials[ind].cpa(
                                obj.temperature[i][j][0])
                            obj.k[i][j] = obj.materials[ind].ka(
                                obj.temperature[i][j][0])
                        if obj.state[i][j] is False:
                            ind = obj.materials_index[i][j]
                            obj.rho[i][j] = obj.materials[ind].rho0(
                                obj.temperature[i][j][0])
                            obj.Cp[i][j] = obj.materials[ind].cp0(
                                obj.temperature[i][j][0])
                            obj.k[i][j] = obj.materials[ind].k0(
                                obj.temperature[i][j][0])

                # explicit k constant
                if solver == 'explicit_general':
                    temp = []
                    for i in range(obj.size[0]):
                        temp.append([])
                        for j in range(obj.size[1]):
                            temp[-1].append(obj.temperature[i][j][0])
                    obj.temperature, obj.lheat = solvers.explicit_general(obj)
                    temp = []
                    for i in range(obj.size[0]):
                        temp.append([])
                        for j in range(obj.size[1]):
                            temp[-1].append(obj.temperature[i][j][0])

                # explicit k constant
                if solver == 'explicit_k(x)':
                    temp = []
                    for i in range(obj.size[0]):
                        temp.append([])
                        for j in range(obj.size[1]):
                            temp[-1].append(obj.temperature[i][j][0])
                    obj.temperature, obj.lheat = solvers.explicit_k(obj)
                    temp = []
                    for i in range(obj.size[0]):
                        temp.append([])
                        for j in range(obj.size[1]):
                            temp[-1].append(obj.temperature[i][j][0])

                if obj.file_name:
                    if nw + 1 == write_interval or k == 0 or k == nt - 1:
                        line = '%f' % obj.time_passed
                        for i in range(obj.size[0]):
                            for j in range(obj.size[1]):
                                new_line = ',%f' % obj.temperature[i][j][1]
                                line = line + new_line
                        f = open(obj.file_name, 'a')
                        f.write(line+'\n')
                        f.close()

            if nw == write_interval:
                nw = 0
                if verbose:
                    print('progress:', int(100*k/nt), '%', end='\r')
            else:
                nw = nw + 1

        if verbose:
            print('Finished simulation')

Compute the thermal process.

Computes the system for time_interval, and writes into the file_name file every write_interval time steps. Two different solvers can be used: 'explicit_general' and 'explicit_k(x)'. If verbose = True, then the progress of the computation is shown.

#   class SingleObject2D:
View Source
class SingleObject:
    """Single_object class.

    This class solves numerically the two-dimensional heat conduction equation.

    """

    def __init__(self, amb_temperature, material='Cu', dx=0.01, dy=0.01,
                 dt=0.1, size=(10, 10), file_name=None,
                 boundaries=(0, 0, 0, 0), Q=[], Q0=[], initial_state=False,
                 materials_path=False,
                 draw=['temperature', 'materials'], draw_scale=None):
        """Object initialization.

        `amb_temperature` is the ambient temperature of the whole system.
        `materials` is the background material present in `material_path`.
        `dx`, `dy` are the space steps along the x- and y-axis, respectively.
        `dt` is the time step. `file_name` is the file name where the
        temperature is saved. `boundaries` is a list of four entries that
        define the boundary condition for temperature (left, right, bottom,
        top). If 0 the boundary condition is insulation. `initial_state` is the
        initial state of the materials. True if there are an applied field and
        False if them field is absent. `materials_path` is absolute path of the
        materials database. If false, then the materials database is the
        standard heatrapy database. `draw` is a list of strings representing
        the online plots. In this version live plotting can be performed for
        `temperature`, `materials`, `state`, `Q` and `Q0`. If the list is
        empty, then no drawing is performed. `draw_scale` is a list of two
        values, representing the minimum and maximum temperature to be drawn.
        If None, there are no limits. `Q` is a list of fixed heat source
        coefficient and `Q0` is a list of temperature dependent heat source
        coefficient.

        """
        boundaries = tuple(boundaries)
        cond01 = isinstance(amb_temperature, float)
        cond01 = cond01 or isinstance(amb_temperature, int)
        cond02 = isinstance(material, str)
        cond05 = isinstance(dx, int) or isinstance(dx, float)
        cond06 = isinstance(dy, int) or isinstance(dy, float)
        cond07 = isinstance(dt, int) or isinstance(dt, float)
        cond08 = isinstance(file_name, str)
        cond08 = cond08 or (file_name is None)
        cond09 = isinstance(boundaries, tuple)
        cond10 = isinstance(initial_state, bool)
        cond11 = isinstance(Q, list)
        cond12 = isinstance(Q0, list)
        cond13 = isinstance(draw, list)
        cond14 = isinstance(draw_scale, list) or isinstance(draw_scale, tuple)
        cond14 = cond14 or draw_scale is None
        condition = cond01 and cond02 and cond05
        condition = condition and cond06 and cond07 and cond08 and cond09
        condition = condition and cond10 and cond11 and cond12 and cond13
        condition = condition and cond14
        if not condition:
            raise ValueError

        self.materials_path = materials_path
        self.time_passed = 0.
        self.size = size
        self.dt = dt
        self.dx = dx
        self.dy = dy
        self.object = Object(amb_temperature, material=material, dx=dx, dy=dy,
                             dt=dt, size=size, file_name=file_name,
                             boundaries=boundaries, Q=[], Q0=[],
                             initial_state=initial_state,
                             materials_path=materials_path)

        # Initializes plotting
        self.draw = draw
        self.draw_scale = draw_scale
        if self.draw:
            cmap = matplotlib.cm.RdBu
            name = 'my_cmap_r'
            reverse = []
            k = []
            for key in cmap._segmentdata:
                k.append(key)
                channel = cmap._segmentdata[key]
                data = []
                for t in channel:
                    data.append((1-t[0], t[2], t[1]))
                reverse.append(sorted(data))
            linear = dict(zip(k, reverse))
            my_cmap_r = matplotlib.colors.LinearSegmentedColormap(name, linear)
            cmap_r = my_cmap_r
            for drawing in self.draw:
                if drawing == 'temperature':
                    self.figure = plt.figure()
                    self.ax = self.figure.add_subplot(111)
                    temp = []
                    for i in range(self.object.size[0]):
                        temp.append([])
                        for j in range(self.object.size[1]):
                            temp[-1].append(self.object.temperature[i][j][0])
                    if not self.draw_scale:
                        vmax = max(max(temp, key=max))
                        vmin = min(min(temp, key=min))
                        temp = np.array(temp)
                        extent = [0, size[0]*dx, 0, size[1]*dy]
                        self.im = self.ax.imshow(np.transpose(temp), vmax=vmax,
                                                 vmin=vmin, cmap=cmap_r,
                                                 extent=extent, origin='lower',
                                                 interpolation='hamming')
                    else:
                        temp = np.array(temp)
                        extent = [0, size[0]*dx, 0, size[1]*dy]
                        self.im = self.ax.imshow(np.transpose(temp),
                                                 vmax=self.draw_scale[0],
                                                 vmin=self.draw_scale[1],
                                                 cmap=cmap_r, extent=extent,
                                                 origin='lower',
                                                 interpolation='hamming')
                    cbar_kw = {}
                    cbar = self.ax.figure.colorbar(self.im, ax=self.ax,
                                                   **cbar_kw)
                    self.ax.set_title('Temperature (K)')
                    self.ax.set_xlabel('x axis (m)')
                    self.ax.set_ylabel('y axis (m)')
                    plt.show(block=False)
                if drawing == 'state':
                    self.figure_state = plt.figure()
                    self.ax_state = self.figure_state.add_subplot(111)
                    vmax = 1
                    vmin = 0
                    state = np.array(self.object.state)
                    cmap = plt.get_cmap("gray", 2)
                    extent = [0, size[0]*dx, 0, size[1]*dy]
                    self.im_state = self.ax_state.imshow(np.transpose(state),
                                                         vmax=1.5, vmin=-0.5,
                                                         cmap=cmap,
                                                         extent=extent,
                                                         origin='lower')
                    cbar_kw = {}
                    cbarlabel = ""
                    qrates = np.array(['active', 'inactive'])
                    value = np.linspace(0, 1, 2)
                    norm = matplotlib.colors.BoundaryNorm(value, 1)
                    func = lambda x, pos: qrates[::-1][norm(x)]
                    fmt = matplotlib.ticker.FuncFormatter(func)
                    cbar_kw = dict(ticks=np.arange(-3, 4), format=fmt)
                    cbar_stat = self.ax_state.figure.colorbar(self.im_state,
                                                              ax=self.ax_state,
                                                              **cbar_kw)
                    cbar_stat.ax.set_ylabel(cbarlabel, rotation=-90,
                                            va="bottom")
                    self.ax_state.set_title('State')
                    self.ax_state.set_xlabel('x axis (m)')
                    self.ax_state.set_ylabel('y axis (m)')
                    plt.show(block=False)
                value = len(self.object.materials_name) > 1
                if drawing == 'materials' and value:
                    self.figure_materials = plt.figure()
                    self.ax_materials = self.figure_materials.add_subplot(111)
                    vmax = len(self.object.materials)-1
                    vmin = 0
                    material_id = np.array(self.object.materials_index)
                    cmap = plt.get_cmap("gray", vmax)
                    extent = [0, size[0]*dx, 0, size[1]*dy]
                    origin = 'lower'
                    value = np.transpose(material_id)
                    self.im_materials = self.ax_materials.imshow(value,
                                                                 vmax=vmax,
                                                                 vmin=vmin,
                                                                 cmap=cmap,
                                                                 extent=extent,
                                                                 origin=origin)
                    cbar_kw = {}
                    cbarlabel = ""
                    qrates = np.array(self.object.materials_name)
                    value_1 = np.linspace(0, 1, len(self.object.materials))
                    value_2 = len(self.object.materials)-1
                    norm = matplotlib.colors.BoundaryNorm(value_1, value_2)
                    func = lambda x, pos: qrates[::-1][norm(x)]
                    fmt = matplotlib.ticker.FuncFormatter(func)
                    cbar_kw = dict(ticks=np.arange(-3, 4), format=fmt)
                    value_1 = self.im_materials
                    value_2 = self.ax_materials
                    cbar_m = self.ax_materials.figure.colorbar(value_1,
                                                               ax=value_2,
                                                               **cbar_kw)
                    cbar_m.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
                    self.ax_materials.set_title('Materials')
                    self.ax_materials.set_xlabel('x axis (m)')
                    self.ax_materials.set_ylabel('y axis (m)')
                    plt.show(block=False)
                if drawing == 'Q':
                    self.figure_Q = plt.figure()
                    self.ax_Q = self.figure_Q.add_subplot(111)
                    temp = np.array(self.object.Q)
                    vmax = 1
                    vmin = 0
                    extent = [0, size[0]*dx, 0, size[1]*dy]
                    self.im_Q = self.ax_Q.imshow(np.transpose(temp), vmax=vmax,
                                                 vmin=vmin, cmap='inferno',
                                                 extent=extent, origin='lower',
                                                 interpolation='hamming')
                    cbar_kw = {}
                    cbar = self.ax_Q.figure.colorbar(self.im_Q, ax=self.ax_Q,
                                                     **cbar_kw)
                    self.ax_Q.set_title('Q (W/m²)')
                    self.ax_Q.set_xlabel('x axis (m)')
                    self.ax_Q.set_ylabel('y axis (m)')
                    plt.show(block=False)
                if drawing == 'Q0':
                    self.figure_Q0 = plt.figure()
                    self.ax_Q0 = self.figure_Q0.add_subplot(111)
                    temp = np.array(self.object.Q0)
                    vmax = 1
                    vmin = 0
                    extent = [0, size[0]*dx, 0, size[1]*dy]
                    self.im_Q0 = self.ax_Q0.imshow(np.transpose(temp),
                                                   vmax=vmax, vmin=vmin,
                                                   cmap='inferno',
                                                   extent=extent,
                                                   origin='lower',
                                                   interpolation='hamming')
                    cbar_kw = {}
                    cbar = self.ax_Q0.figure.colorbar(self.im_Q0,
                                                      ax=self.ax_Q0,
                                                      **cbar_kw)
                    self.ax_Q0.set_title('Q0 (W/m²)')
                    self.ax_Q0.set_xlabel('x axis (m)')
                    self.ax_Q0.set_ylabel('y axis (m)')
                    plt.show(block=False)

    def show_figure(self, figure_type):
        """Plotting.

        Initializes a specific plotting. `figure_type` is a string identifying
        the plotting. In this version live plotting can be performed for
        `temperature`, `materials`, `state`, `Q` and `Q0`.

        """
        # check the validity of inputs
        condition = isinstance(figure_type, str)
        if not condition:
            raise ValueError

        if figure_type not in self.draw:
            self.draw.append(figure_type)
        if figure_type == 'temperature':
            self.figure = plt.figure()
            self.ax = self.figure.add_subplot(111)
            temp = []
            for i in range(self.object.size[0]):
                temp.append([])
                for j in range(self.object.size[1]):
                    temp[-1].append(self.object.temperature[i][j][0])
            if not self.draw_scale:
                vmax = max(max(temp, key=max))
                vmin = min(min(temp, key=min))
                temp = np.array(temp)
                extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
                self.im = self.ax.imshow(np.transpose(temp), vmax=vmax,
                                         vmin=vmin, cmap='jet', extent=extent,
                                         origin='lower',
                                         interpolation='hamming')
            else:
                temp = np.array(temp)
                extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
                self.im = self.ax.imshow(np.transpose(temp),
                                         vmax=self.draw_scale[0],
                                         vmin=self.draw_scale[1],
                                         cmap='jet', extent=extent,
                                         origin='lower',
                                         interpolation='hamming')
            cbar_kw = {}
            cbarlabel = "temperature (K)"
            cbar = self.ax.figure.colorbar(self.im, ax=self.ax, **cbar_kw)
            cbar.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
            self.ax.set_title('Temperature')
            self.ax.set_xlabel('x axis (m)')
            self.ax.set_ylabel('y axis (m)')
            plt.show(block=False)
        if figure_type == 'state':
            self.figure_state = plt.figure()
            self.ax_state = self.figure_state.add_subplot(111)
            vmax = 1
            vmin = 0
            state = np.array(self.object.state)
            extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
            self.im_state = self.ax_state.imshow(np.transpose(state), vmax=1.5,
                                                 vmin=-0.5,
                                                 cmap=plt.get_cmap("gray", 2),
                                                 extent=extent, origin='lower')
            cbar_kw = {}
            cbarlabel = ""  # "state"
            qrates = np.array(['active', 'inactive'])
            norm = matplotlib.colors.BoundaryNorm(np.linspace(0, 1, 2), 1)
            func = lambda x, pos: qrates[::-1][norm(x)]
            fmt = matplotlib.ticker.FuncFormatter(func)
            cbar_kw = dict(ticks=np.arange(-3, 4), format=fmt)
            cbar_state = self.ax_state.figure.colorbar(self.im_state,
                                                       ax=self.ax_state,
                                                       **cbar_kw)
            cbar_state.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
            self.ax_state.set_title('State')
            self.ax_state.set_xlabel('x axis (m)')
            self.ax_state.set_ylabel('y axis (m)')
            plt.show(block=False)
        if figure_type == 'materials' and len(self.object.materials_name) > 1:
            self.figure_materials = plt.figure()
            self.ax_materials = self.figure_materials.add_subplot(111)
            vmax = len(self.object.materials)-1
            vmin = 0
            material_id = np.array(self.object.materials_index)
            cmap = plt.get_cmap("PiYG", vmax+1)
            extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
            value = np.transpose(material_id)
            self.im_materials = self.ax_materials.imshow(value,
                                                         vmax=vmax,
                                                         vmin=vmin,
                                                         cmap=cmap,
                                                         extent=extent,
                                                         origin='lower')
            cbar_kw = {}
            cbarlabel = ""
            materials_name_list = copy.deepcopy(self.object.materials_name)
            materials_name_list.reverse()
            qrates = np.array(materials_name_list)
            value = np.linspace(0, len(self.object.materials) - 1,
                                len(self.object.materials))
            norm = matplotlib.colors.BoundaryNorm(value,
                                                  len(self.object.materials)-1)
            func = lambda x, pos: qrates[::-1][norm(x)]
            fmt = matplotlib.ticker.FuncFormatter(func)
            cbar_kw = dict(ticks=np.arange(0, len(self.object.materials)+1),
                           format=fmt)
            cbar_m = self.ax_materials.figure.colorbar(self.im_materials,
                                                       ax=self.ax_materials,
                                                       **cbar_kw)
            cbar_m.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
            self.ax_materials.set_title('Materials')
            self.ax_materials.set_xlabel('x axis (m)')
            self.ax_materials.set_ylabel('y axis (m)')
            plt.show(block=False)
            print(self.object.materials_name)
        if figure_type == 'materials' and len(self.object.materials_name) == 1:
            print(self.object.materials_name)
        if figure_type == 'Q':
            self.figure_Q = plt.figure()
            self.ax_Q = self.figure_Q.add_subplot(111)
            temp = np.array(self.object.Q)
            vmax = 1
            vmin = 0
            extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
            self.im_Q = self.ax_Q.imshow(np.transpose(temp), vmax=vmax,
                                         vmin=vmin, cmap='inferno',
                                         extent=extent, origin='lower',
                                         interpolation='hamming')
            cbar_kw = {}
            cbar = self.ax_Q.figure.colorbar(self.im_Q, ax=self.ax_Q,
                                             **cbar_kw)
            self.ax_Q.set_title('Q (W/m²)')
            self.ax_Q.set_xlabel('x axis (m)')
            self.ax_Q.set_ylabel('y axis (m)')
            plt.show(block=False)
        if figure_type == 'Q0':
            self.figure_Q0 = plt.figure()
            self.ax_Q0 = self.figure_Q0.add_subplot(111)
            temp = np.array(self.object.Q0)
            vmax = 1
            vmin = 0
            extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
            self.im_Q0 = self.ax_Q0.imshow(np.transpose(temp), vmax=vmax,
                                           vmin=vmin, cmap='inferno',
                                           extent=extent,
                                           origin='lower',
                                           interpolation='hamming')
            cbar_kw = {}
            cbar = self.ax_Q0.figure.colorbar(self.im_Q0, ax=self.ax_Q0,
                                              **cbar_kw)
            self.ax_Q0.set_title('Q0 (W/m²)')
            self.ax_Q0.set_xlabel('x axis (m)')
            self.ax_Q0.set_ylabel('y axis (m)')
            plt.show(block=False)

    def activate(self, initial_point, final_point, shape='square'):
        """Activation of the material.

        Activates a given piece of material. If `shape` is `'square'`, then the
        `initial_point` is the tuple (x,y) of the bottom left point and the
        `final_point` is the tuple (x,y) of the top right point. If the shape
        is `'circle'`, the `initial_point` is the tuple (x,y) of the center of
        the circle and `final_point` is its radius.

        """
        # check the validity of inputs
        if isinstance(shape, str):
            if shape == 'square':
                value = isinstance(initial_point, tuple)
                if value and isinstance(final_point, tuple):
                    condition = len(initial_point) == 2
                    condition = condition and len(final_point) == 2
                else:
                    condition = False
            elif shape == 'circle':
                value = isinstance(final_point, int)
                value = value or isinstance(final_point, float)
                value = value and isinstance(initial_point, tuple)
                if value:
                    condition = len(initial_point) == 2
                else:
                    condition = False
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.object.activate(initial_point=initial_point,
                             final_point=final_point, shape=shape)
        if self.draw:
            for drawing in self.draw:
                if drawing == 'temperature':
                    temp = []
                    for i in range(self.object.size[0]):
                        temp.append([])
                        for j in range(self.object.size[1]):
                            temp[-1].append(self.object.temperature[i][j][0])
                    self.im.set_array(np.transpose(temp))
                    if not self.draw_scale:
                        vmax = max(max(temp, key=max))
                        vmin = min(min(temp, key=min))
                        self.im.set_clim(vmin=vmin)
                        self.im.set_clim(vmax=vmax)
                    self.figure.canvas.draw()
                if drawing == 'state':
                    self.im_state.set_array(np.transpose(self.object.state))
                    self.figure_state.canvas.draw()

    def deactivate(self, initial_point, final_point, shape='square'):
        """Deactivation of the material.

        Deactivates a given piece of material. If `shape` is `'square'`, then
        the `initial_point` is the tuple (x,y) of the bottom left point and the
        `final_point` is the tuple (x,y) of the top right point. If the shape
        is `'circle'`, the `initial_point` is the tuple (x,y) of the center of
        the circle and `final_point` is its radius.

        """
        # check the validity of inputs
        if isinstance(shape, str):
            if shape == 'square':
                value = isinstance(initial_point, tuple)
                if value and isinstance(final_point, tuple):
                    condition = len(initial_point) == 2
                    condition = condition and len(final_point) == 2
                else:
                    condition = False
            elif shape == 'circle':
                value = isinstance(final_point, int)
                value = value or isinstance(final_point, float)
                value = value and isinstance(initial_point, tuple)
                if value:
                    condition = len(initial_point) == 2
                else:
                    condition = False
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.object.deactivate(initial_point=initial_point,
                               final_point=final_point, shape=shape)
        if self.draw:
            for drawing in self.draw:
                if drawing == 'temperature':
                    temp = []
                    for i in range(self.object.size[0]):
                        temp.append([])
                        for j in range(self.object.size[1]):
                            temp[-1].append(self.object.temperature[i][j][0])
                    self.im.set_array(np.transpose(temp))
                    if not self.draw_scale:
                        vmax = max(max(temp, key=max))
                        vmin = min(min(temp, key=min))
                        self.im.set_clim(vmin=vmin)
                        self.im.set_clim(vmax=vmax)
                    self.figure.canvas.draw()
                if drawing == 'state':
                    self.im_state.set_array(np.transpose(self.object.state))
                    self.figure_state.canvas.draw()

    def change_boundaries(self, boundaries):
        """Boundary change.

        Changes the `boundaries` variable.

        """
        # check the validity of inputs
        if isinstance(boundaries, tuple):
            if len(boundaries) == 4:
                condition = True
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.object.boundaries = boundaries

    def change_material(self, shape, material, initial_point, length,
                        state=False):
        """Material change.

        Changes the material of a given piece of the background material. If
        `shape` is `'square'`, then the initial_point is the tuple (x,y) of the
        bottom left point and the `length` is the tuple (x,y) of the length. If
        the shape is `'circle'`, the `initial_point` is the tuple (x,y) of the
        center of the circle and `length` is its radius.

        """
        # check the validity of inputs
        if isinstance(shape, str):
            if shape == 'square':
                value = isinstance(initial_point, tuple)
                if value and isinstance(length, tuple):
                    condition = len(initial_point) == 2
                    condition = condition and len(length) == 2
                else:
                    condition = False
            elif shape == 'circle':
                value = isinstance(length, int)
                value = value or isinstance(length, float)
                value = value and isinstance(initial_point, tuple)
                if value:
                    condition = len(initial_point) == 2
                else:
                    condition = False
            else:
                condition = False
        else:
            condition = False
        condition = condition and isinstance(state, bool)
        if not condition:
            raise ValueError

        if shape == 'square':
            self.object.square(material=material,
                               initial_point=initial_point, length=length,
                               state=state, materials_path=self.materials_path)
        if shape == 'circle':
            self.object.circle(material=material,
                               initial_point=initial_point, radius=length,
                               state=state, materials_path=self.materials_path)
        try:
            plt.close(self.figure_materials)
        except:
            pass

        if self.draw:
            if 'materials' in self.draw:
                self.figure_materials = plt.figure()
                self.ax_materials = self.figure_materials.add_subplot(111)
                vmax = len(self.object.materials)-1
                vmin = 0
                cmap = plt.get_cmap("PiYG", vmax+1)
                extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
                material_id = np.array(self.object.materials_index)
                value = np.transpose(material_id)
                self.im_materials = self.ax_materials.imshow(value,
                                                             vmax=vmax,
                                                             vmin=vmin,
                                                             cmap=cmap,
                                                             extent=extent,
                                                             origin='lower')
                cbar_kw = {}
                cbarlabel = ""
                materials_name_list = copy.deepcopy(self.object.materials_name)
                materials_name_list.reverse()
                qrates = np.array(materials_name_list)
                value_1 = np.linspace(0, len(self.object.materials)-1,
                                      len(self.object.materials))
                value_2 = len(self.object.materials)-1
                norm = matplotlib.colors.BoundaryNorm(value_1, value_2)
                func = lambda x, pos: qrates[::-1][norm(x)]
                fmt = matplotlib.ticker.FuncFormatter(func)
                value = np.arange(0, len(self.object.materials)+1)
                cbar_kw = dict(ticks=value, format=fmt)
                cba_m = self.ax_materials.figure.colorbar(self.im_materials,
                                                          ax=self.ax_materials,
                                                          **cbar_kw)
                cba_m.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
                self.ax_materials.set_title('Materials')
                self.ax_materials.set_xlabel('x axis (m)')
                self.ax_materials.set_ylabel('y axis (m)')
                plt.show(block=False)

    def change_power(self, shape, power_type, initial_point, final_point,
                     power):
        """Power change.

        Changes the power matrix of the thermal object. If `shape` is
        `'square'`, then the `initial_point` is the tuple (x,y) of the bottom
        left point and the `final_point` is the tuple (x,y) of the top right
        point. If the `shape` is `'circle'`, the `initial_point` is the tuple
        (x,y) of the center of the circle and `final_point` is its radius.
        `power` is the value of the power to add, and `power_type` is the type
        of power to be introduced, which has the value `'Q'` if it is
        temperature dependent and `'Q0'` if it is temperature independent.

        """
        # check the validity of inputs
        if isinstance(shape, str):
            if shape == 'square':
                value = isinstance(initial_point, tuple)
                if value and isinstance(final_point, tuple):
                    cond1 = len(initial_point) == 2
                    cond1 = cond1 and len(final_point) == 2
                else:
                    cond1 = False
            elif shape == 'circle':
                value = isinstance(final_point, int)
                value = value or isinstance(final_point, float)
                value = value and isinstance(initial_point, tuple)
                if value:
                    cond1 = len(initial_point) == 2
                else:
                    cond1 = False
            else:
                cond1 = False
        else:
            cond1 = False
        cond2 = isinstance(power, int) or isinstance(power, float)
        if isinstance(power_type, str):
            if power_type == 'Q' or power_type == 'Q0':
                cond3 = True
            else:
                cond3 = False
        else:
            cond3 = False
        if not cond1 and cond2 and cond3:
            raise ValueError

        if shape == 'square':
            self.object.power_add(initial_point, final_point, power,
                                  shape=shape, power_type=power_type)
        if shape == 'circle':
            self.object.power_add(initial_point, final_point, power,
                                  shape=shape, power_type=power_type)
        if self.draw:
            if 'Q' in self.draw and power_type == 'Q':
                self.im_Q.set_array(np.transpose(self.object.Q))
                vmax = max(max(self.object.Q, key=max))
                vmin = min(min(self.object.Q, key=min))
                self.im_Q.set_clim(vmin=vmin)
                self.im_Q.set_clim(vmax=vmax)
                self.figure_Q.canvas.draw()
            if 'Q0' in self.draw and power_type == 'Q0':
                self.im_Q0.set_array(np.transpose(self.object.Q0))
                vmax = max(max(self.object.Q0, key=max))
                vmin = min(min(self.object.Q0, key=min))
                self.im_Q0.set_clim(vmin=vmin)
                self.im_Q0.set_clim(vmax=vmax)
                self.figure_Q0.canvas.draw()

    def compute(self, time_interval, write_interval, solver='explicit_general',
                verbose=True):
        """Compute the thermal process.

        Computes the system for `time_interval`, and writes into the
        `file_name` file every `write_interval` time steps. Two different
        solvers can be used: `'explicit_general'` and `'explicit_k(x)'`. If
        verbose = True, then the progress of the computation is shown.

        """
        # check the validity of inputs
        cond1 = isinstance(time_interval, float)
        cond1 = cond1 or isinstance(time_interval, int)
        cond2 = isinstance(write_interval, int)
        all_solvers = ['explicit_general', 'explicit_k(x)']
        cond3 = isinstance(solver, str) and solver in all_solvers
        cond4 = isinstance(verbose, bool)
        condition = cond1 and cond2 and cond3 and cond4
        if not condition:
            raise ValueError

        # number of time steps for the given timeInterval
        nt = int(time_interval / self.object.dt)

        # number of time steps counting from the last writing process
        nw = 0

        # computes
        for k in range(nt):

            # updates the time_passed
            self.time_passed = self.time_passed + self.object.dt

            # defines the material properties accoring to the state list
            for i in range(self.object.size[0]):
                for j in range(self.object.size[1]):
                    if self.object.state[i][j] is True:
                        ix = self.object.materials_index[i][j]
                        self.object.rho[i][j] = self.object.materials[ix].rhoa(
                            self.object.temperature[i][j][0])
                        self.object.Cp[i][j] = self.object.materials[ix].cpa(
                            self.object.temperature[i][j][0])
                        self.object.k[i][j] = self.object.materials[ix].ka(
                            self.object.temperature[i][j][0])
                    if self.object.state[i][j] is False:
                        ix = self.object.materials_index[i][j]
                        self.object.rho[i][j] = self.object.materials[ix].rho0(
                            self.object.temperature[i][j][0])
                        self.object.Cp[i][j] = self.object.materials[ix].cp0(
                            self.object.temperature[i][j][0])
                        self.object.k[i][j] = self.object.materials[ix].k0(
                            self.object.temperature[i][j][0])

            # SOLVERS
            # explicit k constant
            if solver == 'explicit_general':
                temp = []
                for i in range(self.object.size[0]):
                    temp.append([])
                    for j in range(self.object.size[1]):
                        temp[-1].append(self.object.temperature[i][j][0])
                value = solvers.explicit_general(self.object)
                self.object.temperature, self.object.lheat = value
                temp = []
                for i in range(self.object.size[0]):
                    temp.append([])
                    for j in range(self.object.size[1]):
                        temp[-1].append(self.object.temperature[i][j][0])
            # explicit k constant
            if solver == 'explicit_k(x)':
                temp = []
                for i in range(self.object.size[0]):
                    temp.append([])
                    for j in range(self.object.size[1]):
                        temp[-1].append(self.object.temperature[i][j][0])
                value = solvers.explicit_k(self.object)
                self.object.temperature, self.object.lheat = value
                temp = []
                for i in range(self.object.size[0]):
                    temp.append([])
                    for j in range(self.object.size[1]):
                        temp[-1].append(self.object.temperature[i][j][0])

            nw = nw + 1

            if self.object.file_name:
                if nw + 1 == write_interval or k == 0 or k == nt - 1:
                    line = '%f' % self.time_passed
                    for i in range(self.object.size[0]):
                        for j in range(self.object.size[1]):
                            new_line = ',%f' % self.object.temperature[i][j][1]
                            line = line + new_line
                    f = open(self.object.file_name, 'a')
                    f.write(line+'\n')
                    f.close()
            if self.draw:
                for drawing in self.draw:
                    if drawing == 'temperature':
                        if nw + 1 == write_interval or k == 0 or k == nt - 1:
                            temp = []
                            for i in range(self.object.size[0]):
                                temp.append([])
                                for j in range(self.object.size[1]):
                                    value = self.object.temperature[i][j][0]
                                    temp[-1].append(value)
                            try:
                                self.im.set_array(np.transpose(temp))
                                if not self.draw_scale:
                                    vmax = max(max(temp, key=max))
                                    vmin = min(min(temp, key=min))
                                    self.im.set_clim(vmin=vmin)
                                    self.im.set_clim(vmax=vmax)
                                self.figure.canvas.draw()
                            except:
                                pass

            if nw == write_interval:
                nw = 0
                if verbose:
                    print('pogress:', int(100*k/nt), '%', end="\r")
        if verbose:
            print('Finished simulation')

Single_object class.

This class solves numerically the two-dimensional heat conduction equation.

#   SingleObject2D( self, amb_temperature, material='Cu', dx=0.01, dy=0.01, dt=0.1, size=(10, 10), file_name=None, boundaries=(0, 0, 0, 0), Q=[], Q0=[], initial_state=False, materials_path=False, draw=['temperature', 'materials'], draw_scale=None )
View Source
    def __init__(self, amb_temperature, material='Cu', dx=0.01, dy=0.01,
                 dt=0.1, size=(10, 10), file_name=None,
                 boundaries=(0, 0, 0, 0), Q=[], Q0=[], initial_state=False,
                 materials_path=False,
                 draw=['temperature', 'materials'], draw_scale=None):
        """Object initialization.

        `amb_temperature` is the ambient temperature of the whole system.
        `materials` is the background material present in `material_path`.
        `dx`, `dy` are the space steps along the x- and y-axis, respectively.
        `dt` is the time step. `file_name` is the file name where the
        temperature is saved. `boundaries` is a list of four entries that
        define the boundary condition for temperature (left, right, bottom,
        top). If 0 the boundary condition is insulation. `initial_state` is the
        initial state of the materials. True if there are an applied field and
        False if them field is absent. `materials_path` is absolute path of the
        materials database. If false, then the materials database is the
        standard heatrapy database. `draw` is a list of strings representing
        the online plots. In this version live plotting can be performed for
        `temperature`, `materials`, `state`, `Q` and `Q0`. If the list is
        empty, then no drawing is performed. `draw_scale` is a list of two
        values, representing the minimum and maximum temperature to be drawn.
        If None, there are no limits. `Q` is a list of fixed heat source
        coefficient and `Q0` is a list of temperature dependent heat source
        coefficient.

        """
        boundaries = tuple(boundaries)
        cond01 = isinstance(amb_temperature, float)
        cond01 = cond01 or isinstance(amb_temperature, int)
        cond02 = isinstance(material, str)
        cond05 = isinstance(dx, int) or isinstance(dx, float)
        cond06 = isinstance(dy, int) or isinstance(dy, float)
        cond07 = isinstance(dt, int) or isinstance(dt, float)
        cond08 = isinstance(file_name, str)
        cond08 = cond08 or (file_name is None)
        cond09 = isinstance(boundaries, tuple)
        cond10 = isinstance(initial_state, bool)
        cond11 = isinstance(Q, list)
        cond12 = isinstance(Q0, list)
        cond13 = isinstance(draw, list)
        cond14 = isinstance(draw_scale, list) or isinstance(draw_scale, tuple)
        cond14 = cond14 or draw_scale is None
        condition = cond01 and cond02 and cond05
        condition = condition and cond06 and cond07 and cond08 and cond09
        condition = condition and cond10 and cond11 and cond12 and cond13
        condition = condition and cond14
        if not condition:
            raise ValueError

        self.materials_path = materials_path
        self.time_passed = 0.
        self.size = size
        self.dt = dt
        self.dx = dx
        self.dy = dy
        self.object = Object(amb_temperature, material=material, dx=dx, dy=dy,
                             dt=dt, size=size, file_name=file_name,
                             boundaries=boundaries, Q=[], Q0=[],
                             initial_state=initial_state,
                             materials_path=materials_path)

        # Initializes plotting
        self.draw = draw
        self.draw_scale = draw_scale
        if self.draw:
            cmap = matplotlib.cm.RdBu
            name = 'my_cmap_r'
            reverse = []
            k = []
            for key in cmap._segmentdata:
                k.append(key)
                channel = cmap._segmentdata[key]
                data = []
                for t in channel:
                    data.append((1-t[0], t[2], t[1]))
                reverse.append(sorted(data))
            linear = dict(zip(k, reverse))
            my_cmap_r = matplotlib.colors.LinearSegmentedColormap(name, linear)
            cmap_r = my_cmap_r
            for drawing in self.draw:
                if drawing == 'temperature':
                    self.figure = plt.figure()
                    self.ax = self.figure.add_subplot(111)
                    temp = []
                    for i in range(self.object.size[0]):
                        temp.append([])
                        for j in range(self.object.size[1]):
                            temp[-1].append(self.object.temperature[i][j][0])
                    if not self.draw_scale:
                        vmax = max(max(temp, key=max))
                        vmin = min(min(temp, key=min))
                        temp = np.array(temp)
                        extent = [0, size[0]*dx, 0, size[1]*dy]
                        self.im = self.ax.imshow(np.transpose(temp), vmax=vmax,
                                                 vmin=vmin, cmap=cmap_r,
                                                 extent=extent, origin='lower',
                                                 interpolation='hamming')
                    else:
                        temp = np.array(temp)
                        extent = [0, size[0]*dx, 0, size[1]*dy]
                        self.im = self.ax.imshow(np.transpose(temp),
                                                 vmax=self.draw_scale[0],
                                                 vmin=self.draw_scale[1],
                                                 cmap=cmap_r, extent=extent,
                                                 origin='lower',
                                                 interpolation='hamming')
                    cbar_kw = {}
                    cbar = self.ax.figure.colorbar(self.im, ax=self.ax,
                                                   **cbar_kw)
                    self.ax.set_title('Temperature (K)')
                    self.ax.set_xlabel('x axis (m)')
                    self.ax.set_ylabel('y axis (m)')
                    plt.show(block=False)
                if drawing == 'state':
                    self.figure_state = plt.figure()
                    self.ax_state = self.figure_state.add_subplot(111)
                    vmax = 1
                    vmin = 0
                    state = np.array(self.object.state)
                    cmap = plt.get_cmap("gray", 2)
                    extent = [0, size[0]*dx, 0, size[1]*dy]
                    self.im_state = self.ax_state.imshow(np.transpose(state),
                                                         vmax=1.5, vmin=-0.5,
                                                         cmap=cmap,
                                                         extent=extent,
                                                         origin='lower')
                    cbar_kw = {}
                    cbarlabel = ""
                    qrates = np.array(['active', 'inactive'])
                    value = np.linspace(0, 1, 2)
                    norm = matplotlib.colors.BoundaryNorm(value, 1)
                    func = lambda x, pos: qrates[::-1][norm(x)]
                    fmt = matplotlib.ticker.FuncFormatter(func)
                    cbar_kw = dict(ticks=np.arange(-3, 4), format=fmt)
                    cbar_stat = self.ax_state.figure.colorbar(self.im_state,
                                                              ax=self.ax_state,
                                                              **cbar_kw)
                    cbar_stat.ax.set_ylabel(cbarlabel, rotation=-90,
                                            va="bottom")
                    self.ax_state.set_title('State')
                    self.ax_state.set_xlabel('x axis (m)')
                    self.ax_state.set_ylabel('y axis (m)')
                    plt.show(block=False)
                value = len(self.object.materials_name) > 1
                if drawing == 'materials' and value:
                    self.figure_materials = plt.figure()
                    self.ax_materials = self.figure_materials.add_subplot(111)
                    vmax = len(self.object.materials)-1
                    vmin = 0
                    material_id = np.array(self.object.materials_index)
                    cmap = plt.get_cmap("gray", vmax)
                    extent = [0, size[0]*dx, 0, size[1]*dy]
                    origin = 'lower'
                    value = np.transpose(material_id)
                    self.im_materials = self.ax_materials.imshow(value,
                                                                 vmax=vmax,
                                                                 vmin=vmin,
                                                                 cmap=cmap,
                                                                 extent=extent,
                                                                 origin=origin)
                    cbar_kw = {}
                    cbarlabel = ""
                    qrates = np.array(self.object.materials_name)
                    value_1 = np.linspace(0, 1, len(self.object.materials))
                    value_2 = len(self.object.materials)-1
                    norm = matplotlib.colors.BoundaryNorm(value_1, value_2)
                    func = lambda x, pos: qrates[::-1][norm(x)]
                    fmt = matplotlib.ticker.FuncFormatter(func)
                    cbar_kw = dict(ticks=np.arange(-3, 4), format=fmt)
                    value_1 = self.im_materials
                    value_2 = self.ax_materials
                    cbar_m = self.ax_materials.figure.colorbar(value_1,
                                                               ax=value_2,
                                                               **cbar_kw)
                    cbar_m.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
                    self.ax_materials.set_title('Materials')
                    self.ax_materials.set_xlabel('x axis (m)')
                    self.ax_materials.set_ylabel('y axis (m)')
                    plt.show(block=False)
                if drawing == 'Q':
                    self.figure_Q = plt.figure()
                    self.ax_Q = self.figure_Q.add_subplot(111)
                    temp = np.array(self.object.Q)
                    vmax = 1
                    vmin = 0
                    extent = [0, size[0]*dx, 0, size[1]*dy]
                    self.im_Q = self.ax_Q.imshow(np.transpose(temp), vmax=vmax,
                                                 vmin=vmin, cmap='inferno',
                                                 extent=extent, origin='lower',
                                                 interpolation='hamming')
                    cbar_kw = {}
                    cbar = self.ax_Q.figure.colorbar(self.im_Q, ax=self.ax_Q,
                                                     **cbar_kw)
                    self.ax_Q.set_title('Q (W/m²)')
                    self.ax_Q.set_xlabel('x axis (m)')
                    self.ax_Q.set_ylabel('y axis (m)')
                    plt.show(block=False)
                if drawing == 'Q0':
                    self.figure_Q0 = plt.figure()
                    self.ax_Q0 = self.figure_Q0.add_subplot(111)
                    temp = np.array(self.object.Q0)
                    vmax = 1
                    vmin = 0
                    extent = [0, size[0]*dx, 0, size[1]*dy]
                    self.im_Q0 = self.ax_Q0.imshow(np.transpose(temp),
                                                   vmax=vmax, vmin=vmin,
                                                   cmap='inferno',
                                                   extent=extent,
                                                   origin='lower',
                                                   interpolation='hamming')
                    cbar_kw = {}
                    cbar = self.ax_Q0.figure.colorbar(self.im_Q0,
                                                      ax=self.ax_Q0,
                                                      **cbar_kw)
                    self.ax_Q0.set_title('Q0 (W/m²)')
                    self.ax_Q0.set_xlabel('x axis (m)')
                    self.ax_Q0.set_ylabel('y axis (m)')
                    plt.show(block=False)

Object initialization.

amb_temperature is the ambient temperature of the whole system. materials is the background material present in material_path. dx, dy are the space steps along the x- and y-axis, respectively. dt is the time step. file_name is the file name where the temperature is saved. boundaries is a list of four entries that define the boundary condition for temperature (left, right, bottom, top). If 0 the boundary condition is insulation. initial_state is the initial state of the materials. True if there are an applied field and False if them field is absent. materials_path is absolute path of the materials database. If false, then the materials database is the standard heatrapy database. draw is a list of strings representing the online plots. In this version live plotting can be performed for temperature, materials, state, Q and Q0. If the list is empty, then no drawing is performed. draw_scale is a list of two values, representing the minimum and maximum temperature to be drawn. If None, there are no limits. Q is a list of fixed heat source coefficient and Q0 is a list of temperature dependent heat source coefficient.

#   def show_figure(self, figure_type):
View Source
    def show_figure(self, figure_type):
        """Plotting.

        Initializes a specific plotting. `figure_type` is a string identifying
        the plotting. In this version live plotting can be performed for
        `temperature`, `materials`, `state`, `Q` and `Q0`.

        """
        # check the validity of inputs
        condition = isinstance(figure_type, str)
        if not condition:
            raise ValueError

        if figure_type not in self.draw:
            self.draw.append(figure_type)
        if figure_type == 'temperature':
            self.figure = plt.figure()
            self.ax = self.figure.add_subplot(111)
            temp = []
            for i in range(self.object.size[0]):
                temp.append([])
                for j in range(self.object.size[1]):
                    temp[-1].append(self.object.temperature[i][j][0])
            if not self.draw_scale:
                vmax = max(max(temp, key=max))
                vmin = min(min(temp, key=min))
                temp = np.array(temp)
                extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
                self.im = self.ax.imshow(np.transpose(temp), vmax=vmax,
                                         vmin=vmin, cmap='jet', extent=extent,
                                         origin='lower',
                                         interpolation='hamming')
            else:
                temp = np.array(temp)
                extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
                self.im = self.ax.imshow(np.transpose(temp),
                                         vmax=self.draw_scale[0],
                                         vmin=self.draw_scale[1],
                                         cmap='jet', extent=extent,
                                         origin='lower',
                                         interpolation='hamming')
            cbar_kw = {}
            cbarlabel = "temperature (K)"
            cbar = self.ax.figure.colorbar(self.im, ax=self.ax, **cbar_kw)
            cbar.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
            self.ax.set_title('Temperature')
            self.ax.set_xlabel('x axis (m)')
            self.ax.set_ylabel('y axis (m)')
            plt.show(block=False)
        if figure_type == 'state':
            self.figure_state = plt.figure()
            self.ax_state = self.figure_state.add_subplot(111)
            vmax = 1
            vmin = 0
            state = np.array(self.object.state)
            extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
            self.im_state = self.ax_state.imshow(np.transpose(state), vmax=1.5,
                                                 vmin=-0.5,
                                                 cmap=plt.get_cmap("gray", 2),
                                                 extent=extent, origin='lower')
            cbar_kw = {}
            cbarlabel = ""  # "state"
            qrates = np.array(['active', 'inactive'])
            norm = matplotlib.colors.BoundaryNorm(np.linspace(0, 1, 2), 1)
            func = lambda x, pos: qrates[::-1][norm(x)]
            fmt = matplotlib.ticker.FuncFormatter(func)
            cbar_kw = dict(ticks=np.arange(-3, 4), format=fmt)
            cbar_state = self.ax_state.figure.colorbar(self.im_state,
                                                       ax=self.ax_state,
                                                       **cbar_kw)
            cbar_state.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
            self.ax_state.set_title('State')
            self.ax_state.set_xlabel('x axis (m)')
            self.ax_state.set_ylabel('y axis (m)')
            plt.show(block=False)
        if figure_type == 'materials' and len(self.object.materials_name) > 1:
            self.figure_materials = plt.figure()
            self.ax_materials = self.figure_materials.add_subplot(111)
            vmax = len(self.object.materials)-1
            vmin = 0
            material_id = np.array(self.object.materials_index)
            cmap = plt.get_cmap("PiYG", vmax+1)
            extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
            value = np.transpose(material_id)
            self.im_materials = self.ax_materials.imshow(value,
                                                         vmax=vmax,
                                                         vmin=vmin,
                                                         cmap=cmap,
                                                         extent=extent,
                                                         origin='lower')
            cbar_kw = {}
            cbarlabel = ""
            materials_name_list = copy.deepcopy(self.object.materials_name)
            materials_name_list.reverse()
            qrates = np.array(materials_name_list)
            value = np.linspace(0, len(self.object.materials) - 1,
                                len(self.object.materials))
            norm = matplotlib.colors.BoundaryNorm(value,
                                                  len(self.object.materials)-1)
            func = lambda x, pos: qrates[::-1][norm(x)]
            fmt = matplotlib.ticker.FuncFormatter(func)
            cbar_kw = dict(ticks=np.arange(0, len(self.object.materials)+1),
                           format=fmt)
            cbar_m = self.ax_materials.figure.colorbar(self.im_materials,
                                                       ax=self.ax_materials,
                                                       **cbar_kw)
            cbar_m.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
            self.ax_materials.set_title('Materials')
            self.ax_materials.set_xlabel('x axis (m)')
            self.ax_materials.set_ylabel('y axis (m)')
            plt.show(block=False)
            print(self.object.materials_name)
        if figure_type == 'materials' and len(self.object.materials_name) == 1:
            print(self.object.materials_name)
        if figure_type == 'Q':
            self.figure_Q = plt.figure()
            self.ax_Q = self.figure_Q.add_subplot(111)
            temp = np.array(self.object.Q)
            vmax = 1
            vmin = 0
            extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
            self.im_Q = self.ax_Q.imshow(np.transpose(temp), vmax=vmax,
                                         vmin=vmin, cmap='inferno',
                                         extent=extent, origin='lower',
                                         interpolation='hamming')
            cbar_kw = {}
            cbar = self.ax_Q.figure.colorbar(self.im_Q, ax=self.ax_Q,
                                             **cbar_kw)
            self.ax_Q.set_title('Q (W/m²)')
            self.ax_Q.set_xlabel('x axis (m)')
            self.ax_Q.set_ylabel('y axis (m)')
            plt.show(block=False)
        if figure_type == 'Q0':
            self.figure_Q0 = plt.figure()
            self.ax_Q0 = self.figure_Q0.add_subplot(111)
            temp = np.array(self.object.Q0)
            vmax = 1
            vmin = 0
            extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
            self.im_Q0 = self.ax_Q0.imshow(np.transpose(temp), vmax=vmax,
                                           vmin=vmin, cmap='inferno',
                                           extent=extent,
                                           origin='lower',
                                           interpolation='hamming')
            cbar_kw = {}
            cbar = self.ax_Q0.figure.colorbar(self.im_Q0, ax=self.ax_Q0,
                                              **cbar_kw)
            self.ax_Q0.set_title('Q0 (W/m²)')
            self.ax_Q0.set_xlabel('x axis (m)')
            self.ax_Q0.set_ylabel('y axis (m)')
            plt.show(block=False)

Plotting.

Initializes a specific plotting. figure_type is a string identifying the plotting. In this version live plotting can be performed for temperature, materials, state, Q and Q0.

#   def activate(self, initial_point, final_point, shape='square'):
View Source
    def activate(self, initial_point, final_point, shape='square'):
        """Activation of the material.

        Activates a given piece of material. If `shape` is `'square'`, then the
        `initial_point` is the tuple (x,y) of the bottom left point and the
        `final_point` is the tuple (x,y) of the top right point. If the shape
        is `'circle'`, the `initial_point` is the tuple (x,y) of the center of
        the circle and `final_point` is its radius.

        """
        # check the validity of inputs
        if isinstance(shape, str):
            if shape == 'square':
                value = isinstance(initial_point, tuple)
                if value and isinstance(final_point, tuple):
                    condition = len(initial_point) == 2
                    condition = condition and len(final_point) == 2
                else:
                    condition = False
            elif shape == 'circle':
                value = isinstance(final_point, int)
                value = value or isinstance(final_point, float)
                value = value and isinstance(initial_point, tuple)
                if value:
                    condition = len(initial_point) == 2
                else:
                    condition = False
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.object.activate(initial_point=initial_point,
                             final_point=final_point, shape=shape)
        if self.draw:
            for drawing in self.draw:
                if drawing == 'temperature':
                    temp = []
                    for i in range(self.object.size[0]):
                        temp.append([])
                        for j in range(self.object.size[1]):
                            temp[-1].append(self.object.temperature[i][j][0])
                    self.im.set_array(np.transpose(temp))
                    if not self.draw_scale:
                        vmax = max(max(temp, key=max))
                        vmin = min(min(temp, key=min))
                        self.im.set_clim(vmin=vmin)
                        self.im.set_clim(vmax=vmax)
                    self.figure.canvas.draw()
                if drawing == 'state':
                    self.im_state.set_array(np.transpose(self.object.state))
                    self.figure_state.canvas.draw()

Activation of the material.

Activates a given piece of material. If shape is 'square', then the initial_point is the tuple (x,y) of the bottom left point and the final_point is the tuple (x,y) of the top right point. If the shape is 'circle', the initial_point is the tuple (x,y) of the center of the circle and final_point is its radius.

#   def deactivate(self, initial_point, final_point, shape='square'):
View Source
    def deactivate(self, initial_point, final_point, shape='square'):
        """Deactivation of the material.

        Deactivates a given piece of material. If `shape` is `'square'`, then
        the `initial_point` is the tuple (x,y) of the bottom left point and the
        `final_point` is the tuple (x,y) of the top right point. If the shape
        is `'circle'`, the `initial_point` is the tuple (x,y) of the center of
        the circle and `final_point` is its radius.

        """
        # check the validity of inputs
        if isinstance(shape, str):
            if shape == 'square':
                value = isinstance(initial_point, tuple)
                if value and isinstance(final_point, tuple):
                    condition = len(initial_point) == 2
                    condition = condition and len(final_point) == 2
                else:
                    condition = False
            elif shape == 'circle':
                value = isinstance(final_point, int)
                value = value or isinstance(final_point, float)
                value = value and isinstance(initial_point, tuple)
                if value:
                    condition = len(initial_point) == 2
                else:
                    condition = False
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.object.deactivate(initial_point=initial_point,
                               final_point=final_point, shape=shape)
        if self.draw:
            for drawing in self.draw:
                if drawing == 'temperature':
                    temp = []
                    for i in range(self.object.size[0]):
                        temp.append([])
                        for j in range(self.object.size[1]):
                            temp[-1].append(self.object.temperature[i][j][0])
                    self.im.set_array(np.transpose(temp))
                    if not self.draw_scale:
                        vmax = max(max(temp, key=max))
                        vmin = min(min(temp, key=min))
                        self.im.set_clim(vmin=vmin)
                        self.im.set_clim(vmax=vmax)
                    self.figure.canvas.draw()
                if drawing == 'state':
                    self.im_state.set_array(np.transpose(self.object.state))
                    self.figure_state.canvas.draw()

Deactivation of the material.

Deactivates a given piece of material. If shape is 'square', then the initial_point is the tuple (x,y) of the bottom left point and the final_point is the tuple (x,y) of the top right point. If the shape is 'circle', the initial_point is the tuple (x,y) of the center of the circle and final_point is its radius.

#   def change_boundaries(self, boundaries):
View Source
    def change_boundaries(self, boundaries):
        """Boundary change.

        Changes the `boundaries` variable.

        """
        # check the validity of inputs
        if isinstance(boundaries, tuple):
            if len(boundaries) == 4:
                condition = True
            else:
                condition = False
        else:
            condition = False
        if not condition:
            raise ValueError

        self.object.boundaries = boundaries

Boundary change.

Changes the boundaries variable.

#   def change_material(self, shape, material, initial_point, length, state=False):
View Source
    def change_material(self, shape, material, initial_point, length,
                        state=False):
        """Material change.

        Changes the material of a given piece of the background material. If
        `shape` is `'square'`, then the initial_point is the tuple (x,y) of the
        bottom left point and the `length` is the tuple (x,y) of the length. If
        the shape is `'circle'`, the `initial_point` is the tuple (x,y) of the
        center of the circle and `length` is its radius.

        """
        # check the validity of inputs
        if isinstance(shape, str):
            if shape == 'square':
                value = isinstance(initial_point, tuple)
                if value and isinstance(length, tuple):
                    condition = len(initial_point) == 2
                    condition = condition and len(length) == 2
                else:
                    condition = False
            elif shape == 'circle':
                value = isinstance(length, int)
                value = value or isinstance(length, float)
                value = value and isinstance(initial_point, tuple)
                if value:
                    condition = len(initial_point) == 2
                else:
                    condition = False
            else:
                condition = False
        else:
            condition = False
        condition = condition and isinstance(state, bool)
        if not condition:
            raise ValueError

        if shape == 'square':
            self.object.square(material=material,
                               initial_point=initial_point, length=length,
                               state=state, materials_path=self.materials_path)
        if shape == 'circle':
            self.object.circle(material=material,
                               initial_point=initial_point, radius=length,
                               state=state, materials_path=self.materials_path)
        try:
            plt.close(self.figure_materials)
        except:
            pass

        if self.draw:
            if 'materials' in self.draw:
                self.figure_materials = plt.figure()
                self.ax_materials = self.figure_materials.add_subplot(111)
                vmax = len(self.object.materials)-1
                vmin = 0
                cmap = plt.get_cmap("PiYG", vmax+1)
                extent = [0, self.size[0]*self.dx, 0, self.size[1]*self.dy]
                material_id = np.array(self.object.materials_index)
                value = np.transpose(material_id)
                self.im_materials = self.ax_materials.imshow(value,
                                                             vmax=vmax,
                                                             vmin=vmin,
                                                             cmap=cmap,
                                                             extent=extent,
                                                             origin='lower')
                cbar_kw = {}
                cbarlabel = ""
                materials_name_list = copy.deepcopy(self.object.materials_name)
                materials_name_list.reverse()
                qrates = np.array(materials_name_list)
                value_1 = np.linspace(0, len(self.object.materials)-1,
                                      len(self.object.materials))
                value_2 = len(self.object.materials)-1
                norm = matplotlib.colors.BoundaryNorm(value_1, value_2)
                func = lambda x, pos: qrates[::-1][norm(x)]
                fmt = matplotlib.ticker.FuncFormatter(func)
                value = np.arange(0, len(self.object.materials)+1)
                cbar_kw = dict(ticks=value, format=fmt)
                cba_m = self.ax_materials.figure.colorbar(self.im_materials,
                                                          ax=self.ax_materials,
                                                          **cbar_kw)
                cba_m.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom")
                self.ax_materials.set_title('Materials')
                self.ax_materials.set_xlabel('x axis (m)')
                self.ax_materials.set_ylabel('y axis (m)')
                plt.show(block=False)

Material change.

Changes the material of a given piece of the background material. If shape is 'square', then the initial_point is the tuple (x,y) of the bottom left point and the length is the tuple (x,y) of the length. If the shape is 'circle', the initial_point is the tuple (x,y) of the center of the circle and length is its radius.

#   def change_power(self, shape, power_type, initial_point, final_point, power):
View Source
    def change_power(self, shape, power_type, initial_point, final_point,
                     power):
        """Power change.

        Changes the power matrix of the thermal object. If `shape` is
        `'square'`, then the `initial_point` is the tuple (x,y) of the bottom
        left point and the `final_point` is the tuple (x,y) of the top right
        point. If the `shape` is `'circle'`, the `initial_point` is the tuple
        (x,y) of the center of the circle and `final_point` is its radius.
        `power` is the value of the power to add, and `power_type` is the type
        of power to be introduced, which has the value `'Q'` if it is
        temperature dependent and `'Q0'` if it is temperature independent.

        """
        # check the validity of inputs
        if isinstance(shape, str):
            if shape == 'square':
                value = isinstance(initial_point, tuple)
                if value and isinstance(final_point, tuple):
                    cond1 = len(initial_point) == 2
                    cond1 = cond1 and len(final_point) == 2
                else:
                    cond1 = False
            elif shape == 'circle':
                value = isinstance(final_point, int)
                value = value or isinstance(final_point, float)
                value = value and isinstance(initial_point, tuple)
                if value:
                    cond1 = len(initial_point) == 2
                else:
                    cond1 = False
            else:
                cond1 = False
        else:
            cond1 = False
        cond2 = isinstance(power, int) or isinstance(power, float)
        if isinstance(power_type, str):
            if power_type == 'Q' or power_type == 'Q0':
                cond3 = True
            else:
                cond3 = False
        else:
            cond3 = False
        if not cond1 and cond2 and cond3:
            raise ValueError

        if shape == 'square':
            self.object.power_add(initial_point, final_point, power,
                                  shape=shape, power_type=power_type)
        if shape == 'circle':
            self.object.power_add(initial_point, final_point, power,
                                  shape=shape, power_type=power_type)
        if self.draw:
            if 'Q' in self.draw and power_type == 'Q':
                self.im_Q.set_array(np.transpose(self.object.Q))
                vmax = max(max(self.object.Q, key=max))
                vmin = min(min(self.object.Q, key=min))
                self.im_Q.set_clim(vmin=vmin)
                self.im_Q.set_clim(vmax=vmax)
                self.figure_Q.canvas.draw()
            if 'Q0' in self.draw and power_type == 'Q0':
                self.im_Q0.set_array(np.transpose(self.object.Q0))
                vmax = max(max(self.object.Q0, key=max))
                vmin = min(min(self.object.Q0, key=min))
                self.im_Q0.set_clim(vmin=vmin)
                self.im_Q0.set_clim(vmax=vmax)
                self.figure_Q0.canvas.draw()

Power change.

Changes the power matrix of the thermal object. If shape is 'square', then the initial_point is the tuple (x,y) of the bottom left point and the final_point is the tuple (x,y) of the top right point. If the shape is 'circle', the initial_point is the tuple (x,y) of the center of the circle and final_point is its radius. power is the value of the power to add, and power_type is the type of power to be introduced, which has the value 'Q' if it is temperature dependent and 'Q0' if it is temperature independent.

#   def compute( self, time_interval, write_interval, solver='explicit_general', verbose=True ):
View Source
    def compute(self, time_interval, write_interval, solver='explicit_general',
                verbose=True):
        """Compute the thermal process.

        Computes the system for `time_interval`, and writes into the
        `file_name` file every `write_interval` time steps. Two different
        solvers can be used: `'explicit_general'` and `'explicit_k(x)'`. If
        verbose = True, then the progress of the computation is shown.

        """
        # check the validity of inputs
        cond1 = isinstance(time_interval, float)
        cond1 = cond1 or isinstance(time_interval, int)
        cond2 = isinstance(write_interval, int)
        all_solvers = ['explicit_general', 'explicit_k(x)']
        cond3 = isinstance(solver, str) and solver in all_solvers
        cond4 = isinstance(verbose, bool)
        condition = cond1 and cond2 and cond3 and cond4
        if not condition:
            raise ValueError

        # number of time steps for the given timeInterval
        nt = int(time_interval / self.object.dt)

        # number of time steps counting from the last writing process
        nw = 0

        # computes
        for k in range(nt):

            # updates the time_passed
            self.time_passed = self.time_passed + self.object.dt

            # defines the material properties accoring to the state list
            for i in range(self.object.size[0]):
                for j in range(self.object.size[1]):
                    if self.object.state[i][j] is True:
                        ix = self.object.materials_index[i][j]
                        self.object.rho[i][j] = self.object.materials[ix].rhoa(
                            self.object.temperature[i][j][0])
                        self.object.Cp[i][j] = self.object.materials[ix].cpa(
                            self.object.temperature[i][j][0])
                        self.object.k[i][j] = self.object.materials[ix].ka(
                            self.object.temperature[i][j][0])
                    if self.object.state[i][j] is False:
                        ix = self.object.materials_index[i][j]
                        self.object.rho[i][j] = self.object.materials[ix].rho0(
                            self.object.temperature[i][j][0])
                        self.object.Cp[i][j] = self.object.materials[ix].cp0(
                            self.object.temperature[i][j][0])
                        self.object.k[i][j] = self.object.materials[ix].k0(
                            self.object.temperature[i][j][0])

            # SOLVERS
            # explicit k constant
            if solver == 'explicit_general':
                temp = []
                for i in range(self.object.size[0]):
                    temp.append([])
                    for j in range(self.object.size[1]):
                        temp[-1].append(self.object.temperature[i][j][0])
                value = solvers.explicit_general(self.object)
                self.object.temperature, self.object.lheat = value
                temp = []
                for i in range(self.object.size[0]):
                    temp.append([])
                    for j in range(self.object.size[1]):
                        temp[-1].append(self.object.temperature[i][j][0])
            # explicit k constant
            if solver == 'explicit_k(x)':
                temp = []
                for i in range(self.object.size[0]):
                    temp.append([])
                    for j in range(self.object.size[1]):
                        temp[-1].append(self.object.temperature[i][j][0])
                value = solvers.explicit_k(self.object)
                self.object.temperature, self.object.lheat = value
                temp = []
                for i in range(self.object.size[0]):
                    temp.append([])
                    for j in range(self.object.size[1]):
                        temp[-1].append(self.object.temperature[i][j][0])

            nw = nw + 1

            if self.object.file_name:
                if nw + 1 == write_interval or k == 0 or k == nt - 1:
                    line = '%f' % self.time_passed
                    for i in range(self.object.size[0]):
                        for j in range(self.object.size[1]):
                            new_line = ',%f' % self.object.temperature[i][j][1]
                            line = line + new_line
                    f = open(self.object.file_name, 'a')
                    f.write(line+'\n')
                    f.close()
            if self.draw:
                for drawing in self.draw:
                    if drawing == 'temperature':
                        if nw + 1 == write_interval or k == 0 or k == nt - 1:
                            temp = []
                            for i in range(self.object.size[0]):
                                temp.append([])
                                for j in range(self.object.size[1]):
                                    value = self.object.temperature[i][j][0]
                                    temp[-1].append(value)
                            try:
                                self.im.set_array(np.transpose(temp))
                                if not self.draw_scale:
                                    vmax = max(max(temp, key=max))
                                    vmin = min(min(temp, key=min))
                                    self.im.set_clim(vmin=vmin)
                                    self.im.set_clim(vmax=vmax)
                                self.figure.canvas.draw()
                            except:
                                pass

            if nw == write_interval:
                nw = 0
                if verbose:
                    print('pogress:', int(100*k/nt), '%', end="\r")
        if verbose:
            print('Finished simulation')

Compute the thermal process.

Computes the system for time_interval, and writes into the file_name file every write_interval time steps. Two different solvers can be used: 'explicit_general' and 'explicit_k(x)'. If verbose = True, then the progress of the computation is shown.