Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 41 additions & 17 deletions tofu/geom/_GG.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -188,30 +188,51 @@ def CoordShift(Pts, In='(X,Y,Z)', Out='(R,Z)', CrossRef=None):

def Poly_isClockwise(np.ndarray[double,ndim=2] Poly):
""" Assuming 2D closed Poly !
TODO @LM :
http://www.faqs.org/faqs/graphics/algorithms-faq/
A slightly faster method is based on the observation that it isn't
necessary to compute the area. Find the lowest vertex (or, if
there is more than one vertex with the same lowest coordinate,
the rightmost of those vertices) and then take the cross product
of the edges fore and aft of it. Both methods are O(n) for n vertices,
but it does seem a waste to add up the total area when a single cross
product (of just the right edges) suffices. Code for this is
available at ftp://cs.smith.edu/pub/code/polyorient.C (2K).
Find the lowest vertex (or, if there is more than one vertex with
the same lowest coordinate, the rightmost of those vertices) and then
take the cross product of the edges before and after it.
Both methods are O(n) for n vertices, but it does seem a waste to add up
the total area when a single cross product (of just the right edges)
suffices. Code for this is available at
ftp://cs.smith.edu/pub/code/polyorient.C (2K).
"""
cdef double res
cdef double[:,::1] mv_poly = np.ascontiguousarray(Poly)
cdef int npts = mv_poly.shape[1]
cdef double[::1] mvx = mv_poly[0,:]
cdef double[::1] mvy = mv_poly[1,:]
cdef int idmin = _bgt.find_ind_lowerright_corner(mvx, mvy, npts)
cdef int idm1 = idmin - 1
cdef int idp1 = (idmin + 1)%npts
cdef int ndim = mv_poly.shape[0]
cdef double[::1] mvx
cdef double[::1] mvy
cdef int idmin
cdef int idm1
cdef int idp1
cdef str err_msg = ""
# Checking that Poly wasn't given in the shape (npts, ndim)
if ndim > npts:
mv_poly = np.ascontiguousarray(Poly.T)
npts = mv_poly.shape[1]
ndim = mv_poly.shape[0]
mvx = mv_poly[0,:]
mvy = mv_poly[1,:]
# Getting index of lower right corner and its neighbors
idmin = _bgt.find_ind_lowerright_corner(mvx, mvy, npts)
idm1 = idmin - 1
idp1 = (idmin + 1) % npts
if idmin == 0 :
idm1 = npts - 1
idm1 = npts - 2
# Computing area of lower right triangle
res = mvx[idm1] * (mvy[idmin] - mvy[idp1]) + \
mvx[idmin] * (mvy[idp1] - mvy[idm1]) + \
mvx[idp1] * (mvy[idm1] - mvy[idmin])
if abs(res) < _VSMALL:
err_msg += ("In Poly_isClockwise : \n"
+ " Found lowest right point at index : "
+ str(idmin)
+ ", of coordinates :" + str(mvx[idmin])
+ ", " + str(mvy[idmin]) + ".\n"
+ " The two neighboring points are : "
+ str(idm1) + " and " + str(idp1) + ".")
raise Exception(err_msg) # not working
Comment thread
Didou09 marked this conversation as resolved.
return res < 0.


Expand Down Expand Up @@ -274,8 +295,11 @@ def Poly_Order(np.ndarray[double,ndim=2] Poly, str order='C', Clock=False,
if not np.allclose(poly[:,0],poly[:,-1], atol=_VSMALL):
poly = np.concatenate((poly,poly[:,0:1]),axis=1)
if poly.shape[0]==2 and not Clock is None:
if not Clock==Poly_isClockwise(poly):
poly = poly[:,::-1]
try:
if not Clock==Poly_isClockwise(poly):
poly = poly[:,::-1]
except Exception as excp:
raise excp
Comment thread
Didou09 marked this conversation as resolved.
if not close:
poly = poly[:,:-1]
if layout.lower()=='(n,cc)':
Expand Down
1 change: 1 addition & 0 deletions tofu/geom/_basic_geom_tools.pxd
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# cython: boundscheck=False
# cython: wraparound=False
# cython: cdivision=True
# cython: initializedcheck=False
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this flag do ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cython normally checks if a memory view is initialized before using it. This turns the verification off (for speed purposes). I wanted to match the flags with the GG file.

#
################################################################################
# Utility functions for basic geometry :
Expand Down
2 changes: 2 additions & 0 deletions tofu/geom/_basic_geom_tools.pyx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# cython: boundscheck=False
# cython: wraparound=False
# cython: cdivision=True
# cython: initializedcheck=False
#
cimport cython

from cython.parallel import prange
Expand Down
15 changes: 10 additions & 5 deletions tofu/geom/_comp.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ def _Struct_set_Poly(
""" Compute geometrical attributes of a Struct object """

# Make Poly closed, counter-clockwise, with '(cc,N)' layout and arrayorder
Poly = _GG.Poly_Order(
Poly, order="C", Clock=False, close=True, layout="(cc,N)", Test=True
)
try:
Poly = _GG.Poly_Order(Poly, order="C", Clock=False, close=True,
layout="(cc,N)", Test=True)
except Exception as excp:
print(excp)
Comment thread
lasofivec marked this conversation as resolved.
assert Poly.shape[0] == 2, "Arg Poly must be a 2D polygon !"
fPfmt = np.ascontiguousarray if arrayorder == "C" else np.asfortranarray

Expand All @@ -62,8 +64,11 @@ def _Struct_set_Poly(
else:
Vol, BaryV = _GG.Poly_VolAngTor(Poly)
if Vol <= 0.0:
msg = "Pb. with volume computation for Ves object of type 'Tor' !"
msg = "\n Here Volume = " + str(Vol)
msg = ("Pb. with volume computation for Struct of type 'Tor' !\n"
+ "\t- Vol = {}\n".format(Vol)
+ "\t- Poly = {}\n\n".format(str(Poly))
+ " => Probably corrupted polygon\n"
+ " => Please check polygon is not self-intersecting")
raise Exception(msg)

# Compute the non-normalized vector of each side of the Poly
Expand Down
40 changes: 23 additions & 17 deletions tofu/geom/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2203,8 +2203,8 @@ def _get_largs_dsino():

def _checkformat_inputs_Struct(self, struct, err=True):
assert issubclass(struct.__class__, Struct)
C0 = struct.Id.Exp==self.Id.Exp
C1 = struct.Id.Type==self.Id.Type
C0 = struct.Id.Exp == self.Id.Exp
C1 = struct.Id.Type == self.Id.Type
C2 = struct.Id.Name.isidentifier()
C2 = C2 and '_' not in struct.Id.Name
msgi = None
Expand Down Expand Up @@ -3134,7 +3134,6 @@ def plot_phithetaproj_dist(self, refpt=None, ntheta=None, nphi=None,
tit=tit, wintit=wintit,
invertx=invertx, draw=draw)


def isInside(self, pts, In="(X,Y,Z)", log="any"):

""" Return a 2D array of bool
Expand Down Expand Up @@ -3728,7 +3727,7 @@ def _checkformat_inputs_dgeom(self, dgeom=None):
if (isinstance(dgeom, self._dcases[k]['type'])
and all([kk in dgeom.keys() # noqa
for kk in self._dcases[k]['lk']]))]
if not len(lC)==1:
if not len(lC) == 1:
lstr = [v['lk'] for v in self._dcases.values()]
msg = "Arg dgeom must be either:\n"
msg += " - dict with keys:\n"
Expand Down Expand Up @@ -4141,7 +4140,8 @@ def _complete_dX12(self, dgeom):
k = np.sum(DDb*(u - np.sqrt(sca2)*dgeom['u'][:, 1:]),
axis=0)
k = k / (1.0-sca2)
if k[0] > 0 and np.allclose(k, k[0], atol=1.e-3, rtol=1.e-6):
if k[0] > 0 and np.allclose(k, k[0], atol=1.e-3,
rtol=1.e-6):
pinhole = dgeom['D'][:, 0] + k[0]*u[:, 0]
dgeom['pinhole'] = pinhole

Expand Down Expand Up @@ -5033,8 +5033,8 @@ def D(self):

@property
def u(self):
if (self._dgeom['u'] is not None
and self._dgeom['u'].shape[1] == self._dgeom['nRays']):
if self._dgeom['u'] is not None \
and self._dgeom['u'].shape[1] == self._dgeom['nRays']:
u = self._dgeom['u']
elif self.isPinhole:
u = self._dgeom['pinhole'][:, None] - self._dgeom['D']
Expand Down Expand Up @@ -5127,7 +5127,7 @@ def _isLOS(cls):
def _check_indch(self, ind, out=int):
if ind is not None:
ind = np.asarray(ind)
assert ind.ndim==1
assert ind.ndim == 1
assert ind.dtype in [np.int64, np.bool_, np.long]
if ind.dtype == np.bool_:
assert ind.size == self.nRays
Expand Down Expand Up @@ -5574,17 +5574,17 @@ def _kInOut_Isoflux_inputs_usr(self, lPoly, lVIn=None):
if type(lPoly) is list:
for ii in range(nPoly):
# Check closed and anti-clockwise
if _GG.Poly_isClockwise(lPoly[ii]):
lPoly[ii] = lPoly[ii][:, ::-1]
if not np.allclose(lPoly[ii][:, 0], lPoly[ii][:, -1]):
lPoly[ii] = np.concatenate(
(lPoly[ii], lPoly[ii][:, 0:1]), axis=-1
)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first we close the poly then we check if clockwise

try:
if _GG.Poly_isClockwise(lPoly[ii]):
lPoly[ii] = lPoly[ii][:, ::-1]
except Exception as excp:
print("For structure ", ii, " : ", excp)
else:
for ii in range(nPoly):
# Check closed and anti-clockwise
if _GG.Poly_isClockwise(lPoly[ii]):
lPoly[ii] = lPoly[ii][:, ::-1]
# Check closed and anti-clockwise
d = np.sum((lPoly[:, :, 0]-lPoly[:, :, -1])**2, axis=1)
if np.allclose(d, 0.):
pass
Expand All @@ -5593,6 +5593,12 @@ def _kInOut_Isoflux_inputs_usr(self, lPoly, lVIn=None):
else:
msg = "All poly in lPoly should be closed or all non-closed!"
raise Exception(msg)
for ii in range(nPoly):
try:
if _GG.Poly_isClockwise(lPoly[ii]):
lPoly[ii] = lPoly[ii][:, ::-1]
except Exception as excp:
print("For structure ", ii, " : ", excp)

# Check lVIn
if lVIn is None:
Expand Down Expand Up @@ -5663,14 +5669,14 @@ def calc_kInkOut_Isoflux(self, lPoly, lVIn=None, Lim=None,

# Compute intersections
assert(self._method in ['ref', 'optimized'])
if self._method=='ref':
if self._method == 'ref':
for ii in range(0, nPoly):
largs, dkwd = self._kInOut_Isoflux_inputs([lPoly[ii]],
lVIn=[lVIn[ii]])
out = _GG.SLOW_LOS_Calc_PInOut_VesStruct(*largs, **dkwd)
# PIn, POut, kin, kout, VperpIn, vperp, IIn, indout = out[]
kIn[ii, :], kOut[ii, :] = out[2], out[3]
elif self._method=="optimized":
elif self._method == "optimized":
for ii in range(0, nPoly):
largs, dkwd = self._kInOut_Isoflux_inputs([lPoly[ii]],
lVIn=[lVIn[ii]])
Expand Down Expand Up @@ -6900,7 +6906,7 @@ def get_summary(
# Prepare
kout = self._dgeom["kOut"]
indout = self._dgeom["indout"]
lS = self._dconfig["Config"].lStruct
# lS = self._dconfig["Config"].lStruct
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is not being used, so I commented it

angles = np.arccos(-np.sum(self.u*self.dgeom['vperp'], axis=0))

# ar0
Expand Down
2 changes: 1 addition & 1 deletion tofu/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Do not edit, pipeline versioning governed by git tags!
__version__ = '1.4.2-a5-113-gcbcc34c7'
__version__ = '1.4.2b13-65-ga0f432bb'