5def print_const(arg, fmt = '%4.6e', prefix = ""):
6 return prefix + fmt % arg +
'\n'
8def print_list(arg, fmt = '%4.6e', delim = ', '):
10 for i
in range(len(arg)):
16def print_bool(arg, prefix = ""):
17 return prefix +
'True\n' if arg ==
True else 'False\n'
19def print_dbl(arg, prefix = ""):
20 return print_const(arg,
'%4.6e', prefix)
22def print_int(arg, prefix = ""):
23 return print_const(arg,
'%d', prefix)
25def print_dbl_list(arg, prefix = ""):
26 a = prefix +
'[' + print_list(arg,
'%4.6e') +
']\n'
29def print_int_list(arg, prefix = ""):
30 a = prefix +
'[' + print_list(arg,
'%4.6e') +
']\n'
33def print_point_gmsh(arg, n):
34 return 'Point(%d) = {' % n + print_list(arg) +
'};\n'
36def print_cir_gmsh(arg, n):
37 return 'Circle(%d) = {' % n + print_list(arg,
'%d') +
'};\n'
39def print_line_gmsh(arg, n):
40 return 'Line(%d) = {' % n + print_list(arg,
'%d') +
'};\n'
42def print_lineloop_gmsh(arg, n):
43 return 'Line Loop(%d) = {' % n + print_list(arg,
'%d') +
'};\n'
46 f.write(
'cl__1 = 1;\n')
47 f.write(
'Mesh.MshFileVersion = 2.2;\n')
51 Returns Young's modulus given bulk modulus and Poisson's ratio
65 return 3. * K * (1. - 2. * nu)
69 Returns shear modulus given Young's modulus and Poisson's ratio
83 return E / (2. * (1. + nu))
88 Returns effective bulk modulus
100 Effective bulk modulus
102 return 2. * k1 * k2 / (k1 + k2)
106 Returns maximum value in list
121def rotate(p, theta, axis):
123 Returns rotation of vector about specified axis by specified angle
128 Coordinates of vector
137 Coordinates of rotated vector
139 p_np, axis_np = np.array(p), np.array(axis)
140 ct, st = np.cos(theta), np.sin(theta)
141 p_dot_n = np.dot(p_np,axis_np)
142 n_cross_p = np.cross(axis_np, p_np)
144 return (1. - ct) * p_dot_n * axis_np + ct * p_np + st * n_cross_p
146def get_ref_hex_points(center, radius, add_center = False):
148 Returns size points on reference hexagon
162 Axis is a vector from x to v1 and radius is distance between x and v1.
167 Coordinates of center of hexagon
171 True if we include the center to the returned list (first point in the returned list will be the center if the flag is true)
176 Coordinates of points
179 rotate_axis = [0., 0., 1.]
182 points.append(center)
185 xi = rotate(axis, i*np.pi/3., rotate_axis)
186 points.append([center[i] + radius * xi[i]
for i
in range(3)])
190def get_ref_drum_points(center, radius, width, add_center = False):
192 Returns size points on reference concave polygon (we refer to it as drum)
194 Reference concave polygon:
197 + -------------------------------- +
203 + -------------------------------- +
206 Axis is a vector from x to v1, radius is distance between x and v2, and width of neck is the distance between v2 and v4.
211 Coordinates of center of polygon
213 Radius of polygon (distance between center x and vertex v2)
215 Width of neck, i.e. distance between vertex v2 and v4
217 True if we include the center to the returned list (first point in the returned list will be the center if the flag is true)
222 Coordinates of points
225 rotate_axis = [0., 0., 1.]
227 x1 = rotate(axis, np.pi/3., rotate_axis)
228 x2 = rotate(axis, -np.pi/3., rotate_axis)
232 points.append(center)
235 points.append([center[i] + width*0.5*axis[i]
for i
in range(3)])
237 points.append([center[i] + radius*x1[i]
for i
in range(3)])
239 points.append([center[i] + radius*x1[i] - radius*axis[i]
for i
in range(3)])
241 points.append([center[i] - width*0.5*axis[i]
for i
in range(3)])
243 v6 = [center[i] + radius*x2[i]
for i
in range(3)]
244 points.append([v6[i] - radius*axis[i]
for i
in range(3)])
251def does_intersect(p, particles, padding):
253 Returns true if particle p intersects or is near enough to existing particles
258 Coordinates of center and radius of particle [x,y,z,r]
260 List of center + radius of multiple particles. E.g. particles[0] is a list containing coordinates of center and radius.
262 Minimum distance between circle boundaries such that if two circles
267 True if particle intersects or is near enough to one of the particle in the list
269 if len(p) < 4:
raise Exception(
'p = {} must have atleast 4 elements'.format(p))
270 if len(particles) == 0:
raise Exception(
'particles = {} can not be empty'.format(particles))
271 if padding < 0.:
raise Exception(
'padding = {} can not be negative'.format(padding))
274 if len(q) < 4:
raise Exception(
'q = {} in particles must have atleast 4 elements'.format(q))
275 pq = np.array([p[i] - q[i]
for i
in range(3)])
276 if np.linalg.norm(pq) <= p[3] + q[3] + padding:
280def does_intersect_rect(p, particles, padding, rect, is_3d = False):
282 Returns true if particle p is sufficiently close or outside the rectangle (in 2d) or cuboid (in 3d)
287 Coordinates of center and radius of particle [x,y,z,r]
289 List of center + radius of multiple particles. E.g. particles[0] is a list containing coordinates of center and radius.
291 Minimum distance between circle boundaries such that if two circles
293 Coordinates of left-bottom and right-top corner points of rectangle (2d) or cuboid (3d). E.g. [x1 y1, z1, x2, y2, z2]
295 True if we are dealing with cuboid
300 True if particle intersects or is near enough to the rectangle
302 if len(p) < 4:
raise Exception(
'p = {} must have atleast 4 elements'.format(p))
303 if len(particles) == 0:
raise Exception(
'particles = {} can not be empty'.format(particles))
304 if padding < 0.:
raise Exception(
'padding = {} can not be negative'.format(padding))
305 if len(rect) < 6:
raise Exception(
'rect = {} must have 6 elements'.format(rect))
307 pr = [p[0] - p[3], p[1] - p[3], p[2], p[0] + p[3], p[1] + p[3], p[2]]
312 if pr[0] < rect[0] + padding
or pr[1] < rect[1] + padding
or pr[3] > rect[3] - padding
or pr[4] > rect[4] - padding:
314 if pr[2] < rect[2] + padding
or pr[5] > rect[5] - padding:
320def generate_circle_gmsh_input(filename, center, radius, mesh_size, pp_tag = None):
322 Creates .geo file for discretization of circle using gmsh
327 Filename of .geo file to be created
329 Coordinates of center of circle
334 pp_tag: str, optional
335 Postfix .geo file with this tag
337 pp_tag_str =
'_{}'.format(str(pp_tag))
if pp_tag
is not None else ''
338 geof = open(filename + pp_tag_str +
'.geo',
'w')
343 points.append([center[0], center[1], center[2]])
344 points.append([center[0] + radius, center[1], center[2]])
345 points.append([center[0] - radius, center[1], center[2]])
346 points.append([center[0], center[1] + radius, center[2]])
347 points.append([center[0], center[1] - radius, center[2]])
348 for i
in range(len(points)):
349 geof.write(print_point_gmsh([points[i][0], points[i][1], points[i][2], mesh_size], i+1))
352 geof.write(print_cir_gmsh([2,1,4], 1))
353 geof.write(print_cir_gmsh([4,1,3], 2))
354 geof.write(print_cir_gmsh([3,1,5], 3))
355 geof.write(print_cir_gmsh([5,1,2], 4))
358 geof.write(print_lineloop_gmsh([2, 3, 4, 1], 1))
361 geof.write(
"Plane Surface(1) = {1};\n")
364 geof.write(
"Point{1} In Surface {1};")
369def generate_rectangle_gmsh_input(filename, rectangle, mesh_size, pp_tag = None):
371 Creates .geo file for discretization of rectangle using gmsh
376 Filename of .geo file to be created
378 Coordinates of left-bottom and right-top corner points of rectangle
381 pp_tag: str, optional
382 Postfix .geo file with this tag
384 pp_tag_str =
'_{}'.format(str(pp_tag))
if pp_tag
is not None else ''
385 geof = open(filename + pp_tag_str +
'.geo',
'w')
390 points.append([rectangle[0], rectangle[1], rectangle[2]])
391 points.append([rectangle[3], rectangle[1], rectangle[2]])
392 points.append([rectangle[3], rectangle[4], rectangle[2]])
393 points.append([rectangle[0], rectangle[4], rectangle[2]])
394 for i
in range(len(points)):
395 geof.write(print_point_gmsh([points[i][0], points[i][1], points[i][2], mesh_size], i+1))
400 geof.write(print_line_gmsh([i+1,i+2], i+1))
402 geof.write(print_line_gmsh([i+1,1], i+1))
405 geof.write(print_lineloop_gmsh([i+1
for i
in range(4)], 1))
408 geof.write(
"Plane Surface(1) = {1};\n")
411 geof.write(
"Point{1} In Surface {1};")
414 tag =
'"' +
"a" +
'"'
415 geof.write(
"Physical Surface(%s) = {1};\n" % (tag))
420def generate_hexagon_gmsh_input(filename, center, radius, mesh_size, pp_tag = None):
422 Creates .geo file for discretization of hexagon using gmsh
427 Filename of .geo file to be created
429 Coordinates of center of hexagon
434 pp_tag: str, optional
435 Postfix .geo file with this tag
437 pp_tag_str =
'_{}'.format(str(pp_tag))
if pp_tag
is not None else ''
438 geof = open(filename + pp_tag_str +
'.geo',
'w')
442 points = get_ref_hex_points(center, radius,
True)
443 for i
in range(len(points)):
444 geof.write(print_point_gmsh([points[i][0], points[i][1], points[i][2], mesh_size], i+1))
449 geof.write(print_line_gmsh([i+2,i+3], i+1))
451 geof.write(print_line_gmsh([i+2,2], i+1))
454 geof.write(print_lineloop_gmsh([i+1
for i
in range(6)], 1))
457 geof.write(
"Plane Surface(1) = {1};\n")
460 geof.write(
"Point{1} In Surface {1};")
466def generate_drum_gmsh_input(filename, center, radius, width, mesh_size, pp_tag = None):
468 Creates .geo file for discretization of drum (concave polygon, see get_ref_drum_points) using gmsh
473 Filename of .geo file to be created
475 Coordinates of center
479 Neck width (see get_ref_drum_points())
482 pp_tag: str, optional
483 Postfix .geo file with this tag
485 pp_tag_str =
'_{}'.format(str(pp_tag))
if pp_tag
is not None else ''
486 geof = open(filename + pp_tag_str +
'.geo',
'w')
490 points = get_ref_drum_points(center, radius, width,
True)
491 for i
in range(len(points)):
492 geof.write(print_point_gmsh([points[i][0], points[i][1], points[i][2], mesh_size], i+1))
497 geof.write(print_line_gmsh([i+2,i+3], i+1))
499 geof.write(print_line_gmsh([i+2,2], i+1))
502 geof.write(print_lineloop_gmsh([i+1
for i
in range(6)], 1))
505 geof.write(
"Plane Surface(1) = {1};\n")
508 geof.write(
"Point{1} In Surface {1};")