Nathan Collier avatar Nathan Collier committed cf84fb9

added geometry tutorial

Comments (0)

Files changed (6)

 .. role:: file(literal)
 .. _TUTORIAL3:
 
-Creating Geometry with igakit (*)
-=================================
+Creating Geometry with igakit
+=============================
 
-**Objective:** At the end of this tutorial you will understand how
-  geometries may be generated with igakit and then be read and used in PetIGA.
+**Objective:** At the end of this tutorial you will understand how geometries may be generated with igakit and then be read and used in PetIGA.
 
-**Assumptions:** I assume 
+**Assumptions:** I assume that you are familiar with python and have both packages installed and working.
 
 
 A Brief Overview of igakit
 --------------------------
 
+We created igakit to enable both a interface into many low-level
+routines which are needed to manipulate knot vectors or control point
+grids as well as a high level interface to simplify the creation of
+NURBS geometries by hand. These geometries then can be read in to
+PetIGA for use as a mapping. We also use the package for
+post-processing solution results from PetIGA. Below we briefly sketch
+some of the objects available in the package.
+
+* :file:`igalib` - a python module which contains several
+  submodules. This is a python wrapper around the Fortran module
+  implemented in :file:`igalib.f90`.
+
+  * :file:`bsp` - contains interfaces for B-spline related functions such as
+    :file:`FindSpan`, :file:`EvalBasisFunsDers`, :file:`Greville`,
+    :file:`InsertKnot`, :file:`RemoveKnot`, :file:`DegreeElevate`
+  * :file:`iga` - contains interfaces for a few functions that can be
+    used to solve B-spline-based Galerkin problems in python
+    
+    * :file:`KnotVector` - will create a uniform knot vector of
+      user-specified number of elements, polynomial order,
+      inter-element continuity
+    * :file:`BasisData` - returns a series of objects needing to
+      integrate weak form
+
+* :file:`nurbs` - contains a dimension independent python class
+  (:file:`NURBS`) which simplifies the usage of routines contained in
+  the :file:`igalib` module to create and manipulate NURBS curves,
+  surfaces, and volumes.
+
+* :file:`io` - a module which contains two python classes:
+  :file:`PetIGA` and :file:`VTK` which are used to create input/output
+  files suitable to read in by other software.
+
+* :file:`cad` - a python module which is a collection of python
+  functions which generate commonly used geometries (lines,circles)
+  and perform geometry operations (extrude, join, revolve, ruled,
+  sweep).
+
+* :file:`plot` - a python module which enables plotting natively in
+  python.
+
 Creating a Geometry
 -------------------
 
+In this tutorial we will not exhaust the possibilities of igakit for
+generating geometry, but rather explain how igakit geometries can be
+created and read into PetIGA. We encourage the reader to explore the
+demo directories of the igakit package for more samples in how igakit
+can be used to generate NURBS geometries.
+
+As an example, we will create the ever-popular patch test of
+isogeometric analysis: the quarter annulus. I will write this tutorial
+as if you are following me in the python interpreter. If you aren't
+using ipython_, I highly recommend it. First we import the circle
+functionality from the :file:`cad` module::
+
+ >>> from igakit.cad import circle
+
+Most functions we have implement come with documentation (of various
+degrees of completeness) built-in to the source code. You can view
+this by::
+
+ >>> help(circle)
+
+where you will see something like the following::
+
+ circle(radius=1, center=None, angle=None)
+    Construct a NURBS circular arc or full circle
+    
+    Parameters
+    ----------
+    radius : float, optional
+    center : array_like, optional
+    angle : float or 2-tuple of floats, optional
+
+The third argument of the circle is of interest here. The angle lets
+us choose a sweep to define our annulus. We can use this to create a
+circular arc::
+
+ >>> from numpy import pi
+ >>> c1 = circle(angle=(0,pi/2.))
+
+The circle function returns a NURBS object. To get an idea of what you
+can possibly do with this object, examine the help for it::
+
+ >>> help(c1)
+
+You will see a long list of functions and examples of attributes and
+operations which are possible in the NURBS class. For now, let's
+inspect our curve to see what was created. If you are using ipython_,
+you can type::
+
+ >>> c1.
+
+and then hit the TAB key. You will see a more concise list of what can
+be done to this curve::
+
+ c1.array      c1.control    c1.evaluate   c1.insert     c1.refine     c1.scale      c1.transform  
+ c1.boundary   c1.copy       c1.extract    c1.knots      c1.remap      c1.shape      c1.translate  
+ c1.breaks     c1.degree     c1.fields     c1.move       c1.remove     c1.slice      c1.transpose  
+ c1.clamp      c1.dim        c1.gradient   c1.plot       c1.reverse    c1.spans      c1.unclamp    
+ c1.clone      c1.elevate    c1.greville   c1.points     c1.rotate     c1.swap       c1.weights  
+
+So we see that we can inspect the knot vector::
+
+ >>> c1.knots
+ (array([ 0.,  0.,  0.,  1.,  1.,  1.]),)
+
+As expected, we created a single span of quadratics. The control point
+grid can also be inspected::
+
+ >>> c1.control 
+ array([[  1.00000000e+00,   0.00000000e+00,   0.00000000e+00, 1.00000000e+00],
+        [  7.07106781e-01,   7.07106781e-01,   0.00000000e+00, 7.07106781e-01],
+        [  2.22044605e-16,   1.00000000e+00,   0.00000000e+00, 1.00000000e+00]])
+
+which are the control points in the 4D space. The first three columns
+are the x-y-z locations of the control points and the last are the
+weights. Now we create a second circular arc, this time with a radius
+of 2::
+
+ >>> c2 = circle(radius=2,angle=(0,pi/2.))
+
+We also have some plotting functionality built into igakit. We will
+use this now to visually check that our curves have been created as
+expected::
+
+ >>> from igakit.plot import plt
+ >>> plt.plot(c1,color='b')
+ >>> plt.plot(c2,color='g')
+ >>> plt.show()
+
+You will see a 3D window open with the two curves we created that
+should look something like the following image.
+
+.. image:: ./figs/two_curves.png
+   :align: center
+
+Now, we will create a `ruled surface`_ using another function in the
+:file:`cad` module, and then also check the result with a plot::
+
+ >>> from igakit.cad import ruled
+ >>> srf = ruled(c1,c2)
+ >>> plt.plot(srf)
+ >>> plt.show()
+
+.. image:: ./figs/qannulus.png
+   :align: center
+
 Reading Geometry Into PetIGA
 ----------------------------
 
+Now while we have the geometry in hand, we need to prepare it for
+analysis. Let's inspect the polynomial orders of the surface that we
+created::
+
+ >>> srf.degree
+ (2,1)
+
+Here we see that the first direction is the quadratic curve that we
+had originally, but the ruled operation linearly blended the bounding
+curves together. Let's assume that we prefer to use equal polynomial
+orders in each direction for the annulus. So we need to degree elevate
+the second direction by one.
+
+ >>> srf.elevate(1,1)
+ >>> srf.degree
+ (2,2)
+
+We can also inspect the knot vectors::
+
+ >>> srf.knots
+ (array([ 0.,  0.,  0.,  1.,  1.,  1.]), array([ 0.,  0.,  0.,  1.,  1.,  1.]))
+
+Where we see that we have a single nonzero span of
+bi-quadratics. Since PetIGA does not handle geometry modification
+internally we need to insert knots here such that the function space
+matches the one we will use in the analysis portion. To this end, we
+will create a 10 by 10 element mesh of *C1* quadratics by knot
+insertion::
+
+ >>> from numpy import linspace
+ >>> to_insert = linspace(0,1,11)[1:-1]
+ >>> srf.refine(0,to_insert)
+ >>> srf.refine(1,to_insert)
+ >>> srf.knots
+ (array([ 0. ,  0. ,  0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8, 0.9,  1. ,  1. ,  1. ]),
+  array([ 0. ,  0. ,  0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8, 0.9,  1. ,  1. ,  1. ]))
+
+Now the geometry is ready for analysis and to be exported to
+PetIGA. We use functionality from the :file:`io` module of igakit.
+
+ >>> from igakit.io import PetIGA
+ >>> PetIGA().write("quarter_annulus.dat",srf)
+
+This will create a datafile that can be read by PetIGA. Now we will
+use this geometry in the Poisson code with the setup from the previous
+tutorial, :ref:`TUTORIAL2`. Exit python and compile the demo code
+:file:`$PETIGA_DIR/demo/Poisson.c`. I am assuming that the file
+:file:`quarter_annulus.dat` that we just created is in this directory. If it
+is not here, then you will need to move it here. Then run the PetIGA
+code with these options::
+
+ Poisson -iga_geometry quarter_annulus.dat -iga_view -save
+
+This code solves the Poisson equation with unit Dirichlet boundary
+conditions everywhere and a unit body force. When we execute this
+code, we can see what function space was used. Note that this
+corresponds to what we created in igakit::
+
+ IGA: dim=2  dof=1  order=2  geometry=2  rational=1  property=0
+ Axis 0: periodic=0  degree=2  quadrature=3  processors=1  nodes=12  elements=10
+ Axis 1: periodic=0  degree=2  quadrature=3  processors=1  nodes=12  elements=10
+ Partitioning - nodes:    sum=144  min=144  max=144  max/min=1
+ Partitioning - elements: sum=100  min=100  max=100  max/min=1
+
+Unlike the previous tutorial, the geometry is now flagged as 2D and
+the rational is flagged to True. If the input geometry is a NURBS then
+PetIGA detects and compensates for this automatically. Also, if a
+geometry is used, the basis is mapped automatically with zero code
+changes required by the user.
+
+Just as in the previous tutorial, the :file:`-save` option generates
+two files (:file:`PoissonGeometry.dat` and
+:file:`PoissonSolution.dat`). Then we can run the same visualization
+script::
+
+ python PoissonPlot.py
+
+which generates :file:`PoissonVTK.vtk`. However, this time the
+resulting VTK file encodes the solution on the mapped geometry as in
+the following image.
+
+.. image:: ./figs/quarter_annulus_poisson.png
+   :align: center
+
 Periodicity
 -----------
+
+Now, what if we did not want to take advantage of the quarter
+symmetry? How do we generate this geometry? Here I will write a single
+script which extends the above ideas to all four quadrants::
+
+ from igakit import cad
+ from igakit.io import PetIGA
+ from numpy import linspace
+ c1 = cad.circle()
+ c2 = cad.circle(radius=2)
+ srf = cad.ruled(c1,c2).elevate(1,1)
+ to_insert = linspace(0,0.25,11)[1:-1]
+ for i in range(4):
+     srf.refine(0,i*0.25+to_insert)
+     srf.refine(1,i*0.25+to_insert)
+ PetIGA().write("annulus.dat",srf)
+
+But if run this geometry through the Poisson solver, this geometry
+will not produce the desired effect, but rather as shown in the
+following figure.
+
+.. image:: ./figs/annulus_no.png
+   :align: center
+
+This is because we set all boundary conditions to one. We need to set
+the boundaries in the first parametric direction to have periodic
+boundary conditions. We need to add a line to our script, just before
+we output the geometry using the PetIGA class::
+
+ from igakit import cad
+ from igakit.io import PetIGA
+ from numpy import linspace
+ c1 = cad.circle()
+ c2 = cad.circle(radius=2)
+ srf = cad.ruled(c1,c2).elevate(1,1)
+ to_insert = linspace(0,0.25,11)[1:-1]
+ for i in range(4):
+     srf.refine(0,i*0.25+to_insert)
+     srf.refine(1,i*0.25+to_insert)
+ srf.unclamp(0) # <----------------------- added this line
+ PetIGA().write("annulus.dat",srf)
+
+This will modify the geometry to use unclamped knot vectors as
+opposed to clamped (or open) ones. Now we can rerun the code,
+specifying the periodicity::
+
+ ./Poisson -iga_geometry annulus.dat -iga_view -save -iga_periodic 1,0
+ IGA: dim=2  dof=1  order=2  geometry=2  rational=1  property=0
+ Axis 0: periodic=1  degree=2  quadrature=3  processors=1  nodes=44  elements=40
+ Axis 1: periodic=0  degree=2  quadrature=3  processors=1  nodes=39  elements=37
+ Partitioning - nodes:    sum=1716  min=1716  max=1716  max/min=1
+ Partitioning - elements: sum=1480  min=1480  max=1480  max/min=1
+
+You will see now that the first direction is flagged periodic and the
+resulting plot now displays the proper symmetry.
+
+.. image:: ./figs/annulus_yes.png
+   :align: center
+
+.. _ipython: http://ipython.org/
+.. _ruled surface: http://en.wikipedia.org/wiki/Ruled_surface
Added
New image
Added
New image
Added
New image
Add a comment to this file

figs/quarter_annulus_poisson.png

Added
New image
Added
New image
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.