Source code for casinotools.file_format.casino3.region

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
.. py:currentmodule:: casinotools.file_format.casino3.region
.. moduleauthor:: Hendrix Demers <hendrix.demers@mail.mcgill.ca>

Description
"""

###############################################################################
# Copyright 2020 Hendrix Demers
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
###############################################################################

# Standard library modules.
import logging
import decimal

# Third party modules.

# Local modules.

# Project modules.
from casinotools.file_format.file_reader_writer_tools import read_int, read_double, read_str, write_int, \
    write_double, write_str
from casinotools.file_format.tags import find_tag
from casinotools.file_format.casino3.element import Element

# Globals and constants variables.
decimal.getcontext().prec = 28
EPSILON = 1.0e-4

NB_PAR_MAX = 4

TAG_REGIONS_DATA = b"*regionSDATA%%%"


[docs] class Region: def __init__(self): self._file = None self._start_position = 0 self._file_pathname = "" self._file_descriptor = 0 self.version = 0 self._carrier_diffusion_length = 0.0 self.id_ed = 0 self._number_elements = 0 self.rho = 0.0 self.zmoy = 0.0 self._work_function = 0.0 self._average_plasmon_energy = 0.0 self.id = 0 self.substrate = 0 self.user_density = 0 self.user_composition = 0 self._checked = 0 self._energy_intensity = 0.0 self.name = "" self._number_sample_objects = 0 self._sample_object_ids = {} self._moller_init = 0.0 self._triangle_color_x = 0.0 self._triangle_color_y = 0.0 self._triangle_color_z = 0.0 self.elements = [] self._chemical_name = ""
[docs] def read(self, file): self._file = file self._start_position = file.tell() self._file_pathname = file.name self._file_descriptor = file.fileno() logging.debug("File position at the start of %s.%s: %i", self.__class__.__name__, "read", self._start_position) self.version = read_int(file) tag_id = TAG_REGIONS_DATA find_tag(file, tag_id) if self.version > 30104072: self._carrier_diffusion_length = read_double(file) if self.version < 30105005: self.id_ed = read_int(file) self._number_elements = read_int(file) self.rho = read_double(file) if self.version < 30105001: self.zmoy = read_double(file) self._work_function = read_double(file) self._average_plasmon_energy = read_double(file) self.id = read_int(file) self.substrate = read_int(file) self.user_density = read_int(file) self.user_composition = read_int(file) self._checked = read_int(file) if self.version < 30105022: self._energy_intensity = read_double(file) self.name = read_str(file) self._number_sample_objects = read_int(file) self._sample_object_ids = {} for dummy in range(self._number_sample_objects): object_id = read_int(file) inside_or_outside = read_int(file) self._sample_object_ids[object_id] = inside_or_outside self._moller_init = read_double(file) self._triangle_color_x = read_double(file) self._triangle_color_y = read_double(file) self._triangle_color_z = read_double(file) self.elements = [] for dummy in range(self._number_elements): element = Element() element.read(file) self.elements.append(element) self._chemical_name = read_str(file)
[docs] def _modify(self, file): assert file.mode == 'r+b' logging.debug("File position at the start of %s.%s: %i", self.__class__.__name__, "_write", file.tell()) tag_id = TAG_REGIONS_DATA if find_tag(file, tag_id): write_int(file, self.version) write_double(file, self._carrier_diffusion_length) write_int(file, self._number_elements) write_double(file, self.rho) write_double(file, self._work_function) write_double(file, self._average_plasmon_energy) write_int(file, self.id) write_int(file, self.substrate) write_int(file, self.user_density) write_int(file, self.user_composition) write_int(file, self._checked) write_str(file, self.name) write_int(file, self._number_sample_objects) for objectID in sorted(self._sample_object_ids.keys()): write_int(file, objectID) write_int(file, self._sample_object_ids[objectID]) write_double(file, self._moller_init) write_double(file, self._triangle_color_x) write_double(file, self._triangle_color_y) write_double(file, self._triangle_color_z) for element in self.elements: element.modify(file) write_str(file, self._chemical_name)
[docs] def write(self, file): raise NotImplementedError
[docs] def modify_name(self, name): self.name = name if not self._file.closed: current_position = self._file.tell() self._file.close() else: current_position = 0 self._file = open(self._file_pathname, 'r+b') self._file.seek(self._start_position) self._modify(self._file) self._file.close() self._file = open(self._file_pathname, 'rb') self._file.seek(current_position)
[docs] def get_number_elements(self): assert len(self.elements) == self._number_elements return self._number_elements
[docs] def remove_all_elements(self): self._number_elements = 0 self.elements = [] assert len(self.elements) == self._number_elements
[docs] def add_element(self, symbol, weight_fraction=1.0, number_x_ray_layers=500): self._number_elements += 1 element = Element() element.set_element(symbol, weight_fraction) self.elements.append(element) assert len(self.elements) == self._number_elements
[docs] def get_element(self, index): return self.elements[index]
[docs] def get_element_by_symbol(self, symbol): for element in self.elements: if element.get_symbol() == symbol: return element
[docs] def update(self): self._number_elements = self._compute_number_elements() self.rho = self._compute_mean_mass_density_g_cm3() self.zmoy = self._compute_mean_atomic_number() self.name = self._generate_name() self._compute_atomic_fraction_elements() self._check_weight_fraction() self._check_atomic_fraction()
[docs] def _compute_number_elements(self): return len(self.elements)
[docs] def _compute_mean_mass_density_g_cm3(self): inverse_total = 0.0 for element in self.elements: weight_fraction = element.get_weight_fraction() mass_density_g_cm3 = element.get_mass_density_g_cm3() inverse_total += weight_fraction / mass_density_g_cm3 mean_mass_density = 1.0 / inverse_total return mean_mass_density
[docs] def _compute_mean_atomic_number(self): total_z = 0.0 total_elements = 0.0 for element in self.elements: repetition = element.get_repetition() total_elements += repetition total_z += element.get_atomic_number() * repetition mean_atomic_number = total_z / total_elements return mean_atomic_number
[docs] def _generate_name(self): name = "" for element in self.elements: name += element.get_symbol().strip() return name
[docs] def _compute_atomic_fraction_elements(self): total = 0.0 for element in self.elements: weight_fraction = element.get_weight_fraction() atomic_weight = element.get_atomic_weight_g_mol() total += weight_fraction / atomic_weight for element in self.elements: weight_fraction = element.get_weight_fraction() atomic_weight = element.get_atomic_weight_g_mol() atomic_fraction = (weight_fraction / atomic_weight) / total element.set_atomic_fraction(atomic_fraction)
[docs] def _check_weight_fraction(self): weight_fractions = [element.get_weight_fraction() for element in self.elements] total = sum(weight_fractions) assert abs(total - 1.0) < EPSILON for element in self.elements: new_weight_fraction = decimal.Decimal(str(element.get_weight_fraction())) / decimal.Decimal(str(total)) element.set_weight_fraction(float(new_weight_fraction)) weight_fractions = [element.get_weight_fraction() for element in self.elements] total = sum(weight_fractions) assert abs(total - 1.0) < EPSILON * EPSILON
[docs] def _check_atomic_fraction(self): atomic_fractions = [element.get_atomic_fraction() for element in self.elements] total = sum(atomic_fractions) assert abs(total - 1.0) < EPSILON for element in self.elements: new_atomic_fraction = decimal.Decimal(str(element.get_atomic_fraction())) / decimal.Decimal(str(total)) element.set_atomic_fraction(float(new_atomic_fraction)) atomic_fractions = [element.get_atomic_fraction() for element in self.elements] total = sum(atomic_fractions) assert abs(total - 1.0) < EPSILON * EPSILON
[docs] def get_mean_mass_density_g_cm3(self): return self.rho
[docs] def get_mean_atomic_number(self): return self.zmoy
[docs] def get_name(self): return self.name
[docs] def get_composition(self): return self._chemical_name
[docs] def get_id(self): return self.id
[docs] def export(self, export_file): # todo: implement the export method. logging.error("implement the export method.")