### Complete Grid Generation Script Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/tutorial.html A full example script demonstrating the setup of input parameters, initialization of the pyHyp object, and execution of the grid generation. ```python # rst import (start) import os from pyhyp import pyHyp # rst import (end) baseDir = os.path.dirname(os.path.abspath(__file__)) surfaceFile = os.path.join(baseDir, "bwb.fmt") volumeFile = os.path.join(baseDir, "bwb.cgns") options = { # --------------------------- # Input Parameters # --------------------------- "inputFile": surfaceFile, "unattachedEdgesAreSymmetry": True, "outerFaceBC": "farfield", "autoConnect": True, "BC": {}, "families": "wall", # --------------------------- # Grid Parameters # --------------------------- "N": 81, "s0": 4e-6, "marchDist": 1100.0, # --------------------------- # Pseudo Grid Parameters # --------------------------- "ps0": -1.0, "pGridRatio": -1.0, "cMax": 2.5, # --------------------------- # Smoothing parameters # --------------------------- "epsE": 1.0, "epsI": 2.0, "theta": 3.0, "volCoef": 0.25, "volBlend": 0.0002, "volSmoothIter": 150, } # rst object hyp = pyHyp(options=options) # rst run hyp.run() hyp.writeCGNS(volumeFile) ``` -------------------------------- ### Install the Python interface Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/install.rst.txt Install the package in the current directory using pip. ```bash pip install . ``` -------------------------------- ### Install testing dependencies Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/install.rst.txt Install the required dependencies for running regression tests. ```bash pip install .[testing] ``` -------------------------------- ### Grid Generation Output Log Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/tutorial.html Example output log showing the progress of the grid generation process. ```text #--------------------# Total Nodes: 14105 Unique Nodes: 13457 Total Faces: 13376 #--------------------# Normal orientation check ... Normals are consistent! Determining topology ... Topology complete. #--------------------# Grid Ratio: 1.2532 #--------------------# #-------------------------------------------------------------------------------------------------------------------# # Grid | CPU | Sub | KSP | nAvg | Sl | Sensor | Sensor | Min | Min | deltaS | March | cMax | Ratio | # Lvl | Time | Its | Its | | | Max | Min | Quality | Volume | | Distance | | kMax | #-------------------------------------------------------------------------------------------------------------------# 2 0.1 2 11 0 0.055 1.00006 0.98387 0.38387 0.359E-10 0.314E-05 0.451E-05 0.0011 0.0000 3 0.2 2 11 0 0.064 1.00010 0.96703 0.35947 0.657E-10 0.493E-05 0.116E-04 0.0018 1.9184 4 0.3 1 11 0 0.067 1.00012 0.96111 0.35650 0.103E-09 0.618E-05 0.165E-04 0.0022 1.5882 5 0.4 2 11 0 0.074 1.00024 0.90864 0.35575 0.174E-09 0.787E-05 0.305E-04 0.0035 1.7282 6 0.4 1 11 0 0.076 1.00031 0.89199 0.35610 0.237E-09 0.987E-05 0.383E-04 0.0035 1.3561 7 0.5 1 11 0 0.079 1.00037 0.87508 0.35613 0.371E-09 0.124E-04 0.482E-04 0.0044 1.5634 8 0.5 2 11 0 0.084 1.00083 0.78268 0.35729 0.548E-09 0.155E-04 0.761E-04 0.0069 1.4708 9 0.6 1 11 0 0.087 1.00108 0.75129 0.36201 0.717E-09 0.194E-04 0.916E-04 0.0069 1.3003 10 0.6 1 11 0 0.089 1.00124 0.74002 0.36599 0.104E-08 0.243E-04 0.111E-03 0.0086 1.4222 < iterations skipped for brevity > 78 33.9 22 29 0 0.904 0.98475 0.97354 0.32556 0.347E+04 0.730E+01 0.562E+03 2.5000 1.2603 79 36.1 22 29 0 0.936 0.98435 0.97427 0.32565 0.688E+04 0.930E+01 0.708E+03 2.5000 1.2570 80 38.0 21 29 0 0.968 0.98388 0.97469 0.32573 0.138E+05 0.119E+02 0.885E+03 2.5000 1.2551 81 39.9 20 29 0 1.000 0.98341 0.97476 0.32579 0.276E+05 0.152E+02 0.110E+04 2.5000 1.2540 ``` -------------------------------- ### Configure pyHyp Grid Options Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/adapt.html Example configuration dictionary for pyHyp, demonstrating settings for input files, boundary conditions, and grid generation parameters like cMax and s0. ```python options = { # --------------------------- # Input Parameters # --------------------------- "inputFile": "rae2822.xyz", "unattachedEdgesAreSymmetry": False, "outerFaceBC": "farfield", "autoConnect": True, "BC": { 1: { "jLow": "zSymm", "jHigh": "zSymm", } }, "families": "wall", # --------------------------- # Grid Parameters # --------------------------- "N": 31, "s0": 1e-3, "marchDist": 100.0, "nConstantStart": 1, # --------------------------- # Pseudo Grid Parameters # --------------------------- "cMax": 1.0, } ``` -------------------------------- ### Configure family and patch settings Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Handles the assignment of boundary families and patches to grid blocks before invoking the Fortran setup routine. ```python elif isinstance(families, dict): for blkBC in families: if blkBC < 1 or blkBC > nBlocks or not isinstance(blkBC, int): raise Error( "Keys in families dictionary must be 1-based integers and less " "than or equal to the total number of blocks" ) fFamilies[blkBC - 1] = families[blkBC] else: raise Error( "'families' option must be a string or a dictionary. A string will " "set all wall families to the single string. A dictionary with " "one-based keys for the blocks may be used to specify individual " "families for each block.\n Examples: 'families':'fuselage' or" "'families':{'1:'fuselage', 2:'wing'}." ) # Set our family information in fortran for i in range(nBlocks): self.hyp.setfamily(i + 1, fFamilies[i]) # Explicitly set patches if necessary if patchInput: self.hyp.setnumberpatches(len(patches)) for i in range(len(patches)): self.hyp.setpatch(i + 1, patches[i]) intFileType = self.hyp.hypinput.patchinput # Now run the fortran setup. self.hyp.setup(self.getOption("inputFile"), intFileType) ``` -------------------------------- ### Define pyHypMulti options list Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/API.html Example of providing a list of dictionaries and filenames to configure multiple grid extrusion cases simultaneously. ```python options1 = { "epsE": 4.0, "epsI": 8.0, "outputFile": "corner1_hyp.cgns", "skip": False, } options2 = "cartesian.cgns" options3 = { "epsE": 2.0, "epsI": 4.0, "outputFile": "corner2_hyp.cgns", "skip": False, } options = [options1, options2, options3] ``` -------------------------------- ### Define pyHypMulti options dictionary Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/API.html Example of an options dictionary used for configuring a single grid extrusion case. ```python options = { "epsE": 4.0, "epsI": 8.0, "outputFile": "corner_hyp.cgns", "skip": False, } ``` -------------------------------- ### Define BC dictionary Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/BC.html Example dictionary structure for the BC option, mapping block numbers to boundary edge specifications and conditions. ```json "BC": {1: {"iLow": "ySymm"}, 3: {"jHigh": "splay", "iHigh": "xConst"}} ``` -------------------------------- ### Configure the build environment Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/install.rst.txt Copy a default configuration file to the active configuration location. ```bash cp config/defaults/config.LINUX_GFORTRAN.mk config/config.mk ``` -------------------------------- ### Download reference mesh files Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/install.rst.txt Run the provided script to download necessary reference files for testing. ```bash ./tests/ref/get-ref-files.sh ``` -------------------------------- ### Define default configuration options Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Returns a dictionary containing all default parameters for grid generation, including input, grid, elliptic, and smoothing settings. ```python @staticmethod def _getDefaultOptions(): defOpts = { # --------------------------- # Input Information # --------------------------- "inputFile": [str, ""], "patches": [list, []], "fileType": [str, ["PLOT3D", "CGNS"]], "skip": [bool, False], "mode": [str, ["hyperbolic", "elliptic"]], "unattachedEdgesAreSymmetry": [bool, True], "outerFaceBC": [str, ["farfield", "overset"]], "BC": [dict, {}], "families": [(str, dict), {}], "autoConnect": [bool, True], "noPointReduce": [bool, False], # --------------------------- # Grid Parameters # --------------------------- "N": [int, 65], "s0": [float, 0.01], "nConstantStart": [int, 1], "nConstantEnd": [int, 1], "nTruncate": [int, -1], "marchDist": [float, 50.0], "nodeTol": [float, 1e-8], "splay": [(list, float), 0.25], "splayEdgeOrthogonality": [(list, float), 0.1], "splayCornerOrthogonality": [(list, float), 0.2], "cornerAngle": [(list, float), 60.0], "coarsen": [int, 1], # --------------------------- # Elliptic Parameters # --------------------------- "panelEps": [float, 1e-8], "farfieldTolerance": [float, 4.0], "useMatrixFree": [bool, True], "evalMode": [str, ["fast", "exact", "slow"]], "sourceStrengthFile": [str, "panelStrength.source"], # ------------------------------------------ # Pseudo Grid Parameters (Hyperbolic only) # ------------------------------------------ "cMax": [float, 1.0], "nonLinear": [bool, False], "slExp": [float, 0.15], "ps0": [float, -1.0], "pGridRatio": [float, -1.0], "growthRatios": [(list, type(None)), None], # ---------------------------------------- # Smoothing parameters (Hyperbolic only) # ---------------------------------------- "epsE": [(list, float), 1.0], "epsI": [(list, float), 2.0], "theta": [(list, float), 3.0], "volCoef": [(list, float), 0.25], "volBlend": [(list, float), 0.0001], "volSmoothIter": [(list, int), 100], # ------------------------------- # Solution Parameters (Common) # ------------------------------- "KSPRelTol": [float, 1e-8], "KSPMaxIts": [int, 500], "KSPSubspaceSize": [int, 50], # --------------------------- # Output Parameters # --------------------------- "writeMetrics": [bool, False], "outputType": [str, ["CGNS", "PLOT3D"]], "outputFile": [(str, type(None)), None], } return defOpts ``` -------------------------------- ### run() Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Executes the grid generation process based on the configured mode (hyperbolic or elliptic). ```APIDOC ## run() ### Description Executes the grid generation process. It checks the configured mode and runs either the hyperbolic or elliptic solver accordingly. ### Usage `pyHyp.run()` ``` -------------------------------- ### Launch ICEMCFD Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/icem.rst.txt Command to initialize the ICEMCFD application from a terminal within a designated project folder. ```bash $ icemcfd ``` -------------------------------- ### Print Marching Parameters Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Outputs the current grid ratio and marching distance to the console for the root process. ```python def _printMarchingParameters(self): """ Print the marching parameters used. """ if not self.comm.Get_rank() == 0: return growthRatioString = getGrowthRatioString(self.growthRatios) print("#--------------------#") print(f"Grid Ratio: {growthRatioString}") print(f"March Dist: {self.marchDistance:.3e}") ``` -------------------------------- ### Initializing the pyHyp Object Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/tutorial.rst.txt Creating the pyHyp object using the options dictionary to control grid generation parameters. ```python hyp = pyHyp(options=options) ``` -------------------------------- ### Verify Import Success Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/install.html Expected output indicating successful compilation and module availability. ```text Testing if module hyp can be imported... Module hyp was successfully imported. ``` -------------------------------- ### pyHyp.__init__ Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Initializes the pyHyp object with MPI communicator, configuration options, and debug settings. ```APIDOC ## pyHyp.__init__(comm=None, options=None, debug=False) ### Description Creates the pyHyp object for hyperbolic mesh generation. The options dictionary is required for configuration. ### Parameters - **comm** (MPI_INTRACOMM) - Optional - The MPI communicator to use. Defaults to MPI.COMM_WORLD. - **options** (dict) - Required - A dictionary containing the options for pyHyp. - **debug** (bool) - Optional - Flag to specify if debugging is enabled, typically used with symbolic debuggers. ``` -------------------------------- ### pyHypMulti.__init__ Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Initializes the pyHypMulti class to set up, run, and write results for multiple grid extrusion cases. ```APIDOC ## pyHypMulti.__init__(comm=None, options=None, commonOptions=None, debug=False, skipList=[]) ### Description Initializes the pyHypMulti instance. This method processes the provided options for grid extrusion, sets up the MPI communicator, and prepares the cases for execution. ### Parameters - **comm** (MPI.Intracomm) - Optional - The MPI communicator to use. Defaults to MPI.COMM_WORLD. - **options** (dict/list) - Optional - An ordered dictionary or list of dictionaries containing configuration options for each grid extrusion case. Can also include strings representing CGNS files to be combined. - **commonOptions** (dict) - Optional - A dictionary of options applied to all cases in the options parameter. - **debug** (bool) - Optional - Flag to enable debug mode. - **skipList** (list) - Optional - A list of case names to be skipped during execution. ``` -------------------------------- ### Configure Boundary Conditions and Families Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Initializes block boundary conditions and family names based on input options or file metadata. Requires a valid pyHyp instance with configured options. ```python # Determine how we are getting data: by Input file or # explictly by patches. patchInput = False patches = self.getOption("patches") if len(patches) > 0: patchInput = True nBlocks = len(patches) if not patchInput: if not os.path.isfile(self.getOption("inputFile")): raise Error("Input file '%s' not found." % self.getOption("inputFile")) # Determine the number of blocks we have so we can initialize # the BC array: nBlocks = self.hyp.getnblocks(self.getOption("inputFile"), intFileType) self.hyp.allocatefamilies(nBlocks) if self.getOption("noPointReduce") and nBlocks > 1: raise Error("The noPointReduce option may only be true when a single surface grid is provided.") # The fortran BC information fBCs = numpy.zeros((4, nBlocks), order="f") fBCs[:, :] = self.hyp.hypinput.bcdefault # The python BC information BCs = self.getOption("BC") BCMap = { "splay": self.hyp.hypinput.bcsplay, "xsymm": self.hyp.hypinput.bcxsymm, "ysymm": self.hyp.hypinput.bcysymm, "zsymm": self.hyp.hypinput.bczsymm, "xconst": self.hyp.hypinput.bcxconst, "yconst": self.hyp.hypinput.bcyconst, "zconst": self.hyp.hypinput.bczconst, "xyconst": self.hyp.hypinput.bcxyconst, "yzconst": self.hyp.hypinput.bcyzconst, "xzconst": self.hyp.hypinput.bcxzconst, } edgeMap = { "ilow": self.hyp.hypinput.ilow - 1, "ihigh": self.hyp.hypinput.ihigh - 1, "jlow": self.hyp.hypinput.jlow - 1, "jhigh": self.hyp.hypinput.jhigh - 1, } helpStr = "An example of a boundary specification is: 'BC':{1:{'iLow':'ySymm'}, 2:{'jHigh':'splay'}}" for blkBC in BCs: if blkBC < 1 or blkBC > nBlocks or not isinstance(blkBC, int): raise Error( "Keys in BC array must be 1-based integers and less " "than or equal to the total number of blocks. %s" % helpStr ) for edgeKey in BCs[blkBC]: lKey = edgeKey.lower() if lKey not in edgeMap.keys(): raise Error( "Boundary edge specification must be one of: 'iLow', 'iHigh', 'jLow', or 'jHigh'. %s" % helpStr ) BCToSet = BCs[blkBC][edgeKey].lower() if BCToSet.lower() not in BCMap.keys(): raise Error( "Boundary condition specification unknown. Must be one of: " "'splay', 'xSymm', 'ySymm', 'zSymm', " "'xConst', 'yConst', 'zConst, 'xyConst, " "'yzConst or xzConst'. %s" % helpStr ) fBCs[edgeMap[lKey], blkBC - 1] = BCMap[BCToSet] # Set the boundary condition information into fortran self.hyp.hypinput.bcs = fBCs # Now process the family information if we have any: families = self.getOption("families") fFamilies = [] # Set default a default name of "wall". for _i in range(nBlocks): fFamilies.append("Wall") # If we were given a CGNS file we might have families # there. So load them and overwrite the default. if intFileType == self.hyp.hypinput.cgnsfiletype: if self.comm.rank == 0: for i in range(nBlocks): family, foundFam = self.hyp.readfamily(self.getOption("inputFile"), i + 1) if foundFam and len(family.strip()) > 0: fFamilies[i] = family.strip() fFamilies = self.comm.bcast(fFamilies) # If we have explictly other families given, these will # overwrite anything we already have. if isinstance(families, str): for i in range(nBlocks): fFamilies[i] = families ``` -------------------------------- ### Configure Pseudo-Grid Parameters Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Validates and computes pseudo-grid growth ratios and initial layer heights, raising errors if inputs are unreasonable. ```python def _configurePseudoGridParameters(self): """ Figures out if the user set pseudo grid parameters. If this is the case, error checking makes sure they are reasonable. If the user did not set it, an automatic value is computed. Returns ------- pGridRatio: float Growth ratio for the pseudo grid. ps0 : float First layer height for the pseudo grid. """ pGridRatio = self.getOption("pGridRatio") ps0 = self.getOption("ps0") s0 = self.getOption("s0") minGrowthRatio = numpy.min(self.growthRatios[self.growthRatios > 1]) if pGridRatio == -1: pGridRatio = minGrowthRatio else: if pGridRatio > minGrowthRatio: raise Error(f"The `pGridRatio` option has to be lower than the lowest grid ratio ({minGrowthRatio})") # figure out initial pseudo grid initial offwall spacing if ps0 <= 0: ps0 = s0 / 2 else: if ps0 > s0: raise Error(f"The `ps0` option has to be lower than the off wall spacing s0: ({s0})") return pGridRatio, ps0 ``` -------------------------------- ### Launch TecPlot 360 Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/icem.rst.txt Open the TecPlot 360 application from the terminal to visualize the volume mesh. ```bash $ tec360 ``` -------------------------------- ### Utility Methods Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Helper methods for string padding and memory cleanup. ```python def _expandString(self, s): """Expand a supplied string 's' to be of the constants.maxstring length so we can set them in fortran """ return s + " " * (512 - len(s)) def __del__(self): """ Clean up fortran allocated values if necessary """ self.hyp.releasememory() ``` -------------------------------- ### Initialize and Execute pyHyp Multi-Grid Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Handles the conversion of input options into a dictionary, iterates through grid configurations, and manages the execution and logging of pyHyp objects. ```python # Convert input to dictionary even if user gave a single element if type(options) is dict: raise Error( "pyHypMulti only accepts Ordered Dictionaries or Lists as inputs." + " Declare your options using options=OrderedDict()" ) elif type(options) is list: # Set ordered dict optionsDict = OrderedDict() # Convert list to dictionary using integers as keys optionsDict = {k: v for (k, v) in zip(range(len(options)), options[:])} else: # User gave an ordered dictionary optionsDict = deepcopy(options) # Add unused common options to each set for name in optionsDict: # Avoid options that are just strings indicating volume grids if type(optionsDict[name]) is not str: for key in commonOptions: if key not in optionsDict[name].keys(): optionsDict[name][key] = commonOptions[key] # Initilize counter index = 0 # Get the number of grids self.numGrids = len(optionsDict) # Initialize dictionary with results self.results = { "name": list(optionsDict.keys()), "outputFile": [0] * self.numGrids, "gridRatio": [""] * self.numGrids, "minQualityOverall": [0] * self.numGrids, "minVolumeOverall": [0] * self.numGrids, } # Loop over all elements in the options list for optionName in optionsDict: options = optionsDict[optionName] if type(options) is str: # Just set up relationships to combine it with the other grids # later on self.results["name"][index] = optionName self.results["outputFile"][index] = options self.results["gridRatio"][index] = "N/A" self.results["minQualityOverall"][index] = "N/A" self.results["minVolumeOverall"][index] = "N/A" # Increment counter index = index + 1 elif optionName in skipList: if myid == 0: print("Skipping case: ", optionName) # Get input file name try: inputFile = options["inputfile"] except KeyError: inputFile = options["inputFile"] # Check if output name exists or if we should get the # the automatically generated one try: outputFile = options["outputfile"] except KeyError: try: outputFile = options["outputFile"] except KeyError: # User probably did not set neither in options or common options outputFile = generateOutputName(inputFile, outputType="cgns") # Save results self.results["name"][index] = optionName self.results["outputFile"][index] = outputFile self.results["gridRatio"][index] = "skip" self.results["minQualityOverall"][index] = "skip" self.results["minVolumeOverall"][index] = "skip" # Increment counter index = index + 1 elif type(options) is dict: # Only the root processor will print if myid == 0: # change the printout based on which option is actually present if "inputFile" in options.keys(): caseName = options["inputFile"] else: caseName = options["outputFile"] print("\n\nRunning case %d : %s\n" % (index, caseName)) # Create pyHyp object using the corresponding options hypGrid = pyHyp(comm, options, debug) # Run it hypGrid.run() # Write outputs hypGrid.writeOutput() # Save results self.results["name"][index] = optionName self.results["outputFile"][index] = hypGrid.options["outputfile"] self.results["minQualityOverall"][index] = float(hypGrid.hyp.hypdata.minqualityoverall) self.results["minVolumeOverall"][index] = float(hypGrid.hyp.hypdata.minvolumeoverall) self.results["gridRatio"][index] = hypGrid.growthRatios # Delete object to free memory del hypGrid # Increment counter index = index + 1 # Print the log self.writeLog() ``` -------------------------------- ### Define deprecated configuration options Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Returns a mapping of deprecated configuration keys to their modern replacements. ```python @staticmethod def _getDeprecatedOptions(): deprecatedOptions = { "volSmoothSchedule": "Please use 'volSmoothIter' for the same functionality", } return deprecatedOptions ``` -------------------------------- ### Executing Grid Generation Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/tutorial.rst.txt Running the grid generation process and writing the output to a CGNS file. ```python hyp.generate() hyp.writeGrid('grid.cgns') ``` -------------------------------- ### Initialize pyHyp Object Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Constructor for the pyHyp class, setting up MPI communication, default options, and initializing the underlying Fortran modules. ```python class pyHyp(BaseSolver): def __init__(self, comm=None, options=None, debug=False): """ Create the pyHyp object. Parameters ---------- comm : MPI_INTRACOMM Comm to use. This is used when running in parallel. If not provided, MPI.COMM_WORLD is used by default. options : dict A dictionary containing the the options for pyHyp. debug : bool Flag used to specify if debugging. This only needs to be set to true when using a symbolic debugger. """ name = "pyHyp" category = "Hyperbolic mesh generator" informs = {} # Set the possible MPI Intracomm if comm is None: comm = MPI.COMM_WORLD # Default options for hyperbolic generation defOpts = self._getDefaultOptions() # Use supplied options if options is None: raise Error("The options = keyword argument is *NOT* optional. It must always be provided") # Deprecated options deprecatedOptions = self._getDeprecatedOptions() # Initialize the inherited BaseSolver super().__init__( name, category, defaultOptions=defOpts, options=options, deprecatedOptions=deprecatedOptions, comm=comm, informs=informs, ) # Import and set the hyp module curDir = os.path.basename(os.path.dirname(os.path.realpath(__file__))) self.hyp = MExt.MExt("hyp", curDir, debug=debug)._module # Initialize PETSc and MPI if not already done so: self.hyp.initpetsc(self.comm.py2f()) # Set the fortan options self._setOptions() self.gridGenerated = False # Convert file type to integer fileType = {"CGNS": self.hyp.hypinput.cgnsfiletype, "PLOT3D": self.hyp.hypinput.plot3dfiletype} intFileType = fileType[self.getOption("fileType")] ``` -------------------------------- ### Open TecPlot layout from command line Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/icem.rst.txt Use this command to open a saved TecPlot layout file directly, bypassing the need to navigate through menus. ```bash $ tec360 layout_hyp.lay ``` -------------------------------- ### Configure Marching Parameters Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Determines the marching distance and growth ratios for grid layers, prioritizing explicit user options if provided. ```python def _determineMarchingParameters(self): """ Figure out what marching parameters to use. This logic is needed because there are multiple ways to define those parameters. Returns ------- fullDeltaS : list[float] The ideal height for each layer. marchDist : float The marching distance used. growthRatios : list[float] The growth ratio for each layer. """ # if the user specified an explicit growth-ratio, use this optionsGrowthRatios = self.getOption("growthRatios") if optionsGrowthRatios is not None: growthRatios = self._expandPerLayerOption("growthRatios") if self.comm.Get_rank() == 0: pyHypWarning( "The option `growthRatios` has been specified. This takes precedence over `marchDist`, `nConstantStart` and `nConstantEnd`." ) else: # no growth ratio was provided -> compute it growthRatios = self._computeGrowthRatio() # finally compute each layers deltaS and set it in fortran fullDeltaS = self._computeDeltaS(growthRatios) # figure out what marching distance to use if optionsGrowthRatios is not None: marchDist = numpy.sum(fullDeltaS) else: marchDist = self.getOption("marchDist") return fullDeltaS, marchDist, growthRatios ``` -------------------------------- ### Run regression tests Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/install.rst.txt Execute the test suite using testflo. ```bash testflo -v ``` -------------------------------- ### writeLog Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/API.html Prints a log containing important information regarding all generated grids. ```APIDOC ## writeLog() ### Description This method prints a log with important information regarding all grids. ``` -------------------------------- ### pyHyp.run Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/API.html Executes the grid generation process based on the provided options. ```APIDOC ## run() ### Description Executes the grid generation process using the options specified during initialization. ``` -------------------------------- ### Verify CGNS structure with cgnsview Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/icem.rst.txt Use the cgnsview GUI to inspect the structure of a generated CGNS file. ```bash $ cgnsview ``` -------------------------------- ### Utility functions for file and data management Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Helper functions for generating output filenames and calculating growth ratio statistics. ```python def generateOutputName(inputFile, outputType): """ This function will automatically create an output filename by appending "_hyp" to the original filename. """ outputType = outputType.lower() # Use just lower case strings # Get rid of the extension and add an 'hyp' to the end of the filename outputFile = os.path.splitext(os.path.basename(inputFile))[0] + "_hyp" # Add extension acording to output file type if outputType == "cgns": outputFile = outputFile + ".cgns" elif outputType == "plot3d": outputFile = outputFile + ".fmt" # Return the generated name return outputFile ``` ```python def getGrowthRatioString(growthRatios): """ Returns a rounded string with the current growth ratio. If the growth ratio is constant, a single value is returned. Otherwise a range is returned. Parameters ---------- growthRatios : list(float) List holding the growth ratio for each layer Returns ------- growthRatioString : str The string holding the rounded growth ratio. """ minGrowthRatio = numpy.min(growthRatios[growthRatios > 1]) maxGrowthRatio = numpy.max(growthRatios[growthRatios > 1]) ``` -------------------------------- ### Compile pyHyp Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/install.rst.txt Execute the make command to compile the package. ```bash make ``` -------------------------------- ### Execute Grid Generation Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/icem.html Commands to run the generation script in serial or parallel modes. ```bash $ python generate_grid.py ``` ```bash $ mpirun -np 4 python generate_grid.py ``` -------------------------------- ### Execute pyHyp script Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/icem.rst.txt Run the grid generation script using the Python interpreter. ```bash $ python generate_grid.py ``` -------------------------------- ### Configure and run pyHyp for volume mesh generation Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/icem.rst.txt Define pyHyp options and execute the grid generation process using a Python script. ```python from pyhyp import pyHyp fileName = 'plate.cgns' fileType = 'cgns' options = { # --------------------------- # Input File # --------------------------- 'inputFile': fileName, 'fileType': fileType, # --------------------------- # Grid Parameters # --------------------------- 'N': 65, 's0': 1e-6, 'marchDist': 2.5, # --------------------------- # Pseudo Grid Parameters # --------------------------- 'ps0': 1e-6, 'pGridRatio': 1.15, 'cMax': 5.0, # --------------------------- # Smoothing parameters # --------------------------- 'epsE': 1.0, 'epsI': 2.0, 'theta': 0.0, 'volCoef': 0.3, 'volBlend': 0.001, 'volSmoothIter': 10, # --------------------------- # Solution Parameters # --------------------------- 'kspRelTol': 1e-15, 'kspMaxIts': 1500, 'kspSubspaceSize': 50, 'writeMetrics': False, } hyp = pyHyp(options=options) hyp.run() hyp.writeCGNS('plate3D.cgns') ``` -------------------------------- ### surfaceSmooth(nIter, stepSize, surfFile=None) Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Runs smoothing iterations on the body surface. ```APIDOC ## surfaceSmooth ### Description Run smoothing iterations on the body surface. ### Parameters - **nIter** (int) - Required - Number of iterations to run. - **stepSize** (float) - Required - Size of step. Must be < 1. - **surfFile** (str) - Optional - Optional surface file for reprojection. ``` -------------------------------- ### Write Output File Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Determines the output format and filename based on options and triggers the appropriate write method. ```python def writeOutput(self, fileName=None, fileType=None): """ This selects the output type based on what is specified in the options """ # Get desired output type from options, unless provided if fileType is None: outputType = self.getOption("outputType") else: outputType = fileType # Check if the user specified name in the options if fileName is None: fileName = self.getOption("outputFile") # If no name is specified even in the options, then # we generate one if fileName is None: fileName = generateOutputName(self.getOption("inputfile"), outputType=outputType) # Update the name stored in the options for future uses self.setOption("outputFile", fileName) if outputType == "CGNS": self.writeCGNS(fileName) elif outputType == "PLOT3D": self.writePlot3D(fileName) ``` -------------------------------- ### Run Grid Generation Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Executes the grid generation process based on the configured mode (hyperbolic or elliptic). ```python def run(self): """ Run given using the options given """ if not self.getOption("skip"): if self.getOption("mode") == "hyperbolic": self.hyp.runhyperbolic() elif self.getOption("mode") == "elliptic": self.hyp.setuppanels() self.hyp.runelliptic() self.gridGenerated = True else: print("Skipped generation of this grid") self.gridGenerated = False ``` -------------------------------- ### Define writeLog Method Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Prints a log containing information regarding all processed grids. ```python [docs] def writeLog(self): """ This will print a log with important information regarding all grids """ ``` -------------------------------- ### Run pyHyp and Process Mesh Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/utils.html Executes the pyHyp mesh generation process, handles temporary CGNS file creation, and performs post-processing on the generated grid. ```python # Use user-defined options if provided if userOptions is not None: hypOptions.update(userOptions) # Run pyHyp hyp = pyHyp(options=hypOptions) hyp.run() fName = None if MPI.COMM_WORLD.rank == 0: dirpath = tempfile.mkdtemp() fName = os.path.join(dirpath, "tmp.cgns") hyp.writeCGNS(MPI.COMM_WORLD.bcast(fName)) # Reset symmetry to single axis if "x" in sym or "xmin" in sym or "xmax" in sym: sym = "x" elif "y" in sym or "ymin" in sym or "ymax" in sym: sym = "y" elif "z" in sym or "zmin" in sym or "zmax" in sym: sym = "z" if MPI.COMM_WORLD.rank == 0: # Read the pyhyp mesh back in and add our additional "X" from above. simple_ocart_grid = readGrid(fName) dims = X.shape[0:3] simple_ocart_grid.addBlock(Block("interiorBlock", dims, X)) simple_ocart_grid.renameBlocks() simple_ocart_grid.connect() simple_ocart_grid.BCs = [] if useFarfield: simple_ocart_grid.autoFarfieldBC(sym) else: simple_ocart_grid.autoNearfieldBC(sym) simple_ocart_grid.writeToCGNS(outFile) # Delete the temp file os.remove(fName) ``` -------------------------------- ### Run pyHyp in parallel Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_sources/icem.rst.txt Execute the grid generation script using multiple processors via mpirun. ```bash $ mpirun -np 4 python generate_grid.py ``` -------------------------------- ### combineCGNS Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/API.html Gathers all newly generated grids and combines them into a single CGNS file. ```APIDOC ## combineCGNS(combinedFile, additionalGrids, skipList, eraseFiles) ### Description This method gathers all newly generated grids and combines them into a single CGNS file. This functionality is specific to CGNS output files. ### Parameters - **combinedFile** (str) - The name of the combined output file. - **additionalGrids** (list) - The filenames of any grids that were not generated by the current pyHypMulti object, but should still be included in the combined output file. - **skipList** (list) - The keys of any generated grids that should not be included in the combined output file. - **eraseFiles** (bool) - If True, the individual files that are combined will be erased. ``` -------------------------------- ### writeCGNS(fileName) Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Writes the generated grid to a CGNS file. ```APIDOC ## writeCGNS(fileName) ### Description Exports the generated grid to a 1-Cell wide CGNS file. Requires that the grid has already been generated via the run() method. ### Parameters - **fileName** (string) - Required - The path and name of the file to be written. ``` -------------------------------- ### Print pyHyp Summary Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Formats and prints a summary table of grid generation results to the console, restricted to the root processor. ```python # round gridRatios results = copy.deepcopy(self.results) key = "gridRatio" for n in range(len(results[key])): if not isinstance(results[key][n], numpy.ndarray): continue results[key][n] = getGrowthRatioString(results[key][n]) # Get processor ID myid = self.comm.Get_rank() # Only the root processor will print if myid == 0: print("") print("") print("") print("=" * 40) print(" " * 12 + "pyHyp Summary" + " " * 12) print("=" * 40) print("") print(tabulate(results, headers="keys", floatfmt=".4e")) print("") print("") ``` -------------------------------- ### Format Growth Ratio String Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/_modules/pyhyp/pyHyp.html Generates a formatted string representing the growth ratio range based on minimum and maximum values. ```python if maxGrowthRatio - minGrowthRatio <= 0: growthRatioString = f"{minGrowthRatio:.3e}" else: growthRatioString = f"{minGrowthRatio:.3e} - {maxGrowthRatio:.3e}" return growthRatioString ``` -------------------------------- ### Configure pyHyp options for coarse grid generation Source: https://mdolab-pyhyp.readthedocs-hosted.com/en/latest/adapt.html Defines the dictionary of parameters used to generate a mesh, including input files, boundary conditions, and grid spacing settings. ```python options = { # --------------------------- # Input Parameters # --------------------------- "inputFile": "rae2822.xyz", "unattachedEdgesAreSymmetry": False, "outerFaceBC": "farfield", "autoConnect": True, "BC": { 1: { "jLow": "zSymm", "jHigh": "zSymm", } }, "families": "wall", # --------------------------- # Grid Parameters # --------------------------- "N": 31, "s0": 4e-5, "marchDist": 100.0, "nConstantStart": 1, # --------------------------- # Pseudo Grid Parameters # --------------------------- "cMax": 3.0, } ```