Source code for turbigen.ohmesh

import numpy as np
import turbigen.autogrid
import os
import turbigen.util
from turbigen.base import BaseConfig

logger = turbigen.util.make_logger()


[docs] class OHMeshConfig(BaseConfig): """Contains all configuration options with default values.""" _name = "OH mesh" spf_ref = 0.5 """Set blade-to-blade mesh parameters based on geometry at this span fraction.""" dspf_mid = 0.03 """Spanwise grid spacing at midspan, as a fraction of span.""" remote_host = "" """Remote host on which AutoGrid server is running.""" span_interpolation = 2.0 """Spanwise % spacing between optimisations of the mesh, interpolate between.""" via_host = "" """Jump host for SSH connection to the AutoGrid server.""" queue_path = "~/.ag_queue.txt" """File on remote host to append our queued meshing jobs.""" workdir = "" gbcs_path = "" """Location of pre-made mesh, or 'reuse' to take from `workdir/mesh.{g,bcs}`.""" ni_inlet = 65 """Number of streamwise points in inlet.""" ni_outlet = 65 """Number of streamwise points in outlet.""" refine_factor = 0 """Divide each edge into 2**(refine_factor) sub-edges.""" fix_h_blocks = True wake_control = False wake_deviation = 0.0 skewness_control = 0 orthogonality_control = 0.5 nsmooth = 500 nsmooth_multigrid = 100 blade_streamwise_weight = 3.0 untwist_outlet = False round_TE = True nj_tip = 25 frac_inlet = 0.9 frac_outlet = 0.15 relax_outlet = 1 R_fillet_hub = 0.0 R_fillet_shd = 0.0 nj_fillet_hub = 17 nj_fillet_shd = 17 is_butterfly = False nk_fillet = 9 inlet_bulb = "" def __setattr__(self, key, value): if key not in dir(self): raise TypeError(f"Invalid OH-mesh configuration variable '{key}'") elif not isinstance(value, type(getattr(self, key))): raise TypeError( f"Invalid type for OH-mesh configuration variable {key}={value}," f" should be {type(getattr(self,key))}" ) else: super().__setattr__(key, value) def __init__(self, **kwargs): """Initialise a configuration, overriding defaults with keyword arguments.""" for k, v in kwargs.items(): setattr(self, k, v) def to_autogrid_dict(self, chi_ref, dhub, dcas, dsurf, splitter): nj = int(1.0 / self.dspf_mid * 2.0) stagger_topo = _get_stagger_topology(chi_ref) nrow = len(stagger_topo) if self.via_host == "": via = None else: via = self.via_host # Default configs return { "verbose": True, "is_cascade": False, "fix_h_blocks": self.fix_h_blocks, "nrow": nrow, "inlet_bulb": self.inlet_bulb, "nx_up": self.ni_inlet, "nx_dn": self.ni_outlet, "nx_mix": 9, "dr_hub": dhub, "dr_cas": dcas, "nr": nj, "round_TE": self.round_TE, "drt_row": dsurf.tolist(), "stagger": stagger_topo, "const_cells_pc": 45.0, "nr_tip_gap": self.nj_tip, "relax_outlet": self.relax_outlet, "ER_boundary_layer": 1.1, "ER_blade_surf": 1.2, "n_te": 17, "frac_up": self.frac_inlet, "frac_dn": self.frac_outlet, "prefix": "mesh", "spf_ref": self.spf_ref, "remote": self.remote_host, "via": via, "queue_file": self.queue_path, "nsmooth": self.nsmooth, "nsmooth_multigrid": self.nsmooth_multigrid, "orthogonality_control": self.orthogonality_control, "skewness_control": self.skewness_control, "wake_control": self.wake_control, "wake_deviation": self.wake_deviation, "untwist_outlet": self.untwist_outlet, "splitter": splitter, "span_interp": self.span_interpolation, "blade_streamwise_weight": self.blade_streamwise_weight, "R_fillet_hub": self.R_fillet_hub, "R_fillet_shd": self.R_fillet_shd, "nk_fillet": self.nk_fillet, "nj_fillet_hub": self.nj_fillet_hub, "nj_fillet_shd": self.nj_fillet_shd, "is_butterfly": self.is_butterfly, }
def _get_stagger_topology(Al): nAl = len(Al) assert np.mod(nAl, 2) == 0 Nrow = nAl // 2 # Threshold for 'normal' angles Al[np.abs(Al) < 45.0] = 0.0 return [ np.sign( Al[ (irow * 2, irow * 2 + 1), ] ) .astype(int) .tolist() for irow in range(Nrow) ] def make_grid(machine, mesh_config, dhub, dcas, dsurf, unbladed, Omega, skip=False): logger.info("Generating OH-mesh...") dsurf = np.mean(dsurf, axis=0) # File paths workdir = mesh_config.workdir if workdir == "": raise Exception("workdir for OH meshing not set") output_stem = os.path.join(os.path.abspath(workdir), "mesh") if (mesh_config.gbcs_path == "reuse") or ( os.path.exists(os.path.join(output_stem + ".g")) ): logger.info(f"Reusing existing {output_stem}." + r"{g,bcs}") elif mesh_config.gbcs_path == "": chi_ref = [] is_unbladed = [] for bld in machine.bld: if bld: chi_ref.append(bld.get_chi(mesh_config.spf_ref)) is_unbladed.append(0) # else: # chi_ref.append(np.zeros((2,))) # is_unbladed.append(1) chi_ref = np.concatenate(chi_ref) logger.info("Making a new mesh.") splitter = [] if machine.split: for irow, splt in enumerate(machine.split): if splt: splitter.append(irow) else: splitter = [] ag_config = mesh_config.to_autogrid_dict(chi_ref, dhub, dcas, dsurf, splitter) ag_config["Nb"] = machine.Nb.tolist() ag_config["tip"] = machine.tip.tolist() success = turbigen.autogrid.autogrid.make_mesh( output_stem, *machine.get_coords(), Omega, ag_config ) if not success: raise Exception("Meshing failed.") else: output_stem = os.path.abspath(mesh_config.gbcs_path) logger.info(f"Loading {output_stem}." + r"{g,bcs}") bcs_path = output_stem + ".bcs" g_path = output_stem + ".g" g = turbigen.autogrid.reader.read(g_path, bcs_path) if rf := mesh_config.refine_factor: for b in g: b.refine(rf) return g