API
Project creation and saving
New Project
[Return:Project] proj = newProject(name::String, folder::String)
The supplied name will be the default name of the control, mesh, and plot files generated by HOHQMesh. The folder is the directory in which those files will be placed. The empty project will include default RunParameters
and a default SpringSmoother
, both of which can be modified later, if desired. The only thing required to add is the background grid.
Opening an existing project file
A project can be created from an existing HOHQMesh control file with
[Return:Project] proj = openProject(fileName::String, folder::String)
The supplied fileName
will be the name of the project and the generated mesh and plot files will be placed in the supplied folder
.
Saving a Project
saveProject(proj::Project)
writes a control file to the folder designated when creating the new project. It can be read in again with openProject
.
Plotting a Project
plotProject!(proj::Project, options)
The plot options are any combination of MODEL
, GRID
, REFINEMENTS
, and MESH
. MODEL
refers to any inner / outer boundary curves contained in the project. GRID
refers to the background grid, which you an view to make sure that it can resolve the boundary curves in the model. REFINEMENTS
will show the placement where user defined manual refinement regions are placed. MESH
refers to the actual mesh of quadrilateral elements generated by HOHQMesh. Before meshing one probably wants to view MODEL+GRID
, and afterwards, MODEL+MESH
.
If the model is modified and you want to re-plot with the new values, invoke
updatePlot!(proj::Project, options)
but generally the plot will be updated automatically as you build the model.
Modifying/editing a Project
Setting the name of a Project
The project name is the name under which the mesh, plot, statistics and control files will be written. It can be changed at any time with
setName!(proj::Project,name::String)
Getting the current name of a Project
The project name can be fetched and printed to the screen with
[Return:String] getName(proj::Project)
Controlling the mesh generation
Editing the RunParameters
The run parameters can be enquired and set with these getter/setter pairs:
[Return:nothing] setPolynomialOrder!(proj::Project, p::Int)
[Return:Int] getPolynomialOrder(proj::Project)
[Return:nothing] setMeshFileFormat!(proj::Project, meshFileFormat::String)
[Return:String] getMeshFileFormat(proj::Project)
[Return:nothing] setPlotFileFormat!(proj::Project, plotFileFormat::String)
[Return:String] getPlotFileFormat(proj::Project)
HOHQMesh generates mesh files that contain high-order polynomial interpolations for any curved boundaries in the model. The degree of this polynomial representation is controlled by the above getter/setter pair. The default polynomial order is set to 5
.
The available mesh file formats are "ISM"
, "ISM-V2"
, or "ABAQUS"
. See the HOHQMesh documentation, Appendix A or Appendix E, as well as the Trixi.jl documentation, Unstructured quadrilateral mesh or P4est-based mesh, for details and discussions on the latter two mesh file formats.
The plot file (which can be viewed with something like VisIt or ParaView) format is either "skeleton"
or "sem"
. The former is just a low order finite element representation of the mesh. The latter (which is a much bigger file) includes the interior degrees of freedom.
Changing the output file names
By default, the mesh, plot and stats files will be written with the name and path supplied when newProject
is called. They can be changed/enquired with
[Return:nothing] setName!(proj::Project,name::String)
[Return:String] getName(proj::Project)
[Return:nothing] setFolder!(proj::Project,folder::String)
[Return:String] getFolder(proj::Project)
Smoothing operations
A default smoother is created when newProject
is called, which sets the status to ON
, type to LinearAndCrossbarSpring
, and number of iterations = 25. These are generally good enough for most purposes. The most likely parameter to change is the number of iterations. Further details on the smoothing strategy and how it works are available in the documentation and in Minoli2011.
To change the defaults, the smoother parameters can be set/enquired with the functions
[Return:nothing] setSmoothingStatus!(proj::Project, status::String)
[Return:String] getSmoothingStatus(proj::Project)
[Return:nothing] setSmoothingType!(proj::Project, type::String)
[Return:String] getSmoothingType(proj::Project)
[Return:nothing] setSmoothingIterations!(proj::Project, iterations::Int)
[Return:Int] getSmoothingIterations(proj::Project)
The smooth status
is either "ON" or "OFF".
To remove the smoother altogether, use
[Return:nothing] removeSpringSmoother!(proj::Project)
Adding the background grid
There are three forms for the background grid definition, one for when there is an outer boundary, and two for when there is not. One form of background grid must be specified after a new project has been created.
[Return:nothing] addBackgroundGrid!(proj::Project,
x0::Array{Float64},
dx::Array{Float64},
N::Array{Int})
[Return:nothing] addBackgroundGrid!(proj::Project,
box::Array{Float64},
N::Array{Int})
[Return:nothing] addBackgroundGrid!(proj::Project,
bgSize::Array{Float64})
Use one of the first two if there is no outer boundary present in the model. With the first, a rectangular outer boundary will be created of extent [x0[1], x0[1] + N*dx[1]]
by [x0[2], x0[2] + N*dx[2]]
. The second lets you set the bounding box = [top, left, bottom, right], and the number of points in each direction. The arrays x0
, dx
, and N
are all vectors [ *, *, * ]
giving the x, y, and z components. When an outer boundary is present use the third variant where one only need specify the desired background grid size with the vector bgSize
.
Changing the background grid
The size of an existing background grid in a Project
can be adjusted with
[Return:nothing] setBackgroundGridSize!(proj::Project,
dx::Float64,
dy::Float64)
If a plot is present it will be updated automatically.
Manual refinement regions
Refinement can be specified either at a point, using the RefinementCenter
, or along a line, using a RefinementLine
. You can have as many of these refinement regions as you want. They are useful if you know regions of the solution where refinement is needed (e.g. a wake) or in problematic areas of the geometry (e.g. a sharp corner).
To create a RefinementCenter
,
[Return:Dict{String,Any}] newRefinementCenter(name::String,
type::String,
x0::Array{Float64},
h::Float64,
w::Float64)
where name
labels the refinement region, the type
is either "smooth" or "sharp", x0
= [x, y, z] is the location of the center, h
is the mesh size, and w
is the extent of the refinement region. The z component must be zero.
Similarly, one can create a RefinementLine
,
[Return:Dict{String,Any}] newRefinementLine(name::String,
type::String,
x0::Array{Float64}, x1::Array{Float64},
h::Float64,
w::Float64)
where x0
is the start position and x1
is the end of the line. The name
, type
, h
, and w
parameters are the same as for a RefinementCenter
.
To add a refinement region to the project,
[Return:nothing] addRefinementRegion!(proj::Project, r::Dict{String,Any})
To get a reference to a refinement region with a given name, use
[Return:Dict{String,Any}] getRefinementRegion(proj::Project, name::String)
Finally, to get a list of all the refinement regions,
[Return:Array{Dict{String,Any}}] array = allRefinementRegions(proj::Project)
A refinement region can be edited by using the following:
[Return:nothing] setRefinementType!(r::Dict{String,Any}, type::String)
[Return:String] getRefinementType(r::Dict{String,Any})
[Return:nothing] setRefinementLocation!(r::Dict{String,Any}, x::Array{Float64})
[Return:Array{Float64}] getRefinementLocation(r::Dict{String,Any})
[Return:nothing] setRefinementGridSize!(r::Dict{String,Any}, h::Float64)
[Return:Float64] getRefinementGridSize(r::Dict{String,Any})
[Return:nothing] setRefinementWidth!(r::Dict{String,Any}, w::Float64)
[Return:Float64] getRefinementWidth(r::Dict{String,Any})
where r
is a dictionary returned by newRefinementCenter!
, newRefinementLine!
, or getRefinementRegion
.
To further edit a RefinementLine
, use the methods
[Return:nothing] setRefinementStart!(r::Dict{String,Any}, x::Array{Float64})
[Return:Array{Float64}] getRefinementStart(r::Dict{String,Any})
[Return:nothing] setRefinementEnd!(r::Dict{String,Any}, x::Array{Float64})
[Return:Array{Float64}] getRefinementEnd(r::Dict{String,Any})
Boundary curves
The Project
contains a model that contains information about any inner and/or outer boundary curves that a user can add to define a domain to be meshed. Each curve is defined as a "chain" that can be built from multiple connected curves. More details on boundary curves and HOHQMesh can be found here.
The domain can have a single outer boundary chain and an arbitrary number of inner boundary chains.
The orientation of any curve chains must be counter-clockwise. This orientation is automatically checked in generate_mesh
and a warning is thrown if a user attempts to connect the curve chain in an invalid way.
See the tutorial Creating and editing curves for a demonstration of defining, constructing, and removing curves from a Project
.
Defining curves
Four curve types can be added to the outer and inner boundary curve chains. They are
- Parametric equations
- Cubic Splines
- Lines defined by their end points
- Circular arcs
Parametric equations
Creating a new curve equation
[Return:Dict{String,Any}] newParametricEquationCurve(name::String,
xEqn::String,
yEqn::String,
zEqn::String = "z(t) = 0.0")
Returns a new set of parametric equation. Equations must be of the form
<function name>(<argument>) = ...
The name of the function, and the argument are arbitrary. The equation can be any legitimate equation. The constant pi
is defined for use. Exponentiation is done with ^
. All number literals are interpreted as floating point numbers.
Example:
xEqn = "x(t) = 4*cos(2*pi*t) - 0.6*cos(8*pi*t)^3"
yEqn = "y(t) = 4*sin(2*pi*t) - 0.5*sin(11*pi*t)^2"
zEqn = "z(t) = 0.0"
blob = newParametricEquationCurve("Blob", xEqn, yEqn, zEqn)
The z-Equation is optional, but for now must define zero for z by default.
Cubic spline curve
A cubic spline is defined by an array of knots, $t_j$, $x_j$, $y_j$, $z_j$. It can either be supplied by a data file whose first line is the number of knots, and succeeding lines define the $t$, $x$, $y$, $z$ values, e.g.
9
0.000000000000000 -3.50000000000000 3.50000000000000 0.0
3.846153846153846E-002 -3.20000000000000 5.00000000000 0.0
7.692307692307693E-002 -2.00000000000000 6.00000000000 0.0
0.769230769230769 0.000000000000000 -1.00000000000000 0.0
0.807692307692308 -1.00000000000000 -1.00000000000000 0.0
0.846153846153846 -2.00000000000000 -0.800000000000000 0.0
0.884615384615385 -2.50000000000000 0.000000000000000 0.0
0.923076923076923 -3.00000000000000 1.00000000000000 0.0
1.00000000000000 -3.50000000000000 3.50000000000000 0.0
or by constructing the required nKnots
x 4
array and supplying it to the new procedure. The respective constructors for a spline curve are
[Return:Dict{String,Any}] newSplineCurve(name::String,
dataFile::String)
[Return:Dict{String,Any}] newSplineCurve(name::String,
nKnots::Int,
data::Matrix{Float64})
If the spline curve is to be closed. The last data point must be the same as the first.
Example:
spline_data = [ [0.0 1.75 -1.0 0.0]
[0.25 2.1 -0.5 0.0]
[0.5 2.7 -1.0 0.0]
[0.75 0.6 -2.0 0.0]
[1.0 1.75 -1.0 0.0] ]
ex_spline = newSplineCurve("small_spline", 5, spline_data)
Line defined by end points
A straight line is constructed with
[Return:Dict{String,Any}] newEndPointsLineCurve(name::String,
xStart::Array{Float64},
xEnd::Array{Float64})
The xStart
and xEnd
are arrays of the form [x, y, z]. The z
component should be zero and for now is ignored.
Example:
line1 = newEndPointsLineCurve("line_segment", [0.0, -3.0, 0.0], [1.0, 0.0, 0.0])
Circular arc
[Return:Dict{String,Any}] newCircularArcCurve(name::String,
center::Array{Float64},
radius::Float64,
startAngle::Float64,
endAngle::Float64,
units::String)
The center is an array of the form [x, y, z]. The units argument defines the start and end angle units. It is either "degrees" or "radians". That argument is optional, and defaults to "degrees".
Example:
halfCircle = newCircularArcCurve("Dome", [0.0, 0.0, 0.0], 1.0, 0.0, 180.0, "degrees")
Adding and removing outer and inner boundaries
Adding an outer boundary curve
Using the curve creation routines described above, create curves counter-clockwise along the outer boundary and add them to the outer boundary curve using
[Return:nothing] addCurveToOuterBoundary!(proj::Project, crv::Dict{String,Any})
crv
is the dictionary that represents the curve.Example:
circ = newCircularArcCurve("outerCircle", [0.0, -1.0, 0.0], 4.0, 0.0, 360.0, "degrees") addCurveToOuterBoundary!(p, circ)
Adding an inner boundary curve
The syntax is analogous to the creation of an outer boundary curve. Once interior curves are defined they can be added to chain, again in counter-clockwise orientation. Note that the individual pieces of the curve are given a name. The entire chain is also given a name.
[Return:nothing] addCurveToInnerBoundary!(proj::Project, crv::Dict{String,Any}, chainName::String)
Example:
line1 = newEndPointsLineCurve("line_segment", [0.0, -3.0, 0.0], [1.0, 0.0, 0.0]) addCurveToInnerBoundary!(p, line1, "interior_curve")
To edit curves they can be accessed by the name:
[Return:Dict{String,Any}] getInnerBoundaryCurve(proj::Project, curveName::String, chainName::String) [Return:Dict{String,Any}] getOuterBoundaryCurveWithName(proj::Project, name::String)
Deleting boundary curves
The entire outer boundary or an entire inner boundary can be removed from the project.
[Return:nothing] removeOuterBoundary!(proj::Project) [Return:nothing] removeInnerBoundary!(proj::Project, chainName::String)
Alternatively, individual pieces of the boundary curve chains can be removed.
[Return:nothing] removeOuterBoundaryCurveWithName!(proj::Project, name::String) [Return:nothing] removeInnerBoundaryCurve!(proj::Project, name::String, chainName::String)
As in HOHQMesh the project can have only one outer boundary chain, so the removal does not require a specific
chainName
.
Editing curves
You can determine the type of a curve by
[Return:String] getCurveType(crv::Dict{String,Any})
For any of the curves, their name can be changed by
setCurveName!(crv::Dict{String,Any}, name::String)
and checked by
getCurveName(crv::Dict{String,Any})
Alternatively, all curves on an outer or inner boundary with the same name can have that name changed all at once everywhere in the project with the function
renameCurve!(proj::Project, oldName::String, newName::String)
Otherwise there are special functions to change the parameters of curves
[Return:nothing] setXEqn!(crv::Dict{String,Any}, eqn::String)
[Return:nothing] setYEqn!(crv::Dict{String,Any}, eqn::String)
[Return:nothing] setZEqn!(crv::Dict{String,Any}, eqn::String)
[Return:nothing] setStartPoint!(crv::Dict{String,Any}, point::Array{Float64})
[Return:nothing] setEndPoint!(crv::Dict{String,Any}, point::Array{Float64})
[Return:nothing] setArcUnits!(arc::Dict{String,Any}, units::String)
[Return:nothing] setArcCenter!(arc::Dict{String,Any}, point::Array{Float64})
[Return:nothing] setArcStartAngle!(arc::Dict{String,Any}, angle::Float64)
[Return:nothing] setArcEndAngle!(arc::Dict{String,Any}, angle::Float64)
[Return:nothing] setArcRadius!(arc::Dict{String,Any}, radius::Float64)
[Return:String] getXEqn(crv::Dict{String,Any})
[Return:String] getYEqn(crv::Dict{String,Any})
[Return:String] getZEqn(crv::Dict{String,Any})
[Return:Array{Float64}] getStartPoint(crv::Dict{String,Any})
[Return:Array{Float64}] getEndPoint(crv::Dict{String,Any})
[Return:String] getArcUnits(arc::Dict{String,Any})
[Return:Array{Float64}] getArcCenter(arc::Dict{String,Any})
[Return:Float64] getArcStartAngle(arc::Dict{String,Any})
[Return:Float64] getArcEndAngle(arc::Dict{String,Any})
[Return:Float64] getArcRadius(arc::Dict{String,Any})
Undo/redo
The interactive mesh functionality has unlimited undo/redo for most actions.
In interactive mode, actions can be undone by the commands
[Return:String] undo()
[Return:String] redo()
where the return string contains the name of the action performed.
To find out what the next actions are, use
[Return:String] undoActionName()
[Return:String] redoActionName()
Finally, to clear the undo stack, use
[Return:nothing] clearUndoRedo()