Source code for xopto.mcbase.mctypes

# -*- coding: utf-8 -*-
################################ Begin license #################################
# Copyright (C) Laboratory of Imaging technologies,
#               Faculty of Electrical Engineering,
#               University of Ljubljana.
#
# This file is part of PyXOpto.
#
# PyXOpto is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyXOpto is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyXOpto. If not, see <https://www.gnu.org/licenses/>.
################################# End license ##################################

import math
from typing import List, Tuple

import numpy as np
from jinja2 import Template

from xopto.mcbase import cltypes
from xopto.mcbase.mcobject import McObject


[docs]class StructToListBasic:
[docs] def tolist(self): return [getattr(self, name).value for name, _ in self._fields_]
[docs]class Matrix2Helper:
[docs] def fromarray(self, array: np.ndarray): self.a_11, self.a_12 = array[0, 0], array[0, 1] self.a_21, self.a_22 = array[1, 0], array[1, 1]
[docs] def toarray(self) -> np.ndarray: return np.array([ [self.a_11.value, self.a_12.value], [self.a_21.value, self.a_22.value], ])
[docs]class Matrix3Helper:
[docs] def fromarray(self, array: np.ndarray): self.a_11, self.a_12, self.a_13 = array[0, 0], array[0, 1], array[0, 2] self.a_21, self.a_22, self.a_23 = array[1, 0], array[1, 1], array[1, 2] self.a_31, self.a_32, self.a_33 = array[2, 0], array[2, 1], array[2, 2]
[docs] def toarray(self) -> np.ndarray: return np.array([ [self.a_11.value, self.a_12.value, self.a_13.value], [self.a_21.value, self.a_22.value, self.a_23.value], [self.a_31.value, self.a_32.value, self.a_33.value] ])
[docs]class Vector4Helper:
[docs] def fromarray(self, array: np.ndarray): self.x, self.y, self.z, self.w = array[0], array[1], array[2], array[3]
[docs] def toarray(self) -> np.ndarray: return np.array([self.x.value, self.y.value, self.z.value, self.w.value])
[docs]class Vector3Helper:
[docs] def fromarray(self, array: np.ndarray): self.x, self.y, self.z = array[0], array[1], array[2]
[docs] def toarray(self) -> np.ndarray: return np.array([self.x.value, self.y.value, self.z.value])
[docs]class Vector2Helper:
[docs] def fromarray(self, array: np.ndarray): self.x, self.y = array[0], array[1]
[docs] def toarray(self) -> np.ndarray: return np.array([self.x.value, self.y.value])
[docs]class McSizeT32: ''' Class that represents 32-bit size type. The OpenCL data types are defined by the following attributes: - mc_size_t - Size type. - mc_size<n>_t for vectorized unsigned integers (<n> must be one of 2, 3, 4, 8, 16) - mc_point2s_t structure for a 2D point with mc_size_t coordinates. - mc_point3s_t structure for a 3D point with mc_size_t coordinates. - mc_point4s_t structure for a 4D point with mc_size_t coordinates. The related numpy data types are defined by the following attributes: - np_size - For mc_size_t. - np_size2 - For mc_size2_t. - np_size3 - For mc_size3_t. - np_size4 - For mc_size4_t. Additional attributes of the class: - mc_maxsize - maximum unsigned integer value that can be represented by the size type. ''' mc_size_t = cltypes.cl_uint mc_size2_t = cltypes.cl_uint2 mc_size3_t = cltypes.cl_uint3 mc_size4_t = cltypes.cl_uint4 mc_size8_t = cltypes.cl_uint8 mc_size16_t = cltypes.cl_uint16
[docs] class mc_point2s_t(cltypes.Structure, StructToListBasic, Vector3Helper): ''' Structure representing a 2D point using mc_size_t. ''' _fields_ = [ ('x', cltypes.cl_uint), ('y', cltypes.cl_uint), ]
[docs] class mc_point3s_t(cltypes.Structure, StructToListBasic, Vector3Helper): ''' Structure representing a 3D point using mc_size_t. ''' _fields_ = [ ('x', cltypes.cl_uint), ('y', cltypes.cl_uint), ('z', cltypes.cl_uint) ]
[docs] class mc_point4s_t(cltypes.Structure, StructToListBasic, Vector4Helper): ''' Structure representing a 4D point using mc_size_t. ''' _fields_ = [ ('x', cltypes.cl_uint), ('y', cltypes.cl_uint), ('z', cltypes.cl_uint), ('w', cltypes.cl_uint) ]
mc_maxsize = 4294967295 np_size = 'uint32' np_size2 = np.dtype([('x', np_size), ('y', np_size)]) np_size3 = np.dtype([('x', np_size), ('y', np_size), ('z', np_size), ('_', np_size)]) np_size4 = np.dtype([('x', np_size), ('y', np_size), ('z', np_size), ('w', np_size)])
[docs] @staticmethod def size_t_str(value: int) -> str: ''' Convert a size type integer value to a string without loosing precision. Parameters ---------- value: int A size type integer value to convert to string. Returns ------- str_value: str A string representation of the input size type integer value. ''' return '{:d}u'.format(int(value))
[docs]class McSizeT64: ''' Class that represents 64-bit size type. The OpenCL data types are defined by the following attributes: - mc_size_t - Size type. - mc_size<n>_t - For vectorized unsigned integers (<n> must be one of 2, 3, 4, 8, 16) - mc_point2s_t structure for a 2D point with mc_size_t coordinates. - mc_point3s_t structure for a 3D point with mc_size_t coordinates. - mc_point4s_t structure for a 4D point with mc_size_t coordinates. - mc_point2_t - For a structure representing a 2D point with mc_int_t coordinates. - mc_point3_t - For a structure representing a 3D point with mc_int_t coordinates. - mc_point4_t - For a structure representing a 4D point with mc_int_t coordinates. - mc_matrix3_t - For a structure representing a 3x3 matrix with mc_int_t components. The related numpy data types are defined by the following attributes: - np_size - For mc_size_t. - np_size2 - For mc_size2_t. - np_size3 - For mc_size3_t. - np_size4 - For mc_size4_t. Additional attributes of the class: - mc_maxsize - maximum unsigned integer value that can be represented by the size type. ''' mc_size_t = cltypes.cl_ulong mc_size2_t = cltypes.cl_ulong2 mc_size3_t = cltypes.cl_ulong3 mc_size4_t = cltypes.cl_ulong4 mc_size8_t = cltypes.cl_ulong8 mc_size16_t = cltypes.cl_ulong16
[docs] class mc_point2s_t(cltypes.Structure, StructToListBasic, Vector3Helper): ''' Structure representing a 2D point using mc_size_t. ''' _fields_ = [ ('x', cltypes.cl_ulong), ('y', cltypes.cl_ulong), ]
[docs] class mc_point3s_t(cltypes.Structure, StructToListBasic, Vector3Helper): ''' Structure representing a 3D point using mc_size_t. ''' _fields_ = [ ('x', cltypes.cl_ulong), ('y', cltypes.cl_ulong), ('z', cltypes.cl_ulong) ]
[docs] class mc_point4s_t(cltypes.Structure, StructToListBasic, Vector4Helper): ''' Structure representing a 4D point using mc_size_t. ''' _fields_ = [ ('x', cltypes.cl_ulong), ('y', cltypes.cl_ulong), ('z', cltypes.cl_ulong), ('w', cltypes.cl_ulong) ]
mc_maxsize = 18446744073709551615 np_size = 'uint64' np_size2 = np.dtype([('x', np_size), ('y', np_size)]) np_size3 = np.dtype([('x', np_size), ('y', np_size), ('z', np_size), ('_', np_size)]) np_size4 = np.dtype([('x', np_size), ('y', np_size), ('z', np_size), ('w', np_size)])
[docs] @staticmethod def size_t_str(value: int) -> str: ''' Convert a size type integer value to a string without loosing precision. Parameters ---------- value: int A size type integer value to convert to string. Returns ------- str_value: str A string representation of the input size type integer value. ''' return '{:d}ul'.format(int(value))
[docs]class McInt32: ''' Class that represents a 32-bit default integer type. The OpenCL data types are defined by the following attributes: - mc_int_t - For signed integers. - mc_int<n>_t - For vectorized signed integers (<n> must be one of 2, 3, 4, 8, 16). - mc_uint_t - For unsigned integers. - mc_uint<n>_t - For vectorized unsigned integers (<n> must be one of 2, 3, 4, 8, 16). - mc_point2_t - For a structure representing a 2D point with mc_int_t coordinates. - mc_point3_t - For a structure representing a 3D point with mc_int_t coordinates. - mc_point4_t - For a structure representing a 4D point with mc_int_t coordinates. - mc_matrix3_t - For a structure representing a 3x3 matrix with mc_int_t components. The related numpy data types are defined by the following attributes: - np_int - For signed integers. - np_uint - For unsigned integers. Additional attributes of the class: - mc_uint_max - maximum unsigned integer value that can be represented by the data type. ''' mc_int_t = cltypes.cl_int mc_int2_t = cltypes.cl_int2 mc_int3_t = cltypes.cl_int3 mc_int4_t = cltypes.cl_int4 mc_int8_t = cltypes.cl_int8 mc_int16_t = cltypes.cl_int16 mc_uint_t = cltypes.cl_uint mc_uint2_t = cltypes.cl_uint2 mc_uint3_t = cltypes.cl_uint3 mc_uint4_t = cltypes.cl_uint4 mc_uint8_t = cltypes.cl_uint8 mc_uint16_t = cltypes.cl_uint16
[docs] class mc_point4_t(cltypes.Structure, StructToListBasic, Vector4Helper): ''' Structure representing a 4D point using 32-bit integers. ''' _fields_ = [ ('x', cltypes.cl_int), ('y', cltypes.cl_int), ('z', cltypes.cl_int), ('w', cltypes.cl_int) ]
[docs] class mc_point3_t(cltypes.Structure, StructToListBasic, Vector3Helper): ''' Structure representing a 3D point using 32-bit integers. ''' _fields_ = [ ('x', cltypes.cl_int), ('y', cltypes.cl_int), ('z', cltypes.cl_int) ]
[docs] class mc_point2_t(cltypes.Structure, StructToListBasic, Vector2Helper): ''' Structure representing a 2D point using 32-bit integers. ''' _fields_ = [ ('x', cltypes.cl_int), ('y', cltypes.cl_int), ]
[docs] class mc_matrix3_t(cltypes.Structure, StructToListBasic, Matrix3Helper): ''' Structure representing a 3x3 matrix using 32-bit integers. ''' _fields_ = [ ('a_11', cltypes.cl_int), ('a_12', cltypes.cl_int), ('a_13', cltypes.cl_int), ('a_21', cltypes.cl_int), ('a_22', cltypes.cl_int), ('a_23', cltypes.cl_int), ('a_31', cltypes.cl_int), ('a_32', cltypes.cl_int), ('a_33', cltypes.cl_int) ]
mc_uint_max = 4294967296 mc_int_max = 2147483647 np_int = 'int32' np_uint = 'uint32'
[docs] @staticmethod def int_str(value: int) -> str: ''' Convert an integer value to a string without loosing precision. Parameters ---------- value: int An integer value to convert to string. Returns ------- str_value: str A string representation of the input integer value. ''' return '{:d}'.format(int(np.int32(value)))
[docs] @staticmethod def uint_str(value: int) -> str: ''' Convert an unsigned integer value to a string without loosing precision. Parameters ---------- value: int An unsigned integer value to convert to string. Returns ------- str_value: str A string representation of the input unsigned integer value. ''' return '{:d}'.format(int(np.uint32(value)))
[docs]class McInt64: ''' Class that represents a 64-bit default integer type. The OpenCL data types are defined by the following attributes: - mc_int_t - For signed integers. - mc_int<n>_t - For vectorized signed integers (<n> must be one of 2, 3, 4, 8, 16). - mc_uint_t - For unsigned integers. - mc_uint<n>_t - For vectorized unsigned integers (<n> must be one of 2, 3, 4, 8, 16). - mc_point2_t - For a Structure representing a 2D point with mc_int_t coordinates. - mc_point3_t - For a Structure for representing a 3D point with mc_int_t coordinates. - mc_point4_t - For a Structure for representing a 4D point with mc_int_t coordinates. - mc_matrix3_t - For a Structure representing a 3x3 matrix with mc_int_t elements. The related numpy data types are defined by the following attributes: - mc_int_t - For signed integers. - mc_uint_t - For unsigned integers. Additional attributes of the class: - mc_uint_max - maximum unsigned integer value that can be represented by the data type. ''' mc_int_t = cltypes.cl_long mc_int2_t = cltypes.cl_long2 mc_int3_t = cltypes.cl_long3 mc_int4_t = cltypes.cl_long4 mc_int8_t = cltypes.cl_long8 mc_int16_t = cltypes.cl_long16 mc_uint_t = cltypes.cl_ulong mc_uint2_t = cltypes.cl_ulong2 mc_uint3_t = cltypes.cl_ulong3 mc_uint4_t = cltypes.cl_ulong4 mc_uint8_t = cltypes.cl_ulong8 mc_uint16_t = cltypes.cl_ulong16
[docs] class mc_point4_t(cltypes.Structure, StructToListBasic, Vector4Helper): ''' Structure representing a 4D point using 64-bit integers. ''' _fields_ = [ ('x', cltypes.cl_long), ('y', cltypes.cl_long), ('z', cltypes.cl_long), ('w', cltypes.cl_long) ]
[docs] class mc_point3_t(cltypes.Structure, StructToListBasic, Vector3Helper): ''' Structure representing a 3D point using 64-bit integers. ''' _fields_ = [ ('x', cltypes.cl_long), ('y', cltypes.cl_long), ('z', cltypes.cl_long) ]
[docs] class mc_point2_t(cltypes.Structure, StructToListBasic, Vector2Helper): ''' Structure representing a 2D point using 64-bit integers. ''' _fields_ = [ ('x', cltypes.cl_long), ('y', cltypes.cl_long), ]
[docs] class mc_matrix3_t(cltypes.Structure, StructToListBasic, Matrix3Helper): ''' Structure representing a 3x3 matrix using 64-bit integers. ''' _fields_ = [ ('a_11', cltypes.cl_long), ('a_12', cltypes.cl_long), ('a_13', cltypes.cl_long), ('a_21', cltypes.cl_long), ('a_22', cltypes.cl_long), ('a_23', cltypes.cl_long), ('a_31', cltypes.cl_long), ('a_32', cltypes.cl_long), ('a_33', cltypes.cl_long) ]
mc_uint_max = 18446744073709551616 mc_int_max = 9223372036854775807 np_uint = 'int64' np_uint = 'uint64'
[docs] @staticmethod def int_str(value: int) -> str: ''' Convert an integer value to a string without loosing precision. Parameters ---------- value: int A integer value to convert to string. Returns ------- str_value: str A string representation of the input integer value. ''' return '{:d}l'.format(int(np.int64(value)))
[docs] @staticmethod def uint_str(value: int) -> str: ''' Convert an unsigned integer value to a string without loosing precision. Parameters ---------- value: int An unsigned integer value to convert to string. Returns ------- str_value: str A string representation of the input unsigned integer value. ''' return '{:d}ul'.format(int(np.uint64(value)))
McInt = McInt32
[docs]class McAccu32: ''' Class that represents a 32-bit detector accumulator type. Tends to quickly overflow, even with a relatively small number of simulated photon packets. This class exposes the following attributes: - mc_accu_t - Defines the related OpenCL data type. - np_accu - Defines the related numpy data type. - mc_accu_k - Defines the factor that converts floating-point photon packet weight to an integer. - mc_accu_max - Defines the maximum integer value that can be represented by the detector accumulator type. ''' mc_accu_t = cltypes.cl_uint mc_accu_k = 0x7FFFFF # 23 bits mc_cnt_max = 4294967296 np_accu = 'uint32'
[docs]class McAccu64: ''' Class that represents a 64-bit detector accumulator type. This class exposes the following attributes: - mc_accu_t - Defines the related OpenCL data type. - np_accu - Defines the related numpy data type. - mc_accu_k - Defines the factor that converts floating-point photon packet weight to an integer. - mc_accu_max - Defines the maximum integer value that can be represented by the detector accumulator type. ''' mc_accu_t = cltypes.cl_ulong mc_accu_k = 0x7FFFFF # 23 bits mc_accu_max = 18446744073709551616 np_accu = 'uint64'
[docs]class McCnt32: ''' Class that represents a 32-bit photon packet counter type. The maximum number of photon packets that can be processed in a single OpenCL call of the Monte Carlo kernel is limited to 4,294,967,296. This class exposes the following attributes: - mc_cnt_t - Defines the related OpenCL data type. - np_cnt - Defines the related numpy data type. - mc_cnt_max - Defines the maximum integer value that can be represented by the photon packet counter type. ''' mc_cnt_t = cltypes.cl_uint mc_cnt_max = 4294967296 np_cnt = 'uint32'
[docs]class McCnt64: ''' Class that represents a 64-bit photon packet counter type. The maximum number of photon packets that can be processed in a single OpenCL call of the Monte Carlo kernel is for all practical purposes virtually unlimited (18,446,744,073,709,551,616). This class exposes the following attributes: - mc_cnt_t - Defines the related OpenCL data type. - np_cnt - Defines the related numpy data type. - mc_cnt_max - Defines the maximum integer value that can be represented by the photon packet counter type. ''' mc_cnt_t = cltypes.cl_ulong mc_cnt_max = 18446744073709551616 np_cnt = 'uint64'
McCnt = McCnt32
[docs]class McFloat: ''' Class that represents a single precision floating-point data type/arithmetics. This class implements the following attributes that define the related OpenCL data types: - mc_fp_t - Scalar floating-point data type. - mc_fp<n>_t - Vectorized floating point data types (<n> must be one of 2, 3, 4, 8, 16). - mc_point2f_t - Structure representing a 2D point with mc_fp_t coordinates. - mc_point3f_t - Structure representing a 3D point with mc_fp_t coordinates. - mc_point4f_t - Structure representing a 4D point with mc_fp_t coordinates. - mc_matrix2f_t - Structure representing a 2x2 matrix with mc_fp_t components. - mc_matrix3f_t - Structure representing a 3x3 matrix with mc_fp_t components. Attribute that defined the related numpy data type: - np_float - Scalar floating-point data type form mc_fp_t. - np2_float - Vector floating-point data type form mc_fp2_t. - np3_float - Vector floating-point data type form mc_fp3_t. - np4_float - Vector floating-point data type form mc_fp4_t. Additional attributes of the class: - eps - The difference between 1.0 and the next smallest representable float larger than 1.0. - mc_fp_maxint - Maximum unsigned integer value that can be represented by the float type. ''' mc_fp_t = cltypes.cl_float mc_fp2_t = cltypes.cl_float2 mc_fp3_t = cltypes.cl_float3 mc_fp4_t = cltypes.cl_float4 mc_fp8_t = cltypes.cl_float8 mc_fp16_t = cltypes.cl_float16 eps = 1.1920929e-07 mc_fp_maxint = 0x7FFFFF # 23 bits np_float = 'float32' np_float2 = np.dtype([('x', np_float), ('y', np_float)]) np_float3 = np.dtype([('x', np_float), ('y', np_float), ('z', np_float), ('_', np_float)]) np_float4 = np.dtype([('x', np_float), ('y', np_float), ('z', np_float), ('w', np_float)])
[docs] class mc_point2f_t(cltypes.Structure, StructToListBasic, Vector2Helper): ''' Structure representing a 2D point using single-precision floating-point. ''' _fields_ = [ ('x', cltypes.cl_float), ('y', cltypes.cl_float), ]
[docs] class mc_point3f_t(cltypes.Structure, StructToListBasic, Vector3Helper): ''' Structure representing a 3D point using single-precision floating-point. ''' _fields_ = [ ('x', cltypes.cl_float), ('y', cltypes.cl_float), ('z', cltypes.cl_float) ]
[docs] class mc_point4f_t(cltypes.Structure, StructToListBasic, Vector4Helper): ''' Structure representing a 4D point using single-precision floating-point. ''' _fields_ = [ ('x', cltypes.cl_float), ('y', cltypes.cl_float), ('z', cltypes.cl_float), ('w', cltypes.cl_float) ]
[docs] class mc_matrix2f_t(cltypes.Structure, StructToListBasic, Matrix2Helper): ''' Structure representing a 2x2 matrix using single-precision floating-point. ''' _fields_ = [ ('a_11', cltypes.cl_float), ('a_12', cltypes.cl_float), ('a_21', cltypes.cl_float), ('a_22', cltypes.cl_float), ]
[docs] class mc_matrix3f_t(cltypes.Structure, StructToListBasic, Matrix3Helper): ''' Structure representing a 3x3 matrix using single-precision floating-point. ''' _fields_ = [ ('a_11', cltypes.cl_float), ('a_12', cltypes.cl_float), ('a_13', cltypes.cl_float), ('a_21', cltypes.cl_float), ('a_22', cltypes.cl_float), ('a_23', cltypes.cl_float), ('a_31', cltypes.cl_float), ('a_32', cltypes.cl_float), ('a_33', cltypes.cl_float), ]
[docs] @staticmethod def fp_str(value: float) -> str: ''' Convert a floating-point value to a string without loosing precision. Parameters ---------- value: float A floating-point value to convert to string. Returns ------- str_value: str A string representation of the input floating-point value. ''' if np.isinf(value): return 'FP_INF' if value >= 0.0 else '-FP_INF' return '{:#.8g}f'.format(float(value))
McFloat32 = McFloat McSingle = McFloat
[docs]class McDouble: ''' Class that represents a double precision floating-point data type/arithmetics. This class implements the following attributes that define the related OpenCL data types: - mc_fp_t - Scalar floating-point data type. - mc_fp<n>_t - Vectorized floating point data types (<n> must be one of 2, 3, 4, 8, 16). - mc_point2f_t - Structure representing a 2D point with mc_fp_t coordinates. - mc_point3f_t - Structure representing a 3D point with mc_fp_t coordinates. - mc_point4f_t - Structure representing a 4D point with mc_fp_t coordinates. - mc_matrix2f_t - Structure representing a 2x2 matrix with mc_fp_t components. - mc_matrix3f_t - Structure representing a 3x3 matrix with mc_fp_t components. Attribute that defined the related numpy data type: - np_float - Scalar floating-point data type. - np2_float - Vector floating-point data type form mc_fp2_t. - np3_float - Vector floating-point data type form mc_fp3_t. - np4_float - Vector floating-point data type form mc_fp4_t. Additional attributes of the class: - eps - The difference between 1.0 and the next smallest representable float larger than 1.0. - mc_fp_maxint - Maximum unsigned integer value that can be represented by the float type. ''' mc_fp_t = cltypes.cl_double mc_fp2_t = cltypes.cl_double2 mc_fp3_t = cltypes.cl_double3 mc_fp4_t = cltypes.cl_double4 mc_fp8_t = cltypes.cl_double8 mc_fp16_t = cltypes.cl_double16 eps = 2.220446049250313e-16 mc_fp_maxint = 0xFFFFFFFFFFFFF # 52 bits np_float = 'float64' np_float2 = np.dtype([('x', np_float), ('y', np_float)]) np_float3 = np.dtype([('x', np_float), ('y', np_float), ('z', np_float), ('_', np_float)]) np_float4 = np.dtype([('x', np_float), ('y', np_float), ('z', np_float), ('w', np_float)])
[docs] class mc_point2f_t(cltypes.Structure, StructToListBasic, Vector2Helper): ''' Structure representing a 2D point using double-precision floating-point. ''' _fields_ = [ ('x', cltypes.cl_double), ('y', cltypes.cl_double), ]
[docs] class mc_point3f_t(cltypes.Structure, StructToListBasic, Vector3Helper): ''' Structure representing a 3D point using single-precision floating-point. ''' _fields_ = [ ('x', cltypes.cl_double), ('y', cltypes.cl_double), ('z', cltypes.cl_double) ]
[docs] class mc_point4f_t(cltypes.Structure, StructToListBasic, Vector4Helper): ''' Structure representing a 4D point using single-precision floating-point. ''' _fields_ = [ ('x', cltypes.cl_double), ('y', cltypes.cl_double), ('z', cltypes.cl_double), ('w', cltypes.cl_double) ]
[docs] class mc_matrix2f_t(cltypes.Structure, StructToListBasic, Matrix2Helper): ''' Structure representing a 2x2 matrix using double-precision floating-point. ''' _fields_ = [ ('a_11', cltypes.cl_double), ('a_12', cltypes.cl_double), ('a_21', cltypes.cl_double), ('a_22', cltypes.cl_double) ]
[docs] class mc_matrix3f_t(cltypes.Structure, StructToListBasic, Matrix3Helper): ''' Structure representing a 3x3 matrix using double-precision floating-point. ''' _fields_ = [ ('a_11', cltypes.cl_double), ('a_12', cltypes.cl_double), ('a_13', cltypes.cl_double), ('a_21', cltypes.cl_double), ('a_22', cltypes.cl_double), ('a_23', cltypes.cl_double), ('a_31', cltypes.cl_double), ('a_32', cltypes.cl_double), ('a_33', cltypes.cl_double) ]
[docs] @staticmethod def fp_str(value: float) -> str: ''' Convert a floating-point value to a string without loosing precision. Parameters ---------- value: float A floating-point value to convert to string. Returns ------- str_value: str A string representation of the input floating-point value. ''' return '{:.16g}'.format(float(value))
McFloat64 = McDouble class _McDataTypesMeta(type): def __str__(self): int_t = {False:McInt32, True:McInt64}.get( cltypes.sizeof(self.mc_int_t) == 8) accu_t = {False:McAccu32, True:McAccu64}.get( cltypes.sizeof(self.mc_accu_t) == 8) cnt_t = {False:McCnt32, True:McCnt64}.get( cltypes.sizeof(self.mc_cnt_t) == 8) fp_t = {False:McSingle, True:McDouble}.get( cltypes.sizeof(self.mc_fp_t) == 8) return 'class McDataTypes({}, {}, {}, {})'.format( int_t.__name__, accu_t.__name__, cnt_t.__name__, fp_t.__name__) def __repr__(self): return '{} # {}'.format(self.__str__(), id(self)) class _McDataTypesHelper: @classmethod def cl_options(cls, *_): ''' Returns a list of OpenCL options that set the selected default data types of the Monte Carlo kernel. ''' return [ ('MC_USE_DOUBLE_PRECISION', cltypes.sizeof(cls.mc_fp_t) == 8), ('MC_USE_64_BIT_SIZE_T', cltypes.sizeof(cls.mc_size_t) == 8), ('MC_USE_64_BIT_INTEGER', cltypes.sizeof(cls.mc_int_t) == 8), ('MC_USE_64_BIT_PACKET_COUNTER', cltypes.sizeof(cls.mc_cnt_t) == 8), ('MC_USE_64_BIT_ACCUMULATORS', cltypes.sizeof(cls.mc_accu_t) == 8), ('MC_INT_ACCUMULATOR_K', cls.mc_accu_k), ] @classmethod def double_precision(cls) -> 'McDataTypes': ''' Returns a double-precision variant of the data type. ''' return cls.custom(McDouble) @classmethod def single_precision(cls) -> 'McDataTypes': ''' Returns a single-precision variant of the data type. ''' return cls.custom(McFloat) @classmethod def custom(cls, *args) -> 'McDataTypes': ''' Creates a custom data type configuration for the Monte Carlo kernel. Parameters ---------- args: tuple Positional arguments that customize the default kernel data types: - size type - Use McSizeT32 for 32-bit unsigned integer size type. - Use McSizeT64 for 64-bit unsigned integer size type. - integer type - Use McInt32 for 32-bit integers. - Use McInt64 for 64-bit integers. - photon packet counter type - Use McCnt32 for a 32-bit unsigned counter. - Use McCnt64 for a 64-bit unsigned counter. - floating point precision - Use McSingle for single precision floating-point arithmetics. - Use McDouble for double precision floating-point arithmetics. - accumulator integer type - Use McAccu32 for 32-bit detector accumulators (not recommended). - Use McAccu64 for 64-bit detector accumulators. ''' class McDataTypesCustom(*cls.make_base(*args), metaclass =_McDataTypesMeta): pass return McDataTypesCustom @classmethod def make_base(cls, *args): ''' Creates a customized list of base classes for the specified data type configuration for the OpenCL kernel. Parameters ---------- args: tuple Positional arguments that customize the default kernel data types: - size type - Use McSizeT32 for 32-bit unsigned integer size type. - Use McSizeT64 for 64-bit unsigned integer size type. - integer type - Use McInt32 for 32-bit integers. - Use McInt64 for 64-bit integers. - photon packet counter type - Use McCnt32 for a 32-bit unsigned counter. - Use McCnt64 for a 64-bit unsigned counter. - floating point precision - Use McSingle for single precision floating-point arithmetics. - Use McDouble for double precision floating-point arithmetics. - accumulator integer type - Use McAccu32 for 32-bit detector accumulators (not recommended). - Use McAccu64 for 64-bit detector accumulators. ''' base = list(cls.__bases__) for item in args: if item == McDouble and McSingle in base: base[base.index(McSingle)] = McDouble elif item == McSingle and McDouble in base: base[base.index(McDouble)] = McSingle elif item == McInt32 and McInt64 in base: base[base.index(McInt64)] = McInt32 elif item == McInt64 and McInt32 in base: base[base.index(McInt32)] = McInt64 elif item == McCnt32 and McCnt64 in base: base[base.index(McCnt64)] = McCnt32 elif item == McCnt64 and McCnt32 in base: base[base.index(McCnt32)] = McCnt64 elif item == McSizeT32 and McSizeT64 in base: base[base.index(McSizeT64)] = McSizeT32 elif item == McSizeT64 and McSizeT32 in base: base[base.index(McSizeT32)] = McSizeT64 elif item == McAccu32 and McAccu64 in base: base[base.index(McAccu64)] = McAccu32 elif item == McAccu64 and McAccu32 in base: base[base.index(McAccu32)] = McAccu64 return base @classmethod def mc_fp_lut_t(cls): ''' Returns a ctypes structure type that represents a linear lookup table. ''' class ClFpLut(cltypes.Structure): ''' Structure representing a lookup table. ''' _fields_ = [ ('first', cls.mc_fpt_t), ('inv_span', cls.mc_fp_t), ('n', cls.mc_size_t), ('offset', cls.mc_size_t), ] return ClFpLut
[docs]class McDataTypesBase: pass
[docs]class McDataTypes(McFloat32, McCnt32, McInt32, McAccu64, McSizeT32, McDataTypesBase, _McDataTypesHelper, McObject, metaclass =_McDataTypesMeta): ''' Class representing Monte Carlo kernel data types. Use the customize static method to customize the default integer, floating-point, detector accumulator and photon packet counter data types. This class sets up the default set of kernel data types: - size type Use McSizeT32 for 32-bit unsigned integer size type. - integer type Use McInt32 for 32-bit integers. - photon packet counter type Use McCnt32 for a 32-bit unsigned counter. - floating point precision Use McSingle for single precision floating-point arithmetics. - accumulator integer type Use McAccu64 for 64-bit detector accumulators. ''' pass
[docs]class McDataTypesSingle(*McDataTypes.make_base(), metaclass =_McDataTypesMeta): ''' Class will set up the following OpenCL data types: - size type Use McSizeT32 for 32-bit unsigned integer size type. - integer type Use McInt32 for 32-bit integers. - photon packet counter type Use McCnt32 for a 32-bit unsigned counter. - floating point precision Use McSingle for single precision floating-point arithmetics. - accumulator integer type Use McAccu64 for 64-bit detector accumulators. '''
[docs] @classmethod def double_precision(cls) -> 'McDataTypesDouble': ''' Returns a double-precision floating-point variant of the data type. ''' return McDataTypesDouble
[docs] @classmethod def single_precision(cls) -> 'McDataTypesSingle': ''' Returns a single-precision floating-point variant of the data type. ''' return cls
[docs]class McDataTypesSingleCnt64(*McDataTypes.make_base(McCnt64, McSizeT64), metaclass =_McDataTypesMeta): ''' Class will set up the following OpenCL data types: - size type Use McSizeT64 for 64-bit unsigned integer size type. - integer type Use McInt32 for 32-bit integers. - photon packet counter type Use McCnt64 for a 64-bit unsigned counter. - floating point precision Use McSingle for single precision floating-point arithmetics. - accumulator integer type Use McAccu64 for 64-bit detector accumulators. '''
[docs] @classmethod def double_precision(cls) -> 'McDataTypesDoubleCnt64': ''' Returns a double-precision floating-point variant of the data type. ''' return McDataTypesDoubleCnt64
[docs] @classmethod def single_precision(cls) -> 'McDataTypesSingleCnt64': ''' Returns a single-precision floating-point variant of the data type. ''' return cls
[docs]class McDataTypesDouble(*McDataTypes.make_base(McDouble), metaclass =_McDataTypesMeta): ''' Class will set up the following OpenCL data types: - size type Use McSizeT32 for 32-bit unsigned integer size type. - integer type Use McInt32 for 32-bit integers. - photon packet counter type Use McCnt32 for a 32-bit unsigned counter. - floating point precision Use McDouble for double precision floating-point arithmetics. - accumulator integer type Use McAccu64 for 64-bit detector accumulators. '''
[docs] @classmethod def double_precsision(cls) -> 'McDataTypesDouble': ''' Returns a double-precision floating-point variant of the data type. ''' return cls
[docs] @classmethod def single_precision(cls) -> McDataTypesSingle: ''' Returns a single-precision floating-point variant of the data type. ''' return McDataTypesSingle
[docs]class McDataTypesDoubleCnt64( *McDataTypes.make_base(McDouble, McCnt64, McSizeT64), metaclass =_McDataTypesMeta): ''' Class will set up the following OpenCL data types: - size type Use McSizeT64 for 64-bit unsigned integer size type. - integer type Use McInt32 for 32-bit integers. - photon packet counter type Use McCnt32 for a 32-bit unsigned counter. - floating point precision Use McDouble for double precision floating-point arithmetics. - accumulator integer type Use McAccu64 for 64-bit detector accumulators. '''
[docs] @classmethod def double_precsision(cls) -> 'McDataTypesDoubleCnt64': ''' Returns a double-precision floating-point variant of the data type. ''' return cls
[docs] @classmethod def single_precision(cls) -> McDataTypesSingleCnt64: ''' Returns a single-precision floating-point variant of the data type. ''' return McDataTypesSingleCnt64
[docs]class OpenCLSource: def __init__(self, headers: List[str], sources: List[str]): ''' Merges OpenCL header and source files in the listed order. Parameters ---------- headers: list List of OpenCL headers. sources: list List of OpenCL headers. ''' self._cl_sources = '\n'.join(headers) + '\n'.join(sources) self._cl_template = Template(self._cl_source)
[docs] def render(self, data: dict): default = { 'mc': {'options': ''}, 'source': {'declaration':'', 'implementation': ''}, 'pf': {'declaration':'', 'implementation': ''}, 'rt': {'declaration':'', 'implementation': ''}, 'trace': {'declaration':'', 'implementation': ''}, 'fluence': {'declaration':'', 'implementation': ''}, 'top_geometry': {'declaration':'', 'implementation': ''}, 'bottom_geometry': {'declaration':'', 'implementation': ''} } default.update(data) return self._cl_template.render(**default)