voro++-0.4.6/000700 000765 000024 00000000000 12230024355 012535 5ustar00chrstaff000000 000000 voro++-0.4.6/config.mk000600 000765 000024 00000001204 12230022105 014321 0ustar00chrstaff000000 000000 # Voro++, a 3D cell-based Voronoi library # # Author : Chris H. Rycroft (LBL / UC Berkeley) # Email : chr@alum.mit.edu # Date : August 28th 2011 # This a common configuration file that includes definitions used by all # the Makefiles. # C++ compiler CXX=g++ # Flags for the C++ compiler CFLAGS=-Wall -ansi -pedantic -O3 # Relative include and library paths for compilation of the examples E_INC=-I../../src E_LIB=-L../../src # Installation directory PREFIX=/usr/local # Install command INSTALL=install # Flags for install command for executable IFLAGS_EXEC=-m 0755 # Flags for install command for non-executable files IFLAGS=-m 0644 voro++-0.4.6/examples/000700 000765 000024 00000000000 12230022105 014342 5ustar00chrstaff000000 000000 voro++-0.4.6/LICENSE000600 000765 000024 00000004542 12230022105 013540 0ustar00chrstaff000000 000000 Voro++ Copyright (c) 2008, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: (1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory, U.S. Dept. of Energy nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. You are under no obligation whatsoever to provide any bug fixes, patches, or upgrades to the features, functionality or performance of the source code ("Enhancements") to anyone; however, if you choose to make your Enhancements available either publicly, or directly to Lawrence Berkeley National Laboratory, without imposing a separate written license agreement for such Enhancements, then you hereby grant the following license: a non-exclusive, royalty-free perpetual license to install, use, modify, prepare derivative works, incorporate into other computer software, distribute, and sublicense such enhancements or derivative works thereof, in binary and source code form. voro++-0.4.6/Makefile000600 000765 000024 00000005160 12230022105 014170 0ustar00chrstaff000000 000000 # Voro++ makefile # # Author : Chris H. Rycroft (LBL / UC Berkeley) # Email : chr@alum.mit.edu # Date : August 30th 2011 # Tell make that these are phony targets .PHONY: all help clean install uninstall include config.mk # Build all of the executable files all: $(MAKE) -C src $(MAKE) -C examples # Build the help files (with Doxygen) help: $(MAKE) -C src help # Clean up the executable files clean: $(MAKE) -C src clean $(MAKE) -C examples clean # Install the executable, man page, and shared library install: $(MAKE) -C src $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/bin $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/lib $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/man $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/man/man1 $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/include $(INSTALL) -d $(IFLAGS_EXEC) $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS_EXEC) src/voro++ $(PREFIX)/bin $(INSTALL) $(IFLAGS) man/voro++.1 $(PREFIX)/man/man1 $(INSTALL) $(IFLAGS) src/libvoro++.a $(PREFIX)/lib $(INSTALL) $(IFLAGS) src/voro++.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/c_loops.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/cell.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/common.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/config.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/container.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/container_prd.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/rad_option.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/pre_container.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/unitcell.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/v_base.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/v_compute.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/wall.hh $(PREFIX)/include/voro++ $(INSTALL) $(IFLAGS) src/worklist.hh $(PREFIX)/include/voro++ # Uninstall the executable, man page, and shared library uninstall: rm -f $(PREFIX)/bin/voro++ rm -f $(PREFIX)/man/man1/voro++.1 rm -f $(PREFIX)/lib/libvoro++.a rm -f $(PREFIX)/include/voro++/voro++.hh rm -f $(PREFIX)/include/voro++/c_loops.hh rm -f $(PREFIX)/include/voro++/cell.hh rm -f $(PREFIX)/include/voro++/common.hh rm -f $(PREFIX)/include/voro++/config.hh rm -f $(PREFIX)/include/voro++/container.hh rm -f $(PREFIX)/include/voro++/container_prd.hh rm -f $(PREFIX)/include/voro++/pre_container.hh rm -f $(PREFIX)/include/voro++/rad_option.hh rm -f $(PREFIX)/include/voro++/unitcell.hh rm -f $(PREFIX)/include/voro++/v_base.hh rm -f $(PREFIX)/include/voro++/v_compute.hh rm -f $(PREFIX)/include/voro++/wall.hh rm -f $(PREFIX)/include/voro++/worklist.hh rmdir $(PREFIX)/include/voro++ voro++-0.4.6/man/000700 000765 000024 00000000000 12230024322 013302 5ustar00chrstaff000000 000000 voro++-0.4.6/NEWS000600 000765 000024 00000045634 12230022760 013250 0ustar00chrstaff000000 000000 Version 0.4.6 (October 17th 2013) ================================= * Fixed an issue with template instantiation in wall.cc that was causing compilation problems with new versions of Apple Xcode. Thanks to Barend Thijsse (Delft University of Technology) and Juan Pablo Cruz Pérez (Instituto de Física y Matemáticas) for pointing this out. * Added routines to the container classes to compute a ghost Voronoi cell at any given location, as though an extra particle was inserted at that location * Removed unused private variable in c_loops.hh * Updated Doxyfile to 1.8.5 Version 0.4.5 (July 27th 2012) ============================== * Removed "using namespace std" from the header files and added extra "std::" qualifiers on STL vectors and queues. This is to prevent naming conflicts with other libraries. Thanks to Florian Hoffmann (University of Luxembourg) for pointing this out. * Fixed an error in the check_facets diagnostic routine. Thanks to Tristan Carrier-Baudouin (Université catholique de Louvain) for pointing this out. * Fixed a memory leak in the new container_periodic class. Thanks to Massimo Marchi (Commissariat á l'Energie Atomique) for pointing this out. * Removed some duplicate or unnecessary #include statements of the standard C++ header files * Fix small naming mismatch between cell.cc and cell.hh in plane_intersects and nplane routines, which would give a warning with Doxygen * More changes for older MS Visual C++ compatability * Updated Doxyfile to 1.8.1.1 Version 0.4.4 (January 17th 2012) ================================= * Fixed an error in pointer arithmetic that was introduced in version 0.4, which would occur in cases where the delete stack was extended when a large number of vertices were being removed. Thanks to Jeff Johnson (Lawrence Berkeley Laboratory) and Matt Freeman (Texas A&M University) for pointing this out. Version 0.4.3 (November 12th 2011) ================================== * Removed spurious Gnuplot output line from torus.cc example * More changes for better Visual C++ compatibility * Fixed indexing error in worklist generation routine. This had no effect on the generated worklists, but would become apparent in other situations. * Added rad_option.hh to the list of files included by voro++.hh for completeness * Fix errors in Gnuplot commands in the basic examples README file. Thanks to William-Fernando Oquendo (National University of Colombia) for pointing this out. * Fixed memory allocation issue in face_freq_table routine - thanks to Lingti Kong for pointing this out * Minor cleanups and optimizations to wall classes Version 0.4.2 (September 23rd 2011) =================================== * Fixed a bug in the put_remap routine where a z periodic boolean was switched to an x periodic boolean. This would only be noticed when using mixed periodic boundary conditions and importing particles that need to be remapped. * The pid function in the c_loop_base class was mistakenly labeled as double instead of int - this is now fixed. Thanks to William-Fernando Oquendo (National University of Colombia) for pointing this out. * Fixed an extremely subtle bounds checking issue that would only materialize for the radical Voronoi tessellation with large particle radii. Thanks to Richard Martin and Maciej Haranczyk (Lawrence Berkeley Laboratory) for pointing out the original problem. * Fixed other problems with the radical tessellation. Originally, the algorithms were concieved for with hard spheres in mind, where the particles would not overlap, and an assumption was used in the cutoff procedure that made use of this, but would not be true in general. * Removed more bracket initializations like "double a(3);" for better consistency, and more compatibility with older versions of MS Visual C++. Thanks to Martin Brehm for help with this. * Factored out the regular/radical inline routines into separate classes, so that they don't have to be duplicated in the container_periodic classes * Fixed problems with the container_periodic classes referencing the wrong loop classes. Thanks to Wang Chuncheng (Nanyang Technological University) for pointing this out. * Added c_loop_order_periodic class for doing ordered loops with the periodic container classes * Updated the README file in the src directory. The detailed description of each file has been removed since this is difficult to maintain and this information is already present in the class reference manual. * Fixed an error in the pre_container selection of the optimal computational grid size * Code comment cleanups, particularly in wall.hh * Minor man page reformatting * Updated Doxyfile to version 1.7.5.1 Version 0.4.1 (September 7th 2011) ================================== * Fixed bug in command-line utility that would give incorrect results when using the "-c" option for custom output. Thanks to Prof. Aldo Romero (CINVESTAV-Unidad Queretaro) for pointing this out. * Added some additional documentation about neighbor information Version 0.4 (August 30th 2011) ============================== * New classes called container_periodic and container_periodic_poly that carry out Voronoi computations in 3D periodic parallelepiped unit cells have been added. This adds significant complexity to the computation, and the memory organization of these classes is different, requiring allocation for ghost regions. Currently these classes cannot be accessed by the command-line utility, but will be integrated further in future releases. These classes are currently mainly exploited by a sister software project Zeo++ for chemical informatics (Maciej Haranczyk, Chris Rycroft, Thomas Willems, Richard Martin) to be released in late 2011. * As part of the new container_periodic classes, a new class called unitcell has been added, which will compute the Voronoi cell for a single particle in a 3D periodic parallelepiped class. The Voronoi cell is formed by the influences of the periodic images of itself only. This turns out to be an important component of the calculations done by the container_periodic classes but can also be used independently. * The container classes now have a routine called find_voronoi_cell that will take a given position vector and return the Voronoi cell which is contained within. For the regular Voronoi tessellation, this is just the Voronoi cell corresponding to the closest particle (by definition). For the radical Voronoi tessellation, this is weighted by the particle radii. * The library is now enclosed within the "voro" namespace. This requires specifying "using namespace voro;" in the preamble of codes or prepending "voro::" to access functions. This greatly minimizes the possiblity of naming conflicts when using multiple libraries, particularly since many of the classes iin the library have fairly generic names (eg. "container"). Thanks to Allan Johns (Dr. D Studios) for suggesting this. * Voro++ can now be built as a static library that can be installed and linked to. As part of this, the .cc and .hh files have been significantly revised with some small inline functions and template code being written into the header files. * Previously, all of the voronoicell output routines sent data to an output stream. However, input and output are now carried out using the STL vector class, allowing for programs to directly link to and use Voro++ output. The STL vector class has been chosen since it the simplest and most standard mechanism for returning a variable amount of data. Several new examples are provided to demonstrate this functionality, for both the voronoicell class and the container class. * A common issue has been that the order of particles in the output file does not match the input file, since Voro++ internally sorts particles according to their position. A new class called voro_order has been provided, which can link to particles as they are stored, allowing for the Voronoi computation to be carried out in the same order as the input file. The core computation routines can be run with a variety of different loops, and a new example "loops.cc" is provided to demonstrate this. * The order of parameters to certain functions have been changed to take advantage of the C++ default parameter mechanism wherever possible * The container and container_poly classes are now derived from a base class, rather than being different instances of a template. This simplifies the code and stops common routines from being duplicated. The core Voronoi computation routine is now held within a voro_compute class, which can be instantiated on any container with the correct access functions. * The voronoicell and voronoicell_neighbor classes are now derived from a common base class, rather than being different instances of a template. This simplifies the code and stops common routines from being duplicated. The core nplane routine is now a function template that can be instantiated on the parent class itself. * All output routines have been switched from using C++ iostreams to using the C cstdio library. This has been done for increased performance. In general the cstdio routines run significantly faster than the comparable iostream routines: for one file import test, using fscanf from cstdio was five times as fast as the comparable << operator from iostream. As another example, the program "cylinder.cc", which uses both file import and export, runs approximately twice as fast before. Since many people use Voro++ to batch process large numbers of input files, this increase in input/output speed seemed desirable. * The Gnuplot output routines now merge individual lines into contiguous paths wherever possible, resulting in a ~15% reduction in their file size and a noticeable improvement in rendering speed * Previously, the POV-Ray output routines could create cylinders where the start and end points matched. This was a benign problem, due to the fact the vertex positions within Voro++ were held to higher precision than the POV-Ray output file, meaning that distinct vertices could appear to be at the same position; a perl script was provided to post-process and remove these. However, Voro++ now scans each cylinder before saving to file to automatically remove these cases from consideration. * Pointer arithmetic is now used within a number of critical cell computation routines, and gives a speedup of 10%-20% in many cases. On some typical problems on typical machines, Voro++ currently computes around 50,000 cells/second. New machines can achieve upwards of 70,000 cells/second. * A new pre-container mechanism is provided, which can read in a file of unknown length, and then make a guess at the correct computational grid size to use. This removes the need for specifying a length scale with the command-line utility. However, a length scale or grid decomposition can still be manually specified. * Removed the option to compile in single-precision. This was a highly specialized feature, and it appears better to allow users who wish to do this to make their own modifications. This option also conflicted with building Voro++ as a standard static library. * Fixed a benign bug in the block computation list that would cause it to get extended prematurely * Numerous small improvements to memory allocation routines * Added routines to copy a Voronoi cell * Created a new wall_list class to handle a list of walls. This simplifies the command-line utility code. * Labels in the worklist that are used in the transition from the radius search to the block search have been optimized * The command-line utility can now produce POV-Ray output. Also, the main loop in the utility has been combined so that the Voronoi tessellation is only carried out once, even if POV-Ray and Gnuplot output is also required. * The command-line utility does range checking on the filename to prevent buffer overruns * The routines that put particles into a container now do so more reliably for periodic cases, remapping them into the primary domain if necessary * A number of the POV-Ray header files have been altered to directly make use of a right-handed coordinate system in which the z axis points upwards. This matches the Gnuplot style, and the style used in many scientific simulations. It avoids the need for a rotation or matrix transformation when rendering many of the particle packings. Some of the test particle packings have been transformed to ensure consistency with previous renderings. * Some POV-Ray files have been cleaned up and there are additional comments * Fixed a bug in the print_all_custom() routine, affecting "%P" output. Thanks to David Waroquiers (Université Catholique de Louvain, Belgium) for pointing this out. * Fixed a bug that caused the neighbor list not to be outputted in the same order as the other plane diagnostic routines. Thanks to Olufemi Olorode (Texas A&M University) for pointing this out. * Removed the add_vertex() and init_test() routines, which were mainly used for debugging * Updated Doxyfile to version 1.7.4 Version 0.3.1 (September 29, 2009) ================================== * Carried out a major overhaul of the source code comments that are used by Doxygen. Several errors in the documentation were fixed. * Additional comments in the Makefiles, and added the "phony target" keyword * Many code cleanups and standardizations. Some double and triple loops were concatenated into one to reduce the amount of indentation. * Fixed the import.cc example program * Updated Doxyfile to version 1.6.1 Version 0.3 (August 17, 2009) ============================= * In response to feedback from several people, the routines for computing statistics about computed Voronoi cells have been significantly revised, extended, and put within a common framework. The voronoicell class now has a large number of routines of the form output_...() that will print cell information to an output stream. There are also a number of new, simple routines for computing basic statistics such as the number of edges and faces of each cell. All of these routines can now be used during the container analysis, by making use of the new print_custom() routine, which can output according to a given format string, that uses control sequences similar to the standard C printf() routine. * Renamed the "radical" example directory to "custom", and added two new programs called "cell_statistics.cc" and "custom_output.cc" for demonstrating the new output routines for the voronoicell and container classes respectively * Added a routine for computing the centroid of a Voronoi cell * Added new routines for computing neighbor normals, in response to a request from Dave Greenwood * Removed unnecessary trailing tabs and spaces in the source code * Fixed a few text justification problems, and altered some of the comments in the example programs * Improved the command-line utility, allowing it to specify custom information in the output. Implemented better error checking on command-line arguments. * Removed the facets() routine, since this has been superseded by the new output_...() routines. This also rendered some functions in the neighbor_none and neighbor_track classes obsolete, and they have also been removed. * Some reorganization of the cell.hh and container.hh header files to group similar functions together * Added torus.cc example that shows how to write custom walls as derived classes * Updated Doxyfile to version 1.5.9 Version 0.2.7 (March 25, 2009) ============================== * Added some missing cstdlib and cstring header files that cause compilation errors on some systems * Some text cleanups in the main README file and cmd_line.cc * The worklist_gen.pl script was in DOS format. It has been switched to Unix format to match the rest of the code. * Fixed some incorrect inequalities in degenerate2.cc * Improved some error messages in container.cc Version 0.2.6 (March 23, 2009) ============================== * Significantly improved the error messages generated by the code. It now makes use of the exit() routine rather than throwing errors, and it returns various status codes (defined in config.hh) for different types of abnormal behavior. * Changed two occurences of "cin" to "cout" in the draw_particles routines * Corrected error in comment in the tetrahedron example * Minor comment cleanups of the worklist_gen.pl script * Updated Doxyfile to version 1.5.8 * Added a routine print_facet_information() in response to a problem from Hengxing Lan * Many of the cell based statistics routines (like number_of_faces() and facets()) internally track their progress by temporarily flipping the edge table entries to negative values, so that they know where they have already been. The common code that was used at the end of each of these functions for resetting the edges back to positive has now been made into a private inline function called reset_edges(). * Fixed a missing initialization of max_radius to zero in the radius_poly class. This should not have ever caused any errors, as max_radius would always have been big enough. However if max_radius was initially set to a large value, it could have potentially made the code run slower. * Fixed the code layout in the suretest class header * Added some additional checks in the command-line utility to screen out invalid command-line arguments. Switched the test on the number of computational blocks to use floating point arithmetic, because integers could potentially overflow and become negative. * Included several more of the POV-Ray header files that were used to create the example images on the website * Removed a "cout" statement in the wall_cone class * Cleanup of the README files for the basic examples and the wall examples Version 0.2.5 (January 1, 2009) =============================== * Added the DOE acknowledgements to the code overview document Version 0.2.4 (December 14, 2008) ================================= * Added the code overview PDF document to the package, in the docs directory * Fixed some spelling errors in the comments * Many more documentation updates Version 0.2.3 (December 9, 2008) ================================ * Removed an unused variable that was reported by the Portland C compiler * Documentation updates * Added the import.pov script * Added some simple functions to solve the problem from Stefan Eibl of counting faces * Renamed the facets_loop to voropp_loop Version 0.2.2 (November 19, 2008) ================================= * Main README file updated Version 0.2.1 (November 3, 2008) ================================ * Much more documentation * Brief Doxygen class comments * Updated Doxyfile to version 1.5.7 Version 0.2 (October 31, 2008) ============================== * Updated some occurrences of char* with const char* for compatability with version 4.2 of the GNU C++ compiler * Making use of default parameters in the wall classes * The command-line utility can now add walls Version 0.1 (August 22, 2008) ============================= * Initial version uploaded to the web voro++-0.4.6/README000600 000765 000024 00000016652 12230022105 013420 0ustar00chrstaff000000 000000 Voro++, a 3D cell-based Voronoi library (http://math.lbl.gov/voro++/) By Chris H. Rycroft (UC Berkeley / Lawrence Berkeley Laboratory) ================================================================ Voro++ is a software library for carrying out three-dimensional computations of the Voronoi tessellation. A distinguishing feature of the Voro++ library is that it carries out cell-based calculations, computing the Voronoi cell for each particle individually, rather than computing the Voronoi tessellation as a global network of vertices and edges. It is particularly well-suited for applications that rely on cell-based statistics, where features of Voronoi cells (eg. volume, centroid, number of faces) can be used to analyze a system of particles Voro++ comprises of several C++ classes that can be built as a static library and linked to. A command-line utility is also provided that can analyze text files of particle configurations and use most of the features of the code. Numerous examples are provided to demonstrate the library's features and all of these are discussed in detail on the library website. Compilation - Linux / Mac OS / Windows with Cygwin ================================================== The code is written in ANSI C++, and compiles on many system architectures. The package contains the C++ source code, example files, miscellaneous utilities and documentation. On Linux, Mac OS, and Windows (using Cygwin), the compilation and installed can be carried out using GNU Make. To begin, the user should review the file "config.mk" in the top level directory, to make sure that the compilation and installation settings are appropriate for their system. Typing "make" will then compile the static library, command-line utility, and examples. The command-line utility and library will appear within the "src" directory. Following successful compilation, the library, command-line utility, and documentation can be installed by typing "sudo make install". By default, the program files are installed into /usr/local, and it may be necessary to modify your environment variables in order to access the installed files: - to use the command-line utility, the variable PATH should contain /usr/local/bin. - to access the Voro++ man page, the variable MANPATH should contain /usr/local/man. - to access the Voro++ header files, code compilation should include the flag '-I/usr/local/include/voro++'. - to link to the static library, code compilation should include the flags '-L/usr/local/lib' to tell the linker where to look, and then '-lvoro++' to link to the library. The library website contains additional notes on setting environment variables, and many guides are available on the Internet. The code can later be uninstalled with "sudo make uninstall". It is also possible to use the library and command-line utility without installation by calling the files directly once they have been compiled. On systems where the user does not have root privileges to install into /usr/local, the "config.mk" file can be modified to install into the user's home directory by setting PREFIX=$(HOME). Voro++ supports parallel compilation by using the "make -j " command where n is the number of threads. Compilation - Windows without Cygwin ==================================== On a Windows machine without a terminal environment like Cygwin, it is possible to import and compile the library in many standard C++ development environments. Users have reported success in building the library with Microsoft Visual C++ Express and Code::Blocks. Related programs ================ No external dependencies are required to compile and run the code, but several programs may be useful for analyzing the output: - The freeware plotting program Gnuplot (available at www.gnuplot.info) can be used for rapid 2D and 3D visualization of the program output. - The freeware raytracer POV-Ray (available at www.povray.org) can be used for high-quality renderings of the program output. - The reference manual is generated from comments in the source code using Doxygen (available at www.doxygen.org). This package is only required if the library files are being developed and the reference manuals need to be regenerated. The complete reference manual to the current code is available online at http://math.lbl.gov/voro++/doc/refman/ Contents ======== examples - many documented examples making use of the library html - an HTML-based reference manual (generated by Doxygen) man - contains the man page that is installed with the program scripts - miscellaneous helper scripts src - source code files Usage ===== Voro++ is released as free software through the Lawrence Berkeley National Laboratory - a detailed copyright notice is provided below, and the complete terms of the license can be found in the LICENSE file. I am very interested to hear from users of the software, so if you find this useful, please email me at chr@alum.mit.edu. Also, if you plan to publish an academic paper using this software, please consider citing one of the following publications: - Chris H. Rycroft, "Voro++: A three-dimensional Voronoi cell library in C++", Chaos 19, 041111 (2009). - Chris H. Rycroft, Gary S. Grest, James W. Landry, and Martin Z. Bazant, "Analysis of Granular Flow in a Pebble-Bed Nuclear Reactor", Phys. Rev. E 74, 021306 (2006). - Chris H. Rycroft, "Multiscale Modeling in Granular Flow", PhD thesis submitted to the Massachusetts Institute of Technology, September 2007. (http://math.berkeley.edu/~chr/publish/phd.html) The first reference contains a one-page overview of the library. The second reference contains some of the initial images that were made using a very early version of this code, to track small changes in packing fraction in a large particle simulation. The third reference discusses the use of 3D Voronoi cells, and describes the algorithms that were employed in the early version of this code. Since the publication of the above references, the algorithms in Voro++ have been significantly improved, and a paper specifically devoted to the current code architecture will be published during 2012. Copyright Notice ================ Voro++ Copyright (c) 2008, The Regents of the University of California, through Lawrence Berkeley National Laboratory (subject to receipt of any required approvals from the U.S. Dept. of Energy). All rights reserved. If you have questions about your rights to use or distribute this software, please contact Berkeley Lab's Technology Transfer Department at TTD@lbl.gov. NOTICE. This software was developed under partial funding from the U.S. Department of Energy. As such, the U.S. Government has been granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software to reproduce, prepare derivative works, and perform publicly and display publicly. Beginning five (5) years after the date permission to assert copyright is obtained from the U.S. Department of Energy, and subject to any subsequent five (5) year renewals, the U.S. Government is granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software to reproduce, prepare derivative works, distribute copies to the public, perform publicly and display publicly, and to permit others to do so. Acknowledgments =============== This work was supported by the Director, Office of Science, Computational and Technology Research, U.S. Department of Energy under Contract No. DE-AC02-05CH11231. voro++-0.4.6/scripts/000700 000765 000024 00000000000 12230022105 014213 5ustar00chrstaff000000 000000 voro++-0.4.6/src/000700 000765 000024 00000000000 12230024764 013330 5ustar00chrstaff000000 000000 voro++-0.4.6/src/c_loops.cc000600 000765 000024 00000012524 12230022105 015266 0ustar00chrstaff000000 000000 // Voro++, a 3D cell-based Voronoi library // // Author : Chris H. Rycroft (LBL / UC Berkeley) // Email : chr@alum.mit.edu // Date : August 30th 2011 /** \file c_loops.cc * \brief Function implementations for the loop classes. */ #include "c_loops.hh" namespace voro { /** Initializes a c_loop_subset object to scan over all particles within a * given sphere. * \param[in] (vx,vy,vz) the position vector of the center of the sphere. * \param[in] r the radius of the sphere. * \param[in] bounds_test whether to do detailed bounds checking. If this is * false then the class will loop over all particles in * blocks that overlap the given sphere. If it is true, * the particle will only loop over the particles which * actually lie within the sphere. * \return True if there is any valid point to loop over, false otherwise. */ void c_loop_subset::setup_sphere(double vx,double vy,double vz,double r,bool bounds_test) { if(bounds_test) {mode=sphere;v0=vx;v1=vy;v2=vz;v3=r*r;} else mode=no_check; ai=step_int((vx-ax-r)*xsp); bi=step_int((vx-ax+r)*xsp); aj=step_int((vy-ay-r)*ysp); bj=step_int((vy-ay+r)*ysp); ak=step_int((vz-az-r)*zsp); bk=step_int((vz-az+r)*zsp); setup_common(); } /** Initializes the class to loop over all particles in a rectangular subgrid * of blocks. * \param[in] (ai_,bi_) the subgrid range in the x-direction, inclusive of both * ends. * \param[in] (aj_,bj_) the subgrid range in the y-direction, inclusive of both * ends. * \param[in] (ak_,bk_) the subgrid range in the z-direction, inclusive of both * ends. * \return True if there is any valid point to loop over, false otherwise. */ void c_loop_subset::setup_intbox(int ai_,int bi_,int aj_,int bj_,int ak_,int bk_) { ai=ai_;bi=bi_;aj=aj_;bj=bj_;ak=ak_;bk=bk_; mode=no_check; setup_common(); } /** Sets up all of the common constants used for the loop. * \return True if there is any valid point to loop over, false otherwise. */ void c_loop_subset::setup_common() { if(!xperiodic) { if(ai<0) {ai=0;if(bi<0) bi=0;} if(bi>=nx) {bi=nx-1;if(ai>=nx) ai=nx-1;} } if(!yperiodic) { if(aj<0) {aj=0;if(bj<0) bj=0;} if(bj>=ny) {bj=ny-1;if(aj>=ny) aj=ny-1;} } if(!zperiodic) { if(ak<0) {ak=0;if(bk<0) bk=0;} if(bk>=nz) {bk=nz-1;if(ak>=nz) ak=nz-1;} } ci=ai;cj=aj;ck=ak; di=i=step_mod(ci,nx);apx=px=step_div(ci,nx)*sx; dj=j=step_mod(cj,ny);apy=py=step_div(cj,ny)*sy; dk=k=step_mod(ck,nz);apz=pz=step_div(ck,nz)*sz; inc1=di-step_mod(bi,nx); inc2=nx*(ny+dj-step_mod(bj,ny))+inc1; inc1+=nx; ijk=di+nx*(dj+ny*dk); q=0; } /** Starts the loop by finding the first particle within the container to * consider. * \return True if there is any particle to consider, false otherwise. */ bool c_loop_subset::start() { while(co[ijk]==0) {if(!next_block()) return false;} while(mode!=no_check&&out_of_bounds()) { q++; while(q>=co[ijk]) {q=0;if(!next_block()) return false;} } return true; } /** Initializes the class to loop over all particles in a rectangular box. * \param[in] (xmin,xmax) the minimum and maximum x coordinates of the box. * \param[in] (ymin,ymax) the minimum and maximum y coordinates of the box. * \param[in] (zmin,zmax) the minimum and maximum z coordinates of the box. * \param[in] bounds_test whether to do detailed bounds checking. If this is * false then the class will loop over all particles in * blocks that overlap the given box. If it is true, the * particle will only loop over the particles which * actually lie within the box. * \return True if there is any valid point to loop over, false otherwise. */ void c_loop_subset::setup_box(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax,bool bounds_test) { if(bounds_test) {mode=box;v0=xmin;v1=xmax;v2=ymin;v3=ymax;v4=zmin;v5=zmax;} else mode=no_check; ai=step_int((xmin-ax)*xsp); bi=step_int((xmax-ax)*xsp); aj=step_int((ymin-ay)*ysp); bj=step_int((ymax-ay)*ysp); ak=step_int((zmin-az)*zsp); bk=step_int((zmax-az)*zsp); setup_common(); } /** Computes whether the current point is out of bounds, relative to the * current loop setup. * \return True if the point is out of bounds, false otherwise. */ bool c_loop_subset::out_of_bounds() { double *pp=p[ijk]+ps*q; if(mode==sphere) { double fx(*pp+px-v0),fy(pp[1]+py-v1),fz(pp[2]+pz-v2); return fx*fx+fy*fy+fz*fz>v3; } else { double f(*pp+px);if(fv1) return true; f=pp[1]+py;if(fv3) return true; f=pp[2]+pz;return fv5; } } /** Returns the next block to be tested in a loop, and updates the periodicity * vector if necessary. */ bool c_loop_subset::next_block() { if(i c_loop_base(c_class &con) : nx(con.nx), ny(con.ny), nz(con.nz), nxy(con.nxy), nxyz(con.nxyz), ps(con.ps), p(con.p), id(con.id), co(con.co) {} /** Returns the position vector of the particle currently being * considered by the loop. * \param[out] (x,y,z) the position vector of the particle. */ inline void pos(double &x,double &y,double &z) { double *pp=p[ijk]+ps*q; x=*(pp++);y=*(pp++);z=*pp; } /** Returns the ID, position vector, and radius of the particle * currently being considered by the loop. * \param[out] pid the particle ID. * \param[out] (x,y,z) the position vector of the particle. * \param[out] r the radius of the particle. If no radius * information is available the default radius * value is returned. */ inline void pos(int &pid,double &x,double &y,double &z,double &r) { pid=id[ijk][q]; double *pp=p[ijk]+ps*q; x=*(pp++);y=*(pp++);z=*pp; r=ps==3?default_radius:*(++pp); } /** Returns the x position of the particle currently being * considered by the loop. */ inline double x() {return p[ijk][ps*q];} /** Returns the y position of the particle currently being * considered by the loop. */ inline double y() {return p[ijk][ps*q+1];} /** Returns the z position of the particle currently being * considered by the loop. */ inline double z() {return p[ijk][ps*q+2];} /** Returns the ID of the particle currently being considered * by the loop. */ inline int pid() {return id[ijk][q];} }; /** \brief Class for looping over all of the particles in a container. * * This is one of the simplest loop classes, that scans the computational * blocks in order, and scans all the particles within each block in order. */ class c_loop_all : public c_loop_base { public: /** The constructor copies several necessary constants from the * base container class. * \param[in] con the container class to use. */ template c_loop_all(c_class &con) : c_loop_base(con) {} /** Sets the class to consider the first particle. * \return True if there is any particle to consider, false * otherwise. */ inline bool start() { i=j=k=ijk=q=0; while(co[ijk]==0) if(!next_block()) return false; return true; } /** Finds the next particle to test. * \return True if there is another particle, false if no more * particles are available. */ inline bool inc() { q++; if(q>=co[ijk]) { q=0; do { if(!next_block()) return false; } while(co[ijk]==0); } return true; } private: /** Updates the internal variables to find the next * computational block with any particles. * \return True if another block is found, false if there are * no more blocks. */ inline bool next_block() { ijk++; i++; if(i==nx) { i=0;j++; if(j==ny) { j=0;k++; if(ijk==nxyz) return false; } } return true; } }; /** \brief Class for looping over a subset of particles in a container. * * This class can loop over a subset of particles in a certain geometrical * region within the container. The class can be set up to loop over a * rectangular box or sphere. It can also rectangular group of internal * computational blocks. */ class c_loop_subset : public c_loop_base { public: /** The current mode of operation, determining whether tests * should be applied to particles to ensure they are within a * certain geometrical object. */ c_loop_subset_mode mode; /** The constructor copies several necessary constants from the * base container class. * \param[in] con the container class to use. */ template c_loop_subset(c_class &con) : c_loop_base(con), ax(con.ax), ay(con.ay), az(con.az), sx(con.bx-ax), sy(con.by-ay), sz(con.bz-az), xsp(con.xsp), ysp(con.ysp), zsp(con.zsp), xperiodic(con.xperiodic), yperiodic(con.yperiodic), zperiodic(con.zperiodic) {} void setup_sphere(double vx,double vy,double vz,double r,bool bounds_test=true); void setup_box(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax,bool bounds_test=true); void setup_intbox(int ai_,int bi_,int aj_,int bj_,int ak_,int bk_); bool start(); /** Finds the next particle to test. * \return True if there is another particle, false if no more * particles are available. */ inline bool inc() { do { q++; while(q>=co[ijk]) {q=0;if(!next_block()) return false;} } while(mode!=no_check&&out_of_bounds()); return true; } private: const double ax,ay,az,sx,sy,sz,xsp,ysp,zsp; const bool xperiodic,yperiodic,zperiodic; double px,py,pz,apx,apy,apz; double v0,v1,v2,v3,v4,v5; int ai,bi,aj,bj,ak,bk; int ci,cj,ck,di,dj,dk,inc1,inc2; inline int step_mod(int a,int b) {return a>=0?a%b:b-1-(b-1-a)%b;} inline int step_div(int a,int b) {return a>=0?a/b:-1+(a+1)/b;} inline int step_int(double a) {return a<0?int(a)-1:int(a);} void setup_common(); bool next_block(); bool out_of_bounds(); }; /** \brief Class for looping over all of the particles specified in a * pre-assembled particle_order class. * * The particle_order class can be used to create a specific order of particles * within the container. This class can then loop over these particles in this * order. The class is particularly useful in cases where the ordering of the * output must match the ordering of particles as they were inserted into the * container. */ class c_loop_order : public c_loop_base { public: /** A reference to the ordering class to use. */ particle_order &vo; /** A pointer to the current position in the ordering class. */ int *cp; /** A pointer to the end position in the ordering class. */ int *op; /** The constructor copies several necessary constants from the * base class, and sets up a reference to the ordering class to * use. * \param[in] con the container class to use. * \param[in] vo_ the ordering class to use. */ template c_loop_order(c_class &con,particle_order &vo_) : c_loop_base(con), vo(vo_), nx(con.nx), nxy(con.nxy) {} /** Sets the class to consider the first particle. * \return True if there is any particle to consider, false * otherwise. */ inline bool start() { cp=vo.o;op=vo.op; if(cp!=op) { ijk=*(cp++);decode(); q=*(cp++); return true; } else return false; } /** Finds the next particle to test. * \return True if there is another particle, false if no more * particles are available. */ inline bool inc() { if(cp==op) return false; ijk=*(cp++);decode(); q=*(cp++); return true; } private: /** The number of computational blocks in the x direction. */ const int nx; /** The number of computational blocks in a z-slice. */ const int nxy; /** Takes the current block index and computes indices in the * x, y, and z directions. */ inline void decode() { k=ijk/nxy; int ijkt=ijk-nxy*k; j=ijkt/nx; i=ijkt-j*nx; } }; /** \brief A class for looping over all particles in a container_periodic or * container_periodic_poly class. * * Since the container_periodic and container_periodic_poly classes have a * fundamentally different memory organization, the regular loop classes cannot * be used with them. */ class c_loop_all_periodic : public c_loop_base { public: /** The constructor copies several necessary constants from the * base periodic container class. * \param[in] con the periodic container class to use. */ template c_loop_all_periodic(c_class &con) : c_loop_base(con), ey(con.ey), ez(con.ez), wy(con.wy), wz(con.wz), ijk0(nx*(ey+con.oy*ez)), inc2(2*nx*con.ey+1) {} /** Sets the class to consider the first particle. * \return True if there is any particle to consider, false * otherwise. */ inline bool start() { i=0; j=ey; k=ez; ijk=ijk0; q=0; while(co[ijk]==0) if(!next_block()) return false; return true; } /** Finds the next particle to test. * \return True if there is another particle, false if no more * particles are available. */ inline bool inc() { q++; if(q>=co[ijk]) { q=0; do { if(!next_block()) return false; } while(co[ijk]==0); } return true; } private: /** The lower y index (inclusive) of the primary domain within * the block structure. */ int ey; /** The lower y index (inclusive) of the primary domain within * the block structure. */ int ez; /** The upper y index (exclusive) of the primary domain within * the block structure. */ int wy; /** The upper z index (exclusive) of the primary domain within * the block structure. */ int wz; /** The index of the (0,0,0) block within the block structure. */ int ijk0; /** A value to increase ijk by when the z index is increased. */ int inc2; /** Updates the internal variables to find the next * computational block with any particles. * \return True if another block is found, false if there are * no more blocks. */ inline bool next_block() { i++; if(i==nx) { i=0;j++; if(j==wy) { j=ey;k++; if(k==wz) return false; ijk+=inc2; } else ijk++; } else ijk++; return true; } }; /** \brief Class for looping over all of the particles specified in a * pre-assembled particle_order class, for use with container_periodic classes. * * The particle_order class can be used to create a specific order of particles * within the container. This class can then loop over these particles in this * order. The class is particularly useful in cases where the ordering of the * output must match the ordering of particles as they were inserted into the * container. */ class c_loop_order_periodic : public c_loop_base { public: /** A reference to the ordering class to use. */ particle_order &vo; /** A pointer to the current position in the ordering class. */ int *cp; /** A pointer to the end position in the ordering class. */ int *op; /** The constructor copies several necessary constants from the * base class, and sets up a reference to the ordering class to * use. * \param[in] con the container class to use. * \param[in] vo_ the ordering class to use. */ template c_loop_order_periodic(c_class &con,particle_order &vo_) : c_loop_base(con), vo(vo_), nx(con.nx), oxy(con.nx*con.oy) {} /** Sets the class to consider the first particle. * \return True if there is any particle to consider, false * otherwise. */ inline bool start() { cp=vo.o;op=vo.op; if(cp!=op) { ijk=*(cp++);decode(); q=*(cp++); return true; } else return false; } /** Finds the next particle to test. * \return True if there is another particle, false if no more * particles are available. */ inline bool inc() { if(cp==op) return false; ijk=*(cp++);decode(); q=*(cp++); return true; } private: /** The number of computational blocks in the x direction. */ const int nx; /** The number of computational blocks in a z-slice. */ const int oxy; /** Takes the current block index and computes indices in the * x, y, and z directions. */ inline void decode() { k=ijk/oxy; int ijkt=ijk-oxy*k; j=ijkt/nx; i=ijkt-j*nx; } }; } #endif voro++-0.4.6/src/cell.cc000600 000765 000024 00000206206 12230022105 014551 0ustar00chrstaff000000 000000 // Voro++, a 3D cell-based Voronoi library // // Author : Chris H. Rycroft (LBL / UC Berkeley) // Email : chr@alum.mit.edu // Date : August 30th 2011 /** \file cell.cc * \brief Function implementations for the voronoicell and related classes. */ #include #include #include "config.hh" #include "common.hh" #include "cell.hh" namespace voro { /** Constructs a Voronoi cell and sets up the initial memory. */ voronoicell_base::voronoicell_base() : current_vertices(init_vertices), current_vertex_order(init_vertex_order), current_delete_size(init_delete_size), current_delete2_size(init_delete2_size), ed(new int*[current_vertices]), nu(new int[current_vertices]), pts(new double[3*current_vertices]), mem(new int[current_vertex_order]), mec(new int[current_vertex_order]), mep(new int*[current_vertex_order]), ds(new int[current_delete_size]), stacke(ds+current_delete_size), ds2(new int[current_delete2_size]), stacke2(ds2+current_delete_size), current_marginal(init_marginal), marg(new int[current_marginal]) { int i; for(i=0;i<3;i++) { mem[i]=init_n_vertices;mec[i]=0; mep[i]=new int[init_n_vertices*((i<<1)+1)]; } mem[3]=init_3_vertices;mec[3]=0; mep[3]=new int[init_3_vertices*7]; for(i=4;i=0;i--) if(mem[i]>0) delete [] mep[i]; delete [] marg; delete [] ds2;delete [] ds; delete [] mep;delete [] mec; delete [] mem;delete [] pts; delete [] nu;delete [] ed; } /** Ensures that enough memory is allocated prior to carrying out a copy. * \param[in] vc a reference to the specialized version of the calling class. * \param[in] vb a pointered to the class to be copied. */ template void voronoicell_base::check_memory_for_copy(vc_class &vc,voronoicell_base* vb) { while(current_vertex_ordercurrent_vertex_order) add_memory_vorder(vc); for(int i=0;imec[i]) add_memory(vc,i,ds2); while(current_verticesp) add_memory_vertices(vc); } /** Copies the vertex and edge information from another class. The routine * assumes that enough memory is available for the copy. * \param[in] vb a pointer to the class to copy. */ void voronoicell_base::copy(voronoicell_base* vb) { int i,j; p=vb->p;up=0; for(i=0;imec[i]; for(j=0;jmep[i][j]; for(j=0;jnu[i]; for(i=0;i<3*p;i++) pts[i]=vb->pts[i]; } /** Copies the information from another voronoicell class into this * class, extending memory allocation if necessary. * \param[in] c the class to copy. */ void voronoicell_neighbor::operator=(voronoicell &c) { voronoicell_base *vb=((voronoicell_base*) &c); check_memory_for_copy(*this,vb);copy(vb); int i,j; for(i=0;i void voronoicell_base::add_memory(vc_class &vc,int i,int *stackp2) { int s=(i<<1)+1; if(mem[i]==0) { vc.n_allocate(i,init_n_vertices); mep[i]=new int[init_n_vertices*s]; mem[i]=init_n_vertices; #if VOROPP_VERBOSE >=2 fprintf(stderr,"Order %d vertex memory created\n",i); #endif } else { int j=0,k,*l; mem[i]<<=1; if(mem[i]>max_n_vertices) voro_fatal_error("Point memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); #if VOROPP_VERBOSE >=2 fprintf(stderr,"Order %d vertex memory scaled up to %d\n",i,mem[i]); #endif l=new int[s*mem[i]]; int m=0; vc.n_allocate_aux1(i); while(j=0) { ed[k]=l+j; vc.n_set_to_aux1_offset(k,m); } else { int *dsp; for(dsp=ds2;dsp=3 fputs("Relocated dangling pointer",stderr); #endif } for(k=0;k void voronoicell_base::add_memory_vertices(vc_class &vc) { int i=(current_vertices<<1),j,**pp,*pnu; if(i>max_vertices) voro_fatal_error("Vertex memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); #if VOROPP_VERBOSE >=2 fprintf(stderr,"Vertex memory scaled up to %d\n",i); #endif double *ppts; pp=new int*[i]; for(j=0;j void voronoicell_base::add_memory_vorder(vc_class &vc) { int i=(current_vertex_order<<1),j,*p1,**p2; if(i>max_vertex_order) voro_fatal_error("Vertex order memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); #if VOROPP_VERBOSE >=2 fprintf(stderr,"Vertex order memory scaled up to %d\n",i); #endif p1=new int[i]; for(j=0;jmax_delete_size) voro_fatal_error("Delete stack 1 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); #if VOROPP_VERBOSE >=2 fprintf(stderr,"Delete stack 1 memory scaled up to %d\n",current_delete_size); #endif int *dsn=new int[current_delete_size],*dsnp=dsn,*dsp=ds; while(dspmax_delete2_size) voro_fatal_error("Delete stack 2 memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); #if VOROPP_VERBOSE >=2 fprintf(stderr,"Delete stack 2 memory scaled up to %d\n",current_delete2_size); #endif int *dsn=new int[current_delete2_size],*dsnp=dsn,*dsp=ds2; while(dsp inline bool voronoicell_base::search_for_outside_edge(vc_class &vc,int &up) { int i,lp,lw,*j(ds2),*stackp2(ds2); double l; *(stackp2++)=up; while(j inline void voronoicell_base::add_to_stack(vc_class &vc,int lp,int *&stackp2) { for(int *k(ds2);k bool voronoicell_base::nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id) { int count=0,i,j,k,lp=up,cp,qp,rp,*stackp(ds),*stackp2(ds2),*dsp; int us=0,ls=0,qs,iqs,cs,uw,qw,lw; int *edp,*edd; double u,l,r,q;bool complicated_setup=false,new_double_edge=false,double_edge=false; // Initialize the safe testing routine n_marg=0;px=x;py=y;pz=z;prsq=rsq; // Test approximately sqrt(n)/4 points for their proximity to the plane // and keep the one which is closest uw=m_test(up,u); // Starting from an initial guess, we now move from vertex to vertex, // to try and find an edge which intersects the cutting plane, // or a vertex which is on the plane try { if(uw==1) { // The test point is inside the cutting plane. us=0; do { lp=ed[up][us]; lw=m_test(lp,l); if(l=p) throw true; u=l;up=lp; for(us=0;us=p) throw true; u=q;up=qp; for(us=0;us=1 fputs("Bailed out of convex calculation\n",stderr); #endif qw=1;lw=0; for(qp=0;qp=current_vertex_order) add_memory_vorder(vc); if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2); vc.n_set_pointer(p,nu[p]); ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++; ed[p][nu[p]<<1]=p; // Copy the edges of the original vertex into the new // one. Delete the edges of the original vertex, and // update the relational table. us=cycle_down(i,up); while(i=current_vertex_order) add_memory_vorder(vc); if(mec[nu[p]]==mem[nu[p]]) add_memory(vc,nu[p],stackp2); // Copy the edges of the original vertex into the new // one. Delete the edges of the original vertex, and // update the relational table. vc.n_set_pointer(p,nu[p]); ed[p]=mep[nu[p]]+((nu[p]<<1)+1)*mec[nu[p]]++; ed[p][nu[p]<<1]=p; us=i++; while(i0) k+=nu[j]; } else { if(j>0) { // This vertex was visited before, so // count those vertices to the ones we // already have. k+=nu[j]; // The only time when we might make a // duplicate edge is if the point we're // going to move to next is also a // marginal point, so test for that // first. if(lw==0) { // Now see whether this marginal point // has been visited before. i=-ed[lp][nu[lp]<<1]; if(i>0) { // Now see if the last edge of that other // marginal point actually ends up here. if(ed[i][nu[i]-1]==j) { new_double_edge=true; k-=1; } else new_double_edge=false; } else { // That marginal point hasn't been visited // before, so we probably don't have to worry // about duplicate edges, except in the // case when that's the way into the end // of the facet, because that way always creates // an edge. if(j==rp&&lp==up&&ed[qp][nu[qp]+qs]==us) { new_double_edge=true; k-=1; } else new_double_edge=false; } } else new_double_edge=false; } else { // The vertex hasn't been visited // before, but let's see if it's // marginal if(lw==0) { // If it is, we need to check // for the case that it's a // small branch, and that we're // heading right back to where // we came from i=-ed[lp][nu[lp]<<1]; if(i==cp) { new_double_edge=true; k-=1; } else new_double_edge=false; } else new_double_edge=false; } } // k now holds the number of edges of the new vertex // we are forming. Add memory for it if it doesn't exist // already. while(k>=current_vertex_order) add_memory_vorder(vc); if(mec[k]==mem[k]) add_memory(vc,k,stackp2); // Now create a new vertex with order k, or augment // the existing one if(j>0) { // If we're augmenting a vertex but we don't // actually need any more edges, just skip this // routine to avoid memory confusion if(nu[j]!=k) { // Allocate memory and copy the edges // of the previous instance into it vc.n_set_aux1(k); edp=mep[k]+((k<<1)+1)*mec[k]++; i=0; while(ids) { --p; while(ed[p][nu[p]]==-1) { j=nu[p]; edp=ed[p];edd=(mep[j]+((j<<1)+1)*--mec[j]); while(edp0) voro_fatal_error("Zero order vertex formed",VOROPP_INTERNAL_ERROR); // Collapse any order 2 vertices and exit return collapse_order2(vc); } /** During the creation of a new facet in the plane routine, it is possible * that some order two vertices may arise. This routine removes them. * Suppose an order two vertex joins c and d. If there's a edge between * c and d already, then the order two vertex is just removed; otherwise, * the order two vertex is removed and c and d are joined together directly. * It is possible this process will create order two or order one vertices, * and the routine is continually run until all of them are removed. * \return False if the vertex removal was unsuccessful, indicative of the cell * reducing to zero volume and disappearing; true if the vertex removal * was successful. */ template inline bool voronoicell_base::collapse_order2(vc_class &vc) { if(!collapse_order1(vc)) return false; int a,b,i,j,k,l; while(mec[2]>0) { // Pick a order 2 vertex and read in its edges i=--mec[2]; j=mep[2][5*i];k=mep[2][5*i+1]; if(j==k) { #if VOROPP_VERBOSE >=1 fputs("Order two vertex joins itself",stderr); #endif return false; } // Scan the edges of j to see if joins k for(l=0;l inline bool voronoicell_base::collapse_order1(vc_class &vc) { int i,j,k; while(mec[1]>0) { up=0; #if VOROPP_VERBOSE >=1 fputs("Order one collapse\n",stderr); #endif i=--mec[1]; j=mep[1][3*i];k=mep[1][3*i+1]; i=mep[1][3*i+2]; if(!delete_connection(vc,j,k,false)) return false; --p; if(up==i) up=0; if(p!=i) { if(up==p) up=i; pts[3*i]=pts[3*p]; pts[3*i+1]=pts[3*p+1]; pts[3*i+2]=pts[3*p+2]; for(k=0;k inline bool voronoicell_base::delete_connection(vc_class &vc,int j,int k,bool hand) { int q=hand?k:cycle_up(k,j); int i=nu[j]-1,l,*edp,*edd,m; #if VOROPP_VERBOSE >=1 if(i<1) { fputs("Zero order vertex formed\n",stderr); return false; } #endif if(mec[i]==mem[i]) add_memory(vc,i,ds2); vc.n_set_aux1(i); for(l=0;l=0) { ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); vx=pts[3*k]-*pts; vy=pts[3*k+1]-pts[1]; vz=pts[3*k+2]-pts[2]; m=ed[k][l];ed[k][l]=-1-m; while(m!=i) { n=cycle_up(ed[k][nu[k]+l],m); wx=pts[3*m]-*pts; wy=pts[3*m+1]-pts[1]; wz=pts[3*m+2]-pts[2]; vol+=ux*vy*wz+uy*vz*wx+uz*vx*wy-uz*vy*wx-uy*vx*wz-ux*vz*wy; k=m;l=n;vx=wx;vy=wy;vz=wz; m=ed[k][l];ed[k][l]=-1-m; } } } } reset_edges(); return vol*fe; } /** Calculates the areas of each face of the Voronoi cell and prints the * results to an output stream. * \param[out] v the vector to store the results in. */ void voronoicell_base::face_areas(std::vector &v) { double area; v.clear(); int i,j,k,l,m,n; double ux,uy,uz,vx,vy,vz,wx,wy,wz; for(i=1;i=0) { area=0; ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); m=ed[k][l];ed[k][l]=-1-m; while(m!=i) { n=cycle_up(ed[k][nu[k]+l],m); ux=pts[3*k]-pts[3*i]; uy=pts[3*k+1]-pts[3*i+1]; uz=pts[3*k+2]-pts[3*i+2]; vx=pts[3*m]-pts[3*i]; vy=pts[3*m+1]-pts[3*i+1]; vz=pts[3*m+2]-pts[3*i+2]; wx=uy*vz-uz*vy; wy=uz*vx-ux*vz; wz=ux*vy-uy*vx; area+=sqrt(wx*wx+wy*wy+wz*wz); k=m;l=n; m=ed[k][l];ed[k][l]=-1-m; } v.push_back(0.125*area); } } reset_edges(); } /** Calculates the total surface area of the Voronoi cell. * \return The computed area. */ double voronoicell_base::surface_area() { double area=0; int i,j,k,l,m,n; double ux,uy,uz,vx,vy,vz,wx,wy,wz; for(i=1;i=0) { ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); m=ed[k][l];ed[k][l]=-1-m; while(m!=i) { n=cycle_up(ed[k][nu[k]+l],m); ux=pts[3*k]-pts[3*i]; uy=pts[3*k+1]-pts[3*i+1]; uz=pts[3*k+2]-pts[3*i+2]; vx=pts[3*m]-pts[3*i]; vy=pts[3*m+1]-pts[3*i+1]; vz=pts[3*m+2]-pts[3*i+2]; wx=uy*vz-uz*vy; wy=uz*vx-ux*vz; wz=ux*vy-uy*vx; area+=sqrt(wx*wx+wy*wy+wz*wz); k=m;l=n; m=ed[k][l];ed[k][l]=-1-m; } } } reset_edges(); return 0.125*area; } /** Calculates the centroid of the Voronoi cell, by decomposing the cell into * tetrahedra extending outward from the zeroth vertex. * \param[out] (cx,cy,cz) references to floating point numbers in which to * pass back the centroid vector. */ void voronoicell_base::centroid(double &cx,double &cy,double &cz) { double tvol,vol=0;cx=cy=cz=0; int i,j,k,l,m,n; double ux,uy,uz,vx,vy,vz,wx,wy,wz; for(i=1;i=0) { ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); vx=pts[3*k]-*pts; vy=pts[3*k+1]-pts[1]; vz=pts[3*k+2]-pts[2]; m=ed[k][l];ed[k][l]=-1-m; while(m!=i) { n=cycle_up(ed[k][nu[k]+l],m); wx=pts[3*m]-*pts; wy=pts[3*m+1]-pts[1]; wz=pts[3*m+2]-pts[2]; tvol=ux*vy*wz+uy*vz*wx+uz*vx*wy-uz*vy*wx-uy*vx*wz-ux*vz*wy; vol+=tvol; cx+=(wx+vx-ux)*tvol; cy+=(wy+vy-uy)*tvol; cz+=(wz+vz-uz)*tvol; k=m;l=n;vx=wx;vy=wy;vz=wz; m=ed[k][l];ed[k][l]=-1-m; } } } } reset_edges(); if(vol>tolerance_sq) { vol=0.125/vol; cx=cx*vol+0.5*(*pts); cy=cy*vol+0.5*pts[1]; cz=cz*vol+0.5*pts[2]; } else cx=cy=cz=0; } /** Computes the maximum radius squared of a vertex from the center of the * cell. It can be used to determine when enough particles have been testing an * all planes that could cut the cell have been considered. * \return The maximum radius squared of a vertex.*/ double voronoicell_base::max_radius_squared() { double r,s,*ptsp=pts+3,*ptse=pts+3*p; r=*pts*(*pts)+pts[1]*pts[1]+pts[2]*pts[2]; while(ptspr) r=s; } return r; } /** Calculates the total edge distance of the Voronoi cell. * \return A floating point number holding the calculated distance. */ double voronoicell_base::total_edge_distance() { int i,j,k; double dis=0,dx,dy,dz; for(i=0;ii) { dx=pts[3*k]-pts[3*i]; dy=pts[3*k+1]-pts[3*i+1]; dz=pts[3*k+2]-pts[3*i+2]; dis+=sqrt(dx*dx+dy*dy+dz*dz); } } return 0.5*dis; } /** Outputs the edges of the Voronoi cell in POV-Ray format to an open file * stream, displacing the cell by given vector. * \param[in] (x,y,z) a displacement vector to be added to the cell's position. * \param[in] fp a file handle to write to. */ void voronoicell_base::draw_pov(double x,double y,double z,FILE* fp) { int i,j,k;double *ptsp=pts,*pt2; char posbuf1[128],posbuf2[128]; for(i=0;i,r}\n",posbuf1); for(j=0;j,<%s>,r}\n",posbuf1,posbuf2); } } } } /** Outputs the edges of the Voronoi cell in gnuplot format to an output stream. * \param[in] (x,y,z) a displacement vector to be added to the cell's position. * \param[in] fp a file handle to write to. */ void voronoicell_base::draw_gnuplot(double x,double y,double z,FILE *fp) { int i,j,k,l,m; for(i=1;i=0) { fprintf(fp,"%g %g %g\n",x+0.5*pts[3*i],y+0.5*pts[3*i+1],z+0.5*pts[3*i+2]); l=i;m=j; do { ed[k][ed[l][nu[l]+m]]=-1-l; ed[l][m]=-1-k; l=k; fprintf(fp,"%g %g %g\n",x+0.5*pts[3*k],y+0.5*pts[3*k+1],z+0.5*pts[3*k+2]); } while (search_edge(l,m,k)); fputs("\n\n",fp); } } reset_edges(); } inline bool voronoicell_base::search_edge(int l,int &m,int &k) { for(m=0;m=0) return true; } return false; } /** Outputs the Voronoi cell in the POV mesh2 format, described in section * 1.3.2.2 of the POV-Ray documentation. The mesh2 output consists of a list of * vertex vectors, followed by a list of triangular faces. The routine also * makes use of the optional inside_vector specification, which makes the mesh * object solid, so the the POV-Ray Constructive Solid Geometry (CSG) can be * applied. * \param[in] (x,y,z) a displacement vector to be added to the cell's position. * \param[in] fp a file handle to write to. */ void voronoicell_base::draw_pov_mesh(double x,double y,double z,FILE *fp) { int i,j,k,l,m,n; double *ptsp=pts; fprintf(fp,"mesh2 {\nvertex_vectors {\n%d\n",p); for(i=0;i\n",x+*ptsp*0.5,y+ptsp[1]*0.5,z+ptsp[2]*0.5); fprintf(fp,"}\nface_indices {\n%d\n",(p-2)<<1); for(i=1;i=0) { ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); m=ed[k][l];ed[k][l]=-1-m; while(m!=i) { n=cycle_up(ed[k][nu[k]+l],m); fprintf(fp,",<%d,%d,%d>\n",i,k,m); k=m;l=n; m=ed[k][l];ed[k][l]=-1-m; } } } fputs("}\ninside_vector <0,0,1>\n}\n",fp); reset_edges(); } /** Several routines in the class that gather cell-based statistics internally * track their progress by flipping edges to negative so that they know what * parts of the cell have already been tested. This function resets them back * to positive. When it is called, it assumes that every edge in the routine * should have already been flipped to negative, and it bails out with an * internal error if it encounters a positive edge. */ inline void voronoicell_base::reset_edges() { int i,j; for(i=0;i=0) voro_fatal_error("Edge reset routine found a previously untested edge",VOROPP_INTERNAL_ERROR); ed[i][j]=-1-ed[i][j]; } } /** Checks to see if a given vertex is inside, outside or within the test * plane. If the point is far away from the test plane, the routine immediately * returns whether it is inside or outside. If the routine is close the the * plane and within the specified tolerance, then the special check_marginal() * routine is called. * \param[in] n the vertex to test. * \param[out] ans the result of the scalar product used in evaluating the * location of the point. * \return -1 if the point is inside the plane, 1 if the point is outside the * plane, or 0 if the point is within the plane. */ inline int voronoicell_base::m_test(int n,double &ans) { double *pp=pts+n+(n<<1); ans=*(pp++)*px; ans+=*(pp++)*py; ans+=*pp*pz-prsq; if(ans<-tolerance2) { return -1; } else if(ans>tolerance2) { return 1; } return check_marginal(n,ans); } /** Checks to see if a given vertex is inside, outside or within the test * plane, for the case when the point has been detected to be very close to the * plane. The routine ensures that the returned results are always consistent * with previous tests, by keeping a table of any marginal results. The routine * first sees if the vertex is in the table, and if it finds a previously * computed result it uses that. Otherwise, it computes a result for this * vertex and adds it the table. * \param[in] n the vertex to test. * \param[in] ans the result of the scalar product used in evaluating * the location of the point. * \return -1 if the point is inside the plane, 1 if the point is outside the * plane, or 0 if the point is within the plane. */ int voronoicell_base::check_marginal(int n,double &ans) { int i; for(i=0;imax_marginal) voro_fatal_error("Marginal case buffer allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); #if VOROPP_VERBOSE >=2 fprintf(stderr,"Marginal cases buffer scaled up to %d\n",i); #endif int *pmarg=new int[current_marginal]; for(int j=0;jtolerance?1:(ans<-tolerance?-1:0); return marg[n_marg-1]; } /** For each face of the Voronoi cell, this routine prints the out the normal * vector of the face, and scales it to the distance from the cell center to * that plane. * \param[out] v the vector to store the results in. */ void voronoicell_base::normals(std::vector &v) { int i,j,k; v.clear(); for(i=1;i=0) normals_search(v,i,j,k); } reset_edges(); } /** This inline routine is called by normals(). It attempts to construct a * single normal vector that is associated with a particular face. It first * traces around the face, trying to find two vectors along the face edges * whose vector product is above the numerical tolerance. It then constructs * the normal vector using this product. If the face is too small, and none of * the vector products are large enough, the routine may return (0,0,0) as the * normal vector. * \param[in] v the vector to store the results in. * \param[in] i the initial vertex of the face to test. * \param[in] j the index of an edge of the vertex. * \param[in] k the neighboring vertex of i, set to ed[i][j]. */ inline void voronoicell_base::normals_search(std::vector &v,int i,int j,int k) { ed[i][j]=-1-k; int l=cycle_up(ed[i][nu[i]+j],k),m; double ux,uy,uz,vx,vy,vz,wx,wy,wz,wmag; do { m=ed[k][l];ed[k][l]=-1-m; ux=pts[3*m]-pts[3*k]; uy=pts[3*m+1]-pts[3*k+1]; uz=pts[3*m+2]-pts[3*k+2]; // Test to see if the length of this edge is above the tolerance if(ux*ux+uy*uy+uz*uz>tolerance_sq) { while(m!=i) { l=cycle_up(ed[k][nu[k]+l],m); k=m;m=ed[k][l];ed[k][l]=-1-m; vx=pts[3*m]-pts[3*k]; vy=pts[3*m+1]-pts[3*k+1]; vz=pts[3*m+2]-pts[3*k+2]; // Construct the vector product of this edge with // the previous one wx=uz*vy-uy*vz; wy=ux*vz-uz*vx; wz=uy*vx-ux*vy; wmag=wx*wx+wy*wy+wz*wz; // Test to see if this vector product of the // two edges is above the tolerance if(wmag>tolerance_sq) { // Construct the normal vector and print it wmag=1/sqrt(wmag); v.push_back(wx*wmag); v.push_back(wy*wmag); v.push_back(wz*wmag); // Mark all of the remaining edges of this // face and exit while(m!=i) { l=cycle_up(ed[k][nu[k]+l],m); k=m;m=ed[k][l];ed[k][l]=-1-m; } return; } } v.push_back(0); v.push_back(0); v.push_back(0); return; } l=cycle_up(ed[k][nu[k]+l],m); k=m; } while (k!=i); v.push_back(0); v.push_back(0); v.push_back(0); } /** Returns the number of faces of a computed Voronoi cell. * \return The number of faces. */ int voronoicell_base::number_of_faces() { int i,j,k,l,m,s=0; for(i=1;i=0) { s++; ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); do { m=ed[k][l]; ed[k][l]=-1-m; l=cycle_up(ed[k][nu[k]+l],m); k=m; } while (k!=i); } } reset_edges(); return s; } /** Returns a vector of the vertex orders. * \param[out] v the vector to store the results in. */ void voronoicell_base::vertex_orders(std::vector &v) { v.resize(p); for(int i=0;i0) { fprintf(fp,"%d",*nu); for(int *nup=nu+1;nup &v) { v.resize(3*p); double *ptsp=pts; for(int i=0;i<3*p;i+=3) { v[i]=*(ptsp++)*0.5; v[i+1]=*(ptsp++)*0.5; v[i+2]=*(ptsp++)*0.5; } } /** Outputs the vertex vectors using the local coordinate system. * \param[out] fp the file handle to write to. */ void voronoicell_base::output_vertices(FILE *fp) { if(p>0) { fprintf(fp,"(%g,%g,%g)",*pts*0.5,pts[1]*0.5,pts[2]*0.5); for(double *ptsp=pts+3;ptsp &v) { v.resize(3*p); double *ptsp=pts; for(int i=0;i<3*p;i+=3) { v[i]=x+*(ptsp++)*0.5; v[i+1]=y+*(ptsp++)*0.5; v[i+2]=z+*(ptsp++)*0.5; } } /** Outputs the vertex vectors using the global coordinate system. * \param[out] fp the file handle to write to. * \param[in] (x,y,z) the position vector of the particle in the global * coordinate system. */ void voronoicell_base::output_vertices(double x,double y,double z,FILE *fp) { if(p>0) { fprintf(fp,"(%g,%g,%g)",x+*pts*0.5,y+pts[1]*0.5,z+pts[2]*0.5); for(double *ptsp=pts+3;ptsp &v) { v.clear(); int i,j,k,l,m; double dx,dy,dz,perim; for(i=1;i=0) { dx=pts[3*k]-pts[3*i]; dy=pts[3*k+1]-pts[3*i+1]; dz=pts[3*k+2]-pts[3*i+2]; perim=sqrt(dx*dx+dy*dy+dz*dz); ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); do { m=ed[k][l]; dx=pts[3*m]-pts[3*k]; dy=pts[3*m+1]-pts[3*k+1]; dz=pts[3*m+2]-pts[3*k+2]; perim+=sqrt(dx*dx+dy*dy+dz*dz); ed[k][l]=-1-m; l=cycle_up(ed[k][nu[k]+l],m); k=m; } while (k!=i); v.push_back(0.5*perim); } } reset_edges(); } /** For each face, this routine outputs a bracketed sequence of numbers * containing a list of all the vertices that make up that face. * \param[out] v the vector to store the results in. */ void voronoicell_base::face_vertices(std::vector &v) { int i,j,k,l,m,vp(0),vn; v.clear(); for(i=1;i=0) { v.push_back(0); v.push_back(i); ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); do { v.push_back(k); m=ed[k][l]; ed[k][l]=-1-m; l=cycle_up(ed[k][nu[k]+l],m); k=m; } while (k!=i); vn=v.size(); v[vp]=vn-vp-1; vp=vn; } } reset_edges(); } /** Outputs a list of the number of edges in each face. * \param[out] v the vector to store the results in. */ void voronoicell_base::face_orders(std::vector &v) { int i,j,k,l,m,q; v.clear(); for(i=1;i=0) { q=1; ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); do { q++; m=ed[k][l]; ed[k][l]=-1-m; l=cycle_up(ed[k][nu[k]+l],m); k=m; } while (k!=i); v.push_back(q);; } } reset_edges(); } /** Computes the number of edges that each face has and outputs a frequency * table of the results. * \param[out] v the vector to store the results in. */ void voronoicell_base::face_freq_table(std::vector &v) { int i,j,k,l,m,q; v.clear(); for(i=1;i=0) { q=1; ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); do { q++; m=ed[k][l]; ed[k][l]=-1-m; l=cycle_up(ed[k][nu[k]+l],m); k=m; } while (k!=i); if((unsigned int) q>=v.size()) v.resize(q+1,0); v[q]++; } } reset_edges(); } /** This routine tests to see whether the cell intersects a plane by starting * from the guess point up. If up intersects, then it immediately returns true. * Otherwise, it calls the plane_intersects_track() routine. * \param[in] (x,y,z) the normal vector to the plane. * \param[in] rsq the distance along this vector of the plane. * \return False if the plane does not intersect the plane, true if it does. */ bool voronoicell_base::plane_intersects(double x,double y,double z,double rsq) { double g=x*pts[3*up]+y*pts[3*up+1]+z*pts[3*up+2]; if(g>3,mp=1; double m; while(cag) { if(m>rsq) return true; g=m;up=mp; } ca+=mp++; } return plane_intersects_track(x,y,z,rsq,g); } return true; } /* This routine tests to see if a cell intersects a plane, by tracing over the cell from * vertex to vertex, starting at up. It is meant to be called either by plane_intersects() * or plane_intersects_track(), when those routines cannot immediately resolve the case. * \param[in] (x,y,z) the normal vector to the plane. * \param[in] rsq the distance along this vector of the plane. * \param[in] g the distance of up from the plane. * \return False if the plane does not intersect the plane, true if it does. */ inline bool voronoicell_base::plane_intersects_track(double x,double y,double z,double rsq,double g) { int count=0,ls,us,tp; double t; // The test point is outside of the cutting space for(us=0;usg) { ls=ed[up][nu[up]+us]; up=tp; while (t=p) { #if VOROPP_VERBOSE >=1 fputs("Bailed out of convex calculation",stderr); #endif for(tp=0;tprsq) return true; return false; } // Test all the neighbors of the current point // and find the one which is closest to the // plane for(us=0;ust) break; } if(us==ls) { us++; while(ust) break; us++; } if(us==nu[up]) return false; } ls=ed[up][nu[up]+us];up=tp;t=g; } return true; } } return false; } /** Counts the number of edges of the Voronoi cell. * \return the number of edges. */ int voronoicell_base::number_of_edges() { int edges=0,*nup=nu; while(nup>1; } /** Outputs a custom string of information about the Voronoi cell. The string * of information follows a similar style as the C printf command, and detailed * information about its format is available at * http://math.lbl.gov/voro++/doc/custom.html. * \param[in] format the custom string to print. * \param[in] i the ID of the particle associated with this Voronoi cell. * \param[in] (x,y,z) the position of the particle associated with this Voronoi * cell. * \param[in] r a radius associated with the particle. * \param[in] fp the file handle to write to. */ void voronoicell_base::output_custom(const char *format,int i,double x,double y,double z,double r,FILE *fp) { char *fmp=(const_cast(format)); std::vector vi; std::vector vd; while(*fmp!=0) { if(*fmp=='%') { fmp++; switch(*fmp) { // Particle-related output case 'i': fprintf(fp,"%d",i);break; case 'x': fprintf(fp,"%g",x);break; case 'y': fprintf(fp,"%g",y);break; case 'z': fprintf(fp,"%g",z);break; case 'q': fprintf(fp,"%g %g %g",x,y,z);break; case 'r': fprintf(fp,"%g",r);break; // Vertex-related output case 'w': fprintf(fp,"%d",p);break; case 'p': output_vertices(fp);break; case 'P': output_vertices(x,y,z,fp);break; case 'o': output_vertex_orders(fp);break; case 'm': fprintf(fp,"%g",0.25*max_radius_squared());break; // Edge-related output case 'g': fprintf(fp,"%d",number_of_edges());break; case 'E': fprintf(fp,"%g",total_edge_distance());break; case 'e': face_perimeters(vd);voro_print_vector(vd,fp);break; // Face-related output case 's': fprintf(fp,"%d",number_of_faces());break; case 'F': fprintf(fp,"%g",surface_area());break; case 'A': { face_freq_table(vi); voro_print_vector(vi,fp); } break; case 'a': face_orders(vi);voro_print_vector(vi,fp);break; case 'f': face_areas(vd);voro_print_vector(vd,fp);break; case 't': { face_vertices(vi); voro_print_face_vertices(vi,fp); } break; case 'l': normals(vd); voro_print_positions(vd,fp); break; case 'n': neighbors(vi); voro_print_vector(vi,fp); break; // Volume-related output case 'v': fprintf(fp,"%g",volume());break; case 'c': { double cx,cy,cz; centroid(cx,cy,cz); fprintf(fp,"%g %g %g",cx,cy,cz); } break; case 'C': { double cx,cy,cz; centroid(cx,cy,cz); fprintf(fp,"%g %g %g",x+cx,y+cy,z+cz); } break; // End-of-string reached case 0: fmp--;break; // The percent sign is not part of a // control sequence default: putc('%',fp);putc(*fmp,fp); } } else putc(*fmp,fp); fmp++; } fputs("\n",fp); } /** This initializes the class to be a rectangular box. It calls the base class * initialization routine to set up the edge and vertex information, and then * sets up the neighbor information, with initial faces being assigned ID * numbers from -1 to -6. * \param[in] (xmin,xmax) the minimum and maximum x coordinates. * \param[in] (ymin,ymax) the minimum and maximum y coordinates. * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */ void voronoicell_neighbor::init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax) { init_base(xmin,xmax,ymin,ymax,zmin,zmax); int *q=mne[3]; *q=-5;q[1]=-3;q[2]=-1; q[3]=-5;q[4]=-2;q[5]=-3; q[6]=-5;q[7]=-1;q[8]=-4; q[9]=-5;q[10]=-4;q[11]=-2; q[12]=-6;q[13]=-1;q[14]=-3; q[15]=-6;q[16]=-3;q[17]=-2; q[18]=-6;q[19]=-4;q[20]=-1; q[21]=-6;q[22]=-2;q[23]=-4; *ne=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9; ne[4]=q+12;ne[5]=q+15;ne[6]=q+18;ne[7]=q+21; } /** This initializes the class to be an octahedron. It calls the base class * initialization routine to set up the edge and vertex information, and then * sets up the neighbor information, with the initial faces being assigned ID * numbers from -1 to -8. * \param[in] l The distance from the octahedron center to a vertex. Six * vertices are initialized at (-l,0,0), (l,0,0), (0,-l,0), * (0,l,0), (0,0,-l), and (0,0,l). */ void voronoicell_neighbor::init_octahedron(double l) { init_octahedron_base(l); int *q=mne[4]; *q=-5;q[1]=-6;q[2]=-7;q[3]=-8; q[4]=-1;q[5]=-2;q[6]=-3;q[7]=-4; q[8]=-6;q[9]=-5;q[10]=-2;q[11]=-1; q[12]=-8;q[13]=-7;q[14]=-4;q[15]=-3; q[16]=-5;q[17]=-8;q[18]=-3;q[19]=-2; q[20]=-7;q[21]=-6;q[22]=-1;q[23]=-4; *ne=q;ne[1]=q+4;ne[2]=q+8;ne[3]=q+12;ne[4]=q+16;ne[5]=q+20; } /** This initializes the class to be a tetrahedron. It calls the base class * initialization routine to set up the edge and vertex information, and then * sets up the neighbor information, with the initial faces being assigned ID * numbers from -1 to -4. * \param (x0,y0,z0) a position vector for the first vertex. * \param (x1,y1,z1) a position vector for the second vertex. * \param (x2,y2,z2) a position vector for the third vertex. * \param (x3,y3,z3) a position vector for the fourth vertex. */ void voronoicell_neighbor::init_tetrahedron(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3) { init_tetrahedron_base(x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3); int *q=mne[3]; *q=-4;q[1]=-3;q[2]=-2; q[3]=-3;q[4]=-4;q[5]=-1; q[6]=-4;q[7]=-2;q[8]=-1; q[9]=-2;q[10]=-3;q[11]=-1; *ne=q;ne[1]=q+3;ne[2]=q+6;ne[3]=q+9; } /** This routine checks to make sure the neighbor information of each face is * consistent. */ void voronoicell_neighbor::check_facets() { int i,j,k,l,m,q; for(i=1;i=0) { ed[i][j]=-1-k; q=ne[i][j]; l=cycle_up(ed[i][nu[i]+j],k); do { m=ed[k][l]; ed[k][l]=-1-m; if(ne[k][l]!=q) fprintf(stderr,"Facet error at (%d,%d)=%d, started from (%d,%d)=%d\n",k,l,ne[k][l],i,j,q); l=cycle_up(ed[k][nu[k]+l],m); k=m; } while (k!=i); } } reset_edges(); } /** The class constructor allocates memory for storing neighbor information. */ voronoicell_neighbor::voronoicell_neighbor() { int i; mne=new int*[current_vertex_order]; ne=new int*[current_vertices]; for(i=0;i<3;i++) mne[i]=new int[init_n_vertices*i]; mne[3]=new int[init_3_vertices*3]; for(i=4;i=0;i--) if(mem[i]>0) delete [] mne[i]; delete [] mne; delete [] ne; } /** Computes a vector list of neighbors. */ void voronoicell_neighbor::neighbors(std::vector &v) { v.clear(); int i,j,k,l,m; for(i=1;i=0) { v.push_back(ne[i][j]); ed[i][j]=-1-k; l=cycle_up(ed[i][nu[i]+j],k); do { m=ed[k][l]; ed[k][l]=-1-m; l=cycle_up(ed[k][nu[k]+l],m); k=m; } while (k!=i); } } reset_edges(); } /** Prints the vertices, their edges, the relation table, and also notifies if * any memory errors are visible. */ void voronoicell_base::print_edges() { int j; double *ptsp=pts; for(int i=0;i=mep[nu[i]]+mec[nu[i]]*((nu[i]<<1)+1)) puts(" Memory error"); else puts(""); } } /** This prints out the neighbor information for vertex i. */ void voronoicell_neighbor::print_edges_neighbors(int i) { if(nu[i]>0) { int j=0; printf(" ("); while(j #include "config.hh" #include "common.hh" namespace voro { /** \brief A class representing a single Voronoi cell. * * This class represents a single Voronoi cell, as a collection of vertices * that are connected by edges. The class contains routines for initializing * the Voronoi cell to be simple shapes such as a box, tetrahedron, or octahedron. * It the contains routines for recomputing the cell based on cutting it * by a plane, which forms the key routine for the Voronoi cell computation. * It contains numerous routine for computing statistics about the Voronoi cell, * and it can output the cell in several formats. * * This class is not intended for direct use, but forms the base of the * voronoicell and voronoicell_neighbor classes, which extend it based on * whether neighboring particle ID information needs to be tracked. */ class voronoicell_base { public: /** This holds the current size of the arrays ed and nu, which * hold the vertex information. If more vertices are created * than can fit in this array, then it is dynamically extended * using the add_memory_vertices routine. */ int current_vertices; /** This holds the current maximum allowed order of a vertex, * which sets the size of the mem, mep, and mec arrays. If a * vertex is created with more vertices than this, the arrays * are dynamically extended using the add_memory_vorder routine. */ int current_vertex_order; /** This sets the size of the main delete stack. */ int current_delete_size; /** This sets the size of the auxiliary delete stack. */ int current_delete2_size; /** This sets the total number of vertices in the current cell. */ int p; /** This is the index of particular point in the cell, which is * used to start the tracing routines for plane intersection * and cutting. These routines will work starting from any * point, but it's often most efficient to start from the last * point considered, since in many cases, the cell construction * algorithm may consider many planes with similar vectors * concurrently. */ int up; /** This is a two dimensional array that holds information * about the edge connections of the vertices that make up the * cell. The two dimensional array is not allocated in the * usual method. To account for the fact the different vertices * have different orders, and thus require different amounts of * storage, the elements of ed[i] point to one-dimensional * arrays in the mep[] array of different sizes. * * More specifically, if vertex i has order m, then ed[i] * points to a one-dimensional array in mep[m] that has 2*m+1 * entries. The first m elements hold the neighboring edges, so * that the jth edge of vertex i is held in ed[i][j]. The next * m elements hold a table of relations which is redundant but * helps speed up the computation. It satisfies the relation * ed[ed[i][j]][ed[i][m+j]]=i. The final entry holds a back * pointer, so that ed[i+2*m]=i. The back pointers are used * when rearranging the memory. */ int **ed; /** This array holds the order of the vertices in the Voronoi * cell. This array is dynamically allocated, with its current * size held by current_vertices. */ int *nu; /** This in an array with size 3*current_vertices for holding * the positions of the vertices. */ double *pts; voronoicell_base(); ~voronoicell_base(); void init_base(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax); void init_octahedron_base(double l); void init_tetrahedron_base(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3); void translate(double x,double y,double z); void draw_pov(double x,double y,double z,FILE *fp=stdout); /** Outputs the cell in POV-Ray format, using cylinders for edges * and spheres for vertices, to a given file. * \param[in] (x,y,z) a displacement to add to the cell's * position. * \param[in] filename the name of the file to write to. */ inline void draw_pov(double x,double y,double z,const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_pov(x,y,z,fp); fclose(fp); }; void draw_pov_mesh(double x,double y,double z,FILE *fp=stdout); /** Outputs the cell in POV-Ray format as a mesh2 object to a * given file. * \param[in] (x,y,z) a displacement to add to the cell's * position. * \param[in] filename the name of the file to write to. */ inline void draw_pov_mesh(double x,double y,double z,const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_pov_mesh(x,y,z,fp); fclose(fp); } void draw_gnuplot(double x,double y,double z,FILE *fp=stdout); /** Outputs the cell in Gnuplot format a given file. * \param[in] (x,y,z) a displacement to add to the cell's * position. * \param[in] filename the name of the file to write to. */ inline void draw_gnuplot(double x,double y,double z,const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_gnuplot(x,y,z,fp); fclose(fp); } double volume(); double max_radius_squared(); double total_edge_distance(); double surface_area(); void centroid(double &cx,double &cy,double &cz); int number_of_faces(); int number_of_edges(); void vertex_orders(std::vector &v); void output_vertex_orders(FILE *fp=stdout); void vertices(std::vector &v); void output_vertices(FILE *fp=stdout); void vertices(double x,double y,double z,std::vector &v); void output_vertices(double x,double y,double z,FILE *fp=stdout); void face_areas(std::vector &v); /** Outputs the areas of the faces. * \param[in] fp the file handle to write to. */ inline void output_face_areas(FILE *fp=stdout) { std::vector v;face_areas(v); voro_print_vector(v,fp); } void face_orders(std::vector &v); /** Outputs a list of the number of sides of each face. * \param[in] fp the file handle to write to. */ inline void output_face_orders(FILE *fp=stdout) { std::vector v;face_orders(v); voro_print_vector(v,fp); } void face_freq_table(std::vector &v); /** Outputs a */ inline void output_face_freq_table(FILE *fp=stdout) { std::vector v;face_freq_table(v); voro_print_vector(v,fp); } void face_vertices(std::vector &v); /** Outputs the */ inline void output_face_vertices(FILE *fp=stdout) { std::vector v;face_vertices(v); voro_print_face_vertices(v,fp); } void face_perimeters(std::vector &v); /** Outputs a list of the perimeters of each face. * \param[in] fp the file handle to write to. */ inline void output_face_perimeters(FILE *fp=stdout) { std::vector v;face_perimeters(v); voro_print_vector(v,fp); } void normals(std::vector &v); /** Outputs a list of the perimeters of each face. * \param[in] fp the file handle to write to. */ inline void output_normals(FILE *fp=stdout) { std::vector v;normals(v); voro_print_positions(v,fp); } /** Outputs a custom string of information about the Voronoi * cell to a file. It assumes the cell is at (0,0,0) and has a * the default_radius associated with it. * \param[in] format the custom format string to use. * \param[in] fp the file handle to write to. */ inline void output_custom(const char *format,FILE *fp=stdout) {output_custom(format,0,0,0,0,default_radius,fp);} void output_custom(const char *format,int i,double x,double y,double z,double r,FILE *fp=stdout); template bool nplane(vc_class &vc,double x,double y,double z,double rsq,int p_id); bool plane_intersects(double x,double y,double z,double rsq); bool plane_intersects_guess(double x,double y,double z,double rsq); void construct_relations(); void check_relations(); void check_duplicates(); void print_edges(); /** Returns a list of IDs of neighboring particles * corresponding to each face. * \param[out] v a reference to a vector in which to return the * results. If no neighbor information is * available, a blank vector is returned. */ virtual void neighbors(std::vector &v) {v.clear();} /** This is a virtual function that is overridden by a routine * to print a list of IDs of neighboring particles * corresponding to each face. By default, when no neighbor * information is available, the routine does nothing. * \param[in] fp the file handle to write to. */ virtual void output_neighbors(FILE *fp=stdout) {} /** This a virtual function that is overridden by a routine to * print the neighboring particle IDs for a given vertex. By * default, when no neighbor information is available, the * routine does nothing. * \param[in] i the vertex to consider. */ virtual void print_edges_neighbors(int i) {}; /** This is a simple inline function for picking out the index * of the next edge counterclockwise at the current vertex. * \param[in] a the index of an edge of the current vertex. * \param[in] p the number of the vertex. * \return 0 if a=nu[p]-1, or a+1 otherwise. */ inline int cycle_up(int a,int p) {return a==nu[p]-1?0:a+1;} /** This is a simple inline function for picking out the index * of the next edge clockwise from the current vertex. * \param[in] a the index of an edge of the current vertex. * \param[in] p the number of the vertex. * \return nu[p]-1 if a=0, or a-1 otherwise. */ inline int cycle_down(int a,int p) {return a==0?nu[p]-1:a-1;} protected: /** This a one dimensional array that holds the current sizes * of the memory allocations for them mep array.*/ int *mem; /** This is a one dimensional array that holds the current * number of vertices of order p that are stored in the mep[p] * array. */ int *mec; /** This is a two dimensional array for holding the information * about the edges of the Voronoi cell. mep[p] is a * one-dimensional array for holding the edge information about * all vertices of order p, with each vertex holding 2*p+1 * integers of information. The total number of vertices held * on mep[p] is stored in mem[p]. If the space runs out, the * code allocates more using the add_memory() routine. */ int **mep; inline void reset_edges(); template void check_memory_for_copy(vc_class &vc,voronoicell_base* vb); void copy(voronoicell_base* vb); private: /** This is the delete stack, used to store the vertices which * are going to be deleted during the plane cutting procedure. */ int *ds,*stacke; /** This is the auxiliary delete stack, which has size set by * current_delete2_size. */ int *ds2,*stacke2; /** This stores the current memory allocation for the marginal * cases. */ int current_marginal; /** This stores the total number of marginal points which are * currently in the buffer. */ int n_marg; /** This array contains a list of the marginal points, and also * the outcomes of the marginal tests. */ int *marg; /** The x coordinate of the normal vector to the test plane. */ double px; /** The y coordinate of the normal vector to the test plane. */ double py; /** The z coordinate of the normal vector to the test plane. */ double pz; /** The magnitude of the normal vector to the test plane. */ double prsq; template void add_memory(vc_class &vc,int i,int *stackp2); template void add_memory_vertices(vc_class &vc); template void add_memory_vorder(vc_class &vc); void add_memory_ds(int *&stackp); void add_memory_ds2(int *&stackp2); template inline bool collapse_order1(vc_class &vc); template inline bool collapse_order2(vc_class &vc); template inline bool delete_connection(vc_class &vc,int j,int k,bool hand); template inline bool search_for_outside_edge(vc_class &vc,int &up); template inline void add_to_stack(vc_class &vc,int lp,int *&stackp2); inline bool plane_intersects_track(double x,double y,double z,double rs,double g); inline void normals_search(std::vector &v,int i,int j,int k); inline bool search_edge(int l,int &m,int &k); inline int m_test(int n,double &ans); int check_marginal(int n,double &ans); friend class voronoicell; friend class voronoicell_neighbor; }; /** \brief Extension of the voronoicell_base class to represent a Voronoi * cell without neighbor information. * * This class is an extension of the voronoicell_base class, in cases when * is not necessary to track the IDs of neighboring particles associated * with each face of the Voronoi cell. */ class voronoicell : public voronoicell_base { public: using voronoicell_base::nplane; /** Copies the information from another voronoicell class into * this class, extending memory allocation if necessary. * \param[in] c the class to copy. */ inline void operator=(voronoicell &c) { voronoicell_base* vb((voronoicell_base*) &c); check_memory_for_copy(*this,vb);copy(vb); } /** Cuts a Voronoi cell using by the plane corresponding to the * perpendicular bisector of a particle. * \param[in] (x,y,z) the position of the particle. * \param[in] rsq the modulus squared of the vector. * \param[in] p_id the plane ID, ignored for this case where no * neighbor tracking is enabled. * \return False if the plane cut deleted the cell entirely, * true otherwise. */ inline bool nplane(double x,double y,double z,double rsq,int p_id) { return nplane(*this,x,y,z,rsq,0); } /** Cuts a Voronoi cell using by the plane corresponding to the * perpendicular bisector of a particle. * \param[in] (x,y,z) the position of the particle. * \param[in] p_id the plane ID, ignored for this case where no * neighbor tracking is enabled. * \return False if the plane cut deleted the cell entirely, * true otherwise. */ inline bool nplane(double x,double y,double z,int p_id) { double rsq=x*x+y*y+z*z; return nplane(*this,x,y,z,rsq,0); } /** Cuts a Voronoi cell using by the plane corresponding to the * perpendicular bisector of a particle. * \param[in] (x,y,z) the position of the particle. * \param[in] rsq the modulus squared of the vector. * \return False if the plane cut deleted the cell entirely, * true otherwise. */ inline bool plane(double x,double y,double z,double rsq) { return nplane(*this,x,y,z,rsq,0); } /** Cuts a Voronoi cell using by the plane corresponding to the * perpendicular bisector of a particle. * \param[in] (x,y,z) the position of the particle. * \return False if the plane cut deleted the cell entirely, * true otherwise. */ inline bool plane(double x,double y,double z) { double rsq=x*x+y*y+z*z; return nplane(*this,x,y,z,rsq,0); } /** Initializes the Voronoi cell to be rectangular box with the * given dimensions. * \param[in] (xmin,xmax) the minimum and maximum x coordinates. * \param[in] (ymin,ymax) the minimum and maximum y coordinates. * \param[in] (zmin,zmax) the minimum and maximum z coordinates. */ inline void init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax) { init_base(xmin,xmax,ymin,ymax,zmin,zmax); } /** Initializes the cell to be an octahedron with vertices at * (l,0,0), (-l,0,0), (0,l,0), (0,-l,0), (0,0,l), and (0,0,-l). * \param[in] l a parameter setting the size of the octahedron. */ inline void init_octahedron(double l) { init_octahedron_base(l); } /** Initializes the cell to be a tetrahedron. * \param[in] (x0,y0,z0) the coordinates of the first vertex. * \param[in] (x1,y1,z1) the coordinates of the second vertex. * \param[in] (x2,y2,z2) the coordinates of the third vertex. * \param[in] (x3,y3,z3) the coordinates of the fourth vertex. */ inline void init_tetrahedron(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3) { init_tetrahedron_base(x0,y0,z0,x1,y1,z1,x2,y2,z2,x3,y3,z3); } private: inline void n_allocate(int i,int m) {}; inline void n_add_memory_vertices(int i) {}; inline void n_add_memory_vorder(int i) {}; inline void n_set_pointer(int p,int n) {}; inline void n_copy(int a,int b,int c,int d) {}; inline void n_set(int a,int b,int c) {}; inline void n_set_aux1(int k) {}; inline void n_copy_aux1(int a,int b) {}; inline void n_copy_aux1_shift(int a,int b) {}; inline void n_set_aux2_copy(int a,int b) {}; inline void n_copy_pointer(int a,int b) {}; inline void n_set_to_aux1(int j) {}; inline void n_set_to_aux2(int j) {}; inline void n_allocate_aux1(int i) {}; inline void n_switch_to_aux1(int i) {}; inline void n_copy_to_aux1(int i,int m) {}; inline void n_set_to_aux1_offset(int k,int m) {}; inline void n_neighbors(std::vector &v) {v.clear();}; friend class voronoicell_base; }; /** \brief Extension of the voronoicell_base class to represent a Voronoi cell * with neighbor information. * * This class is an extension of the voronoicell_base class, in cases when the * IDs of neighboring particles associated with each face of the Voronoi cell. * It contains additional data structures mne and ne for storing this * information. */ class voronoicell_neighbor : public voronoicell_base { public: using voronoicell_base::nplane; /** This two dimensional array holds the neighbor information * associated with each vertex. mne[p] is a one dimensional * array which holds all of the neighbor information for * vertices of order p. */ int **mne; /** This is a two dimensional array that holds the neighbor * information associated with each vertex. ne[i] points to a * one-dimensional array in mne[nu[i]]. ne[i][j] holds the * neighbor information associated with the jth edge of vertex * i. It is set to the ID number of the plane that made the * face that is clockwise from the jth edge. */ int **ne; voronoicell_neighbor(); ~voronoicell_neighbor(); void operator=(voronoicell &c); void operator=(voronoicell_neighbor &c); /** Cuts the Voronoi cell by a particle whose center is at a * separation of (x,y,z) from the cell center. The value of rsq * should be initially set to \f$x^2+y^2+z^2\f$. * \param[in] (x,y,z) the normal vector to the plane. * \param[in] rsq the distance along this vector of the plane. * \param[in] p_id the plane ID (for neighbor tracking only). * \return False if the plane cut deleted the cell entirely, * true otherwise. */ inline bool nplane(double x,double y,double z,double rsq,int p_id) { return nplane(*this,x,y,z,rsq,p_id); } /** This routine calculates the modulus squared of the vector * before passing it to the main nplane() routine with full * arguments. * \param[in] (x,y,z) the vector to cut the cell by. * \param[in] p_id the plane ID (for neighbor tracking only). * \return False if the plane cut deleted the cell entirely, * true otherwise. */ inline bool nplane(double x,double y,double z,int p_id) { double rsq=x*x+y*y+z*z; return nplane(*this,x,y,z,rsq,p_id); } /** This version of the plane routine just makes up the plane * ID to be zero. It will only be referenced if neighbor * tracking is enabled. * \param[in] (x,y,z) the vector to cut the cell by. * \param[in] rsq the modulus squared of the vector. * \return False if the plane cut deleted the cell entirely, * true otherwise. */ inline bool plane(double x,double y,double z,double rsq) { return nplane(*this,x,y,z,rsq,0); } /** Cuts a Voronoi cell using the influence of a particle at * (x,y,z), first calculating the modulus squared of this * vector before passing it to the main nplane() routine. Zero * is supplied as the plane ID, which will be ignored unless * neighbor tracking is enabled. * \param[in] (x,y,z) the vector to cut the cell by. * \return False if the plane cut deleted the cell entirely, * true otherwise. */ inline bool plane(double x,double y,double z) { double rsq=x*x+y*y+z*z; return nplane(*this,x,y,z,rsq,0); } void init(double xmin,double xmax,double ymin,double ymax,double zmin,double zmax); void init_octahedron(double l); void init_tetrahedron(double x0,double y0,double z0,double x1,double y1,double z1,double x2,double y2,double z2,double x3,double y3,double z3); void check_facets(); virtual void neighbors(std::vector &v); virtual void print_edges_neighbors(int i); virtual void output_neighbors(FILE *fp=stdout) { std::vector v;neighbors(v); voro_print_vector(v,fp); } private: int *paux1; int *paux2; inline void n_allocate(int i,int m) {mne[i]=new int[m*i];} inline void n_add_memory_vertices(int i) { int **pp=new int*[i]; for(int j=0;j #include "voro++.hh" using namespace voro; enum blocks_mode { none, length_scale, specified }; // A maximum allowed number of regions, to prevent enormous amounts of memory // being allocated const int max_regions=16777216; // This message gets displayed if the user requests the help flag void help_message() { puts("Voro++ version 0.4.5, by Chris H. Rycroft (UC Berkeley/LBL)\n\n" "Syntax: voro++ [options] \n" " \n\n" "By default, the utility reads in the input file of particle IDs and positions,\n" "computes the Voronoi cell for each, and then creates with an\n" "additional column containing the volume of each Voronoi cell.\n\n" "Available options:\n" " -c : Specify a custom output string\n" " -g : Turn on the gnuplot output to \n" " -h/--help : Print this information\n" " -hc : Print information about custom output\n" " -l : Manually specify a length scale to configure the internal\n" " computational grid\n" " -m : Manually choose the memory allocation per grid block\n" " (default 8)\n" " -n [3] : Manually specify the internal grid size\n" " -o : Ensure that the output file has the same order as the input\n" " file\n" " -p : Make container periodic in all three directions\n" " -px : Make container periodic in the x direction\n" " -py : Make container periodic in the y direction\n" " -pz : Make container periodic in the z direction\n" " -r : Assume the input file has an extra coordinate for radii\n" " -v : Verbose output\n" " --version : Print version information\n" " -wb [6] : Add six plane wall objects to make rectangular box containing\n" " the space x1 and POV-Ray Voronoi\n" " cells to \n" " -yp : Save only POV-Ray particles to \n" " -yv : Save only POV-Ray Voronoi cells to "); } // This message gets displayed if the user requests information about doing // custom output void custom_output_message() { puts("The \"-c\" option allows a string to be specified that will customize the output\n" "file to contain a variety of statistics about each computed Voronoi cell. The\n" "string is similar to the standard C printf() function, made up of text with\n" "additional control sequences that begin with percentage signs that are expanded\n" "to different statistics. See http://math.lbl.gov/voro++/doc/custom.html for more\n" "information.\n" "\nParticle-related:\n" " %i The particle ID number\n" " %x The x coordinate of the particle\n" " %y The y coordinate of the particle\n" " %z The z coordinate of the particle\n" " %q The position vector of the particle, short for \"%x %y %z\"\n" " %r The radius of the particle (only printed if -p enabled)\n" "\nVertex-related:\n" " %w The number of vertices in the Voronoi cell\n" " %p A list of the vertices of the Voronoi cell in the format (x,y,z),\n" " relative to the particle center\n" " %P A list of the vertices of the Voronoi cell in the format (x,y,z),\n" " relative to the global coordinate system\n" " %o A list of the orders of each vertex\n" " %m The maximum radius squared of a vertex position, relative to the\n" " particle center\n" "\nEdge-related:\n" " %g The number of edges of the Voronoi cell\n" " %E The total edge distance\n" " %e A list of perimeters of each face\n" "\nFace-related:\n" " %s The number of faces of the Voronoi cell\n" " %F The total surface area of the Voronoi cell\n" " %A A frequency table of the number of edges for each face\n" " %a A list of the number of edges for each face\n" " %f A list of areas of each face\n" " %t A list of bracketed sequences of vertices that make up each face\n" " %l A list of normal vectors for each face\n" " %n A list of neighboring particle or wall IDs corresponding to each face\n" "\nVolume-related:\n" " %v The volume of the Voronoi cell\n" " %c The centroid of the Voronoi cell, relative to the particle center\n" " %C The centroid of the Voronoi cell, in the global coordinate system"); } // Ths message is displayed if the user requests version information void version_message() { puts("Voro++ version 0.4.5 (July 27th 2012)"); } // Prints an error message. This is called when the program is unable to make // sense of the command-line options. void error_message() { fputs("voro++: Unrecognized command-line options; type \"voro++ -h\" for more\ninformation.\n",stderr); } // Carries out the Voronoi computation and outputs the results to the requested // files template void cmd_line_output(c_loop &vl,c_class &con,const char* format,FILE* outfile,FILE* gnu_file,FILE* povp_file,FILE* povv_file,bool verbose,double &vol,int &vcc,int &tp) { int pid,ps=con.ps;double x,y,z,r; if(con.contains_neighbor(format)) { voronoicell_neighbor c; if(vl.start()) do if(con.compute_cell(c,vl)) { vl.pos(pid,x,y,z,r); if(outfile!=NULL) c.output_custom(format,pid,x,y,z,r,outfile); if(gnu_file!=NULL) c.draw_gnuplot(x,y,z,gnu_file); if(povp_file!=NULL) { fprintf(povp_file,"// id %d\n",pid); if(ps==4) fprintf(povp_file,"sphere{<%g,%g,%g>,%g}\n",x,y,z,r); else fprintf(povp_file,"sphere{<%g,%g,%g>,s}\n",x,y,z); } if(povv_file!=NULL) { fprintf(povv_file,"// cell %d\n",pid); c.draw_pov(x,y,z,povv_file); } if(verbose) {vol+=c.volume();vcc++;} } while(vl.inc()); } else { voronoicell c; if(vl.start()) do if(con.compute_cell(c,vl)) { vl.pos(pid,x,y,z,r); if(outfile!=NULL) c.output_custom(format,pid,x,y,z,r,outfile); if(gnu_file!=NULL) c.draw_gnuplot(x,y,z,gnu_file); if(povp_file!=NULL) { fprintf(povp_file,"// id %d\n",pid); if(ps==4) fprintf(povp_file,"sphere{<%g,%g,%g>,%g}\n",x,y,z,r); else fprintf(povp_file,"sphere{<%g,%g,%g>,s}\n",x,y,z); } if(povv_file!=NULL) { fprintf(povv_file,"// cell %d\n",pid); c.draw_pov(x,y,z,povv_file); } if(verbose) {vol+=c.volume();vcc++;} } while(vl.inc()); } if(verbose) tp=con.total_particles(); } int main(int argc,char **argv) { int i=1,j=-7,custom_output=0,nx,ny,nz,init_mem(8); double ls=0; blocks_mode bm=none; bool gnuplot_output=false,povp_output=false,povv_output=false,polydisperse=false; bool xperiodic=false,yperiodic=false,zperiodic=false,ordered=false,verbose=false; pre_container *pcon=NULL;pre_container_poly *pconp=NULL; wall_list wl; // If there's one argument, check to see if it's requesting help. // Otherwise, bail out with an error. if(argc==2) { if(strcmp(argv[1],"-h")==0||strcmp(argv[1],"--help")==0) { help_message();return 0; } else if(strcmp(argv[1],"-hc")==0) { custom_output_message();return 0; } else if(strcmp(argv[1],"--version")==0) { version_message();return 0; } else { error_message(); return VOROPP_CMD_LINE_ERROR; } } // If there aren't enough command-line arguments, then bail out // with an error. if(argc<7) { error_message(); return VOROPP_CMD_LINE_ERROR; } // We have enough arguments. Now start searching for command-line // options. while(i=argc-8) {error_message();wl.deallocate();return VOROPP_CMD_LINE_ERROR;} if(custom_output==0) { custom_output=++i; } else { fputs("voro++: multiple custom output strings detected\n",stderr); wl.deallocate(); return VOROPP_CMD_LINE_ERROR; } } else if(strcmp(argv[i],"-g")==0) { gnuplot_output=true; } else if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0) { help_message();wl.deallocate();return 0; } else if(strcmp(argv[i],"-hc")==0) { custom_output_message();wl.deallocate();return 0; } else if(strcmp(argv[i],"-l")==0) { if(i>=argc-8) {error_message();wl.deallocate();return VOROPP_CMD_LINE_ERROR;} if(bm!=none) { fputs("voro++: Conflicting options about grid setup (-l/-n)\n",stderr); wl.deallocate(); return VOROPP_CMD_LINE_ERROR; } bm=length_scale; i++;ls=atof(argv[i]); } else if(strcmp(argv[i],"-m")==0) { i++;init_mem=atoi(argv[i]); } else if(strcmp(argv[i],"-n")==0) { if(i>=argc-10) {error_message();wl.deallocate();return VOROPP_CMD_LINE_ERROR;} if(bm!=none) { fputs("voro++: Conflicting options about grid setup (-l/-n)\n",stderr); wl.deallocate(); return VOROPP_CMD_LINE_ERROR; } bm=specified; i++; nx=atoi(argv[i++]); ny=atoi(argv[i++]); nz=atoi(argv[i]); if(nx<=0||ny<=0||nz<=0) { fputs("voro++: Computational grid specified with -n must be greater than one\n" "in each direction\n",stderr); wl.deallocate(); return VOROPP_CMD_LINE_ERROR; } } else if(strcmp(argv[i],"-o")==0) { ordered=true; } else if(strcmp(argv[i],"-p")==0) { xperiodic=yperiodic=zperiodic=true; } else if(strcmp(argv[i],"-px")==0) { xperiodic=true; } else if(strcmp(argv[i],"-py")==0) { yperiodic=true; } else if(strcmp(argv[i],"-pz")==0) { zperiodic=true; } else if(strcmp(argv[i],"-r")==0) { polydisperse=true; } else if(strcmp(argv[i],"-v")==0) { verbose=true; } else if(strcmp(argv[i],"--version")==0) { version_message(); wl.deallocate(); return 0; } else if(strcmp(argv[i],"-wb")==0) { if(i>=argc-13) {error_message();wl.deallocate();return VOROPP_CMD_LINE_ERROR;} i++; double w0=atof(argv[i++]),w1=atof(argv[i++]); double w2=atof(argv[i++]),w3=atof(argv[i++]); double w4=atof(argv[i++]),w5=atof(argv[i]); wl.add_wall(new wall_plane(-1,0,0,-w0,j));j--; wl.add_wall(new wall_plane(1,0,0,w1,j));j--; wl.add_wall(new wall_plane(0,-1,0,-w2,j));j--; wl.add_wall(new wall_plane(0,1,0,w3,j));j--; wl.add_wall(new wall_plane(0,0,-1,-w4,j));j--; wl.add_wall(new wall_plane(0,0,1,w5,j));j--; } else if(strcmp(argv[i],"-ws")==0) { if(i>=argc-11) {error_message();wl.deallocate();return VOROPP_CMD_LINE_ERROR;} i++; double w0=atof(argv[i++]),w1=atof(argv[i++]); double w2=atof(argv[i++]),w3=atof(argv[i]); wl.add_wall(new wall_sphere(w0,w1,w2,w3,j)); j--; } else if(strcmp(argv[i],"-wp")==0) { if(i>=argc-11) {error_message();wl.deallocate();return VOROPP_CMD_LINE_ERROR;} i++; double w0=atof(argv[i++]),w1=atof(argv[i++]); double w2=atof(argv[i++]),w3=atof(argv[i]); wl.add_wall(new wall_plane(w0,w1,w2,w3,j)); j--; } else if(strcmp(argv[i],"-wc")==0) { if(i>=argc-14) {error_message();wl.deallocate();return VOROPP_CMD_LINE_ERROR;} i++; double w0=atof(argv[i++]),w1=atof(argv[i++]); double w2=atof(argv[i++]),w3=atof(argv[i++]); double w4=atof(argv[i++]),w5=atof(argv[i++]); double w6=atof(argv[i]); wl.add_wall(new wall_cylinder(w0,w1,w2,w3,w4,w5,w6,j)); j--; } else if(strcmp(argv[i],"-wo")==0) { if(i>=argc-14) {error_message();wl.deallocate();return VOROPP_CMD_LINE_ERROR;} i++; double w0=atof(argv[i++]),w1=atof(argv[i++]); double w2=atof(argv[i++]),w3=atof(argv[i++]); double w4=atof(argv[i++]),w5=atof(argv[i++]); double w6=atof(argv[i]); wl.add_wall(new wall_cone(w0,w1,w2,w3,w4,w5,w6,j)); j--; } else if(strcmp(argv[i],"-y")==0) { povp_output=povv_output=true; } else if(strcmp(argv[i],"-yp")==0) { povp_output=true; } else if(strcmp(argv[i],"-yv")==0) { povv_output=true; } else { wl.deallocate(); error_message(); return VOROPP_CMD_LINE_ERROR; } i++; } // Check the memory guess is positive if(init_mem<=0) { fputs("voro++: The memory allocation must be positive\n",stderr); wl.deallocate(); return VOROPP_CMD_LINE_ERROR; } // Read in the dimensions of the test box, and estimate the number of // boxes to divide the region up into double ax=atof(argv[i]),bx=atof(argv[i+1]); double ay=atof(argv[i+2]),by=atof(argv[i+3]); double az=atof(argv[i+4]),bz=atof(argv[i+5]); // Check that for each coordinate, the minimum value is smaller // than the maximum value if(bximport(argv[i+6]); pconp->guess_optimal(nx,ny,nz); } else { pcon=new pre_container(ax,bx,ay,by,az,bz,xperiodic,yperiodic,zperiodic); pcon->import(argv[i+6]); pcon->guess_optimal(nx,ny,nz); } } else { double nxf,nyf,nzf; if(bm==length_scale) { // Check that the length scale is positive and // reasonably large if(lsmax_regions) { fprintf(stderr,"voro++: Number of computational blocks exceeds the maximum allowed of %d.\n" "Either increase the particle length scale, or recompile with an increased\nmaximum.",max_regions); wl.deallocate(); return VOROPP_MEMORY_ERROR; } } // Check that the output filename is a sensible length int flen=strlen(argv[i+6]); if(flen>4096) { fputs("voro++: Filename too long\n",stderr); wl.deallocate(); return VOROPP_CMD_LINE_ERROR; } // Open files for output char *buffer=new char[flen+7]; sprintf(buffer,"%s.vol",argv[i+6]); FILE *outfile=safe_fopen(buffer,"w"),*gnu_file,*povp_file,*povv_file; if(gnuplot_output) { sprintf(buffer,"%s.gnu",argv[i+6]); gnu_file=safe_fopen(buffer,"w"); } else gnu_file=NULL; if(povp_output) { sprintf(buffer,"%s_p.pov",argv[i+6]); povp_file=safe_fopen(buffer,"w"); } else povp_file=NULL; if(povv_output) { sprintf(buffer,"%s_v.pov",argv[i+6]); povv_file=safe_fopen(buffer,"w"); } else povv_file=NULL; delete [] buffer; const char *c_str=(custom_output==0?(polydisperse?"%i %q %v %r":"%i %q %v"):argv[custom_output]); // Now switch depending on whether polydispersity was enabled, and // whether output ordering is requested double vol=0;int tp=0,vcc=0; if(polydisperse) { if(ordered) { particle_order vo; container_poly con(ax,bx,ay,by,az,bz,nx,ny,nz,xperiodic,yperiodic,zperiodic,init_mem); con.add_wall(wl); if(bm==none) { pconp->setup(vo,con);delete pconp; } else con.import(vo,argv[i+6]); c_loop_order vlo(con,vo); cmd_line_output(vlo,con,c_str,outfile,gnu_file,povp_file,povv_file,verbose,vol,vcc,tp); } else { container_poly con(ax,bx,ay,by,az,bz,nx,ny,nz,xperiodic,yperiodic,zperiodic,init_mem); con.add_wall(wl); if(bm==none) { pconp->setup(con);delete pconp; } else con.import(argv[i+6]); c_loop_all vla(con); cmd_line_output(vla,con,c_str,outfile,gnu_file,povp_file,povv_file,verbose,vol,vcc,tp); } } else { if(ordered) { particle_order vo; container con(ax,bx,ay,by,az,bz,nx,ny,nz,xperiodic,yperiodic,zperiodic,init_mem); con.add_wall(wl); if(bm==none) { pcon->setup(vo,con);delete pcon; } else con.import(vo,argv[i+6]); c_loop_order vlo(con,vo); cmd_line_output(vlo,con,c_str,outfile,gnu_file,povp_file,povv_file,verbose,vol,vcc,tp); } else { container con(ax,bx,ay,by,az,bz,nx,ny,nz,xperiodic,yperiodic,zperiodic,init_mem); con.add_wall(wl); if(bm==none) { pcon->setup(con);delete pcon; } else con.import(argv[i+6]); c_loop_all vla(con); cmd_line_output(vla,con,c_str,outfile,gnu_file,povp_file,povv_file,verbose,vol,vcc,tp); } } // Print information if verbose output requested if(verbose) { printf("Container geometry : [%g:%g] [%g:%g] [%g:%g]\n" "Computational grid size : %d by %d by %d (%s)\n" "Filename : %s\n" "Output string : %s%s\n",ax,bx,ay,by,az,bz,nx,ny,nz, bm==none?"estimated from file":(bm==length_scale? "estimated using length scale":"directly specified"), argv[i+6],c_str,custom_output==0?" (default)":""); printf("Total imported particles : %d (%.2g per grid block)\n" "Total V. cells computed : %d\n" "Total container volume : %g\n" "Total V. cell volume : %g\n",tp,((double) tp)/(nx*ny*nz), vcc,(bx-ax)*(by-ay)*(bz-az),vol); } // Close output files fclose(outfile); if(gnu_file!=NULL) fclose(gnu_file); if(povp_file!=NULL) fclose(povp_file); if(povv_file!=NULL) fclose(povv_file); return 0; } voro++-0.4.6/src/common.cc000600 000765 000024 00000004452 12230022105 015121 0ustar00chrstaff000000 000000 // Voro++, a 3D cell-based Voronoi library // // Author : Chris H. Rycroft (LBL / UC Berkeley) // Email : chr@alum.mit.edu // Date : August 30th 2011 /** \file common.cc * \brief Implementations of the small helper functions. */ #include "common.hh" namespace voro { /** \brief Prints a vector of integers. * * Prints a vector of integers. * \param[in] v the vector to print. * \param[in] fp the file stream to print to. */ void voro_print_vector(std::vector &v,FILE *fp) { int k=0,s=v.size(); while(k+4 &v,FILE *fp) { int k=0,s=v.size(); while(k+4 &v,FILE *fp) { int j,k=0,l; if(v.size()>0) { l=v[k++]; if(l<=1) { if(l==1) fprintf(fp,"(%d)",v[k++]); else fputs("()",fp); } else { j=k+l; fprintf(fp,"(%d",v[k++]); while(k #include #include #include "config.hh" namespace voro { /** \brief Function for printing fatal error messages and exiting. * * Function for printing fatal error messages and exiting. * \param[in] p a pointer to the message to print. * \param[in] status the status code to return with. */ inline void voro_fatal_error(const char *p,int status) { fprintf(stderr,"voro++: %s\n",p); exit(status); } /** \brief Prints a vector of positions. * * Prints a vector of positions as bracketed triplets. * \param[in] v the vector to print. * \param[in] fp the file stream to print to. */ inline void voro_print_positions(std::vector &v,FILE *fp=stdout) { if(v.size()>0) { fprintf(fp,"(%g,%g,%g)",v[0],v[1],v[2]); for(int k=3;(unsigned int) k &v,FILE *fp=stdout); void voro_print_vector(std::vector &v,FILE *fp=stdout); void voro_print_face_vertices(std::vector &v,FILE *fp=stdout); } #endif voro++-0.4.6/src/config.hh000600 000765 000024 00000012054 12230022105 015105 0ustar00chrstaff000000 000000 // Voro++, a 3D cell-based Voronoi library // // Author : Chris H. Rycroft (LBL / UC Berkeley) // Email : chr@alum.mit.edu // Date : August 30th 2011 /** \file config.hh * \brief Master configuration file for setting various compile-time options. */ #ifndef VOROPP_CONFIG_HH #define VOROPP_CONFIG_HH namespace voro { // These constants set the initial memory allocation for the Voronoi cell /** The initial memory allocation for the number of vertices. */ const int init_vertices=256; /** The initial memory allocation for the maximum vertex order. */ const int init_vertex_order=64; /** The initial memory allocation for the number of regular vertices of order * 3. */ const int init_3_vertices=256; /** The initial memory allocation for the number of vertices of higher order. */ const int init_n_vertices=8; /** The initial buffer size for marginal cases used by the suretest class. */ const int init_marginal=64; /** The initial size for the delete stack. */ const int init_delete_size=256; /** The initial size for the auxiliary delete stack. */ const int init_delete2_size=256; /** The initial size for the wall pointer array. */ const int init_wall_size=32; /** The default initial size for the ordering class. */ const int init_ordering_size=4096; /** The initial size of the pre_container chunk index. */ const int init_chunk_size=256; // If the initial memory is too small, the program dynamically allocates more. // However, if the limits below are reached, then the program bails out. /** The maximum memory allocation for the number of vertices. */ const int max_vertices=16777216; /** The maximum memory allocation for the maximum vertex order. */ const int max_vertex_order=2048; /** The maximum memory allocation for the any particular order of vertex. */ const int max_n_vertices=16777216; /** The maximum buffer size for marginal cases used by the suretest class. */ const int max_marginal=16777216; /** The maximum size for the delete stack. */ const int max_delete_size=16777216; /** The maximum size for the auxiliary delete stack. */ const int max_delete2_size=16777216; /** The maximum amount of particle memory allocated for a single region. */ const int max_particle_memory=16777216; /** The maximum size for the wall pointer array. */ const int max_wall_size=2048; /** The maximum size for the ordering class. */ const int max_ordering_size=67108864; /** The maximum size for the pre_container chunk index. */ const int max_chunk_size=65536; /** The chunk size in the pre_container classes. */ const int pre_container_chunk_size=1024; #ifndef VOROPP_VERBOSE /** Voro++ can print a number of different status and debugging messages to * notify the user of special behavior, and this macro sets the amount which * are displayed. At level 0, no messages are printed. At level 1, messages * about unusual cases during cell construction are printed, such as when the * plane routine bails out due to floating point problems. At level 2, general * messages about memory expansion are printed. At level 3, technical details * about memory management are printed. */ #define VOROPP_VERBOSE 0 #endif /** If a point is within this distance of a cutting plane, then the code * assumes that point exactly lies on the plane. */ const double tolerance=1e-11; /** If a point is within this distance of a cutting plane, then the code stores * whether this point is inside, outside, or exactly on the cutting plane in * the marginal cases buffer, to prevent the test giving a different result on * a subsequent evaluation due to floating point rounding errors. */ const double tolerance2=2e-11; /** The square of the tolerance, used when deciding whether some squared * quantities are large enough to be used. */ const double tolerance_sq=tolerance*tolerance; /** A large number that is used in the computation. */ const double large_number=1e30; /** A radius to use as a placeholder when no other information is available. */ const double default_radius=0.5; /** The maximum number of shells of periodic images to test over. */ const int max_unit_voro_shells=10; /** A guess for the optimal number of particles per block, used to set up the * container grid. */ const double optimal_particles=5.6; /** If this is set to 1, then the code reports any instances of particles being * put outside of the container geometry. */ #define VOROPP_REPORT_OUT_OF_BOUNDS 0 /** Voro++ returns this status code if there is a file-related error, such as * not being able to open file. */ #define VOROPP_FILE_ERROR 1 /** Voro++ returns this status code if there is a memory allocation error, if * one of the safe memory limits is exceeded. */ #define VOROPP_MEMORY_ERROR 2 /** Voro++ returns this status code if there is any type of internal error, if * it detects that representation of the Voronoi cell is inconsistent. This * status code will generally indicate a bug, and the developer should be * contacted. */ #define VOROPP_INTERNAL_ERROR 3 /** Voro++ returns this status code if it could not interpret the command line * arguments passed to the command line utility. */ #define VOROPP_CMD_LINE_ERROR 4 } #endif voro++-0.4.6/src/container.cc000600 000765 000024 00000054437 12230022105 015623 0ustar00chrstaff000000 000000 // Voro++, a 3D cell-based Voronoi library // // Author : Chris H. Rycroft (LBL / UC Berkeley) // Email : chr@alum.mit.edu // Date : August 30th 2011 /** \file container.cc * \brief Function implementations for the container and related classes. */ #include "container.hh" namespace voro { /** The class constructor sets up the geometry of container, initializing the * minimum and maximum coordinates in each direction, and setting whether each * direction is periodic or not. It divides the container into a rectangular * grid of blocks, and allocates memory for each of these for storing particle * positions and IDs. * \param[in] (ax_,bx_) the minimum and maximum x coordinates. * \param[in] (ay_,by_) the minimum and maximum y coordinates. * \param[in] (az_,bz_) the minimum and maximum z coordinates. * \param[in] (nx_,ny_,nz_) the number of grid blocks in each of the three * coordinate directions. * \param[in] (xperiodic_,yperiodic_,zperiodic_) flags setting whether the * container is periodic in each * coordinate direction. * \param[in] init_mem the initial memory allocation for each block. * \param[in] ps_ the number of floating point entries to store for each * particle. */ container_base::container_base(double ax_,double bx_,double ay_,double by_,double az_,double bz_, int nx_,int ny_,int nz_,bool xperiodic_,bool yperiodic_,bool zperiodic_,int init_mem,int ps_) : voro_base(nx_,ny_,nz_,(bx_-ax_)/nx_,(by_-ay_)/ny_,(bz_-az_)/nz_), ax(ax_), bx(bx_), ay(ay_), by(by_), az(az_), bz(bz_), xperiodic(xperiodic_), yperiodic(yperiodic_), zperiodic(zperiodic_), id(new int*[nxyz]), p(new double*[nxyz]), co(new int[nxyz]), mem(new int[nxyz]), ps(ps_) { int l; for(l=0;l=nx) return false; int j=step_int((y-ay)*ysp); if(yperiodic) {l=step_mod(j,ny);y+=boxy*(l-j);j=l;} else if(j<0||j>=ny) return false; int k=step_int((z-az)*zsp); if(zperiodic) {l=step_mod(k,nz);z+=boxz*(l-k);k=l;} else if(k<0||k>=nz) return false; ijk+=nx*j+nxy*k; return true; } /** Takes a position vector and attempts to remap it into the primary domain. * \param[out] (ai,aj,ak) the periodic image displacement that the vector is in, * with (0,0,0) corresponding to the primary domain. * \param[out] (ci,cj,ck) the index of the block that the position vector is * within, once it has been remapped. * \param[in,out] (x,y,z) the position vector to consider, which is remapped * into the primary domain during the routine. * \param[out] ijk the block index that the vector is within. * \return True if the particle is within the container or can be remapped into * it, false if it lies outside of the container bounds. */ inline bool container_base::remap(int &ai,int &aj,int &ak,int &ci,int &cj,int &ck,double &x,double &y,double &z,int &ijk) { ci=step_int((x-ax)*xsp); if(ci<0||ci>=nx) { if(xperiodic) {ai=step_div(ci,nx);x-=ai*(bx-ax);ci-=ai*nx;} else return false; } else ai=0; cj=step_int((y-ay)*ysp); if(cj<0||cj>=ny) { if(yperiodic) {aj=step_div(cj,ny);y-=aj*(by-ay);cj-=aj*ny;} else return false; } else aj=0; ck=step_int((z-az)*zsp); if(ck<0||ck>=nz) { if(zperiodic) {ak=step_div(ck,nz);z-=ak*(bz-az);ck-=ak*nz;} else return false; } else ak=0; ijk=ci+nx*cj+nxy*ck; return true; } /** Takes a vector and finds the particle whose Voronoi cell contains that * vector. This is equivalent to finding the particle which is nearest to the * vector. Additional wall classes are not considered by this routine. * \param[in] (x,y,z) the vector to test. * \param[out] (rx,ry,rz) the position of the particle whose Voronoi cell * contains the vector. If the container is periodic, * this may point to a particle in a periodic image of * the primary domain. * \param[out] pid the ID of the particle. * \return True if a particle was found. If the container has no particles, * then the search will not find a Voronoi cell and false is returned. */ bool container::find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid) { int ai,aj,ak,ci,cj,ck,ijk; particle_record w; double mrs; // If the given vector lies outside the domain, but the container // is periodic, then remap it back into the domain if(!remap(ai,aj,ak,ci,cj,ck,x,y,z,ijk)) return false; vc.find_voronoi_cell(x,y,z,ci,cj,ck,ijk,w,mrs); if(w.ijk!=-1) { // Assemble the position vector of the particle to be returned, // applying a periodic remapping if necessary if(xperiodic) {ci+=w.di;if(ci<0||ci>=nx) ai+=step_div(ci,nx);} if(yperiodic) {cj+=w.dj;if(cj<0||cj>=ny) aj+=step_div(cj,ny);} if(zperiodic) {ck+=w.dk;if(ck<0||ck>=nz) ak+=step_div(ck,nz);} rx=p[w.ijk][3*w.l]+ai*(bx-ax); ry=p[w.ijk][3*w.l+1]+aj*(by-ay); rz=p[w.ijk][3*w.l+2]+ak*(bz-az); pid=id[w.ijk][w.l]; return true; } // If no particle if found then just return false return false; } /** Takes a vector and finds the particle whose Voronoi cell contains that * vector. Additional wall classes are not considered by this routine. * \param[in] (x,y,z) the vector to test. * \param[out] (rx,ry,rz) the position of the particle whose Voronoi cell * contains the vector. If the container is periodic, * this may point to a particle in a periodic image of * the primary domain. * \param[out] pid the ID of the particle. * \return True if a particle was found. If the container has no particles, * then the search will not find a Voronoi cell and false is returned. */ bool container_poly::find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid) { int ai,aj,ak,ci,cj,ck,ijk; particle_record w; double mrs; // If the given vector lies outside the domain, but the container // is periodic, then remap it back into the domain if(!remap(ai,aj,ak,ci,cj,ck,x,y,z,ijk)) return false; vc.find_voronoi_cell(x,y,z,ci,cj,ck,ijk,w,mrs); if(w.ijk!=-1) { // Assemble the position vector of the particle to be returned, // applying a periodic remapping if necessary if(xperiodic) {ci+=w.di;if(ci<0||ci>=nx) ai+=step_div(ci,nx);} if(yperiodic) {cj+=w.dj;if(cj<0||cj>=ny) aj+=step_div(cj,ny);} if(zperiodic) {ck+=w.dk;if(ck<0||ck>=nz) ak+=step_div(ck,nz);} rx=p[w.ijk][4*w.l]+ai*(bx-ax); ry=p[w.ijk][4*w.l+1]+aj*(by-ay); rz=p[w.ijk][4*w.l+2]+ak*(bz-az); pid=id[w.ijk][w.l]; return true; } // If no particle if found then just return false return false; } /** Increase memory for a particular region. * \param[in] i the index of the region to reallocate. */ void container_base::add_particle_memory(int i) { int l,nmem=mem[i]<<1; // Carry out a check on the memory allocation size, and // print a status message if requested if(nmem>max_particle_memory) voro_fatal_error("Absolute maximum memory allocation exceeded",VOROPP_MEMORY_ERROR); #if VOROPP_VERBOSE >=3 fprintf(stderr,"Particle memory in region %d scaled up to %d\n",i,nmem); #endif // Allocate new memory and copy in the contents of the old arrays int *idp=new int[nmem]; for(l=0;lbx||yby||zbz) return false; return point_inside_walls(x,y,z); } /** Draws an outline of the domain in gnuplot format. * \param[in] fp the file handle to write to. */ void container_base::draw_domain_gnuplot(FILE *fp) { fprintf(fp,"%g %g %g\n%g %g %g\n%g %g %g\n%g %g %g\n",ax,ay,az,bx,ay,az,bx,by,az,ax,by,az); fprintf(fp,"%g %g %g\n%g %g %g\n%g %g %g\n%g %g %g\n",ax,by,bz,bx,by,bz,bx,ay,bz,ax,ay,bz); fprintf(fp,"%g %g %g\n\n%g %g %g\n%g %g %g\n\n",ax,by,bz,ax,ay,az,ax,ay,bz); fprintf(fp,"%g %g %g\n%g %g %g\n\n%g %g %g\n%g %g %g\n\n",bx,ay,az,bx,ay,bz,bx,by,az,bx,by,bz); } /** Draws an outline of the domain in POV-Ray format. * \param[in] fp the file handle to write to. */ void container_base::draw_domain_pov(FILE *fp) { fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n" "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",ax,ay,az,bx,ay,az,ax,by,az,bx,by,az); fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n" "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",ax,by,bz,bx,by,bz,ax,ay,bz,bx,ay,bz); fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n" "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",ax,ay,az,ax,by,az,bx,ay,az,bx,by,az); fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n" "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",bx,ay,bz,bx,by,bz,ax,ay,bz,ax,by,bz); fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n" "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",ax,ay,az,ax,ay,bz,bx,ay,az,bx,ay,bz); fprintf(fp,"cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n" "cylinder{<%g,%g,%g>,<%g,%g,%g>,rr}\n",bx,by,az,bx,by,bz,ax,by,az,ax,by,bz); fprintf(fp,"sphere{<%g,%g,%g>,rr}\nsphere{<%g,%g,%g>,rr}\n" "sphere{<%g,%g,%g>,rr}\nsphere{<%g,%g,%g>,rr}\n",ax,ay,az,bx,ay,az,ax,by,az,bx,by,az); fprintf(fp,"sphere{<%g,%g,%g>,rr}\nsphere{<%g,%g,%g>,rr}\n" "sphere{<%g,%g,%g>,rr}\nsphere{<%g,%g,%g>,rr}\n",ax,ay,bz,bx,ay,bz,ax,by,bz,bx,by,bz); } /** The wall_list constructor sets up an array of pointers to wall classes. */ wall_list::wall_list() : walls(new wall*[init_wall_size]), wep(walls), wel(walls+init_wall_size), current_wall_size(init_wall_size) {} /** The wall_list destructor frees the array of pointers to the wall classes. */ wall_list::~wall_list() { delete [] walls; } /** Adds all of the walls on another wall_list to this class. * \param[in] wl a reference to the wall class. */ void wall_list::add_wall(wall_list &wl) { for(wall **wp=wl.walls;wpmax_wall_size) voro_fatal_error("Wall memory allocation exceeded absolute maximum",VOROPP_MEMORY_ERROR); wall **nwalls=new wall*[current_wall_size],**nwp=nwalls,**wp=walls; while(wp #include #include "config.hh" #include "common.hh" #include "v_base.hh" #include "cell.hh" #include "c_loops.hh" #include "v_compute.hh" #include "rad_option.hh" namespace voro { /** \brief Pure virtual class from which wall objects are derived. * * This is a pure virtual class for a generic wall object. A wall object * can be specified by deriving a new class from this and specifying the * functions.*/ class wall { public: virtual ~wall() {} /** A pure virtual function for testing whether a point is * inside the wall object. */ virtual bool point_inside(double x,double y,double z) = 0; /** A pure virtual function for cutting a cell without * neighbor-tracking with a wall. */ virtual bool cut_cell(voronoicell &c,double x,double y,double z) = 0; /** A pure virtual function for cutting a cell with * neighbor-tracking enabled with a wall. */ virtual bool cut_cell(voronoicell_neighbor &c,double x,double y,double z) = 0; }; /** \brief A class for storing a list of pointers to walls. * * This class stores a list of pointers to wall classes. It contains several * simple routines that make use of the wall classes (such as telling whether a * given position is inside all of the walls or not). It can be used by itself, * but also forms part of container_base, for associating walls with this * class. */ class wall_list { public: /** An array holding pointers to wall objects. */ wall **walls; /** A pointer to the next free position to add a wall pointer. */ wall **wep; wall_list(); ~wall_list(); /** Adds a wall to the list. * \param[in] w the wall to add. */ inline void add_wall(wall *w) { if(wep==wel) increase_wall_memory(); *(wep++)=w; } /** Adds a wall to the list. * \param[in] w a reference to the wall to add. */ inline void add_wall(wall &w) {add_wall(&w);} void add_wall(wall_list &wl); /** Determines whether a given position is inside all of the * walls on the list. * \param[in] (x,y,z) the position to test. * \return True if it is inside, false if it is outside. */ inline bool point_inside_walls(double x,double y,double z) { for(wall **wp=walls;wppoint_inside(x,y,z))) return false; return true; } /** Cuts a Voronoi cell by all of the walls currently on * the list. * \param[in] c a reference to the Voronoi cell class. * \param[in] (x,y,z) the position of the cell. * \return True if the cell still exists, false if the cell is * deleted. */ template bool apply_walls(c_class &c,double x,double y,double z) { for(wall **wp=walls;wpcut_cell(c,x,y,z))) return false; return true; } void deallocate(); protected: void increase_wall_memory(); /** A pointer to the limit of the walls array, used to * determine when array is full. */ wall **wel; /** The current amount of memory allocated for walls. */ int current_wall_size; }; /** \brief Class for representing a particle system in a three-dimensional * rectangular box. * * This class represents a system of particles in a three-dimensional * rectangular box. Any combination of non-periodic and periodic coordinates * can be used in the three coordinate directions. The class is not intended * for direct use, but instead forms the base of the container and * container_poly classes that add specialized routines for computing the * regular and radical Voronoi tessellations respectively. It contains routines * that are commonly between these two classes, such as those for drawing the * domain, and placing particles within the internal data structure. * * The class is derived from the wall_list class, which encapsulates routines * for associating walls with the container, and the voro_base class, which * encapsulates routines about the underlying computational grid. */ class container_base : public voro_base, public wall_list { public: /** The minimum x coordinate of the container. */ const double ax; /** The maximum x coordinate of the container. */ const double bx; /** The minimum y coordinate of the container. */ const double ay; /** The maximum y coordinate of the container. */ const double by; /** The minimum z coordinate of the container. */ const double az; /** The maximum z coordinate of the container. */ const double bz; /** A boolean value that determines if the x coordinate in * periodic or not. */ const bool xperiodic; /** A boolean value that determines if the y coordinate in * periodic or not. */ const bool yperiodic; /** A boolean value that determines if the z coordinate in * periodic or not. */ const bool zperiodic; /** This array holds the numerical IDs of each particle in each * computational box. */ int **id; /** A two dimensional array holding particle positions. For the * derived container_poly class, this also holds particle * radii. */ double **p; /** This array holds the number of particles within each * computational box of the container. */ int *co; /** This array holds the maximum amount of particle memory for * each computational box of the container. If the number of * particles in a particular box ever approaches this limit, * more is allocated using the add_particle_memory() function. */ int *mem; /** The amount of memory in the array structure for each * particle. This is set to 3 when the basic class is * initialized, so that the array holds (x,y,z) positions. If * the container class is initialized as part of the derived * class container_poly, then this is set to 4, to also hold * the particle radii. */ const int ps; container_base(double ax_,double bx_,double ay_,double by_,double az_,double bz_, int nx_,int ny_,int nz_,bool xperiodic_,bool yperiodic_,bool zperiodic_, int init_mem,int ps_); ~container_base(); bool point_inside(double x,double y,double z); void region_count(); /** Initializes the Voronoi cell prior to a compute_cell * operation for a specific particle being carried out by a * voro_compute class. The cell is initialized to fill the * entire container. For non-periodic coordinates, this is set * by the position of the walls. For periodic coordinates, the * space is equally divided in either direction from the * particle's initial position. Plane cuts made by any walls * that have been added are then applied to the cell. * \param[in,out] c a reference to a voronoicell object. * \param[in] ijk the block that the particle is within. * \param[in] q the index of the particle within its block. * \param[in] (ci,cj,ck) the coordinates of the block in the * container coordinate system. * \param[out] (i,j,k) the coordinates of the test block * relative to the voro_compute * coordinate system. * \param[out] (x,y,z) the position of the particle. * \param[out] disp a block displacement used internally by the * compute_cell routine. * \return False if the plane cuts applied by walls completely * removed the cell, true otherwise. */ template inline bool initialize_voronoicell(v_cell &c,int ijk,int q,int ci,int cj,int ck, int &i,int &j,int &k,double &x,double &y,double &z,int &disp) { double x1,x2,y1,y2,z1,z2,*pp=p[ijk]+ps*q; x=*(pp++);y=*(pp++);z=*pp; if(xperiodic) {x1=-(x2=0.5*(bx-ax));i=nx;} else {x1=ax-x;x2=bx-x;i=ci;} if(yperiodic) {y1=-(y2=0.5*(by-ay));j=ny;} else {y1=ay-y;y2=by-y;j=cj;} if(zperiodic) {z1=-(z2=0.5*(bz-az));k=nz;} else {z1=az-z;z2=bz-z;k=ck;} c.init(x1,x2,y1,y2,z1,z2); if(!apply_walls(c,x,y,z)) return false; disp=ijk-i-nx*(j+ny*k); return true; } /** Initializes parameters for a find_voronoi_cell call within * the voro_compute template. * \param[in] (ci,cj,ck) the coordinates of the test block in * the container coordinate system. * \param[in] ijk the index of the test block * \param[out] (i,j,k) the coordinates of the test block * relative to the voro_compute * coordinate system. * \param[out] disp a block displacement used internally by the * find_voronoi_cell routine. */ inline void initialize_search(int ci,int cj,int ck,int ijk,int &i,int &j,int &k,int &disp) { i=xperiodic?nx:ci; j=yperiodic?ny:cj; k=zperiodic?nz:ck; disp=ijk-i-nx*(j+ny*k); } /** Returns the position of a particle currently being computed * relative to the computational block that it is within. It is * used to select the optimal worklist entry to use. * \param[in] (x,y,z) the position of the particle. * \param[in] (ci,cj,ck) the block that the particle is within. * \param[out] (fx,fy,fz) the position relative to the block. */ inline void frac_pos(double x,double y,double z,double ci,double cj,double ck, double &fx,double &fy,double &fz) { fx=x-ax-boxx*ci; fy=y-ay-boxy*cj; fz=z-az-boxz*ck; } /** Calculates the index of block in the container structure * corresponding to given coordinates. * \param[in] (ci,cj,ck) the coordinates of the original block * in the current computation, relative * to the container coordinate system. * \param[in] (ei,ej,ek) the displacement of the current block * from the original block. * \param[in,out] (qx,qy,qz) the periodic displacement that * must be added to the particles * within the computed block. * \param[in] disp a block displacement used internally by the * find_voronoi_cell and compute_cell routines. * \return The block index. */ inline int region_index(int ci,int cj,int ck,int ei,int ej,int ek,double &qx,double &qy,double &qz,int &disp) { if(xperiodic) {if(ci+ei=(nx<<1)) {ei-=nx;qx=bx-ax;} else qx=0;} if(yperiodic) {if(cj+ej=(ny<<1)) {ej-=ny;qy=by-ay;} else qy=0;} if(zperiodic) {if(ck+ek=(nz<<1)) {ek-=nz;qz=bz-az;} else qz=0;} return disp+ei+nx*(ej+ny*ek); } void draw_domain_gnuplot(FILE *fp=stdout); /** Draws an outline of the domain in Gnuplot format. * \param[in] filename the filename to write to. */ inline void draw_domain_gnuplot(const char* filename) { FILE *fp=safe_fopen(filename,"w"); draw_domain_gnuplot(fp); fclose(fp); } void draw_domain_pov(FILE *fp=stdout); /** Draws an outline of the domain in Gnuplot format. * \param[in] filename the filename to write to. */ inline void draw_domain_pov(const char* filename) { FILE *fp=safe_fopen(filename,"w"); draw_domain_pov(fp); fclose(fp); } /** Sums up the total number of stored particles. * \return The number of particles. */ inline int total_particles() { int tp=*co; for(int *cop=co+1;cop void draw_particles(c_loop &vl,FILE *fp) { double *pp; if(vl.start()) do { pp=p[vl.ijk]+3*vl.q; fprintf(fp,"%d %g %g %g\n",id[vl.ijk][vl.q],*pp,pp[1],pp[2]); } while(vl.inc()); } /** Dumps all of the particle IDs and positions to a file. * \param[in] fp a file handle to write to. */ inline void draw_particles(FILE *fp=stdout) { c_loop_all vl(*this); draw_particles(vl,fp); } /** Dumps all of the particle IDs and positions to a file. * \param[in] filename the name of the file to write to. */ inline void draw_particles(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_particles(fp); fclose(fp); } /** Dumps particle positions in POV-Ray format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_particles_pov(c_loop &vl,FILE *fp) { double *pp; if(vl.start()) do { pp=p[vl.ijk]+3*vl.q; fprintf(fp,"// id %d\nsphere{<%g,%g,%g>,s}\n", id[vl.ijk][vl.q],*pp,pp[1],pp[2]); } while(vl.inc()); } /** Dumps all particle positions in POV-Ray format. * \param[in] fp a file handle to write to. */ inline void draw_particles_pov(FILE *fp=stdout) { c_loop_all vl(*this); draw_particles_pov(vl,fp); } /** Dumps all particle positions in POV-Ray format. * \param[in] filename the name of the file to write to. */ inline void draw_particles_pov(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_particles_pov(fp); fclose(fp); } /** Computes Voronoi cells and saves the output in gnuplot * format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_cells_gnuplot(c_loop &vl,FILE *fp) { voronoicell c;double *pp; if(vl.start()) do if(compute_cell(c,vl)) { pp=p[vl.ijk]+ps*vl.q; c.draw_gnuplot(*pp,pp[1],pp[2],fp); } while(vl.inc()); } /** Computes all Voronoi cells and saves the output in gnuplot * format. * \param[in] fp a file handle to write to. */ inline void draw_cells_gnuplot(FILE *fp=stdout) { c_loop_all vl(*this); draw_cells_gnuplot(vl,fp); } /** Computes all Voronoi cells and saves the output in gnuplot * format. * \param[in] filename the name of the file to write to. */ inline void draw_cells_gnuplot(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_cells_gnuplot(fp); fclose(fp); } /** Computes Voronoi cells and saves the output in POV-Ray * format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_cells_pov(c_loop &vl,FILE *fp) { voronoicell c;double *pp; if(vl.start()) do if(compute_cell(c,vl)) { fprintf(fp,"// cell %d\n",id[vl.ijk][vl.q]); pp=p[vl.ijk]+ps*vl.q; c.draw_pov(*pp,pp[1],pp[2],fp); } while(vl.inc()); } /** Computes all Voronoi cells and saves the output in POV-Ray * format. * \param[in] fp a file handle to write to. */ inline void draw_cells_pov(FILE *fp=stdout) { c_loop_all vl(*this); draw_cells_pov(vl,fp); } /** Computes all Voronoi cells and saves the output in POV-Ray * format. * \param[in] filename the name of the file to write to. */ inline void draw_cells_pov(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_cells_pov(fp); fclose(fp); } /** Computes the Voronoi cells and saves customized information * about them. * \param[in] vl the loop class to use. * \param[in] format the custom output string to use. * \param[in] fp a file handle to write to. */ template void print_custom(c_loop &vl,const char *format,FILE *fp) { int ijk,q;double *pp; if(contains_neighbor(format)) { voronoicell_neighbor c; if(vl.start()) do if(compute_cell(c,vl)) { ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q; c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],default_radius,fp); } while(vl.inc()); } else { voronoicell c; if(vl.start()) do if(compute_cell(c,vl)) { ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q; c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],default_radius,fp); } while(vl.inc()); } } void print_custom(const char *format,FILE *fp=stdout); void print_custom(const char *format,const char *filename); bool find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid); /** Computes the Voronoi cell for a particle currently being * referenced by a loop class. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] vl the loop class to use. * \return True if the cell was computed. If the cell cannot be * computed, if it is removed entirely by a wall or boundary * condition, then the routine returns false. */ template inline bool compute_cell(v_cell &c,c_loop &vl) { return vc.compute_cell(c,vl.ijk,vl.q,vl.i,vl.j,vl.k); } /** Computes the Voronoi cell for given particle. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] ijk the block that the particle is within. * \param[in] q the index of the particle within the block. * \return True if the cell was computed. If the cell cannot be * computed, if it is removed entirely by a wall or boundary * condition, then the routine returns false. */ template inline bool compute_cell(v_cell &c,int ijk,int q) { int k=ijk/nxy,ijkt=ijk-nxy*k,j=ijkt/nx,i=ijkt-j*nx; return vc.compute_cell(c,ijk,q,i,j,k); } /** Computes the Voronoi cell for a ghost particle at a given * location. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] (x,y,z) the location of the ghost particle. * \return True if the cell was computed. If the cell cannot be * computed, if it is removed entirely by a wall or boundary * condition, then the routine returns false. */ template inline bool compute_ghost_cell(v_cell &c,double x,double y,double z) { int ijk; if(put_locate_block(ijk,x,y,z)) { double *pp=p[ijk]+3*co[ijk]++; *(pp++)=x;*(pp++)=y;*pp=z; bool q=compute_cell(c,ijk,co[ijk]-1); co[ijk]--; return q; } return false; } private: voro_compute vc; friend class voro_compute; }; /** \brief Extension of the container_base class for computing radical Voronoi * tessellations. * * This class is an extension of container_base class that has routines * specifically for computing the radical Voronoi tessellation that depends on * the particle radii. */ class container_poly : public container_base, public radius_poly { public: container_poly(double ax_,double bx_,double ay_,double by_,double az_,double bz_, int nx_,int ny_,int nz_,bool xperiodic_,bool yperiodic_,bool zperiodic_,int init_mem); void clear(); void put(int n,double x,double y,double z,double r); void put(particle_order &vo,int n,double x,double y,double z,double r); void import(FILE *fp=stdin); void import(particle_order &vo,FILE *fp=stdin); /** Imports a list of particles from an open file stream into * the container_poly class. Entries of five numbers (Particle * ID, x position, y position, z position, radius) are searched * for. If the file cannot be successfully read, then the * routine causes a fatal error. * \param[in] filename the name of the file to open and read * from. */ inline void import(const char* filename) { FILE *fp=safe_fopen(filename,"r"); import(fp); fclose(fp); } /** Imports a list of particles from an open file stream into * the container_poly class. Entries of five numbers (Particle * ID, x position, y position, z position, radius) are searched * for. In addition, the order in which particles are read is * saved into an ordering class. If the file cannot be * successfully read, then the routine causes a fatal error. * \param[in,out] vo the ordering class to use. * \param[in] filename the name of the file to open and read * from. */ inline void import(particle_order &vo,const char* filename) { FILE *fp=safe_fopen(filename,"r"); import(vo,fp); fclose(fp); } void compute_all_cells(); double sum_cell_volumes(); /** Dumps particle IDs, positions and radii to a file. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_particles(c_loop &vl,FILE *fp) { double *pp; if(vl.start()) do { pp=p[vl.ijk]+4*vl.q; fprintf(fp,"%d %g %g %g %g\n",id[vl.ijk][vl.q],*pp,pp[1],pp[2],pp[3]); } while(vl.inc()); } /** Dumps all of the particle IDs, positions and radii to a * file. * \param[in] fp a file handle to write to. */ inline void draw_particles(FILE *fp=stdout) { c_loop_all vl(*this); draw_particles(vl,fp); } /** Dumps all of the particle IDs, positions and radii to a * file. * \param[in] filename the name of the file to write to. */ inline void draw_particles(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_particles(fp); fclose(fp); } /** Dumps particle positions in POV-Ray format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_particles_pov(c_loop &vl,FILE *fp) { double *pp; if(vl.start()) do { pp=p[vl.ijk]+4*vl.q; fprintf(fp,"// id %d\nsphere{<%g,%g,%g>,%g}\n", id[vl.ijk][vl.q],*pp,pp[1],pp[2],pp[3]); } while(vl.inc()); } /** Dumps all the particle positions in POV-Ray format. * \param[in] fp a file handle to write to. */ inline void draw_particles_pov(FILE *fp=stdout) { c_loop_all vl(*this); draw_particles_pov(vl,fp); } /** Dumps all the particle positions in POV-Ray format. * \param[in] filename the name of the file to write to. */ inline void draw_particles_pov(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_particles_pov(fp); fclose(fp); } /** Computes Voronoi cells and saves the output in gnuplot * format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_cells_gnuplot(c_loop &vl,FILE *fp) { voronoicell c;double *pp; if(vl.start()) do if(compute_cell(c,vl)) { pp=p[vl.ijk]+ps*vl.q; c.draw_gnuplot(*pp,pp[1],pp[2],fp); } while(vl.inc()); } /** Compute all Voronoi cells and saves the output in gnuplot * format. * \param[in] fp a file handle to write to. */ inline void draw_cells_gnuplot(FILE *fp=stdout) { c_loop_all vl(*this); draw_cells_gnuplot(vl,fp); } /** Compute all Voronoi cells and saves the output in gnuplot * format. * \param[in] filename the name of the file to write to. */ inline void draw_cells_gnuplot(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_cells_gnuplot(fp); fclose(fp); } /** Computes Voronoi cells and saves the output in POV-Ray * format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_cells_pov(c_loop &vl,FILE *fp) { voronoicell c;double *pp; if(vl.start()) do if(compute_cell(c,vl)) { fprintf(fp,"// cell %d\n",id[vl.ijk][vl.q]); pp=p[vl.ijk]+ps*vl.q; c.draw_pov(*pp,pp[1],pp[2],fp); } while(vl.inc()); } /** Computes all Voronoi cells and saves the output in POV-Ray * format. * \param[in] fp a file handle to write to. */ inline void draw_cells_pov(FILE *fp=stdout) { c_loop_all vl(*this); draw_cells_pov(vl,fp); } /** Computes all Voronoi cells and saves the output in POV-Ray * format. * \param[in] filename the name of the file to write to. */ inline void draw_cells_pov(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_cells_pov(fp); fclose(fp); } /** Computes the Voronoi cells and saves customized information * about them. * \param[in] vl the loop class to use. * \param[in] format the custom output string to use. * \param[in] fp a file handle to write to. */ template void print_custom(c_loop &vl,const char *format,FILE *fp) { int ijk,q;double *pp; if(contains_neighbor(format)) { voronoicell_neighbor c; if(vl.start()) do if(compute_cell(c,vl)) { ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q; c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],pp[3],fp); } while(vl.inc()); } else { voronoicell c; if(vl.start()) do if(compute_cell(c,vl)) { ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q; c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],pp[3],fp); } while(vl.inc()); } } /** Computes the Voronoi cell for a particle currently being * referenced by a loop class. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] vl the loop class to use. * \return True if the cell was computed. If the cell cannot be * computed, if it is removed entirely by a wall or boundary * condition, then the routine returns false. */ template inline bool compute_cell(v_cell &c,c_loop &vl) { return vc.compute_cell(c,vl.ijk,vl.q,vl.i,vl.j,vl.k); } /** Computes the Voronoi cell for given particle. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] ijk the block that the particle is within. * \param[in] q the index of the particle within the block. * \return True if the cell was computed. If the cell cannot be * computed, if it is removed entirely by a wall or boundary * condition, then the routine returns false. */ template inline bool compute_cell(v_cell &c,int ijk,int q) { int k=ijk/nxy,ijkt=ijk-nxy*k,j=ijkt/nx,i=ijkt-j*nx; return vc.compute_cell(c,ijk,q,i,j,k); } /** Computes the Voronoi cell for a ghost particle at a given * location. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] (x,y,z) the location of the ghost particle. * \param[in] r the radius of the ghost particle. * \return True if the cell was computed. If the cell cannot be * computed, if it is removed entirely by a wall or boundary * condition, then the routine returns false. */ template inline bool compute_ghost_cell(v_cell &c,double x,double y,double z,double r) { int ijk; if(put_locate_block(ijk,x,y,z)) { double *pp=p[ijk]+4*co[ijk]++,tm=max_radius; *(pp++)=x;*(pp++)=y;*(pp++)=z;*pp=r; if(r>max_radius) max_radius=r; bool q=compute_cell(c,ijk,co[ijk]-1); co[ijk]--;max_radius=tm; return q; } return false; } void print_custom(const char *format,FILE *fp=stdout); void print_custom(const char *format,const char *filename); bool find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid); private: voro_compute vc; friend class voro_compute; }; } #endif voro++-0.4.6/src/container_prd.cc000600 000765 000024 00000067722 12230022105 016471 0ustar00chrstaff000000 000000 // Voro++, a 3D cell-based Voronoi library // // Author : Chris H. Rycroft (LBL / UC Berkeley) // Email : chr@alum.mit.edu // Date : August 30th 2011 /** \file container_prd.cc * \brief Function implementations for the container_periodic_base and * related classes. */ #include "container_prd.hh" namespace voro { /** The class constructor sets up the geometry of container, initializing the * minimum and maximum coordinates in each direction, and setting whether each * direction is periodic or not. It divides the container into a rectangular * grid of blocks, and allocates memory for each of these for storing particle * positions and IDs. * \param[in] (bx_) The x coordinate of the first unit vector. * \param[in] (bxy_,by_) The x and y coordinates of the second unit vector. * \param[in] (bxz_,byz_,bz_) The x, y, and z coordinates of the third unit * vector. * \param[in] (nx_,ny_,nz_) the number of grid blocks in each of the three * coordinate directions. * \param[in] init_mem_ the initial memory allocation for each block. * \param[in] ps_ the number of floating point entries to store for each * particle. */ container_periodic_base::container_periodic_base(double bx_,double bxy_,double by_, double bxz_,double byz_,double bz_,int nx_,int ny_,int nz_,int init_mem_,int ps_) : unitcell(bx_,bxy_,by_,bxz_,byz_,bz_), voro_base(nx_,ny_,nz_,bx_/nx_,by_/ny_,bz_/nz_), ey(int(max_uv_y*ysp+1)), ez(int(max_uv_z*zsp+1)), wy(ny+ey), wz(nz+ez), oy(ny+2*ey), oz(nz+2*ez), oxyz(nx*oy*oz), id(new int*[oxyz]), p(new double*[oxyz]), co(new int[oxyz]), mem(new int[oxyz]), img(new char[oxyz]), init_mem(init_mem_), ps(ps_) { int i,j,k,l; // Clear the global arrays int *pp=co;while(pp=0;l--) if(mem[l]>0) { delete [] p[l]; delete [] id[l]; } delete [] img; delete [] mem; delete [] co; delete [] id; delete [] p; } /** The class constructor sets up the geometry of container. * \param[in] (bx_) The x coordinate of the first unit vector. * \param[in] (bxy_,by_) The x and y coordinates of the second unit vector. * \param[in] (bxz_,byz_,bz_) The x, y, and z coordinates of the third unit * vector. * \param[in] (nx_,ny_,nz_) the number of grid blocks in each of the three * coordinate directions. * \param[in] init_mem_ the initial memory allocation for each block. */ container_periodic::container_periodic(double bx_,double bxy_,double by_,double bxz_,double byz_,double bz_, int nx_,int ny_,int nz_,int init_mem_) : container_periodic_base(bx_,bxy_,by_,bxz_,byz_,bz_,nx_,ny_,nz_,init_mem_,3), vc(*this,2*nx_+1,2*ey+1,2*ez+1) {} /** The class constructor sets up the geometry of container. * \param[in] (bx_) The x coordinate of the first unit vector. * \param[in] (bxy_,by_) The x and y coordinates of the second unit vector. * \param[in] (bxz_,byz_,bz_) The x, y, and z coordinates of the third unit * vector. * \param[in] (nx_,ny_,nz_) the number of grid blocks in each of the three * coordinate directions. * \param[in] init_mem_ the initial memory allocation for each block. */ container_periodic_poly::container_periodic_poly(double bx_,double bxy_,double by_,double bxz_,double byz_,double bz_, int nx_,int ny_,int nz_,int init_mem_) : container_periodic_base(bx_,bxy_,by_,bxz_,byz_,bz_,nx_,ny_,nz_,init_mem_,4), vc(*this,2*nx_+1,2*ey+1,2*ez+1) {ppr=p;} /** Put a particle into the correct region of the container. * \param[in] n the numerical ID of the inserted particle. * \param[in] (x,y,z) the position vector of the inserted particle. */ void container_periodic::put(int n,double x,double y,double z) { int ijk; put_locate_block(ijk,x,y,z); id[ijk][co[ijk]]=n; double *pp=p[ijk]+3*co[ijk]++; *(pp++)=x;*(pp++)=y;*pp=z; } /** Put a particle into the correct region of the container. * \param[in] n the numerical ID of the inserted particle. * \param[in] (x,y,z) the position vector of the inserted particle. * \param[in] r the radius of the particle. */ void container_periodic_poly::put(int n,double x,double y,double z,double r) { int ijk; put_locate_block(ijk,x,y,z); id[ijk][co[ijk]]=n; double *pp=p[ijk]+4*co[ijk]++; *(pp++)=x;*(pp++)=y;*(pp++)=z;*pp=r; if(max_radius=nz) { int ak=step_div(k,nz); z-=ak*bz;y-=ak*byz;x-=ak*bxz;k-=ak*nz; } // Remap particle in the y direction if necessary int j=step_int(y*ysp); if(j<0||j>=ny) { int aj=step_div(j,ny); y-=aj*by;x-=aj*bxy;j-=aj*ny; } // Remap particle in the x direction if necessary ijk=step_int(x*xsp); if(ijk<0||ijk>=nx) { int ai=step_div(ijk,nx); x-=ai*bx;ijk-=ai*nx; } // Compute the block index and check memory allocation j+=ey;k+=ez; ijk+=nx*(j+oy*k); if(co[ijk]==mem[ijk]) add_particle_memory(ijk); } /** Takes a particle position vector and computes the region index into which * it should be stored. If the container is periodic, then the routine also * maps the particle position to ensure it is in the primary domain. If the * container is not periodic, the routine bails out. * \param[out] ijk the region index. * \param[in,out] (x,y,z) the particle position, remapped into the primary * domain if necessary. * \param[out] (ai,aj,ak) the periodic image displacement that the particle is * in, with (0,0,0) corresponding to the primary domain. * \return True if the particle can be successfully placed into the container, * false otherwise. */ void container_periodic_base::put_locate_block(int &ijk,double &x,double &y,double &z,int &ai,int &aj,int &ak) { // Remap particle in the z direction if necessary int k=step_int(z*zsp); if(k<0||k>=nz) { ak=step_div(k,nz); z-=ak*bz;y-=ak*byz;x-=ak*bxz;k-=ak*nz; } else ak=0; // Remap particle in the y direction if necessary int j=step_int(y*ysp); if(j<0||j>=ny) { aj=step_div(j,ny); y-=aj*by;x-=aj*bxy;j-=aj*ny; } else aj=0; // Remap particle in the x direction if necessary ijk=step_int(x*xsp); if(ijk<0||ijk>=nx) { ai=step_div(ijk,nx); x-=ai*bx;ijk-=ai*nx; } else ai=0; // Compute the block index and check memory allocation j+=ey;k+=ez; ijk+=nx*(j+oy*k); if(co[ijk]==mem[ijk]) add_particle_memory(ijk); } /** Takes a position vector and remaps it into the primary domain. * \param[out] (ai,aj,ak) the periodic image displacement that the vector is in, * with (0,0,0) corresponding to the primary domain. * \param[out] (ci,cj,ck) the index of the block that the position vector is * within, once it has been remapped. * \param[in,out] (x,y,z) the position vector to consider, which is remapped * into the primary domain during the routine. * \param[out] ijk the block index that the vector is within. */ inline void container_periodic_base::remap(int &ai,int &aj,int &ak,int &ci,int &cj,int &ck,double &x,double &y,double &z,int &ijk) { // Remap particle in the z direction if necessary ck=step_int(z*zsp); if(ck<0||ck>=nz) { ak=step_div(ck,nz); z-=ak*bz;y-=ak*byz;x-=ak*bxz;ck-=ak*nz; } else ak=0; // Remap particle in the y direction if necessary cj=step_int(y*ysp); if(cj<0||cj>=ny) { aj=step_div(cj,ny); y-=aj*by;x-=aj*bxy;cj-=aj*ny; } else aj=0; // Remap particle in the x direction if necessary ci=step_int(x*xsp); if(ci<0||ci>=nx) { ai=step_div(ci,nx); x-=ai*bx;ci-=ai*nx; } else ai=0; cj+=ey;ck+=ez; ijk=ci+nx*(cj+oy*ck); } /** Takes a vector and finds the particle whose Voronoi cell contains that * vector. This is equivalent to finding the particle which is nearest to the * vector. * \param[in] (x,y,z) the vector to test. * \param[out] (rx,ry,rz) the position of the particle whose Voronoi cell * contains the vector. This may point to a particle in * a periodic image of the primary domain. * \param[out] pid the ID of the particle. * \return True if a particle was found. If the container has no particles, * then the search will not find a Voronoi cell and false is returned. */ bool container_periodic::find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid) { int ai,aj,ak,ci,cj,ck,ijk; particle_record w; double mrs; // Remap the vector into the primary domain and then search for the // Voronoi cell that it is within remap(ai,aj,ak,ci,cj,ck,x,y,z,ijk); vc.find_voronoi_cell(x,y,z,ci,cj,ck,ijk,w,mrs); if(w.ijk!=-1) { // Assemble the position vector of the particle to be returned, // applying a periodic remapping if necessary ci+=w.di;if(ci<0||ci>=nx) ai+=step_div(ci,nx); rx=p[w.ijk][3*w.l]+ak*bxz+aj*bxy+ai*bx; ry=p[w.ijk][3*w.l+1]+ak*byz+aj*by; rz=p[w.ijk][3*w.l+2]+ak*bz; pid=id[w.ijk][w.l]; return true; } return false; } /** Takes a vector and finds the particle whose Voronoi cell contains that * vector. Additional wall classes are not considered by this routine. * \param[in] (x,y,z) the vector to test. * \param[out] (rx,ry,rz) the position of the particle whose Voronoi cell * contains the vector. If the container is periodic, * this may point to a particle in a periodic image of * the primary domain. * \param[out] pid the ID of the particle. * \return True if a particle was found. If the container has no particles, * then the search will not find a Voronoi cell and false is returned. */ bool container_periodic_poly::find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid) { int ai,aj,ak,ci,cj,ck,ijk; particle_record w; double mrs; // Remap the vector into the primary domain and then search for the // Voronoi cell that it is within remap(ai,aj,ak,ci,cj,ck,x,y,z,ijk); vc.find_voronoi_cell(x,y,z,ci,cj,ck,ijk,w,mrs); if(w.ijk!=-1) { // Assemble the position vector of the particle to be returned, // applying a periodic remapping if necessary ci+=w.di;if(ci<0||ci>=nx) ai+=step_div(ci,nx); rx=p[w.ijk][4*w.l]+ak*bxz+aj*bxy+ai*bx; ry=p[w.ijk][4*w.l+1]+ak*byz+aj*by; rz=p[w.ijk][4*w.l+2]+ak*bz; pid=id[w.ijk][w.l]; return true; } return false; } /** Increase memory for a particular region. * \param[in] i the index of the region to reallocate. */ void container_periodic_base::add_particle_memory(int i) { // Handle the case when no memory has been allocated for this block if(mem[i]==0) { mem[i]=init_mem; id[i]=new int[init_mem]; p[i]=new double[ps*init_mem]; return; } // Otherwise, double the memory allocation for this block. Carry out a // check on the memory allocation size, and print a status message if // requested. int l,nmem(mem[i]<<1); if(nmem>max_particle_memory) voro_fatal_error("Absolute maximum memory allocation exceeded",VOROPP_MEMORY_ERROR); #if VOROPP_VERBOSE >=3 fprintf(stderr,"Particle memory in region %d scaled up to %d\n",i,nmem); #endif // Allocate new memory and copy in the contents of the old arrays int *idp=new int[nmem]; for(l=0;l0) { // Compute the block's bounds, adding in a small tolerance mix=i*boxx-tolerance;max=mix+boxx+tolerance; miy=(j-ey)*boxy-tolerance;may=miy+boxy+tolerance; miz=(k-ez)*boxz-tolerance;maz=miz+boxz+tolerance; // Print entries for any particles that lie outside the block's // bounds for(pp=p[l],c=0;cmax||pp[1]may||pp[2]maz) printf("%d %d %d %d %f %f %f %f %f %f %f %f %f\n", id[l][c],i,j,k,*pp,pp[1],pp[2],mix,max,miy,may,miz,maz); } } /** Creates particles within an image block that is aligned with the primary * domain in the z axis. In this case, the image block may be comprised of * particles from two primary blocks. The routine considers these two primary * blocks, and adds the needed particles to the image. The remaining particles * from the primary blocks are also filled into the neighboring images. * \param[in] (di,dj,dk) the index of the block to consider. The z index must * satisfy ez<=dk0) { odijk=dijk-1;adis=dis; } else { odijk=dijk+nx-1;adis=dis+bx; } img[odijk]|=2; for(l=0;lswitchx) put_image(dijk,fijk,l,dis,by*ima,0); else put_image(odijk,fijk,l,adis,by*ima,0); } } // Right image computation if((img[dijk]&2)==0) { if(fi==nx-1) { fijk+=1-nx;switchx+=(1-nx)*boxx;dis+=bx; } else { fijk++;switchx+=boxx; } if(di==nx-1) { odijk=dijk-nx+1;adis=dis-bx; } else { odijk=dijk+1;adis=dis; } img[odijk]|=1; for(l=0;l=wz. */ void container_periodic_base::create_vertical_image(int di,int dj,int dk) { int l,dijk=di+nx*(dj+oy*dk),dijkl,dijkr,ima=step_div(dk-ez,nz); int qj=dj+step_int(-ima*byz*ysp),qjdiv=step_div(qj-ey,ny); int qi=di+step_int((-ima*bxz-qjdiv*bxy)*xsp),qidiv=step_div(qi,nx); int fi=qi-qidiv*nx,fj=qj-qjdiv*ny,fijk=fi+nx*(fj+oy*(dk-ima*nz)),fijk2; double disy=ima*byz+qjdiv*by,switchy=(dj-ey)*boxy-ima*byz-qjdiv*by; double disx=ima*bxz+qjdiv*bxy+qidiv*bx,switchx=di*boxx-ima*bxz-qjdiv*bxy-qidiv*bx; double switchx2,disxl,disxr,disx2,disxr2; if(di==0) {dijkl=dijk+nx-1;disxl=disx+bx;} else {dijkl=dijk-1;disxl=disx;} if(di==nx-1) {dijkr=dijk-nx+1;disxr=disx-bx;} else {dijkr=dijk+1;disxr=disx;} // Down-left image computation bool y_exist=dj!=0; if((img[dijk]&1)==0) { img[dijkl]|=2; if(y_exist) { img[dijkl-nx]|=8; img[dijk-nx]|=4; } for(l=0;lswitchy) { if(p[fijk][ps*l]>switchx) put_image(dijk,fijk,l,disx,disy,bz*ima); else put_image(dijkl,fijk,l,disxl,disy,bz*ima); } else { if(!y_exist) continue; if(p[fijk][ps*l]>switchx) put_image(dijk-nx,fijk,l,disx,disy,bz*ima); else put_image(dijkl-nx,fijk,l,disxl,disy,bz*ima); } } } // Down-right image computation if((img[dijk]&2)==0) { if(fi==nx-1) { fijk2=fijk+1-nx;switchx2=switchx+(1-nx)*boxx;disx2=disx+bx;disxr2=disxr+bx; } else { fijk2=fijk+1;switchx2=switchx+boxx;disx2=disx;disxr2=disxr; } img[dijkr]|=1; if(y_exist) { img[dijkr-nx]|=4; img[dijk-nx]|=8; } for(l=0;lswitchy) { if(p[fijk2][ps*l]>switchx2) put_image(dijkr,fijk2,l,disxr2,disy,bz*ima); else put_image(dijk,fijk2,l,disx2,disy,bz*ima); } else { if(!y_exist) continue; if(p[fijk2][ps*l]>switchx2) put_image(dijkr-nx,fijk2,l,disxr2,disy,bz*ima); else put_image(dijk-nx,fijk2,l,disx2,disy,bz*ima); } } } // Recomputation of some intermediate quantities for boundary cases if(fj==wy-1) { fijk+=nx*(1-ny)-fi; switchy+=(1-ny)*boxy; disy+=by; qi=di+step_int(-(ima*bxz+(qjdiv+1)*bxy)*xsp); int dqidiv=step_div(qi,nx)-qidiv;qidiv+=dqidiv; fi=qi-qidiv*nx; fijk+=fi; disx+=bxy+bx*dqidiv; disxl+=bxy+bx*dqidiv; disxr+=bxy+bx*dqidiv; switchx-=bxy+bx*dqidiv; } else { fijk+=nx;switchy+=boxy; } // Up-left image computation y_exist=dj!=oy-1; if((img[dijk]&4)==0) { img[dijkl]|=8; if(y_exist) { img[dijkl+nx]|=2; img[dijk+nx]|=1; } for(l=0;lswitchy) { if(!y_exist) continue; if(p[fijk][ps*l]>switchx) put_image(dijk+nx,fijk,l,disx,disy,bz*ima); else put_image(dijkl+nx,fijk,l,disxl,disy,bz*ima); } else { if(p[fijk][ps*l]>switchx) put_image(dijk,fijk,l,disx,disy,bz*ima); else put_image(dijkl,fijk,l,disxl,disy,bz*ima); } } } // Up-right image computation if((img[dijk]&8)==0) { if(fi==nx-1) { fijk2=fijk+1-nx;switchx2=switchx+(1-nx)*boxx;disx2=disx+bx;disxr2=disxr+bx; } else { fijk2=fijk+1;switchx2=switchx+boxx;disx2=disx;disxr2=disxr; } img[dijkr]|=4; if(y_exist) { img[dijkr+nx]|=1; img[dijk+nx]|=2; } for(l=0;lswitchy) { if(!y_exist) continue; if(p[fijk2][ps*l]>switchx2) put_image(dijkr+nx,fijk2,l,disxr2,disy,bz*ima); else put_image(dijk+nx,fijk2,l,disx2,disy,bz*ima); } else { if(p[fijk2][ps*l]>switchx2) put_image(dijkr,fijk2,l,disxr2,disy,bz*ima); else put_image(dijk,fijk2,l,disx2,disy,bz*ima); } } } // All contributions to the block now added, so set all four bits of // the image information img[dijk]=15; } /** Copies a particle position from the primary domain into an image block. * \param[in] reg the block index within the primary domain that the particle * is within. * \param[in] fijk the index of the image block. * \param[in] l the index of the particle entry within the primary block. * \param[in] (dx,dy,dz) the displacement vector to add to the particle. */ void container_periodic_base::put_image(int reg,int fijk,int l,double dx,double dy,double dz) { if(co[reg]==mem[reg]) add_particle_memory(reg); double *p1=p[reg]+ps*co[reg],*p2=p[fijk]+ps*l; *(p1++)=*(p2++)+dx; *(p1++)=*(p2++)+dy; *p1=*p2+dz; if(ps==4) *(++p1)=*(++p2); id[reg][co[reg]++]=id[fijk][l]; } } voro++-0.4.6/src/container_prd.hh000600 000765 000024 00000063301 12230022105 016470 0ustar00chrstaff000000 000000 // Voro++, a 3D cell-based Voronoi library // // Author : Chris H. Rycroft (LBL / UC Berkeley) // Email : chr@alum.mit.edu // Date : August 30th 2011 /** \file container_prd.hh * \brief Header file for the container_periodic_base and related classes. */ #ifndef VOROPP_CONTAINER_PRD_HH #define VOROPP_CONTAINER_PRD_HH #include #include #include "config.hh" #include "common.hh" #include "v_base.hh" #include "cell.hh" #include "c_loops.hh" #include "v_compute.hh" #include "unitcell.hh" #include "rad_option.hh" namespace voro { /** \brief Class for representing a particle system in a 3D periodic * non-orthogonal periodic domain. * * This class represents a particle system in a three-dimensional * non-orthogonal periodic domain. The domain is defined by three periodicity * vectors (bx,0,0), (bxy,by,0), and (bxz,byz,bz) that represent a * parallelepiped. Internally, the class stores particles in the box 0 inline bool initialize_voronoicell(v_cell &c,int ijk,int q,int ci,int cj,int ck,int &i,int &j,int &k,double &x,double &y,double &z,int &disp) { c=unit_voro; double *pp=p[ijk]+ps*q; x=*(pp++);y=*(pp++);z=*pp; i=nx;j=ey;k=ez; return true; } /** Initializes parameters for a find_voronoi_cell call within * the voro_compute template. * \param[in] (ci,cj,ck) the coordinates of the test block in * the container coordinate system. * \param[in] ijk the index of the test block * \param[out] (i,j,k) the coordinates of the test block * relative to the voro_compute * coordinate system. * \param[out] disp a block displacement used internally by the * find_voronoi_cell routine (but not needed * in this instance.) */ inline void initialize_search(int ci,int cj,int ck,int ijk,int &i,int &j,int &k,int &disp) { i=nx;j=ey;k=ez; } /** Returns the position of a particle currently being computed * relative to the computational block that it is within. It is * used to select the optimal worklist entry to use. * \param[in] (x,y,z) the position of the particle. * \param[in] (ci,cj,ck) the block that the particle is within. * \param[out] (fx,fy,fz) the position relative to the block. */ inline void frac_pos(double x,double y,double z,double ci,double cj,double ck,double &fx,double &fy,double &fz) { fx=x-boxx*ci; fy=y-boxy*(cj-ey); fz=z-boxz*(ck-ez); } /** Calculates the index of block in the container structure * corresponding to given coordinates. * \param[in] (ci,cj,ck) the coordinates of the original block * in the current computation, relative * to the container coordinate system. * \param[in] (ei,ej,ek) the displacement of the current block * from the original block. * \param[in,out] (qx,qy,qz) the periodic displacement that * must be added to the particles * within the computed block. * \param[in] disp a block displacement used internally by the * find_voronoi_cell and compute_cell routines * (but not needed in this instance.) * \return The block index. */ inline int region_index(int ci,int cj,int ck,int ei,int ej,int ek,double &qx,double &qy,double &qz,int &disp) { int qi=ci+(ei-nx),qj=cj+(ej-ey),qk=ck+(ek-ez); int iv(step_div(qi,nx));if(iv!=0) {qx=iv*bx;qi-=nx*iv;} else qx=0; create_periodic_image(qi,qj,qk); return qi+nx*(qj+oy*qk); } void create_all_images(); void check_compartmentalized(); protected: void add_particle_memory(int i); void put_locate_block(int &ijk,double &x,double &y,double &z); void put_locate_block(int &ijk,double &x,double &y,double &z,int &ai,int &aj,int &ak); /** Creates particles within an image block by copying them * from the primary domain and shifting them. If the given * block is aligned with the primary domain in the z-direction, * the routine calls the simpler create_side_image routine * where the image block may comprise of particles from up to * two primary blocks. Otherwise is calls the more complex * create_vertical_image where the image block may comprise of * particles from up to four primary blocks. * \param[in] (di,dj,dk) the coordinates of the image block to * create. */ inline void create_periodic_image(int di,int dj,int dk) { if(di<0||di>=nx||dj<0||dj>=oy||dk<0||dk>=oz) voro_fatal_error("Constructing periodic image for nonexistent point",VOROPP_INTERNAL_ERROR); if(dk>=ez&&dk=wy) create_side_image(di,dj,dk); } else create_vertical_image(di,dj,dk); } void create_side_image(int di,int dj,int dk); void create_vertical_image(int di,int dj,int dk); void put_image(int reg,int fijk,int l,double dx,double dy,double dz); inline void remap(int &ai,int &aj,int &ak,int &ci,int &cj,int &ck,double &x,double &y,double &z,int &ijk); }; /** \brief Extension of the container_periodic_base class for computing regular * Voronoi tessellations. * * This class is an extension of the container_periodic_base that has routines * specifically for computing the regular Voronoi tessellation with no * dependence on particle radii. */ class container_periodic : public container_periodic_base, public radius_mono { public: container_periodic(double bx_,double bxy_,double by_,double bxz_,double byz_,double bz_, int nx_,int ny_,int nz_,int init_mem_); void clear(); void put(int n,double x,double y,double z); void put(int n,double x,double y,double z,int &ai,int &aj,int &ak); void put(particle_order &vo,int n,double x,double y,double z); void import(FILE *fp=stdin); void import(particle_order &vo,FILE *fp=stdin); /** Imports a list of particles from an open file stream into * the container. Entries of four numbers (Particle ID, x * position, y position, z position) are searched for. If the * file cannot be successfully read, then the routine causes a * fatal error. * \param[in] filename the name of the file to open and read * from. */ inline void import(const char* filename) { FILE *fp=safe_fopen(filename,"r"); import(fp); fclose(fp); } /** Imports a list of particles from an open file stream into * the container. Entries of four numbers (Particle ID, x * position, y position, z position) are searched for. In * addition, the order in which particles are read is saved * into an ordering class. If the file cannot be successfully * read, then the routine causes a fatal error. * \param[in,out] vo the ordering class to use. * \param[in] filename the name of the file to open and read * from. */ inline void import(particle_order &vo,const char* filename) { FILE *fp=safe_fopen(filename,"r"); import(vo,fp); fclose(fp); } void compute_all_cells(); double sum_cell_volumes(); /** Dumps particle IDs and positions to a file. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_particles(c_loop &vl,FILE *fp) { double *pp; if(vl.start()) do { pp=p[vl.ijk]+3*vl.q; fprintf(fp,"%d %g %g %g\n",id[vl.ijk][vl.q],*pp,pp[1],pp[2]); } while(vl.inc()); } /** Dumps all of the particle IDs and positions to a file. * \param[in] fp a file handle to write to. */ inline void draw_particles(FILE *fp=stdout) { c_loop_all_periodic vl(*this); draw_particles(vl,fp); } /** Dumps all of the particle IDs and positions to a file. * \param[in] filename the name of the file to write to. */ inline void draw_particles(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_particles(fp); fclose(fp); } /** Dumps particle positions in POV-Ray format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_particles_pov(c_loop &vl,FILE *fp) { double *pp; if(vl.start()) do { pp=p[vl.ijk]+3*vl.q; fprintf(fp,"// id %d\nsphere{<%g,%g,%g>,s}\n", id[vl.ijk][vl.q],*pp,pp[1],pp[2]); } while(vl.inc()); } /** Dumps all particle positions in POV-Ray format. * \param[in] fp a file handle to write to. */ inline void draw_particles_pov(FILE *fp=stdout) { c_loop_all_periodic vl(*this); draw_particles_pov(vl,fp); } /** Dumps all particle positions in POV-Ray format. * \param[in] filename the name of the file to write to. */ inline void draw_particles_pov(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_particles_pov(fp); fclose(fp); } /** Computes Voronoi cells and saves the output in gnuplot * format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_cells_gnuplot(c_loop &vl,FILE *fp) { voronoicell c;double *pp; if(vl.start()) do if(compute_cell(c,vl)) { pp=p[vl.ijk]+ps*vl.q; c.draw_gnuplot(*pp,pp[1],pp[2],fp); } while(vl.inc()); } /** Computes all Voronoi cells and saves the output in gnuplot * format. * \param[in] fp a file handle to write to. */ inline void draw_cells_gnuplot(FILE *fp=stdout) { c_loop_all_periodic vl(*this); draw_cells_gnuplot(vl,fp); } /** Compute all Voronoi cells and saves the output in gnuplot * format. * \param[in] filename the name of the file to write to. */ inline void draw_cells_gnuplot(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_cells_gnuplot(fp); fclose(fp); } /** Computes Voronoi cells and saves the output in POV-Ray * format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_cells_pov(c_loop &vl,FILE *fp) { voronoicell c;double *pp; if(vl.start()) do if(compute_cell(c,vl)) { fprintf(fp,"// cell %d\n",id[vl.ijk][vl.q]); pp=p[vl.ijk]+ps*vl.q; c.draw_pov(*pp,pp[1],pp[2],fp); } while(vl.inc()); } /** Computes all Voronoi cells and saves the output in POV-Ray * format. * \param[in] fp a file handle to write to. */ inline void draw_cells_pov(FILE *fp=stdout) { c_loop_all_periodic vl(*this); draw_cells_pov(vl,fp); } /** Computes all Voronoi cells and saves the output in POV-Ray * format. * \param[in] filename the name of the file to write to. */ inline void draw_cells_pov(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_cells_pov(fp); fclose(fp); } /** Computes the Voronoi cells and saves customized information * about them. * \param[in] vl the loop class to use. * \param[in] format the custom output string to use. * \param[in] fp a file handle to write to. */ template void print_custom(c_loop &vl,const char *format,FILE *fp) { int ijk,q;double *pp; if(contains_neighbor(format)) { voronoicell_neighbor c; if(vl.start()) do if(compute_cell(c,vl)) { ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q; c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],default_radius,fp); } while(vl.inc()); } else { voronoicell c; if(vl.start()) do if(compute_cell(c,vl)) { ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q; c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],default_radius,fp); } while(vl.inc()); } } void print_custom(const char *format,FILE *fp=stdout); void print_custom(const char *format,const char *filename); bool find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid); /** Computes the Voronoi cell for a particle currently being * referenced by a loop class. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] vl the loop class to use. * \return True if the cell was computed. If the cell cannot be * computed because it was removed entirely for some reason, * then the routine returns false. */ template inline bool compute_cell(v_cell &c,c_loop &vl) { return vc.compute_cell(c,vl.ijk,vl.q,vl.i,vl.j,vl.k); } /** Computes the Voronoi cell for given particle. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] ijk the block that the particle is within. * \param[in] q the index of the particle within the block. * \return True if the cell was computed. If the cell cannot be * computed because it was removed entirely for some reason, * then the routine returns false. */ template inline bool compute_cell(v_cell &c,int ijk,int q) { int k(ijk/(nx*oy)),ijkt(ijk-(nx*oy)*k),j(ijkt/nx),i(ijkt-j*nx); return vc.compute_cell(c,ijk,q,i,j,k); } /** Computes the Voronoi cell for a ghost particle at a given * location. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] (x,y,z) the location of the ghost particle. * \return True if the cell was computed. If the cell cannot be * computed, if it is removed entirely by a wall or boundary * condition, then the routine returns false. */ template inline bool compute_ghost_cell(v_cell &c,double x,double y,double z) { int ijk; put_locate_block(ijk,x,y,z); double *pp=p[ijk]+3*co[ijk]++; *(pp++)=x;*(pp++)=y;*(pp++)=z; bool q=compute_cell(c,ijk,co[ijk]-1); co[ijk]--; return q; } private: voro_compute vc; friend class voro_compute; }; /** \brief Extension of the container_periodic_base class for computing radical * Voronoi tessellations. * * This class is an extension of container_periodic_base that has routines * specifically for computing the radical Voronoi tessellation that depends * on the particle radii. */ class container_periodic_poly : public container_periodic_base, public radius_poly { public: container_periodic_poly(double bx_,double bxy_,double by_,double bxz_,double byz_,double bz_, int nx_,int ny_,int nz_,int init_mem_); void clear(); void put(int n,double x,double y,double z,double r); void put(int n,double x,double y,double z,double r,int &ai,int &aj,int &ak); void put(particle_order &vo,int n,double x,double y,double z,double r); void import(FILE *fp=stdin); void import(particle_order &vo,FILE *fp=stdin); /** Imports a list of particles from an open file stream into * the container_poly class. Entries of five numbers (Particle * ID, x position, y position, z position, radius) are searched * for. If the file cannot be successfully read, then the * routine causes a fatal error. * \param[in] filename the name of the file to open and read * from. */ inline void import(const char* filename) { FILE *fp=safe_fopen(filename,"r"); import(fp); fclose(fp); } /** Imports a list of particles from an open file stream into * the container_poly class. Entries of five numbers (Particle * ID, x position, y position, z position, radius) are searched * for. In addition, the order in which particles are read is * saved into an ordering class. If the file cannot be * successfully read, then the routine causes a fatal error. * \param[in,out] vo the ordering class to use. * \param[in] filename the name of the file to open and read * from. */ inline void import(particle_order &vo,const char* filename) { FILE *fp=safe_fopen(filename,"r"); import(vo,fp); fclose(fp); } void compute_all_cells(); double sum_cell_volumes(); /** Dumps particle IDs, positions and radii to a file. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_particles(c_loop &vl,FILE *fp) { double *pp; if(vl.start()) do { pp=p[vl.ijk]+4*vl.q; fprintf(fp,"%d %g %g %g %g\n",id[vl.ijk][vl.q],*pp,pp[1],pp[2],pp[3]); } while(vl.inc()); } /** Dumps all of the particle IDs, positions and radii to a * file. * \param[in] fp a file handle to write to. */ inline void draw_particles(FILE *fp=stdout) { c_loop_all_periodic vl(*this); draw_particles(vl,fp); } /** Dumps all of the particle IDs, positions and radii to a * file. * \param[in] filename the name of the file to write to. */ inline void draw_particles(const char *filename) { FILE *fp=safe_fopen(filename,"w"); draw_particles(fp); fclose(fp); } /** Dumps particle positions in POV-Ray format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_particles_pov(c_loop &vl,FILE *fp) { double *pp; if(vl.start()) do { pp=p[vl.ijk]+4*vl.q; fprintf(fp,"// id %d\nsphere{<%g,%g,%g>,%g}\n", id[vl.ijk][vl.q],*pp,pp[1],pp[2],pp[3]); } while(vl.inc()); } /** Dumps all the particle positions in POV-Ray format. * \param[in] fp a file handle to write to. */ inline void draw_particles_pov(FILE *fp=stdout) { c_loop_all_periodic vl(*this); draw_particles_pov(vl,fp); } /** Dumps all the particle positions in POV-Ray format. * \param[in] filename the name of the file to write to. */ inline void draw_particles_pov(const char *filename) { FILE *fp(safe_fopen(filename,"w")); draw_particles_pov(fp); fclose(fp); } /** Computes Voronoi cells and saves the output in gnuplot * format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_cells_gnuplot(c_loop &vl,FILE *fp) { voronoicell c;double *pp; if(vl.start()) do if(compute_cell(c,vl)) { pp=p[vl.ijk]+ps*vl.q; c.draw_gnuplot(*pp,pp[1],pp[2],fp); } while(vl.inc()); } /** Compute all Voronoi cells and saves the output in gnuplot * format. * \param[in] fp a file handle to write to. */ inline void draw_cells_gnuplot(FILE *fp=stdout) { c_loop_all_periodic vl(*this); draw_cells_gnuplot(vl,fp); } /** Compute all Voronoi cells and saves the output in gnuplot * format. * \param[in] filename the name of the file to write to. */ inline void draw_cells_gnuplot(const char *filename) { FILE *fp(safe_fopen(filename,"w")); draw_cells_gnuplot(fp); fclose(fp); } /** Computes Voronoi cells and saves the output in POV-Ray * format. * \param[in] vl the loop class to use. * \param[in] fp a file handle to write to. */ template void draw_cells_pov(c_loop &vl,FILE *fp) { voronoicell c;double *pp; if(vl.start()) do if(compute_cell(c,vl)) { fprintf(fp,"// cell %d\n",id[vl.ijk][vl.q]); pp=p[vl.ijk]+ps*vl.q; c.draw_pov(*pp,pp[1],pp[2],fp); } while(vl.inc()); } /** Computes all Voronoi cells and saves the output in POV-Ray * format. * \param[in] fp a file handle to write to. */ inline void draw_cells_pov(FILE *fp=stdout) { c_loop_all_periodic vl(*this); draw_cells_pov(vl,fp); } /** Computes all Voronoi cells and saves the output in POV-Ray * format. * \param[in] filename the name of the file to write to. */ inline void draw_cells_pov(const char *filename) { FILE *fp(safe_fopen(filename,"w")); draw_cells_pov(fp); fclose(fp); } /** Computes the Voronoi cells and saves customized information * about them. * \param[in] vl the loop class to use. * \param[in] format the custom output string to use. * \param[in] fp a file handle to write to. */ template void print_custom(c_loop &vl,const char *format,FILE *fp) { int ijk,q;double *pp; if(contains_neighbor(format)) { voronoicell_neighbor c; if(vl.start()) do if(compute_cell(c,vl)) { ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q; c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],pp[3],fp); } while(vl.inc()); } else { voronoicell c; if(vl.start()) do if(compute_cell(c,vl)) { ijk=vl.ijk;q=vl.q;pp=p[ijk]+ps*q; c.output_custom(format,id[ijk][q],*pp,pp[1],pp[2],pp[3],fp); } while(vl.inc()); } } /** Computes the Voronoi cell for a particle currently being * referenced by a loop class. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] vl the loop class to use. * \return True if the cell was computed. If the cell cannot be * computed because it was removed entirely for some reason, * then the routine returns false. */ template inline bool compute_cell(v_cell &c,c_loop &vl) { return vc.compute_cell(c,vl.ijk,vl.q,vl.i,vl.j,vl.k); } /** Computes the Voronoi cell for given particle. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] ijk the block that the particle is within. * \param[in] q the index of the particle within the block. * \return True if the cell was computed. If the cell cannot be * computed because it was removed entirely for some reason, * then the routine returns false. */ template inline bool compute_cell(v_cell &c,int ijk,int q) { int k(ijk/(nx*oy)),ijkt(ijk-(nx*oy)*k),j(ijkt/nx),i(ijkt-j*nx); return vc.compute_cell(c,ijk,q,i,j,k); } /** Computes the Voronoi cell for a ghost particle at a given * location. * \param[out] c a Voronoi cell class in which to store the * computed cell. * \param[in] (x,y,z) the location of the ghost particle. * \param[in] r the radius of the ghost particle. * \return True if the cell was computed. If the cell cannot be * computed, if it is removed entirely by a wall or boundary * condition, then the routine returns false. */ template inline bool compute_ghost_cell(v_cell &c,double x,double y,double z,double r) { int ijk; put_locate_block(ijk,x,y,z); double *pp=p[ijk]+4*co[ijk]++,tm=max_radius; *(pp++)=x;*(pp++)=y;*(pp++)=z;*pp=r; if(r>max_radius) max_radius=r; bool q=compute_cell(c,ijk,co[ijk]-1); co[ijk]--;max_radius=tm; return q; } void print_custom(const char *format,FILE *fp=stdout); void print_custom(const char *format,const char *filename); bool find_voronoi_cell(double x,double y,double z,double &rx,double &ry,double &rz,int &pid); private: voro_compute vc; friend class voro_compute; }; } #endif voro++-0.4.6/src/Doxyfile000600 000765 000024 00000301660 12230022760 015040 0ustar00chrstaff000000 000000 # Doxyfile 1.8.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = Voro++ # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = .. # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- # Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, # Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, # Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, # Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = . # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = cmd_line.cc # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = NO # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = NO # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = YES # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /