Source code for src.Libs.Simulation.UFO.UFO_CCode

#!/usr/bin/env python3
"""
This file is part of the PAFFrontendSim.

The PAFFrontendSim is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License v3 as published by the Free Software Foundation.

The PAFFrontendSim 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 the PAFFrontendSim. If not, see https://www.gnu.org/licenses/.
"""
#############################################################################
#
# including c-code library for fast calculation of electromagnetic wave propagation from surface to surface
# and providing all necessay data-typed to operate it
#
#
#############################################################################
# ToDo
#############################################################################
# - clean-up code (frequently and regularly, please)
# - improve readability and add more comments (frequently and regularly)
#
# single task-changes / add-ons
# - add geometric trace
#
#############################################################################
# import libs
#############################################################################
from   ctypes                  import *
import subprocess
from   copy                    import copy, deepcopy

import LogClass
from   Simulation.constants    import _pythonPath

#############################################################################
# constants
#############################################################################
_CLASSNAME   = "UFO-CCode"

# import c-code (and compile it if necessary)
log = LogClass.LogClass(_CLASSNAME)         # documentation class used for all in and output messages

try:
    libCalc = CDLL(_pythonPath + "/src/Libs/Simulation/UFO/C-includes/libUFO.so")
except:

    log.printOut("  C-library not found, try to compile it", log.WARNING_TYPE, False)
    try:
        x = subprocess.call("gcc -Wall -Ofast -shared -o %s/src/Libs/Simulation/UFO/C-includes/libUFO.so -fPIC -fopenmp -lm -lc %s/src/Libs/Simulation/UFO/C-includes/UFO_calc.c" %(_pythonPath, _pythonPath), shell = True)
        libCalc = CDLL(_pythonPath + "/src/Libs/Simulation/UFO/C-includes/libUFO.so")
    except:
        libCalc = None

if libCalc == None :
    log.printOut("  C-library not available (can't be compiled and included", log.ERROR_TYPE, False)
else :
    log.printOut("  C-library sucessfully included", log.FLOW_TYPE, False)

def _cCalc_setLog ( newlog ) :
    global log 
    
    log = deepcopy(newlog)             # logging class used for all in and output messages
    log.addLabel( _CLASSNAME )

#############################################################################
# classes
#############################################################################
class _UFOVector(Structure) :
    _fields_ = [("x", c_double), ("y", c_double), ("z", c_double)]

class _UFOMatrix(Structure) :
    _fields_ = [("vx", _UFOVector), ("vy", _UFOVector), ("vz", _UFOVector)]

[docs] class UFODataPoint(Structure) : _fields_ =[ ("v", _UFOVector), ("n", _UFOVector), ("Jr", _UFOVector), ("Ji", _UFOVector), ("Er", _UFOVector), ("Ei", _UFOVector), ("Jtr", _UFOVector), ("Jti", _UFOVector), ("df", c_double), ("I", c_double) ]
[docs] class UFOHeaderPoint(Structure) : _fields_ =[ ("v", _UFOVector), ("n", _UFOVector), ("o", _UFOVector)#, ]
############################################################################# # setup method calls on c-library ############################################################################# # for calculating a current distribution cCalc_CurrentDist = libCalc.Calc_CurrentDist cCalc_CurrentDist.argtypes = [ POINTER(UFODataPoint), # Surface 1 POINTER(UFODataPoint), # Surface 2 c_int, # number of points in Surface 1 c_int, # number of points in Surface 2 c_double, # wavelength of the calculation c_double, # e_r of the material on the incomming ray c_double, # tangens Delta of the material c_int # adding up to previous data (< 0) or not ] cCalc_CurrentDist.restype = None # full simulation for transmission and reflection cCalc_CurrentDistFull = libCalc.Calc_CurrentDistFull cCalc_CurrentDistFull.argtypes = [ POINTER(UFODataPoint), # Surface 1 POINTER(UFODataPoint), # Surface 2 c_int, # number of points in Surface 1 c_int, # number of points in Surface 2 c_double, # wavelength of the calculation c_double, # e_r of the material on the incomming ray, c_double, # e_r of the material on the outgoing ray, c_double, # tangens Delta of the material c_int # adding up to previous data (< 0) or not ] cCalc_CurrentDistFull.restype = None # for moving a surface cMove = libCalc.move cMove.argtypes = [ POINTER(UFODataPoint), # Surface c_int, # number of points in Surface _UFOVector # vector to add ] cMove.restype = None # for matrix transforming a surface (e.g. rotation) cTransform = libCalc.transform cTransform.argtypes = [ POINTER(UFODataPoint), # Surface c_int, # number of points in Surface _UFOMatrix # transformation matrix ] cTransform.restype = None def _cCalc_CurrentDist(Data, new, points, wavelength, er, tanD, number): cCalc_CurrentDist(Data, new.Data, points, new.points , wavelength, er, tanD, number) # for calculating a current distribution return new def _cMove(Data, points, UFOVector): cMove(Data, points, UFOVector) # for moving a surface return Data, points def _cTransform(Data, points, UFOMatrix): cTransform(Data, points, UFOMatrix) # for matrix transforming a surface (e.g. rotation) return Data, points def _cCalc_CurrentDistFull(obj, new, wavelength = -1, add = False, trans = False): """ Calculate a current distribution on object new, starting with the current distribution on object obj Parameters: obj (UFODataClass) : Object to start with new (UFODataClass) : Object to calculate the current distribution on wavelength (float) : simulation wavelength; if negative, wavelength of object obj is used add (bool) : if true, the new currents and fields will be added to the fields and currents existing on object new already. trans (bool) : if true, using transmittance data of object 'obj' for the simulation """ erIn = 1. tanD = 0. if isinstance(obj.er, (float, int, complex) ) : erIn = obj.er if isinstance(obj.tanD, (float, int, complex) ) : tanD = obj.tanD if isinstance(new.er, (float, int, complex) ) : erOut = new.er else: erOut = erIn # check if transmitted field should be used if trans : # and rearange data and invert normal vector if so obj = deepcopy( obj ) for idx, d in enumerate( obj.Data ) : obj.Data[idx].Jr = d.Jtr obj.Data[idx].Ji = d.Jti obj.Data[idx].n.x *= -1. obj.Data[idx].n.y *= -1. obj.Data[idx].n.z *= -1. number = 0 if add: number = 1 if wavelength < 0 : wavelength = obj.Wavelength if True : #erOut == erIn : log.printOut("Using reflection simulation only", log.FLOW_TYPE, False) cCalc_CurrentDist ( obj.Data, new.Data, obj.points, new.points , wavelength, erIn, tanD, number ) else : log.printOut("Using full simulation", log.FLOW_TYPE, False) cCalc_CurrentDistFull( obj.Data, new.Data, obj.points, new.points , wavelength, erIn, erOut, tanD, number ) if not trans : # das ist falsch, man braucht zwei Speicherplätze für Permittivity bei Current-Files new.er = erIn return new