<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.1d3 20150301//EN" "http://jats.nlm.nih.gov/publishing/1.1d3/JATS-journalpublishing1.dtd">
<article article-type="research-article" dtd-version="1.1d3" xml:lang="en" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink">
<front>
<journal-meta>
<journal-id journal-id-type="nlm-ta">PLoS ONE</journal-id>
<journal-id journal-id-type="publisher-id">plos</journal-id>
<journal-id journal-id-type="pmc">plosone</journal-id>
<journal-title-group>
<journal-title>PLOS ONE</journal-title>
</journal-title-group>
<issn pub-type="epub">1932-6203</issn>
<publisher>
<publisher-name>Public Library of Science</publisher-name>
<publisher-loc>San Francisco, CA USA</publisher-loc>
</publisher>
</journal-meta>
<article-meta>
<article-id pub-id-type="publisher-id">PONE-D-20-19341</article-id>
<article-id pub-id-type="doi">10.1371/journal.pone.0240735</article-id>
<article-categories>
<subj-group subj-group-type="heading">
<subject>Research Article</subject>
</subj-group>
<subj-group subj-group-type="Discipline-v3">
<subject>Physical sciences</subject><subj-group><subject>Materials science</subject><subj-group><subject>Materials</subject><subj-group><subject>Optical materials</subject></subj-group></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Computer and information sciences</subject><subj-group><subject>Software engineering</subject><subj-group><subject>Computer software</subject><subj-group><subject>Open source software</subject></subj-group></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Engineering and technology</subject><subj-group><subject>Software engineering</subject><subj-group><subject>Computer software</subject><subj-group><subject>Open source software</subject></subj-group></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Science policy</subject><subj-group><subject>Open science</subject><subj-group><subject>Open source software</subject></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Engineering and technology</subject><subj-group><subject>Energy and power</subject><subj-group><subject>Alternative energy</subject><subj-group><subject>Photovoltaic power</subject></subj-group></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Engineering and technology</subject><subj-group><subject>Energy and power</subject><subj-group><subject>Alternative energy</subject></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Physical sciences</subject><subj-group><subject>Physics</subject><subj-group><subject>Classical mechanics</subject><subj-group><subject>Reflection</subject></subj-group></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Engineering and technology</subject><subj-group><subject>Equipment</subject><subj-group><subject>Optical equipment</subject><subj-group><subject>Mirrors</subject></subj-group></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Computer and information sciences</subject><subj-group><subject>Software engineering</subject><subj-group><subject>Software tools</subject></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Engineering and technology</subject><subj-group><subject>Software engineering</subject><subj-group><subject>Software tools</subject></subj-group></subj-group></subj-group><subj-group subj-group-type="Discipline-v3">
<subject>Engineering and technology</subject><subj-group><subject>Equipment</subject><subj-group><subject>Optical equipment</subject></subj-group></subj-group></subj-group></article-categories>
<title-group>
<article-title>OTSun, a python package for the optical analysis of solar-thermal collectors and photovoltaic cells with arbitrary geometry</article-title>
<alt-title alt-title-type="running-head">OTSun, a python package for the optical analysis of solar energy devices with arbitrary geometry</alt-title>
</title-group>
<contrib-group>
<contrib contrib-type="author" xlink:type="simple">
<contrib-id authenticated="true" contrib-id-type="orcid">http://orcid.org/0000-0001-8845-4290</contrib-id>
<name name-style="western">
<surname>Cardona</surname> <given-names>Gabriel</given-names></name>
<role content-type="https://casrai.org/credit/">Conceptualization</role>
<role content-type="https://casrai.org/credit/">Formal analysis</role>
<role content-type="https://casrai.org/credit/">Investigation</role>
<role content-type="https://casrai.org/credit/">Methodology</role>
<role content-type="https://casrai.org/credit/">Software</role>
<role content-type="https://casrai.org/credit/">Supervision</role>
<role content-type="https://casrai.org/credit/">Writing – original draft</role>
<role content-type="https://casrai.org/credit/">Writing – review &amp; editing</role>
<xref ref-type="aff" rid="aff001"><sup>1</sup></xref>
<xref ref-type="aff" rid="aff002"><sup>2</sup></xref>
</contrib>
<contrib contrib-type="author" corresp="yes" xlink:type="simple">
<contrib-id authenticated="true" contrib-id-type="orcid">http://orcid.org/0000-0003-0523-6904</contrib-id>
<name name-style="western">
<surname>Pujol-Nadal</surname> <given-names>Ramon</given-names></name>
<role content-type="https://casrai.org/credit/">Data curation</role>
<role content-type="https://casrai.org/credit/">Formal analysis</role>
<role content-type="https://casrai.org/credit/">Funding acquisition</role>
<role content-type="https://casrai.org/credit/">Investigation</role>
<role content-type="https://casrai.org/credit/">Project administration</role>
<role content-type="https://casrai.org/credit/">Validation</role>
<role content-type="https://casrai.org/credit/">Visualization</role>
<role content-type="https://casrai.org/credit/">Writing – original draft</role>
<xref ref-type="aff" rid="aff003"><sup>3</sup></xref>
<xref ref-type="corresp" rid="cor001">*</xref>
</contrib>
</contrib-group>
<aff id="aff001">
<label>1</label>
<addr-line>Departament de Ciències Matemàtiques i Informàtica, Universitat de les Illes Balears, Palma de Mallorca, Spain</addr-line>
</aff>
<aff id="aff002">
<label>2</label>
<addr-line>Institut des Sciences de l’Évolution, Université de Montpellier, Montpellier, France</addr-line>
</aff>
<aff id="aff003">
<label>3</label>
<addr-line>Departament d’Enginyeria Industrial i Construcció, Universitat de les Illes Balears, Palma de Mallorca, Spain</addr-line>
</aff>
<contrib-group>
<contrib contrib-type="editor" xlink:type="simple">
<name name-style="western">
<surname>Li</surname> <given-names>Fankang</given-names></name>
<role>Editor</role>
<xref ref-type="aff" rid="edit1"/>
</contrib>
</contrib-group>
<aff id="edit1">
<addr-line>Oak Ridge National Laboratory, UNITED STATES</addr-line>
</aff>
<author-notes>
<fn fn-type="conflict" id="coi001">
<p>The authors have declared that no competing interests exist.</p>
</fn>
<corresp id="cor001">* E-mail: <email xlink:type="simple">ramon.pujol@uib.es</email></corresp>
</author-notes>
<pub-date pub-type="collection">
<year>2020</year>
</pub-date>
<pub-date pub-type="epub">
<day>14</day>
<month>10</month>
<year>2020</year>
</pub-date>
<volume>15</volume>
<issue>10</issue>
<elocation-id>e0240735</elocation-id>
<history>
<date date-type="received">
<day>23</day>
<month>6</month>
<year>2020</year>
</date>
<date date-type="accepted">
<day>1</day>
<month>10</month>
<year>2020</year>
</date>
</history>
<permissions>
<copyright-year>2020</copyright-year>
<copyright-holder>Cardona, Pujol-Nadal</copyright-holder>
<license xlink:href="http://creativecommons.org/licenses/by/4.0/" xlink:type="simple">
<license-p>This is an open access article distributed under the terms of the <ext-link ext-link-type="uri" xlink:href="http://creativecommons.org/licenses/by/4.0/" xlink:type="simple">Creative Commons Attribution License</ext-link>, which permits unrestricted use, distribution, and reproduction in any medium, provided the original author and source are credited.</license-p>
</license>
</permissions>
<self-uri content-type="pdf" xlink:href="info:doi/10.1371/journal.pone.0240735"/>
<abstract>
<p>Ray tracing software systems are commonly used to analyze the optics of solar energy devices, since they allow to predict the energy gains of devices in real conditions, and also to compare them with other systems constantly emerging in the market. However, the available open-source packages apply excessive simplifications to the model of light-matter interaction, making that the optical behaviour of the systems can not be properly characterized, which in turn implies disagreements between physical experiments and computer simulations. We present here the open source python package OTSun, which applies the Fresnel equations in their most general form, without further simplifications, and is suitable for the simulation of both solar-thermal and photovoltaic systems. The geometrical objects used in this package are created using the parametric 3D modeler FreeCAD, which is also a free and open source program and allows for the construction of arbitrary geometries that can be analyzed with OTSun. These, and other software capabilities, make OTSun extremely flexible and accurate for the optical analysis of solar devices with arbitrary geometry. Additionally, OTSun has a companion webtool, OTSunWebApp, that allows for the usage of certain features of the package without the need to install anything locally. We also show here two numerical experiments that we performed in order to validate the model and implementation: The analysis of the optical efficiency of a Linear Fresnel Reflector (with moving objects), and of a second surface mirror (with variable wavelengths). In each case, the numerical computations had deviations of less than 0.25% from reference models (either computed with another program or with exact formulas).</p>
</abstract>
<funding-group>
<award-group id="award001">
<funding-source>
<institution>Ministerio de Economía y Competitividad, Gobierno de España (ES)</institution>
</funding-source>
<award-id>ENE2015-68339-R</award-id>
</award-group>
<award-group id="award002">
<funding-source>
<institution-wrap>
<institution-id institution-id-type="funder-id">http://dx.doi.org/10.13039/501100011033</institution-id>
<institution>Agencia Estatal de Investigación</institution>
</institution-wrap>
</funding-source>
<award-id>ENE2015–68339-R</award-id>
</award-group>
<award-group id="award003">
<funding-source>
<institution-wrap>
<institution-id institution-id-type="funder-id">http://dx.doi.org/10.13039/501100008530</institution-id>
<institution>European Regional Development Fund</institution>
</institution-wrap>
</funding-source>
</award-group>
<funding-statement>The work was funded by the Spanish Ministry of Economy and Competitiveness [grant number ENE2015–68339-R], AEI and the European Regional Development Fund, European Union. The funders had no role in study design, data collection and analysis, decision to publish, or preparation of the manuscript.</funding-statement>
</funding-group>
<counts>
<fig-count count="4"/>
<table-count count="1"/>
<page-count count="15"/>
</counts>
<custom-meta-group>
<custom-meta id="data-availability">
<meta-name>Data Availability</meta-name>
<meta-value>The otsun package is available at (<ext-link ext-link-type="uri" xlink:href="https://github.com/bielcardona/OTSun" xlink:type="simple">https://github.com/bielcardona/OTSun</ext-link>). The scripts and auxiliary files used in the Model Validation section can be found at (<ext-link ext-link-type="uri" xlink:href="https://github.com/bielcardona/OTSunSuppMat" xlink:type="simple">https://github.com/bielcardona/OTSunSuppMat</ext-link>). The complete documentation of the API can be found at (<ext-link ext-link-type="uri" xlink:href="https://otsun.readthedocs.io" xlink:type="simple">https://otsun.readthedocs.io</ext-link>). The web tool OTSunWebApp is available at (<ext-link ext-link-type="uri" xlink:href="http://otsun.uib.es" xlink:type="simple">http://otsun.uib.es</ext-link>).</meta-value>
</custom-meta>
</custom-meta-group>
</article-meta>
</front>
<body>
<sec id="sec001" sec-type="intro">
<title>Introduction</title>
<p>There is a great variety of solar energy technologies [<xref ref-type="bibr" rid="pone.0240735.ref001">1</xref>], which, depending on the type of energy conversion, can be classified into two large groups: solar-thermal and photovoltaic technologies. The first one is intended to transfer heat, usually to a working fluid, that can be later converted into electricity. The second one is intended to directly generate electricity. Moreover, there are also mixed solar technologies (PVT) that perform both types of energy conversion. Furthermore, and regardless of the solar collector technology, the solar energy device can also be considered as an optical system, designed to maximize the absorption of solar radiation. Thus, the optical characterization of such devices is the key underpinning for improving solar energy conversion technologies [<xref ref-type="bibr" rid="pone.0240735.ref002">2</xref>].</p>
<p>In addition, with the increase of CPU and GPU capacities, simulations based on ray tracing of light are the most suitable techniques to obtain accurate results, since they allow for considering realistic configurations, with complex geometries and novel materials, and also enable to model different types of light sources [<xref ref-type="bibr" rid="pone.0240735.ref003">3</xref>]. In fact, the Monte Carlo Forward Ray Tracing (MCFRT) is the most used method for ray tracing simulations. It consists on applying the geometrical optics equations to the rays emitted from a light source to determine its interaction with an optical system (the solar energy device). At the end, the more realistic they are the optical models implemented in the MCFRT, the more diversity of solar energy materials can be considered for the optical system construction. This is the case of implementing the optical Fresnel equations to determine the path trajectory of the rays traveling through the system having into account: the ray wavelength, the light polarization, the complex refraction index and other physical properties of materials. With this method, several interesting parameters, such as the optical efficiency, flux irradiation and charge carrier generation, can be accurately determined. It is important to mention that rigorous optical models are needed to elucidate the optical behavior of a solar optical system.</p>
<p>Focusing on solar thermal applications, a review of existing optical simulation tools used for Solar Central Receiver Systems (SCRS) was recently presented in [<xref ref-type="bibr" rid="pone.0240735.ref003">3</xref>]. In this review, a total of 18 different software bundles have been analyzed. At present, only three of them, Tonatiuh [<xref ref-type="bibr" rid="pone.0240735.ref004">4</xref>], HOpS [<xref ref-type="bibr" rid="pone.0240735.ref005">5</xref>] and SolTrace [<xref ref-type="bibr" rid="pone.0240735.ref006">6</xref>], are licensed as open source. Another recent study focused in solar thermal applications was realized in the context of IEA/SHC Task 49 “Solar Heat Integration in Industrial Processes” [<xref ref-type="bibr" rid="pone.0240735.ref007">7</xref>], where a round-robin ray tracing software comparison for Linear Focusing Solar Collectors (LFSC) was done. In this study, the main differences between the software packages under study were found in how they model the angular dependency of the optical properties of the materials. As a consequence, different modeling options by different software tools produced different values of optical efficiency. The main reason is that they implement simplified models of optical Fresnel equations, instead of implementing them in its generic form.</p>
<p>On the photovoltaic applications side, optical simulation tools based on MCFRT for solar cells are also used [<xref ref-type="bibr" rid="pone.0240735.ref008">8</xref>]. While there are many proprietary software packages, for example, CROWM [<xref ref-type="bibr" rid="pone.0240735.ref009">9</xref>], actually, to the best knowledge of the authors, Scientrace [<xref ref-type="bibr" rid="pone.0240735.ref010">10</xref>] is the only open-source ray tracing software focused on photovoltaic cells [<xref ref-type="bibr" rid="pone.0240735.ref011">11</xref>].</p>
<p>It should be noted that some of the commercial software packages can be used for both solar-thermal and photovoltaic cells technologies, but no open source software has been found that applies to both technologies. Related to this, we mention here some proprietary packages that apply Fresnel equations: OptiCAD [<xref ref-type="bibr" rid="pone.0240735.ref012">12</xref>], ZEMAX [<xref ref-type="bibr" rid="pone.0240735.ref013">13</xref>], ASAP [<xref ref-type="bibr" rid="pone.0240735.ref014">14</xref>], TracePro [<xref ref-type="bibr" rid="pone.0240735.ref015">15</xref>], and COMSOL [<xref ref-type="bibr" rid="pone.0240735.ref016">16</xref>]. In all of them, the optical efficiency and radiance flux can be determined, among others parameters. However, we want to emphasize the importance of having open source software, since this allows for the inspection, modification, and implementation of new capabilities by the scientific community, which gives transparency and added value to the tool.</p>
<p>In this setting, our contribution with the development of OTSun is twofold. On the one hand, we cover the absence of open source software that is focused on both solar technologies (thermal and photovoltaic). On the second hand, we implement the Fresnel equations in their most general form, without further simplifications, avoiding the aforementioned problem reported in [<xref ref-type="bibr" rid="pone.0240735.ref007">7</xref>]. The OTSun package uses FreeCAD [<xref ref-type="bibr" rid="pone.0240735.ref017">17</xref>], a free 3D CAD system, in order to model the geometry of the optical systems to be analyzed, and also uses its API to compute the intersections of rays with the scene. FreeCAD is open sourced and permits to work with open file formats such as STEP, STL, DXF, and OBJ.</p>
<p>OTSun is a python package, open sourced under the MIT license. It can be obtained from the public repository <ext-link ext-link-type="uri" xlink:href="https://github.com/bielcardona/OTSun" xlink:type="simple">https://github.com/bielcardona/OTSun</ext-link>, and can also be installed directly from the Python Package Index (PyPI) by calling <monospace>pip install otsun</monospace>.</p>
<p>We also remark the existence of the web tool OTSunWebApp, publicly available at <ext-link ext-link-type="uri" xlink:href="http://otsun.uib.es" xlink:type="simple">http://otsun.uib.es</ext-link>, which has been developed to allow for making experiments without having to install anything. Some tutorials for this tool can be found in [<xref ref-type="bibr" rid="pone.0240735.ref018">18</xref>].</p>
<p>The aim of this paper is to give a full overview of the OTSun package. In Section Background, we give a brief account of the theory of geometrical optics and describe the algorithm we have used as a basis for our model. Section Implementation gives an overall view of the implementation of the different modules in the OTSun package. In Section The Model validation, we exhibit some experiments we have performed to validate our models and implementations. We conclude this manuscript with some final remarks in Section Conclusion.</p>
</sec>
<sec id="sec002" sec-type="intro">
<title>Background</title>
<p>The so-called ray tracing method is used to calculate the trajectory of light rays through systems composed by objects with different geometrical and optical properties. In the framework of solar energy, this implies that the optical efficiency of systems can be assessed by computer simulation. Two major elements are required for this purpose. First, a mathematical theory of optics. Second, an algorithm for the simulation of pathways of rays emitted in the system. These two main elements, which constitute the theoretical basis of OTSun, are described in the following subsections.</p>
<sec id="sec003">
<title>Geometrical optics</title>
<p>Geometrical optics is a model that describes the propagation of light in terms of rays (see [<xref ref-type="bibr" rid="pone.0240735.ref019">19</xref>]). This model can be figured out from approximate solutions of Maxwell’s equations and is valid whenever the waves of light are propagated across and around objects with dimensions greater than the wavelength. Hence, ray theory does not cover phenomena such as interference and diffraction, but notice that OTSun is supplemented by the 1D transform matrix method (TMM) to consider interference in thin films (see item <monospace>PolarizedThinFilm</monospace> in Section The <monospace>Material</monospace> class).</p>
<p>The first main ingredient in this model is given by the Lambert-Beers law, which states that the initial and final energies (<italic>E</italic><sub>0</sub> and <italic>E</italic>, respectively) of a ray with wavelength λ traveling a distance ℓ inside an optical medium are related by the equation
<disp-formula id="pone.0240735.e001"><alternatives><graphic id="pone.0240735.e001g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e001" xlink:type="simple"/><mml:math display="block" id="M1"><mml:mtable displaystyle="true"><mml:mtr><mml:mtd columnalign="right"><mml:mrow><mml:mi>E</mml:mi> <mml:mo>=</mml:mo> <mml:msub><mml:mi>E</mml:mi> <mml:mn>0</mml:mn></mml:msub> <mml:msup><mml:mi>e</mml:mi> <mml:mrow><mml:mo>-</mml:mo> <mml:mi>α</mml:mi> <mml:mo>(</mml:mo> <mml:mo>λ</mml:mo> <mml:mo>)</mml:mo> <mml:mi>ℓ</mml:mi></mml:mrow></mml:msup> <mml:mo>,</mml:mo></mml:mrow></mml:mtd></mml:mtr></mml:mtable></mml:math></alternatives> <label>(1)</label></disp-formula>
where <italic>α</italic>(λ) = 4<italic>πk</italic>(λ) is the absorption coefficient of the medium.</p>
<p>The second main ingredient establishes what happens when a ray hits a surface delimiting two different optical media. In this case, different phenomena can take place, since the ray may get absorbed, reflected or transmitted (or a combination of those). In either case, this models determines the ray direction in the new medium <inline-formula id="pone.0240735.e002"><alternatives><graphic id="pone.0240735.e002g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e002" xlink:type="simple"/><mml:math display="inline" id="M2"><mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>2</mml:mn></mml:msub></mml:math></alternatives></inline-formula> in terms of the initial ray direction <inline-formula id="pone.0240735.e003"><alternatives><graphic id="pone.0240735.e003g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e003" xlink:type="simple"/><mml:math display="inline" id="M3"><mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>1</mml:mn></mml:msub></mml:math></alternatives></inline-formula> and <inline-formula id="pone.0240735.e004"><alternatives><graphic id="pone.0240735.e004g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e004" xlink:type="simple"/><mml:math display="inline" id="M4"><mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>→</mml:mo></mml:mover></mml:math></alternatives></inline-formula>, the unit vector normal to the surface at the point of incidence, and pointing towards the first medium. The vector <inline-formula id="pone.0240735.e005"><alternatives><graphic id="pone.0240735.e005g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e005" xlink:type="simple"/><mml:math display="inline" id="M5"><mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>1</mml:mn></mml:msub></mml:math></alternatives></inline-formula> also characterizes the incidence angle <italic>θ</italic><sub>1</sub> by means of the equation <inline-formula id="pone.0240735.e006"><alternatives><graphic id="pone.0240735.e006g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e006" xlink:type="simple"/><mml:math display="inline" id="M6"><mml:mrow><mml:mo form="prefix">cos</mml:mo> <mml:msub><mml:mi>θ</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo>=</mml:mo> <mml:mo>-</mml:mo> <mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>1</mml:mn></mml:msub> <mml:mo>·</mml:mo> <mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>→</mml:mo></mml:mover></mml:mrow></mml:math></alternatives></inline-formula>. Analogously, <inline-formula id="pone.0240735.e007"><alternatives><graphic id="pone.0240735.e007g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e007" xlink:type="simple"/><mml:math display="inline" id="M7"><mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>2</mml:mn></mml:msub></mml:math></alternatives></inline-formula> characterizes the reflection/refraction angle <italic>θ</italic><sub>2</sub> via <inline-formula id="pone.0240735.e008"><alternatives><graphic id="pone.0240735.e008g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e008" xlink:type="simple"/><mml:math display="inline" id="M8"><mml:mrow><mml:mo form="prefix">cos</mml:mo> <mml:msub><mml:mi>θ</mml:mi> <mml:mn>2</mml:mn></mml:msub> <mml:mo>=</mml:mo> <mml:mo>±</mml:mo> <mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>2</mml:mn></mml:msub> <mml:mo>·</mml:mo> <mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>→</mml:mo></mml:mover></mml:mrow></mml:math></alternatives></inline-formula>, where the sign is positive in case of reflection and negative in case of refraction.</p>
<p>In case of reflection, the new ray direction is given by the law of reflection:
<disp-formula id="pone.0240735.e009"><alternatives><graphic id="pone.0240735.e009g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e009" xlink:type="simple"/><mml:math display="block" id="M9"><mml:mtable displaystyle="true"><mml:mtr><mml:mtd columnalign="right"><mml:mrow><mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>2</mml:mn></mml:msub> <mml:mo>=</mml:mo> <mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>1</mml:mn></mml:msub> <mml:mo>+</mml:mo> <mml:mn>2</mml:mn> <mml:mo form="prefix">cos</mml:mo> <mml:msub><mml:mi>θ</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mo>.</mml:mo></mml:mrow></mml:mtd></mml:mtr></mml:mtable></mml:math></alternatives> <label>(2)</label></disp-formula></p>
<p>If the ray is refracted (transmitted) the new ray direction <inline-formula id="pone.0240735.e010"><alternatives><graphic id="pone.0240735.e010g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e010" xlink:type="simple"/><mml:math display="inline" id="M10"><mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>2</mml:mn></mml:msub></mml:math></alternatives></inline-formula> is then given by the Snell’s law:
<disp-formula id="pone.0240735.e011"><alternatives><graphic id="pone.0240735.e011g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e011" xlink:type="simple"/><mml:math display="block" id="M11"><mml:mtable displaystyle="true"><mml:mtr><mml:mtd columnalign="right"><mml:mrow><mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>2</mml:mn></mml:msub> <mml:mo>=</mml:mo> <mml:mi>r</mml:mi> <mml:msub><mml:mover accent="true"><mml:mi>v</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mn>1</mml:mn></mml:msub> <mml:mo>+</mml:mo> <mml:mo>(</mml:mo> <mml:mi>r</mml:mi> <mml:mo form="prefix">cos</mml:mo> <mml:msub><mml:mi>θ</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo>-</mml:mo> <mml:msqrt><mml:mrow><mml:mn>1</mml:mn> <mml:mo>-</mml:mo> <mml:msup><mml:mi>r</mml:mi> <mml:mn>2</mml:mn></mml:msup> <mml:msup><mml:mo form="prefix">sin</mml:mo> <mml:mn>2</mml:mn></mml:msup> <mml:msub><mml:mi>θ</mml:mi> <mml:mn>1</mml:mn></mml:msub></mml:mrow></mml:msqrt> <mml:mo>)</mml:mo> <mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mo>.</mml:mo></mml:mrow></mml:mtd></mml:mtr></mml:mtable></mml:math></alternatives> <label>(3)</label></disp-formula></p>
<p>In this equation, <inline-formula id="pone.0240735.e012"><alternatives><graphic id="pone.0240735.e012g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e012" xlink:type="simple"/><mml:math display="inline" id="M12"><mml:mrow><mml:mi>r</mml:mi> <mml:mo>=</mml:mo> <mml:mo form="prefix">Re</mml:mo> <mml:mo>(</mml:mo> <mml:msub><mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mn>1</mml:mn></mml:msub> <mml:mo>/</mml:mo> <mml:msub><mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mn>2</mml:mn></mml:msub> <mml:mo>)</mml:mo></mml:mrow></mml:math></alternatives></inline-formula>, where <inline-formula id="pone.0240735.e013"><alternatives><graphic id="pone.0240735.e013g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e013" xlink:type="simple"/><mml:math display="inline" id="M13"><mml:mrow><mml:msub><mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mi>i</mml:mi></mml:msub> <mml:mrow><mml:mo>(</mml:mo> <mml:mo>λ</mml:mo> <mml:mo>)</mml:mo></mml:mrow> <mml:mo>=</mml:mo> <mml:msub><mml:mi>n</mml:mi> <mml:mi>i</mml:mi></mml:msub> <mml:mrow><mml:mo>(</mml:mo> <mml:mo>λ</mml:mo> <mml:mo>)</mml:mo></mml:mrow> <mml:mo>-</mml:mo> <mml:mi>i</mml:mi> <mml:msub><mml:mi>k</mml:mi> <mml:mi>i</mml:mi></mml:msub> <mml:mrow><mml:mo>(</mml:mo> <mml:mo>λ</mml:mo> <mml:mo>)</mml:mo></mml:mrow></mml:mrow></mml:math></alternatives></inline-formula> (for <italic>i</italic> = 1, 2) is the complex refractive index in each of the two media. Finally, Fresnel’s equations give the reflectance <italic>R</italic> and transmittance <italic>T</italic> rates for the energy of incident rays as follows (we have used the formalism exposed in [<xref ref-type="bibr" rid="pone.0240735.ref020">20</xref>, Ch. 2]):
<disp-formula id="pone.0240735.e014"><alternatives><graphic id="pone.0240735.e014g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e014" xlink:type="simple"/><mml:math display="block" id="M14"><mml:mtable displaystyle="true"><mml:mtr><mml:mtd columnalign="right"><mml:mi>R</mml:mi><mml:mrow><mml:mo>=</mml:mo> <mml:mo>(</mml:mo> <mml:mfrac><mml:mrow><mml:msub><mml:mi>η</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo>-</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>2</mml:mn></mml:msub></mml:mrow> <mml:mrow><mml:msub><mml:mi>η</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo>+</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>2</mml:mn></mml:msub></mml:mrow></mml:mfrac> <mml:mo>)</mml:mo> <mml:msup><mml:mrow><mml:mo>(</mml:mo> <mml:mfrac><mml:mrow><mml:msub><mml:mi>η</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo>-</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>2</mml:mn></mml:msub></mml:mrow> <mml:mrow><mml:msub><mml:mi>η</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo>+</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>2</mml:mn></mml:msub></mml:mrow></mml:mfrac> <mml:mo>)</mml:mo></mml:mrow> <mml:mo>*</mml:mo></mml:msup> <mml:mo>,</mml:mo></mml:mrow></mml:mtd></mml:mtr></mml:mtable></mml:math></alternatives> <label>(4)</label></disp-formula>
<disp-formula id="pone.0240735.e015"><alternatives><graphic id="pone.0240735.e015g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e015" xlink:type="simple"/><mml:math display="block" id="M15"><mml:mtable displaystyle="true"><mml:mtr><mml:mtd columnalign="right"><mml:mi>T</mml:mi><mml:mrow><mml:mo>=</mml:mo> <mml:mfrac><mml:mrow><mml:mn>4</mml:mn> <mml:msub><mml:mi>η</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo form="prefix">Re</mml:mo> <mml:mrow><mml:mo>(</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>2</mml:mn></mml:msub> <mml:mo>)</mml:mo></mml:mrow></mml:mrow> <mml:mrow><mml:mrow><mml:mo>(</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo>+</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>2</mml:mn></mml:msub> <mml:mo>)</mml:mo></mml:mrow> <mml:msup><mml:mrow><mml:mo>(</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>1</mml:mn></mml:msub> <mml:mo>+</mml:mo> <mml:msub><mml:mi>η</mml:mi> <mml:mn>2</mml:mn></mml:msub> <mml:mo>)</mml:mo></mml:mrow> <mml:mo>*</mml:mo></mml:msup></mml:mrow></mml:mfrac> <mml:mo>,</mml:mo></mml:mrow></mml:mtd></mml:mtr></mml:mtable></mml:math></alternatives> <label>(5)</label></disp-formula>
where <italic>η</italic><sub>1</sub> and <italic>η</italic><sub>2</sub> are the tilted optical admittances of the two optical media, and they depend on the polarization of the incident light:
<disp-formula id="pone.0240735.e016"><alternatives><graphic id="pone.0240735.e016g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e016" xlink:type="simple"/><mml:math display="block" id="M16"><mml:mtable displaystyle="true"><mml:mtr><mml:mtd columnalign="right"><mml:mrow><mml:msub><mml:mi>η</mml:mi> <mml:mi>i</mml:mi></mml:msub> <mml:mo>=</mml:mo> <mml:mo>{</mml:mo> <mml:mtable><mml:mtr><mml:mtd columnalign="left"><mml:mrow><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mfrac><mml:mrow><mml:msub><mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mi>i</mml:mi></mml:msub> <mml:mrow><mml:mo>(</mml:mo> <mml:mo>λ</mml:mo> <mml:mo>)</mml:mo></mml:mrow> <mml:mo form="prefix">cos</mml:mo> <mml:msub><mml:mi>θ</mml:mi> <mml:mi>i</mml:mi></mml:msub></mml:mrow> <mml:msub><mml:mi>Z</mml:mi> <mml:mn>0</mml:mn></mml:msub></mml:mfrac></mml:mstyle> <mml:mo>,</mml:mo></mml:mrow></mml:mtd> <mml:mtd columnalign="left"><mml:mrow><mml:mtext>for</mml:mtext><mml:mspace width="4pt"/><mml:mi mathvariant="normal">s</mml:mi> <mml:mo>-</mml:mo> <mml:mtext>polarization</mml:mtext> <mml:mo>,</mml:mo></mml:mrow></mml:mtd></mml:mtr> <mml:mtr><mml:mtd columnalign="left"><mml:mrow><mml:mstyle displaystyle="true" scriptlevel="0"><mml:mfrac><mml:mrow><mml:msub><mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mi>i</mml:mi></mml:msub> <mml:mrow><mml:mo>(</mml:mo> <mml:mo>λ</mml:mo> <mml:mo>)</mml:mo></mml:mrow></mml:mrow> <mml:mrow><mml:msub><mml:mi>Z</mml:mi> <mml:mn>0</mml:mn></mml:msub> <mml:mo form="prefix">cos</mml:mo> <mml:msub><mml:mi>θ</mml:mi> <mml:mi>i</mml:mi></mml:msub></mml:mrow></mml:mfrac></mml:mstyle> <mml:mo>,</mml:mo></mml:mrow></mml:mtd> <mml:mtd columnalign="left"><mml:mrow><mml:mtext>for</mml:mtext><mml:mspace width="4pt"/><mml:mi mathvariant="normal">p</mml:mi><mml:mo>-</mml:mo> <mml:mtext>polarization</mml:mtext> <mml:mo>,</mml:mo></mml:mrow></mml:mtd></mml:mtr></mml:mtable> <mml:mo/></mml:mrow></mml:mtd></mml:mtr></mml:mtable></mml:math></alternatives> <label>(6)</label></disp-formula>
being <inline-formula id="pone.0240735.e017"><alternatives><graphic id="pone.0240735.e017g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e017" xlink:type="simple"/><mml:math display="inline" id="M17"><mml:mrow><mml:msub><mml:mi>Z</mml:mi> <mml:mn>0</mml:mn></mml:msub> <mml:mo>=</mml:mo> <mml:msqrt><mml:mrow><mml:msub><mml:mi>μ</mml:mi> <mml:mn>0</mml:mn></mml:msub> <mml:mo>/</mml:mo> <mml:msub><mml:mi>∈</mml:mi> <mml:mn>0</mml:mn></mml:msub></mml:mrow></mml:msqrt></mml:mrow></mml:math></alternatives></inline-formula> the optical impedance of free space.</p>
</sec>
<sec id="sec004">
<title>The ray tracing algorithm</title>
<p>The key ingredients for any ray tracing simulation are shown in <xref ref-type="fig" rid="pone.0240735.g001">Fig 1</xref>. The light source is the geometric region from where rays are emitted to the scene. The optical system is formed by different elements that interact with the rays, some of which are made of absorber materials that capture energy. In our implementation, the optical system is composed by surface and volume elements generated by FreeCAD, and each of them must be associated to an optical material (otherwise it will not interact with light rays). Two kinds of special materials are implemented for defining the absorber material: thermal materials (for solar-thermal collectors) and the PV materials (the active materials of photovoltaic cells). See Section Implementation for details on how we implement all these ingredients.</p>
<fig id="pone.0240735.g001" position="float">
<object-id pub-id-type="doi">10.1371/journal.pone.0240735.g001</object-id>
<label>Fig 1</label>
<caption>
<title>Overview of the key elements of the ray tracing procedure.</title>
<p>The scene is composed by the optical system, formed by FreeCAD volume and surface elements. On the scene, at least one material has the functionality of light absorption. The light source emits rays to the scene.</p>
</caption>
<graphic mimetype="image" position="float" xlink:href="info:doi/10.1371/journal.pone.0240735.g001" xlink:type="simple"/>
</fig>
<p>An overview of the algorithm for the tracing of each single ray is shown in <xref ref-type="fig" rid="pone.0240735.g002">Fig 2</xref>. The path followed by a ray is composed of several “hops”, corresponding to different rectilinear segments where the ray moves inside a fixed optical medium. The algorithm starts with the simulation of the emission of a ray from the light source. The point of emission, direction, polarization and wavelength are determined by the light source, while the energy is normalized to be unitary. Then, we sequentially simulate hops, determined by the interaction of the ray with the scene as follows. First, we find the closest intersection of the simulated ray with the scene; in case no intersection is found, then the ray has exited the scene and the tracing is finished. In case we find such an intersection, we update the energy level of the ray at this point, since it could have been traveling inside a dissipative medium during the current hop; also, and in the case that this medium is a “PV material”, we compute the collected energy for future computations. Next, we determine if the ray has been absorbed at the point of intersection, either by having found a “Thermal material” (and in this case we compute the absorbed energy for future computations) or some other absorbent material; in any case, the ray tracing is finished. Likewise, if the energy level of the ray is below a threshold (by default 10<sup>−6</sup>), the ray is assumed to have disappeared and the tracing is finished too. Furthermore, we check if the number of hops has reached its maximum (200 hops by default), in which case we determine that the ray has been caught in a loop and stop the simulation. Otherwise, and since at this point the tracing of the ray has to continue, we simulate the optical effect (either reflection or refraction) of the materials on the ray to compute its new direction and polarization, and proceed to the simulation of the next hop.</p>
<fig id="pone.0240735.g002" position="float">
<object-id pub-id-type="doi">10.1371/journal.pone.0240735.g002</object-id>
<label>Fig 2</label>
<caption>
<title>Overview of the sequential ray tracing algorithm.</title>
</caption>
<graphic mimetype="image" position="float" xlink:href="info:doi/10.1371/journal.pone.0240735.g002" xlink:type="simple"/>
</fig>
</sec>
</sec>
<sec id="sec005">
<title>Implementation</title>
<p>The python package OTSun (imported as <monospace>otsun</monospace>) is composed by different modules, some of them collecting helper functions that implement both mathematical and optical methods, and other ones built around each of the main classes that define the functionality of the package. To ease the reading of this section, where we shall be dealing with classes and instances of those classes, whenever a class (say <monospace>Scene</monospace> or <monospace>LightSource</monospace>) is considered, the downcase version of their identifiers (<monospace>scene</monospace> and <monospace>light_source</monospace> in our example) will indicate instances of those classes. Except for those classes defined by FreeCAD (like <monospace>Part.Face</monospace> or <monospace>Base.Vector</monospace>), we refer to the corresponding section in this manuscript for the definition and initialization options for each of these classes. For instance, in Section The <monospace>Experiment</monospace> class we explain how to create an <monospace>experiment</monospace> (an instance of the <monospace>Experiment</monospace> class), giving an <monospace>scene</monospace> and a <monospace>light_source</monospace>, which are instances of <monospace>Scene</monospace> and <monospace>LightSource</monospace>, described in Sections The <monospace>Scene</monospace> class and The <monospace>LightSource</monospace> class, respectively.</p>
<p>A typical use of the package involves the creation of an <monospace>experiment</monospace>, which specifies the solar optics experiment to be run, defined by certain data that includes a <monospace>scene</monospace> and a <monospace>light_source</monospace>. The <monospace>scene</monospace> holds the data of all the different objects that interact with light rays, included in a FreeCAD document [<xref ref-type="bibr" rid="pone.0240735.ref017">17</xref>], and where each of them has a <monospace>material</monospace> associated describing its optical behaviour. Eventually, some objects may have movements, implemented by a <monospace>multi_tracking</monospace>, and in such a case these elements will be moved to maximize the absorbed energy. When the experiment is run, the <monospace>light_source</monospace> creates <monospace>ray</monospace>s, which interact with the scene until they either leave the scene or are absorbed, and in this last case the collected energy (among other data) is stored for future analysis.</p>
<p>We comment now the main classes that have been implemented, together with its basic functionality. The complete documentation of the API can be found at <ext-link ext-link-type="uri" xlink:href="https://otsun.readthedocs.io" xlink:type="simple">https://otsun.readthedocs.io</ext-link>.</p>
<sec id="sec006">
<title>The <monospace>Experiment</monospace> class</title>
<p>An <monospace>experiment</monospace> is initialized giving the parameters that define it: An <monospace>scene</monospace> and a <monospace>light_source</monospace> that describe the physical environment where the experiment takes place, and the number of rays that have to be simulated. The execution of the experiment is launched with the <monospace>experiment.run()</monospace> method, and once it is finished, the information that has been recollected is found in instance variables like <monospace>experiment.captured_energy_Th</monospace> and <monospace>experiment.captured_energy_PV</monospace>, that give the overall thermal and photovoltaic (respectively) energy that has been collected by the active materials found in the scene.</p>
</sec>
<sec id="sec007">
<title>The <monospace>Scene</monospace> class</title>
<p>Instances of the class <monospace>Scene</monospace> hold the data used to describe the physical objects present in an experiment, stored in three main variables, <monospace>faces</monospace>, <monospace>solids</monospace> and <monospace>materials</monospace>. Each object in the array <monospace>faces</monospace> (resp. <monospace>solids</monospace>) is a <monospace>Part.Face</monospace> (resp. <monospace>Part.Solid</monospace>) object of FreeCAD that represents a surface (resp. volume) that can affect the propagation of a ray incident with it. The dictionary <monospace>materials</monospace> assigns to each face or solid a <monospace>material</monospace> that describes its optical properties.</p>
<p>Such a <monospace>scene</monospace> is initialized with an array <monospace>objects</monospace>, all whose elements are instances of <monospace>Part.Feature</monospace>, and typically they are all the objects included in a FreeCAD document. The assignation of materials to each object is done by looking at its label. Namely, if an object <monospace>obj</monospace> in a FreeCAD document has a label of the form “Label<monospace>(mat_name)</monospace>”, then the assigned material <monospace>scene.materials[obj]</monospace> will be the <monospace>Material</monospace> instance <monospace>mat</monospace> such that <monospace>mat.name</monospace> is <monospace>mat_name</monospace>.</p>
<p>For instance, the file <monospace>ParabolicTrough.FCStd</monospace> in the public repository <ext-link ext-link-type="uri" xlink:href="https://github.com/bielcardona/OTSunSuppMat" xlink:type="simple">https://github.com/bielcardona/OTSunSuppMat</ext-link> (see also Section The <monospace>MultiTracking</monospace> class) contains a model prepared to analyze a parabolic trough collector. The parabolic mirror (in blue) is made by extruding a parabolic segment, and its label is <monospace>Parabolic_reflector(Mir1)</monospace>. It means that when imported with OTSun, it will have an associated material whose parameter <monospace>name</monospace> is <monospace>Mir1</monospace>. In turn, this material has to be properly defined (see Section The <monospace>Material</monospace> class) so that it behaves as a mirror. Other elements in this model are the central cylindrical surface (in red), labeled <monospace>Cylindrical_absorber(Abs1)</monospace>, and its covering (in green), labeled <monospace>Tube_glass(Glass1)</monospace>; hence, materials named <monospace>Abs1</monospace> and <monospace>Glass1</monospace> have to be defined as an absorber surface and as a transparent volume material, respectively (see Section The <monospace>Material</monospace> class).</p>
</sec>
<sec id="sec008">
<title>The <monospace>LightSource</monospace> class</title>
<p>Instances of the class <monospace>LightSource</monospace> are used to model the source of rays in an experiment. There are many parameters that define its behaviour, like its <monospace>emitting_region</monospace>, describing the physical location of the source of the rays to be emitted, and its <monospace>light_spectrum</monospace> and <monospace>direction_distribution</monospace>, describing respectively the distribution of wavelengths and directions of the rays to be emitted.</p>
<p>The parameter <monospace>light_spectrum</monospace> can either be a constant, meaning that all rays will be emitted with the same specified wavelength (given in nanometers), or a cumulative distribution function (CDF) <italic>F</italic>(λ) which is defined by interpolation on the discrete values (λ<sub><italic>i</italic></sub>, <italic>F</italic>(λ<sub><italic>i</italic></sub>)) stored in an array ((λ<sub>1</sub>, λ<sub>2</sub>, …), (<italic>F</italic>(λ<sub>1</sub>), <italic>F</italic>(λ<sub>2</sub>) …).</p>
<p>The <monospace>emitting_region</monospace> has to be an instance of any class that implements the method <monospace>random_point()</monospace>, which returns a random point from where a ray will be emitted, and has an attribute <monospace>main_direction</monospace>, giving the direction of the emitted ray. For convenience, the class <monospace>SunWindow</monospace> implements such an emitting region as a plane rectangle <italic>Π</italic> in the space, orthogonal to a fixed direction <inline-formula id="pone.0240735.e018"><alternatives><graphic id="pone.0240735.e018g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e018" xlink:type="simple"/><mml:math display="inline" id="M18"><mml:mover accent="true"><mml:mi>u</mml:mi> <mml:mo>→</mml:mo></mml:mover></mml:math></alternatives></inline-formula>, and such that all the objects in the scene are contained in the rectangular semi-prism <inline-formula id="pone.0240735.e019"><alternatives><graphic id="pone.0240735.e019g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e019" xlink:type="simple"/><mml:math display="inline" id="M19"><mml:mrow><mml:mo>{</mml:mo> <mml:mi>Π</mml:mi> <mml:mo>+</mml:mo> <mml:mi>ξ</mml:mi> <mml:mover accent="true"><mml:mi>u</mml:mi> <mml:mo>→</mml:mo></mml:mover> <mml:mo>∣</mml:mo> <mml:mi>ξ</mml:mi> <mml:mo>≥</mml:mo> <mml:mn>0</mml:mn> <mml:mo>}</mml:mo></mml:mrow></mml:math></alternatives></inline-formula>.</p>
<p>The parameter <monospace>direction_distribution</monospace> can either be <monospace>None</monospace> (meaning that the emitted rays are emitted in the main direction) or an instance of a class that implements the method <monospace>angle_distribution()</monospace>, giving a random angle (in degrees) of deviation for the emitted ray with respect to the main direction <inline-formula id="pone.0240735.e020"><alternatives><graphic id="pone.0240735.e020g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e020" xlink:type="simple"/><mml:math display="inline" id="M20"><mml:mover accent="true"><mml:mi>u</mml:mi> <mml:mo>→</mml:mo></mml:mover></mml:math></alternatives></inline-formula>. For convenience, the class <monospace>BuieDistribution</monospace> implements such deviation according to the Buie distribution [<xref ref-type="bibr" rid="pone.0240735.ref021">21</xref>], determined by its circumsolar ratio (CSR), which is a parameter of the class.</p>
</sec>
<sec id="sec009">
<title>The <monospace>Ray</monospace> class</title>
<p>Instances of the class <monospace>Ray</monospace> model light rays, which are emitted by a <monospace>light_source</monospace>. A <monospace>ray</monospace> is initialized giving its initial <monospace>optical_state</monospace>, as well as the <monospace>scene</monospace> where it will travel. Instances of <monospace>OpticalState</monospace> gather some relevant information of a light ray at a given moment, like its <monospace>direction</monospace>, <monospace>polarization</monospace> and <monospace>material</monospace>, giving, respectively, the direction and polarization vector of the ray, and the material (optical medium) where it is traveling. When the method <monospace>ray.run()</monospace> is called, the propagation of the ray inside the scene starts to be simulated. A simplified version of the iteration process is (see also Section The ray tracing algorithm):</p>
<list list-type="order">
<list-item>
<p>Find the closest intersection of <monospace>ray</monospace> with objects in <monospace>scene</monospace>.</p>
</list-item>
<list-item>
<p>If no intersection is found, the <monospace>ray</monospace> is lost and the simulation is finished.</p>
</list-item>
<list-item>
<p>If the first intersection is with an object having a determined <monospace>material</monospace>, then the method <monospace>material.change_of_optical_state()</monospace> is called (with different parameters that determine how the ray hits the material), which decides if the ray is reflected or refracted (and gives the next optical state) or that the ray has been absorbed by some active optical element.</p>
</list-item>
<list-item>
<p>If the ray has been reflected or refracted, go to step 1. Otherwise, the simulation is finished.</p>
</list-item>
</list>
</sec>
<sec id="sec010">
<title>The <monospace>Material</monospace> class</title>
<p>The <monospace>Material</monospace> class is the most complex of all the classes implemented in OTSun, since there are many kinds of materials, and their optical properties need to be explicitly defined. There are two main subclasses, <monospace>SurfaceMaterial</monospace> and <monospace>VolumeMaterial</monospace>, corresponding, respectively, to materials that can be assumed to be two-dimensional (like first surface mirrors and selective absorbers) or not (like glasses, second surface mirrors, PV active materials, thin films,…). Any material has an important property, <monospace>material.name</monospace>, indicating how it will be called when identifying objects in a scene as explained in Section The <monospace>Scene</monospace> class. The physical properties of a <monospace>material</monospace> are encoded in <monospace>material.properties</monospace>, a dictionary whose contents depend on the kind of material.</p>
<p>Any user willing to use his own materials in his experiments can subclass <monospace>SurfaceMaterial</monospace> or <monospace>VolumeMaterial</monospace> to adapt the contents of <monospace>material.properties</monospace>, which implement the specific properties of the materials. The user must override the method <monospace>material.change_of_optical_state()</monospace> to implement the computation of how the interaction with the material changes the optical state (direction, polarization, etc.) of a ray.</p>
<p>Additionally, since it is interesting to store externally the properties of materials, the method <monospace>material.to_json()</monospace> and the class method <monospace>SubclassedMaterial.load_from_json(info)</monospace> should be implemented. The first one must convert any information stored in <monospace>material.properties</monospace> into a serializable dictionary, and the second one must use this dictionary to reconstruct the <monospace>material.properties</monospace> dictionary.</p>
<sec id="sec011">
<title>The <monospace>VolumeMaterial</monospace> class</title>
<p>Instances of <monospace>VolumeMaterial</monospace> represent the optical properties of physical objects whose depth is not negligible, like glasses or PV active materials, where the ray energy attenuation is determined by the Beer–Lambert law (<xref ref-type="disp-formula" rid="pone.0240735.e001">1</xref>). In this case, the method <monospace>material.change_of_optical_state()</monospace> is generically implemented using the law of reflection (<xref ref-type="disp-formula" rid="pone.0240735.e009">2</xref>), Snell’s law (<xref ref-type="disp-formula" rid="pone.0240735.e011">3</xref>), and Fresnel’s Eqs (<xref ref-type="disp-formula" rid="pone.0240735.e014">4</xref>)–(<xref ref-type="disp-formula" rid="pone.0240735.e016">6</xref>), but any user could subclass it and implement some other optical behaviour of the material.</p>
<p>Some subclasses of this class are provided, so that materials appearing usually in the field of solar collectors can be used without further implementation. For example:</p>
<list list-type="bullet">
<list-item>
<p>
<monospace>SimpleVolumeMaterial</monospace>, representing a material with constant optical parameters (refraction index and absorption coefficient, given in mm<sup>−1</sup>).</p>
</list-item>
<list-item>
<p>
<monospace>WavelengthVolumeMaterial</monospace>, where the index of refraction is complex (<inline-formula id="pone.0240735.e021"><alternatives><graphic id="pone.0240735.e021g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e021" xlink:type="simple"/><mml:math display="inline" id="M21"><mml:mrow><mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mo>=</mml:mo> <mml:mi>n</mml:mi> <mml:mo>-</mml:mo> <mml:mi>i</mml:mi> <mml:mi>κ</mml:mi></mml:mrow></mml:math></alternatives></inline-formula>) and depends on the wavelength of the ray. These values are computed by interpolation from data given in tabulated form with rows (λ, <italic>n</italic>(λ), <italic>κ</italic>(λ)). Note that the imaginary part of the refractive index is the so called the extinction coefficient, and the absorption coefficient is calculated as <italic>α</italic> = 4<italic>πκ</italic>/λ. The wavelengths are given in nanometers.</p>
</list-item>
<list-item>
<p>
<monospace>PolarizedThinFilm</monospace>, which represents a thin layer, such as an optical coating, where the thickness and light coherence (that enables interference) can not be considered as negligible in the simulation. The data values are given in tabulated form with rows (λ, <italic>θ</italic>, <italic>R</italic><sub><italic>s</italic></sub>(λ, <italic>θ</italic>), <italic>R</italic><sub><italic>p</italic></sub>(λ, <italic>θ</italic>), <italic>T</italic><sub><italic>s</italic></sub>(λ, <italic>θ</italic>), <italic>T</italic><sub><italic>p</italic></sub>(λ, <italic>θ</italic>)), where <italic>θ</italic> is the incidence angle, <italic>R</italic> and <italic>T</italic> denote the power reflection and transmission coefficients respectively, and sub-indexes <italic>s</italic> and <italic>p</italic> denote respectively the perpendicular and parallel ray polarization. Wavelengths are given in nanometers and incidence angles in degrees. We remark that it is precisely in this case where the ray equations are complemented by the so-called fully-coherent medium transfer matrix formalism (TMM).</p>
</list-item>
<list-item>
<p>
<monospace>PVMaterial</monospace>, which represents the active material in photovoltaic cells such as semiconductors or any other material with that functionality. This is the case of the “PV material” exposed in Section The ray tracing algorithm. The photo-absorption in such materials is characterized by their extinction coefficient. The values of the index of refraction <inline-formula id="pone.0240735.e022"><alternatives><graphic id="pone.0240735.e022g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e022" xlink:type="simple"/><mml:math display="inline" id="M22"><mml:mrow><mml:mo>(</mml:mo> <mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mo>=</mml:mo> <mml:mi>n</mml:mi> <mml:mo>-</mml:mo> <mml:mi>i</mml:mi> <mml:mi>κ</mml:mi> <mml:mo>)</mml:mo></mml:mrow></mml:math></alternatives></inline-formula>, which depends on the light wavelength, are given in tabulated form as in the <monospace>WavelengthVolumeMaterial</monospace> case.</p>
</list-item>
</list>
</sec>
<sec id="sec012">
<title>The <monospace>SurfaceMaterial</monospace> class</title>
<p>Any <monospace>surface_material</monospace> represents a two-dimensional physical object, in the sense that its third dimension is negligible, or simply that its behaviour does not depend on it. Examples of these objects are front surface mirrors, selective absorbers, metallic coatings,…. In a first approximation, the interaction of a ray with such a material can result in a reflection, an absorption or a transmittance, each with a given probability that may depend on the wavelength of the ray and are stored in the dictionary <monospace>p = material.properties</monospace>. Hence, <monospace>material.change_of_optical_state()</monospace> generically implements these different phenomena. This behaviour is also affected by other properties of the material, like the booleans:</p>
<list list-type="bullet">
<list-item>
<p>
<monospace>p['lambertian_material']</monospace>, indicating that, in the case of reflection, the direction of the reflected ray should be a random vector, instead of that computed using the law of reflection.</p>
</list-item>
<list-item>
<p>
<monospace>p['thermal_material']</monospace>, indicating that, in case of absorption, the energy is absorbed and processed, instead of lost in the material. This is the case of the “Thermal material” exposed in Section The ray tracing algorithm.</p>
</list-item>
</list>
<p>Some more specific materials are provided by subclassing <monospace>SurfaceMaterial</monospace> and overriding the <monospace>change_of_optical_state()</monospace> method. Some examples of these specific materials are:</p>
<list list-type="bullet">
<list-item>
<p>
<monospace>AbsorberTWModelLayer</monospace>, represents a thermal absorber where its absorption depends on the incidence angle, <italic>θ</italic>, according to <inline-formula id="pone.0240735.e023"><alternatives><graphic id="pone.0240735.e023g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e023" xlink:type="simple"/><mml:math display="inline" id="M23"><mml:mrow><mml:mi>α</mml:mi> <mml:mo>=</mml:mo> <mml:msub><mml:mi>α</mml:mi> <mml:mn>0</mml:mn></mml:msub> <mml:mo>{</mml:mo> <mml:mn>1</mml:mn> <mml:mo>-</mml:mo> <mml:mi>b</mml:mi> <mml:msup><mml:mrow><mml:mo>(</mml:mo> <mml:mfrac><mml:mn>1</mml:mn> <mml:mrow><mml:mo form="prefix">cos</mml:mo> <mml:mi>θ</mml:mi></mml:mrow></mml:mfrac> <mml:mo>-</mml:mo> <mml:mn>1</mml:mn> <mml:mo>)</mml:mo></mml:mrow> <mml:mi>c</mml:mi></mml:msup> <mml:mo>}</mml:mo></mml:mrow></mml:math></alternatives></inline-formula>, see [<xref ref-type="bibr" rid="pone.0240735.ref022">22</xref>] for more details. The following data values are given: <italic>α</italic><sub>0</sub>, <italic>b</italic>, <italic>c</italic>. In this case, the boolean property <monospace>p['thermal_material']</monospace> is <monospace>True</monospace>.</p>
</list-item>
<list-item>
<p>
<monospace>MetallicSpecularLayer</monospace>, represents a metal surface, such as the silver coating in second surface mirrors. Fresnel equations are considered and its characterization is defined by the complex index of refraction <inline-formula id="pone.0240735.e024"><alternatives><graphic id="pone.0240735.e024g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e024" xlink:type="simple"/><mml:math display="inline" id="M24"><mml:mrow><mml:mo>(</mml:mo> <mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mo>=</mml:mo> <mml:mi>n</mml:mi> <mml:mo>-</mml:mo> <mml:mi>i</mml:mi> <mml:mi>κ</mml:mi> <mml:mo>)</mml:mo></mml:mrow></mml:math></alternatives></inline-formula> depending on the light wavelength. The data values are given in tabulated form like in the <monospace>WavelengthVolumeMaterial</monospace> case.</p>
</list-item>
<list-item>
<p>
<monospace>MetallicLambertianLayer</monospace>, represents a metal surface where Fresnel equations are considered, but if the ray is reflected, a total diffuse reflection model with Lambertian scattering is used. In this material, the boolean property <monospace>p['lambertian_material']</monospace> is <monospace>True</monospace>. Also, its characterization is defined by the complex index of refraction <inline-formula id="pone.0240735.e025"><alternatives><graphic id="pone.0240735.e025g" mimetype="image" position="anchor" xlink:href="info:doi/10.1371/journal.pone.0240735.e025" xlink:type="simple"/><mml:math display="inline" id="M25"><mml:mrow><mml:mo>(</mml:mo> <mml:mover accent="true"><mml:mi>n</mml:mi> <mml:mo>˜</mml:mo></mml:mover> <mml:mo>=</mml:mo> <mml:mi>n</mml:mi> <mml:mo>-</mml:mo> <mml:mi>i</mml:mi> <mml:mi>κ</mml:mi> <mml:mo>)</mml:mo></mml:mrow></mml:math></alternatives></inline-formula> depending on the light wavelength. The data values are given in tabulated form like in the <monospace>WavelengthVolumeMaterial</monospace> case.</p>
</list-item>
<list-item>
<p>
<monospace>PolarizedCoatingLayer</monospace>, and its subclasses <monospace>PolarizedCoatingReflectorLayer</monospace>, <monospace>PolarizedCoatingTransparentLayer</monospace>, <monospace>PolarizedCoatingAbsorberLayer</monospace>, that represent thin layers such as optical coatings. The difference with the <monospace>PolarizedThinFilm</monospace> is that the thickness of such material is negligible. The data values are given as in the <monospace>PolarizedThinFilm</monospace> case. Depending on the role of the material, three cases are defined: reflector (no light transmission is possible), transparent (reflection, absorption and transmission are possible), and thermal absorber material (the boolean property <monospace>p['thermal_material']</monospace> is <monospace>True</monospace> and no light transmission is possible). In each case, the parameters are given analogously to the case of <monospace>PolarizedThinFilm</monospace>.</p>
</list-item>
</list>
</sec>
</sec>
<sec id="sec013">
<title>The <monospace>MultiTracking</monospace> class</title>
<p>The class <monospace>MultiTracking</monospace> is designed to implement movements of the active elements in a <monospace>scene</monospace> so that the rays emitted by a given <monospace>light_source</monospace> tend to be focused on a target (in case that the attribute <monospace>target</monospace> is set to a point) or tend to return it to the source (in case that the attribute is not set). That is, <monospace>MultiTracking</monospace> can be used either to orient the solar collector to the sun or to direct rays to a target, as happens with the segment mirrors of a Linear Fresnel Collector (LFR) or the heliostats in solar power tower plants.</p>
<p>Movements of elements are implemented by the helper class <monospace>Joint</monospace>, and its subclasses <monospace>CentralJoint</monospace> and <monospace>AxialJoint</monospace>. The former implements rotations around a given point in space (that is, with two degrees of freedom), while in the latter the rotations are around an axis (and hence with a single degree of freedom). Each kind of joint can be easily represented by a geometrical object in FreeCAD, either by a <monospace>Vertex</monospace> or an <monospace>Edge</monospace> with two points.</p>
<p>To describe the movement of a concrete element in the <monospace>scene</monospace>, one needs to associate to this object a <monospace>joint</monospace>, but since the goal is to direct the rays to a specified region, one also needs to specify the corresponding <italic>principal vector</italic>. Here, by the <italic>principal vector</italic>, we mean the direction that best approaches the normal of the mobile element. When <monospace>multi_tracking.target</monospace> is not set, the element will be moved so that this vector points to the source; otherwise, the movement will be computed so that a solar ray reflected on the plane normal to the <italic>principal vector</italic> and passing through the <monospace>joint</monospace> hits the point stored in <monospace>multi_tracking.target</monospace>.</p>
<p>We associate objects in the scene to joints using the following convention (see also Section The <monospace>Scene</monospace> class): Instead of giving to the object under consideration a label of the form “Label<monospace>(mat_name)</monospace>”, where <monospace>mat_name</monospace> is the identifier of the <monospace>material</monospace> of the object, we use a label of the form “Label<monospace>(mat_name,joint_name,normal_name)</monospace>” or “Label<monospace>(mat_name,joint_name,normal_name,target_name)</monospace>”, where <monospace>joint_name</monospace> is the label of the FreeCAD object that describes the joint (i.e. either a <monospace>Vertex</monospace> or a <monospace>Edge</monospace>), <monospace>normal_name</monospace> is the label of the FreeCAD <monospace>Edge</monospace> whose direction is the <italic>principal vector</italic> of the optical element, and <monospace>target_name</monospace> (if present) is the label of the FreeCAD object acting as target.</p>
<p>A <monospace>multi_tracking</monospace> is created by giving the <monospace>scene</monospace> (which includes the elements that describe the joints, together with their principal vectors and targets, if needed) and the <monospace>light_source</monospace>, a <monospace>Base.Vector</monospace> giving the main direction of the sun rays. Once it is created, the method <monospace>target_tracking.make_movements()</monospace> transforms the scene, rotating conveniently the elements, so that the scene behaves as explained above.</p>
</sec>
</sec>
<sec id="sec014">
<title>Model validation</title>
<p>We discuss here two experiments showing how the results obtained with OTSun are compared with those obtained using other software tools, hence providing a validation for both our model and our implementation. A third validation example, related to the optical behaviour of perovskite solar cells, can be found in [<xref ref-type="bibr" rid="pone.0240735.ref002">2</xref>]. In each case, we have compared the results obtained by OTSun with a reference model using both the mean error (ME), so that we can determine if OTSun has an overall tendency to overestimate or underestimate the results, and the root mean square error (RMSE), to evaluate the global accuracy. The scripts and auxiliary files cited in this section can be found at <ext-link ext-link-type="uri" xlink:href="https://github.com/bielcardona/OTSunSuppMat" xlink:type="simple">https://github.com/bielcardona/OTSunSuppMat</ext-link>.</p>
<sec id="sec015">
<title>First experiment</title>
<p>We have compared the computations of the optical efficiency of a Linear Fresnel Reflector (LFR) obtained using OTSun and Tonatiuh [<xref ref-type="bibr" rid="pone.0240735.ref004">4</xref>]. We have chosen this geometry due to its complexity, having mobile objects and using four different types of optical materials. The geometry of the LFR is composed by 11 parabolic mirrors of 500 mm width, a secondary CPC reflector with a maximum concentration of 1.66 truncated at 61.81 mm, and a flat receiver of 70 mm width placed 6 meters above the mirrors field. The parabolic mirrors track the sun with the purpose of reflecting the sunlight to a target located at 46.45 mm under the flat receiver. Each parabolic mirror has a focal length equal to the distance between its center position (which includes the rotation axis) and the mentioned target. The files <monospace>LFR.FCStd</monospace> and <monospace>LFR.tnh</monospace> contain the implementation of this geometry in FreeCAD and Tonatiuh, respectively. Additionally, the file <monospace>LFR_output.FCStd</monospace> shows the output given by OTSun with the simulation of some rays with a transversal incidence angle equal to 45 degrees. Since the optics implemented in Tonatiuh is not based on the Fresnel equations in all its generality, we took the decision to use materials with constant optical properties, so that we can use materials with the same properties in both programs. The file <monospace>validation1.py</monospace> contains the specification of the optical materials used in this example, as well as the code used to compute the optical efficiency.</p>
<p>In our computations (both with OTSun and Tonatiuh), we have simulated the emission of 100,000 sun rays per each sun position, using the Buie model approach [<xref ref-type="bibr" rid="pone.0240735.ref021">21</xref>] with a value of 0.05 for the circumsolar ratio. <xref ref-type="fig" rid="pone.0240735.g003">Fig 3</xref> shows the optical efficiencies obtained with the two software packages using different angles for the sun position in both the transversal and longitudinal planes.</p>
<fig id="pone.0240735.g003" position="float">
<object-id pub-id-type="doi">10.1371/journal.pone.0240735.g003</object-id>
<label>Fig 3</label>
<caption>
<title>Optical efficiency at transversal and longitudinal planes of the analyzed LFR, as computed by OTSun and Tonatiuh.</title>
</caption>
<graphic mimetype="image" position="float" xlink:href="info:doi/10.1371/journal.pone.0240735.g003" xlink:type="simple"/>
</fig>
</sec>
<sec id="sec016">
<title>Second experiment</title>
<p>We have determined the reflectance of a second surface mirror composed by a layer of 4 mm of borosilicate glass with a silver coating. The model can be found in the file <monospace>mirror.FCStd</monospace>, where it can be seen that we created a surface material formed by two layers to be put over the mirror. The outside layer is a transparent material, while the inner one is an ideal thermal material absorber. With this setting, the rays that reach the outer layer pass through it, and those that are later reflected by the mirror are collected by the absorber material, hence providing a measure of the optical efficiency of the mirror. This efficiency, divided by the cosine of the incidence angle of the light rays with respect to the normal vector of the mirror surface, gives the reflectance of the mirror. See the files <monospace>mirror.FCStd</monospace> and <monospace>validation2.py</monospace> for more details on this geometry and the script we have used to make the simulation with OTSun. Also, file <monospace>mirror_output.FCStd</monospace> shows the output produced by OTSun with some simulated rays drawn.</p>
<p>The optical properties of this configuration can also be determined by the analytic transform matrix method (TMM), as exposed in [<xref ref-type="bibr" rid="pone.0240735.ref023">23</xref>] and implemented in [<xref ref-type="bibr" rid="pone.0240735.ref024">24</xref>]. A comparison of the results obtained using these two methods is shown in <xref ref-type="fig" rid="pone.0240735.g004">Fig 4</xref>, where the reflectances are plot as a function of the wavelength using two different incidence angles (<italic>θ</italic> = 45° and <italic>θ</italic> = 80° degrees) and with parallel and perpendicular polarizations.</p>
<fig id="pone.0240735.g004" position="float">
<object-id pub-id-type="doi">10.1371/journal.pone.0240735.g004</object-id>
<label>Fig 4</label>
<caption>
<title>Reflectance of a second surface mirror at an incidence angle of 45 and 80 degrees, with parallel and perpendicular polarization, computed using the TMM and OTSun.</title>
</caption>
<graphic mimetype="image" position="float" xlink:href="info:doi/10.1371/journal.pone.0240735.g004" xlink:type="simple"/>
</fig>
</sec>
<sec id="sec017">
<title>Robustness of validations</title>
<p>To prove the robustness of the validations, we have computed the mean error (ME) and the root mean square error (RMSE) between the results obtained by OTSun and those obtained either by Tonatiuh or TMM. <xref ref-type="table" rid="pone.0240735.t001">Table 1</xref> summarizes these computations.</p>
<table-wrap id="pone.0240735.t001" position="float">
<object-id pub-id-type="doi">10.1371/journal.pone.0240735.t001</object-id>
<label>Table 1</label>
<caption>
<title>Mean Error (ME) and Root Mean Square Error (RMSE) between OTSun simulations and the reference models.</title>
</caption>
<alternatives>
<graphic id="pone.0240735.t001g" mimetype="image" position="float" xlink:href="info:doi/10.1371/journal.pone.0240735.t001" xlink:type="simple"/>
<table border="0" frame="box" rules="all">
<colgroup>
<col align="left" valign="middle"/>
<col align="left" valign="middle"/>
<col align="left" valign="middle"/>
<col align="left" valign="middle"/>
</colgroup>
<thead>
<tr>
<th align="left">Experiment</th>
<th align="left">Case</th>
<th align="left">ME</th>
<th align="left">RMSE</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">First</td>
<td align="left">Transversal</td>
<td align="char" char=".">0.00130</td>
<td align="char" char=".">0.0020</td>
</tr>
<tr>
<td align="left">First</td>
<td align="left">Longitudinal</td>
<td align="char" char=".">−0.00983</td>
<td align="char" char=".">0.0013</td>
</tr>
<tr>
<td align="left">Second</td>
<td align="left"><italic>θ</italic> = 45°, ∥ pol.</td>
<td align="char" char=".">0.00035</td>
<td align="char" char=".">0.0015</td>
</tr>
<tr>
<td align="left">Second</td>
<td align="left"><italic>θ</italic> = 45°, ⊥ pol.</td>
<td align="char" char=".">−0.00019</td>
<td align="char" char=".">0.0016</td>
</tr>
<tr>
<td align="left">Second</td>
<td align="left"><italic>θ</italic> = 80°, ∥ pol.</td>
<td align="char" char=".">−0.00193</td>
<td align="char" char=".">0.0024</td>
</tr>
<tr>
<td align="left">Second</td>
<td align="left"><italic>θ</italic> = 80°, ⊥ pol.</td>
<td align="char" char=".">−0.00019</td>
<td align="char" char=".">0.0025</td>
</tr>
</tbody>
</table>
</alternatives>
</table-wrap>
<p>One remark is due for these results. In the case of the second experiment, plotted in <xref ref-type="fig" rid="pone.0240735.g003">Fig 3</xref>, the optical efficiency in the longitudinal plane for angles greater than or equal to 80 degrees is nearly zero, since the sun is nearly in the direction of the axis of the mirrors and hence nearly no reflections are captured by the receiver. To avoid the spurious behaviour of the indicators due to values close to zero, we have opted for omitting the values corresponding to these angles in the computation of ME and RMSE.</p>
<p>From <xref ref-type="table" rid="pone.0240735.t001">Table 1</xref>, we see that the ME takes both positive and negative values, which implies that OTSun does not present any tendency to overestimate or underestimate the results with respect to the reference models. From the result obtained by OTSun respect to the reference cases, we can see that OTSun presents RMSE values between 0.0013 and 0.0025 for the cases analyzed, which represents an error lower than 0.25%.</p>
</sec>
</sec>
<sec id="sec018" sec-type="conclusions">
<title>Conclusion</title>
<p>Ray tracing software systems are commonly used to make optical analysis of solar energy devices. However, the available open source systems make excessive simplifications in the implementation of optics, causing limitations on their features. In this paper, we have presented the open source package OTSun. It is a Monte Carlo ray tracing python library, where the optics is implemented using the Fresnel optics equations in their most general form. The optical phenomena implemented in OTSun allow for dependence on wavelength, incidence angle, light polarization, interference, ray attenuation, complex refractive index, source spectrum and direction of emission, among others. OTSun also implements tracking movements, so that objects move to track the sun or to reflect the rays onto a specific target. The geometry of the optical systems used by OTSun is built with FreeCAD, which is also open source, and hence allows for the simulation of solar energy devices with arbitrary geometry. In addition, OTSun is accompanied by the webtool OTSunWebApp, that allows to make some simulations without the need to install anything locally.</p>
<p>We presented numerical simulations to validate the OTSun models and implementations. For this purpose, we made two different experiments. The first one is mainly devoted to testing the reflections and movements of optical elements, while the second one focuses on the full implementation of the Fresnel equations. The robustness of such validations is demonstrated, achieving deviations lower than 0.25% from the reference models, Tonatiuh and TMM, respectively.</p>
<p>We think that OTSun will become a valuable resource for the community of designers and researchers on solar optics. But not only for them: It has been demonstrated that OTSun is a software tool suitable to analyze opto-mechanic problems, due to its flexibility and that the optics equations are implemented in its most general form. To this end, and as our future work, we have in mind to develop modules for FreeCAD to simplify the construction of optical elements such as lenses, collimators, filters, etc., and solar energy devices such as LFRs, PTCs, solar power towers, PV cells, etc.</p>
<p>In its present form, OTSun is exclusively an optics simulator. Even with this limitation, and for the case of solar cells, we have implement functions to obtain the photocurrent if the internal quantum efficiency is given as input. A future work consists in integrating a solver for the carrier transport equations, to evaluate the capabilities of power electricity conversion of solar cells. This would provide in a single tool, the capability of considering both optical and electronic aspects of solar cells.</p>
</sec>
</body>
<back>
<ack>
<p>We thank David Gómez Sospedra for the assistance on the design of the LFR used in the first experiment.</p>
</ack>
<ref-list>
<title>References</title>
<ref id="pone.0240735.ref001">
<label>1</label>
<mixed-citation publication-type="journal" xlink:type="simple">
<name name-style="western"><surname>Malinowski</surname> <given-names>M</given-names></name>, <name name-style="western"><surname>Leon</surname> <given-names>JI</given-names></name>, <name name-style="western"><surname>Abu-Rub</surname> <given-names>H</given-names></name>. <article-title>Solar Photovoltaic and Thermal Energy Systems: Current Technology and Future Trends</article-title>. <source>Proceedings of the IEEE</source>. <year>2017</year>;<volume>105</volume>(<issue>11</issue>):<fpage>2132</fpage>–<lpage>2146</lpage>. <comment>doi: <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.1109/JPROC.2017.2690343" xlink:type="simple">10.1109/JPROC.2017.2690343</ext-link></comment></mixed-citation>
</ref>
<ref id="pone.0240735.ref002">
<label>2</label>
<mixed-citation publication-type="journal" xlink:type="simple">
<name name-style="western"><surname>Bonnín-Ripoll</surname> <given-names>F</given-names></name>, <name name-style="western"><surname>Martynov</surname> <given-names>YB</given-names></name>, <name name-style="western"><surname>Cardona</surname> <given-names>G</given-names></name>, <name name-style="western"><surname>Nazmitdinov</surname> <given-names>RG</given-names></name>, <name name-style="western"><surname>Pujol-Nadal</surname> <given-names>R</given-names></name>. <article-title>Synergy of the ray tracing+carrier transport approach: On efficiency of perovskite solar cells with a back reflector</article-title>. <source>Solar Energy Materials and Solar Cells</source>. <year>2019</year>;<volume>200</volume>:<fpage>110050</fpage>. <comment>doi: <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.1016/j.solmat.2019.110050" xlink:type="simple">10.1016/j.solmat.2019.110050</ext-link></comment></mixed-citation>
</ref>
<ref id="pone.0240735.ref003">
<label>3</label>
<mixed-citation publication-type="journal" xlink:type="simple">
<name name-style="western"><surname>Cruz</surname> <given-names>NC</given-names></name>, <name name-style="western"><surname>Redondo</surname> <given-names>JL</given-names></name>, <name name-style="western"><surname>Berenguel</surname> <given-names>M</given-names></name>, <name name-style="western"><surname>Álvarez</surname> <given-names>JD</given-names></name>, <name name-style="western"><surname>Ortigosa</surname> <given-names>PM</given-names></name>. <article-title>Review of software for optical analyzing and optimizing heliostat fields</article-title>. <source>Renewable and Sustainable Energy Reviews</source>. <year>2017</year>;<volume>72</volume>:<fpage>1001</fpage>–<lpage>1018</lpage>. <comment>doi: <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.1016/j.rser.2017.01.032" xlink:type="simple">10.1016/j.rser.2017.01.032</ext-link></comment></mixed-citation>
</ref>
<ref id="pone.0240735.ref004">
<label>4</label>
<mixed-citation publication-type="other" xlink:type="simple">Blanco M, Mutuberria A, Monreal A, Albert R. Results of the empirical validation of Tonatiuh at Mini-Pegase CNRS-PROMES facility. In: Proceedings of the 17th SolarPACES Int. Symposium on Concentrating Solar Power and Chemical Energy; 2011. Available from: <ext-link ext-link-type="uri" xlink:href="https://iat-cener.github.io/tonatiuh/" xlink:type="simple">https://iat-cener.github.io/tonatiuh/</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref005">
<label>5</label>
<mixed-citation publication-type="other" xlink:type="simple">Google Inc. HOpS: The Heliostat Optical Simulator; 2013. Available from: <ext-link ext-link-type="uri" xlink:href="https://github.com/google/hops" xlink:type="simple">https://github.com/google/hops</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref006">
<label>6</label>
<mixed-citation publication-type="other" xlink:type="simple">Wendelin T. SolTRACE: A New Optical Modeling Tool for Concentrating Solar Optics. In: Proceedings of the ISEC 2003: International Solar Energy Conference; 2003. p. 253–260. Available from: <ext-link ext-link-type="uri" xlink:href="https://www.nrel.gov/csp/soltrace.html" xlink:type="simple">https://www.nrel.gov/csp/soltrace.html</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref007">
<label>7</label>
<mixed-citation publication-type="journal" xlink:type="simple"><name name-style="western"><surname>Osório</surname> <given-names>T</given-names></name>, <name name-style="western"><surname>Horta</surname> <given-names>P</given-names></name>, <name name-style="western"><surname>Larcher</surname> <given-names>M</given-names></name>, <name name-style="western"><surname>Pujol-Nadal</surname> <given-names>R</given-names></name>, <name name-style="western"><surname>Hertel</surname> <given-names>J</given-names></name>, <name name-style="western"><surname>Van Rooyen</surname> <given-names>DW</given-names></name>, <etal>et al</etal>. <article-title>Ray-tracing software comparison for linear focusing solar collectors</article-title>. <source>AIP Conference Proceedings</source>. <year>2016</year>;<volume>1734</volume>. <comment>doi: <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.1063/1.4949041" xlink:type="simple">10.1063/1.4949041</ext-link></comment></mixed-citation>
</ref>
<ref id="pone.0240735.ref008">
<label>8</label>
<mixed-citation publication-type="journal" xlink:type="simple">
<name name-style="western"><surname>Magnin</surname> <given-names>V</given-names></name>, <name name-style="western"><surname>Harari</surname> <given-names>J</given-names></name>, <name name-style="western"><surname>Halbwax</surname> <given-names>M</given-names></name>, <name name-style="western"><surname>Bastide</surname> <given-names>S</given-names></name>, <name name-style="western"><surname>Cherfi</surname> <given-names>D</given-names></name>, <name name-style="western"><surname>Vilcot</surname> <given-names>JP</given-names></name>. <article-title>Angle-dependent ray tracing simulations of reflections on pyramidal textures for silicon solar cells</article-title>. <source>Solar Energy</source>. <year>2014</year>;<volume>110</volume>:<fpage>378</fpage>–<lpage>385</lpage>. <comment>doi: <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.1016/j.solener.2014.09.025" xlink:type="simple">10.1016/j.solener.2014.09.025</ext-link></comment></mixed-citation>
</ref>
<ref id="pone.0240735.ref009">
<label>9</label>
<mixed-citation publication-type="other" xlink:type="simple">Lipovšek B, Krč J, Topič M. CROWM; 2019. Available from: <ext-link ext-link-type="uri" xlink:href="http://lpvo.fe.uni-lj.si/en/software/crowm/" xlink:type="simple">http://lpvo.fe.uni-lj.si/en/software/crowm/</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref010">
<label>10</label>
<mixed-citation publication-type="other" xlink:type="simple">Bos-Coenraad J. Scientrace; 2020. Available from: <ext-link ext-link-type="uri" xlink:href="http://joepbc.github.io/scientrace/" xlink:type="simple">http://joepbc.github.io/scientrace/</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref011">
<label>11</label>
<mixed-citation publication-type="journal" xlink:type="simple">
<name name-style="western"><surname>Bos-Coenraad</surname> <given-names>J</given-names></name>, <name name-style="western"><surname>Bunthof</surname> <given-names>LAA</given-names></name>, <name name-style="western"><surname>Schermer</surname> <given-names>JJ</given-names></name>. <article-title>Scientrace: An open source, programmable 3D ray tracer</article-title>. <source>Solar Energy</source>. <year>2017</year>;<volume>155</volume>:<fpage>1188</fpage>–<lpage>1196</lpage>. <comment>doi: <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.1016/j.solener.2017.07.003" xlink:type="simple">10.1016/j.solener.2017.07.003</ext-link></comment></mixed-citation>
</ref>
<ref id="pone.0240735.ref012">
<label>12</label>
<mixed-citation publication-type="other" xlink:type="simple">OptiCAD Corp. OptiCAD; 2020. Available from: <ext-link ext-link-type="uri" xlink:href="http://www.opticad.com" xlink:type="simple">http://www.opticad.com</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref013">
<label>13</label>
<mixed-citation publication-type="other" xlink:type="simple">Zemax LLC. Zemax; 2020. Available from: <ext-link ext-link-type="uri" xlink:href="https://www.zemax.com/" xlink:type="simple">https://www.zemax.com/</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref014">
<label>14</label>
<mixed-citation publication-type="other" xlink:type="simple">Breault Research Organization Inc. ASAP; 2020. Available from: <ext-link ext-link-type="uri" xlink:href="http://www.breault.com/software/asap-nextgen" xlink:type="simple">http://www.breault.com/software/asap-nextgen</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref015">
<label>15</label>
<mixed-citation publication-type="other" xlink:type="simple">Lambda Research Corp. TracePro; 2020. Available from: <ext-link ext-link-type="uri" xlink:href="https://www.lambdares.com/tracepro/" xlink:type="simple">https://www.lambdares.com/tracepro/</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref016">
<label>16</label>
<mixed-citation publication-type="other" xlink:type="simple">COMSOL Inc. COMSOL; 2020. Available from: <ext-link ext-link-type="uri" xlink:href="https://www.comsol.com/" xlink:type="simple">https://www.comsol.com/</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref017">
<label>17</label>
<mixed-citation publication-type="other" xlink:type="simple">Riegel J, Mayer W, van Havre Y. FreeCAD; 2020. Available from: <ext-link ext-link-type="uri" xlink:href="http://www.freecadweb.org" xlink:type="simple">http://www.freecadweb.org</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref018">
<label>18</label>
<mixed-citation publication-type="other" xlink:type="simple">Cardona G, Pujol-Nadal R. OTSunWebApp Tutorials; 2020. Available from: <ext-link ext-link-type="uri" xlink:href="https://github.com/bielcardona/OTSun/tree/master/OTSunWebApp" xlink:type="simple">https://github.com/bielcardona/OTSun/tree/master/OTSunWebApp</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref019">
<label>19</label>
<mixed-citation publication-type="other" xlink:type="simple">Verma RK. Ray Optics. Discovery Publishing House Pvt. Limited; 2006. Available from: <ext-link ext-link-type="uri" xlink:href="https://books.google.es/books?id=acZGvg_7Z0gC" xlink:type="simple">https://books.google.es/books?id=acZGvg_7Z0gC</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref020">
<label>20</label>
<mixed-citation publication-type="book" xlink:type="simple">
<name name-style="western"><surname>Macleod</surname> <given-names>HA</given-names></name>. <source>Thin-film optical filters</source>. <publisher-name>CRC Press/Taylor &amp; Francis</publisher-name>; <year>2010</year>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref021">
<label>21</label>
<mixed-citation publication-type="journal" xlink:type="simple">
<name name-style="western"><surname>Buie</surname> <given-names>D</given-names></name>, <name name-style="western"><surname>Dey</surname> <given-names>CJ</given-names></name>, <name name-style="western"><surname>Bosi</surname> <given-names>S</given-names></name>. <article-title>The effective size of the solar cone for solar concentrating systems</article-title>. <source>Solar Energy</source>. <year>2003</year>;<volume>74</volume>(<issue>5</issue>):<fpage>417</fpage>–<lpage>427</lpage>. <comment>doi: <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.1016/S0038-092X(03)00156-7" xlink:type="simple">10.1016/S0038-092X(03)00156-7</ext-link></comment></mixed-citation>
</ref>
<ref id="pone.0240735.ref022">
<label>22</label>
<mixed-citation publication-type="journal" xlink:type="simple">
<name name-style="western"><surname>Tesfamichael</surname> <given-names>T</given-names></name>, <name name-style="western"><surname>Wäckelgård</surname> <given-names>E</given-names></name>. <article-title>Angular solar absorptance and incident angle modifier of selective absorbers for solar thermal collectors</article-title>. <source>Solar Energy</source>. <year>2000</year>;<volume>68</volume>(<issue>4</issue>):<fpage>335</fpage>–<lpage>341</lpage>. <comment>doi: <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.1016/S0038-092X(00)00029-3" xlink:type="simple">10.1016/S0038-092X(00)00029-3</ext-link></comment></mixed-citation>
</ref>
<ref id="pone.0240735.ref023">
<label>23</label>
<mixed-citation publication-type="other" xlink:type="simple">Byrnes SJ. Multilayer optical calculations; 2016. Available from: <ext-link ext-link-type="uri" xlink:href="https://arxiv.org/abs/1603.02720" xlink:type="simple">https://arxiv.org/abs/1603.02720</ext-link>.</mixed-citation>
</ref>
<ref id="pone.0240735.ref024">
<label>24</label>
<mixed-citation publication-type="other" xlink:type="simple">Steven Byrnes. tmm 0.1.7: Python Package Index; 2017. Available from: <ext-link ext-link-type="uri" xlink:href="https://pypi.python.org/pypi/tmm" xlink:type="simple">https://pypi.python.org/pypi/tmm</ext-link>.</mixed-citation>
</ref>
</ref-list>
</back>
</article>