from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
#for python 2:
#from builtins import super
from .data_spectral import SolarSpectrum, MirrorRhoSpectrum
from .cal_layout import multi_aperture_pos
import sys
class Sun:
"""Sun parameters for solstice-input
Example:
>>> sun = Sun(dni=1000, sunshape='buie', csr=0.2)
>>> print(sun.yaml(spectrum = "*solar_spectrum"))
"""
def __init__(self,dni=1000,sunshape=None,csr=0.01,half_angle_deg=0.2664,std_dev=0.2):
"""Define sun parameters for Solstice input file.
`dni`: Direct normal irradance (W/m2)
`sunshape`: Sunshape: can be None, ``'pillbox'``,``'gaussian'`` or ``'buie'``
`half_angle_deg`: sun angular size (in DEGREES, half-angle) (ONLY in case of ``'pillbox'``)
`csr`: circumsolar ratio (ONLY in case of ``'buie'``)
`std_dev`: standard deviation of the angular dsn ratio (ONLY in case of ``'gaussian'``)
"""
self.dni = dni
self.sunshape = sunshape
if sunshape is not None:
assert sunshape in ['buie','pillbox','gaussian']
self.sunshape = sunshape
if sunshape == "pillbox":
self.half_angle_deg = half_angle_deg
elif sunshape == "buie":
self.csr = csr
elif sunshape == "gaussian":
self.std_dev = std_dev
def yaml(self,spectrum = None):
"""YAML representation of the sun for solstice-input.
`spectrum`: YAML value of the solar spectrum. Would normally be set to the string ``"*solar_spectrum"``.
"""
# FIXME surely we find a smarter way to do this serialization AND deseralization with YAML?
s = "{dni: %15.8e" % (self.dni,)
if spectrum is not None:
s += ", spectrum = %s" % (spectrum,)
if self.sunshape is not None:
if self.sunshape=='pillbox':
s += ", pillbox: {half_angle: %6.4f}" % (self.half_angle_deg,)
elif self.sunshape=='buie':
s += ", buie: {csr: %6.4f}" % (self.csr,)
elif self.sunshape=='gaussian':
s += ", gaussian: {std_dev: %6.4f}" % (self.std_dev,)
s += "}"
return s
[docs]def gen_yaml(sun, hst_pos, hst_foc, hst_aims,hst_w, hst_h
, rho_refl, slope_error, receiver, rec_param, rec_abs
, outfile_yaml, outfile_recv
, hemisphere='North', tower_h=0.01, tower_r=0.01, spectral=False
, medium=0, one_heliostat=False
):
"""Generate the heliostat field and receiver YAML input files for Solstice ray-tracing simulation.
1. the sun
* `sun` (`Sun` object): parameters relating to the solar source
2. the field
* `hst_pos` (nx3 numpy array): heliostat positions (x, y, z) (first of the 'field' parameters)
* `hst_foc` (nx1 numpy array): heliostat focal length
* `hst_aims` (nx3 numpy array): heliostat aiming point (ax, ay, az)
* `hst_w` (float): heliostat mirror width (in x direction)
* `hst_h` (float): heliostat mirror height (in y direction)
* `hst_z` (float): heliostat center height (in z direction)
* `rho_refl` (float): reflector reflectivity
* `slope_error` (float): reflector surface slope error rms, radians
* `tower_h` (float): tower height (m)
* `tower_r` (float): tower radius (a cylindrical shape tower) (m)
3. the receiver
* `receiver` (str): ``'flat'``, ``'cylinder'``, or ``'stl' or 'multi-aperture'`` (first of the 'receiver' parameters)
* `rec_abs` (float): receiver absorptivity
* `rec_param` (numpy array or str): each element contains the geometrical parameter of the corresponding receiver.
4. others
* `spectral` (bool): True - simulate the spectral dependent performance (first of the 'other' parameters)
* `medium` (float): if the atmosphere is surrounded by non-participant medium, medium=0; otherwise it is the extinction coefficient in m-1
* `one_heliosat` (boolean): if `True`, implements ray tracing from just one heliostat.
Returns: nothing (requested files are created and written)
Note that the parameters are in groups that relate to the `sun`, the `field` and the `receiver` then `others`.
Note also the type for `rec_param` should be as follows.
* if ``receiver == 'flat'``: np.array([width, height, grid_w, grid_h,, x, y, z, tilt angle (deg))]
* if ``receiver == 'cylinder'``: np.array([radius, height, grid_circ, grid_h, x, y, z, tilt angle (deg)])
* if ``receiver == 'stl'``: the directory of the stl file
* if ``receiver == 'multi-aperture'``: np.array([width, height, grid_w, grid_h,, x, y, z, tilt angle (deg),num_aperture, gamma (deg) ])
"""
# FIXME Parameters should be named according to what they are, eg
# the parameter should be called 'csr', not 'sunsize', to avoid confusion.
# We can still improve our calling convention, to make this library easier
# to use and more maintainable.
sys.stderr.write("Generating YAML file...\n")
iyaml='' # the input yaml file
#
### Section (1)
# set the spectral data:
# solar radiative intensity, refractive indexes, extinction coefficients, reflectivities
#------------------------------
if spectral:
I_sun=SolarSpectrum()
# CREATE the spectrum for the sun
iyaml+='- spectrum: &solar_spectrum \n'
for i in range(0,len(I_sun)-1):
iyaml+=' - {wavelength: %s, data: %s }\n' % (I_sun[i][0],I_sun[i][1])
i = len(I_sun)-1
iyaml+=' - {wavelength: %s, data: %s }\n' % (I_sun[i][0],I_sun[i][1])
iyaml+='\n'
# CREATE the spectrum for the reflectivity (mirror)
mirror_rho= MirrorRhoSpectrum()
mirror_ref=mirror_rho
for i in range(0,len(mirror_rho)):
mirror_ref[i][0] = mirror_rho[len(mirror_rho)-1-i][0]/1000.
mirror_ref[i][1] = mirror_rho[len(mirror_rho)-1-i][1]/100.
mirror_ref.append([4,0.9])
iyaml+='- spectrum: &%s \n' % 'ref_mirror'
for i in range(0,len(mirror_ref)-1):
iyaml+=' - {wavelength: %15.8e, data: %15.8e }\n' % (float(mirror_ref[i][0]),float(mirror_ref[i][1]))
i = len(mirror_ref)-1
iyaml+=' - {wavelength: %15.8e, data: %15.8e }\n' % (float(mirror_ref[i][0]),float(mirror_ref[i][1]))
iyaml+='\n'
#
### Section (2)
# set the medium types:
# air, glass, vacuum, etc. gathering spectral data
#------------------------------
#
#
# Creation of the sun and atmosphere
#
if spectral:
spectrum = "*solar_spectrum"
else:
spectrum = None
iyaml += "- sun: %s\n" % (sun.yaml(spectrum),)
if medium>1e-99:
iyaml+='- atmosphere: {extinction: %s}\n'%medium
iyaml+='\n'
#
### Section (3)
# set the materials
# (gathering media)
# occultant material, mirror specular material, receiver material, virtual target
#------------------------------
#
# CREATE an occultant material
r_f = 0. # front
r_b = 0. # and back reflectivity
iyaml+='- material: &%s\n' % 'material_black'
iyaml+=' front:\n'
iyaml+=' matte: {reflectivity: %6.4f }\n' % r_f
iyaml+=' back:\n'
iyaml+=' matte: {reflectivity: %6.4f }\n' % r_b
iyaml+='\n'
#
# CREATE a specular material
r_f= rho_refl # front
r_b = 0. # and back reflectivity
iyaml+='- material: &%s\n' % 'material_mirror'
iyaml+=' front:\n'
if spectral:
iyaml+=' mirror: {reflectivity: *%s, slope_error: %15.8e }\n' % ('ref_mirror', slope_error )
else:
iyaml+=' mirror: {reflectivity: %6.4f, slope_error: %15.8e }\n' % (r_f, slope_error)
iyaml+=' back:\n'
iyaml+=' matte: {reflectivity: %6.4f }\n' % r_b
iyaml+='\n'
#
# CREATE a material for the target
r_f = 1.-rec_abs # front
r_b = 1.-rec_abs # and back reflectivity
iyaml+='- material: &%s\n' % 'material_target'
iyaml+=' front:\n'
iyaml+=' matte: {reflectivity: %6.4f }\n' % r_f
iyaml+=' back:\n'
iyaml+=' matte: {reflectivity: %6.4f }\n' % r_b
iyaml+='\n'
#
# CREATE a virtual material for the calculation of spillage
iyaml+='- material: &%s\n' % 'material_virtual'
iyaml+=' virtual:\n'
iyaml+='\n'
#
### Section (4)
# set the geometries
# (gathering shapes and materials)
# the tower, the receiver, the heliostat
#------------------------------
#
# Tower Geometry
# (cylindrical shape)
#
slices = 10 # slices for the envelop circle
iyaml+='- geometry: &%s\n' % 'tower_g'
iyaml+=' - material: *%s\n' % 'material_black'
#iyaml+=' transform: { translation: %s, rotation: %s }\n' % ([0, 0, h_tow*0.5], [0, 90, 0])
iyaml+=' cylinder: {height: %7.3f, radius: %7.3f, slices: %d }\n' % (tower_h, tower_r, slices)
iyaml+='\n'
#
# Receiver Geometry
#
if receiver=='flat':
geom, rec_entt, rcv = flat_receiver(rec_param, hemisphere)
iyaml+=geom
elif receiver=='cylinder':
geom, rec_entt, rcv = cylindrical_receiver(rec_param, hemisphere)
iyaml+=geom
elif receiver=='stl':
rec_entt, rcv=STL_receiver(rec_param, hemisphere)
elif receiver=='multi-aperture':
geom, rec_entt, rcv =multi_aperture_receiver(rec_param, hemisphere)
iyaml+=geom
#
# Heliostats Geometry
#
if one_heliostat:
hst_x=np.r_[hst_pos[0]]
hst_y=np.r_[hst_pos[1]]
hst_z=np.r_[hst_pos[2]]
aim_x=np.r_[hst_aims[0]]
aim_y=np.r_[hst_aims[1]]
aim_z=np.r_[hst_aims[2]]
num_hst=1
hst_foc=np.r_[hst_foc]
else:
hst_x=hst_pos[:,0]
hst_y=hst_pos[:,1]
hst_z=hst_pos[:,2]
aim_x=hst_aims[:,0]
aim_y=hst_aims[:,1]
aim_z=hst_aims[:,2]
num_hst=len(hst_x)
slices = 4 # slices for the envelop circle
pts_hst = [ [-hst_w*0.5, -hst_h*0.5], [-hst_w*0.5, hst_h*0.5], [hst_w*0.5, hst_h*0.5], [hst_w*0.5,-hst_h*0.5] ]
# CREATE a reflective facet (mirror)
for i in range(0,num_hst):
name_hst_g = 'hst_g_'+str(i)
iyaml+='- geometry: &%s\n' % name_hst_g
iyaml+=' - material: *%s\n' % 'material_mirror'
#iyaml+=' transform: { translation: %s, rotation: %s }\n' % ([hst_x[i], hst_y[i], hst_z[i]], [0, 0, 0]) )
iyaml+=' parabol: \n'
iyaml+=' focal: %s\n' % hst_foc[i]
iyaml+=' clip: \n'
iyaml+=' - operation: AND \n'
iyaml+=' vertices: %s\n' % pts_hst
iyaml+=' slices: %d\n' % slices
# CREATE the pylon "pylon_g" geometry cylindrical shape
h_pyl = 0.001 # pylon height
r_pyl = 0.2 # pylon radius
slices = 4 # slices for the envelop circle
iyaml+='- geometry: &%s\n' % 'pylon_g'
iyaml+=' - material: *%s\n' % 'material_black'
iyaml+=' transform: { translation: %s, rotation: %s }\n' % ([0, 0, -h_pyl*3], [0, 90, 0])
iyaml+=' cylinder: {height: %7.3f, radius: %7.3f, slices: %d }\n' % (h_pyl,r_pyl,slices)
#
#
### Section (5)
# set the templates
# (programming objects gathering geometries or pivot and geometries)
#------------------------------
# CREATE the heliostat templates
for i in range(0,num_hst):
name_hst_t = 'hst_t_'+str(i)
iyaml+='- template: &%s\n' % name_hst_t
name_hst_n = 'hst_'+ str(i)
iyaml+=' name: %s\n' % name_hst_n
iyaml+=' primary: 0\n'
iyaml+=' geometry: *pylon_g\n'
iyaml+=' children: \n'
iyaml+=' - name: pivot\n'
iyaml+=' zx_pivot: {target: {position: %s}} \n' % ([aim_x[i],aim_y[i],aim_z[i]])
iyaml+=' children: \n'
iyaml+=' - name: reflect_surface\n'
iyaml+=' primary: 1\n'
iyaml+=' transform: {rotation: [-90,0,0]} \n'
name_hst_g = 'hst_g_'+str(i)
iyaml+=' geometry: *%s\n' % name_hst_g
#
### Section (6)
# set the entities
# (gather templates to be created and active in the scene)
#------------------------------
#
# receiver entities
iyaml+=rec_entt
#
# tower entities
iyaml+='\n- entity:\n'
iyaml+=' name: tower_e\n'
iyaml+=' primary: 0\n'
iyaml+=' transform: { translation: %s, rotation: %s }\n' % ([0, -tower_r, tower_h*0.5], [0, 0, 0])
iyaml+=' geometry: *%s\n' % 'tower_g'
#
# heliostat entities from the template
for i in range(0,num_hst):
name_e ='H_'+str(i)
name_hst_t = 'hst_t_'+str(i)
iyaml+='\n- entity:\n'
iyaml+=' name: %s\n' % name_e
iyaml+=' transform: { translation: %s, rotation: %s }\n' % ([hst_x[i], hst_y[i], hst_z[i]], [0, 0, 0])
iyaml+=' children: [ *%s ]\n' % name_hst_t
with open(outfile_yaml,'w') as f:
f.write(iyaml)
with open(outfile_recv,'w') as f:
f.write(rcv)
def flat_receiver(rec_param, hemisphere='North'):
"""
hemisphere : 'North' or 'South' hemisphere of the earth where the field located
if North: the field is in the positive y direction
if South: the field is in the negtive y direction
this will influence:
(1) the setting of the receiver tilt angle,
if the front surface always facing to the field is desirable
(2) the position of the virtual target
"""
rec_w=rec_param[0]
rec_h=rec_param[1]
slices=rec_param[2] # it assumes equal number of slices in x and y directions
x=rec_param[4]
y=rec_param[5]
z=rec_param[6]
tilt=rec_param[7]
# receiver tilt angle:
# 0 is vertical
# the standby posiion of a plane in solstice is normal points to the +z axis
# rotation anagle, positive is anti-clockwise
geom=''
pts=[ [-rec_w*0.5, -rec_h*0.5], [-rec_w*0.5, rec_h*0.5], [rec_w*0.5, rec_h*0.5], [rec_w*0.5,-rec_h*0.5] ]
geom+='- geometry: &%s\n' % 'target_g'
geom+=' - material: *%s\n' % 'material_target'
geom+=' plane: \n'
geom+=' clip: \n'
geom+=' - operation: AND \n'
geom+=' vertices: %s\n' % pts
geom+=' slices: %d\n' % slices
geom+='\n'
# CREATE a receiver entity from "target_g" geometry (primary = 0)
entt=''
entt+='\n- entity:\n'
entt+=' name: target_e\n'
entt+=' primary: 0\n'
if hemisphere=='North':
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y, z], [-90.-tilt, 0, 0])
else:
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y, z], [90.+tilt, 0, 0])
entt+=' geometry: *%s\n' % 'target_g'
# CREATE a virtual target entity from "target_g" geometry (primary = 0)
pts = [ [-rec_w*10., -rec_h*10.], [-rec_w*10., rec_h*10.], [rec_w*10., rec_h*10.], [rec_w*10.,-rec_h*10.] ]
slices = 4
entt+='\n- entity:\n'
entt+=' name: virtual_target_e\n'
entt+=' primary: 0\n'
if hemisphere=='North':
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y-5., z], [-90.-tilt, 0, 0])
else:
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y+5., z], [90.+tilt, 0, 0])
entt+=' geometry: \n'
entt+=' - material: *%s\n' % 'material_virtual'
entt+=' plane: \n'
entt+=' clip: \n'
entt+=' - operation: AND \n'
entt+=' vertices: %s\n' % pts
entt+=' slices: %d\n' % slices
rcv=''
rcv+='- name: target_e \n'
rcv+=' side: %s \n' % 'FRONT_AND_BACK'
rcv+=' per_primitive: %s \n' % 'INCOMING_AND_ABSORBED'
rcv+='- name: virtual_target_e \n'
rcv+=' side: %s \n' % 'FRONT'
rcv+=' per_primitive: %s \n' % 'INCOMING'
return geom, entt, rcv
def cylindrical_receiver(rec_param, hemisphere='North'):
'''
hemishpere : 'North' or 'South' hemisphere of the earth where the field located
if North: the field is in the positive y direction
if South: the field is in the negtive y direction
this will influence:
(1) the setting of the receiver tilt angle,
if the front surface always facing to the field is desirable
(2) the position of the virtual target
'''
rec_r=rec_param[0]/2.
rec_h=rec_param[1]
slices=rec_param[2] # number of elements in the circumferetial direction
stacks=rec_param[3] # number of elements in the vertical direction
x=rec_param[4]
y=rec_param[5]
z=rec_param[6]
geom=''
geom+='- geometry: &%s\n' % 'target_g'
geom+=' - material: *%s\n' % 'material_target'
geom+=' cylinder: \n'
geom+=' height: %s\n'%rec_h
geom+=' radius: %s\n'%rec_r
geom+=' slices: %d\n' % slices
geom+=' stacks: %d\n' % stacks
geom+='\n'
# CREATE a receiver entity from "target_g" geometry (primary = 0)
entt=''
entt+='\n- entity:\n'
entt+=' name: target_e\n'
entt+=' primary: 0\n'
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y, z], [0., 0., 0.])
entt+=' geometry: *%s\n' % 'target_g'
# CREATE a virtual target entity from "target_g" geometry (primary = 0)
Vsize=100.
pts = [ [-rec_h*Vsize, -rec_h*Vsize], [-rec_h*Vsize, rec_h*Vsize], [rec_h*Vsize, rec_h*Vsize], [rec_h*Vsize,-rec_h*Vsize] ]
slices = 4
entt+='\n- entity:\n'
entt+=' name: virtual_target_e\n'
entt+=' primary: 0\n'
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y, z+rec_h/2.+1], [-180., 0, 0])
entt+=' geometry: \n'
entt+=' - material: *%s\n' % 'material_virtual'
entt+=' plane: \n'
entt+=' clip: \n'
entt+=' - operation: AND \n'
entt+=' vertices: %s\n' % pts
entt+=' slices: %d\n' % slices
rcv=''
rcv+='- name: target_e \n'
rcv+=' side: %s \n' % 'FRONT_AND_BACK'
rcv+=' per_primitive: %s \n' % 'INCOMING_AND_ABSORBED'
rcv+='- name: virtual_target_e \n'
rcv+=' side: %s \n' % 'FRONT'
rcv+=' per_primitive: %s \n' % 'INCOMING'
return geom, entt, rcv
def STL_receiver(rec_param, hemisphere='North'):
'''
hemishpere : 'North' or 'South' hemisphere of the earth where the field located
if North: the field is in the positive y direction
if South: the field is in the negtive y direction
this will influence:
(1) the setting of the receiver tilt angle,
if the front surface always facing to the field is desirable
(2) the position of the virtual target
'''
rec_w=rec_param[0].astype(float) # for creating the virtual target
rec_h=rec_param[1].astype(float)
stlfile=rec_param[2] # directory of the stl file
x=rec_param[3].astype(float)
y=rec_param[4].astype(float)
z=rec_param[5].astype(float)
tilt=rec_param[6].astype(float) # need to figure out the initial mesh orientation
# CREATE a receiver entity from a STL file
entt=''
entt+='\n- entity:\n'
entt+=' name: STL_receiver_e\n'
entt+=' primary: 0\n'
if hemisphere=='North':
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y, z], [-90.-tilt, 0, 0])
else:
# if it is the mesh model of the bladed receiver at CSIRO
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y, z], [180.+tilt, 0, 0])
entt+=' geometry:\n'
entt+=' - material: *material_target\n'
entt+=' transform: {translation: [0, 0, 0], rotation: [0, 0, 0]}\n'
entt+=" stl : {path: %s } \n"%(stlfile)
# CREATE a virtual target entity from "target_g" geometry (primary = 0)
pts = [ [-rec_w*10., -rec_h*10.], [-rec_w*10., rec_h*10.], [rec_w*10., rec_h*10.], [rec_w*10.,-rec_h*10.] ]
slices = 4
entt+='\n- entity:\n'
entt+=' name: virtual_target_e\n'
entt+=' primary: 0\n'
if hemisphere=='North':
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y-5., z], [-90.-tilt, 0, 0])
else:
entt+=' transform: { translation: %s, rotation: %s }\n' % ([x, y+5., z], [90.+tilt, 0, 0])
entt+=' geometry: \n'
entt+=' - material: *%s\n' % 'material_virtual'
entt+=' plane: \n'
entt+=' clip: \n'
entt+=' - operation: AND \n'
entt+=' vertices: %s\n' % pts
entt+=' slices: %d\n' % slices
rcv=''
rcv+='- name: STL_receiver_e \n'
rcv+=' side: %s \n' % 'FRONT_AND_BACK'
rcv+=' per_primitive: %s \n' % 'INCOMING_AND_ABSORBED'
rcv+='- name: virtual_target_e \n'
rcv+=' side: %s \n' % 'FRONT'
rcv+=' per_primitive: %s \n' % 'INCOMING'
return entt, rcv
def multi_aperture_receiver(rec_param, hemisphere='North', plot=False):
"""
hemisphere : 'North' or 'South' hemisphere of the earth where the field located
if North: the field is in the positive y direction
if South: the field is in the negtive y direction
this will influence:
(1) the setting of the receiver tilt angle,
if the front surface always facing to the field is desirable
(2) the position of the virtual target
"""
# rec_w and rec_h is the size of one aperture
# rec_grid_w and rec_gird_h is the number of elements of one aperture
# rec_z is a list of the elevation height of the center of apertures
# rec_tilt is the tilt angle of each aperture (the default is facing to the horizon)
# num_aperture is the number of apertures
# gamma is the angular range of the multi-aperture configration
rec_w=rec_param[0]
rec_h=rec_param[1]
rec_grid_w=rec_param[2]
rec_grid_h=rec_param[3]
rec_z=rec_param[4]
rec_tilt=rec_param[5]
# receiver tilt angle:
# 0 is vertical
# the standby posiion of a plane in solstice is normal points to the +z axis
# rotation anagle, positive is anti-clockwise
num_aperture=int(rec_param[6])
gamma=rec_param[7] # angular range of the multi-aperture configration (deg)
geom=''
entt=''
vir_z=0.
for i in range(num_aperture):
pts=[ [-rec_w[i]*0.5, -rec_h[i]*0.5], [-rec_w[i]*0.5, rec_h[i]*0.5], [rec_w[i]*0.5, rec_h[i]*0.5], [rec_w[i]*0.5,-rec_h[i]*0.5] ]
geom+='- geometry: &%s\n' % 'target_g_%.0f\n'%(i)
geom+=' - material: *%s\n' % 'material_target'
geom+=' plane: \n'
geom+=' clip: \n'
geom+=' - operation: AND \n'
geom+=' vertices: %s\n' % pts
geom+=' slices: %d\n' % rec_grid_w
geom+='\n'
ang_pos, xc, yc=multi_aperture_pos(rec_w, gamma, num_aperture, i)
zc=rec_z[i]
vir_z+=zc
# CREATE a receiver entity from "target_g" geometry (primary = 0)
entt+='\n- entity:\n'
entt+=' name: target_e_%.0f\n'%(i)
entt+=' primary: 0\n'
if hemisphere=='North':
entt+=' transform: { translation: %s, rotation: %s }\n' % ([xc, yc, zc], [-90.-rec_tilt, 90.-ang_pos,0])
else:
entt+=' transform: { translation: %s, rotation: %s }\n' % ([-xc, -yc, zc], [90.+rec_tilt, 90.-ang_pos,0])
entt+=' geometry: *%s\n' % 'target_g_%.0f\n'%(i)
vir_z/=float(num_aperture)
# CREATE a virtual target entity from "target_g" geometry (primary = 0)
slices = 16
radius=vir_z*0.5
entt+='\n- entity:\n'
entt+=' name: virtual_target_e\n'
entt+=' primary: 0\n'
entt+=' transform: { translation: %s}\n' % ([0., 0., vir_z])
entt+=' geometry: \n'
entt+=' - material: *%s\n' % 'material_virtual'
entt+=' sphere: \n'
entt+=' radius: %s\n' % radius
entt+=' slices: %d\n' % slices
rcv=''
for i in range(num_aperture):
rcv+='- name: target_e_%.0f \n'%(i)
rcv+=' side: %s \n' % 'FRONT_AND_BACK'
rcv+=' per_primitive: %s \n' % 'INCOMING_AND_ABSORBED'
rcv+='- name: virtual_target_e \n'
rcv+=' side: %s \n' % 'FRONT'
rcv+=' per_primitive: %s \n' % 'INCOMING'
return geom, entt, rcv
#------------------------------