@@ -375,6 +375,7 @@ def gen_rect_mesh(num_x, num_y, span, chord, span_cos_spacing=0.0, chord_cos_spa
375375 mesh = np .zeros ((num_x , num_y , 3 ))
376376 ny2 = (num_y + 1 ) // 2
377377
378+ # --- spanwise discretization ---
378379 # Hotfix a special case for spacing bunched at the root and tips
379380 if span_cos_spacing == 2.0 :
380381 beta = np .linspace (0 , np .pi , ny2 )
@@ -396,23 +397,17 @@ def gen_rect_mesh(num_x, num_y, span, chord, span_cos_spacing=0.0, chord_cos_spa
396397 half_wing = cosine * span_cos_spacing + (1 - span_cos_spacing ) * uniform
397398 full_wing = np .hstack ((- half_wing [:- 1 ], half_wing [::- 1 ])) * span
398399
399- nx2 = (num_x + 1 ) // 2
400- beta = np .linspace (0 , np .pi / 2 , nx2 )
401-
402- # mixed spacing with span_cos_spacing as a weighting factor
403- # this is for the chordwise spacing
404- cosine = 0.5 * np .cos (beta ) # cosine spacing
405- uniform = np .linspace (0 , 0.5 , nx2 )[::- 1 ] # uniform spacing
406- half_wing = cosine * chord_cos_spacing + (1 - chord_cos_spacing ) * uniform
407- full_wing_x = np .hstack ((- half_wing [:- 1 ], half_wing [::- 1 ])) * chord
408-
409- # Special case if there are only 2 chordwise nodes
410- if num_x <= 2 :
411- full_wing_x = np .array ([0.0 , chord ])
400+ # --- chordwise discretization ---
401+ cosine = 0.5 * (1 - np .cos (np .linspace (0 , np .pi , num_x ))) # cosine spacing from 0 to 1
402+ uniform = np .linspace (0 , 1 , num_x ) # uniform spacing
403+ # mixed spacing with chord_cos_spacing as a weighting factor
404+ wing_x = cosine * chord_cos_spacing + (1 - chord_cos_spacing ) * uniform
405+ wing_x *= chord # apply chord length
412406
407+ # --- form 3D mesh array ---
413408 for ind_x in range (num_x ):
414409 for ind_y in range (num_y ):
415- mesh [ind_x , ind_y , :] = [full_wing_x [ind_x ], full_wing [ind_y ], 0 ]
410+ mesh [ind_x , ind_y , :] = [wing_x [ind_x ], full_wing [ind_y ], 0 ]
416411
417412 return mesh
418413
@@ -557,24 +552,12 @@ def add_chordwise_panels(mesh, num_x, chord_cos_spacing):
557552
558553 # Obtain mesh and num properties
559554 num_y = mesh .shape [1 ]
560- nx2 = (num_x + 1 ) // 2
561-
562- # Create beta, an array of linear sampling points to pi/2
563- beta = np .linspace (0 , np .pi / 2 , nx2 )
564-
565- # Obtain the two spacings that we will use to blend
566- cosine = 0.5 * np .cos (beta ) # cosine spacing
567- uniform = np .linspace (0 , 0.5 , nx2 )[::- 1 ] # uniform spacing
568-
569- # Create half of the wing in the chordwise direction
570- half_wing = cosine * chord_cos_spacing + (1 - chord_cos_spacing ) * uniform
571555
572- if chord_cos_spacing == 0.0 :
573- full_wing_x = np .linspace (0 , 1.0 , num_x )
574-
575- else :
576- # Mirror this half wing into a full wing; offset by 0.5 so it goes 0 to 1
577- full_wing_x = np .hstack ((- half_wing [:- 1 ], half_wing [::- 1 ])) + 0.5
556+ # chordwise discretization
557+ cosine = 0.5 * (1 - np .cos (np .linspace (0 , np .pi , num_x ))) # cosine spacing from 0 to 1
558+ uniform = np .linspace (0 , 1 , num_x ) # uniform spacing
559+ # mixed spacing with chord_cos_spacing as a weighting factor
560+ wing_x = cosine * chord_cos_spacing + (1 - chord_cos_spacing ) * uniform
578561
579562 # Obtain the leading and trailing edges
580563 le = mesh [0 , :, :]
@@ -586,7 +569,7 @@ def add_chordwise_panels(mesh, num_x, chord_cos_spacing):
586569 new_mesh [- 1 , :, :] = te
587570
588571 for i in range (1 , num_x - 1 ):
589- w = full_wing_x [i ]
572+ w = wing_x [i ]
590573 new_mesh [i , :, :] = (1 - w ) * le + w * te
591574
592575 return new_mesh
@@ -635,6 +618,29 @@ def get_default_geo_dict():
635618
636619
637620def generate_mesh (input_dict ):
621+ """
622+ Generate an OAS mesh.
623+
624+ Parameters
625+ ----------
626+ input_dict : dict
627+ Dictionary containing user-provided parameters for the surface definition.
628+ See the following for more information:
629+ https://mdolab-openaerostruct.readthedocs-hosted.com/en/latest/user_reference/mesh_surface_dict.html#mesh-dict
630+
631+ Returns
632+ -------
633+ mesh : numpy array
634+ Nodal coordinates defining the mesh.
635+ shape = (nx, ny, 3),
636+ where nx is the number of chordwise discretization nodes, ny is the number of spanwise discretization nodes.
637+ If input_dict["symmetry"] is True, mesh defines left half of wing.
638+ twist : numpy array, optional
639+ Only for CRM wing (input_dict["wing_type"] == "CRM").
640+ Twist values at the spanwise locations.
641+
642+ """
643+
638644 # Get defaults and update surface with the user-provided input
639645 surf_dict = get_default_geo_dict ()
640646
@@ -677,10 +683,6 @@ def generate_mesh(input_dict):
677683 if not num_y % 2 :
678684 raise ValueError ("num_y must be an odd number." )
679685
680- # Check to make sure that an odd number of chordwise points (num_x) was provided
681- if not num_x % 2 and not num_x == 2 :
682- raise ValueError ("num_x must be an odd number." )
683-
684686 # Generate rectangular mesh
685687 if surf_dict ["wing_type" ] == "rect" :
686688 span = surf_dict ["span" ]
0 commit comments