Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Surface generation refactor #5

Merged
merged 33 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
63efcf2
Factoring out the gq surface characterization
pshriwise Sep 19, 2024
5faea95
Moving some functions relying on encapsulation into their own file.
pshriwise Sep 20, 2024
09519bc
Moving another function over.
pshriwise Sep 20, 2024
e70cc54
Factoring out some geometry functions into their own file
pshriwise Sep 20, 2024
54760c9
Factoring out planar surfaces
pshriwise Sep 20, 2024
c873b1d
Further refactor of classes
pshriwise Sep 20, 2024
d186dda
Reducing common code
pshriwise Sep 20, 2024
7d37a0f
Adding surfaces file
pshriwise Sep 20, 2024
b0b0c30
Factoring out axis-aligned cylinders
pshriwise Sep 23, 2024
bfdc2cb
Factoring out general cylinder
pshriwise Sep 23, 2024
0ddf087
Adding tests for x and y cylinders
pshriwise Sep 30, 2024
2315239
Add sphere to capabilities. Correct error message formatting
pshriwise Sep 30, 2024
31f1676
Add test dir module file
pshriwise Sep 30, 2024
273cb5a
Correcting rotation code
pshriwise Oct 1, 2024
aacb8f6
Adding test for cylinder
pshriwise Oct 1, 2024
b7d328a
QOL updates
pshriwise Oct 22, 2024
967ba98
Fixing inheritance
pshriwise Oct 23, 2024
fe1f80f
Adding a note for future implementation
pshriwise Oct 23, 2024
55f9ab4
Add update capability to test suite
pshriwise Oct 23, 2024
fc67dd9
Updating test files with new material assignments
pshriwise Oct 23, 2024
b17dfbd
Truncate group names over 32 characters
pshriwise Oct 23, 2024
d11cff8
Adding axis-aligned cone tests
pshriwise Oct 24, 2024
13791d3
New axis-aligned cone classes.
pshriwise Oct 24, 2024
08551ac
p8
pshriwise Oct 24, 2024
c956ceb
Use CADZCone
pshriwise Oct 24, 2024
6c222de
Adding torii tests
pshriwise Oct 24, 2024
cb5b475
Add torus surfaces
pshriwise Oct 24, 2024
f738270
Reduce test clutter, apply run_in_tmpdir
pshriwise Oct 24, 2024
1f7205b
Fix assembly test
pshriwise Oct 24, 2024
8048a69
Running examples in tmp dir for clean repo
pshriwise Oct 24, 2024
39c1d36
Update tests. Check for corner case with torii
pshriwise Oct 24, 2024
f782bed
Updating README regarding limitations
pshriwise Oct 24, 2024
dd41ae0
Making a placeholder class for Cone
pshriwise Oct 24, 2024
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
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ There has been no methodical V&V on this converter; use at your own risk!

There are several known and many unknown limitations of this tool. It is in a
preliminary state and subject to considerable redesign, including the addition
of a backend for other CAD engines.
of a backend for other CAD engines.

Specific Limitations:

- general Cones are not handled
- Torii are required to have a single minor radius, OpenMC allows for different minor radii orthogonal to the toroidal axis
28 changes: 28 additions & 0 deletions src/openmc_cad_adapter/cubit_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
_CUBIT_ID = 1


def reset_cubit_ids():
global _CUBIT_ID
_CUBIT_ID = 1


def lastid():
global _CUBIT_ID
id_out = _CUBIT_ID
_CUBIT_ID += 1
return id_out


def new_variable():
idn = lastid()
return f"id{idn}"


def emit_get_last_id(type="body", cmds=None):
idn = lastid()
ids = f"id{idn}"
if cmds is not None:
cmds.append(f'#{{ {ids} = Id("{type}") }}')
else:
print('Warning: cmds is None')
return ids
42 changes: 42 additions & 0 deletions src/openmc_cad_adapter/geom_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import math
import numpy as np

def vector_to_euler_xyz(v):
v = np.asarray(v)
v /= np.linalg.norm(v)

x, y, z = v

xy_norm = math.sqrt(x**2 + y**2)

theta = np.arctan2(z, xy_norm)
# if z component is zero, vector is in the xy plane
if z == 0:
theta = np.pi / 2
phi = np.arctan2(y, x)

# Ensure angles are within [0, 2*pi] range
phi %= (2 * math.pi)
theta %= (2 * math.pi)

oe = 180 / math.pi
return phi * oe, theta * oe, 0.0


def rotate(id, x, y, z, cmds):
if nonzero(x, y, z):
phi, theta, psi = vector_to_euler_xyz((x, y, z))
cmds.append(f"body {{ {id} }} rotate {theta} about Y")
cmds.append(f"body {{ {id} }} rotate {phi} about Z")
# cmds.append(f"body {{ {id} }} rotate {phi} about Z")
# cmds.append(f"body {{ {id} }} rotate {theta} about Y")
# cmds.append(f"body {{ {id} }} rotate {psi} about X")


def nonzero(*args):
return any(arg != 0 for arg in args)


def move( id, x, y, z, cmds):
if nonzero( x, y, z ):
cmds.append(f"body {{ {id} }} move {x} {y} {z}")
136 changes: 136 additions & 0 deletions src/openmc_cad_adapter/gqs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import numpy as np


ELLIPSOID = 1
ONE_SHEET_HYPERBOLOID = 2
TWO_SHEET_HYPERBOLOID = 3
ELLIPTIC_CONE = 4
ELLIPTIC_PARABOLOID = 5
HYPERBOLIC_PARABOLOID = 6
ELLIPTIC_CYLINDER = 7
HYPERBOLIC_CYLINDER = 8
PARABOLIC_CYLINDER = 9


def characterize_general_quadratic( surface ): #s surface
gq_tol = 1e-6
equivalence_tol = 1e-8
a = surface.coefficients['a']
b = surface.coefficients['b']
c = surface.coefficients['c']
d = surface.coefficients['d']
e = surface.coefficients['e']
f = surface.coefficients['f']
g = surface.coefficients['g']
h = surface.coefficients['h']
j = surface.coefficients['j']
k = surface.coefficients['k']
#coefficient matrix
Aa = np.matrix([
[a, d/2, f/2],
[d/2, b, e/2],
[f/2, e/2, c]])
#hessian matrix
Ac = np.matrix([
[a, d/2, f/2, g/2],
[d/2, b, e/2, h/2],
[f/2, e/2, c, j/2],
[g/2, h/2, j/2, k]])
rank_Aa = matrix_rank( Aa )
rank_Ac = matrix_rank( Ac )

det_Ac = np.linalg.det(Ac)
if np.abs( det_Ac ) < gq_tol:
delta = 0
else:
delta = -1 if det_Ac < 0 else -1
eigen_results = np.linalg.eig(Aa);
signs = np.array([ 0, 0, 0 ])
for i in range( 0, 3 ):
if eigen_results.eigenvalues[ i ] > -1 * gq_tol:
signs[i] = 1
else:
signs[i] = -1

S = 1 if np.abs( signs.sum() ) == 3 else -1

B = np.array([[ -g/2], [-h/2], [-j/2 ]])

Aai = np.linalg.pinv( Aa )

C = Aai * B

dx = C[0]
dy = C[1]
dz = C[2]

#Update the constant using the resulting translation
K_ = k + g/2*dx + h/2*dy + j/2*dz

if rank_Aa == 2 and rank_Ac == 3 and S == 1:
delta = -1 if K_ * signs[0] else 1

D = -1 if K_ * signs[0] else 1


def find_type( rAa, rAc, delta, S, D ):
if 3 == rAa and 4 == rAc and -1 == delta and 1 == S:
return ELLIPSOID
elif 3 == rAa and 4 == rAc and 1 == delta and -1 == S:
return ONE_SHEET_HYPERBOLOID
elif 3 == rAa and 4 == rAc and -1 == delta and -1 == S:
return TWO_SHEET_HYPERBOLOID
elif 3 == rAa and 3 == rAc and 0 == delta and -1 == S:
return ELLIPTIC_CONE
elif 2 == rAa and 4 == rAc and -1 == delta and 1 == S:
return ELLIPTIC_PARABOLOID
elif 2 == rAa and 4 == rAc and 1 == delta and -1 == S:
return HYPERBOLIC_PARABOLOID
elif 2 == rAa and 3 == rAc and -1 == delta and 1 == S:
return ELLIPTIC_CYLINDER
elif 2 == rAa and 3 == rAc and 0 == delta and -1 == S:
return HYPERBOLIC_CYLINDER
elif 2 == rAa and 3 == rAc and 0 == delta and 1 == S:
return PARABOLIC_CYLINDER
elif 2 == rAa and 3 == rAc and 1 == S and D != 0 :
return find_type( rAa, rAc, D, S, 0 )
else:
raise "UNKNOWN QUADRATIC"

gq_type = find_type( rank_Aa, rank_Ac, delta, S, D )

#set the translation
translation = C

rotation_matrix = eigen_results.eigenvectors
eigenvalues = eigen_results.eigenvalues

for i in range( 0, 3 ):
if abs(eigenvalues[i]) < gq_tol:
eigenvalues[i] = 0

A_ = eigenvalues[0]
B_ = eigenvalues[1]
C_ = eigenvalues[2];
D_ = 0; E_ = 0; F_ = 0;
G_ = 0; H_ = 0; J_ = 0;
if gq_type == ONE_SHEET_HYPERBOLOID:
if abs( K_) < equivalence_tol:
K_ = 0
return ELLIPTIC_CONE
if gq_type == TWO_SHEET_HYPERBOLOID:
if abs( K_) < equivalence_tol:
K_ = 0
return ELLIPTIC_CONE
if gq_type == ELLIPSOID:
if abs( A_) < equivalence_tol:
A_ = 0
return ELLIPTIC_CYLINDER
elif abs( B_) < equivalence_tol:
B_ = 0
return ELLIPTIC_CYLINDER
elif abs( C_) < equivalence_tol:
C_ = 0
return ELLIPTIC_CYLINDER
else:
return (gq_type, A_, B_, C_, K_, translation, rotation_matrix)
Loading
Loading