├── .gitignore ├── LICENSE ├── Makefile ├── README ├── benchmarking ├── cylinder2Pa.geom ├── cylinder2PaPlunge.geom └── runbenchmarks.sh ├── build └── Makefile ├── config ├── make.inc ├── make.inc.clang ├── make.inc.gcc ├── make.inc.gccjoshy ├── make.inc.joshy └── make.inc.ystone ├── doc ├── Doxyfile ├── Figures │ ├── IBFSDesign.graffle │ ├── IBFSDesign.pdf │ ├── IBPMDesign.graffle │ ├── IBPMDesign.pdf │ ├── grid.graffle │ └── grid.pdf ├── Library.dox ├── Makefile ├── Overview.dox ├── References.dox ├── examples │ ├── Makefile │ ├── cylinder.cc │ ├── cylinder.lay │ ├── hello.cc │ └── plot_cylinder.mcr ├── ibpm_design.tex ├── ibpm_manual.tex ├── references.bib └── snippets │ ├── Makefile │ ├── hello_snippet.cc │ ├── setup_grid.cc │ └── template.cc.tpl ├── examples ├── Makefile ├── Oseen.cc ├── RigidBodyLoad.cc ├── bin2plt.cc ├── bininfo.cc ├── cylinder.geom ├── pitching.cc └── plunging.cc ├── ibpm.geom ├── src ├── Array.h ├── BC.cc ├── BC.h ├── BaseFlow.cc ├── BaseFlow.h ├── BoundaryVector.cc ├── BoundaryVector.h ├── CholeskySolver.cc ├── CholeskySolver.h ├── ConjugateGradientSolver.cc ├── ConjugateGradientSolver.h ├── Direction.h ├── Eldredge1.h ├── Eldredge2.h ├── EldredgeCombined2.h ├── EldredgeManeuver.h ├── EllipticSolver.cc ├── EllipticSolver.h ├── EllipticSolver2d.cc ├── EllipticSolver2d.h ├── Field.cc ├── Field.h ├── FixedPosition.h ├── FixedVelocity.h ├── Flux.cc ├── Flux.h ├── Geometry.cc ├── Geometry.h ├── Grid.cc ├── Grid.h ├── IBSolver.cc ├── IBSolver.h ├── LagStep1.h ├── LagStep2.h ├── Logger.cc ├── Logger.h ├── Motion.h ├── MotionFile.h ├── MotionFilePeriodic.h ├── NavierStokesModel.cc ├── NavierStokesModel.h ├── Output.h ├── OutputEnergy.cc ├── OutputEnergy.h ├── OutputForce.cc ├── OutputForce.h ├── OutputProbes.cc ├── OutputProbes.h ├── OutputRestart.cc ├── OutputRestart.h ├── OutputTecplot.cc ├── OutputTecplot.h ├── ParmParser.cc ├── ParmParser.h ├── PitchPlunge.h ├── ProjectionSolver.cc ├── ProjectionSolver.h ├── RandomNumber.h ├── Regularizer.cc ├── Regularizer.h ├── RigidBody.cc ├── RigidBody.h ├── Scalar.cc ├── Scalar.h ├── ScalarToTecplot.cc ├── ScalarToTecplot.h ├── Scheme.h ├── SigmoidalStep.h ├── State.cc ├── State.h ├── StateVector.cc ├── StateVector.h ├── TangentSE2.h ├── VectorOperations.cc ├── VectorOperations.h ├── checkgeom.cc ├── ibpm.cc ├── ibpm.h ├── utils.cc └── utils.h ├── test ├── BCTest.cc ├── BoundaryVectorTest.cc ├── CheckAdjoint.cc ├── CheckCurl.cc ├── CheckFluxToX.cc ├── CheckLaplacian.cc ├── EllipticSolver2dTest.cc ├── EllipticSolverTest.cc ├── FluxTest.cc ├── GeometryTest.cc ├── GridTest.cc ├── Makefile ├── MotionTest.cc ├── NavierStokesModelTest.cc ├── OutputProbesTest.cc ├── ParmParserTest.cc ├── ProjectionSolverTest.cc ├── RegularizerTest.cc ├── RigidBodyTest.cc ├── ScalarTest.cc ├── SingleWavenumber.h ├── StateTest.cc ├── TangentSE2Test.cc ├── VectorOperationsTest.cc └── gtest-1.6.0 │ ├── COPYING │ ├── include │ └── gtest │ │ ├── gtest-death-test.h │ │ ├── gtest-message.h │ │ ├── gtest-param-test.h │ │ ├── gtest-param-test.h.pump │ │ ├── gtest-printers.h │ │ ├── gtest-spi.h │ │ ├── gtest-test-part.h │ │ ├── gtest-typed-test.h │ │ ├── gtest.h │ │ ├── gtest_pred_impl.h │ │ ├── gtest_prod.h │ │ └── internal │ │ ├── gtest-death-test-internal.h │ │ ├── gtest-filepath.h │ │ ├── gtest-internal.h │ │ ├── gtest-linked_ptr.h │ │ ├── gtest-param-util-generated.h │ │ ├── gtest-param-util-generated.h.pump │ │ ├── gtest-param-util.h │ │ ├── gtest-port.h │ │ ├── gtest-string.h │ │ ├── gtest-tuple.h │ │ ├── gtest-tuple.h.pump │ │ ├── gtest-type-util.h │ │ └── gtest-type-util.h.pump │ └── src │ ├── gtest-all.cc │ ├── gtest-death-test.cc │ ├── gtest-filepath.cc │ ├── gtest-internal-inl.h │ ├── gtest-port.cc │ ├── gtest-printers.cc │ ├── gtest-test-part.cc │ ├── gtest-typed-test.cc │ ├── gtest.cc │ └── gtest_main.cc └── xcode └── IBPM.xcodeproj ├── clancy.pbxuser └── project.pbxproj /.gitignore: -------------------------------------------------------------------------------- 1 | build/*.o 2 | build/libibpm.a 3 | build/checkgeom 4 | build/ibpm 5 | examples/*.cmd 6 | examples/*.force 7 | examples/*.bin 8 | examples/*.plt 9 | examples/*.cholesky 10 | TAGS 11 | test/*.o 12 | test/runner 13 | test/runner.err 14 | test/gtest_main.a 15 | test/gtest.a 16 | doc/*.aux 17 | doc/*.bbl 18 | doc/*.blg 19 | doc/*.log 20 | doc/*.out 21 | doc/*.pdfsync 22 | doc/*.synctex.gz 23 | doc/*.toc 24 | doc/ibpm_design.pdf 25 | doc/html 26 | doc/latex 27 | doc/ibpm_manual.pdf 28 | doc/examples/*.plt 29 | doc/examples/*.out 30 | doc/snippets/*.out 31 | callgrind.out.* 32 | .depend 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012, Clarence W. Rowley, Princeton University 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of Princeton University nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Main makefile for IBPM code 2 | # 3 | # Clancy Rowley 4 | # Princeton University 5 | # 6 | # $Date$ 7 | # $Revision$ 8 | # $Author$ 9 | # $HeadURL$ 10 | 11 | .PHONY: ibpm test doc clean distclean 12 | DIRS = build test doc 13 | 14 | ibpm: 15 | cd build && $(MAKE) 16 | 17 | test: 18 | cd test && $(MAKE) 19 | 20 | doc: 21 | cd doc && $(MAKE) 22 | 23 | all: ibpm test doc 24 | 25 | clean: 26 | for dir in $(DIRS); do ( cd $$dir && $(MAKE) clean; ) done 27 | 28 | distclean: clean 29 | for dir in $(DIRS); do \ 30 | ( cd $$dir && $(MAKE) distclean; )\ 31 | done 32 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README for Immersed Boundary Projection Method (IBPM) 2 | ===================================================== 3 | 4 | The code contained in this distribution uses an immersed boundary method to 5 | solve the two-dimensional incompressible Navier-Stokes equations around 6 | complex geometries, using the projection method described in Taira and 7 | Colonius (2007). In particular, this code implements the "fast method" 8 | described in Section 3.3 of Colonius and Taira (2008), using the multi-domain 9 | approach for far-field boundary conditions, as described in section 4 of this 10 | reference. 11 | 12 | 13 | Getting started 14 | =============== 15 | 16 | To run the code, first build the executables as described below. The main 17 | executable is called 'ibpm' and will be created in the 'build' directory. 18 | 19 | The code reads an input file to determine the geometry, and a sample input 20 | file (for a cylinder) is contained in 'examples/cylinder.geom'. 21 | 22 | To run the code for this example: 23 | cd examples 24 | ../build/ibpm -geom cylinder.geom 25 | 26 | This will initialize the solver with a zero initial condition, and evolve the 27 | flow for 250 timesteps, writing binary 'restart' files (e.g. ibpm00100.bin) 28 | and ASCII files readable by the Tecplot plotting software (ibpm00100.plt). 29 | Lift and drag forces are written to the file ibpm.force, and the command 30 | executed is written to a file ibpm.cmd (so the same run can be recreated 31 | later). 32 | 33 | The default options (numbers of gridpoints, names of output files, etc) can be 34 | changed by command line arguments. To see the available options: 35 | ../build/ibpm -h 36 | 37 | 38 | Installation 39 | ============ 40 | 41 | Requirements: 42 | C++ compiler 43 | 44 | FFTW library, version 3 45 | http://www.fftw.org/ 46 | 47 | Doxygen (to build documentation) 48 | http://www.stack.nl/~dimitri/doxygen/ 49 | 50 | 51 | Building the library and executables: 52 | 53 | The default configuration is to compile the code with the GCC compiler, with 54 | the FFTW library in a default location known to the compiler (e.g. 55 | /usr/local/lib). If this is acceptable, then to build the library and 56 | executables, all you need to do is type 57 | 58 | make 59 | 60 | from the root directory of the distribution (we will call this ). The 61 | library and command-line tools will be generated in the 'build' directory. 62 | 63 | To customize the build process for your system, make a copy of the file 64 | 'config/make.inc.gcc' and modify it as needed (this file is included by other 65 | Makefiles, and the format is pretty self-explanatory). Save the new file as 66 | /config/make.inc and type 'make' from the root directory, as 67 | before. 68 | 69 | Building and running the automated tests: 70 | make test 71 | 72 | Building the documentation: 73 | make doc 74 | 75 | 76 | Documentation 77 | ============= 78 | 79 | The documentation consists of a user manual (in doc/ibpm_manual.tex), which 80 | describes the main functionality of the code, as well as detailed 81 | documentation automatically generated by Doxygen. 82 | 83 | The user manual is the best starting place for new users, and explains the 84 | format of the geometry files, among other things. 85 | 86 | The default configuration for the automatically generated documentation is to 87 | generate both html and LaTeX documentation, but this can be changed by 88 | modifying the file 'doc/Doxyfile'. Once the documentation has been built, the 89 | html documentation (usually the most useful) can be found in 90 | 'doc/html/index.html', and the LaTeX documentation can be found in 91 | 'doc/latex/refman.tex'. 92 | 93 | 94 | References 95 | ========== 96 | K. Taira and T. Colonius. The immersed boundary method: A projection approach. J. Comput. Phys., 225(2):2118-2137, August 2007. 97 | 98 | T. Colonius and K. Taira. A fast immersed boundary method using a nullspace approach and multi-domain far-field boundary conditions. Comp. Meth. Appl. Mech. Eng., 197(25-28):2131–46, 2008. 99 | -------------------------------------------------------------------------------- /benchmarking/cylinder2Pa.geom: -------------------------------------------------------------------------------- 1 | #Stationary cylinder 2 | body Large Circle 3 | circle_n 0 0 0.5 160 #circle centered at (0, 0) with r = 0.5 4 | motion fixed 0 0 0 5 | end 6 | -------------------------------------------------------------------------------- /benchmarking/cylinder2PaPlunge.geom: -------------------------------------------------------------------------------- 1 | #Stationary cylinder 2 | body Large Circle 3 | circle_n 0 0 0.5 160 #circle centered at (0, 0) with r = 0.5 4 | motion PitchPlunge 0 0 0.5 0.2 #plunging 0.5 amplitude 0.2 freq 5 | end 6 | -------------------------------------------------------------------------------- /benchmarking/runbenchmarks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Speed benchmarking tests" 4 | echo "Stationary body, body fixed frame running...time taken is " 5 | tfixedubf1="$(TIMEFORMAT='%lU'; (time ./build/ibpm -outdir benchmarking/benchout -tecplot 0 -restart 0 -nx 200 -ny 200 -ngrid 3 -length 4 -xoffset -2 -yoffset -2 -xshift 0.72 -geom benchmarking/cylinder2Pa.geom -ubf 1 -Re 100 -dt 0.01 -nsteps 20 -scheme euler 2>&1 1>/dev/null))" 6 | 7 | rm benchmarking/benchout/* 8 | echo "Stationary body, inertial frame running...time taken is " 9 | tfixedubf0="$(TIMEFORMAT='%lU'; (time ./build/ibpm -outdir benchmarking/benchout -tecplot 0 -restart 0 -nx 200 -ny 200 -ngrid 3 -length 4 -xoffset -2 -yoffset -2 -xshift 0.72 -geom benchmarking/cylinder2Pa.geom -ubf 0 -Re 100 -dt 0.01 -nsteps 20 -scheme euler 2>&1 1>/dev/null))" 10 | 11 | rm benchmarking/benchout/* 12 | echo "Moving body, body fixed frame running...time taken is " 13 | tplungeubf1="$(TIMEFORMAT='%lU'; (time ./build/ibpm -outdir benchmarking/benchout -tecplot 0 -restart 0 -nx 200 -ny 200 -ngrid 3 -length 4 -xoffset -2 -yoffset -2 -xshift 0.72 -geom benchmarking/cylinder2PaPlunge.geom -ubf 1 -Re 100 -dt 0.01 -nsteps 20 -scheme euler 2>&1 1>/dev/null))" 14 | 15 | rm benchmarking/benchout/* 16 | echo "Moving body, inertial frame running...time taken is" 17 | tplungeubf0="$(TIMEFORMAT='%lU'; (time ./build/ibpm -outdir benchmarking/benchout -tecplot 0 -restart 0 -nx 200 -ny 200 -ngrid 3 -length 4 -xoffset -2 -yoffset -2 -xshift 0.72 -geom benchmarking/cylinder2PaPlunge.geom -ubf 0 -Re 100 -dt 0.01 -nsteps 20 -scheme euler 2>&1 1>/dev/null))" 18 | 19 | rm benchmarking/benchout/* 20 | 21 | 22 | -------------------------------------------------------------------------------- /build/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for library and main executable for IBPM code 2 | # 3 | # Clancy Rowley 4 | # Princeton University 5 | # 6 | # $Date: 2009-05-12 21:37:53 -0600 (Tue, 12 May 2009) $ 7 | # $Revision: 201 $ 8 | # $Author: zma $ 9 | # $HeadURL: svn+ssh://rainier.princeton.edu/ibpm/trunk/src/Makefile $ 10 | 11 | EXECUTABLES = ibpm checkgeom 12 | 13 | all: libibpm.a $(EXECUTABLES) 14 | 15 | include ../config/make.inc 16 | 17 | OBJS = \ 18 | BaseFlow.o \ 19 | BC.o \ 20 | BoundaryVector.o \ 21 | CholeskySolver.o \ 22 | ConjugateGradientSolver.o \ 23 | EllipticSolver.o \ 24 | EllipticSolver2d.o \ 25 | Field.o \ 26 | Flux.o \ 27 | Geometry.o \ 28 | Grid.o \ 29 | IBSolver.o \ 30 | Logger.o \ 31 | NavierStokesModel.o \ 32 | OutputEnergy.o \ 33 | OutputForce.o \ 34 | OutputRestart.o \ 35 | OutputTecplot.o \ 36 | OutputProbes.o\ 37 | ParmParser.o \ 38 | ProjectionSolver.o \ 39 | Regularizer.o \ 40 | RigidBody.o \ 41 | Scalar.o \ 42 | ScalarToTecplot.o \ 43 | State.o \ 44 | StateVector.o \ 45 | utils.o \ 46 | VectorOperations.o 47 | 48 | VPATH = ../src 49 | 50 | AR = ar 51 | ARFLAGS = -r 52 | MAKEDEPEND = gcc -MM 53 | 54 | LDLIBS = -lfftw3 -lm 55 | LDFLAGS += $(lib_dirs) 56 | CXXFLAGS += $(include_dirs) 57 | 58 | .PHONY: clean distclean depend 59 | 60 | libibpm.a: $(OBJS) 61 | $(AR) $(ARFLAGS) $@ $? 62 | 63 | $(EXECUTABLES) : % : %.o libibpm.a 64 | $(CXX) $(LDFLAGS) -o $@ $^ $(LDLIBS) 65 | 66 | clean: 67 | -/bin/rm -rf *.o .depend 68 | 69 | distclean: clean 70 | -/bin/rm -rf libibpm.a $(EXECUTABLES) 71 | 72 | depend: 73 | $(MAKEDEPEND) $(CXXFLAGS) ../src/*.cc > .depend 74 | 75 | -include .depend 76 | -------------------------------------------------------------------------------- /config/make.inc: -------------------------------------------------------------------------------- 1 | make.inc.gcc -------------------------------------------------------------------------------- /config/make.inc.clang: -------------------------------------------------------------------------------- 1 | # standard config file, using gcc compiler 2 | 3 | CXX = c++ 4 | 5 | # flags for compiling with optimization 6 | CXXFLAGS = -Wall -g -O3 -DNDEBUG 7 | 8 | # Specify directories for libraries and header files here 9 | # lib_dirs = -L/path/to/lib 10 | 11 | # include_dirs = -I/path/to/include 12 | -------------------------------------------------------------------------------- /config/make.inc.gcc: -------------------------------------------------------------------------------- 1 | # standard config file, using gcc compiler 2 | 3 | CXX = g++ 4 | 5 | # flags for compiling with optimization 6 | CXXFLAGS = -Wall -g -Ofast -funroll-loops -DNDEBUG 7 | 8 | # for debugging, uncomment the following line 9 | # CXXFLAGS = -Wall -g 10 | 11 | # Specify directories for libraries and header files here 12 | # lib_dirs = -L/path/to/lib 13 | 14 | # include_dirs = -I/path/to/include 15 | -------------------------------------------------------------------------------- /config/make.inc.gccjoshy: -------------------------------------------------------------------------------- 1 | # standard config file, using gcc compiler 2 | # a modified make.inc for using g++ on joshy, by Zhanhua Ma, Apr 28, 2009 3 | 4 | CXX = g++ 5 | CXXFLAGS = -Wall -g -O4 -funroll-loops -DNDEBUG #-fast 6 | # for debugging, uncomment the following line 7 | #CXXFLAGS = -Wall -g 8 | 9 | lib_dirs = \ 10 | -L/home/cwrowley/pgi/lib \ 11 | -L/opt/fftw3.pgi/lib 12 | 13 | include_dirs = \ 14 | -I/home/cwrowley/pgi/include \ 15 | -I/opt/fftw3.pgi/include 16 | -------------------------------------------------------------------------------- /config/make.inc.joshy: -------------------------------------------------------------------------------- 1 | # config file for joshy.princeton.edu, using PGI compiler 2 | 3 | CXX = pgcpp 4 | CXXFLAGS = -fast -Minform=severe -Mipa=fast,inline -Msmartalloc -DNDEBUG 5 | # for debugging, uncomment the following line 6 | CXXFLAGS = -Minform=severe -g 7 | 8 | lib_dirs = \ 9 | -L/home/cwrowley/pgi/lib \ 10 | -L/opt/fftw3.pgi/lib 11 | 12 | include_dirs = \ 13 | -I/home/cwrowley/pgi/include \ 14 | -I/opt/fftw3.pgi/include 15 | -------------------------------------------------------------------------------- /config/make.inc.ystone: -------------------------------------------------------------------------------- 1 | # Config file for compiling on Yellowstone 2 | # Uses local installation of GoogleTest 1.3.1, by Jonathan Tu 3 | # Uses shared installation of fft library 4 | # June 2, 2009 5 | 6 | 7 | CXX = g++ 8 | CXXFLAGS = -Wall -g -O4 -funroll-loops -DNDEBUG #-fast 9 | 10 | # for debugging, uncomment the following line 11 | # CXXFLAGS = -Wall -g 12 | 13 | lib_dirs = \ 14 | -L/usr/local/lib 15 | 16 | 17 | include_dirs = \ 18 | -I/usr/local/include 19 | 20 | -------------------------------------------------------------------------------- /doc/Figures/IBFSDesign.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwrowley/ibpm/0af66f4195e4de80e1b9d0c33d9a242937a76616/doc/Figures/IBFSDesign.graffle -------------------------------------------------------------------------------- /doc/Figures/IBFSDesign.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwrowley/ibpm/0af66f4195e4de80e1b9d0c33d9a242937a76616/doc/Figures/IBFSDesign.pdf -------------------------------------------------------------------------------- /doc/Figures/IBPMDesign.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwrowley/ibpm/0af66f4195e4de80e1b9d0c33d9a242937a76616/doc/Figures/IBPMDesign.graffle -------------------------------------------------------------------------------- /doc/Figures/IBPMDesign.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwrowley/ibpm/0af66f4195e4de80e1b9d0c33d9a242937a76616/doc/Figures/IBPMDesign.pdf -------------------------------------------------------------------------------- /doc/Figures/grid.graffle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwrowley/ibpm/0af66f4195e4de80e1b9d0c33d9a242937a76616/doc/Figures/grid.graffle -------------------------------------------------------------------------------- /doc/Figures/grid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cwrowley/ibpm/0af66f4195e4de80e1b9d0c33d9a242937a76616/doc/Figures/grid.pdf -------------------------------------------------------------------------------- /doc/Library.dox: -------------------------------------------------------------------------------- 1 | namespace ibpm { 2 | 3 | /*! \page Library Library overview 4 | 5 | The algorithms used by the main \p ibpm code are made available in a library that can be used by other codes, for instance to write wrapper routines around the main timestepper, or to perform post-processing tasks. The library is written in an object-oriented style, with the various algorithms and data structures provided by different classes. Here, we give an overview of the various classes and their roles, as well as some \ref Examples. For a detailed description of their interfaces, consult the Doxygen documentation, or the corresponding header files. 6 | 7 | An overview of the classes and their interactions is shown in the figure below. 8 | 9 | \image html IBPMDesign.pdf Overview of the main classes in the IBPM library. 10 | \image latex IBPMDesign.pdf Overview of the main classes in the IBPM library. 11 | 12 | \section DataStructures Data structures 13 | 14 | The main data structures consist of a Grid that specifies the grid characteristics, a Geometry that specifies the configuration of the bodies and the locations of their boundary points, and variables that take on values either on the grid (Scalar, Flux), or on the boundary points (BoundaryVector). 15 | 16 | A Grid defines the number of grid points in x- and y-directions, as well as the physical dimensions, and the number of grids to be used in a multi-domain solver. 17 | 18 | Two classes, Scalar and Flux, define variables that take on values on the grid. In particular, a Scalar variable (such as vorticity and streamfunction) takes on a single value at each node in the figure below. 19 | 20 | \image html grid.pdf "Layout of staggered grid" 21 | \image latex grid.pdf "Layout of staggered grid" 22 | 23 | A Flux is vector-valued: the x-component is defined as the flux through vertical edges in the figure (blue arrows), while the y-component is defined as the flux through horizontal edges (red arrows). 24 | 25 | A Geometry defines the configuration of the bodies and the locations of their boundary points. In particular, a Geometry contains a number of RigidBody objects, each with an associated Motion that prescribes the motion of that body in time. 26 | 27 | A BoundaryVector defines a vector-valued function that takes on values at the boundary points defined by a particular Geometry. For instance, the x- and y-forces at the boundary points are described by a BoundaryVector, as are the velocities at the boundary points, in the case of a moving body. 28 | 29 | Finally, a State consists of the complete flow state at any time. In particular, a State has components 30 | 31 | \code 32 | Scalar omega; // vorticity at each node 33 | Flux q; // u- and v-velocity flux through cell edges 34 | BoundaryVector f; // forces at each of the boundary points 35 | int timestep; // current timestep 36 | double time; // current time 37 | \endcode 38 | 39 | \section Examples 40 | 41 | \subsection GridSec Grid 42 | For example, the following code defines a grid: 43 | 44 | \include setup_grid.cc 45 | 46 | output: 47 | 48 | \include setup_grid.out 49 | 50 | 51 | 52 | \subsection CylExamp Flow past a cylinder 53 | 54 | The following is a complete program to compute flow past a cylinder: 55 | 56 | \include cylinder.cc 57 | 58 | output: 59 | 60 | \include cylinder.out 61 | 62 | */ 63 | /* 64 | \image html cylinder.png "Vorticity from cylinder example" 65 | \image latex cylinder.png "Vorticity from cylinder example" 66 | 67 | 68 | */ 69 | 70 | } // namespace ibpm 71 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for documentation for IBPM code 2 | # 3 | # Clancy Rowley 4 | # Princeton University 5 | # 6 | # $Date$ 7 | # $Revision$ 8 | # $Author$ 9 | # $HeadURL$ 10 | 11 | all: doc ibpm_manual.pdf 12 | 13 | SUBDIRS = examples snippets 14 | 15 | .PHONY: doc clean distclean $(SUBDIRS) 16 | .SUFFIXES: .tex .pdf 17 | 18 | include ../config/make.inc 19 | 20 | doc: $(SUBDIRS) 21 | doxygen 22 | 23 | $(SUBDIRS): 24 | $(MAKE) -C $@ 25 | 26 | .tex.pdf: 27 | (pdflatex $<; pdflatex $<; pdflatex $<) 28 | 29 | clean: 30 | -$(RM) -f *.aux *.toc *.blg *.fdb_latexmk *.log *.out *.pdfsync 31 | for dir in $(SUBDIRS); do \ 32 | $(MAKE) -C $$dir clean; \ 33 | done 34 | 35 | distclean: clean 36 | -$(RM) -rf html latex ibpm_design.pdf 37 | -------------------------------------------------------------------------------- /doc/Overview.dox: -------------------------------------------------------------------------------- 1 | namespace ibpm { 2 | 3 | /*! \mainpage Immersed Boundary Projection Method 4 | 5 | \section TOC Table of contents 6 | - \ref Overview 7 | - \ref Installation 8 | - \ref Method "What the code does" 9 | - \ref CLtool "Command line tool" 10 | - \ref Library "Library overview" 11 | - \ref References 12 | 13 | \section Overview 14 | The code described in this manual uses an immersed boundary method to solve the two-dimensional incompressible Navier-Stokes equations around complex geometries, using the projection method described in \ref TaiCol07. In particular, this code implements the ``fast method'' described in Section 3.3 of \ref ColTai08, using the multi-domain approach for far-field boundary conditions, as described in section 4 of this paper. 15 | 16 | \subsection Organization How this manual is organized 17 | 18 | This package provides a command-line tool \c ibpm, as well as a library (libibpm.a) that can be used for writing customized programs, such as post-processing utilities, or computational wrappers around the main solver. 19 | 20 | \ref Installation describes how to compile the library and executables. \ref Method describes what the code does, giving the highlights of the numerical method. \ref CLtool describes the simplest way to use the code, via the command-line tool. \ref Library "Library overview" describes the high-level classes provided by the library, geared towards users of the library. 21 | 22 | 23 | \section Installation 24 | 25 | installation instructions here 26 | 27 | \section Method 28 | 29 | what the code does 30 | 31 | \section CLtool Command line 32 | 33 | command line tool 34 | 35 | 36 | 37 | */ 38 | 39 | } // namespace ibpm -------------------------------------------------------------------------------- /doc/References.dox: -------------------------------------------------------------------------------- 1 | namespace ibpm { 2 | 3 | /*! \page References References 4 | 5 | \section References 6 | 7 | \subsection TaiCol07 8 | K. Taira and T. Colonius, J. Comput. Phys. \b 225(2):2118-2137, 2007. 9 | 10 | \subsection ColTai08 11 | T. Colonius and K. Taira, Comp. Meth. Appl. Mech. Eng. \b 197(25-28):2131-2146, 2008. 12 | 13 | */ 14 | 15 | } // namespace ibpm -------------------------------------------------------------------------------- /doc/examples/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for compiling and running examples 2 | # CWR, 23 Sep 2009 3 | 4 | .PHONY: all clean lib 5 | 6 | IBPM_DIR = ../.. 7 | SRC_DIR = $(IBPM_DIR)/src 8 | IBPM_LIB = $(IBPM_DIR)/build/libibpm.a 9 | 10 | include $(IBPM_DIR)/config/make.inc 11 | 12 | output_files := $(patsubst %.cc, %.out, $(wildcard *.cc)) 13 | 14 | all: $(output_files) 15 | 16 | %.out: %.x 17 | ./$< > $@ 18 | 19 | %.x: %.cc 20 | make lib 21 | $(CXX) -o $@ -I$(SRC_DIR) $< $(IBPM_LIB) -lfftw3 -lm 22 | 23 | cylinder.png: cylinder.out cyl010.plt cylinder.lay plot_cylinder.mcr 24 | tec360 -b -p plot_cylinder.mcr cylinder.lay 25 | 26 | lib: 27 | $(MAKE) -C $(IBPM_DIR)/build libibpm.a 28 | 29 | clean: 30 | -$(RM) *.out *.x *.plt *.log *.png 31 | 32 | -------------------------------------------------------------------------------- /doc/examples/cylinder.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ibpm.h" 4 | 5 | using namespace std; 6 | using namespace ibpm; 7 | 8 | int main(int argc, char* argv[]) { 9 | // Setup grid 10 | int nx = 100; 11 | int ny = 50; 12 | int ngrid = 3; 13 | double length = 10; 14 | double xOffset = -2; 15 | double yOffset = -2.5; 16 | Grid grid( nx, ny, ngrid, length, xOffset, yOffset ); 17 | 18 | // Make a cylinder, diameter 1, with center at (0,0) 19 | RigidBody cylinder; 20 | cylinder.addCircle( 0, 0, 0.5, grid.Dx() ); 21 | Geometry geom; 22 | geom.addBody(cylinder); 23 | 24 | // Setup equations to solve, with uniform flow U = 1 25 | double magnitude = 1.; 26 | double angle = 0.; 27 | BaseFlow q_potential( grid, magnitude, angle ); 28 | double Reynolds=100; 29 | NavierStokesModel model( grid, geom, Reynolds, q_potential ); 30 | model.init(); 31 | 32 | // Setup timestepper 33 | double dt = 0.05; 34 | NonlinearIBSolver solver( grid, model, dt, Scheme::EULER ); 35 | solver.init(); 36 | 37 | // State variable with zero initial conditions 38 | State x( grid, geom.getNumPoints() ); 39 | x.omega = 0.; 40 | 41 | // Setup output routines 42 | OutputTecplot tecplot( "cyl%03d.plt", "Cylinder, step %03d", false ); 43 | 44 | // Output initial condition 45 | tecplot.doOutput( x ); 46 | 47 | // Step 48 | int numSteps = 10; 49 | for(int i=1; i <= numSteps; ++i) { 50 | cout << "step " << i << endl; 51 | solver.advance( x ); 52 | } 53 | 54 | // Output final state 55 | tecplot.doOutput( x ); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /doc/examples/hello.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) { 4 | std::cout << "Hello world!" << std::endl; 5 | } 6 | -------------------------------------------------------------------------------- /doc/examples/plot_cylinder.mcr: -------------------------------------------------------------------------------- 1 | #!MC 1120 2 | # Created by Tecplot 360 build 11.2-0-563 3 | $!EXPORTSETUP EXPORTFORMAT = PNG 4 | $!EXPORTSETUP IMAGEWIDTH = 600 5 | $!EXPORTSETUP USESUPERSAMPLEANTIALIASING = YES 6 | $!EXPORTSETUP EXPORTFNAME = 'cylinder.png' 7 | $!EXPORT 8 | EXPORTREGION = CURRENTFRAME 9 | -------------------------------------------------------------------------------- /doc/references.bib: -------------------------------------------------------------------------------- 1 | % BibTeX bibliography file 2 | 3 | @Misc{AhuRow-08, 4 | author = {Ahuja, S. and Rowley, C. W.}, 5 | title = {Low-dimensional models for feedback stabilization of unstable steady 6 | states}, 7 | year = {2008}, 8 | month = {January}, 9 | howpublished = {AIAA Paper 2008-553, 46th AIAA Aerospace Sciences Meeting and 10 | Exhibit} 11 | } 12 | 13 | @Article{ColTai-07, 14 | author = {Colonius, T. and Taira, K.}, 15 | title = {A fast immersed boundary method using a nullspace approach and 16 | multi-domain far-field boundary conditions}, 17 | journal = {Comp.\ Meth.\ Appl.\ Mech.\ Eng.}, 18 | year = {2008}, 19 | volume = {197}, 20 | number = {25-28}, 21 | pages = {2131-46} 22 | } 23 | 24 | @Book{Peyret:2002, 25 | author = {Peyret, Roger}, 26 | title = {Spectral Methods for Incompressible Viscous Flow}, 27 | year = {2002}, 28 | series = {Applied Mathematical Sciences}, 29 | volume = {148}, 30 | publisher = {Springer-Verlag} 31 | } 32 | 33 | @Article{TaiCol-06, 34 | author = {Taira, Kunihiko and Colonius, T.}, 35 | title = {The Immersed Boundary Method: A Projection Approach}, 36 | journal = {J.\ Comput.\ Phys.}, 37 | year = {2007}, 38 | month = {August}, 39 | volume = {225}, 40 | number = {2}, 41 | pages = {2118--2137} 42 | } 43 | 44 | -------------------------------------------------------------------------------- /doc/snippets/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for compiling and running snippets 2 | # CWR, 23 Sep 2009 3 | 4 | .PHONY: all clean lib 5 | 6 | output_files := $(patsubst %.cc, %.out, $(wildcard *.cc)) 7 | IBPM_DIR = ../.. 8 | SRC_DIR = $(IBPM_DIR)/src 9 | IBPM_LIB = $(IBPM_DIR)/build/libibpm.a 10 | 11 | include $(IBPM_DIR)/config/make.inc 12 | 13 | all: $(output_files) 14 | 15 | %.out: %.x 16 | ./$< > $@ 17 | 18 | %.o: %.cc 19 | $(CXX) -c -o $@ -I$(SRC_DIR) -x c++ -DSNIPPET_FNAME="\"$<\"" template.cc.tpl 20 | 21 | %.x: %.o 22 | make lib 23 | $(CXX) -o $@ $< $(IBPM_LIB) 24 | 25 | lib: 26 | $(MAKE) -C $(IBPM_DIR)/build libibpm.a 27 | 28 | clean: 29 | -$(RM) *.out *.x 30 | -------------------------------------------------------------------------------- /doc/snippets/hello_snippet.cc: -------------------------------------------------------------------------------- 1 | int i = 7; 2 | std::cout << "Hello world!" << std::endl; 3 | std::cout << "i is " << i << std::endl; -------------------------------------------------------------------------------- /doc/snippets/setup_grid.cc: -------------------------------------------------------------------------------- 1 | int nx = 100; 2 | int ny = 200; 3 | int ngrid = 3; 4 | double length = 10; 5 | double xOffset = -5; 6 | double yOffset = -5; 7 | Grid grid( nx, ny, ngrid, length, xOffset, yOffset ); 8 | cout << "Grid spacing is " << grid.Dx() << endl; 9 | -------------------------------------------------------------------------------- /doc/snippets/template.cc.tpl: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ibpm.h" 3 | 4 | using namespace std; 5 | using namespace ibpm; 6 | 7 | int main(int argc, char *argv[]) { 8 | #include SNIPPET_FNAME 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for examples using IBPM library 2 | # 3 | # Clancy Rowley 4 | # Princeton University 5 | # 6 | # $Date$ 7 | # $Revision$ 8 | # $Author$ 9 | # $HeadURL$ 10 | 11 | include ../config/make.inc 12 | 13 | TARGETS = pitching plunging Oseen RigidBodyLoad bin2plt bininfo 14 | 15 | LDLIBS = -lfftw3 -lm 16 | MAKEDEPEND = gcc -MM 17 | 18 | LDFLAGS += $(lib_dirs) 19 | CXXFLAGS += -I../src $(include_dirs) 20 | 21 | IBPMLIB = libibpm.a 22 | 23 | .PHONY: lib clean depend 24 | 25 | all: $(TARGETS) 26 | 27 | % : %.o lib 28 | $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $< ../build/$(IBPMLIB) $(LDLIBS) 29 | 30 | lib: 31 | cd ../build && $(MAKE) 32 | 33 | %.o : %.cc 34 | $(CXX) $(CXXFLAGS) -c $^ 35 | 36 | % : %.cc 37 | 38 | clean: 39 | -$(RM) -r *.o $(TARGETS) 40 | -$(RM) tecplot/*.plt 41 | 42 | depend: 43 | $(MAKEDEPEND) $(CXXFLAGS) *.cc > .depend 44 | 45 | -include .depend 46 | -------------------------------------------------------------------------------- /examples/RigidBodyLoad.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ibpm.h" 3 | 4 | using namespace ibpm; 5 | using namespace std; 6 | 7 | int main() { 8 | cout << "Type commands to define a RigidBody:" << endl; 9 | RigidBody body; 10 | body.load( cin ); 11 | 12 | int nPoints = body.getNumPoints(); 13 | BoundaryVector pts = body.getPoints(); 14 | cout << "The body [" << body.getName() << "] has " << nPoints << " points:" << endl; 15 | cout << pts; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /examples/bin2plt.cc: -------------------------------------------------------------------------------- 1 | // bin2plt - utility to convert restart files to Tecplot format, for IBPM code 2 | // 3 | // Clancy Rowley 4 | // 6 Sep 2008 5 | // 6 | // $Revision$ 7 | // $LastChangedDate$ 8 | // $LastChangedBy$ 9 | // $HeadURL$ 10 | 11 | #include 12 | #include 13 | #include 14 | #include "ibpm.h" 15 | 16 | using namespace std; 17 | using namespace ibpm; 18 | 19 | string GetBasename( string s ); 20 | 21 | int main(int argc, char *argv[]) { 22 | if (argc < 2) { 23 | cout << "Usage: " << argv[0] << " " << endl; 24 | exit(1); 25 | } 26 | 27 | for (int i=1; i= 0 ) { 54 | s = string( s, slashPosition + 1, s.length() ); 55 | } 56 | int suffixPosition = s.find_last_of( '.' ); 57 | if ( suffixPosition >= 0 ) { 58 | s = string( s, 0, suffixPosition ); 59 | } 60 | return s; 61 | } 62 | -------------------------------------------------------------------------------- /examples/bininfo.cc: -------------------------------------------------------------------------------- 1 | // bininfo - utility for printing header information from a restart file 2 | // 3 | // Clancy Rowley 4 | // 7 Sep 2008 5 | // 6 | // $Revision$ 7 | // $LastChangedDate$ 8 | // $LastChangedBy$ 9 | // $HeadURL$ 10 | 11 | #include 12 | #include "ibpm.h" 13 | 14 | using namespace std; 15 | using namespace ibpm; 16 | 17 | int main(int argc, char *argv[]) { 18 | if (argc != 2) { 19 | cerr << "Usage: " << argv[0] << " " << endl; 20 | } 21 | 22 | State x; 23 | 24 | // Read in a restart file 25 | if ( ! x.load( argv[1] ) ) { 26 | cerr << "Error reading file " << argv[1] << endl; 27 | } 28 | else { 29 | cout << "Timestep " << x.timestep << endl; 30 | cout << "time = " << x.time << endl; 31 | // Write out the Grid information 32 | cout << "nx = " << x.omega.Nx() << endl 33 | << "ny = " << x.omega.Ny() << endl 34 | << "dx = " << x.omega.Dx() << endl 35 | << "x0 = " << x.omega.getXEdge(0,0) << endl 36 | << "y0 = " << x.omega.getYEdge(0,0) << endl 37 | << "numPoints = " << x.f.getNumPoints() << endl; 38 | } 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /examples/cylinder.geom: -------------------------------------------------------------------------------- 1 | # Cylinder, diameter 1, with 160 points 2 | 3 | 4 | body Cylinder 5 | circle_n 0 0 0.5 160 6 | end 7 | -------------------------------------------------------------------------------- /examples/pitching.cc: -------------------------------------------------------------------------------- 1 | // plunging - example of main routine for a pitching flat plate 2 | // 3 | // Clancy Rowley 4 | // 30 Aug 2008 5 | // Princeton University 6 | // 7 | // $Revision$ 8 | // $LastChangedDate$ 9 | // $LastChangedBy$ 10 | // $HeadURL$ 11 | 12 | #include 13 | #include 14 | #include 15 | #include "ibpm.h" 16 | 17 | using namespace std; 18 | using namespace ibpm; 19 | 20 | int main(int argc, char* argv[]) { 21 | cout << "Pitching flat plate example\n"; 22 | 23 | // lift and drag 24 | double lift = 0.; 25 | double drag = 0.; 26 | 27 | // Setup grid 28 | int nx = 100; 29 | int ny = 100; 30 | int ngrid = 1; 31 | double length = 4.0; 32 | double xOffset = -1; 33 | double yOffset = -2; 34 | Grid grid( nx, ny, ngrid, length, xOffset, yOffset ); 35 | 36 | 37 | // Make a flat plate, length 1, with center at 1/4 chord 38 | RigidBody plate; 39 | plate.addLine( 0, 0, 1, 0, grid.Dx() ); 40 | plate.setCenter( 0.25, 0 ); 41 | 42 | // Set the motion to pitching, amplitude = 0.25, period 10 time units 43 | double amplitude = 0.25; 44 | double freq = 0.1; 45 | PitchPlunge motion( amplitude, freq, 0, 0, 0, 0 ); 46 | plate.setMotion( motion ); 47 | Geometry geom; 48 | geom.addBody( plate ); 49 | geom.moveBodies(0); 50 | 51 | // Setup equations to solve 52 | double Reynolds=100; 53 | double magnitude = 1; 54 | double alpha = 0; // angle of background flow 55 | BaseFlow q_potential( grid, magnitude, alpha ); 56 | cout << "Setting up Navier Stokes model..." << flush; 57 | NavierStokesModel model( grid, geom, Reynolds, q_potential ); 58 | model.init(); 59 | cout << "done" << endl; 60 | 61 | // Setup timestepper 62 | double dt = 0.005; 63 | NonlinearIBSolver solver( grid, model, dt, Scheme::AB2 ); 64 | solver.init(); 65 | 66 | // Build the state variable, zero initial conditions 67 | State x(grid, geom.getNumPoints()); 68 | x.omega = 0.; 69 | x.q = 0.; 70 | x.f = 0.; 71 | 72 | // Create output directory, if does not already exist 73 | mkdir( "pitching_out", S_IRWXU | S_IRWXG | S_IRWXO ); 74 | 75 | // Setup output routines 76 | OutputForce force( "pitching_out/force.dat" ); 77 | OutputTecplot tecplot( "pitching_out/pitch%03d.plt", "Pitching plate, step %03d", 1 ); 78 | Logger logger; 79 | // Output Tecplot file every few timesteps 80 | logger.addOutput( &tecplot, 25 ); 81 | logger.addOutput( &force, 1 ); 82 | logger.init(); 83 | logger.doOutput( x ); 84 | 85 | // Step 86 | const double PI = 4. * atan(1.); 87 | int numSteps = 250; 88 | for(int i=1; i <= numSteps; ++i) { 89 | double theta = amplitude * sin( 2 * PI * freq * x.time ); 90 | cout << "step " << setw(4) << i 91 | << " time = " << setw(5) << x.time 92 | << " theta = " << theta << endl; 93 | solver.advance( x ); 94 | x.computeNetForce( drag, lift); 95 | cout << " x force : " << setw(16) << drag*2 << " , y force : " 96 | << setw(16) << lift*2 << "\n"; 97 | logger.doOutput( x ); 98 | } 99 | logger.cleanup(); 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /examples/plunging.cc: -------------------------------------------------------------------------------- 1 | // plunging - example of main routine for a plunging flat plate 2 | // 3 | // Clancy Rowley 4 | // 29 Aug 2008 5 | // Princeton University 6 | // 7 | // $Revision$ 8 | // $LastChangedDate$ 9 | // $LastChangedBy$ 10 | // $HeadURL$ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "ibpm.h" 18 | 19 | using namespace std; 20 | using namespace ibpm; 21 | 22 | int main(int argc, char* argv[]) { 23 | cout << "Plunging flat plate example\n"; 24 | 25 | // lift and drag 26 | double lift = 0.; 27 | double drag = 0.; 28 | 29 | // Setup grid 30 | int nx = 200; 31 | int ny = 200; 32 | int ngrid = 1; 33 | double length = 4.0; 34 | double xOffset = -1; 35 | double yOffset = -2; 36 | Grid grid( nx, ny, ngrid, length, xOffset, yOffset ); 37 | 38 | 39 | // Make a flat plate, length 1, with center at 1/4 chord 40 | RigidBody plate; 41 | plate.addLine( 0, 0, 1, 0, grid.Dx() ); 42 | plate.setCenter( 0.25, 0 ); 43 | 44 | // Set the motion to plunging: amplitude = 0.1, period 0.25 time unit 45 | double amplitude = 0.1; 46 | double freq = 0.25; 47 | PitchPlunge motion( 0, 0, 0, amplitude, freq, 0 ); 48 | plate.setMotion( motion ); 49 | Geometry geom; 50 | geom.addBody( plate ); 51 | geom.moveBodies(0); 52 | 53 | // Setup equations to solve 54 | double Reynolds=100; 55 | double magnitude = 1; 56 | double alpha = 0; // angle of background flow 57 | BaseFlow q_potential( grid, magnitude, alpha ); 58 | cout << "Setting up Navier Stokes model..." << flush; 59 | NavierStokesModel model( grid, geom, Reynolds, q_potential ); 60 | model.init(); 61 | cout << "done" << endl; 62 | 63 | // Setup timestepper 64 | double dt = 0.001; 65 | NonlinearIBSolver solver( grid, model, dt, Scheme::AB2 ); 66 | solver.init(); 67 | 68 | // Build the state variable, zero initial conditions 69 | State x(grid, geom.getNumPoints()); 70 | x.omega = 0.; 71 | x.q = 0.; 72 | x.f = 0.; 73 | 74 | // Create output directory, if does not already exist 75 | mkdir( "plunging_out", S_IRWXU | S_IRWXG | S_IRWXO ); 76 | 77 | // Setup output routines 78 | OutputTecplot tecplot( "plunging_out/plunge%03d.plt", "Plunging plate, step %03d", 1 ); 79 | OutputForce force( "plunging_out/force.dat" ); 80 | Logger logger; 81 | // Output Tecplot file every few timesteps 82 | logger.addOutput( &tecplot, 10 ); 83 | logger.addOutput( &force, 1 ); 84 | logger.init(); 85 | logger.doOutput( x ); 86 | 87 | // Step 88 | const double PI = 4. * atan(1.); 89 | int numSteps = 250; 90 | for(int i=1; i <= numSteps; ++i) { 91 | double y = amplitude * sin( 2 * PI * freq * x.time ); 92 | cout << "step " << setw(4) << i 93 | << " time = " << setw(5) << x.time 94 | << " y = " << y << endl; 95 | solver.advance( x ); 96 | x.computeNetForce(drag, lift); 97 | cout << " x force : " << setw(16) << drag*2 << " , y force : " 98 | << setw(16) << lift*2 << "\n"; 99 | logger.doOutput( x ); 100 | } 101 | logger.cleanup(); 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /ibpm.geom: -------------------------------------------------------------------------------- 1 | # Cylinder, diameter 1, with 314 points 2 | # (to match a test case with Fortran code) 3 | 4 | body Cylinder 5 | circle_n 0 0 0.5 314 6 | end 7 | -------------------------------------------------------------------------------- /src/BC.cc: -------------------------------------------------------------------------------- 1 | // BC.cc 2 | // 3 | // Description: 4 | // Implementation of the BC class 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 28 Sep 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | // Boundary data is stored in a 1d array. 17 | // For an (8 x 4) grid, the data is arranged as follows: 18 | // 19 | // 4 5 6 7 8 9 10 11 12 20 | // 3 13 21 | // 2 14 22 | // 1 15 23 | // 0 23 22 21 20 19 18 17 16 24 | // 25 | // Note that the total number of boundary points is 26 | // (nx+1) * 2 + (ny-1) * 2 = 2 * (nx + ny) 27 | 28 | #include "BC.h" 29 | 30 | namespace ibpm { 31 | 32 | BC::BC( int nx, int ny ) : 33 | _nx( nx ), 34 | _ny( ny ), 35 | _data( 2*(nx+ny) ) 36 | { 37 | _data = 0.; 38 | } 39 | 40 | BC::BC( const BC& bc ) : 41 | _nx( bc._nx ), 42 | _ny( bc._ny ), 43 | _data( 2*(_nx+_ny) ) { 44 | 45 | // copy data 46 | for (unsigned int i=0; i<_data.Size(); ++i) { 47 | _data(i) = bc._data(i); 48 | } 49 | } 50 | 51 | BC::~BC() 52 | {} 53 | 54 | } // namespace ibpm 55 | -------------------------------------------------------------------------------- /src/BC.h: -------------------------------------------------------------------------------- 1 | #ifndef _BC_H_ 2 | #define _BC_H_ 3 | 4 | #include "Array.h" 5 | 6 | namespace ibpm { 7 | 8 | /*! 9 | \file BC.h 10 | \class BC 11 | 12 | \brief Class for storing and accessing boundary conditions for a 2d 13 | scalar field. 14 | 15 | \author Clancy Rowley 16 | \author $LastChangedBy$ 17 | \date 28 Sep 2008 18 | \date $LastChangedDate$ 19 | \version $Revision$ 20 | */ 21 | 22 | // For an (8 x 4) grid, the data is arranged as follows: 23 | // 24 | // 4 5 6 7 8 9 10 11 12 25 | // 3 13 26 | // 2 14 27 | // 1 15 28 | // 0 23 22 21 20 19 18 17 16 29 | 30 | class BC { 31 | public: 32 | /// \brief Constructor: initializes boundary data to zero 33 | /// \param[in] nx number of cells in x-direction 34 | /// \param[in] ny number of cells in y-direction 35 | BC( int nx, int ny ); 36 | BC( const BC& bc ); 37 | ~BC(); 38 | 39 | /// \brief Return reference to value on left boundary, at index j 40 | /// \param[in] j must be from 0..ny 41 | inline double& left( int j ) { 42 | assert( j >= 0 && j <= _ny ); 43 | return _data(j); 44 | } 45 | inline const double& left( int j ) const { 46 | assert( j >= 0 && j <= _ny ); 47 | return _data(j); 48 | } 49 | 50 | /// \brief Return reference to value on right boundary, at index j 51 | /// \param[in] j must be from 0..ny 52 | inline double& right( int j ) { 53 | assert( j >= 0 && j <= _ny ); 54 | return _data( 2 * _ny + _nx - j); 55 | } 56 | inline const double& right( int j ) const { 57 | assert( j >= 0 && j <= _ny ); 58 | return _data( 2 * _ny + _nx - j); 59 | } 60 | 61 | /// \brief Return reference to value on top boundary, at index i 62 | /// \param[in] i must be from 0..nx 63 | inline double& top( int i ) { 64 | assert( i >= 0 && i <= _nx ); 65 | return _data( _ny + i ); 66 | } 67 | inline const double& top( int i ) const { 68 | assert( i >= 0 && i <= _nx ); 69 | return _data( _ny + i ); 70 | } 71 | 72 | /// \brief Return reference to value on bottom boundary, at index i 73 | /// \param[in] j must be from 0..nx 74 | inline double& bottom( int i ) { 75 | assert( i >= 0 && i <= _nx ); 76 | if (i == 0) return _data(0); 77 | else return _data( 2 * (_nx + _ny) - i ); 78 | } 79 | inline const double& bottom( int i ) const { 80 | assert( i >= 0 && i <= _nx ); 81 | if (i == 0) return _data(0); 82 | else return _data( 2 * (_nx + _ny) - i ); 83 | } 84 | 85 | inline BC& operator=(double a) { 86 | _data = a; 87 | return *this; 88 | } 89 | 90 | inline int Nx() const { return _nx; } 91 | inline int Ny() const { return _ny; } 92 | 93 | private: 94 | int _nx; 95 | int _ny; 96 | Array::Array1 _data; 97 | }; 98 | 99 | } // namespace ibpm 100 | 101 | #endif /* _BC_H_ */ 102 | -------------------------------------------------------------------------------- /src/BaseFlow.h: -------------------------------------------------------------------------------- 1 | #ifndef _BASEFLOW_H_ 2 | #define _BASEFLOW_H_ 3 | 4 | #include "Grid.h" 5 | #include "Flux.h" 6 | #include "Scalar.h" 7 | #include "BoundaryVector.h" 8 | #include 9 | 10 | using std::string; 11 | 12 | namespace ibpm { 13 | 14 | class BoundaryVector; 15 | class Motion; 16 | 17 | /*! 18 | \file BaseFlow.h 19 | \class BaseFlow 20 | 21 | \brief Structure for a BaseFlow (flux) that moves with time 22 | 23 | \author Steve Brunton 24 | \author $LastChangedBy: sbrunton $ 25 | \date 7 Jul 2008 26 | \date $LastChangedDate: 2009-11-09 14:58:56 -0500 (Mon, 09 Nov 2009) $ 27 | \version $Revision: 288 $ 28 | */ 29 | 30 | class BaseFlow { 31 | public: 32 | /// Default constructor: do not allocate memory 33 | BaseFlow(); 34 | 35 | /// Initialize without any constant or moving base flow 36 | BaseFlow( const Grid& grid ); 37 | 38 | /// Initialize without any motion 39 | BaseFlow( const Grid& grid, double mag, double alpha); 40 | 41 | /// Initialize without any constant base flow 42 | BaseFlow( const Grid& grid, const Motion& motion ); 43 | 44 | /// Initialize with constant and moving component 45 | BaseFlow( const Grid& grid, double mag, double alpha, const Motion& motion ); 46 | 47 | ~BaseFlow(); 48 | 49 | /// \brief Allocate memory, with the specified Grid and number of 50 | /// boundary points 51 | void resize( const Grid& grid ); 52 | 53 | /// Return true if the body is not moving in time 54 | bool isStationary() const; 55 | 56 | /// Set the evolution of the current BaseFlow (which may be stationary or not) 57 | void setMotion(const Motion& motion); 58 | 59 | /// Set the center of the domain, about which rotations are defined 60 | inline void setCenter(double x, double y) { 61 | _xCenter = x; 62 | _yCenter = y; 63 | } 64 | 65 | /// Get the center of the domain, about which rotations are defined 66 | inline void getCenter(double& x, double& y) const { 67 | x = _xCenter; 68 | y = _yCenter; 69 | } 70 | 71 | /// Get the angle of attack 72 | inline double getAlpha() const { 73 | return _alpha; 74 | } 75 | 76 | /// Get the magnitude of base flow 77 | inline double getMag() const { 78 | return _mag; 79 | } 80 | 81 | /// Determine the magnitude and angle of the base flow, including rigid body motion 82 | void setAlphaMag(double time); 83 | 84 | /// Update the BaseFlow, based on the Motion 85 | void moveFlow(double time); 86 | 87 | /// Set the value of the flux _q 88 | inline void setFlux(Flux& f) { _q = f;}; 89 | 90 | inline void setFlux(double f) { _q = f;}; 91 | 92 | /// Return flux _q 93 | inline const Flux& getFlux() const {return _q;}; 94 | 95 | private: 96 | double _magBF; /// Initial magnitude of base flow 97 | double _alphaBF; /// Initial angle of base flow 98 | double _mag; /// True magnitude of flow, taking into account rigid body motion 99 | double _gamma; /// Flight Path Angle 100 | double _alpha; /// True angle of attack, taking into account rigid body motion 101 | Flux _q; 102 | double _time; 103 | double _xCenter; 104 | double _yCenter; 105 | bool _isStationary; 106 | Motion *_motion; 107 | }; 108 | 109 | 110 | } // namespace ibpm 111 | 112 | #endif /* _BASEFLOW_H_ */ 113 | -------------------------------------------------------------------------------- /src/BoundaryVector.cc: -------------------------------------------------------------------------------- 1 | // BoundaryVector.cc 2 | // 3 | // Description: 4 | // Implementation of the BoundaryVector class, using Blitz++ arrays 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 7 Sep 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "BoundaryVector.h" 17 | 18 | namespace ibpm { 19 | 20 | BoundaryVector::BoundaryVector() {} 21 | 22 | BoundaryVector::BoundaryVector(int numPoints ) { 23 | resize( numPoints ); 24 | } 25 | 26 | /// Allocate a new BoundaryVector, copy the data 27 | BoundaryVector::BoundaryVector(const BoundaryVector& f) { 28 | resize( f._numPoints ); 29 | _data = f._data; 30 | } 31 | 32 | void BoundaryVector::resize( int numPoints ) { 33 | _numPoints = numPoints; 34 | // blitz: _data.resize( _numPoints * XY ); 35 | _data.Deallocate(); 36 | _data.Allocate( _numPoints * XY ); 37 | } 38 | 39 | } // namespace ibpm 40 | -------------------------------------------------------------------------------- /src/CholeskySolver.h: -------------------------------------------------------------------------------- 1 | #ifndef _CHOLESKYSOLVER_H_ 2 | #define _CHOLESKYSOLVER_H_ 3 | 4 | #include "ProjectionSolver.h" 5 | #include "Array.h" 6 | #include 7 | 8 | using Array::array1; 9 | using Array::array2; 10 | 11 | namespace ibpm { 12 | 13 | /*! 14 | \file CholeskySolver.h 15 | \class CholeskySolver 16 | 17 | \brief Subclass of ProjectionSolver, in which the system M f = b is solved 18 | directly, using Cholesky factorization. 19 | 20 | Here M is the matrix 21 | \beta C A^{-1} B 22 | where 23 | A = (1 + \alpha\beta / 2) * Laplacian 24 | 25 | This class assumes the matrix M is symmetric. For now, it computes the 26 | Cholesky factorization when it is instantiated, but this should be changed 27 | to do this explicitly, or load a previously computed factorization from a 28 | file. 29 | 30 | \author Clancy Rowley 31 | \author $LastChangedBy$ 32 | \date 28 Aug 2008 33 | \date $LastChangedDate$ 34 | \version $Revision$ 35 | */ 36 | 37 | class CholeskySolver : public ProjectionSolver { 38 | public: 39 | 40 | CholeskySolver( 41 | const Grid& grid, 42 | const NavierStokesModel& model, 43 | double beta 44 | ); 45 | 46 | ~CholeskySolver(); 47 | 48 | /// \brief Compute the Cholesky decomposition of M 49 | void init(); 50 | 51 | /// \brief Load a Cholesky decomposition from the specified file. 52 | /// Returns true if successful 53 | bool load(const std::string& filename); 54 | 55 | /// \brief Save a Cholesky decomposition to the specified file, 56 | /// overwriting if necessary. 57 | /// Returns true if successful 58 | bool save(const std::string& filename); 59 | 60 | protected: 61 | /// \brief Solve Mf = b for f, using the Cholesky factorization of M. 62 | /// Assumes M is symmetric. 63 | void Minv( 64 | const BoundaryVector& b, 65 | BoundaryVector& x 66 | ); 67 | 68 | private: 69 | int _numPoints; // number of points in the geometry 70 | int _size; // size of the vectors: numPoints * 2 71 | const double _alphaBeta; // keep a local copy of alpha * beta, as a 72 | // check when reading in Cholesky factorizations 73 | // from files 74 | array2 _lower; 75 | array1 _diagonal; 76 | void computeMatrixM( array2& M ); 77 | void computeFactorization( const array2& M ); 78 | bool _hasBeenInitialized; 79 | }; 80 | 81 | } // namespace ibpm 82 | 83 | #endif /* _CHOLESKYSOLVER_H_ */ 84 | -------------------------------------------------------------------------------- /src/ConjugateGradientSolver.cc: -------------------------------------------------------------------------------- 1 | // ConjugateGradientSolver.cc 2 | // 3 | // Description: 4 | // Implementation of the ConjugateGradientSolver class 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 8 Aug 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "NavierStokesModel.h" 17 | #include "ProjectionSolver.h" 18 | #include "ConjugateGradientSolver.h" 19 | 20 | namespace ibpm { 21 | 22 | const int MAX_ITERATIONS = 3000; 23 | 24 | ConjugateGradientSolver::ConjugateGradientSolver( 25 | const Grid& grid, 26 | const NavierStokesModel& model, 27 | double beta, 28 | double tolerance 29 | ) : 30 | ProjectionSolver( grid, model, beta ), 31 | _toleranceSquared(tolerance*tolerance) 32 | {} 33 | 34 | // Implementation of conjugate gradient method 35 | void ConjugateGradientSolver::Minv( 36 | const BoundaryVector& b, 37 | BoundaryVector& x 38 | ) { 39 | double alpha; 40 | double beta; 41 | double delta; 42 | double delta_old; 43 | int numIterations = 0; 44 | 45 | // r = b - M(x) 46 | BoundaryVector r = b; 47 | BoundaryVector q = M(x); 48 | r -= q; 49 | BoundaryVector d = r; 50 | delta = InnerProduct(r,r); 51 | 52 | // while error is greater than tolerance 53 | while ( (delta > _toleranceSquared) && 54 | (numIterations < MAX_ITERATIONS) ) { 55 | // alpha = r^2 / 56 | q = M(d); 57 | alpha = delta / InnerProduct( d, q ); 58 | x += alpha * d; 59 | r -= alpha * q; 60 | delta_old = delta; 61 | delta = InnerProduct( r, r ); 62 | beta = delta / delta_old; 63 | d = r + beta * d; 64 | } 65 | } 66 | 67 | } // namespace ibpm 68 | -------------------------------------------------------------------------------- /src/ConjugateGradientSolver.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONJUGATEGRADIENTSOLVER_H_ 2 | #define _CONJUGATEGRADIENTSOLVER_H_ 3 | 4 | #include 5 | 6 | namespace ibpm { 7 | 8 | class ProjectionSolver; 9 | class NavierStokesModel; 10 | class BoundaryVector; 11 | 12 | /*! 13 | \file ConjugateGradientSolver.h 14 | \class ConjugateGradientSolver 15 | 16 | \brief Subclass of ProjectionSolver, in which the system Mf = b is solved iteratively, using a conjugate gradient method 17 | 18 | This class assumes the matrix M is symmetric, and iterates until a 19 | specified tolerance has been reached. 20 | 21 | \author Clancy Rowley 22 | \author $LastChangedBy$ 23 | \date 9 Aug 2008 24 | \date $LastChangedDate$ 25 | \version $Revision$ 26 | */ 27 | 28 | class ConjugateGradientSolver : public ProjectionSolver { 29 | public: 30 | 31 | /// Constructor. Store the tolerance as private data 32 | ConjugateGradientSolver( 33 | const Grid& grid, 34 | const NavierStokesModel& model, 35 | double beta, 36 | double tolerance 37 | ); 38 | 39 | inline void setTolerance(double tolerance) { 40 | _toleranceSquared = tolerance * tolerance; 41 | } 42 | 43 | inline double getTolerance() { 44 | return sqrt(_toleranceSquared); 45 | } 46 | 47 | protected: 48 | /// \brief Solve Mf = b for f iteratively, using a conjugate-gradient method. 49 | /// Assumes M is symmetric 50 | void Minv( 51 | const BoundaryVector& b, 52 | BoundaryVector& x 53 | ); 54 | 55 | private: 56 | double _toleranceSquared; 57 | }; 58 | 59 | } // namespace ibpm 60 | 61 | #endif /* _CONJUGATEGRADIENTSOLVER_H_ */ 62 | 63 | -------------------------------------------------------------------------------- /src/Direction.h: -------------------------------------------------------------------------------- 1 | #ifndef _DIRECTION_H_ 2 | #define _DIRECTION_H_ 3 | 4 | namespace ibpm { 5 | 6 | /*! 7 | \file Direction.h 8 | 9 | \brief Type for specifying directions of vectors (X or Y) 10 | 11 | \author Clancy Rowley 12 | \author $LastChangedBy$ 13 | \date 27 Jul 2008 14 | \date $LastChangedDate$ 15 | \version $Revision$ 16 | */ 17 | enum Direction {X, Y, XY}; 18 | 19 | /// Postfix operator dir++ 20 | inline Direction operator++(Direction& dir, int) { 21 | return dir = (Direction)(dir + 1); 22 | } 23 | 24 | /// Prefix operator ++dir 25 | inline Direction operator++(Direction& dir) { 26 | return dir = (Direction)(dir + 1); 27 | } 28 | 29 | } // namespace ibpm 30 | 31 | #endif /* _DIRECTION_H_ */ 32 | -------------------------------------------------------------------------------- /src/Eldredge1.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELDREDGE1_H_ 2 | #define _ELDREDGE1_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file Eldredge1.h 12 | \class Eldredge1 13 | 14 | \brief Subclass of Motion, for the canonical maneuver described by Eldredge 15 | 16 | \author Steven Brunton 17 | \author $LastChangedBy: sbrunton $ 18 | \date 26 Apr 2010 19 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 20 | \version $Revision: 132 $ 21 | */ 22 | 23 | class Eldredge1 : public Motion { 24 | public: 25 | 26 | Eldredge1( 27 | double AMP, 28 | double a, 29 | double t1, 30 | double t2, 31 | double t3, 32 | double t4 33 | ) : 34 | _AMP(AMP), 35 | _a(a), 36 | _t1(t1), 37 | _t2(t2), 38 | _t3(t3), 39 | _t4(t4) { 40 | double tt = (_t2+_t3)/2.; 41 | _maxG = log((cosh(_a*(tt-_t1))*cosh(_a*(tt-_t4)))/(cosh(_a*(tt-_t2))*cosh(_a*(tt-_t3)))); 42 | } 43 | 44 | /// Returns transformation for sinusoidal pitch/plunge: 45 | /// (0, 0, theta(t), 0, 0, thetadot(t)) 46 | inline TangentSE2 getTransformation(double time) const { 47 | double t1d = time-_t1; 48 | double t2d = time-_t2; 49 | double t3d = time-_t3; 50 | double t4d = time-_t4; 51 | double G,dGdt; 52 | double Garg = ((cosh(_a*t1d)*cosh(_a*t4d))/(cosh(_a*t2d)*cosh(_a*t3d))); 53 | G = log(Garg); 54 | dGdt = _a*(tanh(_a*t1d)-tanh(_a*t2d)-tanh(_a*t3d)+tanh(_a*t4d)); 55 | 56 | return TangentSE2( 0, G*_AMP/_maxG, 0, 0, dGdt*_AMP/_maxG, 0 ); 57 | } 58 | 59 | inline Motion* clone() const { 60 | return new Eldredge1( 61 | _AMP, 62 | _a, 63 | _t1, 64 | _t2, 65 | _t3, 66 | _t4 67 | ); 68 | }; 69 | 70 | private: 71 | double _AMP; 72 | double _a; 73 | double _t1; 74 | double _t2; 75 | double _t3; 76 | double _t4; 77 | double _maxG; 78 | }; 79 | 80 | } // namespace ibpm 81 | 82 | #endif /* _ELDREDGE1_H_ */ 83 | -------------------------------------------------------------------------------- /src/Eldredge2.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELDREDGE2_H_ 2 | #define _ELDREDGE2_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | 11 | /*! 12 | \file Eldredge2.h 13 | \class Eldredge2 14 | 15 | \brief Subclass of Motion, for the canonical maneuver described by Eldredge 16 | 17 | \author Steven Brunton 18 | \author $LastChangedBy: sbrunton $ 19 | \date 26 Apr 2010 20 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 21 | \version $Revision: 132 $ 22 | */ 23 | 24 | class Eldredge2 : public Motion { 25 | public: 26 | 27 | Eldredge2( 28 | double AMP, 29 | double a, 30 | double t1, 31 | double t2, 32 | double t3, 33 | double t4 34 | ) : 35 | _AMP(AMP), 36 | _a(a), 37 | _t1(t1), 38 | _t2(t2), 39 | _t3(t3), 40 | _t4(t4) { 41 | double tt = (_t2+_t3)/2.; 42 | cout << " got her"<< endl; 43 | _intG = 0.; 44 | _oldtime = 0.; 45 | cout << " not here" << endl; 46 | _maxG = log((cosh(_a*(tt-_t1))*cosh(_a*(tt-_t4)))/(cosh(_a*(tt-_t2))*cosh(_a*(tt-_t3)))); 47 | // _maxG = log((cosh(_a*(tt-t1)))/(cosh(_a*(tt-_t2)))); 48 | } 49 | 50 | /// Returns transformation for sinusoidal pitch/plunge: 51 | /// (0, 0, theta(t), 0, 0, thetadot(t)) 52 | inline TangentSE2 getTransformation(double time) const { 53 | double t1d = time-_t1; 54 | double t2d = time-_t2; 55 | double t3d = time-_t3; 56 | double t4d = time-_t4; 57 | double G,dGdt; 58 | double Garg = ((cosh(_a*t1d)*cosh(_a*t4d))/(cosh(_a*t2d)*cosh(_a*t3d))); 59 | G = log(Garg); 60 | //G = log((cosh(_a*t1d)*cosh(_a*t4d))/(cosh(_a*t2d)*cosh(_a*t3d))); 61 | dGdt = _a*(tanh(_a*t1d)-tanh(_a*t2d)-tanh(_a*t3d)+tanh(_a*t4d)); 62 | 63 | // The following is a hack to compute integral of G so that I can step vertical velocity... 64 | double dtt = time-_oldtime; 65 | _intG = _intG + G*dtt; 66 | _oldtime = time; 67 | cout << "dtt = " << dtt << endl; 68 | cout << "intG = " << _intG << endl; 69 | cout << "G = " << G*_AMP/_maxG << endl; 70 | cout << "intG*stuff = " << _intG*_AMP/_maxG << endl; 71 | return TangentSE2( 0, _intG*_AMP/_maxG, 0, 0, G*_AMP/_maxG, 0 ); 72 | } 73 | 74 | inline Motion* clone() const { 75 | return new Eldredge2( 76 | _AMP, 77 | _a, 78 | _t1, 79 | _t2, 80 | _t3, 81 | _t4 82 | ); 83 | }; 84 | 85 | private: 86 | double _AMP; 87 | double _a; 88 | double _t1; 89 | double _t2; 90 | double _t3; 91 | double _t4; 92 | double _maxG; 93 | mutable double _intG; 94 | mutable double _oldtime; 95 | }; 96 | 97 | } // namespace ibpm 98 | 99 | #endif /* _ELDREDGE2_H_ */ 100 | -------------------------------------------------------------------------------- /src/EldredgeCombined2.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELDREDGECOMBINED2_H_ 2 | #define _ELDREDGECOMBINED2_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | 11 | /*! 12 | \file EldredgeCombined2.h 13 | \class EldredgeCombined2 14 | 15 | \brief Subclass of Motion, for the canonical maneuver described by Eldredge 16 | 17 | \author Steven Brunton 18 | \author $LastChangedBy: sbrunton $ 19 | \date 26 Apr 2010 20 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 21 | \version $Revision: 132 $ 22 | */ 23 | 24 | class EldredgeCombined2 : public Motion { 25 | public: 26 | 27 | EldredgeCombined2( 28 | double AMPa, 29 | double a, 30 | double a1, 31 | double a2, 32 | double a3, 33 | double a4, 34 | double AMPb, 35 | double b, 36 | double b1, 37 | double b2, 38 | double b3, 39 | double b4 40 | ) : 41 | _AMPa(AMPa), 42 | _a(a), 43 | _a1(a1), 44 | _a2(a2), 45 | _a3(a3), 46 | _a4(a4), 47 | _AMPb(AMPb), 48 | _b(b), 49 | _b1(b1), 50 | _b2(b2), 51 | _b3(b3), 52 | _b4(b4) { 53 | // a variables are for plunging, b variables are for pitching 54 | double tta = (_a2+_a3)/2.; 55 | double ttb = (_b2+_b3)/2.; 56 | _intG = 0.; 57 | _oldtime = 0.; 58 | _maxGa = log((cosh(_a*(tta-_a1))*cosh(_a*(tta-_a4)))/(cosh(_a*(tta-_a2))*cosh(_a*(tta-_a3)))); 59 | _maxGb = log((cosh(_b*(ttb-_b1))*cosh(_a*(ttb-_b4)))/(cosh(_b*(ttb-_b2))*cosh(_b*(ttb-_b3)))); 60 | } 61 | 62 | /// Returns transformation for sinusoidal pitch/plunge: 63 | /// (0, h(t), theta(t), 0, hdot(t), thetadot(t)) 64 | inline TangentSE2 getTransformation(double time) const { 65 | double pi = 4. * atan(1.); 66 | double AMPrad = _AMPb*(pi/180); 67 | double a1d = time-_a1; 68 | double a2d = time-_a2; 69 | double a3d = time-_a3; 70 | double a4d = time-_a4; 71 | double b1d = time-_b1; 72 | double b2d = time-_b2; 73 | double b3d = time-_b3; 74 | double b4d = time-_b4; 75 | double Ga,Gb,dGdtb; 76 | double Garga = ((cosh(_a*a1d)*cosh(_a*a4d))/(cosh(_a*a2d)*cosh(_a*a3d))); 77 | double Gargb = ((cosh(_b*b1d)*cosh(_b*b4d))/(cosh(_b*b2d)*cosh(_b*b3d))); 78 | Ga = log(Garga); 79 | Gb = log(Gargb); 80 | dGdtb = _b*(tanh(_b*b1d)-tanh(_b*b2d)-tanh(_b*b3d)+tanh(_b*b4d)); 81 | 82 | // The following is a hack to compute integral of G so that I can step vertical velocity... 83 | double dtt = time-_oldtime; 84 | _intG = _intG + Ga*dtt; 85 | _oldtime = time; 86 | 87 | return TangentSE2( 0, _intG*_AMPa/_maxGa, Gb*AMPrad/_maxGb, 0, Ga*_AMPa/_maxGa, dGdtb*AMPrad/_maxGb ); 88 | } 89 | 90 | inline Motion* clone() const { 91 | return new EldredgeCombined2( 92 | _AMPa, 93 | _a, 94 | _a1, 95 | _a2, 96 | _a3, 97 | _a4, 98 | _AMPb, 99 | _b, 100 | _b1, 101 | _b2, 102 | _b3, 103 | _b4 104 | ); 105 | }; 106 | 107 | private: 108 | double _AMPa; 109 | double _a; 110 | double _a1; 111 | double _a2; 112 | double _a3; 113 | double _a4; 114 | double _AMPb; 115 | double _b; 116 | double _b1; 117 | double _b2; 118 | double _b3; 119 | double _b4; 120 | double _maxGa; 121 | double _maxGb; 122 | mutable double _intG; 123 | mutable double _oldtime; 124 | }; 125 | 126 | } // namespace ibpm 127 | 128 | #endif /* _ELDREDGECOMBINED2_H_ */ 129 | -------------------------------------------------------------------------------- /src/EldredgeManeuver.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELDREDGEMANEUVER_H_ 2 | #define _ELDREDGEMANEUVER_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file EldredgeManeuver.h 12 | \class EldredgeManeuver 13 | 14 | \brief Subclass of Motion, for the canonical maneuver described by Eldredge 15 | 16 | \author Steven Brunton 17 | \author $LastChangedBy: sbrunton $ 18 | \date 26 Apr 2010 19 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 20 | \version $Revision: 132 $ 21 | */ 22 | 23 | class EldredgeManeuver : public Motion { 24 | public: 25 | 26 | /// \brief Define a Motion corresponding to a first-order lag filtered square pulse in dtheta 27 | EldredgeManeuver( 28 | double AMP, 29 | double a, 30 | double t1, 31 | double t2, 32 | double t3, 33 | double t4 34 | ) : 35 | _AMP(AMP), 36 | _a(a), 37 | _t1(t1), 38 | _t2(t2), 39 | _t3(t3), 40 | _t4(t4) { 41 | double tt = (_t2+_t3)/2.; 42 | _maxG = log((cosh(_a*(tt-_t1))*cosh(_a*(tt-_t4)))/(cosh(_a*(tt-_t2))*cosh(_a*(tt-_t3)))); 43 | // _maxG = log((cosh(_a*(tt-t1)))/(cosh(_a*(tt-_t2)))); 44 | } 45 | 46 | /// Returns transformation for sinusoidal pitch/plunge: 47 | /// (0, 0, theta(t), 0, 0, thetadot(t)) 48 | inline TangentSE2 getTransformation(double time) const { 49 | double pi = 4. * atan(1.); 50 | double AMPrad = _AMP*(pi/180); 51 | double t1d = time-_t1; 52 | double t2d = time-_t2; 53 | double t3d = time-_t3; 54 | double t4d = time-_t4; 55 | double G,dGdt; 56 | double Garg = ((cosh(_a*t1d)*cosh(_a*t4d))/(cosh(_a*t2d)*cosh(_a*t3d))); 57 | G = log(Garg); 58 | //G = log((cosh(_a*t1d)*cosh(_a*t4d))/(cosh(_a*t2d)*cosh(_a*t3d))); 59 | dGdt = _a*(tanh(_a*t1d)-tanh(_a*t2d)-tanh(_a*t3d)+tanh(_a*t4d)); 60 | 61 | return TangentSE2( 0, 0, G*AMPrad/_maxG, 0, 0, dGdt*AMPrad/_maxG ); 62 | } 63 | 64 | inline Motion* clone() const { 65 | return new EldredgeManeuver( 66 | _AMP, 67 | _a, 68 | _t1, 69 | _t2, 70 | _t3, 71 | _t4 72 | ); 73 | }; 74 | 75 | private: 76 | double _AMP; 77 | double _a; 78 | double _t1; 79 | double _t2; 80 | double _t3; 81 | double _t4; 82 | double _maxG; 83 | }; 84 | 85 | } // namespace ibpm 86 | 87 | #endif /* _ELDREDGEMANEUVER_H_ */ 88 | -------------------------------------------------------------------------------- /src/EllipticSolver.cc: -------------------------------------------------------------------------------- 1 | // EllipticSolver.cc 2 | // 3 | // Description: 4 | // Implementation of the EllipticSolver class 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 30 Sep 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "EllipticSolver.h" 17 | #include 18 | 19 | 20 | namespace ibpm { 21 | 22 | typedef EllipticSolver2d::Array2d Array2d; 23 | 24 | EllipticSolver::EllipticSolver( const Grid& grid ) : 25 | _ngrid( grid.Ngrid() ), 26 | _dx( grid.Dx() ), 27 | _solvers( grid.Ngrid() ) 28 | {} 29 | 30 | // Deallocate 2d solvers 31 | EllipticSolver::~EllipticSolver() { 32 | for (int lev=0; lev<_ngrid; ++lev) { 33 | delete _solvers[lev]; 34 | } 35 | } 36 | 37 | // Create 2d solvers 38 | void EllipticSolver::init() { 39 | for (int lev=0; lev<_ngrid; ++lev) { 40 | // calculate grid spacing on this grid level 41 | double dx = _dx * ( 1 << lev ); 42 | _solvers[lev] = create2dSolver( dx ); 43 | } 44 | } 45 | 46 | // Multi-domain elliptic solver 47 | void EllipticSolver::solve( const Scalar& f, Scalar& u ) const { 48 | assert( f.Ngrid() == _ngrid ); 49 | assert( f.Ngrid() == u.Ngrid() ); 50 | assert( f.Nx() == u.Nx() ); 51 | assert( f.Ny() == u.Ny() ); 52 | 53 | // First "coarsify" right-hand side (f) to coarse grids 54 | Scalar rhs = f; 55 | rhs.coarsify(); 56 | // Solve coarsest grid first, then finer grids 57 | for (int lev = f.Ngrid() - 1; lev >= 0; --lev ) { 58 | // Get slices of input and output data at current grid level 59 | Array2d rhs1 = rhs[lev]; 60 | Array2d u1 = u[lev]; 61 | // if on the coarsest grid, solve with zero bcs 62 | if (lev == f.Ngrid() - 1) { 63 | _solvers[lev]->solve( rhs1, u1 ); 64 | } 65 | else { 66 | // Get boundary condition from next coarser grid 67 | BC bc(f.Nx(), f.Ny()); 68 | u.getBC( lev, bc ); 69 | // solve with specified boundary conditions 70 | _solvers[lev]->solve( rhs1, bc, u1 ); 71 | } 72 | } 73 | } 74 | 75 | Scalar EllipticSolver::solve( const Scalar& f ) const { 76 | Scalar u( f.getGrid() ); 77 | solve( f, u ); 78 | return u; 79 | } 80 | 81 | /******************************************************************************/ 82 | 83 | PoissonSolver::PoissonSolver( const Grid& grid ) : 84 | EllipticSolver( grid ), 85 | _nx( grid.Nx() ), 86 | _ny( grid.Ny() ) 87 | { 88 | init(); 89 | } 90 | 91 | EllipticSolver2d* PoissonSolver::create2dSolver( double dx ) { 92 | return new PoissonSolver2d( _nx, _ny, dx ); 93 | } 94 | 95 | /******************************************************************************/ 96 | 97 | HelmholtzSolver::HelmholtzSolver( const Grid& grid, double alpha ) : 98 | EllipticSolver( grid ), 99 | _nx( grid.Nx() ), 100 | _ny( grid.Ny() ), 101 | _alpha( alpha ) 102 | { 103 | init(); 104 | } 105 | 106 | EllipticSolver2d* HelmholtzSolver::create2dSolver( double dx ) { 107 | return new HelmholtzSolver2d( _nx, _ny, dx, _alpha ); 108 | } 109 | 110 | } // namespace ibpm 111 | -------------------------------------------------------------------------------- /src/EllipticSolver.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELLIPTICSOLVERMULTI_H_ 2 | #define _ELLIPTICSOLVERMULTI_H_ 3 | 4 | #include "Grid.h" 5 | #include "Scalar.h" 6 | #include "EllipticSolver2d.h" 7 | #include 8 | 9 | using std::vector; 10 | 11 | namespace ibpm { 12 | 13 | /*! 14 | \file EllipticSolver.h 15 | \class EllipticSolver 16 | 17 | \brief Solve Poisson and Helmholtz equations on a multi-domain grid (Scalar) 18 | 19 | \author Clancy Rowley 20 | \author $LastChangedBy$ 21 | \date 30 Sep 2008 22 | \date $LastChangedDate$ 23 | \version $Revision$ 24 | */ 25 | 26 | class EllipticSolver { 27 | public: 28 | EllipticSolver( const Grid& grid ); 29 | virtual ~EllipticSolver() = 0; 30 | 31 | /// \brief Solve L u = f, assuming zero boundary conditions on u 32 | void solve( const Scalar& f, Scalar& u ) const; 33 | /// \brief Convenience form 34 | Scalar solve( const Scalar& f ) const; 35 | protected: 36 | virtual EllipticSolver2d* create2dSolver( double dx ) = 0; 37 | void init(); 38 | private: 39 | int _ngrid; 40 | double _dx; 41 | vector _solvers; 42 | }; 43 | 44 | /******************************************************************************/ 45 | 46 | /*! \class PoissonSolver 47 | 48 | \brief Solve a Poisson equation on a multi-domain grid. 49 | Solves L u = f, with zero boundary conditions on the outer domain of u, 50 | where L is the Laplacian. 51 | */ 52 | class PoissonSolver : public EllipticSolver { 53 | public: 54 | PoissonSolver( const Grid& grid ); 55 | EllipticSolver2d* create2dSolver( double dx ); 56 | private: 57 | int _nx; 58 | int _ny; 59 | }; 60 | 61 | /******************************************************************************/ 62 | 63 | /*! \class HelmholtzSolver 64 | \brief Solve a Helmholtz equation on a multi-domain grid 65 | Solves (1 + alpha * L) u = f, with zero boundary conditions on u, 66 | where L is the Laplacian. 67 | */ 68 | class HelmholtzSolver : public EllipticSolver { 69 | public: 70 | HelmholtzSolver( const Grid& grid, double alpha ); 71 | EllipticSolver2d* create2dSolver( double dx ); 72 | private: 73 | int _nx; 74 | int _ny; 75 | double _alpha; 76 | }; 77 | 78 | } // namespace ibpm 79 | 80 | #endif /* _ELLIPTICSOLVERMULTI_H_ */ 81 | -------------------------------------------------------------------------------- /src/EllipticSolver2d.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELLIPTICSOLVER_H_ 2 | #define _ELLIPTICSOLVER_H_ 3 | 4 | #include "Array.h" 5 | #include "BC.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file EllipticSolver2d.h 12 | \class EllipticSolver2d 13 | 14 | \brief Class for solving Poisson and Helmholtz equations on a uniform grid 15 | 16 | Uses a sin transform, or a nested family of sin transforms. Note that this 17 | is an abstract base class, and cannot be instantiated. 18 | 19 | \author Clancy Rowley 20 | \author $LastChangedBy$ 21 | \date 17 Sep 2008 22 | \date $LastChangedDate$ 23 | \version $Revision$ 24 | */ 25 | 26 | class EllipticSolver2d { 27 | public: 28 | /// Type for arrays used to store 2d scalar fields 29 | typedef Array::Array2 Array2d; 30 | 31 | /// \brief Instantiate a new solver. 32 | /// 33 | /// Here, nx and ny are the number of cells in x- and y-directions, and dx 34 | /// is the grid spacing. 35 | /// Note that the number of gridpoints is (nx+1) x (ny+1), and the number 36 | /// of interior gridpoints is (nx-1) x (ny-1). 37 | EllipticSolver2d( int nx, int ny, double dx ); 38 | virtual ~EllipticSolver2d() = 0; 39 | 40 | /// \brief Solve L u = f, assuming zero boundary conditions on u 41 | /// The 2D arrays f and u must have indices (1..nx-1, 1..ny-1) 42 | void solve( const Array2d& f, Array2d& u ) const; 43 | 44 | /// \brief Solve L u = f, with specified boundary conditions on u. 45 | /// Note that u contains only the interior points of the domain. 46 | /// The 2D arrays f and u must have indices (1..nx-1, 1..ny-1) 47 | /// and the BC object has size (nx,ny) 48 | void solve( const Array2d& f, const BC& bc, Array2d& u ) const; 49 | 50 | protected: 51 | Array2d getLaplacianEigenvalues() const; 52 | virtual void getRHS( const Array2d& f, const BC& bc, Array2d& rhs ) const = 0; 53 | Array2d _eigenvaluesOfInverse; 54 | int _nx; 55 | int _ny; 56 | double _dx; 57 | 58 | private: 59 | void sinTransform( const Array2d& u, Array2d& v ) const; 60 | void sinTransformInv( const Array2d& u, Array2d& v ) const; 61 | fftw_plan _FFTWPlan; 62 | Array2d _fft; 63 | }; 64 | 65 | /******************************************************************************/ 66 | 67 | /*! \class PoissonSolver2d 68 | 69 | \brief Solve a Poisson equation on a uniform grid. 70 | Solves L u = f, with specified boundary conditions on u, where 71 | L is the Laplacian. 72 | */ 73 | class PoissonSolver2d : public EllipticSolver2d { 74 | public: 75 | PoissonSolver2d( int nx, int ny, double dx ); 76 | protected: 77 | // set rhs = f - L * bc 78 | void getRHS( const Array2d& f, const BC& bc, Array2d& rhs ) const; 79 | private: 80 | void calculateEigenvalues(); 81 | }; 82 | 83 | /******************************************************************************/ 84 | 85 | /*! \class HelmholtzSolver2d 86 | \brief Solve a Helmholtz equation on a uniform grid 87 | Solves (1 + alpha * L) u = f, with specified boundary conditions on u, 88 | where L is the Laplacian. 89 | */ 90 | class HelmholtzSolver2d : public EllipticSolver2d { 91 | public: 92 | HelmholtzSolver2d( int nx, int ny, double dx, double alpha ); 93 | protected: 94 | // set rhs = f - alpha * L * bc 95 | void getRHS( const Array2d& f, const BC& bc, Array2d& rhs ) const; 96 | private: 97 | double _alpha; 98 | void calculateEigenvalues(); 99 | }; 100 | 101 | } // namespace ibpm 102 | 103 | #endif /* _ELLIPTICSOLVER_H_ */ 104 | -------------------------------------------------------------------------------- /src/Field.cc: -------------------------------------------------------------------------------- 1 | // Field.cc 2 | // 3 | // Description: 4 | // Implementation of the Field class (base class for Scalar, Flux) 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 6 Sep 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "Grid.h" 17 | #include "Field.h" 18 | 19 | namespace ibpm { 20 | 21 | Field::Field() { 22 | // Note: cannot set nx to zero or computation of dx will divide by zero 23 | // Set to -1 to indicate no grid defined 24 | int nx = -1; 25 | int ny = -1; 26 | int ngrid = 1; 27 | double length = 0; 28 | double xOffset = 0; 29 | double yOffset = 0; 30 | _grid.resize( nx, ny, ngrid, length, xOffset, yOffset ); 31 | } 32 | 33 | Field::Field(const Grid& grid) { 34 | _grid = grid; 35 | } 36 | 37 | Field::Field(const Field& field) { 38 | _grid = field._grid; 39 | } 40 | 41 | Field::~Field() {} 42 | 43 | } // namespace ibpm 44 | -------------------------------------------------------------------------------- /src/Field.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIELD_H_ 2 | #define _FIELD_H_ 3 | 4 | #include "Grid.h" 5 | 6 | namespace ibpm { 7 | 8 | /*! 9 | \file Field.h 10 | \class Field 11 | 12 | \brief Abstract base class for a field defined on a grid. 13 | 14 | For instance, scalar fields (Scalar) and vector fields described by 15 | Flux objects are subclasses of a Field. 16 | 17 | \author Clancy Rowley 18 | \author $LastChangedBy$ 19 | \date 7 Sep 2008 20 | \date $LastChangedDate$ 21 | \version $Revision$ 22 | */ 23 | 24 | class Field { 25 | public: 26 | Field(); 27 | Field( const Grid& grid ); 28 | Field( const Field& field ); 29 | virtual ~Field(); 30 | 31 | inline int Nx() const { return _grid.Nx(); } 32 | inline int NxExt() const { return _grid.NxExt(); } 33 | inline int Ny() const { return _grid.Ny(); } 34 | inline int NyExt() const { return _grid.NyExt(); } 35 | inline int Ngrid() const { return _grid.Ngrid(); } 36 | inline double Dx() const { return _grid.Dx(); } 37 | inline double Dx(int lev) const { return _grid.Dx(lev); } 38 | inline double getXShift() const { return _grid.getXShift(); } 39 | inline double getYShift() const { return _grid.getYShift(); } 40 | inline const Grid& getGrid() const { return _grid; } 41 | inline void setGrid( const Grid& grid ) { _grid = grid; } 42 | 43 | /// Return the x-coordinate of the center of cell i (i in 0..m-1) 44 | inline double getXCenter(int lev, int i) const { 45 | return _grid.getXCenter( lev, i ); 46 | } 47 | 48 | /// Return the y-coordinate of the center of cell j (j in 0..n-1) 49 | inline double getYCenter(int lev, int j) const { 50 | return _grid.getYCenter( lev, j ); 51 | } 52 | 53 | /// Return the x-coordinate of the left edge of cell i (i in 0..m) 54 | inline double getXEdge(int lev, int i) const { 55 | return _grid.getXEdge( lev, i ); 56 | } 57 | 58 | /// Return the y-coordinate of the bottom edge of cell j (j in 0..n) 59 | inline double getYEdge(int lev, int j) const { 60 | return _grid.getYEdge( lev, j ); 61 | } 62 | 63 | private: 64 | Grid _grid; 65 | }; 66 | 67 | } // namespace ibpm 68 | 69 | 70 | #endif /* _FIELD_H_ */ 71 | -------------------------------------------------------------------------------- /src/FixedPosition.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIXEDPOSITION_H_ 2 | #define _FIXEDPOSITION_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | 7 | namespace ibpm { 8 | 9 | /*! 10 | \file FixedPosition.h 11 | \class FixedPosition 12 | 13 | \brief Subclass of Motion, for stationary body 14 | 15 | Specifies the location of the center of the body, and an angle of 16 | rotation about the center 17 | 18 | \author Clancy Rowley 19 | \author $LastChangedBy$ 20 | \date 12 Aug 2008 21 | \date $LastChangedDate$ 22 | \version $Revision$ 23 | */ 24 | 25 | class FixedPosition : public Motion { 26 | public: 27 | 28 | /// Define a Motion corresponding to a fixed position and rotation 29 | /// about the center 30 | FixedPosition( 31 | double x, 32 | double y, 33 | double theta) : 34 | _x(x), 35 | _y(y), 36 | _theta(theta) { 37 | } 38 | 39 | inline bool isStationary() const { return true; } 40 | 41 | /// Returns a fixed transformation for all time: (x,y,theta,0,0,0) 42 | inline TangentSE2 getTransformation(double time) const { 43 | return TangentSE2( _x, _y, _theta, 0, 0, 0 ); 44 | } 45 | 46 | inline Motion* clone() const { 47 | return new FixedPosition( _x, _y, _theta ); 48 | }; 49 | 50 | private: 51 | double _x; 52 | double _y; 53 | double _theta; 54 | }; 55 | 56 | } // namespace ibpm 57 | 58 | #endif /* _FIXEDPOSITION_H_ */ 59 | -------------------------------------------------------------------------------- /src/FixedVelocity.h: -------------------------------------------------------------------------------- 1 | #ifndef _FIXEDVELOCITY_H_ 2 | #define _FIXEDVELOCITY_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file FixedVelocity.h 12 | \class FixedVelocity 13 | 14 | \brief Subclass of Motion, for a constant vertical velocity 15 | 16 | \author Steven Brunton 17 | \author $LastChangedBy: sbrunton $ 18 | \date 26 Apr 2010 19 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 20 | \version $Revision: 132 $ 21 | */ 22 | 23 | class FixedVelocity : public Motion { 24 | public: 25 | 26 | FixedVelocity( 27 | double xdot, 28 | double ydot, 29 | double thetadot 30 | ) : 31 | _xdot(xdot), 32 | _ydot(ydot), 33 | _thetadot(thetadot) { 34 | _intX = 0.; 35 | _intY = 0.; 36 | _intTheta = 0.; 37 | _oldtime = 0.; 38 | } 39 | 40 | /// Returns transformation for sinusoidal pitch/plunge: 41 | /// (0, 0, theta(t), 0, 0, thetadot(t)) 42 | inline TangentSE2 getTransformation(double time) const { 43 | double dtt = time-_oldtime; 44 | if (dtt > 1) dtt = 0.; 45 | _intX = _intX + _xdot*dtt; 46 | _intY = _intY + _ydot*dtt; 47 | _intTheta = _intTheta + _thetadot*dtt; 48 | _oldtime = time; 49 | return TangentSE2( _intX, _intY, _intTheta, _xdot, _ydot, _thetadot ); 50 | } 51 | 52 | inline Motion* clone() const { 53 | return new FixedVelocity( 54 | _xdot, 55 | _ydot, 56 | _thetadot 57 | ); 58 | }; 59 | 60 | private: 61 | double _xdot; 62 | double _ydot; 63 | double _thetadot; 64 | mutable double _intX; 65 | mutable double _intY; 66 | mutable double _intTheta; 67 | mutable double _oldtime; 68 | }; 69 | 70 | } // namespace ibpm 71 | 72 | #endif /* _FIXEDVELOCITY_H_ */ 73 | -------------------------------------------------------------------------------- /src/Flux.cc: -------------------------------------------------------------------------------- 1 | // Flux.cc 2 | // 3 | // Description: 4 | // Implementation of the Flux class, using Blitz++ arrays 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 4 Jul 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "Flux.h" 17 | #include "Scalar.h" 18 | #include "Grid.h" 19 | 20 | using std::cout; 21 | 22 | namespace ibpm { 23 | 24 | Flux::Flux() {} 25 | 26 | Flux::Flux( const Grid& grid ) : 27 | Field( grid ) { 28 | resize( grid ); 29 | } 30 | 31 | /// Allocate new array, copy the data 32 | Flux::Flux( const Flux& q ) : 33 | Field( q ) { 34 | resize( q.getGrid() ); 35 | // copy the data 36 | for (unsigned int i=0; i<_data.Size(); ++i) { 37 | _data(i) = q._data(i); 38 | } 39 | } 40 | 41 | /// Set all parameters and reallocate arrays based on the Grid dimensions 42 | void Flux::resize( const Grid& grid ) { 43 | setGrid( grid ); 44 | int nx = Nx(); 45 | int ny = Ny(); 46 | _numXFluxes = nx * ny + ny; 47 | _numFluxes = 2 * nx * ny + nx + ny; 48 | _data.Deallocate(); 49 | _data.Allocate( Ngrid(), _numFluxes ); 50 | } 51 | 52 | Flux::~Flux() {} // deallocation automatic for Blitz++ arrays 53 | 54 | // Print the X and Y components to standard out (for debugging) 55 | void Flux::print() { 56 | cout << "X:" << endl; 57 | for (int lev=0; lev=0; --j) { 59 | for (int i=0; i<=Nx(); ++i) { 60 | cout << (*this)(lev,X,i,j) << " "; 61 | } 62 | cout << endl; 63 | } 64 | cout << endl; 65 | } 66 | cout << "Y:" << endl; 67 | for (int lev=0; lev=0; --j) { 69 | for (int i=0; i 8 | #include 9 | 10 | using std::string; 11 | using std::vector; 12 | 13 | namespace ibpm { 14 | 15 | class RigidBody; 16 | class Regularizer; 17 | 18 | /*! 19 | \file Geometry.h 20 | \class Geometry 21 | 22 | \brief Create, load, and save geometries composed of RigidBody objects. 23 | 24 | \author Clancy Rowley 25 | \date 3 Jul 2008 26 | 27 | $Revision$ 28 | $LastChangedDate$ 29 | $LastChangedBy$ 30 | $HeadURL$ 31 | */ 32 | 33 | class Geometry { 34 | public: 35 | /// Constructor 36 | Geometry(); 37 | /// Constructor: load the geometry from the specified file 38 | Geometry(string filename); 39 | 40 | /// Destructor 41 | ~Geometry(); 42 | 43 | /// \brief Append the given RigidBody to the list of bodies in the 44 | /// current geometry. 45 | /// Makes a copy of it internally. 46 | void addBody(const RigidBody& body); 47 | 48 | /// \brief Return number of boundary points 49 | int getNumPoints() const; 50 | 51 | /// \brief Return number of bodies 52 | inline int getNumBodies() const { 53 | return _bodies.size(); 54 | } 55 | 56 | /// \brief Return motion from one of the bodies, and clear that motion 57 | /// useful for unsteady baseflow, since we want to initialize baseFlow's motion 58 | /// from the motion in a geometry. We need to get that motion, and then remove it from the 59 | /// rigid body object it came from. 60 | Motion* transferMotion(); 61 | 62 | /// \brief Fill (x,y) with the center of rotation of the first RigidBody 63 | void transferCenter(double &x, double &y); 64 | 65 | /// \brief Return the boundary points in the geometry 66 | BoundaryVector getPoints() const; 67 | 68 | /// \brief Return the velocities of the boundary points 69 | BoundaryVector getVelocities() const; 70 | 71 | /// \brief Return true if the body is not moving; false otherwise 72 | bool isStationary() const; 73 | 74 | /// \brief Move the boundary points and update their velocities 75 | void moveBodies(double time) const; 76 | 77 | /// \brief Load a geometry from the specified input stream. 78 | /// Returns false if invalid input was encountered 79 | /// Input format is as follows: 80 | /// name My Geometry 81 | /// body Flat Plate 82 | /// line 0 0 1 0 0.1 # points on a line, spacing approximately 0.1 83 | /// center 0.25 0 # center at quarter chord 84 | /// motion fixed 0 0 0.3 # 0.3 radians angle of attack 85 | /// end 86 | /// body Large Circle 87 | /// circle 2 3 5 0.1 # Points on a circle 88 | /// # default center is (2,3) 89 | /// end 90 | /// body Airfoil 91 | /// raw naca0012.in # Read in the raw data file 92 | /// end 93 | bool load(istream& in); 94 | 95 | /// \brief Load a geometry from the specified input file 96 | /// Returns true if successful 97 | bool load(string filename); 98 | 99 | private: 100 | vector _bodies; 101 | int _numPoints; 102 | bool _isStationary; 103 | }; 104 | 105 | } // namespace 106 | 107 | #endif /* _GEOMETRY_H_ */ 108 | -------------------------------------------------------------------------------- /src/LagStep1.h: -------------------------------------------------------------------------------- 1 | #ifndef _LAGSTEP1_H_ 2 | #define _LAGSTEP1_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file LagStep1.h 12 | \class LagStep1 13 | 14 | \brief Subclass of Motion, for a First-order lag filtered square pulse in dtheta (with area under pulse equal to AMP) 15 | 16 | \author Steven Brunton 17 | \author $LastChangedBy: sbrunton $ 18 | \date 26 Apr 2010 19 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 20 | \version $Revision: 132 $ 21 | */ 22 | 23 | class LagStep1 : public Motion { 24 | public: 25 | 26 | /// \brief Define a Motion corresponding to a first-order lag filtered square pulse in dtheta 27 | LagStep1( 28 | double AMP, 29 | double PW, 30 | double TAU, 31 | double t0 32 | ) : 33 | _AMP(AMP), 34 | _PW(PW), 35 | _TAU(TAU), 36 | _t0(t0) { 37 | } 38 | 39 | /// Returns transformation for sinusoidal pitch/plunge: 40 | /// (0, 0, theta(t), 0, 0, thetadot(t)) 41 | inline TangentSE2 getTransformation(double time) const { 42 | double pi = 4. * atan(1.); 43 | double AMPrad = _AMP*(pi/180); 44 | double tdiff = time-_t0; 45 | double theta, thetadot; 46 | if(tdiff <= 0) { 47 | theta = 0.; 48 | thetadot = 0.; 49 | } 50 | else if( (tdiff > 0) && (tdiff <= _PW) ) { 51 | theta = tdiff + _TAU*exp(-tdiff/_TAU) - _TAU; 52 | thetadot = 1-exp(-tdiff/_TAU); 53 | } 54 | else if(tdiff > _PW) { 55 | theta = _PW + _TAU*exp(-tdiff/_TAU) - _TAU*exp(-(tdiff-_PW)/_TAU); 56 | thetadot = -1.*exp(-tdiff/_TAU) + exp(-(tdiff-_PW)/_TAU); 57 | } 58 | else { 59 | cerr << "LagStep1 (ERROR): time is not compatible\n"; 60 | exit(1); 61 | } 62 | return TangentSE2( 0, 0, theta*AMPrad/_PW, 0, 0, thetadot*AMPrad/_PW ); 63 | } 64 | 65 | inline Motion* clone() const { 66 | return new LagStep1( 67 | _AMP, 68 | _PW, 69 | _TAU, 70 | _t0 71 | ); 72 | }; 73 | 74 | private: 75 | double _AMP; 76 | double _PW; 77 | double _TAU; 78 | double _t0; 79 | }; 80 | 81 | } // namespace ibpm 82 | 83 | #endif /* _LAGSTEP1_H_ */ 84 | -------------------------------------------------------------------------------- /src/LagStep2.h: -------------------------------------------------------------------------------- 1 | #ifndef _LAGSTEP2_H_ 2 | #define _LAGSTEP2_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file LagStep2.h 12 | \class LagStep2 13 | 14 | \brief Subclass of Motion, for a second-order lag filtered square pulse in dtheta (with area under pulse equal to AMP) 15 | 16 | \author Steven Brunton 17 | \author $LastChangedBy: sbrunton $ 18 | \date 26 Apr 2010 19 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 20 | \version $Revision: 132 $ 21 | */ 22 | 23 | class LagStep2 : public Motion { 24 | public: 25 | 26 | /// \brief Define a Motion corresponding to a second-order lag filtered square pulse in dtheta 27 | LagStep2( 28 | double AMP, 29 | double PW, 30 | double TAU, 31 | double t0 32 | ) : 33 | _AMP(AMP), 34 | _PW(PW), 35 | _TAU(TAU), 36 | _t0(t0) { 37 | } 38 | 39 | /// Returns transformation for sinusoidal pitch/plunge: 40 | /// (0, 0, theta(t), 0, 0, thetadot(t)) 41 | inline TangentSE2 getTransformation(double time) const { 42 | double pi = 4. * atan(1.); 43 | double AMPrad = _AMP*(pi/180); 44 | double tdiff = time-_t0; 45 | double theta, thetadot; 46 | if(tdiff <= 0) { 47 | theta = 0.; 48 | thetadot = 0.; 49 | } 50 | else if( (tdiff > 0) && (tdiff <= _PW) ) { 51 | theta = tdiff + (2*_TAU+tdiff)*exp(-tdiff/_TAU) - 2*_TAU; 52 | thetadot = 1.-(1.+tdiff/_TAU)*exp(-tdiff/_TAU); 53 | } 54 | else if(tdiff > _PW) { 55 | theta = _PW + (2*_TAU+tdiff)*exp(-tdiff/_TAU) + (_PW-2*_TAU)*exp(-(tdiff-_PW)/_TAU) - tdiff*exp(-(tdiff-_PW)/_TAU); 56 | thetadot = -(1.+tdiff/_TAU)*exp(-tdiff/_TAU) + (1.+(tdiff-_PW)/_TAU)*exp(-(tdiff-_PW)/_TAU); 57 | } 58 | else { 59 | cerr << "LagStep2 (ERROR): time is not compatible\n"; 60 | exit(1); 61 | } 62 | return TangentSE2( 0, 0, theta*AMPrad/_PW, 0, 0, thetadot*AMPrad/_PW ); 63 | } 64 | 65 | inline Motion* clone() const { 66 | return new LagStep2( 67 | _AMP, 68 | _PW, 69 | _TAU, 70 | _t0 71 | ); 72 | }; 73 | 74 | private: 75 | double _AMP; 76 | double _PW; 77 | double _TAU; 78 | double _t0; 79 | }; 80 | 81 | } // namespace ibpm 82 | 83 | #endif /* _LAGSTEP2_H_ */ 84 | -------------------------------------------------------------------------------- /src/Logger.cc: -------------------------------------------------------------------------------- 1 | // Logger.cc 2 | // 3 | // Description: 4 | // Implementation of Logger class for calling output routines 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 22 Aug 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include 17 | #include 18 | #include "Output.h" 19 | #include "BaseFlow.h" 20 | #include "State.h" 21 | #include "Logger.h" 22 | 23 | 24 | namespace ibpm { 25 | 26 | #define LOOP_OVER_ALL_OUTPUTS( a ) \ 27 | vector::iterator entry; \ 28 | bool successful = true; \ 29 | for (entry = _outputs.begin(); entry != _outputs.end(); ++entry) { \ 30 | bool result = (entry->output)->a; \ 31 | successful = successful && result; \ 32 | } \ 33 | return successful; 34 | 35 | 36 | Logger::Logger() { 37 | _hasBeenInitialized = false; 38 | } 39 | 40 | void Logger::addOutput(Output* output, int numSkip) { 41 | Entry entry; 42 | entry.output = output; 43 | entry.numSkip = numSkip; 44 | _outputs.push_back(entry); 45 | } 46 | 47 | /// \brief Call all output routines needed at the current timestep,. 48 | bool Logger::doOutput(const State& x) { 49 | assert( _hasBeenInitialized ); 50 | vector::iterator entry; 51 | bool successful = true; 52 | for (entry = _outputs.begin(); entry != _outputs.end(); ++entry) { 53 | if ( entry->shouldBeCalled( x ) ) { 54 | bool result = (entry->output)->doOutput( x ); 55 | successful = successful && result; 56 | } 57 | } 58 | return successful; 59 | } 60 | 61 | /// \brief Call all output routines needed at the current timestep, using baseflow. 62 | bool Logger::doOutput(const BaseFlow& q, const State& x) { 63 | assert( _hasBeenInitialized ); 64 | vector::iterator entry; 65 | bool successful = true; 66 | for (entry = _outputs.begin(); entry != _outputs.end(); ++entry) { 67 | if ( entry->shouldBeCalled( x ) ) { 68 | bool result = (entry->output)->doOutput( q , x ); 69 | successful = successful && result; 70 | } 71 | } 72 | return successful; 73 | } 74 | 75 | // Initialize all of the output routines. 76 | bool Logger::init() { 77 | _hasBeenInitialized = true; 78 | LOOP_OVER_ALL_OUTPUTS( init() ); 79 | } 80 | 81 | /// Clean up all of the output routines. 82 | bool Logger::cleanup() { 83 | assert( _hasBeenInitialized ); 84 | LOOP_OVER_ALL_OUTPUTS( cleanup() ); 85 | } 86 | 87 | #undef LOOP_OVER_ALL_OUTPUTS 88 | 89 | } // namespace 90 | -------------------------------------------------------------------------------- /src/Logger.h: -------------------------------------------------------------------------------- 1 | #ifndef _LOGGER_H_ 2 | #define _LOGGER_H_ 3 | 4 | #include "BaseFlow.h" 5 | #include "State.h" 6 | #include 7 | 8 | using std::vector; 9 | 10 | namespace ibpm { 11 | 12 | class Output; 13 | 14 | /*! 15 | \file Logger.h 16 | \class Logger 17 | 18 | \brief Maintain a list of output routines, and call them when specified. 19 | 20 | \author Clancy Rowley 21 | \date 21 Aug 2008 22 | 23 | \author $LastChangedBy$ 24 | \date $LastChangedDate$ 25 | \version $Revision$ 26 | */ 27 | 28 | class Logger { 29 | public: 30 | Logger(); 31 | 32 | /// \brief Add the specified Output to the list of output routines. 33 | /// The caller is responsible for allocating and deallocating memory for 34 | /// Output. 35 | /// \param[in] output is a pointer to the output routine to add. 36 | /// \param[in] numSkip specifies how often to call the given routine 37 | /// (number of timesteps). 38 | void addOutput(Output* output, int numSkip); 39 | 40 | /// \brief Call all output routines needed at the current timestep. 41 | bool doOutput(const State& x); 42 | 43 | /// \brief Call all output routines needed at the current timestep, making use of baseflow. 44 | bool doOutput(const BaseFlow& q, const State& x); 45 | 46 | /// \brief Initialize all of the output routines. 47 | bool init(); 48 | 49 | /// \brief Clean up all of the output routines. 50 | bool cleanup(); 51 | 52 | private: 53 | struct Entry { 54 | Output* output; 55 | int numSkip; 56 | inline bool shouldBeCalled(const State& x) { 57 | return (x.timestep % numSkip == 0); 58 | } 59 | }; 60 | vector _outputs; 61 | bool _hasBeenInitialized; 62 | }; 63 | 64 | #undef LOOP_OVER_ALL_OUTPUTS 65 | 66 | } // namespace ibpm 67 | 68 | #endif /* _LOGGER_H_ */ 69 | -------------------------------------------------------------------------------- /src/Motion.h: -------------------------------------------------------------------------------- 1 | #ifndef _MOTION_H_ 2 | #define _MOTION_H_ 3 | 4 | namespace ibpm { 5 | 6 | class TangentSE2; 7 | 8 | /*! 9 | \file Motion.h 10 | \class Motion 11 | 12 | \brief Specify a position and orientation as a function of time 13 | 14 | Abstract base class: must be subclassed to be instantiated 15 | 16 | \author Clancy Rowley 17 | \author $LastChangedBy$ 18 | \date 12 Aug 2008 19 | \date $LastChangedDate$ 20 | \version $Revision$ 21 | */ 22 | 23 | class Motion { 24 | public: 25 | virtual ~Motion() {}; 26 | 27 | /// True if the body is moving (default is False) 28 | virtual bool isStationary() const { return false; } 29 | 30 | /// Return a Euclidean transformation and its velocity 31 | /// (an element of TSE(2) at the specified time 32 | virtual TangentSE2 getTransformation(double time) const = 0; 33 | 34 | /// Return a pointer to a new copy: subclasses must overload 35 | virtual Motion* clone() const = 0; 36 | }; 37 | 38 | } // namespace 39 | 40 | #endif /* _MOTION_H_ */ 41 | -------------------------------------------------------------------------------- /src/MotionFile.h: -------------------------------------------------------------------------------- 1 | #ifndef _MOTIONFILE_H_ 2 | #define _MOTIONFILE_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "utils.h" 14 | 15 | using std::ifstream; 16 | 17 | 18 | namespace ibpm { 19 | 20 | // Defining a struct for storing (t,x,y,theta), which I call TxTSE2 21 | struct TxTSE2 { 22 | TxTSE2(double t_in, double x_in, double y_in, double theta_in, double dx_in, double dy_in, double dtheta_in) { 23 | t = t_in; 24 | x = x_in; 25 | y = y_in; 26 | theta = theta_in; 27 | dx = dx_in; 28 | dy = dy_in; 29 | dtheta = dtheta_in; 30 | } 31 | double t; 32 | double x; 33 | double y; 34 | double theta; 35 | double dx; 36 | double dy; 37 | double dtheta; 38 | }; 39 | 40 | /*! 41 | \file MotionFile.h 42 | \class MotionFile 43 | 44 | \brief Subclass of Motion, for a motions defined in a file 45 | 46 | \author Steven Brunton 47 | \author $LastChangedBy: sbrunton $ 48 | \date 26 Apr 2010 49 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 50 | \version $Revision: 132 $ 51 | */ 52 | 53 | class MotionFile : public Motion { 54 | public: 55 | 56 | /// \brief Define a Motion corresponding to data specified in a file 57 | MotionFile( 58 | string filename 59 | ) : 60 | _filename(filename) { 61 | ifstream in( filename.c_str() ); 62 | int n; 63 | double t,x,y,theta,dx,dy,dtheta; 64 | double tlast = -1.e+5; 65 | in >> n; 66 | if( in.fail() ) { 67 | cerr << "ERROR:: MotionFile: file " << filename <<" formatted incorrectly! (err1)" << endl; 68 | } 69 | for(int i=0; i> t >> x >> y >> theta >> dx >> dy >> dtheta; 71 | if( in.fail() ) { 72 | cerr << "ERROR:: MotionFile: file " << filename << " formatted incorrectly! (err2)" << endl; 73 | } 74 | if( t=_data[i].t) && (time<_data[i+1].t) ) index = i; 96 | } 97 | double xo = 0.; 98 | double yo = 0.; 99 | double thetao = 0.; 100 | double dxo = 0.; 101 | double dyo = 0.; 102 | double dthetao = 0.; 103 | double alpha=0.; 104 | double tdiff=0.; 105 | if( index != -1 ) { 106 | tdiff = _data[index+1].t-_data[index].t; 107 | alpha = (time-_data[index].t)/tdiff; 108 | xo = alpha*_data[index+1].x+(1-alpha)*_data[index].x; 109 | yo = alpha*_data[index+1].y+(1-alpha)*_data[index].y; 110 | thetao = alpha*_data[index+1].theta+(1-alpha)*_data[index].theta; 111 | dxo = alpha*_data[index+1].dx+(1-alpha)*_data[index].dx; 112 | dyo = alpha*_data[index+1].dy+(1-alpha)*_data[index].dy; 113 | dthetao = alpha*_data[index+1].dtheta+(1-alpha)*_data[index].dtheta; 114 | } 115 | return TangentSE2( xo, yo, thetao, dxo, dyo, dthetao ); 116 | } 117 | 118 | inline Motion* clone() const { 119 | return new MotionFile( 120 | _filename 121 | ); 122 | }; 123 | 124 | private: 125 | string _filename; 126 | vector _data; 127 | }; 128 | } // namespace ibpm 129 | 130 | #endif /* _MOTIONFILE_H_ */ 131 | -------------------------------------------------------------------------------- /src/NavierStokesModel.h: -------------------------------------------------------------------------------- 1 | #ifndef _NAVIERSTOKES_H_ 2 | #define _NAVIERSTOKES_H_ 3 | 4 | #include "Grid.h" 5 | #include "Geometry.h" 6 | #include "Scalar.h" 7 | #include "Flux.h" 8 | #include "BaseFlow.h" 9 | #include "BoundaryVector.h" 10 | #include "State.h" 11 | #include "VectorOperations.h" 12 | #include "Regularizer.h" 13 | #include "EllipticSolver.h" 14 | #include 15 | 16 | namespace ibpm { 17 | 18 | /*! 19 | \file NavierStokesModel.h 20 | \class NavierStokesModel 21 | 22 | \brief Define operators for the Navier-Stokes equations 23 | 24 | Note: This is an abstract base class, and may not be instantiated directly 25 | 26 | \author Clancy Rowley 27 | \date 3 Jul 2008 28 | 29 | $Revision$ 30 | $LastChangedDate$ 31 | $LastChangedBy$ 32 | $HeadURL$ 33 | */ 34 | 35 | class NavierStokesModel { 36 | public: 37 | /*! \brief Constructor, given a specified grid, geometry, 38 | and potential flow flux 39 | */ 40 | NavierStokesModel( 41 | const Grid& grid, 42 | const Geometry& geometry, 43 | double Reynolds, 44 | const BaseFlow& q_potential 45 | ); 46 | 47 | /// \brief Constructor, assuming potential flow part is zero 48 | NavierStokesModel( 49 | const Grid& grid, 50 | const Geometry& geometry, 51 | double Reynolds 52 | ); 53 | 54 | ~NavierStokesModel(); 55 | 56 | /// Perform initial calculations needed to use model 57 | void init(); 58 | 59 | /// \brief Return true if the geometry has moving bodies 60 | bool isTimeDependent() const; 61 | bool geTimeDependent() const; // geometry TD? 62 | bool bfTimeDependent() const; // baseflow TD? 63 | 64 | 65 | /// \brief Return the number of points in the geometry 66 | int getNumPoints() const; 67 | 68 | /// \brief Return the right-hand side b of the constraint equations. 69 | /// Here, this is the velocity of the bodies minus the base flow velocity 70 | BoundaryVector getConstraints() const; 71 | 72 | /// \brief Update operators, for time-dependent models 73 | void updateOperators( double time ); 74 | 75 | // /// Return a pointer to the associated Geometry 76 | // inline const Geometry& getGeometry() const { return _geometry; } 77 | // 78 | /// Return a pointer to the associated Grid 79 | inline const Grid& getGrid() const { return _grid; } 80 | 81 | /// Compute omega = B(f) as in (14) 82 | void B(const BoundaryVector& f, Scalar& omega ) const; 83 | 84 | /// Compute f = C(omega) as in (14) 85 | void C(const Scalar& omega, BoundaryVector& f) const; 86 | 87 | /// \brief Return the constant alpha = 1/ReynoldsNumber 88 | double getAlpha() const; 89 | 90 | /// Return the angle of attack of the baseflow 91 | inline double getAlphaBF() const { return _baseFlow.getAlpha(); } 92 | 93 | /// Compute flux q from vorticity omega, including base flow q0 94 | void computeFlux(const Scalar& omega, Flux& q ) const; 95 | 96 | /// \brief Compute flux q from the vorticity omega, including base flow 97 | void refreshState( State& x ) const; 98 | 99 | /*! \brief Given the vorticity omega, return the streamfunction psi. 100 | 101 | Assumes psi = 0 on the boundary, and does not add in potential flow solution 102 | */ 103 | Scalar vorticityToStreamfunction(const Scalar& omega) const; 104 | 105 | /// Return the BaseFlow 106 | inline const BaseFlow& getBaseFlow() const { return _baseFlow; } 107 | 108 | private: 109 | // Perhaps copy constructor should be made private to prevent future memory deallocation errors 110 | 111 | BoundaryVector getBaseFlowBoundaryVelocities() const; 112 | void computeFluxWithoutBaseFlow(const Scalar& omega, Flux& q ) const; 113 | 114 | // data 115 | const Grid& _grid; 116 | const Geometry& _geometry; 117 | Regularizer _regularizer; 118 | BaseFlow _baseFlow; 119 | double _ReynoldsNumber; 120 | PoissonSolver _poisson; 121 | bool _hasBeenInitialized; 122 | }; 123 | 124 | } // namespace ibpm 125 | 126 | #endif /* _NAVIERSTOKES_H_ */ 127 | -------------------------------------------------------------------------------- /src/Output.h: -------------------------------------------------------------------------------- 1 | #ifndef _OUTPUT_H_ 2 | #define _OUTPUT_H_ 3 | 4 | namespace ibpm { 5 | 6 | class BaseFlow; 7 | class State; 8 | 9 | /*! 10 | \file Output.h 11 | \class Output 12 | 13 | \brief Abstract base class for output routines. 14 | 15 | Subclasses provide a callback routine for writing output in various forms. 16 | 17 | \author Clancy Rowley 18 | \author $LastChangedBy$ 19 | \date 21 Aug 2008 20 | \date $LastChangedDate$ 21 | \version $Revision$ 22 | */ 23 | class Output { 24 | public: 25 | virtual ~Output() {} 26 | 27 | /// \brief Provide initialization, if needed (e.g. opening a file). 28 | /// Returns true if successful 29 | virtual bool init() { return true; } 30 | 31 | /// \brief Clean up, if needed (e.g. close a file) 32 | /// Returns true if successful 33 | virtual bool cleanup() { return false; } 34 | 35 | /// \brief Callback for performing the actual output from a state object. 36 | /// Returns true if successful; otherwise false. 37 | /// Pure virtual: must be defined by subclasses. 38 | virtual bool doOutput(const State& x) = 0; 39 | 40 | /// \brief Callback for performing the actual output from a state and a baseflow object. 41 | /// Returns true if successful; otherwise false. 42 | /// Pure virtual: must be defined by subclasses. 43 | virtual bool doOutput(const BaseFlow& q, const State& x) = 0; 44 | 45 | }; 46 | 47 | } // namespace ibpm 48 | 49 | #endif /* _OUTPUT_H_ */ 50 | -------------------------------------------------------------------------------- /src/OutputEnergy.cc: -------------------------------------------------------------------------------- 1 | #include "OutputEnergy.h" 2 | #include "State.h" 3 | #include "Output.h" 4 | #include "VectorOperations.h" 5 | #include 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | OutputEnergy::OutputEnergy(string filename) : 11 | _filename( filename ) 12 | {} 13 | 14 | bool OutputEnergy::init() { 15 | _fp = fopen( _filename.c_str(), "w" ); 16 | if ( _fp == NULL ) return false; 17 | else return true; 18 | } 19 | 20 | bool OutputEnergy::cleanup() { 21 | bool status = true; 22 | if ( _fp != NULL ) { 23 | status = fclose( _fp ); 24 | } 25 | return status; 26 | } 27 | 28 | bool OutputEnergy::doOutput(const State& x) { 29 | double energy = 0.; 30 | energy = .5 * InnerProduct( x.q, x.q ); 31 | 32 | if ( _fp == NULL ) return false; 33 | fprintf( _fp, "%5d %.5e %.5e\n", x.timestep, x.time, energy ); 34 | fflush( _fp ); 35 | return true; 36 | } 37 | 38 | bool OutputEnergy::doOutput(const BaseFlow & q, const State& x) { 39 | // Currently no use for baseflow, but this method is defined for future 40 | // flexibility 41 | return doOutput(x); 42 | } 43 | 44 | } // namespace ibpm 45 | -------------------------------------------------------------------------------- /src/OutputEnergy.h: -------------------------------------------------------------------------------- 1 | #ifndef _OUTPUTENERGY_H_ 2 | #define _OUTPUTENERGY_H_ 3 | 4 | #include "Output.h" 5 | #include 6 | #include 7 | using std::string; 8 | 9 | namespace ibpm { 10 | 11 | class OutputEnergy : public Output { 12 | public: 13 | /// \brief Constructor 14 | /// \param[in] filename to which force data will be written. 15 | OutputEnergy(string filename); 16 | 17 | /// \brief Open the file for writing. 18 | /// If a file with the same name is already present, it is overwritten. 19 | /// Returns true if successful. 20 | bool init(); 21 | 22 | /// \brief Close the file. 23 | /// Returns true if successful 24 | bool cleanup(); 25 | 26 | /// \brief Write data to the energy file. 27 | bool doOutput(const State& x); 28 | 29 | /// \brief Write data to the energy file, making use of the baseflow. 30 | bool doOutput(const BaseFlow& q, const State& x); 31 | 32 | private: 33 | string _filename; 34 | FILE* _fp; 35 | }; 36 | 37 | } // namespace ibpm 38 | 39 | #endif /* _OUTPUTENERGY_H_ */ 40 | -------------------------------------------------------------------------------- /src/OutputForce.cc: -------------------------------------------------------------------------------- 1 | // OutputForce.cc 2 | // 3 | // Description: 4 | // Implementation of output routine for writing a list of force coefficients. 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // Steve Brunton 9 | // 10 | // Date: 22 Aug 2008 11 | // 12 | // $Revision$ 13 | // $LastChangedDate$ 14 | // $LastChangedBy$ 15 | // $HeadURL$ 16 | 17 | #include "OutputForce.h" 18 | #include "BaseFlow.h" 19 | #include "State.h" 20 | #include "Output.h" 21 | #include "VectorOperations.h" 22 | #include 23 | #include 24 | 25 | namespace ibpm { 26 | 27 | OutputForce::OutputForce(string filename) : 28 | _filename( filename ) 29 | {} 30 | 31 | bool OutputForce::init() { 32 | _fp = fopen( _filename.c_str(), "w" ); 33 | if ( _fp == NULL ) return false; 34 | else return true; 35 | } 36 | 37 | bool OutputForce::cleanup() { 38 | bool status = true; 39 | if ( _fp != NULL ) { 40 | status = fclose( _fp ); 41 | } 42 | return status; 43 | } 44 | 45 | // Method to compute lift, drag from state (x), angle of attack (alpha), and freestream velocity (mag) 46 | bool OutputForce::doOutput( const double alpha, const double mag, const State& x) { 47 | double xF, yF; // force in x and y direction in domain 48 | double drag, lift; // actual drag and lift, wrt alpha 49 | x.computeNetForce( xF, yF ); 50 | drag = xF * cos(alpha) + yF * sin(alpha); 51 | lift = xF * -1.*sin(alpha) + yF * cos(alpha); 52 | 53 | // Convert forces to lift and drag coefficients: 54 | // If L_d is dimensional lift, then in the nondimensionalization of the 55 | // code (lengths by c, density by rho, velocity by U), we have 56 | // L = L_d / (c rho U^2) 57 | // so 58 | // C_L = L_d / (1/2 rho U^2) 59 | // = 2 L 60 | drag *= 2.; 61 | lift *= 2.; 62 | 63 | if ( _fp == NULL ) return false; 64 | fprintf( _fp, "%5d %.5e %.5e %.5e\n", x.timestep, x.time, drag, lift ); 65 | fflush( _fp ); 66 | 67 | return true; 68 | } 69 | 70 | // If no other information is provided, assume zero angle of attack, unity freestrem velocity 71 | bool OutputForce::doOutput(const State& x) { 72 | double alpha = 0.; 73 | double mag = 1.; 74 | 75 | return doOutput(alpha, mag, x); 76 | } 77 | 78 | bool OutputForce::doOutput( const BaseFlow& q, const State& x) { 79 | double alpha = q.getAlpha(); 80 | double mag = q.getMag(); 81 | 82 | return doOutput(alpha, mag, x); 83 | } 84 | 85 | 86 | } // namespace ibpm 87 | -------------------------------------------------------------------------------- /src/OutputForce.h: -------------------------------------------------------------------------------- 1 | #ifndef _OUTPUTFORCE_H_ 2 | #define _OUTPUTFORCE_H_ 3 | 4 | #include "Output.h" 5 | #include 6 | #include 7 | using std::string; 8 | 9 | namespace ibpm { 10 | 11 | /*! 12 | \file OutputForce.h 13 | \class OutputForce 14 | 15 | \brief Output routine for writing a list of force coefficients. 16 | 17 | \author Steve Brunton 18 | \author Clancy Rowley 19 | \date 21 Aug 2008 20 | 21 | \author $LastChangedBy$ 22 | \date $LastChangedDate$ 23 | \version $Revision$ 24 | */ 25 | 26 | class OutputForce : public Output { 27 | public: 28 | /// \brief Constructor 29 | /// \param[in] filename to which force data will be written. 30 | OutputForce(string filename); 31 | 32 | /// \brief Open the file for writing. 33 | /// If a file with the same name is already present, it is overwritten. 34 | /// Returns true if successful. 35 | bool init(); 36 | 37 | /// \brief Close the file. 38 | /// Returns true if successful 39 | bool cleanup(); 40 | 41 | /// \brief Write data to the force file from a state object, angle of attack, and freestream velocity. 42 | bool doOutput(const double alpha, const double mag, const State& x); 43 | 44 | /// \brief Write data to the force file, making use of baseflow. 45 | bool doOutput(const BaseFlow& q, const State& x); 46 | 47 | /// \brief Write data to the force file. 48 | bool doOutput(const State& x); 49 | 50 | 51 | private: 52 | string _filename; 53 | FILE* _fp; 54 | }; 55 | 56 | } // namespace ibpm 57 | 58 | #endif /* _OUTPUTFORCE_H_ */ 59 | -------------------------------------------------------------------------------- /src/OutputProbes.h: -------------------------------------------------------------------------------- 1 | #ifndef _OUTPUTPROBES_H_ 2 | #define _OUTPUTPROBES_H_ 3 | 4 | #include "Output.h" 5 | #include "Grid.h" 6 | #include "Array.h" 7 | #include 8 | #include 9 | 10 | using std::string; 11 | using std::vector; 12 | 13 | namespace ibpm { 14 | 15 | /*! 16 | \file OutputProbes.h 17 | \class OutputProbes 18 | 19 | \brief Write velocities, fluxes, and vorticity, at given probe locations, to files. 20 | 21 | Each probe has a corresponding output file. 22 | 23 | All probes are supposed to be located at the interior nodes 24 | at the finest grid level (level 0). 25 | 26 | Probes are labelled as Probe 1, 2, ... . 27 | 28 | Probe information (probe #, position) is stored in a separate file. 29 | 30 | \author Clancy Rowley 31 | \author Zhanhua Ma 32 | \date 11 May 2009 33 | 34 | */ 35 | 36 | class OutputProbes : public Output { 37 | public: 38 | /// \brief Constructor 39 | /// \param[in] filename, to which probe data will be written. 40 | /// For instance, if filename = "out/probe%02.dat" 41 | /// then the following files will be created: 42 | /// out/probe00.dat (description of probe locations) 43 | /// out/probe01.dat (first probe) 44 | /// out/probe02.dat (second probe) 45 | /// ... 46 | OutputProbes(string filename, Grid& grid); 47 | 48 | /// Write a file with description of probe locations 49 | /// (this file has index 0) 50 | /// Also, open a file for each probe 51 | /// If a file with the same name is already present, it is overwritten. 52 | /// Returns true if successful. 53 | bool init(); 54 | 55 | /// \brief Close all the files. 56 | /// Returns true if successful 57 | bool cleanup(); 58 | 59 | /// Write velocities u, v, fluxes q.x, q,y and vorticity omega for each probe, 60 | /// to the correpsonding file with name (filename + probe#). 61 | bool doOutput( const State& x ); 62 | 63 | /// Write velocities u, v, fluxes q.x, q,y and vorticity omega for each probe, 64 | /// to the correpsonding file with name (filename + probe#), making use of the baseflow too. 65 | bool doOutput( const BaseFlow& q, const State& x ); 66 | 67 | /// \brief Add a probe by specifying its gridpoint indices 68 | void addProbeByIndex( int i, int j ); 69 | 70 | /// \brief Add a probe by specifying its absolute coordinates 71 | void addProbeByPosition( double xcord, double ycord ); 72 | // TODO: Write up this member function. 73 | 74 | /// \brief Add a probe by specifying its gridpoint indices 75 | void addProbe( int i, int j ); 76 | 77 | /// \brief Add a probe by specifying its absolute coordinates 78 | void addProbe( double xcord, double ycord ); 79 | 80 | /// Print out probe locations (by grid indices), for debugging 81 | void print(); 82 | 83 | /// Return the number of probes 84 | inline int getNumProbes(){ return _probes.size(); } 85 | 86 | /// Return the gridpoint index i of the corresponding probe 87 | inline int getProbeIndexX( unsigned int index ){ 88 | assert( index <= _probes.size() && index >= 1 ); 89 | return _probes[index-1].i; 90 | } 91 | 92 | /// Return the gridpoint index j of the corresponding probe 93 | inline int getProbeIndexY( unsigned int index ){ 94 | assert( index <= _probes.size() ); 95 | assert( index >= 1 ); 96 | return _probes[index-1].j; 97 | } 98 | 99 | /// Return the gridpoint x coordinate of the corresponding probe 100 | inline double getProbeCoordX( unsigned int index ){ 101 | assert( index <= _probes.size() && index >= 1 ); 102 | return _grid.getXEdge( _lev, _probes[index-1].i ); 103 | } 104 | 105 | /// Return the gridpoint y coordinate of the corresponding probe 106 | inline double getProbeCoordY( unsigned int index ){ 107 | assert( index <= _probes.size() && index >= 1 ); 108 | return _grid.getYEdge( _lev, _probes[index-1].j ); 109 | } 110 | 111 | private: 112 | class Probe { 113 | public: 114 | Probe(int ii, int jj) : 115 | i(ii), 116 | j(jj), 117 | fp(NULL) 118 | {} 119 | int i,j; 120 | FILE *fp; 121 | }; 122 | 123 | bool writeSummaryFile(void); 124 | 125 | // Private data 126 | string _filename; 127 | Grid _grid; 128 | bool _hasBeenInitialized; 129 | vector _probes; 130 | static const int _lev; 131 | static const int _dimen; 132 | }; 133 | 134 | } // namespace ibpm 135 | 136 | #endif /* _OUTPUTPROBES_H_ */ 137 | -------------------------------------------------------------------------------- /src/OutputRestart.cc: -------------------------------------------------------------------------------- 1 | // OutputRestart.cc 2 | // 3 | // Description: 4 | // Implementation of output routine for writing restart files. 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 22 Aug 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "OutputRestart.h" 17 | #include "State.h" 18 | #include "Output.h" 19 | #include 20 | #include 21 | 22 | namespace ibpm { 23 | 24 | OutputRestart::OutputRestart(string formatString) { 25 | _formatString = formatString; 26 | } 27 | 28 | bool OutputRestart::doOutput(const State& x) { 29 | char filename[256]; 30 | sprintf( filename, _formatString.c_str(), x.timestep ); 31 | bool status = x.save( filename ); 32 | return status; 33 | } 34 | 35 | bool OutputRestart::doOutput(const BaseFlow& q, const State& x) { 36 | // Currently no use for baseflow, but this method is defined for future 37 | // flexibility 38 | return doOutput(x); 39 | } 40 | 41 | void OutputRestart::setFilename( string formatString ) { 42 | _formatString = formatString; 43 | } 44 | 45 | } // namespace ibpm 46 | 47 | -------------------------------------------------------------------------------- /src/OutputRestart.h: -------------------------------------------------------------------------------- 1 | #ifndef _OUTPUTRESTART_H_ 2 | #define _OUTPUTRESTART_H_ 3 | 4 | #include "Output.h" 5 | #include 6 | using std::string; 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file OutputRestart.h 12 | \class OutputRestart 13 | 14 | \brief Output routine for writing a restart file 15 | 16 | \author Clancy Rowley 17 | \date 21 Aug 2008 18 | 19 | \author $LastChangedBy$ 20 | \date $LastChangedDate$ 21 | \version $Revision$ 22 | */ 23 | 24 | class OutputRestart : public Output { 25 | public: 26 | /// \brief Constructor 27 | /// \param[in] formatString Filename in the standard printf format 28 | /// (e.g. "file%06d.bin"), where timestep will be substituted for %d 29 | OutputRestart(string formatString); 30 | 31 | /// \brief Write the restart file 32 | bool doOutput(const State& x); 33 | 34 | /// \brief Write the restart file, making use of the baseflow too 35 | bool doOutput(const BaseFlow& q, const State& x); 36 | 37 | /// \brief Change the filename for the output file 38 | void setFilename( string formatString ); 39 | 40 | private: 41 | string _formatString; 42 | }; 43 | 44 | } // namespace ibpm 45 | 46 | #endif /* _OUTPUTRESTART_H_ */ 47 | -------------------------------------------------------------------------------- /src/OutputTecplot.cc: -------------------------------------------------------------------------------- 1 | // OutputTecplot.cc 2 | // 3 | // Description: 4 | // Implementation of output routine for writing Tecplot ASCII files. 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 22 Aug 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "OutputTecplot.h" 17 | #include "State.h" 18 | #include "Output.h" 19 | #include "VectorOperations.h" 20 | #include "ScalarToTecplot.h" 21 | #include 22 | #include 23 | #include 24 | 25 | namespace ibpm { 26 | 27 | OutputTecplot::OutputTecplot( string filename, string title, bool TecplotAllGrids ) { 28 | _filename = filename; 29 | _title = title; 30 | _TecplotAllGrids = TecplotAllGrids; 31 | } 32 | 33 | bool OutputTecplot::doOutput(const State& state) { 34 | // Add timestep to filename and title 35 | char filename[256]; 36 | sprintf( filename, _filename.c_str(), state.timestep ); 37 | char title[256]; 38 | sprintf( title, _title.c_str(), state.timestep ); 39 | bool status = false; 40 | const Grid& grid = state.omega.getGrid(); 41 | 42 | // Calculate velocities 43 | Scalar u( state.omega.getGrid() ); 44 | Scalar v( state.omega.getGrid() ); 45 | FluxToVelocity( state.q, u, v ); 46 | 47 | // Create vector of Scalar fields 48 | vector varVec; 49 | varVec.push_back( &u ); 50 | varVec.push_back( &v); 51 | varVec.push_back( &state.omega ); 52 | 53 | vector varNameVec; 54 | varNameVec.push_back( "u" ); 55 | varNameVec.push_back( "v" ); 56 | varNameVec.push_back( "Vorticity" ); 57 | 58 | // Write the tecplot file 59 | if(_TecplotAllGrids) { 60 | status = true; 61 | for(int i=0;i < grid.Ngrid(); i++) { 62 | sprintf( filename, _filename.c_str(), state.timestep, i ); 63 | cout << filename << endl; 64 | status = status && ScalarToTecplot( varVec, varNameVec, filename, title, i); 65 | } 66 | } 67 | else status = ScalarToTecplot( varVec, varNameVec, filename, title ); 68 | return status; 69 | } 70 | 71 | bool OutputTecplot::doOutput(const BaseFlow& q, const State& x) { 72 | // Currently no use for baseflow, but this method is defined for future 73 | // flexibility 74 | return doOutput(x); 75 | } 76 | 77 | void OutputTecplot::setFilename( string filename ) { 78 | _filename = filename; 79 | } 80 | 81 | void OutputTecplot::setTitle( string title ) { 82 | _title = title; 83 | } 84 | 85 | } // namespace ibpm 86 | -------------------------------------------------------------------------------- /src/OutputTecplot.h: -------------------------------------------------------------------------------- 1 | #ifndef _OUTPUTTECPLOT_H_ 2 | #define _OUTPUTTECPLOT_H_ 3 | 4 | #include "Output.h" 5 | #include "Scalar.h" 6 | #include "ScalarToTecplot.h" 7 | #include 8 | #include 9 | using std::string; 10 | 11 | namespace ibpm { 12 | 13 | /*! 14 | \file OutputTecplot.h 15 | \class OutputTecplot 16 | 17 | \brief Output routines for writing ASCII Tecplot files 18 | 19 | \author Clancy Rowley 20 | \date 22 Aug 2008 21 | 22 | \author $LastChangedBy$ 23 | \date $LastChangedDate$ 24 | \version $Revision$ 25 | */ 26 | 27 | 28 | class OutputTecplot : public Output { 29 | public: 30 | /// \brief Constructor 31 | /// \param[in] filename Filename in the standard printf format (e.g. "file%06d.plt"), where timestep will be supplied 32 | /// \param[in] title Title in the standard printf format 33 | OutputTecplot( string filename, string title, bool TecplotAllGrids ); 34 | 35 | /// \brief Write the Tecplot file 36 | bool doOutput(const State& x); 37 | 38 | /// \brief Write the Tecplot file 39 | bool doOutput(const BaseFlow& q, const State& x); 40 | 41 | /// \brief Change the filename for the output file 42 | void setFilename( string filename ); 43 | 44 | /// \brief Change the title for the output file 45 | void setTitle( string title ); 46 | 47 | private: 48 | string _filename; 49 | string _title; 50 | bool _TecplotAllGrids; 51 | }; 52 | 53 | } // namespace ibpm 54 | 55 | #endif /* _OUTPUTTECPLOT_H_ */ 56 | -------------------------------------------------------------------------------- /src/ParmParser.h: -------------------------------------------------------------------------------- 1 | #ifndef _PARMPARSER_H_ 2 | #define _PARMPARSER_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::string; 11 | using std::ostream; 12 | using std::vector; 13 | using std::ostringstream; 14 | using std::endl; 15 | using std::ios_base; 16 | using std::setw; 17 | using std::istringstream; 18 | using std::cerr; 19 | using std::fstream; 20 | 21 | /*! 22 | \file ParmParser.h 23 | \class ParmParser 24 | 25 | \brief Class for parsing command-line arguments 26 | 27 | \author Clancy Rowley 28 | \author $LastChangedBy$ 29 | \date 4 Sep 2008 30 | \date $LastChangedDate$ 31 | \version $Revision$ 32 | */ 33 | 34 | class ParmParser { 35 | public: 36 | /// Constructor, taking command line arguments as input 37 | ParmParser(int argc, char* argv[]); 38 | 39 | /// \brief Search the parameter list for the given flag, that does not take 40 | /// an argument. Returns true if the flag is present 41 | bool getFlag( string flag, string description ); 42 | 43 | /// \brief Search the parameter list for the given entry \a parm and a single 44 | /// integer argument, returning \a defaultVal if not specified. 45 | /// If argument is invalid, print a warning message and return \a defaultVal 46 | int getInt( string parm, string description, int defaultVal ); 47 | 48 | /// \brief Search the parameter list for \a description, and return the 49 | /// corresponding double value, or \a defaultVal if not specified. 50 | double getDouble( string parm, string description, double defaultVal ); 51 | 52 | /// \brief Search the parameter list for \a description, and return the 53 | /// corresponding string value, or \a defaultVal if not specified. 54 | string getString( string parm, string description, string defaultVal ); 55 | 56 | /// \brief Search the parameter list for \a description, and return the 57 | /// corresponding boolean value, or \a defaultVal if not specified. 58 | bool getBool( string parm, string description, bool defaultVal ); 59 | 60 | /// \brief Check if any input parameters were invalid, or unused. 61 | /// 62 | /// Returns true if everything is valid and all parameters used 63 | /// If any were not used, prints them to standard error and returns false 64 | bool inputIsValid(); 65 | 66 | /// \brief Print a usage message 67 | void printUsage( ostream& out ); 68 | 69 | /// \brief Return argument list in a string 70 | string getParameters(); 71 | 72 | /// \brief Save argument list to a file 73 | void saveParameters( string fname ); 74 | 75 | private: 76 | void appendUsageMessage( string flag, string description ); 77 | void appendUsageMessage( 78 | string parm, 79 | string type, 80 | string description, 81 | string defVal 82 | ); 83 | template T getParm( 84 | string parm, 85 | string description, 86 | T defaultVal 87 | ); 88 | 89 | // data 90 | int _argc; 91 | vector _argv; 92 | vector _used; 93 | string _args; 94 | ostringstream _argOut; 95 | ostringstream _usageMessage; 96 | }; 97 | 98 | #endif /* _PARMPARSER_H_ */ 99 | -------------------------------------------------------------------------------- /src/PitchPlunge.h: -------------------------------------------------------------------------------- 1 | #ifndef _PITCHPLUNGE_H_ 2 | #define _PITCHPLUNGE_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file PitchPlunge.h 12 | \class PitchPlunge 13 | 14 | \brief Subclass of Motion, for a pitching and plunging body 15 | 16 | \author Clancy Rowley 17 | \author $LastChangedBy$ 18 | \date 29 Aug 2008 19 | \date $LastChangedDate$ 20 | \version $Revision$ 21 | */ 22 | 23 | class PitchPlunge : public Motion { 24 | public: 25 | 26 | /// \brief Define a Motion corresponding to sinusoidal pitching and 27 | /// plunging, centered about the origin: 28 | /// y(t) = A_y sin( 2*pi * f_y t + phi_y) 29 | /// \theta(t) = A_\theta sin( 2*pi * f_theta t + phi_theta) 30 | PitchPlunge( 31 | double pitchAmplitude, 32 | double pitchFrequency, 33 | double pitchPhase, 34 | double plungeAmplitude, 35 | double plungeFrequency, 36 | double plungePhase 37 | ) : 38 | _pitchAmp(pitchAmplitude), 39 | _pitchFreq(pitchFrequency), 40 | _pitchPhase(pitchPhase), 41 | _plungeAmp(plungeAmplitude), 42 | _plungeFreq(plungeFrequency), 43 | _plungePhase(plungePhase) { 44 | 45 | double twopi = 8. * atan(1.); 46 | _pitchFreq *= twopi; 47 | _plungeFreq *= twopi; 48 | } 49 | 50 | /// Returns transformation for sinusoidal pitch/plunge: 51 | /// (0, y(t), theta(t), 0, ydot(t), thetadot(t)) 52 | inline TangentSE2 getTransformation(double time) const { 53 | double y = _plungeAmp * sin( _plungeFreq * time + _plungePhase ); 54 | double ydot = _plungeAmp * _plungeFreq * cos( _plungeFreq * time + _plungePhase ); 55 | double theta = _pitchAmp * sin( _pitchFreq * time + _pitchPhase ); 56 | double thetadot = _pitchAmp * _pitchFreq * cos( _pitchFreq * time + _pitchPhase ); 57 | return TangentSE2( 0, y, theta, 0, ydot, thetadot ); 58 | } 59 | 60 | inline Motion* clone() const { 61 | double twopi = 8. * atan(1.); 62 | return new PitchPlunge( 63 | _pitchAmp, 64 | _pitchFreq / twopi, 65 | _pitchPhase, 66 | _plungeAmp, 67 | _plungeFreq / twopi, 68 | _plungePhase 69 | ); 70 | }; 71 | 72 | private: 73 | double _pitchAmp; 74 | double _pitchFreq; 75 | double _pitchPhase; 76 | double _plungeAmp; 77 | double _plungeFreq; 78 | double _plungePhase; 79 | }; 80 | 81 | } // namespace ibpm 82 | 83 | #endif /* _PITCHPLUNGE_H_ */ 84 | -------------------------------------------------------------------------------- /src/ProjectionSolver.cc: -------------------------------------------------------------------------------- 1 | // ProjectionSolver.cc 2 | // 3 | // Description: 4 | // Implementation of the ProjectionSolver class 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 3 Jul 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "Scalar.h" 17 | #include "BoundaryVector.h" 18 | #include "NavierStokesModel.h" 19 | #include "ProjectionSolver.h" 20 | #include 21 | 22 | namespace ibpm { 23 | 24 | // Constructor: initialize Helmholtz solver to solve (1 - beta/2 L) u = f 25 | // 26 | ProjectionSolver::ProjectionSolver( 27 | const Grid& grid, 28 | const NavierStokesModel& model, 29 | double beta) : 30 | _beta(beta), 31 | _grid(grid), 32 | _model(model), 33 | _helmholtz( grid, -beta/2. * _model.getAlpha() ) 34 | {} 35 | 36 | ProjectionSolver::~ProjectionSolver() {} 37 | 38 | // Initialization for this base class done in constructor 39 | // Subclasses use this for their own initialization, if needed 40 | void ProjectionSolver::init() {} 41 | 42 | // Subclasses can override these to save and load their own state 43 | // (e.g. a Cholesky factorization) 44 | // By default, not implemented: return false 45 | bool ProjectionSolver::save(const std::string& filename) { return false; } 46 | bool ProjectionSolver::load(const std::string& filename) { return false; } 47 | 48 | 49 | // Solve for omega and f for a system of the form 50 | // A omega + B f = a 51 | // C omega = b 52 | // using a fractional step method: 53 | // A omega^* = a 54 | // C A^{-1}B f = C omega^* - b 55 | // omega = omega^* - A^{-1} B f 56 | 57 | void ProjectionSolver::solve( 58 | const Scalar& a, 59 | const BoundaryVector& b, 60 | Scalar& omega, 61 | BoundaryVector& f 62 | ) { 63 | 64 | // A omega^* = a 65 | Scalar omegaStar( a.getGrid() ); 66 | Ainv( a, omegaStar ); 67 | 68 | // C A^{-1}B f = C omega^* - b 69 | BoundaryVector rhs( f.getNumPoints() ); 70 | C( omegaStar, rhs ); 71 | rhs -= b; // rhs = C omega^* - b 72 | Minv( rhs, f ); // f = Minv( rhs ) 73 | 74 | // omega = omega^* - A^{-1} B f 75 | Scalar c( a.getGrid() ); 76 | B( f, c ); // c = Bf 77 | Ainv( c, c ); // c = Ainv(Bf) 78 | omega = omegaStar - c; 79 | } 80 | 81 | void ProjectionSolver::Ainv(const Scalar& x, Scalar& y) { 82 | _helmholtz.solve( x, y ); 83 | } 84 | 85 | void ProjectionSolver::B(const BoundaryVector& f, Scalar& y) { 86 | _model.B( f, y ); 87 | y *= _beta; 88 | } 89 | 90 | 91 | void ProjectionSolver::C(const Scalar& x, BoundaryVector& y ) { 92 | _model.C( x, y ); 93 | } 94 | 95 | // Compute y = M(f), where M = C A^{-1} B 96 | void ProjectionSolver::M(const BoundaryVector& f, BoundaryVector& y ) { 97 | Scalar u( _grid ); 98 | B( f, u ); // u = B f 99 | Ainv( u, u ); // u = Ainv B f 100 | C( u, y ); // y = C Ainv B f 101 | } 102 | 103 | BoundaryVector ProjectionSolver::M(const BoundaryVector& f) { 104 | BoundaryVector y( f.getNumPoints() ); 105 | M( f, y ); 106 | return y; 107 | } 108 | 109 | } // namespace ibpm 110 | -------------------------------------------------------------------------------- /src/ProjectionSolver.h: -------------------------------------------------------------------------------- 1 | #ifndef _PROJECTIONSOLVER_H_ 2 | #define _PROJECTIONSOLVER_H_ 3 | 4 | #include "Scalar.h" 5 | #include "BoundaryVector.h" 6 | #include "NavierStokesModel.h" 7 | #include "EllipticSolver.h" 8 | #include 9 | using std::string; 10 | 11 | namespace ibpm { 12 | 13 | /*! 14 | \file ProjectionSolver.h 15 | \class ProjectionSolver 16 | 17 | \brief Solve systems arising in a fractional step method. 18 | 19 | Solve a system of the form 20 | \f{align} 21 | (1 - \frac{\alpha\beta}{2}L )x + \beta B f &= a\\ 22 | C x &= b 23 | \f} 24 | for \a f and \a x, using the following algorithm (a fractional step method): 25 | 26 | \f{align} 27 | Ax^* &= a\\ 28 | C A^{-1}B_1 f &= Cx^* - b\\ 29 | x &= x^* - A^{-1}B_1 f 30 | \f} 31 | 32 | where 33 | \f{align} 34 | A &= 1-\frac{\alpha\beta}{2}L\\ 35 | B_1 &= \beta B 36 | \f} 37 | 38 | Note that this form of the equations arises for all of the timesteppers 39 | considered (so far). The parameter \f$ \beta \f$ is fixed, L is the discrete 40 | Laplacian, and the operators B, and C and the parameter \f$ \alpha \f$ are 41 | determined by an associated Model. 42 | 43 | This is an abstract base class, and may not be instantiated directly. 44 | 45 | \author Clancy Rowley 46 | \date 3 Jul 2008 47 | 48 | $Revision$ 49 | $LastChangedDate$ 50 | $LastChangedBy$ 51 | $HeadURL$ 52 | */ 53 | 54 | class ProjectionSolver { 55 | 56 | // 57 | // Public methods 58 | // 59 | public: 60 | 61 | /// Constructor 62 | ProjectionSolver(const Grid& grid, const NavierStokesModel& model, double beta); 63 | 64 | /// Destructor 65 | virtual ~ProjectionSolver(); 66 | 67 | /// Perform initialization, if needed 68 | /// NOTE: Does not call init() on the Model model 69 | virtual void init(); 70 | 71 | /// \brief Save information to a file, if there is any to write. 72 | /// Return true if successful 73 | virtual bool save(const string& basename); 74 | 75 | /// \brief Load information from a file 76 | /// Can be used in place of init() (if successful) 77 | /// Return true if successful 78 | virtual bool load(const string& basename); 79 | 80 | /*! \brief Solve for \a omega and \a f using a fractional step method. 81 | Solves equations (1-2) using the algorithm (3-5). 82 | 83 | Assumes the Model has been initialized with init() 84 | 85 | \param[in] a Right-hand side of equation (1) 86 | \param[in] b Right-hand side of constraint equation (2) 87 | \param[out] omega Vorticity after solution 88 | \param[out] f Boundary force after solution 89 | */ 90 | void solve( 91 | const Scalar& a, 92 | const BoundaryVector& b, 93 | Scalar& omega, 94 | BoundaryVector& f 95 | ); 96 | 97 | // 98 | // Protected methods 99 | // 100 | protected: 101 | 102 | /// Solve \f$ y = A^{-1} b \f$. 103 | void Ainv( const Scalar& b, Scalar& y ); 104 | 105 | /// Compute \a y = B(\a f) 106 | void B( const BoundaryVector& f, Scalar& y ); 107 | 108 | /// Compute \a y = C(\a x) 109 | void C( const Scalar& x, BoundaryVector& y ); 110 | 111 | /// Compute \a y = M(\a f), where \f$ M = C A^{-1} B \f$. 112 | void M( const BoundaryVector& f, BoundaryVector& y ); 113 | BoundaryVector M( const BoundaryVector& f ); 114 | 115 | /// Compute \f$ x = M^{-1} b \f$. 116 | virtual void Minv( const BoundaryVector& b, BoundaryVector& x ) = 0; 117 | 118 | // 119 | // Private data 120 | // 121 | private: 122 | double _beta; 123 | const Grid _grid; 124 | const NavierStokesModel& _model; 125 | HelmholtzSolver _helmholtz; 126 | }; 127 | 128 | } // namespace ibpm 129 | 130 | #endif /* _PROJECTIONSOLVER_H_ */ 131 | -------------------------------------------------------------------------------- /src/RandomNumber.h: -------------------------------------------------------------------------------- 1 | // Random number generator adapted from Numerical Recipes 2 | #include 3 | 4 | typedef unsigned long long int Ullong; 5 | typedef unsigned int Uint; 6 | typedef double Doub; 7 | 8 | class RandomNumber { 9 | public: 10 | // Constructor. Call with any integer seed (except value of v above). 11 | RandomNumber( ) : 12 | v(4101842887655102017LL), 13 | w(1), 14 | j( time(0) ) { // Seed with current time (random seed) 15 | u = j ^ v; 16 | getLongInt(); 17 | v = u; 18 | getLongInt(); 19 | w = v; 20 | getLongInt(); 21 | } 22 | 23 | // Return 64-bit random integer. 24 | inline Ullong getLongInt() { 25 | u = u * 2862933555777941757LL + 7046029254386353087LL; 26 | v ^= v >> 17; v ^= v << 31; v ^= v >> 8; 27 | w = 4294957665U*(w & 0xffffffff) + (w >> 32); 28 | Ullong x = u ^ (u << 21); x ^= x >> 35; x ^= x << 4; 29 | return (x + v) ^ w; 30 | } 31 | 32 | // Return random double-precision floating value in the range 0. to 1. 33 | inline Doub getDouble() { return 5.42101086242752217E-20 * getLongInt(); } 34 | 35 | // Return 32-bit random integer. 36 | inline Uint getInt() { return (Uint)getLongInt(); } 37 | 38 | private: 39 | Ullong u, v, w; 40 | Ullong j; // initial seed 41 | }; 42 | -------------------------------------------------------------------------------- /src/Regularizer.cc: -------------------------------------------------------------------------------- 1 | // Regularizer.cc 2 | // 3 | // Description: 4 | // Implementation of the Regularizer class 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 7 Jul 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL: Header$ 15 | 16 | #include "Regularizer.h" 17 | #include "Grid.h" 18 | #include "Geometry.h" 19 | #include "Flux.h" 20 | #include 21 | #include 22 | 23 | namespace ibpm { 24 | 25 | Regularizer::Regularizer(const Grid& grid, const Geometry& geometry) : 26 | _grid(grid), 27 | _geometry(geometry) 28 | {} 29 | 30 | // number of cells over which delta function has support 31 | const double deltaSupportRadius = 1.5; 32 | 33 | // Return the value of the regularized delta function phi(r) 34 | // where delta(x) \approx phi(x/h) / h, where h is the grid spacing 35 | // 36 | // From Roma, Peskin, and Berger, JCP 1999, eq (22) 37 | // Note that the input r is given in numbers of cells 38 | // (e.g. normalized by the cell width) 39 | inline double deltaFunction(double r) { 40 | if (r > deltaSupportRadius) { 41 | return 0; 42 | } 43 | else { 44 | if (r <= 0.5) 45 | return (1 + sqrt(1 - 3*r*r)) / 3; 46 | else 47 | return (5 - 3*r - sqrt(1 - 3*(1-r)*(1-r)) ) / 6; 48 | } 49 | } 50 | 51 | // Update list of relationships between boundary points and cells, and the 52 | // corresponding weights 53 | // Checks only the finest grid level, level=0 54 | void Regularizer::update() { 55 | Direction dir; 56 | Flux f(_grid); 57 | int i; 58 | Flux::index j; 59 | double dx, dy; 60 | double h = _grid.Dx(); // mesh spacing 61 | Association a; 62 | 63 | // Clear the list of associated Flux and BoundaryVector points 64 | _neighbors.clear(); 65 | 66 | // Get the coordinates of the body 67 | BoundaryVector bodyCoords = _geometry.getPoints(); 68 | 69 | // For each direction (x and y) 70 | for (dir = X; dir <= Y; ++dir) { 71 | // For each point on the boundary 72 | for (i = 0; i < bodyCoords.getNumPoints(); ++i) { 73 | // For each cell 74 | for (j = f.begin(dir); j != f.end(dir); ++j) { 75 | // Find x and y distances between boundary point and cell 76 | dx = fabs(f.x(0,j) - bodyCoords(X,i)) / h; 77 | dy = fabs(f.y(0,j) - bodyCoords(Y,i)) / h; 78 | // If cell is within the radius of support of delta function 79 | if ((dx < deltaSupportRadius) && (dy < deltaSupportRadius)) { 80 | // Compute the weight factor 81 | a.weight = deltaFunction(dx) * deltaFunction(dy); 82 | a.fluxIndex = j; 83 | a.boundaryIndex = bodyCoords.getIndex(dir,i); 84 | // Add to list of associated cells 85 | _neighbors.push_back(a); 86 | } 87 | } 88 | } 89 | } 90 | } 91 | 92 | Flux Regularizer::toFlux(const BoundaryVector& u1) const { 93 | // Allocate a new Flux field, initialized to zero 94 | Flux u2(_grid); 95 | u2 = 0; 96 | 97 | // For each association between cells and boundary points 98 | vector::const_iterator a; 99 | for (a = _neighbors.begin(); a != _neighbors.end(); ++a) { 100 | // add the weight factor times the boundary value to the flux 101 | u2(0,a->fluxIndex) += a->weight * u1(a->boundaryIndex); 102 | } 103 | 104 | // Multiply by grid spacing for correct dimension (vector -> Flux) 105 | u2 *= _grid.Dx(); 106 | 107 | // Return the new flux field 108 | return u2; 109 | } 110 | 111 | BoundaryVector Regularizer::toBoundary(const Flux& u2) const { 112 | // Allocate a new BoundaryVector, initialized to zero 113 | BoundaryVector u1(_geometry.getNumPoints()); 114 | u1 = 0; 115 | 116 | // For each association between cells and boundary points 117 | vector::const_iterator a; 118 | for (a = _neighbors.begin(); a != _neighbors.end(); ++a) { 119 | // Add the weight factor times the flux value to the boundary 120 | u1(a->boundaryIndex) += a->weight * u2(0,a->fluxIndex); 121 | } 122 | 123 | // Divide by grid spacing for correct dimension (Flux -> vector) 124 | u1 /= _grid.Dx(); 125 | 126 | // Return the new BoundaryVector 127 | return u1; 128 | } 129 | 130 | } // namespace 131 | 132 | -------------------------------------------------------------------------------- /src/Regularizer.h: -------------------------------------------------------------------------------- 1 | #ifndef _REGULARIZER_H_ 2 | #define _REGULARIZER_H_ 3 | 4 | #include 5 | #include "Flux.h" 6 | #include "BoundaryVector.h" 7 | 8 | using std::vector; 9 | 10 | namespace ibpm { 11 | 12 | class Grid; 13 | class Geometry; 14 | 15 | /*! 16 | \file Regularizer.h 17 | \class Regularizer 18 | 19 | \brief Define regularization operations between grid and boundary data 20 | 21 | Regularization (smearing) lifts values defined on the boundary to values 22 | defined on a grid, and interpolation takes data defined on a grid and 23 | interpolates it to the boundary. 24 | 25 | Specifically, if \f$ u(x) \f$ are values of u defined on a grid, and if 26 | \f$ u(\xi) \f$ denotes values on a boundary, then regularization defines 27 | 28 | \f[ 29 | u(x) = \int_\Omega u(\xi) \delta(x-\xi)\,d\xi 30 | \f] 31 | 32 | where a discrete approximation of the delta function is used, and 33 | interpolation defines 34 | 35 | \f[ 36 | u(\xi) = \int_\Omega u(x) \delta(x-\xi)\,dx 37 | \f] 38 | 39 | These integrals are discretized using a regularized version of the delta 40 | function, with finite support, as in (14) of Taira & Colonius (J Comput Phys, 41 | 2007). 42 | 43 | \author Clancy Rowley 44 | \author $LastChangedBy$ 45 | \date 7 Jul 2008 46 | \date $LastChangedDate$ 47 | \version $Revision$ 48 | */ 49 | 50 | class Regularizer { 51 | public: 52 | /// Constructor 53 | Regularizer(const Grid& grid, const Geometry& geometry); 54 | 55 | /// Destructor 56 | ~Regularizer() {} 57 | 58 | /// Update operators, for instance when the position of the bodies changes 59 | void update(); 60 | 61 | /// \brief Smear boundary data to grid. 62 | /// In particular, if u1 denotes the vectors along the boundary, 63 | /// and u2 denotes the velocity vectors in the 2d domain, computes 64 | /// a discrete approximation to 65 | /// u2(x,y) = \int u1(\xi,\eta) \delta(x-\xi) \delta(y-\eta) d\xi d\eta 66 | /// \approx \sum u1(\xi,\eta) \delta(x-\xi) \delta(y-\eta) * dx^2 67 | /// The flux returned is the corresponding flux through cell edges, 68 | /// or u2 * dx 69 | Flux toFlux(const BoundaryVector& u) const; 70 | 71 | /// \brief Interpolate grid data to boundary. 72 | /// In particular, if q denotes fluxes in the 2D domain, compute 73 | /// corresponding velocities u2 = q / dx, and define velocities u1 at 74 | /// boundary points by interpolation: 75 | /// u1(x,y) = \int u2(\xi,\eta) \delta(x-\xi) \delta(y-\eta) d\xi d\eta 76 | /// \approx \sum u2(\xi,\eta) \delta(x-\xi) \delta(y-\eta) * dx^2 77 | BoundaryVector toBoundary(const Flux& u) const; 78 | 79 | private: 80 | const Grid& _grid; 81 | const Geometry& _geometry; 82 | 83 | // Associations between BoundaryVector points and nearby Flux values 84 | struct Association { 85 | BoundaryVector::index boundaryIndex; 86 | Flux::index fluxIndex; 87 | double weight; 88 | }; 89 | 90 | vector _neighbors; 91 | }; 92 | 93 | } // namespace ibpm 94 | 95 | #endif /* _REGULARIZER_H_ */ 96 | -------------------------------------------------------------------------------- /src/Scalar.cc: -------------------------------------------------------------------------------- 1 | // Scalar.cc 2 | // 3 | // Description: 4 | // Implementation of the Scalar class, using Blitz++ arrays 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 4 Jul 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "Scalar.h" 17 | #include 18 | 19 | using std::cout; 20 | 21 | namespace ibpm { 22 | 23 | Scalar::Scalar( const Grid& grid ) : 24 | Field( grid ) { 25 | resize( grid ); 26 | } 27 | 28 | /// Default constructor: do not allocate memory yet 29 | Scalar::Scalar() {} 30 | 31 | /// Allocate new array, copy the data 32 | Scalar::Scalar( const Scalar& f ) : 33 | Field( f ) { 34 | resize( f.getGrid() ); 35 | // copy data 36 | for (unsigned int i=0; i<_data.Size(); ++i) { 37 | _data(i) = f._data(i); 38 | } 39 | } 40 | 41 | /// Deallocate memory in the destructor 42 | Scalar::~Scalar() { 43 | // deallocation automatic for Arrays 44 | } 45 | 46 | void Scalar::coarsify() { 47 | // Fine grid unchanged: start with next finest grid 48 | for (int lev=1; lev 0; --j) { 71 | for(int i = 1; i < nx; ++i) { 72 | cout << _data(lev,i,j) << " "; 73 | } 74 | cout << endl; 75 | } 76 | cout << endl; 77 | } 78 | 79 | } 80 | 81 | void Scalar::resize( const Grid& grid ) { 82 | setGrid( grid ); 83 | _data.Deallocate(); 84 | // Allocate arrays for interior points: 85 | // lev in 0..lev-1 86 | // i in 1..nx-1 87 | // j in 1..ny-1 88 | _data.Allocate( Ngrid(), Nx() - 1, Ny() - 1, 0, 1, 1 ); 89 | } 90 | 91 | void Scalar::getBC( int lev, BC& bc ) const { 92 | assert( Nx() == bc.Nx() ); 93 | assert( Ny() == bc.Ny() ); 94 | assert( lev >= 0 && lev < Ngrid()-1 ); 95 | 96 | // top and bottom boundaries 97 | /* if grid is shifted completely up or down, 98 | then all poinsts on the shared boundary must take a value of 0, 99 | as required on the boundary of the outermost grid */ 100 | for (int i=0; i<=Nx(); ++i) { 101 | int ii,jj; // indices on coarse grid 102 | getGrid().f2c(i,0,ii,jj); 103 | // copy point that coincides with coarse point 104 | bc.bottom(i) = (*this)( lev+1, ii, jj ); 105 | bc.top(i) = (*this)( lev+1, ii, Ny()/2+jj ); 106 | 107 | if ( ++i <= Nx() ) { 108 | // interpolate point in between coarse points 109 | bc.bottom(i) = 0.5 * ( (*this)( lev+1, ii, jj ) + (*this)( lev+1, ii+1, jj) ); 110 | bc.top(i) = 0.5 * ( (*this)( lev+1, ii, Ny()/2+jj ) + (*this)( lev+1, ii+1, Ny()/2+jj) ); 111 | } 112 | } 113 | 114 | // left and right boundaries 115 | for (int j=0; j<=Ny(); ++j) { 116 | int ii,jj; // indices on coarse grid 117 | getGrid().f2c(0,j,ii,jj); 118 | // copy point that coincides with coarse point 119 | bc.left(j) = (*this)( lev+1, ii, jj ); 120 | bc.right(j) = (*this)( lev+1, Nx()/2+ii, jj ); 121 | if ( ++j <= Ny() ) { 122 | // interpolate point in between coarse points 123 | bc.left(j) = 0.5 * ( (*this)( lev+1, ii, jj ) + (*this)( lev+1, ii, jj+1) ); 124 | bc.right(j) = 0.5 * ( (*this)( lev+1, Nx()/2+ii, jj ) + (*this)( lev+1, Nx()/2+ii, jj+1 ) ); 125 | } 126 | } 127 | } 128 | 129 | 130 | 131 | } // namespace 132 | -------------------------------------------------------------------------------- /src/ScalarToTecplot.h: -------------------------------------------------------------------------------- 1 | #ifndef _SCALARTOTECPLOT_H_ 2 | #define _SCALARTOTECPLOT_H_ 3 | 4 | #include "Scalar.h" 5 | #include 6 | #include 7 | using std::string; 8 | using std::vector; 9 | 10 | namespace ibpm { 11 | 12 | bool ScalarToTecplot( const Scalar* var, string varName, string filename, string title ); 13 | 14 | bool ScalarToTecplot( vector varVec, vector varNameVec, string filename, string title ); 15 | 16 | bool ScalarToTecplot( const Scalar* var, string varName, string filename, string title, int lev ); 17 | 18 | bool ScalarToTecplot( vector varVec, vector varNameVec, string filename, string title, int lev ); 19 | 20 | } // namespace ibpm 21 | 22 | #endif /* _SCALARTOTECPLOT_H_ */ 23 | -------------------------------------------------------------------------------- /src/Scheme.h: -------------------------------------------------------------------------------- 1 | // header file for storing integration schemes 2 | 3 | #include "Array.h" 4 | #include 5 | 6 | using std::string; 7 | using std::cout; 8 | 9 | class Scheme { 10 | public: 11 | enum SchemeType { EULER, AB2, RK3, RK3b }; 12 | 13 | Scheme( SchemeType scheme ) { 14 | if ( scheme == EULER ) { 15 | _coeff.Allocate(1,3); 16 | _coeff(0,0) = 1.; // an 17 | _coeff(0,1) = 0.; // bn 18 | _coeff(0,2) = 1.; // cn 19 | _name = "Explicit Euler"; 20 | } 21 | else if ( scheme == AB2 ) { 22 | _coeff.Allocate(1,3); 23 | _coeff(0,0) = 3./2.; // an 24 | _coeff(0,1) = -1./2.; // bn 25 | _coeff(0,2) = 1.; // cn 26 | _name = "Adams Bashforth"; 27 | } 28 | else if ( scheme == RK3 ) { 29 | _coeff.Allocate(3,3); 30 | _coeff(0,0) = 8./15.; // an 31 | _coeff(1,0) = 5./12.; 32 | _coeff(2,0) = 3./4.; 33 | _coeff(0,1) = 0.; // bn 34 | _coeff(1,1) = -17./60.; 35 | _coeff(2,1) = -5./12.; 36 | _coeff(0,2) = 8./15.; // cn 37 | _coeff(1,2) = 2./3.; 38 | _coeff(2,2) = 1.; 39 | _name = "3rd-order Runge Kutta (3-step)"; 40 | } 41 | else if ( scheme == RK3b ) { 42 | _coeff.Allocate(4,3); 43 | _coeff(0,0) = 8./17.; // an 44 | _coeff(1,0) = 17./60.; 45 | _coeff(2,0) = 5./12.; 46 | _coeff(3,0) = 3./4.; 47 | _coeff(0,1) = 0.; // bn 48 | _coeff(1,1) = -15./68.; 49 | _coeff(2,1) = -17./60.; 50 | _coeff(3,1) = -5./12.; 51 | _coeff(0,2) = 8./17.; // cn 52 | _coeff(1,2) = 8./15.; 53 | _coeff(2,2) = 2./3.; 54 | _coeff(3,2) = 1.; 55 | _name = "3rd-order Runge Kutta (4-step)"; 56 | } 57 | else { 58 | cout << endl << "ERROR: unrecognized solver: " << scheme << endl << endl; 59 | exit(1); 60 | } 61 | } 62 | 63 | inline double an( int i ) { return _coeff(i,0); } 64 | inline double bn( int i ) { return _coeff(i,1); } 65 | inline double cn( int i ) { return _coeff(i,2); } 66 | inline int nsteps() { return _coeff.Nx(); } 67 | inline string name() { return _name; } 68 | 69 | private: 70 | Array::Array2 _coeff; 71 | string _name; 72 | 73 | }; 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/SigmoidalStep.h: -------------------------------------------------------------------------------- 1 | #ifndef _SIGMOIDALSTEP_H_ 2 | #define _SIGMOIDALSTEP_H_ 3 | 4 | #include "Motion.h" 5 | #include "TangentSE2.h" 6 | #include 7 | 8 | namespace ibpm { 9 | 10 | /*! 11 | \file SigmoidalStep.h 12 | \class SigmoidalStep 13 | 14 | \brief Subclass of Motion, for a sigmoidal step in angle-of-attack 15 | 16 | \author Steven Brunton 17 | \author $LastChangedBy: sbrunton $ 18 | \date 26 Apr 2010 19 | \date $LastChangedDate: 2008-09-03 02:41:03 -0400 (Wed, 03 Sep 2008) $ 20 | \version $Revision: 132 $ 21 | */ 22 | 23 | class SigmoidalStep : public Motion { 24 | public: 25 | 26 | /// \brief Define a Motion corresponding to a sigmoidal pitch-up 27 | /// centered about the origin: 28 | /// \alpha(t) = \text{AMP}\cdot \frac{1}{2} \left(1+\erf\left(12\frac{t}{\text{DUR}}-6\right)\right) 29 | SigmoidalStep( 30 | double AMP, 31 | double DUR, 32 | double t0 33 | ) : 34 | _AMP(AMP), 35 | _DUR(DUR), 36 | _t0(t0) { 37 | } 38 | 39 | /// Returns transformation for sinusoidal pitch/plunge: 40 | /// (0, 0, theta(t), 0, 0, thetadot(t)) 41 | inline TangentSE2 getTransformation(double time) const { 42 | double pi = 4. * atan(1.); 43 | double tdiff = time-_t0; 44 | double arg = ((12.*tdiff/_DUR)-6.); 45 | double coeff = 12./(_DUR*sqrt(pi)); 46 | double nerf = erf(arg); 47 | double sig = (1./2)*_AMP*(pi/180)*(1.+nerf); 48 | double sigdot = _AMP*(pi/180)*coeff*exp(-arg*arg); 49 | double theta = sig; 50 | double thetadot = sigdot; 51 | return TangentSE2( 0, 0, theta, 0, 0, thetadot ); 52 | } 53 | 54 | inline Motion* clone() const { 55 | return new SigmoidalStep( 56 | _AMP, 57 | _DUR, 58 | _t0 59 | ); 60 | }; 61 | 62 | private: 63 | double _AMP; 64 | double _DUR; 65 | double _t0; 66 | }; 67 | 68 | } // namespace ibpm 69 | 70 | #endif /* _SIGMOIDALSTEP_H_ */ 71 | -------------------------------------------------------------------------------- /src/State.h: -------------------------------------------------------------------------------- 1 | #ifndef _STATE_H_ 2 | #define _STATE_H_ 3 | 4 | #include "Grid.h" 5 | #include "Flux.h" 6 | #include "Scalar.h" 7 | #include "BoundaryVector.h" 8 | #include 9 | 10 | using std::string; 11 | 12 | namespace ibpm { 13 | 14 | /*! 15 | \file State.h 16 | \class State 17 | 18 | \brief Structure for grouping state variables 19 | 20 | \author Clancy Rowley 21 | \author $LastChangedBy$ 22 | \date 7 Jul 2008 23 | \date $LastChangedDate$ 24 | \version $Revision$ 25 | */ 26 | 27 | class State { 28 | public: 29 | /// Default constructor: do not allocate memory 30 | State(); 31 | 32 | State( const Grid& grid, int numPoints ); 33 | 34 | /// \brief Instantiate a state by reading data from the specified file 35 | State( string filename ); 36 | 37 | ~State(); 38 | 39 | /// \brief Allocate memory, with the specified Grid and number of 40 | /// boundary points 41 | void resize( const Grid& grid, int numPoints ); 42 | 43 | /// \brief Save the state to a file (e.g. as a restart file) 44 | /// Return true if successful 45 | /* WARNING: At this point, the xshift and yshift parameters are not saved 46 | and are not checked for compatibility when loading. Caution should be 47 | taken when working with shifted grids. This approach was taken to pre- 48 | serve backwards compatibility with previously saved binary files. In 49 | the future perhaps using HDF5 would prevent such problems. 50 | */ 51 | bool save(std::string filename) const; 52 | 53 | /// \brief Load the state from a file (e.g. as a restart file) 54 | /// Return true if successful 55 | bool load(const std::string& filename); 56 | 57 | /// \brief Routine for computing X & Y forces 58 | void computeNetForce( double& xforce, double& yforce ) const; 59 | 60 | // public data 61 | Flux q; 62 | Scalar omega; 63 | BoundaryVector f; 64 | int timestep; 65 | double time; 66 | }; 67 | 68 | } // namespace ibpm 69 | 70 | #endif /* _STATE_H_ */ 71 | -------------------------------------------------------------------------------- /src/StateVector.cc: -------------------------------------------------------------------------------- 1 | // StateVector.cc 2 | // 3 | // Description: 4 | // Implementation of the StateVector class 5 | // 6 | // Author(s): 7 | // Daniel Floryan 8 | // 9 | // Date: 16 Jan 2019 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include "StateVector.h" 17 | #include 18 | #include 19 | 20 | using namespace ibpm; 21 | 22 | namespace ibpm { 23 | 24 | StateVector::StateVector() {} 25 | 26 | StateVector::StateVector(const StateVector& v) { 27 | resize( v.x.omega.getGrid(), v.x.f.getNumPoints() ); 28 | x.q = v.x.q; 29 | x.omega = v.x.omega; 30 | x.f = v.x.f; 31 | x.timestep = v.x.timestep; 32 | x.time = v.x.time; 33 | } 34 | 35 | StateVector::StateVector(const State& y) { 36 | resize( y.omega.getGrid(), y.f.getNumPoints() ); 37 | x.q = y.q; 38 | x.omega = y.omega; 39 | x.f = y.f; 40 | x.timestep = y.timestep; 41 | x.time = y.time; 42 | } 43 | 44 | StateVector::StateVector(const Grid& grid, int numPoints ) { 45 | resize( grid, numPoints ); 46 | } 47 | 48 | void StateVector::resize( const Grid& grid, int numPoints ) { 49 | x.q.resize( grid ); 50 | x.omega.resize( grid ); 51 | x.f.resize( numPoints ); 52 | } 53 | 54 | StateVector::StateVector( string filename ) { 55 | load( filename ); 56 | } 57 | 58 | StateVector::~StateVector() {} 59 | 60 | bool StateVector::load(const std::string& filename) { 61 | return x.load(filename); 62 | } 63 | 64 | bool StateVector::save(std::string filename) const { 65 | return x.save(filename); 66 | } 67 | 68 | } // namespace ibpm 69 | -------------------------------------------------------------------------------- /src/TangentSE2.h: -------------------------------------------------------------------------------- 1 | #ifndef _TANGENTSE2_H_ 2 | #define _TANGENTSE2_H_ 3 | 4 | #include 5 | 6 | namespace ibpm { 7 | 8 | /*! 9 | \file TangentSE2.h 10 | \class TangentSE2 11 | 12 | \brief An abstraction of the group TSE(2) of transformations in 2D 13 | 14 | Keeps track of translations and rotations in 2D, and their velocities. 15 | \author Clancy Rowley 16 | \author $LastChangedBy$ 17 | \date 12 Aug 2008 18 | \date $LastChangedDate$ 19 | \version $Revision$ 20 | */ 21 | 22 | class TangentSE2 { 23 | public: 24 | 25 | /// Constructor: specify the base point and corresponding velocity 26 | /// The base point is (x,y,theta), velocity (xdot, ydot, thetadot) 27 | TangentSE2( 28 | double x, 29 | double y, 30 | double theta, 31 | double xdot, 32 | double ydot, 33 | double thetadot) : 34 | _x(x), 35 | _y(y), 36 | _theta(theta), 37 | _xdot(xdot), 38 | _ydot(ydot), 39 | _thetadot(thetadot) { 40 | } 41 | 42 | inline void setPosition( 43 | double x, 44 | double y, 45 | double theta 46 | ) { 47 | _x = x; 48 | _y = y; 49 | _theta = theta; 50 | } 51 | 52 | inline void getPosition( 53 | double& x, 54 | double& y, 55 | double& theta 56 | ) { 57 | x = _x; 58 | y = _y; 59 | theta = _theta; 60 | } 61 | 62 | inline void setVelocity( 63 | double xdot, 64 | double ydot, 65 | double thetadot 66 | ) { 67 | _xdot = xdot; 68 | _ydot = ydot; 69 | _thetadot = thetadot; 70 | } 71 | 72 | inline void getVelocity( 73 | double& xdot, 74 | double& ydot, 75 | double& thetadot 76 | ) { 77 | xdot = _xdot; 78 | ydot = _ydot; 79 | thetadot = _thetadot; 80 | } 81 | 82 | /// Given the point (a,b), compute the mapped point (a_new, b_new) 83 | inline void mapPosition( 84 | double a, 85 | double b, 86 | double& a_new, 87 | double& b_new 88 | ) { 89 | double cost = cos(_theta); 90 | double sint = sin(_theta); 91 | a_new = _x + a * cost - b * sint; 92 | b_new = _y + a * sint + b * cost; 93 | } 94 | 95 | /// Given the point (a,b) (with zero initial velocity), compute the 96 | /// mapped velocity (u_new, v_new) 97 | inline void mapVelocity( 98 | double a, 99 | double b, 100 | double& u_new, 101 | double& v_new 102 | ) { 103 | double cost = cos(_theta); 104 | double sint = sin(_theta); 105 | u_new = - a * sint * _thetadot - b * cost * _thetadot + _xdot; 106 | v_new = a * cost * _thetadot - b * sint * _thetadot + _ydot; 107 | } 108 | 109 | private: 110 | // Note: may be better to implement this in terms of a vector (x,y,theta) 111 | // so that we can use matrix multiplication for transformations 112 | // Here, just the simplest implementation 113 | double _x; 114 | double _y; 115 | double _theta; 116 | double _xdot; 117 | double _ydot; 118 | double _thetadot; 119 | }; 120 | 121 | } 122 | 123 | #endif /* _TANGENTSE2_H_ */ 124 | -------------------------------------------------------------------------------- /src/VectorOperations.h: -------------------------------------------------------------------------------- 1 | #ifndef _VECTOROPERATIONS_H_ 2 | #define _VECTOROPERATIONS_H_ 3 | 4 | #include "Array.h" 5 | using Array::Array2; 6 | 7 | namespace ibpm { 8 | 9 | class BC; 10 | class Scalar; 11 | class Flux; 12 | class BoundaryVector; 13 | class NavierStokesModel; 14 | 15 | /*! 16 | \file VectorOperations.h 17 | \module VectorOperations 18 | 19 | \brief Collection of vector operations on Scalar and Flux objects. 20 | 21 | Operations include curl on scalars and fluxes, inner products of two 22 | scalars or two fluxes, sine transform of scalars, and 'cross product' 23 | between fluxes/scalars. 24 | 25 | \author Clancy Rowley 26 | \author Zhanhua Ma 27 | \author $LastChangedBy$ 28 | \date 15 Jul 2008 29 | \date $LastChangedDate$ 30 | \version $Revision$ 31 | */ 32 | 33 | /*! \brief Return the curl of Flux q, as a Scalar object. 34 | 35 | The curl is defined only at the interior nodes, and this routine returns zero at the boundary nodes. 36 | */ 37 | Scalar Curl(const Flux& q); 38 | void Curl(const Flux& q, Scalar& omega ); 39 | 40 | /// \brief Return the curl of Scalar f, as a Flux object. 41 | Flux Curl(const Scalar& f); 42 | void Curl(const Scalar& f, Flux& q); 43 | 44 | /// \brief Return the inner product of Scalar f and Scalar g, calculated over the finest grid only. 45 | double FineGridInnerProduct( const Scalar& f, const Scalar& g ); 46 | 47 | /// \brief Return the inner product of Scalar f and Scalar g. 48 | double InnerProduct( const Scalar& f, const Scalar& g ); 49 | 50 | /// \brief Return the inner product of Flux p and Flux q, calculated over the finest grid only. 51 | double FineGridInnerProduct( const Flux& p, const Flux& q ); 52 | 53 | /// \brief Return the inner product of Flux p and Flux q. 54 | double InnerProduct( const Flux& p, const Flux& q ); 55 | 56 | 57 | /// \brief Return the energy-equivalent inner product of two (Scalar) vorticity fields, calculated over the fine grid only. 58 | /* This is distinct from the standard L2 inner product so that the product of 59 | vorticity fields is equal to the product of fluxes (ie both yield KE) 60 | */ 61 | double FineGridVorticityInnerProduct( const Scalar& omega1, const Scalar& omega2, const NavierStokesModel& model ); 62 | 63 | /// \brief Return the energy-equivalent inner product of two (Scalar) vorticity fields. 64 | double VorticityInnerProduct( const Scalar& omega1, const Scalar& omega2, const NavierStokesModel& model ); 65 | 66 | /// \brief Compute the Laplacian of f 67 | void Laplacian( const Scalar& f, Scalar& g ); 68 | Scalar Laplacian( const Scalar& f ); 69 | void Laplacian( 70 | const Array2& f, 71 | double dx, 72 | const BC& bc, 73 | Array2& g ); 74 | 75 | 76 | /*! \brief Return the cross product of a Flux q and a Scalar f, as a Flux. 77 | 78 | q x f = (f v, -f u) 79 | 80 | This routine is designed so that the following identity holds at the 81 | discrete level: 82 | < a, q1 x q2 > = < q1, q2 x a > 83 | */ 84 | Flux CrossProduct(const Flux& q, const Scalar& f); 85 | 86 | /*! \brief Return the cross product of two Flux objects, q1, q2, as a Scalar. 87 | 88 | q1 x q2 = u1 v2 - u2 v1 89 | 90 | This routine is designed so that the following identity holds at the 91 | discrete level: 92 | < a, q1 x q2 > = < q1, q2 x a > 93 | */ 94 | Scalar CrossProduct(const Flux& q, const Flux& p); 95 | 96 | /// \brief Convert x-fluxes through edges to velocities at vertices 97 | void FluxToXVelocity(const Flux& q, Scalar& u); 98 | 99 | /// \brief Convert y-fluxes through edges to velocities at vertices 100 | void FluxToYVelocity(const Flux& q, Scalar& v); 101 | 102 | /// \brief Convert u-velocities at vertices to x-fluxes through edges. 103 | /// Does not touch the y-component of the Flux q passed in. 104 | void XVelocityToFlux(const Scalar& u, Flux& q); 105 | 106 | /// \brief Convert v-velocities at vertices to y-fluxes through edges. 107 | /// Does not touch the x-component of the Flux q passed in. 108 | void YVelocityToFlux(const Scalar& v, Flux& q); 109 | 110 | /// \brief Convert u- and v-velocities at vertices to fluxes through edges 111 | void VelocityToFlux(const Scalar& u, const Scalar& v, Flux& q); 112 | 113 | /// \brief Convert fluxes through edges to u- and v-velocities at vertices 114 | void FluxToVelocity(const Flux& q, Scalar& u, Scalar& v); 115 | 116 | } // namespace ibpm 117 | 118 | #endif /* _VECTOROPERATIONS_H_ */ 119 | -------------------------------------------------------------------------------- /src/checkgeom.cc: -------------------------------------------------------------------------------- 1 | // checkgeom - read in geometry file and write corresponding Tecplot file 2 | // 3 | // Use this utility to check the spacing of the boundary points. 4 | // If the boundary points are too sparse, the boundary will look "leaky". 5 | // 6 | // NOTE: If the points are too finely spaced, the solution will not converge 7 | // when used in a timestepper. 8 | // 9 | // Clancy Rowley 10 | // 18 May 2009 11 | // Princeton University 12 | // 13 | // $Revision: $ 14 | // $LastChangedDate: $ 15 | // $LastChangedBy: cwrowley $ 16 | // $HeadURL: $ 17 | 18 | #include 19 | #include 20 | #include "ibpm.h" 21 | #include "Regularizer.h" 22 | 23 | using namespace ibpm; 24 | 25 | int main(int argc, char* argv[]) { 26 | cout << "Check geometry\n"; 27 | 28 | ParmParser parser( argc, argv ); 29 | bool helpFlag = parser.getFlag( "h", "print this help message and exit" ); 30 | int nx = parser.getInt( 31 | "nx", "number of gridpoints in x-direction", 200 ); 32 | int ny = parser.getInt( 33 | "ny", "number of gridpoints in y-direction", 200 ); 34 | int ngrid = parser.getInt( 35 | "ngrid", "number of grid levels for multi-domain scheme", 1 ); 36 | double length = parser.getDouble( 37 | "length", "length of finest domain in x-dir", 4.0 ); 38 | double xOffset = parser.getDouble( 39 | "xoffset", "x-coordinate of left edge of finest domain", -2. ); 40 | double yOffset = parser.getDouble( 41 | "yoffset", "y-coordinate of bottom edge of finest domain", -2. ); 42 | string geomFile = parser.getString( 43 | "geom", "filename for reading geometry", "ibpm.geom" ); 44 | string outFileName = parser.getString( 45 | "o", "filename for writing Tecplot file", "" ); 46 | 47 | if ( ! parser.inputIsValid() || helpFlag ) { 48 | parser.printUsage( cerr ); 49 | exit(1); 50 | } 51 | 52 | // Setup grid 53 | cout << "Grid parameters:" << endl 54 | << " nx " << nx << endl 55 | << " ny " << ny << endl 56 | << " ngrid " << ngrid << endl 57 | << " length " << length << endl 58 | << " xoffset " << xOffset << endl 59 | << " yoffset " << yOffset << endl; 60 | Grid grid( nx, ny, ngrid, length, xOffset, yOffset ); 61 | 62 | // Setup geometry 63 | Geometry geom; 64 | cout << "Reading geometry from file " << geomFile << endl; 65 | if ( geom.load( geomFile ) ) { 66 | cout << " " << geom.getNumPoints() << " points on the boundary" << endl; 67 | } 68 | else { 69 | cout << " There were errors reading the geometry file." << endl; 70 | return 1; 71 | } 72 | 73 | if ( outFileName == "" ) return 0; 74 | 75 | Regularizer regularizer( grid, geom ); 76 | regularizer.update(); 77 | State x( grid, geom.getNumPoints() ); 78 | 79 | // set the boundary force to 1 (in x- and y- directions) 80 | x.f = 1.; 81 | x.q = regularizer.toFlux( x.f ); 82 | 83 | OutputTecplot tecplot( outFileName, "Check geometry", false ); 84 | BaseFlow q_potential(grid, 0., 0.); 85 | tecplot.doOutput(q_potential, x); 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /src/ibpm.h: -------------------------------------------------------------------------------- 1 | #ifndef _IBPM_H_ 2 | #define _IBPM_H_ 3 | 4 | /*! 5 | \file ibpm.h 6 | 7 | \brief Main header file for immersed boundary projection method (IBPM) library 8 | 9 | \author Clancy Rowley 10 | \author $LastChangedBy$ 11 | \date 30 Aug 2008 12 | \date $LastChangedDate$ 13 | \version $Revision$ 14 | */ 15 | 16 | #define IBPM_VERSION "1.0" 17 | 18 | // basic classes 19 | #include "Grid.h" 20 | #include "RigidBody.h" 21 | #include "Geometry.h" 22 | 23 | // data structures 24 | #include "Scalar.h" 25 | #include "Flux.h" 26 | #include "BoundaryVector.h" 27 | #include "BaseFlow.h" 28 | #include "State.h" 29 | #include "StateVector.h" 30 | 31 | // operations 32 | #include "VectorOperations.h" 33 | #include "NavierStokesModel.h" 34 | 35 | // timesteppers 36 | #include "IBSolver.h" 37 | 38 | // motion 39 | #include "Motion.h" 40 | #include "FixedPosition.h" 41 | #include "FixedVelocity.h" 42 | #include "PitchPlunge.h" 43 | #include "SigmoidalStep.h" 44 | #include "LagStep1.h" 45 | #include "LagStep2.h" 46 | #include "EldredgeManeuver.h" 47 | #include "EldredgeCombined2.h" // combines EldredgeManeuver for pitch and Eldredge2 for plunge 48 | #include "Eldredge1.h" 49 | #include "Eldredge2.h" 50 | #include "MotionFile.h" 51 | #include "MotionFilePeriodic.h" 52 | 53 | // output routines 54 | #include "Logger.h" 55 | #include "OutputTecplot.h" 56 | #include "OutputRestart.h" 57 | #include "OutputEnergy.h" 58 | #include "OutputForce.h" 59 | #include "OutputProbes.h" 60 | #include "ScalarToTecplot.h" 61 | 62 | // utilities 63 | #include "utils.h" 64 | #include "ParmParser.h" 65 | 66 | #endif /* _IBPM_H_ */ 67 | -------------------------------------------------------------------------------- /src/utils.cc: -------------------------------------------------------------------------------- 1 | // utils.cc 2 | // 3 | // Description: 4 | // Utilities for working with strings 5 | // 6 | // Author(s): 7 | // Clancy Rowley 8 | // 9 | // Date: 1 Sep 2008 10 | // 11 | // $Revision$ 12 | // $LastChangedDate$ 13 | // $LastChangedBy$ 14 | // $HeadURL$ 15 | 16 | #include 17 | #include 18 | 19 | using std::string; 20 | 21 | void EatWhitespace( string& s ) { 22 | while ( isspace( s[0] ) ) { 23 | s.erase(0,1); 24 | } 25 | } 26 | 27 | void MakeLowercase( string& s ) { 28 | for (unsigned int i=0; i 0 && s[len-1] != '/' ) { 36 | s += "/"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTILS_H_ 2 | #define _UTILS_H_ 3 | 4 | /*! 5 | \file utils.h 6 | 7 | \brief Utilities for working with strings 8 | 9 | \author Clancy Rowley 10 | \author $LastChangedBy$ 11 | \date 2 Sep 2008 12 | \date $LastChangedDate$ 13 | \version $Revision$ 14 | */ 15 | 16 | /// \brief Remove whitespace at the beginning of the string s 17 | void EatWhitespace( string& s ); 18 | 19 | /// \brief Convert the string s to lower case 20 | void MakeLowercase( string& s ); 21 | 22 | /// \brief Add a slash to the end of the string s, if not already present 23 | void AddSlashToPath( string& s ); 24 | 25 | #endif /* _UTILS_H_ */ 26 | -------------------------------------------------------------------------------- /test/BCTest.cc: -------------------------------------------------------------------------------- 1 | #include "BC.h" 2 | #include 3 | 4 | using namespace ibpm; 5 | 6 | class BCTest : public testing::Test { 7 | protected: 8 | BCTest() : 9 | _nx(8), 10 | _ny(4), 11 | _bc( _nx, _ny ) 12 | {} 13 | 14 | ~BCTest() {} 15 | 16 | // data 17 | int _nx; 18 | int _ny; 19 | BC _bc; 20 | }; 21 | 22 | TEST_F( BCTest, InitializeToZero ) { 23 | for ( int i=0; i<=_nx; ++i ) { 24 | EXPECT_DOUBLE_EQ( 0., _bc.bottom(i) ); 25 | EXPECT_DOUBLE_EQ( 0., _bc.top(i) ); 26 | } 27 | for ( int j=0; j <= _ny; ++j ) { 28 | EXPECT_DOUBLE_EQ( 0., _bc.left(j) ); 29 | EXPECT_DOUBLE_EQ( 0., _bc.right(j) ); 30 | } 31 | } 32 | 33 | TEST_F( BCTest, CheckAssignment ) { 34 | // left boundary 35 | _bc.left(0) = 3.; 36 | EXPECT_DOUBLE_EQ( 3., _bc.left(0) ); 37 | _bc.left(_ny/2) = 4.; 38 | EXPECT_DOUBLE_EQ( 4., _bc.left(_ny/2) ); 39 | _bc.left(_ny) = 5.; 40 | EXPECT_DOUBLE_EQ( 5., _bc.left(_ny) ); 41 | 42 | // right boundary 43 | _bc.right(0) = 6.; 44 | EXPECT_DOUBLE_EQ( 6., _bc.right(0) ); 45 | _bc.right(_ny/2) = 7.; 46 | EXPECT_DOUBLE_EQ( 7., _bc.right(_ny/2) ); 47 | _bc.right(_ny) = 8.; 48 | EXPECT_DOUBLE_EQ( 8., _bc.right(_ny) ); 49 | 50 | // top boundary 51 | _bc.top(0) = 9.; 52 | EXPECT_DOUBLE_EQ( 9., _bc.top(0) ); 53 | _bc.top(_nx/2) = 10.; 54 | EXPECT_DOUBLE_EQ( 10., _bc.top(_nx/2) ); 55 | _bc.top(_nx) = 11.; 56 | EXPECT_DOUBLE_EQ( 11., _bc.top(_nx) ); 57 | 58 | // bottom boundary 59 | _bc.bottom(0) = 12.; 60 | EXPECT_DOUBLE_EQ( 12., _bc.bottom(0) ); 61 | _bc.bottom(_nx/2) = 13.; 62 | EXPECT_DOUBLE_EQ( 13., _bc.bottom(_nx/2) ); 63 | _bc.bottom(_nx) = 14.; 64 | EXPECT_DOUBLE_EQ( 14., _bc.bottom(_nx) ); 65 | 66 | } 67 | 68 | TEST_F( BCTest, CheckCorners ) { 69 | // left(0) should equal bottom(0) 70 | _bc.left(0) = 3.; 71 | EXPECT_DOUBLE_EQ( 3., _bc.bottom(0) ); 72 | _bc.bottom(0) = 4.; 73 | EXPECT_DOUBLE_EQ( 4., _bc.left(0) ); 74 | 75 | // top(0) should equal left(ny) 76 | _bc.top(0) = 6.; 77 | EXPECT_DOUBLE_EQ( 6., _bc.left(_ny) ); 78 | _bc.left(_ny) = 7.; 79 | EXPECT_DOUBLE_EQ( 7., _bc.top(0) ); 80 | 81 | // top(nx) should equal right(ny) 82 | _bc.right(_ny) = 8; 83 | EXPECT_DOUBLE_EQ( 8., _bc.top(_nx) ); 84 | _bc.top(_nx) = 9.; 85 | EXPECT_DOUBLE_EQ( 9., _bc.right(_ny) ); 86 | 87 | // bottom(nx) should equal right(0) 88 | _bc.bottom(_nx) = 10.; 89 | EXPECT_DOUBLE_EQ( 10., _bc.right(0) ); 90 | _bc.right(0) = 11.; 91 | EXPECT_DOUBLE_EQ( 11., _bc.bottom(_nx) ); 92 | } 93 | 94 | TEST_F( BCTest, BCEqualsDouble ) { 95 | const double val = 7.; 96 | _bc = val; 97 | for (int i=0; i<=_nx; ++i) { 98 | EXPECT_DOUBLE_EQ( val, _bc.bottom(i) ); 99 | EXPECT_DOUBLE_EQ( val, _bc.top(i) ); 100 | } 101 | for (int j=0; j<=_ny; ++j) { 102 | EXPECT_DOUBLE_EQ( val, _bc.left(j) ); 103 | EXPECT_DOUBLE_EQ( val, _bc.right(j) ); 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /test/CheckCurl.cc: -------------------------------------------------------------------------------- 1 | // Test Curl operation 2 | 3 | #include 4 | #include "ibpm.h" 5 | 6 | using namespace std; 7 | using namespace ibpm; 8 | 9 | void AdjointOfScalarCurl( const Flux& q, Scalar& f ) { 10 | // Loop over all Scalar fields 11 | for (int lev=0; lev 2 | #include "ibpm.h" 3 | 4 | using namespace std; 5 | using namespace ibpm; 6 | 7 | void printX(Flux q) { 8 | for (int lev=0; lev=0; --j) { 11 | for (int i=0; i<=q.Nx(); ++i) { 12 | cout << q(lev,X,i,j) << " "; 13 | } 14 | cout << endl; 15 | } 16 | cout << endl; 17 | } 18 | } 19 | 20 | // In FluxToXVelocity, scalar x(lev,i,j) depends on nearby flux values 21 | // Set q to the coefficient of each flux value that influences x(lev,i,j) 22 | void computeDependencies(int lev, int i, int j, Flux& q) { 23 | // Loop over all possible X-fluxes 24 | q = 0.; 25 | for (int l=0; l < q.Ngrid(); ++l) { 26 | for (int ind=q.begin(X); ind != q.end(X); ++ind) { 27 | Flux e( q.getGrid() ); 28 | Scalar x( q.getGrid() ); 29 | e = 0.; 30 | e(l,ind) = 1.; 31 | FluxToXVelocity(e, x); 32 | q(l,ind) = x(lev,i,j); 33 | } 34 | } 35 | } 36 | 37 | int main() { 38 | int nx=8; 39 | int ny=8; 40 | int ngrid=3; 41 | double length=8; // dx = 0.1 42 | Grid grid( nx, ny, ngrid, length, 0., 0. ); 43 | 44 | // Loop over all possible X-fluxes 45 | if (0) { 46 | for (int lev=0; lev 2 | #include "SingleWavenumber.h" 3 | #include "VectorOperations.h" 4 | #include "EllipticSolver.h" 5 | #include "Array.h" 6 | #include 7 | 8 | using namespace ibpm; 9 | using Array::Array2; 10 | 11 | namespace { 12 | 13 | const double tolerance = 1e-10; 14 | 15 | #define EXPECT_ALL_EQ(a,b) \ 16 | for (int lev=0; lev runner.err 44 | 45 | runner: lib $(TEST_FILES) gtest_main.a 46 | $(CXX) $(LDFLAGS) -o $@ $(TEST_FILES) gtest_main.a $(LIBS) 47 | 48 | lib: 49 | cd $(BUILDDIR) && make $(IBPMLIB) 50 | 51 | % : %.o lib 52 | $(CXX) $(LDFLAGS) -o $@ $< $(LIBS) 53 | 54 | %.o : %.cc 55 | $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $(INCPATH) $< 56 | 57 | # Usually you shouldn't tweak such internal variables, indicated by a 58 | # trailing _. 59 | GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) 60 | 61 | # For simplicity and to avoid depending on Google Test's 62 | # implementation details, the dependencies specified below are 63 | # conservative and not optimized. This is fine as Google Test 64 | # compiles fast and for ordinary users its source rarely changes. 65 | gtest-all.o : $(GTEST_SRCS_) 66 | $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ 67 | $(GTEST_DIR)/src/gtest-all.cc 68 | 69 | gtest_main.o : $(GTEST_SRCS_) 70 | $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ 71 | $(GTEST_DIR)/src/gtest_main.cc 72 | 73 | gtest.a : gtest-all.o 74 | $(AR) $(ARFLAGS) $@ $^ 75 | 76 | gtest_main.a : gtest-all.o gtest_main.o 77 | $(AR) $(ARFLAGS) $@ $^ 78 | 79 | clean: 80 | -$(RM) -r *.o 81 | 82 | distclean: clean 83 | -$(RM) runner 84 | 85 | depend: 86 | $(MAKEDEPEND) $(CXXFLAGS) $(INCPATH) *.cc > .depend 87 | 88 | -include .depend 89 | -------------------------------------------------------------------------------- /test/MotionTest.cc: -------------------------------------------------------------------------------- 1 | #include "FixedPosition.h" 2 | #include "PitchPlunge.h" 3 | #include "TangentSE2.h" 4 | #include 5 | 6 | using namespace ibpm; 7 | 8 | TEST( Motion, FixedPosition ) { 9 | double x = 1; 10 | double y = 2; 11 | double theta = 3; 12 | 13 | Motion* motion; 14 | motion = new FixedPosition( x, y, theta ); 15 | 16 | // Check stationary flag is true 17 | EXPECT_EQ( true, motion->isStationary() ); 18 | 19 | // Check position is correct 20 | TangentSE2 g = motion->getTransformation(0.); 21 | double a, b, omega; 22 | g.getPosition( a, b, omega ); 23 | EXPECT_DOUBLE_EQ( a, x ); 24 | EXPECT_DOUBLE_EQ( b, y ); 25 | EXPECT_DOUBLE_EQ( omega, theta ); 26 | 27 | // Check velocity is zero 28 | double adot, bdot, omegadot; 29 | g.getVelocity( adot, bdot, omegadot ); 30 | EXPECT_DOUBLE_EQ( adot, 0 ); 31 | EXPECT_DOUBLE_EQ( bdot, 0 ); 32 | EXPECT_DOUBLE_EQ( omegadot, 0 ); 33 | 34 | delete motion; 35 | } 36 | 37 | TEST( Motion, PitchPlunge ) { 38 | double pitchAmp = 2; 39 | double plungeAmp = 3; 40 | double pitchFreq = 4; 41 | double plungeFreq = 5; 42 | const double twopi = 8. * atan(1.); 43 | 44 | Motion* motion; 45 | motion = new PitchPlunge( pitchAmp, pitchFreq, plungeAmp, plungeFreq ); 46 | 47 | // Check stationary flag is false 48 | EXPECT_EQ( false, motion->isStationary() ); 49 | 50 | // Check position is correct 51 | TangentSE2 g = motion->getTransformation(0.); 52 | double x, y, theta; 53 | g.getPosition( x, y, theta ); 54 | EXPECT_DOUBLE_EQ( 0, x ); 55 | EXPECT_DOUBLE_EQ( 0, y ); 56 | EXPECT_DOUBLE_EQ( 0, theta ); 57 | 58 | // Check velocity is correct 59 | double xdot, ydot, thetadot; 60 | // WORK HERE 61 | g.getVelocity( xdot, ydot, thetadot ); 62 | EXPECT_DOUBLE_EQ( 0, xdot ); 63 | EXPECT_DOUBLE_EQ( plungeAmp * twopi * plungeFreq, ydot ); 64 | EXPECT_DOUBLE_EQ( pitchAmp * twopi * pitchFreq, thetadot ); 65 | // TODO: add phase shift to pitch/plunge 66 | // TODO: check different points in time 67 | } 68 | -------------------------------------------------------------------------------- /test/NavierStokesModelTest.cc: -------------------------------------------------------------------------------- 1 | #include "RigidBody.h" 2 | #include "Geometry.h" 3 | #include "NavierStokesModel.h" 4 | #include "SingleWavenumber.h" 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | using namespace ibpm; 10 | 11 | namespace { 12 | 13 | // Print a Scalar to standard out 14 | void print(const Scalar& f); 15 | 16 | class NavierStokesModelTest : public testing::Test { 17 | protected: 18 | NavierStokesModelTest() : 19 | _nx(4), 20 | _ny(4), 21 | _ngrid(1), 22 | _length(4.*atan(1.)), // length is pi 23 | _xOffset(-1), 24 | _yOffset(-3), 25 | _grid( _nx, _ny, _ngrid, _length, _xOffset, _yOffset ) { 26 | 27 | // Choose Reynolds number such that linear term is Laplacian 28 | _Reynolds = 1.; 29 | // Add the geometry 30 | RigidBody body; 31 | body.addPoint(0,0); 32 | _geom.addBody(body); 33 | double magnitude = 1.; 34 | double angle = 0.; 35 | BaseFlow q0( _grid, magnitude, angle ); 36 | _model = new NavierStokesModel( _grid, _geom, _Reynolds, q0 ); 37 | _model->init(); 38 | } 39 | 40 | Scalar linearTerm(const Scalar& g) { 41 | Scalar a( g.getGrid() ); 42 | Laplacian( g, a ); 43 | a *= _model->getAlpha(); 44 | return a; 45 | } 46 | 47 | // data 48 | int _nx; 49 | int _ny; 50 | int _ngrid; 51 | double _length; 52 | double _xOffset; 53 | double _yOffset; 54 | const Grid _grid; 55 | Geometry _geom; 56 | double _Reynolds; 57 | NavierStokesModel* _model; 58 | }; 59 | 60 | #define EXPECT_ALL_EQ(a,b) \ 61 | for (int i=1; i<_nx; ++i) { \ 62 | for (int j=1; j<_ny; ++j) { \ 63 | EXPECT_NEAR((a), (b), 3e-15); \ 64 | } \ 65 | } 66 | 67 | #define EXPECT_ALL_X_EQ(a,b) \ 68 | for ( int i=0; i<_nx+1; ++i ) { \ 69 | for ( int j=0; j<_ny; ++j ) { \ 70 | EXPECT_DOUBLE_EQ( (a), (b) ); \ 71 | } \ 72 | } 73 | 74 | #define EXPECT_ALL_Y_EQ(a,b) \ 75 | for ( int i=0; i<_nx; ++i ) { \ 76 | for ( int j=0; j<_ny+1; ++j ) { \ 77 | EXPECT_DOUBLE_EQ( (a), (b) ); \ 78 | } \ 79 | } 80 | /* 81 | 82 | // If the base flow is zero and 83 | // q = computeFlux(omega) 84 | // then curl(q) should equal omega 85 | TEST_F( NavierStokesModelTest, GammaToFlux ) { 86 | Scalar omega(_grid); 87 | Flux q(_grid); 88 | Scalar curlQ(_grid); 89 | 90 | // create a model with no base flow 91 | NavierStokesModel model( _grid, _geom, _Reynolds ); 92 | model.init(); 93 | // For a range of wavenumbers 94 | for (int xWavenumber = 0; xWavenumber < _nx; ++xWavenumber ) { 95 | for (int yWavenumber = 0; yWavenumber < _ny; ++yWavenumber) { 96 | InitializeSingleWavenumber( xWavenumber, yWavenumber, omega ); 97 | model.computeFlux( omega, q ); 98 | Curl( q, curlQ ); 99 | EXPECT_ALL_EQ( omega(0,i,j), curlQ(0,i,j) ); 100 | 101 | // Now put into a state vector and check refreshState() 102 | NavierStokesModel* modelp = &model; 103 | State x( _grid, _geom.getNumPoints() ); 104 | x.q = 0.; 105 | x.omega = omega; 106 | modelp->refreshState( x ); 107 | EXPECT_ALL_X_EQ( q(0,X,i,j), x.q(0,X,i,j) ); 108 | EXPECT_ALL_Y_EQ( q(0,Y,i,j), x.q(0,Y,i,j) ); 109 | } 110 | } 111 | } 112 | */ 113 | } // namespace 114 | -------------------------------------------------------------------------------- /test/OutputProbesTest.cc: -------------------------------------------------------------------------------- 1 | #include "OutputProbes.h" 2 | #include 3 | 4 | using namespace ibpm; 5 | 6 | namespace { 7 | 8 | double tol = 1e-14; 9 | 10 | class OutputProbesTest : public testing::Test { 11 | protected: 12 | OutputProbesTest( ) : 13 | _nx(8), 14 | _ny(12), 15 | _ngrid(3), 16 | _xLength(2), 17 | _yLength(_xLength * _ny/_nx), 18 | _xOffset(-1), 19 | _yOffset(-3), 20 | _dx(_xLength/_nx), 21 | _filename("testOutputProbes.probe"), 22 | _grid(_nx, _ny, _ngrid, _xLength, _xOffset, _yOffset), 23 | _flagInitialization(false), 24 | _probe(_filename, _grid) { 25 | } 26 | 27 | virtual ~OutputProbesTest() { } 28 | 29 | int _nx; 30 | int _ny; 31 | int _ngrid; 32 | double _xLength; 33 | double _yLength; 34 | double _xOffset; 35 | double _yOffset; 36 | double _dx; 37 | string _filename; 38 | Grid _grid; 39 | int _lev; 40 | int _numProbes; 41 | int _dimen; 42 | bool _flagInitialization; 43 | Array::Array2 _probePositions; 44 | OutputProbes _probe; 45 | }; 46 | 47 | TEST_F(OutputProbesTest, TestgetProbeInfoFunctions){ 48 | // test getNumProbes, getProbeIndexX, getProbeIndexY, addProbebyIndex, addProbebyPosition 49 | int i = 4; int j = 3; // probe 1 50 | int ii = 6; int jj = 8; // probe 2 51 | int lev = 0; 52 | OutputProbes probe(_filename, _grid); 53 | EXPECT_DOUBLE_EQ( 0, probe.getNumProbes() ); 54 | probe.addProbeByIndex( i , j ); 55 | EXPECT_DOUBLE_EQ( 1, probe.getNumProbes() ); 56 | probe.addProbeByIndex( ii, jj ); 57 | EXPECT_DOUBLE_EQ( 2, probe.getNumProbes() ); 58 | EXPECT_DOUBLE_EQ( i, probe.getProbeIndexX(1) ); 59 | EXPECT_DOUBLE_EQ( j, probe.getProbeIndexY(1) ); 60 | EXPECT_DOUBLE_EQ( ii, probe.getProbeIndexX(2) ); 61 | EXPECT_DOUBLE_EQ( jj, probe.getProbeIndexY(2) ); 62 | EXPECT_DOUBLE_EQ( _grid.getXEdge(lev, ii), probe.getProbeCoordX(2) ); 63 | EXPECT_DOUBLE_EQ( _grid.getYEdge(lev, jj), probe.getProbeCoordY(2) ); 64 | probe.addProbeByPosition( _grid.getXEdge(lev, ii), _grid.getYEdge(lev, jj) ); 65 | EXPECT_DOUBLE_EQ( 3, probe.getNumProbes() ); 66 | EXPECT_DOUBLE_EQ( ii, probe.getProbeIndexX(3) ); 67 | EXPECT_DOUBLE_EQ( jj, probe.getProbeIndexY(3) ); 68 | } 69 | 70 | } // namespace 71 | -------------------------------------------------------------------------------- /test/ParmParserTest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "ParmParser.h" 8 | 9 | using namespace std; 10 | 11 | namespace { 12 | 13 | // Utility function to construct an argument list (argc, argv) from 14 | // a given string 15 | void GetArgList(string s, int& argc, char**& argv ) { 16 | // First, count number of arguments 17 | istringstream in(s); 18 | argc = 0; 19 | string str; 20 | while ( in >> str ) { 21 | ++argc; 22 | } 23 | 24 | // Allocate memory for argv 25 | argv = (char **) malloc( argc * sizeof(char *) ); 26 | 27 | // Reset input stream and get arguments 28 | in.clear(); 29 | in.str(s); 30 | for (int i=0; i> str; 32 | argv[i] = (char *) malloc ( (str.length()+1) * sizeof(char) ); 33 | strcpy( argv[i], str.c_str() ); 34 | } 35 | } 36 | 37 | ParmParser* GetParser(string s) { 38 | int argc; 39 | char **argv; 40 | GetArgList( s, argc, argv ); 41 | ParmParser* parser = new ParmParser( argc, argv ); 42 | return parser; 43 | } 44 | 45 | TEST( ParmParserTest, True ) { 46 | EXPECT_EQ(1, 1); 47 | } 48 | 49 | TEST( ParmParserTest, CorrectArguments ) { 50 | string cmd = "a.out -b 1 -flag -fname myFile -ny 20 -nx 10 -length 3.14"; 51 | ParmParser* parser = GetParser( cmd ); 52 | int nx = parser->getInt( "nx", "description of nx", 100 ); 53 | EXPECT_EQ( 10, nx ); 54 | 55 | int ny = parser->getInt( "ny", "description of ny", 200 ); 56 | EXPECT_EQ( 20, ny ); 57 | 58 | double length = parser->getDouble( "length", "description", 10. ); 59 | EXPECT_DOUBLE_EQ( 3.14, length ); 60 | 61 | string fname = parser->getString( "fname", "description", "name" ); 62 | EXPECT_EQ( "myFile", fname ); 63 | 64 | bool on = parser->getBool( "b", "description", 0 ); 65 | EXPECT_EQ( true, on ); 66 | 67 | bool flag = parser->getFlag( "flag", "description" ); 68 | EXPECT_EQ( true, flag ); 69 | 70 | bool flag2 = parser->getFlag( "flag2", "description" ); 71 | EXPECT_EQ( false, flag2 ); 72 | 73 | EXPECT_EQ( true, parser->inputIsValid() ); 74 | EXPECT_EQ( "a.out -nx 10 -ny 20 -length 3.14 -fname myFile -b 1 -flag", 75 | parser->getParameters() ); 76 | 77 | delete parser; 78 | } 79 | 80 | TEST( ParmParserTest, BadArg ) { 81 | string cmd = "a.out -nx 10 bad"; 82 | ParmParser* parser = GetParser( cmd ); 83 | int nx = parser->getInt( "nx", "description", 100 ); 84 | EXPECT_EQ( 10, nx ); 85 | EXPECT_EQ( false, parser->inputIsValid() ); 86 | EXPECT_EQ( "a.out -nx 10", parser->getParameters() ); 87 | delete parser; 88 | } 89 | 90 | TEST( ParmParserTest, MissingValueAtEnd ) { 91 | string cmd = "a.out -nx"; 92 | ParmParser* parser = GetParser( cmd ); 93 | int nx = parser->getInt( "nx", "desc", 100 ); 94 | EXPECT_EQ( 100, nx ); 95 | EXPECT_EQ( false, parser->inputIsValid() ); 96 | EXPECT_EQ( "a.out", parser->getParameters() ); 97 | delete parser; 98 | } 99 | 100 | TEST( ParmParserTest, MissingValueInMiddle ) { 101 | string cmd = "a.out -nx -ny 20"; 102 | ParmParser* parser = GetParser( cmd ); 103 | int nx = parser->getInt( "nx", "desc", 100 ); 104 | EXPECT_EQ( 100, nx ); 105 | int ny = parser->getInt( "ny", "desc", 200 ); 106 | EXPECT_EQ( 20, ny ); 107 | EXPECT_EQ( false, parser->inputIsValid() ); 108 | EXPECT_EQ( "a.out -ny 20", parser->getParameters() ); 109 | delete parser; 110 | } 111 | 112 | } // namelist -------------------------------------------------------------------------------- /test/SingleWavenumber.h: -------------------------------------------------------------------------------- 1 | // SingleWavenumber.h - routine for initializing single-wavenumber fields 2 | #include "Grid.h" 3 | #include "Scalar.h" 4 | #include "Array.h" 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | using namespace ibpm; 10 | using Array::Array2; 11 | 12 | // Set the output Scalar f equal to sin(kx * x) * sin(ky * y) 13 | // with the specified wavenumbers in x and y 14 | inline void InitializeSingleWavenumber( 15 | int xWavenumber, 16 | int yWavenumber, 17 | Scalar& f 18 | ) { 19 | const double pi = 4 * atan(1.); 20 | const int nx = f.Nx(); 21 | const int ny = f.Ny(); 22 | const int ngrid = f.Ngrid(); 23 | const double x0 = f.getXEdge(ngrid-1,0); 24 | const double y0 = f.getYEdge(ngrid-1,0); 25 | const double xLength = f.getXEdge(ngrid-1,nx) - x0; 26 | const double yLength = f.getYEdge(ngrid-1,ny) - y0; 27 | const double kx = xWavenumber * pi / xLength; 28 | const double ky = yWavenumber * pi / yLength; 29 | 30 | for (int lev=0; lev < ngrid; ++lev ) { 31 | for (int i=1; i < nx; ++i) { 32 | double x = f.getXEdge(lev,i); 33 | for (int j=1; j < ny; ++j) { 34 | double y = f.getYEdge(lev,j); 35 | f(lev,i,j) = sin(kx * (x-x0)) * sin(ky * (y-y0)); 36 | } 37 | } 38 | } 39 | } 40 | 41 | // Set the output Array f equal to sin(kx * x) * sin(ky * y), 42 | // where the domain is length pi in each direction 43 | // The input array is assumed to have indices ( 1..nx, 1..ny ) 44 | inline void InitializeSingleWavenumber( 45 | int kx, 46 | int ky, 47 | Array2& f 48 | ) { 49 | int nx = f.Nx() + 1; 50 | int ny = f.Ny() + 1; 51 | const double pi = 4 * atan(1.); 52 | double dx = pi / nx; 53 | double dy = pi / ny; 54 | for (int i=1; i < nx; ++i) { 55 | for (int j=1; j < ny; ++j) { 56 | f(i,j) = sin( kx * i * dx ) * sin( ky * j * dy ); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test/StateTest.cc: -------------------------------------------------------------------------------- 1 | #include "State.h" 2 | #include 3 | #include 4 | 5 | using namespace ibpm; 6 | 7 | namespace { 8 | 9 | #define EXPECT_SCALAR_EQ(a,b) \ 10 | for (int lev=0; lev<_ngrid; ++lev) { \ 11 | for (int i=1; i<_nx; ++i) { \ 12 | for (int j=1; j<_ny; ++j) { \ 13 | EXPECT_DOUBLE_EQ((a), (b)); \ 14 | } \ 15 | } \ 16 | } 17 | 18 | #define EXPECT_FLUX_X_EQ(a,b) \ 19 | for (int lev=0; lev<_ngrid; ++lev) { \ 20 | for ( int i=0; i<_nx+1; ++i ) { \ 21 | for ( int j=0; j<_ny; ++j ) { \ 22 | EXPECT_DOUBLE_EQ( (a), (b) ); \ 23 | } \ 24 | } \ 25 | } 26 | 27 | #define EXPECT_FLUX_Y_EQ(a,b) \ 28 | for (int lev=0; lev<_ngrid; ++lev) { \ 29 | for ( int i=0; i<_nx; ++i ) { \ 30 | for ( int j=0; j<_ny+1; ++j ) { \ 31 | EXPECT_DOUBLE_EQ( (a), (b) ); \ 32 | } \ 33 | } \ 34 | } 35 | 36 | 37 | #define EXPECT_BV_EQ(a,b) \ 38 | for ( Direction dir=X; dir < XY; ++dir ) { \ 39 | for ( int i=0; i<_numPoints; ++i ) { \ 40 | EXPECT_DOUBLE_EQ( (a), (b) ); \ 41 | } \ 42 | } 43 | 44 | class StateTest : public testing::Test { 45 | protected: 46 | StateTest() : 47 | _nx(4), 48 | _ny(8), 49 | _ngrid(3), 50 | _numPoints(2), 51 | _grid( _nx, _ny, _ngrid, 2, -1, -2 ), 52 | _x( _grid, _numPoints ) { 53 | 54 | // Initialize a State 55 | _x.q = 1.; 56 | _x.omega = 2.; 57 | _x.f = 3.; 58 | _x.timestep = 4; 59 | _x.time = 0.5; 60 | } 61 | 62 | // data 63 | int _nx; 64 | int _ny; 65 | int _ngrid; 66 | int _numPoints; 67 | Grid _grid; 68 | State _x; 69 | }; 70 | 71 | TEST_F( StateTest, Save ) { 72 | bool success = _x.save("state_test"); 73 | EXPECT_EQ( true, success ); 74 | 75 | State y( _grid, _numPoints ); 76 | y.load( "state_test" ); 77 | EXPECT_SCALAR_EQ( _x.omega(lev,i,j), y.omega(lev,i,j) ); 78 | EXPECT_FLUX_X_EQ( _x.q(lev,X,i,j), y.q(lev,X,i,j) ); 79 | EXPECT_FLUX_Y_EQ( _x.q(lev,Y,i,j), y.q(lev,Y,i,j) ); 80 | EXPECT_BV_EQ( _x.f(dir,i), y.f(dir,i) ); 81 | EXPECT_DOUBLE_EQ( _x.time, y.time ); 82 | EXPECT_EQ( _x.timestep, y.timestep ); 83 | 84 | unlink("state_test"); 85 | } 86 | 87 | TEST_F( StateTest, LoadBadGeometry ) { 88 | bool status = _x.save("state_test"); 89 | ASSERT_EQ( true, status ); 90 | 91 | // Create another state with a different Geometry (no points) 92 | State y( _grid, 0 ); 93 | status = y.load( "state_test" ); 94 | EXPECT_EQ( false, status ); 95 | 96 | unlink("state_test"); 97 | } 98 | 99 | TEST_F( StateTest, LoadBadGrid ) { 100 | bool status = _x.save("state_test"); 101 | ASSERT_EQ( true, status ); 102 | 103 | // Create another state with a different Grid 104 | Grid newGrid( 4, 5, 1, 2, -1, -2 ); 105 | State y( newGrid, _numPoints ); 106 | status = y.load( "state_test" ); 107 | EXPECT_EQ( false, status ); 108 | 109 | unlink("state_test"); 110 | } 111 | 112 | } // namespace 113 | -------------------------------------------------------------------------------- /test/TangentSE2Test.cc: -------------------------------------------------------------------------------- 1 | #include "TangentSE2.h" 2 | #include 3 | #include 4 | 5 | using namespace ibpm; 6 | 7 | namespace { 8 | 9 | const double pi = 4 * atan(1); 10 | 11 | TEST( TangentSE2Test, Identity ) { 12 | TangentSE2 a( 0, 0, 0, 0, 0, 0 ); 13 | double x = 1; 14 | double y = 2; 15 | 16 | double x1, y1; 17 | a.mapPosition( x, y, x1, y1 ); 18 | EXPECT_DOUBLE_EQ( x, x1 ); 19 | EXPECT_DOUBLE_EQ( y, y1 ); 20 | 21 | double u, v; 22 | a.mapVelocity( x, y, u, v ); 23 | EXPECT_DOUBLE_EQ( u, 0 ); 24 | EXPECT_DOUBLE_EQ( v, 0 ); 25 | } 26 | 27 | TEST( TangentSE2Test, Stationary ) { 28 | TangentSE2 a( 1, 2, 0, 0, 0, 0 ); 29 | double x = 3; 30 | double y = 4; 31 | 32 | double x1, y1; 33 | a.mapPosition( x, y, x1, y1 ); 34 | EXPECT_DOUBLE_EQ( x1, x + 1 ); 35 | EXPECT_DOUBLE_EQ( y1, y + 2 ); 36 | 37 | double u, v; 38 | a.mapVelocity( x, y, u, v ); 39 | EXPECT_DOUBLE_EQ( u, 0 ); 40 | EXPECT_DOUBLE_EQ( v, 0 ); 41 | } 42 | 43 | TEST( TangentSE2Test, Rotate90 ) { 44 | TangentSE2 a( 0, 0, pi/2., 0, 0, 0 ); 45 | double x = 2; 46 | double y = 3; 47 | 48 | double x1, y1; 49 | a.mapPosition( x, y, x1, y1 ); 50 | EXPECT_DOUBLE_EQ( x1, -y ); 51 | EXPECT_DOUBLE_EQ( y1, x ); 52 | } 53 | 54 | TEST( TangentSE2Test, Moving ) { 55 | double u = 3; 56 | double v = 7; 57 | double omega = 11; 58 | TangentSE2 a( 0, 0, 0, u, v, omega ); 59 | double x = 5; 60 | double y = 0; 61 | 62 | double xdot, ydot; 63 | a.mapVelocity( x, y, xdot, ydot ); 64 | EXPECT_DOUBLE_EQ( xdot, u ); 65 | EXPECT_DOUBLE_EQ( ydot, v + x * omega ); 66 | } 67 | 68 | TEST( TangentSE2Test, MovingWithTranslation ) { 69 | double u = 3; 70 | double v = 7; 71 | double omega = 11; 72 | TangentSE2 a( 1, 2, pi/2, u, v, omega ); 73 | double x = 5; 74 | double y = 0; 75 | 76 | double xdot, ydot; 77 | a.mapVelocity( x, y, xdot, ydot ); 78 | EXPECT_DOUBLE_EQ( xdot, u + -x * omega ); 79 | EXPECT_DOUBLE_EQ( ydot, v + 0 ); 80 | } 81 | 82 | } // namespace 83 | -------------------------------------------------------------------------------- /test/gtest-1.6.0/COPYING: -------------------------------------------------------------------------------- 1 | Copyright 2008, Google Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above 11 | copyright notice, this list of conditions and the following disclaimer 12 | in the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Google Inc. nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /test/gtest-1.6.0/include/gtest/gtest_prod.h: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | // 32 | // Google C++ Testing Framework definitions useful in production code. 33 | 34 | #ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 35 | #define GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 36 | 37 | // When you need to test the private or protected members of a class, 38 | // use the FRIEND_TEST macro to declare your tests as friends of the 39 | // class. For example: 40 | // 41 | // class MyClass { 42 | // private: 43 | // void MyMethod(); 44 | // FRIEND_TEST(MyClassTest, MyMethod); 45 | // }; 46 | // 47 | // class MyClassTest : public testing::Test { 48 | // // ... 49 | // }; 50 | // 51 | // TEST_F(MyClassTest, MyMethod) { 52 | // // Can call MyClass::MyMethod() here. 53 | // } 54 | 55 | #define FRIEND_TEST(test_case_name, test_name)\ 56 | friend class test_case_name##_##test_name##_Test 57 | 58 | #endif // GTEST_INCLUDE_GTEST_GTEST_PROD_H_ 59 | -------------------------------------------------------------------------------- /test/gtest-1.6.0/src/gtest-all.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: mheule@google.com (Markus Heule) 31 | // 32 | // Google C++ Testing Framework (Google Test) 33 | // 34 | // Sometimes it's desirable to build Google Test by compiling a single file. 35 | // This file serves this purpose. 36 | 37 | // This line ensures that gtest.h can be compiled on its own, even 38 | // when it's fused. 39 | #include "gtest/gtest.h" 40 | 41 | // The following lines pull in the real gtest *.cc files. 42 | #include "src/gtest.cc" 43 | #include "src/gtest-death-test.cc" 44 | #include "src/gtest-filepath.cc" 45 | #include "src/gtest-port.cc" 46 | #include "src/gtest-printers.cc" 47 | #include "src/gtest-test-part.cc" 48 | #include "src/gtest-typed-test.cc" 49 | -------------------------------------------------------------------------------- /test/gtest-1.6.0/src/gtest-typed-test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2008 Google Inc. 2 | // All Rights Reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | // Author: wan@google.com (Zhanyong Wan) 31 | 32 | #include "gtest/gtest-typed-test.h" 33 | #include "gtest/gtest.h" 34 | 35 | namespace testing { 36 | namespace internal { 37 | 38 | #if GTEST_HAS_TYPED_TEST_P 39 | 40 | // Skips to the first non-space char in str. Returns an empty string if str 41 | // contains only whitespace characters. 42 | static const char* SkipSpaces(const char* str) { 43 | while (IsSpace(*str)) 44 | str++; 45 | return str; 46 | } 47 | 48 | // Verifies that registered_tests match the test names in 49 | // defined_test_names_; returns registered_tests if successful, or 50 | // aborts the program otherwise. 51 | const char* TypedTestCasePState::VerifyRegisteredTestNames( 52 | const char* file, int line, const char* registered_tests) { 53 | typedef ::std::set::const_iterator DefinedTestIter; 54 | registered_ = true; 55 | 56 | // Skip initial whitespace in registered_tests since some 57 | // preprocessors prefix stringizied literals with whitespace. 58 | registered_tests = SkipSpaces(registered_tests); 59 | 60 | Message errors; 61 | ::std::set tests; 62 | for (const char* names = registered_tests; names != NULL; 63 | names = SkipComma(names)) { 64 | const String name = GetPrefixUntilComma(names); 65 | if (tests.count(name) != 0) { 66 | errors << "Test " << name << " is listed more than once.\n"; 67 | continue; 68 | } 69 | 70 | bool found = false; 71 | for (DefinedTestIter it = defined_test_names_.begin(); 72 | it != defined_test_names_.end(); 73 | ++it) { 74 | if (name == *it) { 75 | found = true; 76 | break; 77 | } 78 | } 79 | 80 | if (found) { 81 | tests.insert(name); 82 | } else { 83 | errors << "No test named " << name 84 | << " can be found in this test case.\n"; 85 | } 86 | } 87 | 88 | for (DefinedTestIter it = defined_test_names_.begin(); 89 | it != defined_test_names_.end(); 90 | ++it) { 91 | if (tests.count(*it) == 0) { 92 | errors << "You forgot to list test " << *it << ".\n"; 93 | } 94 | } 95 | 96 | const String& errors_str = errors.GetString(); 97 | if (errors_str != "") { 98 | fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), 99 | errors_str.c_str()); 100 | fflush(stderr); 101 | posix::Abort(); 102 | } 103 | 104 | return registered_tests; 105 | } 106 | 107 | #endif // GTEST_HAS_TYPED_TEST_P 108 | 109 | } // namespace internal 110 | } // namespace testing 111 | -------------------------------------------------------------------------------- /test/gtest-1.6.0/src/gtest_main.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2006, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | #include 31 | 32 | #include "gtest/gtest.h" 33 | 34 | GTEST_API_ int main(int argc, char **argv) { 35 | std::cout << "Running main() from gtest_main.cc\n"; 36 | 37 | testing::InitGoogleTest(&argc, argv); 38 | return RUN_ALL_TESTS(); 39 | } 40 | --------------------------------------------------------------------------------