pyviewfactor


Namepyviewfactor JSON
Version 0.0.16 PyPI version JSON
download
home_pagehttps://gitlab.com/arep-dev/pyViewFactor/
SummaryA python library to calculate numerically exact radiation view factors between planar faces.
upload_time2023-11-20 11:19:35
maintainer
docs_urlNone
authorMateusz BOGDAN, Edouard WALTHER, Marc ALECIAN, Mina CHAPON
requires_python
licenseMIT
keywords radiative-transfer radiation vtk geometry viewfactor stl visibility
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # PyViewFactor
 [![Latest Release](https://gitlab.com/arep-dev/pyViewFactor/-/badges/release.svg)](https://gitlab.com/arep-dev/pyViewFactor/-/releases) 
 [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
 [![Pypi Version](https://img.shields.io/pypi/v/pyviewfactor)](https://pypi.org/project/pyviewfactor/)
 [![Pypi Downloads](https://img.shields.io/pypi/dm/pyviewfactor.svg?label=pypi%20downloads)](https://pypi.org/project/pyviewfactor/)
 
A python library to compute exact view factors between planar faces ([Documentation](https://arep-dev.gitlab.io/pyViewFactor/)).

This code computes the radiation view factor between polygons using the double contour integral method described in [(Mazumder and Ravishankar 2012)](https://www.academia.edu/download/77459051/Viewfactor_paper_IJHMT.pdf) and [(Schmid 2016)](https://hal.archives-ouvertes.fr/tel-01734545/).

It uses the handy [Pyvista](https://docs.pyvista.org/) package to deal with geometrical aspects of such problems. 

##  How does it work?

- [x] Use [pyvista](https://docs.pyvista.org/index.html) to import your geometry (*.stl, *.vtk, *.obj, ...) or alternately draw it with the same package.
- [x] Optionally check that the faces can "see" each other with `get_visibility(face1, face2)`
- [x] Optionally check that no obstruction lies between them `get_visibility_obstruction(face1, face2, obstacle)`
- [x] Compute the view factor from `face2` to `face1` with `compute_view_factor(face1, face2)`: Done!

##  Minimum working example : facet to facet view factor computation 

Suppose we want to compute the radiation view factor between a triangle and a rectangle.

<img src="https://gitlab.com/arep-dev/pyViewFactor/-/raw/64e19ed126bbfd1bc2bff1197b1dee23d35c7836/img/mwe.png?raw=true" alt="Triangle and rectangle configuration" width="260"/>


You are now 18 lines of code away from your first view factor computation:

```python
import pyvista as pv
import pyviewfactor as pvf

# first define a rectangle...
pointa = [1, 0, 0] 
pointb = [1, 1, 0]
pointc = [0, 1, 0]
pointd = [0, 0, 0]
rectangle = pv.Rectangle([pointa, pointb, pointc, pointd])

# ... then a triangle
pointa = [1, 0, 1] 
pointb = [1, 1, 1]
pointc = [0, 1, 1]
liste_pts = [pointa, pointb, pointc]
liste_pts.reverse() # let us put the normal the other way around (facing the rectangle)
triangle = pv.Triangle(liste_pts) # ... done with geometry.

# preliminary check for visibility
if pvf.get_visibility(rectangle , triangle):
    F = pvf.compute_viewfactor(rectangle, triangle)
    print("View factor from triangle to rectangle = ", F)
else:
    print("Not facing each other")
```

You usually get your geometry from a different format? (*.idf, *.dat, ...)

Check pyvista's documentation on [how to generate a PolyData facet from points](https://docs.pyvista.org/examples/00-load/create-poly.html).

## Example with a closed geometry and the VTK file format

We will now compute the view factors within a more complex geometry: a  closed sphere (clipped in half below), with inwards facing normals, so the faces can "see" each other. Note that the face-to-face visibility is unobstructed (for obstructed geometries, see next section).

The field of view factors from one facet to all others will be computed and stored in a VTK file, which you can explore with the open source [Paraview software](https://www.paraview.org/download/).

<img src="https://gitlab.com/arep-dev/pyViewFactor/-/raw/73249e2093b207d5030d9b6637603c4b77b2374c/img/demi_sphere.png?raw=true" alt="Sphere" width="350"/>

Following snippet can be reused as a kick-start for your own purposes:
```python
import pyvista as pv
import numpy as np
from pyviewfactor import  compute_viewfactor, fc_unstruc2poly # viewfactor + a useful conversion function
from tqdm import tqdm # for a fancy progress bar

# create a raw sphere with pyvista
sphere = pv.Sphere(radius=50, center=(0, 0, 0), direction=(0, 0, 1),
                 theta_resolution=9, phi_resolution=9)
# and put the normals inwards please
sphere.flip_normals()

# let us chose a cell to compute view factors from
chosen_face = sphere.extract_cells(10)
# convert the face from UnstructuredGrid to PolyData
chosen_face = fc_unstruc2poly(chosen_face)
# "one array to contain them all" -> the results will be stored there
F = np.zeros(sphere.n_cells) 

# now let us compute the view factor to all other faces
# (with a fancy progress bar, iterating over the mesh's faces)
for i in tqdm(range(sphere.n_cells), total=sphere.n_cells):
    face = sphere.extract_cells(i) # other facet
    face = fc_unstruc2poly(face) # convert to PolyData
    F[i] = compute_viewfactor(face, chosen_face) # compute VF

print("Complementarity check: \n (e.g. is \sum_{i=0}^n F_i =? 1)", np.sum(F))

# put the scalar values in the geometry
sphere.cell_data["F"] = F
sphere.save("./sphere.vtk") # ... and save.

# let us have a look in 3D with an interactive window...
p=pv.Plotter() # instantiate 3D window
p.add_mesh(sphere, scalars='F', cmap='jet') # add mesh with a nice color scheme
p.show() # plot
```
The results look as per following images showing the view factor from the chosen cell to all others.

<img src="https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/F_sphere.png?raw=true" alt="VF to other faces inside the sphere" width="240"/>
<img src="https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/F_sphere_clip.png?raw=true" alt="Clipped result" width="240"/>

## View factors of an individual with a wall

For comfort computations, it may be useful to determine heat transfer between an invidivual and a wall. We will use here PyVista's [doorman example](https://docs.pyvista.org/api/examples/_autosummary/pyvista.examples.downloads.download_doorman.html?highlight=example+man#pyvista.examples.downloads.download_doorman) as a basis for the human geometry.

<img src="https://gitlab.com/arep-dev/pyViewFactor/-/raw/efeae65b20630978972a94de2cffaa4ab5e427dc/img/Fground.png?raw=true" alt="View factors of the doorman's faces to the ground" width="380"/>

The following code and VTK file of the doorman example are available in the [./examples/](https://gitlab.com/arep-dev/pyViewFactor/-/tree/main/examples) folder.
```python
# -*- coding: utf-8 -*-
from tqdm import tqdm
import numpy as np
import pyvista as pv
import pyviewfactor as pvf

def fc_Fwall(nom_vtk):
    mesh=pv.read(nom_vtk)
    
    # find all types of walls
    wall_types=list(np.unique(mesh['names']))
    # remove the individual from the list (still named 'cylinder'...)
    wall_types.remove('cylinder\r') # with dirty trailing character
    # where is the doorman in the list?
    index_doorman=np.where(mesh['names']=='cylinder\r')[0]
    # prepare storage for the different walls in a dict
    dict_F={}
    # loop over wall types
    for type_wall in wall_types:
        # prepare for storing doorman to wall view factor
        F=np.zeros(mesh.n_cells)
        # get the indices of this type of wall
        indices=np.where(mesh['names']==type_wall )[0]
        # loop over
        for i in indices:
            wall=mesh.extract_cells(i)
            wall=pvf.fc_unstruc2poly(wall) # convert for normals
            # ... for each facet of the individual
            for idx in tqdm(index_doorman):
                face = mesh.extract_cells(idx)
                face =pvf.fc_unstruc2poly(face) # convert for normals
                # check if faces can "see" each other
                if pvf.get_visibility(wall,face):
                    Ffp=pvf.compute_viewfactor(wall,face) # compute face2wall view factor
                else:
                    Ffp=0
                F[idx]=Ffp
        #store array F in e.g. dict_F['F_ceiling']
        dict_F['F_'+type_wall.replace('\r','')]=F
    return dict_F

# download it directly from https://gitlab.com/arep-dev/pyViewFactor/-/blob/main/examples/example_doorman.vtk ...
# ...or get it from this repository's examples
file="./example_doorman.vtk"
# compute the view factors or the doorman to the different wall types in the scene
dict_F=fc_Fwall(file)

# re-read and store
mesh=pv.read(file)
# loop over what is in the dictionary of view factors
for elt in dict_F.keys():
    mesh[elt.replace('\r','')]=dict_F[elt] # name the field
mesh.save(file) # store in the intial VTK

# have a look without paraview with fancy colors
mesh.plot(cmap='jet',lighting=False)
```

More details and view abacuses in [this page](https://lhypercube.arep.fr/en/confort/calcul-de-la-temperature-radiante/). Is the computation time a bit lengthy? Learn how to [go parallel!](https://eddes.github.io/#go-parallel).

## Computing the view factors of a wall in its built environment

For building simulation purposes, it may prove to be useful to compute the ground and sky view factors of a given wall, or the view factor of the wall to other walls in the built environment. In following example (available in the "examples" folder), we compute the view factors of the environment of the purple wall depicted below.

<img src="https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/wall_view_factors.png?raw=true" alt="View factors in built environment" width="430"/>

```python
import numpy as np
import pyvista as pv
from tqdm import tqdm
import pyviewfactor as pvf

# read the geometry
mesh = pv.read("./built_envmt.vtk")
meshpoly = pvf.fc_unstruc2poly(mesh) # convert to polydata for obstruction check

# identify who is who
i_wall = np.where(mesh["wall_names"]=='wall')[0]
i_sky = np.where(mesh["wall_names"]=='sky')[0]
i_building1 = np.where(mesh["wall_names"]=='building1')[0]
i_building2 = np.where(mesh["wall_names"]=='building2')[0]

# get the different elements
wall = mesh.extract_cells(i_wall)
sky = mesh.extract_cells(i_sky)
building1 = mesh.extract_cells(i_building1)
building2 = mesh.extract_cells(i_building2)

# convert to polydata
wall = pvf.fc_unstruc2poly(wall)

Fsky = 0
# for all cells constituting the ensemble
for patch in tqdm(i_sky):
    sky = mesh.extract_cells(patch) # extract one cell
    sky = pvf.fc_unstruc2poly(sky) # convert to polydata
    if pvf.get_visibility(sky, wall): # if the can see each other...
        if pvf.get_visibility_raytrace(sky, wall, meshpoly): # ... if no obstruction
            Fsky += pvf.compute_viewfactor(sky, wall) # compute and increment view factor : F_i->(j+k) = F_i->j + F_i->k

# same for building 1
Fbuilding1 = 0
for patch in tqdm(i_building1):
    bldng1 = mesh.extract_cells(patch)
    bldng1 = pvf.fc_unstruc2poly(bldng1)
    if pvf.get_visibility(bldng1, wall):
        if pvf.get_visibility_raytrace(bldng1, wall, meshpoly):
            Fbuilding1 += pvf.compute_viewfactor(bldng1, wall)

# same for building 2
Fbuilding2 = 0
for patch in tqdm(i_building2):
    bldng2 = mesh.extract_cells(patch)
    bldng2 = pvf.fc_unstruc2poly(bldng2)
    if pvf.get_visibility(bldng2, wall):
        if pvf.get_visibility_raytrace(bldng2, wall, meshpoly):
            Fbuilding2 += pvf.compute_viewfactor(bldng2, wall)

# complementarity implies \sigma F_i = 1 : compute viewfactor to ground
Fground = 1-Fbuilding1-Fbuilding2-Fsky

print('\n----------------------')
print('Wall to environment view factors :')
print('\tSky ', round(Fsky, 4))
print('\tBuilding 1 ', round(Fbuilding1, 4))
print('\tBuilding 2 ', round(Fbuilding2, 4))
print('Ground view factor :')
print('\tGround ', round(Fground, 4))
```
The code yields following view factors :
```math
F_{\text{sky}} = 0.345 \\
F_{\text{ground}} = 0.373 \\
F_{\text{building1}} = 0.251 \\
F_{\text{building2}} = 0.031 \\
```

## Understanding the obstruction check function

In real life problems, obstacles may well hinder the radiation heat transfer between surfaces. We make use here of [pyvista's raytrace function](https://docs.pyvista.org/examples/01-filter/poly-ray-trace.html) to perform obstruction tests, as per following example, much inspired from pyvista's online documentation.

<img src="https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/intersection_simple.png?raw=true" alt="Obstruction check between rectangles" width="350"/>

The code snippet below shows how the ray tracing function works and allows to understand its usage in the pyviewfactor `get_visibility_raytrace` function.
```python
import pyvista as pv
from pyviewfactor import get_visibility_raytrace
# let us first create two rectangles
pointa = [1, 0, 0]
pointb = [1, 1, 0]
pointc = [0, 1, 0]
pointd = [0, 0, 0]
rectangle_down = pv.Rectangle([pointa, pointb, pointc, pointd])
pointa = [1, 0, 1]
pointb = [1, 1, 1]
pointc = [0, 1, 1]
pointd = [0, 0, 1]
rectangle_up = pv.Rectangle([pointa, pointb, pointc, pointd])

# a circle will be the obstruction
z_translation, r = 0.5, 2
obstacle = pv.Circle(radius=r, resolution=10)
# we translate the obstruction right between both rectangles
obstacle.translate([0, 0, z_translation], inplace=True)
# Define line segment
start = rectangle_down.cell_centers().points[0]
stop = rectangle_up.cell_centers().points[0]
# Perform ray trace
points, ind = obstacle.ray_trace(start, stop)

# Create geometry to represent ray trace
ray = pv.Line(start, stop)
intersection = pv.PolyData(points)

# Render the result
p = pv.Plotter(notebook=True)
p.add_mesh(obstacle, show_edges=True, opacity=0.5, color="red", lighting=False, label="obstacle")
p.add_mesh(rectangle_up, color="blue", line_width=5, opacity=0.5, label="rect up")
p.add_mesh(rectangle_down, color="yellow", line_width=5,opacity=0.5, label="rect down")
p.add_mesh(ray, color="green", line_width=5, label="ray trace")

# if any intersection
if intersection.n_cells > 0:
    p.add_mesh(intersection, color="green", point_size=25, label="Intersection Points")
p.add_legend()
p.show(cpos="yz")

#now a call to the obstruction check function
print(get_visibility_raytrace(rectangle_up, rectangle_down, obstacle))
```

More complex scenes can then be treated with the function `get_visibility_raytrace`.

<img src="https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/intersection.png?raw=true" alt="Obstruction within an enclosure" width="350"/>

## Installation
pyViewFactor can be installed from [PyPi](https://pypi.org/project/pyviewfactor/) using `pip` on Python >= 3.7:
```
pip install pyviewfactor
```
You can also visit [PyPi](https://pypi.org/project/pyviewfactor/) or [Gitlab](https://gitlab.com/arep-dev/pyViewFactor) to download the sources. 

Requirements: 
```
numpy==1.17.4
pandas==1.4.2
pyvista==0.35.2
scipy==1.8.1
numba>=0.55.2
```
The code will probably work with lower versions of the required packages, however this has not been tested.

__Note__ - If you are alergic to `numba`, you may `pip install pyviewfactor==0.0.10` that works (and give up the x2 speed-up in view factor computation).

## Authors and acknowledgment
Mateusz BOGDAN, Edouard WALTHER, Marc ALECIAN, Mina CHAPON

## Citation
There is even a [conference paper](https://www.researchgate.net/publication/360835982_Calcul_des_facteurs_de_forme_entre_polygones_-Application_a_la_thermique_urbaine_et_aux_etudes_de_confort), showing analytical validations :
> Mateusz BOGDAN, Edouard WALTHER, Marc ALECIAN and Mina CHAPON. _Calcul des facteurs de forme entre polygones - Application à la thermique urbaine et aux études de confort_. IBPSA France 2022, Châlons-en-Champagne. 

Bibtex entry:
``` latex
@inproceedings{pyViewFactor22bogdan,
  authors      = "Mateusz BOGDAN and Edouard WALTHER and Marc ALECIAN and Mina CHAPON",
  title        = "Calcul des facteurs de forme entre polygones - Application à la thermique urbaine et aux études de confort",
  year         = "2022",
  organization = "IBPSA France",
  venue        = "Châlons-en-Champagne, France"
  note         = "IBPSA France 2022",
}
```

## License
MIT License - Copyright (c) AREP 2022



            

Raw data

            {
    "_id": null,
    "home_page": "https://gitlab.com/arep-dev/pyViewFactor/",
    "name": "pyviewfactor",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "radiative-transfer radiation vtk geometry ViewFactor STL visibility",
    "author": "Mateusz BOGDAN, Edouard WALTHER, Marc ALECIAN, Mina CHAPON",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/40/57/e1fac9cd3509ba3692b484aa5883ba413114977a6ac97a9f16c9d26b92e0/pyviewfactor-0.0.16.tar.gz",
    "platform": null,
    "description": "# PyViewFactor\n [![Latest Release](https://gitlab.com/arep-dev/pyViewFactor/-/badges/release.svg)](https://gitlab.com/arep-dev/pyViewFactor/-/releases) \n [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n [![Pypi Version](https://img.shields.io/pypi/v/pyviewfactor)](https://pypi.org/project/pyviewfactor/)\n [![Pypi Downloads](https://img.shields.io/pypi/dm/pyviewfactor.svg?label=pypi%20downloads)](https://pypi.org/project/pyviewfactor/)\n \nA python library to compute exact view factors between planar faces ([Documentation](https://arep-dev.gitlab.io/pyViewFactor/)).\n\nThis code computes the radiation view factor between polygons using the double contour integral method described in [(Mazumder and Ravishankar 2012)](https://www.academia.edu/download/77459051/Viewfactor_paper_IJHMT.pdf) and [(Schmid 2016)](https://hal.archives-ouvertes.fr/tel-01734545/).\n\nIt uses the handy [Pyvista](https://docs.pyvista.org/) package to deal with geometrical aspects of such problems. \n\n##  How does it work?\n\n- [x] Use [pyvista](https://docs.pyvista.org/index.html) to import your geometry (*.stl, *.vtk, *.obj, ...) or alternately draw it with the same package.\n- [x] Optionally check that the faces can \"see\" each other with `get_visibility(face1, face2)`\n- [x] Optionally check that no obstruction lies between them `get_visibility_obstruction(face1, face2, obstacle)`\n- [x] Compute the view factor from `face2` to `face1` with `compute_view_factor(face1, face2)`: Done!\n\n##  Minimum working example : facet to facet view factor computation \n\nSuppose we want to compute the radiation view factor between a triangle and a rectangle.\n\n<img src=\"https://gitlab.com/arep-dev/pyViewFactor/-/raw/64e19ed126bbfd1bc2bff1197b1dee23d35c7836/img/mwe.png?raw=true\" alt=\"Triangle and rectangle configuration\" width=\"260\"/>\n\n\nYou are now 18 lines of code away from your first view factor computation:\n\n```python\nimport pyvista as pv\nimport pyviewfactor as pvf\n\n# first define a rectangle...\npointa = [1, 0, 0] \npointb = [1, 1, 0]\npointc = [0, 1, 0]\npointd = [0, 0, 0]\nrectangle = pv.Rectangle([pointa, pointb, pointc, pointd])\n\n# ... then a triangle\npointa = [1, 0, 1] \npointb = [1, 1, 1]\npointc = [0, 1, 1]\nliste_pts = [pointa, pointb, pointc]\nliste_pts.reverse() # let us put the normal the other way around (facing the rectangle)\ntriangle = pv.Triangle(liste_pts) # ... done with geometry.\n\n# preliminary check for visibility\nif pvf.get_visibility(rectangle , triangle):\n    F = pvf.compute_viewfactor(rectangle, triangle)\n    print(\"View factor from triangle to rectangle = \", F)\nelse:\n    print(\"Not facing each other\")\n```\n\nYou usually get your geometry from a different format? (*.idf, *.dat, ...)\n\nCheck pyvista's documentation on [how to generate a PolyData facet from points](https://docs.pyvista.org/examples/00-load/create-poly.html).\n\n## Example with a closed geometry and the VTK file format\n\nWe will now compute the view factors within a more complex geometry: a  closed sphere (clipped in half below), with inwards facing normals, so the faces can \"see\" each other. Note that the face-to-face visibility is unobstructed (for obstructed geometries, see next section).\n\nThe field of view factors from one facet to all others will be computed and stored in a VTK file, which you can explore with the open source [Paraview software](https://www.paraview.org/download/).\n\n<img src=\"https://gitlab.com/arep-dev/pyViewFactor/-/raw/73249e2093b207d5030d9b6637603c4b77b2374c/img/demi_sphere.png?raw=true\" alt=\"Sphere\" width=\"350\"/>\n\nFollowing snippet can be reused as a kick-start for your own purposes:\n```python\nimport pyvista as pv\nimport numpy as np\nfrom pyviewfactor import  compute_viewfactor, fc_unstruc2poly # viewfactor + a useful conversion function\nfrom tqdm import tqdm # for a fancy progress bar\n\n# create a raw sphere with pyvista\nsphere = pv.Sphere(radius=50, center=(0, 0, 0), direction=(0, 0, 1),\n                 theta_resolution=9, phi_resolution=9)\n# and put the normals inwards please\nsphere.flip_normals()\n\n# let us chose a cell to compute view factors from\nchosen_face = sphere.extract_cells(10)\n# convert the face from UnstructuredGrid to PolyData\nchosen_face = fc_unstruc2poly(chosen_face)\n# \"one array to contain them all\" -> the results will be stored there\nF = np.zeros(sphere.n_cells) \n\n# now let us compute the view factor to all other faces\n# (with a fancy progress bar, iterating over the mesh's faces)\nfor i in tqdm(range(sphere.n_cells), total=sphere.n_cells):\n    face = sphere.extract_cells(i) # other facet\n    face = fc_unstruc2poly(face) # convert to PolyData\n    F[i] = compute_viewfactor(face, chosen_face) # compute VF\n\nprint(\"Complementarity check: \\n (e.g. is \\sum_{i=0}^n F_i =? 1)\", np.sum(F))\n\n# put the scalar values in the geometry\nsphere.cell_data[\"F\"] = F\nsphere.save(\"./sphere.vtk\") # ... and save.\n\n# let us have a look in 3D with an interactive window...\np=pv.Plotter() # instantiate 3D window\np.add_mesh(sphere, scalars='F', cmap='jet') # add mesh with a nice color scheme\np.show() # plot\n```\nThe results look as per following images showing the view factor from the chosen cell to all others.\n\n<img src=\"https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/F_sphere.png?raw=true\" alt=\"VF to other faces inside the sphere\" width=\"240\"/>\n<img src=\"https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/F_sphere_clip.png?raw=true\" alt=\"Clipped result\" width=\"240\"/>\n\n## View factors of an individual with a wall\n\nFor comfort computations, it may be useful to determine heat transfer between an invidivual and a wall. We will use here PyVista's [doorman example](https://docs.pyvista.org/api/examples/_autosummary/pyvista.examples.downloads.download_doorman.html?highlight=example+man#pyvista.examples.downloads.download_doorman) as a basis for the human geometry.\n\n<img src=\"https://gitlab.com/arep-dev/pyViewFactor/-/raw/efeae65b20630978972a94de2cffaa4ab5e427dc/img/Fground.png?raw=true\" alt=\"View factors of the doorman's faces to the ground\" width=\"380\"/>\n\nThe following code and VTK file of the doorman example are available in the [./examples/](https://gitlab.com/arep-dev/pyViewFactor/-/tree/main/examples) folder.\n```python\n# -*- coding: utf-8 -*-\nfrom tqdm import tqdm\nimport numpy as np\nimport pyvista as pv\nimport pyviewfactor as pvf\n\ndef fc_Fwall(nom_vtk):\n    mesh=pv.read(nom_vtk)\n    \n    # find all types of walls\n    wall_types=list(np.unique(mesh['names']))\n    # remove the individual from the list (still named 'cylinder'...)\n    wall_types.remove('cylinder\\r') # with dirty trailing character\n    # where is the doorman in the list?\n    index_doorman=np.where(mesh['names']=='cylinder\\r')[0]\n    # prepare storage for the different walls in a dict\n    dict_F={}\n    # loop over wall types\n    for type_wall in wall_types:\n        # prepare for storing doorman to wall view factor\n        F=np.zeros(mesh.n_cells)\n        # get the indices of this type of wall\n        indices=np.where(mesh['names']==type_wall )[0]\n        # loop over\n        for i in indices:\n            wall=mesh.extract_cells(i)\n            wall=pvf.fc_unstruc2poly(wall) # convert for normals\n            # ... for each facet of the individual\n            for idx in tqdm(index_doorman):\n                face = mesh.extract_cells(idx)\n                face =pvf.fc_unstruc2poly(face) # convert for normals\n                # check if faces can \"see\" each other\n                if pvf.get_visibility(wall,face):\n                    Ffp=pvf.compute_viewfactor(wall,face) # compute face2wall view factor\n                else:\n                    Ffp=0\n                F[idx]=Ffp\n        #store array F in e.g. dict_F['F_ceiling']\n        dict_F['F_'+type_wall.replace('\\r','')]=F\n    return dict_F\n\n# download it directly from https://gitlab.com/arep-dev/pyViewFactor/-/blob/main/examples/example_doorman.vtk ...\n# ...or get it from this repository's examples\nfile=\"./example_doorman.vtk\"\n# compute the view factors or the doorman to the different wall types in the scene\ndict_F=fc_Fwall(file)\n\n# re-read and store\nmesh=pv.read(file)\n# loop over what is in the dictionary of view factors\nfor elt in dict_F.keys():\n    mesh[elt.replace('\\r','')]=dict_F[elt] # name the field\nmesh.save(file) # store in the intial VTK\n\n# have a look without paraview with fancy colors\nmesh.plot(cmap='jet',lighting=False)\n```\n\nMore details and view abacuses in [this page](https://lhypercube.arep.fr/en/confort/calcul-de-la-temperature-radiante/). Is the computation time a bit lengthy? Learn how to [go parallel!](https://eddes.github.io/#go-parallel).\n\n## Computing the view factors of a wall in its built environment\n\nFor building simulation purposes, it may prove to be useful to compute the ground and sky view factors of a given wall, or the view factor of the wall to other walls in the built environment. In following example (available in the \"examples\" folder), we compute the view factors of the environment of the purple wall depicted below.\n\n<img src=\"https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/wall_view_factors.png?raw=true\" alt=\"View factors in built environment\" width=\"430\"/>\n\n```python\nimport numpy as np\nimport pyvista as pv\nfrom tqdm import tqdm\nimport pyviewfactor as pvf\n\n# read the geometry\nmesh = pv.read(\"./built_envmt.vtk\")\nmeshpoly = pvf.fc_unstruc2poly(mesh) # convert to polydata for obstruction check\n\n# identify who is who\ni_wall = np.where(mesh[\"wall_names\"]=='wall')[0]\ni_sky = np.where(mesh[\"wall_names\"]=='sky')[0]\ni_building1 = np.where(mesh[\"wall_names\"]=='building1')[0]\ni_building2 = np.where(mesh[\"wall_names\"]=='building2')[0]\n\n# get the different elements\nwall = mesh.extract_cells(i_wall)\nsky = mesh.extract_cells(i_sky)\nbuilding1 = mesh.extract_cells(i_building1)\nbuilding2 = mesh.extract_cells(i_building2)\n\n# convert to polydata\nwall = pvf.fc_unstruc2poly(wall)\n\nFsky = 0\n# for all cells constituting the ensemble\nfor patch in tqdm(i_sky):\n    sky = mesh.extract_cells(patch) # extract one cell\n    sky = pvf.fc_unstruc2poly(sky) # convert to polydata\n    if pvf.get_visibility(sky, wall): # if the can see each other...\n        if pvf.get_visibility_raytrace(sky, wall, meshpoly): # ... if no obstruction\n            Fsky += pvf.compute_viewfactor(sky, wall) # compute and increment view factor : F_i->(j+k) = F_i->j + F_i->k\n\n# same for building 1\nFbuilding1 = 0\nfor patch in tqdm(i_building1):\n    bldng1 = mesh.extract_cells(patch)\n    bldng1 = pvf.fc_unstruc2poly(bldng1)\n    if pvf.get_visibility(bldng1, wall):\n        if pvf.get_visibility_raytrace(bldng1, wall, meshpoly):\n            Fbuilding1 += pvf.compute_viewfactor(bldng1, wall)\n\n# same for building 2\nFbuilding2 = 0\nfor patch in tqdm(i_building2):\n    bldng2 = mesh.extract_cells(patch)\n    bldng2 = pvf.fc_unstruc2poly(bldng2)\n    if pvf.get_visibility(bldng2, wall):\n        if pvf.get_visibility_raytrace(bldng2, wall, meshpoly):\n            Fbuilding2 += pvf.compute_viewfactor(bldng2, wall)\n\n# complementarity implies \\sigma F_i = 1 : compute viewfactor to ground\nFground = 1-Fbuilding1-Fbuilding2-Fsky\n\nprint('\\n----------------------')\nprint('Wall to environment view factors :')\nprint('\\tSky ', round(Fsky, 4))\nprint('\\tBuilding 1 ', round(Fbuilding1, 4))\nprint('\\tBuilding 2 ', round(Fbuilding2, 4))\nprint('Ground view factor :')\nprint('\\tGround ', round(Fground, 4))\n```\nThe code yields following view factors :\n```math\nF_{\\text{sky}} = 0.345 \\\\\nF_{\\text{ground}} = 0.373 \\\\\nF_{\\text{building1}} = 0.251 \\\\\nF_{\\text{building2}} = 0.031 \\\\\n```\n\n## Understanding the obstruction check function\n\nIn real life problems, obstacles may well hinder the radiation heat transfer between surfaces. We make use here of [pyvista's raytrace function](https://docs.pyvista.org/examples/01-filter/poly-ray-trace.html) to perform obstruction tests, as per following example, much inspired from pyvista's online documentation.\n\n<img src=\"https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/intersection_simple.png?raw=true\" alt=\"Obstruction check between rectangles\" width=\"350\"/>\n\nThe code snippet below shows how the ray tracing function works and allows to understand its usage in the pyviewfactor `get_visibility_raytrace` function.\n```python\nimport pyvista as pv\nfrom pyviewfactor import get_visibility_raytrace\n# let us first create two rectangles\npointa = [1, 0, 0]\npointb = [1, 1, 0]\npointc = [0, 1, 0]\npointd = [0, 0, 0]\nrectangle_down = pv.Rectangle([pointa, pointb, pointc, pointd])\npointa = [1, 0, 1]\npointb = [1, 1, 1]\npointc = [0, 1, 1]\npointd = [0, 0, 1]\nrectangle_up = pv.Rectangle([pointa, pointb, pointc, pointd])\n\n# a circle will be the obstruction\nz_translation, r = 0.5, 2\nobstacle = pv.Circle(radius=r, resolution=10)\n# we translate the obstruction right between both rectangles\nobstacle.translate([0, 0, z_translation], inplace=True)\n# Define line segment\nstart = rectangle_down.cell_centers().points[0]\nstop = rectangle_up.cell_centers().points[0]\n# Perform ray trace\npoints, ind = obstacle.ray_trace(start, stop)\n\n# Create geometry to represent ray trace\nray = pv.Line(start, stop)\nintersection = pv.PolyData(points)\n\n# Render the result\np = pv.Plotter(notebook=True)\np.add_mesh(obstacle, show_edges=True, opacity=0.5, color=\"red\", lighting=False, label=\"obstacle\")\np.add_mesh(rectangle_up, color=\"blue\", line_width=5, opacity=0.5, label=\"rect up\")\np.add_mesh(rectangle_down, color=\"yellow\", line_width=5,opacity=0.5, label=\"rect down\")\np.add_mesh(ray, color=\"green\", line_width=5, label=\"ray trace\")\n\n# if any intersection\nif intersection.n_cells > 0:\n    p.add_mesh(intersection, color=\"green\", point_size=25, label=\"Intersection Points\")\np.add_legend()\np.show(cpos=\"yz\")\n\n#now a call to the obstruction check function\nprint(get_visibility_raytrace(rectangle_up, rectangle_down, obstacle))\n```\n\nMore complex scenes can then be treated with the function `get_visibility_raytrace`.\n\n<img src=\"https://gitlab.com/arep-dev/pyViewFactor/-/raw/3ac896fe2f420443c7c96eaa9dbbb955474e80d5/img/intersection.png?raw=true\" alt=\"Obstruction within an enclosure\" width=\"350\"/>\n\n## Installation\npyViewFactor can be installed from [PyPi](https://pypi.org/project/pyviewfactor/) using `pip` on Python >= 3.7:\n```\npip install pyviewfactor\n```\nYou can also visit [PyPi](https://pypi.org/project/pyviewfactor/) or [Gitlab](https://gitlab.com/arep-dev/pyViewFactor) to download the sources. \n\nRequirements: \n```\nnumpy==1.17.4\npandas==1.4.2\npyvista==0.35.2\nscipy==1.8.1\nnumba>=0.55.2\n```\nThe code will probably work with lower versions of the required packages, however this has not been tested.\n\n__Note__ - If you are alergic to `numba`, you may `pip install pyviewfactor==0.0.10` that works (and give up the x2 speed-up in view factor computation).\n\n## Authors and acknowledgment\nMateusz BOGDAN, Edouard WALTHER, Marc ALECIAN, Mina CHAPON\n\n## Citation\nThere is even a [conference paper](https://www.researchgate.net/publication/360835982_Calcul_des_facteurs_de_forme_entre_polygones_-Application_a_la_thermique_urbaine_et_aux_etudes_de_confort), showing analytical validations :\n> Mateusz BOGDAN, Edouard WALTHER, Marc ALECIAN and Mina CHAPON. _Calcul des facteurs de forme entre polygones - Application \u00e0 la thermique urbaine et aux \u00e9tudes de confort_. IBPSA France 2022, Ch\u00e2lons-en-Champagne. \n\nBibtex entry:\n``` latex\n@inproceedings{pyViewFactor22bogdan,\n  authors      = \"Mateusz BOGDAN and Edouard WALTHER and Marc ALECIAN and Mina CHAPON\",\n  title        = \"Calcul des facteurs de forme entre polygones - Application \u00e0 la thermique urbaine et aux \u00e9tudes de confort\",\n  year         = \"2022\",\n  organization = \"IBPSA France\",\n  venue        = \"Ch\u00e2lons-en-Champagne, France\"\n  note         = \"IBPSA France 2022\",\n}\n```\n\n## License\nMIT License - Copyright (c) AREP 2022\n\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A python library to calculate numerically exact radiation view factors between planar faces.",
    "version": "0.0.16",
    "project_urls": {
        "Documentation": "https://arep-dev.gitlab.io/pyViewFactor/",
        "Homepage": "https://gitlab.com/arep-dev/pyViewFactor/",
        "Source": "https://gitlab.com/arep-dev/pyViewFactor/",
        "Tracker": "https://gitlab.com/arep-dev/pyViewFactor/-/issues"
    },
    "split_keywords": [
        "radiative-transfer",
        "radiation",
        "vtk",
        "geometry",
        "viewfactor",
        "stl",
        "visibility"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "4057e1fac9cd3509ba3692b484aa5883ba413114977a6ac97a9f16c9d26b92e0",
                "md5": "b8f868dfe3cfaaf53a86896aeb7e978a",
                "sha256": "f3df3cee1e858f036d7db804198ace0958445a4340944ffe0c500b36e3becf9d"
            },
            "downloads": -1,
            "filename": "pyviewfactor-0.0.16.tar.gz",
            "has_sig": false,
            "md5_digest": "b8f868dfe3cfaaf53a86896aeb7e978a",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 18799,
            "upload_time": "2023-11-20T11:19:35",
            "upload_time_iso_8601": "2023-11-20T11:19:35.818316Z",
            "url": "https://files.pythonhosted.org/packages/40/57/e1fac9cd3509ba3692b484aa5883ba413114977a6ac97a9f16c9d26b92e0/pyviewfactor-0.0.16.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-20 11:19:35",
    "github": false,
    "gitlab": true,
    "bitbucket": false,
    "codeberg": false,
    "gitlab_user": "arep-dev",
    "gitlab_project": "pyViewFactor",
    "lcname": "pyviewfactor"
}
        
Elapsed time: 0.15257s