Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Genrich <daniel.genrich@gmx.net>2012-05-20 21:25:45 +0400
committerDaniel Genrich <daniel.genrich@gmx.net>2012-05-20 21:25:45 +0400
commit37ed2e4f46d43c6011ee756c3e6b0062816bdac6 (patch)
tree95f33620156353abc94fc22fc4355d8cde9435fb
parentf3ed42fd4b58d329641b4e76bcc617df83782b00 (diff)
- Use Smoke code from trunk again:
Unforeseen problems: The new code uses hidden arrays, file based functions. Nils himself describes the code as following in one of his new papers "Unuseable for rising smoke". What a bummer. - New approach: Backport features as moving obstacles, preconditioned conjugate gradient solver, etc. - This commit also contains the following code: Better pressure and divergence calculation, idea taken from NVIDIA (graphic gems #3)
-rw-r--r--intern/smoke/CMakeLists.txt84
-rw-r--r--intern/smoke/SConscript11
-rw-r--r--intern/smoke/extern/smoke_API.h3
-rw-r--r--intern/smoke/intern/COPYING339
-rw-r--r--intern/smoke/intern/EIGENVALUE_HELPER.cpp888
-rw-r--r--intern/smoke/intern/EIGENVALUE_HELPER.h77
-rw-r--r--intern/smoke/intern/FFT_NOISE.h181
-rw-r--r--intern/smoke/intern/FLUID_3D.cpp1458
-rw-r--r--intern/smoke/intern/FLUID_3D.h231
-rw-r--r--intern/smoke/intern/FLUID_3D_SOLVERS.cpp389
-rw-r--r--intern/smoke/intern/FLUID_3D_STATIC.cpp685
-rw-r--r--intern/smoke/intern/IMAGE.h289
-rw-r--r--intern/smoke/intern/INTERPOLATE.h230
-rw-r--r--intern/smoke/intern/LICENSE.txt674
-rw-r--r--intern/smoke/intern/LU_HELPER.cpp139
-rw-r--r--intern/smoke/intern/LU_HELPER.h54
-rw-r--r--intern/smoke/intern/MERSENNETWISTER.h432
-rw-r--r--intern/smoke/intern/Makefile42
-rw-r--r--intern/smoke/intern/Makefile.FFT22
-rw-r--r--intern/smoke/intern/Makefile.cygwin23
-rw-r--r--intern/smoke/intern/Makefile.linux23
-rw-r--r--intern/smoke/intern/Makefile.mac35
-rw-r--r--intern/smoke/intern/OBSTACLE.h46
-rw-r--r--intern/smoke/intern/README.txt90
-rw-r--r--intern/smoke/intern/SPHERE.cpp53
-rw-r--r--intern/smoke/intern/SPHERE.h44
-rw-r--r--intern/smoke/intern/VEC3.h (renamed from intern/smoke/intern/util/vectorbase.h)660
-rw-r--r--intern/smoke/intern/WAVELET_NOISE.h517
-rw-r--r--intern/smoke/intern/WTURBULENCE.cpp1071
-rw-r--r--intern/smoke/intern/WTURBULENCE.h133
-rw-r--r--intern/smoke/intern/smoke_API.cpp183
-rw-r--r--intern/smoke/intern/source/advectionplugins.cpp915
-rw-r--r--intern/smoke/intern/source/animplugins.cpp642
-rw-r--r--intern/smoke/intern/source/conjugategrad.cpp250
-rw-r--r--intern/smoke/intern/source/conjugategrad.h505
-rw-r--r--intern/smoke/intern/source/fileio.cpp633
-rw-r--r--intern/smoke/intern/source/fluidsolver.cpp428
-rw-r--r--intern/smoke/intern/source/fluidsolver.h162
-rw-r--r--intern/smoke/intern/source/glutgui.cpp951
-rw-r--r--intern/smoke/intern/source/grid.h723
-rw-r--r--intern/smoke/intern/source/guihelpers.cpp250
-rw-r--r--intern/smoke/intern/source/initplugins.cpp499
-rw-r--r--intern/smoke/intern/source/operators.h922
-rw-r--r--intern/smoke/intern/source/poissonsolvers.cpp1032
-rw-r--r--intern/smoke/intern/source/smoke.cpp193
-rw-r--r--intern/smoke/intern/source/smoke.h116
-rw-r--r--intern/smoke/intern/source/smokeplugins.cpp255
-rw-r--r--intern/smoke/intern/source/solverinit.cpp264
-rw-r--r--intern/smoke/intern/source/solverinit.h83
-rw-r--r--intern/smoke/intern/source/solverparams.cpp280
-rw-r--r--intern/smoke/intern/source/solverparams.h169
-rw-r--r--intern/smoke/intern/source/solverplugin.h120
-rw-r--r--intern/smoke/intern/source/stdplugins.cpp429
-rw-r--r--intern/smoke/intern/source/vortexpart.cpp667
-rw-r--r--intern/smoke/intern/source/vortexpart.h140
-rw-r--r--intern/smoke/intern/source/vortexplugins.cpp931
-rw-r--r--intern/smoke/intern/util/boundbox.h61
-rw-r--r--intern/smoke/intern/util/globals.cpp395
-rw-r--r--intern/smoke/intern/util/globals.h457
-rw-r--r--intern/smoke/intern/util/matrixbase.h810
-rw-r--r--intern/smoke/intern/util/paramset.cpp373
-rw-r--r--intern/smoke/intern/util/paramset.h113
-rw-r--r--intern/smoke/intern/util/quaternion.h149
-rw-r--r--intern/smoke/intern/util/randomstream.h380
-rw-r--r--intern/smoke/intern/util/waveletnoise.h600
65 files changed, 8114 insertions, 15889 deletions
diff --git a/intern/smoke/CMakeLists.txt b/intern/smoke/CMakeLists.txt
index 8cac5f2daa3..9524f7b2935 100644
--- a/intern/smoke/CMakeLists.txt
+++ b/intern/smoke/CMakeLists.txt
@@ -24,9 +24,9 @@
# ***** END GPL LICENSE BLOCK *****
set(INC
- intern/util
- intern/source
+ intern
../memutil
+ ../../extern/bullet2/src
)
set(INC_SYS
@@ -35,44 +35,68 @@ set(INC_SYS
)
set(SRC
+ intern/EIGENVALUE_HELPER.cpp
+ intern/FLUID_3D.cpp
+ intern/FLUID_3D_SOLVERS.cpp
+ intern/FLUID_3D_STATIC.cpp
+ intern/LU_HELPER.cpp
+ intern/SPHERE.cpp
+ intern/WTURBULENCE.cpp
intern/smoke_API.cpp
-
- intern/source/advectionplugins.cpp
- intern/source/animplugins.cpp
- intern/source/conjugategrad.cpp
- intern/source/fileio.cpp
- intern/source/fluidsolver.cpp
- intern/source/glutgui.cpp
- intern/source/guihelpers.cpp
- intern/source/initplugins.cpp
- intern/source/smoke.cpp
- intern/source/poissonsolvers.cpp
- intern/source/smokeplugins.cpp
- intern/source/solverinit.cpp
- intern/source/solverparams.cpp
- intern/source/stdplugins.cpp
- intern/source/vortexpart.cpp
- intern/source/vortexplugins.cpp
-
- intern/util/globals.cpp
- intern/util/paramset.cpp
+
+ extern/smoke_API.h
+ intern/EIGENVALUE_HELPER.h
+ intern/FFT_NOISE.h
+ intern/FLUID_3D.h
+ intern/IMAGE.h
+ intern/INTERPOLATE.h
+ intern/LU_HELPER.h
+ intern/MERSENNETWISTER.h
+ intern/OBSTACLE.h
+ intern/SPHERE.h
+ intern/VEC3.h
+ intern/WAVELET_NOISE.h
+ intern/WTURBULENCE.h
+ intern/tnt/jama_eig.h
+ intern/tnt/jama_lu.h
+ intern/tnt/tnt.h
+ intern/tnt/tnt_array1d.h
+ intern/tnt/tnt_array1d_utils.h
+ intern/tnt/tnt_array2d.h
+ intern/tnt/tnt_array2d_utils.h
+ intern/tnt/tnt_array3d.h
+ intern/tnt/tnt_array3d_utils.h
+ intern/tnt/tnt_cmat.h
+ intern/tnt/tnt_fortran_array1d.h
+ intern/tnt/tnt_fortran_array1d_utils.h
+ intern/tnt/tnt_fortran_array2d.h
+ intern/tnt/tnt_fortran_array2d_utils.h
+ intern/tnt/tnt_fortran_array3d.h
+ intern/tnt/tnt_fortran_array3d_utils.h
+ intern/tnt/tnt_i_refvec.h
+ intern/tnt/tnt_math_utils.h
+ intern/tnt/tnt_sparse_matrix_csr.h
+ intern/tnt/tnt_stopwatch.h
+ intern/tnt/tnt_subscript.h
+ intern/tnt/tnt_vec.h
+ intern/tnt/tnt_version.h
)
# quiet -Wundef
add_definitions(-DDDF_DEBUG=0)
if(WITH_OPENMP)
- add_definitions(-DDDF_OPENMP=1)
+ add_definitions(-DPARALLEL=1)
else()
- add_definitions(-DDDF_OPENMP=0)
+ add_definitions(-DPARALLEL=0)
endif()
-#if(WITH_FFTW3)
-# add_definitions(-DWITH_FFTW3)
-# list(APPEND INC
-# ${FFTW3_INCLUDE_DIRS}
-# )
-#endif()
+if(WITH_FFTW3)
+ add_definitions(-DWITH_FFTW3)
+ list(APPEND INC
+ ${FFTW3_INCLUDE_DIRS}
+ )
+endif()
blender_add_lib(bf_intern_smoke "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/intern/smoke/SConscript b/intern/smoke/SConscript
index 3ede5a97640..0511257d319 100644
--- a/intern/smoke/SConscript
+++ b/intern/smoke/SConscript
@@ -2,20 +2,21 @@
Import ('env')
sources = env.Glob('intern/*.cpp')
-sources += env.Glob('intern/util/*.cpp')
-sources += env.Glob('intern/source/*.cpp')
incs = ''
-defs = ' DDF_GLUTGUI=0 '
+defs = ''
if env['WITH_BF_OPENMP']:
if env['OURPLATFORM'] == 'linuxcross':
incs += ' ' + env['BF_OPENMP_INC']
- defs += ' DDF_OPENMP=1'
+ defs += ' PARALLEL=1'
incs += ' ' + env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC']
-incs += ' intern intern/util intern/source '
+incs += ' intern ../../extern/bullet2/src ../memutil ../guardealloc '
+if env['WITH_BF_FFTW3']:
+ defs += ' WITH_FFTW3'
+ incs += env['BF_FFTW3_INC']
env.BlenderLib ('bf_intern_smoke', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )
diff --git a/intern/smoke/extern/smoke_API.h b/intern/smoke/extern/smoke_API.h
index d9273db97ed..d5a43c19929 100644
--- a/intern/smoke/extern/smoke_API.h
+++ b/intern/smoke/extern/smoke_API.h
@@ -53,6 +53,8 @@ float *smoke_get_velocity_x(struct FLUID_3D *fluid);
float *smoke_get_velocity_y(struct FLUID_3D *fluid);
float *smoke_get_velocity_z(struct FLUID_3D *fluid);
+float *smoke_get_pressure(struct FLUID_3D *fluid);
+
/* Moving obstacle velocity provided by blender */
void smoke_get_ob_velocity(struct FLUID_3D *fluid, float **x, float **y, float **z);
@@ -61,7 +63,6 @@ float *smoke_get_force_y(struct FLUID_3D *fluid);
float *smoke_get_force_z(struct FLUID_3D *fluid);
unsigned char *smoke_get_obstacle(struct FLUID_3D *fluid);
-unsigned char *smoke_get_obstacle_anim(struct FLUID_3D *fluid);
size_t smoke_get_index(int x, int max_x, int y, int max_y, int z);
size_t smoke_get_index2d(int x, int max_x, int y);
diff --git a/intern/smoke/intern/COPYING b/intern/smoke/intern/COPYING
deleted file mode 100644
index d511905c164..00000000000
--- a/intern/smoke/intern/COPYING
+++ /dev/null
@@ -1,339 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/intern/smoke/intern/EIGENVALUE_HELPER.cpp b/intern/smoke/intern/EIGENVALUE_HELPER.cpp
new file mode 100644
index 00000000000..4910a2b42a7
--- /dev/null
+++ b/intern/smoke/intern/EIGENVALUE_HELPER.cpp
@@ -0,0 +1,888 @@
+/** \file smoke/intern/EIGENVALUE_HELPER.cpp
+ * \ingroup smoke
+ */
+
+#include "EIGENVALUE_HELPER.h"
+
+
+void Eigentred2(sEigenvalue& eval) {
+
+ // This is derived from the Algol procedures tred2 by
+ // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+ // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutine in EISPACK.
+
+ int n=eval.n;
+
+ for (int j = 0; j < n; j++) {
+ eval.d[j] = eval.V[n-1][j];
+ }
+
+ // Householder reduction to tridiagonal form.
+
+ for (int i = n-1; i > 0; i--) {
+
+ // Scale to avoid under/overflow.
+
+ float scale = 0.0;
+ float h = 0.0;
+ for (int k = 0; k < i; k++) {
+ scale = scale + fabs(eval.d[k]);
+ }
+ if (scale == 0.0) {
+ eval.e[i] = eval.d[i-1];
+ for (int j = 0; j < i; j++) {
+ eval.d[j] = eval.V[i-1][j];
+ eval.V[i][j] = 0.0;
+ eval.V[j][i] = 0.0;
+ }
+ } else {
+
+ // Generate Householder vector.
+
+ for (int k = 0; k < i; k++) {
+ eval.d[k] /= scale;
+ h += eval.d[k] * eval.d[k];
+ }
+ float f = eval.d[i-1];
+ float g = sqrt(h);
+ if (f > 0) {
+ g = -g;
+ }
+ eval.e[i] = scale * g;
+ h = h - f * g;
+ eval.d[i-1] = f - g;
+ for (int j = 0; j < i; j++) {
+ eval.e[j] = 0.0;
+ }
+
+ // Apply similarity transformation to remaining columns.
+
+ for (int j = 0; j < i; j++) {
+ f = eval.d[j];
+ eval.V[j][i] = f;
+ g = eval.e[j] + eval.V[j][j] * f;
+ for (int k = j+1; k <= i-1; k++) {
+ g += eval.V[k][j] * eval.d[k];
+ eval.e[k] += eval.V[k][j] * f;
+ }
+ eval.e[j] = g;
+ }
+ f = 0.0;
+ for (int j = 0; j < i; j++) {
+ eval.e[j] /= h;
+ f += eval.e[j] * eval.d[j];
+ }
+ float hh = f / (h + h);
+ for (int j = 0; j < i; j++) {
+ eval.e[j] -= hh * eval.d[j];
+ }
+ for (int j = 0; j < i; j++) {
+ f = eval.d[j];
+ g = eval.e[j];
+ for (int k = j; k <= i-1; k++) {
+ eval.V[k][j] -= (f * eval.e[k] + g * eval.d[k]);
+ }
+ eval.d[j] = eval.V[i-1][j];
+ eval.V[i][j] = 0.0;
+ }
+ }
+ eval.d[i] = h;
+ }
+
+ // Accumulate transformations.
+
+ for (int i = 0; i < n-1; i++) {
+ eval.V[n-1][i] = eval.V[i][i];
+ eval.V[i][i] = 1.0;
+ float h = eval.d[i+1];
+ if (h != 0.0) {
+ for (int k = 0; k <= i; k++) {
+ eval.d[k] = eval.V[k][i+1] / h;
+ }
+ for (int j = 0; j <= i; j++) {
+ float g = 0.0;
+ for (int k = 0; k <= i; k++) {
+ g += eval.V[k][i+1] * eval.V[k][j];
+ }
+ for (int k = 0; k <= i; k++) {
+ eval.V[k][j] -= g * eval.d[k];
+ }
+ }
+ }
+ for (int k = 0; k <= i; k++) {
+ eval.V[k][i+1] = 0.0;
+ }
+ }
+ for (int j = 0; j < n; j++) {
+ eval.d[j] = eval.V[n-1][j];
+ eval.V[n-1][j] = 0.0;
+ }
+ eval.V[n-1][n-1] = 1.0;
+ eval.e[0] = 0.0;
+}
+
+void Eigencdiv(sEigenvalue& eval, float xr, float xi, float yr, float yi) {
+ float r,d;
+ if (fabs(yr) > fabs(yi)) {
+ r = yi/yr;
+ d = yr + r*yi;
+ eval.cdivr = (xr + r*xi)/d;
+ eval.cdivi = (xi - r*xr)/d;
+ } else {
+ r = yr/yi;
+ d = yi + r*yr;
+ eval.cdivr = (r*xr + xi)/d;
+ eval.cdivi = (r*xi - xr)/d;
+ }
+ }
+
+void Eigentql2 (sEigenvalue& eval) {
+
+ // This is derived from the Algol procedures tql2, by
+ // Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+ // Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutine in EISPACK.
+
+ int n=eval.n;
+
+ for (int i = 1; i < n; i++) {
+ eval.e[i-1] = eval.e[i];
+ }
+ eval.e[n-1] = 0.0;
+
+ float f = 0.0;
+ float tst1 = 0.0;
+ float eps = pow(2.0,-52.0);
+ for (int l = 0; l < n; l++) {
+
+ // Find small subdiagonal element
+
+ tst1 = max(tst1,fabs(eval.d[l]) + fabs(eval.e[l]));
+ int m = l;
+
+ // Original while-loop from Java code
+ while (m < n) {
+ if (fabs(eval.e[m]) <= eps*tst1) {
+ break;
+ }
+ m++;
+ }
+
+
+ // If m == l, d[l] is an eigenvalue,
+ // otherwise, iterate.
+
+ if (m > l) {
+ int iter = 0;
+ do {
+ iter = iter + 1; // (Could check iteration count here.)
+
+ // Compute implicit shift
+
+ float g = eval.d[l];
+ float p = (eval.d[l+1] - g) / (2.0 * eval.e[l]);
+ float r = hypot(p,1.0);
+ if (p < 0) {
+ r = -r;
+ }
+ eval.d[l] = eval.e[l] / (p + r);
+ eval.d[l+1] = eval.e[l] * (p + r);
+ float dl1 = eval.d[l+1];
+ float h = g - eval.d[l];
+ for (int i = l+2; i < n; i++) {
+ eval.d[i] -= h;
+ }
+ f = f + h;
+
+ // Implicit QL transformation.
+
+ p = eval.d[m];
+ float c = 1.0;
+ float c2 = c;
+ float c3 = c;
+ float el1 = eval.e[l+1];
+ float s = 0.0;
+ float s2 = 0.0;
+ for (int i = m-1; i >= l; i--) {
+ c3 = c2;
+ c2 = c;
+ s2 = s;
+ g = c * eval.e[i];
+ h = c * p;
+ r = hypot(p,eval.e[i]);
+ eval.e[i+1] = s * r;
+ s = eval.e[i] / r;
+ c = p / r;
+ p = c * eval.d[i] - s * g;
+ eval.d[i+1] = h + s * (c * g + s * eval.d[i]);
+
+ // Accumulate transformation.
+
+ for (int k = 0; k < n; k++) {
+ h = eval.V[k][i+1];
+ eval.V[k][i+1] = s * eval.V[k][i] + c * h;
+ eval.V[k][i] = c * eval.V[k][i] - s * h;
+ }
+ }
+ p = -s * s2 * c3 * el1 * eval.e[l] / dl1;
+ eval.e[l] = s * p;
+ eval.d[l] = c * p;
+
+ // Check for convergence.
+
+ } while (fabs(eval.e[l]) > eps*tst1);
+ }
+ eval.d[l] = eval.d[l] + f;
+ eval.e[l] = 0.0;
+ }
+
+ // Sort eigenvalues and corresponding vectors.
+
+ for (int i = 0; i < n-1; i++) {
+ int k = i;
+ float p = eval.d[i];
+ for (int j = i+1; j < n; j++) {
+ if (eval.d[j] < p) {
+ k = j;
+ p = eval.d[j];
+ }
+ }
+ if (k != i) {
+ eval.d[k] = eval.d[i];
+ eval.d[i] = p;
+ for (int j = 0; j < n; j++) {
+ p = eval.V[j][i];
+ eval.V[j][i] = eval.V[j][k];
+ eval.V[j][k] = p;
+ }
+ }
+ }
+}
+
+void Eigenorthes (sEigenvalue& eval) {
+
+ // This is derived from the Algol procedures orthes and ortran,
+ // by Martin and Wilkinson, Handbook for Auto. Comp.,
+ // Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutines in EISPACK.
+
+ int n=eval.n;
+
+ int low = 0;
+ int high = n-1;
+
+ for (int m = low+1; m <= high-1; m++) {
+
+ // Scale column.
+
+ float scale = 0.0;
+ for (int i = m; i <= high; i++) {
+ scale = scale + fabs(eval.H[i][m-1]);
+ }
+ if (scale != 0.0) {
+
+ // Compute Householder transformation.
+
+ float h = 0.0;
+ for (int i = high; i >= m; i--) {
+ eval.ort[i] = eval.H[i][m-1]/scale;
+ h += eval.ort[i] * eval.ort[i];
+ }
+ float g = sqrt(h);
+ if (eval.ort[m] > 0) {
+ g = -g;
+ }
+ h = h - eval.ort[m] * g;
+ eval.ort[m] = eval.ort[m] - g;
+
+ // Apply Householder similarity transformation
+ // H = (I-u*u'/h)*H*(I-u*u')/h)
+
+ for (int j = m; j < n; j++) {
+ float f = 0.0;
+ for (int i = high; i >= m; i--) {
+ f += eval.ort[i]*eval.H[i][j];
+ }
+ f = f/h;
+ for (int i = m; i <= high; i++) {
+ eval.H[i][j] -= f*eval.ort[i];
+ }
+ }
+
+ for (int i = 0; i <= high; i++) {
+ float f = 0.0;
+ for (int j = high; j >= m; j--) {
+ f += eval.ort[j]*eval.H[i][j];
+ }
+ f = f/h;
+ for (int j = m; j <= high; j++) {
+ eval.H[i][j] -= f*eval.ort[j];
+ }
+ }
+ eval.ort[m] = scale*eval.ort[m];
+ eval.H[m][m-1] = scale*g;
+ }
+ }
+
+ // Accumulate transformations (Algol's ortran).
+
+ for (int i = 0; i < n; i++) {
+ for (int j = 0; j < n; j++) {
+ eval.V[i][j] = (i == j ? 1.0 : 0.0);
+ }
+ }
+
+ for (int m = high-1; m >= low+1; m--) {
+ if (eval.H[m][m-1] != 0.0) {
+ for (int i = m+1; i <= high; i++) {
+ eval.ort[i] = eval.H[i][m-1];
+ }
+ for (int j = m; j <= high; j++) {
+ float g = 0.0;
+ for (int i = m; i <= high; i++) {
+ g += eval.ort[i] * eval.V[i][j];
+ }
+ // Double division avoids possible underflow
+ g = (g / eval.ort[m]) / eval.H[m][m-1];
+ for (int i = m; i <= high; i++) {
+ eval.V[i][j] += g * eval.ort[i];
+ }
+ }
+ }
+ }
+ }
+
+void Eigenhqr2 (sEigenvalue& eval) {
+
+ // This is derived from the Algol procedure hqr2,
+ // by Martin and Wilkinson, Handbook for Auto. Comp.,
+ // Vol.ii-Linear Algebra, and the corresponding
+ // Fortran subroutine in EISPACK.
+
+ // Initialize
+
+ int nn = eval.n;
+ int n = nn-1;
+ int low = 0;
+ int high = nn-1;
+ float eps = pow(2.0,-52.0);
+ float exshift = 0.0;
+ float p=0,q=0,r=0,s=0,z=0,t,w,x,y;
+
+ // Store roots isolated by balanc and compute matrix norm
+
+ float norm = 0.0;
+ for (int i = 0; i < nn; i++) {
+ if ((i < low) || (i > high)) {
+ eval.d[i] = eval.H[i][i];
+ eval.e[i] = 0.0;
+ }
+ for (int j = max(i-1,0); j < nn; j++) {
+ norm = norm + fabs(eval.H[i][j]);
+ }
+ }
+
+ // Outer loop over eigenvalue index
+
+ int iter = 0;
+ int totIter = 0;
+ while (n >= low) {
+
+ // NT limit no. of iterations
+ totIter++;
+ if(totIter>100) {
+ //if(totIter>15) std::cout<<"!!!!iter ABORT !!!!!!! "<<totIter<<"\n";
+ // NT hack/fix, return large eigenvalues
+ for (int i = 0; i < nn; i++) {
+ eval.d[i] = 10000.;
+ eval.e[i] = 10000.;
+ }
+ return;
+ }
+
+ // Look for single small sub-diagonal element
+
+ int l = n;
+ while (l > low) {
+ s = fabs(eval.H[l-1][l-1]) + fabs(eval.H[l][l]);
+ if (s == 0.0) {
+ s = norm;
+ }
+ if (fabs(eval.H[l][l-1]) < eps * s) {
+ break;
+ }
+ l--;
+ }
+
+ // Check for convergence
+ // One root found
+
+ if (l == n) {
+ eval.H[n][n] = eval.H[n][n] + exshift;
+ eval.d[n] = eval.H[n][n];
+ eval.e[n] = 0.0;
+ n--;
+ iter = 0;
+
+ // Two roots found
+
+ } else if (l == n-1) {
+ w = eval.H[n][n-1] * eval.H[n-1][n];
+ p = (eval.H[n-1][n-1] - eval.H[n][n]) / 2.0;
+ q = p * p + w;
+ z = sqrt(fabs(q));
+ eval.H[n][n] = eval.H[n][n] + exshift;
+ eval.H[n-1][n-1] = eval.H[n-1][n-1] + exshift;
+ x = eval.H[n][n];
+
+ // float pair
+
+ if (q >= 0) {
+ if (p >= 0) {
+ z = p + z;
+ } else {
+ z = p - z;
+ }
+ eval.d[n-1] = x + z;
+ eval.d[n] = eval.d[n-1];
+ if (z != 0.0) {
+ eval.d[n] = x - w / z;
+ }
+ eval.e[n-1] = 0.0;
+ eval.e[n] = 0.0;
+ x = eval.H[n][n-1];
+ s = fabs(x) + fabs(z);
+ p = x / s;
+ q = z / s;
+ r = sqrt(p * p+q * q);
+ p = p / r;
+ q = q / r;
+
+ // Row modification
+
+ for (int j = n-1; j < nn; j++) {
+ z = eval.H[n-1][j];
+ eval.H[n-1][j] = q * z + p * eval.H[n][j];
+ eval.H[n][j] = q * eval.H[n][j] - p * z;
+ }
+
+ // Column modification
+
+ for (int i = 0; i <= n; i++) {
+ z = eval.H[i][n-1];
+ eval.H[i][n-1] = q * z + p * eval.H[i][n];
+ eval.H[i][n] = q * eval.H[i][n] - p * z;
+ }
+
+ // Accumulate transformations
+
+ for (int i = low; i <= high; i++) {
+ z = eval.V[i][n-1];
+ eval.V[i][n-1] = q * z + p * eval.V[i][n];
+ eval.V[i][n] = q * eval.V[i][n] - p * z;
+ }
+
+ // Complex pair
+
+ } else {
+ eval.d[n-1] = x + p;
+ eval.d[n] = x + p;
+ eval.e[n-1] = z;
+ eval.e[n] = -z;
+ }
+ n = n - 2;
+ iter = 0;
+
+ // No convergence yet
+
+ } else {
+
+ // Form shift
+
+ x = eval.H[n][n];
+ y = 0.0;
+ w = 0.0;
+ if (l < n) {
+ y = eval.H[n-1][n-1];
+ w = eval.H[n][n-1] * eval.H[n-1][n];
+ }
+
+ // Wilkinson's original ad hoc shift
+
+ if (iter == 10) {
+ exshift += x;
+ for (int i = low; i <= n; i++) {
+ eval.H[i][i] -= x;
+ }
+ s = fabs(eval.H[n][n-1]) + fabs(eval.H[n-1][n-2]);
+ x = y = 0.75 * s;
+ w = -0.4375 * s * s;
+ }
+
+ // MATLAB's new ad hoc shift
+
+ if (iter == 30) {
+ s = (y - x) / 2.0;
+ s = s * s + w;
+ if (s > 0) {
+ s = sqrt(s);
+ if (y < x) {
+ s = -s;
+ }
+ s = x - w / ((y - x) / 2.0 + s);
+ for (int i = low; i <= n; i++) {
+ eval.H[i][i] -= s;
+ }
+ exshift += s;
+ x = y = w = 0.964;
+ }
+ }
+
+ iter = iter + 1; // (Could check iteration count here.)
+
+ // Look for two consecutive small sub-diagonal elements
+
+ int m = n-2;
+ while (m >= l) {
+ z = eval.H[m][m];
+ r = x - z;
+ s = y - z;
+ p = (r * s - w) / eval.H[m+1][m] + eval.H[m][m+1];
+ q = eval.H[m+1][m+1] - z - r - s;
+ r = eval.H[m+2][m+1];
+ s = fabs(p) + fabs(q) + fabs(r);
+ p = p / s;
+ q = q / s;
+ r = r / s;
+ if (m == l) {
+ break;
+ }
+ if (fabs(eval.H[m][m-1]) * (fabs(q) + fabs(r)) <
+ eps * (fabs(p) * (fabs(eval.H[m-1][m-1]) + fabs(z) +
+ fabs(eval.H[m+1][m+1])))) {
+ break;
+ }
+ m--;
+ }
+
+ for (int i = m+2; i <= n; i++) {
+ eval.H[i][i-2] = 0.0;
+ if (i > m+2) {
+ eval.H[i][i-3] = 0.0;
+ }
+ }
+
+ // Double QR step involving rows l:n and columns m:n
+
+ for (int k = m; k <= n-1; k++) {
+ int notlast = (k != n-1);
+ if (k != m) {
+ p = eval.H[k][k-1];
+ q = eval.H[k+1][k-1];
+ r = (notlast ? eval.H[k+2][k-1] : 0.0);
+ x = fabs(p) + fabs(q) + fabs(r);
+ if (x != 0.0) {
+ p = p / x;
+ q = q / x;
+ r = r / x;
+ }
+ }
+ if (x == 0.0) {
+ break;
+ }
+ s = sqrt(p * p + q * q + r * r);
+ if (p < 0) {
+ s = -s;
+ }
+ if (s != 0) {
+ if (k != m) {
+ eval.H[k][k-1] = -s * x;
+ } else if (l != m) {
+ eval.H[k][k-1] = -eval.H[k][k-1];
+ }
+ p = p + s;
+ x = p / s;
+ y = q / s;
+ z = r / s;
+ q = q / p;
+ r = r / p;
+
+ // Row modification
+
+ for (int j = k; j < nn; j++) {
+ p = eval.H[k][j] + q * eval.H[k+1][j];
+ if (notlast) {
+ p = p + r * eval.H[k+2][j];
+ eval.H[k+2][j] = eval.H[k+2][j] - p * z;
+ }
+ eval.H[k][j] = eval.H[k][j] - p * x;
+ eval.H[k+1][j] = eval.H[k+1][j] - p * y;
+ }
+
+ // Column modification
+
+ for (int i = 0; i <= min(n,k+3); i++) {
+ p = x * eval.H[i][k] + y * eval.H[i][k+1];
+ if (notlast) {
+ p = p + z * eval.H[i][k+2];
+ eval.H[i][k+2] = eval.H[i][k+2] - p * r;
+ }
+ eval.H[i][k] = eval.H[i][k] - p;
+ eval.H[i][k+1] = eval.H[i][k+1] - p * q;
+ }
+
+ // Accumulate transformations
+
+ for (int i = low; i <= high; i++) {
+ p = x * eval.V[i][k] + y * eval.V[i][k+1];
+ if (notlast) {
+ p = p + z * eval.V[i][k+2];
+ eval.V[i][k+2] = eval.V[i][k+2] - p * r;
+ }
+ eval.V[i][k] = eval.V[i][k] - p;
+ eval.V[i][k+1] = eval.V[i][k+1] - p * q;
+ }
+ } // (s != 0)
+ } // k loop
+ } // check convergence
+ } // while (n >= low)
+ //if(totIter>15) std::cout<<"!!!!iter "<<totIter<<"\n";
+
+ // Backsubstitute to find vectors of upper triangular form
+
+ if (norm == 0.0) {
+ return;
+ }
+
+ for (n = nn-1; n >= 0; n--) {
+ p = eval.d[n];
+ q = eval.e[n];
+
+ // float vector
+
+ if (q == 0) {
+ int l = n;
+ eval.H[n][n] = 1.0;
+ for (int i = n-1; i >= 0; i--) {
+ w = eval.H[i][i] - p;
+ r = 0.0;
+ for (int j = l; j <= n; j++) {
+ r = r + eval.H[i][j] * eval.H[j][n];
+ }
+ if (eval.e[i] < 0.0) {
+ z = w;
+ s = r;
+ } else {
+ l = i;
+ if (eval.e[i] == 0.0) {
+ if (w != 0.0) {
+ eval.H[i][n] = -r / w;
+ } else {
+ eval.H[i][n] = -r / (eps * norm);
+ }
+
+ // Solve real equations
+
+ } else {
+ x = eval.H[i][i+1];
+ y = eval.H[i+1][i];
+ q = (eval.d[i] - p) * (eval.d[i] - p) + eval.e[i] * eval.e[i];
+ t = (x * s - z * r) / q;
+ eval.H[i][n] = t;
+ if (fabs(x) > fabs(z)) {
+ eval.H[i+1][n] = (-r - w * t) / x;
+ } else {
+ eval.H[i+1][n] = (-s - y * t) / z;
+ }
+ }
+
+ // Overflow control
+
+ t = fabs(eval.H[i][n]);
+ if ((eps * t) * t > 1) {
+ for (int j = i; j <= n; j++) {
+ eval.H[j][n] = eval.H[j][n] / t;
+ }
+ }
+ }
+ }
+
+ // Complex vector
+
+ } else if (q < 0) {
+ int l = n-1;
+
+ // Last vector component imaginary so matrix is triangular
+
+ if (fabs(eval.H[n][n-1]) > fabs(eval.H[n-1][n])) {
+ eval.H[n-1][n-1] = q / eval.H[n][n-1];
+ eval.H[n-1][n] = -(eval.H[n][n] - p) / eval.H[n][n-1];
+ } else {
+ Eigencdiv(eval, 0.0,-eval.H[n-1][n],eval.H[n-1][n-1]-p,q);
+ eval.H[n-1][n-1] = eval.cdivr;
+ eval.H[n-1][n] = eval.cdivi;
+ }
+ eval.H[n][n-1] = 0.0;
+ eval.H[n][n] = 1.0;
+ for (int i = n-2; i >= 0; i--) {
+ float ra,sa,vr,vi;
+ ra = 0.0;
+ sa = 0.0;
+ for (int j = l; j <= n; j++) {
+ ra = ra + eval.H[i][j] * eval.H[j][n-1];
+ sa = sa + eval.H[i][j] * eval.H[j][n];
+ }
+ w = eval.H[i][i] - p;
+
+ if (eval.e[i] < 0.0) {
+ z = w;
+ r = ra;
+ s = sa;
+ } else {
+ l = i;
+ if (eval.e[i] == 0) {
+ Eigencdiv(eval,-ra,-sa,w,q);
+ eval.H[i][n-1] = eval.cdivr;
+ eval.H[i][n] = eval.cdivi;
+ } else {
+
+ // Solve complex equations
+
+ x = eval.H[i][i+1];
+ y = eval.H[i+1][i];
+ vr = (eval.d[i] - p) * (eval.d[i] - p) + eval.e[i] * eval.e[i] - q * q;
+ vi = (eval.d[i] - p) * 2.0 * q;
+ if ((vr == 0.0) && (vi == 0.0)) {
+ vr = eps * norm * (fabs(w) + fabs(q) +
+ fabs(x) + fabs(y) + fabs(z));
+ }
+ Eigencdiv(eval, x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+ eval.H[i][n-1] = eval.cdivr;
+ eval.H[i][n] = eval.cdivi;
+ if (fabs(x) > (fabs(z) + fabs(q))) {
+ eval.H[i+1][n-1] = (-ra - w * eval.H[i][n-1] + q * eval.H[i][n]) / x;
+ eval.H[i+1][n] = (-sa - w * eval.H[i][n] - q * eval.H[i][n-1]) / x;
+ } else {
+ Eigencdiv(eval, -r-y*eval.H[i][n-1],-s-y*eval.H[i][n],z,q);
+ eval.H[i+1][n-1] = eval.cdivr;
+ eval.H[i+1][n] = eval.cdivi;
+ }
+ }
+
+ // Overflow control
+
+ t = max(fabs(eval.H[i][n-1]),fabs(eval.H[i][n]));
+ if ((eps * t) * t > 1) {
+ for (int j = i; j <= n; j++) {
+ eval.H[j][n-1] = eval.H[j][n-1] / t;
+ eval.H[j][n] = eval.H[j][n] / t;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Vectors of isolated roots
+
+ for (int i = 0; i < nn; i++) {
+ if (i < low || i > high) {
+ for (int j = i; j < nn; j++) {
+ eval.V[i][j] = eval.H[i][j];
+ }
+ }
+ }
+
+ // Back transformation to get eigenvectors of original matrix
+
+ for (int j = nn-1; j >= low; j--) {
+ for (int i = low; i <= high; i++) {
+ z = 0.0;
+ for (int k = low; k <= min(j,high); k++) {
+ z = z + eval.V[i][k] * eval.H[k][j];
+ }
+ eval.V[i][j] = z;
+ }
+ }
+}
+
+
+
+int computeEigenvalues3x3(
+ float dout[3],
+ float a[3][3])
+{
+ /*TNT::Array2D<float> A = TNT::Array2D<float>(3,3, &a[0][0]);
+ TNT::Array1D<float> eig = TNT::Array1D<float>(3);
+ TNT::Array1D<float> eigImag = TNT::Array1D<float>(3);
+ JAMA::Eigenvalue<float> jeig = JAMA::Eigenvalue<float>(A);*/
+
+ sEigenvalue jeig;
+
+ // Compute the values
+ {
+ jeig.n = 3;
+ int n=3;
+ //V = Array2D<float>(n,n);
+ //d = Array1D<float>(n);
+ //e = Array1D<float>(n);
+ for (int y=0; y<3; y++)
+ {
+ jeig.d[y]=0.0f;
+ jeig.e[y]=0.0f;
+ for (int t=0; t<3; t++) jeig.V[y][t]=0.0f;
+ }
+
+ jeig.issymmetric = 1;
+ for (int j = 0; (j < 3) && jeig.issymmetric; j++) {
+ for (int i = 0; (i < 3) && jeig.issymmetric; i++) {
+ jeig.issymmetric = (a[i][j] == a[j][i]);
+ }
+ }
+
+ if (jeig.issymmetric) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ jeig.V[i][j] = a[i][j];
+ }
+ }
+
+ // Tridiagonalize.
+ Eigentred2(jeig);
+
+ // Diagonalize.
+ Eigentql2(jeig);
+
+ } else {
+ //H = TNT::Array2D<float>(n,n);
+ for (int y=0; y<3; y++)
+ {
+ jeig.ort[y]=0.0f;
+ for (int t=0; t<3; t++) jeig.H[y][t]=0.0f;
+ }
+ //ort = TNT::Array1D<float>(n);
+
+ for (int j = 0; j < n; j++) {
+ for (int i = 0; i < n; i++) {
+ jeig.H[i][j] = a[i][j];
+ }
+ }
+
+ // Reduce to Hessenberg form.
+ Eigenorthes(jeig);
+
+ // Reduce Hessenberg to real Schur form.
+ Eigenhqr2(jeig);
+ }
+ }
+
+ //jeig.getfloatEigenvalues(eig);
+
+ // complex ones
+ //jeig.getImagEigenvalues(eigImag);
+ dout[0] = sqrt(jeig.d[0]*jeig.d[0] + jeig.e[0]*jeig.e[0]);
+ dout[1] = sqrt(jeig.d[1]*jeig.d[1] + jeig.e[1]*jeig.e[1]);
+ dout[2] = sqrt(jeig.d[2]*jeig.d[2] + jeig.e[2]*jeig.e[2]);
+ return 0;
+}
diff --git a/intern/smoke/intern/EIGENVALUE_HELPER.h b/intern/smoke/intern/EIGENVALUE_HELPER.h
new file mode 100644
index 00000000000..a3f983c3209
--- /dev/null
+++ b/intern/smoke/intern/EIGENVALUE_HELPER.h
@@ -0,0 +1,77 @@
+/** \file smoke/intern/EIGENVALUE_HELPER.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+//////////////////////////////////////////////////////////////////////
+// Modified to not require TNT matrix library anymore. It was very slow
+// when being run in parallel. Required TNT JAMA::Eigenvalue libraries were
+// converted into independent functions.
+// - MiikaH
+//
+//////////////////////////////////////////////////////////////////////
+// Helper function, compute eigenvalues of 3x3 matrix
+//////////////////////////////////////////////////////////////////////
+
+#ifndef EIGENVAL_HELPER_H
+#define EIGENVAL_HELPER_H
+
+//#include "tnt/jama_eig.h"
+
+#include <algorithm>
+#include <cmath>
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////
+// eigenvalues of 3x3 non-symmetric matrix
+//////////////////////////////////////////////////////////////////////
+
+
+struct sEigenvalue
+{
+ int n;
+ int issymmetric;
+ float d[3]; /* real part */
+ float e[3]; /* img part */
+ float V[3][3]; /* Eigenvectors */
+
+ float H[3][3];
+
+
+ float ort[3];
+
+ float cdivr;
+ float cdivi;
+};
+
+void Eigentred2(sEigenvalue& eval);
+
+void Eigencdiv(sEigenvalue& eval, float xr, float xi, float yr, float yi);
+
+void Eigentql2 (sEigenvalue& eval);
+
+void Eigenorthes (sEigenvalue& eval);
+
+void Eigenhqr2 (sEigenvalue& eval);
+
+int computeEigenvalues3x3(float dout[3], float a[3][3]);
+
+
+#endif
diff --git a/intern/smoke/intern/FFT_NOISE.h b/intern/smoke/intern/FFT_NOISE.h
new file mode 100644
index 00000000000..a087b4e1391
--- /dev/null
+++ b/intern/smoke/intern/FFT_NOISE.h
@@ -0,0 +1,181 @@
+/** \file smoke/intern/FFT_NOISE.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+/////////////////////////////////////////////////////////////////////////
+//
+
+#ifndef FFT_NOISE_H_
+#define FFT_NOISE_H_
+
+#ifdef WITH_FFTW3
+#include <iostream>
+#include <fftw3.h>
+#include <MERSENNETWISTER.h>
+
+#include "WAVELET_NOISE.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+/////////////////////////////////////////////////////////////////////////
+// shift spectrum to the format that FFTW expects
+/////////////////////////////////////////////////////////////////////////
+static void shift3D(float*& field, int xRes, int yRes, int zRes)
+{
+ int xHalf = xRes / 2;
+ int yHalf = yRes / 2;
+ int zHalf = zRes / 2;
+ // int slabSize = xRes * yRes;
+ for (int z = 0; z < zHalf; z++)
+ for (int y = 0; y < yHalf; y++)
+ for (int x = 0; x < xHalf; x++)
+ {
+ int index = x + y * xRes + z * xRes * yRes;
+ float temp;
+ int xSwap = xHalf;
+ int ySwap = yHalf * xRes;
+ int zSwap = zHalf * xRes * yRes;
+
+ // [0,0,0] to [1,1,1]
+ temp = field[index];
+ field[index] = field[index + xSwap + ySwap + zSwap];
+ field[index + xSwap + ySwap + zSwap] = temp;
+
+ // [1,0,0] to [0,1,1]
+ temp = field[index + xSwap];
+ field[index + xSwap] = field[index + ySwap + zSwap];
+ field[index + ySwap + zSwap] = temp;
+
+ // [0,1,0] to [1,0,1]
+ temp = field[index + ySwap];
+ field[index + ySwap] = field[index + xSwap + zSwap];
+ field[index + xSwap + zSwap] = temp;
+
+ // [0,0,1] to [1,1,0]
+ temp = field[index + zSwap];
+ field[index + zSwap] = field[index + xSwap + ySwap];
+ field[index + xSwap + ySwap] = temp;
+ }
+}
+
+static void generatTile_FFT(float* const noiseTileData, std::string filename)
+{
+ if (loadTile(noiseTileData, filename)) return;
+
+ int res = NOISE_TILE_SIZE;
+ int xRes = res;
+ int yRes = res;
+ int zRes = res;
+ int totalCells = xRes * yRes * zRes;
+
+ // create and shift the filter
+ float* filter = new float[totalCells];
+ for (int z = 0; z < zRes; z++)
+ for (int y = 0; y < yRes; y++)
+ for (int x = 0; x < xRes; x++)
+ {
+ int index = x + y * xRes + z * xRes * yRes;
+ float diff[] = {abs(x - xRes/2),
+ abs(y - yRes/2),
+ abs(z - zRes/2)};
+ float radius = sqrtf(diff[0] * diff[0] +
+ diff[1] * diff[1] +
+ diff[2] * diff[2]) / (xRes / 2);
+ radius *= M_PI;
+ float H = cos((M_PI / 2.0f) * log(4.0f * radius / M_PI) / log(2.0f));
+ H = H * H;
+ float filtered = H;
+
+ // clamp everything outside the wanted band
+ if (radius >= M_PI / 2.0f)
+ filtered = 0.0f;
+
+ // make sure to capture all low frequencies
+ if (radius <= M_PI / 4.0f)
+ filtered = 1.0f;
+
+ filter[index] = filtered;
+ }
+ shift3D(filter, xRes, yRes, zRes);
+
+ // create the noise
+ float* noise = new float[totalCells];
+ int index = 0;
+ MTRand twister;
+ for (int z = 0; z < zRes; z++)
+ for (int y = 0; y < yRes; y++)
+ for (int x = 0; x < xRes; x++, index++)
+ noise[index] = twister.randNorm();
+
+ // create padded field
+ fftw_complex* forward = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * totalCells);
+
+ // init padded field
+ index = 0;
+ for (int z = 0; z < zRes; z++)
+ for (int y = 0; y < yRes; y++)
+ for (int x = 0; x < xRes; x++, index++)
+ {
+ forward[index][0] = noise[index];
+ forward[index][1] = 0.0f;
+ }
+
+ // forward FFT
+ fftw_complex* backward = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * totalCells);
+ fftw_plan forwardPlan = fftw_plan_dft_3d(xRes, yRes, zRes, forward, backward, FFTW_FORWARD, FFTW_ESTIMATE);
+ fftw_execute(forwardPlan);
+ fftw_destroy_plan(forwardPlan);
+
+ // apply filter
+ index = 0;
+ for (int z = 0; z < zRes; z++)
+ for (int y = 0; y < yRes; y++)
+ for (int x = 0; x < xRes; x++, index++)
+ {
+ backward[index][0] *= filter[index];
+ backward[index][1] *= filter[index];
+ }
+
+ // backward FFT
+ fftw_plan backwardPlan = fftw_plan_dft_3d(xRes, yRes, zRes, backward, forward, FFTW_BACKWARD, FFTW_ESTIMATE);
+ fftw_execute(backwardPlan);
+ fftw_destroy_plan(backwardPlan);
+
+ // subtract out the low frequency components
+ index = 0;
+ for (int z = 0; z < zRes; z++)
+ for (int y = 0; y < yRes; y++)
+ for (int x = 0; x < xRes; x++, index++)
+ noise[index] -= forward[index][0] / totalCells;
+
+ // save out the noise tile
+ saveTile(noise, filename);
+
+ fftw_free(forward);
+ fftw_free(backward);
+ delete[] filter;
+ delete[] noise;
+}
+
+#endif
+
+#endif /* FFT_NOISE_H_ */
diff --git a/intern/smoke/intern/FLUID_3D.cpp b/intern/smoke/intern/FLUID_3D.cpp
new file mode 100644
index 00000000000..525774358e6
--- /dev/null
+++ b/intern/smoke/intern/FLUID_3D.cpp
@@ -0,0 +1,1458 @@
+/** \file smoke/intern/FLUID_3D.cpp
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// FLUID_3D.cpp: implementation of the FLUID_3D class.
+//
+//////////////////////////////////////////////////////////////////////
+// Heavy parallel optimization done. Many of the old functions now
+// take begin and end parameters and process only specified part of the data.
+// Some functions were divided into multiple ones.
+// - MiikaH
+//////////////////////////////////////////////////////////////////////
+
+#include "FLUID_3D.h"
+#include "IMAGE.h"
+#include <INTERPOLATE.h>
+#include "SPHERE.h"
+#include <zlib.h>
+
+#include "float.h"
+
+#if PARALLEL==1
+#include <omp.h>
+#endif // PARALLEL
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+FLUID_3D::FLUID_3D(int *res, float *p0, float dtdef) :
+ _xRes(res[0]), _yRes(res[1]), _zRes(res[2]), _res(0.0f)
+{
+ // set simulation consts
+ _dt = dtdef; // just in case. set in step from a RNA factor
+
+ // start point of array
+ _p0[0] = p0[0];
+ _p0[1] = p0[1];
+ _p0[2] = p0[2];
+
+ _iterations = 100;
+ _tempAmb = 0;
+ _heatDiffusion = 1e-3;
+ _totalTime = 0.0f;
+ _totalSteps = 0;
+ _res = Vec3Int(_xRes,_yRes,_zRes);
+ _maxRes = MAX3(_xRes, _yRes, _zRes);
+
+ // initialize wavelet turbulence
+ /*
+ if(amplify)
+ _wTurbulence = new WTURBULENCE(_res[0],_res[1],_res[2], amplify, noisetype);
+ else
+ _wTurbulence = NULL;
+ */
+
+ // scale the constants according to the refinement of the grid
+ _dx = 1.0f / (float)_maxRes;
+ _constantScaling = 64.0f / _maxRes;
+ _constantScaling = (_constantScaling < 1.0f) ? 1.0f : _constantScaling;
+ _vorticityEps = 2.0f / _constantScaling; // Just in case set a default value
+
+ // allocate arrays
+ _totalCells = _xRes * _yRes * _zRes;
+ _slabSize = _xRes * _yRes;
+ _xVelocity = new float[_totalCells];
+ _yVelocity = new float[_totalCells];
+ _zVelocity = new float[_totalCells];
+ _xVelocityOb = new float[_totalCells];
+ _yVelocityOb = new float[_totalCells];
+ _zVelocityOb = new float[_totalCells];
+ _xVelocityOld = new float[_totalCells];
+ _yVelocityOld = new float[_totalCells];
+ _zVelocityOld = new float[_totalCells];
+ _xForce = new float[_totalCells];
+ _yForce = new float[_totalCells];
+ _zForce = new float[_totalCells];
+ _density = new float[_totalCells];
+ _densityOld = new float[_totalCells];
+ _heat = new float[_totalCells];
+ _heatOld = new float[_totalCells];
+ _obstacles = new unsigned char[_totalCells]; // set 0 at end of step
+
+ // For debugging purposes
+ _pressure = new float[_totalCells];
+
+ // For threaded version:
+ _xVelocityTemp = new float[_totalCells];
+ _yVelocityTemp = new float[_totalCells];
+ _zVelocityTemp = new float[_totalCells];
+ _densityTemp = new float[_totalCells];
+ _heatTemp = new float[_totalCells];
+
+ // DG TODO: check if alloc went fine
+
+ for (int x = 0; x < _totalCells; x++)
+ {
+ _density[x] = 0.0f;
+ _densityOld[x] = 0.0f;
+ _heat[x] = 0.0f;
+ _heatOld[x] = 0.0f;
+ _xVelocity[x] = 0.0f;
+ _yVelocity[x] = 0.0f;
+ _zVelocity[x] = 0.0f;
+ _xVelocityOb[x] = 0.0f;
+ _yVelocityOb[x] = 0.0f;
+ _zVelocityOb[x] = 0.0f;
+ _xVelocityOld[x] = 0.0f;
+ _yVelocityOld[x] = 0.0f;
+ _zVelocityOld[x] = 0.0f;
+ _xForce[x] = 0.0f;
+ _yForce[x] = 0.0f;
+ _zForce[x] = 0.0f;
+ _obstacles[x] = false;
+ _pressure[x] = 0.0f;
+ }
+
+ // boundary conditions of the fluid domain
+ // set default values -> vertically non-colliding
+ _domainBcFront = true;
+ _domainBcTop = false;
+ _domainBcLeft = true;
+ _domainBcBack = _domainBcFront;
+ _domainBcBottom = _domainBcTop;
+ _domainBcRight = _domainBcLeft;
+
+ _colloPrev = 1; // default value
+
+ setBorderObstacles(); // walls
+
+}
+
+void FLUID_3D::setBorderObstacles()
+{
+
+ // set side obstacles
+ unsigned int index;
+ for (int y = 0; y < _yRes; y++)
+ for (int x = 0; x < _xRes; x++)
+ {
+ // bottom slab
+ index = x + y * _xRes;
+ if(_domainBcBottom==1) _obstacles[index] = 1;
+
+ // top slab
+ index += _totalCells - _slabSize;
+ if(_domainBcTop==1) _obstacles[index] = 1;
+ }
+
+ for (int z = 0; z < _zRes; z++)
+ for (int x = 0; x < _xRes; x++)
+ {
+ // front slab
+ index = x + z * _slabSize;
+ if(_domainBcFront==1) _obstacles[index] = 1;
+
+ // back slab
+ index += _slabSize - _xRes;
+ if(_domainBcBack==1) _obstacles[index] = 1;
+ }
+
+ for (int z = 0; z < _zRes; z++)
+ for (int y = 0; y < _yRes; y++)
+ {
+ // left slab
+ index = y * _xRes + z * _slabSize;
+ if(_domainBcLeft==1) _obstacles[index] = 1;
+
+ // right slab
+ index += _xRes - 1;
+ if(_domainBcRight==1) _obstacles[index] = 1;
+ }
+}
+
+FLUID_3D::~FLUID_3D()
+{
+ if (_xVelocity) delete[] _xVelocity;
+ if (_yVelocity) delete[] _yVelocity;
+ if (_zVelocity) delete[] _zVelocity;
+ if (_xVelocityOb) delete[] _xVelocityOb;
+ if (_yVelocityOb) delete[] _yVelocityOb;
+ if (_zVelocityOb) delete[] _zVelocityOb;
+ if (_xVelocityOld) delete[] _xVelocityOld;
+ if (_yVelocityOld) delete[] _yVelocityOld;
+ if (_zVelocityOld) delete[] _zVelocityOld;
+ if (_xForce) delete[] _xForce;
+ if (_yForce) delete[] _yForce;
+ if (_zForce) delete[] _zForce;
+ if (_density) delete[] _density;
+ if (_densityOld) delete[] _densityOld;
+ if (_heat) delete[] _heat;
+ if (_heatOld) delete[] _heatOld;
+ if (_obstacles) delete[] _obstacles;
+ // if (_wTurbulence) delete _wTurbulence;
+
+ // for debugging purposes
+ if(_pressure)
+ delete[] _pressure;
+
+ if (_xVelocityTemp) delete[] _xVelocityTemp;
+ if (_yVelocityTemp) delete[] _yVelocityTemp;
+ if (_zVelocityTemp) delete[] _zVelocityTemp;
+ if (_densityTemp) delete[] _densityTemp;
+ if (_heatTemp) delete[] _heatTemp;
+
+ // printf("deleted fluid\n");
+}
+
+// init direct access functions from blender
+void FLUID_3D::initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *borderCollision)
+{
+ _alpha = alpha;
+ _beta = beta;
+ _dtFactor = dt_factor;
+ _vorticityRNA = vorticity;
+ _borderColli = borderCollision;
+}
+
+//////////////////////////////////////////////////////////////////////
+// step simulation once
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::step(float dt)
+{
+#if 0
+ // If border rules have been changed
+ if (_colloPrev != *_borderColli) {
+ printf("Border collisions changed\n");
+
+ // DG TODO: Need to check that no animated obstacle flags are overwritten
+ setBorderCollisions();
+ }
+#endif
+
+ // DG: TODO for the moment redo border for every timestep since it's been deleted every time by moving obstacles
+ setBorderCollisions();
+
+
+ // set delta time by dt_factor
+ _dt = (*_dtFactor) * dt;
+ // set vorticity from RNA value
+ _vorticityEps = (*_vorticityRNA)/_constantScaling;
+
+
+#if PARALLEL==1
+ int threadval = 1;
+ threadval = omp_get_max_threads();
+
+ int stepParts = 1;
+ float partSize = _zRes;
+
+ stepParts = threadval*2; // Dividing parallelized sections into numOfThreads * 2 sections
+ partSize = (float)_zRes/stepParts; // Size of one part;
+
+ if (partSize < 4) {stepParts = threadval; // If the slice gets too low (might actually slow things down, change it to larger
+ partSize = (float)_zRes/stepParts;}
+ if (partSize < 4) {stepParts = (int)(ceil((float)_zRes/4.0f)); // If it's still too low (only possible on future systems with +24 cores), change it to 4
+ partSize = (float)_zRes/stepParts;}
+#else
+ int zBegin=0;
+ int zEnd=_zRes;
+#endif
+
+
+#if PARALLEL==1
+ #pragma omp parallel
+ {
+ #pragma omp for schedule(static,1)
+ for (int i=0; i<stepParts; i++)
+ {
+ int zBegin = (int)((float)i*partSize + 0.5f);
+ int zEnd = (int)((float)(i+1)*partSize + 0.5f);
+#endif
+
+ wipeBoundariesSL(zBegin, zEnd);
+ addVorticity(zBegin, zEnd);
+ addBuoyancy(_heat, _density, zBegin, zEnd);
+ addForce(zBegin, zEnd);
+
+#if PARALLEL==1
+ } // end of parallel
+ #pragma omp barrier
+
+ #pragma omp single
+ {
+#endif
+ /*
+ * addForce() changed Temp values to preserve thread safety
+ * (previous functions in per thread loop still needed
+ * original velocity data)
+ *
+ * So swap temp values to velocity
+ */
+ SWAP_POINTERS(_xVelocity, _xVelocityTemp);
+ SWAP_POINTERS(_yVelocity, _yVelocityTemp);
+ SWAP_POINTERS(_zVelocity, _zVelocityTemp);
+#if PARALLEL==1
+ } // end of single
+
+ #pragma omp barrier
+
+ #pragma omp for
+ for (int i=0; i<2; i++)
+ {
+ if (i==0)
+ {
+#endif
+ project();
+#if PARALLEL==1
+ }
+ else
+ {
+#endif
+ diffuseHeat();
+#if PARALLEL==1
+ }
+ }
+
+ #pragma omp barrier
+
+ #pragma omp single
+ {
+#endif
+ /*
+ * For thread safety use "Old" to read
+ * "current" values but still allow changing values.
+ */
+ SWAP_POINTERS(_xVelocity, _xVelocityOld);
+ SWAP_POINTERS(_yVelocity, _yVelocityOld);
+ SWAP_POINTERS(_zVelocity, _zVelocityOld);
+ SWAP_POINTERS(_density, _densityOld);
+ SWAP_POINTERS(_heat, _heatOld);
+
+ advectMacCormackBegin(0, _zRes);
+
+#if PARALLEL==1
+ } // end of single
+
+ #pragma omp barrier
+
+
+ #pragma omp for schedule(static,1)
+ for (int i=0; i<stepParts; i++)
+ {
+
+ int zBegin = (int)((float)i*partSize + 0.5f);
+ int zEnd = (int)((float)(i+1)*partSize + 0.5f);
+#endif
+
+ advectMacCormackEnd1(zBegin, zEnd);
+
+#if PARALLEL==1
+ } // end of parallel
+
+ #pragma omp barrier
+
+ #pragma omp for schedule(static,1)
+ for (int i=0; i<stepParts; i++)
+ {
+
+ int zBegin = (int)((float)i*partSize + 0.5f);
+ int zEnd = (int)((float)(i+1)*partSize + 0.5f);
+#endif
+
+ advectMacCormackEnd2(zBegin, zEnd);
+
+ artificialDampingSL(zBegin, zEnd);
+
+ // Using forces as temp arrays
+
+#if PARALLEL==1
+ }
+ }
+
+
+
+ for (int i=1; i<stepParts; i++)
+ {
+ int zPos=(int)((float)i*partSize + 0.5f);
+
+ artificialDampingExactSL(zPos);
+
+ }
+#endif
+
+ /*
+ * swap final velocity back to Velocity array
+ * from temp xForce storage
+ */
+ SWAP_POINTERS(_xVelocity, _xForce);
+ SWAP_POINTERS(_yVelocity, _yForce);
+ SWAP_POINTERS(_zVelocity, _zForce);
+
+
+
+
+ _totalTime += _dt;
+ _totalSteps++;
+
+ for (int i = 0; i < _totalCells; i++)
+ {
+ _xForce[i] = _yForce[i] = _zForce[i] = 0.0f;
+ }
+
+}
+
+
+// Set border collision model from RNA setting
+
+void FLUID_3D::setBorderCollisions() {
+
+
+ _colloPrev = *_borderColli; // saving the current value
+
+ // boundary conditions of the fluid domain
+ if (_colloPrev == 0)
+ {
+ // No collisions
+ _domainBcFront = false;
+ _domainBcTop = false;
+ _domainBcLeft = false;
+ }
+ else if (_colloPrev == 2)
+ {
+ // Collide with all sides
+ _domainBcFront = true;
+ _domainBcTop = true;
+ _domainBcLeft = true;
+ }
+ else
+ {
+ // Default values: Collide with "walls", but not top and bottom
+ _domainBcFront = true;
+ _domainBcTop = false;
+ _domainBcLeft = true;
+ }
+
+ _domainBcBack = _domainBcFront;
+ _domainBcBottom = _domainBcTop;
+ _domainBcRight = _domainBcLeft;
+
+
+
+ // set side obstacles
+ int index;
+ for (int y = 0; y < _yRes; y++)
+ for (int x = 0; x < _xRes; x++)
+ {
+ // front slab
+ index = x + y * _xRes;
+ if(_domainBcBottom==1) _obstacles[index] = 1;
+ else _obstacles[index] = 0;
+
+ // back slab
+ index += _totalCells - _slabSize;
+ if(_domainBcTop==1) _obstacles[index] = 1;
+ else _obstacles[index] = 0;
+ }
+
+ for (int z = 0; z < _zRes; z++)
+ for (int x = 0; x < _xRes; x++)
+ {
+ // bottom slab
+ index = x + z * _slabSize;
+ if(_domainBcFront==1) _obstacles[index] = 1;
+ else _obstacles[index] = 0;
+
+ // top slab
+ index += _slabSize - _xRes;
+ if(_domainBcBack==1) _obstacles[index] = 1;
+ else _obstacles[index] = 0;
+ }
+
+ for (int z = 0; z < _zRes; z++)
+ for (int y = 0; y < _yRes; y++)
+ {
+ // left slab
+ index = y * _xRes + z * _slabSize;
+ if(_domainBcLeft==1) _obstacles[index] = 1;
+ else _obstacles[index] = 0;
+
+ // right slab
+ index += _xRes - 1;
+ if(_domainBcRight==1) _obstacles[index] = 1;
+ else _obstacles[index] = 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// helper function to dampen co-located grid artifacts of given arrays in intervals
+// (only needed for velocity, strength (w) depends on testcase...
+//////////////////////////////////////////////////////////////////////
+
+
+void FLUID_3D::artificialDampingSL(int zBegin, int zEnd) {
+ const float w = 0.9;
+
+ memmove(_xForce+(_slabSize*zBegin), _xVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
+ memmove(_yForce+(_slabSize*zBegin), _yVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
+ memmove(_zForce+(_slabSize*zBegin), _zVelocityTemp+(_slabSize*zBegin), sizeof(float)*_slabSize*(zEnd-zBegin));
+
+
+ if(_totalSteps % 4 == 1) {
+ for (int z = zBegin+1; z < zEnd-1; z++)
+ for (int y = 1; y < _res[1]-1; y++)
+ for (int x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
+ const int index = x + y*_res[0] + z * _slabSize;
+ _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
+ _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
+ _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
+ _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
+
+ _yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
+ _yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
+ _yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
+ _yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
+
+ _zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
+ _zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
+ _zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
+ _zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
+ }
+ }
+
+ if(_totalSteps % 4 == 3) {
+ for (int z = zBegin+1; z < zEnd-1; z++)
+ for (int y = 1; y < _res[1]-1; y++)
+ for (int x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
+ const int index = x + y*_res[0] + z * _slabSize;
+ _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
+ _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
+ _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
+ _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
+
+ _yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
+ _yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
+ _yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
+ _yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
+
+ _zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
+ _zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
+ _zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
+ _zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
+ }
+
+ }
+}
+
+
+
+void FLUID_3D::artificialDampingExactSL(int pos) {
+ const float w = 0.9;
+ int index, x,y,z;
+
+
+ size_t posslab;
+
+ for (z=pos-1; z<=pos; z++)
+ {
+ posslab=z * _slabSize;
+
+ if(_totalSteps % 4 == 1) {
+ for (y = 1; y < _res[1]-1; y++)
+ for (x = 1+(y+z)%2; x < _res[0]-1; x+=2) {
+ index = x + y*_res[0] + posslab;
+ /*
+ * Uses xForce as temporary storage to allow other threads to read
+ * old values from xVelocityTemp
+ */
+ _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
+ _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
+ _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
+ _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
+
+ _yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
+ _yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
+ _yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
+ _yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
+
+ _zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
+ _zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
+ _zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
+ _zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
+
+ }
+ }
+
+ if(_totalSteps % 4 == 3) {
+ for (y = 1; y < _res[1]-1; y++)
+ for (x = 1+(y+z+1)%2; x < _res[0]-1; x+=2) {
+ index = x + y*_res[0] + posslab;
+
+ /*
+ * Uses xForce as temporary storage to allow other threads to read
+ * old values from xVelocityTemp
+ */
+ _xForce[index] = (1-w)*_xVelocityTemp[index] + 1./6. * w*(
+ _xVelocityTemp[index+1] + _xVelocityTemp[index-1] +
+ _xVelocityTemp[index+_res[0]] + _xVelocityTemp[index-_res[0]] +
+ _xVelocityTemp[index+_slabSize] + _xVelocityTemp[index-_slabSize] );
+
+ _yForce[index] = (1-w)*_yVelocityTemp[index] + 1./6. * w*(
+ _yVelocityTemp[index+1] + _yVelocityTemp[index-1] +
+ _yVelocityTemp[index+_res[0]] + _yVelocityTemp[index-_res[0]] +
+ _yVelocityTemp[index+_slabSize] + _yVelocityTemp[index-_slabSize] );
+
+ _zForce[index] = (1-w)*_zVelocityTemp[index] + 1./6. * w*(
+ _zVelocityTemp[index+1] + _zVelocityTemp[index-1] +
+ _zVelocityTemp[index+_res[0]] + _zVelocityTemp[index-_res[0]] +
+ _zVelocityTemp[index+_slabSize] + _zVelocityTemp[index-_slabSize] );
+
+ }
+
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// copy out the boundary in all directions
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::copyBorderAll(float* field, int zBegin, int zEnd)
+{
+ int index, x, y, z;
+ int zSize = zEnd-zBegin;
+ int _blockTotalCells=_slabSize * zSize;
+
+ if (zBegin==0)
+ for (int y = 0; y < _yRes; y++)
+ for (int x = 0; x < _xRes; x++)
+ {
+ // front slab
+ index = x + y * _xRes;
+ field[index] = field[index + _slabSize];
+ }
+
+ if (zEnd==_zRes)
+ for (y = 0; y < _yRes; y++)
+ for (x = 0; x < _xRes; x++)
+ {
+
+ // back slab
+ index = x + y * _xRes + _blockTotalCells - _slabSize;
+ field[index] = field[index - _slabSize];
+ }
+
+ for (z = 0; z < zSize; z++)
+ for (x = 0; x < _xRes; x++)
+ {
+ // bottom slab
+ index = x + z * _slabSize;
+ field[index] = field[index + _xRes];
+
+ // top slab
+ index += _slabSize - _xRes;
+ field[index] = field[index - _xRes];
+ }
+
+ for (z = 0; z < zSize; z++)
+ for (y = 0; y < _yRes; y++)
+ {
+ // left slab
+ index = y * _xRes + z * _slabSize;
+ field[index] = field[index + 1];
+
+ // right slab
+ index += _xRes - 1;
+ field[index] = field[index - 1];
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// wipe boundaries of velocity and density
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::wipeBoundaries(int zBegin, int zEnd)
+{
+ setZeroBorder(_xVelocity, _res, zBegin, zEnd);
+ setZeroBorder(_yVelocity, _res, zBegin, zEnd);
+ setZeroBorder(_zVelocity, _res, zBegin, zEnd);
+ setZeroBorder(_density, _res, zBegin, zEnd);
+}
+
+void FLUID_3D::wipeBoundariesSL(int zBegin, int zEnd)
+{
+
+ /////////////////////////////////////
+ // setZeroBorder to all:
+ /////////////////////////////////////
+
+ /////////////////////////////////////
+ // setZeroX
+ /////////////////////////////////////
+
+ const int slabSize = _xRes * _yRes;
+ int index, x,y,z;
+
+ for (z = zBegin; z < zEnd; z++)
+ for (y = 0; y < _yRes; y++)
+ {
+ // left slab
+ index = y * _xRes + z * slabSize;
+ _xVelocity[index] = 0.0f;
+ _yVelocity[index] = 0.0f;
+ _zVelocity[index] = 0.0f;
+ _density[index] = 0.0f;
+
+ // right slab
+ index += _xRes - 1;
+ _xVelocity[index] = 0.0f;
+ _yVelocity[index] = 0.0f;
+ _zVelocity[index] = 0.0f;
+ _density[index] = 0.0f;
+ }
+
+ /////////////////////////////////////
+ // setZeroY
+ /////////////////////////////////////
+
+ for (z = zBegin; z < zEnd; z++)
+ for (x = 0; x < _xRes; x++)
+ {
+ // bottom slab
+ index = x + z * slabSize;
+ _xVelocity[index] = 0.0f;
+ _yVelocity[index] = 0.0f;
+ _zVelocity[index] = 0.0f;
+ _density[index] = 0.0f;
+
+ // top slab
+ index += slabSize - _xRes;
+ _xVelocity[index] = 0.0f;
+ _yVelocity[index] = 0.0f;
+ _zVelocity[index] = 0.0f;
+ _density[index] = 0.0f;
+
+ }
+
+ /////////////////////////////////////
+ // setZeroZ
+ /////////////////////////////////////
+
+
+ const int totalCells = _xRes * _yRes * _zRes;
+
+ index = 0;
+ if (zBegin == 0)
+ for (y = 0; y < _yRes; y++)
+ for (x = 0; x < _xRes; x++, index++)
+ {
+ // front slab
+ _xVelocity[index] = 0.0f;
+ _yVelocity[index] = 0.0f;
+ _zVelocity[index] = 0.0f;
+ _density[index] = 0.0f;
+ }
+
+ if (zEnd == _zRes)
+ {
+ index=0;
+ int indexx=0;
+ const int cellsslab = totalCells - slabSize;
+
+ for (y = 0; y < _yRes; y++)
+ for (x = 0; x < _xRes; x++, index++)
+ {
+
+ // back slab
+ indexx = index + cellsslab;
+ _xVelocity[indexx] = 0.0f;
+ _yVelocity[indexx] = 0.0f;
+ _zVelocity[indexx] = 0.0f;
+ _density[indexx] = 0.0f;
+ }
+ }
+
+}
+//////////////////////////////////////////////////////////////////////
+// add forces to velocity field
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::addForce(int zBegin, int zEnd)
+{
+ int begin=zBegin * _slabSize;
+ int end=begin + (zEnd - zBegin) * _slabSize;
+
+ for (int i = begin; i < end; i++)
+ {
+ _xVelocityTemp[i] = _xVelocity[i] + _dt * _xForce[i];
+ _yVelocityTemp[i] = _yVelocity[i] + _dt * _yForce[i];
+ _zVelocityTemp[i] = _zVelocity[i] + _dt * _zForce[i];
+ }
+}
+//////////////////////////////////////////////////////////////////////
+// project into divergence free field
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::project()
+{
+ int x, y, z;
+ size_t index;
+
+ // float *_pressure = new float[_totalCells];
+ float *_divergence = new float[_totalCells];
+
+ memset(_pressure, 0, sizeof(float)*_totalCells);
+ memset(_divergence, 0, sizeof(float)*_totalCells);
+
+ // set VELOCITY and PRESSURE inside of obstacles cells to zero
+ setObstacleBoundaries(_pressure, 0, _zRes);
+
+ // copy out the boundaries
+ if(_domainBcLeft == 0) setNeumannX(_xVelocity, _res, 0, _zRes);
+ else setZeroX(_xVelocity, _res, 0, _zRes);
+
+ if(_domainBcFront == 0) setNeumannY(_yVelocity, _res, 0, _zRes);
+ else setZeroY(_yVelocity, _res, 0, _zRes);
+
+ if(_domainBcTop == 0) setNeumannZ(_zVelocity, _res, 0, _zRes);
+ else setZeroZ(_zVelocity, _res, 0, _zRes);
+
+ // calculate divergence
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+
+ if(_obstacles[index])
+ {
+ _divergence[index] = 0.0f;
+ continue;
+ }
+
+ float xright = _xVelocity[index + 1];
+ float xleft = _xVelocity[index - 1];
+ float yup = _yVelocity[index + _xRes];
+ float ydown = _yVelocity[index - _xRes];
+ float ztop = _zVelocity[index + _slabSize];
+ float zbottom = _zVelocity[index - _slabSize];
+
+ if(_obstacles[index+1]) xright = - _xVelocity[index]; // DG: +=
+ if(_obstacles[index-1]) xleft = - _xVelocity[index];
+ if(_obstacles[index+_xRes]) yup = - _yVelocity[index];
+ if(_obstacles[index-_xRes]) ydown = - _yVelocity[index];
+ if(_obstacles[index+_slabSize]) ztop = - _zVelocity[index];
+ if(_obstacles[index-_slabSize]) zbottom = - _zVelocity[index];
+
+ if(_obstacles[index+1]) xright += _xVelocityOb[index + 1];
+ if(_obstacles[index-1]) xleft += _xVelocityOb[index - 1];
+ if(_obstacles[index+_xRes]) yup += _yVelocityOb[index + _xRes];
+ if(_obstacles[index-_xRes]) ydown += _yVelocityOb[index - _xRes];
+ if(_obstacles[index+_slabSize]) ztop += _zVelocityOb[index + _slabSize];
+ if(_obstacles[index-_slabSize]) zbottom += _zVelocityOb[index - _slabSize];
+
+ _divergence[index] = -_dx * 0.5f * (
+ xright - xleft +
+ yup - ydown +
+ ztop - zbottom );
+
+ // Pressure is zero anyway since now a local array is used
+ _pressure[index] = 0.0f;
+ }
+
+ // copyBorderAll(_pressure, 0, _zRes);
+
+ // solve Poisson equation
+ solvePressurePre(_pressure, _divergence, _obstacles);
+
+ // DG TODO: Alternative for solvePressurePre, does not work correctly
+ // solvePressureJacobian(_pressure, _divergence, _obstacles);
+
+ {
+ float maxvalue = 0;
+ for(unsigned int i = 0; i < _xRes * _yRes * _zRes; i++)
+ {
+ if(_pressure[i] > maxvalue)
+ maxvalue = _pressure[i];
+
+ /* HACK: Animated collision object sometimes result in a non converging solvePressurePre() */
+ if(_pressure[i] > _dx * _dt)
+ _pressure[i] = _dx * _dt;
+ else if(_pressure[i] < -_dx * _dt)
+ _pressure[i] = -_dx * _dt;
+
+ // if(_obstacle[i] && _pressure[i] != 0.0)
+ // printf("BAD PRESSURE i\n");
+
+ // if(_pressure[i]>1)
+ // printf("index: %d\n", i);
+ }
+ // printf("Max pressure: %f, dx: %f\n", maxvalue, _dx);
+ }
+
+ // DG TODO: check this function, for now this is done in the next function
+ // setObstaclePressure(_pressure, 0, _zRes);
+
+ // project out solution
+ float invDx = 1.0f / _dx;
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+ float vMask[3] = {1.0f, 1.0f, 1.0f}, vObst[3] = {0, 0, 0};
+ float vR = 0.0f, vL = 0.0f, vT = 0.0f, vB = 0.0f, vD = 0.0f, vU = 0.0f;
+
+ float pC = _pressure[index]; // center
+ float pR = _pressure[index + 1]; // right
+ float pL = _pressure[index - 1]; // left
+ float pT = _pressure[index + _slabSize]; // top
+ float pB = _pressure[index - _slabSize]; // bottom
+ float pU = _pressure[index + _xRes]; // Up
+ float pD = _pressure[index - _xRes]; // Down
+
+ if(!_obstacles[index])
+ {
+ // DG TODO: What if obstacle is left + right and one is moving?
+ if(_obstacles[index+1]) { pR = pC; vObst[0] = _xVelocityOb[index + 1]; vMask[0] = 0; }
+ if(_obstacles[index-1]) { pL = pC; vObst[0] = _xVelocityOb[index - 1]; vMask[0] = 0; }
+ if(_obstacles[index+_xRes]) { pU = pC; vObst[1] = _yVelocityOb[index + _xRes]; vMask[1] = 0; }
+ if(_obstacles[index-_xRes]) { pD = pC; vObst[1] = _yVelocityOb[index - _xRes]; vMask[1] = 0; }
+ if(_obstacles[index+_slabSize]) { pT = pC; vObst[2] = _zVelocityOb[index + _slabSize]; vMask[2] = 0; }
+ if(_obstacles[index-_slabSize]) { pB = pC; vObst[2] = _zVelocityOb[index - _slabSize]; vMask[2] = 0; }
+
+ _xVelocity[index] -= 0.5f * (pR - pL) * invDx;
+ _yVelocity[index] -= 0.5f * (pU - pD) * invDx;
+ _zVelocity[index] -= 0.5f * (pT - pB) * invDx;
+
+ _xVelocity[index] = (vMask[0] * _xVelocity[index]) + vObst[0];
+ _yVelocity[index] = (vMask[1] * _yVelocity[index]) + vObst[1];
+ _zVelocity[index] = (vMask[2] * _zVelocity[index]) + vObst[2];
+ }
+ else
+ {
+ _xVelocity[index] = _xVelocityOb[index];
+ _yVelocity[index] = _yVelocityOb[index];
+ _zVelocity[index] = _zVelocityOb[index];
+ }
+ }
+
+ // setObstacleVelocity(0, _zRes);
+
+ // if (_pressure) delete[] _pressure;
+ if (_divergence) delete[] _divergence;
+}
+
+//////////////////////////////////////////////////////////////////////
+// calculate the obstacle velocity at boundary
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setObstacleVelocity(int zBegin, int zEnd)
+{
+
+ // completely TODO <-- who wrote this and what is here TODO? DG
+
+ const size_t index_ = _slabSize + _xRes + 1;
+
+ //int vIndex=_slabSize + _xRes + 1;
+
+ int bb=0;
+ int bt=0;
+
+ if (zBegin == 0) {bb = 1;}
+ if (zEnd == _zRes) {bt = 1;}
+
+ // tag remaining obstacle blocks
+ for (int z = zBegin + bb; z < zEnd - bt; z++)
+ {
+ size_t index = index_ +(z-1)*_slabSize;
+
+ for (int y = 1; y < _yRes - 1; y++, index += 2)
+ {
+ for (int x = 1; x < _xRes - 1; x++, index++)
+ {
+ if (!_obstacles[index])
+ {
+ // if(_obstacles[index+1]) xright = - _xVelocityOb[index];
+ if((_obstacles[index - 1] & 8) && abs(_xVelocityOb[index - 1]) > FLT_EPSILON )
+ {
+ // printf("velocity x!\n");
+ _xVelocity[index] = _xVelocityOb[index - 1];
+ _xVelocity[index - 1] = _xVelocityOb[index - 1];
+ }
+ // if(_obstacles[index+_xRes]) yup = - _yVelocityOb[index];
+ if((_obstacles[index - _xRes] & 8) && abs(_yVelocityOb[index - _xRes]) > FLT_EPSILON)
+ {
+ // printf("velocity y!\n");
+ _yVelocity[index] = _yVelocityOb[index - _xRes];
+ _yVelocity[index - _xRes] = _yVelocityOb[index - _xRes];
+ }
+ // if(_obstacles[index+_slabSize]) ztop = - _zVelocityOb[index];
+ if((_obstacles[index - _slabSize] & 8) && abs(_zVelocityOb[index - _slabSize]) > FLT_EPSILON)
+ {
+ // printf("velocity z!\n");
+ _zVelocity[index] = _zVelocityOb[index - _slabSize];
+ _zVelocity[index - _slabSize] = _zVelocityOb[index - _slabSize];
+ }
+ }
+ else
+ {
+ _density[index] = 0;
+ }
+ //vIndex++;
+ } // x loop
+ //vIndex += 2;
+ } // y loop
+ //vIndex += 2 * _xRes;
+ } // z loop
+}
+
+//////////////////////////////////////////////////////////////////////
+// diffuse heat
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::diffuseHeat()
+{
+ SWAP_POINTERS(_heat, _heatOld);
+
+ copyBorderAll(_heatOld, 0, _zRes);
+ solveHeat(_heat, _heatOld, _obstacles);
+
+ // zero out inside obstacles
+ for (int x = 0; x < _totalCells; x++)
+ if (_obstacles[x])
+ _heat[x] = 0.0f;
+
+}
+
+//////////////////////////////////////////////////////////////////////
+// stamp an obstacle in the _obstacles field
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::addObstacle(OBSTACLE* obstacle)
+{
+ int index = 0;
+ for (int z = 0; z < _zRes; z++)
+ for (int y = 0; y < _yRes; y++)
+ for (int x = 0; x < _xRes; x++, index++)
+ if (obstacle->inside(x * _dx, y * _dx, z * _dx)) {
+ _obstacles[index] = true;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// calculate the obstacle directional types
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setObstaclePressure(float *_pressure, int zBegin, int zEnd)
+{
+
+ // completely TODO <-- who wrote this and what is here TODO? DG
+
+ const size_t index_ = _slabSize + _xRes + 1;
+
+ //int vIndex=_slabSize + _xRes + 1;
+
+ int bb=0;
+ int bt=0;
+
+ if (zBegin == 0) {bb = 1;}
+ if (zEnd == _zRes) {bt = 1;}
+
+ // tag remaining obstacle blocks
+ for (int z = zBegin + bb; z < zEnd - bt; z++)
+ {
+ size_t index = index_ +(z-1)*_slabSize;
+
+ for (int y = 1; y < _yRes - 1; y++, index += 2)
+ {
+ for (int x = 1; x < _xRes - 1; x++, index++)
+ {
+ // could do cascade of ifs, but they are a pain
+ if (_obstacles[index] /* && !(_obstacles[index] & 8) DG TODO TEST THIS CONDITION */)
+ {
+ const int top = _obstacles[index + _slabSize];
+ const int bottom= _obstacles[index - _slabSize];
+ const int up = _obstacles[index + _xRes];
+ const int down = _obstacles[index - _xRes];
+ const int left = _obstacles[index - 1];
+ const int right = _obstacles[index + 1];
+
+ // unused
+ // const bool fullz = (top && bottom);
+ // const bool fully = (up && down);
+ //const bool fullx = (left && right);
+
+ /*
+ _xVelocity[index] =
+ _yVelocity[index] =
+ _zVelocity[index] = 0.0f;
+ */
+ _pressure[index] = 0.0f;
+
+ // average pressure neighbors
+ float pcnt = 0.;
+ if (left && !right) {
+ _pressure[index] += _pressure[index + 1];
+ pcnt += 1.;
+ }
+ if (!left && right) {
+ _pressure[index] += _pressure[index - 1];
+ pcnt += 1.;
+ }
+ if (up && !down) {
+ _pressure[index] += _pressure[index - _xRes];
+ pcnt += 1.;
+ }
+ if (!up && down) {
+ _pressure[index] += _pressure[index + _xRes];
+ pcnt += 1.;
+ }
+ if (top && !bottom) {
+ _pressure[index] += _pressure[index - _slabSize];
+ pcnt += 1.;
+ }
+ if (!top && bottom) {
+ _pressure[index] += _pressure[index + _slabSize];
+ pcnt += 1.;
+ }
+
+ if(pcnt > 0.000001f)
+ _pressure[index] /= pcnt;
+
+ // TODO? set correct velocity bc's
+ // velocities are only set to zero right now
+ // this means it's not a full no-slip boundary condition
+ // but a "half-slip" - still looks ok right now
+ }
+ //vIndex++;
+ } // x loop
+ //vIndex += 2;
+ } // y loop
+ //vIndex += 2 * _xRes;
+ } // z loop
+}
+
+void FLUID_3D::setObstacleBoundaries(float *_pressure, int zBegin, int zEnd)
+{
+ // cull degenerate obstacles , move to addObstacle?
+
+ // r = b - Ax
+ const size_t index_ = _slabSize + _xRes + 1;
+
+ int bb=0;
+ int bt=0;
+
+ if (zBegin == 0) {bb = 1;}
+ if (zEnd == _zRes) {bt = 1;}
+
+ for (int z = zBegin + bb; z < zEnd - bt; z++)
+ {
+ size_t index = index_ +(z-1)*_slabSize;
+
+ for (int y = 1; y < _yRes - 1; y++, index += 2)
+ {
+ for (int x = 1; x < _xRes - 1; x++, index++)
+ {
+ if (_obstacles[index] != EMPTY)
+ {
+ const int top = _obstacles[index + _slabSize];
+ const int bottom= _obstacles[index - _slabSize];
+ const int up = _obstacles[index + _xRes];
+ const int down = _obstacles[index - _xRes];
+ const int left = _obstacles[index - 1];
+ const int right = _obstacles[index + 1];
+
+ int counter = 0;
+ if (up) counter++;
+ if (down) counter++;
+ if (left) counter++;
+ if (right) counter++;
+ if (top) counter++;
+ if (bottom) counter++;
+
+ // DG TODO: Do not shrink obstacles for now
+ // if (counter < 3)
+ // _obstacles[index] = EMPTY;
+ }
+ if (_obstacles[index])
+ {
+ _xVelocity[index] =
+ _yVelocity[index] =
+ _zVelocity[index] = 0.0f;
+ _pressure[index] = 0.0f;
+ }
+ //vIndex++;
+ } // x-loop
+ //vIndex += 2;
+ } // y-loop
+ //vIndex += 2* _xRes;
+ } // z-loop
+}
+
+//////////////////////////////////////////////////////////////////////
+// add buoyancy forces
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::addBuoyancy(float *heat, float *density, int zBegin, int zEnd)
+{
+ int index = zBegin*_slabSize;
+
+ for (int z = zBegin; z < zEnd; z++)
+ for (int y = 0; y < _yRes; y++)
+ for (int x = 0; x < _xRes; x++, index++)
+ {
+ _zForce[index] += *_alpha * density[index] + (*_beta * (heat[index] - _tempAmb)); // DG: was _yForce, changed for Blender
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// add vorticity to the force field
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::addVorticity(int zBegin, int zEnd)
+{
+ //int x,y,z,index;
+ if(_vorticityEps<=0.) return;
+
+ int _blockSize=zEnd-zBegin;
+ int _blockTotalCells = _slabSize * (_blockSize+2);
+
+ float *_xVorticity, *_yVorticity, *_zVorticity, *_vorticity;
+
+ int bb=0;
+ int bt=0;
+ int bb1=-1;
+ int bt1=-1;
+
+ if (zBegin == 0) {bb1 = 1; bb = 1; _blockTotalCells-=_blockSize;}
+ if (zEnd == _zRes) {bt1 = 1;bt = 1; _blockTotalCells-=_blockSize;}
+
+ _xVorticity = new float[_blockTotalCells];
+ _yVorticity = new float[_blockTotalCells];
+ _zVorticity = new float[_blockTotalCells];
+ _vorticity = new float[_blockTotalCells];
+
+ memset(_xVorticity, 0, sizeof(float)*_blockTotalCells);
+ memset(_yVorticity, 0, sizeof(float)*_blockTotalCells);
+ memset(_zVorticity, 0, sizeof(float)*_blockTotalCells);
+ memset(_vorticity, 0, sizeof(float)*_blockTotalCells);
+
+ //const size_t indexsetupV=_slabSize;
+ const size_t index_ = _slabSize + _xRes + 1;
+
+ // calculate vorticity
+ float gridSize = 0.5f / _dx;
+ //index = _slabSize + _xRes + 1;
+
+
+ size_t vIndex=_xRes + 1;
+
+ for (int z = zBegin + bb1; z < (zEnd - bt1); z++)
+ {
+ size_t index = index_ +(z-1)*_slabSize;
+ vIndex = index-(zBegin-1+bb)*_slabSize;
+
+ for (int y = 1; y < _yRes - 1; y++, index += 2)
+ {
+ for (int x = 1; x < _xRes - 1; x++, index++)
+ {
+
+ int up = _obstacles[index + _xRes] ? index : index + _xRes;
+ int down = _obstacles[index - _xRes] ? index : index - _xRes;
+ float dy = (up == index || down == index) ? 1.0f / _dx : gridSize;
+ int out = _obstacles[index + _slabSize] ? index : index + _slabSize;
+ int in = _obstacles[index - _slabSize] ? index : index - _slabSize;
+ float dz = (out == index || in == index) ? 1.0f / _dx : gridSize;
+ int right = _obstacles[index + 1] ? index : index + 1;
+ int left = _obstacles[index - 1] ? index : index - 1;
+ float dx = (right == index || left == index) ? 1.0f / _dx : gridSize;
+
+ _xVorticity[vIndex] = (_zVelocity[up] - _zVelocity[down]) * dy + (-_yVelocity[out] + _yVelocity[in]) * dz;
+ _yVorticity[vIndex] = (_xVelocity[out] - _xVelocity[in]) * dz + (-_zVelocity[right] + _zVelocity[left]) * dx;
+ _zVorticity[vIndex] = (_yVelocity[right] - _yVelocity[left]) * dx + (-_xVelocity[up] + _xVelocity[down])* dy;
+
+ _vorticity[vIndex] = sqrtf(_xVorticity[vIndex] * _xVorticity[vIndex] +
+ _yVorticity[vIndex] * _yVorticity[vIndex] +
+ _zVorticity[vIndex] * _zVorticity[vIndex]);
+
+ vIndex++;
+ }
+ vIndex+=2;
+ }
+ //vIndex+=2*_xRes;
+ }
+
+ // calculate normalized vorticity vectors
+ float eps = _vorticityEps;
+
+ //index = _slabSize + _xRes + 1;
+ vIndex=_slabSize + _xRes + 1;
+
+ for (int z = zBegin + bb; z < (zEnd - bt); z++)
+ {
+ size_t index = index_ +(z-1)*_slabSize;
+ vIndex = index-(zBegin-1+bb)*_slabSize;
+
+ for (int y = 1; y < _yRes - 1; y++, index += 2)
+ {
+ for (int x = 1; x < _xRes - 1; x++, index++)
+ {
+ //
+
+ if (!_obstacles[index])
+ {
+ float N[3];
+
+ int up = _obstacles[index + _xRes] ? vIndex : vIndex + _xRes;
+ int down = _obstacles[index - _xRes] ? vIndex : vIndex - _xRes;
+ float dy = (up == vIndex || down == vIndex) ? 1.0f / _dx : gridSize;
+ int out = _obstacles[index + _slabSize] ? vIndex : vIndex + _slabSize;
+ int in = _obstacles[index - _slabSize] ? vIndex : vIndex - _slabSize;
+ float dz = (out == vIndex || in == vIndex) ? 1.0f / _dx : gridSize;
+ int right = _obstacles[index + 1] ? vIndex : vIndex + 1;
+ int left = _obstacles[index - 1] ? vIndex : vIndex - 1;
+ float dx = (right == vIndex || left == vIndex) ? 1.0f / _dx : gridSize;
+ N[0] = (_vorticity[right] - _vorticity[left]) * dx;
+ N[1] = (_vorticity[up] - _vorticity[down]) * dy;
+ N[2] = (_vorticity[out] - _vorticity[in]) * dz;
+
+ float magnitude = sqrtf(N[0] * N[0] + N[1] * N[1] + N[2] * N[2]);
+ if (magnitude > 0.0f)
+ {
+ magnitude = 1.0f / magnitude;
+ N[0] *= magnitude;
+ N[1] *= magnitude;
+ N[2] *= magnitude;
+
+ _xForce[index] += (N[1] * _zVorticity[vIndex] - N[2] * _yVorticity[vIndex]) * _dx * eps;
+ _yForce[index] -= (N[0] * _zVorticity[vIndex] - N[2] * _xVorticity[vIndex]) * _dx * eps;
+ _zForce[index] += (N[0] * _yVorticity[vIndex] - N[1] * _xVorticity[vIndex]) * _dx * eps;
+ }
+ } // if
+ vIndex++;
+ } // x loop
+ vIndex+=2;
+ } // y loop
+ //vIndex+=2*_xRes;
+ } // z loop
+
+ if (_xVorticity) delete[] _xVorticity;
+ if (_yVorticity) delete[] _yVorticity;
+ if (_zVorticity) delete[] _zVorticity;
+ if (_vorticity) delete[] _vorticity;
+}
+
+
+void FLUID_3D::advectMacCormackBegin(int zBegin, int zEnd)
+{
+ Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
+
+ if(_domainBcLeft == 0) copyBorderX(_xVelocityOld, res, zBegin, zEnd);
+ else setZeroX(_xVelocityOld, res, zBegin, zEnd);
+
+ if(_domainBcFront == 0) copyBorderY(_yVelocityOld, res, zBegin, zEnd);
+ else setZeroY(_yVelocityOld, res, zBegin, zEnd);
+
+ if(_domainBcTop == 0) copyBorderZ(_zVelocityOld, res, zBegin, zEnd);
+ else setZeroZ(_zVelocityOld, res, zBegin, zEnd);
+}
+
+//////////////////////////////////////////////////////////////////////
+// Advect using the MacCormack method from the Selle paper
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::advectMacCormackEnd1(int zBegin, int zEnd)
+{
+ Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
+
+ const float dt0 = _dt / _dx;
+
+ int begin=zBegin * _slabSize;
+ int end=begin + (zEnd - zBegin) * _slabSize;
+ for (int x = begin; x < end; x++)
+ _xForce[x] = 0.0;
+
+ // advectFieldMacCormack1(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res)
+
+ advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _densityTemp, res, zBegin, zEnd);
+ advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heatTemp, res, zBegin, zEnd);
+ advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocity, res, zBegin, zEnd);
+ advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocity, res, zBegin, zEnd);
+ advectFieldMacCormack1(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocity, res, zBegin, zEnd);
+
+ // Have to wait untill all the threads are done -> so continuing in step 3
+}
+
+//////////////////////////////////////////////////////////////////////
+// Advect using the MacCormack method from the Selle paper
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::advectMacCormackEnd2(int zBegin, int zEnd)
+{
+ const float dt0 = _dt / _dx;
+ Vec3Int res = Vec3Int(_xRes,_yRes,_zRes);
+
+ // use force array as temp arrays
+ float* t1 = _xForce;
+
+ // advectFieldMacCormack2(dt, xVelocity, yVelocity, zVelocity, oldField, newField, tempfield, temp, res, obstacles)
+
+ advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _densityOld, _density, _densityTemp, t1, res, _obstacles, zBegin, zEnd);
+ advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _heatOld, _heat, _heatTemp, t1, res, _obstacles, zBegin, zEnd);
+ advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _xVelocityOld, _xVelocityTemp, _xVelocity, t1, res, _obstacles, zBegin, zEnd);
+ advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _yVelocityOld, _yVelocityTemp, _yVelocity, t1, res, _obstacles, zBegin, zEnd);
+ advectFieldMacCormack2(dt0, _xVelocityOld, _yVelocityOld, _zVelocityOld, _zVelocityOld, _zVelocityTemp, _zVelocity, t1, res, _obstacles, zBegin, zEnd);
+
+ if(_domainBcLeft == 0) copyBorderX(_xVelocityTemp, res, zBegin, zEnd);
+ else setZeroX(_xVelocityTemp, res, zBegin, zEnd);
+
+ if(_domainBcFront == 0) copyBorderY(_yVelocityTemp, res, zBegin, zEnd);
+ else setZeroY(_yVelocityTemp, res, zBegin, zEnd);
+
+ if(_domainBcTop == 0) copyBorderZ(_zVelocityTemp, res, zBegin, zEnd);
+ else setZeroZ(_zVelocityTemp, res, zBegin, zEnd);
+
+ setZeroBorder(_density, res, zBegin, zEnd);
+ setZeroBorder(_heat, res, zBegin, zEnd);
+#if 0
+ {
+ const size_t index_ = _slabSize + _xRes + 1;
+ int bb=0;
+ int bt=0;
+
+ if (zBegin == 0) {bb = 1;}
+ if (zEnd == _zRes) {bt = 1;}
+
+ for (int z = zBegin + bb; z < zEnd - bt; z++)
+ {
+ size_t index = index_ +(z-1)*_slabSize;
+
+ for (int y = 1; y < _yRes - 1; y++, index += 2)
+ {
+ for (int x = 1; x < _xRes - 1; x++, index++)
+ {
+ // clean custom velocities from moving obstacles again
+ if (_obstacles[index])
+ {
+ _xVelocity[index] =
+ _yVelocity[index] =
+ _zVelocity[index] = 0.0f;
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ /*int begin=zBegin * _slabSize;
+ int end=begin + (zEnd - zBegin) * _slabSize;
+ for (int x = begin; x < end; x++)
+ _xForce[x] = _yForce[x] = 0.0f;*/
+}
diff --git a/intern/smoke/intern/FLUID_3D.h b/intern/smoke/intern/FLUID_3D.h
new file mode 100644
index 00000000000..0e7863df6c6
--- /dev/null
+++ b/intern/smoke/intern/FLUID_3D.h
@@ -0,0 +1,231 @@
+/** \file smoke/intern/FLUID_3D.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// FLUID_3D.h: interface for the FLUID_3D class.
+//
+//////////////////////////////////////////////////////////////////////
+// Heavy parallel optimization done. Many of the old functions now
+// take begin and end parameters and process only specified part of the data.
+// Some functions were divided into multiple ones.
+// - MiikaH
+//////////////////////////////////////////////////////////////////////
+
+#ifndef FLUID_3D_H
+#define FLUID_3D_H
+
+#include <cstdlib>
+#include <cmath>
+#include <cstring>
+#include <iostream>
+#include "OBSTACLE.h"
+// #include "WTURBULENCE.h"
+#include "VEC3.h"
+
+using namespace std;
+using namespace BasicVector;
+class WTURBULENCE;
+
+class FLUID_3D
+{
+ public:
+ FLUID_3D(int *res, /* int amplify, */ float *p0, float dtdef);
+ FLUID_3D() {};
+ virtual ~FLUID_3D();
+
+ void initBlenderRNA(float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli);
+
+ // create & allocate vector noise advection
+ void initVectorNoise(int amplify);
+
+ void addSmokeColumn();
+ static void addSmokeTestCase(float* field, Vec3Int res);
+
+ void step(float dt);
+ void addObstacle(OBSTACLE* obstacle);
+
+ const float* xVelocity() { return _xVelocity; };
+ const float* yVelocity() { return _yVelocity; };
+ const float* zVelocity() { return _zVelocity; };
+
+ int xRes() const { return _xRes; };
+ int yRes() const { return _yRes; };
+ int zRes() const { return _zRes; };
+
+ public:
+ // dimensions
+ int _xRes, _yRes, _zRes, _maxRes;
+ Vec3Int _res;
+ size_t _totalCells;
+ int _slabSize;
+ float _dx;
+ float _p0[3];
+ float _p1[3];
+ float _totalTime;
+ int _totalSteps;
+ int _totalImgDumps;
+ int _totalVelDumps;
+
+ void artificialDampingSL(int zBegin, int zEnd);
+ void artificialDampingExactSL(int pos);
+
+ void setBorderObstacles();
+
+ // fields
+ float* _density;
+ float* _densityOld;
+ float* _heat;
+ float* _heatOld;
+ float* _xVelocity;
+ float* _yVelocity;
+ float* _zVelocity;
+ float* _xVelocityOb;
+ float* _yVelocityOb;
+ float* _zVelocityOb;
+ float* _xVelocityOld;
+ float* _yVelocityOld;
+ float* _zVelocityOld;
+ float* _xForce;
+ float* _yForce;
+ float* _zForce;
+ unsigned char* _obstacles; /* only used (usefull) for static obstacles like domain boundaries */
+ unsigned char* _obstaclesAnim;
+
+ // for debug purposes
+ float *_pressure;
+
+ // Required for proper threading:
+ float* _xVelocityTemp;
+ float* _yVelocityTemp;
+ float* _zVelocityTemp;
+ float* _heatTemp;
+ float* _densityTemp;
+
+ // CG fields
+ int _iterations;
+
+ // simulation constants
+ float _dt;
+ float *_dtFactor;
+ float _vorticityEps;
+ float _heatDiffusion;
+ float *_vorticityRNA; // RNA-pointer.
+ float *_alpha; // for the buoyancy density term <-- as pointer to get blender RNA in here
+ float *_beta; // was _buoyancy <-- as pointer to get blender RNA in here
+ float _tempAmb; /* ambient temperature */
+ float _constantScaling;
+
+ bool _domainBcFront; // z
+ bool _domainBcTop; // y
+ bool _domainBcLeft; // x
+ bool _domainBcBack; // DOMAIN_BC_FRONT
+ bool _domainBcBottom; // DOMAIN_BC_TOP
+ bool _domainBcRight; // DOMAIN_BC_LEFT
+ int *_borderColli; // border collision rules <-- as pointer to get blender RNA in here
+ int _colloPrev; // To track whether value has been changed (to not
+ // have to recalibrate borders if nothing has changed
+ void setBorderCollisions();
+
+ void setObstacleVelocity(int zBegin, int zEnd);
+
+ // WTURBULENCE object, if active
+ // WTURBULENCE* _wTurbulence;
+
+ // boundary setting functions
+ void copyBorderAll(float* field, int zBegin, int zEnd);
+
+ // timestepping functions
+ void wipeBoundaries(int zBegin, int zEnd);
+ void wipeBoundariesSL(int zBegin, int zEnd);
+ void addForce(int zBegin, int zEnd);
+ void addVorticity(int zBegin, int zEnd);
+ void addBuoyancy(float *heat, float *density, int zBegin, int zEnd);
+
+ // solver stuff
+ void project();
+ void diffuseHeat();
+ void solvePressure(float* field, float* b, unsigned char* skip);
+
+ void solvePressurePre(float* field, float* b, unsigned char* skip);
+ void solvePressureJacobian(float* p, float* d, unsigned char* ob);
+
+ void solveHeat(float* field, float* b, unsigned char* skip);
+
+
+ // handle obstacle boundaries
+ void setObstacleBoundaries(float *_pressure, int zBegin, int zEnd);
+ void setObstaclePressure(float *_pressure, int zBegin, int zEnd);
+
+ public:
+ // advection, accessed e.g. by WTURBULENCE class
+ //void advectMacCormack();
+ void advectMacCormackBegin(int zBegin, int zEnd);
+ void advectMacCormackEnd1(int zBegin, int zEnd);
+ void advectMacCormackEnd2(int zBegin, int zEnd);
+
+ // boundary setting functions
+ static void copyBorderX(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void copyBorderY(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void copyBorderZ(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void setNeumannX(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void setNeumannY(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void setZeroX(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void setZeroY(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void setZeroZ(float* field, Vec3Int res, int zBegin, int zEnd);
+ static void setZeroBorder(float* field, Vec3Int res, int zBegin, int zEnd) {
+ setZeroX(field, res, zBegin, zEnd);
+ setZeroY(field, res, zBegin, zEnd);
+ setZeroZ(field, res, zBegin, zEnd);
+ };
+
+
+
+ // static advection functions, also used by WTURBULENCE
+ static void advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz,
+ float* oldField, float* newField, Vec3Int res, int zBegin, int zEnd);
+ static void advectFieldMacCormack1(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
+ float* oldField, float* tempResult, Vec3Int res, int zBegin, int zEnd);
+ static void advectFieldMacCormack2(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
+ float* oldField, float* newField, float* tempResult, float* temp1,Vec3Int res, const unsigned char* obstacles, int zBegin, int zEnd);
+
+
+ // temp ones for testing
+ /*static void advectFieldMacCormack(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
+ float* oldField, float* newField, float* temp1, float* temp2, Vec3Int res, const unsigned char* obstacles);*/
+ /*static void advectFieldSemiLagrange2(const float dt, const float* velx, const float* vely, const float* velz,
+ float* oldField, float* newField, Vec3Int res);*/
+
+ // maccormack helper functions
+ static void clampExtrema(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
+ float* oldField, float* newField, Vec3Int res, int zBegin, int zEnd);
+ static void clampOutsideRays(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
+ float* oldField, float* newField, Vec3Int res, const unsigned char* obstacles, const float *oldAdvection, int zBegin, int zEnd);
+
+
+
+ // output helper functions
+ // static void writeImageSliceXY(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.);
+ // static void writeImageSliceYZ(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.);
+ // static void writeImageSliceXZ(const float *field, Vec3Int res, int slice, string prefix, int picCnt, float scale=1.);
+ // static void writeProjectedIntern(const float *field, Vec3Int res, int dir1, int dir2, string prefix, int picCnt, float scale=1.);
+};
+
+#endif
diff --git a/intern/smoke/intern/FLUID_3D_SOLVERS.cpp b/intern/smoke/intern/FLUID_3D_SOLVERS.cpp
new file mode 100644
index 00000000000..eaadccf566e
--- /dev/null
+++ b/intern/smoke/intern/FLUID_3D_SOLVERS.cpp
@@ -0,0 +1,389 @@
+/** \file smoke/intern/FLUID_3D_SOLVERS.cpp
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// FLUID_3D.cpp: implementation of the FLUID_3D class.
+//
+//////////////////////////////////////////////////////////////////////
+// Both solvers optimized by merging loops and precalculating
+// stuff used in iteration loop.
+// - MiikaH
+//////////////////////////////////////////////////////////////////////
+
+#include "FLUID_3D.h"
+#include <cstring>
+#define SOLVER_ACCURACY 1e-06
+
+//////////////////////////////////////////////////////////////////////
+// solve the heat equation with CG
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::solveHeat(float* field, float* b, unsigned char* skip)
+{
+ int x, y, z;
+ const int twoxr = 2 * _xRes;
+ size_t index;
+ const float heatConst = _dt * _heatDiffusion / (_dx * _dx);
+ float *_q, *_residual, *_direction, *_Acenter;
+
+ // i = 0
+ int i = 0;
+
+ _residual = new float[_totalCells]; // set 0
+ _direction = new float[_totalCells]; // set 0
+ _q = new float[_totalCells]; // set 0
+ _Acenter = new float[_totalCells]; // set 0
+
+ memset(_residual, 0, sizeof(float)*_totalCells);
+ memset(_q, 0, sizeof(float)*_totalCells);
+ memset(_direction, 0, sizeof(float)*_totalCells);
+ memset(_Acenter, 0, sizeof(float)*_totalCells);
+
+ float deltaNew = 0.0f;
+
+ // r = b - Ax
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += twoxr)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+ // if the cell is a variable
+ _Acenter[index] = 1.0f;
+ if (!skip[index])
+ {
+ // set the matrix to the Poisson stencil in order
+ if (!skip[index + 1]) _Acenter[index] += heatConst;
+ if (!skip[index - 1]) _Acenter[index] += heatConst;
+ if (!skip[index + _xRes]) _Acenter[index] += heatConst;
+ if (!skip[index - _xRes]) _Acenter[index] += heatConst;
+ if (!skip[index + _slabSize]) _Acenter[index] += heatConst;
+ if (!skip[index - _slabSize]) _Acenter[index] += heatConst;
+
+ _residual[index] = b[index] - (_Acenter[index] * field[index] +
+ field[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) +
+ field[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) +
+ field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) +
+ field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) +
+ field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) +
+ field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst));
+ }
+ else
+ {
+ _residual[index] = 0.0f;
+ }
+
+ _direction[index] = _residual[index];
+ deltaNew += _residual[index] * _residual[index];
+ }
+
+
+ // While deltaNew > (eps^2) * delta0
+ const float eps = SOLVER_ACCURACY;
+ float maxR = 2.0f * eps;
+ while ((i < _iterations) && (maxR > eps))
+ {
+ // q = Ad
+ float alpha = 0.0f;
+
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += twoxr)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+ // if the cell is a variable
+ if (!skip[index])
+ {
+
+ _q[index] = (_Acenter[index] * _direction[index] +
+ _direction[index - 1] * (skip[index - 1] ? 0.0 : -heatConst) +
+ _direction[index + 1] * (skip[index + 1] ? 0.0 : -heatConst) +
+ _direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -heatConst) +
+ _direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -heatConst) +
+ _direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -heatConst) +
+ _direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -heatConst));
+ }
+ else
+ {
+ _q[index] = 0.0f;
+ }
+ alpha += _direction[index] * _q[index];
+ }
+
+ if (fabs(alpha) > 0.0f)
+ alpha = deltaNew / alpha;
+
+ float deltaOld = deltaNew;
+ deltaNew = 0.0f;
+
+ maxR = 0.0f;
+
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += twoxr)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+ field[index] += alpha * _direction[index];
+
+ _residual[index] -= alpha * _q[index];
+ maxR = (_residual[index] > maxR) ? _residual[index] : maxR;
+
+ deltaNew += _residual[index] * _residual[index];
+ }
+
+ float beta = deltaNew / deltaOld;
+
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += twoxr)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ _direction[index] = _residual[index] + beta * _direction[index];
+
+
+ i++;
+ }
+ // cout << i << " iterations converged to " << maxR << endl;
+
+ if (_residual) delete[] _residual;
+ if (_direction) delete[] _direction;
+ if (_q) delete[] _q;
+ if (_Acenter) delete[] _Acenter;
+}
+
+
+void FLUID_3D::solvePressurePre(float* field, float* b, unsigned char* skip)
+{
+ int x, y, z;
+ size_t index;
+ float *_q, *_Precond, *_h, *_residual, *_direction;
+
+ // i = 0
+ int i = 0;
+
+ _residual = new float[_totalCells]; // set 0
+ _direction = new float[_totalCells]; // set 0
+ _q = new float[_totalCells]; // set 0
+ _h = new float[_totalCells]; // set 0
+ _Precond = new float[_totalCells]; // set 0
+
+ memset(_residual, 0, sizeof(float)*_xRes*_yRes*_zRes);
+ memset(_q, 0, sizeof(float)*_xRes*_yRes*_zRes);
+ memset(_direction, 0, sizeof(float)*_xRes*_yRes*_zRes);
+ memset(_h, 0, sizeof(float)*_xRes*_yRes*_zRes);
+ memset(_Precond, 0, sizeof(float)*_xRes*_yRes*_zRes);
+
+ float deltaNew = 0.0f;
+
+ // r = b - Ax
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+ // if the cell is a variable
+ float Acenter = 0.0f;
+ if (!skip[index])
+ {
+ // set the matrix to the Poisson stencil in order
+ if (!skip[index + 1]) Acenter += 1.;
+ if (!skip[index - 1]) Acenter += 1.;
+ if (!skip[index + _xRes]) Acenter += 1.;
+ if (!skip[index - _xRes]) Acenter += 1.;
+ if (!skip[index + _slabSize]) Acenter += 1.;
+ if (!skip[index - _slabSize]) Acenter += 1.;
+
+ _residual[index] = b[index] - (Acenter * field[index] +
+ field[index - 1] * (skip[index - 1] ? 0.0 : -1.0f)+
+ field[index + 1] * (skip[index + 1] ? 0.0 : -1.0f)+
+ field[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f)+
+ field[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
+ field[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f)+
+ field[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f) );
+ }
+ else
+ {
+ _residual[index] = 0.0f;
+ }
+
+ // P^-1
+ if(Acenter < 1.0)
+ _Precond[index] = 0.0;
+ else
+ _Precond[index] = 1.0 / Acenter;
+
+ // p = P^-1 * r
+ _direction[index] = _residual[index] * _Precond[index];
+
+ deltaNew += _residual[index] * _direction[index];
+ }
+
+
+ // While deltaNew > (eps^2) * delta0
+ const float eps = SOLVER_ACCURACY;
+ //while ((i < _iterations) && (deltaNew > eps*delta0))
+ float maxR = 2.0f * eps;
+ // while (i < _iterations)
+ while ((i < _iterations) && (maxR > 0.001*eps))
+ {
+
+ float alpha = 0.0f;
+
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+ // if the cell is a variable
+ float Acenter = 0.0f;
+ if (!skip[index])
+ {
+ // set the matrix to the Poisson stencil in order
+ if (!skip[index + 1]) Acenter += 1.;
+ if (!skip[index - 1]) Acenter += 1.;
+ if (!skip[index + _xRes]) Acenter += 1.;
+ if (!skip[index - _xRes]) Acenter += 1.;
+ if (!skip[index + _slabSize]) Acenter += 1.;
+ if (!skip[index - _slabSize]) Acenter += 1.;
+
+ _q[index] = Acenter * _direction[index] +
+ _direction[index - 1] * (skip[index - 1] ? 0.0 : -1.0f) +
+ _direction[index + 1] * (skip[index + 1] ? 0.0 : -1.0f) +
+ _direction[index - _xRes] * (skip[index - _xRes] ? 0.0 : -1.0f) +
+ _direction[index + _xRes] * (skip[index + _xRes] ? 0.0 : -1.0f)+
+ _direction[index - _slabSize] * (skip[index - _slabSize] ? 0.0 : -1.0f) +
+ _direction[index + _slabSize] * (skip[index + _slabSize] ? 0.0 : -1.0f);
+ }
+ else
+ {
+ _q[index] = 0.0f;
+ }
+
+ alpha += _direction[index] * _q[index];
+ }
+
+
+ if (fabs(alpha) > 0.0f)
+ alpha = deltaNew / alpha;
+
+ float deltaOld = deltaNew;
+ deltaNew = 0.0f;
+
+ maxR = 0.0;
+
+ float tmp;
+
+ // x = x + alpha * d
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+ field[index] += alpha * _direction[index];
+
+ _residual[index] -= alpha * _q[index];
+
+ _h[index] = _Precond[index] * _residual[index];
+
+ tmp = _residual[index] * _h[index];
+ deltaNew += tmp;
+ maxR = (tmp > maxR) ? tmp : maxR;
+
+ }
+
+
+ // beta = deltaNew / deltaOld
+ float beta = deltaNew / deltaOld;
+
+ // d = h + beta * d
+ index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ _direction[index] = _h[index] + beta * _direction[index];
+
+ // i = i + 1
+ i++;
+ }
+ // cout << i << " iterations converged to " << sqrt(maxR) << endl;
+
+ if (_h) delete[] _h;
+ if (_Precond) delete[] _Precond;
+ if (_residual) delete[] _residual;
+ if (_direction) delete[] _direction;
+ if (_q) delete[] _q;
+}
+#if 0
+void FLUID_3D::solvePressureJacobian(float* p, float* d, unsigned char* ob)
+{
+ float *_tmp = new float[_totalCells];
+ unsigned int x, y, z;
+
+ float maxdp = 0.0f;
+
+ do
+ {
+ maxdp = 0.0f;
+
+ size_t index = _slabSize + _xRes + 1;
+ for (z = 1; z < _zRes - 1; z++, index += 2 * _xRes)
+ for (y = 1; y < _yRes - 1; y++, index += 2)
+ for (x = 1; x < _xRes - 1; x++, index++)
+ {
+ float dC = d[index];
+ float pC = p[index]; // center
+
+ float pR = p[index + 1]; // right
+ float pL = p[index - 1]; // left
+ float pT = p[index + _slabSize]; // top
+ float pB = p[index - _slabSize]; // bottom
+ float pU = p[index + _xRes]; // Up
+ float pD = p[index - _xRes]; // Down
+
+ if(ob[index + 1]) pR = pC;
+ if(ob[index - 1]) pL = pC;
+ if(ob[index + _slabSize]) pT = pC;
+ if(ob[index - _slabSize]) pB = pC;
+ if(ob[index + _xRes]) pU = pC;
+ if(ob[index - _xRes]) pD = pC;
+
+ _tmp[index] = (pR + pL + pT + pB + pU + pD + dC) / 6.0f;
+
+ if(ob[index])
+ _tmp[index] = 0;
+ }
+
+ for(unsigned int i = 0; i < _totalCells; i++)
+ {
+ float dp = _tmp[i] - p[i];
+
+ if(dp < 0)
+ dp *= -1.0f;
+
+ if(dp > maxdp)
+ maxdp = dp;
+
+ p[i] = _tmp[i];
+ }
+ printf("maxdp: %f\n", maxdp);
+ } while(maxdp > SOLVER_ACCURACY);
+
+ printf("\n");
+
+ if (_tmp) delete[] _tmp;
+}
+#endif
diff --git a/intern/smoke/intern/FLUID_3D_STATIC.cpp b/intern/smoke/intern/FLUID_3D_STATIC.cpp
new file mode 100644
index 00000000000..85b3657dc92
--- /dev/null
+++ b/intern/smoke/intern/FLUID_3D_STATIC.cpp
@@ -0,0 +1,685 @@
+/** \file smoke/intern/FLUID_3D_STATIC.cpp
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// FLUID_3D.cpp: implementation of the static functions of the FLUID_3D class.
+//
+//////////////////////////////////////////////////////////////////////
+// Heavy parallel optimization done. Many of the old functions now
+// take begin and end parameters and process only specified part of the data.
+// Some functions were divided into multiple ones.
+// - MiikaH
+//////////////////////////////////////////////////////////////////////
+
+#include <zlib.h>
+#include "FLUID_3D.h"
+#include "IMAGE.h"
+#include "WTURBULENCE.h"
+#include "INTERPOLATE.h"
+
+//////////////////////////////////////////////////////////////////////
+// add a test cube of density to the center
+//////////////////////////////////////////////////////////////////////
+/*
+void FLUID_3D::addSmokeColumn() {
+ addSmokeTestCase(_density, _res, 1.0);
+ // addSmokeTestCase(_zVelocity, _res, 1.0);
+ addSmokeTestCase(_heat, _res, 1.0);
+ if (_wTurbulence) {
+ addSmokeTestCase(_wTurbulence->getDensityBig(), _wTurbulence->getResBig(), 1.0);
+ }
+}
+*/
+
+//////////////////////////////////////////////////////////////////////
+// generic static version, so that it can be applied to the
+// WTURBULENCE grid as well
+//////////////////////////////////////////////////////////////////////
+
+void FLUID_3D::addSmokeTestCase(float* field, Vec3Int res)
+{
+ const int slabSize = res[0]*res[1]; int maxRes = (int)MAX3V(res);
+ float dx = 1.0f / (float)maxRes;
+
+ float xTotal = dx * res[0];
+ float yTotal = dx * res[1];
+
+ float heighMin = 0.05;
+ float heighMax = 0.10;
+
+ for (int y = 0; y < res[2]; y++)
+ for (int z = (int)(heighMin*res[2]); z <= (int)(heighMax * res[2]); z++)
+ for (int x = 0; x < res[0]; x++) {
+ float xLength = x * dx - xTotal * 0.4f;
+ float yLength = y * dx - yTotal * 0.5f;
+ float radius = sqrtf(xLength * xLength + yLength * yLength);
+
+ if (radius < 0.075f * xTotal) {
+ int index = x + y * res[0] + z * slabSize;
+ field[index] = 1.0f;
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// set x direction to Neumann boundary conditions
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setNeumannX(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ int index;
+ for (int z = zBegin; z < zEnd; z++)
+ for (int y = 0; y < res[1]; y++)
+ {
+ // left slab
+ index = y * res[0] + z * slabSize;
+ field[index] = field[index + 2];
+
+ // right slab
+ index += res[0] - 1;
+ field[index] = field[index - 2];
+ }
+
+ // fix, force top slab to only allow outwards flux
+ for (int y = 0; y < res[1]; y++)
+ for (int z = zBegin; z < zEnd; z++)
+ {
+ // top slab
+ index = y * res[0] + z * slabSize;
+ index += res[0] - 1;
+ if(field[index]<0.) field[index] = 0.;
+ index -= 1;
+ if(field[index]<0.) field[index] = 0.;
+ }
+ }
+
+//////////////////////////////////////////////////////////////////////
+// set y direction to Neumann boundary conditions
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setNeumannY(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ int index;
+ for (int z = zBegin; z < zEnd; z++)
+ for (int x = 0; x < res[0]; x++)
+ {
+ // bottom slab
+ index = x + z * slabSize;
+ field[index] = field[index + 2 * res[0]];
+
+ // top slab
+ index += slabSize - res[0];
+ field[index] = field[index - 2 * res[0]];
+ }
+
+ // fix, force top slab to only allow outwards flux
+ for (int z = zBegin; z < zEnd; z++)
+ for (int x = 0; x < res[0]; x++)
+ {
+ // top slab
+ index = x + z * slabSize;
+ index += slabSize - res[0];
+ if(field[index]<0.) field[index] = 0.;
+ index -= res[0];
+ if(field[index]<0.) field[index] = 0.;
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////
+// set z direction to Neumann boundary conditions
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setNeumannZ(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ const int totalCells = res[0] * res[1] * res[2];
+ const int cellsslab = totalCells - slabSize;
+ int index;
+
+ index = 0;
+ if (zBegin == 0)
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+ // front slab
+ field[index] = field[index + 2 * slabSize];
+ }
+
+ if (zEnd == res[2])
+ {
+ index = 0;
+ int indexx = 0;
+
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+
+ // back slab
+ indexx = index + cellsslab;
+ field[indexx] = field[indexx - 2 * slabSize];
+ }
+
+
+ // fix, force top slab to only allow outwards flux
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++)
+ {
+ // top slab
+ index = x + y * res[0];
+ index += cellsslab;
+ if(field[index]<0.) field[index] = 0.;
+ index -= slabSize;
+ if(field[index]<0.) field[index] = 0.;
+ }
+
+ } // zEnd == res[2]
+
+}
+
+//////////////////////////////////////////////////////////////////////
+// set x direction to zero
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setZeroX(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ int index;
+ for (int z = zBegin; z < zEnd; z++)
+ for (int y = 0; y < res[1]; y++)
+ {
+ // left slab
+ index = y * res[0] + z * slabSize;
+ field[index] = 0.0f;
+
+ // right slab
+ index += res[0] - 1;
+ field[index] = 0.0f;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// set y direction to zero
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setZeroY(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ int index;
+ for (int z = zBegin; z < zEnd; z++)
+ for (int x = 0; x < res[0]; x++)
+ {
+ // bottom slab
+ index = x + z * slabSize;
+ field[index] = 0.0f;
+
+ // top slab
+ index += slabSize - res[0];
+ field[index] = 0.0f;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// set z direction to zero
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::setZeroZ(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ const int totalCells = res[0] * res[1] * res[2];
+
+ int index = 0;
+ if ((zBegin == 0))
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+ // front slab
+ field[index] = 0.0f;
+ }
+
+ if (zEnd == res[2])
+ {
+ index=0;
+ int indexx=0;
+ const int cellsslab = totalCells - slabSize;
+
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+
+ // back slab
+ indexx = index + cellsslab;
+ field[indexx] = 0.0f;
+ }
+ }
+ }
+//////////////////////////////////////////////////////////////////////
+// copy grid boundary
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::copyBorderX(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ int index;
+ for (int z = zBegin; z < zEnd; z++)
+ for (int y = 0; y < res[1]; y++)
+ {
+ // left slab
+ index = y * res[0] + z * slabSize;
+ field[index] = field[index + 1];
+
+ // right slab
+ index += res[0] - 1;
+ field[index] = field[index - 1];
+ }
+}
+void FLUID_3D::copyBorderY(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ //const int totalCells = res[0] * res[1] * res[2];
+ int index;
+ for (int z = zBegin; z < zEnd; z++)
+ for (int x = 0; x < res[0]; x++)
+ {
+ // bottom slab
+ index = x + z * slabSize;
+ field[index] = field[index + res[0]];
+ // top slab
+ index += slabSize - res[0];
+ field[index] = field[index - res[0]];
+ }
+}
+void FLUID_3D::copyBorderZ(float* field, Vec3Int res, int zBegin, int zEnd)
+{
+ const int slabSize = res[0] * res[1];
+ const int totalCells = res[0] * res[1] * res[2];
+ int index=0;
+
+ if ((zBegin == 0))
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+ field[index] = field[index + slabSize];
+ }
+
+ if ((zEnd == res[2]))
+ {
+
+ index=0;
+ int indexx=0;
+ const int cellsslab = totalCells - slabSize;
+
+ for (int y = 0; y < res[1]; y++)
+ for (int x = 0; x < res[0]; x++, index++)
+ {
+ // back slab
+ indexx = index + cellsslab;
+ field[indexx] = field[indexx - slabSize];
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////
+// advect field with the semi lagrangian method
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::advectFieldSemiLagrange(const float dt, const float* velx, const float* vely, const float* velz,
+ float* oldField, float* newField, Vec3Int res, int zBegin, int zEnd)
+{
+ const int xres = res[0];
+ const int yres = res[1];
+ const int zres = res[2];
+ const int slabSize = res[0] * res[1];
+
+
+ for (int z = zBegin; z < zEnd; z++)
+ for (int y = 0; y < yres; y++)
+ for (int x = 0; x < xres; x++)
+ {
+ const int index = x + y * xres + z * xres*yres;
+
+ // backtrace
+ float xTrace = x - dt * velx[index];
+ float yTrace = y - dt * vely[index];
+ float zTrace = z - dt * velz[index];
+
+ // clamp backtrace to grid boundaries
+ if (xTrace < 0.5) xTrace = 0.5;
+ if (xTrace > xres - 1.5) xTrace = xres - 1.5;
+ if (yTrace < 0.5) yTrace = 0.5;
+ if (yTrace > yres - 1.5) yTrace = yres - 1.5;
+ if (zTrace < 0.5) zTrace = 0.5;
+ if (zTrace > zres - 1.5) zTrace = zres - 1.5;
+
+ // locate neighbors to interpolate
+ const int x0 = (int)xTrace;
+ const int x1 = x0 + 1;
+ const int y0 = (int)yTrace;
+ const int y1 = y0 + 1;
+ const int z0 = (int)zTrace;
+ const int z1 = z0 + 1;
+
+ // get interpolation weights
+ const float s1 = xTrace - x0;
+ const float s0 = 1.0f - s1;
+ const float t1 = yTrace - y0;
+ const float t0 = 1.0f - t1;
+ const float u1 = zTrace - z0;
+ const float u0 = 1.0f - u1;
+
+ const int i000 = x0 + y0 * xres + z0 * slabSize;
+ const int i010 = x0 + y1 * xres + z0 * slabSize;
+ const int i100 = x1 + y0 * xres + z0 * slabSize;
+ const int i110 = x1 + y1 * xres + z0 * slabSize;
+ const int i001 = x0 + y0 * xres + z1 * slabSize;
+ const int i011 = x0 + y1 * xres + z1 * slabSize;
+ const int i101 = x1 + y0 * xres + z1 * slabSize;
+ const int i111 = x1 + y1 * xres + z1 * slabSize;
+
+ // interpolate
+ // (indices could be computed once)
+ newField[index] = u0 * (s0 * (t0 * oldField[i000] +
+ t1 * oldField[i010]) +
+ s1 * (t0 * oldField[i100] +
+ t1 * oldField[i110])) +
+ u1 * (s0 * (t0 * oldField[i001] +
+ t1 * oldField[i011]) +
+ s1 * (t0 * oldField[i101] +
+ t1 * oldField[i111]));
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// advect field with the maccormack method
+//
+// comments are the pseudocode from selle's paper
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::advectFieldMacCormack1(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
+ float* oldField, float* tempResult, Vec3Int res, int zBegin, int zEnd)
+{
+ /*const int sx= res[0];
+ const int sy= res[1];
+ const int sz= res[2];
+
+ for (int x = 0; x < sx * sy * sz; x++)
+ phiHatN[x] = phiHatN1[x] = oldField[x];*/ // not needed as all the values are written first
+
+ float*& phiN = oldField;
+ float*& phiN1 = tempResult;
+
+
+
+ // phiHatN1 = A(phiN)
+ advectFieldSemiLagrange( dt, xVelocity, yVelocity, zVelocity, phiN, phiN1, res, zBegin, zEnd); // uses wide data from old field and velocities (both are whole)
+}
+
+
+
+void FLUID_3D::advectFieldMacCormack2(const float dt, const float* xVelocity, const float* yVelocity, const float* zVelocity,
+ float* oldField, float* newField, float* tempResult, float* temp1, Vec3Int res, const unsigned char* obstacles, int zBegin, int zEnd)
+{
+ float* phiHatN = tempResult;
+ float* t1 = temp1;
+ const int sx= res[0];
+ const int sy= res[1];
+
+ float*& phiN = oldField;
+ float*& phiN1 = newField;
+
+
+
+ // phiHatN = A^R(phiHatN1)
+ advectFieldSemiLagrange( -1.0*dt, xVelocity, yVelocity, zVelocity, phiHatN, t1, res, zBegin, zEnd); // uses wide data from old field and velocities (both are whole)
+
+ // phiN1 = phiHatN1 + (phiN - phiHatN) / 2
+ const int border = 0;
+ for (int z = zBegin+border; z < zEnd-border; z++)
+ for (int y = border; y < sy-border; y++)
+ for (int x = border; x < sx-border; x++) {
+ int index = x + y * sx + z * sx*sy;
+ phiN1[index] = phiHatN[index] + (phiN[index] - t1[index]) * 0.50f;
+ //phiN1[index] = phiHatN1[index]; // debug, correction off
+ }
+ copyBorderX(phiN1, res, zBegin, zEnd);
+ copyBorderY(phiN1, res, zBegin, zEnd);
+ copyBorderZ(phiN1, res, zBegin, zEnd);
+
+ // clamp any newly created extrema
+ clampExtrema(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res, zBegin, zEnd); // uses wide data from old field and velocities (both are whole)
+
+ // if the error estimate was bad, revert to first order
+ clampOutsideRays(dt, xVelocity, yVelocity, zVelocity, oldField, newField, res, obstacles, phiHatN, zBegin, zEnd); // phiHatN is only used at cells within thread range, so its ok
+
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// Clamp the extrema generated by the BFECC error correction
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::clampExtrema(const float dt, const float* velx, const float* vely, const float* velz,
+ float* oldField, float* newField, Vec3Int res, int zBegin, int zEnd)
+{
+ const int xres= res[0];
+ const int yres= res[1];
+ const int zres= res[2];
+ const int slabSize = res[0] * res[1];
+
+ int bb=0;
+ int bt=0;
+
+ if (zBegin == 0) {bb = 1;}
+ if (zEnd == res[2]) {bt = 1;}
+
+
+ for (int z = zBegin+bb; z < zEnd-bt; z++)
+ for (int y = 1; y < yres-1; y++)
+ for (int x = 1; x < xres-1; x++)
+ {
+ const int index = x + y * xres+ z * xres*yres;
+ // backtrace
+ float xTrace = x - dt * velx[index];
+ float yTrace = y - dt * vely[index];
+ float zTrace = z - dt * velz[index];
+
+ // clamp backtrace to grid boundaries
+ if (xTrace < 0.5) xTrace = 0.5;
+ if (xTrace > xres - 1.5) xTrace = xres - 1.5;
+ if (yTrace < 0.5) yTrace = 0.5;
+ if (yTrace > yres - 1.5) yTrace = yres - 1.5;
+ if (zTrace < 0.5) zTrace = 0.5;
+ if (zTrace > zres - 1.5) zTrace = zres - 1.5;
+
+ // locate neighbors to interpolate
+ const int x0 = (int)xTrace;
+ const int x1 = x0 + 1;
+ const int y0 = (int)yTrace;
+ const int y1 = y0 + 1;
+ const int z0 = (int)zTrace;
+ const int z1 = z0 + 1;
+
+ const int i000 = x0 + y0 * xres + z0 * slabSize;
+ const int i010 = x0 + y1 * xres + z0 * slabSize;
+ const int i100 = x1 + y0 * xres + z0 * slabSize;
+ const int i110 = x1 + y1 * xres + z0 * slabSize;
+ const int i001 = x0 + y0 * xres + z1 * slabSize;
+ const int i011 = x0 + y1 * xres + z1 * slabSize;
+ const int i101 = x1 + y0 * xres + z1 * slabSize;
+ const int i111 = x1 + y1 * xres + z1 * slabSize;
+
+ float minField = oldField[i000];
+ float maxField = oldField[i000];
+
+ minField = (oldField[i010] < minField) ? oldField[i010] : minField;
+ maxField = (oldField[i010] > maxField) ? oldField[i010] : maxField;
+
+ minField = (oldField[i100] < minField) ? oldField[i100] : minField;
+ maxField = (oldField[i100] > maxField) ? oldField[i100] : maxField;
+
+ minField = (oldField[i110] < minField) ? oldField[i110] : minField;
+ maxField = (oldField[i110] > maxField) ? oldField[i110] : maxField;
+
+ minField = (oldField[i001] < minField) ? oldField[i001] : minField;
+ maxField = (oldField[i001] > maxField) ? oldField[i001] : maxField;
+
+ minField = (oldField[i011] < minField) ? oldField[i011] : minField;
+ maxField = (oldField[i011] > maxField) ? oldField[i011] : maxField;
+
+ minField = (oldField[i101] < minField) ? oldField[i101] : minField;
+ maxField = (oldField[i101] > maxField) ? oldField[i101] : maxField;
+
+ minField = (oldField[i111] < minField) ? oldField[i111] : minField;
+ maxField = (oldField[i111] > maxField) ? oldField[i111] : maxField;
+
+ newField[index] = (newField[index] > maxField) ? maxField : newField[index];
+ newField[index] = (newField[index] < minField) ? minField : newField[index];
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// Reverts any backtraces that go into boundaries back to first
+// order -- in this case the error correction term was totally
+// incorrect
+//////////////////////////////////////////////////////////////////////
+void FLUID_3D::clampOutsideRays(const float dt, const float* velx, const float* vely, const float* velz,
+ float* oldField, float* newField, Vec3Int res, const unsigned char* obstacles, const float *oldAdvection, int zBegin, int zEnd)
+{
+ const int sx= res[0];
+ const int sy= res[1];
+ const int sz= res[2];
+ const int slabSize = res[0] * res[1];
+
+ int bb=0;
+ int bt=0;
+
+ if (zBegin == 0) {bb = 1;}
+ if (zEnd == res[2]) {bt = 1;}
+
+ for (int z = zBegin+bb; z < zEnd-bt; z++)
+ for (int y = 1; y < sy-1; y++)
+ for (int x = 1; x < sx-1; x++)
+ {
+ const int index = x + y * sx+ z * slabSize;
+ // backtrace
+ float xBackward = x + dt * velx[index];
+ float yBackward = y + dt * vely[index];
+ float zBackward = z + dt * velz[index];
+ float xTrace = x - dt * velx[index];
+ float yTrace = y - dt * vely[index];
+ float zTrace = z - dt * velz[index];
+
+ // see if it goes outside the boundaries
+ bool hasObstacle =
+ (zTrace < 1.0f) || (zTrace > sz - 2.0f) ||
+ (yTrace < 1.0f) || (yTrace > sy - 2.0f) ||
+ (xTrace < 1.0f) || (xTrace > sx - 2.0f) ||
+ (zBackward < 1.0f) || (zBackward > sz - 2.0f) ||
+ (yBackward < 1.0f) || (yBackward > sy - 2.0f) ||
+ (xBackward < 1.0f) || (xBackward > sx - 2.0f);
+ // reuse old advection instead of doing another one...
+ if(hasObstacle) { newField[index] = oldAdvection[index]; continue; }
+
+ // clamp to prevent an out of bounds access when looking into
+ // the _obstacles array
+ zTrace = (zTrace < 0.5f) ? 0.5f : zTrace;
+ zTrace = (zTrace > sz - 1.5f) ? sz - 1.5f : zTrace;
+ yTrace = (yTrace < 0.5f) ? 0.5f : yTrace;
+ yTrace = (yTrace > sy - 1.5f) ? sy - 1.5f : yTrace;
+ xTrace = (xTrace < 0.5f) ? 0.5f : xTrace;
+ xTrace = (xTrace > sx - 1.5f) ? sx - 1.5f : xTrace;
+
+ // locate neighbors to interpolate,
+ // do backward first since we will use the forward indices if a
+ // reversion is actually necessary
+ zBackward = (zBackward < 0.5f) ? 0.5f : zBackward;
+ zBackward = (zBackward > sz - 1.5f) ? sz - 1.5f : zBackward;
+ yBackward = (yBackward < 0.5f) ? 0.5f : yBackward;
+ yBackward = (yBackward > sy - 1.5f) ? sy - 1.5f : yBackward;
+ xBackward = (xBackward < 0.5f) ? 0.5f : xBackward;
+ xBackward = (xBackward > sx - 1.5f) ? sx - 1.5f : xBackward;
+
+ int x0 = (int)xBackward;
+ int x1 = x0 + 1;
+ int y0 = (int)yBackward;
+ int y1 = y0 + 1;
+ int z0 = (int)zBackward;
+ int z1 = z0 + 1;
+ if(obstacles && !hasObstacle) {
+ hasObstacle = hasObstacle ||
+ obstacles[x0 + y0 * sx + z0*slabSize] ||
+ obstacles[x0 + y1 * sx + z0*slabSize] ||
+ obstacles[x1 + y0 * sx + z0*slabSize] ||
+ obstacles[x1 + y1 * sx + z0*slabSize] ||
+ obstacles[x0 + y0 * sx + z1*slabSize] ||
+ obstacles[x0 + y1 * sx + z1*slabSize] ||
+ obstacles[x1 + y0 * sx + z1*slabSize] ||
+ obstacles[x1 + y1 * sx + z1*slabSize] ;
+ }
+ // reuse old advection instead of doing another one...
+ if(hasObstacle) { newField[index] = oldAdvection[index]; continue; }
+
+ x0 = (int)xTrace;
+ x1 = x0 + 1;
+ y0 = (int)yTrace;
+ y1 = y0 + 1;
+ z0 = (int)zTrace;
+ z1 = z0 + 1;
+ if(obstacles && !hasObstacle) {
+ hasObstacle = hasObstacle ||
+ obstacles[x0 + y0 * sx + z0*slabSize] ||
+ obstacles[x0 + y1 * sx + z0*slabSize] ||
+ obstacles[x1 + y0 * sx + z0*slabSize] ||
+ obstacles[x1 + y1 * sx + z0*slabSize] ||
+ obstacles[x0 + y0 * sx + z1*slabSize] ||
+ obstacles[x0 + y1 * sx + z1*slabSize] ||
+ obstacles[x1 + y0 * sx + z1*slabSize] ||
+ obstacles[x1 + y1 * sx + z1*slabSize] ;
+ } // obstacle array
+ // reuse old advection instead of doing another one...
+ if(hasObstacle) { newField[index] = oldAdvection[index]; continue; }
+
+ // see if either the forward or backward ray went into
+ // a boundary
+ if (hasObstacle) {
+ // get interpolation weights
+ float s1 = xTrace - x0;
+ float s0 = 1.0f - s1;
+ float t1 = yTrace - y0;
+ float t0 = 1.0f - t1;
+ float u1 = zTrace - z0;
+ float u0 = 1.0f - u1;
+
+ const int i000 = x0 + y0 * sx + z0 * slabSize;
+ const int i010 = x0 + y1 * sx + z0 * slabSize;
+ const int i100 = x1 + y0 * sx + z0 * slabSize;
+ const int i110 = x1 + y1 * sx + z0 * slabSize;
+ const int i001 = x0 + y0 * sx + z1 * slabSize;
+ const int i011 = x0 + y1 * sx + z1 * slabSize;
+ const int i101 = x1 + y0 * sx + z1 * slabSize;
+ const int i111 = x1 + y1 * sx + z1 * slabSize;
+
+ // interpolate, (indices could be computed once)
+ newField[index] = u0 * (s0 * (
+ t0 * oldField[i000] +
+ t1 * oldField[i010]) +
+ s1 * (t0 * oldField[i100] +
+ t1 * oldField[i110])) +
+ u1 * (s0 * (t0 * oldField[i001] +
+ t1 * oldField[i011]) +
+ s1 * (t0 * oldField[i101] +
+ t1 * oldField[i111]));
+ }
+ } // xyz
+}
diff --git a/intern/smoke/intern/IMAGE.h b/intern/smoke/intern/IMAGE.h
new file mode 100644
index 00000000000..a606fcddf72
--- /dev/null
+++ b/intern/smoke/intern/IMAGE.h
@@ -0,0 +1,289 @@
+/** \file smoke/intern/IMAGE.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+//////////////////////////////////////////////////////////////////////
+//
+#ifndef IMAGE_H
+#define IMAGE_H
+
+#include <stdlib.h>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <zlib.h>
+
+//////////////////////////////////////////////////////////////////////
+// NT helper functions
+//////////////////////////////////////////////////////////////////////
+template < class T > inline T ABS( T a ) {
+ return (0 < a) ? a : -a ;
+}
+
+template < class T > inline void SWAP_POINTERS( T &a, T &b ) {
+ T temp = a;
+ a = b;
+ b = temp;
+}
+
+template < class T > inline void CLAMP( T &a, T b=0., T c=1.) {
+ if(a<b) { a=b; return; }
+ if(a>c) { a=c; return; }
+}
+
+template < class T > inline T MIN( T a, T b) {
+ return (a < b) ? a : b;
+}
+
+template < class T > inline T MAX( T a, T b) {
+ return (a > b) ? a : b;
+}
+
+template < class T > inline T MAX3( T a, T b, T c) {
+ T max = (a > b) ? a : b;
+ max = (max > c) ? max : c;
+ return max;
+}
+
+template < class T > inline float MAX3V( T vec) {
+ float max = (vec[0] > vec[1]) ? vec[0] : vec[1];
+ max = (max > vec[2]) ? max : vec[2];
+ return max;
+}
+
+template < class T > inline float MIN3V( T vec) {
+ float min = (vec[0] < vec[1]) ? vec[0] : vec[1];
+ min = (min < vec[2]) ? min : vec[2];
+ return min;
+}
+
+//////////////////////////////////////////////////////////////////////
+// PNG, POV-Ray, and PBRT output functions
+//////////////////////////////////////////////////////////////////////
+#ifndef NOPNG
+#ifdef WIN32
+#include "png.h"
+#else
+#include <png.h>
+#endif
+#endif // NOPNG
+
+/*
+ NOTE when someone decided to uncomment the following code, please remember to put it between #ifndef NOPNG #endif
+*/
+namespace IMAGE {
+ /*
+ static int writePng(const char *fileName, unsigned char **rowsp, int w, int h)
+ {
+ // defaults
+ const int colortype = PNG_COLOR_TYPE_RGBA;
+ const int bitdepth = 8;
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ png_bytep *rows = rowsp;
+
+ FILE *fp = NULL;
+ std::string doing = "open for writing";
+ if (!(fp = fopen(fileName, "wb"))) goto fail;
+
+ if(!png_ptr) {
+ doing = "create png write struct";
+ if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) goto fail;
+ }
+ if(!info_ptr) {
+ doing = "create png info struct";
+ if (!(info_ptr = png_create_info_struct(png_ptr))) goto fail;
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr))) goto fail;
+ doing = "init IO";
+ png_init_io(png_ptr, fp);
+ doing = "write header";
+ png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colortype, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+ doing = "write info";
+ png_write_info(png_ptr, info_ptr);
+ doing = "write image";
+ png_write_image(png_ptr, rows);
+ doing = "write end";
+ png_write_end(png_ptr, NULL);
+ doing = "write destroy structs";
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ fclose( fp );
+ return 0;
+
+ fail:
+ std::cerr << "writePng: could not "<<doing<<" !\n";
+ if(fp) fclose( fp );
+ if(png_ptr || info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr);
+ return -1;
+ }
+ */
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // write a numbered PNG file out, padded with zeros up to three zeros
+ /////////////////////////////////////////////////////////////////////////////////
+ /*
+ static void dumpNumberedPNG(int counter, std::string prefix, float* field, int xRes, int yRes)
+ {
+ char buffer[256];
+ sprintf(buffer,"%04i", counter);
+ std::string number = std::string(buffer);
+
+ unsigned char pngbuf[xRes*yRes*4];
+ unsigned char *rows[yRes];
+ float *pfield = field;
+ for (int j=0; j<yRes; j++) {
+ for (int i=0; i<xRes; i++) {
+ float val = *pfield;
+ if(val>1.) val=1.;
+ if(val<0.) val=0.;
+ pngbuf[(j*xRes+i)*4+0] = (unsigned char)(val*255.);
+ pngbuf[(j*xRes+i)*4+1] = (unsigned char)(val*255.);
+ pngbuf[(j*xRes+i)*4+2] = (unsigned char)(val*255.);
+ pfield++;
+ pngbuf[(j*xRes+i)*4+3] = 255;
+ }
+ rows[j] = &pngbuf[(yRes-j-1)*xRes*4];
+ }
+ std::string filenamePNG = prefix + number + std::string(".png");
+ writePng(filenamePNG.c_str(), rows, xRes, yRes, false);
+ printf("Writing %s\n", filenamePNG.c_str());
+
+ }
+*/
+ /////////////////////////////////////////////////////////////////////////////////
+ // export pbrt volumegrid geometry object
+ /////////////////////////////////////////////////////////////////////////////////
+ /*
+ static void dumpPBRT(int counter, std::string prefix, float* fieldOrg, int xRes, int yRes, int zRes)
+ {
+ char buffer[256];
+ sprintf(buffer,"%04i", counter);
+ std::string number = std::string(buffer);
+
+ std::string filenamePbrt = prefix + number + std::string(".pbrt.gz");
+ printf("Writing PBRT %s\n", filenamePbrt.c_str());
+
+ float *field = new float[xRes*yRes*zRes];
+ // normalize values
+ float maxDensVal = ABS(fieldOrg[0]);
+ float targetNorm = 0.5;
+ for (int i = 0; i < xRes * yRes * zRes; i++) {
+ if(ABS(fieldOrg[i])>maxDensVal) maxDensVal = ABS(fieldOrg[i]);
+ field[i] = 0.;
+ }
+ if(maxDensVal>0.) {
+ for (int i = 0; i < xRes * yRes * zRes; i++) {
+ field[i] = ABS(fieldOrg[i]) / maxDensVal * targetNorm;
+ }
+ }
+
+ std::fstream fout;
+ fout.open(filenamePbrt.c_str(), std::ios::out);
+
+ int maxRes = (xRes > yRes) ? xRes : yRes;
+ maxRes = (maxRes > zRes) ? maxRes : zRes;
+
+ const float xSize = 1.0 / (float)maxRes * (float)xRes;
+ const float ySize = 1.0 / (float)maxRes * (float)yRes;
+ const float zSize = 1.0 / (float)maxRes * (float)zRes;
+
+ gzFile file;
+ file = gzopen(filenamePbrt.c_str(), "wb1");
+ if (file == NULL) {
+ std::cerr << " Couldn't write file " << filenamePbrt << "!!!" << std::endl;
+ return;
+ }
+
+ // dimensions
+ gzprintf(file, "Volume \"volumegrid\" \n");
+ gzprintf(file, " \"integer nx\" %i\n", xRes);
+ gzprintf(file, " \"integer ny\" %i\n", yRes);
+ gzprintf(file, " \"integer nz\" %i\n", zRes);
+ gzprintf(file, " \"point p0\" [ 0.0 0.0 0.0 ] \"point p1\" [%f %f %f ] \n", xSize, ySize, zSize);
+ gzprintf(file, " \"float density\" [ \n");
+ for (int i = 0; i < xRes * yRes * zRes; i++)
+ gzprintf(file, "%f ", field[i]);
+ gzprintf(file, "] \n \n");
+
+ gzclose(file);
+ delete[] field;
+ }
+ */
+
+ /////////////////////////////////////////////////////////////////////////////////
+ // 3D df3 export
+ /////////////////////////////////////////////////////////////////////////////////
+/*
+ static void dumpDF3(int counter, std::string prefix, float* fieldOrg, int xRes, int yRes, int zRes)
+ {
+ char buffer[256];
+
+ // do deferred copying to final directory, better for network directories
+ sprintf(buffer,"%04i", counter);
+ std::string number = std::string(buffer);
+ std::string filenameDf3 = prefix + number + std::string(".df3.gz");
+ printf("Writing DF3 %s\n", filenameDf3.c_str());
+
+ gzFile file;
+ file = gzopen(filenameDf3.c_str(), "wb1");
+ if (file == NULL) {
+ std::cerr << " Couldn't write file " << filenameDf3 << "!!!" << std::endl;
+ return;
+ }
+
+ // dimensions
+ const int byteSize = 2;
+ const unsigned short int onx=xRes,ony=yRes,onz=zRes;
+ unsigned short int nx,ny,nz;
+ nx = onx >> 8;
+ ny = ony >> 8;
+ nz = onz >> 8;
+ nx += (onx << 8);
+ ny += (ony << 8);
+ nz += (onz << 8);
+ gzwrite(file, (void*)&nx, sizeof(short));
+ gzwrite(file, (void*)&ny, sizeof(short));
+ gzwrite(file, (void*)&nz, sizeof(short));
+ const int nitems = onx*ony*onz;
+ const float mul = (float)( (1<<(8*byteSize))-1);
+
+ unsigned short int *buf = new unsigned short int[nitems];
+ for (int k = 0; k < onz; k++)
+ for (int j = 0; j < ony; j++)
+ for (int i = 0; i < onx; i++) {
+ float val = fieldOrg[k*(onx*ony)+j*onx+i] ;
+ CLAMP(val);
+ buf[k*(onx*ony)+j*onx+i] = (short int)(val*mul);
+ }
+ gzwrite(file, (void*)buf, sizeof(unsigned short int)* nitems);
+
+ gzclose(file);
+ delete[] buf;
+ }
+ */
+
+};
+
+
+#endif
+
diff --git a/intern/smoke/intern/INTERPOLATE.h b/intern/smoke/intern/INTERPOLATE.h
new file mode 100644
index 00000000000..b76c8df0b59
--- /dev/null
+++ b/intern/smoke/intern/INTERPOLATE.h
@@ -0,0 +1,230 @@
+/** \file smoke/intern/INTERPOLATE.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+//////////////////////////////////////////////////////////////////////
+#ifndef INTERPOLATE_H
+#define INTERPOLATE_H
+
+#include <iostream>
+#include <VEC3.h>
+
+namespace INTERPOLATE {
+
+//////////////////////////////////////////////////////////////////////
+// linear interpolators
+//////////////////////////////////////////////////////////////////////
+static inline float lerp(float t, float a, float b) {
+ return ( a + t * (b - a) );
+}
+
+static inline float lerp(float* field, float x, float y, int res) {
+ // clamp backtrace to grid boundaries
+ if (x < 0.5f) x = 0.5f;
+ if (x > res - 1.5f) x = res - 1.5f;
+ if (y < 0.5f) y = 0.5f;
+ if (y > res - 1.5f) y = res - 1.5f;
+
+ const int x0 = (int)x;
+ const int y0 = (int)y;
+ x -= x0;
+ y -= y0;
+ float d00, d10, d01, d11;
+
+ // lerp the velocities
+ d00 = field[x0 + y0 * res];
+ d10 = field[(x0 + 1) + y0 * res];
+ d01 = field[x0 + (y0 + 1) * res];
+ d11 = field[(x0 + 1) + (y0 + 1) * res];
+ return lerp(y, lerp(x, d00, d10),
+ lerp(x, d01, d11));
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// 3d linear interpolation
+//////////////////////////////////////////////////////////////////////////////////////////
+static inline float lerp3d(float* field, float x, float y, float z, int xres, int yres, int zres) {
+ // clamp pos to grid boundaries
+ if (x < 0.5) x = 0.5;
+ if (x > xres - 1.5) x = xres - 1.5;
+ if (y < 0.5) y = 0.5;
+ if (y > yres - 1.5) y = yres - 1.5;
+ if (z < 0.5) z = 0.5;
+ if (z > zres - 1.5) z = zres - 1.5;
+
+ // locate neighbors to interpolate
+ const int x0 = (int)x;
+ const int x1 = x0 + 1;
+ const int y0 = (int)y;
+ const int y1 = y0 + 1;
+ const int z0 = (int)z;
+ const int z1 = z0 + 1;
+
+ // get interpolation weights
+ const float s1 = x - (float)x0;
+ const float s0 = 1.0f - s1;
+ const float t1 = y - (float)y0;
+ const float t0 = 1.0f - t1;
+ const float u1 = z - (float)z0;
+ const float u0 = 1.0f - u1;
+
+ const int slabSize = xres*yres;
+ const int i000 = x0 + y0 * xres + z0 * slabSize;
+ const int i010 = x0 + y1 * xres + z0 * slabSize;
+ const int i100 = x1 + y0 * xres + z0 * slabSize;
+ const int i110 = x1 + y1 * xres + z0 * slabSize;
+ const int i001 = x0 + y0 * xres + z1 * slabSize;
+ const int i011 = x0 + y1 * xres + z1 * slabSize;
+ const int i101 = x1 + y0 * xres + z1 * slabSize;
+ const int i111 = x1 + y1 * xres + z1 * slabSize;
+
+ // interpolate (indices could be computed once)
+ return ( u0 * (s0 * (t0 * field[i000] +
+ t1 * field[i010]) +
+ s1 * (t0 * field[i100] +
+ t1 * field[i110])) +
+ u1 * (s0 * (t0 * field[i001] +
+ t1 * field[i011]) +
+ s1 * (t0 * field[i101] +
+ t1 * field[i111])) );
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// convert field entries of type T to floats, then interpolate
+//////////////////////////////////////////////////////////////////////////////////////////
+template <class T>
+static inline float lerp3dToFloat(T* field1,
+ float x, float y, float z, int xres, int yres, int zres) {
+ // clamp pos to grid boundaries
+ if (x < 0.5) x = 0.5;
+ if (x > xres - 1.5) x = xres - 1.5;
+ if (y < 0.5) y = 0.5;
+ if (y > yres - 1.5) y = yres - 1.5;
+ if (z < 0.5) z = 0.5;
+ if (z > zres - 1.5) z = zres - 1.5;
+
+ // locate neighbors to interpolate
+ const int x0 = (int)x;
+ const int x1 = x0 + 1;
+ const int y0 = (int)y;
+ const int y1 = y0 + 1;
+ const int z0 = (int)z;
+ const int z1 = z0 + 1;
+
+ // get interpolation weights
+ const float s1 = x - (float)x0;
+ const float s0 = 1.0f - s1;
+ const float t1 = y - (float)y0;
+ const float t0 = 1.0f - t1;
+ const float u1 = z - (float)z0;
+ const float u0 = 1.0f - u1;
+
+ const int slabSize = xres*yres;
+ const int i000 = x0 + y0 * xres + z0 * slabSize;
+ const int i010 = x0 + y1 * xres + z0 * slabSize;
+ const int i100 = x1 + y0 * xres + z0 * slabSize;
+ const int i110 = x1 + y1 * xres + z0 * slabSize;
+ const int i001 = x0 + y0 * xres + z1 * slabSize;
+ const int i011 = x0 + y1 * xres + z1 * slabSize;
+ const int i101 = x1 + y0 * xres + z1 * slabSize;
+ const int i111 = x1 + y1 * xres + z1 * slabSize;
+
+ // interpolate (indices could be computed once)
+ return (float)(
+ ( u0 * (s0 * (t0 * (float)field1[i000] +
+ t1 * (float)field1[i010]) +
+ s1 * (t0 * (float)field1[i100] +
+ t1 * (float)field1[i110])) +
+ u1 * (s0 * (t0 * (float)field1[i001] +
+ t1 * (float)field1[i011]) +
+ s1 * (t0 * (float)field1[i101] +
+ t1 * (float)field1[i111])) ) );
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// interpolate a vector from 3 fields
+//////////////////////////////////////////////////////////////////////////////////////////
+static inline Vec3 lerp3dVec(float* field1, float* field2, float* field3,
+ float x, float y, float z, int xres, int yres, int zres) {
+ // clamp pos to grid boundaries
+ if (x < 0.5) x = 0.5;
+ if (x > xres - 1.5) x = xres - 1.5;
+ if (y < 0.5) y = 0.5;
+ if (y > yres - 1.5) y = yres - 1.5;
+ if (z < 0.5) z = 0.5;
+ if (z > zres - 1.5) z = zres - 1.5;
+
+ // locate neighbors to interpolate
+ const int x0 = (int)x;
+ const int x1 = x0 + 1;
+ const int y0 = (int)y;
+ const int y1 = y0 + 1;
+ const int z0 = (int)z;
+ const int z1 = z0 + 1;
+
+ // get interpolation weights
+ const float s1 = x - (float)x0;
+ const float s0 = 1.0f - s1;
+ const float t1 = y - (float)y0;
+ const float t0 = 1.0f - t1;
+ const float u1 = z - (float)z0;
+ const float u0 = 1.0f - u1;
+
+ const int slabSize = xres*yres;
+ const int i000 = x0 + y0 * xres + z0 * slabSize;
+ const int i010 = x0 + y1 * xres + z0 * slabSize;
+ const int i100 = x1 + y0 * xres + z0 * slabSize;
+ const int i110 = x1 + y1 * xres + z0 * slabSize;
+ const int i001 = x0 + y0 * xres + z1 * slabSize;
+ const int i011 = x0 + y1 * xres + z1 * slabSize;
+ const int i101 = x1 + y0 * xres + z1 * slabSize;
+ const int i111 = x1 + y1 * xres + z1 * slabSize;
+
+ // interpolate (indices could be computed once)
+ return Vec3(
+ ( u0 * (s0 * (t0 * field1[i000] +
+ t1 * field1[i010]) +
+ s1 * (t0 * field1[i100] +
+ t1 * field1[i110])) +
+ u1 * (s0 * (t0 * field1[i001] +
+ t1 * field1[i011]) +
+ s1 * (t0 * field1[i101] +
+ t1 * field1[i111])) ) ,
+ ( u0 * (s0 * (t0 * field2[i000] +
+ t1 * field2[i010]) +
+ s1 * (t0 * field2[i100] +
+ t1 * field2[i110])) +
+ u1 * (s0 * (t0 * field2[i001] +
+ t1 * field2[i011]) +
+ s1 * (t0 * field2[i101] +
+ t1 * field2[i111])) ) ,
+ ( u0 * (s0 * (t0 * field3[i000] +
+ t1 * field3[i010]) +
+ s1 * (t0 * field3[i100] +
+ t1 * field3[i110])) +
+ u1 * (s0 * (t0 * field3[i001] +
+ t1 * field3[i011]) +
+ s1 * (t0 * field3[i101] +
+ t1 * field3[i111])) )
+ );
+}
+
+};
+#endif
diff --git a/intern/smoke/intern/LICENSE.txt b/intern/smoke/intern/LICENSE.txt
new file mode 100644
index 00000000000..94a9ed024d3
--- /dev/null
+++ b/intern/smoke/intern/LICENSE.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/intern/smoke/intern/LU_HELPER.cpp b/intern/smoke/intern/LU_HELPER.cpp
new file mode 100644
index 00000000000..40060371071
--- /dev/null
+++ b/intern/smoke/intern/LU_HELPER.cpp
@@ -0,0 +1,139 @@
+/** \file smoke/intern/LU_HELPER.cpp
+ * \ingroup smoke
+ */
+
+#include "LU_HELPER.h"
+
+int isNonsingular (sLU LU_) {
+ for (int j = 0; j < 3; j++) {
+ if (LU_.values[j][j] == 0)
+ return 0;
+ }
+ return 1;
+}
+
+sLU computeLU( float a[3][3])
+{
+ sLU result;
+ int m=3;
+ int n=3;
+
+ //float LU_[3][3];
+ for (int i = 0; i < m; i++) {
+ result.piv[i] = i;
+ for (int j = 0; j < n; j++) result.values[i][j]=a[i][j];
+ }
+
+ result.pivsign = 1;
+ //Real *LUrowi = 0;;
+ //Array1D<Real> LUcolj(m);
+ //float *LUrowi = 0;
+ float LUcolj[3];
+
+ // Outer loop.
+
+ for (int j = 0; j < n; j++) {
+
+ // Make a copy of the j-th column to localize references.
+
+ for (int i = 0; i < m; i++) {
+ LUcolj[i] = result.values[i][j];
+ }
+
+ // Apply previous transformations.
+
+ for (int i = 0; i < m; i++) {
+ //float LUrowi[3];
+ //LUrowi = result.values[i];
+
+ // Most of the time is spent in the following dot product.
+
+ int kmax = min(i,j);
+ double s = 0.0;
+ for (int k = 0; k < kmax; k++) {
+ s += result.values[i][k]*LUcolj[k];
+ }
+
+ result.values[i][j] = LUcolj[i] -= s;
+ }
+
+ // Find pivot and exchange if necessary.
+
+ int p = j;
+ for (int i = j+1; i < m; i++) {
+ if (abs(LUcolj[i]) > abs(LUcolj[p])) {
+ p = i;
+ }
+ }
+ if (p != j) {
+ int k=0;
+ for (k = 0; k < n; k++) {
+ double t = result.values[p][k];
+ result.values[p][k] = result.values[j][k];
+ result.values[j][k] = t;
+ }
+ k = result.piv[p];
+ result.piv[p] = result.piv[j];
+ result.piv[j] = k;
+ result.pivsign = -result.pivsign;
+ }
+
+ // Compute multipliers.
+
+ if ((j < m) && (result.values[j][j] != 0.0)) {
+ for (int i = j+1; i < m; i++) {
+ result.values[i][j] /= result.values[j][j];
+ }
+ }
+ }
+
+ return result;
+}
+
+void solveLU3x3(sLU& A, float x[3], float b[3])
+{
+ //TNT::Array1D<float> jamaB = TNT::Array1D<float>(3, &b[0]);
+ //TNT::Array1D<float> jamaX = A.solve(jamaB);
+
+
+ // Solve A, B
+
+ {
+ if (!isNonsingular(A)) {
+ x[0]=0.0f;
+ x[1]=0.0f;
+ x[2]=0.0f;
+ return;
+ }
+
+
+ //Array1D<Real> Ax = permute_copy(b, piv);
+ float Ax[3];
+
+ // permute copy: b , A.piv
+ {
+ for (int i = 0; i < 3; i++)
+ Ax[i] = b[A.piv[i]];
+ }
+
+ // Solve L*Y = B(piv)
+ for (int k = 0; k < 3; k++) {
+ for (int i = k+1; i < 3; i++) {
+ Ax[i] -= Ax[k]*A.values[i][k];
+ }
+ }
+
+ // Solve U*X = Y;
+ for (int k = 2; k >= 0; k--) {
+ Ax[k] /= A.values[k][k];
+ for (int i = 0; i < k; i++)
+ Ax[i] -= Ax[k]*A.values[i][k];
+ }
+
+
+ x[0] = Ax[0];
+ x[1] = Ax[1];
+ x[2] = Ax[2];
+ return;
+ }
+}
diff --git a/intern/smoke/intern/LU_HELPER.h b/intern/smoke/intern/LU_HELPER.h
new file mode 100644
index 00000000000..b82b8f5030e
--- /dev/null
+++ b/intern/smoke/intern/LU_HELPER.h
@@ -0,0 +1,54 @@
+/** \file smoke/intern/LU_HELPER.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+//////////////////////////////////////////////////////////////////////
+// Modified to not require TNT matrix library anymore. It was very slow
+// when being run in parallel. Required TNT JAMA:LU libraries were
+// converted into independent functions.
+// - MiikaH
+//////////////////////////////////////////////////////////////////////
+
+#ifndef LU_HELPER_H
+#define LU_HELPER_H
+
+#include <cmath>
+#include <algorithm>
+
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////
+// Helper function, compute eigenvalues of 3x3 matrix
+//////////////////////////////////////////////////////////////////////
+
+struct sLU
+{
+ float values[3][3];
+ int pivsign;
+ int piv[3];
+};
+
+
+int isNonsingular (sLU LU_);
+sLU computeLU( float a[3][3]);
+void solveLU3x3(sLU& A, float x[3], float b[3]);
+
+
+#endif
diff --git a/intern/smoke/intern/MERSENNETWISTER.h b/intern/smoke/intern/MERSENNETWISTER.h
new file mode 100644
index 00000000000..116568c2834
--- /dev/null
+++ b/intern/smoke/intern/MERSENNETWISTER.h
@@ -0,0 +1,432 @@
+/** \file smoke/intern/MERSENNETWISTER.h
+ * \ingroup smoke
+ */
+// MersenneTwister.h
+// Mersenne Twister random number generator -- a C++ class MTRand
+// Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// Richard J. Wagner v1.0 15 May 2003 rjwagner@writeme.com
+
+// The Mersenne Twister is an algorithm for generating random numbers. It
+// was designed with consideration of the flaws in various other generators.
+// The period, 2^19937-1, and the order of equidistribution, 623 dimensions,
+// are far greater. The generator is also fast; it avoids multiplication and
+// division, and it benefits from caches and pipelines. For more information
+// see the inventors' web page at http://www.math.keio.ac.jp/~matumoto/emt.html
+
+// Reference
+// M. Matsumoto and T. Nishimura, "Mersenne Twister: A 623-Dimensionally
+// Equidistributed Uniform Pseudo-Random Number Generator", ACM Transactions on
+// Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30.
+
+// Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+// Copyright (C) 2000 - 2003, Richard J. Wagner
+// 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. The names of its contributors may not 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.
+
+// The original code included the following notice:
+//
+// When you use this, send an email to: matumoto@math.keio.ac.jp
+// with an appropriate reference to your work.
+//
+// It would be nice to CC: rjwagner@writeme.com and Cokus@math.washington.edu
+// when you write.
+
+#ifndef MERSENNETWISTER_H
+#define MERSENNETWISTER_H
+
+// Not thread safe (unless auto-initialization is avoided and each thread has
+// its own MTRand object)
+
+#include <iostream>
+#include <limits.h>
+#include <stdio.h>
+#include <time.h>
+#include <math.h>
+
+class MTRand {
+// Data
+public:
+ typedef unsigned long uint32; // unsigned integer type, at least 32 bits
+
+ enum { N = 624 }; // length of state vector
+ enum { SAVE = N + 1 }; // length of array for save()
+
+protected:
+ enum { M = 397 }; // period parameter
+
+ uint32 state[N]; // internal state
+ uint32 *pNext; // next value to get from state
+ int left; // number of values left before reload needed
+
+
+//Methods
+public:
+ MTRand( const uint32& oneSeed ); // initialize with a simple uint32
+ MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
+ MTRand(); // auto-initialize with /dev/urandom or time() and clock()
+
+ // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
+ // values together, otherwise the generator state can be learned after
+ // reading 624 consecutive values.
+
+ // Access to 32-bit random numbers
+ double rand(); // real number in [0,1]
+ double rand( const double& n ); // real number in [0,n]
+ double randExc(); // real number in [0,1)
+ double randExc( const double& n ); // real number in [0,n)
+ double randDblExc(); // real number in (0,1)
+ double randDblExc( const double& n ); // real number in (0,n)
+ uint32 randInt(); // integer in [0,2^32-1]
+ uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
+ double operator()() { return rand(); } // same as rand()
+
+ // Access to 53-bit random numbers (capacity of IEEE double precision)
+ double rand53(); // real number in [0,1)
+
+ // Access to nonuniform random number distributions
+ double randNorm( const double& mean = 0.0, const double& variance = 1.0 );
+
+ // Re-seeding functions with same behavior as initializers
+ void seed( const uint32 oneSeed );
+ void seed( uint32 *const bigSeed, const uint32 seedLength = N );
+ void seed();
+
+ // Saving and loading generator state
+ void save( uint32* saveArray ) const; // to array of size SAVE
+ void load( uint32 *const loadArray ); // from such array
+ friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
+ friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
+
+protected:
+ void initialize( const uint32 oneSeed );
+ void reload();
+ uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
+ uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
+ uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
+ uint32 mixBits( const uint32& u, const uint32& v ) const
+ { return hiBit(u) | loBits(v); }
+ uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
+ { return m ^ (mixBits(s0,s1)>>1) ^ ((~loBit(s1) + 1) & 0x9908b0dfUL); }
+ static uint32 hash( time_t t, clock_t c );
+};
+
+
+inline MTRand::MTRand( const uint32& oneSeed )
+ { seed(oneSeed); }
+
+inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
+ { seed(bigSeed,seedLength); }
+
+inline MTRand::MTRand()
+ { seed(); }
+
+inline double MTRand::rand()
+ { return double(randInt()) * (1.0/4294967295.0); }
+
+inline double MTRand::rand( const double& n )
+ { return rand() * n; }
+
+inline double MTRand::randExc()
+ { return double(randInt()) * (1.0/4294967296.0); }
+
+inline double MTRand::randExc( const double& n )
+ { return randExc() * n; }
+
+inline double MTRand::randDblExc()
+ { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
+
+inline double MTRand::randDblExc( const double& n )
+ { return randDblExc() * n; }
+
+inline double MTRand::rand53()
+{
+ uint32 a = randInt() >> 5, b = randInt() >> 6;
+ return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
+}
+
+inline double MTRand::randNorm( const double& mean, const double& variance )
+{
+ // Return a real number from a normal (Gaussian) distribution with given
+ // mean and variance by Box-Muller method
+ double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
+ double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
+ return mean + r * cos(phi);
+}
+
+inline MTRand::uint32 MTRand::randInt()
+{
+ // Pull a 32-bit integer from the generator state
+ // Every other access function simply transforms the numbers extracted here
+
+ if( left == 0 ) reload();
+ --left;
+
+ register uint32 s1;
+ s1 = *pNext++;
+ s1 ^= (s1 >> 11);
+ s1 ^= (s1 << 7) & 0x9d2c5680UL;
+ s1 ^= (s1 << 15) & 0xefc60000UL;
+ return ( s1 ^ (s1 >> 18) );
+}
+
+inline MTRand::uint32 MTRand::randInt( const uint32& n )
+{
+ // Find which bits are used in n
+ // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
+ uint32 used = n;
+ used |= used >> 1;
+ used |= used >> 2;
+ used |= used >> 4;
+ used |= used >> 8;
+ used |= used >> 16;
+
+ // Draw numbers until one is found in [0,n]
+ uint32 i;
+ do
+ i = randInt() & used; // toss unused bits to shorten search
+ while( i > n );
+ return i;
+}
+
+
+inline void MTRand::seed( const uint32 oneSeed )
+{
+ // Seed the generator with a simple uint32
+ initialize(oneSeed);
+ reload();
+}
+
+
+inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
+{
+ // Seed the generator with an array of uint32's
+ // There are 2^19937-1 possible initial states. This function allows
+ // all of those to be accessed by providing at least 19937 bits (with a
+ // default seed length of N = 624 uint32's). Any bits above the lower 32
+ // in each element are discarded.
+ // Just call seed() if you want to get array from /dev/urandom
+ initialize(19650218UL);
+ register int i = 1;
+ register uint32 j = 0;
+ register int k = ( N > seedLength ? N : seedLength );
+ for( ; k; --k )
+ {
+ state[i] =
+ state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
+ state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
+ state[i] &= 0xffffffffUL;
+ ++i; ++j;
+ if( i >= N ) { state[0] = state[N-1]; i = 1; }
+ if( j >= seedLength ) j = 0;
+ }
+ for( k = N - 1; k; --k )
+ {
+ state[i] =
+ state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
+ state[i] -= i;
+ state[i] &= 0xffffffffUL;
+ ++i;
+ if( i >= N ) { state[0] = state[N-1]; i = 1; }
+ }
+ state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
+ reload();
+}
+
+
+inline void MTRand::seed()
+{
+ // seed deterministically to produce reproducible runs
+ seed(123456);
+
+ /*
+ // Seed the generator with an array from /dev/urandom if available
+ // Otherwise use a hash of time() and clock() values
+
+ // First try getting an array from /dev/urandom
+ FILE* urandom = fopen( "/dev/urandom", "rb" );
+ if( urandom )
+ {
+ uint32 bigSeed[N];
+ register uint32 *s = bigSeed;
+ register int i = N;
+ register bool success = true;
+ while( success && i-- )
+ success = fread( s++, sizeof(uint32), 1, urandom );
+ fclose(urandom);
+ if( success ) { seed( bigSeed, N ); return; }
+ }
+
+ // Was not successful, so use time() and clock() instead
+ seed( hash( time(NULL), clock() ) );
+ */
+}
+
+
+inline void MTRand::initialize( const uint32 seed )
+{
+ // Initialize generator state with seed
+ // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
+ // In previous versions, most significant bits (MSBs) of the seed affect
+ // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
+ register uint32 *s = state;
+ register uint32 *r = state;
+ register int i = 1;
+ *s++ = seed & 0xffffffffUL;
+ for( ; i < N; ++i )
+ {
+ *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
+ r++;
+ }
+}
+
+
+inline void MTRand::reload()
+{
+ // Generate N new values in state
+ // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
+ register uint32 *p = state;
+ register int i;
+ for( i = N - M; i--; ++p )
+ *p = twist( p[M], p[0], p[1] );
+ for( i = M; --i; ++p )
+ *p = twist( p[M-N], p[0], p[1] );
+ *p = twist( p[M-N], p[0], state[0] );
+
+ left = N, pNext = state;
+}
+
+
+inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
+{
+ // Get a uint32 from t and c
+ // Better than uint32(x) in case x is floating point in [0,1]
+ // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
+
+ static uint32 differ = 0; // guarantee time-based seeds will change
+
+ uint32 h1 = 0;
+ unsigned char *p = (unsigned char *) &t;
+ for( size_t i = 0; i < sizeof(t); ++i )
+ {
+ h1 *= UCHAR_MAX + 2U;
+ h1 += p[i];
+ }
+ uint32 h2 = 0;
+ p = (unsigned char *) &c;
+ for( size_t j = 0; j < sizeof(c); ++j )
+ {
+ h2 *= UCHAR_MAX + 2U;
+ h2 += p[j];
+ }
+ return ( h1 + differ++ ) ^ h2;
+}
+
+
+inline void MTRand::save( uint32* saveArray ) const
+{
+ register uint32 *sa = saveArray;
+ register const uint32 *s = state;
+ register int i = N;
+ for( ; i--; *sa++ = *s++ ) {}
+ *sa = left;
+}
+
+
+inline void MTRand::load( uint32 *const loadArray )
+{
+ register uint32 *s = state;
+ register uint32 *la = loadArray;
+ register int i = N;
+ for( ; i--; *s++ = *la++ ) {}
+ left = *la;
+ pNext = &state[N-left];
+}
+
+
+inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
+{
+ register const MTRand::uint32 *s = mtrand.state;
+ register int i = mtrand.N;
+ for( ; i--; os << *s++ << "\t" ) {}
+ return os << mtrand.left;
+}
+
+
+inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
+{
+ register MTRand::uint32 *s = mtrand.state;
+ register int i = mtrand.N;
+ for( ; i--; is >> *s++ ) {}
+ is >> mtrand.left;
+ mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
+ return is;
+}
+
+#endif // MERSENNETWISTER_H
+
+// Change log:
+//
+// v0.1 - First release on 15 May 2000
+// - Based on code by Makoto Matsumoto, Takuji Nishimura, and Shawn Cokus
+// - Translated from C to C++
+// - Made completely ANSI compliant
+// - Designed convenient interface for initialization, seeding, and
+// obtaining numbers in default or user-defined ranges
+// - Added automatic seeding from /dev/urandom or time() and clock()
+// - Provided functions for saving and loading generator state
+//
+// v0.2 - Fixed bug which reloaded generator one step too late
+//
+// v0.3 - Switched to clearer, faster reload() code from Matthew Bellew
+//
+// v0.4 - Removed trailing newline in saved generator format to be consistent
+// with output format of built-in types
+//
+// v0.5 - Improved portability by replacing static const int's with enum's and
+// clarifying return values in seed(); suggested by Eric Heimburg
+// - Removed MAXINT constant; use 0xffffffffUL instead
+//
+// v0.6 - Eliminated seed overflow when uint32 is larger than 32 bits
+// - Changed integer [0,n] generator to give better uniformity
+//
+// v0.7 - Fixed operator precedence ambiguity in reload()
+// - Added access for real numbers in (0,1) and (0,n)
+//
+// v0.8 - Included time.h header to properly support time_t and clock_t
+//
+// v1.0 - Revised seeding to match 26 Jan 2002 update of Nishimura and Matsumoto
+// - Allowed for seeding with arrays of any length
+// - Added access for real numbers in [0,1) with 53-bit resolution
+// - Added access for real numbers from normal (Gaussian) distributions
+// - Increased overall speed by optimizing twist()
+// - Doubled speed of integer [0,n] generation
+// - Fixed out-of-range number generation on 64-bit machines
+// - Improved portability by substituting literal constants for long enum's
+// - Changed license from GNU LGPL to BSD
+
diff --git a/intern/smoke/intern/Makefile b/intern/smoke/intern/Makefile
deleted file mode 100644
index 86093b0a66f..00000000000
--- a/intern/smoke/intern/Makefile
+++ /dev/null
@@ -1,42 +0,0 @@
-# Minimal LBM demonstration program by Nils Thuerey
-# See http://www.ntoken.com and http://www.matthiasmueller.info/realtimephysics/ for further info
-# The code is released under the GPL, see LICENSE.txt for details
-
-EXE=synthturb
-SOURCES = $(wildcard source/*.cpp util/*.cpp)
-HEADERS = $(wildcard source/*.h util/*.h)
-OBJCMD = $(patsubst %.cpp,build_cmd/%.o,$(SOURCES))
-OBJGUI = $(patsubst %.cpp,build_gui/%.o,$(SOURCES))
-
-CXX=g++
-CFLAGS = -c -O3 -Isource -Iutil -DDDF_OPENMP=0
-LDFLAGS = -lz
-
-# comment out the following two lines for disabling OPENMP
-LDFLAGS = -lz -fopenmp -lgomp
-CFLAGS = -c -fopenmp -O3 -Isource -Iutil -DDDF_OPENMP=1
-# uncomment this line for macs
-#LDFLAGS = -lz -framework OpenGL -framework GLUT -lgomp
-
-DEFGUI = -DDDF_GLUTGUI=1
-DEFCMD = -DDDF_GLUTGUI=0
-
-default: all
-
-all: cmd gui
-
-cmd: $(OBJCMD)
- $(CXX) $(LDFLAGS) -o turbCmd $(OBJCMD)
-
-gui: $(OBJGUI)
- $(CXX) $(LDFLAGS) -lglut -o turbGui $(OBJGUI)
-
-build_cmd/%.o : %.cpp $(HEADERS)
- $(CXX) $(CFLAGS) $(DEFCMD) -o $@ $<
-
-build_gui/%.o : %.cpp $(HEADERS)
- $(CXX) $(CFLAGS) $(DEFGUI) -o $@ $<
-
-clean:
- rm -f *.o build_gui/source/*.o build_gui/util/*.o build_cmd/source/*.o build_gui/util/*.o turbCmd turbGui
-
diff --git a/intern/smoke/intern/Makefile.FFT b/intern/smoke/intern/Makefile.FFT
new file mode 100644
index 00000000000..e45af1df29b
--- /dev/null
+++ b/intern/smoke/intern/Makefile.FFT
@@ -0,0 +1,22 @@
+# common stuff
+LDFLAGS_COMMON = -lfftw3 #-lglut -lglu32 -lopengl32 -lz -lpng
+CFLAGS_COMMON = -c -Wall -I./ #-I/cygdrive/c/lib/glvu/include -D_WIN32
+
+CC = g++
+CFLAGS = ${CFLAGS_COMMON} -O3 -Wno-unused
+LDFLAGS = ${LDFLAGS_COMMON}
+EXECUTABLE = noiseFFT
+
+SOURCES = noiseFFT.cpp
+OBJECTS = $(SOURCES:.cpp=.o)
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) -o $@
+
+.cpp.o:
+ $(CC) $(CFLAGS) $< -o $@
+
+clean:
+ rm -f *.o $(EXECUTABLE_LOADER) $(EXECUTABLE)
diff --git a/intern/smoke/intern/Makefile.cygwin b/intern/smoke/intern/Makefile.cygwin
new file mode 100644
index 00000000000..c93753a67fe
--- /dev/null
+++ b/intern/smoke/intern/Makefile.cygwin
@@ -0,0 +1,23 @@
+CC = g++
+LDFLAGS = -lz -lpng
+CFLAGS = -O3 -Wno-unused -c -Wall -I./ -D_WIN32
+EXECUTABLE = FLUID_3D
+
+SOURCES = main.cpp FLUID_3D.cpp FLUID_3D_SOLVERS.cpp FLUID_3D_STATIC.cpp SPHERE.cpp WTURBULENCE.cpp
+OBJECTS = $(SOURCES:.cpp=.o)
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) -o $@
+
+.cpp.o:
+ $(CC) $(CFLAGS) $< -o $@
+
+SPHERE.o: SPHERE.h
+FLUID_3D.o: FLUID_3D.h FLUID_3D.cpp
+FLUID_3D_SOLVERS.o: FLUID_3D.h FLUID_3D_SOLVERS.cpp
+main.o: FLUID_3D.h FLUID_3D.cpp FLUID_3D_SOLVERS.cpp
+
+clean:
+ rm -f *.o $(EXECUTABLE_LOADER) $(EXECUTABLE)
diff --git a/intern/smoke/intern/Makefile.linux b/intern/smoke/intern/Makefile.linux
new file mode 100644
index 00000000000..8e71af465dd
--- /dev/null
+++ b/intern/smoke/intern/Makefile.linux
@@ -0,0 +1,23 @@
+CC = g++
+LDFLAGS = -lz -lpng -fopenmp -lgomp
+CFLAGS = -c -Wall -I./ -fopenmp -DPARALLEL=1 -O3 -Wno-unused
+EXECUTABLE = FLUID_3D
+
+SOURCES = main.cpp FLUID_3D.cpp FLUID_3D_SOLVERS.cpp FLUID_3D_STATIC.cpp SPHERE.cpp WTURBULENCE.cpp
+OBJECTS = $(SOURCES:.cpp=.o)
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) -o $@
+
+.cpp.o:
+ $(CC) $(CFLAGS) $< -o $@
+
+SPHERE.o: SPHERE.h
+FLUID_3D.o: FLUID_3D.h FLUID_3D.cpp
+FLUID_3D_SOLVERS.o: FLUID_3D.h FLUID_3D_SOLVERS.cpp
+main.o: FLUID_3D.h FLUID_3D.cpp FLUID_3D_SOLVERS.cpp
+
+clean:
+ rm -f *.o $(EXECUTABLE_LOADER) $(EXECUTABLE)
diff --git a/intern/smoke/intern/Makefile.mac b/intern/smoke/intern/Makefile.mac
new file mode 100644
index 00000000000..227aaa10a16
--- /dev/null
+++ b/intern/smoke/intern/Makefile.mac
@@ -0,0 +1,35 @@
+CC = g++
+
+# uncomment the other two OPENMP_... lines, if your gcc supports OpenMP
+#OPENMP_FLAGS = -fopenmp -DPARALLEL=1 -I/opt/gcc-4.3/usr/local/include
+#OPENMPLD_FLAGS = -fopenmp -lgomp -I/opt/gcc-4.3/usr/local/lib
+OPENMP_FLAGS =
+OPENMPLD_FLAGS =
+
+# assumes MacPorts libpng installation
+PNG_INCLUDE = -I/opt/local/include
+PNG_LIBS = -I/opt/local/lib
+
+LDFLAGS = $(PNG_LIBS)-lz -lpng $(OPENMPLD_FLAGS)
+CFLAGS = -c -Wall -I./ $(PNG_INCLUDE) $(OPENMP_FLAGS) -O3 -Wno-unused
+EXECUTABLE = FLUID_3D
+
+SOURCES = main.cpp FLUID_3D.cpp FLUID_3D_SOLVERS.cpp FLUID_3D_STATIC.cpp SPHERE.cpp WTURBULENCE.cpp
+OBJECTS = $(SOURCES:.cpp=.o)
+
+all: $(SOURCES) $(EXECUTABLE)
+
+$(EXECUTABLE): $(OBJECTS)
+ $(CC) $(OBJECTS) $(LDFLAGS) -o $@
+
+.cpp.o:
+ $(CC) $(CFLAGS) $< -o $@
+
+SPHERE.o: SPHERE.h
+FLUID_3D.o: FLUID_3D.h FLUID_3D.cpp
+FLUID_3D_SOLVERS.o: FLUID_3D.h FLUID_3D_SOLVERS.cpp
+main.o: FLUID_3D.h FLUID_3D.cpp FLUID_3D_SOLVERS.cpp
+
+clean:
+ rm -f *.o $(EXECUTABLE_LOADER) $(EXECUTABLE)
+
diff --git a/intern/smoke/intern/OBSTACLE.h b/intern/smoke/intern/OBSTACLE.h
new file mode 100644
index 00000000000..da8ec6be024
--- /dev/null
+++ b/intern/smoke/intern/OBSTACLE.h
@@ -0,0 +1,46 @@
+/** \file smoke/intern/OBSTACLE.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// OBSTACLE.h: interface for the OBSTACLE class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#ifndef OBSTACLE_H
+#define OBSTACLE_H
+
+enum OBSTACLE_FLAGS {
+ EMPTY = 0,
+ /* 1 is used to flag an object cell */
+ MARCHED = 2,
+ RETIRED = 4,
+ ANIMATED = 8,
+};
+
+class OBSTACLE
+{
+public:
+ OBSTACLE() {};
+ virtual ~OBSTACLE() {};
+
+ virtual bool inside(float x, float y, float z) = 0;
+};
+
+#endif
diff --git a/intern/smoke/intern/README.txt b/intern/smoke/intern/README.txt
deleted file mode 100644
index fc71f662ac4..00000000000
--- a/intern/smoke/intern/README.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-DDF Fluid solver with Turbulence extensions
----------------------------------------------
-
-Sample implementation for the paper
- "Synthetic turbulence using Artificial Boundary layers"
- T.Pfaff, N.Thuerey, A.Selle, M.Gross
- ACM SIGGRAPH Asia 2009
-
-
- License
-------------
-
-The code is provided under the General Public License (GPL v2).
-Please see the included file COPYRIGHT for more information.
-
-
- Installing
-------------
-
-You will need the GLUT and ZLIB libraries in order to build the project.
-If they aren't installed in the normal include, lib paths, you'll need to
-manually add their install path to the makefile.
-For rendering, you also need to have the (open source) PBRT raytracer
-installed (see www.pbrt.org for details).
-
-By default, the code uses OpenMP for some operations. If your compiler
-doesn't handle OpenMP, disable it as indicated in the Makefile.
-
-
- Running
-------------
-
-The makefiles will build two executables, the command line tool turbCmd
-and the GUI interface turbGui.
-They include two hard-coded scenes, a static one, similar to the fuel tank
-scene in the paper, and a dynamic one, similar to the car scene in the
-paper. Both executables take the following command line arguments:
-
-turbCmd/turbGui [mode]
- where mode is
- scene : generate scene files. has to be run first.
- pre-static : precompute static scene
- pre-dynamic : precompute dynamic scene
- run-static : run static scene
- run-dynamic : run dynamic scene
-
-
- GUI
--------------
-
-The GUI can be used to visualize vortex particles, scalar and velocity grids.
-It shows a 2D slice of the 3D volume grid.
-Additional Information (which slice is displayed, display ranges etc.
-are shown on the console)
-
-Basic Navigation:
-- Press p to start/stop the simulation, l performs a single step
-- Move camera position with WASD, zoom in using Q/E.
-- Hold left mouse button to rotate camera, right mouse button to translate
-- Select displayed slide with +/-
-- Select x/y/z slice with *
-- Press ESC to exit
-
-Grid display:
-- Vector grids (velocity etc.) are hidden by default. Press V to enable display.
-- Shift+V toggles component-wise display and centered vector display of vector grids.
-- Use [ ] keys to adjust the viewing range(scaling) of scalar grids, { } keys
- for vector grids.
-- Use X to select the next scalar grid, Z to select the next vector grid.
-- The simulations include different "solvers", e.g. to handle the normal and the
- upscaled grids. Use ~ to switch between solvers.
-
-Additional options:
-- By default, all vortex particles are displayed. The Shift+G key toggles the display
- of vortex particles in the current slice only.
-
-
- Rendering
---------------
-
-The program saves gzipped pbrt or df3 (povray) smoke density files, which can be used to
-render the smoke volumes. An example script for rendering using PBRT is included
-("render.sh" shell script). You need to edit the PBRT path in the script.
-Use "./render.sh sta" or "./render.sh dyn" to render the static/dynamic scene.
-
-Note that using PBRT rendering of volume data is fairly slow, thus the render
-process will take a while. Also, the rendering of animated meshes is not easily possible,
-therefore the car mesh is omitted in the dynamic scene.
-
-
diff --git a/intern/smoke/intern/SPHERE.cpp b/intern/smoke/intern/SPHERE.cpp
new file mode 100644
index 00000000000..dc59c69d0bd
--- /dev/null
+++ b/intern/smoke/intern/SPHERE.cpp
@@ -0,0 +1,53 @@
+/** \file smoke/intern/SPHERE.cpp
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// SPHERE.cpp: implementation of the SPHERE class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#include "SPHERE.h"
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+SPHERE::SPHERE(float x, float y, float z, float radius) :
+ _radius(radius)
+{
+ _center[0] = x;
+ _center[1] = y;
+ _center[2] = z;
+}
+
+SPHERE::~SPHERE()
+{
+
+}
+
+bool SPHERE::inside(float x, float y, float z)
+{
+ float translate[] = {x - _center[0], y - _center[1], z - _center[2]};
+ float magnitude = translate[0] * translate[0] +
+ translate[1] * translate[1] +
+ translate[2] * translate[2];
+
+ return (magnitude < _radius * _radius) ? true : false;
+}
diff --git a/intern/smoke/intern/SPHERE.h b/intern/smoke/intern/SPHERE.h
new file mode 100644
index 00000000000..d5a232e0242
--- /dev/null
+++ b/intern/smoke/intern/SPHERE.h
@@ -0,0 +1,44 @@
+/** \file smoke/intern/SPHERE.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// SPHERE.h: interface for the SPHERE class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#ifndef SPHERE_H
+#define SPHERE_H
+
+#include "OBSTACLE.h"
+
+class SPHERE : public OBSTACLE
+{
+public:
+ SPHERE(float x, float y, float z, float radius);
+ virtual ~SPHERE();
+
+ bool inside(float x, float y, float z);
+
+private:
+ float _center[3];
+ float _radius;
+};
+
+#endif
diff --git a/intern/smoke/intern/util/vectorbase.h b/intern/smoke/intern/VEC3.h
index 2adfeebc5f7..63ce68566a9 100644
--- a/intern/smoke/intern/util/vectorbase.h
+++ b/intern/smoke/intern/VEC3.h
@@ -1,36 +1,19 @@
+/** \file smoke/intern/VEC3.h
+ * \ingroup smoke
+ */
/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Vector class
- *
+ * Copyright 2007 Nils Thuerey
+ * Basic vector class
*****************************************************************************/
+#ifndef BASICVECTOR_H
+#define BASICVECTOR_H
-
-#ifndef DDF_BASICVEC_H
-#define DDF_BASICVEC_H
-
-// get rid of windos min/max defines
-#ifdef WIN32
-#define NOMINMAX
-#endif
-
-#include <stdio.h>
#include <math.h>
#include <stdlib.h>
+#include <stdio.h>
#include <iostream>
#include <sstream>
-// if min/max are still around...
-#ifdef WIN32
-#undef min
-#undef max
-#endif
-
// use which fp-precision? 1=float, 2=double
#ifndef FLOATINGPOINT_PRECISION
#if DDF_DEBUG==1
@@ -40,12 +23,23 @@
#endif // DDF_DEBUG==1
#endif
-// dimension of solver&problem
-#ifndef DDF_DIM
-#define DDF_DIM 3
+// VECTOR_EPSILON is the minimal vector length
+// In order to be able to discriminate floating point values near zero, and
+// to be sure not to fail a comparison because of roundoff errors, use this
+// value as a threshold.
+
+#if FLOATINGPOINT_PRECISION==1
+typedef float Real;
+#define FP_REAL_MAX __FLT_MAX__
+#define VECTOR_EPSILON (1e-5f)
+#else
+typedef double Real;
+#define FP_REAL_MAX __DBL_MAX__
+#define VECTOR_EPSILON (1e-10)
#endif
-// windos, hardcoded limits for now...
+
+// hardcoded limits for now...
// for e.g. MSVC compiler...
// some of these defines can be needed
// for linux systems as well (e.g. FLT_MAX)
@@ -64,102 +58,100 @@
# endif // DBL_MAX
#endif // __DBL_MAX__
+#ifndef FLT_MAX
+#define FLT_MAX __FLT_MAX__
+#endif
+
+#ifndef DBL_MAX
+#define DBL_MAX __DBL_MAX__
+#endif
+
#ifndef M_PI
# define M_PI 3.1415926536
# define M_E 2.7182818284
#endif
-namespace DDF {
+
+namespace BasicVector {
// basic inlined vector class
template<class Scalar>
-class ntlVector3Dim
+class Vector3Dim
{
public:
// Constructor
- inline ntlVector3Dim();
+ inline Vector3Dim();
// Copy-Constructor
- inline ntlVector3Dim(const ntlVector3Dim<Scalar> &v );
- inline ntlVector3Dim(const float *);
- inline ntlVector3Dim(const double *);
+ inline Vector3Dim(const Vector3Dim<Scalar> &v );
+ inline Vector3Dim(const float *);
+ inline Vector3Dim(const double *);
// construct a vector from one Scalar
- inline ntlVector3Dim(Scalar);
+ inline Vector3Dim(Scalar);
// construct a vector from three Scalars
- inline ntlVector3Dim(Scalar, Scalar, Scalar);
+ inline Vector3Dim(Scalar, Scalar, Scalar);
// get address of array for OpenGL
Scalar *getAddress() { return value; }
// Assignment operator
- inline const ntlVector3Dim<Scalar>& operator= (const ntlVector3Dim<Scalar>& v);
+ inline const Vector3Dim<Scalar>& operator= (const Vector3Dim<Scalar>& v);
// Assignment operator
- inline const ntlVector3Dim<Scalar>& operator= (Scalar s);
+ inline const Vector3Dim<Scalar>& operator= (Scalar s);
// Assign and add operator
- inline const ntlVector3Dim<Scalar>& operator+= (const ntlVector3Dim<Scalar>& v);
+ inline const Vector3Dim<Scalar>& operator+= (const Vector3Dim<Scalar>& v);
// Assign and add operator
- inline const ntlVector3Dim<Scalar>& operator+= (Scalar s);
+ inline const Vector3Dim<Scalar>& operator+= (Scalar s);
// Assign and sub operator
- inline const ntlVector3Dim<Scalar>& operator-= (const ntlVector3Dim<Scalar>& v);
+ inline const Vector3Dim<Scalar>& operator-= (const Vector3Dim<Scalar>& v);
// Assign and sub operator
- inline const ntlVector3Dim<Scalar>& operator-= (Scalar s);
+ inline const Vector3Dim<Scalar>& operator-= (Scalar s);
// Assign and mult operator
- inline const ntlVector3Dim<Scalar>& operator*= (const ntlVector3Dim<Scalar>& v);
+ inline const Vector3Dim<Scalar>& operator*= (const Vector3Dim<Scalar>& v);
// Assign and mult operator
- inline const ntlVector3Dim<Scalar>& operator*= (Scalar s);
+ inline const Vector3Dim<Scalar>& operator*= (Scalar s);
// Assign and div operator
- inline const ntlVector3Dim<Scalar>& operator/= (const ntlVector3Dim<Scalar>& v);
+ inline const Vector3Dim<Scalar>& operator/= (const Vector3Dim<Scalar>& v);
// Assign and div operator
- inline const ntlVector3Dim<Scalar>& operator/= (Scalar s);
+ inline const Vector3Dim<Scalar>& operator/= (Scalar s);
// unary operator
- inline ntlVector3Dim<Scalar> operator- () const;
+ inline Vector3Dim<Scalar> operator- () const;
// binary operator add
- inline ntlVector3Dim<Scalar> operator+ (const ntlVector3Dim<Scalar>&) const;
+ inline Vector3Dim<Scalar> operator+ (const Vector3Dim<Scalar>&) const;
// binary operator add
- inline ntlVector3Dim<Scalar> operator+ (Scalar) const;
+ inline Vector3Dim<Scalar> operator+ (Scalar) const;
// binary operator sub
- inline ntlVector3Dim<Scalar> operator- (const ntlVector3Dim<Scalar>&) const;
+ inline Vector3Dim<Scalar> operator- (const Vector3Dim<Scalar>&) const;
// binary operator sub
- inline ntlVector3Dim<Scalar> operator- (Scalar) const;
+ inline Vector3Dim<Scalar> operator- (Scalar) const;
// binary operator mult
- inline ntlVector3Dim<Scalar> operator* (const ntlVector3Dim<Scalar>&) const;
+ inline Vector3Dim<Scalar> operator* (const Vector3Dim<Scalar>&) const;
// binary operator mult
- inline ntlVector3Dim<Scalar> operator* (Scalar) const;
+ inline Vector3Dim<Scalar> operator* (Scalar) const;
// binary operator div
- inline ntlVector3Dim<Scalar> operator/ (const ntlVector3Dim<Scalar>&) const;
+ inline Vector3Dim<Scalar> operator/ (const Vector3Dim<Scalar>&) const;
// binary operator div
- inline ntlVector3Dim<Scalar> operator/ (Scalar) const;
+ inline Vector3Dim<Scalar> operator/ (Scalar) const;
// Projection normal to a vector
- inline ntlVector3Dim<Scalar> getOrthogonalntlVector3Dim() const;
+ inline Vector3Dim<Scalar> getOrthogonalntlVector3Dim() const;
// Project into a plane
- inline const ntlVector3Dim<Scalar>& projectNormalTo(const ntlVector3Dim<Scalar> &v);
+ inline const Vector3Dim<Scalar>& projectNormalTo(const Vector3Dim<Scalar> &v);
- inline Scalar min() const { return (x<y) ? ( (x<z) ? x:z ) : ( (y<z) ? y:z); }
- inline Scalar max() const { return (x>y) ? ( (x>z) ? x:z ) : ( (y>z) ? y:z); }
-
// minimize
- inline const ntlVector3Dim<Scalar> &minimize(const ntlVector3Dim<Scalar> &);
+ inline const Vector3Dim<Scalar> &minimize(const Vector3Dim<Scalar> &);
// maximize
- inline const ntlVector3Dim<Scalar> &maximize(const ntlVector3Dim<Scalar> &);
+ inline const Vector3Dim<Scalar> &maximize(const Vector3Dim<Scalar> &);
// access operator
inline Scalar& operator[](unsigned int i);
// access operator
inline const Scalar& operator[](unsigned int i) const;
- // return absolutes of all components
- inline ntlVector3Dim<Scalar> getAbsolutes() const { return
- ntlVector3Dim<Scalar>(fabs(value[0]), fabs(value[1]), fabs(value[2]) );
- };
-
- // debug output vector to a string
- std::string toString();
-
//! actual values
union {
struct {
@@ -176,33 +168,6 @@ public:
Scalar Z;
};
};
-
- // expe compatibility functions
- void makeFloor(const ntlVector3Dim<Scalar>& cmp);
- void makeCeil(const ntlVector3Dim<Scalar>& cmp);
- Scalar squaredDistanceTo(const ntlVector3Dim<Scalar>& vec) const;
-
- // Returns true if the vector's s components are all greater that the ones of the vector it is compared against.
- inline bool operator < ( const ntlVector3Dim<Scalar>& vec ) const;
- // Returns true if the vector's s components are all greater or equal that the ones of the vector it is compared against.
- inline bool operator <= ( const ntlVector3Dim<Scalar>& vec ) const;
- // Returns true if the vector's s components are all smaller that the ones of the vector it is compared against.
- inline bool operator > ( const ntlVector3Dim<Scalar>& vec ) const;
- // Returns true if the vector's s components are all smaller or equal that the ones of the vector it is compared against.
- inline bool operator >= ( const ntlVector3Dim<Scalar>& vec ) const;
-
- // Return the maximal component value.
- inline Scalar maxComponent(void) const;
- // Return the minimal component value.
- inline Scalar minComponent(void) const;
- // Return the index of the maximal coordinate value.
- inline int maxComponentId(void) const;
- // Return the index of the minimal coordinate value.
- inline int minComponentId(void) const;
-
- // zero element
- static const ntlVector3Dim<Scalar> ZERO;
-
protected:
};
@@ -210,24 +175,6 @@ protected:
-// VECTOR_EPSILON is the minimal vector length
-// In order to be able to discriminate floating point values near zero, and
-// to be sure not to fail a comparison because of roundoff errors, use this
-// value as a threshold.
-
-#if FLOATINGPOINT_PRECISION==1
-typedef float Real;
-#define FP_REAL_MAX __FLT_MAX__
-#define VECTOR_EPSILON (1e-5f)
-#else
-typedef double Real;
-#define FP_REAL_MAX __DBL_MAX__
-#define VECTOR_EPSILON (1e-10)
-#endif
-// as variable in globals.cpp
-extern const Real gVecEpsilon;
-
-
//------------------------------------------------------------------------------
// VECTOR inline FUNCTIONS
@@ -239,7 +186,7 @@ extern const Real gVecEpsilon;
Constructor.
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>::ntlVector3Dim( void )
+inline Vector3Dim<Scalar>::Vector3Dim( void )
{
value[0] = value[1] = value[2] = 0;
}
@@ -250,25 +197,25 @@ inline ntlVector3Dim<Scalar>::ntlVector3Dim( void )
Copy-Constructor.
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>::ntlVector3Dim( const ntlVector3Dim<Scalar> &v )
+inline Vector3Dim<Scalar>::Vector3Dim( const Vector3Dim<Scalar> &v )
{
- value[0] = v.value[0];
- value[1] = v.value[1];
- value[2] = v.value[2];
+ value[0] = v.value[0];
+ value[1] = v.value[1];
+ value[2] = v.value[2];
}
- template<class Scalar>
-inline ntlVector3Dim<Scalar>::ntlVector3Dim( const float *fvalue)
+template<class Scalar>
+inline Vector3Dim<Scalar>::Vector3Dim( const float *fvalue)
{
- value[0] = (Scalar)fvalue[0];
- value[1] = (Scalar)fvalue[1];
- value[2] = (Scalar)fvalue[2];
+ value[0] = (Scalar)fvalue[0];
+ value[1] = (Scalar)fvalue[1];
+ value[2] = (Scalar)fvalue[2];
}
- template<class Scalar>
-inline ntlVector3Dim<Scalar>::ntlVector3Dim( const double *fvalue)
+template<class Scalar>
+inline Vector3Dim<Scalar>::Vector3Dim( const double *fvalue)
{
- value[0] = (Scalar)fvalue[0];
- value[1] = (Scalar)fvalue[1];
- value[2] = (Scalar)fvalue[2];
+ value[0] = (Scalar)fvalue[0];
+ value[1] = (Scalar)fvalue[1];
+ value[2] = (Scalar)fvalue[2];
}
@@ -280,7 +227,7 @@ inline ntlVector3Dim<Scalar>::ntlVector3Dim( const double *fvalue)
\return The new vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>::ntlVector3Dim(Scalar s )
+inline Vector3Dim<Scalar>::Vector3Dim(Scalar s )
{
value[0]= s;
value[1]= s;
@@ -296,7 +243,7 @@ inline ntlVector3Dim<Scalar>::ntlVector3Dim(Scalar s )
\return The new vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>::ntlVector3Dim(Scalar s1, Scalar s2, Scalar s3)
+inline Vector3Dim<Scalar>::Vector3Dim(Scalar s1, Scalar s2, Scalar s3)
{
value[0]= s1;
value[1]= s2;
@@ -304,29 +251,15 @@ inline ntlVector3Dim<Scalar>::ntlVector3Dim(Scalar s1, Scalar s2, Scalar s3)
}
-/*************************************************************************
- Compute the vector product of two 3D vectors
- \param v Second vector to compute the product with
- \return A new vector with the product values
- */
-/*template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator^( const ntlVector3Dim<Scalar> &v ) const
-{
- return ntlVector3Dim<Scalar>(value[1]*v.value[2] - value[2]*v.value[1],
- value[2]*v.value[0] - value[0]*v.value[2],
- value[0]*v.value[1] - value[1]*v.value[0]);
-}*/
-
/*************************************************************************
- Copy a ntlVector3Dim componentwise.
+ Copy a Vector3Dim componentwise.
\param v vector with values to be copied
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator=( const ntlVector3Dim<Scalar> &v )
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator=( const Vector3Dim<Scalar> &v )
{
value[0] = v.value[0];
value[1] = v.value[1];
@@ -341,8 +274,8 @@ ntlVector3Dim<Scalar>::operator=( const ntlVector3Dim<Scalar> &v )
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator=(Scalar s)
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator=(Scalar s)
{
value[0] = s;
value[1] = s;
@@ -352,13 +285,13 @@ ntlVector3Dim<Scalar>::operator=(Scalar s)
/*************************************************************************
- Add another ntlVector3Dim componentwise.
+ Add another Vector3Dim componentwise.
\param v vector with values to be added
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator+=( const ntlVector3Dim<Scalar> &v )
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator+=( const Vector3Dim<Scalar> &v )
{
value[0] += v.value[0];
value[1] += v.value[1];
@@ -373,8 +306,8 @@ ntlVector3Dim<Scalar>::operator+=( const ntlVector3Dim<Scalar> &v )
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator+=(Scalar s)
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator+=(Scalar s)
{
value[0] += s;
value[1] += s;
@@ -389,8 +322,8 @@ ntlVector3Dim<Scalar>::operator+=(Scalar s)
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator-=( const ntlVector3Dim<Scalar> &v )
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator-=( const Vector3Dim<Scalar> &v )
{
value[0] -= v.value[0];
value[1] -= v.value[1];
@@ -405,8 +338,8 @@ ntlVector3Dim<Scalar>::operator-=( const ntlVector3Dim<Scalar> &v )
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator-=(Scalar s)
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator-=(Scalar s)
{
value[0]-= s;
value[1]-= s;
@@ -421,8 +354,8 @@ ntlVector3Dim<Scalar>::operator-=(Scalar s)
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator*=( const ntlVector3Dim<Scalar> &v )
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator*=( const Vector3Dim<Scalar> &v )
{
value[0] *= v.value[0];
value[1] *= v.value[1];
@@ -437,8 +370,8 @@ ntlVector3Dim<Scalar>::operator*=( const ntlVector3Dim<Scalar> &v )
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator*=(Scalar s)
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator*=(Scalar s)
{
value[0] *= s;
value[1] *= s;
@@ -448,13 +381,13 @@ ntlVector3Dim<Scalar>::operator*=(Scalar s)
/*************************************************************************
- Divide by another ntlVector3Dim componentwise.
+ Divide by another Vector3Dim componentwise.
\param v vector of values to divide by
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator/=( const ntlVector3Dim<Scalar> &v )
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator/=( const Vector3Dim<Scalar> &v )
{
value[0] /= v.value[0];
value[1] /= v.value[1];
@@ -469,8 +402,8 @@ ntlVector3Dim<Scalar>::operator/=( const ntlVector3Dim<Scalar> &v )
\return Reference to self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::operator/=(Scalar s)
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::operator/=(Scalar s)
{
value[0] /= s;
value[1] /= s;
@@ -489,10 +422,10 @@ ntlVector3Dim<Scalar>::operator/=(Scalar s)
\return The new (negative) vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator-() const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator-() const
{
- return ntlVector3Dim<Scalar>(-value[0], -value[1], -value[2]);
+ return Vector3Dim<Scalar>(-value[0], -value[1], -value[2]);
}
@@ -508,10 +441,10 @@ ntlVector3Dim<Scalar>::operator-() const
\return The sum vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator+( const ntlVector3Dim<Scalar> &v ) const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator+( const Vector3Dim<Scalar> &v ) const
{
- return ntlVector3Dim<Scalar>(value[0]+v.value[0],
+ return Vector3Dim<Scalar>(value[0]+v.value[0],
value[1]+v.value[1],
value[2]+v.value[2]);
}
@@ -523,10 +456,10 @@ ntlVector3Dim<Scalar>::operator+( const ntlVector3Dim<Scalar> &v ) const
\return The sum vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator+(Scalar s) const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator+(Scalar s) const
{
- return ntlVector3Dim<Scalar>(value[0]+s,
+ return Vector3Dim<Scalar>(value[0]+s,
value[1]+s,
value[2]+s);
}
@@ -538,10 +471,10 @@ ntlVector3Dim<Scalar>::operator+(Scalar s) const
\return The difference vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator-( const ntlVector3Dim<Scalar> &v ) const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator-( const Vector3Dim<Scalar> &v ) const
{
- return ntlVector3Dim<Scalar>(value[0]-v.value[0],
+ return Vector3Dim<Scalar>(value[0]-v.value[0],
value[1]-v.value[1],
value[2]-v.value[2]);
}
@@ -553,10 +486,10 @@ ntlVector3Dim<Scalar>::operator-( const ntlVector3Dim<Scalar> &v ) const
\return The difference vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator-(Scalar s ) const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator-(Scalar s ) const
{
- return ntlVector3Dim<Scalar>(value[0]-s,
+ return Vector3Dim<Scalar>(value[0]-s,
value[1]-s,
value[2]-s);
}
@@ -569,48 +502,38 @@ ntlVector3Dim<Scalar>::operator-(Scalar s ) const
\return The product vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator*( const ntlVector3Dim<Scalar>& v) const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator*( const Vector3Dim<Scalar>& v) const
{
- return ntlVector3Dim<Scalar>(value[0]*v.value[0],
+ return Vector3Dim<Scalar>(value[0]*v.value[0],
value[1]*v.value[1],
value[2]*v.value[2]);
}
/*************************************************************************
- Build a ntlVector3Dim with a Scalar value multiplied to each component.
+ Build a Vector3Dim with a Scalar value multiplied to each component.
\param s The Scalar value to multiply with
\return The product vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator*(Scalar s) const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator*(Scalar s) const
{
- return ntlVector3Dim<Scalar>(value[0]*s, value[1]*s, value[2]*s);
+ return Vector3Dim<Scalar>(value[0]*s, value[1]*s, value[2]*s);
}
-// allow multiplications of the form: v2 = 3 * v1
-template<class Scalar>
-inline ntlVector3Dim<Scalar>
-operator*(Scalar s, ntlVector3Dim<Scalar> v)
-{
- return ntlVector3Dim<Scalar>(v.value[0]*s, v.value[1]*s, v.value[2]*s);
-}
-
-
-
/*************************************************************************
Build a vector divided componentwise by another vector.
\param v The second vector to divide by
\return The ratio vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator/(const ntlVector3Dim<Scalar>& v) const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator/(const Vector3Dim<Scalar>& v) const
{
- return ntlVector3Dim<Scalar>(value[0]/v.value[0],
+ return Vector3Dim<Scalar>(value[0]/v.value[0],
value[1]/v.value[1],
value[2]/v.value[2]);
}
@@ -623,10 +546,10 @@ ntlVector3Dim<Scalar>::operator/(const ntlVector3Dim<Scalar>& v) const
\return The ratio vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::operator/(Scalar s) const
+inline Vector3Dim<Scalar>
+Vector3Dim<Scalar>::operator/(Scalar s) const
{
- return ntlVector3Dim<Scalar>(value[0]/s,
+ return Vector3Dim<Scalar>(value[0]/s,
value[1]/s,
value[2]/s);
}
@@ -642,7 +565,7 @@ ntlVector3Dim<Scalar>::operator/(Scalar s) const
*/
template<class Scalar>
inline Scalar&
-ntlVector3Dim<Scalar>::operator[]( unsigned int i )
+Vector3Dim<Scalar>::operator[]( unsigned int i )
{
return value[i];
}
@@ -655,7 +578,7 @@ ntlVector3Dim<Scalar>::operator[]( unsigned int i )
*/
template<class Scalar>
inline const Scalar&
-ntlVector3Dim<Scalar>::operator[]( unsigned int i ) const
+Vector3Dim<Scalar>::operator[]( unsigned int i ) const
{
return value[i];
}
@@ -674,7 +597,7 @@ ntlVector3Dim<Scalar>::operator[]( unsigned int i ) const
\return The value of the scalar product
*/
template<class Scalar>
-inline Scalar dot(const ntlVector3Dim<Scalar> &t, const ntlVector3Dim<Scalar> &v )
+inline Scalar dot(const Vector3Dim<Scalar> &t, const Vector3Dim<Scalar> &v )
{
//return t.value[0]*v.value[0] + t.value[1]*v.value[1] + t.value[2]*v.value[2];
return ((t[0]*v[0]) + (t[1]*v[1]) + (t[2]*v[2]));
@@ -685,9 +608,9 @@ inline Scalar dot(const ntlVector3Dim<Scalar> &t, const ntlVector3Dim<Scalar> &v
Calculate the cross product of this and another vector
*/
template<class Scalar>
-inline ntlVector3Dim<Scalar> cross(const ntlVector3Dim<Scalar> &t, const ntlVector3Dim<Scalar> &v)
+inline Vector3Dim<Scalar> cross(const Vector3Dim<Scalar> &t, const Vector3Dim<Scalar> &v)
{
- ntlVector3Dim<Scalar> cp(
+ Vector3Dim<Scalar> cp(
((t[1]*v[2]) - (t[2]*v[1])),
((t[2]*v[0]) - (t[0]*v[2])),
((t[0]*v[1]) - (t[1]*v[0])) );
@@ -703,22 +626,22 @@ inline ntlVector3Dim<Scalar> cross(const ntlVector3Dim<Scalar> &t, const ntlVect
\return The orthonormal vector
*/
template<class Scalar>
-ntlVector3Dim<Scalar>
-ntlVector3Dim<Scalar>::getOrthogonalntlVector3Dim() const
+Vector3Dim<Scalar>
+Vector3Dim<Scalar>::getOrthogonalntlVector3Dim() const
{
- // Determine the component with max. absolute value
- int maxIndex= (fabs(value[0]) > fabs(value[1])) ? 0 : 1;
- maxIndex= (fabs(value[maxIndex]) > fabs(value[2])) ? maxIndex : 2;
-
- /*************************************************************************
- Choose another axis than the one with max. component and project
- orthogonal to self
- */
- ntlVector3Dim<Scalar> vec(0.0);
- vec[(maxIndex+1)%3]= 1;
- vec.normalize();
- vec.projectNormalTo(this->getNormalized());
- return vec;
+ // Determine the component with max. absolute value
+ int max= (fabs(value[0]) > fabs(value[1])) ? 0 : 1;
+ max= (fabs(value[max]) > fabs(value[2])) ? max : 2;
+
+ /*************************************************************************
+ Choose another axis than the one with max. component and project
+ orthogonal to self
+ */
+ Vector3Dim<Scalar> vec(0.0);
+ vec[(max+1)%3]= 1;
+ vec.normalize();
+ vec.projectNormalTo(this->getNormalized());
+ return vec;
}
@@ -729,14 +652,14 @@ ntlVector3Dim<Scalar>::getOrthogonalntlVector3Dim() const
\return The projected vector
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar>&
-ntlVector3Dim<Scalar>::projectNormalTo(const ntlVector3Dim<Scalar> &v)
+inline const Vector3Dim<Scalar>&
+Vector3Dim<Scalar>::projectNormalTo(const Vector3Dim<Scalar> &v)
{
- Scalar sprod = dot(*this,v);
- value[0]= value[0] - v.value[0] * sprod;
- value[1]= value[1] - v.value[1] * sprod;
- value[2]= value[2] - v.value[2] * sprod;
- return *this;
+ Scalar sprod = dot(*this,v);
+ value[0]= value[0] - v.value[0] * sprod;
+ value[1]= value[1] - v.value[1] * sprod;
+ value[2]= value[2] - v.value[2] * sprod;
+ return *this;
}
@@ -754,8 +677,8 @@ ntlVector3Dim<Scalar>::projectNormalTo(const ntlVector3Dim<Scalar> &v)
\return Reference to the modified self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar> &
-ntlVector3Dim<Scalar>::minimize(const ntlVector3Dim<Scalar> &pnt)
+inline const Vector3Dim<Scalar> &
+Vector3Dim<Scalar>::minimize(const Vector3Dim<Scalar> &pnt)
{
for (unsigned int i = 0; i < 3; i++)
value[i] = MIN(value[i],pnt[i]);
@@ -771,8 +694,8 @@ ntlVector3Dim<Scalar>::minimize(const ntlVector3Dim<Scalar> &pnt)
\return Reference to the modified self
*/
template<class Scalar>
-inline const ntlVector3Dim<Scalar> &
-ntlVector3Dim<Scalar>::maximize(const ntlVector3Dim<Scalar> &pnt)
+inline const Vector3Dim<Scalar> &
+Vector3Dim<Scalar>::maximize(const Vector3Dim<Scalar> &pnt)
{
for (unsigned int i = 0; i < 3; i++)
value[i] = MAX(value[i],pnt[i]);
@@ -788,7 +711,7 @@ ntlVector3Dim<Scalar>::maximize(const ntlVector3Dim<Scalar> &pnt)
// HELPER FUNCTIONS, independent of implementation
/************************************************************************/
-#define VECTOR_TYPE ntlVector3Dim<Scalar>
+#define VECTOR_TYPE Vector3Dim<Scalar>
/*************************************************************************
@@ -803,7 +726,7 @@ inline Scalar norm( const VECTOR_TYPE &v)
}
// for e.g. min max operator
-inline Real normHelper(const ntlVector3Dim<Real> &v) {
+inline Real normHelper(const Vector3Dim<Real> &v) {
return norm(v);
}
inline Real normHelper(const Real &v) {
@@ -816,10 +739,11 @@ inline Real normHelper(const int &v) {
/*************************************************************************
Same as getNorm but doesnt sqrt
- */
+ */
template<class Scalar>
-inline Scalar normNoSqrt( const VECTOR_TYPE &v) {
- return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
+inline Scalar normNoSqrt( const VECTOR_TYPE &v)
+{
+ return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
}
@@ -830,67 +754,41 @@ inline Scalar normNoSqrt( const VECTOR_TYPE &v) {
template<class Scalar>
inline VECTOR_TYPE getNormalized( const VECTOR_TYPE &v)
{
- Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
- if (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON)
- return v; /* normalized "enough"... */
- else if (l > VECTOR_EPSILON*VECTOR_EPSILON)
- {
- Scalar fac = 1./sqrt(l);
- return VECTOR_TYPE(v[0]*fac, v[1]*fac, v[2]*fac);
- }
- else
- return VECTOR_TYPE((Scalar)0);
+ Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
+ if (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON)
+ return v; /* normalized "enough"... */
+ else if (l > VECTOR_EPSILON*VECTOR_EPSILON)
+ {
+ Scalar fac = 1./sqrt(l);
+ return VECTOR_TYPE(v[0]*fac, v[1]*fac, v[2]*fac);
+ }
+ else
+ return VECTOR_TYPE((Scalar)0);
}
/*************************************************************************
Compute the norm of the vector and normalize it.
\return The value of the norm
- */
- template<class Scalar>
+ */
+template<class Scalar>
inline Scalar normalize( VECTOR_TYPE &v)
{
- Scalar norm;
- Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
- if (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON) {
- norm = 1.;
+ Scalar norm;
+ Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
+ if (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON) {
+ norm = 1.;
} else if (l > VECTOR_EPSILON*VECTOR_EPSILON) {
- norm = sqrt(l);
- Scalar fac = 1./norm;
- v[0] *= fac;
- v[1] *= fac;
- v[2] *= fac;
+ norm = sqrt(l);
+ Scalar fac = 1./norm;
+ v[0] *= fac;
+ v[1] *= fac;
+ v[2] *= fac;
} else {
- v[0]= v[1]= v[2]= 0;
- norm = 0.;
- }
- return (Scalar)norm;
-}
-
-/*************************************************************************
- Stable vector to angle conversion
- \return unique Angles in the of phi=[0,2PI], th=[0,PI]
- */
- template<class Scalar>
-inline void vecToAngle(const VECTOR_TYPE &v, Scalar& phi, Scalar& theta)
-{
- if (fabs(v.y) < VECTOR_EPSILON)
- theta = M_PI/2;
- else if (fabs(v.x) < VECTOR_EPSILON && fabs(v.z) < VECTOR_EPSILON )
- theta = (v.y>=0) ? 0:M_PI;
- else
- theta = atan(sqrt(v.x*v.x+v.z*v.z)/v.y);
- if (theta<0) theta+=M_PI;
-
- if (fabs(v.x) < VECTOR_EPSILON)
- phi = M_PI/2;
- else
- phi = atan(v.z/v.x);
- if (phi<0) phi+=M_PI;
- if (fabs(v.z) < VECTOR_EPSILON)
- phi = (v.x>=0) ? 0 : M_PI;
- else if (v.z < 0)
- phi += M_PI;
+ v[0]= v[1]= v[2]= 0;
+ norm = 0.;
+ }
+ return (Scalar)norm;
}
@@ -1030,7 +928,10 @@ inline void hsvToRgb( VECTOR_TYPE &V )
//! global string for formatting vector output in utilities.cpp
-extern const char *globVecFormatStr;
+//extern const char *globVecFormatStr;
+#if 0
+static const char *globVecFormatStr = "[%6.4f,%6.4f,%6.4f]";
+#endif
/*************************************************************************
Outputs the object in human readable form using the format
@@ -1038,178 +939,51 @@ extern const char *globVecFormatStr;
*/
template<class Scalar>
std::ostream&
-operator<<( std::ostream& os, const DDF::ntlVector3Dim<Scalar>& i )
+operator<<( std::ostream& os, const BasicVector::Vector3Dim<Scalar>& i )
{
+#if 0
char buf[256];
- snprintf(buf,256,globVecFormatStr, (double)i[0],(double)i[1],(double)i[2]);
+#if _WIN32
+ sprintf(buf,globVecFormatStr, (double)i[0],(double)i[1],(double)i[2]);
+#else
+ snprintf(buf,256,globVecFormatStr, (double)i[0],(double)i[1],(double)i[2]);
+#endif
os << std::string(buf);
- //os << '[' << i[0] << ", " << i[1] << ", " << i[2] << ']';
- return os;
+#endif
+ return os;
}
-
/*************************************************************************
Reads the contents of the object from a stream using the same format
as the output operator.
*/
template<class Scalar>
std::istream&
-operator>>( std::istream& is, DDF::ntlVector3Dim<Scalar>& i )
+operator>>( std::istream& is, BasicVector::Vector3Dim<Scalar>& i )
{
- char c;
- char dummy[3];
- is >> c >> i[0] >> dummy >> i[1] >> dummy >> i[2] >> c;
- return is;
-}
-
-// helper function for output
-template<class Scalar> std::string ntlVector3Dim<Scalar>::toString() {
- char buf[256];
- snprintf(buf,256,globVecFormatStr, (double)(*this)[0],(double)(*this)[1],(double)(*this)[2]);
- return std::string(buf);
+ char c;
+ char dummy[3];
+ is >> c >> i[0] >> dummy >> i[1] >> dummy >> i[2] >> c;
+ return is;
}
-// helper function for output
-template<class Vec> bool intVecIsEqual(Vec a, Vec b) {
- return a[0]==b[0] && a[1]==b[1] && a[2]==b[2];
-}
/**************************************************************************/
// typedefs!
/**************************************************************************/
-// a 3D vector with double precision
-typedef ntlVector3Dim<double> nVec3d;
-
-// a 3D vector with single precision
-typedef ntlVector3Dim<float> nVec3f;
-
-// a 3D integer vector
-typedef ntlVector3Dim<int> nVec3i;
-
-/* convert int,float and double vectors */
-template<class T> inline nVec3i vec2I(T v) { return nVec3i((int)v[0],(int)v[1],(int)v[2]); }
-template<class T> inline nVec3i vec2I(T v0, T v1, T v2) { return nVec3i((int)v0,(int)v1,(int)v2); }
-template<class T> inline nVec3d vec2D(T v) { return nVec3d(v[0],v[1],v[2]); }
-template<class T> inline nVec3i vec2D(T v0, T v1, T v2) { return nVec3d((double)v0,(double)v1,(double)v2); }
-template<class T> inline nVec3f vec2F(T v) { return nVec3f(v[0],v[1],v[2]); }
-template<class T> inline nVec3i vec2F(T v0, T v1, T v2) { return nVec3f((float)v0,(float)v1,(float)v2); }
-template<class T> inline nVec3i vecround(T v) { return nVec3i((int)round(v[0]),(int)round(v[1]),(int)round(v[2])); }
-
-
-
-/************************************************************************/
-// default vector typing
-
-
-// a 3D vector for graphics output, typically float?
-typedef ntlVector3Dim<Real> Vec3;
-
-/* convert to Real vec */
-template<class T> inline Vec3 vec2R(T v) { return Vec3(v[0],v[1],v[2]); }
-
-
/* get minimal vector length value that can be discriminated. */
inline Real getVecEpsilon() { return (Real)VECTOR_EPSILON; }
-// expe compatibility functions
-
-//template<class Scalar>
-//inline XXX ntlVector3Dim<Scalar>::
-
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline Scalar ntlVector3Dim<Scalar>::squaredDistanceTo(const ntlVector3Dim<Scalar>& vec) const
-{
- Scalar dx,dy,dz;
- dx = x-vec.x;
- dy = y-vec.y;
- dz = z-vec.z;
- return dx*dx + dy*dy + dz*dz;
-}
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline void ntlVector3Dim<Scalar>::makeFloor(const ntlVector3Dim<Scalar>& cmp)
-{
- if( cmp.x < x ) x = cmp.x;
- if( cmp.y < y ) y = cmp.y;
- if( cmp.z < z ) z = cmp.z;
-}
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline void ntlVector3Dim<Scalar>::makeCeil(const ntlVector3Dim<Scalar>& cmp)
-{
- if( cmp.x > x ) x = cmp.x;
- if( cmp.y > y ) y = cmp.y;
- if( cmp.z > z ) z = cmp.z;
-}
+// a 3D integer vector
+typedef Vector3Dim<int> Vec3Int;
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline bool ntlVector3Dim<Scalar>::operator < ( const ntlVector3Dim<Scalar>& vec ) const
-{
- if( x < vec.x && y < vec.y && z < vec.z )
- return true;
- return false;
-}
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline bool ntlVector3Dim<Scalar>::operator <= ( const ntlVector3Dim<Scalar>& vec ) const
-{
- if( x <= vec.x && y <= vec.y && z <= vec.z )
- return true;
- return false;
-}
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline bool ntlVector3Dim<Scalar>::operator > ( const ntlVector3Dim<Scalar>& vec ) const
-{
- if( x > vec.x && y > vec.y && z > vec.z )
- return true;
- return false;
-}
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline bool ntlVector3Dim<Scalar>::operator >= ( const ntlVector3Dim<Scalar>& vec ) const
-{
- if( x >= vec.x && y >= vec.y && z >= vec.z )
- return true;
- return false;
-}
+// a 3D vector
+typedef Vector3Dim<Real> Vec3;
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline Scalar ntlVector3Dim<Scalar>::maxComponent(void) const
-{
- return VMAX(*this);
-}
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline Scalar ntlVector3Dim<Scalar>::minComponent(void) const
-{
- return VMIN(*this);
-}
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline int ntlVector3Dim<Scalar>::maxComponentId(void) const
-{
- if (x<y)
- return (y<z ? 2 : 1);
- else
- return (x<z ? 2 : 0);
-}
-//--------------------------------------------------------------------------------
-template<class Scalar>
-inline int ntlVector3Dim<Scalar>::minComponentId(void) const
-{
- if (x<y)
- return (x<z ? 0 : 2);
- else
- return (y<Z ? 1 : 2);
-}
-}; // namespace DDF
+}; // namespace
-#endif /* DDF_BASICVEC_H */
+#endif /* BASICVECTOR_H */
diff --git a/intern/smoke/intern/WAVELET_NOISE.h b/intern/smoke/intern/WAVELET_NOISE.h
new file mode 100644
index 00000000000..66dfb95d143
--- /dev/null
+++ b/intern/smoke/intern/WAVELET_NOISE.h
@@ -0,0 +1,517 @@
+/** \file smoke/intern/WAVELET_NOISE.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+//////////////////////////////////////////////////////////////////////////////////////////
+// Wavelet noise functions
+//
+// This code is based on the C code provided in the appendices of:
+//
+// @article{1073264,
+// author = {Robert L. Cook and Tony DeRose},
+// title = {Wavelet noise},
+// journal = {ACM Trans. Graph.},
+// volume = {24},
+// number = {3},
+// year = {2005},
+// issn = {0730-0301},
+// pages = {803--811},
+// doi = {http://doi.acm.org/10.1145/1073204.1073264},
+// publisher = {ACM},
+// address = {New York, NY, USA},
+// }
+//
+//////////////////////////////////////////////////////////////////////////////////////////
+
+#ifndef WAVELET_NOISE_H
+#define WAVELET_NOISE_H
+
+#include <MERSENNETWISTER.h>
+
+#ifdef WIN32
+#include <float.h>
+#define isnan _isnan
+#endif
+
+// Tile file header, update revision upon any change done to the noise generator
+static const char tilefile_headerstring[] = "Noise Tile File rev. ";
+static const char tilefile_revision[] = "001";
+
+#define NOISE_TILE_SIZE 128
+static const int noiseTileSize = NOISE_TILE_SIZE;
+
+// warning - noiseTileSize has to be 128^3!
+#define modFast128(x) ((x) & 127)
+#define modFast64(x) ((x) & 63)
+#define DOWNCOEFFS 0.000334f,-0.001528f, 0.000410f, 0.003545f,-0.000938f,-0.008233f, 0.002172f, 0.019120f, \
+ -0.005040f,-0.044412f, 0.011655f, 0.103311f,-0.025936f,-0.243780f, 0.033979f, 0.655340f, \
+ 0.655340f, 0.033979f,-0.243780f,-0.025936f, 0.103311f, 0.011655f,-0.044412f,-0.005040f, \
+ 0.019120f, 0.002172f,-0.008233f,-0.000938f, 0.003546f, 0.000410f,-0.001528f, 0.000334f
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Wavelet downsampling -- periodic boundary conditions
+//////////////////////////////////////////////////////////////////////////////////////////
+static void downsampleX(float *from, float *to, int n){
+ // if these values are not local incorrect results are generated
+ float downCoeffs[32] = { DOWNCOEFFS };
+ const float *a = &downCoeffs[16];
+ for (int i = 0; i < n / 2; i++) {
+ to[i] = 0;
+ for (int k = 2 * i - 16; k < 2 * i + 16; k++)
+ to[i] += a[k - 2 * i] * from[modFast128(k)];
+ }
+}
+static void downsampleY(float *from, float *to, int n){
+ // if these values are not local incorrect results are generated
+ float downCoeffs[32] = { DOWNCOEFFS };
+ const float *a = &downCoeffs[16];
+ for (int i = 0; i < n / 2; i++) {
+ to[i * n] = 0;
+ for (int k = 2 * i - 16; k < 2 * i + 16; k++)
+ to[i * n] += a[k - 2 * i] * from[modFast128(k) * n];
+ }
+}
+static void downsampleZ(float *from, float *to, int n){
+ // if these values are not local incorrect results are generated
+ float downCoeffs[32] = { DOWNCOEFFS };
+ const float *a = &downCoeffs[16];
+ for (int i = 0; i < n / 2; i++) {
+ to[i * n * n] = 0;
+ for (int k = 2 * i - 16; k < 2 * i + 16; k++)
+ to[i * n * n] += a[k - 2 * i] * from[modFast128(k) * n * n];
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Wavelet downsampling -- Neumann boundary conditions
+//////////////////////////////////////////////////////////////////////////////////////////
+static void downsampleNeumann(const float *from, float *to, int n, int stride)
+{
+ // if these values are not local incorrect results are generated
+ float downCoeffs[32] = { DOWNCOEFFS };
+ const float *const aCoCenter= &downCoeffs[16];
+ for (int i = 0; i < n / 2; i++) {
+ to[i * stride] = 0;
+ for (int k = 2 * i - 16; k < 2 * i + 16; k++) {
+ // handle boundary
+ float fromval;
+ if (k < 0) {
+ fromval = from[0];
+ } else if(k > n - 1) {
+ fromval = from[(n - 1) * stride];
+ } else {
+ fromval = from[k * stride];
+ }
+ to[i * stride] += aCoCenter[k - 2 * i] * fromval;
+ }
+ }
+}
+static void downsampleXNeumann(float* to, const float* from, int sx,int sy, int sz) {
+ for (int iy = 0; iy < sy; iy++)
+ for (int iz = 0; iz < sz; iz++) {
+ const int i = iy * sx + iz*sx*sy;
+ downsampleNeumann(&from[i], &to[i], sx, 1);
+ }
+}
+static void downsampleYNeumann(float* to, const float* from, int sx,int sy, int sz) {
+ for (int ix = 0; ix < sx; ix++)
+ for (int iz = 0; iz < sz; iz++) {
+ const int i = ix + iz*sx*sy;
+ downsampleNeumann(&from[i], &to[i], sy, sx);
+ }
+}
+static void downsampleZNeumann(float* to, const float* from, int sx,int sy, int sz) {
+ for (int ix = 0; ix < sx; ix++)
+ for (int iy = 0; iy < sy; iy++) {
+ const int i = ix + iy*sx;
+ downsampleNeumann(&from[i], &to[i], sz, sx*sy);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Wavelet upsampling - periodic boundary conditions
+//////////////////////////////////////////////////////////////////////////////////////////
+static float _upCoeffs[4] = {0.25f, 0.75f, 0.75f, 0.25f};
+static void upsampleX(float *from, float *to, int n) {
+ const float *p = &_upCoeffs[2];
+
+ for (int i = 0; i < n; i++) {
+ to[i] = 0;
+ for (int k = i / 2; k <= i / 2 + 1; k++)
+ to[i] += p[i - 2 * k] * from[modFast64(k)];
+ }
+}
+static void upsampleY(float *from, float *to, int n) {
+ const float *p = &_upCoeffs[2];
+
+ for (int i = 0; i < n; i++) {
+ to[i * n] = 0;
+ for (int k = i / 2; k <= i / 2 + 1; k++)
+ to[i * n] += p[i - 2 * k] * from[modFast64(k) * n];
+ }
+}
+static void upsampleZ(float *from, float *to, int n) {
+ const float *p = &_upCoeffs[2];
+
+ for (int i = 0; i < n; i++) {
+ to[i * n * n] = 0;
+ for (int k = i / 2; k <= i / 2 + 1; k++)
+ to[i * n * n] += p[i - 2 * k] * from[modFast64(k) * n * n];
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Wavelet upsampling - Neumann boundary conditions
+//////////////////////////////////////////////////////////////////////////////////////////
+static void upsampleNeumann(const float *from, float *to, int n, int stride) {
+ static const float *const pCoCenter = &_upCoeffs[2];
+ for (int i = 0; i < n; i++) {
+ to[i * stride] = 0;
+ for (int k = i / 2; k <= i / 2 + 1; k++) {
+ float fromval;
+ if(k>n/2) {
+ fromval = from[(n/2) * stride];
+ } else {
+ fromval = from[k * stride];
+ }
+ to[i * stride] += pCoCenter[i - 2 * k] * fromval;
+ }
+ }
+}
+static void upsampleXNeumann(float* to, const float* from, int sx, int sy, int sz) {
+ for (int iy = 0; iy < sy; iy++)
+ for (int iz = 0; iz < sz; iz++) {
+ const int i = iy * sx + iz*sx*sy;
+ upsampleNeumann(&from[i], &to[i], sx, 1);
+ }
+}
+static void upsampleYNeumann(float* to, const float* from, int sx, int sy, int sz) {
+ for (int ix = 0; ix < sx; ix++)
+ for (int iz = 0; iz < sz; iz++) {
+ const int i = ix + iz*sx*sy;
+ upsampleNeumann(&from[i], &to[i], sy, sx);
+ }
+}
+static void upsampleZNeumann(float* to, const float* from, int sx, int sy, int sz) {
+ for (int ix = 0; ix < sx; ix++)
+ for (int iy = 0; iy < sy; iy++) {
+ const int i = ix + iy*sx;
+ upsampleNeumann(&from[i], &to[i], sz, sx*sy);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// load in an existing noise tile
+//////////////////////////////////////////////////////////////////////////////////////////
+static bool loadTile(float* const noiseTileData, std::string filename)
+{
+ FILE* file;
+ char headerbuffer[64];
+ size_t headerlen;
+ size_t bread;
+ int endiantest = 1;
+ char endianness;
+
+ file = fopen(filename.c_str(), "rb");
+
+ if (file == NULL) {
+ printf("loadTile: No noise tile '%s' found.\n", filename.c_str());
+ return false;
+ }
+
+ //Check header
+ headerlen = strlen(tilefile_headerstring) + strlen(tilefile_revision) + 2;
+ bread = fread((void*)headerbuffer, 1, headerlen, file);
+ if (*((unsigned char*)&endiantest) == 1)
+ endianness = 'L';
+ else
+ endianness = 'B';
+ if ((bread != headerlen)
+ || (strncmp(headerbuffer, tilefile_headerstring, strlen(tilefile_headerstring)))
+ || (strncmp(headerbuffer+ strlen(tilefile_headerstring), tilefile_revision, strlen(tilefile_revision)))
+ || (headerbuffer[headerlen-2] != endianness)
+ || (headerbuffer[headerlen-1] != (char)((char)sizeof(long)+'0')))
+ {
+ printf("loadTile : Noise tile '%s' was generated on an incompatible platform.\n",filename.c_str());
+ fclose(file);
+ return false;
+ }
+
+ // dimensions
+ size_t gridSize = noiseTileSize * noiseTileSize * noiseTileSize;
+
+ // noiseTileData memory is managed by caller
+ bread = fread((void*)noiseTileData, sizeof(float), gridSize, file);
+ fclose(file);
+ printf("Noise tile file '%s' loaded.\n", filename.c_str());
+
+ if (bread != gridSize) {
+ printf("loadTile: Noise tile '%s' is wrong size %d.\n", filename.c_str(), (int)bread);
+ return false;
+ }
+
+ // check for invalid nan tile data that could be generated. bug is now
+ // fixed, but invalid files may still hang around
+ if (isnan(noiseTileData[0])) {
+ printf("loadTile: Noise tile '%s' contains nan values.\n", filename.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// write out an existing noise tile
+//////////////////////////////////////////////////////////////////////////////////////////
+static void saveTile(float* const noiseTileData, std::string filename)
+{
+ FILE* file;
+ file = fopen(filename.c_str(), "wb");
+ int endiantest=1;
+ char longsize;
+
+ if (file == NULL) {
+ printf("saveTile: Noise tile '%s' could not be saved.\n", filename.c_str());
+ return;
+ }
+
+ //Write file header
+ fwrite(tilefile_headerstring, strlen(tilefile_headerstring), 1, file);
+ fwrite(tilefile_revision, strlen(tilefile_revision), 1, file);
+ //Endianness
+ if (*((unsigned char*)&endiantest) == 1)
+ fwrite("L", 1, 1, file); //Little endian
+ else
+ fwrite("B",1,1,file); //Big endian
+ //32/64bit
+ longsize = (char)sizeof(long)+'0';
+ fwrite(&longsize, 1, 1, file);
+
+
+ fwrite((void*)noiseTileData, sizeof(float), noiseTileSize * noiseTileSize * noiseTileSize, file);
+ fclose(file);
+
+ printf("saveTile: Noise tile file '%s' saved.\n", filename.c_str());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// create a new noise tile if necessary
+//////////////////////////////////////////////////////////////////////////////////////////
+static void generateTile_WAVELET(float* const noiseTileData, std::string filename) {
+ // if a tile already exists, just use that
+ if (loadTile(noiseTileData, filename)) return;
+
+ const int n = noiseTileSize;
+ const int n3 = n*n*n;
+ std::cout <<"Generating new 3d noise tile size="<<n<<"^3 \n";
+ MTRand twister;
+
+ float *temp13 = new float[n3];
+ float *temp23 = new float[n3];
+ float *noise3 = new float[n3];
+
+ // initialize
+ for (int i = 0; i < n3; i++) {
+ temp13[i] = temp23[i] = noise3[i] = 0.;
+ }
+
+ // Step 1. Fill the tile with random numbers in the range -1 to 1.
+ for (int i = 0; i < n3; i++)
+ noise3[i] = twister.randNorm();
+
+ // Steps 2 and 3. Downsample and upsample the tile
+ for (int iy = 0; iy < n; iy++)
+ for (int iz = 0; iz < n; iz++) {
+ const int i = iy * n + iz*n*n;
+ downsampleX(&noise3[i], &temp13[i], n);
+ upsampleX (&temp13[i], &temp23[i], n);
+ }
+ for (int ix = 0; ix < n; ix++)
+ for (int iz = 0; iz < n; iz++) {
+ const int i = ix + iz*n*n;
+ downsampleY(&temp23[i], &temp13[i], n);
+ upsampleY (&temp13[i], &temp23[i], n);
+ }
+ for (int ix = 0; ix < n; ix++)
+ for (int iy = 0; iy < n; iy++) {
+ const int i = ix + iy*n;
+ downsampleZ(&temp23[i], &temp13[i], n);
+ upsampleZ (&temp13[i], &temp23[i], n);
+ }
+
+ // Step 4. Subtract out the coarse-scale contribution
+ for (int i = 0; i < n3; i++)
+ noise3[i] -= temp23[i];
+
+ // Avoid even/odd variance difference by adding odd-offset version of noise to itself.
+ int offset = n / 2;
+ if (offset % 2 == 0) offset++;
+
+ int icnt=0;
+ for (int ix = 0; ix < n; ix++)
+ for (int iy = 0; iy < n; iy++)
+ for (int iz = 0; iz < n; iz++) {
+ temp13[icnt] = noise3[modFast128(ix+offset) + modFast128(iy+offset)*n + modFast128(iz+offset)*n*n];
+ icnt++;
+ }
+
+ for (int i = 0; i < n3; i++)
+ noise3[i] += temp13[i];
+
+ for (int i = 0; i < n3; i++)
+ noiseTileData[i] = noise3[i];
+
+ saveTile(noise3, filename);
+ delete[] temp13;
+ delete[] temp23;
+ delete[] noise3;
+ std::cout <<"Generating new 3d noise done\n";
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// x derivative of noise
+//////////////////////////////////////////////////////////////////////////////////////////
+static inline float WNoiseDx(Vec3 p, float* data) {
+ int c[3], mid[3], n = noiseTileSize;
+ float w[3][3], t, result = 0;
+
+ mid[0] = (int)ceil(p[0] - 0.5);
+ t = mid[0] - (p[0] - 0.5);
+ w[0][0] = -t;
+ w[0][2] = (1.f - t);
+ w[0][1] = 2.0f * t - 1.0f;
+
+ mid[1] = (int)ceil(p[1] - 0.5);
+ t = mid[1] - (p[1] - 0.5);
+ w[1][0] = t * t / 2;
+ w[1][2] = (1 - t) * (1 - t) / 2;
+ w[1][1] = 1 - w[1][0] - w[1][2];
+
+ mid[2] = (int)ceil(p[2] - 0.5);
+ t = mid[2] - (p[2] - 0.5);
+ w[2][0] = t * t / 2;
+ w[2][2] = (1 - t) * (1 - t)/2;
+ w[2][1] = 1 - w[2][0] - w[2][2];
+
+ // to optimize, explicitly unroll this loop
+ for (int z = -1; z <=1; z++)
+ for (int y = -1; y <=1; y++)
+ for (int x = -1; x <=1; x++)
+ {
+ float weight = 1.0f;
+ c[0] = modFast128(mid[0] + x);
+ weight *= w[0][x+1];
+ c[1] = modFast128(mid[1] + y);
+ weight *= w[1][y+1];
+ c[2] = modFast128(mid[2] + z);
+ weight *= w[2][z+1];
+ result += weight * data[c[2]*n*n+c[1]*n+c[0]];
+ }
+ return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// y derivative of noise
+//////////////////////////////////////////////////////////////////////////////////////////
+static inline float WNoiseDy(Vec3 p, float* data) {
+ int c[3], mid[3], n=noiseTileSize;
+ float w[3][3], t, result =0;
+
+ mid[0] = (int)ceil(p[0] - 0.5);
+ t = mid[0]-(p[0] - 0.5);
+ w[0][0] = t * t / 2;
+ w[0][2] = (1 - t) * (1 - t) / 2;
+ w[0][1] = 1 - w[0][0] - w[0][2];
+
+ mid[1] = (int)ceil(p[1] - 0.5);
+ t = mid[1]-(p[1] - 0.5);
+ w[1][0] = -t;
+ w[1][2] = (1.f - t);
+ w[1][1] = 2.0f * t - 1.0f;
+
+ mid[2] = (int)ceil(p[2] - 0.5);
+ t = mid[2] - (p[2] - 0.5);
+ w[2][0] = t * t / 2;
+ w[2][2] = (1 - t) * (1 - t)/2;
+ w[2][1] = 1 - w[2][0] - w[2][2];
+
+ // to optimize, explicitly unroll this loop
+ for (int z = -1; z <=1; z++)
+ for (int y = -1; y <=1; y++)
+ for (int x = -1; x <=1; x++)
+ {
+ float weight = 1.0f;
+ c[0] = modFast128(mid[0] + x);
+ weight *= w[0][x+1];
+ c[1] = modFast128(mid[1] + y);
+ weight *= w[1][y+1];
+ c[2] = modFast128(mid[2] + z);
+ weight *= w[2][z+1];
+ result += weight * data[c[2]*n*n+c[1]*n+c[0]];
+ }
+
+ return result;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// z derivative of noise
+//////////////////////////////////////////////////////////////////////////////////////////
+static inline float WNoiseDz(Vec3 p, float* data) {
+ int c[3], mid[3], n=noiseTileSize;
+ float w[3][3], t, result =0;
+
+ mid[0] = (int)ceil(p[0] - 0.5);
+ t = mid[0]-(p[0] - 0.5);
+ w[0][0] = t * t / 2;
+ w[0][2] = (1 - t) * (1 - t) / 2;
+ w[0][1] = 1 - w[0][0] - w[0][2];
+
+ mid[1] = (int)ceil(p[1] - 0.5);
+ t = mid[1]-(p[1] - 0.5);
+ w[1][0] = t * t / 2;
+ w[1][2] = (1 - t) * (1 - t) / 2;
+ w[1][1] = 1 - w[1][0] - w[1][2];
+
+ mid[2] = (int)ceil(p[2] - 0.5);
+ t = mid[2] - (p[2] - 0.5);
+ w[2][0] = -t;
+ w[2][2] = (1.f - t);
+ w[2][1] = 2.0f * t - 1.0f;
+
+ // to optimize, explicitly unroll this loop
+ for (int z = -1; z <=1; z++)
+ for (int y = -1; y <=1; y++)
+ for (int x = -1; x <=1; x++)
+ {
+ float weight = 1.0f;
+ c[0] = modFast128(mid[0] + x);
+ weight *= w[0][x+1];
+ c[1] = modFast128(mid[1] + y);
+ weight *= w[1][y+1];
+ c[2] = modFast128(mid[2] + z);
+ weight *= w[2][z+1];
+ result += weight * data[c[2]*n*n+c[1]*n+c[0]];
+ }
+ return result;
+}
+
+#endif
+
diff --git a/intern/smoke/intern/WTURBULENCE.cpp b/intern/smoke/intern/WTURBULENCE.cpp
new file mode 100644
index 00000000000..83bec466c9f
--- /dev/null
+++ b/intern/smoke/intern/WTURBULENCE.cpp
@@ -0,0 +1,1071 @@
+/** \file smoke/intern/WTURBULENCE.cpp
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// WTURBULENCE handling
+///////////////////////////////////////////////////////////////////////////////////
+// Parallelized turbulence even further. TNT matrix library functions
+// rewritten to improve performance.
+// - MiikaH
+//////////////////////////////////////////////////////////////////////
+
+#include "WTURBULENCE.h"
+#include "INTERPOLATE.h"
+#include "IMAGE.h"
+#include <MERSENNETWISTER.h>
+#include "WAVELET_NOISE.h"
+#include "FFT_NOISE.h"
+#include "EIGENVALUE_HELPER.h"
+#include "LU_HELPER.h"
+#include "SPHERE.h"
+#include <zlib.h>
+#include <math.h>
+
+// needed to access static advection functions
+#include "FLUID_3D.h"
+
+#if PARALLEL==1
+#include <omp.h>
+#endif // PARALLEL
+
+// 2^ {-5/6}
+static const float persistence = 0.56123f;
+
+//////////////////////////////////////////////////////////////////////
+// constructor
+//////////////////////////////////////////////////////////////////////
+WTURBULENCE::WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype)
+{
+ // if noise magnitude is below this threshold, its contribution
+ // is negilgible, so stop evaluating new octaves
+ _cullingThreshold = 1e-3;
+
+ // factor by which to increase the simulation resolution
+ _amplify = amplify;
+
+ // manually adjust the overall amount of turbulence
+ // DG - RNA-fied _strength = 2.;
+
+ // add the corresponding octaves of noise
+ _octaves = (int)(log((float)_amplify) / log(2.0f) + 0.5); // XXX DEBUG/ TODO: int casting correct? - dg
+
+ // noise resolution
+ _xResBig = _amplify * xResSm;
+ _yResBig = _amplify * yResSm;
+ _zResBig = _amplify * zResSm;
+ _resBig = Vec3Int(_xResBig, _yResBig, _zResBig);
+ _invResBig = Vec3(1./(float)_resBig[0], 1./(float)_resBig[1], 1./(float)_resBig[2]);
+ _slabSizeBig = _xResBig*_yResBig;
+ _totalCellsBig = _slabSizeBig * _zResBig;
+
+ // original / small resolution
+ _xResSm = xResSm;
+ _yResSm = yResSm;
+ _zResSm = zResSm;
+ _resSm = Vec3Int(xResSm, yResSm, zResSm);
+ _invResSm = Vec3(1./(float)_resSm[0], 1./(float)_resSm[1], 1./(float)_resSm[2] );
+ _slabSizeSm = _xResSm*_yResSm;
+ _totalCellsSm = _slabSizeSm * _zResSm;
+
+ // allocate high resolution density field
+ _totalStepsBig = 0;
+ _densityBig = new float[_totalCellsBig];
+ _densityBigOld = new float[_totalCellsBig];
+
+ for(int i = 0; i < _totalCellsBig; i++) {
+ _densityBig[i] =
+ _densityBigOld[i] = 0.;
+ }
+
+ // allocate & init texture coordinates
+ _tcU = new float[_totalCellsSm];
+ _tcV = new float[_totalCellsSm];
+ _tcW = new float[_totalCellsSm];
+ _tcTemp = new float[_totalCellsSm];
+
+ // map all
+ const float dx = 1./(float)(_resSm[0]);
+ const float dy = 1./(float)(_resSm[1]);
+ const float dz = 1./(float)(_resSm[2]);
+ int index = 0;
+ for (int z = 0; z < _zResSm; z++)
+ for (int y = 0; y < _yResSm; y++)
+ for (int x = 0; x < _xResSm; x++, index++)
+ {
+ _tcU[index] = x*dx;
+ _tcV[index] = y*dy;
+ _tcW[index] = z*dz;
+ _tcTemp[index] = 0.;
+ }
+
+ // noise tiles
+ _noiseTile = new float[noiseTileSize * noiseTileSize * noiseTileSize];
+ /*
+ std::string noiseTileFilename = std::string("noise.wavelets");
+ generateTile_WAVELET(_noiseTile, noiseTileFilename);
+ */
+ setNoise(noisetype);
+ /*
+ std::string noiseTileFilename = std::string("noise.fft");
+ generatTile_FFT(_noiseTile, noiseTileFilename);
+ */
+}
+
+//////////////////////////////////////////////////////////////////////
+// destructor
+//////////////////////////////////////////////////////////////////////
+WTURBULENCE::~WTURBULENCE() {
+ delete[] _densityBig;
+ delete[] _densityBigOld;
+
+ delete[] _tcU;
+ delete[] _tcV;
+ delete[] _tcW;
+ delete[] _tcTemp;
+
+ delete[] _noiseTile;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Change noise type
+//
+// type (1<<0) = wavelet / 2
+// type (1<<1) = FFT / 4
+// type (1<<2) = curl / 8
+//////////////////////////////////////////////////////////////////////
+void WTURBULENCE::setNoise(int type)
+{
+ if(type == (1<<1)) // FFT
+ {
+ // needs fft
+ #ifdef WITH_FFTW3
+ std::string noiseTileFilename = std::string("noise.fft");
+ generatTile_FFT(_noiseTile, noiseTileFilename);
+ #endif
+ }
+ else if(type == (1<<2)) // curl
+ {
+ // TODO: not supported yet
+ }
+ else // standard - wavelet
+ {
+ std::string noiseTileFilename = std::string("noise.wavelets");
+ generateTile_WAVELET(_noiseTile, noiseTileFilename);
+ }
+}
+
+// init direct access functions from blender
+void WTURBULENCE::initBlenderRNA(float *strength)
+{
+ _strength = strength;
+}
+
+//////////////////////////////////////////////////////////////////////
+// Get the smallest valid x derivative
+//
+// Takes the one-sided finite difference in both directions and
+// selects the smaller of the two
+//////////////////////////////////////////////////////////////////////
+static float minDx(int x, int y, int z, float* input, Vec3Int res)
+{
+ const int index = x + y * res[0] + z * res[0] * res[1];
+ const int maxx = res[0]-2;
+
+ // get grid values
+ float center = input[index];
+ float left = (x <= 1) ? FLT_MAX : input[index - 1];
+ float right = (x >= maxx) ? FLT_MAX : input[index + 1];
+
+ const float dx = res[0];
+
+ // get all the derivative estimates
+ float dLeft = (x <= 1) ? FLT_MAX : (center - left) * dx;
+ float dRight = (x >= maxx) ? FLT_MAX : (right - center) * dx;
+ float dCenter = (x <= 1 || x >= maxx) ? FLT_MAX : (right - left) * dx * 0.5f;
+
+ // if it's on a boundary, only one estimate is valid
+ if (x <= 1) return dRight;
+ if (x >= maxx) return dLeft;
+
+ // if it's not on a boundary, get the smallest one
+ float finalD;
+ finalD = (fabs(dCenter) < fabs(dRight)) ? dCenter : dRight;
+ finalD = (fabs(finalD) < fabs(dLeft)) ? finalD : dLeft;
+
+ return finalD;
+}
+
+//////////////////////////////////////////////////////////////////////
+// get the smallest valid y derivative
+//
+// Takes the one-sided finite difference in both directions and
+// selects the smaller of the two
+//////////////////////////////////////////////////////////////////////
+static float minDy(int x, int y, int z, float* input, Vec3Int res)
+{
+ const int index = x + y * res[0] + z * res[0] * res[1];
+ const int maxy = res[1]-2;
+
+ // get grid values
+ float center = input[index];
+ float down = (y <= 1) ? FLT_MAX : input[index - res[0]];
+ float up = (y >= maxy) ? FLT_MAX : input[index + res[0]];
+
+ const float dx = res[1]; // only for square domains
+
+ // get all the derivative estimates
+ float dDown = (y <= 1) ? FLT_MAX : (center - down) * dx;
+ float dUp = (y >= maxy) ? FLT_MAX : (up - center) * dx;
+ float dCenter = (y <= 1 || y >= maxy) ? FLT_MAX : (up - down) * dx * 0.5f;
+
+ // if it's on a boundary, only one estimate is valid
+ if (y <= 1) return dUp;
+ if (y >= maxy) return dDown;
+
+ // if it's not on a boundary, get the smallest one
+ float finalD = (fabs(dCenter) < fabs(dUp)) ? dCenter : dUp;
+ finalD = (fabs(finalD) < fabs(dDown)) ? finalD : dDown;
+
+ return finalD;
+}
+
+//////////////////////////////////////////////////////////////////////
+// get the smallest valid z derivative
+//
+// Takes the one-sided finite difference in both directions and
+// selects the smaller of the two
+//////////////////////////////////////////////////////////////////////
+static float minDz(int x, int y, int z, float* input, Vec3Int res)
+{
+ const int slab = res[0]*res[1];
+ const int index = x + y * res[0] + z * slab;
+ const int maxz = res[2]-2;
+
+ // get grid values
+ float center = input[index];
+ float front = (z <= 1) ? FLT_MAX : input[index - slab];
+ float back = (z >= maxz) ? FLT_MAX : input[index + slab];
+
+ const float dx = res[2]; // only for square domains
+
+ // get all the derivative estimates
+ float dfront = (z <= 1) ? FLT_MAX : (center - front) * dx;
+ float dback = (z >= maxz) ? FLT_MAX : (back - center) * dx;
+ float dCenter = (z <= 1 || z >= maxz) ? FLT_MAX : (back - front) * dx * 0.5f;
+
+ // if it's on a boundary, only one estimate is valid
+ if (z <= 1) return dback;
+ if (z >= maxz) return dfront;
+
+ // if it's not on a boundary, get the smallest one
+ float finalD = (fabs(dCenter) < fabs(dback)) ? dCenter : dback;
+ finalD = (fabs(finalD) < fabs(dfront)) ? finalD : dfront;
+
+ return finalD;
+}
+
+//////////////////////////////////////////////////////////////////////
+// handle texture coordinates (advection, reset, eigenvalues),
+// Beware -- uses big density maccormack as temporary arrays
+//////////////////////////////////////////////////////////////////////
+void WTURBULENCE::advectTextureCoordinates (float dtOrg, float* xvel, float* yvel, float* zvel, float *tempBig1, float *tempBig2) {
+
+ // advection
+ SWAP_POINTERS(_tcTemp, _tcU);
+ FLUID_3D::copyBorderX(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::copyBorderY(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::copyBorderZ(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::advectFieldMacCormack1(dtOrg, xvel, yvel, zvel,
+ _tcTemp, tempBig1, _resSm, 0 , _resSm[2]);
+ FLUID_3D::advectFieldMacCormack2(dtOrg, xvel, yvel, zvel,
+ _tcTemp, _tcU, tempBig1, tempBig2, _resSm, NULL, 0 , _resSm[2]);
+
+ SWAP_POINTERS(_tcTemp, _tcV);
+ FLUID_3D::copyBorderX(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::copyBorderY(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::copyBorderZ(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::advectFieldMacCormack1(dtOrg, xvel, yvel, zvel,
+ _tcTemp, tempBig1, _resSm, 0 , _resSm[2]);
+ FLUID_3D::advectFieldMacCormack2(dtOrg, xvel, yvel, zvel,
+ _tcTemp, _tcV, tempBig1, tempBig2, _resSm, NULL, 0 , _resSm[2]);
+
+ SWAP_POINTERS(_tcTemp, _tcW);
+ FLUID_3D::copyBorderX(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::copyBorderY(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::copyBorderZ(_tcTemp, _resSm, 0 , _resSm[2]);
+ FLUID_3D::advectFieldMacCormack1(dtOrg, xvel, yvel, zvel,
+ _tcTemp, tempBig1, _resSm, 0 , _resSm[2]);
+ FLUID_3D::advectFieldMacCormack2(dtOrg, xvel, yvel, zvel,
+ _tcTemp, _tcW, tempBig1, tempBig2, _resSm, NULL, 0 , _resSm[2]);
+}
+
+//////////////////////////////////////////////////////////////////////
+// Compute the eigenvalues of the advected texture
+//////////////////////////////////////////////////////////////////////
+void WTURBULENCE::computeEigenvalues(float *_eigMin, float *_eigMax) {
+ // stats
+ float maxeig = -1.;
+ float mineig = 10.;
+
+ // texture coordinate eigenvalues
+ for (int z = 1; z < _zResSm-1; z++) {
+ for (int y = 1; y < _yResSm-1; y++)
+ for (int x = 1; x < _xResSm-1; x++)
+ {
+ const int index = x+ y *_resSm[0] + z*_slabSizeSm;
+
+ // compute jacobian
+ float jacobian[3][3] = {
+ { minDx(x, y, z, _tcU, _resSm), minDx(x, y, z, _tcV, _resSm), minDx(x, y, z, _tcW, _resSm) } ,
+ { minDy(x, y, z, _tcU, _resSm), minDy(x, y, z, _tcV, _resSm), minDy(x, y, z, _tcW, _resSm) } ,
+ { minDz(x, y, z, _tcU, _resSm), minDz(x, y, z, _tcV, _resSm), minDz(x, y, z, _tcW, _resSm) }
+ };
+
+ // ONLY compute the eigenvalues after checking that the matrix
+ // is nonsingular
+ sLU LU = computeLU(jacobian);
+
+ if (isNonsingular(LU))
+ {
+ // get the analytic eigenvalues, quite slow right now...
+ Vec3 eigenvalues = Vec3(1.);
+ computeEigenvalues3x3( &eigenvalues[0], jacobian);
+ _eigMax[index] = MAX3V(eigenvalues);
+ _eigMin[index] = MIN3V(eigenvalues);
+ maxeig = MAX(_eigMax[index],maxeig);
+ mineig = MIN(_eigMin[index],mineig);
+ }
+ else
+ {
+ _eigMax[index] = 10.0f;
+ _eigMin[index] = 0.1;
+ }
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// advect & reset texture coordinates based on eigenvalues
+//////////////////////////////////////////////////////////////////////
+void WTURBULENCE::resetTextureCoordinates(float *_eigMin, float *_eigMax)
+{
+ // allowed deformation of the textures
+ const float limit = 2.f;
+ const float limitInv = 1./limit;
+
+ // standard reset
+ int resets = 0;
+ const float dx = 1./(float)(_resSm[0]);
+ const float dy = 1./(float)(_resSm[1]);
+ const float dz = 1./(float)(_resSm[2]);
+
+ for (int z = 1; z < _zResSm-1; z++)
+ for (int y = 1; y < _yResSm-1; y++)
+ for (int x = 1; x < _xResSm-1; x++)
+ {
+ const int index = x+ y *_resSm[0] + z*_slabSizeSm;
+ if (_eigMax[index] > limit || _eigMin[index] < limitInv)
+ {
+ _tcU[index] = (float)x * dx;
+ _tcV[index] = (float)y * dy;
+ _tcW[index] = (float)z * dz;
+ resets++;
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// Compute the highest frequency component of the wavelet
+// decomposition
+//////////////////////////////////////////////////////////////////////
+void WTURBULENCE::decomposeEnergy(float *_energy, float *_highFreqEnergy)
+{
+ // do the decomposition -- the goal here is to have
+ // the energy with the high frequency component stomped out
+ // stored in _tcTemp when it is done. _highFreqEnergy is only used
+ // as an additional temp array
+
+ // downsample input
+ downsampleXNeumann(_highFreqEnergy, _energy, _xResSm, _yResSm, _zResSm);
+ downsampleYNeumann(_tcTemp, _highFreqEnergy, _xResSm, _yResSm, _zResSm);
+ downsampleZNeumann(_highFreqEnergy, _tcTemp, _xResSm, _yResSm, _zResSm);
+
+ // upsample input
+ upsampleZNeumann(_tcTemp, _highFreqEnergy, _xResSm, _yResSm, _zResSm);
+ upsampleYNeumann(_highFreqEnergy, _tcTemp, _xResSm, _yResSm, _zResSm);
+ upsampleXNeumann(_tcTemp, _highFreqEnergy, _xResSm, _yResSm, _zResSm);
+
+ // subtract the down and upsampled field from the original field --
+ // what should be left over is solely the high frequency component
+ int index = 0;
+ for (int z = 0; z < _zResSm; z++)
+ for (int y = 0; y < _yResSm; y++) {
+ for (int x = 0; x < _xResSm; x++, index++) {
+ // brute force reset of boundaries
+ if(z >= _zResSm - 1 || x >= _xResSm - 1 || y >= _yResSm - 1 || z <= 0 || y <= 0 || x <= 0)
+ _highFreqEnergy[index] = 0.;
+ else
+ _highFreqEnergy[index] = _energy[index] - _tcTemp[index];
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+// compute velocity from energies and march into obstacles
+// for wavelet decomposition
+//////////////////////////////////////////////////////////////////////
+void WTURBULENCE::computeEnergy(float *_energy, float* xvel, float* yvel, float* zvel, unsigned char *origObstacles)
+{
+ unsigned char *obstacles = new unsigned char[_totalCellsSm];
+ memcpy(obstacles, origObstacles, sizeof(unsigned char) * _totalCellsSm);
+
+ // compute everywhere
+ for (int x = 0; x < _totalCellsSm; x++)
+ _energy[x] = 0.5f * (xvel[x] * xvel[x] + yvel[x] * yvel[x] + zvel[x] * zvel[x]);
+
+ FLUID_3D::copyBorderX(_energy, _resSm, 0 , _resSm[2]);
+ FLUID_3D::copyBorderY(_energy, _resSm, 0 , _resSm[2]);
+ FLUID_3D::copyBorderZ(_energy, _resSm, 0 , _resSm[2]);
+
+ // pseudo-march the values into the obstacles
+ // the wavelet upsampler only uses a 3x3 support neighborhood, so
+ // propagating the values in by 4 should be sufficient
+ int index;
+
+ // iterate
+ for (int iter = 0; iter < 4; iter++)
+ {
+ index = _slabSizeSm + _xResSm + 1;
+ for (int z = 1; z < _zResSm - 1; z++, index += 2 * _xResSm)
+ for (int y = 1; y < _yResSm - 1; y++, index += 2)
+ for (int x = 1; x < _xResSm - 1; x++, index++)
+ if (obstacles[index] && obstacles[index] != RETIRED)
+ {
+ float sum = 0.0f;
+ int valid = 0;
+
+ if (!obstacles[index + 1] || obstacles[index + 1] == RETIRED)
+ {
+ sum += _energy[index + 1];
+ valid++;
+ }
+ if (!obstacles[index - 1] || obstacles[index - 1] == RETIRED)
+ {
+ sum += _energy[index - 1];
+ valid++;
+ }
+ if (!obstacles[index + _xResSm] || obstacles[index + _xResSm] == RETIRED)
+ {
+ sum += _energy[index + _xResSm];
+ valid++;
+ }
+ if (!obstacles[index - _xResSm] || obstacles[index - _xResSm] == RETIRED)
+ {
+ sum += _energy[index - _xResSm];
+ valid++;
+ }
+ if (!obstacles[index + _slabSizeSm] || obstacles[index + _slabSizeSm] == RETIRED)
+ {
+ sum += _energy[index + _slabSizeSm];
+ valid++;
+ }
+ if (!obstacles[index - _slabSizeSm] || obstacles[index - _slabSizeSm] == RETIRED)
+ {
+ sum += _energy[index - _slabSizeSm];
+ valid++;
+ }
+ if (valid > 0)
+ {
+ _energy[index] = sum / (float)valid;
+ obstacles[index] = MARCHED;
+ }
+ }
+ index = _slabSizeSm + _xResSm + 1;
+ for (int z = 1; z < _zResSm - 1; z++, index += 2 * _xResSm)
+ for (int y = 1; y < _yResSm - 1; y++, index += 2)
+ for (int x = 1; x < _xResSm - 1; x++, index++)
+ if (obstacles[index] == MARCHED)
+ obstacles[index] = RETIRED;
+ }
+ index = _slabSizeSm + _xResSm + 1;
+ for (int z = 1; z < _zResSm - 1; z++, index += 2 * _xResSm)
+ for (int y = 1; y < _yResSm - 1; y++, index += 2)
+ for (int x = 1; x < _xResSm - 1; x++, index++)
+ if (obstacles[index])
+ obstacles[index] = 1; // DG TODO ? animated obstacle flag?
+
+ free(obstacles);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Evaluate derivatives
+//////////////////////////////////////////////////////////////////////////////////////////
+Vec3 WTURBULENCE::WVelocity(Vec3 orgPos)
+{
+ // arbitrarily offset evaluation points
+ const Vec3 p1 = orgPos + Vec3(NOISE_TILE_SIZE/2.0,0,0);
+ const Vec3 p2 = orgPos + Vec3(0,NOISE_TILE_SIZE/2.0,0);
+ const Vec3 p3 = orgPos + Vec3(0,0,NOISE_TILE_SIZE/2.0);
+
+ const float f1y = WNoiseDy(p1, _noiseTile);
+ const float f1z = WNoiseDz(p1, _noiseTile);
+
+ const float f2x = WNoiseDx(p2, _noiseTile);
+ const float f2z = WNoiseDz(p2, _noiseTile);
+
+ const float f3x = WNoiseDx(p3, _noiseTile);
+ const float f3y = WNoiseDy(p3, _noiseTile);
+
+ Vec3 ret = Vec3(
+ f3y - f2z,
+ f1z - f3x,
+ f2x - f1y );
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// Evaluate derivatives with Jacobian
+//////////////////////////////////////////////////////////////////////////////////////////
+Vec3 WTURBULENCE::WVelocityWithJacobian(Vec3 orgPos, float* xUnwarped, float* yUnwarped, float* zUnwarped)
+{
+ // arbitrarily offset evaluation points
+ const Vec3 p1 = orgPos + Vec3(NOISE_TILE_SIZE/2.0,0,0);
+ const Vec3 p2 = orgPos + Vec3(0,NOISE_TILE_SIZE/2.0,0);
+ const Vec3 p3 = orgPos + Vec3(0,0,NOISE_TILE_SIZE/2.0);
+
+ Vec3 final;
+ final[0] = WNoiseDx(p1, _noiseTile);
+ final[1] = WNoiseDy(p1, _noiseTile);
+ final[2] = WNoiseDz(p1, _noiseTile);
+ // UNUSED const float f1x = xUnwarped[0] * final[0] + xUnwarped[1] * final[1] + xUnwarped[2] * final[2];
+ const float f1y = yUnwarped[0] * final[0] + yUnwarped[1] * final[1] + yUnwarped[2] * final[2];
+ const float f1z = zUnwarped[0] * final[0] + zUnwarped[1] * final[1] + zUnwarped[2] * final[2];
+
+ final[0] = WNoiseDx(p2, _noiseTile);
+ final[1] = WNoiseDy(p2, _noiseTile);
+ final[2] = WNoiseDz(p2, _noiseTile);
+ const float f2x = xUnwarped[0] * final[0] + xUnwarped[1] * final[1] + xUnwarped[2] * final[2];
+ // UNUSED const float f2y = yUnwarped[0] * final[0] + yUnwarped[1] * final[1] + yUnwarped[2] * final[2];
+ const float f2z = zUnwarped[0] * final[0] + zUnwarped[1] * final[1] + zUnwarped[2] * final[2];
+
+ final[0] = WNoiseDx(p3, _noiseTile);
+ final[1] = WNoiseDy(p3, _noiseTile);
+ final[2] = WNoiseDz(p3, _noiseTile);
+ const float f3x = xUnwarped[0] * final[0] + xUnwarped[1] * final[1] + xUnwarped[2] * final[2];
+ const float f3y = yUnwarped[0] * final[0] + yUnwarped[1] * final[1] + yUnwarped[2] * final[2];
+ // UNUSED const float f3z = zUnwarped[0] * final[0] + zUnwarped[1] * final[1] + zUnwarped[2] * final[2];
+
+ Vec3 ret = Vec3(
+ f3y - f2z,
+ f1z - f3x,
+ f2x - f1y );
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// perform an actual noise advection step
+//////////////////////////////////////////////////////////////////////
+/*void WTURBULENCE::stepTurbulenceReadable(float dtOrg, float* xvel, float* yvel, float* zvel, unsigned char *obstacles)
+{
+ // enlarge timestep to match grid
+ const float dt = dtOrg * _amplify;
+ const float invAmp = 1.0f / _amplify;
+ float *tempBig1 = new float[_totalCellsBig];
+ float *tempBig2 = new float[_totalCellsBig];
+ float *bigUx = new float[_totalCellsBig];
+ float *bigUy = new float[_totalCellsBig];
+ float *bigUz = new float[_totalCellsBig];
+ float *_energy = new float[_totalCellsSm];
+ float *highFreqEnergy = new float[_totalCellsSm];
+ float *eigMin = new float[_totalCellsSm];
+ float *eigMax = new float[_totalCellsSm];
+
+ memset(tempBig1, 0, sizeof(float)*_totalCellsBig);
+ memset(tempBig2, 0, sizeof(float)*_totalCellsBig);
+ memset(highFreqEnergy, 0, sizeof(float)*_totalCellsSm);
+ memset(eigMin, 0, sizeof(float)*_totalCellsSm);
+ memset(eigMax, 0, sizeof(float)*_totalCellsSm);
+
+ // prepare textures
+ advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempBig1, tempBig2);
+
+ // compute eigenvalues of the texture coordinates
+ computeEigenvalues(eigMin, eigMax);
+
+ // do wavelet decomposition of energy
+ computeEnergy(_energy, xvel, yvel, zvel, obstacles);
+ decomposeEnergy(_energy, highFreqEnergy);
+
+ // zero out coefficients inside of the obstacle
+ for (int x = 0; x < _totalCellsSm; x++)
+ if (obstacles[x]) _energy[x] = 0.f;
+
+ float maxVelocity = 0.;
+ for (int z = 1; z < _zResBig - 1; z++)
+ for (int y = 1; y < _yResBig - 1; y++)
+ for (int x = 1; x < _xResBig - 1; x++)
+ {
+ // get unit position for both fine and coarse grid
+ const Vec3 pos = Vec3(x,y,z);
+ const Vec3 posSm = pos * invAmp;
+
+ // get grid index for both fine and coarse grid
+ const int index = x + y *_xResBig + z *_slabSizeBig;
+ const int indexSmall = (int)posSm[0] + (int)posSm[1] * _xResSm + (int)posSm[2] * _slabSizeSm;
+
+ // get a linearly interpolated velocity and texcoords
+ // from the coarse grid
+ Vec3 vel = INTERPOLATE::lerp3dVec( xvel,yvel,zvel,
+ posSm[0], posSm[1], posSm[2], _xResSm,_yResSm,_zResSm);
+ Vec3 uvw = INTERPOLATE::lerp3dVec( _tcU,_tcV,_tcW,
+ posSm[0], posSm[1], posSm[2], _xResSm,_yResSm,_zResSm);
+
+ // multiply the texture coordinate by _resSm so that turbulence
+ // synthesis begins at the first octave that the coarse grid
+ // cannot capture
+ Vec3 texCoord = Vec3(uvw[0] * _resSm[0],
+ uvw[1] * _resSm[1],
+ uvw[2] * _resSm[2]);
+
+ // retrieve wavelet energy at highest frequency
+ float energy = INTERPOLATE::lerp3d(
+ highFreqEnergy, posSm[0],posSm[1],posSm[2], _xResSm, _yResSm, _zResSm);
+
+ // base amplitude for octave 0
+ float coefficient = sqrtf(2.0f * fabs(energy));
+ const float amplitude = *_strength * fabs(0.5 * coefficient) * persistence;
+
+ // add noise to velocity, but only if the turbulence is
+ // sufficiently undeformed, and the energy is large enough
+ // to make a difference
+ const bool addNoise = eigMax[indexSmall] < 2. &&
+ eigMin[indexSmall] > 0.5;
+ if (addNoise && amplitude > _cullingThreshold) {
+ // base amplitude for octave 0
+ float amplitudeScaled = amplitude;
+
+ for (int octave = 0; octave < _octaves; octave++)
+ {
+ // multiply the vector noise times the maximum allowed
+ // noise amplitude at this octave, and add it to the total
+ vel += WVelocity(texCoord) * amplitudeScaled;
+
+ // scale coefficient for next octave
+ amplitudeScaled *= persistence;
+ texCoord *= 2.0f;
+ }
+ }
+
+ // Store velocity + turbulence in big grid for maccormack step
+ //
+ // If you wanted to save memory, you would instead perform a
+ // semi-Lagrangian backtrace for the current grid cell here. Then
+ // you could just throw the velocity away.
+ bigUx[index] = vel[0];
+ bigUy[index] = vel[1];
+ bigUz[index] = vel[2];
+
+ // compute the velocity magnitude for substepping later
+ const float velMag = bigUx[index] * bigUx[index] +
+ bigUy[index] * bigUy[index] +
+ bigUz[index] * bigUz[index];
+ if (velMag > maxVelocity) maxVelocity = velMag;
+
+ // zero out velocity inside obstacles
+ float obsCheck = INTERPOLATE::lerp3dToFloat(
+ obstacles, posSm[0], posSm[1], posSm[2], _xResSm, _yResSm, _zResSm);
+ if (obsCheck > 0.95)
+ bigUx[index] = bigUy[index] = bigUz[index] = 0.;
+ }
+
+ // prepare density for an advection
+ SWAP_POINTERS(_densityBig, _densityBigOld);
+
+ // based on the maximum velocity present, see if we need to substep,
+ // but cap the maximum number of substeps to 5
+ const int maxSubSteps = 5;
+ maxVelocity = sqrt(maxVelocity) * dt;
+ int totalSubsteps = (int)(maxVelocity / (float)maxSubSteps);
+ totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
+ totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
+ const float dtSubdiv = dt / (float)totalSubsteps;
+
+ // set boundaries of big velocity grid
+ FLUID_3D::setZeroX(bigUx, _resBig, 0, _resBig[2]);
+ FLUID_3D::setZeroY(bigUy, _resBig, 0, _resBig[2]);
+ FLUID_3D::setZeroZ(bigUz, _resBig, 0, _resBig[2]);
+
+ // do the MacCormack advection, with substepping if necessary
+ for(int substep = 0; substep < totalSubsteps; substep++)
+ {
+ FLUID_3D::advectFieldMacCormack(dtSubdiv, bigUx, bigUy, bigUz,
+ _densityBigOld, _densityBig, tempBig1, tempBig2, _resBig, NULL);
+
+ if (substep < totalSubsteps - 1)
+ SWAP_POINTERS(_densityBig, _densityBigOld);
+ } // substep
+
+ // wipe the density borders
+ FLUID_3D::setZeroBorder(_densityBig, _resBig, 0, _resBig[2]);
+
+ // reset texture coordinates now in preparation for next timestep
+ // Shouldn't do this before generating the noise because then the
+ // eigenvalues stored do not reflect the underlying texture coordinates
+ resetTextureCoordinates(eigMin, eigMax);
+
+ delete[] tempBig1;
+ delete[] tempBig2;
+ delete[] bigUx;
+ delete[] bigUy;
+ delete[] bigUz;
+ delete[] _energy;
+ delete[] highFreqEnergy;
+
+ delete[] eigMin;
+ delete[] eigMax;
+
+
+ _totalStepsBig++;
+}*/
+
+//struct
+
+//////////////////////////////////////////////////////////////////////
+// perform the full turbulence algorithm, including OpenMP
+// if available
+//////////////////////////////////////////////////////////////////////
+void WTURBULENCE::stepTurbulenceFull(float dtOrg, float* xvel, float* yvel, float* zvel, unsigned char *obstacles)
+{
+ // enlarge timestep to match grid
+ const float dt = dtOrg * _amplify;
+ const float invAmp = 1.0f / _amplify;
+ float *tempBig1 = (float *)calloc(_totalCellsBig, sizeof(float));
+ float *tempBig2 = (float *)calloc(_totalCellsBig, sizeof(float));
+ float *bigUx = (float *)calloc(_totalCellsBig, sizeof(float));
+ float *bigUy = (float *)calloc(_totalCellsBig, sizeof(float));
+ float *bigUz = (float *)calloc(_totalCellsBig, sizeof(float));
+ float *_energy = (float *)calloc(_totalCellsSm, sizeof(float));
+ float *highFreqEnergy = (float *)calloc(_totalCellsSm, sizeof(float));
+ float *eigMin = (float *)calloc(_totalCellsSm, sizeof(float));
+ float *eigMax = (float *)calloc(_totalCellsSm, sizeof(float));
+
+ memset(_tcTemp, 0, sizeof(float)*_totalCellsSm);
+
+
+ // prepare textures
+ advectTextureCoordinates(dtOrg, xvel,yvel,zvel, tempBig1, tempBig2);
+
+ // do wavelet decomposition of energy
+ computeEnergy(_energy, xvel, yvel, zvel, obstacles);
+
+ for (int x = 0; x < _totalCellsSm; x++)
+ if (obstacles[x]) _energy[x] = 0.f;
+
+ decomposeEnergy(_energy, highFreqEnergy);
+
+ // zero out coefficients inside of the obstacle
+ for (int x = 0; x < _totalCellsSm; x++)
+ if (obstacles[x]) highFreqEnergy[x] = 0.f;
+
+ Vec3Int ressm(_xResSm, _yResSm, _zResSm);
+ FLUID_3D::setNeumannX(highFreqEnergy, ressm, 0 , ressm[2]);
+ FLUID_3D::setNeumannY(highFreqEnergy, ressm, 0 , ressm[2]);
+ FLUID_3D::setNeumannZ(highFreqEnergy, ressm, 0 , ressm[2]);
+
+
+ int threadval = 1;
+#if PARALLEL==1
+ threadval = omp_get_max_threads();
+#endif
+
+
+ // parallel region setup
+ // Uses omp_get_max_trheads to get number of required cells.
+ float* maxVelMagThreads = new float[threadval];
+
+ for (int i=0; i<threadval; i++) maxVelMagThreads[i] = -1.0f;
+
+#if PARALLEL==1
+
+#pragma omp parallel
+#endif
+ { float maxVelMag1 = 0.;
+#if PARALLEL==1
+ const int id = omp_get_thread_num(); /*, num = omp_get_num_threads(); */
+#endif
+
+ // vector noise main loop
+#if PARALLEL==1
+#pragma omp for schedule(static,1)
+#endif
+ for (int zSmall = 0; zSmall < _zResSm; zSmall++)
+ {
+ for (int ySmall = 0; ySmall < _yResSm; ySmall++)
+ for (int xSmall = 0; xSmall < _xResSm; xSmall++)
+ {
+ const int indexSmall = xSmall + ySmall * _xResSm + zSmall * _slabSizeSm;
+
+ // compute jacobian
+ float jacobian[3][3] = {
+ { minDx(xSmall, ySmall, zSmall, _tcU, _resSm), minDx(xSmall, ySmall, zSmall, _tcV, _resSm), minDx(xSmall, ySmall, zSmall, _tcW, _resSm) } ,
+ { minDy(xSmall, ySmall, zSmall, _tcU, _resSm), minDy(xSmall, ySmall, zSmall, _tcV, _resSm), minDy(xSmall, ySmall, zSmall, _tcW, _resSm) } ,
+ { minDz(xSmall, ySmall, zSmall, _tcU, _resSm), minDz(xSmall, ySmall, zSmall, _tcV, _resSm), minDz(xSmall, ySmall, zSmall, _tcW, _resSm) }
+ };
+
+ // get LU factorization of texture jacobian and apply
+ // it to unit vectors
+ sLU LU = computeLU(jacobian);
+ float xUnwarped[3], yUnwarped[3], zUnwarped[3];
+ float xWarped[3], yWarped[3], zWarped[3];
+ bool nonSingular = isNonsingular(LU);
+
+ xUnwarped[0] = 1.0f; xUnwarped[1] = 0.0f; xUnwarped[2] = 0.0f;
+ yUnwarped[0] = 0.0f; yUnwarped[1] = 1.0f; yUnwarped[2] = 0.0f;
+ zUnwarped[0] = 0.0f; zUnwarped[1] = 0.0f; zUnwarped[2] = 1.0f;
+
+ xWarped[0] = 1.0f; xWarped[1] = 0.0f; xWarped[2] = 0.0f;
+ yWarped[0] = 0.0f; yWarped[1] = 1.0f; yWarped[2] = 0.0f;
+ zWarped[0] = 0.0f; zWarped[1] = 0.0f; zWarped[2] = 1.0f;
+
+#if 0
+ // UNUSED
+ float eigMax = 10.0f;
+ float eigMin = 0.1f;
+#endif
+ if (nonSingular)
+ {
+ solveLU3x3(LU, xUnwarped, xWarped);
+ solveLU3x3(LU, yUnwarped, yWarped);
+ solveLU3x3(LU, zUnwarped, zWarped);
+
+ // compute the eigenvalues while we have the Jacobian available
+ Vec3 eigenvalues = Vec3(1.);
+ computeEigenvalues3x3( &eigenvalues[0], jacobian);
+ eigMax[indexSmall] = MAX3V(eigenvalues);
+ eigMin[indexSmall] = MIN3V(eigenvalues);
+ }
+
+ // make sure to skip one on the beginning and end
+ int xStart = (xSmall == 0) ? 1 : 0;
+ int xEnd = (xSmall == _xResSm - 1) ? _amplify - 1 : _amplify;
+ int yStart = (ySmall == 0) ? 1 : 0;
+ int yEnd = (ySmall == _yResSm - 1) ? _amplify - 1 : _amplify;
+ int zStart = (zSmall == 0) ? 1 : 0;
+ int zEnd = (zSmall == _zResSm - 1) ? _amplify - 1 : _amplify;
+
+ for (int zBig = zStart; zBig < zEnd; zBig++)
+ for (int yBig = yStart; yBig < yEnd; yBig++)
+ for (int xBig = xStart; xBig < xEnd; xBig++)
+ {
+ const int x = xSmall * _amplify + xBig;
+ const int y = ySmall * _amplify + yBig;
+ const int z = zSmall * _amplify + zBig;
+
+ // get unit position for both fine and coarse grid
+ const Vec3 pos = Vec3(x,y,z);
+ const Vec3 posSm = pos * invAmp;
+
+ // get grid index for both fine and coarse grid
+ const int index = x + y *_xResBig + z *_slabSizeBig;
+
+ // get a linearly interpolated velocity and texcoords
+ // from the coarse grid
+ Vec3 vel = INTERPOLATE::lerp3dVec( xvel,yvel,zvel,
+ posSm[0], posSm[1], posSm[2], _xResSm,_yResSm,_zResSm);
+ Vec3 uvw = INTERPOLATE::lerp3dVec( _tcU,_tcV,_tcW,
+ posSm[0], posSm[1], posSm[2], _xResSm,_yResSm,_zResSm);
+
+ // multiply the texture coordinate by _resSm so that turbulence
+ // synthesis begins at the first octave that the coarse grid
+ // cannot capture
+ Vec3 texCoord = Vec3(uvw[0] * _resSm[0],
+ uvw[1] * _resSm[1],
+ uvw[2] * _resSm[2]);
+
+ // retrieve wavelet energy at highest frequency
+ float energy = INTERPOLATE::lerp3d(
+ highFreqEnergy, posSm[0],posSm[1],posSm[2], _xResSm, _yResSm, _zResSm);
+
+ // base amplitude for octave 0
+ float coefficient = sqrtf(2.0f * fabs(energy));
+ const float amplitude = *_strength * fabs(0.5 * coefficient) * persistence;
+
+ // add noise to velocity, but only if the turbulence is
+ // sufficiently undeformed, and the energy is large enough
+ // to make a difference
+ const bool addNoise = eigMax[indexSmall] < 2. &&
+ eigMin[indexSmall] > 0.5;
+ if (addNoise && amplitude > _cullingThreshold) {
+ // base amplitude for octave 0
+ float amplitudeScaled = amplitude;
+
+ for (int octave = 0; octave < _octaves; octave++)
+ {
+ // multiply the vector noise times the maximum allowed
+ // noise amplitude at this octave, and add it to the total
+ vel += WVelocityWithJacobian(texCoord, &xUnwarped[0], &yUnwarped[0], &zUnwarped[0]) * amplitudeScaled;
+
+ // scale coefficient for next octave
+ amplitudeScaled *= persistence;
+ texCoord *= 2.0f;
+ }
+ }
+
+ // Store velocity + turbulence in big grid for maccormack step
+ //
+ // If you wanted to save memory, you would instead perform a
+ // semi-Lagrangian backtrace for the current grid cell here. Then
+ // you could just throw the velocity away.
+ bigUx[index] = vel[0];
+ bigUy[index] = vel[1];
+ bigUz[index] = vel[2];
+
+ // compute the velocity magnitude for substepping later
+ const float velMag = bigUx[index] * bigUx[index] +
+ bigUy[index] * bigUy[index] +
+ bigUz[index] * bigUz[index];
+ if (velMag > maxVelMag1) maxVelMag1 = velMag;
+
+ // zero out velocity inside obstacles
+ float obsCheck = INTERPOLATE::lerp3dToFloat(
+ obstacles, posSm[0], posSm[1], posSm[2], _xResSm, _yResSm, _zResSm);
+ if (obsCheck > 0.95)
+ bigUx[index] = bigUy[index] = bigUz[index] = 0.;
+ } // xyz*/
+
+#if PARALLEL==1
+ maxVelMagThreads[id] = maxVelMag1;
+#else
+ maxVelMagThreads[0] = maxVelMag1;
+#endif
+ }
+ }
+ } // omp
+
+ // compute maximum over threads
+ float maxVelMag = maxVelMagThreads[0];
+#if PARALLEL==1
+ for (int i = 1; i < threadval; i++)
+ if (maxVelMag < maxVelMagThreads[i])
+ maxVelMag = maxVelMagThreads[i];
+#endif
+ delete [] maxVelMagThreads;
+
+
+ // prepare density for an advection
+ SWAP_POINTERS(_densityBig, _densityBigOld);
+
+ // based on the maximum velocity present, see if we need to substep,
+ // but cap the maximum number of substeps to 5
+ const int maxSubSteps = 25;
+ const int maxVel = 5;
+ maxVelMag = sqrt(maxVelMag) * dt;
+ int totalSubsteps = (int)(maxVelMag / (float)maxVel);
+ totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps;
+ // printf("totalSubsteps: %d\n", totalSubsteps);
+ totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps;
+ const float dtSubdiv = dt / (float)totalSubsteps;
+
+ // set boundaries of big velocity grid
+ FLUID_3D::setZeroX(bigUx, _resBig, 0 , _resBig[2]);
+ FLUID_3D::setZeroY(bigUy, _resBig, 0 , _resBig[2]);
+ FLUID_3D::setZeroZ(bigUz, _resBig, 0 , _resBig[2]);
+
+#if PARALLEL==1
+ int stepParts = threadval*2; // Dividing parallelized sections into numOfThreads * 2 sections
+ float partSize = (float)_zResBig/stepParts; // Size of one part;
+
+ if (partSize < 4) {stepParts = threadval; // If the slice gets too low (might actually slow things down, change it to larger
+ partSize = (float)_zResBig/stepParts;}
+ if (partSize < 4) {stepParts = (int)(ceil((float)_zResBig/4.0f)); // If it's still too low (only possible on future systems with +24 cores), change it to 4
+ partSize = (float)_zResBig/stepParts;}
+#else
+ int zBegin=0;
+ int zEnd=_resBig[2];
+#endif
+
+ // do the MacCormack advection, with substepping if necessary
+ for(int substep = 0; substep < totalSubsteps; substep++)
+ {
+
+#if PARALLEL==1
+ #pragma omp parallel
+ {
+
+ #pragma omp for schedule(static,1)
+ for (int i=0; i<stepParts; i++)
+ {
+ int zBegin = (int)((float)i*partSize + 0.5f);
+ int zEnd = (int)((float)(i+1)*partSize + 0.5f);
+#endif
+ FLUID_3D::advectFieldMacCormack1(dtSubdiv, bigUx, bigUy, bigUz,
+ _densityBigOld, tempBig1, _resBig, zBegin, zEnd);
+#if PARALLEL==1
+ }
+
+ #pragma omp barrier
+
+ #pragma omp for schedule(static,1)
+ for (int i=0; i<stepParts; i++)
+ {
+ int zBegin = (int)((float)i*partSize + 0.5f);
+ int zEnd = (int)((float)(i+1)*partSize + 0.5f);
+#endif
+ FLUID_3D::advectFieldMacCormack2(dtSubdiv, bigUx, bigUy, bigUz,
+ _densityBigOld, _densityBig, tempBig1, tempBig2, _resBig, NULL, zBegin, zEnd);
+#if PARALLEL==1
+ }
+ }
+#endif
+
+ if (substep < totalSubsteps - 1)
+ SWAP_POINTERS(_densityBig, _densityBigOld);
+ } // substep
+
+ free(tempBig1);
+ free(tempBig2);
+ free(bigUx);
+ free(bigUy);
+ free(bigUz);
+ free(_energy);
+ free(highFreqEnergy);
+
+ // wipe the density borders
+ FLUID_3D::setZeroBorder(_densityBig, _resBig, 0 , _resBig[2]);
+
+ // reset texture coordinates now in preparation for next timestep
+ // Shouldn't do this before generating the noise because then the
+ // eigenvalues stored do not reflect the underlying texture coordinates
+ resetTextureCoordinates(eigMin, eigMax);
+
+ free(eigMin);
+ free(eigMax);
+
+ // output files
+ // string prefix = string("./amplified.preview/density_bigxy_");
+ // FLUID_3D::writeImageSliceXY(_densityBig, _resBig, _resBig[2]/2, prefix, _totalStepsBig, 1.0f);
+ //string df3prefix = string("./df3/density_big_");
+ //IMAGE::dumpDF3(_totalStepsBig, df3prefix, _densityBig, _resBig[0],_resBig[1],_resBig[2]);
+ // string pbrtPrefix = string("./pbrt/density_big_");
+ // IMAGE::dumpPBRT(_totalStepsBig, pbrtPrefix, _densityBig, _resBig[0],_resBig[1],_resBig[2]);
+
+ _totalStepsBig++;
+}
diff --git a/intern/smoke/intern/WTURBULENCE.h b/intern/smoke/intern/WTURBULENCE.h
new file mode 100644
index 00000000000..f31ca100fdf
--- /dev/null
+++ b/intern/smoke/intern/WTURBULENCE.h
@@ -0,0 +1,133 @@
+/** \file smoke/intern/WTURBULENCE.h
+ * \ingroup smoke
+ */
+//////////////////////////////////////////////////////////////////////
+// This file is part of Wavelet Turbulence.
+//
+// Wavelet Turbulence is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Wavelet Turbulence is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Wavelet Turbulence. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright 2008 Theodore Kim and Nils Thuerey
+//
+// WTURBULENCE handling
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef WTURBULENCE_H
+#define WTURBULENCE_H
+
+#include "VEC3.h"
+using namespace BasicVector;
+class SIMPLE_PARSER;
+
+///////////////////////////////////////////////////////////////////////////////
+/// Main WTURBULENCE class, stores large density array etc.
+///////////////////////////////////////////////////////////////////////////////
+class WTURBULENCE
+{
+ public:
+ // both config files can be NULL, altCfg might override values from noiseCfg
+ WTURBULENCE(int xResSm, int yResSm, int zResSm, int amplify, int noisetype);
+
+ /// destructor
+ virtual ~WTURBULENCE();
+
+ void setNoise(int type);
+ void initBlenderRNA(float *strength);
+
+ // step more readable version -- no rotation correction
+ void stepTurbulenceReadable(float dt, float* xvel, float* yvel, float* zvel, unsigned char *obstacles);
+
+ // step more complete version -- include rotation correction
+ // and use OpenMP if available
+ void stepTurbulenceFull(float dt, float* xvel, float* yvel, float* zvel, unsigned char *obstacles);
+
+ // texcoord functions
+ void advectTextureCoordinates(float dtOrg, float* xvel, float* yvel, float* zvel, float *tempBig1, float *tempBig2);
+ void resetTextureCoordinates(float *_eigMin, float *_eigMax);
+
+ void computeEnergy(float *energy, float* xvel, float* yvel, float* zvel, unsigned char *obstacles);
+
+ // evaluate wavelet noise function
+ Vec3 WVelocity(Vec3 p);
+ Vec3 WVelocityWithJacobian(Vec3 p, float* xUnwarped, float* yUnwarped, float* zUnwarped);
+
+ // access functions
+ inline float* getDensityBig() { return _densityBig; }
+ inline float* getArrayTcU() { return _tcU; }
+ inline float* getArrayTcV() { return _tcV; }
+ inline float* getArrayTcW() { return _tcW; }
+
+ inline Vec3Int getResSm() { return _resSm; } // small resolution
+ inline Vec3Int getResBig() { return _resBig; }
+ inline int getOctaves() { return _octaves; }
+
+ // is accessed on through rna gui
+ float *_strength;
+
+ // protected:
+ // enlargement factor from original velocity field / simulation
+ // _Big = _amplify * _Sm
+ int _amplify;
+ int _octaves;
+
+ // noise settings
+ float _cullingThreshold;
+ // float _noiseStrength;
+ // float _noiseSizeScale;
+ // bool _uvwAdvection;
+ // bool _uvwReset;
+ // float _noiseTimeanimSpeed;
+ // int _dumpInterval;
+ // nt _noiseControlType;
+ // debug, scale density for projections output images
+ // float _outputScale;
+
+ // noise resolution
+ int _xResBig;
+ int _yResBig;
+ int _zResBig;
+ Vec3Int _resBig;
+ Vec3 _invResBig;
+ int _totalCellsBig;
+ int _slabSizeBig;
+ // original / small resolution
+ int _xResSm;
+ int _yResSm;
+ int _zResSm;
+ Vec3Int _resSm;
+ Vec3 _invResSm;
+ int _totalCellsSm;
+ int _slabSizeSm;
+
+ float* _densityBig;
+ float* _densityBigOld;
+
+ // texture coordinates for noise
+ float* _tcU;
+ float* _tcV;
+ float* _tcW;
+ float* _tcTemp;
+
+ // noise data
+ float* _noiseTile;
+ //float* _noiseTileExt;
+
+ // step counter
+ int _totalStepsBig;
+
+ void computeEigenvalues(float *_eigMin, float *_eigMax);
+ void decomposeEnergy(float *energy, float *_highFreqEnergy);
+};
+
+#endif // WTURBULENCE_H
+
diff --git a/intern/smoke/intern/smoke_API.cpp b/intern/smoke/intern/smoke_API.cpp
index 0d2e6a81094..01753a25d2d 100644
--- a/intern/smoke/intern/smoke_API.cpp
+++ b/intern/smoke/intern/smoke_API.cpp
@@ -28,37 +28,36 @@
* \ingroup smoke
*/
+
+#include "FLUID_3D.h"
+#include "WTURBULENCE.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
-#include "smoke.h"
-
-// #define FLUID_3D void
-#define WTURBULENCE void
-
-using namespace DDF;
-
// y in smoke is z in blender
extern "C" FLUID_3D *smoke_init(int *res, float *p0, float dtdef)
{
- printf("-------------------- SMOKE CREATE --------------------------\n");
- FLUID_3D *fluid = new FLUID_3D(res);
- printf("-------------------- SMOKE INIT --------------------------\n");
- if(!fluid->_init)
- fluid->init();
+ // smoke lib uses y as top-bottom/vertical axis where blender uses z
+ FLUID_3D *fluid = new FLUID_3D(res, p0, dtdef);
+
+ // printf("xres: %d, yres: %d, zres: %d\n", res[0], res[1], res[2]);
+
return fluid;
}
extern "C" WTURBULENCE *smoke_turbulence_init(int *res, int amplify, int noisetype)
{
- return NULL;
+ // initialize wavelet turbulence
+ if(amplify)
+ return new WTURBULENCE(res[0],res[1],res[2], amplify, noisetype);
+ else
+ return NULL;
}
extern "C" void smoke_free(FLUID_3D *fluid)
{
- printf("-------------------- SMOKE DEL ---------------------------\n");
- fluid->del();
delete fluid;
fluid = NULL;
}
@@ -72,7 +71,7 @@ extern "C" void smoke_turbulence_free(WTURBULENCE *wt)
extern "C" size_t smoke_get_index(int x, int max_x, int y, int max_y, int z /*, int max_z */)
{
// // const int index = x + y * smd->res[0] + z * smd->res[0]*smd->res[1];
- return x + y * max_x + z * max_x*max_y; // (z*mSizeY+y)*mSizeX+x
+ return x + y * max_x + z * max_x*max_y;
}
extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z, int max_z */)
@@ -82,33 +81,103 @@ extern "C" size_t smoke_get_index2d(int x, int max_x, int y /*, int max_y, int z
extern "C" void smoke_step(FLUID_3D *fluid, float dtSubdiv)
{
- printf("-------------------- SMOKE STEP --------------------------\n");
- fluid->step();
+ fluid->step(dtSubdiv);
}
extern "C" void smoke_turbulence_step(WTURBULENCE *wt, FLUID_3D *fluid)
{
-
+ wt->stepTurbulenceFull(fluid->_dt/fluid->_dx, fluid->_xVelocity, fluid->_yVelocity, fluid->_zVelocity, fluid->_obstacles);
}
extern "C" void smoke_initBlenderRNA(FLUID_3D *fluid, float *alpha, float *beta, float *dt_factor, float *vorticity, int *border_colli)
{
-
+ fluid->initBlenderRNA(alpha, beta, dt_factor, vorticity, border_colli);
}
extern "C" void smoke_dissolve(FLUID_3D *fluid, int speed, int log)
{
-
+ float *density = fluid->_density;
+ //float *densityOld = fluid->_densityOld;
+ float *heat = fluid->_heat;
+
+ if(log)
+ {
+ /* max density/speed = dydx */
+ float dydx = 1.0 / (float)speed;
+ size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
+
+ for(size_t i = 0; i < size; i++)
+ {
+ density[i] *= (1.0 - dydx);
+
+ if(density[i] < 0.0f)
+ density[i] = 0.0f;
+
+ heat[i] *= (1.0 - dydx);
+
+ /*if(heat[i] < 0.0f)
+ heat[i] = 0.0f;*/
+ }
+ }
+ else // linear falloff
+ {
+ /* max density/speed = dydx */
+ float dydx = 1.0 / (float)speed;
+ size_t size= fluid->_xRes * fluid->_yRes * fluid->_zRes;
+
+ for(size_t i = 0; i < size; i++)
+ {
+ density[i] -= dydx;
+
+ if(density[i] < 0.0f)
+ density[i] = 0.0f;
+
+ if(abs(heat[i]) < dydx) heat[i] = 0.0f;
+ else if (heat[i]>0.0f) heat[i] -= dydx;
+ else if (heat[i]<0.0f) heat[i] += dydx;
+
+ }
+ }
}
extern "C" void smoke_dissolve_wavelet(WTURBULENCE *wt, int speed, int log)
{
-
+ float *density = wt->getDensityBig();
+ Vec3Int r = wt->getResBig();
+
+ if(log)
+ {
+ /* max density/speed = dydx */
+ float dydx = 1.0 / (float)speed;
+ size_t size= r[0] * r[1] * r[2];
+
+ for(size_t i = 0; i < size; i++)
+ {
+ density[i] *= (1.0 - dydx);
+
+ if(density[i] < 0.0f)
+ density[i] = 0.0f;
+ }
+ }
+ else // linear falloff
+ {
+ /* max density/speed = dydx */
+ float dydx = 1.0 / (float)speed;
+ size_t size= r[0] * r[1] * r[2];
+
+ for(size_t i = 0; i < size; i++)
+ {
+ density[i] -= dydx;
+
+ if(density[i] < 0.0f)
+ density[i] = 0.0f;
+ }
+ }
}
extern "C" void smoke_initWaveletBlenderRNA(WTURBULENCE *wt, float *strength)
{
-
+ wt->initBlenderRNA(strength);
}
template < class T > inline T ABS( T a )
@@ -118,83 +187,113 @@ template < class T > inline T ABS( T a )
extern "C" void smoke_export(FLUID_3D *fluid, float *dt, float *dx, float **dens, float **densold, float **heat, float **heatold, float **vx, float **vy, float **vz, float **vxold, float **vyold, float **vzold, unsigned char **obstacles)
{
-
+ *dens = fluid->_density;
+ *densold = fluid->_densityOld;
+ *heat = fluid->_heat;
+ *heatold = fluid->_heatOld;
+ *vx = fluid->_xVelocity;
+ *vy = fluid->_yVelocity;
+ *vz = fluid->_zVelocity;
+ *vxold = fluid->_xVelocityOld;
+ *vyold = fluid->_yVelocityOld;
+ *vzold = fluid->_zVelocityOld;
+ *obstacles = fluid->_obstacles;
+ dt = &(fluid->_dt);
+ dx = &(fluid->_dx);
+
}
extern "C" void smoke_turbulence_export(WTURBULENCE *wt, float **dens, float **densold, float **tcu, float **tcv, float **tcw)
{
-
+ if(!wt)
+ return;
+
+ *dens = wt->_densityBig;
+ *densold = wt->_densityBigOld;
+ *tcu = wt->_tcU;
+ *tcv = wt->_tcV;
+ *tcw = wt->_tcW;
+}
+
+extern "C" float *smoke_get_pressure(FLUID_3D *fluid)
+{
+ return fluid->_pressure;
}
extern "C" float *smoke_get_density(FLUID_3D *fluid)
{
- if(fluid->_density)
- return fluid->_density->data();
- else
- return NULL;
+ return fluid->_density;
}
extern "C" float *smoke_get_heat(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_heat;
}
extern "C" float *smoke_get_velocity_x(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_xVelocity;
}
extern "C" float *smoke_get_velocity_y(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_yVelocity;
}
extern "C" float *smoke_get_velocity_z(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_zVelocity;
}
extern "C" float *smoke_get_force_x(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_xForce;
}
extern "C" float *smoke_get_force_y(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_yForce;
}
extern "C" float *smoke_get_force_z(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_zForce;
}
extern "C" float *smoke_turbulence_get_density(WTURBULENCE *wt)
{
- return NULL;
+ return wt ? wt->getDensityBig() : NULL;
}
extern "C" void smoke_turbulence_get_res(WTURBULENCE *wt, int *res)
{
-
+ if(wt)
+ {
+ Vec3Int r = wt->getResBig();
+ res[0] = r[0];
+ res[1] = r[1];
+ res[2] = r[2];
+ }
}
extern "C" unsigned char *smoke_get_obstacle(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_obstacles;
}
extern "C" void smoke_get_ob_velocity(FLUID_3D *fluid, float **x, float **y, float **z)
{
-
+ *x = fluid->_xVelocityOb;
+ *y = fluid->_yVelocityOb;
+ *z = fluid->_zVelocityOb;
}
extern "C" unsigned char *smoke_get_obstacle_anim(FLUID_3D *fluid)
{
- return NULL;
+ return fluid->_obstaclesAnim;
}
extern "C" void smoke_turbulence_set_noise(WTURBULENCE *wt, int type)
{
-
+ wt->setNoise(type);
}
diff --git a/intern/smoke/intern/source/advectionplugins.cpp b/intern/smoke/intern/source/advectionplugins.cpp
deleted file mode 100644
index 5ad292352f1..00000000000
--- a/intern/smoke/intern/source/advectionplugins.cpp
+++ /dev/null
@@ -1,915 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Advection plugins:
- * semi lagrange, mac cormack
- *
- *****************************************************************************/
-
-#include "fluidsolver.h"
-#include "solverplugin.h"
-#include "paramset.h"
-
-// safety boundary for semi lagrange advection step
-#define SLADVBOUND 2
-
-namespace DDF {
-
-//*****************************************************************************
-// velocity access helpers
-
-class getVelCentered {
- private:
- getVelCentered() {};
- ~getVelCentered() {};
- public:
- static inline Vec3 getVelocity(GridAccessor<Vec3,1> &gaVel, int i,int j, int k) {
- Vec3 v = Vec3(
- 0.5*( gaVel(i ,j ,k)[0] + gaVel(i+1,j ,k )[0] ),
- 0.5*( gaVel(i ,j ,k)[1] + gaVel(i ,j+1,k )[1] ),
- 0.5*( gaVel(i ,j ,k)[2] + gaVel(i ,j ,k+1)[2] ) );
- if(DDF_DIMENSION==2) { v[2] = 0.; }
- return v;
- }
-}; // getVelCentered
-
-class getVelX {
- private:
- getVelX() {};
- ~getVelX() {};
- public:
- static inline Vec3 getVelocity(GridAccessor<Vec3,1> &gaVel, int i,int j, int k) {
- const Real u = gaVel(i,j,k)[0];
- const Real v = 0.25*(
- gaVel(i ,j ,k)[1] + gaVel(i-1,j ,k)[1] +
- gaVel(i ,j+1,k)[1] + gaVel(i-1,j+1,k)[1] );
-# if DDF_DIMENSION==3
- const Real w = 0.25*(
- gaVel(i ,j,k )[2] + gaVel(i-1,j,k )[2] +
- gaVel(i ,j,k+1)[2] + gaVel(i-1,j,k+1)[2] );
-# else
- const Real w = 0.;
-# endif
- return Vec3(u,v,w);
- }
-}; // getVelX
-
-class getVelY {
- private:
- getVelY() {};
- ~getVelY() {};
- public:
- static inline Vec3 getVelocity(GridAccessor<Vec3,1> &gaVel, int i,int j, int k) {
- const Real u = 0.25*(
- gaVel(i ,j ,k)[0] + gaVel(i ,j-1,k)[0] +
- gaVel(i+1,j ,k)[0] + gaVel(i+1,j-1,k)[0] );
- const Real v = gaVel(i,j,k)[1];
-# if DDF_DIMENSION==3
- const Real w = 0.25*(
- gaVel(i,j ,k )[2] + gaVel(i,j-1,k )[2] +
- gaVel(i,j ,k+1)[2] + gaVel(i,j-1,k+1)[2] );
-# else
- const Real w = 0.;
-# endif
- return Vec3(u,v,w);
- }
-}; // getVelY
-
-class getVelZ {
- private:
- getVelZ() {};
- ~getVelZ() {};
- public:
- static inline Vec3 getVelocity(GridAccessor<Vec3,1> &gaVel, int i,int j, int k) {
- const Real u = 0.25*(
- gaVel(i ,j,k )[0] + gaVel(i ,j,k-1)[0] +
- gaVel(i+1,j,k )[0] + gaVel(i+1,j,k-1)[0] );
- const Real v = 0.25*(
- gaVel(i,j ,k )[1] + gaVel(i,j ,k-1)[1] +
- gaVel(i,j+1,k )[1] + gaVel(i,j+1,k-1)[1] );
- const Real w = gaVel(i,j,k)[2];
- return Vec3(u,v,w);
- }
-}; // getVelZ
-
-
-//*****************************************************************************
-// semi lagrange advection
-class fsSlAdvection : public GridOpBaseFlagbord<SLADVBOUND> {
- public:
- fsSlAdvection(FlagGrid *flags, Grid<Vec3> *vel, Grid<Vec3> *dstvel, Vec3 &minv, Vec3 &maxv, Real dt) :
- GridOpBaseFlagbord<SLADVBOUND>(), mpVel(vel), mpDstVel(dstvel), mDt(dt) {
- mpFlags = flags;
- mMinVel = Vec3( vec2R(mpFlags->getSize()) * 100. );
- mMaxVel = Vec3(0.);
- applyOperatorToGrids(this);
- minv = mMinVel;
- maxv = mMaxVel;
- };
- ~fsSlAdvection() { };
- void resetVariables() { };
- void buildCallList() {
- gaVel.gridAccInit(mpVel, AM_READ, gaCalls);
- gaDstVel.gridAccInit(mpDstVel, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
-
-# define PINIT_INTERPOL \
- Real srcpi = (Real)i-(u*mDt); \
- Real srcpj = (Real)j-(v*mDt); \
- Real srcpk = (Real)k-(w*mDt); \
- int srci = (int)srcpi; \
- int srcj = (int)srcpj; \
- int srck = (int)srcpk; \
- CLAMP_TO_GRID(srci,srcj,srck,mpVel); \
- const float s1 = srcpi-(float)srci, s0 = 1.-s1; \
- const float t1 = srcpj-(float)srcj, t0 = 1.-t1; \
- const float f1 = srcpk-(float)srck, f0 = 1.-f1; \
- /* end init */
-
- inline Real getSladvVel(const int a, const int b, const int c, const int index, const int src_i, const int src_j, const int src_k) {
- const int flag = getFlagAcc()(a,b,c);
- if (fgIsFluid(flag) ) return gaVel(a,b,c)[index];
- if (fgIsObstacle(flag) ) return 0.;
- // default, return own source vel
- return gaVel(src_i,src_j,src_k)[index];
- }
- inline Real interpolateSladvVel(const int i, const int j, const int k, const int index,
- const Real f0, const Real f1, const Real s0, const Real s1, const Real t0, const Real t1) {
-
- int si = i, sip1 = i+1;
- int sj = j, sjp1 = j+1;
- int sk = k, skp1 = k+1;
-
- if(DDF_DIMENSION==3) {
- return ( f0*(
- s0*(t0*getSladvVel(si ,sj,sk , index, si,sj,sk) + t1*getSladvVel(si ,sjp1,sk , index, si,sj,sk) ) +
- s1*(t0*getSladvVel(sip1,sj,sk , index, si,sj,sk) + t1*getSladvVel(sip1,sjp1,sk , index, si,sj,sk) ) )
- + f1 * (
- s0*(t0*getSladvVel(si ,sj,skp1, index, si,sj,sk) + t1*getSladvVel(si ,sjp1,skp1, index, si,sj,sk) ) +
- s1*(t0*getSladvVel(sip1,sj,skp1, index, si,sj,sk) + t1*getSladvVel(sip1,sjp1,skp1, index, si,sj,sk) ) )
- ) ;
- } else {
- // NOTE! srck not used for 2d!
- return ( f0*(
- s0*(t0*getSladvVel(si ,sj,sk, index, si,sj,sk) + t1*getSladvVel(si ,sjp1,sk, index, si,sj,sk) ) +
- s1*(t0*getSladvVel(sip1,sj,sk, index, si,sj,sk) + t1*getSladvVel(sip1,sjp1,sk, index, si,sj,sk) ) ) );
- } // 2d
- }
-
- inline void operator() (int i, int j, int k) {
- // always init...?
- if (fgIsObstacle(getFlagAcc()(i,j,k)) ) {
- gaDstVel.write(i,j,k)=Vec3(0.);
- return;
- }
- if (!fgIsFluid(getFlagAcc()(i,j,k)) ) {
- gaDstVel.write(i,j,k) = gaVel(i,j,k); // copy, not necessary?
- return;
- }
-
- const bool debugAdv = false;
-
- if (1) { // advect x
- const Real u = gaVel(i,j,k)[0];
- const Real v = 0.25*(
- gaVel(i ,j ,k)[1] + gaVel(i-1,j ,k)[1] +
- gaVel(i ,j+1,k)[1] + gaVel(i-1,j+1,k)[1] );
-# if DDF_DIMENSION==3
- const Real w = 0.25*(
- gaVel(i ,j,k )[2] + gaVel(i-1,j,k )[2] +
- gaVel(i ,j,k+1)[2] + gaVel(i-1,j,k+1)[2] );
-# else
- const Real w = 0.;
-# endif
- PINIT_INTERPOL;
- gaDstVel.write(i,j,k)[0] = interpolateSladvVel(srci,srcj,srck,0,f0,f1,s0,s1,t0,t1);
- if (debugAdv) debMsg("sgAdvectX","vel="<<PRINT_VEC(u,v,w)<<" mDt="<<mDt<<" weights="<<s0<<","<<s1<<","<<t0<<","<<t1<<","<<f0<<","<<f1 <<" src"<<PRINT_VEC(srci,srcj,srck)<<" srcp"<<PRINT_VEC(srcpi,srcpj,srcpk)<<" ijk"<<PRINT_VEC(i,j,k) );
- if (debugAdv) debMsg("sgAdvectX","vals: "<<gaVel(srci ,srcj,srck)[0] <<", "<<gaVel(srci ,srcj+1,srck)[0] <<", "<<gaVel(srci+1,srcj,srck)[0] <<", "<<gaVel(srci+1,srcj+1,srck)[0] );
- if (debugAdv && DDF_DIMENSION==3) debMsg("sgAdvectX","vals: "<<gaVel(srci ,srcj,srck+1)[0] <<", "<<gaVel(srci ,srcj+1,srck+1)[0] <<", "<<gaVel(srci+1,srcj,srck+1)[0] <<", "<<gaVel(srci+1,srcj+1,srck+1)[0] );
- }
-
- if (1) { // advect y
- const Real u = 0.25*(
- gaVel(i ,j ,k)[0] + gaVel(i ,j-1,k)[0] +
- gaVel(i+1,j ,k)[0] + gaVel(i+1,j-1,k)[0] );
- const Real v = gaVel(i,j,k)[1];
-# if DDF_DIMENSION==3
- const Real w = 0.25*(
- gaVel(i,j ,k )[2] + gaVel(i,j-1,k )[2] +
- gaVel(i,j ,k+1)[2] + gaVel(i,j-1,k+1)[2] );
-# else
- const Real w = 0.;
-# endif
- PINIT_INTERPOL;
- gaDstVel.write(i,j,k)[1] = interpolateSladvVel(srci,srcj,srck,1,f0,f1,s0,s1,t0,t1);
- if (debugAdv) debMsg("sgAdvectY","vel="<<PRINT_VEC(u,v,w)<<" mDt="<<mDt<<" weights="<<s0<<","<<s1<<","<<t0<<","<<t1<<","<<f0<<","<<f1 <<" src"<<PRINT_VEC(srci,srcj,srck) );
- if (debugAdv) debMsg("sgAdvectY","vals: "<<gaVel(srci ,srcj,srck)[1] <<", "<<gaVel(srci ,srcj+1,srck)[1] <<", "<<gaVel(srci+1,srcj,srck)[1] <<", "<<gaVel(srci+1,srcj+1,srck)[1] );
- }
-
- if (gDim==3){ // advect z
- const Real u = 0.25*(
- gaVel(i ,j,k )[0] + gaVel(i ,j,k-1)[0] +
- gaVel(i+1,j,k )[0] + gaVel(i+1,j,k-1)[0] );
- const Real v = 0.25*(
- gaVel(i,j ,k )[1] + gaVel(i,j ,k-1)[1] +
- gaVel(i,j+1,k )[1] + gaVel(i,j+1,k-1)[1] );
- const Real w = gaVel(i,j,k)[2];
- PINIT_INTERPOL;
- gaDstVel.write(i,j,k)[2] = interpolateSladvVel(srci,srcj,srck,2,f0,f1,s0,s1,t0,t1);
- if (debugAdv) debMsg("sgAdvectZ","vel="<<PRINT_VEC(u,v,w)<<" mDt="<<mDt<<" weights="<<s0<<","<<s1<<","<<t0<<","<<t1<<","<<f0<<","<<f1 <<" src"<<PRINT_VEC(srci,srcj,srck) );
- if (debugAdv) debMsg("sgAdvectZ","vals: "<<gaVel(srci ,srcj,srck)[2] <<", "<<gaVel(srci ,srcj+1,srck)[2] <<", "<<gaVel(srci+1,srcj,srck)[2] <<", "<<gaVel(srci+1,srcj+1,srck)[2] );
- }
- if (DDF_DEBUG) {
- Vec3 v = gaDstVel(i,j,k);
- if (normNoSqrt(v)>normNoSqrt(mMaxVel)) mMaxVel=v;
- if (normNoSqrt(v)<normNoSqrt(mMinVel)) mMinVel=v;
- }
- };
- void reduce(fsSlAdvection &op) {
- // update min/max
- if (normNoSqrt(op.mMaxVel)>normNoSqrt(mMaxVel)) mMaxVel=op.mMaxVel;
- if (normNoSqrt(op.mMinVel)<normNoSqrt(mMinVel)) mMinVel=op.mMinVel;
- };
- protected:
- Grid<Vec3> *mpVel;
- Grid<Vec3> *mpDstVel;
- Real mDt;
- GridAccessor<Vec3,SLADVBOUND> gaVel;
- GridAccessor<Vec3,0> gaDstVel;
- Vec3 mMinVel, mMaxVel;
-}; // fsSlAdvection */
-
-#undef PINIT_INTERPOL
-
-template < class VEL >
-class fsSlAdvectionReal : public GridOpBaseFlagbord<SLADVBOUND> {
- public:
- fsSlAdvectionReal(FlagGrid *flags, Grid<Vec3> *vel, Grid<Real> *srcreal,
- Grid<Real> *dstreal, Real dt, bool advectLs=false) :
- GridOpBaseFlagbord<SLADVBOUND>(), mpVel(vel), mpSrcReal(srcreal),
- mpDstReal(dstreal), mDt(dt), mAdvectLs(advectLs)
- {
- mpFlags = flags;
- //debMsg("fsSlAdvectionReal","Grid "<<srcreal->getName()<<", dt="<<mDt ); // DEBUGold
- applyOperatorToGrids(this);
- };
- ~fsSlAdvectionReal() { };
- void resetVariables() { };
- void buildCallList() {
- gaVel.gridAccInit(mpVel, AM_READ, gaCalls);
- gaSrcReal.gridAccInit(mpSrcReal, AM_READ, gaCalls);
- gaDstReal.gridAccInit(mpDstReal, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- // apply changes for vec sladv later on...
- inline Real getSladvReal(
- const int a, const int b, const int c,
- const int index, const int src_i, const int src_j, const int src_k) {
- // default, return value
- return gaSrcReal(a,b,c);
- }
- inline Real interpolateSladvReal(const int i, const int j, const int k, const int index,
- const Real f0, const Real f1, const Real s0, const Real s1, const Real t0, const Real t1) {
-
- int si = i, sip1 = si+1;
- int sj = j, sjp1 = sj+1;
- int sk = k, skp1 = sk+1;
-
- if(DDF_DIMENSION==3) {
- return ( f0*(
- s0*(t0*getSladvReal(si ,sj,sk , index, si,sj,sk) + t1*getSladvReal(si ,sjp1,sk , index, si,sj,sk) ) +
- s1*(t0*getSladvReal(sip1,sj,sk , index, si,sj,sk) + t1*getSladvReal(sip1,sjp1,sk , index, si,sj,sk) ) )
- + f1 * (
- s0*(t0*getSladvReal(si ,sj,skp1, index, si,j,k) + t1*getSladvReal(si ,sjp1,skp1, index, si,sj,sk) ) +
- s1*(t0*getSladvReal(sip1,sj,skp1, index, si,j,k) + t1*getSladvReal(sip1,sjp1,skp1, index, si,sj,sk) ) )
- ) ;
- } else {
- // NOTE! srck not used for 2d!
- return ( f0*(
- s0*(t0*getSladvReal(si ,sj,sk, index, si,j,k) + t1*getSladvReal(si ,sjp1,sk, index, si,sj,sk) ) +
- s1*(t0*getSladvReal(sip1,sj,sk, index, si,j,k) + t1*getSladvReal(sip1,sjp1,sk, index, si,sj,sk) ) ) );
- } // 2d
- }
-
- inline void operator() (int i, int j, int k) {
- // always init...?
- if (fgIsObstacle(getFlagAcc()(i,j,k)) ) {
- gaDstReal.write(i,j,k)=(0.);
- return;
- }
- if ((!mAdvectLs) && (!fgIsFluid(getFlagAcc()(i,j,k))) ) {
- gaDstReal.write(i,j,k) = gaSrcReal(i,j,k); // copy, not necessary?
- return;
- }
- const bool debugAdv = false;
- const Vec3 vel = VEL::getVelocity(gaVel, i,j,k);
-
- Real srcpi = (Real)i-(vel[0]*mDt);
- Real srcpj = (Real)j-(vel[1]*mDt);
- Real srcpk = (Real)k-(vel[2]*mDt);
- int srci = (int)srcpi;
- int srcj = (int)srcpj;
- int srck = (int)srcpk;
- CLAMP_TO_GRID(srci,srcj,srck,mpVel);
- const float s1 = srcpi-(float)srci, s0 = 1.-s1;
- const float t1 = srcpj-(float)srcj, t0 = 1.-t1;
- const float f1 = srcpk-(float)srck, f0 = 1.-f1;
-
- gaDstReal.write(i,j,k) = interpolateSladvReal(srci,srcj,srck,0,f0,f1,s0,s1,t0,t1);
- };
- void reduce(fsSlAdvectionReal &op) {
- // ...
- };
- protected:
- Grid<Vec3> *mpVel;
- Grid<Real> *mpSrcReal;
- Grid<Real> *mpDstReal;
- Real mDt;
- GridAccessor<Vec3,1> gaVel;
- GridAccessor<Real,SLADVBOUND> gaSrcReal;
- GridAccessor<Real,0> gaDstReal;
- // levelset special, also advect non-fluid cells
- bool mAdvectLs;
-
-}; // fsSlAdvectionReal */
-
-// interface for advection
-class spSemiLagrangeAdvVec3 : public SolverPlugin {
- public:
- spSemiLagrangeAdvVec3() : SolverPlugin(), mNameFlags("flags"),mNameCurrVel("vel-curr"),mNameOldVel("vec-temp"),mNameVel("vel-curr"),
- mTemp1("temp1"),mTemp2("temp2"),mMAC(true) {
- };
- ~spSemiLagrangeAdvVec3() { };
-
- // init plugin, return failure
- virtual bool parseParams(const ParamSet& params) {
- debMsg("spSemiLagrangeAdvVec3","parse");
- mNameFlags = params.FindOneString("flags",mNameFlags);
- mNameVel = params.FindOneString("vel",mNameVel);
- mTemp1 = params.FindOneString("temp1",mTemp1);
- mTemp2 = params.FindOneString("temp2",mTemp1);
- mNameCurrVel = params.FindOneString("vel-src",mNameCurrVel);
- mNameOldVel = params.FindOneString("vel-dst",mNameOldVel);
- mMAC = params.FindOneInt("mac",1) != 0;
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spSemiLagrangeAdvVec3","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spSemiLagrangeAdvVec3","step "<<dt);
- Vec3 mMinv,mMaxv;
- FlagGrid* flags = mpPlParams->getGridInt(mNameFlags);
- Grid<Vec3>* Currvel = mpPlParams->getGridVec3(mNameCurrVel);
- Grid<Vec3>* Oldvel = mpPlParams->getGridVec3(mNameOldVel);
- Grid<Real>* tmp1 = mpPlParams->getGridReal(mTemp1);
- Grid<Real>* tmp2 = mpPlParams->getGridReal(mTemp2);
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mNameVel);
-
- if (mMAC)
- fsSlAdvection(flags, Currvel, Oldvel, mMinv,mMaxv, dt);
- else
- {
- // X
- goCopyVec3ToScalar<Real,0>(tmp1,Currvel);
- fsSlAdvectionReal<getVelCentered>(flags, vel, tmp1, tmp2, dt, false);
- goCopyScalarToVec3<Real,0>(Oldvel,tmp2);
- // Y
- goCopyVec3ToScalar<Real,1>(tmp1,Currvel);
- fsSlAdvectionReal<getVelCentered>(flags, vel, tmp1, tmp2, dt, false);
- goCopyScalarToVec3<Real,1>(Oldvel,tmp2);
- // Z
- goCopyVec3ToScalar<Real,2>(tmp1,Currvel);
- fsSlAdvectionReal<getVelCentered>(flags, vel, tmp1, tmp2, dt, false);
- goCopyScalarToVec3<Real,2>(Oldvel,tmp2);
- }
- swapGrids(mpPlParams, mNameCurrVel, mNameOldVel);
- return true;
- };
-
- protected:
- // grid access
- std::string mNameFlags, mNameCurrVel, mNameOldVel, mNameVel, mTemp1, mTemp2;
- bool mMAC;
-};
-
-// interface for real advection
-class spSemiLagrangeAdvReal : public SolverPlugin {
- public:
- spSemiLagrangeAdvReal() :
- SolverPlugin(), mNameFlags("flags"),
- mNameVel("vel-curr"), mNameCurrReal("-unnamed1-"),
- mNameOldReal("real-temp") ,
- mAdvectLs(false) { };
- ~spSemiLagrangeAdvReal() { };
-
- // init plugin, return failure
- virtual bool parseParams(const ParamSet& params) {
- debMsg("spSemiLagrangeAdvReal","parse");
- mNameFlags = params.FindOneString("flags",mNameFlags);
- mNameVel = params.FindOneString("vel",mNameVel);
- mNameCurrReal = params.FindOneString("real-src",mNameCurrReal);
- mNameOldReal = params.FindOneString("real-dst",mNameOldReal);
- mAdvectLs = params.FindOneInt("advect-ls",mAdvectLs);
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spSemiLagrangeAdvReal","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spSemiLagrangeAdvReal","step "<<dt);
- FlagGrid* flags = mpPlParams->getGridInt(mNameFlags);
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mNameVel);
- Grid<Real>* CurrReal = mpPlParams->getGridReal(mNameCurrReal);
- Grid<Real>* newReal = mpPlParams->getGridReal(mNameOldReal);
-
- fsSlAdvectionReal<getVelCentered>(flags, vel, CurrReal, newReal, dt, mAdvectLs);
- swapGrids(mpPlParams, mNameCurrReal, mNameOldReal);
- return true;
- };
-
- protected:
- // grid access
- std::string mNameFlags, mNameVel, mNameCurrReal, mNameOldReal;
- bool mAdvectLs;
-};
-
-// mac cormack adevection - correct using the back and forth sl steps
-template < class VEL >
-class fsMacCormackCorrect : public GridOpBaseFlagbord<1> {
- public:
- fsMacCormackCorrect(FlagGrid *flags, Grid<Real> *dst, Grid<Real> *old, Grid<Real> *temp1,
- Grid<Real> *temp2, Real strength, bool advLs) :
- GridOpBaseFlagbord<1>(), mpDst(dst), mpOld(old), mpTemp1(temp1), mpTemp2(temp2)
- , mStrength(strength), mAdvectLs(advLs)
- {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
-
- ~fsMacCormackCorrect() { };
-
- void resetVariables() { };
-
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaOld.gridAccInit(mpOld, AM_READ, gaCalls);
- gaTemp1.gridAccInit(mpTemp1, AM_READ, gaCalls);
- gaTemp2.gridAccInit(mpTemp2, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- if (!fgIsFluid(getFlagAcc()(i,j,k)) ) {
- if(mAdvectLs) gaDst.write(i,j,k) = gaTemp1(i,j,k); // levelset -> copy value
- else gaDst.write(i,j,k) = 0.; // default, reset
- return;
- }
- gaDst.write(i,j,k) = gaTemp1(i,j,k) +
- (gaOld(i,j,k)
- - gaTemp2(i,j,k)) * 0.5;
-
- // interpolate between SL and MC
- if(mStrength<1.) {
- gaDst.write(i,j,k) = (1.-mStrength)*gaTemp1(i,j,k) + mStrength*gaDst(i,j,k);
- }
- };
-
- void reduce(fsMacCormackCorrect &op) { };
-
- protected:
- Grid<Real> *mpDst, *mpOld, *mpTemp1, *mpTemp2;
- GridAccessor<Real,0> gaDst;
- GridAccessor<Real,1> gaOld, gaTemp1, gaTemp2;
- Real mStrength;
- bool mAdvectLs;
-};
-
-// mac cormack adevection - clamp sl advection
-template < class VEL >
-class fsMacCormackClamp : public GridOpBaseFlagbord<SLADVBOUND> {
- public:
- fsMacCormackClamp(FlagGrid *flags, Grid<Vec3> *vel, Grid<Real> *srcreal,
- Grid<Real> *dstreal, Real dt) :
- GridOpBaseFlagbord<SLADVBOUND>(), mpVel(vel), mpSrcReal(srcreal),
- mpDstReal(dstreal), mDt(dt) {
-
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsMacCormackClamp() { };
- void resetVariables() { };
- void buildCallList() {
- gaVel.gridAccInit(mpVel, AM_READ, gaCalls);
- gaSrcReal.gridAccInit(mpSrcReal, AM_READ, gaCalls);
- gaDstReal.gridAccInit(mpDstReal, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- //! hack to fix negative rounding, this depends on always rounding down... define P2IOFF 200
-
- // apply changes for vec sladv later on...
- inline Real getSladvReal(
- const int a, const int b, const int c,
- const int src_i, const int src_j, const int src_k) {
- // default, return value
- return gaSrcReal(a,b,c);
- }
- inline Real clampValue(const int i, const int j, const int k,
- Real val) {
- int si = i, sip1 = i+1;
- int sj = j, sjp1 = j+1;
- int sk = k, skp1 = k+1;
-
- const Real v000 = getSladvReal(si ,sj ,sk , si,sj,sk);
- const Real v010 = getSladvReal(si ,sjp1,sk , si,sj,sk);
- const Real v100 = getSladvReal(sip1,sj ,sk , si,sj,sk);
- const Real v110 = getSladvReal(sip1,sjp1,sk , si,sj,sk);
-
- // compute minima/maxima
- Real max = v000, min=v000;
- if(v010>max) max = v010;
- if(v100>max) max = v100;
- if(v110>max) max = v110;
-
- if(v010<min) min = v010;
- if(v100<min) min = v100;
- if(v110<min) min = v110;
-
- if(DDF_DIMENSION==3) {
- const Real v001 = getSladvReal(si ,sj ,skp1, si,j,k);
- const Real v011 = getSladvReal(si ,sjp1,skp1, si,sj,sk);
- const Real v101 = getSladvReal(sip1,sj ,skp1, si,j,k);
- const Real v111 = getSladvReal(sip1,sjp1,skp1, si,sj,sk);
-
- if(v001>max) max = v001;
- if(v011>max) max = v011;
- if(v101>max) max = v101;
- if(v111>max) max = v111;
- if(v001<min) min = v001;
- if(v011<min) min = v011;
- if(v101<min) min = v101;
- if(v111<min) min = v111;
- }
- if(val<min) return min;
- if(val>max) return max;
- return val;
- }
-
- // same as semi-lagrange advection, only clamp instead of interpolation
- inline void operator() (int i, int j, int k) {
- // always init...?
- if (fgIsObstacle(getFlagAcc()(i,j,k)) ) {
- return;
- }
- if (!fgIsFluid(getFlagAcc()(i,j,k)) ) {
- return;
- }
- const Vec3 vel = VEL::getVelocity(gaVel, i,j,k);
-
- Real srcpi = (Real)i-(vel[0]*mDt);
- Real srcpj = (Real)j-(vel[1]*mDt);
- Real srcpk = (Real)k-(vel[2]*mDt);
-
- int srci = (int)srcpi;
- int srcj = (int)srcpj;
- int srck = (int)srcpk;
- CLAMP_TO_GRID(srci,srcj,srck,mpVel);
-
- gaDstReal.write(i,j,k) = clampValue(srci,srcj,srck, gaDstReal(i,j,k) );
- };
- void reduce(fsMacCormackClamp &op) {
- // ...
- };
- protected:
- Grid<Vec3> *mpVel;
- Grid<Real> *mpSrcReal;
- Grid<Real> *mpDstReal;
- Real mDt;
- GridAccessor<Vec3,1> gaVel;
- GridAccessor<Real,SLADVBOUND> gaSrcReal;
- GridAccessor<Real,0> gaDstReal;
-}; // fsMacCormackClamp */
-
-
-// mac cormack adevection - clamp boundaries
-template < class VEL >
-class fsMacCormackBoundaryClamp : public GridOpBaseFlagbord<SLADVBOUND> {
- public:
- fsMacCormackBoundaryClamp(FlagGrid *flags, Grid<Vec3> *vel,
- Grid<Real> *dstreal, Grid<Real> *srcorg, Real dt) :
- GridOpBaseFlagbord<SLADVBOUND>(),
- mpVel(vel),
- mpSrcOrg(srcorg),
- mpDstReal(dstreal),
- mDt(dt)
- {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
-
- ~fsMacCormackBoundaryClamp() { };
-
- void resetVariables() { };
-
- void buildCallList() {
- gaVel.gridAccInit(mpVel, AM_READ, gaCalls);
- gaDstReal.gridAccInit(mpDstReal, AM_WRITE, gaCalls);
- gaSrcOrg.gridAccInit(mpSrcOrg, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- // same as semi-lagrange advection, only clamp instead of interpolation
- inline void operator() (int i, int j, int k) {
- // always init...?
- if (fgIsObstacle(getFlagAcc()(i,j,k)) ) {
- return;
- }
- if (!fgIsFluid(getFlagAcc()(i,j,k)) ) {
- // NT fix, preserve surrounding values from original grid everywhere in empty space
- gaDstReal.write(i,j,k) = gaSrcOrg(i,j,k); // fix , SURROUND_RESET
- return;
- }
- const Vec3 vel = VEL::getVelocity(gaVel, i,j,k);
- bool doReset = false;
-
- // forward lookup
- Real srcpiForw = (Real)i-(vel[0]*mDt);
- Real srcpjForw = (Real)j-(vel[1]*mDt);
- Real srcpkForw = (Real)k-(vel[2]*mDt);
- // backward lookup
- Real srcpiBack = (Real)i+(vel[0]*mDt);
- Real srcpjBack = (Real)j+(vel[1]*mDt);
- Real srcpkBack = (Real)k+(vel[2]*mDt);
-
- int srciForw = (int)srcpiForw;
- int srcjForw = (int)srcpjForw;
- int srckForw = (int)srcpkForw;
- if( CLAMP_TO_GRID_BOOL(srciForw,srcjForw,srckForw,mpVel) ) doReset = true;
-
- int srciBack = (int)srcpiBack;
- int srcjBack = (int)srcpjBack;
- int srckBack = (int)srcpkBack;
- if(!doReset) {
- if( CLAMP_TO_GRID_BOOL(srciBack,srcjBack,srckBack,mpVel) ) doReset = true;
- } // not yet reset
-
- if(!doReset) {
- if ( fgIsObstacle(getFlagAcc()(srciForw,srcjForw,srckForw)) ||
- fgIsObstacle(getFlagAcc()(srciBack,srcjBack,srckBack))
- ) {
- doReset = true;
- }
- } // not yet reset
-
- if(doReset) {
- gaDstReal.write(i,j,k) = gaSrcOrg(i,j,k);
- }
- };
- void reduce(fsMacCormackBoundaryClamp &op) {
- // ...
- };
- protected:
- Grid<Vec3> *mpVel;
- Grid<Real> *mpSrcOrg;
- Grid<Real> *mpDstReal;
- Real mDt;
- GridAccessor<Vec3,1> gaVel;
- GridAccessor<Real,0> gaDstReal;
- GridAccessor<Real,0> gaSrcOrg;
-}; // fsMacCormackBoundaryClamp */
-
-
-// interface for MacCormack advection of a scalar field
-class spMacCormackReal : public SolverPlugin {
- public:
- spMacCormackReal() :
- SolverPlugin(), mNameFlags("flags"),
- mNameVel("vel-curr"),
- mNameCurrReal("-unnamed1-"), mNameOldReal("real-temp") ,
- mNameTemp1("temp1"), mNameTemp2("temp2") ,
- mStrength(0.5), mAdvectLs(false)
- { };
- ~spMacCormackReal() { };
-
- // init plugin, return failure
- virtual bool parseParams(const ParamSet& params) {
- debMsg("spMacCormackReal","parse");
- mNameFlags = params.FindOneString("flags",mNameFlags);
- mNameVel = params.FindOneString("vel",mNameVel);
- mNameCurrReal = params.FindOneString("real-src",mNameCurrReal);
- mNameOldReal = params.FindOneString("real-dst",mNameOldReal);
- mNameTemp1 = params.FindOneString("temp1",mNameTemp1);
- mNameTemp2 = params.FindOneString("temp2",mNameTemp2);
- mAdvectLs = params.FindOneInt("advect-ls",mAdvectLs);
- mStrength = params.FindOneFloat("strength",mStrength);
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spMacCormackReal","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spMacCormackReal","step "<<dt);
-
- FlagGrid* flags = mpPlParams->getGridInt(mNameFlags);
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mNameVel);
- Grid<Real>* CurrReal = mpPlParams->getGridReal(mNameCurrReal);
- Grid<Real>* newReal = mpPlParams->getGridReal(mNameOldReal);
- Grid<Real>* temp1 = mpPlParams->getGridReal(mNameTemp1);
- Grid<Real>* temp2 = mpPlParams->getGridReal(mNameTemp2);
-
- // normal forward step
- fsSlAdvectionReal<getVelCentered>(flags, vel, CurrReal, temp1, dt, mAdvectLs);
-
- // backwards step
- fsSlAdvectionReal<getVelCentered>(flags, vel, temp1, temp2, -1. * dt, mAdvectLs);
-
- // compute correction
- fsMacCormackCorrect<getVelCentered>(flags, newReal, CurrReal, temp1, temp2, mStrength, mAdvectLs);
-
- // clamp values
- fsMacCormackClamp<getVelCentered>(flags, vel, CurrReal, newReal, dt);
- //fsMacCormackBoundaryClamp(flags, vel, CurrReal, temp1, dt);
- fsMacCormackBoundaryClamp<getVelCentered>(flags, vel, newReal, temp1, dt);
-
- swapGrids(mpPlParams, mNameCurrReal, mNameOldReal);
- return true;
- };
-
- protected:
- // grid access
- std::string mNameFlags, mNameVel, mNameCurrReal, mNameOldReal, mNameTemp1, mNameTemp2;
- Real mStrength;
- bool mAdvectLs;
-};
-
-// interface for maccormack advection of the velocities
-class spMacCormackVec3 : public SolverPlugin {
- public:
- spMacCormackVec3() :
- SolverPlugin(), mNameFlags("flags"),
- mNameVel("vel-curr"),
- mNameCurrVec3("vel-curr"), mNameOldVec3("vec-temp") ,
- mNameTemp1("temp1"), mNameTemp2("temp2"), mMAC(true)
- { };
- ~spMacCormackVec3() { };
-
- // init plugin, return failure
- virtual bool parseParams(const ParamSet& params) {
- debMsg("spMacCormackVec3","parse");
- mNameFlags = params.FindOneString("flags",mNameFlags);
- mNameCurrVec3 = params.FindOneString("vel-src",mNameCurrVec3);
- mNameOldVec3 = params.FindOneString("vel-dst",mNameOldVec3);
- mMAC = params.FindOneInt("mac",1) != 0;
-
- // reuse currvec3, if given
- mNameVel = params.FindOneString("vel",mNameCurrVec3);
-
- mNameTemp1 = params.FindOneString("temp1",mNameTemp1);
- mNameTemp2 = params.FindOneString("temp2",mNameTemp2);
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spMacCormackVec3","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spMacCormackVec3","step "<<dt);
- const Real mStrength = 0.5;
-
- FlagGrid* flags = mpPlParams->getGridInt(mNameFlags);
- Grid<Vec3>* advVel = mpPlParams->getGridVec3(mNameVel);
- Grid<Vec3>* currVec3 = mpPlParams->getGridVec3(mNameCurrVec3);
- Grid<Vec3>* oldVec3 = mpPlParams->getGridVec3(mNameOldVec3);
- Grid<Real>* temp1 = mpPlParams->getGridReal(mNameTemp1);
- Grid<Real>* temp2 = mpPlParams->getGridReal(mNameTemp2);
-
- Grid<Real>* realTmp = mpPlParams->getGridReal("residual");
- Grid<Real>* realNew = mpPlParams->getGridReal("tmp");
-
- // normal forward step
- bool advectLs = false;
- //fsSlAdvectionReal<getVelCentered>(flags, currVec3, realTmp, temp1, dt, advectLs);
-
- if (mMAC)
- {
- // X
- goCopyVec3ToScalar<Real,0>(realTmp,currVec3);
- // normal forward step
- fsSlAdvectionReal<getVelX>(flags, advVel, realTmp, temp1, dt, advectLs);
- // backwards step
- fsSlAdvectionReal<getVelX>(flags, advVel, temp1, temp2, -1. * dt, advectLs);
- // compute correction
- fsMacCormackCorrect<getVelX>(flags, realNew, realTmp, temp1, temp2, mStrength, advectLs);
- // clamp values
- fsMacCormackClamp<getVelX>(flags, advVel, realTmp, realNew, dt);
- fsMacCormackBoundaryClamp<getVelX>(flags, advVel, realNew, temp1, dt);
- goCopyScalarToVec3<Real,0>(oldVec3,realNew);
-
- // Y
- goCopyVec3ToScalar<Real,1>(realTmp,currVec3);
- // normal forward step
- fsSlAdvectionReal<getVelY>(flags, advVel, realTmp, temp1, dt, advectLs);
- // backwards step
- fsSlAdvectionReal<getVelY>(flags, advVel, temp1, temp2, -1. * dt, advectLs);
- // compute correction
- fsMacCormackCorrect<getVelY>(flags, realNew, realTmp, temp1, temp2, mStrength, advectLs);
- // clamp values
- fsMacCormackClamp<getVelY>(flags, advVel, realTmp, realNew, dt);
- fsMacCormackBoundaryClamp<getVelY>(flags, advVel, realNew, temp1, dt);
- goCopyScalarToVec3<Real,1>(oldVec3,realNew);
-
- // Z
- goCopyVec3ToScalar<Real,2>(realTmp,currVec3);
- // normal forward step
- fsSlAdvectionReal<getVelZ>(flags, advVel, realTmp, temp1, dt, advectLs);
- // backwards step
- fsSlAdvectionReal<getVelZ>(flags, advVel, temp1, temp2, -1. * dt, advectLs);
- // compute correction
- fsMacCormackCorrect<getVelZ>(flags, realNew, realTmp, temp1, temp2, mStrength, advectLs);
- // clamp values
- fsMacCormackClamp<getVelZ>(flags, advVel, realTmp, realNew, dt);
- fsMacCormackBoundaryClamp<getVelZ>(flags, advVel, realNew, temp1, dt);
- goCopyScalarToVec3<Real,2>(oldVec3,realNew);
- }
- else
- {
- for (int i=0;i<3;i++)
- {
- if (i==0) goCopyVec3ToScalar<Real,0>(realTmp,currVec3);
- if (i==1) goCopyVec3ToScalar<Real,1>(realTmp,currVec3);
- if (i==2) goCopyVec3ToScalar<Real,2>(realTmp,currVec3);
- // normal forward step
- fsSlAdvectionReal<getVelCentered>(flags, advVel, realTmp, temp1, dt, advectLs);
- // backwards step
- fsSlAdvectionReal<getVelCentered>(flags, advVel, temp1, temp2, -1. * dt, advectLs);
- // compute correction
- fsMacCormackCorrect<getVelCentered>(flags, realNew, realTmp, temp1, temp2, mStrength, advectLs);
- // clamp values
- fsMacCormackClamp<getVelCentered>(flags, advVel, realTmp, realNew, dt);
- fsMacCormackBoundaryClamp<getVelCentered>(flags, advVel, realNew, temp1, dt);
- if (i==0) goCopyScalarToVec3<Real,0>(oldVec3,realNew);
- if (i==1) goCopyScalarToVec3<Real,1>(oldVec3,realNew);
- if (i==2) goCopyScalarToVec3<Real,2>(oldVec3,realNew);
- }
- }
- swapGrids(mpPlParams, mNameCurrVec3, mNameOldVec3);
- return true;
- };
-
- protected:
- // grid access
- std::string mNameFlags, mNameVel, mNameCurrVec3, mNameOldVec3, mNameTemp1, mNameTemp2;
- bool mMAC;
- //bool mAdvectLs;
-};
-
-//*****************************************************************************
-// external accessor helper function
-
-void doSemiLagrangeReal(FlagGrid* flags, Grid<Vec3>* vel, Grid<Real>* src, Grid<Real>* dst, Real dt)
-{
- fsSlAdvectionReal<getVelCentered>(flags, vel, src, dst, dt, false);
-}
-
-//*****************************************************************************
-
-// create one of the standard hard coded plugins
-SolverPlugin* MakeAdvectionPlugin(std::string name) {
-
- if(name.compare("semi-lagr-advect-vec3")==0) {
- return new spSemiLagrangeAdvVec3;
- } else if(name.compare( "semi-lagr-advect-real")==0) {
- return new spSemiLagrangeAdvReal;
-
- } else if(name.compare( string("maccormack-advect-real") )==0) {
- return new spMacCormackReal;
- } else if(name.compare( string("maccormack-advect-vec3") )==0) {
- return new spMacCormackVec3;
- }
-
- return NULL;
-}
-
-
-} // end namespace DDF
-
diff --git a/intern/smoke/intern/source/animplugins.cpp b/intern/smoke/intern/source/animplugins.cpp
deleted file mode 100644
index ba7bb884f82..00000000000
--- a/intern/smoke/intern/source/animplugins.cpp
+++ /dev/null
@@ -1,642 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Plugins to animate boundaries and ABL fields.
- *
- *****************************************************************************/
-
-#include <fstream>
-#include "fluidsolver.h"
-#include "solverplugin.h"
-#include "paramset.h"
-#include "quaternion.h"
-#include <zlib.h>
-
-#include "matrixbase.h"
-
-using namespace std;
-
-// safety boundary for semi lagrange advection step
-#define SLADVBOUND 2
-
-namespace DDF {
-
-class ObjectTransformation {
- public:
- ObjectTransformation(Real v) :
- center(v), pos(v), posVel(v),
- rotMat(v), rotVel(v),
- scale(v), scaleVel(v) {};
-
- Vec3 center;
- Vec3 pos, posVel;
- Mat4 rotMat;
- Vec3 rotVel;
- Vec3 scale, scaleVel;
-};
-
-//*****************************************************************************
-// Gridop : update moving obstacles
-class opSetMovingObstacleBC : public GridOpBaseFlagbord<SLADVBOUND> {
- public:
- opSetMovingObstacleBC(FlagGrid *flags, Grid<Vec3> *vel, FlagGrid *obs,
- ObjectTransformation trafo, Real dt, bool deleteOld, Grid<Real> *distsrc, Grid<Real> *distdst, const vector<Vec3>& if1, const vector<Vec3>& if2, bool doforces) :
- GridOpBaseFlagbord<SLADVBOUND>(),
- mpVel(vel), mTrafo(trafo), mDt(dt) ,
- mpObs(obs), mDeleteOld(deleteOld), mIF1(), mIF2(), mpDistSrc(distsrc), mpDistDst(distdst), mDoForces(doforces)
- {
- mpFlags = flags;
-
- // don't scale to infinity
- if (normNoSqrt(mTrafo.scale) < 1e-16) mTrafo.scale = 1.;
-
- // transform positions to src coordinates
- Vec3 srcSize = vec2R(mpFlags->getSize());
- Vec3 destSize = vec2R(mpObs->getSize());
- mCenterFlag = (mTrafo.center + mTrafo.pos) * srcSize;
- mTrafo.pos *= srcSize;
- mTrafo.center *= destSize;
- mTrafo.scale = Vec3(destSize.max()/srcSize.max()) / mTrafo.scale;
- mTrafo.posVel *= srcSize;
-
- for (unsigned i=0; i<if1.size(); i++) mIF1.push_back( if1[i] * destSize);
- for (unsigned i=0; i<if2.size(); i++) mIF2.push_back( if2[i] * destSize);
-
- cout << "pos " << mTrafo.pos << " scale " << mTrafo.scale << " center " << mTrafo.center << endl;
- debMsg("opSetMovingObstacleBC","pos="<<mTrafo.pos << " ");
-
- // assume an additional layer of obstacle cells, so BND=2
- applyOperatorWithBoundToGrid(this, mpFlags, 1);
- };
-
-
- ~opSetMovingObstacleBC() { };
- void resetVariables() { };
- void reduce(opSetMovingObstacleBC &op) { };
-
- void buildCallList() {
- this->gaFlags.gridAccInit(mpFlags, AM_WRITE, gaCalls);
- gaVel.gridAccInit(mpVel, AM_WRITE, gaCalls);
- gaObs.gridAccInit(mpObs, AM_READ, gaCalls);
-
- if(mpDistSrc) gaDistSrc.gridAccInit(mpDistSrc, AM_READ, gaCalls);
- if(mpDistDst) gaDistDst.gridAccInit(mpDistDst, AM_READWRITE, gaCalls);
- //setFlags(mpFlags);
- };
-
- // point transformation
- inline void trafoPoint(Vec3 &pos, Mat4 &mat) {
- pos -= mCenterFlag;
- pos = (mat * pos) * mTrafo.scale;
- pos += mTrafo.center; // to dest coordinates
- }
-
- inline void operator() (int i, int j, int k) {
- int srcFlag = FEMPTY;
- Vec3 currVel = mTrafo.posVel;
- Vec3 pos (i,j,k);
- nVec3i src (1,1,1);
-
- // with rotation, use trafo matrix
- if (mDoForces)
- {
- Vec3 r = (pos-mCenterFlag);
- currVel += cross( mTrafo.rotVel, r );
- }
- trafoPoint( pos, mTrafo.rotMat);
- src = vecround( pos);
-
- // check validity of lookup
- bool isvalid = mpObs->checkIndexValidWithBounds(src.x,src.y,src.z, 1);
- if(isvalid)
- srcFlag = gaObs( src.x,src.y,src.z );
-
- // write new flag grid
- if (mDeleteOld && fgIsObstacle( getFlagAcc()(i,j,k) ) )
- this->gaFlags.write(i,j,k) = FEMPTY;
-
- if (!isvalid) return;
-
- if (fgIsObstacle(srcFlag) ) {
- gaFlags.write(i,j,k) = FOBSTACLE;
- if (mDoForces) gaVel.write(i,j,k) = currVel; // velocity boundary condition
- }
- else if (mpDistSrc != NULL) {
- // join distance fields, if the exist
- Real ndst = gaDistDst(i,j,k), nsrc = gaDistSrc(src.x,src.y,src.z);
- if (nsrc > 0 && (ndst == 0 || nsrc < ndst))
- gaDistDst.write(i,j,k) = nsrc;
- }
-
- // initialize density source (moving smoke-box)
- for (unsigned n=0; n<mIF1.size(); n++)
- {
- if (src.x >= mIF1[n].x && src.y >= mIF1[n].y && src.z >= mIF1[n].z &&
- src.x <= mIF2[n].x && src.y <= mIF2[n].y && src.z <= mIF2[n].z)
- this->gaFlags.write(i,j,k) = gaFlags(i,j,k) | FDENSITYSOURCE;
- }
-
- // done...
- };
- protected:
- Grid<Vec3> *mpVel;
- GridAccessor<Vec3,1> gaVel;
-
- ObjectTransformation mTrafo;
-
- Real mDt;
- FlagGrid *mpObs;
- GridAccessor<int,0> gaObs;
- Vec3 mCenterFlag;
- bool mDeleteOld;
-
- Mat4 mMatRot,mMatRotNext;
-
- vector<Vec3> mIF1, mIF2;
- Grid<Real> *mpDistSrc, *mpDistDst;
- GridAccessor<Real,1> gaPhiDebug;
- GridAccessor<Real,0> gaDistSrc, gaDistDst;
- bool mDoForces;
-};
-
-//*****************************************************************************
-// Plugin for moving obstacles with linear speed
-class spSetMovingObstacleBC : public SolverPlugin {
- public:
- spSetMovingObstacleBC() :
- SolverPlugin(), mNameFlags("flags"),
- mNameVel("vel-curr"), mObstacle(""),mTrafo(0.)
- { };
- ~spSetMovingObstacleBC() { };
-
- // init plugin, return failure
- virtual bool parseParams(const ParamSet& params) {
- mNameFlags = params.FindOneString("flags",mNameFlags); // flag grid
- mNameFlagsSrc = params.FindOneString("flags-src",""); // static background flag grid
- mNameVel = params.FindOneString("vel","vel-curr"); // velocity grid
- mObstacle = params.FindOneString("obstacle",mObstacle); // flag grid of the moving object
-
- mTrafo.posVel = params.FindOneVector("obs-vel",mTrafo.posVel); // linear velocity
- mTrafo.pos = params.FindOneVector("obs-pos",mTrafo.pos); // initial position
-
- // center of rotation/scale
- mTrafo.center = params.FindOneVector("obs-center",mTrafo.center); // rotation pivot
- mRotAxis = params.FindOneVector("obs-rot-axis",Vec3(0.)); // rotation axis
- mRotAngle = params.FindOneFloat("obs-rot-angle",0.); // initial rotation angle (degrees)
- mRotVel = params.FindOneFloat("obs-rot-vel",0.); // rotation velocity (degrees/timestep)
- mTrafo.scaleVel = params.FindOneVector("obs-scale-vel",mTrafo.scaleVel); // scale velocity
- mTrafo.scale = params.FindOneVector("obs-scale",mTrafo.scale); // initial scaling
- mRotAngle *= M_PI/180.;
- mRotVel *= M_PI/180.;
- normalize(mRotAxis);
- mTrafo.rotVel = mRotAxis * mRotVel;
- return true;
- };
- virtual bool initPlugin() {
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spSetMovingObstacleBC","step "<<dt);
- const Real mStrength = 0.5;
-
- // get grids
- FlagGrid* flags = mpPlParams->getGridInt(mNameFlags);
- FlagGrid* flagsrc = mNameFlagsSrc.empty() ? NULL : mpPlParams->getGridInt(mNameFlagsSrc);
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mNameVel);
- FlagGrid* obs = mpPlParams->getGridInt(mObstacle);
- Grid<Real>* phiCurr = NULL; // mpPlParams->getGridReal("phi-curr");
-
- // copy background grid
- if (flagsrc) goCopyGrid<int>(flags,flagsrc);
-
- // set flags & velocities inside cells
- Quat q(mRotAxis,mRotAngle);
- mTrafo.rotMat = q.getRotMat();
- opSetMovingObstacleBC(flags, vel, obs, mTrafo, dt, flagsrc==NULL, NULL, NULL, vector<Vec3>(),vector<Vec3>(),true);
-
- // initialize obstacle boundaries with velocities
- FOR_IJK_GRID(flags) {
- if (!fgIsObstacle( flags->getGlobal(i,j,k) ) ) {
- if (i>0 && fgIsObstacle( flags->getGlobal(i-1,j,k) ) ) {
- vel->getGlobal(i,j,k)[0] = vel->getGlobal(i-1,j,k)[0];
- }
- if (j>0 && fgIsObstacle( flags->getGlobal(i,j-1,k) ) ) {
- vel->getGlobal(i,j,k)[1] = vel->getGlobal(i,j-1,k)[1];
- }
- if(gDim==3 && (k>0 && fgIsObstacle( flags->getGlobal(i,j,k-1) ) )) {
- vel->getGlobal(i,j,k)[2] = vel->getGlobal(i,j,k-1)[2];
- }
- }
- else {
- // reset level set inside of the obstacle?
- if (phiCurr) {
- if(phiCurr->getGlobal(i,j,k)<0.) phiCurr->getGlobal(i,j,k) = 0.5;
- }
- }
- }
-
- // update pos, rot, scale
- mTrafo.pos += mTrafo.posVel * dt;
- mRotAngle += mRotVel * dt;
- mTrafo.scale += mTrafo.scaleVel * dt;
-
- return true;
- };
-
- protected:
- std::string mNameFlags, mNameVel, mObstacle, mNameFlagsSrc;
- ObjectTransformation mTrafo;
- Vec3 mRotAxis;
- Real mRotAngle, mRotVel;
-};
-
-//*****************************************************************************
-// A set of precalculated boundary layers
-class VortexDBSet {
- public:
- // load from file
- VortexDBSet(gzFile& gzf, int numPhi, int numTheta, const Vec3& sizeFlags)
- {
- Real gd;
- if (gzread(gzf,&numPoints,sizeof(int)) != sizeof(int)) { errFatal("spAnimate::initPlugin","gzread failed", SIMWORLD_INITERROR); }
- if (gzread(gzf,&gd,sizeof(Real)) != sizeof(Real)) { errFatal("spAnimate::initPlugin","gzread failed", SIMWORLD_INITERROR); }
- if (gzread(gzf,&mSize[0],sizeof(Vec3)) != sizeof(Vec3)) { errFatal("spAnimate::initPlugin","gzread failed", SIMWORLD_INITERROR); }
- if (gzread(gzf,&mVScale[0],sizeof(Vec3)) != sizeof(Vec3)) { errFatal("spAnimate::initPlugin","gzread failed", SIMWORLD_INITERROR); }
- if (gzread(gzf,&mVOffs[0],sizeof(Vec3)) != sizeof(Vec3)) { errFatal("spAnimate::initPlugin","gzread failed", SIMWORLD_INITERROR); }
- mPos.resize(numPoints);
- mNoDir.resize(numPoints);
- for (int i=0;i<numPoints;i++)
- if (gzread(gzf,&mPos[i][0],sizeof(Vec3)) != sizeof(Vec3)) { errFatal("spAnimate::initPlugin","gzread failed", SIMWORLD_INITERROR); }
- for (int i=0;i<numPoints;i++)
- if (gzread(gzf,&mNoDir[i][0],sizeof(Vec3)) != sizeof(Vec3)) { errFatal("spAnimate::initPlugin","gzread failed", SIMWORLD_INITERROR); }
- mLookup.resize(numTheta);
- for (int i=0;i<numTheta;i++)
- {
- mLookup[i] = vector<int>(numPhi);
- if (gzread(gzf,&mLookup[i][0],numPhi*sizeof(int)) != (int)(numPhi*sizeof(int))) { errFatal("spAnimate::initPlugin","gzread failed", SIMWORLD_INITERROR); }
- }
- gd /= sizeFlags.max();
- mIGriddiv2 = 1./ ( gd*gd);
- mIScale = sizeFlags / (mVScale * mSize);
- //cout << "load set : N " << mSize << " vscale " << mVScale<< " offs " << mVOffs << endl << numPoints << " items" << endl;
- }
-
- // bilinear interpolation of the nearest datapoints in the set
- void bilinearChooseSets(const vector<Real>& mPhi, const vector<Real>& mTheta, const vector<Vec3>& mSetDir, Real& a11, Real& a12, Real& a21, Real& a22, int& idx11, int& idx12, int& idx21, int& idx22, const Vec3& vel, Real& mult) const
- {
- Vec3 dir = vel;
- mult = normalize(dir); cout << " norm dir " << mult;
- if (mult < 1e-10){
- mult=0; return;
- }
- mult /= mNorm; cout << " set norm " << mNorm << " total " << mult << endl;
- Real phi, theta;
- vecToAngle(dir, phi, theta);
-
- // find linear coefficients
- int idxp1=0, idxp2=mPhi.size()-1;
- for (unsigned i=0;i<mPhi.size();i++)
- {
- if (mPhi[i] <= phi && mPhi[i] > mPhi[idxp1]) idxp1=i;
- if (mPhi[i] >= phi && mPhi[i] < mPhi[idxp2]) idxp2=i;
- }
- Real ap = (idxp1 == idxp2) ? 0 : (phi - mPhi[idxp1]) / (mPhi[idxp2] - mPhi[idxp1]);
-
- int idxt1=0, idxt2=mTheta.size()-1;
- for (unsigned i=0;i<mTheta.size();i++)
- {
- if (mTheta[i] <= theta && mTheta[i] > mTheta[idxt1]) idxt1=i;
- if (mTheta[i] >= theta && mTheta[i] < mTheta[idxt2]) idxt2=i;
- }
- Real at = (idxt1 == idxt2) ? 0 : (theta - mTheta[idxt1]) / (mTheta[idxt2] - mTheta[idxt1]);
-
- idx11 = mLookup[idxt1][idxp1]; a11 = (1.-at)*(1.-ap);
- idx12 = mLookup[idxt1][idxp2]; a12 = (1.-at)*(ap);
- idx21 = mLookup[idxt2][idxp1]; a21 = (at)*(1.-ap);
- idx22 = mLookup[idxt2][idxp2]; a22 = (at)*(ap);
-
- //printf("phi %g theta %g : chose phi= %g(%g)%g ,theta= %g(%g)%g\n",phi*180./M_PI,theta*180./M_PI,mPhi[idxp1]*180./M_PI,ap,mPhi[idxp2]*180./M_PI,mTheta[idxt1]*180./M_PI,at,mTheta[idxt2]*180./M_PI );
- //cout << vel << " to " << mSetDir[idx11]*mult << " " << mSetDir[idx12]*mult << " " << mSetDir[idx21]*mult << " " << mSetDir[idx22]*mult << endl;
- //cout << idx11 << "," << idx12 << "," << idx21 << "," << idx22 << "," <<endl;
- //cout << "final : " << mult*(a11*mSetDir[idx11]+a12*mSetDir[idx12]+a21*mSetDir[idx21]+a22*mSetDir[idx22]) << " to orig " << vel <<endl;
-
- }
-
- // map confined vorticity to simulation grid
- void mapdown(FlagGrid *flags, Grid<Vec3>* dst, const Mat4& rot, const Vec3& pos, const Vec3& nvec, const vector<vector<Vec3> >& mSetVort, const vector<Real>& mPhi, const vector<Real>& mTheta, const vector<Vec3>& mSetDir, const Vec3& cnt, const Vec3& sc)
- {
- Real mult, a11, a12, a21, a22;
- int idx11, idx12, idx22, idx21;
- bilinearChooseSets(mPhi,mTheta,mSetDir, a11,a12,a21,a22,idx11,idx12,idx21,idx22,nvec,mult);
- if (mult == 0) return;
-
- Vec3 srcSize = vec2R(flags->getSize());
- Vec3 centerSrc = (cnt + pos) * srcSize;
- Vec3 centerDst = cnt * mSize;
- Vec3 iscale = Vec3(srcSize.max()/mSize.max()) * sc;
- cout << "mult " << mult << " gridd " << iscale << " total " << mult*mIGriddiv2 <<endl;
- //mult /= mIGriddiv2;
- Real pt,pp;
- vecToAngle(nvec,pp,pt);
- for (unsigned n=0;n<mPos.size();n++)
- {
- Vec3 p = (mPos[n] - centerDst) * iscale;
- p = rot * p;
- p += centerSrc;
- // transfer vorticity sources
- nVec3i npos = vecround(p);
-
- if (!flags->checkIndexValid(npos.x,npos.y,npos.z)) continue;
- //printf("point %d : set %g %g %g grid %g %g %g\n",n,mPos[n].x,mPos[n].y,mPos[n].z,p.x,p.y,p.z);
-
- if (fgIsFluid(flags->getGlobal(npos.x,npos.y,npos.z)))
- {
- Vec3 vsi = a11*mSetVort[idx11][n];
- vsi += a12*mSetVort[idx12][n];
- vsi += a21*mSetVort[idx21][n];
- vsi += a22*mSetVort[idx22][n];
- Vec3 vs = rot * vsi;
- (*dst)(npos.x,npos.y,npos.z) += -vs * mult;
- //cout << dst->getName() << ":" << npos << " <<= " <<-vs*mult << " : " << (*dst)(npos.x,npos.y,npos.z) << endl;
- }
- }
- }
-
- vector<vector<int> > mLookup;
- vector<Vec3> mPos, mNoDir;
- Vec3 mVScale, mVOffs, mSize, mIScale;
- Real mIGriddiv2, mNorm;
- int numPoints;
-};
-
-//*****************************************************************************
-// Interface for precalculated DB
-class VortexDB
-{
- public:
- // load from file
- VortexDB(const string& file, const Vec3& sizeFlags)
- {
- // load database
- int numSets, numPhi, numTheta;
- gzFile gzf = gzopen(file.c_str(),"rb");
- if (gzf == NULL) { errFatal("spAnimate::initPlugin","can't open vortex source database",SIMWORLD_INITERROR);exit(1); }
- if (gzread(gzf,&numSets,sizeof(int)) != sizeof(int)) { errFatal("spAnimate::initPlugin","gzread numSets failed",SIMWORLD_INITERROR); }
- if (gzread(gzf,&numTheta,sizeof(int)) != sizeof(int)) { errFatal("spAnimate::initPlugin","gzread numTheta failed",SIMWORLD_INITERROR); }
- if (gzread(gzf,&numPhi,sizeof(int)) != sizeof(int)) { errFatal("spAnimate::initPlugin","gzread numPhi failed",SIMWORLD_INITERROR); }
- mTheta.resize(numTheta);
- mPhi.resize(numPhi);
- if (gzread(gzf,&mTheta[0],numTheta*sizeof(Real)) != (int)(numTheta*sizeof(Real))) { errFatal("spAnimate::initPlugin","gzread theta failed",SIMWORLD_INITERROR); }
- if (gzread(gzf,&mPhi[0],numPhi*sizeof(Real)) != (int)(numPhi*sizeof(Real))) { errFatal("spAnimate::initPlugin","gzread phi failed",SIMWORLD_INITERROR); }
- mTrans = new VortexDBSet(gzf, numPhi, numTheta, sizeFlags);
- mRot = new VortexDBSet(gzf, numPhi, numTheta, sizeFlags);
-
- mSetDir.resize(numSets);
- mSetVort.resize(numSets);
- for (int i=0;i<numSets;i++)
- {
- VortexDBSet *cset = ((i & 1) == 0) ? mTrans : mRot;
- if (gzread(gzf,&mSetDir[i][0],sizeof(Vec3)) != sizeof(Vec3)) { errFatal("spAnimate::initPlugin","gzread u0 failed",SIMWORLD_INITERROR); }
-
- mSetVort[i] = vector<Vec3>(cset->numPoints);
- for (int j=0;j<cset->numPoints;j++)
- if (gzread(gzf,&mSetVort[i][j][0],sizeof(Vec3)) != sizeof(Vec3)) { errFatal("spAnimate::initPlugin","gzread data failed",SIMWORLD_INITERROR); }
- }
- mTrans->mNorm = norm(mSetDir[0]);
- mRot->mNorm = norm(mSetDir[1]);
-
- gzclose(gzf);
- debMsg("VortexDB::VortexDB()", "VDB loaded, " << numSets << " sets");
- }
- ~VortexDB()
- {
- delete mRot;
- delete mTrans;
- }
-
- // map confined vorticity to simulation grid
- void project(FlagGrid *flags, Grid<Vec3>* dst, const ObjectTransformation& trafo, const Vec3& uvel)
- {
- Mat4 matRotBack = trafo.rotMat;
- matRotBack.transpose();
- Vec3 uv = trafo.rotMat * uvel;
- Vec3 urot = matRotBack * trafo.rotVel;
- cout << "linear " << uv << " (unrot " << uvel << ") rot " << urot << " (unrot " << trafo.rotVel << ")" <<endl;
-
- mTrans->mapdown(flags, dst, matRotBack, trafo.pos, uv, mSetVort, mPhi, mTheta, mSetDir, trafo.center, trafo.scale);
- mRot->mapdown(flags, dst, matRotBack, trafo.pos, urot, mSetVort, mPhi, mTheta, mSetDir, trafo.center, trafo.scale);
- }
-
- private:
- vector<Real> mPhi, mTheta;
- vector<vector<Vec3> > mSetVort;
- vector<Vec3> mSetDir;
- VortexDBSet *mRot, *mTrans;
-};
-
-// Helper class for loading animation data
-class AnimFrame
-{
- public:
- AnimFrame(ifstream& ifs)
- {
- Real rx,ry,rz; Mat4 mat;
- ifs >> time >> pos.x >> pos.y >> pos.z >> rx >> ry >> rz; ifs.ignore(1000,'\n');
- rot = Quat(rx*M_PI/180.,ry*M_PI/180.,rz*M_PI/180.);
- }
-
- Vec3 pos, pvel, rvel;
- Quat rot;
- Real time;
-};
-
-//*****************************************************************************
-// load and playback animation
-class spAnimate : public SolverPlugin {
- public:
- spAnimate() :
- SolverPlugin(),mFrames(),mTime(0.),mVDB(NULL), mIflow1(), mIflow2()
- { };
- ~spAnimate() {
- if (mVDB!=NULL) delete mVDB;
- };
-
- // init plugin, return failure
- virtual bool parseParams(const ParamSet& params) {
- mNameSrc = params.FindOneString("flags-src","unnamed"); // static background flags
- mNameDst = params.FindOneString("flags-dst","flags"); // flag grid
- mDistSrc = params.FindOneString("ndist-src",""); // static background distance field
- mDistDst = params.FindOneString("ndist-dst",""); // distance field
- mVortSrc = params.FindOneString("vort-src",""); // static background ABL source
- mVortDst = params.FindOneString("vort-dst",""); // ABL source field
- mVortFile = params.FindOneString("vort-file",""); // vortex DB filename
- mDoForces = params.FindOneInt("do-forces",1)!=0; // enforce velocities on the moving object boundary
- mNameVel = params.FindOneString("vel","vel-curr"); // velocity field
- mFile = params.FindOneString("file","no-filename"); // animation control file
- mAnimParams = params.FindOneString("params","unnamed"); // params where animated object is stored
- return true;
- };
- virtual bool initPlugin() {
-
- // load animation stream from text file
- ifstream ifs (mFile.c_str());
- if (!ifs) {
- errMsg("spAnimate::initPlugin","can't load animation file !"); return false;
- }
- int numFrames, numInflows;
- Vec3 lastPos(0.), lastAxis(0.);
- Real delta, lastTime(0.);
- ifs >> numFrames; ifs.ignore(1000,'\n');
- ifs >> delta; ifs.ignore(1000,'\n');
- ifs >> mScale; ifs.ignore(1000,'\n');
- ifs >> mRotCenter.x >> mRotCenter.y >> mRotCenter.z; ifs.ignore(1000,'\n');
- // obtain frame data
- for (int n=0;n<numFrames;n++)
- {
- // load frame, calculate speed by finite differences
- AnimFrame frame(ifs);
- frame.time *= delta;
- frame.pvel = (frame.pos - lastPos) / (frame.time - lastTime);
-
- Vec3 axis = frame.rot.getAxis();
- frame.rvel = (axis - lastAxis) / (frame.time - lastTime);
- mFrames.push_back(frame);
- lastPos = frame.pos;
- lastAxis = axis;
- lastTime = frame.time;
- }
- mFrames[0].pvel = mFrames[1].pvel;
- mFrames[0].rvel = mFrames[1].rvel;
-
- // load inflow box information
- ifs >> numInflows; ifs.ignore(1000,'\n');
- for (int n=0;n<numInflows;n++)
- {
- Vec3 b1,b2;
- ifs >> b1.x >> b1.y >> b1.z >> b2.x >> b2.y >> b2.z; ifs.ignore(1000,'\n');
- mIflow1.push_back(b1);
- mIflow2.push_back(b2);
- }
- // load vortex database
- if (!mVortFile.empty())
- mVDB = new VortexDB(mVortFile,vec2R(mpPlParams->getFluidSolver()->getGridFlags()->getSize()));
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spAnimate","step "<<dt);
-
- // linear interpolatation of the animation frames
- Real multiplier = mpPlParams->getMultiplier();
- if (multiplier < 1) multiplier = 1;
- dt /= multiplier;
- mTime += dt;
- vector<AnimFrame>::const_iterator f1=mFrames.begin(), f2=mFrames.end()-1, it=mFrames.begin();
- for (;it != mFrames.end();++it)
- {
- if (it->time <= mTime && it->time > f1->time) f1 = it;
- if (it->time >= mTime && it->time < f2->time) f2 = it;
- }
- Real a2 = (f1->time == f2->time) ? 0 : (mTime - f1->time) / (f2->time - f1->time), a1=1.-a2;
-
- // setup transformation matrix
- Vec3 finalPos = f1->pos * a1 + f2->pos * a2;
- Quat finalQ = Quat::slerp(f1->rot, f2->rot, a2);
-
- ObjectTransformation trafo(0.);
- Vec3 ax = finalQ.getAxis() * 180./M_PI;
- //printf("QUAT %g %g %g %g\nAXIS %g %g %g\n",finalQ.x,finalQ.y,finalQ.z,finalQ.w,ax.x,ax.y,ax.z);
- trafo.rotMat = finalQ.getRotMat();
- trafo.pos = finalPos;
- trafo.posVel = f2->pvel;
- trafo.rotVel = f2->rvel;
- trafo.scale = mScale;
- trafo.center = mRotCenter;
- cout << "pvel : " << trafo.posVel << endl;
-
- // log data for output in pbrt files
- /*Vec3 rpos = (finalPos * mDomainSize) + mDomain0;
- ostringstream str;
- Real angle = normalize(ax);
- if (angle < 1e-8) ax = Vec3(0.,1.,0.);
- str << rpos.x << " " << rpos.y << " " << rpos.z << " " << ax.x << " " << ax.y << " " << ax.z << " " << -angle;
- mpPlParams->getFluidSolver()->setDebugBuffer(str.str());*/
-
- // get grids
- FlagGrid* src = mpPlParams->getGridInt(mNameSrc);
- FlagGrid* dst = mpPlParams->getGridInt(mNameDst);
- FlagGrid* obs = ddfWorldFindSolver(mAnimParams)->getGridFlags();
- Grid<Real>* distsrc = mDistSrc.empty() ? NULL : mpPlParams->getGridReal(mDistSrc);
- Grid<Real>* distdst = mDistDst.empty() ? NULL : mpPlParams->getGridReal(mDistDst);
- Grid<Real>* distobs = mDistSrc.empty() ? NULL : ddfWorldFindSolver(mAnimParams)->getParams()->getGridReal(mDistSrc);
- Grid<Vec3>* vortsrc = mVortSrc.empty() ? NULL : mpPlParams->getGridVec3(mVortSrc);
- Grid<Vec3>* vortdst = mVortDst.empty() ? NULL : mpPlParams->getGridVec3(mVortDst);
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mNameVel);
-
- cout << "time " << mTime << " pos " << trafo.pos << endl;
- //cout << "lookup bounds: " << trafo.pos * vec2R(obs->getSize()) << " to " << mScale * vec2R(obs->getSize()) + trafo.pos * vec2R(obs->getSize()) << endl;
-
- // copy static fields
- goCopyGrid<int>(dst,src);
- if (distsrc != NULL) goCopyGrid<Real>(distdst,distsrc);
- if (vortsrc != NULL) goCopyGrid<Vec3>(vortdst,vortsrc);
-
- // set flags & velocities inside cells
- opSetMovingObstacleBC(dst, vel, obs, trafo, dt, false, distobs, distdst, mIflow1, mIflow2, mDoForces);
-
- // query vortex DB
- Vec3 uvel = -trafo.posVel * vec2R(dst->getSize()) ;//+ mpPlParams->mU0 ;
- if (mVDB != NULL)
- mVDB->project(dst, vortdst, trafo,uvel);
-
- // initialize obstacle boundaries with velocities
- if (mDoForces) {
- FOR_IJK_GRID_BND(dst,1) {
- if (!fgIsObstacle( dst->getGlobal(i,j,k) ) ) {
- if (fgIsObstacle( dst->getGlobal(i-1,j,k) ) && !fgIsObstacle( src->getGlobal(i-1,j,k) ) ) {
- vel->getGlobal(i,j,k)[0] = vel->getGlobal(i-1,j,k)[0];
- }
- if (fgIsObstacle( dst->getGlobal(i,j-1,k) ) && !fgIsObstacle( src->getGlobal(i,j-1,k) )) {
- vel->getGlobal(i,j,k)[1] = vel->getGlobal(i,j-1,k)[1];
- }
- if(gDim==3 && (fgIsObstacle( dst->getGlobal(i,j,k-1) ) && !fgIsObstacle( src->getGlobal(i,j,k-1) ) )) {
- vel->getGlobal(i,j,k)[2] = vel->getGlobal(i,j,k-1)[2];
- }
- }
- } }
-
- return true;
- };
-
- protected:
- // grid access
- std::string mNameSrc, mNameDst, mNameVel, mAnimParams, mFile, mDistSrc, mDistDst, mVortSrc, mVortDst, mVortFile;
- vector<AnimFrame> mFrames;
- Real mTime, mScale;
- Vec3 mRotCenter;
- VortexDB* mVDB;
- vector<Vec3> mIflow1, mIflow2;
- bool mDoForces;
-};
-
-//*****************************************************************************
-// create plugins
-SolverPlugin* MakeAnimPlugin(std::string name) {
- if(name.compare( "set-moving-obs-bcs" )==0) {
- return new spSetMovingObstacleBC;
- } else if(name.compare( "animate" )==0) {
- return new spAnimate;
- }
-
- return NULL;
-}
-
-}
diff --git a/intern/smoke/intern/source/conjugategrad.cpp b/intern/smoke/intern/source/conjugategrad.cpp
deleted file mode 100644
index 042469e093f..00000000000
--- a/intern/smoke/intern/source/conjugategrad.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Conjugate Gradient solver classes, used in Pressure solve
- *
- *****************************************************************************/
-
-#include "globals.h"
-#include "vectorbase.h"
-#include "grid.h"
-#include "operators.h"
-#include "conjugategrad.h"
-
-// oreconditioning methods:
-// 1 = incomplete cholesky ala wavelet turbulence (needs 4 additional grids)
-// 2 = modified IC ala Bridson (1 add. grid)
-
-namespace DDF {
-
-void InitPreconditionIncompCholesky(FlagGrid *flags,
- Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak,
- Grid<Real> *orgA0, Grid<Real> *orgAi, Grid<Real> *orgAj, Grid<Real> *orgAk)
-{
- // compute IC according to Golub and Van Loan
-
- if(!A0 || !Ai || !Aj || !Ak) {
- errFatal("InitPreconditioner","method=1 but grids PCA0,j,k not set!", SIMWORLD_GRIDERROR);
- return;
- }
- FOR_IJK_GRID(A0) {
- A0->getGlobal(i,j,k) = orgA0->getGlobal(i,j,k);
- Ai->getGlobal(i,j,k) = orgAi->getGlobal(i,j,k);
- Aj->getGlobal(i,j,k) = orgAj->getGlobal(i,j,k);
- Ak->getGlobal(i,j,k) = orgAk->getGlobal(i,j,k);
- }
-
- if(0) FOR_IJK_GRID(flags) { // DEBUG
- if(0) debMsg("DEB_INCOMP_CHOL mat","at "<<PRINT_IJK<<" "<<
- A0->getGlobal(i,j,k)<<" "<< Ai->getGlobal(i,j,k)<<" "<< Aj->getGlobal(i,j,k)<<" "<< Ak->getGlobal(i,j,k)<<" " );
- printf("ORGMAT debug at %d,%d,%d = %f, %f, %f, %f \n", i,j,k,
- A0->getGlobal(i,j,k), Ai->getGlobal(i,j,k), Aj->getGlobal(i,j,k), Ak->getGlobal(i,j,k) );
- } // DEBUG
-
- FOR_IJK_GRID(flags) {
- if (fgIsFluid(flags->getGlobal(i,j,k)) ) {
- A0->getGlobal(i,j,k) = sqrt(A0->getGlobal(i,j,k));
-
- // correct left and top stencil in other entries
- // for i = k+1:n
- // if (A(i,k) != 0)
- // A(i,k) = A(i,k) / A(k,k)
- Real invDiagonal = 1.0f / A0->getGlobal(i,j,k);
- Ai->getGlobal(i,j,k) *= invDiagonal;
- Aj->getGlobal(i,j,k) *= invDiagonal;
- Ak->getGlobal(i,j,k) *= invDiagonal;
-
- // correct the right and bottom stencil in other entries
- // for j = k+1:n // for i = j:n
- // if (A(i,j) != 0)
- // A(i,j) = A(i,j) - A(i,k) * A(j,k)
- A0->getGlobal(i+1,j,k) -= Ai->getGlobal(i,j,k) * Ai->getGlobal(i,j,k);
- A0->getGlobal(i,j+1,k) -= Aj->getGlobal(i,j,k) * Aj->getGlobal(i,j,k);
- A0->getGlobal(i,j,k+1) -= Ak->getGlobal(i,j,k) * Ak->getGlobal(i,j,k);
- }
- }
-
- // invert A0 for faster computation later
- FOR_IJK_GRID(flags) {
- if ( (fgIsFluid(flags->getGlobal(i,j,k)) ) &&
- (A0->getGlobal(i,j,k) > 0.) )
- {
- // invert
- A0->getGlobal(i,j,k) = 1. / A0->getGlobal(i,j,k);
- }
- }
-
- if(0) FOR_IJK_GRID(flags) { // DEBUG
- if(0) debMsg("DEB_INCOMP_CHOL mat","at "<<PRINT_IJK<<" "<<
- A0->getGlobal(i,j,k)<<" "<< Ai->getGlobal(i,j,k)<<" "<< Aj->getGlobal(i,j,k)<<" "<< Ak->getGlobal(i,j,k)<<" " );
- printf("debug at %d,%d,%d = %f, %f, %f, %f \n", i,j,k,
- A0->getGlobal(i,j,k), Ai->getGlobal(i,j,k), Aj->getGlobal(i,j,k), Ak->getGlobal(i,j,k) );
- } // DEBUG
- //exit(1);
-};
-
-
-
-void InitPreconditionModifiedIncompCholesky2(FlagGrid *flags,
- Grid<Real> *_A0, Grid<Real> *_Ai, Grid<Real> *_Aj, Grid<Real> *_Ak,
- Grid<Real> *_orgA0, Grid<Real> *_orgAi, Grid<Real> *_orgAj, Grid<Real> *_orgAk)
-{
- // compute IC according to Golub and Van Loan
- // simplify access to grids...
- Grid<Real> &Aprecond = *_A0;
- Grid<Real> &A0 = *_orgA0;
- Grid<Real> &Ai = *_orgAi;
- Grid<Real> &Aj = *_orgAj;
- Grid<Real> &Ak = *_orgAk;
-
- if(!_A0) {
- errFatal("InitPreconditioner","method=2 but grids PCA0 not set!", SIMWORLD_GRIDERROR);
- return;
- }
-
- GridOpTouchMemory<Real>(NULL, _A0, 0.);
-
- const Real tau = 0.97;
- const Real sigma = 0.25;
- FOR_IJK_GRID(flags) {
- if (fgIsFluid(flags->getGlobal(i,j,k)) ) {
- // compute modified incomplete cholesky
- Real e = 0.;
- e = A0(i,j,k)
- - SQUARE(Ai(i-1,j,k) * Aprecond(i-1,j,k) )
- - SQUARE(Aj(i,j-1,k) * Aprecond(i,j-1,k) )
- - SQUARE(Ak(i,j,k-1) * Aprecond(i,j,k-1) ) ;
- e -= tau * (
- Ai(i-1,j,k) * ( Aj(i-1,j,k) + Ak(i-1,j,k) )* SQUARE( Aprecond(i-1,j,k) ) +
- Aj(i,j-1,k) * ( Ai(i,j-1,k) + Ak(i,j-1,k) )* SQUARE( Aprecond(i,j-1,k) ) +
- Ak(i,j,k-1) * ( Ai(i,j,k-1) + Aj(i,j,k-1) )* SQUARE( Aprecond(i,j,k-1) ) +
- 0. );
-
- // stability cutoff
- if(e < sigma * A0(i,j,k))
- e = A0(i,j,k);
-
- Aprecond(i,j,k) = 1. / sqrt( e );
- //debMsg("Aprecond","at "<<PRINT_IJK<<" "<<Aprecond(i,j,k) );
- // */
- }
- }
-};
-
-
-
-void InitPrecondition(int method, FlagGrid *Flags,
- Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak,
- Grid<Real> *orgA0, Grid<Real> *orgAi, Grid<Real> *orgAj, Grid<Real> *orgAk)
-{
-
- //debMsg("InitPrecondition","Method="<<method);
-
- switch(method) {
- case 1:
- InitPreconditionIncompCholesky(Flags, A0,Ai,Aj,Ak , orgA0,orgAi,orgAj,orgAk );
- break;
- case 2:
- InitPreconditionModifiedIncompCholesky2(Flags, A0,Ai,Aj,Ak , orgA0,orgAi,orgAj,orgAk );
- break;
- //default:
- // nothing to do ... goInitPreconditionID(mpSearch, mpResidual, mpFlags );
- };
-
-};
-
-
-
-
-
-void ApplyPreconditionIncompCholesky(Grid<Real> *dst, Grid<Real> *Var1, FlagGrid *flags,
- Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak,
- Grid<Real> *orgA0, Grid<Real> *orgAi, Grid<Real> *orgAj, Grid<Real> *orgAk) {
- // debug out
- if(0) { FOR_IJK_GRID(dst) {
- printf("apply1 at %d,%d,%d = %f, %f \n", i,j,k, dst->getGlobal(i,j,k)*1000., Var1->getGlobal(i,j,k)*1000. );
- } } // DEBUG out
-
- FOR_IJK_GRID(dst) {
- if (fgIsFluid(flags->getGlobal(i,j,k)) ) {
- // forward substitution
- dst->getGlobal(i,j,k) = ( Var1->getGlobal(i,j,k)
- - ( dst->getGlobal(i-1, j, k) * Ai->getGlobal(i-1, j,k) )
- - ( dst->getGlobal(i, j-1, k) * Aj->getGlobal(i, j-1,k) )
- - ( dst->getGlobal(i, j, k-1) * Ak->getGlobal(i,j, k-1) ) )
- * A0->getGlobal(i,j,k) ; // */
- }
- }
-
- FOR_IJKREV_GRID(dst) {
- if (fgIsFluid(flags->getGlobal(i,j,k)) ) {
- // backw. substitution
- dst->getGlobal(i,j,k) = ( dst->getGlobal(i,j,k)
- - ( dst->getGlobal(i+1,j,k) * Ai->getGlobal(i+0,j,k) )
- - ( dst->getGlobal(i,j+1,k) * Aj->getGlobal(i,j+0,k) )
- - ( dst->getGlobal(i,j,k+1) * Ak->getGlobal(i,j,k+0) ) )
- * A0->getGlobal(i,j,k) ;// */
- }
- }
-
- // debug out
- if(0) { FOR_IJK_GRID(dst) {
- printf("apply2 at %d,%d,%d = %f, %f \n", i,j,k, dst->getGlobal(i,j,k)*1000., Var1->getGlobal(i,j,k)*1000. );
- } } // DEBUG out
-};
-
-
-void ApplyPreconditionModifiedIncompCholesky2(Grid<Real> *dst, Grid<Real> *Var1, FlagGrid *flags,
- Grid<Real> *Aprecond, Grid<Real> *Aunused1, Grid<Real> *Aunused2, Grid<Real> *Aunused3,
- Grid<Real> *orgA0, Grid<Real> *orgAi, Grid<Real> *orgAj, Grid<Real> *orgAk) {
-
- FOR_IJK_GRID(dst) {
- if (fgIsFluid(flags->getGlobal(i,j,k)) ) {
- const Real precond = Aprecond->getGlobal(i,j,k);
- // forward substitution
- dst->getGlobal(i,j,k) = ( Var1->getGlobal(i,j,k)
- - ( dst->getGlobal(i-1, j, k) * orgAi->getGlobal(i-1, j,k) *precond )
- - ( dst->getGlobal(i, j-1, k) * orgAj->getGlobal(i, j-1,k) *precond )
- - ( dst->getGlobal(i, j, k-1) * orgAk->getGlobal(i,j, k-1) *precond ) )
- * precond ; // */
- }
- }
-
- FOR_IJKREV_GRID(dst) {
- if (fgIsFluid(flags->getGlobal(i,j,k)) ) {
- const Real precond = Aprecond->getGlobal(i,j,k);
- // backw. substitution
- dst->getGlobal(i,j,k) = ( dst->getGlobal(i,j,k)
- - ( dst->getGlobal(i+1,j,k) * orgAi->getGlobal(i+0,j,k) *precond )
- - ( dst->getGlobal(i,j+1,k) * orgAj->getGlobal(i,j+0,k) *precond )
- - ( dst->getGlobal(i,j,k+1) * orgAk->getGlobal(i,j,k+0) *precond ) )
- * precond ;// */
- }
- }
-};
-
-
-void ApplyPrecondition(int method, Grid<Real> *Dst, Grid<Real> *Var1, FlagGrid *Flags,
- Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak,
- Grid<Real> *orgA0, Grid<Real> *orgAi, Grid<Real> *orgAj, Grid<Real> *orgAk) {
-
- // debMsg("ApplyPrecondition","Method="<<method);
- switch(method) {
- case 1:
- ApplyPreconditionIncompCholesky(Dst, Var1, Flags, A0,Ai,Aj,Ak , orgA0,orgAi,orgAj,orgAk );
- break;
- case 2:
- ApplyPreconditionModifiedIncompCholesky2(Dst, Var1, Flags, A0,Ai,Aj,Ak , orgA0,orgAi,orgAj,orgAk );
- break;
- default:
- // id, means PC "off"
- goPreconditionID(Dst, Var1, Flags);
- }
-}
-
-}; // DDF
diff --git a/intern/smoke/intern/source/conjugategrad.h b/intern/smoke/intern/source/conjugategrad.h
deleted file mode 100644
index 7591e1709c8..00000000000
--- a/intern/smoke/intern/source/conjugategrad.h
+++ /dev/null
@@ -1,505 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Conjugate Gradient solver classes, used in Pressure solve
- *
- *****************************************************************************/
-
-#ifndef DDF_CONJUGATEGRADIENT_H
-#define DDF_CONJUGATEGRADIENT_H
-
-#include "vectorbase.h"
-#include "grid.h"
-#include "operators.h"
-
-
-namespace DDF {
-
-static const bool CG_DEBUG = false;
-
-// helper functions from conjugategrad.cpp
-void InitPrecondition(int method, FlagGrid *Flags,
- Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak,
- Grid<Real> *orgA0, Grid<Real> *orgAi, Grid<Real> *orgAj, Grid<Real> *orgAk);
-void ApplyPrecondition(int method, Grid<Real> *Dst, Grid<Real> *Var1, FlagGrid *Flags,
- Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak,
- Grid<Real> *orgA0, Grid<Real> *orgAi, Grid<Real> *orgAj, Grid<Real> *orgAk);
-
-
-// hard coded laplacian operator without stored matix
-class goApplyLacplace : public GridOpBase{
- public:
- goApplyLacplace(Grid<Real> *Dst, Grid<Real> *Src, FlagGrid *Flags) : GridOpBase() {
- mpDst = Dst; mpSrc = Src;
- mpFlags = Flags;
- applyOperatorToGrids(this);
- };
- ~goApplyLacplace() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaSrc.gridAccInit(mpSrc, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- if(!fgIsFluid(getFlagAcc()(i,j,k)) ) {
- gaDst.write(i,j,k) = gaSrc(i,j,k);
- return;
- }
-
- gaDst.write(i,j,k) = LAPLACEFAC * gaSrc(i,j,k)
- - gaSrc(i-1,j,k) - gaSrc(i+1,j,k)
- - gaSrc(i,j-1,k) - gaSrc(i,j+1,k)
-#if DDF_DIMENSION==3
- - gaSrc(i,j,k-1) - gaSrc(i,j,k+1)
-#endif // DDF_DIMENSION==3
- ;
- }
- void getRidOfWarning() { };
- void reduce(goApplyLacplace &op) { getRidOfWarning(); }
- protected:
- Grid<Real> *mpDst, *mpSrc;
- GridAccessor<Real,0> gaDst;
- GridAccessor<Real,1> gaSrc;
-}; // goApplyLacplace
-
-
-
-//*****************************************************************************
-
-// compute residual (init) and add to sigma
-class goInitSigma : public GridOpBase{
- public:
- goInitSigma(Grid<Real> *Dst, Grid<Real> *Var1, Grid<Real> *Var2, FlagGrid *Flags, Real &set_sigma) :
- GridOpBase() {
- mpDst = Dst; // residual
- mpVar1 = Var1; // rhs
- mpVar2 = Var2; // temp
- mpFlags = Flags;
- applyOperatorToGrids( this );
- set_sigma = mSigma;
- }
- ~goInitSigma() {};
- virtual void resetVariables() {
- mSigma = 0.;
- }
- void buildCallList() {
- gaResid.gridAccInit( mpDst, AM_WRITE, gaCalls);
- gaRhs.gridAccInit( mpVar1, AM_READ, gaCalls);
- gaTemp.gridAccInit( mpVar2, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- const Real res = gaRhs(i,j,k) - gaTemp(i,j,k);
- gaResid.write(i,j,k) = res;
-
- // only compute residual in fluid region
- if(!fgIsFluid(getFlagAcc()(i,j,k)) ) return;
- mSigma += res*res;
- }
- void reduce(goInitSigma &op) {
- //debMsg("goInitSigma","reduce mSigma"<<mSigma<<" += "<<op.mSigma);
- mSigma += op.mSigma;
- }
- protected:
- Real mSigma;
- Grid<Real> *mpDst, *mpVar1, *mpVar2;
- GridAccessor<Real,0> gaResid, gaRhs, gaTemp;
-}; // goInitSigma */
-
-
-class goUpdateSolution : public GridOpBase{
- public:
- goUpdateSolution(Grid<Real> *Dst, Grid<Real> *Var1, FlagGrid *Flags, Real factor) : GridOpBase() {
- mpDst = Dst; // pressure or residual
- mpSrc = Var1; // update vector
- mpFlags = Flags;
- mFactor = factor;
- applyOperatorToGrids( this );
- }
- ~goUpdateSolution() {};
- void buildCallList() {
- gaDst.gridAccInit( mpDst, AM_WRITE, gaCalls);
- gaSrc.gridAccInit( mpSrc, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- gaDst.write(i,j,k) += mFactor*gaSrc(i,j,k);
- }
- void reduce(goUpdateSolution &op) { };
- protected:
- Real mFactor;
- Grid<Real> *mpDst;
- Grid<Real> *mpSrc;
- GridAccessor<Real,0> gaDst;
- GridAccessor<Real,0> gaSrc;
-}; // goUpdateSolution */
-
-class goUpdateSearchVec : public GridOpBase{
- public:
- goUpdateSearchVec(Grid<Real> *Dst, Grid<Real> *Var1, FlagGrid *Flags, Real factor) : GridOpBase() {
- mpDst = Dst; // pressure or residual
- mpSrc = Var1; // update vector
- mpFlags = Flags;
- mFactor = factor;
- applyOperatorToGrids( this );
- }
- ~goUpdateSearchVec() {};
- void buildCallList() {
- gaDst.gridAccInit( mpDst, AM_WRITE, gaCalls);
- gaSrc.gridAccInit( mpSrc, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- gaDst.write(i,j,k) = gaSrc(i,j,k) + mFactor*gaDst(i,j,k);
- }
- void reduce(goUpdateSearchVec &op) { };
- protected:
- Real mFactor;
- Grid<Real> *mpDst, *mpSrc;
- GridAccessor<Real,0> gaDst, gaSrc;
-}; // goUpdateSearchVec */
-
-
-
-// currently only copies from source to dest...
-class goPreconditionID : public GridOpBase{
- public:
- goPreconditionID(Grid<Real> *Dst, Grid<Real> *Var1, FlagGrid *Flags) : GridOpBase() {
- mpDst = Dst;
- mpVar1 = Var1;
- mpFlags = Flags;
- applyOperatorToGrids( this );
- }
- ~goPreconditionID() {};
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaVar1.gridAccInit(mpVar1, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- gaDst.write(i,j,k) = gaVar1(i,j,k);
- }
- void reduce(goPreconditionID &op) { }
- protected:
- Grid<Real> *mpDst, *mpVar1;
- GridAccessor<Real,0> gaDst, gaVar1;
-}; // goPreconditionID */
-
-
-
-//*****************************************************************************
-// compute the laplacian of src with right hand side rhs into the tmp grid
-// for reference to CG solver
-class goJacobiSolver : public GridOpBase{
- public:
- goJacobiSolver(Grid<Real> *Dst, Grid<Real> *Src, Grid<Real> *Rhs, FlagGrid *Flags) : GridOpBase() {
- mpDst = Dst;
- mpSrc = Src;
- mpRhs = Rhs;
- mpFlags = Flags;
- applyOperatorToGrids(this);
- };
- ~goJacobiSolver() {};
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaRhs.gridAccInit(mpRhs, AM_READ, gaCalls);
- gaSrc.gridAccInit(mpSrc, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- //debMsg("OPL","at "<<PRINT_IJK<<" dst="<<gaDst.write(i,j,k)<<" rhs="<<gaRhs(i,j,k)<<", src: "<< gaSrc(i-1,j,k) <<" "<< gaSrc(i+1,j,k)<<" "<< gaSrc(i,j-1,k) <<" "<< gaSrc(i,j+1,k) );
- if(fgIsObstacle(getFlagAcc()(i,j,k)) ) return;
- gaDst.write(i,j,k) = ( gaRhs(i,j,k) +
- + gaSrc(i-1,j,k) + gaSrc(i+1,j,k)
- + gaSrc(i,j-1,k) + gaSrc(i,j+1,k)
-#if DDF_DIMENSION==3
- + gaSrc(i,j,k-1) + gaSrc(i,j,k+1)
-#endif // DDF_DIMENSION==3
- ) * (1./LAPLACEFAC);
- }
-
- void reduce(goJacobiSolver &op) { }
-
- protected:
- Grid<Real> *mpDst, *mpRhs, *mpSrc;
- GridAccessor<Real,0> gaDst;
- GridAccessor<Real,0> gaRhs;
- GridAccessor<Real,1> gaSrc;
-}; // goJacobiSolver
-
-
-
-//*****************************************************************************
-// compute max values in grid (no position)
-template<class Value>
-class goCompMaxSimple : public GridOpBase{
- public:
- goCompMaxSimple(Grid<Value> *Var, FlagGrid *Flags) : GridOpBase() {
- mpVar = Var;
- mpFlags = Flags;
- applyOperatorToGrids( this );
- };
- ~goCompMaxSimple() {};
- virtual void resetVariables() {
- mMaxAbs = -1e10;
- mMax = 0.;
- }
- void buildCallList() {
- gaVar.gridAccInit(mpVar, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- const Value s = gaVar(i,j,k);
- const Real sabs = normHelper(s);
-
- if(sabs>mMaxAbs) {
- mMaxAbs = sabs;
- mMax = s;
- //mMaxPos = nVec3i(i,j,k);
- }
- }
-
- void reduce(goCompMaxSimple &op) {
- if(op.mMaxAbs>mMaxAbs) {
- mMaxAbs = op.mMaxAbs;
- mMax = op.mMax;
- //mMaxPos = op.mMaxPos;
- }
- }
-
- Value getMax() { return mMax; }
- Real getMaxAbs() { return mMaxAbs; }
- //Real getMaxPosValue() { return mMaxPos; }
- string toString() {
- std::ostringstream out;
- out << " max="<<mMax<<" ("<<mMaxAbs<<") ";
- return out.str();
- }
- protected:
- //int outcnt;
- Real mMaxAbs;
- Value mMax;
- Grid<Value> *mpVar;
- GridAccessor<Real,0> gaVar;
-}; // goCompMaxSimple
-
-//*****************************************************************************
-
-// basic interface
-class GridCgInterface {
- public:
- GridCgInterface() : mUseResNorm(true) {};
- virtual ~GridCgInterface() {};
-
- // solving functions
- virtual bool iterate() = 0;
- virtual void solve(int maxIter) = 0;
-
- // precond
- virtual void setPreconditioner(int method, Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak) = 0;
-
- // access
- virtual Real getSigma() const = 0;
- virtual Real getIterations() const = 0;
- virtual Real getResNorm() const = 0;
- virtual void setAccuracy(Real set) = 0;
- virtual Real getAccuracy() const = 0;
-
- void setUseResNorm(bool set) { mUseResNorm = set; }
-
- protected:
-
- // use norm of residual, or max value for threshold?
- bool mUseResNorm;
-};
-
-//! run single iteration of the cg solver
-// the template argument determines the type of matrix multiplication,
-// typically a goApplyMatrix object (above), another one is needed e.g. for the
-// mesh-based wave equation solver
-template<class APPLYMAT>
-class GridCg : public GridCgInterface {
- public:
- // constructor
- GridCg(Grid<Real>* dst,Grid<Real>* rhs,Grid<Real>* residual,Grid<Real>* search, FlagGrid* flags, Grid<Real>* tmp,
- Grid<Real> *A0=NULL, Grid<Real> *Ai=NULL, Grid<Real> *Aj=NULL, Grid<Real> *Ak=NULL,
- // optional grids that may be used in the apply-matrix class during matrix myultiplication
- // used eg for surface tension
- Grid<Real> *_optionalReal = NULL, Grid<Vec3> *_optionalVec = NULL ) :
- GridCgInterface(),
- mInited(false), mIterations(0),
- mpDst(dst), mpRhs(rhs), mpResidual(residual),
- mpSearch(search), mpFlags(flags), mpTmp(tmp),
- mpA0(A0), mpAi(Ai), mpAj(Aj), mpAk(Ak),
- mPcMethod(0), mpPCA0(A0), mpPCAi(Ai), mpPCAj(Aj), mpPCAk(Ak),
- mSigma(0.),
- mAccuracy(gVecEpsilon), mResNorm(1e20)
- {
- if(0) debMsg("PB-CG-Norms","init p"<<sqrt( DDF::GridOpNormNosqrt(mpDst, mpFlags).getValue() ) <<
- " rhs"<<sqrt( DDF::GridOpNormNosqrt(mpRhs, mpFlags).getValue() ) << " search"<<sqrt( DDF::GridOpNormNosqrt(mpSearch, mpFlags).getValue() ) <<
- " res"<<sqrt( DDF::GridOpNormNosqrt(mpResidual, mpFlags).getValue() ) << " tmp"<<sqrt( DDF::GridOpNormNosqrt(mpTmp, mpFlags).getValue() )<<
- " sigma="<<mSigma ); // debug
-
- GridOpTouchMemory<Real>(NULL, dst, 0.);
- GridOpTouchMemory<Real>(NULL, residual, 0.);
- GridOpTouchMemory<Real>(NULL, search, 0.);
- GridOpTouchMemory<Real>(NULL, tmp, 0.);
- optionalReal = _optionalReal;
- optionalVec = _optionalVec;
- }
-
- void doInit() {
- mInited = true;
-
- InitPrecondition(mPcMethod, mpFlags, mpPCA0,mpPCAi,mpPCAj,mpPCAk , mpA0,mpAi,mpAj,mpAk);
-
- // old APPLYMAT(mpTmp, mpDst, mpA0,mpAi,mpAj,mpAk, mpFlags, optionalReal, optionalVec);
- // old goInitSigma(mpResidual, mpRhs, mpTmp, mpFlags, mSigma);
- // old ApplyPrecondition(mPcMethod, mpSearch, mpResidual, mpFlags, mpPCA0,mpPCAi,mpPCAj,mpPCAk );
- // old GridOpNormNosqrt(mpResidual, mpFlags, &mResNorm);
-
- goCopyGrid<Real>(mpResidual, mpRhs); // p=0, residual = b
-
- // tmp == apply preconditioner(residual)
- ApplyPrecondition(mPcMethod, mpTmp, mpResidual, mpFlags, mpPCA0,mpPCAi,mpPCAj,mpPCAk, mpA0,mpAi,mpAj,mpAk );
-
- goCopyGrid<Real>(mpSearch, mpTmp); // search = tmp
-
- Real dotProdValue = 0.; // sigma = dot(tmp, residual)
- goDotProd(mpTmp, mpResidual, mpFlags, &dotProdValue);
- mSigma = dotProdValue;
-
- if(CG_DEBUG) debMsg("PB-CG-Norms","init p"<<sqrt( DDF::GridOpNormNosqrt(mpDst, mpFlags).getValue() ) <<
- " rhs"<<sqrt( DDF::GridOpNormNosqrt(mpRhs, mpFlags).getValue() ) << " search"<<sqrt( DDF::GridOpNormNosqrt(mpSearch, mpFlags).getValue() ) <<
- " res"<<sqrt( DDF::GridOpNormNosqrt(mpResidual, mpFlags).getValue() ) << " tmp"<<sqrt( DDF::GridOpNormNosqrt(mpTmp, mpFlags).getValue() )<<
- " sigma="<<mSigma ); // debug
- }
- ~GridCg() {
- };
-
- //! perform cg iteration
- bool iterate() {
- if(!mInited) doInit();
-
- //debMsg("CG","Iterate "<<mIterations<<" "<<mResNorm<<"/"<<mAccuracy);
- //if(mResNorm<mAccuracy) return false;
-
- mIterations++;
-
- // create matrix application operator passed as template argument,
- // this could reinterpret the mpA pointers (not so clean right now)
- // tmp = applyMat(search)
- APPLYMAT(mpTmp, mpSearch, mpA0,mpAi,mpAj,mpAk, mpFlags, optionalReal, optionalVec);
-
- Real dotProdTS; // alpha = sigma/dot(tmp, search)
- goDotProd(mpTmp, mpSearch, mpFlags, &dotProdTS);
- Real alpha = 0.;
- if(fabs(dotProdTS)>0.) alpha = mSigma / dotProdTS;
-
- goUpdateSolution(mpDst, mpSearch, mpFlags, alpha); // dst += search * alpha
- goUpdateSolution(mpResidual, mpTmp , mpFlags, -alpha); // residual += tmp * -alpha
- ApplyPrecondition(mPcMethod, mpTmp, mpResidual, mpFlags, mpPCA0,mpPCAi,mpPCAj,mpPCAk, mpA0,mpAi,mpAj,mpAk );
-
- // compute norm of the residual?
- if(this->mUseResNorm) {
- GridOpNormNosqrt(mpResidual, mpFlags, &mResNorm);
- } else {
- // TODO test...
- goCompMaxSimple<Real> resMax = goCompMaxSimple<Real>(mpResidual, mpFlags);
- mResNorm = resMax.getMaxAbs();
- }
- if(0 || mIterations % 10 == 9) debMsg("GridCg","Iteration i="<<mIterations<<", resNorm="<<mResNorm<<" accuracy="<<mAccuracy );
-
- // abort here to safe some work...
- if(mResNorm<mAccuracy) return false;
-
- Real sigmaNew; // sigma_new = dot(tmp, residual)
- goDotProd(mpTmp, mpResidual, mpFlags, &sigmaNew);
- // abort here?
-
- Real beta = sigmaNew / mSigma;
- // search = tmp + beta * srch
- goUpdateSearchVec(mpSearch, mpTmp, mpFlags, beta);
-
- if(CG_DEBUG) debMsg("PB-Cg","iter2 i="<<mIterations<<" sigma="<<mSigma<<" alpha="<<alpha<<" beta="<<beta<<" ");
- mSigma = sigmaNew;
-
- if(CG_DEBUG) debMsg("PB-CG-Norms","p"<<sqrt( DDF::GridOpNormNosqrt(mpDst, mpFlags).getValue() ) <<" search"<<sqrt( DDF::GridOpNormNosqrt(mpSearch, mpFlags).getValue() )
- <<" res"<<sqrt( DDF::GridOpNormNosqrt(mpResidual, mpFlags).getValue() ) <<" tmp"<<sqrt( DDF::GridOpNormNosqrt(mpTmp, mpFlags).getValue() ) ); // debug
- if(CG_DEBUG) debMsg("PB-CG-Norms","p"<<( DDF::GridOpNormNosqrt(mpDst, mpFlags).getValue() ) <<" search"<<( DDF::GridOpNormNosqrt(mpSearch, mpFlags).getValue() )
- <<" res"<<( DDF::GridOpNormNosqrt(mpResidual, mpFlags).getValue() ) <<" tmp"<<( DDF::GridOpNormNosqrt(mpTmp, mpFlags).getValue() ) ); // debug, no sqrt!
- return true;
- }
-
- void solve(int maxIter) {
- for (int iter=0; iter<maxIter; iter++) {
- if (!iterate()) iter=maxIter;
- }
- return;
- }
-
- // init pointers, and copy values from "normal" matrix
- void setPreconditioner(int method, Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak) {
- mPcMethod = method;
- mpPCA0 = A0;
- mpPCAi = Ai;
- mpPCAj = Aj;
- mpPCAk = Ak;
- }
-
- // access
-
- Real getSigma() const { return mSigma; }
- Real getIterations() const { return mIterations; }
-
- Real getResNorm() const { return mResNorm; }
-
- void setAccuracy(Real set) { mAccuracy=set; }
- Real getAccuracy() const { return mAccuracy; }
-
- protected:
- bool mInited;
- int mIterations;
- // grids
- Grid<Real>* mpDst;
- Grid<Real>* mpRhs;
- Grid<Real>* mpResidual;
- Grid<Real>* mpSearch;
- FlagGrid* mpFlags;
- Grid<Real>* mpTmp;
-
- Grid<Real> *mpA0, *mpAi, *mpAj, *mpAk;
-
- // preconditioning method 0=off, 1=incomp cholesky
- int mPcMethod;
- // preconditioning grids
- Grid<Real> *mpPCA0, *mpPCAi, *mpPCAj, *mpPCAk;
-
- // optional grids that may be used in the apply-matrix class during matrix myultiplication
- // used eg for surface tension
- Grid<Real> *optionalReal;
- Grid<Vec3> *optionalVec;
-
- // sigma / residual
- Real mSigma;
- // accuracy of solver (max. residuum)
- Real mAccuracy;
- // norm of the residual
- Real mResNorm;
-}; // GridCg
-
-
-
-} // namespace DDF
-
-#endif // DDF_CONJUGATEGRADIENT_H
-
diff --git a/intern/smoke/intern/source/fileio.cpp b/intern/smoke/intern/source/fileio.cpp
deleted file mode 100644
index abc6f4ae2cd..00000000000
--- a/intern/smoke/intern/source/fileio.cpp
+++ /dev/null
@@ -1,633 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Plugins for loading and saving grids
- *
- *****************************************************************************/
-
-// lsdebug
-#include "fluidsolver.h"
-#include "solverplugin.h"
-#include "paramset.h"
-#include "vortexpart.h"
-#include <fstream>
-#include <zlib.h>
-
-// global debugging var - reuse frame nr for badtrioutput, used in spluginDumpMeshSurf
-int g_meshSurfaceOutNr = 0;
-using std::endl;
-
-namespace DDF {
-
-// Header for universal grid file
-typedef struct {
- char id[4];
- int dimX, dimY, dimZ;
- int frames, elements, elementType, bytesPerElement, bytesPerFrame;
-} UniversalHeader;
-
-
-// print timing stats
-class spluginPrintTimingStats : public SolverPlugin {
- public:
- spluginPrintTimingStats() :
- SolverPlugin(), mSort(0) { };
-
- ~spluginPrintTimingStats() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mSort = params.FindOneInt("sort", mSort );
- return true;
- };
- virtual bool initPlugin() { return true; };
-
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
-
- debMsg("spluginPrintTimingStats", mpPlParams->getFluidSolver()->getTimingStats(mSort) );
-
- return true;
- };
-
- protected:
- int mSort;
-};
-
-
-/******************************************************************************/
-// helper functions for isosurface
-
-
-
-/******************************************************************************/
-
-class spluginDumperBase : public SolverPlugin {
- public:
- spluginDumperBase() : SolverPlugin(),
- mSimTime(-1.), mMaxFrames(-1),
- mAnimOutCounter(0), mLastAniOutTime(0.), mStart(0.), mDumpAllFrames(false), mLastDumpTime(-10.),
- mOutputOverrideName(""), mOutname("")
- { };
-
- ~spluginDumperBase() { };
-
- bool parseParamsDumperBase(const ParamSet& params) {
- mOutputOverrideName = params.FindOneString("override-name", mOutputOverrideName );
- mDumpAllFrames = params.FindOneInt("dump-all-frames", mDumpAllFrames );
- mStart = params.FindOneFloat("start-time", mStart );
- mMaxFrames = params.FindOneInt("max-frames", mMaxFrames );
-
- // do we have a override name param? if yes use...
- // otherwise take defaults from params
- if(mOutputOverrideName.length()>0)
- mOutname = mOutputOverrideName;
- else
- mOutname = this->mpPlParams->mAnimOutputFile;
-
- mLastAniOutTime = mStart;
- return true;
- }
-
- // check if current frame should be dumped (note, needs valid mSimTime!)
- bool doDump() {
- // dump each frame once
- if(mDumpAllFrames) {
- if(mLastDumpTime<mSimTime) {
- mLastDumpTime = mSimTime;
- return true;
- }
- return false;
- }
-
- // dump according to timestep
- return (mpPlParams->mTimestepAnim>0. &&
- (mSimTime-mLastAniOutTime > mpPlParams->mTimestepAnim) &&
- (!mpPlParams->getQuit()) );
- }
-
- void increaseDumpCounter() {
- mAnimOutCounter++;
- if (mMaxFrames>=0) {
- // signal end
- if (mAnimOutCounter>=mMaxFrames) mpPlParams->setQuit(true);
- }
- }
-
- protected:
- Real mSimTime;
- // max no of frames param
- int mMaxFrames;
- // no of output frames
- int mAnimOutCounter;
- // output time of last animation frame
- Real mLastAniOutTime, mStart;
- // dump each frame?
- int mDumpAllFrames;
- double mLastDumpTime;
-
- // override name from params?
- std::string mOutputOverrideName, mOutname;
-};
-
-
-template<class T>
-class fsLoadData : public GridOpBase {
- public:
- fsLoadData(FlagGrid *flags, Grid<T> *dst, unsigned char *data, const UniversalHeader& head, bool setonlyFluid, int interpol) :
- GridOpBase(), mpDst(dst),mpData(data), onlyFluid(setonlyFluid), mInterpolateWithBorder(interpol) {
- mpFlags = flags;
- mSizeRead = nVec3i(head.dimX, head.dimY, head.dimZ);
- mSizeDst = mpFlags->getSize() -nVec3i(1,1,1);
- mPageSize = head.bytesPerElement * head.dimX * head.dimY * head.dimZ;
- mBytesPerElement = head.bytesPerElement;
- applyOperatorToGridsSimple(this);
- };
- ~fsLoadData() {}
-
- void resetVariables() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- inline T getRaw (unsigned chunk);
-
- // load & safety check access of file data at i,j,k
- inline T getFileData (int i, int j, int k) {
- CLAMP(i, 0, mSizeRead[0]-1);
- CLAMP(j, 0, mSizeRead[1]-1);
- CLAMP(k, 0, mSizeRead[2]-1);
-
- if (gDim==2) k=0;
- unsigned chunk = i + mSizeRead[0]*(j + mSizeRead[1]*k);
- return getRaw(chunk);
- }
-
- inline void operator() (int i, int j, int k) {
- nVec3i src = nVec3i(i,j,k);
- const nVec3i dst = nVec3i(i,j,k);
-
- if(mInterpolateWithBorder>-1) {
- for(int l=0; l<gDim; l++) {
- if(dst[l]<mInterpolateWithBorder) {
- // keep
- } else if(dst[l]>=mSizeDst[l]-mInterpolateWithBorder) {
- // keep upper grid boundary as well
- src[l] = mSizeRead[l]-1 + (dst[l]-mSizeDst[l]);
- } else {
- //src[l] = dst[l]* mSizeRead[l] / mSizeDst[l];
- const int b = mInterpolateWithBorder;
- src[l] = ((dst[l]-b) * (mSizeRead[l]-2*b) / (mSizeDst[l]-2*b)) + b;
- }
- }
- //std::cerr <<"Init debug" << "at dst="<<dst<<"|"<<mSizeDst<<" file src="<<src<<", filesize"<<mSizeRead <<"\n";
- } else {
- // direct read (standard way of loading)
- // nothing to do, load from (i,j,k)
- }
-
- if (!onlyFluid || fgIsFluid(getFlagAcc()(i,j,k)) )
- gaDst.write(i,j,k) = getFileData(src[0],src[1],src[2]);
- };
- void reduce(fsLoadData &op) { };
-
- protected:
- Grid<T> *mpDst;
- GridAccessor<T,0> gaDst;
-
- unsigned char * mpData;
- bool onlyFluid;
- nVec3i mSizeRead; // size of grid in file
- nVec3i mSizeDst; // size of destination grid
- int mInterpolateWithBorder;
- unsigned mPageSize, mBytesPerElement;
-};
-
-template<class T>
-inline T fsLoadData<T>::getRaw(unsigned chunk)
-{
- return *((T*) &mpData[ mBytesPerElement * chunk]);
-}
-template<>
-inline Vec3 fsLoadData<Vec3>::getRaw(unsigned chunk)
-{
- Vec3 a;
- for (int e=0; e < 3; e++)
- a[e] = *((Real*) &mpData[ mBytesPerElement * chunk + e * mPageSize]);
- return a;
-}
-
-// query dimensions of universal grid file
-nVec3i getUniversalGridSize(const string& file)
-{
- UniversalHeader head;
-
- gzFile gzf = gzopen(file.c_str(),"r");
- if (gzf == NULL) {
- errFatal("spluginLoadUniversal","can't open field file " << file, SIMWORLD_INITERROR);
- return nVec3i(0);
- }
- if (gzread(gzf, &head,sizeof(UniversalHeader)) != sizeof(UniversalHeader) || strncmp(head.id, "DDF1", 4)) {
- errFatal("spluginLoadUniversal","wrong filetype in " << file,SIMWORLD_INITERROR);
- return nVec3i(0);
- }
- gzclose(gzf);
-
- return nVec3i(head.dimX, head.dimY, head.dimZ);
-}
-
-// dump any grid to universal file format
-class spluginDumpUniversal : public spluginDumperBase {
- public:
- spluginDumpUniversal() : spluginDumperBase(), mFirstTime(true) { };
- ~spluginDumpUniversal() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("grid", "");
- mMAC = params.FindOneInt("mac", !mGrid.compare("vel-curr")) != 0; // MAC grid is default for 'vel-curr' only
- mFilePerFrame = params.FindOneInt("file-per-frame", 0) != 0;
- mNoExt = params.FindOneInt("no-ext", 0) != 0;
- bool singleDump = params.FindOneInt("single-dump", 0) != 0;
- parseParamsDumperBase(params);
- if (singleDump) { mNoExt = true; mFilePerFrame = true; mDumpAllFrames = true; }
- return true;
- };
- virtual bool initPlugin() {
- mSimTime = 0.;
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real org_dt) {
- Real dt = org_dt * mpPlParams->getDeltaX();
- debMsg("spluginDumpUniversal","dt="<<dt<<" grid:"<<mGrid<<"; simTime="<<
- mSimTime<<", last="<<mLastAniOutTime<<", cnt="<<mAnimOutCounter<<" dump-all-frame="<<mDumpAllFrames );
- mSimTime += dt;
-
- while( this->doDump() )
- {
- UniversalHeader head;
- const nVec3i gridSize = mpPlParams->getGridInt("flags")->getSize();
-
- // get Grid
- Grid<int> *gI=NULL;
- Grid<Real> *gR=NULL;
- Grid<Vec3> *gV=NULL;
- if (mpPlParams->haveGridInt(mGrid)) {
- gI = mpPlParams->getGridInt(mGrid);
- head.bytesPerElement = sizeof(int);
- head.elementType = 0;
- head.elements = 1;
- }
- else if (mpPlParams->haveGridReal(mGrid)) {
- gR = mpPlParams->getGridReal(mGrid);
- head.bytesPerElement = sizeof(Real);
- head.elementType = 1;
- head.elements = 1;
- }
- else if (mpPlParams->haveGridVec3(mGrid)) {
- gV = mpPlParams->getGridVec3(mGrid);
- head.bytesPerElement = sizeof(Real);
- head.elementType = 2;
- head.elements = 3;
- }
- else {
- errMsg("spluginDumpUniversal","Grid '"<<mGrid<<"' not found or gridtype unsupported");
- return false;
- }
-
- if (mFirstTime || mFilePerFrame) {
- // Open a file
- std::string filename = mOutname;
- if (mFilePerFrame && !mNoExt) {
- char nrStr[5]; // nr conversion
- snprintf(nrStr, 5, "%04d", mAnimOutCounter );
- filename += nrStr;
- }
- mGzf = gzopen( (filename+".gz").c_str(), "wb1");
- if (!mGzf) {
- errMsg("spluginDumpUniversal","Unable to open output '"<<filename<<"' ");
- return false;
- }
- debMsg("spluginDumpUniversal","writing to file '" << filename << ".gz'" );
-
- // Write header
- strncpy(head.id,"DDF1",4);
- head.dimX = gridSize.x;
- head.dimY = gridSize.y;
- head.dimZ = (gDim==2) ? 1:gridSize.z;
- head.frames = mMaxFrames;
- head.bytesPerFrame = head.dimX * head.dimY * head.dimZ * head.elements * head.bytesPerElement + sizeof(float);
-
- gzwrite(mGzf, &head, sizeof(UniversalHeader));
- }
-
- // write frame
- const int z0 = mpPlParams->getFluidSolver()->get2dKstart();
- const int z1 = mpPlParams->getFluidSolver()->get2dKend();
- for (int e=0; e< head.elements; e++)
- {
- // write grid of current element
- FOR_IJK(z0,z1, 0, head.dimY, 0, head.dimX)
- {
- if (head.elementType == 0)
- gzwrite(mGzf, &(gI->getGlobal(i,j,k)), sizeof(int));
- else if (head.elementType == 1)
- gzwrite(mGzf, &(gR->getGlobal(i,j,k)), sizeof(Real));
- else if (head.elementType == 2) {
- Real data = gV->getGlobal(i,j,k)[e];
- if (mMAC) // get centered value on MAC grid
- {
- nVec3i pos(i,j,k);
- pos[e] += 1;
- if (pos[e] < gridSize[e]) {
- data += gV->getGlobal(pos[0],pos[1],pos[2])[e];
- data *= 0.5;
- }
- }
- gzwrite(mGzf, &data, sizeof(Real));
- }
- }
- }
- // write timestamp
- float tm = mSimTime;
- gzwrite(mGzf, &tm, sizeof(float));
-
- if (mFilePerFrame)
- gzclose(mGzf);
-
- this->increaseDumpCounter();
- }
-
- return true;
- };
-
- virtual void finish()
- {
- if (!mFilePerFrame && !mFirstTime) {
- gzclose(mGzf);
- debMsg("spluginDumpUniversal","file archive closed.");
- }
- };
-
- protected:
- // grid names to swap
- std::string mGrid;
- bool mFirstTime, mFilePerFrame, mMAC, mNoExt;
- gzFile mGzf;
-};
-
-
-class spluginLoadUniversal : public SolverPlugin {
- public:
- spluginLoadUniversal() : SolverPlugin() { };
- ~spluginLoadUniversal() { };
-
- virtual bool parseParams(const ParamSet& params) {
- onlyFluid = params.FindOneInt("onlyfluid", 0 ) != 0;
- mGrid = params.FindOneString("grid", "");
- mSolver = params.FindOneString("solver", "" );
- mFile = params.FindOneString("file", "" );
- mSrcGrid = params.FindOneString("srcgrid", "");
-
- // interpolate, but keep #mInterpolBorder cells from each side unscaled
- // -1 means off, 0 means scale everything
- mInterpolBorder = params.FindOneInt("interpolate-with-border", 1);
-
- return true;
- };
- virtual bool initPlugin() { return true; };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginLoadUniversal","file " + mFile);
- SolverParams* param = mpPlParams;
- if (!mSolver.empty()) param = ddfWorldFindSolver(mSolver)->getParams();
- Grid<int>* flags = param->getGridInt("flags");
- nVec3i gridSize = flags->getSize();
- if (gDim==2) gridSize[2] = 1;
-
-
- /* DG: Only Int Grid supported for the moment */
- /* Used during solver creation "new SolverObject()" with existing flags grid */
- if(!mSrcGrid.empty())
- {
- // delete old grid
- delete param->mGridsInt[mGrid];
- // exchange grid pointer
- param->mGridsInt[mGrid] = param->mGridsInt[mSrcGrid];
-
- return true;
- }
-
- // load file into byte array
- UniversalHeader head;
- gzFile gzf = gzopen(mFile.c_str(),"r");
- if (gzf == NULL)
- errFatal("spluginLoadUniversal","can't open field file " << mFile, SIMWORLD_INITERROR);
-
- if (gzread(gzf, &head,sizeof(UniversalHeader)) != sizeof(UniversalHeader) || strncmp(head.id, "DDF1", 4))
- errFatal("spluginLoadUniversal","wrong filetype in " << mFile,SIMWORLD_INITERROR);
-
- if (gridSize[0] != head.dimX || gridSize[1] != head.dimY || gridSize[2] != head.dimZ) {
- debMsg("spluginLoadUniversal","file's gridsize (" << head.dimX << "," << head.dimY << "," << head.dimZ << ") != gridsize (" << gridSize[0] << "," << gridSize[1] << "," << gridSize[2] << ")");
- if(mInterpolBorder<=-1)
- errFatal("spluginLoadUniversal","Gridsizes don't match, and interpolation is turned off" , SIMWORLD_GRIDERROR);
- }
-
- unsigned char* rawFrame = new unsigned char[head.bytesPerFrame];
- if (gzread(gzf, rawFrame, head.bytesPerFrame) != head.bytesPerFrame)
- errFatal("spluginLoadUniversal","error loading frame data in " << mFile,SIMWORLD_INITERROR);
-
- gzclose(gzf);
-
- // distinguish data types, invoke grid loader
- if(param->haveGridInt(mGrid)) {
- Grid<int>* grid = param->getGridInt(mGrid);
- if (head.elementType != 0 || head.elements != 1)
- errFatal("spluginLoadUniversal","Trying to load non-integer data into integer grid" , SIMWORLD_GRIDERROR);
- fsLoadData<int>(flags, grid, rawFrame, head, onlyFluid, mInterpolBorder);
- } else if(param->haveGridReal(mGrid)) {
- Grid<Real>* grid = param->getGridReal(mGrid);
- if (head.elementType != 1 || head.elements != 1)
- errFatal("spluginLoadUniversal","Trying to load non-real data into real grid" , SIMWORLD_GRIDERROR);
- fsLoadData<Real>(flags, grid, rawFrame, head, onlyFluid, mInterpolBorder);
- } else if(param->haveGridVec3(mGrid)) {
- Grid<Vec3>* grid = param->getGridVec3(mGrid);
- if (head.elementType != 2 || head.elements != 3)
- errFatal("spluginLoadUniversal","Trying to load non-vec3 data into vec3 grid" , SIMWORLD_GRIDERROR);
- fsLoadData<Vec3>(flags, grid, rawFrame, head, onlyFluid, mInterpolBorder);
- } else {
- errFatal("spluginLoadUniversal","Grid not found "<< mGrid , SIMWORLD_GRIDERROR);
- }
- return true;
- };
-
- protected:
- std::string mGrid, mFile, mSolver, mSrcGrid;
- bool onlyFluid;
- int mInterpolBorder;
-};
-
-// dump density to disk as gzipped df3
-class spluginDumpDf3 : public spluginDumperBase {
- public:
- spluginDumpDf3() : spluginDumperBase(),
- mGrid("-unnamed1-"), prefix("") { };
- ~spluginDumpDf3() { };
-
- virtual bool parseParams(const ParamSet& params) {
- //debMsg("spluginDumpDf3","parse");
- mGrid = params.FindOneString("gridname", mGrid );
- prefix = params.FindOneString("prefix", mGrid );
- mPbrt = params.FindOneInt("pbrt", 0 ) != 0;
- parseParamsDumperBase(params);
- return true;
- };
- virtual bool initPlugin() {
- mSimTime = 0.;
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real org_dt) {
- Real dt = org_dt * mpPlParams->getDeltaX();
- debMsg("spluginDumpDf3","dt="<<dt<<" grid:"<<mGrid<<"; simTime="<<
- mSimTime<<", last="<<mLastAniOutTime<<", cnt="<<mAnimOutCounter<<" " );
-
- mSimTime += dt;
- // crude approx if dt is larger than mTimestepAnim,
- // might be better to reduce dt?
- while ( this->doDump() ) {
- myTime_t dumptstart = getTime();
- mLastAniOutTime += mpPlParams->mTimestepAnim;
- FlagGrid* pFlags = mpPlParams->getGridInt( "flags" );
- nVec3i gridSize = pFlags->getSize();
- Grid<Real>* srcVal = mpPlParams->getGridReal(mGrid);
-
- int dimMax = VMAX(gridSize);
-
- const int twodKs = mpPlParams->getFluidSolver()->get2dKstart();
- const int twodKe = mpPlParams->getFluidSolver()->get2dKend();
- // TODO why are x,y swapped?
- //nVec3i min(twodKs, 0, 0);
- //nVec3i max(twodKe, gridSize[0], gridSize[1]);
- //nVec3i res = max-min;
-
- std::ostringstream voutfilename;
- char nrStr[5]; // nr conversion
- snprintf(nrStr, 5, "%04d", mAnimOutCounter );
-
- voutfilename << this->mOutname;
- if(prefix.length()>0) voutfilename << "_" << prefix;
- voutfilename << "_" << nrStr;
-
- std::cout << "FRAME DUMP " << voutfilename.str() << std::endl;
-
- debMsg("spluginDumpDf3","Writing '"<<voutfilename.str()<<"', resolution="<<gridSize<<" " );
- string filenameDf3 = voutfilename.str() + (mPbrt ? ".pbrt.gz" : ".df3.gz");
-
- gzFile file;
- file = gzopen(filenameDf3.c_str(), "wb1");
- if (file != NULL) {
- // dimensions
- const int byteSize = 2;
- const unsigned short int onx=srcVal->getSizeX(),ony=srcVal->getSizeY(),onz=srcVal->getSizeZ();
- /*unsigned short int nx,ny,nz;
- nx = onx >> 8;
- ny = ony >> 8;
- nz = onz >> 8;
- nx += (onx << 8);
- ny += (ony << 8);
- nz += (onz << 8);
- nx = onx; ny = ony; nz = onz;
- gzwrite(file, (void*)&nx, sizeof(short));
- gzwrite(file, (void*)&ny, sizeof(short));
- gzwrite(file, (void*)&nz, sizeof(short));
- */
- // get rid of swizzling
- nVec3i write_res = nVec3i(onx,ony,onz);
- const int nitems = onx*ony*onz;
- const float mul = (float)( (1<<(8*byteSize))-1);
-
- Real *buf = new Real[nitems];
- for (int k = 0; k < onz; k++)
- for (int j = 0; j < ony; j++)
- for (int i = 0; i < onx; i++) {
- float val = srcVal->getGlobal(i,j,k);
- CLAMP(val, 0.f,1.f);
- buf[k*(onx*ony)+j*onx+i] = val;
- }
- if (mPbrt) {
- // text pbrt output
- std::ostringstream sbuf;
- Vec3 prop(onx,ony,onz);
- prop /= prop.max();
- sbuf << "Volume \"volumegrid\"" << endl;
- sbuf << " \"integer nx\" " << onx << endl;
- sbuf << " \"integer ny\" " << ony << endl;
- sbuf << " \"integer nz\" " << onz << endl;
- sbuf << " \"point p0\" [ 0 0 0 ]" << endl;
- sbuf << " \"point p1\" [ " << prop.x << " " << prop.y << " " << prop.z << " ]" << endl;
- sbuf << " \"float density\" [ " << endl;
- for (int i=0;i<nitems;++i)
- sbuf << buf[i] << " ";
- sbuf << " ] " << endl;
- string bs = sbuf.str();
- gzwrite(file, (void*)(bs.c_str()), bs.length());
- } else {
- // binary DF3 output
- gzwrite(file, &write_res[0] , 3*sizeof(int));
- unsigned short int *dbuf = new unsigned short int[nitems];
- for (int i=0;i<nitems;++i)
- dbuf[i] = (unsigned short int)(buf[i]*mul);
- gzwrite(file, (void*)dbuf, sizeof(unsigned short int)* nitems);
- delete[] dbuf;
- }
- gzclose(file);
- delete[] buf;
- // df3 gz written
- } else {
- errMsg("spluginDumpDf3","Unable to write to "<<filenameDf3 );
- }
-
- this->increaseDumpCounter();
-
- myTime_t dumptend = getTime();
- debMsg("spluginDumpDf3","took "<< getTimeString(dumptend-dumptstart)<<" for frame "<<mAnimOutCounter );
- }
-
- return true;
- };
-
- protected:
- // grid names to swap
- std::string mGrid, prefix;
- bool mPbrt;
-};
-
-
-
-//*****************************************************************************
-
-SolverPlugin* MakeIoPlugin(std::string name) {
- if (name.compare( string("dump-df3") )==0) {
- return new spluginDumpDf3;
- } else if (name.compare( string("dump-universal") )==0) {
- return new spluginDumpUniversal;
- } else if (name.compare( string("load-universal") )==0) {
- return new spluginLoadUniversal;
- } else if (name.compare( string("print-timing-stats") )==0) {
- return new spluginPrintTimingStats;
- }
- return NULL;
-}
-
-} // end namespace DDF
-
diff --git a/intern/smoke/intern/source/fluidsolver.cpp b/intern/smoke/intern/source/fluidsolver.cpp
deleted file mode 100644
index 173ce0a3e35..00000000000
--- a/intern/smoke/intern/source/fluidsolver.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Class encapsuling the solver
- *
- *****************************************************************************/
-
-// lsdebug
-#include "globals.h"
-#include "vectorbase.h"
-
-#include "solverparams.h"
-#include "solverplugin.h"
-#include "paramset.h"
-
-#include "vortexpart.h"
-//#include "boundbox.h"
-#include "randomstream.h"
-#include <fstream>
-#include <sstream>
-
-// define global solver list
-map<string, DDF::FluidSolver*> gFluidSolvers;
-DDF::FluidSolver *gpFsolver = NULL;
-
-namespace DDF {
-// search for fluid solve with given name
-FluidSolver* ddfWorldFindSolver(const std::string solverName) {
- if(gFluidSolvers.find(solverName) != gFluidSolvers.end() ) {
- return gFluidSolvers[solverName];
- }
-
- errMsg("ddfWorldFindSolver","Solver '"<<solverName<<"' not found!");
- std::cout<<helperPrintMap(gFluidSolvers,"ddfWorldFindSolver")<<"\n";
- return NULL;
-}
-
-// ctor
-FluidSolver::FluidSolver(const std::string& name) :
- mpParams(NULL),
- mDt(0.), mDim(0), mGravity(0.),
- mpFlags(NULL),
- mStepCounter(0),
- mName(name), mSolverInited(false)
-{
- mpVorticitySys = NULL;
- // debug test inits
- mGravity = Vec3( 0., 0., 0.);
-};
-
-// dtor
-FluidSolver::~FluidSolver() {
- // free plugins
- for (int i=0; i< (int)mPlugins.size(); i++)
- delete mPlugins[i];
- for (int i=0; i< (int)mInitPlugins.size(); i++)
- delete mInitPlugins[i];
- for (int i=0; i< (int)mEndPlugins.size(); i++)
- delete mEndPlugins[i];
-
- mPlugins.clear();
- mEndPlugins.clear();
- mInitPlugins.clear();
- mPluginTimes.clear();
- delete mpParams;
- if (mpVorticitySys != NULL) delete mpVorticitySys;
-
- //note, handle free'ing other pointers...
-};
-
-// *****************************************************************************
-//! init solver
-bool FluidSolver::initFluid() {
- if(!mpParams) {
- errMsg("FluidSolver::initFluid","Fatal - no params given...");
- return false;
- }
- mpParams->setFluidSolver( this );
-
- // restrict z-axis in 2D
- if (gDim==2) {
- nVec3i nn = mpParams->getGridSize();
- nn[2] = gPatchSize;
- mpParams->setGridSize(nn);
- }
-
- const nVec3i n = mpParams->getGridSize();
- // set time to zero
- mpParams->addToSimTime( -mpParams->getSimTime() );
- mpFlags = mpParams->getGridInt("flags");
-
- // init from unittests
- const int nMax = mpParams->getDimMax();
-
- mTwodKs = 0;
- mTwodKe = n[2];
- if (gDim==2) {
- mTwodKs = gPatchSize/2;
- mTwodKe = mTwodKs+1;
- }
- const int ks = mTwodKs;
- const int ke = mTwodKe;
-
- // setup boundaries
- for (int k=ks; k< ke; k++)
- for (int j=0; j< n[1]-0; j++)
- for (int i=0; i< n[0]-0; i++) {
- int set = FFLUID;
- if( k<=0 || j<=0 || i<=0 ||
- (k>=n[2]-1) || (j>=n[1]-1) || (i>=n[0]-1)) { set = FOBSTACLE; }
- mpFlags->getGlobal(i,j,k) = set;
- }
- mDim = n;
-
- if (mpParams->mHostVorticitySystem)
- mpVorticitySys = new VorticitySystem(this);
-
- return true;
-};
-
-//! run init plugins once, similar to simulateFluid
-void FluidSolver::runInitPlugins() {
- mDt = mpParams->getTimestep();
- DDF::myTime_t tStart = DDF::getTime();
-
- // run plugins
- for (int i=0; i< (int)mInitPlugins.size(); i++) {
-
- // execute
- DDF::myTime_t plStart = DDF::getTime();
- if (! mInitPlugins[i]->performStep(mDt) ) {
- errFatal("FluidSolver::runInitPlugins","Plugin step "<<i<<" failed!", SIMWORLD_PLUGINERROR);
- }
- DDF::myTime_t plEnd = DDF::getTime();
- }
-
- // timing...
- DDF::myTime_t tEnd = DDF::getTime();
- debMsg("FluidSolver::runInitPlugins",mpParams->mName<<" t="<<mpParams->getSimTime() <<", dt="<<mDt<<", took "<< DDF::getTimeString(tEnd-tStart)<<" ");
-};
-
-//! run end plugins once, similar to simulateFluid
-void FluidSolver::finalize() {
- mDt = mpParams->getTimestep();
- DDF::myTime_t tStart = DDF::getTime();
-
- // finalize main loop plugins
- for (int i=0; i< (int)mPlugins.size(); i++)
- mPlugins[i]->finish();
-
- // run end plugins
- for (int i=0; i< (int)mEndPlugins.size(); i++) {
-
- // execute
- DDF::myTime_t plStart = DDF::getTime();
- if (! mEndPlugins[i]->performStep(mDt) ) {
- errFatal("FluidSolver::runEndPlugins","Plugin step "<<i<<" failed!", SIMWORLD_PLUGINERROR);
- }
- DDF::myTime_t plEnd = DDF::getTime();
- //mPluginTimes[i] += (double)(plEnd-plStart);
- }
-
- // timing...
- DDF::myTime_t tEnd = DDF::getTime();
- debMsg("FluidSolver::finalize",mpParams->mName<<" t="<<mpParams->getSimTime() <<", dt="<<mDt<<", took "<< DDF::getTimeString(tEnd-tStart)<<" ");
-};
-
-// setup plugin stack
-void FluidSolver::addPlugins(vector<SolverPlugin*>& plugins) {
- debMsg("addPlugins","adding "<<plugins.size() );
- mPluginTimes.clear();
-
- // store plugin stack, and perform first init
- for (int i=0; i< (int)plugins.size(); i++) {
- mPlugins.push_back( plugins[i] );
- mPluginTimes.push_back( 0. );
-
- if(! mPlugins[i]->initPlugin() ) {
- errFatal("FluidSolver::addPlugins","Init "<<i<<" failed!", SIMWORLD_PLUGINERROR);
- }
- }
-}
-
-// setup init plugin stack
-void FluidSolver::addInitPlugins(vector<SolverPlugin*>& plugins) {
- debMsg("addInitPlugins","adding "<<plugins.size() );
- mPluginTimes.clear();
-
- // store plugin stack, and perform first init
- for (int i=0; i< (int)plugins.size(); i++) {
- mInitPlugins.push_back( plugins[i] );
-
- if(! mInitPlugins[i]->initPlugin() ) {
- errFatal("FluidSolver::addInitPlugins","Init "<<i<<" failed!", SIMWORLD_PLUGINERROR);
- }
- }
-}
-
-// setup end plugin stack
-void FluidSolver::addEndPlugins(vector<SolverPlugin*>& plugins) {
- debMsg("addInitPlugins","adding "<<plugins.size() );
-
- // store plugin stack, and perform first init
- for (int i=0; i< (int)plugins.size(); i++) {
- mEndPlugins.push_back( plugins[i] );
-
- if(! mEndPlugins[i]->initPlugin() ) {
- errFatal("FluidSolver::addEndPlugins","Init "<<i<<" failed!", SIMWORLD_PLUGINERROR);
- }
- }
-}
-
-
-//! advance by time t
-bool FluidSolver::simulateFluid() {
- mDt = mpParams->getTimestep();
- DDF::myTime_t tStart = DDF::getTime();
-
- debMsg("\nsimulateFluid"," for '"<<this->getName()<<"' ");
- if(!isSolverInited()) {
- errFatal("simulateFluid","Not inited!? 'SolverEnd' statement missing...?", SIMWORLD_GENERICERROR);
- }
-
- if (mPlugins.size() == 0) {
- mpParams->setQuit(true);
- return false;
- }
-
- // run plugins
- for (int i=0; i< (int)mPlugins.size(); i++) {
- // plugin active? start&stop time
- if(! mPlugins[i]->isCurrentlyActive( mpParams->getSimTime() ) ) {
- continue;
- }
-
- // execute
- DDF::myTime_t plStart = DDF::getTime();
- if (! mPlugins[i]->performStep(mDt) ) {
- errFatal("FluidSolver::simulateFluid","Plugin step "<<i<<" failed!", SIMWORLD_PLUGINERROR);
- }
- DDF::myTime_t plEnd = DDF::getTime();
- mPluginTimes[i] += (double)(plEnd-plStart);
- }
-
- mpParams->addToSimTime( mDt * mpParams->getDeltaX() );
- mpParams->addToNoiseTime(mDt);
- mStepCounter++;
-
- // timing...
- DDF::myTime_t tEnd = DDF::getTime();
- //debMsg("SG-Fl","simtime="<<sgSimTime<<", Time = "<< DDF::getTimeString(tEnd-tStart) );
- debMsg("FluidSolver::simulateFluid",mpParams->mName<<" t="<<mpParams->getSimTime() <<", dt="<<mDt<<", took "<< DDF::getTimeString(tEnd-tStart)<<" #steps:"<<mStepCounter);
-
- return true;
-};
-
-// velocity interpolation helpers
-# define PINIT_INTERPOL(offa,offb,offc) \
- Real srcpi = pos[0]+(offa); \
- Real srcpj = pos[1]+(offb); \
- Real srcpk = pos[2]+(offc); \
- int srci = (int)srcpi; \
- int srcj = (int)srcpj; \
- int srck = (int)srcpk; \
- CLAMP_TO_GRID(srci,srcj,srck,vels); \
- const float s1 = srcpi-(float)srci, s0 = 1.-s1; \
- const float t1 = srcpj-(float)srcj, t0 = 1.-t1; \
- const float f1 = srcpk-(float)srck, f0 = 1.-f1;
- /* end init */
-
-# define VELACC vels->getGlobal
-# if DDF_DIMENSION==3
-# define PADV_INTERPOLATE(index) \
- vel[index] = f0*( \
- s0*(t0*VELACC(srci ,srcj,srck)[index] + t1*VELACC(srci ,srcj+1,srck)[index] ) + \
- s1*(t0*VELACC(srci+1,srcj,srck)[index] + t1*VELACC(srci+1,srcj+1,srck)[index] ) ) \
- + f1 * ( \
- s0*(t0*VELACC(srci ,srcj,srck+1)[index] + t1*VELACC(srci ,srcj+1,srck+1)[index] ) + \
- s1*(t0*VELACC(srci+1,srcj,srck+1)[index] + t1*VELACC(srci+1,srcj+1,srck+1)[index] ) ) ;
- /* end interp */
-# else
- // NOTE! srck not used for 2d!
-# define PADV_INTERPOLATE(index) \
- vel[index] = f0*( \
- s0*(t0*VELACC(srci ,srcj,srck)[index] + t1*VELACC(srci ,srcj+1,srck)[index] ) + \
- s1*(t0*VELACC(srci+1,srcj,srck)[index] + t1*VELACC(srci+1,srcj+1,srck)[index] ) ) ;
- /* end interp */
-# endif // DDF_DIMENSION==3
-
-Vec3 FluidSolver::interpolateVelocity(Vec3 pos, Grid<Vec3>* vels, const Real dx) {
- Vec3 vel;
- pos /= dx; // mpParams->getDeltaX();
- if (gDim==2) pos[2] = gPatchSize/2;
-
- Real koff= -0.5;
- if (gDim==2) koff=0.;
-
- { PINIT_INTERPOL(0., -0.5, koff);
- PADV_INTERPOLATE(0); }
-
- { PINIT_INTERPOL(-0.5, 0., koff);
- PADV_INTERPOLATE(1); }
-
-# if DDF_DIMENSION==3
- { PINIT_INTERPOL(-0.5, -0.5, 0.);
- PADV_INTERPOLATE(2); }
-# else
- vel[2] = 0.;
-# endif
-
- //debMsg("interpolateVelocity","At "<<pos<<" = "<<vel ); // DEBUG
- return vel;
-} // interpolateVelocity
-
-
-Vec3 FluidSolver::interpolateVpVelocity(Vec3 pos, Grid<Vec3>* vels) {
- Vec3 vel;
- if (gDim==2) pos[2] = gPatchSize/2;
-
- { PINIT_INTERPOL(0.5, 0., 0.);
- PADV_INTERPOLATE(0); }
-
- { PINIT_INTERPOL(0., 0.5, 0.);
- PADV_INTERPOLATE(1); }
-
-# if DDF_DIMENSION==3
- { PINIT_INTERPOL(0., 0., 0.5);
- PADV_INTERPOLATE(2); }
-# else
- vel[2] = 0.;
-# endif
-
- return vel;
-}
-
-#undef PIOFF
-#undef PINIT_INTERPOL
-#undef PADV_INTERPOLATE
-#undef VELACC
-
-// set velocity, check flags
-// similar to force add (but slower!)
-void FluidSolver::setGlobVelNoobs(int i,int j, int k, Vec3 &set, Grid<Vec3>* velGrid) {
- if ( fgIsObstacle(mpFlags->getGlobal(i,j,k)) ) return;
-
- // new test, only set empty ones
- if (!fgIsEmpty(mpFlags->getGlobal(i,j,k)) ) return;
- Vec3& velE = velGrid->getGlobal(i,j,k);
- if (fgIsEmpty(mpFlags->getGlobal(i-1,j,k)) ) {
- velE[0] = set[0];
- }
- if (fgIsEmpty(mpFlags->getGlobal(i,j-1,k)) ) {
- velE[1] = set[1];
- }
- if (fgIsEmpty(mpFlags->getGlobal(i,j,k-1)) ) {
- velE[2] = set[2];
- }
- return;
-
-
- //Vec3& vel = mpCurrVel->getGlobal(i,j,k);
- Vec3& vel = velGrid->getGlobal(i,j,k);
- if (!fgIsObstacle(mpFlags->getGlobal(i-1,j,k)) ) {
- vel[0] = set[0];
- }
-
- if (!fgIsObstacle(mpFlags->getGlobal(i,j-1,k)) ) {
- vel[1] = set[1];
- }
-
- if (!fgIsObstacle(mpFlags->getGlobal(i,j,k-1)) ) {
- vel[2] = set[2];
- }
-}
-
-// return timing statistics string
-std::string FluidSolver::getTimingStats(int sort) {
- std::ostringstream ret;
- ret << "FluidSolver::getTimingStats, #steps="<< (mStepCounter+1) <<"\n";
- const double istep = 1 / (double)(mStepCounter+1.);
-
- double total = 0.;
- double max = -1.;
- for(int i=0; i<(int)mPluginTimes.size(); i++) {
- total += mPluginTimes[i]*istep;
- if(mPluginTimes[i]*istep > max) max = mPluginTimes[i]*istep;
- }
-
- if(sort==0) {
- for(int i=0; i<(int)mPluginTimes.size(); i++) {
- ret << i <<", "<< mPlugins[i]->getName() << " = "<< getTimeString( (myTime_t)(mPluginTimes[i]*istep) )
- <<"; " << (mPluginTimes[i]*istep / total *100.) <<"%" // per cent
- <<"\n";
- }
- } else {
- std::vector<bool> done;
- int printed = 0;
- done.resize( mPluginTimes.size() );
- for(int i=0; i<(int)mPluginTimes.size(); i++) {
- done[i] = false;
- }
- // sort the slow way...
- while(printed< (int)mPluginTimes.size()) {
- double nextMax = -1.;
- for(int i=0; i<(int)mPluginTimes.size(); i++) {
- if(mPluginTimes[i]*istep==max) {
- ret << i <<", "<< mPlugins[i]->getName() << " = "<< getTimeString( (myTime_t)(mPluginTimes[i]*istep) )
- <<"; " << (mPluginTimes[i]*istep / total *100.) <<"%" // per cent
- <<"\n";
- done[i] = true;
- }
- if(!done[i] && mPluginTimes[i]*istep > nextMax) nextMax = mPluginTimes[i]*istep;
- }
- max = nextMax;
- printed++;
- }
- }
- ret <<"Total time = " << getTimeString( (myTime_t)total ) <<"\n";
-
- return ret.str();
-}
-
-}// end namespace DDF
diff --git a/intern/smoke/intern/source/fluidsolver.h b/intern/smoke/intern/source/fluidsolver.h
deleted file mode 100644
index f3906aa8f48..00000000000
--- a/intern/smoke/intern/source/fluidsolver.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Class encapsuling the solver
- *
- *****************************************************************************/
-
-#ifndef DDF_FLUIDSOLVER_H
-#define DDF_FLUIDSOLVER_H
-
-#include "globals.h"
-#include "grid.h"
-#include "solverparams.h"
-
-namespace DDF {
-class GeomFile;
-class SolverPlugin;
-class VorticitySystem;
-
-extern FluidSolver* ddfWorldFindSolver(const std::string solverName);
-
-//! patch grid based cg solver
-class FluidSolver {
- public:
- // constructor
- FluidSolver(const std::string& name="fluidSolverUnnamed");
- ~FluidSolver();
-
- //! setup plugin stack
- void addPlugins(vector<SolverPlugin*>& plugins);
- //! setup init plugin stack
- void addInitPlugins(vector<SolverPlugin*>& plugins);
- //! setup end plugin stack
- void addEndPlugins(vector<SolverPlugin*>& plugins);
-
- //! init solver
- bool initFluid();
- //! init level set
- void initLevelSet(int eiksolver);
- //! advance by time t
- bool simulateFluid();
- bool advanceParticles(Real t, Grid<Vec3>* vels);
- //! run init plugins
- void runInitPlugins();
-
- //! run final plugins
- void finalize();
-
- // access functions
- inline Real getDt() const { return mDt; }
- inline Real getSimTime() const { return mpParams->getSimTime(); }
- inline nVec3i getDim() const { return mDim; }
- inline VorticitySystem* getVorticitySys() { return mpVorticitySys; }
-
- inline Vec3 getGravity() const { return mGravity; }
- inline void setGravity(Vec3 set) { mGravity=set; }
- inline Real getCellSize() const { return mCellSize; }
-
- inline int getStepCounter() const { return mStepCounter; }
- inline FlagGrid* getGridFlags() { return getParams()->getGridInt("flags"); }
- inline Grid<Vec3>* getGridCurrVel() { return getParams()->getGridVec3("vel-curr"); }
- inline Grid<Vec3>* getGridOtherVel() { return getParams()->getGridVec3("vel-old"); }
- inline Grid<Real>* getGridPressure() { return getParams()->getGridReal("pressure"); }
-
- inline int get2dKstart() const { return mTwodKs; }
- inline int get2dKend() const { return mTwodKe; }
-
- inline void setName(std::string set) { mName = set; }
- inline std::string getName() { return mName; }
-
- void setParams(SolverParams *params) { mpParams = params; }
- SolverParams* getParams() { return mpParams; }
-
- bool isSolverInited() { return mSolverInited; }
- void setSolverInited(bool set) { mSolverInited=set; }
-
- int getNumInitSteps() { return mInitPlugins.size(); }
- int getNumPluginSteps() { return mPlugins.size(); }
-
- // return timing statistics string
- std::string getTimingStats(int sort);
-
- // helper info functions
- int getFrameNum() {
- return (int)(getSimTime() / (getParams()->getDt() * getParams()->getDeltaX())); }
- int getAniFrameNum() {
- return (int)(getSimTime() / (getParams()->mTimestepAnim ) ); }
-
- protected:
- typedef struct {
- std::string name;
- vector<Real> data;
- } DataVector;
-
- // parameter set
- SolverParams* mpParams;
-
- // time step
- Real mDt;
- // dimensions
- nVec3i mDim;
- // size of a single cell
- Real mCellSize;
- // gravity force
- Vec3 mGravity;
-
- // flag grid
- FlagGrid* mpFlags;
-
- VorticitySystem* mpVorticitySys;
-
- // some global info vars from init
- // 2d k region start & end
- int mTwodKs, mTwodKe;
- // for debugging steps
- int mStepCounter;
-
- // actual steps to be performed
- vector<SolverPlugin*> mPlugins;
- // steps for init
- vector<SolverPlugin*> mInitPlugins;
- // final steps
- vector<SolverPlugin*> mEndPlugins;
- // profiling of steps
- vector<double> mPluginTimes;
-
- // debug, store name from init
- std::string mName;
- bool mSolverInited;
-
- public:
-
- // interpolate velocity at a given position (note! velocity is face-centered,
- // so "normal" grid->getInerpolated(..) isnt correct
- static Vec3 interpolateVelocity(Vec3 pos, Grid<Vec3>* vels, const Real dx);
- Vec3 interpolateVpVelocity(Vec3 pos, Grid<Vec3>* vels);
-
- // set velocity using global accesses, and
- // respecting obstacle flags (only !fgIsObstacle cells are modified)
- void setGlobVelNoobs(int i,int j, int k, Vec3 &set, Grid<Vec3>* vel);
-
- // get velocity component interpolated at grid center
- inline Vec3 getCenteredVel(Grid<Vec3> *vel, int x, int y, int z) {
- Vec3 v = vel->getGlobal(x,y,z);
- v[0] += vel->getGlobal(x+1,y ,z )[0];
- v[1] += vel->getGlobal(x ,y+1,z )[1];
- v[2] += vel->getGlobal(x ,y ,z+1)[2];
- v *= 0.5;
- return v;
- };
-
-}; // FluidSolver
-
-
-} // namespace DDF
-
-#endif // DDF_FLUIDSOLVER_H
diff --git a/intern/smoke/intern/source/glutgui.cpp b/intern/smoke/intern/source/glutgui.cpp
deleted file mode 100644
index b766e22c6cf..00000000000
--- a/intern/smoke/intern/source/glutgui.cpp
+++ /dev/null
@@ -1,951 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * GUI
- *
- *****************************************************************************/
-
-#include <list>
-
-#include "globals.h"
-#include "vectorbase.h"
-#include "solverparams.h"
-#include "paramset.h"
-
-#include "fluidsolver.h"
-#include "boundbox.h"
-#include "vortexpart.h"
-
-#if DDF_GLUTGUI==1
-#if defined(__APPLE__)
-// mac
-#include <GLUT/glut.h>
-#else
-#include <GL/glut.h>
-#endif
-#endif // DDF_GLUTGUI==1
-
-// solver object from main
-DDF::FluidSolver *gpGlutFsolver = NULL;
-
-// velocity grid to display "string showvel" param
-std::string gShowVelgridName = std::string("vel-curr");
-// name of real grid to show
-std::string gShowRealgridName = std::string("pressure");
-
-// scale display of velocities with "float vel-scale" parameter for glut gui
-static float gScaleVelocityDisplay = 1.; // = g Vec3 Divider
-// scale real values in grids for display, store one value per grid
-std::map<std::string,float> gScaleRealDisplay;
-
-// draw velocities at center instead of faces?
-static bool gDrawCenteredVels = false;
-static bool gVelocityMAC = true;
-static bool gFinalizationDone = false;
-// draw lines for grid (only for dims <= 128)
-static bool gDrawLines = true;
-
-// toggle flag bit string display for probing on/off
-static bool gProbeShowFlags = false;
-
-// show real values in empty cells?
-const bool gHideEmptyValues = true;
-
-
-/******************************************************************************/
-namespace DDF {
-
-
-
-// set by parser externally, read here...
-ParamSet gGlutGuiParams;
-
-#if DDF_GLUTGUI==1
-
-#if DDF_DIMENSION==2
-Vec3 gViewTrafo(0., 0., -0.01);
-#else
-Vec3 gViewTrafo(0., 0., -0.5);
-#endif
-Vec3 gViewRot(0., 0., 0.);
-
-bool gDrawVortexParticles = true;
-//bool gDrawPhiRef = false;
-bool gDrawVel = false;
-
-// time stepping
-bool gStep = false;
-bool gPause = false;
-// movement speeds
-const float gMoveSpeed = 0.002;
-const float gRotSpeed = 0.2;
-
-// region of interest
-BboxVeci gGlutRoi;
-int gRoiPlane = 2;
-// minimal and maximal values for grid info in GUI
-Real gRealgridMin = 0., gRealgridmMax = 0.;
-Vec3 gVecgridMin = Vec3(0.), gVecgridMax = Vec3(0.);
-
-bool gGlobalVPart = true;
-
-// helper functions in guihelpers.cpp
-void glutgSelectNextSolver();
-void glutgSelectNextFloatArray();
-void glutgSelectNextVec3Array();
-void glutgSelectNextFloatArrayO();
-void initFloatArrayDisplay();
-
-void handle_display();
-
-// mouse motion
-static int g_mouseBut = -1;
-static int g_specialKey = -1;
-static int g_lastMouseX=-1, g_lastMouseY=-1;
-
-/******************************************************************************/
-
-void initGlutRoi(Real planeFac) {
- nVec3i grsize = gpGlutFsolver->getGridFlags()->getSize();
-
- // roi checks are "inclusive" of boundaries, so reduce by one...
- grsize += nVec3i(-1);
- grsize[gRoiPlane] = (grsize[gRoiPlane] * planeFac);
-
- nVec3i grsizeMin(0);
- grsizeMin[gRoiPlane] = grsize[gRoiPlane];
- gGlutRoi = BboxVeci( grsizeMin, grsize );
-
-}
-
-inline void initGlutRoiRect(nVec3f &p0,nVec3f &p1,nVec3f &p2,nVec3f &p3, nVec3i off, Real mDX,nVec3f pOffset) {
- switch( gRoiPlane ) {
- case 2:
- p0 = nVec3f((off[0]+0)*mDX, (off[1]+0)*mDX, (off[2]+0)*mDX)+pOffset;
- p1 = nVec3f((off[0]+1)*mDX, (off[1]+0)*mDX, (off[2]+0)*mDX)+pOffset;
- p2 = nVec3f((off[0]+1)*mDX, (off[1]+1)*mDX, (off[2]+0)*mDX)+pOffset;
- p3 = nVec3f((off[0]+0)*mDX, (off[1]+1)*mDX, (off[2]+0)*mDX)+pOffset;
- break;
- case 1:
- p0 = nVec3f((off[0]+0)*mDX, (off[1])*mDX, (off[2]+0)*mDX)+pOffset;
- p1 = nVec3f((off[0]+1)*mDX, (off[1])*mDX, (off[2]+0)*mDX)+pOffset;
- p2 = nVec3f((off[0]+1)*mDX, (off[1])*mDX, (off[2]+1)*mDX)+pOffset;
- p3 = nVec3f((off[0]+0)*mDX, (off[1])*mDX, (off[2]+1)*mDX)+pOffset;
- break;
- case 0:
- p0 = nVec3f((off[0])*mDX, (off[1]+0)*mDX, (off[2]+0)*mDX)+pOffset;
- p1 = nVec3f((off[0])*mDX, (off[1]+1)*mDX, (off[2]+0)*mDX)+pOffset;
- p2 = nVec3f((off[0])*mDX, (off[1]+1)*mDX, (off[2]+1)*mDX)+pOffset;
- p3 = nVec3f((off[0])*mDX, (off[1]+0)*mDX, (off[2]+1)*mDX)+pOffset;
- break;
- }
-}
-
-void drawVortexParticles(VorticitySystem::VList& parts)
-{
- if (gpGlutFsolver->getVorticitySys()->getParticles().size() == 0) return;
-
- Real dx = gpGlutFsolver->getParams()->getDeltaX();
- int a = gGlutRoi.getStart()[gRoiPlane];
- int b = gGlutRoi.getEnd()[gRoiPlane];
-
- for (VorticitySystem::VList::const_iterator it = parts.begin(); it != parts.end(); ++it)
- {
- if (((*it)->getFlags() & VortexParticle::FInertial) == 0)
- glColor3f(1., 1., 0.);
- else
- glColor3f(0.,1.,1.);
-
- Vec3 pos = (*it)->getPos() +.5;
- glPointSize((*it)->getRadius()*1.5);
-
- if (gDim == 2)
- pos[2] = 0.0;
- else {
- //pos[2] -= 0.5; // z offset to account for centered phi value
- if (!gGlobalVPart && (pos[2]<a-0.5 ||pos[2]>b+0.5))
- continue;
- }
- pos *= dx;
- glBegin(GL_POINTS);glVertex3f(pos[0],pos[1],pos[2]);glEnd();
- }
-
-#if DEBUG_VORTEXPATH==1
- glEnable(GL_BLEND);
- glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glBegin(GL_LINES);
- for (std::list<LineElement>::const_iterator it = gVortexPath.begin(); it != gVortexPath.end();++it)
- {
- Vec3 p1 = it->p0 + .5, p2 = it->p1 + .5;
- if (gDim == 2)
- p2[2] = p1[2] = 0.0;
- else {
- int a2 = gGlutRoi.getStart()[gRoiPlane];
- int b2 = gGlutRoi.getEnd()[gRoiPlane];
- if (!gGlobalVPart && (p1[2]<a2-0.5 ||p1[2]>b2+0.5 || p2[2]<a2-0.5 ||p2[2]>b2+0.5))
- continue;
- }
- const Real intensity = 0.7;
- glColor4f(intensity*it->r,intensity*it->g,intensity*it->b,it->a);
- glVertex3f(dx*p1[0],dx*p1[1],dx*p1[2]);
- glVertex3f(dx*p2[0],dx*p2[1],dx*p2[2]);
- }
- glEnd();
- glDisable(GL_BLEND);
-#endif
-
-}
-
-// draw grid obstacles and compute min/max pressure
-class fsDrawGridLines : public GridOpBase {
- public:
- fsDrawGridLines(FlagGrid *flags, BboxVeci roi) :
- GridOpBase() {
- mpFlags = flags;
- mRoi = roi;
- mDX = 1. / (Real)(mpFlags->getMaxSize());
- pOffset = nVec3f(0., 0., -.00001);
- glBegin(GL_LINES);
- applyOperatorToGridsSimple(this);
- glEnd();
- };
- ~fsDrawGridLines() { };
- void resetVariables() { };
- void reduce(fsDrawGridLines &op) { };
-
- void buildCallList() {
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- nVec3i off = nVec3i(i,j,k);
- if (!mRoi.contains(off)) return; // if (gDim==3 && off[2]!=mRoi) return;
- if (gDim==2) off[2] = 0;
- nVec3f p0,p1,p2,p3; initGlutRoiRect(p0,p1,p2,p3,off,mDX,pOffset);
- glColor3f(0.2,0.2,0.2);
- glVertex3fv(&p0[0]); glVertex3fv(&p1[0]);
- glVertex3fv(&p1[0]); glVertex3fv(&p2[0]);
- glVertex3fv(&p2[0]); glVertex3fv(&p3[0]);
- glVertex3fv(&p3[0]); glVertex3fv(&p0[0]);
- };
- protected:
- nVec3f pOffset; // drawing offset
- BboxVeci mRoi; // display a single slice in 3d
- Real mDX;
-}; // fsDrawGridLines */
-
-// draw grid obstacles and compute min/max pressure
-// which scalar field to show in fsDrawObstacles drawTypes:
-// 0 = eg pressure (w min/max)
-// 1 = levelset (if active)
-// 2 = error function
-class fsDrawObstacles : public GridOpBase {
- public:
- fsDrawObstacles(FlagGrid *flags,
- Grid<Real> *srcGrid, Grid<Real> *err,
- Real minp, Real maxp, BboxVeci roi, int drawtype) :
- GridOpBase(), mpSrc(srcGrid),mpErr(err), mDrawType(0) {
-
- mpFlags = flags;
- mRoi = roi;
- mDX = 1. / (Real)(mpSrc->getMaxSize());
- mMinP = minp;
- mMaxP = maxp;
- mFirstPInit = false;
- pOffset = nVec3f(0., 0., -.00001);
- mDrawType = drawtype;
-
- //mProjMult = gGlutProject / gScaleRealDisplay * mDX;
- mValScale = gScaleRealDisplay[gShowRealgridName];
- mProjMult = 0;//gGlutProject / mValScale * mDX;
-
- SolverParams* prms = gpGlutFsolver->getParams();
-
- mHideEmpty = gHideEmptyValues;
- if(mpSrc->getDisplayFlags() & 2) mHideEmpty = false;
-
- glBegin(GL_QUADS);
- applyOperatorToGridsSimple(this);
- glEnd();
- //minp = mMinP; maxp = mMaxP;
- };
- ~fsDrawObstacles() { };
- void resetVariables() { };
- void reduce(fsDrawObstacles &op) { };
-
- void buildCallList() {
- gaSrc.gridAccInit(mpSrc, AM_READ, gaCalls);
- if (mpErr) {
- gaErr.gridAccInit(mpErr, AM_READ, gaCalls);
- }
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- const int currFlag = getFlagAcc()(i,j,k);
- nVec3i gridPos = nVec3i(i,j,k);
-
- if (!mRoi.contains(gridPos)) return;
- if (gDim==2) gridPos[2] = 0;
- nVec3f p0,p1,p2,p3;
- initGlutRoiRect(p0,p1,p2,p3,gridPos,mDX,pOffset);
-
- if (mDrawType==0) {
- if (mHideEmpty && fgIsObstacle(currFlag)) {
- // obstacle
- glColor3f(0.15,0.15,0.15);
- } else if (1 && fgIsOutflow(currFlag)) {
- glColor3f(0.3,0.0,0.0);
- } else if (mHideEmpty && fgIsEmpty(currFlag)) {
- // empty cells
- glColor3f(0.,0.2,0.); // */
- } else {
- Real ps = 0.;
-
- // override with projection
- {
- // default, show field value
- const Real val = gaSrc(i,j,k);
- ps = val / mValScale ;
- }
-
- if (fgIsInflow(currFlag)) {
- glColor3f(ps, ps, 0.3);
- } else {
- if (ps>0)
- glColor3f(ps,0.,0.);
- else
- glColor3f(0.,0.,fabs(ps));
- }
- }
- } else if (mDrawType==1) {
- // level set display
- if (gDim==2) gridPos[2] = gPatchSize/2;
-
- Real v = gaSrc(i,j,k);
-
- const Real vScale = 1./5. * mValScale;
- v *= vScale;
- CLAMP(v, (Real)-1., (Real)1.);
-
- if (v>=0.) {
- glColor3f(v,0.,0.5);
- } else {
- if (v<=-1000.) {
- glColor3f(0., 0., 0.); // invalid values
- } else {
- glColor3f(0.5, 1.+v, 0.);
- }
- }
- } else if (mDrawType == 2) {
- /* a to b fades from blue to green, b to c from green to red */
- /*const Real a = 0.01;
- const Real b = 1.0;
- const Real c = 20.0;*/
- const Real a = 0.0001;
- const Real b = 0.01;
- const Real c = 1.0;
- if (gDim==2) gridPos[2] = gPatchSize/2;
- Real err = fabs(gaErr(i,j,k));
-
- if (err > b) {
- Real val = (err-b)/(c-b);
- glColor3f(val,1.0f-val,0.0f);
- } else if (err > a) {
- Real val = (err-a)/(b-a);
- glColor3f(0.0f,val,1-val);
- } else
- glColor3f(0.0f, 0.0f, 0.0f);
-
- } else {
- return;
- }
-
- glVertex3fv(&p0[0]);
- glVertex3fv(&p1[0]);
- glVertex3fv(&p2[0]);
- glVertex3fv(&p3[0]);
- };
- protected:
- nVec3f pOffset; // drawing offset
- BboxVeci mRoi;
- Real mDX;
- Real mMinP, mMaxP;
- bool mFirstPInit;
- Grid<Real> *mpSrc;
- Grid<Real> *mpErr;
- GridAccessor<Real,0> gaSrc;
- GridAccessor<Real,0> gaErr;
-
- Grid<Real> *mpPhi;
- Grid<Real> *mpPhiRef;
-
- //! what to display 0=grid, 1=levelset
- int mDrawType;
- int mHideEmpty;
- // multiplier for projected displays, adapted to gridsize
- Real mProjMult, mValScale;
-}; // fsDrawObstacles */
-
-// draw grid obstacles and compute min/max pressure
-class fsDrawCellIndex : public GridOpBase {
- public:
- fsDrawCellIndex(FlagGrid *flags, BboxVeci roi) :
- GridOpBase()
- {
- mpFlags = flags;
- mDX = 1. / (Real)(flags->getMaxSize());
- pOffset = nVec3f(0., 0., -.00001);
- mRoi = roi;
-
- glBegin(GL_QUADS);
- applyOperatorToGridsSimple(this);
- glEnd();
- };
- ~fsDrawCellIndex() { };
- void resetVariables() { };
- void reduce(fsDrawCellIndex &op) { };
-
- void buildCallList() {
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- const int currFlag = getFlagAcc()(i,j,k);
- nVec3i gridPos = /*getFlagAcc().getAccPatch()->mOffset + */nVec3i(i,j,k);
- if (!mRoi.contains(gridPos)) return;
-
- if (gDim==2) gridPos[2] = 0;
- nVec3f p0,p1,p2,p3;
- initGlutRoiRect(p0,p1,p2,p3,gridPos,mDX,pOffset);
-
- if (gDim==2) gridPos[2] = gPatchSize/2;
-
- Vec3 col = Vec3(
- gridPos[0]/(Real)mpFlags->getSizeX(),
- gridPos[1]/(Real)mpFlags->getSizeY(),
- gridPos[2]/(Real)mpFlags->getSizeZ() );
- glColor3f(col[0],col[1],col[2]);
- //debMsg("at "," "<<PRINT_IJK<<" "<<col); // DEBUG
-
- glVertex3fv(&p0[0]);
- glVertex3fv(&p1[0]);
- glVertex3fv(&p2[0]);
- glVertex3fv(&p3[0]);
- };
- protected:
- nVec3f pOffset; // drawing offset
- BboxVeci mRoi;
- Real mDX;
-}; // fsDrawLevelset */
-
-
-
-// draw centered grid vels
-class fsDrawVels : public GridOpBase {
- public:
- fsDrawVels(FlagGrid *flags, Grid<Vec3> *vel, BboxVeci roi) :
- GridOpBase(), mpVel(vel) {
- mpFlags = flags;
- mDX = 1. / (Real)(mpVel->getMaxSize());
- mRoi = roi;
-
- // switch off mac display for this grid, if flags|4 is set
- //if( mpVel->getDisplayFlags() & 4) mMacValues = false;
-
- glBegin(GL_LINES);
- applyOperatorToGridsSimple(this);
- glEnd();
- };
- ~fsDrawVels() { };
- void resetVariables() { };
- void reduce(fsDrawVels &op) { };
-
- void buildCallList() {
- gaVel.gridAccInit(mpVel, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- const int currFlag = getFlagAcc()(i,j,k);
- const bool dxScale = true;
- //if (!fgIsFluid(currFlag)) return;
- //if (fgIsObstacle(currFlag)) return;
-
- nVec3i off = nVec3i(i,j,k);
- if (!mRoi.contains(off)) return;
- if (gDim==2) off[2] = 0;
-
- nVec3f p = nVec3f(off[0]*mDX, off[1]*mDX, off[2]*mDX);
-
- if (gDrawCenteredVels) { // centered
- nVec3f vOrg = vec2F( gaVel(i,j,k) );
- nVec3f v = vOrg;
- if(mpVel->checkIndexValid(i+1,j+1,k+1) && gVelocityMAC) {
- v[0] += gaVel(i+1,j,k)[0];
- v[1] += gaVel(i,j+1,k)[1];
- v[2] += gaVel(i,j,k+1)[2];
- v *= 0.5;
- }
- if(dxScale) v *= mDX;
- v *= gScaleVelocityDisplay;
-
- p[0] += mDX*0.5;
- p[1] += mDX*0.5;
- if (gDim==3) p[2] += mDX*0.5; // offset in z dir for display only
-
- glColor3f(0.,1.,0.);
- glVertex3fv(&p[0]);
- p += v;
- glColor3f(1.,1.,1.);
- glVertex3fv(&p[0]);
- } else { // side
- // dont use averaged vels!
- nVec3f v = vec2F( gaVel(i,j,k) ); // * 0.33;
- if(dxScale) v *= mDX;
- v *= gScaleVelocityDisplay;
-
- p = nVec3f(off[0]*mDX, off[1]*mDX, off[2]*mDX);
- p[0] += 0.5*mDX;
- glColor3f(0.,0.,1.);
- glVertex3fv(&p[0]);
- p[1] += v[1];
- glColor3f(1.,1.,1.);
- glVertex3fv(&p[0]);
-
- p = nVec3f(off[0]*mDX, off[1]*mDX, off[2]*mDX);
- p[1] += 0.5*mDX;
- glColor3f(1.,0.,0.);
- glVertex3fv(&p[0]);
- p[0] += v[0];
- glColor3f(1.,1.,1.);
- glVertex3fv(&p[0]);
-
- if (gDim==3) {
- p = nVec3f(off[0]*mDX, off[1]*mDX, off[2]*mDX);
- p[2] += 0.5*mDX;
- glColor3f(1.,0.,0.);
- glVertex3fv(&p[0]);
- p[2] += v[2];
- glColor3f(1.,1.,1.);
- glVertex3fv(&p[0]); } // 3dim
- }
- };
- protected:
- Real mDX;
- BboxVeci mRoi;
- Grid<Vec3> *mpVel;
- GridAccessor<Vec3,1> gaVel;
- //bool mMacValues;
-}; // fsDrawVels */
-
-
-/******************************************************************************/
-
-extern bool advanceAllSolvers(); // from main
-extern void finalizeAllSolvers(); // from main
-extern void deleteAllSolvers(); // from main
-
-void runSimulation () {
- if (gPause) return;
- if (gFinalizationDone) return;
-
- bool quit = advanceAllSolvers();
- if (quit) {
- gPause=true;
-
- if (!gFinalizationDone) {
- finalizeAllSolvers();
- gFinalizationDone = true;
- }
-
- // immediatly quit for qutorun
- if(getenv("DDF_GUIAUTORUN")) {
- if(atoi(getenv("DDF_GUIAUTORUN"))>=1) {
- exit(0);
- }
- }
- } // quit
-
- // debug info per timestep
- gRealgridMin = gRealgridmMax = 0.;
-
- // compute only once each time step
- if (1) {
- Grid<Real> *realGrid = NULL;
- realGrid = gpGlutFsolver->getParams()->getGridReal(gShowRealgridName); // DEBrealGrid
- goFindMinMax<Real> gomm = goFindMinMax<Real>( gpGlutFsolver->getGridFlags(), realGrid );
- gRealgridMin = gomm.mMinVal;
- gRealgridmMax = gomm.mMaxVal;
- debMsg("MINMAX-REAL","min="<<gRealgridMin<<" at "<<gomm.mMinPos<<" max="<<gRealgridmMax<<" at "<<gomm.mMaxPos);
-
- goFindMinMax<Vec3> gomv = goFindMinMax<Vec3>( gpGlutFsolver->getGridFlags(),
- gpGlutFsolver->getParams()->getGridVec3(gShowVelgridName) );
- gVecgridMin = gomv.mMinVal;
- gVecgridMax = gomv.mMaxVal;
- debMsg("MINMAXV","min="<<gomv.mMinVal<<" at "<<gomv.mMinPos<<" max="<<gomv.mMaxVal<<" at "<<gomv.mMaxPos);
-
- } // end minmax debug info
-
- glutPostRedisplay();
- if (gStep) {
- gPause = true;
- gStep = false;
- }
-
- // pause sim, if an error occurred
- if(!isSimworldOk()) {
- gPause = true;
- }
-}
-
-// debug output for patch solver
-void drawPatchGrid()
-{
- Grid<Real> *perr = NULL;
-
- int drawType = 0;
-
- Grid<Real> *realGrid = NULL;
- realGrid = gpGlutFsolver->getParams()->getGridReal(gShowRealgridName); // DEBUG
-
- // hide everything else for some iso disp settings
- bool drawGridInfo = true;
-
- if(drawGridInfo) {
- fsDrawObstacles(
- gpGlutFsolver->getGridFlags(),
- realGrid, perr,
- gRealgridMin,gRealgridmMax, gGlutRoi, drawType);
- }
-
- glLineWidth(1.0);
- if(gDrawLines && drawGridInfo) {
- fsDrawGridLines( gpGlutFsolver->getGridFlags(), gGlutRoi );
- }
-
- if (gDrawVel && drawGridInfo) {
- Grid<Vec3> *vels = gpGlutFsolver->getParams()->getGridVec3(gShowVelgridName);
- fsDrawVels( gpGlutFsolver->getParams()->getGridInt("flags"), vels, gGlutRoi );
- }
-
- if (gDrawVortexParticles && drawGridInfo && gpGlutFsolver->getVorticitySys() != NULL) {
- drawVortexParticles(gpGlutFsolver->getVorticitySys()->getParticles());
- }
-}
-
-
-/******************************************************************************/
-void handle_display (void) {
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- //gluLookAt(0.5, 0.5, 1.0, 0.5, 0.5, 0.0, 0.0, 1.0, 0.0);
- // from to up
- gluLookAt(0., 0., 0.5, 0., 0., -0.5, 0., 1., 0.);
- glPushMatrix();
-
- glTranslatef( gViewTrafo[0], gViewTrafo[1], gViewTrafo[2] );
- glRotatef(gViewRot[0], 1.,0.,0.);
- glRotatef(gViewRot[1], 0.,1.,0.);
- // center on .5 .5 .5
- glTranslatef( -0.5,-0.5,-0.5 );
-
- drawPatchGrid();
-
- glPopMatrix();
- glFlush();
- glutSwapBuffers();
-}
-
-void print_stats() {
- std::ostringstream outstr;
- int frame = gpGlutFsolver->getFrameNum();
- int aniframe = gpGlutFsolver->getAniFrameNum();
- outstr << "Solver: "<<gpGlutFsolver->getName()<<", t="<< gpGlutFsolver->getSimTime() << " [frame " << frame << ", ani " << aniframe << "]\n";
-
- // real grid stats
- //Real absmax=gRealgridmMax;
- //if (fabs(gRealgridMin)>fabs(absmax)) absmax=gRealgridMin;
- outstr << "Real-grid: "<<gShowRealgridName<< " [range " << gScaleRealDisplay[gShowRealgridName] ;
- if(gRealgridMin != 0.) outstr << " min " << gRealgridMin << "," ;
- outstr << " max " << gRealgridmMax << "]\n";
- int numP = (gpGlutFsolver->getVorticitySys()==NULL) ? 0 : gpGlutFsolver->getVorticitySys()->getParticles().size();
- if (numP > 0) outstr << numP << " vortex parts active\n";
-
- // vec grid stats
- if(gDrawVel) {
- outstr<<"Vec3-grid: "<<gShowVelgridName<<"";
- if(gDrawCenteredVels) outstr<<", centered ";
- else outstr<<", faces ";
-
- outstr << " range=" << gScaleVelocityDisplay ;
- if(norm( gVecgridMin ) > 0.) outstr << " min=" << gVecgridMin << ",";
- outstr << " max=" << gVecgridMax ;
- if (!gVelocityMAC) outstr << " noMAC" ;
- outstr << "\n";
- }
-
- debMsg("GRID", outstr.str());
-}
-
-void handle_reshape (int w, int h) {
- glViewport(0, 0, (GLsizei) w, (GLsizei) h);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 0.05, 20.0);
-
- glMatrixMode(GL_MODELVIEW);
-}
-
-void handle_keyboard(unsigned char key, int x, int y) {
- bool roiMsgs = false;
- switch (key) {
- case 'p':
- // run simulation
- gPause = !gPause;
- break;
- case 'l':
- // single step
- gPause = false;
- gStep = true;
- break;
-
- // roi z plane
- case '-':
- case '_':
- gGlutRoi.getStart()[gRoiPlane]--; gGlutRoi.getEnd()[gRoiPlane]--;
- if (roiMsgs) debMsg("key","- plane = " << gGlutRoi.getStart()[gRoiPlane]);
- if (roiMsgs) debMsg("changeGlutRoi","- roi = "<<gGlutRoi.toString()<<" plane="<<gRoiPlane ); // debug
- break;
- case '+':
- case '=':
- gGlutRoi.getStart()[gRoiPlane]++; gGlutRoi.getEnd()[gRoiPlane]++;
- if (roiMsgs) debMsg("key","+ plane = " << gGlutRoi.getStart()[gRoiPlane]);
- if (roiMsgs) debMsg("changeGlutRoi","+ roi = "<<gGlutRoi.toString()<<" plane="<<gRoiPlane ); // debug
- break;
- case '*':
- gRoiPlane++; gRoiPlane=gRoiPlane%3;
- initGlutRoi( 0.5 );
- if (roiMsgs) debMsg("changeGlutRoi","* roi = "<<gGlutRoi.toString()<<" plane="<<gRoiPlane ); // debug
- break;
- case 'o':
- gDrawVortexParticles = !gDrawVortexParticles;
- break;
- case 'v':
- // toggle velocity display
- gDrawVel = !gDrawVel;
- gVelocityMAC = !(gpGlutFsolver->getParams()->getGridVec3(gShowVelgridName)->getDisplayFlags() & 4);
- break;
- case 'V':
- // toggle centered velocity display
- gDrawCenteredVels = !gDrawCenteredVels;
- break;
- case 'g':
- //gGlutProject *=-1;
- break;
- case 'G':
- gGlobalVPart =!gGlobalVPart;
- break;
- case '`': {
- // remember grid selection factor
- nVec3i grsize = gpGlutFsolver->getGridFlags()->getSize();
- Real planeFac = ( ((Real)gGlutRoi.getStart()[gRoiPlane]+1.0) / (Real)grsize[gRoiPlane]) ;
- //grsize[gRoiPlane] = (grsize[gRoiPlane] * planeFac);
-
- // show next solver, cycle through all available
- glutgSelectNextSolver();
-
- // reset struct that have to be initialized anew for solver
- initGlutRoi(planeFac);
- debMsg("selectNextSolver","Roi factor="<<planeFac<<", plane = "<< gGlutRoi.getStart()[gRoiPlane] );
- print_stats();
- } break;
-
- case '[':
- gScaleRealDisplay[gShowRealgridName] *= 2.;
- print_stats();
- break;
- case ']':
- gScaleRealDisplay[gShowRealgridName] /= 2.;
- print_stats();
- break;
- case '{':
- gScaleVelocityDisplay /= 2.;
- print_stats();
- break;
- case '}':
- gScaleVelocityDisplay *= 2.;
- print_stats();
- break;
-
- case 'z':
- // show next float grid
- glutgSelectNextFloatArray();
- initFloatArrayDisplay();
- print_stats();
- break;
- case 'x':
- // show next vec3 grid
- glutgSelectNextVec3Array();
- gVelocityMAC = !(gpGlutFsolver->getParams()->getGridVec3(gShowVelgridName)->getDisplayFlags() & 4);
- print_stats();
- break;
- // cam movement
- case 'a': gViewTrafo[0] += gMoveSpeed* 15; break;
- case 'd': gViewTrafo[0] += gMoveSpeed*-15; break;
- case 's': gViewTrafo[1] += gMoveSpeed* 15; break;
- case 'w': gViewTrafo[1] += gMoveSpeed*-15; break;
- case 'q': gViewTrafo[2] += gMoveSpeed* 15; break;
- case 'e': gViewTrafo[2] += gMoveSpeed*-15; break;
-
- case 27: // ESC
- // quit
- //cleanSimulation();
- exit(0);
- break;
- }
-
- glutPostRedisplay();
-}
-
-
-void handle_mousePress(int button, int state, int x, int y) {
- g_specialKey = glutGetModifiers();
- // if both a mouse button, and the ALT key, are pressed then
- if ( (state == GLUT_DOWN) ) {
-
- if (button == GLUT_LEFT_BUTTON) {
- g_mouseBut = GLUT_LEFT_BUTTON;
- } else if (button == GLUT_MIDDLE_BUTTON) {
- g_mouseBut = GLUT_MIDDLE_BUTTON;
- } else {
- g_mouseBut = GLUT_RIGHT_BUTTON;
- }
- } else {
- g_mouseBut = -1;
- g_lastMouseX=g_lastMouseY=-1;
- // gProbeGridString = std::string(""); // reset display
- }
-}
-void handle_mouseMotion(int x,int y) {
-
- if (g_lastMouseX==-1 && g_lastMouseY==-1) {
- g_lastMouseX = x;
- g_lastMouseY = y;
- return;
- }
-
- if (g_mouseBut==GLUT_RIGHT_BUTTON) {
- gViewTrafo[0] += (g_lastMouseX-x) * -gMoveSpeed;
- gViewTrafo[1] += (g_lastMouseY-y) * gMoveSpeed;
- glutPostRedisplay();
- }
- if (g_mouseBut==GLUT_MIDDLE_BUTTON) {
- gViewTrafo[2] += (g_lastMouseX-x) * -gMoveSpeed;
- gViewTrafo[2] += (g_lastMouseY-y) * gMoveSpeed;
- glutPostRedisplay();
- }
- if (g_mouseBut==GLUT_LEFT_BUTTON) {
- gViewRot[1] += (g_lastMouseX-x) * -gRotSpeed;
- gViewRot[0] += (g_lastMouseY-y) * -gRotSpeed;
- glutPostRedisplay();
- }
- g_lastMouseX = x;
- g_lastMouseY = y;
- //debMsg("mouseMotion"," at "<<PRINT_VEC(x,y,0.)<<", last "<<PRINT_VEC(g_lastMouseX,g_lastMouseY,0.)<<" but="<<g_mouseBut);
-}
-
-
-
-/******************************************************************************/
-// glut gui test
-int showGlutGui(const char *argv_title)
-{
- int argc=1;
- char argvb[64]; strcpy(argvb,"ddfCmd");
- char* argv = argvb;
- int sx = 800, sy = 800;
-
- debMsg("\nglutGui","Starting...");
-
- // init parser parameters
- string solverName = gGlutGuiParams.FindOneString("solvername","default");
- gScaleVelocityDisplay = gGlutGuiParams.FindOneFloat("vel-scale", gScaleVelocityDisplay );
- gpGlutFsolver = ddfWorldFindSolver(solverName);
- if (!gpGlutFsolver) { return 1; }
-
- //if(gpGlutFsolver->getGridFlags()->getMaxSize() > 128) gDrawLines = false;
- gDrawLines = gGlutGuiParams.FindOneInt("draw-lines", gDrawLines ) > 0;
-
- gShowRealgridName = gGlutGuiParams.FindOneString("showgrid",gShowRealgridName);
- gShowVelgridName = gGlutGuiParams.FindOneString("showvel",gShowVelgridName);
-
- gGlutGuiParams.ReportUnused();
-
- if(gShowRealgridName.length()<=0 || (!gpGlutFsolver->getParams()->haveGridReal(gShowRealgridName)) ) {
- debMsg("glutGui","Invalid gShowRealgridName init '"<<gShowRealgridName<<"', re-init...");
- glutgSelectNextFloatArray();
- }
- initFloatArrayDisplay();
-
- // center view to grid
- Grid<Real> *realGrid = gpGlutFsolver->getParams()->getGridReal(gShowRealgridName);
- nVec3i size = realGrid->getSize();
- double dx = 1./(double)realGrid->getMaxSize();
- gViewTrafo[0] = 0.5 - 0.5* (double)size[0] *dx;
- gViewTrafo[1] = 0.5 - 0.5* (double)size[1] *dx;
-
- // init GLUT
- glutInit(&argc, &argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
- glutInitWindowSize(sx, sy);
- glutInitWindowPosition(10, 10);
-
- std::ostringstream title;
- title << string(argv_title);
- glutCreateWindow( title.str().c_str() );
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- // initialize OpenGL
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClearDepth(1.0);
- //glShadeModel(GL_SMOOTH);
- glDepthFunc(GL_LESS);
-
- // initialize Simulation drawing
- initGlutRoi( 0.5 );
-
- // setup callbacks
- glutDisplayFunc(handle_display);
- glutReshapeFunc(handle_reshape);
- glutKeyboardFunc(handle_keyboard);
- glutIdleFunc(runSimulation);
- glutMouseFunc(handle_mousePress);
- glutMotionFunc(handle_mouseMotion);
- glutMainLoop();
-
- return 0;
-}
-
-
-#else // DDF_GLUTGUI==1
-/******************************************************************************/
-int showGlutGui(const char* str)
-{
- // dummy
- return 0;
-}
-#endif // DDF_GLUTGUI==1
-
-}; // namespace DDF
-
diff --git a/intern/smoke/intern/source/grid.h b/intern/smoke/intern/source/grid.h
deleted file mode 100644
index 02637db2c3c..00000000000
--- a/intern/smoke/intern/source/grid.h
+++ /dev/null
@@ -1,723 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Basic grid class
- *
- *****************************************************************************/
-
-#ifndef DDF_GRIDS_H
-#define DDF_GRIDS_H
-
-//#include "patches.h"
-#include "globals.h"
-#include "vectorbase.h"
-// operators.h is included below
-namespace DDF {
-
-const int gPatchSize = 5;
-
-class GaCallContainer;
-// grid debugging
-const bool gStrictGridDebug = (DDF_DEBUG==1);
-
-// class prototypes
-template<class Scalar> class Grid;
-template<class Scalar, int BOUNDARY> class GridAccessor;
-template<class Scalar> class GridOpTouchMemory;
-
-
-// globals, allocated in globals.cpp
-extern int gGridIdCounter;
-
-// neighbor vectors (helper)
-static const int nbx[27] = { -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1, -1, 0, 1 };
-static const int nby[27] = { -1,-1,-1, 0, 0, 0, 1, 1, 1, -1,-1,-1, 0, 0, 0, 1, 1, 1, -1,-1,-1, 0, 0, 0, 1, 1, 1 };
-static const int nbz[27] = { -1,-1,-1, -1,-1,-1, -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
-
-// debug value
-const bool gUseInvalidCheck = false;
-static const Real gInvalidReal = 0.; // -1e14;
-
-// helper to shorten grid funtions
-//#define RETURN_ZERO {mZero=0; return mZero;}
-#define RETURN_ZERO {this->setDummyZero(); return mZero;}
-
-//*****************************************************************************
-// base class with standard functionality (sizes etc.)
-class GridBase {
- public:
- // cons/des
- GridBase(const std::string& name = "-unnamed-") :
- mGridId(-1),
- mSizeX(0), mSizeY(0), mSizeZ(0),
- mMinIndex(0), mMaxIndex(0),
- mName(name),
- mSanityCheckMode(2),
- mGridFlags(0)
- {
- mGridId = gGridIdCounter++;
- // ...
- };
- virtual ~GridBase() { };
-
-
- // standard access funcs
- nVec3i getMinIndex() { return mMinIndex; }
- void setMinIndex(nVec3i set) { mMinIndex = set; }
- nVec3i getMaxIndex() { return mMaxIndex; }
- void setMaxIndex(nVec3i set) { mMaxIndex = set; }
- //! grid size access
- nVec3i getSize() { return nVec3i(mSizeX,mSizeY,mSizeZ); }
- nVec3i getGridSize() { return nVec3i(mSizeX,mSizeY,mSizeZ); } // synt. sugar...
- int getSizeX() { return mSizeX; }
- int getSizeY() { return mSizeY; }
- int getSizeZ() { return mSizeZ; }
- size_t getNumElements() { return mSizeX * mSizeY * mSizeZ; }
- void setSize(nVec3i set) { mSizeX = set[0]; mSizeY = set[1]; mSizeZ = set[2]; }
-
- // helper functions for 2d/3d distinctions of loop boundaries
- int getMinZLoopValue() { if(gDim==3) { return 0; } else { return gPatchSize/2; } }
- int getMaxZLoopValue() { if(gDim==3) { return mSizeZ; } else { return gPatchSize/2+1; } }
- int getMinZLoopValue(int bnd) { if(gDim==3) { return 0+bnd; } else { return gPatchSize/2; } }
- int getMaxZLoopValue(int bnd) { if(gDim==3) { return mSizeZ-bnd; } else { return gPatchSize/2+1; } }
-
- int getGridId() { return mGridId; }
- int getUsePatches() { return false; }
-
- std::string getName() { return mName; }
- void setName(std::string set) { mName = set; }
-
- int getSanityCheckMode() { return mSanityCheckMode; }
- void setSanityCheckMode(int set) { mSanityCheckMode = set; }
-
- // or'd flags used for debugging in the gui:
- // 1 = means hide from display cycle
- // 2 = show also values in empty region (eg for level set grids)
- // 4 = this is a velocity grid with centered instead of staggered values
- int getDisplayFlags() { return mDisplayFlags; }
- void setDisplayFlags(int set) { mDisplayFlags = set; }
-
- // DG TODO: add description here
- int getGridFlags() { return mGridFlags; }
- void setGridFlags(int set) { mGridFlags = set; }
-
-
- int getMaxSize() {
- int ms = mSizeX;
- if (mSizeY>ms) ms = mSizeY;
- if (mSizeZ>ms) ms = mSizeZ;
- return ms;
- }
-
- bool checkIndexValid(int x,int y, int z) const {
- if (x < 0) return false;
- if (y < 0) return false;
- if (z < 0) return false;
- if (x>=mSizeX) return false;
- if (y>=mSizeY) return false;
- if (z>=mSizeZ) return false;
- return true;
- }
-
- bool checkIndexValidWithBounds(int x,int y, int z, int bnd) const {
- if (x < 0+bnd) return false;
- if (y < 0+bnd) return false;
- if (z < 0+bnd) return false;
- if (x>=mSizeX-bnd) return false;
- if (y>=mSizeY-bnd) return false;
- if (z>=mSizeZ-bnd) return false;
- return true;
- }
-
- bool checkIndexInBounds(int x,int y, int z, nVec3i s, nVec3i e) {
- if (x < s[0]) return false;
- if (y < s[1]) return false;
- if (z < s[2]) return false;
- if (x>= e[0]) return false;
- if (y>= e[1]) return false;
- if (z>= e[2]) return false;
- return true;
- }
-
- protected:
-
- //! global id for grid (for debugging)
- int mGridId;
-
- //! grid sizes
- int mSizeX;
- int mSizeY;
- int mSizeZ;
- //! grid extent min
- nVec3i mMinIndex;
- //! grid extent max
- nVec3i mMaxIndex;
-
- // grid name for debugging etc.
- std::string mName;
- // debugging, sanity check modes: 0=off, 1=check for nan/inf, 2=also check for threshold (default)
- int mSanityCheckMode;
- // debug display flags for grids (or'd)
- // 1 = for debug display in gui - skip this grid?
- // 2 = show empty cells
- int mDisplayFlags;
-
- // see mGridFlags defines below
- int mGridFlags;
-};
-
-// mGridFlags
-#define DDF_GRID_NO_FREE 1
-
-
-//*****************************************************************************
-// container of a single grid
-template<class Scalar>
-class Grid : public GridBase {
- public:
- // cons/des
- Grid(const std::string& name="-unnamed-");
- virtual ~Grid();
-
- //! init memory & reset to zero
- void initGridMem(int x,int y, int z);
- void initGridMem(nVec3i size) { initGridMem(size[0], size[1], size[2]); };
-
- //! change size, dont reset any data
- void resizeGridMem(int set_x,int set_y, int set_z);
-
- // string output
- std::string toString(bool format=true);
- // print formatted in given region
- std::string printWithRoi(int* roi);
-
- // inlined access functions
- inline Scalar& operator() (int x,int y, int z) {
- if (gStrictGridDebug && (!checkIndexValid(x,y,z) )) {
- errFatal("Grid::operator()","Invalid access to "<<PRINT_VEC(x,y,z) << ", grid dim: " << PRINT_VEC(mSizeX,mSizeY,mSizeZ) , SIMWORLD_GRIDERROR);
- RETURN_ZERO;
- }
- return mpData[ ((z*mSizeY+y)*mSizeX+x) ];
- }
-
- // direct global access to grid
- inline Scalar& getGlobal(int x,int y, int z) {
- if (gStrictGridDebug && (!checkIndexValid(x,y,z) )) {
- errFatal("Grid::operator()","Invalid access to "<<PRINT_VEC(x,y,z) << ", grid dim: " << PRINT_VEC(mSizeX,mSizeY,mSizeZ) , SIMWORLD_GRIDERROR);
- RETURN_ZERO;
- }
- return mpData[ ((z*mSizeY+y)*mSizeX+x) ];
- }
- // convenience defines....
- inline Scalar& getGlobal(nVec3i p) { return getGlobal(p[0],p[1],p[2]); }
- inline Scalar& get(int x,int y, int z) { return getGlobal(x,y,z); }
- inline Scalar& get(nVec3i p) { return getGlobal(p[0],p[1],p[2]); }
-
- inline Scalar *data() { return mpData; }
-
- // direct access with given index
- inline Scalar& operator[] (size_t index) {
- if (gStrictGridDebug && (index<0 || index>=(mSizeX*mSizeY*mSizeZ)) ) {
- errFatal("Grid::operator()","Invalid access to index "<< index << ", grid dim: " << PRINT_VEC(mSizeX,mSizeY,mSizeZ) , SIMWORLD_GRIDERROR);
- RETURN_ZERO;
- }
- return mpData[ index ];
- }
-
- // direct global access to grid
- inline void setGlobal(Scalar val, int x,int y, int z) {
- if (gStrictGridDebug && (!checkIndexValid(x,y,z) )) {
- errFatal("Grid::operator()","Invalid access to "<<PRINT_VEC(x,y,z) << ", grid dim: " << PRINT_VEC(mSizeX,mSizeY,mSizeZ) , SIMWORLD_GRIDERROR);
- return;
- }
- mpData[ ((z*mSizeY+y)*mSizeX+x) ] = val;
- }
-
- inline void clearGrid()
- {
- memset(mpData, 0, sizeof(Scalar)*mSizeX*mSizeY*mSizeZ);
- }
-
-
- inline Scalar getInterpolated(Real x, Real y, Real z);
- inline Scalar getInterpolated(Vec3 p) { return getInterpolated(p[0],p[1],p[2]); }
-
- inline size_t getDataSize() { return mDataSize; }
-
- protected:
- //! for safely returning zero from access funcs
- static Scalar mZero;
-
- // implementations ins globals.cpp
- void setDummyZero();
-
- // actual grid data (when usepatches=off)
- Scalar *mpData;
-
- // for resizing the grid
- size_t mDataSize;
-}; // Grid
-
-// static constant fields for returning off-grid values in debug mode (gStrictGridDebug enabled)
-template<class Scalar>
-Scalar Grid<Scalar>::mZero; // = Scalar(0.);
-
-
-
-//*****************************************************************************
-//*****************************************************************************
-//*****************************************************************************
-
-template<class Scalar>
-Grid<Scalar>::Grid(const std::string& name) : GridBase(name) {
- mpData = NULL;
-}
-
-template<class Scalar>
-Grid<Scalar>::~Grid() {
- if (mpData) delete[] mpData;
-}
-
-template<class Scalar>
-void Grid<Scalar>::initGridMem(int set_x,int set_y, int set_z) {
- if (mpData) delete[] mpData;
- Scalar zero;
- zero = 0;
- if (0) debMsg("Grid::Grid","Requested size "<<PRINT_VEC(set_x,set_y,set_z) );
-
- // special 2D init
- if (gDim==2) {
- set_z = gPatchSize;
- // min. thickness of 2d slice should be 5 cells...
- if (gPatchSize<5) {
- errFatal("Grid::initGridMem","Invalid gPatchSize="<<gPatchSize<<" for 2d compile!",SIMWORLD_GRIDERROR);
- }
- }
-
- // only valid for non patch based grids / non dyn. sims
- mSizeX = set_x;
- mSizeY = set_y;
- mSizeZ = set_z;
- mMinIndex = nVec3i(0,0,0);
- mMaxIndex = nVec3i(mSizeX,mSizeY,mSizeZ);
- int numElems = mSizeX*mSizeY*mSizeZ;
- // compute patchsizes = (n-1)/gp
- nVec3i mS(mSizeX,mSizeY,mSizeZ);
- nVec3i mPs = (mS+nVec3i(-1))/gPatchSize;
-
- std::string patchstring[2] = { "full grid", "patchwise" };
-
- // not UsePatches
- mpData = new Scalar[numElems];
- mDataSize = numElems;
-
- for (int i=0; i<numElems; i++) {
- mpData[i] = zero;
- }
-
- if (0) debMsg("Grid::Grid","Inited size"<<mS<<", "<<patchstring[0]<<", mp"<<mPs<<", id="<<mGridId); // GRIDMEMDEB
- // inited...
-}
-
-// resize data, keep old data if new size is smaller
-// parts are similar to initGridMem
-template<class Scalar>
-void Grid<Scalar>::resizeGridMem(int set_x,int set_y, int set_z) {
- const bool debugRealloc = false;
- size_t numElems = set_x*set_y*set_z;
- Scalar zero;
-
- if (debugRealloc) debMsg("Grid::resizeGridMem","Inited size="<<mDataSize<<", requested size="<<numElems<<" "<<PRINT_VEC(set_x,set_y,set_z) );
-
- // sanity check, same as initGridMem
- if (gDim==2) {
- set_z = gPatchSize;
-
- if (gPatchSize<5) {
- errFatal("Grid::initGridMem","Invalid gPatchSize="<<gPatchSize<<" for 2d compile!",SIMWORLD_GRIDERROR);
- }
- }
-
- mSizeX = set_x;
- mSizeY = set_y;
- mSizeZ = set_z;
- mMinIndex = nVec3i(0,0,0);
- mMaxIndex = nVec3i(mSizeX,mSizeY,mSizeZ);
-
- if(mDataSize>=numElems) {
- // ok, keep old size
-
- if (debugRealloc) debMsg("Grid::resizeGridMem","Data block kept");
- return;
- }
-
- // reallocate
- delete [] mpData;
- // add safety buffer for future enlargements
- size_t allocSize = (numElems * 1.5);
- mpData = new Scalar[allocSize];
- mDataSize = allocSize;
-
- for (int i=0; i<allocSize; i++) {
- mpData[i] = zero;
- }
-
- if (debugRealloc) debMsg("Grid::resizeGridMem","Data block re-allocated");
-}
-
-//*****************************************************************************
-//*****************************************************************************
-//*****************************************************************************
-
-
-template<class Scalar>
-std::string Grid<Scalar>::toString(bool format)
-{
- std::ostringstream out;
-
- /*for (int j=mMinIndex[1]; j<mMaxIndex[1]; j++) {
- for (int k=mMinIndex[2]; k<mMaxIndex[2]; k++) {
- for (int i=mMinIndex[0]; i<mMaxIndex[0]; i++) {
- // debug yzx order */
-
- int ks = mMinIndex[2];
- int ke = mMaxIndex[2];
- if (gDim==2) { ks = gPatchSize/2; ke = ks+1; }
- for (int k=ks; k<ke; k++) {
- for (int j=mMinIndex[1]; j<mMaxIndex[1]; j++) {
- for (int i=mMinIndex[0]; i<mMaxIndex[0]; i++) {
- // normal zyx order */
- out << getGlobal(i,j,k);
- out <<" ";
- }
- if (format) out << std::endl;
- }
- if (format) out << std::endl;
- }
-
- return out.str();
-}
-// print only in indicated region
-template<class Scalar>
-std::string Grid<Scalar>::printWithRoi(int *roi)
-{
- std::ostringstream out;
- int ks = mMinIndex[2];
- int ke = mMaxIndex[2];
- if (gDim==2) { ks = gPatchSize/2; ke = ks+1; }
-
- if(0) debMsg("printWithRoi",this->getName()<<" size "<<this->getSize() <<" roi: "<<
- roi[0]<<"-"<< roi[1]<<", "<<
- roi[2]<<"-"<< roi[3]<<", "<<
- roi[4]<<"-"<< roi[5]<<" " );
-
- for (int k=ks; k<ke; k++) {
- if (roi[4]>=0 && roi[4]>k) continue;
- if (roi[5]>=0 && roi[5]<k) continue;
- for (int j=mMinIndex[1]; j<mMaxIndex[1]; j++) {
- if (roi[2]>=0 && roi[2]>j) continue;
- if (roi[3]>=0 && roi[3]<j) continue;
- for (int i=mMinIndex[0]; i<mMaxIndex[0]; i++) {
- if (roi[0]>=0 && roi[0]>i) continue;
- if (roi[1]>=0 && roi[1]<i) continue;
- // normal zyx order */
- out << getGlobal(i,j,k);
- out <<" ";
- }
- out << std::endl;
- }
- out << std::endl;
- }
- return out.str();
-}
-
-template<class Scalar>
-inline Scalar Grid<Scalar>::getInterpolated(Real x, Real y, Real z)
-{
- int xi = (int)x;
- int yi = (int)y;
- int zi = (int)z;
- Real s1 = x-(Real)xi, s0 = 1.-s1;
- Real t1 = y-(Real)yi, t0 = 1.-t1;
- Real f1 = z-(Real)zi, f0 = 1.-f1;
-
- // clamp to border
- if (x < 0) { xi = 0; s0 = 1.0; s1 = 0.0; }
- if (y < 0) { yi = 0; t0 = 1.0; t1 = 0.0; }
- if (z < 0) { zi = 0; f0 = 1.0; f1 = 0.0; }
- if (xi >= mSizeX-1) { xi = mSizeX-2; s0 = 0.0; s1 = 1.0; }
- if (yi >= mSizeY-1) { yi = mSizeY-2; t0 = 0.0; t1 = 1.0; }
- if (zi >= mSizeZ-1) { zi = mSizeZ-2; f0 = 0.0; f1 = 1.0; }
-
- Scalar ret;
-
-#define VAL getGlobal
-#if DDF_DIMENSION==3
- ret = (
- (VAL(xi ,yi,zi)*t0 + VAL(xi ,yi+1,zi)*t1 )*s0 +
- (VAL(xi+1,yi,zi)*t0 + VAL(xi+1,yi+1,zi)*t1 )*s1 )*f0
- + (
- (VAL(xi ,yi,zi+1)*t0 + VAL(xi ,yi+1,zi+1)*t1 )*s0 +
- (VAL(xi+1,yi,zi+1)*t0 + VAL(xi+1,yi+1,zi+1)*t1 )*s1 )*f1 ;
-#else
- ret = (VAL(xi ,yi,zi)*t0 + VAL(xi ,yi+1,zi)*t1 )*s0
- + (VAL(xi+1,yi,zi)*t0 + VAL(xi+1,yi+1,zi)*t1 )*s1 ;
-#endif // DDF_DIMENSION==3
-#undef VAL
-
- return ret;
-}
-
-
-//*****************************************************************************
-//*****************************************************************************
-//*****************************************************************************
-
-
-
-// type to precompute indices
-typedef unsigned int GaccIndex;
-
-
-// access modes
-enum GaAccModes {
- AM_NONE=0,
- AM_READ=1,
- AM_READWRITE=2,
- AM_WRITE=3 };
-
-// interface for simplified locking
-// read/write access and regions are checked during debug
-// compilation with DDF_DEBUG = 1
-class GridAccessorBase {
- public:
- // cons/des
- GridAccessorBase(int accmode) {
- mAccMode = accmode;
- };
- virtual ~GridAccessorBase() { };
-
- virtual void lockRegion(nVec3i s, nVec3i e, int passid) {
- debMsg("GridAccessorBase","Invalid lockRegion called...");
- passid = 0;
- }
- virtual void unlockRegion(int passid) {
- debMsg("GridAccessorBase","Invalid unlockRegion called...");
- passid = 0;
- }
-
- protected:
- //! mode, should be consistent! 0=none, 1=read, 2=read&write, 3=write only
- int mAccMode;
-};
-
-
-// grid accessor class, handles locking and accessing patches
-template<class Scalar, int BOUNDARY>
-class GridAccessor : public GridAccessorBase {
- public:
- // cons/des
- GridAccessor() : GridAccessorBase(AM_NONE),
- mSrc(NULL), mRegionStart(0), mRegionEnd(0)
- { };
-
- virtual ~GridAccessor() { };
-
- // init access to grid, and add accessor to grid-acc call list (for looping)
- void gridAccInit(Grid<Scalar> *grid, GaAccModes acc, GaCallContainer &gacalls);
- //! write access
- Scalar& write(int x,int y, int z);
- //! init write access to region from src grid (no boundaries!)
- virtual void lockRegion(nVec3i s, nVec3i e, int passid);
- //! unlock
- virtual void unlockRegion(int passid);
- //! read access (constant!)
- inline const Scalar& operator() (int x,int y, int z) const;
-
- inline Scalar getInterpolated(Real x, Real y, Real z) const;
-
- //! read access with precomputed index
- inline const Scalar& operator() (GaccIndex index) const;
- //! compute grid acc index
- inline GaccIndex getGaccIndex(int x,int y, int z);
- //! get access to the source grid (mostly for debug checks, e.g. index ranges)
- inline Grid<Scalar>* getGaSourceGrid() { return mSrc; }
-
- protected:
-
- std::string toString() const;
-
- //! source grid for access
- Grid<Scalar>* mSrc;
- // locked region
- nVec3i mRegionStart, mRegionEnd;
-};
-
-
-class GaCallContainer {
- public:
- // ctor, dtor
- GaCallContainer() : threadId(-1), calls() { };
- virtual ~GaCallContainer() { };
-
- int threadId;
- std::vector<DDF::GridAccessorBase*> calls;
-};
-
-
-
-
-
-
-// init access to grid, and add accessor to grid-acc call list (for looping)
-template<class Scalar, int BOUNDARY>
-void
-GridAccessor<Scalar,BOUNDARY>::gridAccInit(Grid<Scalar> *grid, GaAccModes acc, GaCallContainer &gacalls)
-{
- if (!grid) {
- errFatal("GridAccessor::gridAccInit","Invalid source null grid!",SIMWORLD_GRIDERROR);
- return;
- }
- mSrc = grid;
- mAccMode = acc;
-
- // debug, check for double entries
- if (DDF_DEBUG==1) {
- for (size_t i=0; i<gacalls.calls.size(); i++) {
- if (gacalls.calls[i] == this) {
- errFatal("GridAccessor::gridAccInit","Debug check - double gacall entry!",SIMWORLD_GRIDERROR);
- return;
- }
- }
- } // debug
-
- gacalls.calls.push_back(this);
-};
-
-//! write access
-template<class Scalar, int BOUNDARY>
-Scalar&
-GridAccessor<Scalar,BOUNDARY>::write(int x,int y, int z) {
-
- if (gStrictGridDebug) {
- if (!mSrc->checkIndexValid(x,y,z) ) {
- errFatal("GridAccessor::write","Acess to "<<PRINT_VEC(x,y,z)<<", out of bounds for grid "<<mSrc->getGridId()<<"!", SIMWORLD_GRIDERROR);
- }
-
- if (!mSrc->checkIndexInBounds(x,y,z, mRegionStart, mRegionEnd) ) {
- errFatal("GridAccessor::write","Acess to "<<PRINT_VEC(x,y,z)<<", out of locked region "<<
- mRegionStart<<" to "<<mRegionEnd<<" for grid "<<mSrc->getGridId()<<"!", SIMWORLD_GRIDERROR);
- }
-
- if((mAccMode!=AM_WRITE) && (mAccMode!=AM_READWRITE)) {
- errFatal("GridAccessor::write","Acess to "<<PRINT_VEC(x,y,z)<<", region of grid "<<mSrc->getGridId()<<" not locked for writing!", SIMWORLD_GRIDERROR);
- }
- }
-
- //return (*mSrc)(mOffset[0]+x, mOffset[1]+y, mOffset[2]+z);
- return (*mSrc)(x, y, z);
-}
-
-//! init write access to region from src grid (no boundaries!)
-template<class Scalar, int BOUNDARY>
-void GridAccessor<Scalar,BOUNDARY>::lockRegion(nVec3i s, nVec3i e, int passid) {
- //debMsg("GridAccessor","lockRegion #"<<tpatch->mPatchId<<", acc Mode="<<mAcc Mode<<" srcId"<<mSrc->getGridId() );
-
- mRegionStart = s;
- mRegionEnd = e;
-}
-
-//! unlock
-template<class Scalar, int BOUNDARY>
-void GridAccessor<Scalar,BOUNDARY>::unlockRegion(int passid) {
- // nothing to do now...
-}
-
-//! read access (constant!)
-template<class Scalar, int BOUNDARY>
-const Scalar&
-GridAccessor<Scalar,BOUNDARY>:: operator() (int x,int y, int z) const {
- return (*mSrc)(x, y, z);
-}
-
-
-//! read access with gacc index
-template<class Scalar, int BOUNDARY>
-const Scalar&
-GridAccessor<Scalar,BOUNDARY>:: operator() (GaccIndex index) const {
- return (*mSrc)(index);
-}
-template<class Scalar, int BOUNDARY>
-Scalar GridAccessor<Scalar,BOUNDARY>::getInterpolated(Real x, Real y, Real z) const
-{
- return mSrc->getInterpolated(x,y,z);
-}
-
- //const Scalar& operator() (GaccIndex index) const;
-//! compute grid acc index
-template<class Scalar, int BOUNDARY> GaccIndex
-GridAccessor<Scalar,BOUNDARY>::getGaccIndex(int x,int y, int z) {
- return (( (z) *mSrc->getSizeY()+ (y) ) *mSrc->getSizeX()+ (x) );
-}
-
-template<class Scalar, int BOUNDARY>
-std::string
-GridAccessor<Scalar,BOUNDARY>::toString() const {
- std::ostringstream out;
- out <<"accessor: "<<sizeof(Scalar)<<" region="<<mRegionStart<<" to "<<mRegionEnd<<" ";
- // grid info?
-
- return out.str();
-}
-
-
-
-//*****************************************************************************
-//*****************************************************************************
-//*****************************************************************************
-
-//typedef Grid<int> FlagGrid;
-#define FlagGrid Grid<int>
-
-//! obstacle flag types
-typedef enum FluidSolverFlagsT {
- FNONE=0,
- FFLUID=1,
- FOBSTACLE=2,
- FEMPTY=4,
- FINFLOW=8,
- FOUTFLOW=16,
- FPARTICLESOURCE=512,
- FDENSITYSOURCE=1024,
- F_TO_FLUID=(1<<16), // bit flag for changing types
- F_RESEED=(1<<17), // reseed particles here
- FINVALID=-1
-} FluidSolverFlags;
-
-// analogous to IS_OBS, IS_FLUID
-inline bool fgIsObstacle(int flag) {
- return ((flag & FOBSTACLE)!=0);
-}
-inline bool fgIsFluid(int flag) {
- return ((flag & FFLUID)!=0);
-}
-inline bool fgIsEmpty(int flag) {
- return ((flag & FEMPTY)!=0);
-}
-inline bool fgIsInflow(int flag) {
- return ((flag & FINFLOW)!=0);
-}
-inline bool fgIsOutflow(int flag) {
- return ((flag & FOUTFLOW)!=0);
-}
-
-}; // namespace DDF
-
-#include "operators.h"
-#endif // DDF_GRIDS_H
-
diff --git a/intern/smoke/intern/source/guihelpers.cpp b/intern/smoke/intern/source/guihelpers.cpp
deleted file mode 100644
index 058afb2deba..00000000000
--- a/intern/smoke/intern/source/guihelpers.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Helper function for the GUI
- *
- *****************************************************************************/
-
-#include "globals.h"
-#include "vectorbase.h"
-#include "solverparams.h"
-#include "paramset.h"
-
-#include "fluidsolver.h"
-
-extern std::string gPhiRefName;
-extern std::string gShowVelgridName;
-extern std::string gShowRealgridName;
-
-// solver object from main
-extern DDF::FluidSolver *gpGlutFsolver;
-
-// from parser.cpp
-extern std::map<std::string, DDF::FluidSolver*> gFluidSolvers;
-
-// values from gui
-extern std::map<std::string,float> gScaleRealDisplay;
-
-namespace DDF {
-
-extern Real gRealgridMin, gRealgridmMax;
-extern Vec3 gVecgridMin, gVecgridMax;
-
-#if DDF_GLUTGUI==1
-
-/******************************************************************************/
-// switch solvers & grids
-
-
-template<class Scalar>
-void glutgSelectNextGrid(std::map<std::string, Grid<Scalar>*> &gridMap, std::string &gname) {
- bool debSwitch = false;
- SolverParams* prms = gpGlutFsolver->getParams();
- Grid<Scalar> *retgrid = NULL;
-
- // clean up list, might contain entries with NULL pointers...
- if(1) {
- typename std::map<std::string, Grid<Scalar>*>::iterator iter = gridMap.begin();
- for ( ; iter!= gridMap.end(); iter++) {
- if(!(*iter).second) {
- gridMap.erase(iter);
- iter--;
- continue;
- }
- if (debSwitch) debMsg("deb disp","'"<<(*iter).second->getName()<<"' ");
- }
-
- // sanity check, swap messes up names?
- iter = gridMap.begin();
- for ( ; iter!= gridMap.end(); iter++) {
- string name = (*iter).second->getName();
- prms->getGridType(name, retgrid);
- //debMsg("glutGui","Scalar-grid '"<<retgrid->getName()<<"', '"<<name<<"' selected for display");
-
- if(retgrid->getName().length() != name.length() ) {
- errFatal("glutgSelectNextGrid","Invalid grid names!? "<<retgrid->getName()<<" vs. "<<name, SIMWORLD_GENERICERROR );
- }
- retgrid = NULL;
- }
- }
-
- typename std::map<std::string, Grid<Scalar>*>::iterator iter = gridMap.begin();
- if (!(gname.length()>0)) {
- // select first
- if (debSwitch) debMsg("glutgSelectNextGrid","Not inited, getting first");
-
- while((*iter).second->getDisplayFlags() & 1) {
- if (debSwitch) debMsg("glutgSelectNextGrid","1 Skipping "<<" "<<(*iter).second->getName() );
- iter++;
- if (iter == gridMap.end()) { iter = gridMap.begin(); }
- }
-
- } else {
- // iterate through map
- //typename std::map<std::string, Grid<Scalar>*>::iterator iter = gridMap.begin();
- int cnt=0;
- for (; iter!= gridMap.end(); iter++) {
- if (debSwitch) debMsg("glutgSelectNextGrid","Searching "<<(*iter).second->getName() );
- if(gname == (*iter).second->getName()) break;
- cnt++;
- }
- if (iter==gridMap.end()) {
- if (debSwitch) debMsg("glutgSelectNextGrid","Not found, getting first "<<cnt);
- iter = gridMap.begin();
- } else {
- if (debSwitch) debMsg("glutgSelectNextGrid","Found, getting next "<<cnt<<" "<<(*iter).second->getName() );
- iter++;
-
- if (iter==gridMap.end()) {
- if (debSwitch) debMsg("glutgSelectNextGrid","Last, getting first "<<cnt );
- iter = gridMap.begin();
- }
- }
-
- // skip hidden grids... (getDisplayFlags&1)
- while((*iter).second->getDisplayFlags() & 1) {
- if (debSwitch) debMsg("glutgSelectNextGrid","Skipping "<<" "<<(*iter).second->getName() );
-
- iter++;
- if (iter == gridMap.end()) { iter = gridMap.begin(); }
-
- if (debSwitch) debMsg("glutgSelectNextGrid","Now "<<" "<<(*iter).second->getName() );
- }
- }
-
- gname = (*iter).second->getName();
- prms->getGridType(gname, retgrid);
-
- debMsg("glutGui","Scalar-grid '"<<retgrid->getName()<<"', '"<<gname<<"' selected for display");
-}
-
-void glutgSelectNextFloatArray() {
- SolverParams* prms = gpGlutFsolver->getParams();
- glutgSelectNextGrid<Real>( prms->mGridsReal, gShowRealgridName );
-}
-
-// init display, called eg after glutgSelectNextFloatArray
-void initFloatArrayDisplay() {
- // new grid? set standard scale
- if( gScaleRealDisplay[gShowRealgridName] <= 0. ) gScaleRealDisplay[gShowRealgridName] = 1.;
-
- // show min/max values for selected grid
- if(1) {
- Grid<Real> *realGrid = NULL;
- realGrid = gpGlutFsolver->getParams()->getGridReal(gShowRealgridName); // DEBrealGrid
- goFindMinMax<Real> gomm = goFindMinMax<Real>( gpGlutFsolver->getGridFlags(), realGrid );
-
- gRealgridMin = gomm.mMinVal;
- gRealgridmMax = gomm.mMaxVal;
- debMsg("MINMAX-REAL","min="<<gRealgridMin<<" at "<<gomm.mMinPos<<" max="<<gRealgridmMax<<" at "<<gomm.mMaxPos);
- }
-}
-
-void glutgSelectNextVec3Array() {
- SolverParams* prms = gpGlutFsolver->getParams();
- glutgSelectNextGrid<Vec3>( prms->mGridsVec3, gShowVelgridName );
-}
-
-void glutgSelectNextFloatArrayO() {
- //if (gFluidSolvers.find(solverName) != gFluidSolvers.end() ) { gpGlutFsolver = gFluidSolvers[solverName]; }
- bool debSwitch = false;
- SolverParams* prms = gpGlutFsolver->getParams();
- Grid<Real> *grid = NULL;
-
- // clean up list, might contain entries with NULL pointers...
- for ( std::map<std::string, Grid<Real>*>::iterator iter = prms->mGridsReal.begin(); iter!= prms->mGridsReal.end(); iter++) {
- if(!(*iter).second) {
- prms->mGridsReal.erase(iter);
- iter--;
- continue;
- }
- //if (debSwitch) debMsg("deb disp","'"<<(*iter).second->getName()<<"' ");
- }
-
- if (!(gShowRealgridName.length()>0)) {
- // select first
- if (debSwitch) debMsg("glutgSelectNextFloatArray","Not inited, getting first");
- gShowRealgridName = (*prms->mGridsReal.begin()).second->getName();
- grid = prms->getGridReal(gShowRealgridName);
-
- } else {
- // iterate through map
- std::map<std::string, Grid<Real>*>::iterator iter = prms->mGridsReal.begin();
- int cnt=0;
- for (; iter!= prms->mGridsReal.end(); iter++) {
- if (debSwitch) debMsg("glutgSelectNextFloatArray","Searching "<<(*iter).second->getName() );
- if(gShowRealgridName == (*iter).second->getName()) break;
- cnt++;
- }
- if (iter==prms->mGridsReal.end()) {
- if (debSwitch) debMsg("glutgSelectNextFloatArray","Not found, getting first "<<cnt);
- iter = prms->mGridsReal.begin();
- } else {
- if (debSwitch) debMsg("glutgSelectNextFloatArray","Found, getting next "<<cnt<<" "<<(*iter).second->getName() );
- iter++;
-
- if (iter==prms->mGridsReal.end()) {
- if (debSwitch) debMsg("glutgSelectNextFloatArray","Last, getting first "<<cnt );
- iter = prms->mGridsReal.begin();
- //return;
- }
- }
-
- gShowRealgridName = (*iter).second->getName();
- grid = prms->getGridReal(gShowRealgridName);
- }
-
- debMsg("glutGui","Real-grid '"<<grid->getName()<<"' selected for display");
-}
-
-void glutgSelectNextSolver() {
- //if (gFluidSolvers.find(solverName) != gFluidSolvers.end() ) { gpGlutFsolver = gFluidSolvers[solverName]; }
- bool debSwitch = false;
-
- if (!gpGlutFsolver) {
- if (debSwitch) debMsg("glutgSelectNextSolver","Not inited, getting first");
- gpGlutFsolver = (*gFluidSolvers.begin()).second;
- return;
- } else {
-
- std::map<std::string, DDF::FluidSolver*>::iterator iter = gFluidSolvers.begin();
- int cnt=0;
- for (; iter!= gFluidSolvers.end(); iter++) {
- //debMsg("---"," = "<<(long int)(gpGlutFsolver)<<" c "<<cnt<<","<< (long int)((*iter).second) );
- if (gpGlutFsolver == (*iter).second) break;
- cnt++;
- }
- if (iter==gFluidSolvers.end()) {
- if (debSwitch) debMsg("glutgSelectNextSolver","Not found, getting first "<<cnt);
- gpGlutFsolver = (*gFluidSolvers.begin()).second;
- } else {
- iter++;
- if (iter==gFluidSolvers.end()) {
- if (debSwitch) debMsg("glutgSelectNextSolver","Last, getting first "<<cnt);
- gpGlutFsolver = (*gFluidSolvers.begin()).second;
- } else {
- if (debSwitch) debMsg("glutgSelectNextSolver","Found, getting next "<<cnt);
- gpGlutFsolver = (*iter).second;
- }
- }
- }
- debMsg("glutGui","Solver '"<<gpGlutFsolver->getName()<<"' selected for display");
-
- SolverParams* prms = gpGlutFsolver->getParams();
- if(!prms->haveGridReal(gShowRealgridName)) {
- glutgSelectNextFloatArray();
- }
- if(!prms->haveGridVec3(gShowVelgridName)) {
- glutgSelectNextVec3Array();
- }
-}
-
-
-#endif // DDF_GLUTGUI==1
-}; // namespace DDF
-
diff --git a/intern/smoke/intern/source/initplugins.cpp b/intern/smoke/intern/source/initplugins.cpp
deleted file mode 100644
index a43bd152771..00000000000
--- a/intern/smoke/intern/source/initplugins.cpp
+++ /dev/null
@@ -1,499 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Plugins to setup fluid grids
- *
- *****************************************************************************/
-
-// lsdebug
-#include "fluidsolver.h"
-#include "solverplugin.h"
-#include "paramset.h"
-
-
-namespace DDF {
-
-//*****************************************************************************
-// simple, set constant value
-
-class sinitSetConstant : public SolverPlugin {
- public:
- sinitSetConstant() : SolverPlugin(),
- mGrid("-unnamed-"), mVal(0.) { };
- ~sinitSetConstant() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("gridname", mGrid );
- mVal = params.FindOneFloat("value", mVal );
- return true;
- };
- virtual bool initPlugin() { return true; };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("sinitSetConstant","step "<<dt);
- Grid<int>* flags = mpPlParams->getGridInt("flags");
-
- // distinguish data types
- if(mpPlParams->haveGridInt(mGrid) && 1) {
- Grid<int>* grid = mpPlParams->getGridInt(mGrid);
- fsSetConstant<int>(flags, grid, (int)mVal);
- } else if(mpPlParams->haveGridReal(mGrid) && 1) {
- Grid<Real>* grid = mpPlParams->getGridReal(mGrid);
- fsSetConstant<Real>(flags, grid, (Real)mVal);
- } else if(mpPlParams->haveGridVec3(mGrid) && 1) {
- Grid<Vec3>* grid = mpPlParams->getGridVec3(mGrid);
- fsSetConstant<Vec3>(flags, grid, Vec3(mVal));
- } else {
- errFatal("sinitSetConstant::performStep","Grid not found "<<mGrid , SIMWORLD_GRIDERROR);
- }
- return true;
- };
-
- protected:
- // grid names to swap
- std::string mGrid;
- // value
- float mVal;
-};
-
-template<class T>
-class fsSetConditional : public GridOpBase {
- public:
- fsSetConditional(FlagGrid *flags, Grid<T> *dst , T target, int flag) :
- GridOpBase(), mpDst(dst), mTargetVal(target), mCFlag(flag) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsSetConditional() { };
- void resetVariables() { };
- void buildCallList() {
- setFlags(mpFlags);
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- };
- // add forces and update empty cells free surface boundaries
- inline void operator() (int i, int j, int k) {
- if ((getFlagAcc()(i,j,k) & mCFlag)==mCFlag)
- gaDst.write(i,j,k) = mTargetVal;
- };
- void reduce(fsSetConditional &op) { };
-
- protected:
- Grid<T> *mpDst;
- GridAccessor<T,0> gaDst;
- T mTargetVal;
- int mCFlag;
-}; // fsSetConditional */
-
-class spluginSetConditional : public SolverPlugin {
- public:
- spluginSetConditional() : SolverPlugin(),
- mGrid("-unnamed-"), mFlag(4), mTargetVec(0.) {
- debMsg("spluginSetConditional","cons");
- };
- ~spluginSetConditional() {
- debMsg("spluginSetConditional","des");
- };
-
- virtual bool parseParams(const ParamSet& params) {
- debMsg("spluginSetConditional","parse");
- mGrid = params.FindOneString("gridname", mGrid);
- mFlags = params.FindOneString("flaggrid", "flags");
- mTargetVec = params.FindOneVector("target-vec", mTargetVec );
- mTargetReal = params.FindOneFloat("target-real", 0. );
- mFlag = params.FindOneInt("flag", mFlag );
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spluginSetConditional","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginSetConditional"," dt="<<dt<<" dest:"<<mGrid );
- FlagGrid* flagg = mpPlParams->getGridInt(mFlags);
-
- if (mpPlParams->haveGridVec3(mGrid)) {
- fsSetConditional<Vec3>(flagg, mpPlParams->getGridVec3(mGrid), mTargetVec, mFlag);
- } else if (mpPlParams->haveGridReal(mGrid)) {
- fsSetConditional<Real>(flagg, mpPlParams->getGridReal(mGrid), mTargetReal, mFlag);
- } else {
- errFatal("spluginSetConditional::performStep","Grid not found "<<mGrid , SIMWORLD_GRIDERROR);
- }
- return true;
- };
-
- protected:
- std::string mGrid,mFlags;
- int mFlag;
- Vec3 mTargetVec;
- Real mTargetReal;
-};
-
-//*****************************************************************************
-// initializes the domain with empty cells and a single cell border (or
-// more depending on mBorder param) of obstacles
-
-class goInitBoxDomain : public GridOpBase {
- public:
- goInitBoxDomain(Grid<int>* dst, int border, int setempty, int flagInside = FEMPTY, int flagOutside = FOBSTACLE, int flagFloor = 0) :
- GridOpBase(), mpFlagMod(dst), mBorder(border), mDoSetEmpty(setempty), mFlagInside(flagInside), mFlagOutside(flagOutside), mFlagFloor(flagFloor) {
- mpFlags = NULL; // unused
- mS = mpFlagMod->getSize()-nVec3i(1,1,1);
- applyOperatorToGridsWithoutFlags(this, mpFlagMod);
- };
-
- ~goInitBoxDomain() { };
- void resetVariables() { };
- void buildCallList() {
- gaFlagMod.gridAccInit(mpFlagMod, AM_WRITE, gaCalls);
- };
-
- // add forces and update empty cells free surface boundaries
- inline void operator() (int i, int j, int k) {
-
-
- gaFlagMod.write(i,j,k);
- if ((i<1+mBorder) || (i>=mS.x-mBorder)
- || (j<1+mBorder) || (j>=mS.y-mBorder)
-# if DDF_DIMENSION==3
- || (k<1+mBorder) || (k>=mS.z-mBorder)
-# endif
- ) {
- gaFlagMod.write(i,j,k) = mFlagOutside;
- } else {
- if(mDoSetEmpty) gaFlagMod.write(i,j,k) = mFlagInside;
- }
- if (j==0 && mFlagFloor > 0) gaFlagMod.write(i,j,k) = mFlagFloor;
- };
- void reduce(goInitBoxDomain &op) { };
-
- protected:
- Grid<int> *mpFlagMod;
- GridAccessor<int,0> gaFlagMod;
- nVec3i mS;
- int mBorder, mDoSetEmpty, mFlagInside, mFlagOutside, mFlagFloor;
-}; // goInitBoxDomain
-
-class sinitBoxDomain : public SolverPlugin {
- public:
- sinitBoxDomain()
- : SolverPlugin(), mGrid("flags"), mBorder(0) , mDoSetEmpty(1)
- { };
- ~sinitBoxDomain() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("gridname", mGrid );
- mBorder = params.FindOneInt("border", mBorder );
- mDoSetEmpty = params.FindOneInt("set-empty", mDoSetEmpty );
- mFlag1 = params.FindOneInt("flag-inside", FEMPTY );
- mFlag2 = params.FindOneInt("flag-border", FOBSTACLE );
- mFloor = params.FindOneInt("flag-floor", 0);
- return true;
- };
- virtual bool initPlugin() { return true; };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("sinitBoxDomain","step "<<dt);
- Grid<int>* grflags = mpPlParams->getGridInt(mGrid);
-
- goInitBoxDomain(grflags, mBorder,mDoSetEmpty,mFlag1,mFlag2,mFloor);
- return true;
- };
-
- protected:
- std::string mGrid;
- int mBorder, mDoSetEmpty, mFlag1, mFlag2, mFloor;
-};
-
-//*****************************************************************************
-// creates a fluid box spanned by lowCorner and highCorner (both specified
-// in range [0,1])
-
-class goSetBoxFluid : public GridOpBase {
- public:
- goSetBoxFluid(Grid<int> *dst, const Vec3& lowCorner, const Vec3& highCorner, int type, bool brd,
- Grid<Vec3>* vel = NULL, Vec3 set = Vec3(0.), Grid<Real>* dist = NULL, Grid<Vec3>* norm = NULL ) :
- GridOpBase(), mpFlagMod(dst), mType(type), mBorder(brd),
- mpVel(vel), mVelSet(set), mpDist(dist), mpNorm(norm) {
- mpFlags = NULL;
- mILen = 1. / dst->getMaxSize();
- mLowCorner = Vec3(lowCorner.x * float(mpFlagMod->getSizeX()), lowCorner.y * float(mpFlagMod->getSizeY()), lowCorner.z * float(mpFlagMod->getSizeZ()));
- mHighCorner = Vec3(highCorner.x * float(mpFlagMod->getSizeX()), highCorner.y * float(mpFlagMod->getSizeY()), highCorner.z * float(mpFlagMod->getSizeZ()));
- for (int i=0;i<3;i++)
- if(mLowCorner[i] > mHighCorner[i]) {
- Real a=mLowCorner[i]; mLowCorner[i]=mHighCorner[i]; mHighCorner[i]=a; }
- applyOperatorToGridsWithoutFlags(this, mpFlagMod);
- };
-
- ~goSetBoxFluid() { };
- void resetVariables() { };
- void buildCallList() {
- gaFlagMod.gridAccInit(mpFlagMod, AM_WRITE, gaCalls);
- if(mpVel) gaVel.gridAccInit(mpVel, AM_WRITE, gaCalls);
- if(mpDist) gaDist.gridAccInit(mpDist, AM_READWRITE, gaCalls);
- if(mpNorm) gaNorm.gridAccInit(mpNorm, AM_READWRITE, gaCalls);
- };
-
- // add forces and update empty cells free surface boundaries
- inline void operator() (int i, int j, int k) {
- if (mBorder && (i==0 || j==0 || k==0 || i==mpFlagMod->getSizeX()-1 || j==mpFlagMod->getSizeY()-1 || k==mpFlagMod->getSizeZ()-1))
- gaFlagMod.write(i,j,k) = FOBSTACLE;
- if (gaFlagMod.write(i,j,k) == FOBSTACLE)
- return;
- if ((i>=mLowCorner.x) && (i<=mHighCorner.x)
- && (j>=mLowCorner.y) && (j<=mHighCorner.y)
-#if DDF_DIMENSION==3
- && (k>=mLowCorner.z) && (k<=mHighCorner.z)
-#endif
- )
- {
- if(mpVel) {
- Vec3 &v = gaVel.write(i,j,k);
- if(gaFlagMod.write(i,j,k) == mType) {
- //v += mVelSet;
- //v *= 0.5; // warning, depends on init order...
- // NT CJW test, dont overwrite!?
- } else {
- v = mVelSet;
- }
- }
-
- if(fgIsObstacle(mType))
- gaFlagMod.write(i,j,k) = mType;
- else
- gaFlagMod.write(i,j,k) |= mType;
- }
- // build distance field
- if (mpDist && mpNorm) {
- int numIn=0;
- Vec3 pos(i,j,k), ref(0.);
- for (int e=0;e<3;e++) {
- if ((pos[e]>=mLowCorner[e]) && (pos[e]<=mHighCorner[e])) {
- ref[e] = pos[e];
- numIn++;
- } else if (pos[e]>mLowCorner[e])
- ref[e] = mHighCorner[e];
- else
- ref[e] = mLowCorner[e];
- }
- Vec3 nrm = pos-ref;
- Real newDist = normalize(nrm)*mILen, oldDist = gaDist(i,j,k);
- if (oldDist == 0 || newDist < oldDist) {
- gaDist.write(i,j,k) = newDist;
- gaNorm.write(i,j,k) = nrm;
- }
- }
-
- };
- void reduce(goSetBoxFluid &op) { };
-
- protected:
- Grid<int> *mpFlagMod;
- GridAccessor<int,0> gaFlagMod;
- Vec3 mLowCorner, mHighCorner;
- int mType;
- bool mBorder;
-
- // optional velocity
- Grid<Vec3> *mpVel;
- GridAccessor<Vec3,0> gaVel;
- Vec3 mVelSet;
- Real mILen;
- Grid<Real> *mpDist;
- Grid<Vec3> *mpNorm;
- GridAccessor<Vec3,0> gaNorm;
- GridAccessor<Real,0> gaDist;
-}; // goSetBoxFluid
-
-//*****************************************************************************
-// creates a fluid ball with given radius at given position (both specified
-// in range [0,1])
-// optionally, also initializes velocity
-
-class goSetBallFluid : public GridOpBase {
- public:
- goSetBallFluid(Grid<int> *dst, const Vec3& center, const Vec3& scale, Real radius, int type, int cyl,
- Grid<Vec3>* vel = NULL, Vec3 set = Vec3(0.), Grid<Real>* dist = NULL, Grid<Vec3>* norm = NULL ) :
- GridOpBase(), mpFlagMod(dst), mpDist(dist), mpNorm(norm), mType(type), mCylinderAxis(cyl),
- mpVel(vel), mVelSet(set) {
- mpFlags = NULL;
- mScale = Vec3(1.) / scale;
- mCenter = Vec3(
- center.x * float(mpFlagMod->getSizeX()),
- center.y * float(mpFlagMod->getSizeY()),
- center.z * float(mpFlagMod->getSizeZ()));
- mRadiusSqr = radius * float(mpFlagMod->getSizeX());
- mRadiusSqr = mRadiusSqr*mRadiusSqr;
- mILen = 1. / (Real)dst->getMaxSize();
- applyOperatorToGridsWithoutFlags(this, mpFlagMod);
- };
-
- ~goSetBallFluid() { };
- void resetVariables() { };
- void buildCallList() {
- gaFlagMod.gridAccInit(mpFlagMod, AM_WRITE, gaCalls);
- if(mpVel) gaVel.gridAccInit(mpVel, AM_WRITE, gaCalls);
- if(mpDist) gaDist.gridAccInit(mpDist, AM_READWRITE, gaCalls);
- if(mpNorm) gaNorm.gridAccInit(mpNorm, AM_READWRITE, gaCalls);
- };
-
- inline void operator() (int i, int j, int k) {
- if (gaFlagMod.write(i,j,k) == FOBSTACLE)
- return;
- //Real d[3];
- Vec3 d;
- d[0] = mCenter.x - i;
- d[1] = mCenter.y - j;
-#if DDF_DIMENSION==2
- //const Real d = dx*dx + dy*dy;
- d[2] = 0.;
-#else
- d[2] = mCenter.z - k;
-#endif
- d *= mScale;
-
- //const Real d = dx*dx + dy*dy + dz*dz;
- if(mCylinderAxis>=0) d[mCylinderAxis] = 0.;
- const Real dist = normNoSqrt(d);
-
- if (dist < mRadiusSqr)
- {
- if(mpVel) {
- Vec3 &v = gaVel.write(i,j,k);
- if(gaFlagMod.write(i,j,k) == mType) {
- //v += mVelSet;
- //v *= 0.5; // warning, depends on init order...
- // NT CJW test, dont overwrite!?
- } else {
- v = mVelSet;
- }
- }
-
- // set flag
- //gaFlagMod.write(i,j,k) = mType;
- if(fgIsObstacle(mType))
- gaFlagMod.write(i,j,k) = mType;
- else
- gaFlagMod.write(i,j,k) |= mType;
-
- } else if (mpDist && mpNorm) {
- Real ds = sqrt(dist);
- Real oldDist = gaDist(i,j,k), newDist = (ds - sqrt(mRadiusSqr)) * mILen;
- if (oldDist==0 || newDist<oldDist) {
- gaDist.write(i,j,k) = newDist;
- gaNorm.write(i,j,k) = -d / ds;
- }
- }
-
- };
- void reduce(goSetBallFluid &op) { };
-
- protected:
- Grid<int> *mpFlagMod;
- Grid<Real> *mpDist;
- Grid<Vec3> *mpNorm;
- GridAccessor<int,0> gaFlagMod;
- GridAccessor<Real,0> gaDist;
- GridAccessor<Vec3,0> gaNorm;
- Vec3 mCenter;
- Vec3 mScale;
- Real mRadiusSqr,mILen;
- int mType, mCylinderAxis;
-
- // optional velocity
- Grid<Vec3> *mpVel;
- GridAccessor<Vec3,0> gaVel;
- Vec3 mVelSet;
-}; // goSetBallFluid
-
-class sinitSphere : public SolverPlugin {
- public:
- sinitSphere() : SolverPlugin() { };
- ~sinitSphere() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("gridname", "flags");
- mCenter = params.FindOneVector("center", Vec3(0.5,0.5,0.5));
- mRadius = params.FindOneFloat("radius", 0.2);
- mType = params.FindOneInt("type", FOBSTACLE);
- mDist = params.FindOneString("dist", "");
- mNorm = params.FindOneString("norm", "");
- return true;
- };
- virtual bool initPlugin() { return true; };
-
- virtual bool performStep(Real dt) {
- debMsg("sinitSphere","step "<<dt);
- Grid<int>* grflags = mpPlParams->getGridInt(mGrid);
- Grid<Real>* dist = mDist.empty() ? NULL : mpPlParams->getGridReal(mDist);
- Grid<Vec3>* norm = mNorm.empty() ? NULL : mpPlParams->getGridVec3(mNorm);
-
- goSetBallFluid(grflags, mCenter, 1., mRadius, mType, -1, NULL, Vec3(0.), dist, norm);
- return true;
- };
- protected:
- std::string mGrid, mDist, mNorm;
- Vec3 mCenter;
- Real mRadius;
- int mType;
-};
-
-class sinitBox : public SolverPlugin {
- public:
- sinitBox() : SolverPlugin() { };
- ~sinitBox() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("gridname", "flags");
- mPos1 = params.FindOneVector("pos1", Vec3(0.));
- mPos2 = params.FindOneVector("pos2", Vec3(0.));
- mType = params.FindOneInt("type", FOBSTACLE);
- mDist = params.FindOneString("dist", "");
- mNorm = params.FindOneString("norm", "");
- return true;
- };
- virtual bool initPlugin() { return true; };
-
- virtual bool performStep(Real dt) {
- debMsg("sinitBox","step "<<dt);
- Grid<int>* grflags = mpPlParams->getGridInt(mGrid);
- Grid<Real>* dist = mDist.empty() ? NULL : mpPlParams->getGridReal(mDist);
- Grid<Vec3>* norm = mNorm.empty() ? NULL : mpPlParams->getGridVec3(mNorm);
-
- goSetBoxFluid(grflags, mPos1, mPos2, mType, false, NULL, Vec3(0.), dist, norm);
- return true;
- };
- protected:
- std::string mGrid, mDist, mNorm;
- Vec3 mPos1, mPos2;
- int mType;
-};
-
-//*****************************************************************************
-
-SolverPlugin* MakeInitPlugin(std::string name) {
-
- if(name.compare( string("set-constant") )==0) {
- return new sinitSetConstant;
- } else if(name.compare( string("set-conditional") )==0) {
- return new spluginSetConditional;
- } else if (name.compare( string("init-box-domain") )==0) {
- return new sinitBoxDomain;
- } else if (name.compare( string("init-sphere") )==0) {
- return new sinitSphere;
- } else if (name.compare( string("init-box") )==0) {
- return new sinitBox;
- }
- return NULL;
-}
-
-}; // DDF
-
diff --git a/intern/smoke/intern/source/operators.h b/intern/smoke/intern/source/operators.h
deleted file mode 100644
index cbccfa80597..00000000000
--- a/intern/smoke/intern/source/operators.h
+++ /dev/null
@@ -1,922 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Basic functions for applying operators to grids
- *
- *****************************************************************************/
-
-#ifndef DDF_OPERATORS_H
-#define DDF_OPERATORS_H
-
-#include "grid.h"
-#if DDF_OPENMP==1
-#include <omp.h>
-#endif // DDF_OPENMP==1
-
-namespace DDF {
-
-// globals, allocated in globals.cpp
-// id's of seperate passes (for debugging)
-extern int gGridPassCounter;
-
-
-
-//*****************************************************************************
-// operators without openmp
-
-template<class Operator, class GridClass>
-void applyOperatorWithBoundSimple(Operator *opOrg, GridClass *grid, int bound)
-{
- int passid = ++gGridPassCounter;
- opOrg->resetVariables();
-
- Operator *op = opOrg;
- op->getGaCalls().clear();
- op->buildCallList();
- //FlagGrid *pFlags = op->getFlags(); // FLAGMOD
- nVec3i s(0,0,0),e(grid->getSize());
-
- for(size_t gi=0; gi<op->getGaCalls().size(); gi++) {
- op->getGaCalls()[gi]->lockRegion(nVec3i(s), nVec3i(e), passid);
- }
-
-#if DDF_DIMENSION==3
- for(int k=0+bound; k<grid->getSizeZ()-bound; k++) {
-#else // DDF_DIMENSION==3
- { const int k=gPatchSize/2;
-#endif // DDF_DIMENSION==3
- for(int j=0+bound; j<grid->getSizeY()-bound; j++)
- for(int i=0+bound; i<grid->getSizeX()-bound; i++) {
- (*op)(i,j,k);
- }
- }
-
- for(size_t gi=0; gi<op->getGaCalls().size(); gi++) {
- op->getGaCalls()[gi]->unlockRegion(passid);
- }
-
-
- // perform operator reduction
- opOrg->reduce(*op);
-
- // DEBUG - check if patch has not the right passid!?
-}
-
-template<class Operator>
-void applyOperatorToGridsSimple(Operator *opOrg)
-{
- applyOperatorWithBoundSimple(opOrg, opOrg->getFlags(), 0);
-}
-
-//*****************************************************************************
-// operators with openmp
-
-template<class Operator, class GridClass>
-void applyOperatorWithBoundToGrid(Operator *opOrg, GridClass *grid, int bound)
-{
- int passid = ++gGridPassCounter;
- opOrg->resetVariables();
-
-# if DDF_OPENMP==1
-# pragma omp parallel default(shared)
- { // omp region
- const int id = omp_get_thread_num();
- const int Nthrds = omp_get_num_threads();
-# else
- { // non omp
- const int id=0; // , Nthrds=1;
-# endif
-
- Operator myop = *opOrg;
- Operator *op = &myop;
-# pragma omp critical (BUILDCALLLIST)
- {
- op->setThreadId(id);
- op->resetVariables();
- op->getGaCalls().clear();
- op->buildCallList();
- }
- //FlagGrid *pFlags = op->getFlags(); // FLAGMOD
-
- int gridsize = grid->getSizeZ();
- // divide up domain along z dir
- // for 2d, parallelize along Y instead
- if(gDim==2) gridsize = grid->getSizeY();
-# if (DDF_OPENMP==1)
-
- const int totalSize = gridsize -2* bound;
- const int kStart = ( id * (totalSize / Nthrds) ) + bound ;
- int kEnd = ( (id+1) * (totalSize / Nthrds) ) + bound;
-
- // make sure the last thread covers everything
- if(id == Nthrds-1) kEnd = gridsize -bound;
-
- // init region for write accesses
- nVec3i s = nVec3i( 0 );
- nVec3i e = nVec3i( grid->getSize() );
- s[2] = kStart;
- e[2] = kEnd;
-
- // fix access in 2D
- if(gDim==2) {
- s[1]= kStart;
- e[1]= kEnd;
-
- s[2]=gPatchSize/2;
- e[2] = s[2]+1;
- }
-
- if(0) debMsg("T","thread "<<id<<"/"<<Nthrds<<" k="<<kStart<<"-"<<kEnd<<" , totS="<<totalSize<<" gridK="<<gridsize<<" bound="<<bound );
-# else
- // constants for single threaded version
- const int kStart = 0 + bound;
- const int kEnd = gridsize - bound;
- nVec3i s = nVec3i( 0 );
- nVec3i e = nVec3i( grid->getSize() );
-# endif
-
- for(size_t gi=0; gi<op->getGaCalls().size(); gi++) {
- op->getGaCalls()[gi]->lockRegion(nVec3i(s), nVec3i(e), passid);
- }
-
- // loop over grid
-# if DDF_DIMENSION==3
- for(int k=kStart; k<kEnd; k++) {
- for(int j=0+bound; j<grid->getSizeY()-bound; j++)
-# else // DDF_DIMENSION==3
- const int k=gPatchSize/2;
- for(int j=kStart; j<kEnd; j++) {
-# endif // DDF_DIMENSION==3
- for(int i=0+bound; i<grid->getSizeX()-bound; i++) {
- (*op)(i,j,k);
- }
- } // parallel loop
-
-
- for(size_t gi=0; gi<op->getGaCalls().size(); gi++) {
- op->getGaCalls()[gi]->unlockRegion(passid);
- }
-
- // perform operator reduction
-# pragma omp critical (REDUCE)
- { opOrg->reduce(myop); }
-
- //debMsg("P","id "<<id<<"/"<<Nthrds<<", pids"<<npids<<" idsum"<<idsum);
- } // omp region
-}
-
-template<class Operator, class GridClass>
-void applyOperatorToGridsWithoutFlags(Operator *opOrg, GridClass *grid)
-{
- applyOperatorWithBoundToGrid(opOrg, grid, 0);
-}
-
-template<class Operator>
-void applyOperatorToGrids(Operator *opOrg)
-{
- applyOperatorWithBoundToGrid(opOrg, opOrg->getFlags(), 0);
-}
-
-
-
-
-
-
-//*****************************************************************************
-// base class for grid operators
-// currently only manages flag access
-class GridOpBase {
- public:
- GridOpBase() :
- mpFlags(NULL), gaFlags(), gaCalls()
- {
- getGaCalls().clear();
- //gGridPassCounter++; debMsg("GridPass","pass="<<gGridPassCounter);
- };
- virtual ~GridOpBase() {};
-
- // init flag grid
- inline void setFlags(FlagGrid *set) {
- mpFlags=set;
- if(mpFlags) {
- gaFlags.gridAccInit(mpFlags, AM_READ, gaCalls);
- } else {
- errFatal("GridOpBase::setFlags","Flags pointer not set!", SIMWORLD_GENERICERROR);
- }
- }
- // some operators dont need a flag pointer, use this function to zero it, setFlags requires a valid one!
- inline void setNullFlagPointer() {
- mpFlags = NULL;
- }
- // virtual, not time ciritcal - important for e.g. reduction, see below
- virtual void resetVariables() { };
-
- // set & get flag grid access
- inline FlagGrid *getFlags() { return mpFlags; }
- inline GridAccessor<int,0>& getFlagAcc() { return gaFlags; }
- inline int getThreadId() { return gaCalls.threadId; }
- inline std::vector<GridAccessorBase*>& getGaCalls() { return gaCalls.calls; }
- inline void setThreadId(int set) { gaCalls.threadId=set; }
-
- // Warning - make sure copying works, e.g., dont build call list
- // before each thread has own operator copy
-
- // Function to be implemented:
- // void resetVariables():
- // - reset fields that are modified during sweep (e.g. dotproduct
- // reset to zeroo)
- // - this can be called multiple times, e.g., for reducing
- // ! crucial for correct multi threading ! , dont modify such
- // fields in constructor or buildCallList
- // void buildCallList():
- // - init grid accessors, add to gaCalls.calls
- // - call setFlags(mpFlags) to init base op
- // void operator() (int i, int j, int k) :
- // - perform actual computation
- // - note, flag handling has to be done in operator
- // (e.g., const int currFlag = getFlagAcc()(i,j,k); )
- // void reduce(Operator &op) :
- // - reduce results from operator "op" to current one
- // - needed for multithreaded operator execution
- // ... getValue() :
- // - return result of computations
-
- protected:
- //! allow access to flag grid
- FlagGrid *mpFlags;
- GridAccessor<int,0> gaFlags;
- GaCallContainer gaCalls;
-}; // GridOpBase
-
-// same as GridOpBase, but allows access to the border of
-// the flag array
-template<int BORDER>
-class GridOpBaseFlagbord {
- public:
- GridOpBaseFlagbord() :
- mpFlags(NULL), gaFlags(), gaCalls()
- {
- getGaCalls().clear();
- };
- virtual ~GridOpBaseFlagbord() {};
-
- // init flag grid
- inline void setFlags(FlagGrid *set) {
- mpFlags=set;
- if(mpFlags) {
- gaFlags.gridAccInit(mpFlags, AM_READ, gaCalls);
- }
- }
- // virtual, not time ciritcal - important for e.g. reduction, see below
- virtual void resetVariables() { };
-
- // set & get flag grid access
- inline FlagGrid *getFlags() { return mpFlags; }
- inline GridAccessor<int, BORDER>& getFlagAcc() { return gaFlags; }
- inline int getThreadId() { return gaCalls.threadId; }
- inline std::vector<GridAccessorBase*>& getGaCalls() { return gaCalls.calls; }
- inline void setThreadId(int set) { gaCalls.threadId=set; }
-
- protected:
- //! allow access to flag grid
- FlagGrid *mpFlags;
- GridAccessor<int, BORDER> gaFlags;
- GaCallContainer gaCalls;
-}; // GridOpBaseFlagbord
-
-
-
-//*****************************************************************************
-// test operator, does nothing
-class GridOpDummy : public GridOpBase {
- public:
- GridOpDummy(FlagGrid *flags) : GridOpBase() {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~GridOpDummy() { };
- void buildCallList() {
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
-#if DDF_DEBUG==1
- i=j=k= 0;
-#endif
- };
- void reduce(GridOpDummy &op) { };
-}; // GridOpDummy */
-
-
-
-//*****************************************************************************
-// touch operator, resets memory in threaded fashion
-template<class Scalar>
-class GridOpTouchMemory : public GridOpBase {
- public:
- GridOpTouchMemory(FlagGrid *flags, Grid<Scalar> *gDst, Scalar val) : GridOpBase() {
- mValue = val;
- mpDst = gDst;
- flags = NULL;
- // TODO remove mpFlags = flags;
- applyOperatorToGridsWithoutFlags(this, mpDst);
- };
- ~GridOpTouchMemory() { };
- void resetVariables() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- setNullFlagPointer();
- };
- inline void operator() (int i, int j, int k) {
- //debMsg("a","b "<<PRINT_IJK<<" = "<<mValue<<", "<<mpDst->getSize() );
- gaDst.write(i,j,k) = mValue;
- };
- void reduce(GridOpTouchMemory &op) { };
- protected:
- Grid<Scalar> *mpDst;
- GridAccessor<Scalar,0> gaDst;
- Scalar mValue;
-}; // GridOpTouchMemory */
-
-
-//*****************************************************************************
-// copy whole grid
-template<class SCALAR>
-class goCopyGrid : public GridOpBase {
- public:
- goCopyGrid(Grid<SCALAR> *gDst, Grid<SCALAR> *gSrc) : GridOpBase() {
- mpDst = gDst;
- mpSrc = gSrc;
- const bool useMemcpy = true;
-
- // sanity check
- if(mpSrc->getNumElements() != mpDst->getNumElements() ) {
- errFatal("goCopyGrid","Invalid grid sizes! "<< mpSrc->getNumElements() <<" vs "<< mpDst->getNumElements(), SIMWORLD_GRIDERROR );
- }
-
- if(useMemcpy) {
- // direct copy
- memcpy( &mpDst->getGlobal(0,0,0) , &mpSrc->getGlobal(0,0,0), mpDst->getNumElements() * sizeof(SCALAR) );
- } else {
- // parallel transfer
- applyOperatorToGridsWithoutFlags(this, mpDst);
- }
- };
- ~goCopyGrid() { };
- void resetVariables() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaSrc.gridAccInit(mpSrc, AM_READ, gaCalls);
- setNullFlagPointer();
- };
- inline void operator() (int i, int j, int k) {
- gaDst.write(i,j,k) = gaSrc(i,j,k);
- };
- void reduce(goCopyGrid &op) { };
- protected:
- Grid<SCALAR> *mpDst;
- Grid<SCALAR> *mpSrc;
- GridAccessor<SCALAR,0> gaDst;
- GridAccessor<SCALAR,0> gaSrc;
-}; // goCopyGrid */
-
-// copy one element of a vector to a scalar grid
-template<class Scalar,int NUM>
-class goCopyVec3ToScalar : public GridOpBase {
- public:
- goCopyVec3ToScalar(Grid<Scalar> *gDst, Grid<Vec3> *gSrc) : GridOpBase() {
- mpDst = gDst;
- mpSrc = gSrc;
- applyOperatorToGridsWithoutFlags(this, mpDst);
- };
- ~goCopyVec3ToScalar() { };
- void resetVariables() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaSrc.gridAccInit(mpSrc, AM_READ, gaCalls);
- setNullFlagPointer();
- };
- inline void operator() (int i, int j, int k) {
- Real spass=gaSrc(i,j,k)[NUM];
- gaDst.write(i,j,k) = gaSrc(i,j,k)[NUM];
- };
- void reduce(goCopyVec3ToScalar &op) { };
- protected:
- Grid<Scalar> *mpDst;
- Grid<Vec3> *mpSrc;
- GridAccessor<Scalar,0> gaDst;
- GridAccessor<Vec3,0> gaSrc;
-}; // goCopyVec3ToScalar */
-
-// copy one element of a vector from a scalar grid
-template<class Scalar,int NUM>
-class goCopyScalarToVec3 : public GridOpBase {
- public:
- goCopyScalarToVec3(Grid<Vec3> *gDst, Grid<Scalar> *gSrc) : GridOpBase() {
- mpDst = gDst;
- mpSrc = gSrc;
- applyOperatorToGridsWithoutFlags(this, mpDst);
- };
- ~goCopyScalarToVec3() { };
- void resetVariables() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaSrc.gridAccInit(mpSrc, AM_READ, gaCalls);
- setNullFlagPointer();
- };
- inline void operator() (int i, int j, int k) {
- gaDst.write(i,j,k)[NUM] = gaSrc(i,j,k);
- };
- void reduce(goCopyScalarToVec3 &op) { };
- protected:
- Grid<Vec3> *mpDst;
- Grid<Scalar> *mpSrc;
- GridAccessor<Vec3,0> gaDst;
- GridAccessor<Scalar,0> gaSrc;
-}; // goCopyScalarToVec3 */
-
-
-
-#if DDF_DIMENSION==3
-#define LAPLACEFAC 6.
-#else // DDF_DIMENSION==3
-#define LAPLACEFAC 4.
-#endif // DDF_DIMENSION==3
-
-
-//*****************************************************************************
-// compute norm (without sqrt) of a vector
-class GridOpNormNosqrt : public GridOpBase{
- public:
- GridOpNormNosqrt(Grid<Real> *Var, FlagGrid *Flags, Real *result = NULL) : GridOpBase() {
- mpVar = Var;
- mpFlags = Flags;
- applyOperatorToGrids( this );
- if(result) *result = mNorm;
- };
- ~GridOpNormNosqrt() {};
- virtual void resetVariables() {
- mNorm = 0.;
- //outcnt=0;
- }
- void buildCallList() {
- gaVar.gridAccInit(mpVar, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- const Real s = gaVar(i,j,k);
- mNorm += s*s;
- //debMsg("GridOpNormNosqrt","at "<<PRINT_IJK<<" = "<< mNorm );
- //if(outcnt%1000==0) std::cout<<" "<<mNorm;
- //outcnt++;
- }
-
- void reduce(GridOpNormNosqrt &op) {
- //debMsg("GridOpNormNosqrt","reduce mNorm"<<mNorm<<" += "<<op.mNorm);
- mNorm += op.mNorm;
- }
-
- Real getValue() { return mNorm; }
- protected:
- //int outcnt;
- Real mNorm;
- Grid<Real> *mpVar;
- GridAccessor<Real,0> gaVar;
-}; // GridOpNormNosqrt
-
-
-
-//*****************************************************************************
-// compute min and max values in grid 1 (better use goCompMinMax below...)
-static inline Real _helperMinMaxNorm( Real r ) {
- return r;
-};
-static inline Real _helperMinMaxNorm( Vec3 r ) {
- return normNoSqrt(r);
-};
-template<class Scalar>
-class goFindMinMax : public GridOpBase{
- public:
- goFindMinMax(FlagGrid *flags, Grid<Scalar> *grid) : GridOpBase() {
- mpVar = grid;
- mpFlags = flags;
- resetVariables();
- if(flags) {
- // use flags, if supplied to skip obstacle cells
- applyOperatorToGrids( this );
- } else {
- applyOperatorToGridsWithoutFlags(this, grid);
- }
- };
- ~goFindMinMax() {};
- virtual void resetVariables() {
- //outcnt=0; mNorm = 0.;
- mMinLen = 0.5*FP_REAL_MAX;
- mMaxLen = -0.5*FP_REAL_MAX;
- mMinVal = 0.;
- mMaxVal = 0.;
- mMinPos = mMaxPos = 0;
- mInitedMin = mInitedMax =
- mFirstInitRed = false;
- }
- void buildCallList() {
- gaVar.gridAccInit(mpVar, AM_READ, gaCalls);
- if(!mpFlags) setNullFlagPointer();
- else setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- const Scalar s = gaVar(i,j,k);
- const Real slen = _helperMinMaxNorm( s );
- if((!mpFlags) || (!fgIsObstacle(getFlagAcc()(i,j,k)) )) {
- // also max not for obs!?
- if((!mInitedMax) || (mMaxLen<slen)) {
- mMaxVal = s;
- mMaxLen = slen;
- mMaxPos = nVec3i(i,j,k);
- mInitedMax = true;
- }
- // minima only in fluid region
- if((!mInitedMin) || (mMinLen>slen)) {
- mMinVal = s;
- mMinLen = slen;
- mMinPos = nVec3i(i,j,k);
- mInitedMin = true;
- }
- }
- //outcnt++;
- //debMsg("goFindMinMax","at "<<PRINT_IJK<<" = "<< s <<","<<off << " min="<<mMinVal<<" at "<<mMinPos<<" max="<<mMaxVal<<" at "<<mMaxPos);
- }
-
- void reduce(goFindMinMax &op) {
- // used for reducing with opOrg
- if(!mFirstInitRed) {
- mMaxVal = op.mMaxVal;
- mMaxLen = op.mMaxLen;
- mMaxPos = op.mMaxPos;
- mMinVal = op.mMinVal;
- mMinLen = op.mMinLen;
- mMinPos = op.mMinPos;
- mFirstInitRed = true;
- return;
- }
- if(mMaxLen<op.mMaxLen) {
- mMaxVal = op.mMaxVal;
- mMaxLen = op.mMaxLen;
- mMaxPos = op.mMaxPos;
- }
- if(mMinLen>op.mMinLen) {
- mMinVal = op.mMinVal;
- mMinLen = op.mMinLen;
- mMinPos = op.mMinPos;
- }
- }
-
- Real mMinLen;
- Real mMaxLen;
- Scalar mMinVal;
- Scalar mMaxVal;
- nVec3i mMinPos;
- nVec3i mMaxPos;
- protected:
- //int outcnt;
- bool mInitedMin, mInitedMax, mFirstInitRed;
- Grid<Scalar> *mpVar;
- GridAccessor<Scalar,0> gaVar;
-}; // goFindMinMax
-
-
-//*****************************************************************************
-// compute min and max values in grid 2
-template<class Value>
-class goCompMinMax : public GridOpBase{
- public:
- goCompMinMax(Grid<Value> *Var, FlagGrid *Flags) : GridOpBase() {
- mpVar = Var;
- mpFlags = Flags;
- applyOperatorToGrids( this );
- };
- ~goCompMinMax() {};
- virtual void resetVariables() {
- // todo, add debug check for min/max inits!?
- mMinAbs = 1e10;
- mMaxAbs = -1e10;
- mMin = mMax = 0.;
- mMinPos = mMaxPos = 0;
- //outcnt=0;
- }
- void buildCallList() {
- gaVar.gridAccInit(mpVar, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- const Value s = gaVar(i,j,k);
- const Real sabs = normHelper(s);
- //mNorm += s*s;
- if(sabs>mMaxAbs) {
- mMaxAbs = sabs;
- mMax = s;
- mMaxPos = nVec3i(i,j,k);
- }
- if(sabs<mMinAbs) {
- mMinAbs = sabs;
- mMin = s;
- mMinPos = nVec3i(i,j,k);
- }
- }
-
- void reduce(goCompMinMax &op) {
- //debMsg("goCompMinMax","reduce mNorm"<<mNorm<<" += "<<op.mNorm);
- //mNorm += op.mNorm;
- if(op.mMaxAbs>mMaxAbs) {
- mMaxAbs = op.mMaxAbs;
- mMax = op.mMax;
- mMaxPos = op.mMaxPos;
- }
- if(op.mMinAbs<mMinAbs) {
- mMinAbs = op.mMinAbs;
- mMin = op.mMin;
- mMinPos = op.mMinPos;
- }
- }
-
- Value getMinValue() { return mMin; }
- Value getMaxValue() { return mMax; }
- Real getMinAbsValue() { return mMinAbs; }
- Real getMaxAbsValue() { return mMaxAbs; }
- Real getMinPosValue() { return mMinPos; }
- Real getMaxPosValue() { return mMaxPos; }
- string toString() {
- std::ostringstream out;
- out << "min="<<mMin<<" ("<<mMinAbs<<") at "<<mMinPos<<
- " max="<<mMax<<" ("<<mMaxAbs<<") at "<<mMaxPos ;
- return out.str();
- }
- protected:
- //int outcnt;
- Real mMinAbs, mMaxAbs;
- Value mMin, mMax;
- nVec3i mMinPos, mMaxPos;
- Grid<Value> *mpVar;
- GridAccessor<Real,0> gaVar;
-}; // goCompMinMax
-
-//*****************************************************************************
-// subtract the entries of grid 2 from grid 1, store result to destination
-// grid, and sum up the total difference
-template<class Value>
-class GridOpDifference : public GridOpBase{
- public:
- GridOpDifference(Grid<Value>* Dst, Grid<Value>* Var1, Grid<Value>* Var2, FlagGrid *Flags) : GridOpBase() {
- mpDst = Dst;
- mpVar1 = Var1;
- mpVar2 = Var2;
- mpFlags = Flags;
- applyOperatorToGrids( this );
- }
- ~GridOpDifference() {};
- void buildCallList() {
- gaDst.gridAccInit(mpDst, DDF::AM_WRITE, gaCalls);
- gaVar1.gridAccInit(mpVar1, DDF::AM_READ, gaCalls);
- gaVar2.gridAccInit(mpVar2, DDF::AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- Value diff;
- if (gaFlags(i,j,k) != FOBSTACLE)
- diff = gaVar2(i,j,k)-gaVar1(i,j,k);
- else
- diff = 0;
- gaDst.write(i,j,k) = diff;
- mDiffSum += diff;
- }
-
- void reduce(GridOpDifference &op) {
- mDiffSum += op.mDiffSum;
- }
-
- Value getDiffSum(void) { return mDiffSum; }
-
- protected:
- Grid<Value> *mpDst, *mpVar1, *mpVar2;
- GridAccessor<Value,0> gaDst;
- GridAccessor<Value,0> gaVar1;
- GridAccessor<Value,0> gaVar2;
-
- Value mDiffSum;
-}; // GridOpDifference */
-
-//*****************************************************************************
-// sum of two grids
-template<class T>
-class goSum : public GridOpBase{
- public:
- goSum(Grid<T>* dst, Grid<T>* grid1, FlagGrid *flags) : GridOpBase(),
- mpDst(dst), mpVar1(grid1) {
- mpFlags = flags;
- applyOperatorToGrids( this );
- }
- ~goSum() {};
- void buildCallList() {
- gaDst.gridAccInit(mpDst, DDF::AM_READWRITE, gaCalls);
- gaVar1.gridAccInit(mpVar1, DDF::AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- if (gaFlags(i,j,k) != FOBSTACLE)
- gaDst.write(i,j,k) += gaVar1(i,j,k);
- else
- gaDst.write(i,j,k) = 0;
- }
-
- void reduce(goSum &op) {}
-
- protected:
- Grid<T> *mpDst, *mpVar1;
- GridAccessor<T,0> gaDst;
- GridAccessor<T,0> gaVar1;
-}; // goSum
-
-//*****************************************************************************
-// scale a grid
-template<class T>
-class goScale : public GridOpBase{
- public:
- goScale(Grid<T>* dst, FlagGrid *flags, Real s) : GridOpBase(),
- mpDst(dst), mScale(s) {
- mpFlags = flags;
- applyOperatorToGrids( this );
- }
- ~goScale() {};
- void buildCallList() {
- gaDst.gridAccInit(mpDst, DDF::AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- if (gaFlags(i,j,k) != FOBSTACLE)
- gaDst.write(i,j,k) *= mScale;
- }
-
- void reduce(goScale &op) { };
-
- protected:
- Grid<T> *mpDst;
- Real mScale;
- GridAccessor<T,0> gaDst;
-}; // goScale
-
-
-
-//*****************************************************************************
-// multiply entries of both input grids, and store them in destination grid
-class GridOpMultiplyEntries : public GridOpBase{
- public:
- GridOpMultiplyEntries(Grid<Real> *Dst, Grid<Real> *Var1, Grid<Real> *Var2, FlagGrid *Flags) : GridOpBase() {
- mpDst = Dst;
- mpVar1 = Var1;
- mpVar2 = Var2;
- mpFlags = Flags;
- applyOperatorToGrids( this );
- }
- ~GridOpMultiplyEntries() {};
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaVar1.gridAccInit(mpVar1, AM_READ, gaCalls);
- gaVar2.gridAccInit(mpVar2, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- gaDst.write(i,j,k) = gaVar1(i,j,k)*gaVar2(i,j,k);
- }
-
- void reduce(GridOpMultiplyEntries &op) { }
- protected:
- Grid<Real> *mpDst, *mpVar1, *mpVar2;
- GridAccessor<Real,0> gaDst;
- GridAccessor<Real,0> gaVar1;
- GridAccessor<Real,0> gaVar2;
-}; // GridOpMultiplyEntries */
-
-
-//*****************************************************************************
-// compute dot product of two vectors (saved in grid format)
-
-// use current precision (single/double)
-class goDotProdReal : public GridOpBase{
- public:
- goDotProdReal(Grid<Real> *Var1, Grid<Real> *Var2, FlagGrid *Flags, Real *result = NULL) :
- GridOpBase() {
- mpVar1 = Var1;
- mpVar2 = Var2;
- mpFlags = Flags;
- mDot = 0.;
- applyOperatorToGrids( this );
- if(result) *result = mDot;
- }
- ~goDotProdReal() {};
- virtual void resetVariables() {
- mDot = 0.;
- }
- void buildCallList() {
- gaVar1.gridAccInit(mpVar1, AM_READ, gaCalls);
- gaVar2.gridAccInit(mpVar2, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- mDot += gaVar1(i,j,k)*gaVar2(i,j,k);
- }
-
- void reduce(goDotProdReal &op) {
- //debMsg("goDotProdReal","reduce mDot"<<mDot<<" += "<<op.mDot);
- mDot += op.mDot;
- }
- inline Real getValue() { return mDot; }
- protected:
- Real mDot;
- Grid<Real> *mpVar1, *mpVar2;
- GridAccessor<Real,0> gaVar1;
- GridAccessor<Real,0> gaVar2;
-}; // goDotProdReal */
-
-// use enforced double precision (default)
-class goDotProd : public GridOpBase{
- public:
- goDotProd(Grid<Real> *Var1, Grid<Real> *Var2, FlagGrid *Flags, Real *result = NULL) :
- GridOpBase() {
- mpVar1 = Var1;
- mpVar2 = Var2;
- mpFlags = Flags;
- mDot = 0.;
- applyOperatorToGrids( this );
- if(result) *result = mDot;
- }
- ~goDotProd() {};
- virtual void resetVariables() {
- mDot = 0.;
- }
- void buildCallList() {
- gaVar1.gridAccInit(mpVar1, AM_READ, gaCalls);
- gaVar2.gridAccInit(mpVar2, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- mDot += (double)( gaVar1(i,j,k)*gaVar2(i,j,k) );
- }
-
- void reduce(goDotProd &op) {
- //debMsg("goDotProd","reduce mDot"<<mDot<<" += "<<op.mDot);
- mDot += op.mDot;
- }
- inline Real getValue() { return (Real)mDot; }
- protected:
- double mDot;
- Grid<Real> *mpVar1, *mpVar2;
- GridAccessor<Real,0> gaVar1;
- GridAccessor<Real,0> gaVar2;
-}; // goDotProd */
-
-template<class T>
-class fsSetConstant : public GridOpBase {
- public:
- fsSetConstant(FlagGrid *flags, Grid<T> *dst, T value) :
- GridOpBase(), mpDst(dst), mVal(value) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsSetConstant() { };
- void resetVariables() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- // add forces and update empty cells free surface boundaries
- inline void operator() (int i, int j, int k) {
- gaDst.write(i,j,k) = mVal;
- };
- void reduce(fsSetConstant &op) { };
-
- protected:
- Grid<T> *mpDst;
- GridAccessor<T,0> gaDst;
- // value to set
- T mVal;
-}; // fsSetConstant */
-
-
-}; // namespace DDF
-
-#endif // DDF_OPERATORS_H
-
diff --git a/intern/smoke/intern/source/poissonsolvers.cpp b/intern/smoke/intern/source/poissonsolvers.cpp
deleted file mode 100644
index 279675a0a3e..00000000000
--- a/intern/smoke/intern/source/poissonsolvers.cpp
+++ /dev/null
@@ -1,1032 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Plugins for calculating pressure correction and diffusion
- *
- *****************************************************************************/
-
-#include "fluidsolver.h"
-#include "solverplugin.h"
-#include "paramset.h"
-#include "conjugategrad.h"
-
-#include <fstream>
-#include <sstream>
-
-namespace DDF {
-
-
-// *****************************************************************************
-// pressure solve
-// optional modifications:
-// - global volume correction value (set by compute volume plugin, passed over via mpPlParams)
-// - per cell density values (grid), scales RHS values
-// - surface tension values (grid), adds
-class fsPrMakeRhs : public GridOpBaseFlagbord<1> {
- public:
- fsPrMakeRhs(FlagGrid *flags, Grid<Real> *rhs, Grid<Vec3> *vel, Real corr,
- Grid<Real> *dens, Grid<Real> *percell) :
- GridOpBaseFlagbord<1>(), mpRhs(rhs), mpVel(vel), mpPerCellCorrection(percell) ,
- mCorr(corr), mpDensity(dens) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsPrMakeRhs() { };
- void resetVariables() { };
- void buildCallList() {
- gaVel.gridAccInit(mpVel, AM_READ, gaCalls);
- gaRhs.gridAccInit(mpRhs, AM_WRITE, gaCalls);
- if(mpDensity) {
- gaDens.gridAccInit(mpDensity, AM_READ, gaCalls);
- }
- if(mpPerCellCorrection) {
- gaPerCellCorr.gridAccInit(mpPerCellCorrection, AM_READ, gaCalls);
- }
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- if (!fgIsFluid(getFlagAcc()(i,j,k)) ) {
- gaRhs.write(i,j,k) = 0.;
- return;
- }
-
- Real set = 0.;
- set += (gaVel(i,j,k)[0] - gaVel(i+1,j,k)[0]);
- set += (gaVel(i,j,k)[1] - gaVel(i,j+1,k)[1]);
-# if DDF_DIMENSION==3
- set += (gaVel(i,j,k)[2] - gaVel(i,j,k+1)[2]);
-# endif
- gaRhs.write(i,j,k) = set + mCorr;
-
- // multiply RHS by density value, if given...
- if(mpDensity) gaRhs.write(i,j,k) *= gaDens(i,j,k);
- if(mpPerCellCorrection) gaRhs.write(i,j,k) += gaPerCellCorr(i,j,k);
- };
-
- void reduce(fsPrMakeRhs &op) { };
- protected:
- Grid<Real> *mpRhs;
- Grid<Vec3> *mpVel;
- Grid<Real> *mpPerCellCorrection;
- GridAccessor<Real,0> gaRhs;
- GridAccessor<Vec3,1> gaVel;
- GridAccessor<Real,0> gaPerCellCorr;
- Real mCorr;
- // optional density
- Grid<Real> *mpDensity;
- GridAccessor<Real,0> gaDens;
-}; // fsPrMakeRhs */
-
-class fsPrMakeMatrix : public GridOpBaseFlagbord<1> {
- public:
- fsPrMakeMatrix(FlagGrid *flags, Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak) :
- GridOpBaseFlagbord<1>(), mpA0(A0), mpAi(Ai), mpAj(Aj), mpAk(Ak) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsPrMakeMatrix() { };
- void resetVariables() { };
- void buildCallList() {
- gaA0.gridAccInit(mpA0, AM_WRITE, gaCalls);
- gaAi.gridAccInit(mpAi, AM_WRITE, gaCalls);
- gaAj.gridAccInit(mpAj, AM_WRITE, gaCalls);
- gaAk.gridAccInit(mpAk, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- const int currFlag = getFlagAcc()(i,j,k);
- if (!fgIsFluid(currFlag) ) return;
-
- if (!fgIsObstacle(getFlagAcc()(i-1,j,k)) ) gaA0.write(i,j,k) += 1.;
- if (!fgIsObstacle(getFlagAcc()(i+1,j,k)) ) gaA0.write(i,j,k) += 1.;
- if (fgIsFluid(getFlagAcc()(i+1,j,k)) ) gaAi.write(i,j,k) = -1.;
-
- if (!fgIsObstacle(getFlagAcc()(i,j-1,k)) ) gaA0.write(i,j,k) += 1.;
- if (!fgIsObstacle(getFlagAcc()(i,j+1,k)) ) gaA0.write(i,j,k) += 1.;
- if (fgIsFluid(getFlagAcc()(i,j+1,k)) ) gaAj.write(i,j,k) = -1.;
-
-# if DDF_DIMENSION==3
- if (!fgIsObstacle(getFlagAcc()(i,j,k-1)) ) gaA0.write(i,j,k) += 1.;
- if (!fgIsObstacle(getFlagAcc()(i,j,k+1)) ) gaA0.write(i,j,k) += 1.;
- if (fgIsFluid(getFlagAcc()(i,j,k+1)) ) gaAk.write(i,j,k) = -1.;
-# endif
- };
- void reduce(fsPrMakeMatrix &op) { };
- protected:
- Grid<Real> *mpA0, *mpAi, *mpAj, *mpAk;
- GridAccessor<Real,0> gaA0, gaAi, gaAj, gaAk;
-}; // fsPrMakeMatrix */
-
-class fsPrCorrVels : public GridOpBaseFlagbord<1> {
- public:
- fsPrCorrVels(FlagGrid *flags, Grid<Vec3> *vel, Grid<Real> *press, Grid<Real> *dens) :
- GridOpBaseFlagbord<1>(), mpPress(press), mpVel(vel),
- mpDensity(dens) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsPrCorrVels() { };
- void resetVariables() { };
- void buildCallList() {
- gaVel.gridAccInit(mpVel, AM_WRITE, gaCalls);
- gaPress.gridAccInit(mpPress, AM_WRITE, gaCalls);
- if(mpDensity) {
- gaDens.gridAccInit(mpDensity, AM_READ, gaCalls);
- }
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- const int currFlag = getFlagAcc()(i,j,k);
- if (!fgIsFluid(currFlag) ) return;
- //if (fgIsObstacle(currFlag) ) return;
- Real scale = 1.;
- //if(mpDensity) scale = 1. / gaDens(i,j,k);
- Real densCurr = 1.;
- if(mpDensity) densCurr = gaDens(i,j,k);
-
- if (fgIsFluid(getFlagAcc()(i-1,j,k)) ) {
- if(mpDensity) {
- scale = 1. / (0.5* (densCurr + gaDens(i-1,j,k)) );
- }
- gaVel.write(i,j,k)[0] -= scale* (gaPress(i,j,k) - gaPress(i-1,j,k) );
- }
- if (fgIsFluid(getFlagAcc()(i,j-1,k)) ) {
- if(mpDensity) {
- scale = 1. / (0.5* (densCurr + gaDens(i,j-1,k)) );
- }
- gaVel.write(i,j,k)[1] -= scale* (gaPress(i,j,k) - gaPress(i,j-1,k) );
- }
- if (fgIsFluid(getFlagAcc()(i,j,k-1)) ) {
- if(mpDensity) {
- scale = 1. / (0.5* (densCurr + gaDens(i,j,k-1)) );
- }
- gaVel.write(i,j,k)[2] -= scale* (gaPress(i,j,k) - gaPress(i,j,k-1) );
- }
- };
- void reduce(fsPrCorrVels &op) { };
- protected:
- Grid<Real> *mpPress;
- Grid<Vec3> *mpVel;
- GridAccessor<Real,1> gaPress;
- GridAccessor<Vec3,0> gaVel;
- // optional density
- Grid<Real> *mpDensity;
- GridAccessor<Real,0> gaDens;
-}; // fsPrCorrVels */
-
-
-// overwrite domain sides with default stencil
-// TODO set sides individually?
-static void setOpenBound( int bound, Grid<Real>* A0, Grid<Real>* Ai, Grid<Real>* Aj, Grid<Real>* Ak, Grid<Vec3>* vel )
-{
- Real fac = 6.;
- if(gDim==2) fac = 4.;
-
- if(!bound) return;
-
- // set velocities
- const int iMax = A0->getSizeX()-2;
- const int iMin = 1;
- const int jMax = A0->getSizeY()-2;
- const int jMin = 1;
- const int kMax = A0->getSizeZ()-2;
- const int kMin = 1;
-
- // TODO on/off per side...
- // TODO smoothen?
- bool dox = false;
- bool doy = true;
- bool doz = false;
-
- // set velocities
- if(dox)
- for(int j=0;j<A0->getSizeY();j++)
- for(int k=0;k<A0->getSizeZ();k++) {
- vel->getGlobal(iMax+1,j,k) = vel->getGlobal(iMax,j,k);
- vel->getGlobal(iMin-1,j,k) = vel->getGlobal(iMin,j,k);
- }
-
- if(doy)
- for(int i=0;i<A0->getSizeX();i++)
- for(int k=0;k<A0->getSizeZ();k++) {
- vel->getGlobal(i,jMax+1,k) = vel->getGlobal(i,jMax,k);
- vel->getGlobal(i,jMin-1,k) = vel->getGlobal(i,jMin,k);
- }
-
- if(doz)
- for(int i=0;i<A0->getSizeX();i++)
- for(int j=0;j<A0->getSizeY();j++) {
- vel->getGlobal(i,j,kMax+1) = vel->getGlobal(i,j,kMax);
- vel->getGlobal(i,j,kMin-1) = vel->getGlobal(i,j,kMin);
- }
-
- // set matrix stencils at boundary
- if(dox) {
- for(int i=0;i<= 1;i++)
- for(int j=0;j<A0->getSizeY();j++)
- for(int k=0;k<A0->getSizeZ();k++) {
- A0->getGlobal(i,j,k) = fac;
- Ai->getGlobal(i,j,k) = -1.;
- Aj->getGlobal(i,j,k) = -1.;
- if(gDim==3) Ak->getGlobal(i,j,k) = -1.;
- }
- for(int i=A0->getSizeX()-2;i<=A0->getSizeX()-1;i++)
- for(int j=0;j<A0->getSizeY();j++)
- for(int k=0;k<A0->getSizeZ();k++) {
- A0->getGlobal(i,j,k) = fac;
- Ai->getGlobal(i,j,k) = -1.;
- Aj->getGlobal(i,j,k) = -1.;
- if(gDim==3) Ak->getGlobal(i,j,k) = -1.;
- }
- }
-
- if(doy) {
- for(int i=0;i<A0->getSizeX();i++)
- for(int j=0;j<= 1;j++)
- for(int k=0;k<A0->getSizeZ();k++) {
- A0->getGlobal(i,j,k) = fac;
- Ai->getGlobal(i,j,k) = -1.;
- Aj->getGlobal(i,j,k) = -1.;
- if(gDim==3) Ak->getGlobal(i,j,k) = -1.;
- }
- for(int i=0;i<A0->getSizeX();i++)
- for(int j=A0->getSizeY()-2;j<=A0->getSizeY()-1;j++)
- for(int k=0;k<A0->getSizeZ();k++) {
- A0->getGlobal(i,j,k) = fac;
- Ai->getGlobal(i,j,k) = -1.;
- Aj->getGlobal(i,j,k) = -1.;
- if(gDim==3) Ak->getGlobal(i,j,k) = -1.;
- }
- }
-
- if(doz)
- if(gDim==3) {
- for(int i=0;i<A0->getSizeX();i++)
- for(int j=0;j<A0->getSizeY();j++)
- for(int k=0;k<= 1;k++) {
- A0->getGlobal(i,j,k) = fac;
- Ai->getGlobal(i,j,k) = -1.;
- Aj->getGlobal(i,j,k) = -1.;
- if(gDim==3) Ak->getGlobal(i,j,k) = -1.;
- }
-
- for(int i=0;i<A0->getSizeX();i++)
- for(int j=0;j<A0->getSizeY();j++)
- for(int k=A0->getSizeZ()-2;k<=A0->getSizeZ()-1;k++) {
- A0->getGlobal(i,j,k) = fac;
- Ai->getGlobal(i,j,k) = 1.;
- Aj->getGlobal(i,j,k) = 1.;
- if(gDim==3) Ak->getGlobal(i,j,k) = 1.;
- }
- }
-
- debMsg("FluidSolver::solvePressure","Open boundaries set");
-}
-
-static void setBottomOutflow( Grid<Real>* rhs, int height, std::string dir) { // char dir ) {
- const int iMax = rhs->getSizeX()-2;
- const int iMin = 1;
- const int jMax = rhs->getSizeY()-2;
- const int jMin = 1;
- const int kMax = rhs->getSizeZ()-2;
- const int kMin = 1;
- debMsg("setBottomOutflow","Active, using dir='"<<dir<<"' ");
-
- // remove rhs/divergence at bottom
- for(int trs=0; trs<(int)dir.length(); trs++) {
-
- switch(dir[trs]) {
- case 'x': // -x
- debMsg("setBottomOutflow","Active, -X");
- for(int i=0; i< height;i++)
- for(int j=0;j<rhs->getSizeY();j++)
- for(int k=0;k<rhs->getSizeZ();k++) {
- rhs->getGlobal(i,j,k) = 0.;
- }
- break;
- case 'X': // +x
- debMsg("setBottomOutflow","Active, +X");
- for(int i=rhs->getSizeX()-1-height; i< rhs->getSizeX();i++)
- for(int j=0;j<rhs->getSizeY();j++)
- for(int k=0;k<rhs->getSizeZ();k++) {
- rhs->getGlobal(i,j,k) = 0.;
- }
- break;
- case 'y': // -y
- debMsg("setBottomOutflow","Active, -Y");
- for(int i=0;i<rhs->getSizeX();i++)
- for(int j=0;j<= height;j++)
- for(int k=0;k<rhs->getSizeZ();k++) {
- rhs->getGlobal(i,j,k) = 0.;
- }
- break;
- case 'Y': // +y
- debMsg("setBottomOutflow","Active, +Y");
- for(int i=0;i<rhs->getSizeX();i++)
- for(int j=rhs->getSizeY()-1-height; j< rhs->getSizeY();j++)
- for(int k=0;k<rhs->getSizeZ();k++) {
- rhs->getGlobal(i,j,k) = 0.;
- }
- break;
- case 'z': // -z
- debMsg("setBottomOutflow","Active, -Z");
- for(int i=0;i<rhs->getSizeX();i++)
- for(int j=0;j<= rhs->getSizeY();j++)
- for(int k=0;k<height;k++) {
- rhs->getGlobal(i,j,k) = 0.;
- }
- break;
- case 'Z': // +z
- debMsg("setBottomOutflow","Active, +Z");
- for(int i=0;i<rhs->getSizeX();i++)
- for(int j=0;j<rhs->getSizeY();j++)
- for(int k=rhs->getSizeZ()-1-height; k< rhs->getSizeZ();k++) {
- rhs->getGlobal(i,j,k) = 0.;
- }
- break;
-
- default:
- errFatal("setBottomOutflow","Invalid dir "<<dir<<" ",SIMWORLD_GENERICERROR);
- } // dir
-
- } // string
-}
-
-// apply stored symmetric matix
-// simple version - no inclusion of e.g., surface tension forces
-class goApplyMatrix : public GridOpBase{
- public:
- goApplyMatrix(Grid<Real> *Dst, Grid<Real> *Src,
- Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak,
- FlagGrid *Flags,
- Grid<Real> *unusedReal,
- Grid<Vec3> *unusedVec ) : GridOpBase(),
- mpA0(A0), mpAi(Ai), mpAj(Aj), mpAk(Ak) {
- mpDst = Dst; mpSrc = Src;
- //mpMat = Mat;
- mpFlags = Flags;
- applyOperatorToGrids(this);
- };
- ~goApplyMatrix() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaSrc.gridAccInit(mpSrc, AM_READ, gaCalls);
- gaA0.gridAccInit(mpA0, AM_READ, gaCalls);
- gaAi.gridAccInit(mpAi, AM_READ, gaCalls);
- gaAj.gridAccInit(mpAj, AM_READ, gaCalls);
- gaAk.gridAccInit(mpAk, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- if(!fgIsFluid(getFlagAcc()(i,j,k)) ) {
- //gaDst.write(i,j,k) = 0.; // org
- gaDst.write(i,j,k) = gaSrc(i,j,k);
- //gaDst.write(i,j,k) = gaSrc(i,j,k) * gaA0(i ,j ,k);
- return;
- }
-
- gaDst.write(i,j,k) =
- gaSrc(i ,j ,k) * gaA0(i ,j ,k)
- + gaSrc(i-1,j,k) * gaAi(i-1,j,k)
- + gaSrc(i+1,j,k) * gaAi(i ,j,k)
- + gaSrc(i,j-1,k) * gaAj(i,j-1,k)
- + gaSrc(i,j+1,k) * gaAj(i,j ,k)
- + gaSrc(i,j,k-1) * gaAk(i,j,k-1)
- + gaSrc(i,j,k+1) * gaAk(i,j,k );
- }
-
- void getRidOfWarning() { };
- void reduce(goApplyMatrix &op) { getRidOfWarning(); }
- protected:
- Grid<Real> *mpDst, *mpSrc;
- GridAccessor<Real,0> gaDst;
- GridAccessor<Real,1> gaSrc;
-
- Grid<Real> *mpA0, *mpAi, *mpAj, *mpAk;
- GridAccessor<Real,1> gaA0, gaAi, gaAj, gaAk;
-}; // goApplyMatrix
-
-//*****************************************************************************
-
-// add forces to vels
-class spluginSolvePressure : public SolverPlugin {
- public:
- spluginSolvePressure() : SolverPlugin(),
- mVels("-unn1-"), mFlags("-unn1-"),
- mPress("-unn1-"), mRhs("-unn1-"),
- mRes("-unn1-"), mSrch("-unn1-"),
- mTmp("-unn1-"), mDensity("-unn1-"), mOpenBound(0),
- mBottomOutflow(0), mBottomOutflowDir("X"),
- mStPerCellCor("-unn2-"), mUseResNorm(true), mPcMethod(0),
- mNamePcA0("PCA0"), mNamePcAi("PCAi"), mNamePcAj("PCAj"), mNamePcAk("PCAk")
- { };
- ~spluginSolvePressure() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mVels = params.FindOneString("vel", mVels );
- mPress = params.FindOneString("pressure", mPress );
- mDensity = params.FindOneString("density", mDensity );
- mStPerCellCor = params.FindOneString("st-per-cell-corr", mStPerCellCor );
-
- // optional grids for preconditining, not all PCs need all four grids!
- mNamePcA0 = params.FindOneString("grid-pca0", mNamePcA0 );
- mNamePcAi = params.FindOneString("grid-pcai", mNamePcAi );
- mNamePcAj = params.FindOneString("grid-pcaj", mNamePcAj );
- mNamePcAk = params.FindOneString("grid-pcak", mNamePcAk );
-
- mOpenBound = params.FindOneInt("openbound", mOpenBound );
- mPcMethod = params.FindOneInt("precondition", mPcMethod );
- mUseResNorm = params.FindOneInt("use-res-norm", mUseResNorm );
-
- mBottomOutflow = params.FindOneInt("bottom-outflow", mBottomOutflow );
- //std::string boStr = std::string("y");
- mBottomOutflowDir = params.FindOneString("bottom-outflow-dir", mBottomOutflowDir );
- //if(boStr.length()>=1) { mBottomOutflowDir = boStr[0]; }
-
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spluginSolvePressure","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginSolvePressure","step "<<dt<<" velsgrid:"<<mVels<<", precond:"<<mPcMethod<<", use-res-norm:"<<mUseResNorm);
-
- // TODO fixme, hard coded names for now
- mVels = std::string("vel-curr");
- mFlags = std::string("flags");
- mPress = std::string("pressure");
- mRhs = std::string("rhs");
- mRes = std::string("residual");
- mSrch = std::string("search");
- mTmp = std::string("tmp");
-
- std::ostringstream pdebug;
- const bool debugSP= false;
- Grid<Vec3> *currVel = mpPlParams->getGridVec3( mVels );
- FlagGrid* pFlags = mpPlParams->getGridInt( mFlags );
- Grid<Real>* pPressure = mpPlParams->getGridReal( mPress );
- Grid<Real>* pRhs = mpPlParams->getGridReal( mRhs );
- Grid<Real>* pResidual = mpPlParams->getGridReal( mRes );
- Grid<Real>* pSearch = mpPlParams->getGridReal( mSrch );
- Grid<Real>* pTmp = mpPlParams->getGridReal( mTmp );
-
- Grid<Real>* pA0 = mpPlParams->getGridReal( "A0" );
- Grid<Real>* pAi = mpPlParams->getGridReal( "Ai" );
- Grid<Real>* pAj = mpPlParams->getGridReal( "Aj" );
- Grid<Real>* pAk = mpPlParams->getGridReal( "Ak" );
-
- Grid<Real>* pDens = NULL;
- if(mpPlParams->haveGridReal( mDensity )) {
- pDens = mpPlParams->getGridReal( mDensity );
- debMsg("spluginSolvePressure","Pressure correction RHS using density grid '"<<mDensity<<"' ");
- }
-
- Grid<Real>* pStPerCellCorr = NULL;
- if(mpPlParams->haveGridReal( mStPerCellCor )) {
- pStPerCellCorr = mpPlParams->getGridReal( mStPerCellCor );
- debMsg("spluginSolvePressure","Pressure correction RHS using per cell ST-correction grid '"<<mStPerCellCor<<"' ");
- }
-
- if (debugSP) {
- pdebug<<"\n PRE \n\n";
- pdebug<<"P \n"<< pPressure->toString() <<" \n";
- pdebug<<"CURRVEL \n"<< currVel->toString() <<" \n";
- }
-
- // reset necessary
- GridOpTouchMemory<Real>(pFlags, pA0, 0.);
- GridOpTouchMemory<Real>(pFlags, pAi, 0.);
- GridOpTouchMemory<Real>(pFlags, pAj, 0.);
- GridOpTouchMemory<Real>(pFlags, pAk, 0.);
- fsPrMakeMatrix(pFlags, pA0,pAi,pAj,pAk);
- setOpenBound(mOpenBound, pA0,pAi,pAj,pAk, currVel);
-
- // compute divergence and init right hand side
- fsPrMakeRhs(pFlags, pRhs, currVel,
- mpPlParams->getDivergenceCorrection() // usually is zero, set by compute-volume-correction plugin
- , pDens , pStPerCellCorr );
- if(mBottomOutflow>0) {
- setBottomOutflow(pRhs, mBottomOutflow, mBottomOutflowDir);
- }
-
- const int maxIter = (int)(mpPlParams->mCgMaxIterFac *VMAX(pFlags->getSize()) );
- if (1) {
- GridCgInterface *gcg = NULL;
-
- GridCg<goApplyMatrix> *mgcg = new GridCg<goApplyMatrix>(
- pPressure, pRhs, pResidual, pSearch, pFlags, pTmp, pA0,pAi,pAj,pAk );
- gcg = mgcg;
- gcg->setAccuracy( mpPlParams->mCgAccuracy );
- gcg->setUseResNorm( mUseResNorm );
-
- // optional preconditioning, with optional grids
- Grid<Real> *pPCA0 = NULL, *pPCAi=NULL, *pPCAj=NULL, *pPCAk=NULL;
- if(mpPlParams->haveGridReal( mNamePcA0 ))
- pPCA0 = mpPlParams->getGridReal( mNamePcA0 );
- if(mpPlParams->haveGridReal( mNamePcAi ))
- pPCAi = mpPlParams->getGridReal( mNamePcAi );
- if(mpPlParams->haveGridReal( mNamePcAj ))
- pPCAj = mpPlParams->getGridReal( mNamePcAj );
- if(mpPlParams->haveGridReal( mNamePcAk ))
- pPCAk = mpPlParams->getGridReal( mNamePcAk );
- gcg->setPreconditioner( mPcMethod, pPCA0, pPCAi, pPCAj, pPCAk );
-
- for (int iter=0; iter<maxIter; iter++) {
- if (!gcg->iterate()) iter=maxIter;
- }
- debMsg("FluidSolver::solvePressure","iterations:"<<gcg->getIterations()<<", res:"<<gcg->getSigma() );
- delete gcg;
- } else {
- // debug tests
- for (int iter=0; iter<4*maxIter; iter++) {
- goJacobiSolver(pTmp, pPressure, pRhs, pFlags);
- goCopyGrid<Real>(pPressure, pTmp);
- }
- debMsg("FluidSolver::solvePressure","jacobi iterations:"<<4*maxIter );
- }
- fsPrCorrVels(pFlags, currVel, pPressure, pDens);
-
- if (debugSP) {
- goCompMinMax<Real> mm = goCompMinMax<Real>(pPressure, pFlags);
- debMsg("FluidSolver::solvePressure","minmax "<< mm.toString() );
-
- pdebug<<"\n POST \n\n";
- pdebug<<"RHS \n"<< pRhs->toString() <<" \n";
- pdebug<<"P \n"<< pPressure->toString() <<" \n";
- pdebug<<"CURRVEL \n"<< currVel->toString() <<" \n";
-
- pdebug<<"A0 \n"<< pA0->toString() <<" \n";
- pdebug<<"Ai \n"<< pAi->toString() <<" \n";
- pdebug<<"Aj \n"<< pAj->toString() <<" \n";
- pdebug<<"Ak \n"<< pAk->toString() <<" \n";
- std::fstream df; // DEBUG
- df.open("debugOut_pressure.txt", std::ios::out);
- df << pdebug.str();
- df.close(); // DEBUG
- }
-
- return true;
- };
-
- protected:
- // grid names to swap
- std::string mVels, mFlags, mPress, mRhs, mRes, mSrch, mTmp, mDensity;
- // open boundaries?
- int mOpenBound;
- int mBottomOutflow;
- std::string mBottomOutflowDir;
- // grid name to for optional curvatuere/surface tension grid
- std::string mStPerCellCor;
-
- // use residual norm or max entry?
- bool mUseResNorm;
- // preconditiong
- int mPcMethod;
- std::string mNamePcA0, mNamePcAi, mNamePcAj, mNamePcAk;
-};
-
-//*****************************************************************************
-
-template < class Scalar >
-class GridOpDiffuse : public GridOpBase {
- public:
- GridOpDiffuse(Grid<Scalar>* pSrc,Grid<Scalar>* pDst, FlagGrid* flags, Real str)
- : GridOpBase(), mpSrc(pSrc), mpDst(pDst), mStrength(str) {
- mpFlags = flags;
- applyOperatorToGrids( this );
- }
- ~GridOpDiffuse() {};
- void resetVariables() { }
- void reduce(GridOpDiffuse &op) { }
-
- void buildCallList() {
- gaSrc.gridAccInit(mpSrc, DDF::AM_WRITE, gaCalls);
- gaDst.gridAccInit(mpDst, DDF::AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k) {
- if(!fgIsFluid(getFlagAcc()(i,j,k)) ) {
- gaDst.write(i,j,k) = gaSrc(i,j,k);
- return;
- }
-
- const Scalar curr = gaSrc(i,j,k);
- Scalar avg = 0.;
-
- if(1 && fgIsFluid(getFlagAcc()(i+1,j,k)) ) {
- avg += gaSrc(i+1,j,k);
- } else { avg += curr; }
-
- if(1 && fgIsFluid(getFlagAcc()(i-1,j,k)) ) {
- avg += gaSrc(i-1,j,k);
- } else { avg += curr; }
-
- if(1 && fgIsFluid(getFlagAcc()(i,j+1,k)) ) {
- avg += gaSrc(i,j+1,k);
- } else { avg += curr; }
-
- if(1 && fgIsFluid(getFlagAcc()(i,j-1,k)) ) {
- avg += gaSrc(i,j-1,k);
- } else { avg += curr; }
-
- if(gDim==3) {
- if(1 && fgIsFluid(getFlagAcc()(i,j,k+1)) ) {
- avg += gaSrc(i,j,k+1);
- } else { avg += curr; }
-
- if(1 && fgIsFluid(getFlagAcc()(i,j,k-1)) ) {
- avg += gaSrc(i,j,k-1);
- } else { avg += curr; }
- }
-
- avg *= (gDim==3 ? 1./6. : 1./4.);
- //gaDst.write(i,j,k) = (1.-mStrength) * curr + mStrength * avg;
- gaDst.write(i,j,k) = avg*mStrength -curr*mStrength + curr;
- }
-
- protected:
- Grid<Scalar> *mpSrc, *mpDst;
- GridAccessor<Scalar,1> gaSrc;
- GridAccessor<Scalar,0> gaDst;
- Real mStrength;
-}; // GridOpDiffuse */
-
-class spDiffuseGrid : public SolverPlugin {
- public:
- spDiffuseGrid() :
- SolverPlugin(),
- mDest("real-temp") , mDestVec("vec-temp"), mDiffusivity(1.)
- { };
- ~spDiffuseGrid() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mDiffusivity = params.FindOneFloat("diff", mDiffusivity );
- mSrc = params.FindOneString("src-real", mSrc );
- mSrcVec = params.FindOneString("src-vec3", mSrcVec );
- mDest = params.FindOneString("dst-real", mDest );
- mDestVec = params.FindOneString("dst-vec3", mDestVec );
- return true;
- };
- virtual bool initPlugin() { return true; };
-
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- FlagGrid* pFlags = mpPlParams->getGridInt( "flags" );
- Real diff = mDiffusivity * dt;
- //if(diff<0. || diff>1.) debMsg("spDiffuseGrid","WARNING - diffusion param invalid!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
- //CLAMP(diff, (Real)0.,(Real)1.);
-
- int cnt=0;
- while(diff > 0.) {
- debMsg("spDiffuseGrid","str"<<mDiffusivity<<",dt="<<dt<<", diff="<<diff<<". from "<<mSrc<<","<<mSrcVec<<" to "<<mDest<<","<<mDestVec);
-
- if(mSrc.length()>0) {
- Grid<Real>* pSrc = mpPlParams->getGridReal(mSrc);
- Grid<Real>* pDest = mpPlParams->getGridReal(mDest);
- GridOpDiffuse<Real> godiv(pSrc, pDest, pFlags, (diff>1.? 1.:diff) );
- cnt++;
-
- swapGrids(mpPlParams, mSrc, mDest);
- }
- if(mSrcVec.length()>0) {
- Grid<Vec3>* pSrcv = mpPlParams->getGridVec3(mSrcVec);
- Grid<Vec3>* pDestv = mpPlParams->getGridVec3(mDestVec);
- GridOpDiffuse<Vec3> godiv(pSrcv, pDestv, pFlags, (diff>1.? 1.:diff) );
- cnt++;
-
- swapGrids(mpPlParams, mSrcVec, mDestVec);
- }
-
- diff -= 1.;
- }
-
- if(cnt==0 && mDiffusivity>0.) {
- errFatal("spDiffuse","No grid for diffusion found or given!", SIMWORLD_PLUGINERROR);
- return false;
- }
- //debMsg("spDiffuseGrid","abs avg="<<godiv.getAbsAvg()<<",abs max="<<godiv.getAbsMax());
- return true;
- };
-
- protected:
- std::string mSrc, mSrcVec;
- std::string mDest, mDestVec;
- Real mDiffusivity;
-};
-
-
-class fsDiffMakeMatrix : public GridOpBaseFlagbord<1> {
- public:
- fsDiffMakeMatrix(FlagGrid *flags, Grid<Real> *A0, Grid<Real> *Ai, Grid<Real> *Aj, Grid<Real> *Ak, Real coeff) :
- GridOpBaseFlagbord<1>(), mpA0(A0), mpAi(Ai), mpAj(Aj), mpAk(Ak), mCoeff(coeff) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsDiffMakeMatrix() { };
- void resetVariables() { };
- void buildCallList() {
- gaA0.gridAccInit(mpA0, AM_WRITE, gaCalls);
- gaAi.gridAccInit(mpAi, AM_WRITE, gaCalls);
- gaAj.gridAccInit(mpAj, AM_WRITE, gaCalls);
- gaAk.gridAccInit(mpAk, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
- inline void operator() (int i, int j, int k) {
- const int currFlag = getFlagAcc()(i,j,k);
-
- //gaA0.write(i,j,k) = 5.; gaAi.write(i,j,k) = -1.; gaAj.write(i,j,k) = -1.; gaAk.write(i,j,k) = 0.; return;
-
- Real& a0 = gaA0.write(i,j,k);
- a0 = 1.;
-
- // handle diffusion across free surface boundaries, e.g. for velocity
- if (fgIsEmpty(getFlagAcc()(i,j,k)) ) {
- if (fgIsFluid(getFlagAcc()(i+1,j,k)) ) {
- gaAi.write(i,j,k) -= mCoeff;
- }
- if (fgIsFluid(getFlagAcc()(i,j+1,k)) ) {
- gaAj.write(i,j,k) -= mCoeff;
- }
- if (gDim==3 && fgIsFluid(getFlagAcc()(i,j,k+1)) ) {
- gaAk.write(i,j,k) -= mCoeff;
- }
- }
-
- if (!fgIsFluid(currFlag) ) return;
-
- if (!fgIsObstacle(getFlagAcc()(i+1,j,k)) ) {
- a0 += mCoeff;
- }
- if (!fgIsObstacle(getFlagAcc()(i-1,j,k)) ) {
- a0 += mCoeff;
- }
- if(1) {
- gaAi.write(i,j,k) -= mCoeff;
- }
-
- if (!fgIsObstacle(getFlagAcc()(i,j+1,k)) ) {
- a0 += mCoeff;
- }
- if (!fgIsObstacle(getFlagAcc()(i,j-1,k)) ) {
- a0 += mCoeff;
- }
- //if (fgIsFluid(getFlagAcc()(i,j+1,k)) ) {
- //if ( (fgIsFluid(getFlagAcc()(i,j-1,k)) ) && (fgIsFluid(getFlagAcc()(i,j+1,k)) ) ) {
- if(1) {
- //if (fgIsFluid(getFlagAcc()(i,j+1,k)) ) {
- gaAj.write(i,j,k) -= mCoeff;
- }
-
-# if DDF_DIMENSION==3
- if (!fgIsObstacle(getFlagAcc()(i,j,k+1)) ) {
- a0 += mCoeff;
- }
- if (!fgIsObstacle(getFlagAcc()(i,j,k-1)) ) {
- a0 += mCoeff;
- }
- //if (fgIsFluid(getFlagAcc()(i,j,k+1)) ) {
- if(1) {
- gaAk.write(i,j,k) -= mCoeff;
- }
-# endif
-
- //debMsg("D "," at "<<PRINT_IJK<<"a = "<< gaA0.write(i,j,k)<<", "<< gaAi.write(i,j,k)<<", "<< gaAj.write(i,j,k)<<", "<< gaAk.write(i,j,k)<<", ");
- };
- void reduce(fsDiffMakeMatrix &op) { };
- protected:
- Grid<Real> *mpA0, *mpAi, *mpAj, *mpAk;
- GridAccessor<Real,0> gaA0, gaAi, gaAj, gaAk;
- Real mCoeff;
-}; // fsDiffMakeMatrix */
-
-// add forces to vels
-class spluginSolveDiffusion : public SolverPlugin {
- public:
- spluginSolveDiffusion() : SolverPlugin(),
- mDst("-unnamed1-"), mRhs("-unnamed1-"),
- mRes("-unnamed1-"), mSrch("-unnamed1-"),
- mTmp("-unnamed1-"), mOpenBound(0),
- mDiffusion(0.), mAccuracy(1.), mMaxIter(1.) { };
- ~spluginSolveDiffusion() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mDst = params.FindOneString("dst-real", mDst );
- // source = rhs
- mRhs = params.FindOneString("src-real", mRhs );
-
- mVec3Dst = params.FindOneString("dst-vec3", mVec3Dst );
- mVec3Rhs = params.FindOneString("src-vec3", mVec3Rhs );
-
- mOpenBound = params.FindOneInt("openbound", mOpenBound );
- mDiffusion = params.FindOneFloat("diffusion", mDiffusion );
-
- // CG parameters, modify basic fluid solver settings, default = 1
- mAccuracy = params.FindOneFloat("accuracy", mAccuracy );
- mMaxIter = params.FindOneFloat("max-iter", mMaxIter);
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spluginSolveDiffusion","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
-
- const Real dx = mpPlParams->getDeltaX();
- const Real coeff = dt * mDiffusion / (dx*dx);
-
- debMsg("spluginSolveDiffusion","step "<<dt<<" diffusionCoeff:"<<mDiffusion<<" -> coeff="<<coeff);
-
- // TODO fixme, hard coded names for now
- mRes = std::string("residual");
- mSrch = std::string("search");
- mTmp = std::string("tmp");
-
- std::ostringstream pdebug;
- const bool debugSP= false;
- FlagGrid* pFlags = mpPlParams->getFluidSolver()->getGridFlags(); // getGridInt( mFlags );
- Grid<Real>* pResidual = mpPlParams->getGridReal( mRes );
- Grid<Real>* pSearch = mpPlParams->getGridReal( mSrch );
- Grid<Real>* pTmp = mpPlParams->getGridReal( mTmp );
-
- Grid<Real>* pA0 = mpPlParams->getGridReal( "A0" );
- Grid<Real>* pAi = mpPlParams->getGridReal( "Ai" );
- Grid<Real>* pAj = mpPlParams->getGridReal( "Aj" );
- Grid<Real>* pAk = mpPlParams->getGridReal( "Ak" );
-
- GridOpTouchMemory<Real>(pFlags, pA0, 0.);
- GridOpTouchMemory<Real>(pFlags, pAi, 0.);
- GridOpTouchMemory<Real>(pFlags, pAj, 0.);
- GridOpTouchMemory<Real>(pFlags, pAk, 0.);
-
- if( (mpPlParams->haveGridVec3( mVec3Rhs )) && (mpPlParams->haveGridVec3( mVec3Dst )) ) {
- // vec3 version
- Grid<Vec3>* pVec3Rhs = mpPlParams->getGridVec3( mVec3Rhs );
- Grid<Vec3>* pVec3Dst = mpPlParams->getGridVec3( mVec3Dst );
-
- // temp real versions, make sure these grids are not used multiply!
- Grid<Real>* pRhs = mpPlParams->getGridReal( mRhs );
- Grid<Real>* pDst = mpPlParams->getGridReal( mDst );
-
- // setup diffusion matrix
- fsDiffMakeMatrix(pFlags, pA0,pAi,pAj,pAk, coeff);
-
- int maxIter = (int)(mMaxIter *mpPlParams->mCgMaxIterFac *VMAX(pFlags->getSize()) );
- if(maxIter <= 0) maxIter = 1;
-
-
- if(1) {
- goCopyVec3ToScalar<Real,0>(pRhs, pVec3Rhs);
- //goCopyVec3ToScalar<Real,0>(pDst, pVec3Dst);
- goCopyVec3ToScalar<Real,0>(pDst, pVec3Rhs);
-
- GridCg<goApplyMatrix> gcg = GridCg<goApplyMatrix>(pDst, pRhs, pResidual, pSearch, pFlags, pTmp, pA0,pAi,pAj,pAk );
- gcg.setAccuracy( mAccuracy *mpPlParams->mCgAccuracy );
- gcg.solve( maxIter );
- debMsg("FluidSolver::solveDiffusion Vec3","iterations:"<<gcg.getIterations()<<", res:"<<gcg.getSigma() );
-
- goCopyScalarToVec3<Real,0>(pVec3Dst,pDst);
- } else {
- goCopyVec3ToScalar<Real,0>(pRhs,pVec3Rhs);
- goCopyScalarToVec3<Real,0>(pVec3Dst,pRhs);
- }
-
-
- if(1) {
- goCopyVec3ToScalar<Real,1>(pRhs,pVec3Rhs);
- //goCopyVec3ToScalar<Real,1>(pDst,pVec3Dst);
- goCopyVec3ToScalar<Real,1>(pDst,pVec3Rhs);
-
- GridCg<goApplyMatrix> gcg = GridCg<goApplyMatrix>(pDst, pRhs, pResidual, pSearch, pFlags, pTmp, pA0,pAi,pAj,pAk );
- gcg.setAccuracy( mAccuracy *mpPlParams->mCgAccuracy );
- gcg.solve( maxIter );
- debMsg("FluidSolver::solveDiffusion Vec3","iterations:"<<gcg.getIterations()<<", res:"<<gcg.getSigma() );
-
- goCopyScalarToVec3<Real,1>(pVec3Dst,pDst);
- } else {
- goCopyVec3ToScalar<Real,1>(pRhs,pVec3Rhs);
- goCopyScalarToVec3<Real,1>(pVec3Dst,pRhs);
- }
-
-
- if(1) {
- goCopyVec3ToScalar<Real,2>(pRhs,pVec3Rhs);
- goCopyVec3ToScalar<Real,2>(pDst,pVec3Dst);
-
- GridCg<goApplyMatrix> gcg = GridCg<goApplyMatrix>(pDst, pRhs, pResidual, pSearch, pFlags, pTmp, pA0,pAi,pAj,pAk );
- gcg.setAccuracy( mAccuracy *mpPlParams->mCgAccuracy );
- gcg.solve( maxIter );
- debMsg("FluidSolver::solveDiffusion Vec3","iterations:"<<gcg.getIterations()<<", res:"<<gcg.getSigma() );
-
- goCopyScalarToVec3<Real,2>(pVec3Dst,pDst);
- } else {
- goCopyVec3ToScalar<Real,2>(pRhs,pVec3Rhs);
- goCopyScalarToVec3<Real,2>(pVec3Dst,pRhs);
- }
-
- swapGrids(mpPlParams, mVec3Dst, mVec3Rhs);
-
- const bool debugDIFF = false;
- if (debugDIFF) {
- goCompMinMax<Real> mm = goCompMinMax<Real>(pDst, pFlags);
- debMsg("FluidSolver::solvePressure","minmax "<< mm.toString() );
-
- pdebug<<"\n POST \n\n";
- pdebug<<"RHS \n"<< pRhs->toString() <<" \n";
- pdebug<<"Dst \n"<< pDst->toString() <<" \n";
-
- pdebug<<"A0 \n"<< pA0->toString() <<" \n";
- pdebug<<"Ai \n"<< pAi->toString() <<" \n";
- pdebug<<"Aj \n"<< pAj->toString() <<" \n";
- pdebug<<"Ak \n"<< pAk->toString() <<" \n";
- std::fstream df; // DEBUG
- df.open("debugOut_diffusionVec.txt", std::ios::out);
- df << pdebug.str();
- df.close(); // DEBUG
- }
-
- } else if( (mpPlParams->haveGridReal( mRhs )) && (mpPlParams->haveGridReal( mDst )) ) {
- // real version
- Grid<Real>* pRhs = mpPlParams->getGridReal( mRhs );
- Grid<Real>* pDst = mpPlParams->getGridReal( mDst );
-
- // setup diffusion matrix
- fsDiffMakeMatrix(pFlags, pA0,pAi,pAj,pAk, coeff);
-
- int maxIter = (int)(mMaxIter *mpPlParams->mCgMaxIterFac *VMAX(pFlags->getSize()) );
- if(maxIter <= 0) maxIter = 1;
-
- GridCg<goApplyMatrix> *gcg = new GridCg<goApplyMatrix>(pDst, pRhs, pResidual, pSearch, pFlags, pTmp, pA0,pAi,pAj,pAk );
- gcg->setAccuracy( mAccuracy *mpPlParams->mCgAccuracy );
-
- for (int iter=0; iter<maxIter; iter++) {
- if (!gcg->iterate()) iter=maxIter;
- }
- debMsg("FluidSolver::solveDiffusion Real","iterations:"<<gcg->getIterations()<<", res:"<<gcg->getSigma() );
- delete gcg;
-
- const bool debugDIFF = false;
- if (debugDIFF) {
- goCompMinMax<Real> mm = goCompMinMax<Real>(pDst, pFlags);
- debMsg("FluidSolver::solvePressure","minmax "<< mm.toString() );
-
- pdebug<<"\n POST \n\n";
- pdebug<<"RHS \n"<< pRhs->toString() <<" \n";
- pdebug<<"Dst \n"<< pDst->toString() <<" \n";
-
- pdebug<<"A0 \n"<< pA0->toString() <<" \n";
- pdebug<<"Ai \n"<< pAi->toString() <<" \n";
- pdebug<<"Aj \n"<< pAj->toString() <<" \n";
- pdebug<<"Ak \n"<< pAk->toString() <<" \n";
- std::fstream df; // DEBUG
- df.open("debugOut_diffusionReal.txt", std::ios::out);
- df << pdebug.str();
- df.close(); // DEBUG
- }
-
- swapGrids(mpPlParams, mDst, mRhs);
- }
-
- return true;
- };
-
- protected:
- // grid names to swap
- std::string mDst, mRhs, mRes, mSrch, mTmp;
- std::string mVec3Dst, mVec3Rhs;
- // open boundaries?
- int mOpenBound;
- // diffusivity
- Real mDiffusion, mAccuracy, mMaxIter;
-};
-
-// create one of the standard hard coded plugins
-SolverPlugin* MakePoissionSolverPlugins(std::string name) {
-
- if(name.compare( "solve-pressure")==0) {
- return new spluginSolvePressure;
-
- } else if(name.compare( string("diffuse-grid") )==0) {
- return new spDiffuseGrid;
-
- } else if(name.compare( string("solve-diffusion") )==0) {
- return new spluginSolveDiffusion;
-
- }
-
- return NULL;
-}
-
-} // end namespace DDF
-
diff --git a/intern/smoke/intern/source/smoke.cpp b/intern/smoke/intern/source/smoke.cpp
deleted file mode 100644
index 38143171b6a..00000000000
--- a/intern/smoke/intern/source/smoke.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-#include "smoke.h"
-
-using namespace std;
-using namespace DDF;
-
-#include <limits.h>
-
-void FLUID_3D::init()
-{
- printf("-------------------- SMOKE INIT A-------------------------\n");
- { // static scene
- printf("init res %d, %d, %d\n", _res[0], _res[1], _res[2]);
- SolverObject* solverInit = new SolverObject( "makescene", nVec3i ( _res[0], _res[1], _res[2] ), DDF_GRID_NO_FREE ); // 200, 80, 150
- solverInit->createVec3Grid ( "normal", DDF_GRID_NO_FREE );
- solverInit->createRealGrid ( "dist", DDF_GRID_NO_FREE );
- solverInit->addInitPlugin ( "init-box-domain", IntArg ( "flag-inside",FFLUID ) + IntArg ( "flag-border",FINFLOW ) + IntArg("flag-floor", FOBSTACLE) );
- // obstacles
- solverInit->addInitPlugin ( "init-sphere", VecArg("center",Vec3(0.25,0.6,0.35)) + RealArg("radius",0.1) + StringArg("norm","normal")+StringArg("dist","dist"));
- solverInit->addInitPlugin ( "init-box", VecArg("pos1",Vec3(0.2,0.0,0.3)) + VecArg("pos2",Vec3(0.3,0.6,0.4)) + StringArg("norm","normal")+StringArg("dist","dist"));
- solverInit->addInitPlugin ( "init-box", VecArg("pos1",Vec3(0.3,0.0,0.65)) + VecArg("pos2",Vec3(0.5,0.3,0.9)) + StringArg("norm","normal")+StringArg("dist","dist"));
- solverInit->addInitPlugin ( "init-box", VecArg("pos1",Vec3(0.6,0.0,0.3)) + VecArg("pos2",Vec3(0.65,0.4,0.5)) + StringArg("norm","normal")+StringArg("dist","dist"));
- // smoke seed
- solverInit->addInitPlugin ( "init-sphere", VecArg("center",Vec3(0.3,0.65,0.35)) + RealArg("radius",0.1) + IntArg("type", FDENSITYSOURCE));
- solverInit->addInitPlugin ( "init-box", VecArg("pos1",Vec3(0.25,0.0,0.3)) + VecArg("pos2",Vec3(0.35,0.65,0.4)) + IntArg("type", FDENSITYSOURCE));
- solverInit->addInitPlugin ( "init-box", VecArg("pos1",Vec3(0.35,0.0,0.65)) + VecArg("pos2",Vec3(0.55,0.35,0.9)) + IntArg("type", FDENSITYSOURCE));
- solverInit->addInitPlugin ( "init-box", VecArg("pos1",Vec3(0.65,0.0,0.3)) + VecArg("pos2",Vec3(0.7,0.45,0.5)) + IntArg("type", FDENSITYSOURCE));
-
- // solverInit->addInitPlugin ( "dump-universal", StringArg ( "grid", "flags" ) + StringArg ( "override-name","scene/static-flags" ) + IntArg ( "single-dump", 1 ) );
- // solverInit->addInitPlugin ( "dump-universal", StringArg ( "grid", "dist" ) + StringArg ( "override-name","scene/static-dist" ) + IntArg ( "single-dump", 1 ) );
- // solverInit->addInitPlugin ( "dump-universal", StringArg ( "grid", "normal" ) + StringArg ( "override-name","scene/static-normal" ) + IntArg ( "single-dump", 1 ) );
-
- _solvers.push_back(solverInit);
- }
-
- initAllSolvers();
-
- // advanceAllSolvers(); // DG TODO disabled for testing purposed
-
- // finalizeAllSolvers(); // DG TODO disabled for testing purposed
-
- _flags = _solvers[0]->getParams().getGridInt("flags");
- _normal = _solvers[0]->getParams().getGridVec3("normal");
- _dist = _solvers[0]->getParams().getGridReal("dist");
-
- freeAllSolvers();
-
- {
- Vec3 inflow (0.4, 0, 0);
- const int nFrames = 50;
- precompute("static", inflow, nFrames, false);
- }
-
- printf("-------------------- SMOKE INIT B-------------------------\n");
- {
- Vec3 inflow (0.4, 0, 0);
- SolverObject* solverStep = new SolverObject( "run_static", _flags);
-
- solverStep->getParams().mU0 = inflow;
- solverStep->getParams().mTimestepAnim = 0.005;
-
- // create grids
- solverStep->createVec3Grid ( "mean-flow", _meanVel );
- solverStep->createRealGrid ( "dist", _dist );
- solverStep->createVec3Grid ( "vorticity", DDF_GRID_NO_FREE );
- solverStep->createVec3Grid ( "ABL" );
- solverStep->createVec3Grid ( "pre-ABL", _abl );
- solverStep->createVec3Grid ( "vort" );
- solverStep->createRealGrid ( "pdf" );
- solverStep->createRealGrid ( "density", DDF_GRID_NO_FREE );
- solverStep->addStandardSolverGrids();
- solverStep->createNoiseField("noise", Vec3(0.), Vec3(50,50,50), -0.4, 20.0 /* 2.0 */, 0.002);
-
- // program solverStep initialization process
- // solverStep->addInitPlugin ( "load-universal", StringArg("grid","dist") + StringArg("file","scene/static-dist.gz"));
- // solverStep->addInitPlugin ( "load-universal", StringArg("grid","mean-flow") + StringArg("file","scene/static-mean.gz"));
- // solverStep->addInitPlugin ( "load-universal", StringArg("grid","pre-ABL") + StringArg("file","scene/static-abl.gz"));
-
- // program solver main loop
- solverStep->addPlugin ( "copy-grid", StringArg ( "src","mean-flow" ) + StringArg ( "dest","vel-curr") );
- solverStep->addPlugin ("init-density-inflow", StringArg("density","density") + RealArg("target-value",0.7) + IntArg("flag", FDENSITYSOURCE) + StringArg("noise","noise"));
- solverStep->addPlugin ( "gen-vpart", StringArg ("source","pre-ABL") + StringArg ("flow","ABL") + StringArg("dist","dist") + StringArg("pdf","pdf") +
- RealArg("thres-vort", 2e-2) + RealArg("thres-pdf",5e-5) + RealArg("mult-pdf",1) + RealArg("scale-flow", 0.94) + RealArg("max-bl",0.15) +
- RealArg("min-dist", 3) + RealArg("min-rad", 3) + RealArg("max-rad", 7) + RealArg("vortex-gain", 2.5) + RealArg("fade-in", 0));
-
- solverStep->addPlugin ( "semi-lagr-advect-vec3", StringArg ( "vel-src","ABL" ) + IntArg ( "mac", 0) );
- solverStep->addPlugin ( "apply-vpart", StringArg ( "vorticity", "vorticity" ) );
- solverStep->addPlugin ( "advect-vpart");
- solverStep->addPlugin ( "merge-vpart", StringArg("ndist","dist") + RealArg("init-time", 30) + RealArg("decay-time",450) + RealArg("merge-dist",0.8) +
- RealArg("dissipate-radius",1) + RealArg("radius-cascade",1.5) );
- solverStep->addPlugin ("compute-vorticity", StringArg("vorticity","vort"));
- solverStep->addPlugin ("maccormack-advect-real", StringArg("real-src","density"));
- // solverStep->addPlugin( "dump-df3", IntArg("max-frames",200) + StringArg("gridname","density") + StringArg("prefix","sta") + RealArg("start-time",0) + IntArg("pbrt",1) + StringArg ( "override-name", "render/static" ));
-
- _solvers.push_back(solverStep);
- }
-
- initAllSolvers();
-
- _vorticity = _solvers[0]->getParams().getGridVec3("vorticity");
- _density = _solvers[0]->getParams().getGridReal("density");
-
- _init = 1;
-
-}
-
-// static precompute
-void FLUID_3D::precompute(const std::string& name, const Vec3& inflow, int frames, bool dynamic, const Vec3& rotAxis, Real rotSpeed)
-{
- bool rotate = (rotSpeed != 0.);
- SolverObject* solverPreCalc = new SolverObject( "precompute", _flags );
-
- // create grids
- solverPreCalc->createVec3Grid ( "normal", _normal );
- solverPreCalc->createRealGrid ( "dist", _dist );
- solverPreCalc->createVec3Grid ( "mean-vel", DDF_GRID_NO_FREE );
- solverPreCalc->createVec3Grid ( "abl", DDF_GRID_NO_FREE );
- solverPreCalc->addStandardSolverGrids();
-
- // additional grids for rot. precomputation
-#if 0
- // DG: not supoprted yet: possible problems with "flags" grid loading into obstacle-flags?
- if (rotate) {
- solverPreCalc->createIntGrid ("obstacle-flags");
- solverPreCalc->createIntGrid ("empty-flags");
- solverPreCalc->addInitPlugin ( "load-universal", StringArg("grid","obstacle-flags") + StringArg("file","scene/" + name + "-flags.gz"));
- solverPreCalc->addInitPlugin ( "init-box-domain", StringArg("gridname","empty-flags") + IntArg ( "flag-inside",FFLUID ) + IntArg ( "flag-border",FINFLOW ) );
- }
-#endif
- // load grids, initialize fluid velocities
- // solverPreCalc->addInitPlugin ( "load-universal", StringArg("grid","dist") + StringArg("file","scene/" + name + "-dist.gz"));
- // solverPreCalc->addInitPlugin ( "load-universal", StringArg("grid","normal") + StringArg("file","scene/" + name + "-normal.gz"));
- solverPreCalc->addInitPlugin ( "set-conditional", StringArg ( "gridname","vel-curr" ) + VecArg ( "target-vec",inflow ) + IntArg ( "flag", FFLUID ) );
-
- // program solver main loop
- solverPreCalc->addPlugin ( "set-conditional", StringArg ( "gridname","vel-curr" ) + VecArg ( "target-vec",inflow ) + IntArg ( "flag", FINFLOW ) );
- solverPreCalc->addPlugin ( "maccormack-advect-vec3", StringArg ( "vel-src", "vel-curr" ) );
- solverPreCalc->addPlugin ( "set-noslip-bcs", StringArg ( "grid","vel-curr" ) );
- solverPreCalc->addPlugin ( "diffuse-grid", StringArg ( "src-vec3", "vel-curr" ) + RealArg ( "diff", 0.3 ) );
- if (rotate)
- solverPreCalc->addPlugin ("set-moving-obs-bcs", StringArg("obstacle","obstacle-flags") + StringArg("flags-src","empty-flags") +
- VecArg("obs-rot-axis", rotAxis) + RealArg("obs-rot-vel", rotSpeed) + VecArg("obs-center", Vec3(0.5,0.5,0.5)));
- solverPreCalc->addPlugin ( "solve-pressure", IntArg ( "openbound",0 ) );
- if (rotate)
- solverPreCalc->addPlugin ( "average", StringArg ( "gridname","vel-curr" ) + StringArg ( "sumgrid","mean-vel" ) + IntArg ( "from", frames ) + IntArg ( "frames", 3 ) + IntArg ( "post-quit",1 ) + IntArg("stride", frames) );
- else
- solverPreCalc->addPlugin ( "average", StringArg ( "gridname","vel-curr" ) + StringArg ( "sumgrid","mean-vel" ) + IntArg ( "from", frames ) + IntArg ( "frames", frames ) + IntArg ( "post-quit",1 ) );
-
- // program final steps
- solverPreCalc->addEndPlugin ( "calc-abl", StringArg ("mean-vel","mean-vel") + StringArg ("dist","dist") + StringArg("normal","normal") + StringArg("abl","abl") + RealArg("d", 1.7));
-
-#if 0
- // DG: dynamic not supported yet
- if (dynamic)
- solverPreCalc->addEndPlugin ( "add-database", StringArg("grid","abl") + StringArg("normal","normal") + VecArg("u0",rotate ? (rotSpeed*rotAxis):inflow));
- else {
- solverPreCalc->addEndPlugin ( "dump-universal", StringArg ( "grid","abl" ) + StringArg ( "override-name","scene/" + name + "-abl" ) + IntArg ( "single-dump", 1 ) );
- solverPreCalc->addEndPlugin ( "dump-universal", StringArg ( "grid","mean-vel" ) + StringArg ( "override-name","scene/" + name + "-mean" ) + IntArg ( "single-dump", 1 ) );
- }
-#endif
-
- _solvers.push_back(solverPreCalc);
-
- initAllSolvers();
-
- /* Calculate all requested frames */
- /* DG TODO: Can I precalc one frame at a time instead of all at once? */
- while(!advanceAllSolvers()) {};
-
- finalizeAllSolvers();
-
- _abl = _solvers[0]->getParams().getGridVec3("abl");
- _meanVel = _solvers[0]->getParams().getGridVec3("mean-vel");
-
- freeAllSolvers();
-}
-
-void FLUID_3D::step()
-{
- // run();
-
- /* Calculate all requested frames */
- /* DG TODO: Can I precalc one frame at a time instead of all at once? */
- advanceAllSolvers();
-
-}
-
-void FLUID_3D::del()
-{
- finalizeAllSolvers();
- freeAllSolvers();
-
- _init = 0;
-} \ No newline at end of file
diff --git a/intern/smoke/intern/source/smoke.h b/intern/smoke/intern/source/smoke.h
deleted file mode 100644
index fa20137cb1b..00000000000
--- a/intern/smoke/intern/source/smoke.h
+++ /dev/null
@@ -1,116 +0,0 @@
-#ifndef DDF_SMOKE_H
-#define DDF_SMOKE_H
-
-#include "globals.h"
-#include "fluidsolver.h"
-
-#include "solverparams.h"
-#include "paramset.h"
-#include "solverplugin.h"
-#include "solverinit.h"
-
-namespace DDF
-{
- class FLUID_3D
- {
- private:
- vector<SolverObject*> _solvers;
-
- /* DG: use 'public' for variables shared with blender ! */
-
- private:
- // functions taken over from standard main
- bool advanceAllSolvers()
- {
- for (unsigned i=0;i<_solvers.size();i++) {
- if (_solvers[i]->performStep()) return true;
- }
- return false;
- }
-
- void finalizeAllSolvers()
- {
- for (unsigned i=0;i<_solvers.size();i++)
- _solvers[i]->finalize();
- }
-
- void initAllSolvers()
- {
- for (int i = 0; i < _solvers.size(); i++)
- _solvers[i]->forceInit();
- }
-
- void freeAllSolvers()
- {
- // finalizeAllSolvers(); // DG: I call this directly from code
-
- for (unsigned i=0;i<_solvers.size();i++)
- delete _solvers[i];
-
- _solvers.clear();
- }
-
- public:
- int _res[3];
-
- bool _init;
-
- /* Init */
- Grid<int> *_flags;
- Grid<Vec3> *_normal;
- Grid<Real> *_dist;
-
- /* Precompute */
- Grid<Vec3> *_meanVel;
- Grid<Vec3> *_abl;
-
- /* Run */
- Grid<Real> *_density;
- Grid<Vec3> *_vorticity;
-
- FLUID_3D(int res[3])
- {
- _flags = NULL;
- _normal = NULL;
- _dist = NULL;
-
- _meanVel = NULL;
- _abl = NULL;
-
- _density = NULL;
- _vorticity = NULL;
-
- _res[0] = res[0];
- _res[1] = res[1];
- _res[2] = res[2];
-
- _init = 0;
- };
-
- ~FLUID_3D()
- {
- freeAllSolvers();
-
- delete _flags;
- delete _normal;
- delete _dist;
-
- delete _meanVel;
- delete _abl;
-
- delete _density;
- delete _vorticity;
- };
-
- void init();
-
- void precompute(const std::string& name, const Vec3& inflow, int frames, bool dynamic, const Vec3& rotAxis = Vec3(0.), Real rotSpeed = 0.);
- void step();
-
- void del();
- };
-
-};
-
-
-#endif /* DDF_SMOKE_H */ \ No newline at end of file
diff --git a/intern/smoke/intern/source/smokeplugins.cpp b/intern/smoke/intern/source/smokeplugins.cpp
deleted file mode 100644
index 88dccf38543..00000000000
--- a/intern/smoke/intern/source/smokeplugins.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Plugins for seeding smoke
- *
- *****************************************************************************/
-
-#include "fluidsolver.h"
-#include "solverplugin.h"
-#include "paramset.h"
-
-#include "waveletnoise.h"
-using WAVELETNOISE::WaveletNoiseField;
-
-
-namespace DDF {
-
-
-//*****************************************************************************
-// helper plugin
-
-// optionally, write out inflow values for file export
-class fsInitDensityInflow : public GridOpBase {
- public:
- fsInitDensityInflow(FlagGrid *flags, Grid<Real> *dst , Grid<Real> *writeGrid, Real target, int flag,
- WaveletNoiseField* noise = NULL) :
- GridOpBase(), mpDst(dst), mpWriteGrid(writeGrid),
- mTargetValue(target), mFlag(flag), mpNoise(noise) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsInitDensityInflow() { };
- void resetVariables() { };
- void reduce(fsInitDensityInflow &op) { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- if(mpWriteGrid) gaWriteGrid.gridAccInit(mpWriteGrid, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- // add forces and update empty cells free surface boundaries
- inline void operator() (int i, int j, int k) {
- if(mpWriteGrid) gaWriteGrid.write(i,j,k) = 0.;
-
- // safety - always write
- if( (getFlagAcc()(i,j,k) & mFlag) == 0) return;
- Real& v = gaDst.write(i,j,k);
-
- if(!mpNoise) {
- // constant
- if(v<mTargetValue) v = mTargetValue;
- } else {
- const Real targ = mpNoise->evaluate( Vec3(i, j, k) ) * mTargetValue;
- if(v<targ) v = targ;
- }
-
- //debMsg("at"," "<<PRINT_IJK<<" flag ="<< getFlagAcc()(i,j,k)<<" smoke "<< gaDst.write(i,j,k));
- if(mpWriteGrid) gaWriteGrid.write(i,j,k) = v;
- };
-
- protected:
- Grid<Real> *mpDst, *mpWriteGrid;
- GridAccessor<Real,0> gaDst;
- GridAccessor<Real,0> gaWriteGrid;
- Real mTargetValue;
- int mFlag;
- // optional noise eval
- WaveletNoiseField* mpNoise;
-}; // fsInitDensityInflow */
-
-class fsInflowVecApply : public GridOpBase {
- public:
- fsInflowVecApply(FlagGrid *flags, Grid<Vec3> *dst , Vec3 target,
- WaveletNoiseField* noise = NULL, bool set=false, Real noiseThresh=0.) :
- GridOpBase(), mpDst(dst),
- mTargetValue(target), mpNoise(noise), mSet(set), mNoiseThreshold(noiseThresh) {
- debMsg("fsInflowVecApply","noise thresh "<<mNoiseThreshold);
- if(mNoiseThreshold>=0. && !mpNoise) {
- errFatal("fsInflowVecApply","Noise treshhold needs noise field!",SIMWORLD_PLUGINERROR);
- }
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsInflowVecApply() { };
- void resetVariables() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- // add forces and update empty cells free surface boundaries
- inline void operator() (int i, int j, int k) {
- if(! fgIsInflow(getFlagAcc()(i,j,k)) ) return;
- Vec3& v = gaDst.write(i,j,k);
-
- if(!mpNoise) {
- // constant
- if(!mSet) v += mTargetValue;
- else v = mTargetValue;
- } else if(mNoiseThreshold<=0.) {
- // use noise...
-
- if(!mSet) {
- // add
- v[0] += mpNoise->evaluate( Vec3(i, j, k) ) * mTargetValue[0];
- v[1] += mpNoise->evaluate( Vec3(i+100., j, k) ) * mTargetValue[0];
- v[2] += mpNoise->evaluate( Vec3(i, j+200., k) ) * mTargetValue[0];
- } else {
- // overwrite old
- v[0] = mpNoise->evaluate( Vec3(i, j, k) ) * mTargetValue[0];
- v[1] = mpNoise->evaluate( Vec3(i+100., j, k) ) * mTargetValue[0];
- v[2] = mpNoise->evaluate( Vec3(i, j+200., k) ) * mTargetValue[0];
- }
- } else {
- // use noise threshold...
-
- if(!mSet) {
- // add
- errFatal("fsInflowVecApply","Noise treshhold only works with set=1",SIMWORLD_PLUGINERROR);
- } else {
- // overwrite old
- if( mpNoise->evaluate( Vec3(i, j, k) ) > mNoiseThreshold ) {
- v = mTargetValue;
- //debMsg("vec"," "<<PRINT_IJK);
- }
- }
- }
- };
- void reduce(fsInflowVecApply &op) { };
-
- protected:
- Grid<Vec3> *mpDst;
- GridAccessor<Vec3,0> gaDst;
- Vec3 mTargetValue;
- WaveletNoiseField* mpNoise;
- bool mSet;
- // dont set noise values, but set constant value if noise is smaller than threshold
- Real mNoiseThreshold;
-}; // fsInflowVecApply */
-
-class spluginInitDensityInflow : public SolverPlugin {
- public:
- spluginInitDensityInflow() : SolverPlugin(),
- mDensName("-unnamed-"), mWriteName(""),
- mNoiseName(""),
- mAnimOutCounter(0), mTargetValue(1.), mTargetVec(0.), mSet(false),
- mNoiseThresh(0.) {
- debMsg("spluginInitDensityInflow","cons");
- };
- ~spluginInitDensityInflow() {
- debMsg("spluginInitDensityInflow","des");
- };
-
- virtual bool parseParams(const ParamSet& params) {
- debMsg("spluginInitDensityInflow","parse");
- mDensName = params.FindOneString("density", mDensName );
- mFlag = params.FindOneInt("flag", FINFLOW);
- mVecName = params.FindOneString("vecgridname", mVecName );
- mWriteName = params.FindOneString("write-grid", mWriteName );
- mTargetValue = params.FindOneFloat("target-value", mTargetValue );
-
- mSet = 0 < params.FindOneInt("set", mSet );
-
- // preinit vec in case only real value is given
- mTargetVec = Vec3(mTargetValue);
- mTargetVec = params.FindOneVector("target-vec", mTargetVec );
-
- mNoiseName = params.FindOneString("noise", mNoiseName );
- mNoiseThresh = params.FindOneFloat("noise-threshold", mNoiseThresh );
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spluginInitDensityInflow","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginInitDensityInflow"," dt="<<dt<<" dest:"<<mDensName<<"/"<<mVecName );
- //Grid<Real>* dens = mpPlParams->getGridReal(mDensName);
- Grid<Real>* writeGrid = NULL;
- if(mWriteName.length()>0) {
- writeGrid = mpPlParams->getGridReal(mWriteName);
- }
-
- WaveletNoiseField* noise = NULL;
- if(mNoiseName.length()>0)
- noise = mpPlParams->getNoiseField(mNoiseName);
-
- Grid<Real>* dens = NULL;
- if(mpPlParams->haveGridReal(mDensName)) dens = mpPlParams->getGridReal(mDensName);
- Grid<Vec3>* srcVecGrid = NULL;
- if(mpPlParams->haveGridVec3(mVecName)) srcVecGrid = mpPlParams->getGridVec3(mVecName);
-
- GridBase* baseGrid = NULL;
- if(dens) {
- baseGrid = dens;
- } else if(srcVecGrid) {
- baseGrid = srcVecGrid;
- } else {
- errFatal("spluginInitDensityInflow","Provide either 'density'='"<<mDensName<<"', or 'vecgridname'='"<<mVecName<<"' ",SIMWORLD_PLUGINERROR);
- }
-
- if(dens) {
- fsInitDensityInflow(mpPlParams->getFluidSolver()->getGridFlags(), dens,
- writeGrid, mTargetValue, mFlag,noise);
-
- /* writing out grids should now be done with the "dump-grip-scalar" plugin */
- }
- if(srcVecGrid) {
- // sanity checks
- if(dens) {
- errFatal("spluginInitDensityInflow","Error, can't do real-grid and vec-grid handling at same time!", SIMWORLD_PLUGINERROR);
- }
-
- // apply...
- fsInflowVecApply(mpPlParams->getFluidSolver()->getGridFlags(), srcVecGrid,
- mTargetVec, noise, mSet, mNoiseThresh);
- }
-
- return true;
- };
-
- protected:
- // grid names to swap
- std::string mDensName, mWriteName, mVecName;
- std::string mNoiseName;
- int mAnimOutCounter, mFlag;
- Real mTargetValue;
- Vec3 mTargetVec;
- bool mSet;
- int mDoLevelset;
- Real mNoiseThresh;
-};
-
-
-//*****************************************************************************
-
-SolverPlugin* MakeSmokePlugin(std::string name) {
-
- if(name.compare( string("init-density-inflow") )==0) {
- return new spluginInitDensityInflow;
- }
- return NULL;
-}
-
-
-} // end namespace DDF
-
-
diff --git a/intern/smoke/intern/source/solverinit.cpp b/intern/smoke/intern/source/solverinit.cpp
deleted file mode 100644
index 40fa67e0ec5..00000000000
--- a/intern/smoke/intern/source/solverinit.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Class to setup the fluid solver (alternative to Parser/lexer)
- *
- *****************************************************************************/
-
-
-#include "solverinit.h"
-#include "paramset.h"
-#include "solverplugin.h"
-#include "waveletnoise.h"
-#include <map>
-
-// global solver lists for GLUTGUI
-extern map<string, DDF::FluidSolver*> gFluidSolvers;
-extern DDF::FluidSolver *gpFsolver;
-extern map<string, WAVELETNOISE::WaveletNoiseField*> gNoiseFields;
-
-namespace DDF {
-#if DDF_GLUTGUI == 1
-extern ParamSet gGlutGuiParams;
-#endif
-
-// declaration from fileio.cpp
-extern nVec3i getUniversalGridSize(const string& file);
-
-//******************************************************************************
-// PluginArgument class
-
-template<> PluginArgument::PluginArgument(const IntArg& pe) {
- mParam.AddInt(pe.mName, pe.mValue);
-}
-template<> PluginArgument::PluginArgument(const RealArg& pe) {
- mParam.AddFloat(pe.mName, pe.mValue);
-}
-template<> PluginArgument::PluginArgument(const StringArg& pe) {
- mParam.AddString(pe.mName, pe.mValue);
-}
-template<> PluginArgument::PluginArgument(const VecArg& pe) {
- mParam.AddVector(pe.mName, pe.mValue);
-}
-
-PluginArgument operator+ (const PluginArgument& t, const PluginArgument& s)
-{
- PluginArgument n;
- n.mParam.AddSet(t.mParam);
- n.mParam.AddSet(s.mParam);
- return n;
-}
-
-//******************************************************************************
-// SolverObject class
-
-SolverObject::SolverObject(const string& name, const nVec3i& gridSize, int gridFlags)
-{
- init(name, gridSize, gridFlags);
-}
-
-SolverObject::SolverObject(const string& name, const std::string& flagGridFile)
-{
- nVec3i size = getUniversalGridSize(flagGridFile);
- init(name, size);
- addInitPlugin ("load-universal", StringArg("grid","flags") + StringArg("file",flagGridFile));
-}
-
-SolverObject::SolverObject(const std::string& name, const SolverObject& source, int multiplier, int gridFlags)
-{
- nVec3i size = source.getParams().getGridSize() * multiplier;
- init(name, size, gridFlags);
- getParams().setMultiplier(multiplier);
- getParams().adaptInit(&source.getParams());
-}
-
-SolverObject::SolverObject(const string& name, Grid<int> *flags)
-{
- nVec3i size = flags->getSize();
- init(name, size);
- createIntGrid("srcflags", flags);
- addInitPlugin ("load-universal", StringArg("grid","flags") + StringArg("srcgrid", "srcflags"));
-}
-
-SolverObject::~SolverObject()
-{
- delete mSolver;
-}
-
-// initialize default solver params
-void SolverObject::init(const string& name, const nVec3i& size, int gridFlags)
-{
- ParamSet par;
- par.AddInt("host-vorticity-system", 1);
- par.AddFloat("timestep", 1.0);
- par.AddVector("gridsize", vec2R(size));
- par.AddFloat("cg-max-iter-fac", 0.30);
- par.AddFloat("cg-accuracy", 0.001);
- // setup plugin lists
- mInitPlugins.clear();
- mPlugins.clear();
- mEndPlugins.clear();
- mStarted = false;
-
- // create solver
- SolverParams* solverParam = new SolverParams("p_" + name);
- solverParam->initFromParamSet(par);
- mSolver = new FluidSolver("s_" + name);
- mSolver->setParams(solverParam);
-
- // create default grids
- createIntGrid("flags", gridFlags);
- createVec3Grid("vel-curr");
- createRealGrid("pressure");
-
- // globally register solver
- gFluidSolvers[mSolver->getName()] = mSolver;
- if (gpFsolver == NULL) gpFsolver = mSolver;
-
- // setup GUI params
- #if DDF_GLUTGUI == 1
- gGlutGuiParams.AddString("solvername", gpFsolver->getName());
- #endif
-}
-
-void SolverObject::forceInit() {
- if (!mStarted) {
- // start solver
- mSolver->initFluid();
- mSolver->addInitPlugins(mInitPlugins);
- mSolver->addPlugins(mPlugins);
- mSolver->addEndPlugins(mEndPlugins);
- mSolver->runInitPlugins();
- mSolver->setSolverInited(true);
- mStarted = true;
- }
-}
-
-void SolverObject::addStandardSolverGrids()
-{
- createVec3Grid("vec-temp");
- createRealGrid("real-temp");
- createRealGrid("temp1");
- createRealGrid("temp2");
- createRealGrid("tmp");
- createRealGrid("residual");
- createRealGrid("rhs");
- createRealGrid("search");
- createRealGrid("A0");
- createRealGrid("Ai");
- createRealGrid("Aj");
- createRealGrid("Ak");
-}
-
-void SolverObject::finalize()
-{
- mSolver->finalize();
-}
-
-bool SolverObject::performStep()
-{
- if (!mStarted) forceInit();
- for(int i=0; i< mSolver->getParams()->mStepFactor; i++)
- mSolver->simulateFluid();
-
- return mSolver->getParams()->getQuit();
-}
-
-void SolverObject::createIntGrid(const std::string& name, int gridFlags)
-{
- const nVec3i gridsize = mSolver->getParams()->getGridSize();
- Grid<int> *grid = new Grid<int>(name);
- grid->initGridMem(gridsize[0], gridsize[1], gridsize[2]);
- mSolver->getParams()->mGridsInt[name] = grid;
- grid->setGridFlags(gridFlags);
- grid->setDisplayFlags(/* hideInGui */ 1);
-}
-
-void SolverObject::createRealGrid(const std::string& name, int gridFlags)
-{
- const nVec3i gridsize = mSolver->getParams()->getGridSize();
- Grid<Real> *grid = new Grid<Real>(name);
- grid->initGridMem(gridsize[0], gridsize[1], gridsize[2]);
- mSolver->getParams()->mGridsReal[name] = grid;
- grid->setGridFlags(gridFlags);
- grid->setDisplayFlags(/* hideInGui */ 1);
-}
-
-void SolverObject::createVec3Grid(const std::string& name, int gridFlags)
-{
- const nVec3i gridsize = mSolver->getParams()->getGridSize();
- Grid<Vec3> *grid = new Grid<Vec3>(name);
- grid->initGridMem(gridsize[0], gridsize[1], gridsize[2]);
- mSolver->getParams()->mGridsVec3[name] = grid;
- grid->setGridFlags(gridFlags);
- grid->setDisplayFlags(/* hideInGui */ 1);
-}
-
-/* Use existing arrays */
-void SolverObject::createIntGrid(const std::string& name, Grid<int> *grid)
-{
- mSolver->getParams()->mGridsInt[name] = grid;
-}
-
-void SolverObject::createRealGrid(const std::string& name, Grid<Real> *grid)
-{
- mSolver->getParams()->mGridsReal[name] = grid;
-}
-
-void SolverObject::createVec3Grid(const std::string& name, Grid<Vec3> *grid)
-{
- mSolver->getParams()->mGridsVec3[name] = grid;
-}
-
-void SolverObject::createNoiseField(const string& name, const Vec3& posOffset, const Vec3& posScale, Real valOffset, Real valScale, Real timeAnim)
-{
- // set params
- ParamSet p;
- p.AddVector("pos-offset", posOffset);
- p.AddVector("pos-scale", posScale);
- p.AddFloat("val-offset", valOffset);
- p.AddFloat("val-scale", valScale);
- p.AddFloat("time-anim", timeAnim);
- p.AddBool("clamp",true);
- p.AddFloat("clamp-neg",0.);
- p.AddFloat("clamp-pos",1.);
-
- WAVELETNOISE::WaveletNoiseField *f = new WAVELETNOISE::WaveletNoiseField(name, p, getParams().getGridSize());
- p.ReportUnused();
-
- // register globally
- gNoiseFields[name] = f;
- getParams().addNoiseField(f, name);
-}
-
-SolverPlugin* SolverObject::createPlugin(const std::string& name, const PluginArgument& p)
-{
- SolverPlugin* plugin = SolverPlugin::makePlugin(name);
- if (!plugin)
- errFatal("SolverObject::createPlugin","Can't create plugin " << name, SIMWORLD_ERRPARSE);
-
- plugin->setPluginParams(&getParams());
- plugin->SolverPlugin::parseParams(p.mParam);
- if (!plugin->parseParams(p.mParam))
- errFatal("SolverObject::createPlugin","Error parsing arguments of plugin " << name, SIMWORLD_ERRPARSE);
-
- p.mParam.ReportUnused();
- return plugin;
-}
-
-void SolverObject::addPlugin(const std::string& name, const PluginArgument& p) {
- mPlugins.push_back(createPlugin(name, p));
-}
-void SolverObject::addInitPlugin(const std::string& name, const PluginArgument& p) {
- mInitPlugins.push_back(createPlugin(name, p));
-}
-void SolverObject::addEndPlugin(const std::string& name, const PluginArgument& p) {
- mEndPlugins.push_back(createPlugin(name, p));
-}
-
-} // DDF
diff --git a/intern/smoke/intern/source/solverinit.h b/intern/smoke/intern/source/solverinit.h
deleted file mode 100644
index e62363ecc91..00000000000
--- a/intern/smoke/intern/source/solverinit.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Class to setup the fluid solver (alternative to Parser/lexer)
- *
- *****************************************************************************/
-
-#ifndef DDFSOLVERINIT_H
-
-#include "fluidsolver.h"
-#include "paramset.h"
-
-namespace DDF
-{
- template<class T> class PluginArgumentElement {
- public:
- PluginArgumentElement(const std::string& name, const T& value) : mName(name), mValue(value) {}
-
- std::string mName;
- T mValue;
- };
-
- // shortcuts
- typedef PluginArgumentElement<string> StringArg;
- typedef PluginArgumentElement<int> IntArg;
- typedef PluginArgumentElement<Real> RealArg;
- typedef PluginArgumentElement<Vec3> VecArg;
-
- // helper class to easily link plugin arguments
- class PluginArgument {
- public:
- PluginArgument() {};
- template<class T> PluginArgument(const PluginArgumentElement<T>& pe);
-
- ParamSet mParam;
- };
- PluginArgument operator+ (const PluginArgument&, const PluginArgument&);
-
-
- // Wrapper class for a solver
- class SolverObject
- {
- public:
- SolverObject(const std::string& name, const nVec3i& gridSize, int gridFlags = 0);
- SolverObject(const std::string& name, const std::string& flagGridFile);
- SolverObject(const std::string& name, const SolverObject& source, int multiplier, int gridFlags);
- SolverObject(const string& name, Grid<int> *flags);
- ~SolverObject();
-
- bool performStep();
- void finalize();
-
- void createIntGrid(const std::string& name, int gridFlags = 0);
- void createRealGrid(const std::string& name, int gridFlags = 0);
- void createVec3Grid(const std::string& name, int gridFlags = 0);
- void createIntGrid(const std::string& name, Grid<int> *grid);
- void createRealGrid(const std::string& name, Grid<Real> *grid);
- void createVec3Grid(const std::string& name, Grid<Vec3> *grid);
- void createNoiseField(const std::string& name, const Vec3& posOffset, const Vec3& posScale, Real valOffset, Real valScale, Real timeAnim);
- void addPlugin(const std::string& name, const PluginArgument& arg = PluginArgument());
- void addInitPlugin(const std::string& name, const PluginArgument& arg = PluginArgument());
- void addEndPlugin(const std::string& name, const PluginArgument& arg = PluginArgument());
- SolverParams& getParams() { return *(mSolver->getParams()); }
- const SolverParams& getParams() const { return *(mSolver->getParams()); }
- void forceInit();
- void addStandardSolverGrids();
-
- protected:
- void init(const std::string& name, const nVec3i& gridSize, int gridFlags = 0);
- SolverPlugin* createPlugin(const std::string& name, const PluginArgument&);
-
- FluidSolver* mSolver;
- std::vector<SolverPlugin*> mInitPlugins, mPlugins, mEndPlugins;
- bool mStarted;
- };
-};
-
-#endif
diff --git a/intern/smoke/intern/source/solverparams.cpp b/intern/smoke/intern/source/solverparams.cpp
deleted file mode 100644
index eb0604fca13..00000000000
--- a/intern/smoke/intern/source/solverparams.cpp
+++ /dev/null
@@ -1,280 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Class to store solver parameters
- *
- *****************************************************************************/
-
-#include "solverparams.h"
-#include "paramset.h"
-#include "waveletnoise.h"
-namespace DDF {
-
-//*****************************************************************************
-// default init
-SolverParams::SolverParams(const std::string& name) :
- mName(name),
- mMaxTimestep(0.5), mCflFactor(1.),
- //mSurfaceTracker(0), // by default, no surface
- mTimestepLevelsetFactor(1.0),
- mCgMaxIterFac(1.), mCgAccuracy(5.0 * gVecEpsilon),
- mTimestepAnim(0.5), mAnimOutputFile("animout_"), mOutputProgram(0),
- mStepFactor(1),
- mGridsReal(), mGridsVec3(), mGridsInt(),
- mInited(false), mQuit(false), mSimTime(-1.),
- mTimestep(0.5),
- mGridSize(-1), mDeltaX(-1.),
- mDimMax(-1), // updated in setSize
- mAdaptInit(false), mAdaptDtScale(1.),
- mAdapGridMultiplier(-1.),
- mNoiseFields(),
- mDivergenceCorrection(0.),
- mpFluidSolver(NULL)
-{
- mU0 = Vec3(0.);
-};
-
-// adapt init from another solver (eg set timestep)
-bool SolverParams::adaptInit(const SolverParams* const otherParams)
-{
- // use mAdapGridMultiplier ?
- if(mAdapGridMultiplier > 0.) {
- // round size
- nVec3i s = otherParams->getGridSize();
- Vec3 ds = Vec3(s[0],s[1],s[2]);
- ds *= mAdapGridMultiplier;
- setGridSize( nVec3i( (int)ds[0], (int)ds[1], (int)ds[2] ));
- }
-
- mAdaptDtScale = 1. / (double)otherParams->mDimMax * (double)mDimMax;
- mTimestep = otherParams->mTimestep * mAdaptDtScale;
- debMsg("SolverParams","adaptInit, gridsize="<<mGridSize<<", dt="<<mTimestep );
-
- mAdaptInit = true;
-
- return true;
-}
-
-//*****************************************************************************
-// free grids etc.
-SolverParams::~SolverParams() {
- for(std::map<string, Grid<Real>* >::iterator iter=mGridsReal.begin();
- iter!=mGridsReal.end(); iter++) {
- if( (*iter).second && !((*iter).second->getGridFlags() & DDF_GRID_NO_FREE))
- delete (*iter).second;
- }
- mGridsReal.clear();
- for(std::map<string, Grid<int>* >::iterator iter=mGridsInt.begin();
- iter!=mGridsInt.end(); iter++) {
- if( (*iter).second && !((*iter).second->getGridFlags() & DDF_GRID_NO_FREE))
- delete (*iter).second;
- }
- mGridsInt.clear();
- for(std::map<string, Grid<Vec3>* >::iterator iter=mGridsVec3.begin();
- iter!=mGridsVec3.end(); iter++) {
- if( (*iter).second && !((*iter).second->getGridFlags() & DDF_GRID_NO_FREE))
- delete (*iter).second;
- }
- mGridsVec3.clear();
-}
-
-bool SolverParams::verifyInit(string caller) {
- if(!mInited) {
- errMsg("SolverParams::verifyInit","Not inited at all! "<<caller);
- return false;
- }
- if(mGridSize[0]<=0 ||
- mGridSize[1]<=0 ||
- mGridSize[2]<=0 ||
- mGridSize[0]>10000 ||
- mGridSize[1]>10000 ||
- mGridSize[2]>10000 ||
- false ) {
- errMsg("SolverParams::verifyInit","Invalid gridsize "<<mGridSize);
- return false;
- }
- return true;
-}
-
-
-// initialize from parsed paramset
-bool SolverParams::initFromParamSet(const ParamSet &params) {
- // reset values, might be copied from previous settings
- mInited =false;
- mGridsReal.clear();
- mGridsInt.clear();
- mGridsVec3.clear();
- mpFluidSolver = NULL;
-
- // either init from vector or int
- DDF::Vec3 sizeVec = params.FindOneVector("gridsize", vec2R(mGridSize) );
- int sizeInt = params.FindOneInt("gridsize", -1);
- if(sizeInt>0) {
- setGridSize( DDF::nVec3i(sizeInt) );
- } else {
- setGridSize( vec2I(sizeVec) );
- }
- // use adapt init multiplier? -1 for off
- mAdapGridMultiplier = params.FindOneFloat("adap-grid-multiplier", mAdapGridMultiplier);
-
- mU0 = params.FindOneVector("u0", mU0);
- mHostVorticitySystem = params.FindOneInt("host-vorticity-system", 0) != 0;
-
- mTimestep = params.FindOneFloat("timestep", mTimestep );
- mMaxTimestep = mTimestep;
- mCflFactor = params.FindOneFloat("cflfactor", mCflFactor );
- mTimestepLevelsetFactor = params.FindOneFloat("timestep_levelset_factor", mTimestepLevelsetFactor );
-
- mCgMaxIterFac = params.FindOneFloat("cg-max-iter-fac", mCgMaxIterFac );
- mCgAccuracy = params.FindOneFloat("cg-accuracy", mCgAccuracy );
-
- mOutputProgram = params.FindOneInt("outputprogram", mOutputProgram);
- if(mOutputProgram == 1) debMsg("Params","Output program set to blender...");
-
- mTimestepAnim = params.FindOneFloat("timestep_anim", mTimestepAnim );
- if (mAdapGridMultiplier>1) mTimestepAnim*=mAdapGridMultiplier;
-
- mAnimOutputFile = params.FindOneString("animfile", mAnimOutputFile);
- mStepFactor = params.FindOneInt("step-factor", mStepFactor);
-
- setInited(true);
- // check sanity... (requires mInited = true)
- if(!verifyInit("ddfParseGlobals")) {
- setInited(false);
- }
-
- return isInited();
-}
-
-//*****************************************************************************
-// get grids
-
-Grid<int>* SolverParams::getGridInt(std::string name) {
- if(mGridsInt.find(name) != mGridsInt.end() && mGridsInt[name]!=NULL) {
- return mGridsInt[name];
- } else {
- errFatal("SolverParams::getGridInt","'"<< name <<"' int grid required! "<<this->toString(), SIMWORLD_GRIDERROR);
- }
- return NULL;
-}
-
-Grid<Real>* SolverParams::getGridReal(std::string name) {
- if(mGridsReal.find(name) != mGridsReal.end() && mGridsReal[name]!=NULL) {
- return mGridsReal[name];
- } else {
- errFatal("SolverParams::getGridReal","'"<< name <<"' real grid required! "<<this->toString(), SIMWORLD_GRIDERROR);
- }
- return NULL;
-}
-
-Grid<Vec3>* SolverParams::getGridVec3(std::string name) {
- if(mGridsVec3.find(name) != mGridsVec3.end() && mGridsVec3[name]!=NULL) {
- return mGridsVec3[name];
- } else {
- errFatal("SolverParams::getGridVec3","'"<< name <<"' vec3 grid required! "<<this->toString(), SIMWORLD_GRIDERROR);
- }
- return NULL;
-}
-
-
-void SolverParams::setGridInt(std::string name, Grid<int>* set) {
- mGridsInt[name] = set;
-}
-void SolverParams::setGridReal(std::string name, Grid<Real>* set) {
- mGridsReal[name] = set;
-}
-void SolverParams::setGridVec3(std::string name, Grid<Vec3>* set) {
- mGridsVec3[name] = set;
-}
-
-bool SolverParams::haveGridInt(std::string name) {
- if(mGridsInt.find(name) != mGridsInt.end() && mGridsInt[name]!=NULL) {
- return true;
- }
- return false;
- //return ( mGridsInt[name] != NULL);
-}
-bool SolverParams::haveGridReal(std::string name) {
- if(mGridsReal.find(name) != mGridsReal.end() && mGridsReal[name]!=NULL) {
- return true;
- }
- return false;
- //return ( mGridsReal[name] != NULL);
-}
-bool SolverParams::haveGridVec3(std::string name) {
- if(mGridsVec3.find(name) != mGridsVec3.end() && mGridsVec3[name]!=NULL) {
- return true;
- }
- return false;
- //return ( mGridsVec3[name] != NULL);
-}
-bool SolverParams::haveGridAny(std::string name) {
- return ( haveGridInt(name) ||
- haveGridReal(name) ||
- haveGridVec3(name) );
-}
-
-//*****************************************************************************
-// noise fields
-
-void SolverParams::addNoiseField(WAVELETNOISE::WaveletNoiseField* f, std::string name)
-{
- mNoiseFields[name] = f;
- Real dt = mNoiseFields[name]->getTimeAnim();
- // rescaling not necessary anymore
- //debMsg("ADAP"," dt="<<dt<<" scale="<<mAdaptDtScale );
- mNoiseFields[name]->setTimeAnim( dt );
-}
-
-WAVELETNOISE::WaveletNoiseField* SolverParams::getNoiseField(std::string name) {
- if(mNoiseFields.find(name) != mNoiseFields.end() && mNoiseFields[name]!=NULL) {
- return mNoiseFields[name];
- } else {
- errFatal("SolverParams::getNoiseField","'"<< name <<"' noise field required! "<<this->toString(), SIMWORLD_GRIDERROR);
- }
- return NULL;
-}
-
-
-// increase noise times
-void SolverParams::addToNoiseTime(Real dt) {
-
- // scale by size because time anim is essentially
- // a diagonal movement...
- const Real dtFac = 1./(Real)mDimMax;
-
- for(std::map<std::string, WAVELETNOISE::WaveletNoiseField*>::iterator
- iter=mNoiseFields.begin(); iter != mNoiseFields.end(); iter++) {
- WAVELETNOISE::WaveletNoiseField* pntval = (WAVELETNOISE::WaveletNoiseField*)( (*iter).second );
-
- //debMsg("SolverParams","addToNoiseTime, increased by "<<dt);
- pntval->increaseTime(dt * dtFac);
- //pntval->increaseTime(1.);
- }
-}
-
-//*****************************************************************************
-// helper
-
-//void helperPrintMap(std::map<std::string, T*>& pmap, std::string caller) {
-std::string SolverParams::printGridMaps() {
- std::ostringstream out;
- out << helperPrintMap(mGridsInt,"SolverParams::printGridMaps - int");
- out << helperPrintMap(mGridsReal,"SolverParams::printGridMaps - real");
- out << helperPrintMap(mGridsVec3,"SolverParams::printGridMaps - vec3");
- return out.str();
-}
-
-std::string SolverParams::toString() {
- std::ostringstream out;
- out << "SolverParams: gridsize="<<mGridSize<<" dt="<<mTimestep<<" cflfac="<<mCflFactor ;
- return out.str();
-}
-
-} // DDF
-
diff --git a/intern/smoke/intern/source/solverparams.h b/intern/smoke/intern/source/solverparams.h
deleted file mode 100644
index 2edf7373edd..00000000000
--- a/intern/smoke/intern/source/solverparams.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Class to store solver parameters
- *
- *****************************************************************************/
-
-#ifndef DDF_SOLVERPARAMS_H
-#define DDF_SOLVERPARAMS_H
-
-#include "grid.h"
-class ParamSet;
-
-namespace WAVELETNOISE { class WaveletNoiseField; }
-
-namespace DDF {
-
-class GeomFile;
-class FluidSolver;
-
-
-class SolverParams {
- public:
- // cons
- SolverParams(const std::string& name="");
- // des
- ~SolverParams();
- // check that globals have been inited, and are ok
- bool verifyInit(string caller);
- // initializer from parsed paramset
- bool initFromParamSet(const ParamSet &params);
- // adapt init from another solver (eg set timestep)
- bool adaptInit(const SolverParams* const otherParams);
-
- // solver name (from config)
- std::string mName;
-
- // time step (maximal value, might be smaller due to cflfac)
- Real mMaxTimestep;
- // cfl multiplier to change time step according to max velocitites
- Real mCflFactor;
-
- // size of timestep for level set tracker (mTimestep * factor)
- Real mTimestepLevelsetFactor;
-
- // cg pressure solver control: max iteration factor
- Real mCgMaxIterFac;
- // desired accuracy
- Real mCgAccuracy;
-
- //! time step for animation output (<0 for no output)
- Real mTimestepAnim;
- //! output name prefix
- std::string mAnimOutputFile;
- //! output for blender or other program?
- int mOutputProgram;
-
- //! step factor for fixed dt solver comparison
- int mStepFactor;
-
- // VP stuff
- Vec3 mU0;
- bool mHostVorticitySystem;
-
- // grids
- std::map<string, Grid<Real>* > mGridsReal;
- std::map<string, Grid<Vec3>* > mGridsVec3;
- std::map<string, Grid<int>* > mGridsInt;
-
- //! access functions
- void setInited(bool set) { mInited=set; }
- bool isInited() const { return mInited; }
- void setQuit(bool set) { mQuit=set; }
- bool getQuit() const { return mQuit; }
- void setFluidSolver(FluidSolver* set) { mpFluidSolver=set; }
- FluidSolver* getFluidSolver() const { return mpFluidSolver; }
-
- Real getDt() const { return mTimestep; }
- Real getTimestep() const { return mTimestep; }
- void setTimestep(Real set) { mTimestep = set; }
-
- //! get/set grids in a secure(er) way
- Grid<int>* getGridInt(std::string name);
- Grid<Real>* getGridReal(std::string name);
- Grid<Vec3>* getGridVec3(std::string name);
- void setGridInt(std::string name, Grid<int>* set);
- void setGridReal(std::string name, Grid<Real>* set);
- void setGridVec3(std::string name, Grid<Vec3>* set);
- void getGridType(std::string name, Grid<int>* &set) { set = getGridInt(name); };
- void getGridType(std::string name, Grid<Real>* &set) { set = getGridReal(name); };
- void getGridType(std::string name, Grid<Vec3>* &set) { set = getGridVec3(name); };
-
- //! get noise field
- WAVELETNOISE::WaveletNoiseField* getNoiseField(std::string name);
- //! add noise field
- void addNoiseField(WAVELETNOISE::WaveletNoiseField* f, std::string name);
- void addToNoiseTime(Real dt);
-
- //! debug output
- std::string printGridMaps();
- std::string toString();
- //! check if gridname exists
- bool haveGridInt(std::string name);
- bool haveGridReal(std::string name);
- bool haveGridVec3(std::string name);
- bool haveGridAny(std::string name);
-
- void setGridSize(nVec3i set) { mGridSize=set; mDimMax=VMAX(set); mDeltaX=1./(Real)mDimMax; }
- nVec3i getGridSize() const { return mGridSize; }
- // compute spatial discretization, currently given by dimMax,
- // might differ in future
- inline Real getDeltaX() const { return mDeltaX; }
- // max dim.
- inline int getDimMax() const { return mDimMax; }
-
- // simulation time
- inline Real getSimTime() const { return mSimTime; }
- inline void addToSimTime(Real add) { mSimTime += add; }
-
- // div. corr.
- inline Real getDivergenceCorrection() const { return mDivergenceCorrection; }
- inline void setDivergenceCorrection(Real set) { mDivergenceCorrection = set; }
-
- inline Real getMultiplier() { return mAdapGridMultiplier; }
- inline void setMultiplier(Real v) { mAdapGridMultiplier = v; }
-
- protected:
- // global settings
- bool mInited;
- // quit?
- bool mQuit;
- // current time
- Real mSimTime;
-
- // time step (maximal value, might be smaller due to cflfac)
- Real mTimestep;
-
- // size of simulation grid
- nVec3i mGridSize;
- // size of a cell, spatial discr. dx, set by gridsize
- Real mDeltaX;
- // max. dimension
- int mDimMax;
-
- // adapt init
- bool mAdaptInit;
- double mAdaptDtScale;
- // gridsize multiplier for adapted init
- Real mAdapGridMultiplier;
-
- //! noise field storage
- std::map<string, WAVELETNOISE::WaveletNoiseField* > mNoiseFields;
-
- //! pass divergence correction on to poisson solver, e.g. for volume correction
- Real mDivergenceCorrection;
-
- //! simplify access to "parent" fluid solver
- FluidSolver* mpFluidSolver;
-};
-
-}; // DDF
-
-#endif // DDF_SOLVERPARAMS_H
-
diff --git a/intern/smoke/intern/source/solverplugin.h b/intern/smoke/intern/source/solverplugin.h
deleted file mode 100644
index 44467966f25..00000000000
--- a/intern/smoke/intern/source/solverplugin.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Base class for Plugins
- *
- *****************************************************************************/
-
-#ifndef DDF_SOLVERPLUGIN_H
-#define DDF_SOLVERPLUGIN_H
-
-#include "globals.h"
-class ParamSet;
-
-namespace DDF {
-class SolverParams;
-
-// base functions for a plugin
-// plugin handling implementation in solver.cpp,
-// base methods implemented in stdplugins.cpp
-class SolverPlugin {
- public:
- // cons
- SolverPlugin();
- // des
- virtual ~SolverPlugin();
-
- // get parameters, e.g. grid names
- virtual bool parseParams(const ParamSet& params);
- // init plugin, return failure
- virtual bool initPlugin() = 0;
- // optional method, called after main loop is finished
- virtual void finish();
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) = 0;
-
- inline void setPluginParams(SolverParams* set) { mpPlParams=set; }
-
- inline void setName(std::string set) { mName=set; }
- inline std::string getName() { return mName; }
-
- // check for start & end time of plugin
- bool isCurrentlyActive(double t);
-
- static SolverPlugin* makePlugin(const std::string& name);
-
- protected:
- // parameter storage
- SolverParams* mpPlParams;
-
- // store plugin name for debugging
- std::string mName;
-
- // debugging - enable plugin only in an interval
- Real mTimeStart, mTimeStop;
-
- bool mWasActive;
- Real mSingleTime;
-
- Real mInterval, mLastActive;
-
-}; // SolverPlugin
-
-
-// create one of the plugins, e.g., advection or init steps
-
-// stdplugins.cpp
-SolverPlugin* MakeStandardPlugin(std::string name);
-
-// stdplugins.cpp
-SolverPlugin* MakeAdvectionPlugin(std::string name);
-
-// initplugins.cpp
-SolverPlugin* MakeInitPlugin(std::string name);
-
-// vortexplugins.cpp
-SolverPlugin* MakeVortexPlugin(std::string name);
-
-// fileio.cpp
-SolverPlugin* MakeIoPlugin(std::string name);
-
-// poissonsolvers.cpp
-SolverPlugin* MakePoissionSolverPlugins(std::string name);
-
-// animplugins.cpp
-SolverPlugin* MakeAnimPlugin(std::string name);
-
-// smokeplugins.cpp
-SolverPlugin* MakeSmokePlugin(std::string name);
-
-// helper function for plugins moving data from one grid to another
-bool swapGrids(SolverParams* params, std::string mGrid1, std::string mGrid2);
-
-//************************************
-// invoke plugins
-inline SolverPlugin* SolverPlugin::makePlugin(const std::string& name)
-{
- SolverPlugin *plugin = MakeStandardPlugin(name);
- if(!plugin) plugin = MakeInitPlugin(name);
- if(!plugin) plugin = MakeAdvectionPlugin(name);
- if(!plugin) plugin = MakeIoPlugin(name);
- if(!plugin) plugin = MakePoissionSolverPlugins(name);
- if(!plugin) plugin = MakeVortexPlugin(name);
- if(!plugin) plugin = MakeAnimPlugin(name);
- if(!plugin) plugin = MakeSmokePlugin(name);
-
- if(plugin) plugin->setName(name);
- return plugin;
-}
-}; // DDF
-
-
-#endif // DDF_SOLVERPLUGIN_H
-
-
diff --git a/intern/smoke/intern/source/stdplugins.cpp b/intern/smoke/intern/source/stdplugins.cpp
deleted file mode 100644
index c7bed7f0bdb..00000000000
--- a/intern/smoke/intern/source/stdplugins.cpp
+++ /dev/null
@@ -1,429 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Basic plugins (copy, set_bounds, etc.)
- *
- *****************************************************************************/
-
-#include "fluidsolver.h"
-#include "solverplugin.h"
-#include "paramset.h"
-
-#include "matrixbase.h"
-
-// safety boundary for semi lagrange advection step
-#define SLADVBOUND 2
-
-namespace DDF {
-
-static inline bool doSetVelocity(int nbflag, int myflag) {
- if (fgIsObstacle(nbflag) && !fgIsInflow(myflag) ) {
- return false;
- }
- return true;
-}
-
-//*****************************************************************************
-
-class fsSetNoslipBcs : public GridOpBaseFlagbord<1> {
- public:
- fsSetNoslipBcs(FlagGrid *flags, Grid<Vec3> *src) :
- GridOpBaseFlagbord<1>(), mpVecgrid(src) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsSetNoslipBcs() { };
- void resetVariables() { };
- void buildCallList() {
- gaVecgrid.gridAccInit(mpVecgrid, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- // set velocity at NB cell, given current flag myflag?
- inline bool __doSetVelocity(int nbflag, int myflag) {
- if (fgIsObstacle(nbflag) && !fgIsInflow(myflag) ) {
- return false;
- }
- return true;
- }
-
- // add forces and update empty cells free surface boundaries
- inline void operator() (int i, int j, int k) {
- int myFlag = getFlagAcc()(i,j,k);
- Vec3& vel = gaVecgrid.write(i,j,k);
-
- if ( !doSetVelocity(myFlag, myFlag) ) {
- vel = Vec3(0.);
- return;
- }
-
- if (fgIsEmpty(myFlag) )
- return;
-
- if (fgIsFluid(myFlag) ) {
- // only add for faces that are between fluid/fluid fl/empty cells
- if ( !doSetVelocity(getFlagAcc()(i-1,j,k), myFlag) ) { vel[0] = 0.; }
-
- if ( !doSetVelocity(getFlagAcc()(i,j-1,k), myFlag) ) { vel[1] = 0.; }
-
- if ( (!doSetVelocity(getFlagAcc()(i,j,k-1), myFlag) ) && (gDim==3) ) { vel[2] = 0.; }
-
- return;
- }
- };
- void reduce(fsSetNoslipBcs &op) { };
-
- protected:
- Grid<Vec3> *mpVecgrid;
- GridAccessor<Vec3,1> gaVecgrid;
- Vec3 mForce;
- int mModFunc;
- Real mThresh;
-
-}; // fsSetNoslipBcs */
-
-// add forces to vels
-class spSetNoslipBcs : public SolverPlugin {
- public:
- spSetNoslipBcs() : SolverPlugin(), mVel("-unnamed1-") { };
- ~spSetNoslipBcs() { };
- virtual bool initPlugin() { return true; };
- virtual bool parseParams(const ParamSet& params) {
- mVel = params.FindOneString("grid", mVel );
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spSetNoslipBcs","step "<<dt<<" velsgrid:"<<mVel<<" to "<<mVel);
- Grid<Vec3>* velsrc = mpPlParams->getGridVec3(mVel);
- fsSetNoslipBcs(mpPlParams->getFluidSolver()->getGridFlags(), velsrc );
- return true;
- };
- protected:
- std::string mVel;
-};
-
-// copy source grid to destination
-class spluginCopyGrid : public SolverPlugin {
- public:
- spluginCopyGrid() : SolverPlugin(),
- mSrc("-unnamed1-"),
- mDest("-unnamed2-")
- { };
- ~spluginCopyGrid() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mDest = params.FindOneString("dest", mDest );
- mSrc = params.FindOneString("src", mSrc );
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spluginCopyGrid","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginCopyGrid","step "<<dt);
- if(mpPlParams->haveGridInt(mSrc) && 1) {
- Grid<int>* dest = mpPlParams->getGridInt(mDest);
- Grid<int>* src = mpPlParams->getGridInt(mSrc);
- goCopyGrid<int>(dest, src);
- } else if(mpPlParams->haveGridReal(mSrc) && 1) {
- Grid<Real>* dest = mpPlParams->getGridReal(mDest);
- Grid<Real>* src = mpPlParams->getGridReal(mSrc);
- goCopyGrid<Real>(dest, src);
- } else if(mpPlParams->haveGridVec3(mSrc) && 1) {
- Grid<Vec3>* dest = mpPlParams->getGridVec3(mDest);
- Grid<Vec3>* src = mpPlParams->getGridVec3(mSrc);
- goCopyGrid<Vec3>(dest, src);
- }
- return true;
- };
-
- protected:
- std::string mSrc, mDest;
-};
-
-// copy one element of a vector to a scalar grid
-template<class Scalar,int NUM>
-class goGetVec3NormToScalar : public GridOpBase {
- public:
- goGetVec3NormToScalar(Grid<Scalar> *gDst, Grid<Vec3> *gSrc) : GridOpBase() {
- mpDst = gDst;
- mpSrc = gSrc;
- applyOperatorToGridsWithoutFlags(this, mpDst);
- };
- ~goGetVec3NormToScalar() { };
- void resetVariables() { };
- void buildCallList() {
- gaDst.gridAccInit(mpDst, AM_WRITE, gaCalls);
- gaSrc.gridAccInit(mpSrc, AM_READ, gaCalls);
- setNullFlagPointer();
- };
- inline void operator() (int i, int j, int k) {
- gaDst.write(i,j,k) = norm(gaSrc(i,j,k));
- };
- void reduce(goGetVec3NormToScalar &op) { };
- protected:
- Grid<Scalar> *mpDst;
- Grid<Vec3> *mpSrc;
- GridAccessor<Scalar,0> gaDst;
- GridAccessor<Vec3,0> gaSrc;
-}; // goGetVec3NormToScalar */
-
-class spluginGetNorm : public SolverPlugin {
- public:
- spluginGetNorm() : SolverPlugin(),
- mSrc("-unnamed-"), mDest("-unnamed2-"),mode(0) { };
- ~spluginGetNorm() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mSrc = params.FindOneString("src", mSrc );
- mDest = params.FindOneString("dest", mDest );
- return true;
- };
- virtual bool initPlugin() { return true; };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginGetNorm","step "<<dt);
- Grid<int>* flags = mpPlParams->getGridInt("flags");
-
- Grid<Vec3>* src = mpPlParams->getGridVec3(mSrc);
- Grid<Real>* dest = mpPlParams->getGridReal(mDest);
- goGetVec3NormToScalar<Real,0>(dest,src);
- return true;
- };
-
- protected:
- // grid names to swap
- std::string mSrc,mDest;
- int mode;
-};
-
-// Obtain time-averaged field
-class spluginAverage : public SolverPlugin {
- public:
- spluginAverage() : SolverPlugin(), mSummed(0),mStrideCount(0) { };
- ~spluginAverage() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("gridname", "vel-curr");
- mSumGrid = params.FindOneString("sumgrid", "");
- mFrom = params.FindOneInt("from", 0);
- mStride = params.FindOneInt("stride",1);
- mPostQuit = params.FindOneInt("post-quit", 0) != 0;
- mFrames = params.FindOneInt("frames", 100);
- mStrideCount = mStride-1;
- return true;
- };
- virtual bool initPlugin() { return true; };
-
- virtual void finish() {
- if (mSummed == 0) return;
- Grid<int>* flags = mpPlParams->getGridInt("flags");
- if (mpPlParams->haveGridVec3(mGrid))
- goScale<Vec3>(mpPlParams->getGridVec3(mSumGrid), flags, 1./(Real)mSummed);
- else if (mpPlParams->haveGridReal(mGrid))
- goScale<Real>(mpPlParams->getGridReal(mSumGrid), flags, 1./(Real)mSummed);
- else
- errMsg("spluginAverage","can't find grid " << mGrid << " or wrong type");
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- if (mFrom > 0) {
- debMsg("spluginAverage","will start in " << mFrom << " frames");
- --mFrom;
- } else {
- if (mSummed < mFrames) {
- ++mStrideCount;
- if (mStrideCount == mStride) {
- mStrideCount = 0;
- debMsg("spluginAverage", "taking snapshot -- " << mSummed+1 << " frames recorded so far" );
-
- Grid<int>* flags = mpPlParams->getGridInt("flags");
- if (mpPlParams->haveGridVec3(mGrid))
- goSum<Vec3>(mpPlParams->getGridVec3(mSumGrid), mpPlParams->getGridVec3(mGrid), flags);
- else if (mpPlParams->haveGridReal(mGrid))
- goSum<Real>(mpPlParams->getGridReal(mSumGrid), mpPlParams->getGridReal(mGrid), flags);
- else
- errMsg("spluginAverage","can't find grid " << mGrid << " or wrong type");
- mSummed++;
- if (mSummed == mFrames && mPostQuit)
- mpPlParams->setQuit(true);
- }
- }
- }
- return true;
- };
-
- protected:
- // grid names to swap
- std::string mGrid, mSumGrid;
- int mSummed, mFrom, mFrames,mStride, mStrideCount;
- bool mPostQuit;
-};
-
-// Dummy plugin
-class spluginDummy : public SolverPlugin {
- public:
- spluginDummy() : SolverPlugin() { };
- ~spluginDummy() { };
-
- virtual bool parseParams(const ParamSet& params) { return true; }
- virtual bool initPlugin() { return true; };
-
- virtual bool performStep(Real dt) { return true; };
-};
-
-
-//*****************************************************************************
-
-// solver plugin implementation
-SolverPlugin::SolverPlugin() :
- mpPlParams(NULL), mName("-"), mTimeStart(-1.), mTimeStop(1.0e10),
- mWasActive(false), mSingleTime(-1.), mInterval(-1.), mLastActive(0.)
-{
-};
-
-SolverPlugin::~SolverPlugin() {
-};
-
-void SolverPlugin::finish() {
-};
-
-// get parameters, e.g. grid names
-bool SolverPlugin::parseParams(const ParamSet& params) {
- mTimeStart = params.FindOneFloat("plugin-start", mTimeStart );
- mTimeStop = params.FindOneFloat("plugin-stop", mTimeStop );
- mSingleTime = params.FindOneFloat("plugin-single-time", mSingleTime );
- mInterval = params.FindOneFloat("plugin-interval", mInterval );
- if(mTimeStop<mTimeStart) {
- mTimeStop = mTimeStart = -1.;
- }
-
- if (mSingleTime>=0.) {
- debMsg("SolverPlugin::parseParams","Single time active "<<mSingleTime);
- } else {
- if(mInterval>=0.) {
- debMsg("SolverPlugin::parseParams","Interval active "<<mInterval);
- mLastActive = -mInterval;
- if(mTimeStart!=-1.) {
- mLastActive = mTimeStart-mInterval;
- }
- }
- }
-
- return true;
-}
-
-// check for start & end time of plugin
-bool SolverPlugin::isCurrentlyActive(double t) {
- // all timings off, return true by default
- //if( mTimeStart<= -1. && mTimeStop>=1.0e10 && mSingleTime <= -1. ) { return true; }
-
- // else: single time?
- if(mSingleTime >= 0.) {
- if(t >= mSingleTime && !mWasActive) {
- mWasActive = true;
- return true;
- } else {
- return false;
- }
- }
-
- // else: times given & valid, check:
- if(t < mTimeStart || t > mTimeStop) {
- return false;
- }
-
- if(mInterval >= 0.) {
- if(t > mLastActive+mInterval) {
- mLastActive += mInterval;
- return true;
- } else {
- return false;
- }
- }
-
- return true;
-}
-
-//*****************************************************************************
-
-bool swapGrids(SolverParams* params, std::string mGrid1, std::string mGrid2)
-{
- if(0) debMsg("swapGrids","DEBUG: "<<params->printGridMaps() );
-
- // distinguish data types
- // replace pointers in maps, and then change
- // names in grid classes too!
- GridBase *g1=NULL, *g2=NULL;
- if(params->haveGridInt(mGrid1) && 1) {
- Grid<int>* tmp = params->getGridInt(mGrid1);
- Grid<int>* grid2 = params->getGridInt(mGrid2);
- params->setGridInt(mGrid1, grid2);
- params->setGridInt(mGrid2, tmp);
- g1 = tmp; g2 = grid2;
-
- //grid2->setName(mGrid1);
- //tmp->setName(mGrid2);
- } else if(params->haveGridReal(mGrid1) && 1) {
- Grid<Real>* tmp = params->getGridReal(mGrid1);
- Grid<Real>* grid2 = params->getGridReal(mGrid2);
- params->setGridReal(mGrid1, grid2);
- params->setGridReal(mGrid2, tmp);
- g1 = tmp; g2 = grid2;
-
- //grid2->setName(mGrid1);
- //tmp->setName(mGrid2);
- } else if(params->haveGridVec3(mGrid1) && 1) {
- Grid<Vec3>* tmp = params->getGridVec3(mGrid1);
- Grid<Vec3>* grid2 = params->getGridVec3(mGrid2);
- params->setGridVec3(mGrid1, grid2);
- params->setGridVec3(mGrid2, tmp);
- g1 = tmp; g2 = grid2;
- } else {
- return false;
- }
-
- int tmp1 = g1->getDisplayFlags();
- g1->setDisplayFlags( g2->getDisplayFlags() );
- g2->setDisplayFlags( tmp1 );
-
- g2->setName(mGrid1);
- g1->setName(mGrid2);
-
- if(0) debMsg("swapGrids","DEBUG: "<<params->printGridMaps() );
- return true;
-}
-
-
-
-// create one of the standard hard coded plugins
-SolverPlugin* MakeStandardPlugin(std::string name) {
- if(name.compare( "copy-grid")==0) {
- return new spluginCopyGrid;
- } else if(name.compare( "dummy")==0) {
- return new spluginDummy;
- } else if(name.compare( "set-noslip-bcs")==0) {
- return new spSetNoslipBcs;
- } else if(name.compare( "average" )==0) {
- return new spluginAverage;
- } else if(name.compare( string("get-vec3-norm") )==0) {
- return new spluginGetNorm;
- }
- return NULL;
-}
-
-
-} // end namespace DDF
-
diff --git a/intern/smoke/intern/source/vortexpart.cpp b/intern/smoke/intern/source/vortexpart.cpp
deleted file mode 100644
index f36afe5a2b5..00000000000
--- a/intern/smoke/intern/source/vortexpart.cpp
+++ /dev/null
@@ -1,667 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Vortex particle classes
- *
- *****************************************************************************/
-
-
-#include "vortexpart.h"
-
-// get rid of MSVC ambiguities be enforcing single precision
-#ifdef WIN32
-#define pow powf
-#endif
-
-#if DDF_DIMENSION==2
-#define FOR_KERNEL(rd) for (int j=-(rd),k=0,idx=0;j<=rd;++j) for (int i=-(rd);i<=rd;++i,++idx)
-#else
-#define FOR_KERNEL(rd) for (int k=-(rd),idx=0;k<=rd;++k) for (int j=-(rd);j<=rd;++j) for (int i=-(rd);i<=rd;++i,++idx)
-#endif
-
-using namespace std;
-namespace DDF {
-
-const Real PI = (Real)M_PI;
-const Real MININV=1e-8,MININV2=1e-16;
-inline Real SQR(DDF::Real x, DDF::Real y, DDF::Real z) { return x*x+y*y+z*z; }
-inline Real SQRn(DDF::Real x, DDF::Real y, DDF::Real z) { DDF::Real v=x*x+y*y+z*z; if(v<MININV2){x+=MININV;return x*x+y*y+z*z;} return v; }
-
-#ifdef DEBUG_VORTEXPATH
-std::list<LineElement> gVortexPath = std::list<LineElement>();
-#endif
-
-// ******************************************************************
-//
-// VORTEX PARTICLE CONSTANTS
-//
-// ******************************************************************
-
-const Real VortexParticleGaussian::msLogCutoff = sqrt(3.); // 3 is for cutoff at 1e-3 of the exponential term
-
-// workaround for missing erf function in win32 MSVC
-#ifndef WIN32
-const static Real VPGaussian_msAreaMult_erf = erf( VortexParticleGaussian::msLogCutoff);
-#else
-const static Real VPGaussian_msAreaMult_erf = 0.9953222650; // hard coded value for 1e-4 cutoff
-#endif
-
-#if DDF_DIMENSION==3
-const Real VortexParticleGaussian::msAreaMult = pow(PI, 1.5) * VPGaussian_msAreaMult_erf * exp(-1.);
-#else
-const Real VortexParticleGaussian::msAreaMult = 2.* PI * exp(-1.);
-#endif
-// move particles away from obstacles
-const Real VortexParticle::msRepulsion = .5;
-// attenuate particle near obstacles, remove amount of strength per timestep
-const Real VortexParticle::msAttenuation = 0.1;
-// if set to true, magnitude is preserved, otherwise decay is allowed
-const bool VortexParticle::msStretchingPreserve = false;
-
-// Default values, may be changed via plugin
-Real VortexParticle::msRadiusCascade = 2.; // split into particles of new_radius = radius/msRadiusCascade. If this param is small, many weak particles form
-Real VortexParticle::msDissipateRadius = 1.; // dissipate particles smaller than this radius
-Real VortexParticle::msDecayTime = 450.0; // factor to time before splitting
-Real VortexParticle::msInitialTime = 20.5; // factor to time before entering inertial subrange
-Vec3 VortexParticle::msU0 = Vec3(0.); // velocity scale (inflow speed etc.)
-RandomStream VorticitySystem::randStream(13322223);
-
-// ******************************************************************
-//
-// GENERAL PARTICLE FUNCTIONS
-//
-// ******************************************************************
-
-// irad is related to the kernel distribution. orad is the cutoff radius
-VortexParticle::VortexParticle(const Vec3& p, const Vec3& s, Real irad, Real orad)
- : mPos(p),mStrength(s),mForce(0.),mFlags(0),mIRad(irad),mORad(orad), mAttenuate(0.)
-{
- // time before entering inertial subrange
- Real meantime = msInitialTime * pow(norm(msU0),-1./3.);
- mTime = meantime * (1. + .5*(2.*VorticitySystem::rnd()-1.) );
-}
-
-inline void VortexParticle::advance(const Vec3& v)
-{
-#if DEBUG_VORTEXPATH==1
- LineElement le;
- le.p0 = mPos;
- mPos += v;
- le.p1 = mPos;
- Real c = std::max(std::max(fabs(mStrength.x),fabs(mStrength.y)),fabs(mStrength.z));
- le.r = fabs(mStrength.x)/c;
- le.g = fabs(mStrength.y)/c;
- le.b = fabs(mStrength.z)/c;
- le.a = 1.0;
- le.s = mIRad;
- gVortexPath.push_front(le);
-#else
- mPos += v;
-#endif
-}
-
-// calculate velocity gradient matrix at particles position by trilinear interpolation
-inline Vec3 velGradient(Grid<Vec3>* grid, const Vec3& pos, int idx)
-{
- Vec3 res;
- for (int n=0;n<3;n++)
- {
- // translate grid (MAC)
- Vec3 cpos (pos);
- cpos[n] += .5; cpos[idx] -= 0.5;
- nVec3i id(vec2I(cpos)), nid(id+1), nd(id), nnd(nid);
- Vec3 a (cpos-vec2R(id)), na (-a+1.);
- nd[n]++; nnd[n]++;
-
- // trilinear interpolation
- res[n] = na.x * na.y * na.z * ( (*grid)( nd.x, nd.y, nd.z)[idx]-(*grid)( id.x, id.y, id.z)[idx]) +
- na.x * na.y * a.z * ( (*grid)( nd.x, nd.y,nnd.z)[idx]-(*grid)( id.x, id.y,nid.z)[idx]) +
- na.x * a.y * na.z * ( (*grid)( nd.x,nnd.y, nd.z)[idx]-(*grid)( id.x,nid.y, id.z)[idx]) +
- na.x * a.y * a.z * ( (*grid)( nd.x,nnd.y,nnd.z)[idx]-(*grid)( id.x,nid.y,nid.z)[idx]) +
- a.x * na.y * na.z * ( (*grid)(nnd.x, nd.y, nd.z)[idx]-(*grid)(nid.x, id.y, id.z)[idx]) +
- a.x * na.y * a.z * ( (*grid)(nnd.x, nd.y,nnd.z)[idx]-(*grid)(nid.x, id.y,nid.z)[idx]) +
- a.x * a.y * na.z * ( (*grid)(nnd.x,nnd.y, nd.z)[idx]-(*grid)(nid.x,nid.y, id.z)[idx]) +
- a.x * a.y * a.z * ( (*grid)(nnd.x,nnd.y,nnd.z)[idx]-(*grid)(nid.x,nid.y,nid.z)[idx]);
- }
- return res;
-}
-
-// perform vortex stretching
-void VortexParticle::vortexStretch(Grid<Vec3>* pVel, Real dt, Real mult)
-{
- Vec3 spos = mPos*mult;
- // gradient
- Vec3 s;
- s.x = dot(mStrength,velGradient(pVel,spos,0));
- s.y = dot(mStrength,velGradient(pVel,spos,1));
- s.z = dot(mStrength,velGradient(pVel,spos,2));
-
- Vec3 nstr = mStrength + dt * s;
- Real oldStr2 = normNoSqrt(mStrength);
- Real newStr2 = normNoSqrt(nstr);
-
- // do not allow the magnitude to grow
- if (newStr2 > MININV2 && (newStr2 > oldStr2 || msStretchingPreserve))
- nstr *= sqrt(oldStr2 / newStr2);
-
- // apply vorticity update
- mStrength = nstr;
-}
-
-// reset the timer for decay; used after particle splitting etc.
-void VortexParticle::setDecayTimer()
-{
- Real meantime = msDecayTime * pow(norm(msU0),-1./3.) * ( pow(mIRad,-2./3.) - pow(mIRad * msRadiusCascade,-2./3.));
- mTime = meantime * (1. + .5*(2.*VorticitySystem::rnd()-1.) );
-}
-
-string VortexParticle::toString() {
- std::ostringstream out;
- out<< " pos="<<mPos<<" str="<<mStrength<<" radi="<<mIRad<<","<<mORad;
- return out.str();
-}
-
-
-// ******************************************************************
-//
-// GAUSSIAN PARTICLE [psi = a*b/2/exp(-r^2/b)]
-//
-// Kernel used in the paper with b := 2 sqrt(sigma)
-//
-// ******************************************************************
-
-// ATTENTION : For the 2D kernel, some derivations are obsolete. Better doublecheck before using 2D !!
-
-static float gAvgStr=0., gAvgStrCnt=0.;
-VortexParticleGaussian::VortexParticleGaussian(const Vec3& pos, const Vec3& strength, Real irad)
- : VortexParticle(pos,strength,irad, msLogCutoff*irad)
-{
- mSigma = irad*irad; // w is zero at b=irad^2
-
- // measure average strengths
- float str = norm(strength);
- gAvgStr += str;
- gAvgStrCnt += 1.;
-
- printf("\n-> new particle : radius %g/%g strength [%g %g %g], avg %g,%g\n ",mIRad,mORad,strength.x,strength.y,strength.z, (gAvgStr/gAvgStrCnt), gAvgStrCnt);
-}
-
-// Overlay desired vorticity of all kernels in temporary global grid
-// using eq.13 in the paper
-void VortexParticleGaussian::buildReference(Grid<Vec3>* pTemp, FlagGrid* flags, Real mult, bool doForces)
-{
- // precompute frequently used constants
- int irad = 1+(int)ceilf(mIRad*mult);
- Real mult2=mult*mult, irad2 = mIRad*mIRad*mult2, isig=-1.0/(mSigma*mult2);
- Vec3 spos = mPos*mult;
- nVec3i apos = vec2I(spos);
- Vec3 subpos = vec2R(apos)-spos;
- if (gDim==2) {subpos.z = 0; apos.z = (int)mPos.z;}
- Vec3 str = mStrength * (2.0 / mSigma);
- Vec3 ndir(mStrength);
- Real strength = normalize(ndir);
-
- // construct kernel
- int totalSum=0, obsSum=0,freeSum=0;
- Vec3 center(0.);
- FOR_KERNEL(irad)
- {
- int x=apos.x+i, y=apos.y+j, z=apos.z+k;
- Vec3 pa(subpos.x+i,subpos.y+j,subpos.z+k);
- Real r2= SQR(pa.x,pa.y,pa.z);
- if (r2 < irad2)
- {
- if (flags->checkIndexValid(x,y,z))
- {
- // Evaluate Kernel
- Real dz= dot(pa,ndir), rho2 = r2 - dz*dz;
- Real gauss = (-rho2 + mSigma) * exp(isig * r2);
- if (gauss>0)
- (*pTemp)(x,y,z) += str * gauss;
-
- // Calculate overlap with air or obstacles
- if (!doForces) continue;
- if (fgIsEmpty(flags->getGlobal(x,y,z)))
- freeSum++;
- if (fgIsObstacle(flags->getGlobal(x,y,z)))
- {
- obsSum++;
- center += Vec3(x,y,z);
- }
- // Delete particles at inflow
- if ((flags->getGlobal(x,y,z) & FINFLOW) != 0) {markDelete();}
- totalSum++;
- }
- else {markDelete();}
- }
- }
-
- mForce=0.;
- mAttenuate=0.;
- // Calculate repulsion force and delete invalid particles
- if (doForces)
- {
- // Delete below dissipation radius
- if (totalSum <= 1 || mIRad <= msDissipateRadius)
- {markDelete(); }
- else {
- Real obsPart = (Real)obsSum/(Real)totalSum, freePart = (Real)freeSum/(Real)totalSum;
- // Delete particles in the air or in obstacles
- if (freePart > 0.5 || obsPart > 0.7)
- {markDelete();}
- else if (obsSum != 0 || freeSum != 0)
- {
- // Derive origin of repulsion force
- Vec3 diff = spos - (center/obsSum);
- normalize(diff);
- mForce = obsPart * diff;
- mAttenuate = (obsPart + freePart) * msAttenuation;
-#if DDF_DIMENSION==2
- mForce.z = 0.;
-#endif
- }
- /*std::cout << "totalSum " << totalSum << " obsPart " << obsPart << " freePart " << freePart << std::endl;
- std::cout << "force : " << mForce << " attenuate " << mAttenuate << std::endl;*/
- }
- }
-}
-
-// merge current particle with particle v
-// total vorticity and energy per volume are conserved
-bool VortexParticleGaussian::merge(VortexParticle* v)
-{
-#if DDF_DIMENSION==2
- Real aA = mIRad*mIRad, bA = v->getRadius()*v->getRadius();
-#else
- Real aA = mIRad*mIRad*mIRad, bA = v->getRadius()*v->getRadius()*v->getRadius();
-#endif
- //printf("\n* ---------------- MERGING\n[%g %g %g] r%g + [%g %g %g] r%g",mStrength.x,mStrength.y,mStrength.z,mIRad,v->getStrength().x,v->getStrength().y,v->getStrength().z,v->getRadius());
-
- // derive new magnitude by conservation laws
- const Vec3& aS = mStrength, bS = v->getStrength();
- Real midRatio = 0.5 * (norm(aS)/mIRad + norm(bS)/v->getRadius());
- Real magnitude = norm (aA * aS + bA * bS);
-
- // new radius and volume
- Real r = pow ( magnitude/midRatio, 1./(1.+(Real)gDim));
- Real A = (gDim==2) ? (r*r) : (r*r*r);
-
- // obtain direction by weighted average
- mStrength = aS * (aA/A) + bS * (bA/A);
- mIRad = r;
- mORad = msLogCutoff * mIRad;
- mSigma = r*r;
-
- // average timers, enter inertial subrange
- if ((v->getFlags() & FInertial) != 0) mFlags |= FInertial;
- mTime = 0.5 * (mTime + v->getTime());
-
- //printf(" -> [%g %g %g] r%g\n\n",mStrength.x,mStrength.y,mStrength.z,mIRad);
- return true;
-}
-
-// Split particle
-// total vorticity and energy per volume are conserved
-VortexParticle* VortexParticleGaussian::split()
-{
- // obtain new radius depending on the chosen cascade level
- Real bMult = 1.0 / (msRadiusCascade*msRadiusCascade);
- // adapt strength using Kolmogorov law
- Real aMult = sqrt(0.5) * pow(msRadiusCascade,(Real)gDim-5./6.);
-
- // set new radii and strength
- mSigma *= bMult;
- mIRad = sqrt(mSigma);
- mORad = msLogCutoff * mIRad;
- mStrength *= aMult;
-
- VortexParticle *p = new VortexParticleGaussian(mPos, mStrength, mIRad);
- p->getFlags() |= FInertial; // after splitting, always enter inertial subrange
-
- return p;
-}
-
-// velocity field induces by the kernel
-// (eq. 12 in the paper)
-// helper function for applyForce()
-inline Vec3 gaussianKernel(const Vec3& pa, Real isig, Real magnitude,const Vec3& sdir)
-{
- Real r2 = SQR(pa.x,pa.y,pa.z);
- Real z = dot(pa,sdir), z2=z*z;
- Real rho2 = r2-z2;
- if (rho2 > MININV2 && MININV2)
- {
- Vec3 ephi = cross(sdir,pa);
- Real s = magnitude * sqrt(rho2/r2) * exp(r2*isig);
- return ephi*s;
- }
- return Vec3(0.);
-}
-
-// Apply the kernel to the velocity field
-void VortexParticleGaussian::applyForce(
- Grid<Vec3>* pVel,Grid<Vec3>* pVort,Grid<Vec3>* pTemp, FlagGrid* flags,
- Real mult, Real fadein, bool doForces, Grid<Vec3>* velHelper)
-{
- // precalculate frequently used constants
- int irad = 1+(int)ceilf(mIRad*mult);
- Real mult2=mult*mult, irad2 = mIRad*mIRad*mult2;
- Vec3 spos = mPos*mult;
- nVec3i apos = vec2I(spos);
- Vec3 subpos = vec2R(apos)-spos;
- if (gDim==2) {subpos.z = 0; apos.z = (int)mPos.z;}
- Vec3 ndir(mStrength);
- Real strength=normalize(ndir);
- if (strength==0) return;
-
- // integrate vorticity field of the kernel to obtain weight w_k
- Real summRef=0,summDiff=0;
- FOR_KERNEL(irad)
- {
- int x=apos.x+i, y=apos.y+j, z=apos.z+k;
- if (flags->checkIndexValid(x,y,z))
- {
- Real r2= SQR(subpos.x+i,subpos.y+j,subpos.z+k);
- if (r2 < irad2)
- {
- Real wRef = dot((*pTemp)(x,y,z),ndir);
- Real wCur = dot((*pVort)(x,y,z),ndir);
-
- summRef += wRef;
- summDiff += wRef-wCur;
- }
- }
- }
-
- // don't correct backwards, will cause oscillations
- if (summRef >0 && summDiff > 0)
- {
- Real percentage = summDiff/summRef;
- // Only evaluate if deviation from measured vorticity is not neglectable to save comp. time
- if (percentage > 0.05)
- {
- if (percentage > 1.) percentage = 1.; // no jumps > 100%
- Real magnitude = percentage*strength;
-
- // particle fade-in
- //debMsg("VortexParticleGaussian","Fadein="<< fadein ); // debug
- // NT test if ((mFlags & FInertial)==0 && mTime < fadein * mIRad)
- if (mTime < fadein * mIRad)
- magnitude *= mTime / (fadein*mIRad);
-
- // precalculate
- int orad = 1+(int)ceilf(mORad*mult);
- Real orad2=mORad*mORad*mult2, isig=-1.0/(mSigma*mult2);
-
- // apply kernel
- FOR_KERNEL(orad)
- {
- int x=apos.x+i, y=apos.y+j, z=apos.z+k;
- if (flags->checkIndexValid(x,y,z) && !fgIsObstacle(flags->getGlobal(x,y,z)))
- {
- Vec3 pa(subpos.x+i,subpos.y+j,subpos.z+k), v(0.);
- if (SQR(pa.x,pa.y,pa.z) < orad2)
- {
- // x direction
- if (flags->checkIndexValid(x-1,y,z) && fgIsFluid(flags->getGlobal(x-1,y,z)))
- {
- Vec3 vp = gaussianKernel(Vec3(pa.x-.5,pa.y,pa.z), isig, magnitude, ndir);
- v.x = vp.x;
- }
- // y direction
- if (flags->checkIndexValid(x,y-1,z) && fgIsFluid(flags->getGlobal(x,y-1,z)))
- {
- Vec3 vp = gaussianKernel(Vec3(pa.x,pa.y-.5,pa.z), isig, magnitude, ndir);
- v.y = vp.y;
- }
- #if DDF_DIMENSION==3
- // z direction
- if (flags->checkIndexValid(x,y,z-1) && fgIsFluid(flags->getGlobal(x,y,z-1)))
- {
- Vec3 vp = gaussianKernel(Vec3(pa.x,pa.y,pa.z-.5), isig, magnitude, ndir);
- v.z = vp.z;
- }
- #endif
- (*pVel)(x,y,z) +=v;
- if(velHelper) velHelper->getGlobal(x,y,z) += v;
- }
- }
- }
- }
- }
-
- // process attenuation for particles trapped in obstacle
- // shrink radius and strength, such that str/R = const
- if (doForces)
- {
- if (mAttenuate > 1e-4)
- {
- Real perc = 1.-mAttenuate;
- scale(pow(perc,1./((Real)gDim+1.)));
- }
- }
-}
-
-// uniform scaling of the particle
-void VortexParticleGaussian::scale(Real fac)
-{
- mIRad *= fac;
- mORad *= fac;
- mSigma *= fac*fac;
- mStrength *= fac;
-}
-
-
-// ******************************************************************
-//
-// VORTICITY SYSTEM
-//
-// ******************************************************************
-
-// apply the particles velocity kernel onto the grid
-void VorticitySystem::applyForces(Grid<Vec3>* pVel, Grid<Vec3>* pVort, Grid<Vec3>* pTemp,FlagGrid* flags, Real mult, bool doForces,
- Grid<Vec3>* velHelper)
-{
- std::cout << "----------------------" << mParts.size() <<" parts------------------------" << std::endl;
-
- const VList::iterator it_end = mParts.end();
- for (VList::iterator it=mParts.begin(); it != it_end; ++it)
- {
- (*it)->buildReference(pTemp, flags, mult, doForces);
- }
- for (VList::iterator it=mParts.begin(); it != it_end; ++it)
- {
- if ((*it)->isDeleted()) continue;
- (*it)->applyForce(pVel,pVort,pTemp,flags,
- mult, msFadeIn, doForces,velHelper);
- }
-}
-
-// perform merge, split and dissipation of particles
-void VorticitySystem::merge(FlagGrid* flags, Grid<Real>* ndist, Grid<Vec3>* vel,Real dt, Real mergeDist)
-{
- Real mergeDist2 = mergeDist*mergeDist;
-
- // Update timer, split
- for (VList::iterator it=mParts.begin(); it != mParts.end(); ++it)
- {
- VortexParticle *p = *it;
- if (p->isDeleted()) continue;
- p->getTime() -= dt;
- if (VortexParticle::doDecay() && p->getTime() <= 0)
- {
- // dissipatation
- if (p->getRadius() <= VortexParticle::msDissipateRadius)
- {p->markDelete(); }
- // particle splitting
- else if ((p->getFlags() & VortexParticle::FInertial) != 0)
- {
- //printf("split before : %g,%g,%g / r%g\n",p->getStrength().x,p->getStrength().y,p->getStrength().z,p->getRadius());
- VortexParticle* pn = p->split();
- pn->setDecayTimer();
- pn->getFlags() |= VortexParticle::FInertial;
-
- // slightly modify new particle position, so that they don't lump together
- Vec3 ndir (rnd(),rnd(),rnd());
- Real nDP1 = sqrt(p->getRadius()) * (0.5+1.*rnd());
- Real nDP3 = 3. * dt*norm(mpFsolver->interpolateVpVelocity(p->getPos(), vel));
- ndir *= std::max(std::min(nDP1,nDP3),(Real)1.2) / norm(ndir);
- if (gDim==2) ndir.z=0;
- pn->advance(ndir);
- p->advance(-ndir);
-
- // slightly modify new particle axis, so that they don't lump together
-#if DDF_DIMENSION==3
- Vec3 nang (rnd(),rnd(),rnd());
- Real str = norm(p->getStrength());
- nang *= 0.1 * str / norm(nang);
- Vec3 pnew = (p->getStrength()+nang);
- Real pnewn = norm(pnew);
- if (pnewn > MININV)
- p->getStrength() = pnew * (str / pnewn);
- pnew = (pn->getStrength()-nang);
- pnewn = norm(pnew);
- if (pnewn > MININV)
- pn->getStrength() = pnew * (str / pnewn);
-#endif
- mParts.insert(it,pn);
-
- //printf("split 1: %g,%g,%g / r%g\n",p->getStrength().x,p->getStrength().y,p->getStrength().z,p->getRadius());
- //printf("split 2 : %g,%g,%g / r%g\n",pn->getStrength().x,pn->getStrength().y,pn->getStrength().z,pn->getRadius());
- }
- p->getFlags() |= VortexParticle::FInertial;
- p->setDecayTimer();
- }
- else if(VortexParticle::doDecay() && (p->getFlags() & VortexParticle::FInertial) == 0)
- {
- // transfer to inertial range if particle leaves near-wall region
- nVec3i pos(vec2I(p->getPos()+.5));
- if ((*ndist).getGlobal(pos.x,pos.y,pos.z) == 0)
- {
- Real timeLeft = p->getTime();
- p->getFlags() |= VortexParticle::FInertial;
- p->setDecayTimer();
- p->getTime() = 0.5* (p->getTime() + timeLeft);
- }
- }
- }
-
- // Particle merging
- const VList::iterator it_end = mParts.end();
- for (VList::iterator it=mParts.begin(); it != it_end; ++it)
- {
- VortexParticle* p1 = *it;
- if (!p1->canMerge()) continue;
- VList::iterator it2=it;
- for (++it2; it2 != it_end; ++it2)
- {
- VortexParticle* p2 = *it2;
- Real d2 = normNoSqrt(p1->getPos()-p2->getPos());
- // Merge if distance smaller then merge radius
- if (p2->canMerge() &&
- d2 < (p1->getMergeR2()+ p2->getMergeR2())*mergeDist2 &&
- d2 < 4.*min(p1->getMergeR2(), p2->getMergeR2())*mergeDist2)
- {
- // Merging probability scales with axis alignment of the two particles
- Real angle = acos(dot(p1->getStrength(),p2->getStrength())/(norm(p1->getStrength())*norm(p2->getStrength())));
- Real prob = 1.-angle/PI;
- Real rand = rnd();
- if (rand >= prob) continue;
-
- Real dist = norm(p1->getPos()-p2->getPos());
- if (p1->merge(p2))
- {
- p2->markDelete(); cout << "MRG - " << p1->getPos() << " d " << dist << endl;
- break;
- }
- }
- }
- }
-
- // remove particles marked for deletation
- for (VList::iterator it=mParts.begin(); it != mParts.end();)
- if ((*it)->isDeleted())
- {
- delete *it;
- it = mParts.erase(it);
- }
- else
- ++it;
-}
-
-// particle advection and vortex stretching
-void VorticitySystem::advectParticles(Grid<Vec3>* pVel, FlagGrid* flags, Real dt, Real mult)
-{
- const int numParticles = mParts.size();
-
-#if DEBUG_VORTEXPATH==1
- for (std::list<LineElement>::iterator it=gVortexPath.begin(); it != gVortexPath.end();)
- {
- it->a -= 0.015;
- if (it->a < 0)
- it = gVortexPath.erase(it);
- else
- ++it;
- }
-#endif
-
- {
- int i=0;
- const VList::iterator it_end = mParts.end();
- for (VList::iterator it=mParts.begin(); it != it_end;++i)
- {
- VortexParticle& p = *(*it);
- // Second-order Heun/RK2 step
- Vec3 pos1 = p.getPos();
- Vec3 v1 = mpFsolver->interpolateVpVelocity(pos1*mult, pVel);
- Vec3 pos2 = pos1 + v1*dt;
- Vec3 v2 = mpFsolver->interpolateVpVelocity(pos2*mult, pVel);
- Vec3 v = (v1+v2)*0.5;
- // remove deleted particles (only used if no merge plugin is invoked)
- if (p.isDeleted() )
- {
- delete *it;
- it = mParts.erase(it);
- }
- else
- {
- // update vorticity (vortex stretching)
-#if DDF_DIMENSION==3
- p.vortexStretch(pVel, dt, mult);
-#endif
- // update position
- v += dt*p.getForce() * VortexParticle::msRepulsion;
- p.advance(v*dt);
- ++it;
- }
- }
- }
-}
-
-
-// constructor
-VorticitySystem::VorticitySystem(FluidSolver *fs) :
- mpFsolver(fs)
-{
- VortexParticle::msU0 = fs->getParams()->mU0;
-
- // init defaults
- msFadeIn = 2.;
-};
-
-// destructor
-VorticitySystem::~VorticitySystem()
-{
- for (VList::iterator it=mParts.begin(); it != mParts.end();) {
- delete *it;
- it = mParts.erase(it);
- }
-}
-
-} // namespace DDF
-
diff --git a/intern/smoke/intern/source/vortexpart.h b/intern/smoke/intern/source/vortexpart.h
deleted file mode 100644
index 6e14a6c5f32..00000000000
--- a/intern/smoke/intern/source/vortexpart.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Vortex Particle classes
- *
- *****************************************************************************/
-
-#ifndef DDFVORTEXPART_H
-
-#include <list>
-#include "globals.h"
-#include "fluidsolver.h"
-#include "randomstream.h"
-
-#define DEBUG_VORTEXPATH 1
-
-namespace DDF {
-
-#ifdef DEBUG_VORTEXPATH
-// for debugging: draws a line behind the particles
-struct LineElement {
- Vec3 p0, p1;
- Real r,g,b,a,s;
-};
-extern std::list<LineElement> gVortexPath;
-#endif
-
-
-class VortexParticle{
- public:
- VortexParticle(const Vec3& p, const Vec3& s, Real irad, Real orad);
- virtual ~VortexParticle() {};
-
- // check if particle should split
- static inline bool doDecay() { return msDecayTime != 0; }
- inline Vec3& getPos() {return mPos; };
- inline Vec3& getStrength() {return mStrength; };
- inline const Vec3& getPos() const {return mPos; };
- // radius in which particles merge
- inline Real getMergeR2() { return mIRad * mIRad; }
- inline Real getRadius() { return mIRad; }
- inline Vec3& getForce() { return mForce; };
- inline Real& getTime() { return mTime; };
- int& getFlags() { return mFlags; };
- bool isDeleted() { return (mFlags & FDelete) == 1; };
- bool canMerge() { return (mFlags & (FDelete | FInertial)) == 0; }
- // mark for deletation in the next timestep
- void markDelete() { mFlags |= 1; };
- // use this to advect the particle
- inline void advance(const Vec3& v);
- void setDecayTimer();
-
- virtual void scale(Real fac) = 0;
- // merge this particle with particle v
- virtual bool merge(VortexParticle* v) = 0;
- // split into two particles, radius controlled by msRadiusCascade
- virtual VortexParticle* split() = 0;
- // add particles vorticity to desired vorticity grid (w_D)
- virtual void buildReference(Grid<Vec3>* pTemp, FlagGrid* flags, Real mult, bool doForces) = 0;
- // apply vortex stretching
- virtual void vortexStretch(Grid<Vec3>* pVel, Real dt, Real mult);
- // apply particles velocity kernel to simulation
- virtual void applyForce(Grid<Vec3>* pVel,Grid<Vec3>* pVort,Grid<Vec3>* pTemp, FlagGrid* flags,
- Real mult, Real fadein, bool doForces, Grid<Vec3>* velHelper = NULL) = 0;
- virtual std::string toString();
-
- static const Real msRepulsion, msAttenuation; // factor for repulsion, attenuation forces when particles is near a wall
- static const bool msStretchingPreserve; // preserve vortex strength in vortex stretching (only rotate axis) ?
- static Real msDecayTime; // Factor to the decay timescale
- static Real msInitialTime; // Factor to the transition time to inertial subrange
- static Real msRadiusCascade; // Factor to wavenumber in decay (i.e. 0.5 -> radius is halfed). Controls granularity of decay.
- static Real msDissipateRadius; // Particle below this radius are dissipated (usually 0.5..1 grid cells)
- static Vec3 msU0; // Global velocity scale (inflow etc.)
-
- enum Flag { FDelete = 1, FInertial = 2};
-
- protected:
- Vec3 mPos, mStrength, mForce;
- int mFlags;
- Real mIRad, mORad, mTime, mAttenuate;
-};
-
-class VortexParticleGaussian : public VortexParticle{
- public:
- VortexParticleGaussian(const Vec3& pos, const Vec3& strength, Real irad);
-
- void scale(Real fac);
- bool merge(VortexParticle* v);
- VortexParticle* split();
- void buildReference(Grid<Vec3>* pTemp, FlagGrid* flags, Real mult, bool doForces);
- void applyForce(Grid<Vec3>* pVel,Grid<Vec3>* pVort,Grid<Vec3>* pTemp, FlagGrid* flags,
- Real mult, Real fadein, bool doForces, Grid<Vec3>* velHelper = NULL);
- static Real getAreaMultiplier() { return msAreaMult; }
-
- static const Real msLogCutoff, msAreaMult;
- protected:
- Real mSigma;
-};
-
-class VorticitySystem
-{
- public:
- typedef std::list<VortexParticle*> VList;
-
- VorticitySystem(FluidSolver *fs);
- ~VorticitySystem();
-
- inline VList& getParticles() { return mParts; }
- static inline Real rnd() { return randStream.getReal(); }
- static inline Real rndg() { return randStream.getRandNorm(0.,1.); }
-
- // apply all particles to velocity grid
- void applyForces(Grid<Vec3>* pVel, Grid<Vec3>* pVort, Grid<Vec3>* pTemp, FlagGrid* flags, Real mult, bool doForces, Grid<Vec3>* velHelper = NULL);
- void advectParticles(Grid<Vec3>* pVel, FlagGrid* flags, Real dt, Real multiplier);
- void registerPrecomp(vector<Real>* dat) { mpPrecomp = dat; }
- // merge & split particles
- void merge (FlagGrid* flags, Grid<Real>* ndist,Grid<Vec3>* vel, Real dt, Real mergeDist);
- vector<Real>* getPrecomp() { return mpPrecomp; }
-
- Real getFadeIn() const { return msFadeIn; }
- void setFadeIn(Real set) { msFadeIn = set; }
-
- protected:
- VList mParts;
- DDF::FluidSolver * mpFsolver;
- vector<Real> * mpPrecomp;
- static RandomStream randStream;
- Real msFadeIn;
-};
-
-
-}
-
-#define DDFVORTEXPART_H
-#endif
diff --git a/intern/smoke/intern/source/vortexplugins.cpp b/intern/smoke/intern/source/vortexplugins.cpp
deleted file mode 100644
index 170e8d1a9bf..00000000000
--- a/intern/smoke/intern/source/vortexplugins.cpp
+++ /dev/null
@@ -1,931 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Plugins to access vortex particles
- *
- *****************************************************************************/
-
-#include "fluidsolver.h"
-#include "solverplugin.h"
-#include "paramset.h"
-
-#include "randomstream.h"
-#include "vortexpart.h"
-#include <zlib.h>
-
-using namespace std;
-
-namespace DDF {
-
-// declare external accesors
-extern void closeDatabaseWriter();
-extern std::vector<Vec3> initDatabaseWriter(const string&, int, int);
-
-#if DDF_DIMENSION==3
-#define FOR_KERNEL(rad) for (int z=-rad;z<=rad;z++) for (int y=-rad;y<=rad;y++) for (int x=-rad;x<=rad;x++)
-#else
-#define FOR_KERNEL(rad) for (int y=-rad,z=0;y<=rad;y++) for (int x=-rad;x<=rad;x++)
-#endif
-
-//*****************************************************************************
-// Invoke vortex particle advection, vortex stretching
-class spluginAdvectVPart : public SolverPlugin {
- public:
- spluginAdvectVPart() : SolverPlugin(), mGrid("vel-curr")
- { };
- ~spluginAdvectVPart() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("gridname",mGrid);
- mSolver = params.FindOneString("from-solver",""); // use particles hostsed on a different solver
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spluginAdvectVPart","init");
- return true;
- };
-
- // perform step with given dt
- virtual bool performStep(Real dt) {
- debMsg("spluginAdvectVPart","step "<<dt);
- FlagGrid* flags = mpPlParams->getGridInt("flags");
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mGrid);
-
- FluidSolver* solver = mSolver.empty() ? mpPlParams->getFluidSolver() : ddfWorldFindSolver(mSolver);
- Real multiplier = mpPlParams->getMultiplier();
- if (multiplier <=0) multiplier = 1.;
- solver->getVorticitySys()->advectParticles(vel, flags, dt/multiplier, multiplier);
- return true;
- };
-
- protected:
- string mGrid, mSolver;
-};
-
-
-//*****************************************************************************
-// Gridop : compute vorticity of velocity grid
-// output vorticity is centered on ijk
-class fsComputeVort : public GridOpBaseFlagbord<1> {
- public:
- fsComputeVort(FlagGrid *flags, Grid<Vec3> *vel, Grid<Vec3> *vort, Real dx) :
- GridOpBaseFlagbord<1>(), mpVel(vel), mpVort(vort) {
- mDxInv = 1.0;
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsComputeVort() { };
- void resetVariables() { };
- void buildCallList() {
- gaVel.gridAccInit(mpVel, AM_READ, gaCalls);
- gaVort.gridAccInit(mpVort, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k)
- {
- int flag = getFlagAcc()(i,j,k);
- if(!fgIsFluid(flag)) {
- gaVort.write(i,j,k) = Vec3(0.);
- return;
- }
- #define getv(i,j,k) (!fgIsFluid(getFlagAcc()(i,j,k))?v0:gaVel(i,j,k))
- Vec3 w(0.),v0 (gaVel(i,j,k));
- for (int l=0;l<4;l++) // averaging kernel to get center value
- {
- if (gDim==3)
- {
- w[0] += (Real)_b[l] * (getv(i,j+_b[l],k+_a[l])[2] - getv(i,j+_a[l],k+_b[l])[1]);
- w[1] += (Real)_b[l] * (getv(i+_a[l],j,k+_b[l])[0] - getv(i+_b[l],j,k+_a[l])[2]);
- }
- w[2] += (Real)_b[l] * (getv(i+_b[l],j+_a[l],k)[1] - getv(i+_a[l],j+_b[l],k)[0]);
- }
- #undef getv
-
- gaVort.write(i,j,k) = w*(mDxInv*0.25);
- };
- void reduce(fsComputeVort &op) { };
-
- protected:
- Grid<Vec3> *mpVel;
- Grid<Vec3> *mpVort;
- GridAccessor<Vec3,1> gaVel;
- GridAccessor<Vec3,0> gaVort;
-
- static const int _a[4],_b[4];
- Real mDxInv;
-};
-const int fsComputeVort::_a[4]={ 1, 0, 1, 0};
-const int fsComputeVort::_b[4]={ 1, 1,-1,-1};
-
-
-//*****************************************************************************
-// Plugin to invoke vorticity computation of velocity grid
-class spluginComputeVorticity : public SolverPlugin {
- public:
- spluginComputeVorticity() : SolverPlugin(),
- mGrid("vel-curr"),mVort("-unnamed-") {
- };
- ~spluginComputeVorticity() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("velocity", mGrid );
- mVort = params.FindOneString("vorticity", mVort );
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spluginComputeVorticity","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginComputeVorticity"," dt="<<dt<<" vel:"<<mGrid );
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mGrid);
- Grid<Vec3>* vort = mpPlParams->getGridVec3(mVort);
- fsComputeVort(mpPlParams->getFluidSolver()->getGridFlags(),vel,vort,mpPlParams->getDeltaX());
- return true;
- };
-
- protected:
- std::string mGrid, mVort;
-};
-
-//*****************************************************************************
-// Apply velocity kernel of the vortex particles to velocity grid
-class spluginApplyVParts : public SolverPlugin {
- public:
- spluginApplyVParts() : SolverPlugin(),
- mGrid("vel-curr"), mVort("unnamed"),mTemp("vec-temp") {
- };
- ~spluginApplyVParts() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("velocity", mGrid );
- mVort = params.FindOneString("vorticity", mVort ); // current measured vorticity
- mTemp = params.FindOneString("temp", mTemp ); // temporary grid for storing reference vorticity field
- mSolver = params.FindOneString("from-solver", ""); // use vortex particles hosted on a different solver
- mDoForces = params.FindOneInt("doforces", 1) != 0; // activate repulsion forces
- return true;
- };
- virtual bool initPlugin() {return true;};
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginApplyVParts"," dt="<<dt<<" vel:"<<mGrid );
- FlagGrid* flags = mpPlParams->getGridInt("flags");
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mGrid);
- Grid<Vec3>* vort = mpPlParams->getGridVec3(mVort);
- Grid<Vec3>* temp = mpPlParams->getGridVec3(mTemp);
- Grid<Vec3>* velhelp = NULL;
- if (mpPlParams->haveGridVec3("vel-helper")) mpPlParams->getGridVec3("vel-helper"); // helper grid shows only induced velocity
- FluidSolver* solver = mSolver.empty() ? mpPlParams->getFluidSolver() : ddfWorldFindSolver(mSolver);
- Real multiplier = mpPlParams->getMultiplier();
- if (multiplier <0) multiplier = 1.; // multiplier due to grid rescaling
- temp->clearGrid();
-
- solver->getVorticitySys()->applyForces(vel,vort,temp, flags,multiplier,mDoForces, velhelp);
-
- return true;
- };
-
- protected:
- std::string mGrid, mVort,mTemp,mSolver;
- bool mDoForces;
-};
-
-//*****************************************************************************
-// Merge, split, dissipate particles
-class spluginMergeVParts : public SolverPlugin {
- public:
- spluginMergeVParts() : SolverPlugin() {};
- ~spluginMergeVParts() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mDist = params.FindOneString("ndist", "unnamed" ); // Distance field to the obstacles
- mInitTime = params.FindOneFloat("init-time", 50.); // Factor to the lifespan in model-dependant range
- mDecayTime = params.FindOneFloat("decay-time", 250. ); // Factor to the time between particle splitting
- mMergeDist = params.FindOneFloat("merge-dist", 1.); ; // Factor to the merge radius
- mDissipateRadius = params.FindOneFloat("dissipate-radius", 1. ); // Radius below which particles are deleted
- mRadiusCascade = params.FindOneFloat("radius-cascade", 2.); // On split, particle decay into 2 particles of with radius old_radius/radius_cascade
- // a low value leads to frequent splitting
- return true;
- };
- virtual bool initPlugin() {
- debMsg("spluginMergeVParts","init");
- return true;
- };
-
- // perform step with given dt, return failure
- virtual bool performStep(Real dt) {
- debMsg("spluginMergeVParts"," dt="<<dt );
- FlagGrid* flags = mpPlParams->getGridInt("flags");
- Grid<Vec3>* vel = mpPlParams->getGridVec3("vel-curr");
- VortexParticle::msDecayTime = mDecayTime;
- VortexParticle::msInitialTime = mInitTime;
- VortexParticle::msRadiusCascade = mRadiusCascade;
- VortexParticle::msDissipateRadius = mDissipateRadius;
- mpPlParams->getFluidSolver()->getVorticitySys()->merge(flags, mpPlParams->getGridReal(mDist), vel, dt,mMergeDist);
-
- return true;
- };
-
- protected:
- std::string mDist;
- Real mInitTime,mDecayTime,mMergeDist,mRadiusCascade,mDissipateRadius;
-};
-
-//*****************************************************************************
-// initialize a grid from a grid of another solver (possibly with different resolution)
-class spluginInterpolateGridFrom : public SolverPlugin {
- public:
- spluginInterpolateGridFrom() : SolverPlugin(),
- mName("-unnamed1-"), mGridSrc("-unnamed2-"), mGridDst("-unnamed3-"),
- mDoFlagsTreatment(0), mCorrectScale(1), mCorrectAdd(0) {
- };
- ~spluginInterpolateGridFrom() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mName = params.FindOneString("name", mName ); // solver name
- mGridSrc = params.FindOneString("src", mGridSrc ); // source grid
- mGridDst = params.FindOneString("dst", mGridDst ); // dest. grid
- mDoFlagsTreatment = params.FindOneInt("do-flags", mDoFlagsTreatment ); // adjust flags ?
- mCorrectScale = params.FindOneFloat("correctScale", mCorrectScale);
- mCorrectAdd = params.FindOneFloat("correctAdd", mCorrectAdd);
- return true;
- };
- virtual bool initPlugin() { return true; };
-
- virtual bool performStep(Real org_dt);
- bool performStepFlags(FluidSolver* src, FluidSolver* dst);
- protected:
- // name of solver to init from
- std::string mName;
- // name of src/dst grid
- std::string mGridSrc,mGridDst;
-
- int mDoFlagsTreatment;
-
- void initSizeScale(GridBase* src, GridBase* dst);
- nVec3i m_srcSize;
- nVec3i m_dstSize;
- Vec3 m_sizeScale;
-
- float mCorrectScale;
- float mCorrectAdd;
-};
-
-// Helper function to adjust scale size
-void spluginInterpolateGridFrom::initSizeScale(GridBase* src, GridBase* dst) {
- m_srcSize = src->getSize();
- m_dstSize = dst->getSize();
- m_sizeScale = Vec3(
- (Real)m_srcSize[0] / (Real)m_dstSize[0],
- (Real)m_srcSize[1] / (Real)m_dstSize[1],
- (Real)m_srcSize[2] / (Real)m_dstSize[2] );
- debMsg("spluginInterpolateGridFrom ","scale size = "<<m_sizeScale<<", src="<<m_srcSize<<" to dst="<<m_dstSize);
-}
-
-// NYI, TODO, loop over range, use priority of flags: obstacle>fluid>empty
-bool spluginInterpolateGridFrom::performStepFlags(FluidSolver* srcSolver, FluidSolver* dstSolver)
-{
- // similar to real grid treatment
- if( ( srcSolver->getParams()->haveGridInt(mGridSrc)) &&
- ( mpPlParams->haveGridInt(mGridDst) ) ) {
- FlagGrid* src = srcSolver->getParams()->getGridInt(mGridSrc);
- FlagGrid* dst = mpPlParams->getGridInt(mGridDst);
-
- initSizeScale(src,dst);
-
- FOR_IJK_GRID_BND(dst,1) {
- // linearly interpolate values
- Vec3 p = Vec3(i,j,k) * m_sizeScale;
-
- // for safety reasons, don't overwrite obstacle flags
- if( fgIsObstacle(dst->getGlobal(i,j,k)) )
- continue;
- // downsizing, no interpol
- dst->getGlobal(i,j,k) = src->getGlobal( (int)p[0], (int)p[1], (int)p[2]);
- }
-
- } else {
- errFatal("spluginInterpolateGridFrom","Do-flags Grids not found! "<<mGridSrc<<" "<<mGridDst, SIMWORLD_PLUGINERROR);
- return false;
- }
- return true;
-}
-
-// interpolate grid values from another grid of another solver
-bool spluginInterpolateGridFrom::performStep(Real org_dt) {
-
- //Real dt = org_dt * mpPlParams->getDeltaX();
- debMsg("spluginInterpolateGridFrom","name:"<<mName<<"; from="<<mName<<" "<<mGridSrc<<"->"<<mGridDst );
-
- FluidSolver* srcSolver = ddfWorldFindSolver(mName);
- FluidSolver* dstSolver = mpPlParams->getFluidSolver();
- if(!srcSolver) {
- errMsg("spluginInterpolateGridFrom","Source solver '"<<mName<<"' not found!");
- return false;
- }
-
- bool doneSth = false;
-
- if(mDoFlagsTreatment) {
- return performStepFlags(srcSolver, dstSolver);
- }
-
- if( ( srcSolver->getParams()->haveGridVec3(mGridSrc)) &&
- ( mpPlParams->haveGridVec3(mGridDst) ) ) {
-
- Grid<Vec3>* src = srcSolver->getParams()->getGridVec3(mGridSrc);
- Grid<Vec3>* dst = mpPlParams->getGridVec3(mGridDst);
-
- //const nVec3i grs = mpPlParams->getFluidSolver()->get GridInitDim();
- const nVec3i grs = src->getSize();
-
- int ks = 1;
- int ke = grs[2]-1;
- if(gDim==2) {
- ks = mpPlParams->getFluidSolver()->get2dKstart();
- ke = ks+1;
- }
-
- nVec3i srcSize = src->getSize();
- nVec3i dstSize = dst->getSize();
- Vec3 sizeScale = Vec3(
- (Real)srcSize[0] / (Real)dstSize[0],
- (Real)srcSize[1] / (Real)dstSize[1],
- (Real)srcSize[2] / (Real)dstSize[2] );
- debMsg("scale ","size = "<<sizeScale);
-
- const Real dtFac = 1./1.;
-
- FOR_IJK_GRID(dst) {
- // linearly interpolate values
- Real pi = (Real)(i)*sizeScale[0];
- Real pj = (Real)(j)*sizeScale[1];
- Real pk = (Real)(k)*sizeScale[2];
- dst->getGlobal(i,j,k) = src->getInterpolated(pi, pj, pk) * dtFac * mCorrectScale; // */
- }
- doneSth = true;
- } // VEC3
-
- if( ( srcSolver->getParams()->haveGridReal(mGridSrc)) &&
- ( mpPlParams->haveGridReal(mGridDst) ) ) {
- Grid<Real>* src = srcSolver->getParams()->getGridReal(mGridSrc);
- Grid<Real>* dst = mpPlParams->getGridReal(mGridDst);
-
- nVec3i srcSize = src->getSize();
- nVec3i dstSize = dst->getSize();
- Vec3 sizeScale = Vec3(
- (Real)srcSize[0] / (Real)dstSize[0],
- (Real)srcSize[1] / (Real)dstSize[1],
- (Real)srcSize[2] / (Real)dstSize[2] );
- debMsg("scale ","size = "<<sizeScale);
-
- FOR_IJK_GRID(dst) {
- // linearly interpolate values
- Real pi = (Real)(i)*sizeScale[0];
- Real pj = (Real)(j)*sizeScale[1];
- Real pk = (Real)(k)*sizeScale[2];
- dst->getGlobal(i,j,k) = src->getInterpolated(pi, pj, pk) * mCorrectScale + mCorrectAdd;
- }
-
- doneSth = true;
- } // REAL
-
- if(!doneSth) {
- errFatal("spluginInterpolateGridFrom","Grids not found! "<<mGridSrc<<" "<<mGridDst, SIMWORLD_PLUGINERROR);
- return false;
- }
-
- return true;
-};
-
-
-//*****************************************************************************
-// GridOp: update artificial boundary layer
-class fsUpdatePdf : public GridOpBase {
- public:
- fsUpdatePdf(FlagGrid *flags, Grid<Vec3> *ref, Grid<Vec3> *flow, Real scaleFlow, Grid<Vec3> *rans, bool israndom,Real premult) :
- GridOpBase(), mScaleFlow(scaleFlow), mVortPreMult(premult), mpRef(ref), mpFlow(flow),mpRans(rans),mIsRandom(israndom) {
- mpFlags = flags;
- applyOperatorToGrids(this);
- };
- ~fsUpdatePdf() { };
- void resetVariables() { };
- void buildCallList() {
- gaRef.gridAccInit(mpRef, AM_READ, gaCalls);
- gaFlow.gridAccInit(mpFlow, AM_READWRITE, gaCalls);
- if (mpRans != NULL) gaRans.gridAccInit(mpRans, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k)
- {
- if(!fgIsFluid(getFlagAcc()(i,j,k)))
- return;
-
- if (mIsRandom) // hard-coded test-case
- gaFlow.write(i,j,k) = normNoSqrt(gaRef(i,j,k))==0 ? Vec3(0,0,0) : Vec3(1e3,1e3,1e3);
- else
- {
- Vec3 ref = gaRef(i,j,k);
- Real ref2 = normNoSqrt(ref);
- if (ref2 > 1e-10) // only set if src is not empty
- {
- // use source from rans solver, ref contains surface normal
- if (mpRans != NULL)
- {
- ref = cross(ref, gaRans(i,j,k));
- ref2 = normNoSqrt(ref);
- }
- ref *= mVortPreMult;
- ref2 *= mVortPreMult*mVortPreMult;
- Real flow = dot(gaFlow(i,j,k),ref), flow2 = flow*flow;
-
- // min bounding on reference grid
- if (flow2 < ref2 || flow<0)
- gaFlow.write(i,j,k) = ref;
- }
- gaFlow.write(i,j,k) *= mScaleFlow;
- }
- }
- void reduce(fsUpdatePdf &op) { };
-
- protected:
- Real mScaleFlow,mVortPreMult;
- Grid<Vec3> *mpRef, *mpFlow, *mpRans;
- GridAccessor<Vec3,0> gaRef, gaFlow, gaRans;
- bool mIsRandom;
-};
-
-//*****************************************************************************
-// GridOp : Evaluate pdf, generate vortex particles
-class fsGenVPart : public GridOpBase {
- public:
- fsGenVPart(FlagGrid *flags, Grid<Real> *pdf, Grid<Vec3> *flow, Grid<Real> *dist, Real thresVort, VorticitySystem* vsys, Real minRad, Real maxRad, Real mdst, Real threspdf, Real multpdf, Real u02, RandomStream& rnd,
- bool israndom, Real randPdf, Real maxbl) :
- GridOpBase(), randStream(rnd), mThresVort(thresVort), mThresPdf(threspdf), mMultPdf(multpdf), mMaxRad(maxRad), mMinRad(minRad), mU02(u02), mMinDist(mdst), mMaxBL(maxbl), mpVSys(vsys),mpPdf(pdf), mpDist(dist),mpFlow(flow),
- mRandom(israndom), mRandomPdf(randPdf) {
- mpFlags = flags;
- applyOperatorToGridsSimple(this);
- };
- ~fsGenVPart() { };
- void resetVariables() { };
- void buildCallList() {
- gaFlow.gridAccInit(mpFlow, AM_READWRITE, gaCalls);
- gaPdf.gridAccInit(mpPdf, AM_WRITE, gaCalls);
- gaDist.gridAccInit(mpDist, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k)
- {
- if (!fgIsFluid(getFlagAcc()(i,j,k))) return;
-
- // obtain squared vorticity
- Vec3 vvort = gaFlow(i,j,k);
- Real vort2 = normNoSqrt(vvort), dist = gaDist(i,j,k);
- if (dist <= 0 || vort2 < mThresVort*mThresVort)
- {
- gaPdf.write(i,j,k) = 0;
- return;
- }
- // obtain reynolds stress field, pdf
- Real vort=sqrt(vort2);
- Real reyf = vort2 * dist*dist* mU02;
- Real pdf = 2. * (fabs(reyf) - mThresPdf) * mMultPdf;
-
- if (dist < 0 || dist > mMaxBL) pdf=0; // outside allowed range
- if (mRandom) pdf = mRandomPdf; // bypass pdf
- gaPdf.write(i,j,k) = pdf;
- if (pdf<0) pdf=0;
-
- // random test
- Real rnd = randStream.getReal();
- if (rnd >= pdf) return;
-
- // create particle !
-
- // suggested radius
- Real radius = randStream.getReal()*(mMaxRad-mMinRad) + mMinRad, radius2=radius*radius;
-
- // bound kernel radius to wall
- int ceilRad = (int)ceil(radius);
- FOR_KERNEL(ceilRad)
- {
- Real cr2=x*x+y*y+z*z;
- if (!mRandom && cr2<radius2 && (!mpFlags->checkIndexValid(x+i,y+j,z+k) || fgIsObstacle(mpFlags->getGlobal(x+i,y+j,z+k)) || fgIsInflow(mpFlags->getGlobal(x+i,y+j,z+k))))
- radius2 = cr2;
- }
- Real sugRad = radius;
- radius = sqrt(radius2);
-
- // reduce radius if particle is too big and weak
- Real strength=0;
- Vec3 ndir = vvort * (1./vort);
- for (;;) // loop to obtain next-best radius
- {
- if (radius < mMinDist) return;
-
- // sum vorticity within particle radius
- Real wsum = 0, rsum=0;
- radius2=radius*radius;
- ceilRad = (int)ceil(radius);
- FOR_KERNEL(ceilRad)
- {
- int cr2 = x*x+y*y+z*z;
- if (cr2 <= radius2)
- {
- Real w = dot(gaFlow(i+x,j+y,z+k),ndir);
- if (w < 1e-8) continue;
- wsum += w;
- }
- }
-#if DDF_DIMENSION == 3
- Real mint = VortexParticleGaussian::getAreaMultiplier()*radius*radius2; // gauss inner kernel integral
-#else
- Real mint = M_PI*radius2;
-#endif
- strength = wsum/mint;
-
- // test if particle is too big for its strength
- if (strength > vort || mRandom)
- break;
- else
- radius-= 1.0;
- }
-
- // remove vorticity from ABL
- FOR_KERNEL(ceilRad)
- {
- int cr2 = x*x+y*y+z*z;
- if (cr2 <= radius2)
- {
- Real w = dot(gaFlow(i+x,j+y,z+k),ndir);
- if (w < 1e-8) continue;
- gaFlow.write(i+x,j+y,z+k) -= ndir*w;
- }
- }
-
- // seed particle
- Vec3 str = ndir * (strength);
- if (mRandom)
- {
- // hard coded values for test case
- const Real vmin=0.01,vmax=0.40;
- Real nstr = randStream.getReal()* (vmax-vmin)+vmin;
- str = Vec3(randStream.getReal(),randStream.getReal(),randStream.getReal())*2.-1.;
- str *= nstr/norm(str);
- }
- mpVSys->getParticles().push_back(new VortexParticleGaussian(Vec3(i,j,k), str, radius));
- }
- void reduce(fsGenVPart &op) { };
-
- protected:
- RandomStream& randStream;
-
- Real mThresVort,mThresPdf,mMultPdf;
- Real mMaxRad, mMinRad, mU02, mMinDist, mMaxBL;
- VorticitySystem* mpVSys;
- Grid<Real> *mpPdf, *mpDist;
- Grid<Vec3> *mpFlow;
- GridAccessor<Real,0> gaPdf, gaDist;
- GridAccessor<Vec3,0> gaFlow;
- bool mRandom;
- Real mRandomPdf;
-};
-
-//*****************************************************************************
-// maintain artificial boundary layer, generate vortex particles
-class spluginGenVPart : public SolverPlugin {
- public:
- spluginGenVPart() : SolverPlugin(), mRandomStream(13322223) {};
- ~spluginGenVPart() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGridRef = params.FindOneString("source", "" ); // precomputed ABL source field or surface normal, when using RANS
- mGridFlow = params.FindOneString("flow", "" ); // ABL grid
- mRans = params.FindOneString("rans", "" ); // RANS solver name, if used
- mGridDist = params.FindOneString("dist", "" ); // distance field
- mGridPdf = params.FindOneString("pdf", "" ); // pdf output grid
- mMultPdf = params.FindOneFloat("mult-pdf", 0 ); // c_P constant in the paper
- mThresPdf = params.FindOneFloat("thres-pdf", 0 ); // threshold for pdf below which no seeding will occur
- mMaxBL = params.FindOneFloat("max-bl", 0.1 ); // maximal distance to object in which boundary layer is evaluated
- mThresVort = params.FindOneFloat("thres-vort", 0 ); // threshold for confined vorticity below which no seeding will occur
- mScaleFlow = params.FindOneFloat("scale-flow", 0.99 ); // fade-out for ABL plume
- mMinRad = params.FindOneFloat("min-rad", 0 ); // minimum radius for vortex particles
- mMinDist = params.FindOneFloat("min-dist", mMinRad ); // minimal distance to wall
- mMaxRad = params.FindOneFloat("max-rad", 0 ); // maximum radius for vortex particles
- mIsRandom = params.FindOneInt("random", 0 ) != 0; // bypass pdf, use random particles
- mRandPdf = params.FindOneFloat("random-pdf", 1.5e-4 ); // probability for random pdf
- mVortPreMult = params.FindOneFloat("vortex-gain", 1. ); // vortex gain, beta constant in the paper
- mFadein = params.FindOneFloat("fade-in", -1 ); // vortex particle fade-in constant
-
- if(mIsRandom) debMsg("spluginGenVPart","Randomzied vparts on! Pdf="<<mRandPdf);
-
- return true;
- };
- virtual bool initPlugin() {
- if (mFadein >= 0) {
- VorticitySystem* vsys = mpPlParams->getFluidSolver()->getVorticitySys();
- vsys->setFadeIn(mFadein);
- }
- return true;
- };
-
- bool performStep(Real org_dt)
- {
- FlagGrid *flags = mpPlParams->getGridInt("flags");
- Grid<Vec3>* ref = mpPlParams->getGridVec3(mGridRef);
- Grid<Real>* pdf = mpPlParams->getGridReal(mGridPdf);
- Grid<Real>* dist = mpPlParams->getGridReal(mGridDist);
- Grid<Vec3>* flow = mpPlParams->getGridVec3(mGridFlow);
-
- Grid<Vec3>* rans = mRans.empty() ? NULL : ddfWorldFindSolver(mRans)->getParams()->getGridVec3("vel-curr");
- VorticitySystem* vsys = mpPlParams->getFluidSolver()->getVorticitySys();
- Real u0 = norm(mpPlParams->mU0);
- if (u0==0) { errMsg("spluginGenVPart","u0 not set !"); exit(1); }
-
- fsUpdatePdf(flags,ref,flow,mScaleFlow,rans,mIsRandom,mVortPreMult);
- fsGenVPart (flags,pdf,flow,dist,mThresVort * u0, vsys, mMinRad, mMaxRad, mMinDist, mThresPdf,mMultPdf,1./(u0*u0),
- mRandomStream, mIsRandom, mRandPdf, mMaxBL );
-
- return true;
- }
- protected:
- // name of src/dst grid
- RandomStream mRandomStream;
- std::string mGridRef,mGridFlow,mGridPdf,mGridDist,mRans;
- Real mThresPdf, mMultPdf, mScaleFlow, mThresVort,mMinDist;
- Real mMinRad, mMaxRad, mVortPreMult, mFadein, mMaxBL;
- bool mIsRandom; //,test
- Real mRandPdf;
-};
-
-//*****************************************************************************
-// GridOp : calculate boundary layer
-class fsCalcABL : public GridOpBaseFlagbord<1> {
- public:
- fsCalcABL(FlagGrid *flags, Grid<Real> *ndist, Grid<Vec3> *norm, Grid<Vec3> *abl, Grid<Vec3> *vel, Real lABL) :
- GridOpBaseFlagbord<1>(), mpDist(ndist), mpNorm(norm), mpABL(abl), mpVel(vel) {
- mpFlags = flags;
- mMin = (lABL - .5) / (Real)flags->getMaxSize();
- mMax = (lABL + .5) / (Real)flags->getMaxSize();
- applyOperatorToGridsSimple(this);
- };
- ~fsCalcABL() { };
- void resetVariables() { };
- void buildCallList() {
- gaDist.gridAccInit(mpDist, AM_READ, gaCalls);
- gaVel.gridAccInit(mpVel, AM_READ, gaCalls);
- gaNorm.gridAccInit(mpNorm, AM_READ, gaCalls);
- gaABL.gridAccInit(mpABL, AM_WRITE, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k)
- {
- if (!fgIsFluid(getFlagAcc()(i,j,k))) return;
- // inside BL
- if (gaDist(i,j,k) > mMin && gaDist(i,j,k) < mMax)
- {
- // get centered vel
- Vec3 v = gaVel(i,j,k);
- if (mpFlags->checkIndexValid(i+1,j,k) && fgIsFluid(getFlagAcc()(i+1,j,k))) v.x = 0.5*(v.x + gaVel(i+1,j,k).x);
- if (mpFlags->checkIndexValid(i,j+1,k) && fgIsFluid(getFlagAcc()(i,j+1,k))) v.y = 0.5*(v.y + gaVel(i,j+1,k).y);
- if (mpFlags->checkIndexValid(i,j,k+1) && fgIsFluid(getFlagAcc()(i,j,k+1))) v.z = 0.5*(v.z + gaVel(i,j,k+1).z);
-
- // compute ABL
- gaABL.write(i,j,k) = -cross(v, gaNorm(i,j,k));
- }
- }
- void reduce(fsCalcABL &op) { };
-
- protected:
- Real mMin, mMax;
- Grid<Real> *mpDist;
- Grid<Vec3> *mpNorm, *mpABL, *mpVel;
- GridAccessor<Real,0> gaDist;
- GridAccessor<Vec3,0> gaABL,gaNorm;
- GridAccessor<Vec3,1> gaVel;
-};
-
-//*****************************************************************************
-// Plugin to calculate boundary layer
-class spluginCalcABL : public SolverPlugin {
- public:
- spluginCalcABL() : SolverPlugin() {};
- ~spluginCalcABL() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGridDist = params.FindOneString("dist", "" ); // distance field
- mGridNorm = params.FindOneString("normal", "" ); // surface normals
- mGridABL = params.FindOneString("abl", "" ); // ABL
- mGridVel = params.FindOneString("mean-vel", "" ); // averaged velocity grid
- mD = params.FindOneFloat("d", 1.5 ); // boundary layer thickness
- return true;
- };
- virtual bool initPlugin() {return true; };
-
- bool performStep(Real org_dt)
- {
- FlagGrid *flags = mpPlParams->getGridInt("flags");
- Grid<Vec3>* vel = mpPlParams->getGridVec3(mGridVel);
- Grid<Real>* dist = mpPlParams->getGridReal(mGridDist);
- Grid<Vec3>* norm = mpPlParams->getGridVec3(mGridNorm);
- Grid<Vec3>* abl = mpPlParams->getGridVec3(mGridABL);
-
- fsCalcABL (flags,dist,norm,abl,vel,mD);
-
- return true;
- }
- protected:
- // name of src/dst grid
- std::string mGridDist, mGridNorm, mGridVel, mGridABL;
- Real mD;
-};
-
-//*****************************************************************************
-// GridOp : write database
-class fsWriteDatabase : public GridOpBase {
- public:
- fsWriteDatabase(FlagGrid *flags, Grid<Vec3> *norm, Grid<Vec3> *abl, vector<Vec3>& pos, vector<Vec3>& n, vector<Vec3>& val) :
- GridOpBase(), mpABL(abl), mpNorm(norm), mPos(pos), mNormal(n), mValue(val) {
- mpFlags = flags;
- applyOperatorToGridsSimple(this);
- };
- ~fsWriteDatabase() { };
- void resetVariables() { };
- void buildCallList() {
- gaNormal.gridAccInit(mpNorm, AM_READ, gaCalls);
- gaABL.gridAccInit(mpABL, AM_READ, gaCalls);
- setFlags(mpFlags);
- };
-
- inline void operator() (int i, int j, int k)
- {
- if (!fgIsFluid(getFlagAcc()(i,j,k))) return;
- Vec3 v = gaABL(i,j,k);
- if (v.x == 0 && v.y == 0 && v.z == 0) return;
-
- // store point in pointset
- mPos.push_back(Vec3(i,j,k));
- mNormal.push_back(gaNormal(i,j,k));
- mValue.push_back(v);
- }
- void reduce(fsWriteDatabase &op) { };
-
- protected:
- Grid<Vec3> *mpABL, *mpNorm;
- GridAccessor<Vec3,0> gaABL,gaNormal;
- vector<Vec3>& mPos;
- vector<Vec3>& mNormal;
- vector<Vec3>& mValue;
-};
-
-
-//*****************************************************************************
-// Plugin to write database
-class spluginWriteDatabase : public SolverPlugin {
- public:
- spluginWriteDatabase() : SolverPlugin() {};
- ~spluginWriteDatabase() { };
-
- virtual bool parseParams(const ParamSet& params) {
- mGrid = params.FindOneString("grid", "" ); // ABL Grid
- mNormal = params.FindOneString("normal", "" ); // Surface normals
- mU0 = params.FindOneVector("u0", Vec3(0.) ); // inflow/rotation axis
- return true;
- };
- virtual bool initPlugin() {return true; };
-
- bool performStep(Real org_dt)
- {
- FlagGrid *flags = mpPlParams->getGridInt("flags");
- Grid<Vec3>* abl = mpPlParams->getGridVec3(mGrid);
- Grid<Vec3>* norm = mpPlParams->getGridVec3(mNormal);
-
- // obtain sparse list
- vector<Vec3> pos, normal, val;
- fsWriteDatabase(flags, norm, abl, pos, normal, val);
-
- if (msNeedHeader) {
- // separate header for translation and rotation. Here only identical resolutions are supported.
- float grid_divisor = 1;
- Vec3 size = vec2R(flags->getSize());
- Vec3 scaling (1.,1.,1.), offset(0,0,0); // in this version these parameters are ignored
- int numPoints = pos.size();
- for (int t=0;t<2;t++) {
- gzwrite(msGzf, &numPoints, sizeof(int));
- gzwrite(msGzf, &grid_divisor, sizeof(float));
- gzwrite(msGzf, &(size[0]), sizeof(Vec3));
- gzwrite(msGzf, &(scaling[0]), sizeof(Vec3));
- gzwrite(msGzf, &(offset[0]), sizeof(Vec3));
- for (int i=0; i<numPoints; i++) gzwrite(msGzf, &(pos[i][0]), sizeof(Vec3));
- for (int i=0; i<numPoints; i++) gzwrite(msGzf, &(normal[i][0]), sizeof(Vec3));
- for (int i=0; i<(int)msIndexMat.size(); i++) { int idx=msIndexMat[i]+t; gzwrite(msGzf, &(idx), sizeof(int)); }
- }
- msNeedHeader=false;
- }
- // write ABL data
- gzwrite(msGzf, &(mU0[0]), sizeof(Vec3));
- for (int i=0; i<(int)val.size(); i++) gzwrite(msGzf, &(val[i][0]), sizeof(Vec3));
-
- return true;
- }
-
- // open file, write main header
- static vector<Vec3> open(const string& name, int nTheta, int nPhi) {
- // open database file
- msGzf = gzopen((name+".gz").c_str(), "wb9" );
- if (!msGzf)
- errFatal("spluginDatabaseWriter", "can't open database file", SIMWORLD_INITERROR);
-
- // write header
- int elements = 2*nTheta*nPhi;
- gzwrite(msGzf, &elements,sizeof(int));
- gzwrite(msGzf, &nTheta,sizeof(int));
- gzwrite(msGzf, &nPhi,sizeof(int));
-
- // generate angle vectors
- float *theta = new float[nTheta];
- for (int i=0;i<nTheta;++i) theta[i] = M_PI * (float)i/(float)(nTheta-1);
- gzwrite(msGzf, theta, sizeof(float)*nTheta);
- float *phi = new float[nPhi];
- for (int i=0;i<nPhi;++i) phi[i] = 2.*M_PI * (float)i/(float)nPhi;
- gzwrite(msGzf, phi, sizeof(float)*nPhi);
-
- // generate index matrices+axes
- vector<Vec3> axes;
- msIndexMat.resize(nTheta*nPhi);
- for (int i=0, idx=0;i<nTheta;i++)
- for (int j=0;j<nPhi;j++) {
- axes.push_back( Vec3( sin(theta[i])*cos(phi[j]), cos(theta[i]), sin(theta[i])*sin(phi[j])) );
- msIndexMat[nPhi*i+j] = idx;
- idx+=2;
- }
-
- delete[] phi;
- delete[] theta;
- msNeedHeader = true;
- msIndex = 0;
- return axes;
- }
- static void close() {
- msNeedHeader = false;
- gzclose(msGzf);
- }
- protected:
- std::string mGrid, mNormal;
- static gzFile msGzf;
- static bool msNeedHeader;
- static std::vector<int> msIndexMat;
- static int msIndex;
- Vec3 mU0;
-};
-gzFile spluginWriteDatabase::msGzf = NULL;
-bool spluginWriteDatabase::msNeedHeader = false;
-vector<int> spluginWriteDatabase::msIndexMat;
-int spluginWriteDatabase::msIndex = 0;
-
-// static callers
-vector<Vec3> initDatabaseWriter(const string& file, int nTheta, int nPhi) {
- return spluginWriteDatabase::open(file, nTheta, nPhi);
-}
-void closeDatabaseWriter() {
- spluginWriteDatabase::close();
-}
-
-
-//*****************************************************************************
-
-SolverPlugin* MakeVortexPlugin(std::string name)
-{
- if(name.compare( string("advect-vpart") )==0)
- return new spluginAdvectVPart;
- if(name.compare( string("apply-vpart") )==0)
- return new spluginApplyVParts;
- if(name.compare( string("merge-vpart") )==0)
- return new spluginMergeVParts;
- if(name.compare( string("compute-vorticity") )==0)
- return new spluginComputeVorticity;
- if(name.compare( string("interpolate-grid-from") )==0)
- return new spluginInterpolateGridFrom;
- if(name.compare( string("gen-vpart") )==0)
- return new spluginGenVPart;
- if(name.compare( string("calc-abl") )==0)
- return new spluginCalcABL;
- if(name.compare( string("add-database") )==0)
- return new spluginWriteDatabase;
- return NULL;
-}
-
-}; // DDF
-
diff --git a/intern/smoke/intern/util/boundbox.h b/intern/smoke/intern/util/boundbox.h
deleted file mode 100644
index 158f72fafd6..00000000000
--- a/intern/smoke/intern/util/boundbox.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Bounding box class
- *
- *****************************************************************************/
-
-#ifndef BOUNDBOX_H
-#define BOUNDBOX_H
-
-#include "vectorbase.h"
-
-
-namespace DDF {
-
-//! bbox for a vector
-template<class VecClass>
-class BboxVec {
- public:
- BboxVec() : mStart(0), mEnd(0) { };
- BboxVec(VecClass s, VecClass e) :
- mStart(s), mEnd(e) { };
- ~BboxVec() {};
-
- bool contains(VecClass p) {
- for(int i=0; i<3; i++) if(p[i]<mStart[i]) return false;
- for(int i=0; i<3; i++) if(p[i]>mEnd[i]) return false;
-// print stats of pressure min/max
- return true;
- };
-
- inline VecClass& getStart() { return mStart; }
- inline VecClass& getEnd() { return mEnd; }
-
- std::string toString() {
- std::ostringstream out;
- out <<"bbox s:"<<mStart
- <<" e:"<<mEnd <<" ";
- return out.str();
- };
-
- protected:
- // region
- VecClass mStart;
- VecClass mEnd;
-
-}; // BboxVec
-
-typedef BboxVec<Vec3> BboxVecr;
-typedef BboxVec<nVec3i> BboxVeci;
-
-} // namespace DDF
-
-#endif
-
-
diff --git a/intern/smoke/intern/util/globals.cpp b/intern/smoke/intern/util/globals.cpp
deleted file mode 100644
index 6c36f0c8a16..00000000000
--- a/intern/smoke/intern/util/globals.cpp
+++ /dev/null
@@ -1,395 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Global functions for logging etc.
- *
- *****************************************************************************/
-
-#include "globals.h"
-#include "grid.h"
-
-#include <stdlib.h>
-#include <limits.h>
-#include <iostream>
-#include <sstream>
-#include "waveletnoise.h"
-#ifdef WIN32
-// for timing
-#include <windows.h>
-#else
-#include <time.h>
-#include <sys/time.h>
-#include <sys/times.h>
-#endif
-
-// debugging, global id Counter
-long int idCounter = 0;
-
-namespace DDF {
-
-// global debug level
-// 0=all off, 1=err only, 2=err+warn, >=3=all on
-int gDebugLevel = 10;
-
-// globals for grids.h
-int gPatchIdCounter = 0;
-int gGridIdCounter = 0;
-class PatchManager;
-PatchManager *gpPatchManager = NULL;
-
-// globals for operators.h, misc. debugging profiling
-int gGridPassCounter = 0;
-double gPatchCount[10] = {0,0,0,0,0, 0,0,0,0,0};
-double gSerialPatchCnt = 0.;
-unsigned int gCountApplyOp = 0;
-unsigned int gCountApplyOpNoFlag = 0;
-unsigned int gCountApplyOpSimple = 0;
-unsigned int gCountPatchLocks[10] = {0,0,0,0,0, 0,0,0,0,0};
-
-// globals for vectorbase.h
-const Real gVecEpsilon = VECTOR_EPSILON;
-// instantiate zero vectors
-template<> const ntlVector3Dim<float > ntlVector3Dim<float >::ZERO( 0.f, 0.f, 0.f );
-template<> const ntlVector3Dim<double> ntlVector3Dim<double>::ZERO( 0., 0., 0. );
-template<> const ntlVector3Dim<int > ntlVector3Dim<int >::ZERO( 0, 0, 0 );
-
-// globals for waveletnoise.h
-float* stdTileData = NULL;
-
-//! for interval debugging output
-myTime_t globalIntervalTime = 0;
-//! color output setting for messages (0==off, else on)
-#ifdef WIN32
-// switch off first call (=-1)
-#define DEF_globalColorSetting -1
-#else // WIN32
-// linux etc., on by default (=1)
-#define DEF_globalColorSetting -1
-#endif // WIN32
-int globalColorSetting = DEF_globalColorSetting; // linux etc., on by default
-int globalFirstEnvCheck = 0;
-void resetGlobalColorSetting() { globalColorSetting = DEF_globalColorSetting; }
-
-// global string for formatting vector output, TODO test!?
-#if DDF_DIMENSION==3
-//const char *globVecFormatStr = "[%4.2f,%4.2f,%4.2f]";
-const char *globVecFormatStr = "[%6.4f,%6.4f,%6.4f]";
-#else // DDF_DIMENSION==3
-const char *globVecFormatStr = "[%4.2f,%4.2f]";
-#endif
-
-// global state & error
-int gSimState = 0;
-char gSimErrorString[256];
-
-void setSimState(int set) { gSimState = set; }
-int getSimState(void) { return gSimState; }
-int isSimworldOk(void) { return gSimState>=0; }
-
-void setSimErrorString(char* set) { strncpy(gSimErrorString,set,256); }
-char* getSimErrorString(void) { return gSimErrorString; }
-
-// get string of global settings
-string getSettingsString() {
- std::ostringstream ret;
- ret <<
- "Settings"<<
- //", Bits:"<<((sizeof(int*)==8) ? string("64") : string("32") )<<
- ", B:"<<sizeof(int*)<<
- ", Dim:"<<DDF::gDim<<
- ", Patches: OFF"<<
- ", PatchSize:"<<DDF::gPatchSize<<
- ", fp.Prec.:"<<FLOATINGPOINT_PRECISION<<
- ", Omp:"<<DDF_OPENMP<<
- " "
- ;
-#if DDF_OPENMP==1
- //omp_set_num_threads(2); // test
-#pragma omp parallel default(shared)
- { // omp region
- const int id = omp_get_thread_num();
- const int Nthrds = omp_get_num_threads();
- if(id==0) ret << ", #threads:"<<Nthrds;
- }
-#endif // DDF_OPENMP==1
- return ret.str();
-}
-
-//-----------------------------------------------------------------------------
-// helper function that converts a string to integer,
-// and returns an alternative value if the conversion fails
-int convertString2Int(const char *str, int alt)
-{
- int val;
- char *endptr;
- bool success=true;
-
- val = strtol(str, &endptr, 10);
- if( (str==endptr) ||
- ((str!=endptr) && (*endptr != '\0')) ) success = false;
-
- if(!success) {
- return alt;
- }
- return val;
-}
-
-//-----------------------------------------------------------------------------
-//! helper function that converts a flag field to a readable integer
-string convertFlags2String(int flags) {
- std::ostringstream ret;
- ret <<"(";
- int max = sizeof(int)*8;
- for(int i=0; i<max; i++) {
- if(flags & (1<<31)) ret <<"1";
- else ret<<"0";
- if(i<max-1) {
- //ret << ",";
- if((i%8)==7) ret << " ";
- }
- flags = flags << 1;
- }
- ret <<")";
- return ret.str();
-}
-
-//-----------------------------------------------------------------------------
-// helper function to determine current time
-myTime_t getTime()
-{
- myTime_t ret = 0;
-#ifdef WIN32
- LARGE_INTEGER liTimerFrequency;
- QueryPerformanceFrequency(&liTimerFrequency);
- LARGE_INTEGER liLastTime;
- QueryPerformanceCounter(&liLastTime);
- ret = (INT)( ((double)liLastTime.QuadPart / liTimerFrequency.QuadPart)*1000 ); // - mFirstTime;
-#else
- struct timeval tv;
- struct timezone tz;
- tz.tz_minuteswest = 0;
- tz.tz_dsttime = 0;
- gettimeofday(&tv,&tz);
- ret = (tv.tv_sec*1000)+(tv.tv_usec/1000); //-mFirstTime;
-#endif
- return (myTime_t)ret;
-}
-
-//-----------------------------------------------------------------------------
-// convert time to readable string
-string getTimeString(myTime_t usecs) {
- std::ostringstream ret;
- //myTime_t us = usecs % 1000;
- myTime_t ms = (myTime_t)( (double)usecs / (60.0*1000.0) );
- myTime_t ss = (myTime_t)( ((double)usecs / 1000.0) - ((double)ms*60.0) );
- int ps = (int)( ((double)usecs - (double)ss*1000.0)/10.0 );
-
- //ret.setf(ios::showpoint|ios::fixed);
- //ret.precision(5); ret.width(7);
-
- if(ms>0) {
- ret << ms<<"m"<< ss<<"s" ;
- } else {
- if(ps>0) {
- ret << ss<<".";
- if(ps<10) { ret <<"0"; }
- ret <<ps<<"s" ;
- } else {
- ret << ss<<"s" ;
- }
- }
- return ret.str();
-}
-
-//! helper to check if a bounding box was specified in the right way
-bool checkBoundingBox(Vec3 s, Vec3 e, string checker) {
- if( (s[0]>e[0]) ||
- (s[1]>e[1]) ||
- (s[2]>e[2]) ) {
- errFatal("checkBoundingBox","Check by '"<<checker<<"' for BB "<<s<<":"<<e<<" failed! Aborting...",SIMWORLD_INITERROR);
- return 1;
- }
- return 0;
-}
-
-
-
-//-----------------------------------------------------------------------------
-// debug message output
-
-static string col_black ( "\033[0;30m");
-static string col_dark_gray ( "\033[1;30m");
-static string col_bright_gray ( "\033[0;37m");
-static string col_red ( "\033[0;31m");
-static string col_bright_red ( "\033[1;31m");
-static string col_green ( "\033[0;32m");
-static string col_bright_green ( "\033[1;32m");
-static string col_bright_yellow ( "\033[1;33m");
-static string col_yellow ( "\033[0;33m");
-static string col_cyan ( "\033[0;36m");
-static string col_bright_cyan ( "\033[1;36m");
-static string col_purple ( "\033[0;35m");
-static string col_bright_purple ( "\033[1;35m");
-static string col_neutral ( "\033[0m");
-static string col_std = col_bright_gray;
-
-std::ostringstream globOutstr;
-bool globOutstrForce=false;
-#define DM_NONE 100
-void messageOutputForce(string from) {
- bool org = globOutstrForce;
- globOutstrForce = true;
- messageOutputFunc(from, DM_NONE, "\n", 0);
- globOutstrForce = org;
-}
-
-void messageOutputFunc(string from, int id, string msg, myTime_t interval) {
- // fast skip
- if((id!=DM_FATAL)&&(gDebugLevel<=0)) return;
-
- if(interval>0) {
- myTime_t currTime = getTime();
- if((currTime - globalIntervalTime)>interval) {
- globalIntervalTime = getTime();
- } else {
- return;
- }
- }
-
- // colors off?
- if( (globalColorSetting == -1) || // off for e.g. win32
- ((globalColorSetting==1) && ((id==DM_FATAL)||( getenv("DDF_NOCOLOROUT") )) )
- ) {
- // only reset once
- col_std = col_black = col_dark_gray = col_bright_gray =
- col_red = col_bright_red = col_green =
- col_bright_green = col_bright_yellow =
- col_yellow = col_cyan = col_bright_cyan =
- col_purple = col_bright_purple = col_neutral = "";
- globalColorSetting = 0;
- }
-
- std::ostringstream sout;
-
- if(id==DM_FATAL) {
- // dont print?
- if(gDebugLevel==0) return;
- sout << "\n\n\n"; // add newline for output
- sout << " !!!!!!!!!!!!!!!!!!!!!!!! \n"; // add newline for output
- sout << " !!!!!!!!!!!!!!!!!!!!!!!! \n"; // add newline for output
- sout << " !!!!!!!!!!!!!!!!!!!!!!!! \n"; // add newline for output
- }
-
- sout << col_cyan<< from;
- switch(id) {
- case DM_MSG:
- sout << col_std << ":";
- break;
- case DM_WARNING:
- sout << col_bright_red << " warning:" << col_std;
- break;
- case DM_ERROR:
- sout << col_red << " error:" << col_red;
- break;
- case DM_FATAL:
- sout << col_red << " fatal("<<gSimState<<"):" << col_red;
- break;
- default:
- // this shouldnt happen...
- sout << col_red << " --- messageOutputFunc error: invalid id ("<<id<<") --- aborting... \n\n" << col_std;
- break;
- }
- sout <<" "<< msg << col_std;
-
- if(id==DM_FATAL) {
- strncpy(gSimErrorString, sout.str().c_str(), 256);
- // dont print?
- if(gDebugLevel==0) return;
- sout << " ! \n"; // add newline for output
- sout << " !!!!!!!!!!!!!!!!!!!!!!!! \n"; // add newline for output
- sout << " !!!!!!!!!!!!!!!!!!!!!!!! \n"; // add newline for output
- sout << " !!!!!!!!!!!!!!!!!!!!!!!! \n\n\n\n\n\n\n"; // add newline for output
- sout << "\n"; // add newline for output
- }
-
- // determine output - file==1/stdout==0 / globstr==2
- char filen[256];
- strcpy(filen,"debug_unini.txt");
- int fileout = 0;
- /*std::ostringstream mpin;
- if(glob_mpindex>=0) {
- mpin << "ddf_log_"<< glob_mpindex <<".txt";
- } else {
- mpin << "ddf_log_ini.txt";
- }
- fileout = 1;
- strncpy(filen, mpin.str().c_str(),255); filen[255]='\0';// */
- strncpy(filen, "ddf_debug_log.txt",255);
-
- //#ifdef WIN32
- // windows causes trouble with direct output
- //fileout = 1;
- //#endif // WIN32
-
-#if WITH_OPENMP==1
- fileout = 2;// buffer out, switch off again...
- if(globOutstrForce) fileout=1;
-#endif
- if(getenv("DDF_FORCESTDOUT")) {
- fileout = 0;// always direct out
- }
- //fprintf(stdout,"out deb %d, %d, '%s',l%d \n",globOutstrForce,fileout, filen, globOutstr.str().size() );
-
-#if WITH_OPENMP==1
-#pragma omp critical MESSAGE_DEBUG_OUT
-#endif // WITH_OPENMP==1
- {
- if(fileout==1) {
- // debug level is >0 anyway, so write to file...
- FILE *logf = fopen(filen,"a+");
- // dont complain anymore here...
- if(logf) {
- if(globOutstrForce) {
- fprintf(logf, "%s",globOutstr.str().c_str() );
- globOutstr.str(""); // reset
- }
- fprintf(logf, "%s",sout.str().c_str() );
- fclose(logf);
- }
- } else if(fileout==2) {
- globOutstr << sout.str();
- } else {
- // normal stdout output
- fprintf(stdout, "%s",sout.str().c_str() );
- fflush(stdout);
- }
- } // omp crit
-
- // don't segfault in gui
- if(id==DM_FATAL) {
- // DEBUG force segfault
- *(int *)(0) = 0;
- exit(999);
- }
-#if DDF_GLUTGUI!=1
-#endif
-}
-
-// grids.h implementations
-template<> void Grid<int>::setDummyZero() { mZero = 0; }
-template<> void Grid<float>::setDummyZero() { mZero = 0.f; }
-template<> void Grid<double>::setDummyZero() { mZero = 0.; }
-template<> void Grid<Vec3>::setDummyZero() { mZero = Vec3(0.); }
-
-} // DDF
-
-// global list
-map<string, WAVELETNOISE::WaveletNoiseField*> gNoiseFields;
-
-
-
diff --git a/intern/smoke/intern/util/globals.h b/intern/smoke/intern/util/globals.h
deleted file mode 100644
index fd8b3fdd742..00000000000
--- a/intern/smoke/intern/util/globals.h
+++ /dev/null
@@ -1,457 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Declarations for global functions and variables
- *
- *****************************************************************************/
-
-
-#ifndef UTILITIES_H
-#define UTILITIES_H
-
-
-// "brute force" global defines
-#ifndef DDF_DEBUG
-#define DDF_DEBUG 0
-#endif // DDF_DEBUG
-
-// dimension of solver
-#ifndef DDF_DIMENSION
-#define DDF_DIMENSION 3
-#endif
-
-// openmp
-#ifndef DDF_OPENMP
-#define DDF_OPENMP 0
-#endif
-
-#ifdef WIN32
-// If windows.h is included, it defines a macro min() and max(),
-// which can lead to all sorts of weird problems, e.g. conflicts
-// with the STL algorithms min() and max(). By #defining NOMINMAX,
-// we prevent windows.h from defining these macros.
-#define NOMINMAX
-#endif
-
-// this serves as the main include file
-// for all kinds of stuff that might be required.
-// under windos there seem to be strange
-// errors when including the STL header too
-// late...
-#include <iostream>
-#include <map>
-#include <vector>
-#include <string>
-#include <sstream>
-#include <math.h>
-#include <string.h>
-#include <stdio.h>
-#if DDF_OPENMP==1
-#include "omp.h"
-#endif
-
-// hack for MSVC6.0 compiler
-#ifdef _MSC_VER
-# if _MSC_VER < 1300
-# define for if(false); else for
-# define map std::map
-# define vector std::vector
-# define string std::string
- // use this define for MSVC6 stuff hereafter
- //# define USE_MSVC6FIXES
-# else
- // _MSC_VER >= 1300 , 7.0 or higher
- using std::map;
- using std::vector;
- using std::string;
-# endif
-#else // not MSVC6
- // for proper compilers...
- using std::map;
- using std::vector;
- using std::string;
-#endif // MSVC6
-
-#ifdef __APPLE_CC__
- // apple
-#else
-
-# ifdef WIN32
- // windows values missing, see below
-# ifndef snprintf
-# define snprintf _snprintf
-# endif
- // rounding function
-# ifndef round
- inline double round(double x) { return floor(x + 0.5); }
-# endif
-# ifndef false
-# define false 0
-# endif
-# ifndef true
-# define true 1
-# endif
-# else
- // not WIN32
- // floating point limits for linux,*bsd etc...
- #include <float.h>
-# endif // WIN32
-
-#endif // __APPLE_CC__
-
-// standard includes
-#include "vectorbase.h"
-
-namespace DDF {
-
-// dimension variable
-const int gDim = DDF_DIMENSION;
-
-// debugging outputs , debug level 0 (off) to 10 (max)
-extern int gDebugLevel;
-
-// get string of global settings
-string getSettingsString();
-
-// time measurements
-typedef unsigned long myTime_t;
-
-
-// state of the simulation world
-// default state
-#define SIMWORLD_OK 0
-// error during init
-#define SIMWORLD_INITERROR -1
-// error during simulation
-#define SIMWORLD_PANIC -2
-// general error
-#define SIMWORLD_GENERICERROR -3
-// error in grid handling
-#define SIMWORLD_GRIDERROR -4
-// error in grid handling
-#define SIMWORLD_ERRPARSE -5
-// error with plugins
-#define SIMWORLD_PLUGINERROR -6
-
-// access global state of elbeem simulator
-void setSimState(int set);
-int getSimState(void);
-int isSimworldOk(void);
-
-// access elbeem simulator error string
-void setSimErrorString(char* set);
-char* getSimErrorString(void);
-
-// debug messages on/off
-#define USE_DEBUG_MESSAGES 1
-#if USE_DEBUG_MESSAGES==1
-
-/* debug output function */
-#define DM_MSG 1
-#define DM_WARNING 2
-#define DM_ERROR 3
-#define DM_FATAL 4
-void messageOutputFunc(string from, int id, string msg, myTime_t interval);
-
-// debugging messages defines
-//#define MSGSTREAM std::ostringstream msg; msg.precision(15); msg.width(17);
-#define MSGSTREAM std::ostringstream msg; msg.precision(7); msg.width(9);
-
-#define errMsg(from,mStr) if(DDF::gDebugLevel>0){ MSGSTREAM; msg << mStr <<"\n"; DDF::messageOutputFunc(from, DM_ERROR, msg.str(), 0); }
-#define warnMsg(from,mStr) if(DDF::gDebugLevel>1){ MSGSTREAM; msg << mStr <<"\n"; DDF::messageOutputFunc(from, DM_WARNING, msg.str(), 0); }
-#define debMsg(from,mStr) if(DDF::gDebugLevel>2){ MSGSTREAM; msg << mStr <<"\n"; DDF::messageOutputFunc(from, DM_MSG, msg.str(), 0); }
-
-#else
-// no messages at all...
-# define debMsg(mStr)
-# define debMsgId(from,id,mStr,level)
-# define errMsg(from,mStr)
-# define warnMsg(from,mStr)
-#endif
-
-
-// fatal errors - have to be handled
-#define errFatal(from,mStr,errCode) { \
- DDF::setSimState(errCode); \
- MSGSTREAM; msg << mStr; \
- DDF::messageOutputFunc(from, DM_FATAL, msg.str(), 0); \
-}
-
-
-//! helper function that converts a string to integer
-int convertString2Int(const char *str, int alt);
-
-//! helper function that converts a flag field to a readable integer
-string convertFlags2String(int flags);
-
-//! get the current system time
-myTime_t getTime();
-//! convert time to readable string
-string getTimeString(myTime_t usecs);
-
-//! helper to check if a bounding box was specified in the right way
-bool checkBoundingBox(Vec3 s, Vec3 e, string checker);
-
-//! reset color output for elbeem init
-void resetGlobalColorSetting();
-
-
-/*! print some vector from 3 values e.g. for ux,uy,uz */
-#define PRINT_VEC(x,y,z) " ["<<(x)<<","<<(y)<<","<<(z)<<"] "
-
-/*! print i,j,k as a vector, as we need ijk all the time */
-#define PRINT_IJK PRINT_VEC(i,j,k)
-
-
-// write png image
-int writeImage(const char *fileName, unsigned char **rowsp, int w, int h);
-
-
-// template helper funcs
-
-// minimum
-template < class T >
-inline T
-MIN( T a, T b )
-{ return (a < b) ? a : b ; }
-
-// maximum
-template < class T >
-inline T
-MAX( T a, T b )
-{ return (a < b) ? b : a ; }
-
-// maximum of a vector
-template < class T >
-inline T
-VMAX( ntlVector3Dim<T> a )
-{
- if(a[0]<a[1]) {
- if(a[1]<a[2]) return a[2];
- else return a[1];
- } else {
- if(a[0]<a[2]) return a[2];
- else return a[0];
- }
-}
-// minimum of a vector
-template < class T >
-inline T
-VMIN( ntlVector3Dim<T> a )
-{
- if(a[0]>a[1]) {
- if(a[1]>a[2]) return a[2];
- else return a[1];
- } else {
- if(a[0]>a[2]) return a[2];
- else return a[0];
- }
-}
-
-// swap two values
-template < class T >
-inline void
-TRISWAP( T& a, T& b )
-{
- T tmp = a;
- a = b;
- b = tmp;
-}
-
-// absolute value
-template < class T >
-inline T
-ABS( T a )
-{ return (0 < a) ? a : -a ; }
-
-// sign of the value
-template < class T >
-inline T
-SIGNUM( T a )
-{ return (0 < a) ? 1 : -1 ; }
-
-// sign, returns -1,0,1 depending on sign/value=0
-template < class T >
-inline T
-SIGNUM0( T a )
-{ return (0 < a) ? 1 : ( a < 0 ? -1 : 0 ) ; }
-
-// round to nearest integer
-inline int
-ROUND(double d)
-{ return int(d + 0.5); }
-
-// square function
-template < class T >
-inline T
-SQUARE( T a )
-{ return a*a; }
-
-// cube function
-template < class T >
-inline T
-CUBEFUNC( T a )
-{ return a*a*a; }
-
-
-// helper class, track min,max and avg of some scalar type T
-template<class T> class MinMaxTracker {
-public:
- MinMaxTracker() {
- mMin = 1e20;
- mMax = -1e20;
- mAccumulation = 0.0;
- mCnt = 0;
- };
- ~MinMaxTracker() {};
-
- // take into account value
- inline void check(T& val) {
- if (mMin>val) mMin=val;
- if (mMax<val) mMax=val;
- mAccumulation += val;
- mCnt++;
- }
-
- // in out put
-
- T getMin() {return mMin;}
- T getMax() {return mMax;}
- T getAvg() {return mAccumulation/(double)(mCnt);}
-
- std::string str() {
- std::ostringstream out;
- out <<"min="<<mMin<<", max="<<mMax<<", avg="<<getAvg();
- return out.str();
- }
-
-protected:
- T mMin,mMax, mAccumulation;
- int mCnt;
-}; // MinMaxTracker
-
-template<class T>
-std::string helperPrintMap(std::map<std::string, T*>& pmap, std::string caller) {
- std::ostringstream out;
- //debMsg("print map","for '"<<caller<<"', "<<pmap.size()<<" entries ");
- out << "print map for '"<<caller<<"', "<<pmap.size()<<" entries ";
- int cnt=0;
- for(typename std::map<std::string, T*>::iterator iter=pmap.begin(); iter != pmap.end(); iter++) {
- long int pntval = (long int)( (*iter).second );
- //debMsg("entry","i "<<cnt<<"/"<<pmap.size()<<" name '"<<(*iter).first <<"' is " << pntval );
- out << "entry "<<cnt<<"/"<<pmap.size()<<" name '"<<(*iter).first <<"' is " << pntval<<", ";
- cnt++;
- }
- return out.str();
-} // helperPrintMap
-
-
-//*****************************************************************************
-// utility defines
-
-#define FOR_IJK(kmin,kmax,jmin,jmax,imin,imax) \
- for (int k=(kmin); k<(kmax); k++) \
- for (int j=(jmin); j<(jmax); j++) \
- for (int i=(imin); i<(imax); i++) /* loop body */
-#define FOR_IJK_GRID(grid) \
- FOR_IJK( (grid)->getMinZLoopValue(), (grid)->getMaxZLoopValue(), 0, (grid)->getSizeY(), 0, (grid)->getSizeX() )
-#define FOR_IJK_GRID_BND(grid,bnd) \
- FOR_IJK( (grid)->getMinZLoopValue(bnd), (grid)->getMaxZLoopValue(bnd), 0+(bnd), (grid)->getSizeY()-(bnd), 0+(bnd), (grid)->getSizeX()-(bnd) )
-#define FOR_IJK_VEC(vecmin, vecmax) \
- FOR_IJK(vecmin[2],vecmax[2],vecmin[1],vecmax[1],vecmin[0],vecmax[0])
-
-// reverse loops
-#define FOR_IJKREV(kmin,kmax,jmin,jmax,imin,imax) \
- for (int k=(kmin); k>=(kmax); k--) \
- for (int j=(jmin); j>=(jmax); j--) \
- for (int i=(imin); i>=(imax); i--) /* loop body */
-#define FOR_IJKREV_GRID(grid) \
- FOR_IJKREV( (grid)->getMaxZLoopValue()-1,(grid)->getMinZLoopValue(), (grid)->getSizeY()-1, 0, (grid)->getSizeX()-1, 0 )
-
-//*****************************************************************************
-// clamping helper functions
-
-// clamp a in range b<= a <= c
-// write to a
-template < class T >
-inline void
-CLAMP( T &a, T b , T c )
-{
- if(a < b) a=b;
- else if(a > c) a=c;
-}
-
-// clamp , and return value
-template < class T >
-inline T
-CLAMP_RET( T a, T b , T c ) {
- if(a < b) return b;
- else if(a > c) return c;
- return a;
-}
-
-template < class T >
-inline T
-CLAMP_DOWN_RET( T a, T b ) {
- if(a < b) return b;
- return a;
-}
-
-template < class T >
-inline T
-CLAMP_UP_RET( T a, T b ) {
- if(a > b) return b;
- return a;
-}
-
-// clamp and return whether clamping occured
-template < class T >
-inline bool
-CLAMP_BOOL( T &a, T b , T c )
-{
- if(a < b) {
- a=b;
- return true;
- }
-
- if(a > c) {
- a=c;
- return true;
- }
- return false;
-}
-
-// clamp to grid boundaries
-template < class T >
-inline void CLAMP_TO_GRID(int &i, int &j, int &k, T grid) {
- CLAMP(i, 0, grid->getSizeX()-2 );
- CLAMP(j, 0, grid->getSizeY()-2 );
- CLAMP(k, 0, grid->getSizeZ()-2 );
-}
-
-// clamp to grid and return whether clamping occured
-template < class T >
-inline bool CLAMP_TO_GRID_BOOL(int &i, int &j, int &k, T grid) {
- bool ret = false;
- ret |= CLAMP_BOOL(i, 0, grid->getSizeX()-2 );
- ret |= CLAMP_BOOL(j, 0, grid->getSizeY()-2 );
- ret |= CLAMP_BOOL(k, 0, grid->getSizeZ()-2 );
- return ret;
-}
-
-
-// constants for easier neighbor traversal
-static const int nbX[6] = {-1,1, 0,0,0,0};
-static const int nbY[6] = { 0,0, -1,1, 0,0};
-static const int nbZ[6] = { 0,0,0,0, -1,1,};
-
-
-} // DDF
-
-#endif
-
diff --git a/intern/smoke/intern/util/matrixbase.h b/intern/smoke/intern/util/matrixbase.h
deleted file mode 100644
index 396bd589423..00000000000
--- a/intern/smoke/intern/util/matrixbase.h
+++ /dev/null
@@ -1,810 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Simple matrix class
- *
- *****************************************************************************/
-
-
-#include "vectorbase.h"
-
-#ifndef NTL_MATRICES_H
-
-// init matrices with zero always?
-#define MATRIX_INIT_ZERO 0
-
-
-namespace DDF {
-
-
-// a basic simple 4x4 matrix class
-template<class Scalar>
-class ntlMatrix4x4
-{
- public:
- // Constructor
- inline ntlMatrix4x4(void );
- // Copy-Constructor
- inline ntlMatrix4x4(const ntlMatrix4x4<Scalar> &v );
- // construct a matrix from one Scalar
- inline ntlMatrix4x4(Scalar);
- // construct a matrix from three Scalars
- inline ntlMatrix4x4(Scalar, Scalar, Scalar);
-
- // Assignment operator
- inline const ntlMatrix4x4<Scalar>& operator= (const ntlMatrix4x4<Scalar>& v);
- // Assignment operator
- inline const ntlMatrix4x4<Scalar>& operator= (Scalar s);
- // Assign and add operator
- inline const ntlMatrix4x4<Scalar>& operator+= (const ntlMatrix4x4<Scalar>& v);
- // Assign and add operator
- inline const ntlMatrix4x4<Scalar>& operator+= (Scalar s);
- // Assign and sub operator
- inline const ntlMatrix4x4<Scalar>& operator-= (const ntlMatrix4x4<Scalar>& v);
- // Assign and sub operator
- inline const ntlMatrix4x4<Scalar>& operator-= (Scalar s);
- // Assign and mult operator
- inline const ntlMatrix4x4<Scalar>& operator*= (const ntlMatrix4x4<Scalar>& v);
- // Assign and mult operator
- inline const ntlMatrix4x4<Scalar>& operator*= (Scalar s);
- // Assign and div operator
- inline const ntlMatrix4x4<Scalar>& operator/= (const ntlMatrix4x4<Scalar>& v);
- // Assign and div operator
- inline const ntlMatrix4x4<Scalar>& operator/= (Scalar s);
-
-
- // unary operator
- inline ntlMatrix4x4<Scalar> operator- () const;
-
- // binary operator add
- inline ntlMatrix4x4<Scalar> operator+ (const ntlMatrix4x4<Scalar>&) const;
- // binary operator add
- inline ntlMatrix4x4<Scalar> operator+ (Scalar) const;
- // binary operator sub
- inline ntlMatrix4x4<Scalar> operator- (const ntlMatrix4x4<Scalar>&) const;
- // binary operator sub
- inline ntlMatrix4x4<Scalar> operator- (Scalar) const;
- // binary operator mult
- inline ntlMatrix4x4<Scalar> operator* (const ntlMatrix4x4<Scalar>&) const;
- // binary operator mult
- inline ntlVector3Dim<Scalar> operator* (const ntlVector3Dim<Scalar>&) const;
- // binary operator mult
- inline ntlMatrix4x4<Scalar> operator* (Scalar) const;
- // binary operator div
- inline ntlMatrix4x4<Scalar> operator/ (Scalar) const;
-
- // init function
- //! init identity matrix
- inline void initId();
- //! init rotation matrix
- inline void initTranslation(Scalar x, Scalar y, Scalar z);
- //! init rotation matrix
- inline void initRotationX(Scalar rot);
- inline void initRotationY(Scalar rot);
- inline void initRotationZ(Scalar rot);
- inline void initRotationXYZ(Scalar rotx,Scalar roty, Scalar rotz);
- //! init scaling matrix
- inline void initScaling(Scalar scale);
- inline void initScaling(Scalar x, Scalar y, Scalar z);
-
- //! from 16 value array (init id if all 0)
- inline void initFromArray(Scalar *array);
-
- inline void transpose();
-
- //! decompose matrix intro translation, scale, rot and shear
- void decompose(ntlVector3Dim<Scalar> &trans,ntlVector3Dim<Scalar> &scale,ntlVector3Dim<Scalar> &rot,ntlVector3Dim<Scalar> &shear);
-
- //! public to avoid [][] operators
- Scalar value[4][4]; //< Storage of maxtrix values
-
- protected:
-
-};
-
-
-
-
-
-//------------------------------------------------------------------------------
-// STREAM FUNCTIONS
-//------------------------------------------------------------------------------
-
-
-
-/*************************************************************************
- Outputs the object in human readable form using the format
- [x,y,z]
- */
-template<class Scalar>
-std::ostream&
-operator<<( std::ostream& os, const ntlMatrix4x4<Scalar>& m )
-{
- for(int i=0; i<4; i++) {
- os << '|' << m.value[i][0] << ", " << m.value[i][1] << ", " << m.value[i][2] << ", " << m.value[i][3] << '|';
- }
- return os;
-}
-
-
-
-/*************************************************************************
- Reads the contents of the object from a stream using the same format
- as the output operator.
- */
-template<class Scalar>
-std::istream&
-operator>>( std::istream& is, ntlMatrix4x4<Scalar>& m )
-{
- char c;
- char dummy[3];
-
- for(int i=0; i<4; i++) {
- is >> c >> m.value[i][0] >> dummy >> m.value[i][1] >> dummy >> m.value[i][2] >> dummy >> m.value[i][3] >> c;
- }
- return is;
-}
-
-
-//------------------------------------------------------------------------------
-// matrix inline FUNCTIONS
-//------------------------------------------------------------------------------
-
-
-
-/*************************************************************************
- Constructor.
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>::ntlMatrix4x4( void )
-{
-#if MATRIX_INIT_ZERO==1
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- value[i][j] = 0.0;
- }
- }
-#endif
-}
-
-
-
-/*************************************************************************
- Copy-Constructor.
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>::ntlMatrix4x4( const ntlMatrix4x4<Scalar> &v )
-{
- value[0][0] = v.value[0][0]; value[0][1] = v.value[0][1]; value[0][2] = v.value[0][2]; value[0][3] = v.value[0][3];
- value[1][0] = v.value[1][0]; value[1][1] = v.value[1][1]; value[1][2] = v.value[1][2]; value[1][3] = v.value[1][3];
- value[2][0] = v.value[2][0]; value[2][1] = v.value[2][1]; value[2][2] = v.value[2][2]; value[2][3] = v.value[2][3];
- value[3][0] = v.value[3][0]; value[3][1] = v.value[3][1]; value[3][2] = v.value[3][2]; value[3][3] = v.value[3][3];
-}
-
-
-
-/*************************************************************************
- Constructor for a vector from a single Scalar. All components of
- the vector get the same value.
- \param s The value to set
- \return The new vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>::ntlMatrix4x4(Scalar s )
-{
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- value[i][j] = s;
- }
- }
-}
-
-
-
-/*************************************************************************
- Copy a ntlMatrix4x4 componentwise.
- \param v vector with values to be copied
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator=( const ntlMatrix4x4<Scalar> &v )
-{
- value[0][0] = v.value[0][0]; value[0][1] = v.value[0][1]; value[0][2] = v.value[0][2]; value[0][3] = v.value[0][3];
- value[1][0] = v.value[1][0]; value[1][1] = v.value[1][1]; value[1][2] = v.value[1][2]; value[1][3] = v.value[1][3];
- value[2][0] = v.value[2][0]; value[2][1] = v.value[2][1]; value[2][2] = v.value[2][2]; value[2][3] = v.value[2][3];
- value[3][0] = v.value[3][0]; value[3][1] = v.value[3][1]; value[3][2] = v.value[3][2]; value[3][3] = v.value[3][3];
- return *this;
-}
-
-
-/*************************************************************************
- Copy a Scalar to each component.
- \param s The value to copy
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator=(Scalar s)
-{
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- value[i][j] = s;
- }
- }
- return *this;
-}
-
-
-/*************************************************************************
- Add another ntlMatrix4x4 componentwise.
- \param v vector with values to be added
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator+=( const ntlMatrix4x4<Scalar> &v )
-{
- value[0][0] += v.value[0][0]; value[0][1] += v.value[0][1]; value[0][2] += v.value[0][2]; value[0][3] += v.value[0][3];
- value[1][0] += v.value[1][0]; value[1][1] += v.value[1][1]; value[1][2] += v.value[1][2]; value[1][3] += v.value[1][3];
- value[2][0] += v.value[2][0]; value[2][1] += v.value[2][1]; value[2][2] += v.value[2][2]; value[2][3] += v.value[2][3];
- value[3][0] += v.value[3][0]; value[3][1] += v.value[3][1]; value[3][2] += v.value[3][2]; value[3][3] += v.value[3][3];
- return *this;
-}
-
-
-/*************************************************************************
- Add a Scalar value to each component.
- \param s Value to add
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator+=(Scalar s)
-{
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- value[i][j] += s;
- }
- }
- return *this;
-}
-
-
-/*************************************************************************
- Subtract another vector componentwise.
- \param v vector of values to subtract
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator-=( const ntlMatrix4x4<Scalar> &v )
-{
- value[0][0] -= v.value[0][0]; value[0][1] -= v.value[0][1]; value[0][2] -= v.value[0][2]; value[0][3] -= v.value[0][3];
- value[1][0] -= v.value[1][0]; value[1][1] -= v.value[1][1]; value[1][2] -= v.value[1][2]; value[1][3] -= v.value[1][3];
- value[2][0] -= v.value[2][0]; value[2][1] -= v.value[2][1]; value[2][2] -= v.value[2][2]; value[2][3] -= v.value[2][3];
- value[3][0] -= v.value[3][0]; value[3][1] -= v.value[3][1]; value[3][2] -= v.value[3][2]; value[3][3] -= v.value[3][3];
- return *this;
-}
-
-
-/*************************************************************************
- Subtract a Scalar value from each component.
- \param s Value to subtract
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator-=(Scalar s)
-{
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- value[i][j] -= s;
- }
- }
- return *this;
-}
-
-
-/*************************************************************************
- Multiply with another vector componentwise.
- \param v vector of values to multiply with
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator*=( const ntlMatrix4x4<Scalar> &v )
-{
- ntlMatrix4x4<Scalar> nv(0.0);
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
-
- for(int k=0;k<4;k++)
- nv.value[i][j] += (value[i][k] * v.value[k][j]);
- }
- }
- *this = nv;
- return *this;
-}
-
-
-/*************************************************************************
- Multiply each component with a Scalar value.
- \param s Value to multiply with
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator*=(Scalar s)
-{
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- value[i][j] *= s;
- }
- }
- return *this;
-}
-
-
-
-/*************************************************************************
- Divide each component by a Scalar value.
- \param s Value to divide by
- \return Reference to self
- */
-template<class Scalar>
-inline const ntlMatrix4x4<Scalar>&
-ntlMatrix4x4<Scalar>::operator/=(Scalar s)
-{
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- value[i][j] /= s;
- }
- }
- return *this;
-}
-
-
-//------------------------------------------------------------------------------
-// unary operators
-//------------------------------------------------------------------------------
-
-
-/*************************************************************************
- Build componentwise the negative this vector.
- \return The new (negative) vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>
-ntlMatrix4x4<Scalar>::operator-() const
-{
- ntlMatrix4x4<Scalar> nv;
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- nv[i][j] = -value[i][j];
- }
- }
- return nv;
-}
-
-
-
-//------------------------------------------------------------------------------
-// binary operators
-//------------------------------------------------------------------------------
-
-
-/*************************************************************************
- Build a vector with another vector added componentwise.
- \param v The second vector to add
- \return The sum vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>
-ntlMatrix4x4<Scalar>::operator+( const ntlMatrix4x4<Scalar> &v ) const
-{
- ntlMatrix4x4<Scalar> nv;
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- nv[i][j] = value[i][j] + v.value[i][j];
- }
- }
- return nv;
-}
-
-
-/*************************************************************************
- Build a vector with a Scalar value added to each component.
- \param s The Scalar value to add
- \return The sum vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>
-ntlMatrix4x4<Scalar>::operator+(Scalar s) const
-{
- ntlMatrix4x4<Scalar> nv;
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- nv[i][j] = value[i][j] + s;
- }
- }
- return nv;
-}
-
-
-/*************************************************************************
- Build a vector with another vector subtracted componentwise.
- \param v The second vector to subtract
- \return The difference vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>
-ntlMatrix4x4<Scalar>::operator-( const ntlMatrix4x4<Scalar> &v ) const
-{
- ntlMatrix4x4<Scalar> nv;
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- nv[i][j] = value[i][j] - v.value[i][j];
- }
- }
- return nv;
-}
-
-
-/*************************************************************************
- Build a vector with a Scalar value subtracted componentwise.
- \param s The Scalar value to subtract
- \return The difference vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>
-ntlMatrix4x4<Scalar>::operator-(Scalar s ) const
-{
- ntlMatrix4x4<Scalar> nv;
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- nv[i][j] = value[i][j] - s;
- }
- }
- return nv;
-}
-
-
-
-/*************************************************************************
- Build a ntlMatrix4x4 with a Scalar value multiplied to each component.
- \param s The Scalar value to multiply with
- \return The product vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>
-ntlMatrix4x4<Scalar>::operator*(Scalar s) const
-{
- ntlMatrix4x4<Scalar> nv;
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- nv[i][j] = value[i][j] * s;
- }
- }
- return nv;
-}
-
-
-
-
-/*************************************************************************
- Build a vector divided componentwise by a Scalar value.
- \param s The Scalar value to divide by
- \return The ratio vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>
-ntlMatrix4x4<Scalar>::operator/(Scalar s) const
-{
- ntlMatrix4x4<Scalar> nv;
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- nv[i][j] = value[i][j] / s;
- }
- }
- return nv;
-}
-
-
-
-
-
-/*************************************************************************
- Build a vector with another vector multiplied by componentwise.
- \param v The second vector to muliply with
- \return The product vector
- */
-template<class Scalar>
-inline ntlMatrix4x4<Scalar>
-ntlMatrix4x4<Scalar>::operator*( const ntlMatrix4x4<Scalar>& v) const
-{
- ntlMatrix4x4<Scalar> nv(0.0);
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
-
- for(int k=0;k<4;k++)
- nv.value[i][j] += (value[i][k] * v.value[k][j]);
- }
- }
- return nv;
-}
-
-
-template<class Scalar>
-inline ntlVector3Dim<Scalar>
-ntlMatrix4x4<Scalar>::operator*( const ntlVector3Dim<Scalar>& v) const
-{
- ntlVector3Dim<Scalar> nvec(0.0);
- for(int i=0; i<3; i++) {
- for(int j=0; j<3; j++) {
- nvec[i] += (v[j] * value[i][j]);
- }
- }
- // assume normalized w coord
- for(int i=0; i<3; i++) {
- nvec[i] += (1.0 * value[i][3]);
- }
- return nvec;
-}
-
-
-
-//------------------------------------------------------------------------------
-// Other helper functions
-//------------------------------------------------------------------------------
-
-//! init identity matrix
-template<class Scalar>
-inline void ntlMatrix4x4<Scalar>::initId()
-{
- (*this) = (Scalar)(0.0);
- value[0][0] =
- value[1][1] =
- value[2][2] =
- value[3][3] = (Scalar)(1.0);
-}
-
-//! init rotation matrix
-template<class Scalar>
-inline void ntlMatrix4x4<Scalar>::initTranslation(Scalar x, Scalar y, Scalar z)
-{
- //(*this) = (Scalar)(0.0);
- this->initId();
- value[0][3] = x;
- value[1][3] = y;
- value[2][3] = z;
-}
-
-//! init rotation matrix
-template<class Scalar>
-inline void
-ntlMatrix4x4<Scalar>::initRotationX(Scalar rot)
-{
- double drot = (double)(rot/360.0*2.0*M_PI);
- //? while(drot < 0.0) drot += (M_PI*2.0);
-
- this->initId();
- value[1][1] = (Scalar) cos(drot);
- value[1][2] = (Scalar) sin(drot);
- value[2][1] = (Scalar)(-sin(drot));
- value[2][2] = (Scalar) cos(drot);
-}
-template<class Scalar>
-inline void
-ntlMatrix4x4<Scalar>::initRotationY(Scalar rot)
-{
- double drot = (double)(rot/360.0*2.0*M_PI);
- //? while(drot < 0.0) drot += (M_PI*2.0);
-
- this->initId();
- value[0][0] = (Scalar) cos(drot);
- value[0][2] = (Scalar)(-sin(drot));
- value[2][0] = (Scalar) sin(drot);
- value[2][2] = (Scalar) cos(drot);
-}
-template<class Scalar>
-inline void
-ntlMatrix4x4<Scalar>::initRotationZ(Scalar rot)
-{
- double drot = (double)(rot/360.0*2.0*M_PI);
- //? while(drot < 0.0) drot += (M_PI*2.0);
-
- this->initId();
- value[0][0] = (Scalar) cos(drot);
- value[0][1] = (Scalar) sin(drot);
- value[1][0] = (Scalar)(-sin(drot));
- value[1][1] = (Scalar) cos(drot);
-}
-template<class Scalar>
-inline void
-ntlMatrix4x4<Scalar>::initRotationXYZ( Scalar rotx, Scalar roty, Scalar rotz)
-{
- ntlMatrix4x4<Scalar> val;
- ntlMatrix4x4<Scalar> rot;
- this->initId();
-
- // org
- /*rot.initRotationX(rotx);
- (*this) *= rot;
- rot.initRotationY(roty);
- (*this) *= rot;
- rot.initRotationZ(rotz);
- (*this) *= rot;
- // org */
-
- // blender
- rot.initRotationZ(rotz);
- (*this) *= rot;
- rot.initRotationY(roty);
- (*this) *= rot;
- rot.initRotationX(rotx);
- (*this) *= rot;
- // blender */
-}
-
-//! transpose matrix
-template<class Scalar>
-inline void
-ntlMatrix4x4<Scalar>::transpose()
-{
- for (int i=0;i<4;i++)
- for (int j=i+1;j<4;j++)
- {
- Scalar a=value[i][j];
- value[i][j]=value[j][i];
- value[j][i]=a;
- }
-}
-
-//! init scaling matrix
-template<class Scalar>
-inline void
-ntlMatrix4x4<Scalar>::initScaling(Scalar scale)
-{
- this->initId();
- value[0][0] = scale;
- value[1][1] = scale;
- value[2][2] = scale;
-}
-//! init scaling matrix
-template<class Scalar>
-inline void
-ntlMatrix4x4<Scalar>::initScaling(Scalar x, Scalar y, Scalar z)
-{
- this->initId();
- value[0][0] = x;
- value[1][1] = y;
- value[2][2] = z;
-}
-
-
-//! from 16 value array (init id if all 0)
-template<class Scalar>
-inline void
-ntlMatrix4x4<Scalar>::initFromArray(Scalar *array)
-{
- bool allZero = true;
- for(int i=0; i<4; i++) {
- for(int j=0; j<4; j++) {
- value[i][j] = array[i*4+j];
- if(array[i*4+j]!=0.0) allZero=false;
- }
- }
- if(allZero) this->initId();
-}
-
-//! decompose matrix
-template<class Scalar>
-void
-ntlMatrix4x4<Scalar>::decompose(ntlVector3Dim<Scalar> &trans,ntlVector3Dim<Scalar> &scale,ntlVector3Dim<Scalar> &rot,ntlVector3Dim<Scalar> &shear) {
- Vec3 row[3],temp;
-
- for(int i = 0; i < 3; i++) {
- trans[i] = this->value[3][i];
- }
-
- for(int i = 0; i < 3; i++) {
- row[i][0] = this->value[i][0];
- row[i][1] = this->value[i][1];
- row[i][2] = this->value[i][2];
- }
-
- scale[0] = norm(row[0]);
- normalize (row[0]);
-
- shear[0] = dot(row[0], row[1]);
- row[1][0] = row[1][0] - shear[0]*row[0][0];
- row[1][1] = row[1][1] - shear[0]*row[0][1];
- row[1][2] = row[1][2] - shear[0]*row[0][2];
-
- scale[1] = norm(row[1]);
- normalize (row[1]);
-
- if(scale[1] != 0.0)
- shear[0] /= scale[1];
-
- shear[1] = dot(row[0], row[2]);
- row[2][0] = row[2][0] - shear[1]*row[0][0];
- row[2][1] = row[2][1] - shear[1]*row[0][1];
- row[2][2] = row[2][2] - shear[1]*row[0][2];
-
- shear[2] = dot(row[1], row[2]);
- row[2][0] = row[2][0] - shear[2]*row[1][0];
- row[2][1] = row[2][1] - shear[2]*row[1][1];
- row[2][2] = row[2][2] - shear[2]*row[1][2];
-
- scale[2] = norm(row[2]);
- normalize (row[2]);
-
- if(scale[2] != 0.0) {
- shear[1] /= scale[2];
- shear[2] /= scale[2];
- }
-
- temp = cross(row[1], row[2]);
- if(dot(row[0], temp) < 0.0) {
- for(int i = 0; i < 3; i++) {
- scale[i] *= -1.0;
- row[i][0] *= -1.0;
- row[i][1] *= -1.0;
- row[i][2] *= -1.0;
- }
- }
-
- if(row[0][2] < -1.0) row[0][2] = -1.0;
- if(row[0][2] > +1.0) row[0][2] = +1.0;
-
- rot[1] = asin(-row[0][2]);
-
- if(fabs(cos(rot[1])) > VECTOR_EPSILON) {
- rot[0] = atan2 (row[1][2], row[2][2]);
- rot[2] = atan2 (row[0][1], row[0][0]);
- }
- else {
- rot[0] = atan2 (row[1][0], row[1][1]);
- rot[2] = 0.0;
- }
-
- rot[0] = (180.0/M_PI)*rot[0];
- rot[1] = (180.0/M_PI)*rot[1];
- rot[2] = (180.0/M_PI)*rot[2];
-}
-
-//------------------------------------------------------------------------------
-// TYPEDEFS
-//------------------------------------------------------------------------------
-
-
-typedef ntlMatrix4x4<double> ntlMat4d;
-
-// a 3D vector with single precision
-typedef ntlMatrix4x4<float> ntlMat4f;
-
-// a 3D integer vector
-typedef ntlMatrix4x4<int> ntlMat4i;
-
-
-
-// default vector typing
-// a 3D vector for graphics output, typically float?
-typedef ntlMatrix4x4<Real> Mat4;
-
-
-}; // namespace DDF
-
-#define NTL_MATRICES_H
-#endif
-
-
-
-
diff --git a/intern/smoke/intern/util/paramset.cpp b/intern/smoke/intern/util/paramset.cpp
deleted file mode 100644
index 88adc834521..00000000000
--- a/intern/smoke/intern/util/paramset.cpp
+++ /dev/null
@@ -1,373 +0,0 @@
-/******************************************************************************
- * Parameter storage class
- *
- * Copyright(c) 1998-2007 Matt Pharr and Greg Humphreys.
- *
- *****************************************************************************/
-
-// paramset.cpp*
-#define CORE_SOURCE
-#include "globals.h"
-#include "paramset.h"
-
-// ParamSet Macros
-#define ADD_PARAM_TYPE(T, vec) \
- (vec).push_back(new ParamSetItem<T>(name, (const T *)data, nItems))
-
-#define LOOKUP_PTR(vec) \
- for (size_t i = 0; i < (vec).size(); ++i) \
- if ((vec)[i]->name == name) { \
- *nItems = (vec)[i]->nItems; \
- (vec)[i]->lookedUp = true; \
- return (vec)[i]->data; \
- } \
- return NULL
-#define LOOKUP_ONE(vec) \
- for (size_t i = 0; i < (vec).size(); ++i) { \
- if ((vec)[i]->name == name && \
- (vec)[i]->nItems == 1) { \
- (vec)[i]->lookedUp = true; \
- return *((vec)[i]->data); \
-} } \
- return d
-
-// ParamSet Methods
-ParamSet::ParamSet(const ParamSet &p2) {
- *this = p2;
-}
-
-void ParamSet::AddSet(const ParamSet &p2) {
- unsigned i;
- for (i = 0; i < p2.ints.size(); ++i)
- AddInt(p2.ints[i]->name, p2.ints[i]->data);
- for (i = 0; i < p2.bools.size(); ++i)
- AddBool(p2.bools[i]->name, p2.bools[i]->data);
- for (i = 0; i < p2.floats.size(); ++i)
- AddFloat(p2.floats[i]->name, p2.floats[i]->data);
- for (i = 0; i < p2.vectors.size(); ++i)
- AddVector(p2.vectors[i]->name, p2.vectors[i]->data);
- for (i = 0; i < p2.strings.size(); ++i)
- AddString(p2.strings[i]->name, p2.strings[i]->data);
-}
-
-ParamSet &ParamSet::operator=(const ParamSet &p2) {
- if (&p2 != this) {
- Clear(); unsigned i;
- for (i = 0; i < p2.ints.size(); ++i)
- ints.push_back(p2.ints[i]->Clone());
- for (i = 0; i < p2.bools.size(); ++i)
- bools.push_back(p2.bools[i]->Clone());
- for (i = 0; i < p2.floats.size(); ++i)
- floats.push_back(p2.floats[i]->Clone());
- for (i = 0; i < p2.vectors.size(); ++i)
- vectors.push_back(p2.vectors[i]->Clone());
- for (i = 0; i < p2.strings.size(); ++i)
- strings.push_back(p2.strings[i]->Clone());
- }
- return *this;
-}
-
-void ParamSet::override(const ParamSet &p2) {
- // note - this only overrides parameters that already
- // exist in the paramset!
-
- if (&p2 != this) {
- for (size_t i = 0; i < p2.ints.size(); ++i) {
- for (size_t j = 0; j < this->ints.size(); ++j) {
- if (p2.ints[i]->name.compare( this->ints[j]->name )==0) {
- fprintf(stderr,"Overriding int '%s' \n", this->ints[j]->name.c_str() );
- this->ints[j] = p2.ints[i]->Clone();
- }
- }
- }
- for (size_t i = 0; i < p2.bools.size(); ++i) {
- for (size_t j = 0; j < this->bools.size(); ++j) {
- if (p2.bools[i]->name.compare( this->bools[j]->name )==0) {
- fprintf(stderr,"Overriding bool '%s' \n", this->bools[j]->name.c_str() );
- this->bools[j] = p2.bools[i]->Clone();
- }
- }
- }
- for (size_t i = 0; i < p2.floats.size(); ++i) {
- for (size_t j = 0; j < this->floats.size(); ++j) {
- if (p2.floats[i]->name.compare( this->floats[j]->name )==0) {
- fprintf(stderr,"Overriding float '%s' \n", this->floats[j]->name.c_str() );
- this->floats[j] = p2.floats[i]->Clone();
- }
- }
- }
- for (size_t i = 0; i < p2.vectors.size(); ++i) {
- for (size_t j = 0; j < this->vectors.size(); ++j) {
- if (p2.vectors[i]->name.compare( this->vectors[j]->name )==0) {
- fprintf(stderr,"Overriding vec '%s' \n", this->vectors[j]->name.c_str() );
- this->vectors[j] = p2.vectors[i]->Clone();
- }
- }
- }
- for (size_t i = 0; i < p2.strings.size(); ++i) {
- for (size_t j = 0; j < this->strings.size(); ++j) {
- if (p2.strings[i]->name.compare( this->strings[j]->name )==0) {
- fprintf(stderr,"Overriding string '%s' \n", this->strings[j]->name.c_str() );
- this->strings[j] = p2.strings[i]->Clone();
- }
- }
- }
- }
- return;
-}
-
-void ParamSet::AddFloat(const string &name,
- const float *data,
- int nItems) {
- EraseFloat(name);
- floats.push_back(new ParamSetItem<float>(name,
- data,
- nItems));
-}
-void ParamSet::AddInt(const string &name, const int *data, int nItems) {
- EraseInt(name);
- ADD_PARAM_TYPE(int, ints);
-}
-void ParamSet::AddBool(const string &name, const bool *data, int nItems) {
- EraseInt(name);
- ADD_PARAM_TYPE(bool, bools);
-}
-
-void ParamSet::AddVector(const string &name, const DDF::Vec3 *data, int nItems) {
- EraseVector(name);
- ADD_PARAM_TYPE(DDF::Vec3, vectors);
-}
-
-void ParamSet::AddString(const string &name, const string *data, int nItems) {
- EraseString(name);
- ADD_PARAM_TYPE(string, strings);
-}
-
-bool ParamSet::EraseInt(const string &n) {
- for (size_t i = 0; i < ints.size(); ++i)
- if (ints[i]->name == n) {
- delete ints[i];
- ints.erase(ints.begin() + i);
- return true;
- }
- return false;
-}
-bool ParamSet::EraseBool(const string &n) {
- for (size_t i = 0; i < bools.size(); ++i)
- if (bools[i]->name == n) {
- delete bools[i];
- bools.erase(bools.begin() + i);
- return true;
- }
- return false;
-}
-
-bool ParamSet::EraseFloat(const string &n) {
- for (size_t i = 0; i < floats.size(); ++i)
- if (floats[i]->name == n) {
- delete floats[i];
- floats.erase(floats.begin() + i);
- return true;
- }
- return false;
-}
-
-bool ParamSet::EraseVector(const string &n) {
- for (size_t i = 0; i < vectors.size(); ++i)
- if (vectors[i]->name == n) {
- delete vectors[i];
- vectors.erase(vectors.begin() + i);
- return true;
- }
- return false;
-}
-
-bool ParamSet::EraseString(const string &n) {
- for (size_t i = 0; i < strings.size(); ++i)
- if (strings[i]->name == n) {
- delete strings[i];
- strings.erase(strings.begin() + i);
- return true;
- }
- return false;
-}
-float ParamSet::FindOneFloat(const string &name,
- float d) const {
- for (size_t i = 0; i < floats.size(); ++i)
- if (floats[i]->name == name &&
- floats[i]->nItems == 1) {
- floats[i]->lookedUp = true;
- return *(floats[i]->data);
- }
- return d;
-}
-const float *ParamSet::FindFloat(const string &name,
- int *nItems) const {
- for (size_t i = 0; i < floats.size(); ++i)
- if (floats[i]->name == name) {
- *nItems = floats[i]->nItems;
- floats[i]->lookedUp = true;
- return floats[i]->data;
- }
- return NULL;
-}
-const int *ParamSet::FindInt(const string &name, int *nItems) const {
- LOOKUP_PTR(ints);
-}
-const bool *ParamSet::FindBool(const string &name, int *nItems) const {
- LOOKUP_PTR(bools);
-}
-int ParamSet::FindOneInt(const string &name, int d) const {
- LOOKUP_ONE(ints);
-}
-bool ParamSet::FindOneBool(const string &name, bool d) const {
- LOOKUP_ONE(bools);
-}
-const DDF::Vec3 *ParamSet::FindVector(const string &name, int *nItems) const {
- LOOKUP_PTR(vectors);
-}
-DDF::Vec3 ParamSet::FindOneVector(const string &name, const DDF::Vec3 &d) const {
- LOOKUP_ONE(vectors);
-}
-const string *ParamSet::FindString(const string &name, int *nItems) const {
- LOOKUP_PTR(strings);
-}
-string ParamSet::FindOneString(const string &name, const string &d) const {
- LOOKUP_ONE(strings);
-}
-
-void ParamSet::ReportUnused() const {
- bool haveUnused = false;
-
-#define CHECK_UNUSED(v, TYPE) \
- for (i = 0; i < (v).size(); ++i) \
- if (!(v)[i]->lookedUp) { haveUnused = true; \
- debMsg("PARAMSET-WARN","Parameter \""<< (v)[i]->name.c_str() <<"\" not used, type=" TYPE); \
- }
- size_t i;
- CHECK_UNUSED(ints,"int");
- CHECK_UNUSED(bools, "bool");
- CHECK_UNUSED(floats, "float");
- CHECK_UNUSED(vectors, "vec3");
- CHECK_UNUSED(strings, "string");
-
- if(haveUnused) {
- errFatal("ParamSet::ReportUnused","Stopping...", SIMWORLD_ERRPARSE );
- }
-}
-void ParamSet::Clear() {
-#define DEL_PARAMS(name) \
- for (size_t i = 0; i < (name).size(); ++i) \
- delete (name)[i]; \
- (name).erase((name).begin(), (name).end())
- DEL_PARAMS(ints);
- DEL_PARAMS(bools);
- DEL_PARAMS(floats);
- DEL_PARAMS(vectors);
- DEL_PARAMS(strings);
-#undef DEL_PARAMS
-}
-string ParamSet::ToString() const {
- string ret;
- size_t i;
- int j;
- string typeString;
- const int bufLen = 48*1024*1024;
- static char *buf = new char[bufLen];
- char *bufEnd = buf + bufLen;
-
- for (i = 0; i < ints.size(); ++i) {
- char *bufp = buf;
- *bufp = '\0';
- ParamSetItem<int> *item = ints[i];
- typeString = "integer ";
- // Print _ParamSetItem_ declaration, determine how many to print
- int nPrint = item->nItems;
- ret += string("\"");
- ret += typeString;
- ret += item->name;
- ret += string("\"");
- ret += string(" [");
- for (j = 0; j < nPrint; ++j)
- bufp += snprintf(bufp, bufEnd - bufp, "%d ", item->data[j]);
- ret += buf;
- ret += string("] ");
- }
-
- for (i = 0; i < bools.size(); ++i) {
- char *bufp = buf;
- *bufp = '\0';
- ParamSetItem<bool> *item = bools[i];
- typeString = "bool ";
- // Print _ParamSetItem_ declaration, determine how many to print
- int nPrint = item->nItems;
- ret += string("\"");
- ret += typeString;
- ret += item->name;
- ret += string("\"");
- ret += string(" [");
- for (j = 0; j < nPrint; ++j)
- bufp += snprintf(bufp, bufEnd - bufp, "\"%s\" ", item->data[j] ? "true" : "false");
- ret += buf;
- ret += string("] ");
- }
-
- for (i = 0; i < floats.size(); ++i) {
- char *bufp = buf;
- *bufp = '\0';
- ParamSetItem<float> *item = floats[i];
- typeString = "float ";
- // Print _ParamSetItem_ declaration, determine how many to print
- int nPrint = item->nItems;
- ret += string("\"");
- ret += typeString;
- ret += item->name;
- ret += string("\"");
- ret += string(" [");
- for (j = 0; j < nPrint; ++j)
- bufp += snprintf(bufp, bufEnd - bufp, "%.8g ", item->data[j]);
- ret += buf;
- ret += string("] ");
- }
-
- for (i = 0; i < vectors.size(); ++i) {
- char *bufp = buf;
- *bufp = '\0';
- ParamSetItem<DDF::Vec3> *item = vectors[i];
- typeString = "vector ";
- // Print _ParamSetItem_ declaration, determine how many to print
- int nPrint = item->nItems;
- ret += string("\"");
- ret += typeString;
- ret += item->name;
- ret += string("\"");
- ret += string(" [");
- for (j = 0; j < nPrint; ++j)
- bufp += snprintf(bufp, bufEnd - bufp, "%.8g %.8g %.8g ", item->data[j].x,
- item->data[j].y, item->data[j].z);
- ret += buf;
- ret += string("] ");
- }
-
- for (i = 0; i < strings.size(); ++i) {
- char *bufp = buf;
- *bufp = '\0';
- ParamSetItem<string> *item = strings[i];
- typeString = "string ";
- // Print _ParamSetItem_ declaration, determine how many to print
- int nPrint = item->nItems;
- ret += string("\"");
- ret += typeString;
- ret += item->name;
- ret += string("\"");
- ret += string(" [");
- for (j = 0; j < nPrint; ++j)
- bufp += snprintf(bufp, bufEnd - bufp, "\"%s\" ", item->data[j].c_str());
- ret += buf;
- ret += string("] ");
- }
- return ret;
-}
-
-
-
diff --git a/intern/smoke/intern/util/paramset.h b/intern/smoke/intern/util/paramset.h
deleted file mode 100644
index 612345bd775..00000000000
--- a/intern/smoke/intern/util/paramset.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/******************************************************************************
- * Parameter storage class
- *
- * Copyright(c) 1998-2007 Matt Pharr and Greg Humphreys.
- *
- *****************************************************************************/
-
-#ifndef PBRT_PARAMSET_H
-#define PBRT_PARAMSET_H
-
-#include "globals.h"
-using std::string;
-using std::vector;
-#if (_MSC_VER >= 1400) // NOBOOK
-#include <stdio.h> // NOBOOK
-#define snprintf _snprintf // NOBOOK
-#endif // NOBOOK
-
-// forward declaration
-template <class T> struct ParamSetItem;
-
-// ParamSet Declarations
-#if DDF_USEPARSER == 1
-#include "parser.h"
-class COREDLL ParamSet {
-#else
-class ParamSet {
-#endif
-public:
- // ParamSet Public Methods
- ParamSet() { }
- ParamSet &operator=(const ParamSet &p2);
- ParamSet(const ParamSet &p2);
- void AddSet(const ParamSet &p2);
- void AddFloat(const string &, const float *, int nItems = 1);
- void AddInt(const string &, const int *, int nItems = 1);
- void AddBool(const string &, const bool *, int nItems = 1);
- void AddVector(const string &, const DDF::Vec3 *, int nItems = 1);
- void AddString(const string &, const string *, int nItems = 1);
-
- void AddInt(const string &n, int d) { AddInt(n,&d); }
- void AddBool(const string &n, bool d) { AddBool(n,&d); }
- void AddFloat(const string &n, float d) { AddFloat(n,&d); }
- void AddVector(const string &n, const DDF::Vec3& d) { AddVector(n,&d); }
- void AddString(const string &n, const string& d) { AddString(n,&d); }
-
- bool EraseInt(const string &);
- bool EraseBool(const string &);
- bool EraseFloat(const string &);
- bool EraseVector(const string &);
- bool EraseString(const string &);
-
- float FindOneFloat(const string &, float d) const;
- int FindOneInt(const string &, int d) const;
- bool FindOneBool(const string &, bool d) const;
- DDF::Vec3 FindOneVector(const string &, const DDF::Vec3 &d) const;
- string FindOneString(const string &, const string &d) const;
- //string FindTexture(const string &) const;
-
- const float *FindFloat(const string &, int *nItems) const;
- const int *FindInt(const string &, int *nItems) const;
- const bool *FindBool(const string &, int *nItems) const;
- const DDF::Vec3 *FindVector(const string &, int *nItems) const;
- const string *FindString(const string &, int *nItems) const;
-
- void override(const ParamSet &p2);
-
- void ReportUnused() const;
- ~ParamSet() {
- Clear();
- }
- void Clear();
- string ToString() const;
-private:
- // ParamSet Data
- vector<ParamSetItem<int> *> ints;
- vector<ParamSetItem<bool> *> bools;
- vector<ParamSetItem<float> *> floats;
- vector<ParamSetItem<DDF::Vec3> *> vectors;
- vector<ParamSetItem<string> *> strings;
-};
-
-template <class T> struct ParamSetItem {
- // ParamSetItem Public Methods
- ParamSetItem<T> *Clone() const {
- return new ParamSetItem<T>(name, data, nItems);
- }
- ParamSetItem(const string &name, const T *val, int nItems = 1);
- ~ParamSetItem() {
- delete[] data;
- }
- // ParamSetItem Data
- string name;
- int nItems;
- T *data;
- bool lookedUp;
-};
-// ParamSetItem Methods
-template <class T>
-ParamSetItem<T>::ParamSetItem(const string &n,
- const T *v,
- int ni) {
- name = n;
- nItems = ni;
- data = new T[nItems];
- for (int i = 0; i < nItems; ++i)
- data[i] = v[i];
- lookedUp = false;
-}
-
-
-
-#endif // PBRT_PARAMSET_H
diff --git a/intern/smoke/intern/util/quaternion.h b/intern/smoke/intern/util/quaternion.h
deleted file mode 100644
index d06e7110ea5..00000000000
--- a/intern/smoke/intern/util/quaternion.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Basic quaternion class
- *
- *****************************************************************************/
-
-#ifndef UTIL_QUATERIONS_H
-#define UTIL_QUATERIONS_H
-
-#include "matrixbase.h"
-#include "vectorbase.h"
-
-
-#define smax(a,b) ((a>b)?(a):(b))
-#define scpysign(a,b) ((a)*(b)>=0?(a):-(a))
-
-namespace DDF {
-
-template<class Scalar>
-class Quaternion
-{
-public:
- Scalar x,y,z,w;
-
- Quaternion () : x(0),y(0),z(0),w(0) {}
-
- Quaternion (Scalar nx, Scalar ny, Scalar nz, Scalar nw) :
- x(nx),y(ny),z(nz),w(nw) {}
-
- Quaternion (const Quaternion &q)
- {
- x=q.x; y=q.y; z=q.z; w=q.w;
- }
-
- Quaternion (const ntlMatrix4x4<Scalar> &M)
- {
- w = sqrt( smax( 0, 1 + M.value[0][0] + M.value[1][1] + M.value[2][2] ) ) / 2;
- x = sqrt( smax( 0, 1 + M.value[0][0] - M.value[1][1] - M.value[2][2] ) ) / 2;
- y = sqrt( smax( 0, 1 - M.value[0][0] + M.value[1][1] - M.value[2][2] ) ) / 2;
- z = sqrt( smax( 0, 1 - M.value[0][0] - M.value[1][1] + M.value[2][2] ) ) / 2;
- x = scpysign( x, M.value[2][1] - M.value[1][2] );
- y = scpysign( y, M.value[0][2] - M.value[2][0] );
- z = scpysign( z, M.value[1][0] - M.value[0][1] );
- }
-
- Quaternion (const ntlVector3Dim<Scalar>& axis, Scalar angle)
- {
- Scalar mult = sin(angle*.5);
- x = axis.x * mult;
- y = axis.y * mult;
- z = axis.z * mult;
- w = cos (angle*.5);
- }
-
- Quaternion (Scalar rx, Scalar ry, Scalar rz)
- {
- Quaternion qx(ntlVector3Dim<Scalar> (1.,0.,0.),-rx);
- Quaternion qy(ntlVector3Dim<Scalar> (0.,1.,0.),-ry);
- Quaternion qz(ntlVector3Dim<Scalar> (0.,0.,1.),-rz);
- Quaternion q = qz*qy*qx;
- x=q.x; y=q.y; z=q.z; w=q.w;
- }
-
- ntlMatrix4x4<Scalar> getRotMat() const
- {
- const Scalar x2 = x*x;
- const Scalar y2 = y*y;
- const Scalar z2 = z*z;
- // const float w2 = w*w;
-
- ntlMatrix4x4<Scalar> M;
- M.initId();
- M.value[0][0] = 1 - 2*(y2+z2);
- M.value[0][1] = 2*(x*y - w*z);
- M.value[0][2] = 2*(x*z+w*y);
- M.value[1][0] = 2*(x*y+w*z);
- M.value[1][1] = 1-2*(x2+z2);
- M.value[1][2] = 2*(y*z-w*x);
- M.value[2][0] = 2*(x*z-w*y);
- M.value[2][1] = 2*(y*z+w*x);
- M.value[2][2] = 1-2*(x2+y2);
- return M;
- }
-
- ntlVector3Dim<Scalar> getAxis() const
- {
- Scalar phi2 = acos(w);
- ntlVector3Dim<Scalar> axis = ntlVector3Dim<Scalar> (x,y,z) * (1./sin(phi2));
- normalize(axis);
- return axis * 2.* phi2;
- }
-
- inline const Quaternion operator+(const Quaternion &q) const { return Quaternion(x+q.x,y+q.y,z+q.z,w+q.w); };
- inline const Quaternion operator-(const Quaternion &q) const { return Quaternion(x-q.x,y-q.y,z-q.z,w-q.w); };
- inline const Quaternion operator*(const Scalar m) const { return Quaternion(x*m,y*m,z*m,w*m); };
- inline const Quaternion operator-() const { return Quaternion(-x,-y,-z,-w); };
- inline Scalar dot(const Quaternion &q) const { return x*q.x+y*q.y+z*q.z+w*q.w; }
- inline Scalar normSq() const { return x*x+y*y+z*z+w*w; }
- inline Scalar norm() const { return sqrt(normSq()); }
- inline const Quaternion unit() const { Scalar d=1./norm(); return Quaternion(x*d,y*d,z*d,w*d); }
-
- inline const Quaternion operator*(const Quaternion &q) const
- {
- ntlVector3Dim<Scalar> v1(x,y,z), v2(q.x,q.y,q.z);
- ntlVector3Dim<Scalar> nv = v1*q.w + v2*w + cross(v2,v1);
- Scalar nw = w*q.w - (v1.x*v2.x+v1.y*v2.y+v1.z*v2.z);
-
- return Quaternion(nv.x,nv.y,nv.z,nw);
- }
-
- static const Quaternion slerp(Quaternion q, Quaternion p, Scalar t)
- {
- Scalar cosphi = q.dot(p);
-
- if(cosphi < 0.0f)
- {
- cosphi *= -1.0f;
- q = -q;
- }
-
- const Scalar DOT_THRESHOLD = 0.9995f;
- if (cosphi > DOT_THRESHOLD) {
- // interpolate linearly
- return (q + (p - q) * t).unit();
- }
-
- Scalar sinphi = sqrt(1. - cosphi * cosphi);
- Scalar phi = acos(cosphi);
-
- Quaternion res = q * (sin( phi * (1.-t) ) / sinphi) + p * (sin( phi * t) / sinphi);
-
- return res;
- }
-};
-
-typedef Quaternion<Real> Quat;
-
-}
-
-
-#endif // __Quaternion_h__
-
-
diff --git a/intern/smoke/intern/util/randomstream.h b/intern/smoke/intern/util/randomstream.h
deleted file mode 100644
index 9f92bc0c089..00000000000
--- a/intern/smoke/intern/util/randomstream.h
+++ /dev/null
@@ -1,380 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * A seperate random number stream
- *
- *****************************************************************************/
-
-#ifndef NTL_RANDOMSTREAM_HH
-#define NTL_RANDOMSTREAM_HH
-
-namespace DDF {
-
-#include <iostream>
-#include <limits.h>
-#include <stdio.h>
-#include <time.h>
-#include <math.h>
-
-class MTRand {
- // Data
- public:
- typedef unsigned long uint32; // unsigned integer type, at least 32 bits
-
- enum { N = 624 }; // length of state vector
- enum { SAVE = N + 1 }; // length of array for save()
-
- protected:
- enum { M = 397 }; // period parameter
-
- uint32 state[N]; // internal state
- uint32 *pNext; // next value to get from state
- int left; // number of values left before reload needed
-
-
- //Methods
- public:
- MTRand( const uint32& oneSeed ); // initialize with a simple uint32
- MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array
- MTRand(); // auto-initialize with /dev/urandom or time() and clock()
-
- // Do NOT use for CRYPTOGRAPHY without securely hashing several returned
- // values together, otherwise the generator state can be learned after
- // reading 624 consecutive values.
-
- // Access to 32-bit random numbers
- double rand(); // real number in [0,1]
- double rand( const double& n ); // real number in [0,n]
- double randExc(); // real number in [0,1)
- double randExc( const double& n ); // real number in [0,n)
- double randDblExc(); // real number in (0,1)
- double randDblExc( const double& n ); // real number in (0,n)
- uint32 randInt(); // integer in [0,2^32-1]
- uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32
- double operator()() { return rand(); } // same as rand()
-
- // Access to 53-bit random numbers (capacity of IEEE double precision)
- double rand53(); // real number in [0,1)
-
- // Access to nonuniform random number distributions
- double randNorm( const double& mean = 0.0, const double& variance = 1.0 );
-
- // Re-seeding functions with same behavior as initializers
- void seed( const uint32 oneSeed );
- void seed( uint32 *const bigSeed, const uint32 seedLength = N );
- void seed();
-
- // Saving and loading generator state
- void save( uint32* saveArray ) const; // to array of size SAVE
- void load( uint32 *const loadArray ); // from such array
- friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand );
- friend std::istream& operator>>( std::istream& is, MTRand& mtrand );
-
- protected:
- void initialize( const uint32 oneSeed );
- void reload();
- uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; }
- uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; }
- uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; }
- uint32 mixBits( const uint32& u, const uint32& v ) const
- { return hiBit(u) | loBits(v); }
- uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const
- {
- return m ^ (mixBits(s0,s1)>>1) ^ ((~loBit(s1) + 1) & 0x9908b0dfUL);
- // return m ^ (mixBits(s0,s1)>>1) ^ (-((int)loBit(s1)) & 0x9908b0dfUL);
- }
- static uint32 hash( time_t t, clock_t c );
-};
-
-
-inline MTRand::MTRand( const uint32& oneSeed )
- { seed(oneSeed); }
-
-inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength )
- { seed(bigSeed,seedLength); }
-
-inline MTRand::MTRand()
- { seed(); }
-
-inline double MTRand::rand()
- { return double(randInt()) * (1.0/4294967295.0); }
-
-inline double MTRand::rand( const double& n )
- { return rand() * n; }
-
-inline double MTRand::randExc()
- { return double(randInt()) * (1.0/4294967296.0); }
-
-inline double MTRand::randExc( const double& n )
- { return randExc() * n; }
-
-inline double MTRand::randDblExc()
- { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); }
-
-inline double MTRand::randDblExc( const double& n )
- { return randDblExc() * n; }
-
-inline double MTRand::rand53()
-{
- uint32 a = randInt() >> 5, b = randInt() >> 6;
- return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada
-}
-
-inline double MTRand::randNorm( const double& mean, const double& variance )
-{
- // Return a real number from a normal (Gaussian) distribution with given
- // mean and variance by Box-Muller method
- double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance;
- double phi = 2.0 * 3.14159265358979323846264338328 * randExc();
- return mean + r * cos(phi);
-}
-
-inline MTRand::uint32 MTRand::randInt()
-{
- // Pull a 32-bit integer from the generator state
- // Every other access function simply transforms the numbers extracted here
-
- if( left == 0 ) reload();
- --left;
-
- register uint32 s1;
- s1 = *pNext++;
- s1 ^= (s1 >> 11);
- s1 ^= (s1 << 7) & 0x9d2c5680UL;
- s1 ^= (s1 << 15) & 0xefc60000UL;
- return ( s1 ^ (s1 >> 18) );
-}
-
-inline MTRand::uint32 MTRand::randInt( const uint32& n )
-{
- // Find which bits are used in n
- // Optimized by Magnus Jonsson (magnus@smartelectronix.com)
- uint32 used = n;
- used |= used >> 1;
- used |= used >> 2;
- used |= used >> 4;
- used |= used >> 8;
- used |= used >> 16;
-
- // Draw numbers until one is found in [0,n]
- uint32 i;
- do
- i = randInt() & used; // toss unused bits to shorten search
- while( i > n );
- return i;
-}
-
-
-inline void MTRand::seed( const uint32 oneSeed )
-{
- // Seed the generator with a simple uint32
- initialize(oneSeed);
- reload();
-}
-
-
-inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength )
-{
- // Seed the generator with an array of uint32's
- // There are 2^19937-1 possible initial states. This function allows
- // all of those to be accessed by providing at least 19937 bits (with a
- // default seed length of N = 624 uint32's). Any bits above the lower 32
- // in each element are discarded.
- // Just call seed() if you want to get array from /dev/urandom
- initialize(19650218UL);
- const unsigned int Nenum = N;
- register int i = 1;
- register uint32 j = 0;
- register int k = ( Nenum > seedLength ? Nenum : seedLength );
- for( ; k; --k )
- {
- state[i] =
- state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL );
- state[i] += ( bigSeed[j] & 0xffffffffUL ) + j;
- state[i] &= 0xffffffffUL;
- ++i; ++j;
- if( i >= N ) { state[0] = state[N-1]; i = 1; }
- if( j >= seedLength ) j = 0;
- }
- for( k = N - 1; k; --k )
- {
- state[i] =
- state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL );
- state[i] -= i;
- state[i] &= 0xffffffffUL;
- ++i;
- if( i >= N ) { state[0] = state[N-1]; i = 1; }
- }
- state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array
- reload();
-}
-
-
-inline void MTRand::seed()
-{
- // seed deterministically to produce reproducible runs
- seed(123456);
-
- /*
- // Seed the generator with an array from /dev/urandom if available
- // Otherwise use a hash of time() and clock() values
-
- // First try getting an array from /dev/urandom
- FILE* urandom = fopen( "/dev/urandom", "rb" );
- if( urandom )
- {
- uint32 bigSeed[N];
- register uint32 *s = bigSeed;
- register int i = N;
- register bool success = true;
- while( success && i-- )
- success = fread( s++, sizeof(uint32), 1, urandom );
- fclose(urandom);
- if( success ) { seed( bigSeed, N ); return; }
- }
-
- // Was not successful, so use time() and clock() instead
- seed( hash( time(NULL), clock() ) );
- */
-}
-
-
-inline void MTRand::initialize( const uint32 intseed )
-{
- // Initialize generator state with seed
- // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier.
- // In previous versions, most significant bits (MSBs) of the seed affect
- // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto.
- register uint32 *s = state;
- register uint32 *r = state;
- register int i = 1;
- *s++ = intseed & 0xffffffffUL;
- for( ; i < N; ++i )
- {
- *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL;
- r++;
- }
-}
-
-
-inline void MTRand::reload()
-{
- // Generate N new values in state
- // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com)
- register uint32 *p = state;
- register int i;
- for( i = N - M; i--; ++p )
- *p = twist( p[M], p[0], p[1] );
- for( i = M; --i; ++p )
- *p = twist( p[M-N], p[0], p[1] );
- *p = twist( p[M-N], p[0], state[0] );
-
- left = N, pNext = state;
-}
-
-
-inline MTRand::uint32 MTRand::hash( time_t t, clock_t c )
-{
- // Get a uint32 from t and c
- // Better than uint32(x) in case x is floating point in [0,1]
- // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
-
- static uint32 differ = 0; // guarantee time-based seeds will change
-
- uint32 h1 = 0;
- unsigned char *p = (unsigned char *) &t;
- for( size_t i = 0; i < sizeof(t); ++i )
- {
- h1 *= UCHAR_MAX + 2U;
- h1 += p[i];
- }
- uint32 h2 = 0;
- p = (unsigned char *) &c;
- for( size_t j = 0; j < sizeof(c); ++j )
- {
- h2 *= UCHAR_MAX + 2U;
- h2 += p[j];
- }
- return ( h1 + differ++ ) ^ h2;
-}
-
-
-inline void MTRand::save( uint32* saveArray ) const
-{
- register uint32 *sa = saveArray;
- register const uint32 *s = state;
- register int i = N;
- for( ; i--; *sa++ = *s++ ) {}
- *sa = left;
-}
-
-
-inline void MTRand::load( uint32 *const loadArray )
-{
- register uint32 *s = state;
- register uint32 *la = loadArray;
- register int i = N;
- for( ; i--; *s++ = *la++ ) {}
- left = *la;
- pNext = &state[N-left];
-}
-
-
-inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand )
-{
- register const MTRand::uint32 *s = mtrand.state;
- register int i = mtrand.N;
- for( ; i--; os << *s++ << "\t" ) {}
- return os << mtrand.left;
-}
-
-
-inline std::istream& operator>>( std::istream& is, MTRand& mtrand )
-{
- register MTRand::uint32 *s = mtrand.state;
- register int i = mtrand.N;
- for( ; i--; is >> *s++ ) {}
- is >> mtrand.left;
- mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left];
- return is;
-}
-
-
-
-
-
-
-
-// simple interface to mersenne twister
-class RandomStream
-{
-public:
- inline RandomStream(long seed) : mtr(seed) {} ;
- ~RandomStream() {}
-
- /*! get a random number from the stream */
- inline double getDouble( void ) { return mtr.rand(); };
- inline float getFloat( void ) { return (float)mtr.rand(); };
- inline float getFloat( float min, float max ) { return mtr.rand(max-min) + min; };
- inline float getRandNorm( float mean, float var) { return mtr.randNorm(mean, var); };
-
- #if FLOATINGPOINT_PRECISION==1
- inline Real getReal() { return getFloat(); }
- #else
- inline Real getReal() { return getDouble(); }
- #endif
-
-private:
- MTRand mtr;
-};
-
-
-
-} // DDF
-
-#endif
diff --git a/intern/smoke/intern/util/waveletnoise.h b/intern/smoke/intern/util/waveletnoise.h
deleted file mode 100644
index 0eb61fbfd96..00000000000
--- a/intern/smoke/intern/util/waveletnoise.h
+++ /dev/null
@@ -1,600 +0,0 @@
-/******************************************************************************
- * DDF Fluid solver with Turbulence extensions
- *
- * copyright 2009 Nils Thuerey, Tobias Pfaff
- *
- * DDF is free software, distributed under the GNU General Public License (GPL v2).
- * See the file COPYING for more information.
- *
- * Generate defined noise textures
- *
- *****************************************************************************/
-
-
-#include "randomstream.h"
-#include "vectorbase.h"
-#include "paramset.h"
-using DDF::Real;
-using DDF::Vec3;
-using DDF::nVec3i;
-
-namespace DDF {
-// global tile data, defined in globals.cpp
-extern float* stdTileData;
-};
-
-
-namespace WAVELETNOISE {
-
-#define NOISE_TILE_SIZE 128
-static const int noiseTileSize = NOISE_TILE_SIZE;
-static const char* stdTileName = "noiseTile3d.dqt";
-
-//*****************************************************************************
-// helper functions
-
-static int modSlow(int x, int n) {
- int m = x % n;
- return (m<0) ? m+n : m;
-}
-
-// warning - noiseTileSize has to be 128^3!
-#define modFast128(x) ((x) & 127)
-
-
-//*****************************************************************************
-// Wavelet downsampling
-static float _aCoeffs[32] = {
- 0.000334f,-0.001528f, 0.000410f, 0.003545f,-0.000938f,-0.008233f, 0.002172f, 0.019120f,
- -0.005040f,-0.044412f, 0.011655f, 0.103311f,-0.025936f,-0.243780f, 0.033979f, 0.655340f,
- 0.655340f, 0.033979f,-0.243780f,-0.025936f, 0.103311f, 0.011655f,-0.044412f,-0.005040f,
- 0.019120f, 0.002172f,-0.008233f,-0.000938f, 0.003546f, 0.000410f,-0.001528f, 0.000334f};
-static void Downsample(float *from, float *to, int n, int stride){
- const float *a = &_aCoeffs[16];
- for (int i = 0; i < n / 2; i++) {
- to[i * stride] = 0;
- for (int k = 2 * i - 16; k < 2 * i + 16; k++)
- to[i * stride] += a[k - 2 * i] * from[modFast128(k) * stride];
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// Wavelet upsampling
-//////////////////////////////////////////////////////////////////////////////////////////
-static float _pCoeffs[4] = {0.25f, 0.75f, 0.75f, 0.25f};
-static void Upsample(float *from, float *to, int n, int stride) {
- const float *p = &_pCoeffs[2];
-
- for (int i = 0; i < n; i++) {
- to[i * stride] = 0;
- for (int k = i / 2; k <= i / 2 + 1; k++)
- to[i * stride] += p[i - 2 * k] * from[modSlow(k, n / 2) * stride];
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// load in an existing noise tile
-//////////////////////////////////////////////////////////////////////////////////////////
-static bool loadTile(float* const noiseTileData, std::string filename)
-{
- FILE* file;
- file = fopen(filename.c_str(), "rb");
-
- if (file == NULL) {
- printf("loadTile: No noise tile '%s' found.\n", filename.c_str());
- return false;
- }
-
- // dimensions
- int gridSize = noiseTileSize * noiseTileSize * noiseTileSize;
- // noiseTileData memory is managed by caller
- int bread = fread((void*)noiseTileData, sizeof(float), gridSize, file);
- fclose(file);
- printf("Noise tile file loaded.\n");
-
- if (bread != gridSize) {
- printf("loadTile: Noise tile '%s' is wrong size %d.\n", filename.c_str(), bread);
- return false;
- }
- return true;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// write out an existing noise tile
-//////////////////////////////////////////////////////////////////////////////////////////
-static void saveTile(float* const noiseTileData, std::string filename)
-{
- FILE* file;
- file = fopen(filename.c_str(), "wb");
-
- if (file == NULL) {
- printf("saveTile: No noise tile '%s' found.\n", filename.c_str());
- return;
- }
-
- unsigned len = noiseTileSize * noiseTileSize * noiseTileSize;
- if (fwrite((void*)noiseTileData, sizeof(float), len, file) != len) errFatal("saveTile","fwrite failed", SIMWORLD_INITERROR);
- fclose(file);
-
- printf("saveTile: Noise tile file saved.\n");
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// create a new noise tile if necessary
-//////////////////////////////////////////////////////////////////////////////////////////
-static void GenerateNoiseTile(float* const noiseTileData, std::string filename) {
- // if a tile already exists, just use that
- if (loadTile(noiseTileData, filename)) return;
-
- const int n = noiseTileSize;
- const int n3 = n*n*n;
- std::cout <<"Generating new 3d noise tile size="<<n<<"^3 \n";
- //MTRand twister;
- DDF::RandomStream randStream = DDF::RandomStream(13322223);
- DDF::RandomStream randStream2 = DDF::RandomStream(1238201283);
-
- float *temp13 = new float[n3];
- float *temp23 = new float[n3];
- float *noise3 = new float[n3];
-
- // initialize
- for (int i = 0; i < n3; i++) {
- temp13[i] = temp23[i] =
- noise3[i] = 0.;
- }
-
- // Step 1. Fill the tile with random numbers in the range -1 to 1.
- for (int i = 0; i < n3; i++) {
- //noise3[i] = twister.randNorm();
- noise3[i] = (randStream.getFloat() + randStream2.getFloat()) -1.; // produces repeated values??
- noise3[i] = (randStream.getFloat() + randStream2.getFloat()) -1.;
- }
-
- // Steps 2 and 3. Downsample and upsample the tile
- for (int iy = 0; iy < n; iy++)
- for (int iz = 0; iz < n; iz++) {
- const int i = iy * n + iz*n*n;
- Downsample(&noise3[i], &temp13[i], n, 1);
- Upsample (&temp13[i], &temp23[i], n, 1);
- }
- for (int ix = 0; ix < n; ix++)
- for (int iz = 0; iz < n; iz++) {
- const int i = ix + iz*n*n;
- Downsample(&temp23[i], &temp13[i], n, n);
- Upsample (&temp13[i], &temp23[i], n, n);
- }
- for (int ix = 0; ix < n; ix++)
- for (int iy = 0; iy < n; iy++) {
- const int i = ix + iy*n;
- Downsample(&temp23[i], &temp13[i], n, n*n);
- Upsample (&temp13[i], &temp23[i], n, n*n);
- }
-
- // Step 4. Subtract out the coarse-scale contribution
- for (int i = 0; i < n3; i++) {
- noise3[i] -= temp23[i];
- }
-
- // Avoid even/odd variance difference by adding odd-offset version of noise to itself.
- int offset = n / 2;
- if (offset % 2 == 0) offset++;
-
- int icnt=0;
- for (int ix = 0; ix < n; ix++)
- for (int iy = 0; iy < n; iy++)
- for (int iz = 0; iz < n; iz++) {
- temp13[icnt] = noise3[modFast128(ix+offset) + modFast128(iy+offset)*n + modFast128(iz+offset)*n*n];
- icnt++;
- }
-
- for (int i = 0; i < n3; i++) {
- noise3[i] += temp13[i];
- }
-
- for (int i = 0; i < n3; i++) {
- noiseTileData[i] = noise3[i];
- }
- saveTile(noise3, filename);
-
- delete[] temp13;
- delete[] temp23;
- std::cout <<"Generating new 3d noise done\n";
-}
-
-
-#define ADD_WEIGHTED(x,y,z)\
- weight = 1.0f;\
- xC = modFast128(midX + (x));\
- weight *= w[0][(x) + 1];\
- yC = modFast128(midY + (y));\
- weight *= w[1][(y) + 1];\
- zC = modFast128(midZ + (z));\
- weight *= w[2][(z) + 1];\
- result += weight * data[(zC * NOISE_TILE_SIZE + yC) * NOISE_TILE_SIZE + xC];
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// derivatives of 3D noise - unrolled for performance
-//////////////////////////////////////////////////////////////////////////////////////////
-static inline float WNoiseDx(Vec3 p, float *data) {
- float w[3][3], t, result = 0;
-
- // Evaluate quadratic B-spline basis functions
- int midX = (int)ceil(p[0] - 0.5f);
- t = midX - (p[0] - 0.5f);
- w[0][0] = -t;
- w[0][2] = (1.f - t);
- w[0][1] = 2.0f * t - 1.0f;
-
- int midY = (int)ceil(p[1] - 0.5f);
- t = midY - (p[1] - 0.5f);
- w[1][0] = t * t * 0.5f;
- w[1][2] = (1.f - t) * (1.f - t) *0.5f;
- w[1][1] = 1.f - w[1][0] - w[1][2];
-
- int midZ = (int)ceil(p[2] - 0.5f);
- t = midZ - (p[2] - 0.5f);
- w[2][0] = t * t * 0.5f;
- w[2][2] = (1.f - t) * (1.f - t) *0.5f;
- w[2][1] = 1.f - w[2][0] - w[2][2];
-
- // Evaluate noise by weighting noise coefficients by basis function values
- int xC, yC, zC;
- float weight = 1;
-
- ADD_WEIGHTED(-1,-1, -1); ADD_WEIGHTED( 0,-1, -1); ADD_WEIGHTED( 1,-1, -1);
- ADD_WEIGHTED(-1, 0, -1); ADD_WEIGHTED( 0, 0, -1); ADD_WEIGHTED( 1, 0, -1);
- ADD_WEIGHTED(-1, 1, -1); ADD_WEIGHTED( 0, 1, -1); ADD_WEIGHTED( 1, 1, -1);
-
- ADD_WEIGHTED(-1,-1, 0); ADD_WEIGHTED( 0,-1, 0); ADD_WEIGHTED( 1,-1, 0);
- ADD_WEIGHTED(-1, 0, 0); ADD_WEIGHTED( 0, 0, 0); ADD_WEIGHTED( 1, 0, 0);
- ADD_WEIGHTED(-1, 1, 0); ADD_WEIGHTED( 0, 1, 0); ADD_WEIGHTED( 1, 1, 0);
-
- ADD_WEIGHTED(-1,-1, 1); ADD_WEIGHTED( 0,-1, 1); ADD_WEIGHTED( 1,-1, 1);
- ADD_WEIGHTED(-1, 0, 1); ADD_WEIGHTED( 0, 0, 1); ADD_WEIGHTED( 1, 0, 1);
- ADD_WEIGHTED(-1, 1, 1); ADD_WEIGHTED( 0, 1, 1); ADD_WEIGHTED( 1, 1, 1);
-
- return result;
-}
-
-static inline float WNoise(Vec3 p, float *data) {
- float w[3][3], t, result = 0;
-
- // Evaluate quadratic B-spline basis functions
- int midX = (int)ceil(p[0] - 0.5f);
- t = midX - (p[0] - 0.5f);
- w[0][0] = t * t * 0.5f;
- w[0][2] = (1.f - t) * (1.f - t) *0.5f;
- w[0][1] = 1.f - w[0][0] - w[0][2];
-
- int midY = (int)ceil(p[1] - 0.5f);
- t = midY - (p[1] - 0.5f);
- w[1][0] = t * t * 0.5f;
- w[1][2] = (1.f - t) * (1.f - t) *0.5f;
- w[1][1] = 1.f - w[1][0] - w[1][2];
-
- int midZ = (int)ceil(p[2] - 0.5f);
- t = midZ - (p[2] - 0.5f);
- w[2][0] = t * t * 0.5f;
- w[2][2] = (1.f - t) * (1.f - t) *0.5f;
- w[2][1] = 1.f - w[2][0] - w[2][2];
-
- // Evaluate noise by weighting noise coefficients by basis function values
- int xC, yC, zC;
- float weight = 1;
-
- ADD_WEIGHTED(-1,-1, -1); ADD_WEIGHTED( 0,-1, -1); ADD_WEIGHTED( 1,-1, -1);
- ADD_WEIGHTED(-1, 0, -1); ADD_WEIGHTED( 0, 0, -1); ADD_WEIGHTED( 1, 0, -1);
- ADD_WEIGHTED(-1, 1, -1); ADD_WEIGHTED( 0, 1, -1); ADD_WEIGHTED( 1, 1, -1);
-
- ADD_WEIGHTED(-1,-1, 0); ADD_WEIGHTED( 0,-1, 0); ADD_WEIGHTED( 1,-1, 0);
- ADD_WEIGHTED(-1, 0, 0); ADD_WEIGHTED( 0, 0, 0); ADD_WEIGHTED( 1, 0, 0);
- ADD_WEIGHTED(-1, 1, 0); ADD_WEIGHTED( 0, 1, 0); ADD_WEIGHTED( 1, 1, 0);
-
- ADD_WEIGHTED(-1,-1, 1); ADD_WEIGHTED( 0,-1, 1); ADD_WEIGHTED( 1,-1, 1);
- ADD_WEIGHTED(-1, 0, 1); ADD_WEIGHTED( 0, 0, 1); ADD_WEIGHTED( 1, 0, 1);
- ADD_WEIGHTED(-1, 1, 1); ADD_WEIGHTED( 0, 1, 1); ADD_WEIGHTED( 1, 1, 1);
-
- return result;
-}
-
-
-
-#define ADD_WEIGHTEDX(x,y,z)\
- weight = dw[0][(x) + 1] * w[1][(y) + 1] * w[2][(z) + 1];\
- result += weight * neighbors[x + 1][y + 1][z + 1];
-
-#define ADD_WEIGHTEDY(x,y,z)\
- weight = w[0][(x) + 1] * dw[1][(y) + 1] * w[2][(z) + 1];\
- result += weight * neighbors[x + 1][y + 1][z + 1];
-
-#define ADD_WEIGHTEDZ(x,y,z)\
- weight = w[0][(x) + 1] * w[1][(y) + 1] * dw[2][(z) + 1];\
- result += weight * neighbors[x + 1][y + 1][z + 1];
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// compute all derivatives in at once
-//////////////////////////////////////////////////////////////////////////////////////////
-static inline Vec3 WNoiseVec(const Vec3& p, float *data)
-{
- Vec3 final(0.);
- float w[3][3];
- float dw[3][3];
- float result = 0;
- int xC, yC, zC;
- float weight;
-
- int midX = (int)ceil(p[0] - 0.5f);
- int midY = (int)ceil(p[1] - 0.5f);
- int midZ = (int)ceil(p[2] - 0.5f);
-
- float t0 = midX - (p[0] - 0.5f);
- float t1 = midY - (p[1] - 0.5f);
- float t2 = midZ - (p[2] - 0.5f);
-
- // precache all the neighbors for fast access
- float neighbors[3][3][3];
- for (int z = -1; z <=1; z++)
- for (int y = -1; y <= 1; y++)
- for (int x = -1; x <= 1; x++)
- {
- xC = modFast128(midX + (x));
- yC = modFast128(midY + (y));
- zC = modFast128(midZ + (z));
- neighbors[x + 1][y + 1][z + 1] = data[zC * NOISE_TILE_SIZE * NOISE_TILE_SIZE + yC * NOISE_TILE_SIZE + xC];
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // evaluate splines
- ///////////////////////////////////////////////////////////////////////////////////////
- dw[0][0] = -t0;
- dw[0][2] = (1.f - t0);
- dw[0][1] = 2.0f * t0 - 1.0f;
-
- dw[1][0] = -t1;
- dw[1][2] = (1.0f - t1);
- dw[1][1] = 2.0f * t1 - 1.0f;
-
- dw[2][0] = -t2;
- dw[2][2] = (1.0f - t2);
- dw[2][1] = 2.0f * t2 - 1.0f;
-
- w[0][0] = t0 * t0 * 0.5f;
- w[0][2] = (1.f - t0) * (1.f - t0) *0.5f;
- w[0][1] = 1.f - w[0][0] - w[0][2];
-
- w[1][0] = t1 * t1 * 0.5f;
- w[1][2] = (1.f - t1) * (1.f - t1) *0.5f;
- w[1][1] = 1.f - w[1][0] - w[1][2];
-
- w[2][0] = t2 * t2 * 0.5f;
- w[2][2] = (1.f - t2) * (1.f - t2) *0.5f;
- w[2][1] = 1.f - w[2][0] - w[2][2];
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // x derivative
- ///////////////////////////////////////////////////////////////////////////////////////
- result = 0.0f;
- ADD_WEIGHTEDX(-1,-1, -1); ADD_WEIGHTEDX( 0,-1, -1); ADD_WEIGHTEDX( 1,-1, -1);
- ADD_WEIGHTEDX(-1, 0, -1); ADD_WEIGHTEDX( 0, 0, -1); ADD_WEIGHTEDX( 1, 0, -1);
- ADD_WEIGHTEDX(-1, 1, -1); ADD_WEIGHTEDX( 0, 1, -1); ADD_WEIGHTEDX( 1, 1, -1);
-
- ADD_WEIGHTEDX(-1,-1, 0); ADD_WEIGHTEDX( 0,-1, 0); ADD_WEIGHTEDX( 1,-1, 0);
- ADD_WEIGHTEDX(-1, 0, 0); ADD_WEIGHTEDX( 0, 0, 0); ADD_WEIGHTEDX( 1, 0, 0);
- ADD_WEIGHTEDX(-1, 1, 0); ADD_WEIGHTEDX( 0, 1, 0); ADD_WEIGHTEDX( 1, 1, 0);
-
- ADD_WEIGHTEDX(-1,-1, 1); ADD_WEIGHTEDX( 0,-1, 1); ADD_WEIGHTEDX( 1,-1, 1);
- ADD_WEIGHTEDX(-1, 0, 1); ADD_WEIGHTEDX( 0, 0, 1); ADD_WEIGHTEDX( 1, 0, 1);
- ADD_WEIGHTEDX(-1, 1, 1); ADD_WEIGHTEDX( 0, 1, 1); ADD_WEIGHTEDX( 1, 1, 1);
- final[0] = result;
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // y derivative
- ///////////////////////////////////////////////////////////////////////////////////////
- result = 0.0f;
- ADD_WEIGHTEDY(-1,-1, -1); ADD_WEIGHTEDY( 0,-1, -1); ADD_WEIGHTEDY( 1,-1, -1);
- ADD_WEIGHTEDY(-1, 0, -1); ADD_WEIGHTEDY( 0, 0, -1); ADD_WEIGHTEDY( 1, 0, -1);
- ADD_WEIGHTEDY(-1, 1, -1); ADD_WEIGHTEDY( 0, 1, -1); ADD_WEIGHTEDY( 1, 1, -1);
-
- ADD_WEIGHTEDY(-1,-1, 0); ADD_WEIGHTEDY( 0,-1, 0); ADD_WEIGHTEDY( 1,-1, 0);
- ADD_WEIGHTEDY(-1, 0, 0); ADD_WEIGHTEDY( 0, 0, 0); ADD_WEIGHTEDY( 1, 0, 0);
- ADD_WEIGHTEDY(-1, 1, 0); ADD_WEIGHTEDY( 0, 1, 0); ADD_WEIGHTEDY( 1, 1, 0);
-
- ADD_WEIGHTEDY(-1,-1, 1); ADD_WEIGHTEDY( 0,-1, 1); ADD_WEIGHTEDY( 1,-1, 1);
- ADD_WEIGHTEDY(-1, 0, 1); ADD_WEIGHTEDY( 0, 0, 1); ADD_WEIGHTEDY( 1, 0, 1);
- ADD_WEIGHTEDY(-1, 1, 1); ADD_WEIGHTEDY( 0, 1, 1); ADD_WEIGHTEDY( 1, 1, 1);
- final[1] = result;
-
- ///////////////////////////////////////////////////////////////////////////////////////
- // z derivative
- ///////////////////////////////////////////////////////////////////////////////////////
- result = 0.0f;
- ADD_WEIGHTEDZ(-1,-1, -1); ADD_WEIGHTEDZ( 0,-1, -1); ADD_WEIGHTEDZ( 1,-1, -1);
- ADD_WEIGHTEDZ(-1, 0, -1); ADD_WEIGHTEDZ( 0, 0, -1); ADD_WEIGHTEDZ( 1, 0, -1);
- ADD_WEIGHTEDZ(-1, 1, -1); ADD_WEIGHTEDZ( 0, 1, -1); ADD_WEIGHTEDZ( 1, 1, -1);
-
- ADD_WEIGHTEDZ(-1,-1, 0); ADD_WEIGHTEDZ( 0,-1, 0); ADD_WEIGHTEDZ( 1,-1, 0);
- ADD_WEIGHTEDZ(-1, 0, 0); ADD_WEIGHTEDZ( 0, 0, 0); ADD_WEIGHTEDZ( 1, 0, 0);
- ADD_WEIGHTEDZ(-1, 1, 0); ADD_WEIGHTEDZ( 0, 1, 0); ADD_WEIGHTEDZ( 1, 1, 0);
-
- ADD_WEIGHTEDZ(-1,-1, 1); ADD_WEIGHTEDZ( 0,-1, 1); ADD_WEIGHTEDZ( 1,-1, 1);
- ADD_WEIGHTEDZ(-1, 0, 1); ADD_WEIGHTEDZ( 0, 0, 1); ADD_WEIGHTEDZ( 1, 0, 1);
- ADD_WEIGHTEDZ(-1, 1, 1); ADD_WEIGHTEDZ( 0, 1, 1); ADD_WEIGHTEDZ( 1, 1, 1);
- final[2] = result;
-
- //debMsg("FINAL","at "<<p<<" = "<<final); // DEBUG
- return final;
-}
-#undef ADD_WEIGHTEDX
-#undef ADD_WEIGHTEDY
-#undef ADD_WEIGHTEDZ
-
-
-//*****************************************************************************
-static bool loadStdTile()
-{
- if(!DDF::stdTileData) {
- DDF::stdTileData = new float[NOISE_TILE_SIZE * NOISE_TILE_SIZE * NOISE_TILE_SIZE];
- }
- GenerateNoiseTile(DDF::stdTileData, stdTileName);
- return true;
-}
-
-static void freeStdTile()
-{
- if(DDF::stdTileData) {
- delete [] DDF::stdTileData;
- }
-}
-
-static inline float getWNoise(Vec3 p) {
-#ifdef DDF_DEBUG
-#if DDF_DEBUG==1
- if(!DDF::stdTileData) {
- fprintf(stderr,"waveletnoise.h: Fatal, noise not inited!\n");
- exit(1);
- }
-#endif // DDF_DEBUG==1
-#endif // DDF_DEBUG
- return WNoise(p, DDF::stdTileData);
-}
-
-static inline Vec3 getWNoiseVec(Vec3 p) {
-#ifdef DDF_DEBUG
-#if DDF_DEBUG==1
- if(!DDF::stdTileData) {
- fprintf(stderr,"waveletnoise.h: Fatal, noise not inited!\n");
- exit(1);
- }
-#endif // DDF_DEBUG==1
-#endif // DDF_DEBUG
- return WNoiseVec(p, DDF::stdTileData);
-}
-
-
-// wrapper for a parametrized field of wavelet noise
-class WaveletNoiseField {
- public:
- WaveletNoiseField(std::string name, const ParamSet &params, nVec3i gridsize) :
- mName(name),
- mPosOffset(0.), mPosScale(1.),
- mValOffset(0.), mValScale(1.),
- mClamp(false), mClampNeg(0.), mClampPos(1.),
- mTimeAnim(0.) , mTime(0.)
- {
-
- // init params
- mPosOffset = params.FindOneVector("pos-offset", mPosOffset );
- mPosScale = params.FindOneVector("pos-scale", mPosScale );
-
- mValOffset = params.FindOneFloat("val-offset", mValOffset );
- mValScale = params.FindOneFloat("val-scale", mValScale );
-
- mClamp = params.FindOneBool("clamp", mClamp );
- mClampNeg = params.FindOneFloat("clamp-neg", mClampNeg );
- mClampPos = params.FindOneFloat("clamp-pos", mClampPos );
-
- mTimeAnim = params.FindOneFloat("time-anim", mTimeAnim );
-
- // init inv grid size
- mGsInvX = 1. /(Real)gridsize[0];
- mGsInvY = 1. /(Real)gridsize[1];
- mGsInvZ = 1. /(Real)gridsize[2];
-
- if(!loadStdTile()) {
- errFatal("WaveletNoiseField::WaveletNoiseField","Failed to laod/generate tile! Aborting...", SIMWORLD_INITERROR);
- exit(1);
- }
- debMsg("WaveletNoiseField","Created "<<this->toString() );
- };
- ~WaveletNoiseField() {};
-
- //! evaluate noise
- inline Real evaluate(Vec3 pos) {
- pos[0] *= mGsInvX;
- pos[1] *= mGsInvY;
- pos[2] *= mGsInvZ;
-
- // time anim
- pos += Vec3(mTime);
-
- pos[0] *= mPosScale[0];
- pos[1] *= mPosScale[1];
- pos[2] *= mPosScale[2];
- pos += mPosOffset;
-
- Real v = getWNoise(pos);
-
- v += mValOffset;
- v *= mValScale;
- if (mClamp) {
- if (v< mClampNeg) v = mClampNeg;
- if (v> mClampPos) v = mClampPos;
- }
- return v;
- }
-
- //! evaluate noise as a vector
- inline Vec3 evaluateVec(Vec3 pos) {
- pos[0] *= mGsInvX;
- pos[1] *= mGsInvY;
- pos[2] *= mGsInvZ;
-
- // time anim
- pos += Vec3(mTime);
-
- pos[0] *= mPosScale[0];
- pos[1] *= mPosScale[1];
- pos[2] *= mPosScale[2];
- pos += mPosOffset;
-
- Vec3 v = getWNoiseVec(pos);
-
- v += Vec3(mValOffset);
- v *= mValScale;
- if (mClamp) {
- for(int i=0; i<3; i++) {
- if (v[i]< mClampNeg) v[i] = mClampNeg;
- if (v[i]> mClampPos) v[i] = mClampPos;
- }
- }
- return v;
- }
-
- // increase time
- void increaseTime(Real dt) { mTime += dt * mTimeAnim; }
-
- //! helper
- std::string toString() {
- std::ostringstream out;
- out << "NoiseField: name '"<<mName<<"' "<<
- " pos off="<<mPosOffset<<" scale="<<mPosScale<<
- " val off="<<mValOffset<<" scale="<<mValScale<<
- " clamp ="<<mClamp<<" val="<<mClampNeg<<" to "<<mClampPos<<
- " timeAni ="<<mTimeAnim<<
- " gridInv ="<<PRINT_VEC(mGsInvX,mGsInvY,mGsInvZ) ;
- return out.str();
- }
-
- Real getTimeAnim() { return mTimeAnim; }
- void setTimeAnim(Real set) { mTimeAnim = set; }
-
- protected:
-
- //! name
- std::string mName;
- //! texcoord position and scale
- Vec3 mPosOffset, mPosScale;
- //! value offset & scale
- Real mValOffset, mValScale;
- //! clamp? (default 0-1)
- bool mClamp;
- Real mClampNeg, mClampPos;
- // grid size normalization (inverse size)
- Real mGsInvX, mGsInvY, mGsInvZ;
- // animation over time
- Real mTimeAnim, mTime;
-};
-
-
-} // namespace WAVELETNOISE
-